diff --git a/.clang-format b/.clang-format index ec96b2237..758f8e95c 100644 --- a/.clang-format +++ b/.clang-format @@ -1,73 +1,134 @@ +--- +Language: Cpp +Standard: c++20 BasedOnStyle: LLVM + +# Indentation +IndentWidth: 4 +TabWidth: 4 +UseTab: Never +IndentCaseLabels: true +IndentCaseBlocks: false +IndentPPDirectives: None +IndentExternBlock: NoIndent +NamespaceIndentation: None AccessModifierOffset: -4 -AlignAfterOpenBracket: true -AlignEscapedNewlinesLeft: false -AlignOperands: true +ContinuationIndentWidth: 4 + +# Braces - Allman for definitions, K&R for control flow +BreakBeforeBraces: Custom +BraceWrapping: + AfterCaseLabel: false + AfterClass: true + AfterControlStatement: Never + AfterEnum: true + AfterFunction: true + AfterNamespace: false + AfterStruct: true + AfterUnion: true + AfterExternBlock: false + BeforeCatch: false + BeforeElse: false + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: false + SplitEmptyRecord: false + SplitEmptyNamespace: true + +# No column limit - preserve manual formatting +ColumnLimit: 0 + +# Alignment +PointerAlignment: Left +ReferenceAlignment: Left +DerivePointerAlignment: false +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignConsecutiveMacros: false +AlignEscapedNewlines: Left +AlignOperands: Align AlignTrailingComments: true + +# Spaces +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeCaseColon: false +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeRangeBasedForLoopColon: true +SpaceBeforeSquareBrackets: false +SpaceInEmptyBlock: false +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInCStyleCastParentheses: false +SpacesInConditionalStatement: false +SpacesInContainerLiterals: false +SpacesInParentheses: false +SpacesInSquareBrackets: false + +# Includes +SortIncludes: CaseInsensitive +IncludeBlocks: Preserve + +# Constructor initializer lists - comma-first style +BreakConstructorInitializers: BeforeComma +ConstructorInitializerIndentWidth: 4 +PackConstructorInitializers: Never + +# Inheritance +BreakInheritanceList: BeforeComma + +# Arguments and parameters +AllowAllArgumentsOnNextLine: true AllowAllParametersOfDeclarationOnNextLine: true -AllowShortBlocksOnASingleLine: false -AllowShortCaseLabelsOnASingleLine: false +BinPackArguments: true +BinPackParameters: true + +# Short forms +AllowShortBlocksOnASingleLine: Empty +AllowShortCaseLabelsOnASingleLine: true +AllowShortEnumsOnASingleLine: false AllowShortFunctionsOnASingleLine: Inline -AllowShortIfStatementsOnASingleLine: false +AllowShortIfStatementsOnASingleLine: Never +AllowShortLambdasOnASingleLine: Inline AllowShortLoopsOnASingleLine: false -AlwaysBreakAfterDefinitionReturnType: false + +# Breaking +AlwaysBreakAfterReturnType: None AlwaysBreakBeforeMultilineStrings: false -AlwaysBreakTemplateDeclarations: true -BinPackArguments: true -BinPackParameters: true +AlwaysBreakTemplateDeclarations: Yes BreakBeforeBinaryOperators: None -BreakBeforeBraces: Custom -BraceWrapping: { - AfterClass: 'true' - AfterControlStatement: 'false' - AfterEnum: 'true' - AfterFunction: 'true' - AfterNamespace: 'false' - AfterStruct: 'true' - AfterUnion: 'true' - BeforeCatch: 'false' - BeforeElse: 'false' - IndentBraces: 'false' -} BreakBeforeTernaryOperators: true -BreakConstructorInitializersBeforeComma: true -ColumnLimit: 0 -CommentPragmas: '^ IWYU pragma:' -ConstructorInitializerAllOnOneLineOrOnePerLine: false -ConstructorInitializerIndentWidth: 4 -ContinuationIndentWidth: 4 -Cpp11BracedListStyle: true -DerivePointerAlignment: false -DisableFormat: false -ExperimentalAutoDetectBinPacking: false -IndentCaseLabels: true -IndentWidth: 4 -IndentWrappedFunctionNames: false +BreakStringLiterals: true + +# Empty lines +EmptyLineAfterAccessModifier: Never +EmptyLineBeforeAccessModifier: LogicalBlock KeepEmptyLinesAtTheStartOfBlocks: true -Language: Cpp MaxEmptyLinesToKeep: 2 -NamespaceIndentation: None -ObjCBlockIndentWidth: 4 -ObjCSpaceAfterProperty: false -ObjCSpaceBeforeProtocolList: true +SeparateDefinitionBlocks: Leave + +# Other +Cpp11BracedListStyle: true +FixNamespaceComments: true +ReflowComments: false +CompactNamespaces: false +InsertBraces: false + +# Penalties +PenaltyBreakAssignment: 2 PenaltyBreakBeforeFirstCallParameter: 19 PenaltyBreakComment: 300 PenaltyBreakFirstLessLess: 120 PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 PenaltyExcessCharacter: 1000000 PenaltyReturnTypeOnItsOwnLine: 60 -PointerAlignment: Left -SortIncludes: true -SpaceAfterCStyleCast: false -SpaceBeforeAssignmentOperators: true -SpaceBeforeParens: ControlStatements -SpaceInEmptyParentheses: false -SpacesBeforeTrailingComments: 1 -SpacesInAngles: false -SpacesInCStyleCastParentheses: false -SpacesInContainerLiterals: true -SpacesInParentheses: false -SpacesInSquareBrackets: false -Standard: Cpp11 -TabWidth: 4 -UseTab: Never +--- diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 000000000..768fdd5ce --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,45 @@ +--- +# LibSourcey clang-tidy configuration +# Run: clang-tidy -p build src/base/src/*.cpp + +Checks: > + -*, + bugprone-*, + -bugprone-easily-swappable-parameters, + -bugprone-narrowing-conversions, + modernize-use-nullptr, + modernize-use-override, + modernize-use-using, + modernize-use-auto, + modernize-use-default-member-init, + modernize-use-equals-default, + modernize-use-equals-delete, + modernize-use-nodiscard, + modernize-use-noexcept, + modernize-deprecated-headers, + modernize-redundant-void-arg, + modernize-loop-convert, + modernize-return-braced-init-list, + modernize-use-emplace, + performance-*, + -performance-no-int-to-ptr, + readability-container-size-empty, + readability-implicit-bool-conversion, + readability-redundant-member-init, + readability-redundant-string-init, + readability-simplify-boolean-expr, + +WarningsAsErrors: '' + +HeaderFilterRegex: 'src/.*/include/scy/.*\.h$' + +CheckOptions: + - key: modernize-use-nullptr.NullMacros + value: 'NULL' + - key: modernize-use-auto.MinTypeNameLength + value: '5' + - key: modernize-loop-convert.MinConfidence + value: 'reasonable' + - key: performance-unnecessary-value-param.AllowedTypes + value: 'json::value' +... diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..ecbcde1b8 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,16 @@ +# Set the default behavior, in case people don't have core.autocrlf set. +* text=auto + +# Explicitly declare text files you want to always be normalized and converted +# to native line endings on checkout. +*.cmake text +*.cpp text +*.h text +*.md text +*.txt text +*.json text +*.sh text + +# Denote all files that are truly binary and should not be modified. +*.mp4 binary + diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 000000000..89acdc761 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,218 @@ +name: CI + +on: + push: + branches: [master] + pull_request: + branches: [master] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + linux: + runs-on: ubuntu-24.04 + strategy: + fail-fast: false + matrix: + include: + - compiler: gcc + cc: gcc-13 + cxx: g++-13 + - compiler: gcc + cc: gcc-14 + cxx: g++-14 + - compiler: clang + cc: clang-18 + cxx: clang++-18 + name: Linux (${{ matrix.cxx }}) + steps: + - uses: actions/checkout@v4 + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y libssl-dev ${{ matrix.cc }} ${{ matrix.cxx }} + + - name: Setup ccache + uses: hendrikmuhs/ccache-action@v1 + with: + key: linux-${{ matrix.cxx }} + + - name: Configure + run: | + cmake -B build \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_C_COMPILER=${{ matrix.cc }} \ + -DCMAKE_CXX_COMPILER=${{ matrix.cxx }} \ + -DCMAKE_C_COMPILER_LAUNCHER=ccache \ + -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \ + -DBUILD_TESTS=ON \ + -DBUILD_SAMPLES=OFF + + - name: Build + run: cmake --build build --parallel $(nproc) + + - name: Test + run: ctest --test-dir build --output-on-failure --parallel $(nproc) + + macos: + runs-on: macos-14 + name: macOS (AppleClang) + steps: + - uses: actions/checkout@v4 + + - name: Install dependencies + run: brew install openssl@3 + + - name: Setup ccache + uses: hendrikmuhs/ccache-action@v1 + with: + key: macos + + - name: Configure + run: | + cmake -B build \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_C_COMPILER_LAUNCHER=ccache \ + -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \ + -DOPENSSL_ROOT_DIR=$(brew --prefix openssl@3) \ + -DBUILD_TESTS=ON \ + -DBUILD_SAMPLES=OFF + + - name: Build + run: cmake --build build --parallel $(sysctl -n hw.logicalcpu) + + - name: Test + run: ctest --test-dir build --output-on-failure --parallel $(sysctl -n hw.logicalcpu) + + windows: + runs-on: windows-2022 + name: Windows (MSVC 2022) + steps: + - uses: actions/checkout@v4 + + - name: Install OpenSSL + run: choco install openssl -y --no-progress + + - name: Setup ccache + uses: hendrikmuhs/ccache-action@v1 + with: + variant: sccache + key: windows + + - name: Configure + run: | + cmake -B build -G "Visual Studio 17 2022" -A x64 ` + -DBUILD_TESTS=ON ` + -DBUILD_SAMPLES=OFF ` + -DCMAKE_C_COMPILER_LAUNCHER=sccache ` + -DCMAKE_CXX_COMPILER_LAUNCHER=sccache + + - name: Build + run: cmake --build build --config Release --parallel + + - name: Test + run: ctest --test-dir build --config Release --output-on-failure --parallel + + sanitizers: + runs-on: ubuntu-24.04 + strategy: + fail-fast: false + matrix: + sanitizer: [address, thread, undefined] + include: + - sanitizer: address + flags: -fsanitize=address -fno-omit-frame-pointer + env: ASAN_OPTIONS=detect_leaks=1 + - sanitizer: thread + flags: -fsanitize=thread + env: TSAN_OPTIONS=second_deadlock_stack=1 + - sanitizer: undefined + flags: -fsanitize=undefined -fno-sanitize-recover=all + env: UBSAN_OPTIONS=print_stacktrace=1 + name: Sanitizer (${{ matrix.sanitizer }}) + steps: + - uses: actions/checkout@v4 + + - name: Install dependencies + run: sudo apt-get update && sudo apt-get install -y libssl-dev clang-18 + + - name: Setup ccache + uses: hendrikmuhs/ccache-action@v1 + with: + key: sanitizer-${{ matrix.sanitizer }} + + - name: Configure + run: | + cmake -B build \ + -DCMAKE_BUILD_TYPE=Debug \ + -DCMAKE_C_COMPILER=clang-18 \ + -DCMAKE_CXX_COMPILER=clang++-18 \ + -DCMAKE_C_COMPILER_LAUNCHER=ccache \ + -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \ + -DCMAKE_C_FLAGS="${{ matrix.flags }}" \ + -DCMAKE_CXX_FLAGS="${{ matrix.flags }}" \ + -DBUILD_TESTS=ON \ + -DBUILD_SAMPLES=OFF + + - name: Build + run: cmake --build build --parallel $(nproc) + + - name: Test + env: + ${{ matrix.env }} + run: ctest --test-dir build --output-on-failure --parallel $(nproc) + + coverage: + runs-on: ubuntu-24.04 + name: Coverage + steps: + - uses: actions/checkout@v4 + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y libssl-dev lcov + + - name: Setup ccache + uses: hendrikmuhs/ccache-action@v1 + with: + key: coverage + + - name: Configure + run: | + cmake -B build \ + -DCMAKE_BUILD_TYPE=Debug \ + -DCMAKE_C_COMPILER=gcc-14 \ + -DCMAKE_CXX_COMPILER=g++-14 \ + -DCMAKE_C_COMPILER_LAUNCHER=ccache \ + -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \ + -DCMAKE_C_FLAGS="--coverage" \ + -DCMAKE_CXX_FLAGS="--coverage" \ + -DCMAKE_EXE_LINKER_FLAGS="--coverage" \ + -DBUILD_TESTS=ON \ + -DBUILD_SAMPLES=OFF + + - name: Build + run: cmake --build build --parallel $(nproc) + + - name: Test + run: ctest --test-dir build --output-on-failure --parallel $(nproc) + + - name: Collect coverage + run: | + lcov --capture --directory build --output-file coverage.info \ + --gcov-tool gcov-14 --ignore-errors mismatch + lcov --remove coverage.info '/usr/*' '*/build/_deps/*' '*/vendor/*' '*/test/*' \ + --output-file coverage.info --ignore-errors unused + lcov --list coverage.info + + - name: Upload coverage + uses: codecov/codecov-action@v4 + with: + files: coverage.info + fail_ci_if_error: false + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 000000000..812215549 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,37 @@ +name: Release + +on: + push: + tags: + - 'v*' + +permissions: + contents: write + +jobs: + release: + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + + - name: Read version + id: version + run: echo "version=$(cat VERSION)" >> "$GITHUB_OUTPUT" + + - name: Extract changelog + id: changelog + run: | + # Extract the section for this version from CHANGELOG.md + awk '/^## \['"${{ steps.version.outputs.version }}"'\]/{found=1; next} /^## \[/{if(found) exit} found{print}' CHANGELOG.md > release_notes.md + # Fallback if no changelog entry found + if [ ! -s release_notes.md ]; then + echo "Release ${{ steps.version.outputs.version }}" > release_notes.md + fi + + - name: Create GitHub Release + uses: softprops/action-gh-release@v2 + with: + body_path: release_notes.md + draft: false + prerelease: false + generate_release_notes: true diff --git a/.gitignore b/.gitignore index c07bfe6a3..1cfa20f19 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,14 @@ build* private doxygen2md _book + +# Test output +*.mp2 +*.mp4 +*.flv +*.mkv +*.avi +*.pcm +*.wav +*.aac +*.raw diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..d4746f0fb --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule "src/pacm"] + path = src/pacm + url = https://github.com/sourcey/pacm.git +[submodule "src/pluga"] + path = src/pluga + url = https://github.com/sourcey/pluga.git diff --git a/BUILD.md b/BUILD.md index 0c3fa5dec..fe9f7b69a 100644 --- a/BUILD.md +++ b/BUILD.md @@ -1,132 +1,132 @@ -# CMake build commands - -## Doxygen - -git clone https://github.com/doxygen/doxygen.git -git checkout tags/Release_1_8_12 -cd doxygen -mkdir build -cd build -cmake -G "Unix Makefiles" .. -make -sudo make install - -doxygen -g -INPUT=/home/kam/sourcey/libsourcey/src -OUTPUT_DIRECTORY=/home/kam/sourcey/libsourcey/build/doxygen -PROJECT_NAME="LibSourcey" -RECURSIVE=YES -GENERATE_XML=NO -GENERATE_HTML=NO -GENERATE_LATEX=NO -EXCLUDE_PATTERNS = */anionu* */test* */apps* */samples* - -npm install moxygen -node ./node_modules/moxygen/bin/moxygen.js --verbose --groups --output=./doc/api-%s.md ./build/doxygen/xml - -npm install gitbook-cli -node ./node_modules/gitbook-cli/bin/gitbook.js init - -https://github.com/contao/docs/blob/master/cookbook/book.json - -## Default debug build -cmake .. -DCMAKE_BUILD_TYPE=DEBUG -DBUILD_SHARED_LIBS=OFF \ - -DBUILD_MODULES=ON -DBUILD_APPLICATIONS=ON \ - -DBUILD_SAMPLES=ON -DBUILD_TESTS=ON \ - -DWITH_FFMPEG=ON - -## All modules (selective) -cmake .. -DCMAKE_BUILD_TYPE=DEBUG -DBUILD_SHARED_LIBS=OFF \ - -DBUILD_APPLICATIONS=OFF -DBUILD_MODULES=OFF \ - -DBUILD_SAMPLES=ON -DBUILD_TESTS=ON \ - -DWITH_FFMPEG=ON -DWITH_OPENCV=OFF \ - -DBUILD_MODULE_archo=ON \ - -DBUILD_MODULE_base=ON -DBUILD_MODULE_crypto=ON \ - -DBUILD_MODULE_http=ON -DBUILD_MODULE_json=ON \ - -DBUILD_MODULE_av=ON -DBUILD_MODULE_net=ON \ - -DBUILD_MODULE_pacm=ON -DBUILD_MODULE_pluga=ON \ - -DBUILD_MODULE_sked=ON -DBUILD_MODULE_socketio=ON \ - -DBUILD_MODULE_stun=ON -DBUILD_MODULE_symple=ON \ - -DBUILD_MODULE_turn=ON -DBUILD_MODULE_util=ON \ - -DBUILD_MODULE_webrtc=ON - -## Minimum build (base only) -cmake .. -DCMAKE_BUILD_TYPE=DEBUG -DBUILD_MODULES=OFF \ - -DBUILD_MODULE_base=ON - -## Media build -cmake .. -DCMAKE_BUILD_TYPE=DEBUG -DBUILD_SHARED_LIBS=OFF \ - -DBUILD_APPLICATIONS=OFF -DBUILD_MODULES=OFF \ - -DBUILD_SAMPLES=ON -DBUILD_TESTS=ON \ - -DWITH_FFMPEG=ON -DWITH_OPENCV=OFF \ - -DBUILD_MODULE_av=ON -DBUILD_MODULE_base=ON - -## WebRTC default debug build -cmake .. -DCMAKE_BUILD_TYPE=DEBUG -DBUILD_SHARED_LIBS=OFF \ - -DBUILD_MODULES=ON -DBUILD_APPLICATIONS=ON \ - -DBUILD_SAMPLES=ON -DBUILD_TESTS=ON \ - -DWITH_FFMPEG=ON -DWITH_WEBRTC=ON \ - -DWEBRTC_ROOT_DIR=/home/kam/sourcey/webrtcbuilds/out/src - -## WebRTC selective module build -cmake .. -DCMAKE_BUILD_TYPE=DEBUG -DBUILD_SHARED_LIBS=OFF \ - -DBUILD_MODULES=ON -DBUILD_APPLICATIONS=ON \ - -DBUILD_TESTS=OFF -DBUILD_SAMPLES=OFF -DBUILD_SAMPLES_webrtc=ON \ - -DWITH_FFMPEG=ON -DWITH_WEBRTC=ON -DENABLE_LOGGING=ON \ - -DBUILD_MODULE_base=ON -DBUILD_MODULE_av=ON \ - -DBUILD_MODULE_crypto=ON -DBUILD_MODULE_http=ON \ - -DBUILD_MODULE_json=ON -DBUILD_MODULE_net=ON \ - -DBUILD_MODULE_socketio=ON -DBUILD_MODULE_symple=ON \ - -DBUILD_MODULE_util=ON -DBUILD_MODULE_webrtc=ON \ - -DWEBRTC_ROOT_DIR=/home/kam/sourcey/webrtcbuilds/out/webrtc-17657-02ba69d-linux-x64 - -## WebRTC (VS2015, Win64, Static) -cmake -G "Visual Studio 14 Win64" .. -DCMAKE_BUILD_TYPE=DEBUG -DBUILD_SHARED_LIBS=OFF -DBUILD_MODULES=OFF -DBUILD_WITH_STATIC_CRT=ON -DBUILD_APPLICATIONS=ON -DBUILD_SAMPLES=ON -DBUILD_TESTS=ON -DWITH_WEBRTC=ON -DWITH_FFMPEG=ON -DBUILD_MODULE_base=ON -DBUILD_MODULE_crypto=ON -DBUILD_MODULE_http=ON -DBUILD_MODULE_json=ON -DBUILD_MODULE_av=ON -DBUILD_MODULE_net=ON -DBUILD_MODULE_socketio=ON -DBUILD_MODULE_symple=ON -DBUILD_MODULE_util=ON -DBUILD_MODULE_stun=ON -DBUILD_MODULE_turn=ON -DBUILD_MODULE_webrtc=ON -DFFMPEG_ROOT_DIR=E:/dev/vendor/ffmpeg-3.2.2-win64-dev -DWEBRTC_ROOT_DIR=E:/dev/vendor/webrtcbuilds/out/webrtc-17657-02ba69d-win-x64 - -## WebRTC (VS2017, Win64, Static) -cmake -G "Visual Studio 15 Win64" .. -DCMAKE_BUILD_TYPE=DEBUG -DBUILD_SHARED_LIBS=OFF -DBUILD_MODULES=OFF -DBUILD_WITH_STATIC_CRT=ON -DBUILD_APPLICATIONS=ON -DBUILD_SAMPLES=ON -DBUILD_TESTS=ON -DWITH_WEBRTC=ON -DWITH_FFMPEG=ON -DBUILD_MODULE_base=ON -DBUILD_MODULE_crypto=ON -DBUILD_MODULE_http=ON -DBUILD_MODULE_json=ON -DBUILD_MODULE_av=ON -DBUILD_MODULE_net=ON -DBUILD_MODULE_socketio=ON -DBUILD_MODULE_symple=ON -DBUILD_MODULE_util=ON -DBUILD_MODULE_stun=ON -DBUILD_MODULE_turn=ON -DBUILD_MODULE_webrtc=ON -DFFMPEG_ROOT_DIR=E:/dev/vendor/ffmpeg-3.2.2-win64-dev -DWEBRTC_ROOT_DIR=E:/dev/vendor/webrtcbuilds/out/webrtc-17657-02ba69d-win-x64 - -## Symple build (no media) -cmake .. -DCMAKE_BUILD_TYPE=DEBUG -DBUILD_SHARED_LIBS=OFF \ - -DBUILD_APPLICATIONS=ON -DBUILD_MODULES=OFF \ - -DBUILD_SAMPLES=ON -DBUILD_TESTS=ON \ - -DWITH_FFMPEG=OFF -DWITH_OPENCV=OFF \ - -DBUILD_MODULE_base=ON \ - -DBUILD_MODULE_crypto=ON -DBUILD_MODULE_http=ON \ - -DBUILD_MODULE_json=ON -DBUILD_MODULE_net=ON \ - -DBUILD_MODULE_socketio=ON -DBUILD_MODULE_symple=ON \ - -DBUILD_MODULE_util=ON - -## Symple build (with media) -cmake .. -DCMAKE_BUILD_TYPE=DEBUG -DBUILD_SHARED_LIBS=OFF \ - -DBUILD_APPLICATIONS=ON -DBUILD_MODULES=OFF \ - -DBUILD_SAMPLES=ON -DBUILD_TESTS=ON \ - -DWITH_FFMPEG=ON -DWITH_OPENCV=OFF \ - -DBUILD_MODULE_archo=ON -DBUILD_MODULE_base=ON \ - -DBUILD_MODULE_crypto=ON -DBUILD_MODULE_http=ON \ - -DBUILD_MODULE_json=ON -DBUILD_MODULE_av=ON \ - -DBUILD_MODULE_net=ON -DBUILD_MODULE_socketio=ON \ - -DBUILD_MODULE_symple=ON -DBUILD_MODULE_util=ON - -## Net build -cmake .. -DCMAKE_BUILD_TYPE=DEBUG -DBUILD_SHARED_LIBS=OFF \ - -DBUILD_APPLICATIONS=OFF -DBUILD_MODULES=OFF \ - -DBUILD_SAMPLES=OFF -DBUILD_TESTS=ON \ - -DBUILD_MODULE_base=ON \ - -DBUILD_MODULE_crypto=ON -DBUILD_MODULE_net=ON - -## HTTP build -cmake .. -DCMAKE_BUILD_TYPE=RELEASE -DBUILD_SHARED_LIBS=OFF \ - -DBUILD_APPLICATIONS=ON -DBUILD_MODULES=OFF \ - -DBUILD_SAMPLES=ON -DBUILD_TESTS=ON \ - -DBUILD_MODULE_base=ON -DBUILD_MODULE_crypto=ON \ - -DBUILD_MODULE_json=ON -DBUILD_MODULE_net=ON \ - -DBUILD_MODULE_util=ON -DBUILD_MODULE_http=ON - -## STUN/TURN build -cmake .. -DCMAKE_BUILD_TYPE=DEBUG -DBUILD_SHARED_LIBS=OFF \ - -DBUILD_APPLICATIONS=ON -DBUILD_MODULES=OFF \ - -DBUILD_MODULE_base=ON -DBUILD_MODULE_crypto=ON \ - -DBUILD_MODULE_net=ON -DBUILD_MODULE_stun=ON \ - -DBUILD_MODULE_turn=ON -DBUILD_MODULE_util=ON \ - -DBUILD_MODULE_json=ON +# Building LibSourcey + +## Prerequisites + +- CMake 3.21+ +- C++20 compiler (GCC 12+, Clang 15+, MSVC 2022+, AppleClang 15+) +- OpenSSL 3.x development headers +- pkg-config (Linux/macOS) +- FFmpeg 6.x or 7.x (optional, for the `av` module) + +### Platform-specific + +**Linux (Ubuntu/Debian):** +```bash +sudo apt-get install build-essential cmake pkg-config libssl-dev +# Optional: for av module +sudo apt-get install libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libswresample-dev +``` + +**macOS:** +```bash +brew install cmake openssl@3 +# Optional: for av module +brew install ffmpeg +``` + +**Windows:** +```powershell +choco install cmake openssl +``` + +## Default build + +```bash +cmake -B build -DCMAKE_BUILD_TYPE=Release +cmake --build build --parallel $(nproc) +``` + +## Build with tests + +```bash +cmake -B build -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTS=ON +cmake --build build --parallel $(nproc) +ctest --test-dir build --output-on-failure +``` + +## Build options + +| Option | Default | Description | +| ------ | ------- | ----------- | +| `BUILD_SHARED_LIBS` | `OFF` | Build shared libraries | +| `BUILD_MODULES` | `ON` | Build all LibSourcey modules | +| `BUILD_TESTS` | `OFF` | Build module tests | +| `BUILD_SAMPLES` | `OFF` | Build module samples | +| `BUILD_APPLICATIONS` | `ON` | Build applications | +| `BUILD_ALPHA` | `OFF` | Build alpha development modules | +| `ENABLE_LOGGING` | `ON` | Enable internal debug logging | + +## Example configurations + +### Minimum build (base only) + +```bash +cmake -B build -DCMAKE_BUILD_TYPE=Debug -DBUILD_MODULES=OFF -DBUILD_MODULE_base=ON +``` + +### Networking build + +```bash +cmake -B build -DCMAKE_BUILD_TYPE=Debug \ + -DBUILD_MODULES=OFF -DBUILD_TESTS=ON \ + -DBUILD_MODULE_base=ON \ + -DBUILD_MODULE_crypto=ON \ + -DBUILD_MODULE_net=ON +``` + +### HTTP build + +```bash +cmake -B build -DCMAKE_BUILD_TYPE=Release \ + -DBUILD_MODULES=OFF -DBUILD_TESTS=ON -DBUILD_SAMPLES=ON \ + -DBUILD_MODULE_base=ON -DBUILD_MODULE_crypto=ON \ + -DBUILD_MODULE_json=ON -DBUILD_MODULE_net=ON \ + -DBUILD_MODULE_http=ON +``` + +### Media build (with FFmpeg) + +```bash +cmake -B build -DCMAKE_BUILD_TYPE=Debug \ + -DBUILD_MODULES=OFF -DBUILD_TESTS=ON \ + -DWITH_FFMPEG=ON \ + -DBUILD_MODULE_base=ON -DBUILD_MODULE_av=ON +``` + +## Installing + +```bash +cmake --install build --prefix /usr/local +``` + +## Docker + +```bash +docker build -t libsourcey . +``` + +## External module plugin pattern + +LibSourcey supports external modules that live outside the main source tree. Create a directory with a `CMakeLists.txt` that uses `scy_add_module()`: + +```cmake +scy_add_module(mymodule + DEPENDS base net + PACKAGES OpenSSL::SSL + PRETTY_NAME MyModule +) +``` + +Then pass the module path when configuring: + +```bash +cmake -B build -DBUILD_MODULE_mymodule=ON -DLibSourcey_EXTRA_MODULES=/path/to/mymodule +``` + +## Generating API docs + +```bash +# Requires: doxygen, npx (Node.js) +doxygen Doxyfile +npx moxygen --groups --output=./doc/api-%s.md ./build/doxygen/xml +``` diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000..bf12f20e2 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,120 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/), and this project adheres to [Semantic Versioning](https://semver.org/). + +## [2.0.0] - Unreleased + +### Build system + +- Rewrote CMake build system with modern target-based dependencies and `scy_add_module()` pattern +- Replaced vendored sources with CMake FetchContent (libuv, zlib, llhttp, nlohmann/json) +- CMake 3.21 minimum, with proper `find_package(LibSourcey)` and FetchContent consumer support +- CPack packaging support (deb, rpm, tar.gz) +- External module plugin pattern for out-of-tree modules +- Multi-stage Docker build on Ubuntu 24.04 LTS +- GitHub Actions CI replacing CircleCI (Linux GCC/Clang, macOS AppleClang, Windows MSVC) +- CI includes address/undefined sanitizers and code coverage +- `.clang-format` and `.clang-tidy` configurations added + +### Language and code modernisation + +- C++20 minimum standard (from C++14) +- `#pragma once` replaces include guards throughout +- `using` type aliases replace `typedef` +- `nullptr` replaces `NULL` +- `enum class` replaces unscoped enums +- Smart pointers (unique_ptr, shared_ptr) throughout; RAII wrappers for OpenSSL, FFmpeg, and logger resources +- `std::chrono` replaces `clock_t` timing +- `[[nodiscard]]` on key return values (crypto, net, av, archo modules) +- `noexcept` on all destructors +- `std::invoke_result` replaces deprecated `std::result_of` +- C-style casts replaced with `static_cast`/`reinterpret_cast` +- Entire codebase formatted with clang-format + +### Dependencies + +- OpenSSL 3.x migration (new provider/context APIs, deprecated function replacements) +- FFmpeg 6.x/7.x migration (avcodec send/receive API, codecpar, channel layouts, `av_*` iterators) +- llhttp replaces http_parser for HTTP/1.x parsing +- nlohmann/json replaces JsonCpp +- libuv 1.50 compatibility (accessor APIs, proper handle close, loop alive checks) +- FindOpenCV.cmake rewritten for OpenCV 4.x + +### Security + +- pacm: Default checksum algorithm changed from MD5 to SHA256 +- pacm: SSL certificate verification enabled (was `initNoVerifyClient`) +- pacm: Path traversal protection added to zip extraction and package metadata +- pacm: Default API endpoint changed from http to https +- net: SSL hostname verification via `SSL_set1_host()`, auto-wired through `SSLSocket::connect(host, port)` +- net: TLS 1.2 enforced as minimum protocol version +- net: ALPN protocol negotiation support (`SSLContext::setALPNProtocols`) +- net: SNI support (`SSLContext::enableSNI`) + +### Bug fixes + +- STUN: ChannelNumber attribute factory was creating wrong type (ICEUseCandidate instead) +- STUN: Bit shift undefined behavior in UInt32/UInt64Attribute::setBit +- TURN: Permission lifetime corrected to RFC 5766-mandated 5 minutes (was 3) +- TURN: Server::stop() null pointer dereference when sockets not configured +- archo: ZipFile::closeCurrentFile() was calling unzOpenCurrentFile instead of unzCloseCurrentFile +- archo: Compressed/uncompressed file size fields were swapped +- base: once.h missing uv_close() on prepare handle (resource leak) +- base: UV_EOF in Stream::handleRead() now triggers graceful close instead of error state (fixes shutdown() causing spurious errors) +- base: IPC waitForSync() now has configurable timeout (default 5s) preventing infinite hangs +- base: Signal slot ID uniqueness enforced, throws on collision +- base: DateTime constructor/assign validate all components at runtime (was assert-only) +- base: PacketStream destructor warns instead of asserting on non-terminal state +- base: TaskRunner::add() fixed stray semicolon bug that allowed duplicate task insertion +- crypto: EVP_md5 replaced with EVP_sha256 for cipher key derivation +- av: MediaCapture::run() fixed stray semicolon on looping seek (was a no-op) +- av: MultiplexEncoder PTS tracking now mutex-protected across audio/video paths +- av: MediaCapture flags (_stopping, _looping, etc.) changed to std::atomic for thread safety +- av: FFmpeg 6.x const AVOutputFormat compatibility (removed oformat->codec assignment) +- av: Unchecked FFmpeg return values now checked: avformat_write_header, av_write_trailer, avio_close, avcodec_parameters_from_context +- http: Download progress tracking re-enabled via ClientConnection::IncomingProgress signal +- http: WebSocket RFC 6455 compliance: RSV bit validation, opcode validation, mask enforcement, ping/pong auto-response, close frame handshake +- http: WebSocket partial frame buffering across TCP segments +- http: WebSocket fragmentation/continuation frame support +- net: SSLContext min proto version was set before null check on context (crash fix) +- net: SSLAdapter SSL_ERROR_WANT_WRITE now calls flushWriteBIO instead of asserting +- pacm: latestSDKAsset() logic simplified (dead code branch removed) +- sched: Scheduler::update() and run() memory leaks fixed (erased tasks without deleting) + +### Production safety + +- All `assert()` calls in production source code replaced with runtime checks (throws, returns, or warnings) - approximately 110+ asserts across 30 files in base, net, av, crypto, pacm modules +- All stale `#if 0` dead code blocks removed across 13+ source files +- Stream::write() backpressure via configurable high water mark on libuv write queue (default 16MB) +- TaskRunner ownership modernised: `std::deque>` replaces raw pointer container + +### Module changes + +- util module merged into base (headers moved, includes updated, downstream deps fixed) +- archo module updated to use `std::filesystem::path` +- Socket.IO protocol v5 compatibility verified +- FindFFmpeg.cmake rewritten to use pkg-config (old version depended on deleted CMake macros) +- pacm and pluga modules fully modernised (noexcept destructors, dead code removed, typos fixed) + +### Tests + +- base: Timer pause/resume, timer one-shot, IPC round-trip, logger level filtering, PacketStream overflow +- av: Standalone VideoEncoder (synthetic YUV -> libx264), VideoDecoder (test.mp4), AudioDecoder (test.mp4) +- http: Request/response serialisation round-trip, POST request, WebSocket text/binary frame encoding, client masking, control frames +- pacm: Package JSON round-trip, asset version selection, LocalPackage state management, manifest operations, error handling, InstallationState strings + +### Removed + +- WebRTC module (unmaintainable due to Google API churn) +- Deprecated code: `av/deprecated/`, `UserManager`, `SharedObject` +- Dead connection classes from http/client.h +- CircleCI configuration +- Gitbook documentation tooling +- Vendored libuv, zlib, http-parser sources +- Legacy Poco and Anionu dependencies + +## [1.1.4] - 2019-03-15 + +- Last release of the 1.x series diff --git a/CMakeLists.txt b/CMakeLists.txt index d25eb5474..da47e9e64 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,182 +1,92 @@ -# ============================================================================ -# Root CMakeLists.txt file for LibSourcey -# ============================================================================ - -# CMake 2.8.10 or newer for other platforms. -# This version is available via Ubuntu's package manager for the 14.04 LTS. -cmake_minimum_required(VERSION 2.8.10) - -# This must go before `project(LibSourcey)` in order to work. -if(WIN32) - # CMake 3.4 or newer is required on windoes to make use of the - # CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS value for shares releases. - # cmake_minimum_required(VERSION 3.4) - # set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS TRUE) - set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/install" CACHE PATH "Installation Directory") -else() - # set(CMAKE_INSTALL_PREFIX "/usr/local" CACHE PATH "Installation Directory") +cmake_minimum_required(VERSION 3.21) + +# Read version from file +file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/VERSION" LibSourcey_VERSION) +string(STRIP "${LibSourcey_VERSION}" LibSourcey_VERSION) + +project(LibSourcey + VERSION ${LibSourcey_VERSION} + LANGUAGES C CXX + DESCRIPTION "C++ Networking Evolved" + HOMEPAGE_URL "https://github.com/sourcey/libsourcey" +) + +# C++20 standard +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) + +# Default to Release if not specified +if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS Debug Release RelWithDebInfo MinSizeRel) endif() -# set(CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING "Configs" FORCE) -# set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS ${CMAKE_CONFIGURATION_TYPES}) - -project(LibSourcey) - -add_definitions(-DUNICODE -D_UNICODE) - -# set(CMAKE_MACOSX_RPATH 1) - -# Set warning level to W3 -if(CMAKE_BUILD_TOOL MATCHES "(msdev|devenv|nmake)") - add_definitions(/W3) +# Unicode on Windows +if(WIN32) + add_definitions(-DUNICODE -D_UNICODE -DNOMINMAX) endif() -# Remove a couple of annoying CMake warnings -# cmake_policy(SET CMP0054 OLD) -# CMP0042 - - -include(LibSourcey.cmake REQUIRED) -# include(cmake/LibSourceyVersion.cmake) - -# ---------------------------------------------------------------------------- -# Package configuration -# ---------------------------------------------------------------------------- +# Include the main build orchestrator +include(LibSourcey.cmake) +# Package configuration (CPack) include(cmake/LibSourceyPackage.cmake) -# ---------------------------------------------------------------------------- -# Add Tests target -# ---------------------------------------------------------------------------- -# if (BUILD_TESTS) +# CTest support +if(BUILD_TESTS) + enable_testing() set(CMAKE_CTEST_COMMAND ctest -V) add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND}) -# endif() +endif() -# ---------------------------------------------------------------------------- -# Add Doxygen documentation target -# ---------------------------------------------------------------------------- -find_package(Doxygen) +# Doxygen documentation target +find_package(Doxygen QUIET) if(DOXYGEN_FOUND) configure_file( - ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile - ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile @ONLY) + ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile + ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile @ONLY) add_custom_target(doc ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMENT "Generating API documentation with Doxygen" VERBATIM) endif() -# ---------------------------------------------------------------------------- -# Uninstall target for "make uninstall" -# ---------------------------------------------------------------------------- +# Uninstall target if(UNIX) configure_file( "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY) - add_custom_target(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake") endif() -# ---------------------------------------------------------------------------- -# Summary: -# ---------------------------------------------------------------------------- - -# Build platform -status("") -status(" Platform:") -status(" Host:" ${CMAKE_HOST_SYSTEM_NAME} ${CMAKE_HOST_SYSTEM_VERSION} ${CMAKE_HOST_SYSTEM_PROCESSOR}) -if(CMAKE_CROSSCOMPILING) - status(" Target:" ${CMAKE_SYSTEM_NAME} ${CMAKE_SYSTEM_VERSION} ${CMAKE_SYSTEM_PROCESSOR}) -endif() -status(" CMake:" ${CMAKE_VERSION}) -status(" CMake generator:" ${CMAKE_GENERATOR}) -status(" CMake build tool:" ${CMAKE_BUILD_TOOL}) -if(MSVC) - status(" MSVC:" ${MSVC_VERSION}) -endif() -if(CMAKE_GENERATOR MATCHES Xcode) - status(" Xcode:" ${XCODE_VERSION}) -endif() -if(NOT CMAKE_GENERATOR MATCHES "Xcode|Visual Studio") - status(" Configuration:" ${CMAKE_BUILD_TYPE}) -endif() - -# C/C++ options -status("") -status(" C/C++:") -status(" Built as dynamic libs?:" BUILD_SHARED_LIBS THEN YES ELSE NO) -status(" C++ Compiler:" CMAKE_COMPILER_IS_GNUCXX THEN "${CMAKE_CXX_COMPILER} (ver ${CMAKE_CXX_COMPILER_VERSION})" ELSE "${CMAKE_CXX_COMPILER}" ) -status(" C++ flags (Release):" ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_RELEASE}) -status(" C++ flags (Debug):" ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_DEBUG}) - -status(" C Compiler:" ${CMAKE_C_COMPILER}) -status(" C flags (Release):" ${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_RELEASE}) -status(" C flags (Debug):" ${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_DEBUG}) -if(WIN32) - status(" Linker flags (Release):" ${CMAKE_EXE_LINKER_FLAGS} ${CMAKE_EXE_LINKER_FLAGS_RELEASE}) - status(" Linker flags (Debug):" ${CMAKE_EXE_LINKER_FLAGS} ${CMAKE_EXE_LINKER_FLAGS_DEBUG}) -else() - status(" Linker flags (Release):" ${CMAKE_SHARED_LINKER_FLAGS} ${CMAKE_SHARED_LINKER_FLAGS_RELEASE}) - status(" Linker flags (Debug):" ${CMAKE_SHARED_LINKER_FLAGS} ${CMAKE_SHARED_LINKER_FLAGS_DEBUG}) -endif() - -# Modules -status("") -status(" Build Components:") -status("") -status(" Dependencies: ${LibSourcey_BUILD_DEPENDENCIES}") -status(" Modules: ${LibSourcey_BUILD_MODULES}") -status(" Applications: ${LibSourcey_BUILD_APPLICATIONS}") -status(" Samples: ${LibSourcey_BUILD_SAMPLES}") -status(" Tests: ${LibSourcey_BUILD_TESTS}") - -# Dependencies -status("") -status(" Other third-party libraries:") -status("") -if (OPENSSL_IS_BORINGSSL) - status(" Use BoringSSL:" HAVE_BORINGSSL THEN YES ELSE NO) -else() - status(" Use OpenSSL:" HAVE_OPENSSL THEN YES ELSE NO) -endif() -status(" Use FFmpeg:" HAVE_FFMPEG THEN YES ELSE NO) -status(" Use OpenCV:" HAVE_OPENCV THEN "YES (ver ${OPENCV_VERSION})" ELSE NO) -status(" Use WebRTC:" HAVE_WEBRTC THEN YES ELSE NO) -status(" Use Poco:" HAVE_POCO THEN YES ELSE NO) -status(" Use wxWidgets:" HAVE_WXWIDGETS THEN YES ELSE NO) -# status(" Use LibUV:" HAVE_LIBUV THEN YES ELSE NO) -# status(" Use HttpParser:" HAVE_HTTPPARSER THEN YES ELSE NO) -# status(" Use RtAudio:" HAVE_RTAUDIO THEN YES ELSE NO) -# status(" Use JsonCpp:" HAVE_JSONCPP THEN YES ELSE NO) -# status(" Use zlib:" HAVE_ZLIB THEN YES ELSE NO) - -# Includes -# status("") -# status(" Linker paths and libraries:") -# status("") -# status(" Include dirs: ${LibSourcey_INCLUDE_DIRS}") -# status(" Include libs: ${LibSourcey_INCLUDE_LIBRARIES}") -# status(" Library dirs: ${LibSourcey_LIBRARY_DIRS}") -# status(" Standard libs: ${CMAKE_CXX_STANDARD_LIBRARIES}") - -# Auxiliary -status("") -status(" Install path: ${LibSourcey_INSTALL_DIR}") -status("") -status(" libsourcey.h is in: ${LibSourcey_INSTALL_DIR}/include/libsourcey.h") -status("-----------------------------------------------------------------") -status("") - -# Warn in the case of in-source build -if("${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_BINARY_DIR}") - message(WARNING "The source directory is the same as binary directory. \"make clean\" may damage the source tree") -endif() - -# This is a proper place for make iOS build happy. It cannot be moved to the top -if(IOS) - set(SDKROOT "iphoneos") - set(CMAKE_OSX_SYSROOT ${SDKROOT}) +# Build summary +message(STATUS "") +message(STATUS " LibSourcey ${PROJECT_VERSION}") +message(STATUS "") +message(STATUS " Platform: ${CMAKE_SYSTEM_NAME} ${CMAKE_SYSTEM_PROCESSOR}") +message(STATUS " CMake: ${CMAKE_VERSION}") +message(STATUS " Generator: ${CMAKE_GENERATOR}") +message(STATUS " Build type: ${CMAKE_BUILD_TYPE}") +message(STATUS " C++ compiler: ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}") +message(STATUS " C++ standard: ${CMAKE_CXX_STANDARD}") +message(STATUS " Shared libs: ${BUILD_SHARED_LIBS}") +message(STATUS "") +message(STATUS " Modules: ${LibSourcey_BUILD_MODULES}") +message(STATUS " Tests: ${LibSourcey_BUILD_TESTS}") +message(STATUS " Samples: ${LibSourcey_BUILD_SAMPLES}") +message(STATUS "") +message(STATUS " OpenSSL: ${HAVE_OPENSSL}") +message(STATUS " FFmpeg: ${HAVE_FFMPEG}") +message(STATUS " OpenCV: ${HAVE_OPENCV}") + +message(STATUS "") +message(STATUS " Install path: ${CMAKE_INSTALL_PREFIX}") +message(STATUS "") + +# Warn on in-source builds +if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR) + message(WARNING "In-source builds are not recommended. Use a separate build directory.") endif() diff --git a/CMakePresets.json b/CMakePresets.json new file mode 100644 index 000000000..a18f361d0 --- /dev/null +++ b/CMakePresets.json @@ -0,0 +1,68 @@ +{ + "version": 3, + "cmakeMinimumRequired": { + "major": 3, + "minor": 21, + "patch": 0 + }, + "configurePresets": [ + { + "name": "default", + "displayName": "Default (Release, static)", + "binaryDir": "${sourceDir}/build", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Release", + "BUILD_SHARED_LIBS": "OFF" + } + }, + { + "name": "debug", + "displayName": "Debug (static)", + "binaryDir": "${sourceDir}/build-debug", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug", + "BUILD_SHARED_LIBS": "OFF", + "BUILD_TESTS": "ON", + "ENABLE_LOGGING": "ON" + } + }, + { + "name": "shared", + "displayName": "Release (shared libraries)", + "binaryDir": "${sourceDir}/build-shared", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Release", + "BUILD_SHARED_LIBS": "ON" + } + }, + { + "name": "full", + "displayName": "Full build with tests and samples", + "binaryDir": "${sourceDir}/build-full", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug", + "BUILD_TESTS": "ON", + "BUILD_SAMPLES": "ON", + "ENABLE_LOGGING": "ON" + } + } + ], + "buildPresets": [ + { + "name": "default", + "configurePreset": "default" + }, + { + "name": "debug", + "configurePreset": "debug" + }, + { + "name": "shared", + "configurePreset": "shared" + }, + { + "name": "full", + "configurePreset": "full" + } + ] +} diff --git a/Dockerfile b/Dockerfile index 406e671ad..ac627eefe 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,10 +1,7 @@ -FROM ubuntu:14.04 -MAINTAINER Kam Low +FROM ubuntu:24.04 AS builder +LABEL maintainer="Kam Low " -# Install the PPA for GCC 6 which is required for C++14 -RUN apt-get update && \ - apt-get install -y software-properties-common && \ - add-apt-repository -y ppa:ubuntu-toolchain-r/test +ENV DEBIAN_FRONTEND=noninteractive # Install dependencies RUN apt-get update && apt-get install -y \ @@ -12,32 +9,26 @@ RUN apt-get update && apt-get install -y \ pkg-config \ git \ cmake \ - libx11-dev \ - libglu1-mesa-dev \ - gcc-6 \ - g++-6 - -# Use GCC 6 -RUN sudo update-alternatives \ - --install /usr/bin/gcc gcc /usr/bin/gcc-6 60 \ - --slave /usr/bin/g++ g++ /usr/bin/g++-6 - -# Download and extract precompiled WebRTC static libraries -# COPY vendor/webrtc-17657-894c0c6-linux-x64 /vendor/webrtc-17657-894c0c6-linux-x64 -RUN mkdir -p /vendor/webrtc-17657-894c0c6-linux-x64; \ - curl -sSL https://github.com/sourcey/webrtc-precompiled-builds/raw/master/webrtc-17657-894c0c6-linux-x64.tar.gz | sudo tar -xzC /vendor/webrtc-17657-894c0c6-linux-x64 - -# Install LibSourcey -RUN git clone https://github.com/sourcey/libsourcey.git && \ - cd /libsourcey && mkdir build && cd build && \ - cmake .. -DCMAKE_BUILD_TYPE=DEBUG -DBUILD_SHARED_LIBS=OFF -DBUILD_WITH_STATIC_CRT=ON \ - -DBUILD_MODULES=ON -DBUILD_APPLICATIONS=OFF -DBUILD_SAMPLES=OFF -DBUILD_TESTS=OFF \ - -DWITH_FFMPEG=OFF -DWITH_WEBRTC=ON -DENABLE_LOGGING=OFF \ - -DWEBRTC_ROOT_DIR=/vendor/webrtc-17657-894c0c6-linux-x64 \ + libssl-dev \ + && rm -rf /var/lib/apt/lists/* + +COPY . /libsourcey + +RUN cd /libsourcey && mkdir -p build && cd build && \ + cmake .. -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF \ + -DBUILD_MODULES=ON -DBUILD_APPLICATIONS=OFF \ + -DBUILD_SAMPLES=OFF -DBUILD_TESTS=OFF \ -DCMAKE_INSTALL_PREFIX=/libsourcey/install && \ - make VERBOSE=1 && \ - make install - # cachebust + cmake --build . --parallel "$(nproc)" && \ + cmake --install . + +FROM ubuntu:24.04 +LABEL maintainer="Kam Low " + +RUN apt-get update && apt-get install -y --no-install-recommends \ + libssl3t64 \ + && rm -rf /var/lib/apt/lists/* + +COPY --from=builder /libsourcey/install /usr/local -# Set the working directory to the LibSourcey install directory -WORKDIR /libsourcey/install \ No newline at end of file +WORKDIR /usr/local diff --git a/Doxyfile b/Doxyfile index 130ac4a4b..3bd3d8115 100644 --- a/Doxyfile +++ b/Doxyfile @@ -38,13 +38,13 @@ PROJECT_NAME = "LibSourcey" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = +PROJECT_NUMBER = @LibSourcey_VERSION@ # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a # quick idea about the purpose of the project. Keep the description short. -PROJECT_BRIEF = +PROJECT_BRIEF = "C++ Networking Evolved" # With the PROJECT_LOGO tag one can specify a logo or an icon that is included # in the documentation. The maximum height of the logo should not exceed 55 @@ -435,7 +435,7 @@ LOOKUP_CACHE_SIZE = 0 # normally produced when WARNINGS is set to YES. # The default value is: NO. -EXTRACT_ALL = NO +EXTRACT_ALL = YES # If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will # be included in the documentation. @@ -889,7 +889,7 @@ EXCLUDE_SYMLINKS = NO # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories for example use the pattern */test/* -EXCLUDE_PATTERNS = */anionu* */tests* */apps* */samples* +EXCLUDE_PATTERNS = */anionu* */tests* */apps* */samples* */build* */vendor* # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the @@ -2080,7 +2080,7 @@ INCLUDE_FILE_PATTERNS = # recursively expanded use the := operator instead of the = operator. # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. -PREDEFINED = +PREDEFINED = HAVE_FFMPEG HAVE_FFMPEG_AVDEVICE # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this # tag can be used to specify a list of macro names that should be expanded. The diff --git a/LibSourcey.cmake b/LibSourcey.cmake index 5979d9b43..5c949043a 100644 --- a/LibSourcey.cmake +++ b/LibSourcey.cmake @@ -1,402 +1,277 @@ -# ============================================================================ -# CMake file for LibSourcey -# ============================================================================ - -# ---------------------------------------------------------------------------- -# LibSourcey build paths -# ---------------------------------------------------------------------------- -set(LibSourcey_NAME LibSourcey) -set(LibSourcey_DIR ${CMAKE_CURRENT_LIST_DIR}) -set(LibSourcey_SOURCE_DIR ${LibSourcey_DIR}/src) -set(LibSourcey_VENDOR_SOURCE_DIR ${LibSourcey_DIR}/vendor) -set(LibSourcey_BUILD_DIR ${CMAKE_BINARY_DIR}) -set(LibSourcey_VENDOR_BUILD_DIR ${CMAKE_BINARY_DIR}/vendor) - -set(LibSourcey_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}) -set(LibSourcey_SHARED_INSTALL_DIR ${LibSourcey_INSTALL_DIR}/share/libsourcey) -set(LibSourcey_VENDOR_INSTALL_DIR ${LibSourcey_SHARED_INSTALL_DIR}/vendor) -set(LibSourcey_PKGCONFIG_DIR ${LibSourcey_INSTALL_DIR}/lib/pkgconfig) - -# Set CMake defaults -set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${LibSourcey_DIR}/cmake) -set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} ${LibSourcey_DIR}/cmake) -set(CMAKE_LIBRARY_PATH ${LibSourcey_VENDOR_INSTALL_DIR}/lib ${CMAKE_LIBRARY_PATH}) -set(CMAKE_SYSTEM_PREFIX_PATH ${LibSourcey_VENDOR_INSTALL_DIR}/include ${CMAKE_SYSTEM_PREFIX_PATH}) - -# Include CMake extensions -include(CMakeHelpers REQUIRED) -include(CMakeFindExtensions REQUIRED) -include(LibSourceyUtilities REQUIRED) -include(LibSourceyIncludes REQUIRED) -include(LibSourceyModules REQUIRED) -include(LibSourceyVersion REQUIRED) - -# ---------------------------------------------------------------------------- -# LibSourcey build components -# ---------------------------------------------------------------------------- -set_option(BUILD_SHARED_LIBS "Build shared libraries (.dll/.so) instead of static ones (.lib/.a)" NOT (WIN32 OR ANDROID OR IOS)) -set_option(BUILD_MODULES "Build LibSourcey modules" ON) -set_option(BUILD_APPLICATIONS "Build LibSourcey applications" ON IF CMAKE_COMPILER_IS_GNUCXX) -set_option(BUILD_DEPENDENCIES "Build third party dependencies" ON) -set_option(BUILD_TESTS "Build module test applications?" ON IF CMAKE_COMPILER_IS_GNUCXX) -set_option(BUILD_SAMPLES "Build module sample applications?" ON IF CMAKE_COMPILER_IS_GNUCXX) -set_option(BUILD_WITH_DEBUG_INFO "Include debug info into debug libs" ON) -set_option(BUILD_WITH_STATIC_CRT "Enables statically linked CRT for statically linked libraries" OFF) -set_option(BUILD_ALPHA "Build alpha development modules" OFF) - -# ---------------------------------------------------------------------------- -# LibSourcey build options -# ---------------------------------------------------------------------------- -set_option(ENABLE_SOLUTION_FOLDERS "Solution folder in Visual Studio or in other IDEs" MSVC_IDE IF (CMAKE_VERSION VERSION_GREATER "2.8.0") ) -set_option(ENABLE_PROFILING "Enable profiling in the GCC compiler (Add flags: -g -pg)" OFF IF CMAKE_COMPILER_IS_GNUCXX ) -set_option(ENABLE_OMIT_FRAME_POINTER "Enable -fomit-frame-pointer for GCC" ON IF CMAKE_COMPILER_IS_GNUCXX ) -set_option(ENABLE_POWERPC "Enable PowerPC for GCC" ON IF (CMAKE_COMPILER_IS_GNUCXX AND CMAKE_SYSTEM_PROCESSOR MATCHES powerpc.*) ) -set_option(ENABLE_FAST_MATH "Enable -ffast-math (not recommended for GCC 4.6.x)" OFF IF (CMAKE_COMPILER_IS_GNUCXX AND (X86 OR X86_64)) ) -set_option(ENABLE_SSE "Enable SSE instructions" ON IF (MSVC OR CMAKE_COMPILER_IS_GNUCXX AND (X86 OR X86_64)) ) -set_option(ENABLE_SSE2 "Enable SSE2 instructions" ON IF (MSVC OR CMAKE_COMPILER_IS_GNUCXX AND (X86 OR X86_64)) ) -set_option(ENABLE_SSE3 "Enable SSE3 instructions" OFF IF (CMAKE_COMPILER_IS_GNUCXX AND (X86 OR X86_64)) ) -set_option(ENABLE_SSSE3 "Enable SSSE3 instructions" OFF IF (CMAKE_COMPILER_IS_GNUCXX AND (X86 OR X86_64)) ) -set_option(ENABLE_SSE41 "Enable SSE4.1 instructions" OFF IF (CMAKE_COMPILER_IS_GNUCXX AND (X86 OR X86_64)) ) -set_option(ENABLE_SSE42 "Enable SSE4.2 instructions" OFF IF (CMAKE_COMPILER_IS_GNUCXX AND (X86 OR X86_64)) ) -set_option(ENABLE_NOISY_WARNINGS "Show all warnings even if they are too noisy" OFF ) -set_option(ENABLE_WARNINGS_ARE_ERRORS "Treat warnings as errors" OFF ) -set_option(ENABLE_LOGGING "Enable internal debug logging" ON IF (CMAKE_BUILD_TYPE MATCHES DEBUG) ) -set_option(EXCEPTION_RECOVERY "Attempt to recover from internal exceptions" ON IF (CMAKE_BUILD_TYPE MATCHES DEBUG) ) -set_option(MSG_VERBOSE "Print verbose debug status messages" OFF ) - - -# ---------------------------------------------------------------------------- -# LibSourcey internal options -# ---------------------------------------------------------------------------- -set(LibSourcey_INCLUDE_DIRS "") # CACHE INTERNAL "Global include dirs" FORCE) -set(LibSourcey_LIBRARY_DIRS "") # CACHE INTERNAL "Global include library dirs" FORCE) -set(LibSourcey_INCLUDE_LIBRARIES "") # CACHE INTERNAL "Global include libraries" FORCE) - -set(LibSourcey_BUILD_DEPENDENCIES "" CACHE INTERNAL "Dependencies to build" FORCE) -set(LibSourcey_BUILD_MODULES "" CACHE INTERNAL "Modules to build" FORCE) -set(LibSourcey_BUILD_SAMPLES "" CACHE INTERNAL "Samples to build" FORCE) -set(LibSourcey_BUILD_TESTS "" CACHE INTERNAL "Tests to build" FORCE) -set(LibSourcey_BUILD_APPLICATIONS "" CACHE INTERNAL "Applications to build" FORCE) - -# ---------------------------------------------------------------------------- -# Solution folders: -# ---------------------------------------------------------------------------- -if(ENABLE_SOLUTION_FOLDERS) - set_property(GLOBAL PROPERTY USE_FOLDERS ON) - set_property(GLOBAL PROPERTY PREDEFINED_TARGETS_FOLDER "CMakeTargets") -endif() - -# ---------------------------------------------------------------------------- -# C++ standard: -# ---------------------------------------------------------------------------- -# C++ standard 14 minimum is required -# Wait until CMake >= 3.1 is widely adopted to use CMAKE_CXX_STANDARD -# set(CMAKE_CXX_STANDARD 14) -# set(CMAKE_CXX_STANDARD_REQUIRED on) - -# ---------------------------------------------------------------------------- -# Use statically or dynamically linked CRT? -# Default: dynamic -# ---------------------------------------------------------------------------- -if(MSVC) - include(LibSourceyCRTLinkage REQUIRED) -endif() - -# ---------------------------------------------------------------------------- -# Apple and iOS build options -# ---------------------------------------------------------------------------- -if(APPLE) - # Remove the “MACOSX_RPATH is not specified” warning - # set(CMAKE_MACOSX_RPATH 1) - - # Silence CMake warnings by adopting modern behavior for MACOSX_RPATH on newer - # versions of CMake - if(POLICY CMP0042) - cmake_policy(SET CMP0042 NEW) - endif() - if(IOS) - find_package(Threads REQUIRED) - endif() - if(!IOS) - set(CMAKE_CXX_FLAGS "-std=c++0x ${CMAKE_CXX_FLAGS}") - endif() -endif() - -# ---------------------------------------------------------------------------- -# LibSourcey compiler and linker options -# ---------------------------------------------------------------------------- -include(LibSourceyCompilerOptions REQUIRED) - -# ---------------------------------------------------------------------------- -# Set the LibSourcey_LIB_TYPE variable for add_library -# ---------------------------------------------------------------------------- -set(LibSourcey_LIB_TYPE STATIC) -if(BUILD_SHARED_LIBS) - set(LibSourcey_LIB_TYPE SHARED) -endif() - -# ============================================================================ -# Include Dependencies, Modules and Applications -# -# LibSourcey automatically includes all directories inside the ./src folder. -# Libraries in the LibSourcey source tree are broken up into three types: -# -# Dependency: -# A third party library required by a LibSourcey Modue or Application. -# Dependencies may be external or internal. External dependencies reside -# outside on the source tree, while internal dependencies generally reside -# in the ./deps folder. All dependencies must be built, installed, found -# and included by the build system before Modules and Application can be -# built. -# -# Module: -# A static or dynamic library which extends the LibSourcey core, and is -# included by Applications based on LibSourcey architecture. Modules must -# be built and installed before Applications. -# -# Application: -# A standalone application. These can be built once all Dependencies and -# Modules have been built and installed. -# -# ============================================================================ - -# ---------------------------------------------------------------------------- -# Include standard and defult libraries -# ---------------------------------------------------------------------------- -if(MSVC) - # CMAKE_CXX_STANDARD_LIBRARIES must be a string for MSVC - set(CMAKE_CXX_STANDARD_LIBRARIES "${CMAKE_CXX_STANDARD_LIBRARIES} advapi32.lib iphlpapi.lib psapi.lib shell32.lib ws2_32.lib dsound.lib winmm.lib strmiids.lib") -elseif(MSYS) - set(CMAKE_CXX_STANDARD_LIBRARIES "${CMAKE_CXX_STANDARD_LIBRARIES} -lws2_32 -liphlpapi") #${LibSourcey_INCLUDE_LIBRARIES} -elseif(APPLE) - set(CMAKE_CXX_STANDARD_LIBRARIES "${CMAKE_CXX_STANDARD_LIBRARIES} -ldl") # -lm -lz -llibc -lglibc #${LibSourcey_INCLUDE_LIBRARIES} -elseif(UNIX) - set(CMAKE_CXX_STANDARD_LIBRARIES "${CMAKE_CXX_STANDARD_LIBRARIES} -lm -ldl -lrt") # -lz -lrt -lpulse-simple -lpulse -ljack -llibc -lglibc #${LibSourcey_INCLUDE_LIBRARIES} -endif() -#if (CMAKE_COMPILER_IS_GNUCXX) -# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread") -#endif() - -if(MSVC) - # Temporary workaround for "error LNK2026: module unsafe for SAFESEH image" - # when compiling with certain externally compiled libraries with VS2012, - # such as http://ffmpeg.zeranoe.com/builds/ - # This disables safe exception handling by default. - if(${_MACHINE_ARCH_FLAG} MATCHES X86) - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SAFESEH:NO") - set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /SAFESEH:NO") - set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} /SAFESEH:NO") - endif() - - # No pesky windows min/max macros - add_definitions(-DNOMINMAX) -endif() - - -# ---------------------------------------------------------------------------- -# Include third party dependencies -# ---------------------------------------------------------------------------- - -# Set some required vendor variables for all modules -link_directories(${LibSourcey_VENDOR_INSTALL_DIR}/lib) - -list(APPEND LibSourcey_INCLUDE_DIRS ${LibSourcey_VENDOR_INSTALL_DIR}/include) -if (EXISTS ${LibSourcey_VENDOR_INSTALL_DIR}/lib) - list(APPEND LibSourcey_LIBRARY_DIRS ${LibSourcey_VENDOR_INSTALL_DIR}/lib) -endif() - -# Prefind external dependencies so we can set defaults -# find_package(OpenSSL) -find_package(Threads) -find_package(OpenCV) -find_package(FFmpeg) - -# set_option(WITH_LIBUV "Include LibUV support" ON) -# set_option(WITH_RTAUDIO "Include RtAudio support" ON) -# set_option(WITH_HTTPPARSER "Include HttpParser support" ON) -# set_option(WITH_JSONCPP "Include JsonCpp support" ON) -set_option(WITH_ZLIB "Include zlib support" ON) -set_option(WITH_OPENSSL "Include OpenSSL support" ON) #IF (OPENSSL_FOUND) -set_option(WITH_FFMPEG "Include FFmpeg support" OFF) #ON IF (FFmpeg_FOUND) -set_option(WITH_OPENCV "Include OpenCV support" OFF) #ON IF (OpenCV_FOUND) -set_option(WITH_WEBRTC "Include WebRTC support" OFF) -set_option(WITH_POCO "Include Poco support" OFF) -set_option(WITH_WXWIDGETS "Include wxWidgets support" OFF) - -# Include dependencies -if(APPLE) - status("Including APPLE's foundation and AVFoundation frameworks") - - # Don't use RPATH's. The resulting binary could fail a security audit. - # if (NOT CMAKE_VERSION VERSION_LESS 2.8.12) - # set(CMAKE_MACOSX_RPATH OFF) - # endif() - set(CMAKE_MACOSX_RPATH ON) - - if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - find_library(FOUNDATION Foundation) - find_library(AVFOUNDATION AVFoundation) - - list(APPEND LibSourcey_BUILD_DEPENDENCIES ${FOUNDATION} ${AVFOUNDATION}) - endif() - - #set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -framework Foundation -framework AVFoundation") - #set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /SAFESEH:NO") - #set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} /SAFESEH:NO") -endif() - -# Build dependencies -add_vendor_dependency(LIBUV libuv) -if(WITH_ZLIB) - add_vendor_dependency(ZLIB zlib) - add_vendor_dependency(MINIZIP minizip) -endif() -# if(WITH_JSONCPP) -# add_vendor_dependency(JSONCPP jsoncpp) -# endif() -# add_vendor_dependency(JSON json) -add_vendor_dependency(HTTPPARSER http_parser) - -# External dependencies -if(WITH_WEBRTC) - find_dependency(WebRTC REQUIRED) - - # We will be building with BoringSSL instead of OpenSSL - message(STATUS "Using BoringSSL") - set(WITH_OPENSSL OFF) - set(HAVE_OPENSSL ON) - set(OPENSSL_IS_BORINGSSL ON) - unset(OPENSSL_INCLUDE_DIR CACHE) - unset(LIB_EAY_DEBUG CACHE) - unset(LIB_EAY_RELEASE CACHE) - unset(SSL_EAY_DEBUG CACHE) - unset(SSL_EAY_RELEASE CACHE) - find_path(OPENSSL_INCLUDE_DIR - NAMES openssl/ssl.h - PATHS - ${WEBRTC_ROOT_DIR}/third_party/boringssl/src/include - ${WEBRTC_ROOT_DIR}/include/third_party/boringssl/src/include - NO_DEFAULT_PATH) - list(APPEND LibSourcey_VENDOR_INCLUDE_DIRS ${OPENSSL_INCLUDE_DIR}) -endif() -if(WITH_OPENSSL) - find_dependency(OpenSSL REQUIRED) -endif() -if(WITH_FFMPEG) - find_dependency(FFmpeg REQUIRED) -endif() -if(WITH_OPENCV) - find_dependency(OpenCV REQUIRED) -endif() -if(WITH_POCO) - find_dependency(Poco REQUIRED Util XML CppParser Foundation) -endif() -if(WITH_WXWIDGETS) - # TODO: specify required library options - find_dependency(wxWidgets REQUIRED core base adv) -endif() - -# ---------------------------------------------------------------------------- -# Include the LibSourcey source tree -# ---------------------------------------------------------------------------- - -# Include vendor source dirs -list(APPEND LibSourcey_VENDOR_INCLUDE_DIRS - ${LibSourcey_VENDOR_SOURCE_DIR}/zlib - ${LibSourcey_VENDOR_BUILD_DIR}/zlib - ${LibSourcey_VENDOR_SOURCE_DIR}/minizip - ${LibSourcey_VENDOR_SOURCE_DIR}/libuv/include - ${LibSourcey_VENDOR_SOURCE_DIR}/http_parser - ${LibSourcey_VENDOR_SOURCE_DIR}/json/src) - # ${LibSourcey_VENDOR_SOURCE_DIR}/rtaudio - # ${LibSourcey_VENDOR_SOURCE_DIR}/rtaudio/include - # ${LibSourcey_VENDOR_SOURCE_DIR}/jsoncpp - -# Include inttypes.h for windows -# if (MSVC) -# include_directories(${LibSourcey_VENDOR_SOURCE_DIR}/msvc) -# endif() - -# Enable testing if requested -if (BUILD_TESTS) - enable_testing() -endif() - -# Include source tree modules -subdirlist(subdirs ${LibSourcey_SOURCE_DIR}) -foreach(name ${subdirs}) - # This variable is so modules can set HAVE_LibSourcey_XXX for our - # libsourcey.h inside the child scope. See include_sourcey_modules() - # TODO: Need to refactor since modules may be nested. - set(HAVE_LibSourcey_${name} 0) - set(dir "${LibSourcey_SOURCE_DIR}/${name}") - if (EXISTS "${dir}/CMakeLists.txt") - add_subdirectory(${dir} ${LibSourcey_BUILD_DIR}/${name}) - endif() -endforeach() - -# Condense related sublists into main variables -list(APPEND LibSourcey_INCLUDE_DIRS ${LibSourcey_MODULE_INCLUDE_DIRS} ${LibSourcey_VENDOR_INCLUDE_DIRS}) -list(APPEND LibSourcey_LIBRARY_DIRS ${LibSourcey_MODULE_LIBRARY_DIRS} ${LibSourcey_BUILD_DIR}) -list(APPEND LibSourcey_INCLUDE_LIBRARIES ${LibSourcey_MODULE_INCLUDE_LIBRARIES}) - -# Remove any duplicates from our lists -if(LibSourcey_LINK_LIBRARIES) - list(REMOVE_DUPLICATES LibSourcey_LINK_LIBRARIES) -endif() -if(LibSourcey_BUILD_DEPENDENCIES) - list(REMOVE_DUPLICATES LibSourcey_BUILD_DEPENDENCIES) -endif() - -# ---------------------------------------------------------------------------- -# Install targets -# ---------------------------------------------------------------------------- - -# Install specific vendor headers -install(FILES ${LibSourcey_VENDOR_SOURCE_DIR}/json/src/json.hpp - DESTINATION ${LibSourcey_VENDOR_INSTALL_DIR}/include - COMPONENT dev) - -# Copy CMake files to shared install directory -install(DIRECTORY ${LibSourcey_DIR}/cmake - DESTINATION ${LibSourcey_SHARED_INSTALL_DIR} - COMPONENT dev - FILES_MATCHING PATTERN "CMake*" PATTERN "Find*") - -# ---------------------------------------------------------------------------- -# Install PkgConfig file -# ---------------------------------------------------------------------------- - -set(PKG_CONFIG_LIBS) -foreach(module ${LibSourcey_BUILD_MODULES}) - set(PKG_CONFIG_LIBS "${PKG_CONFIG_LIBS} -lscy_${module}") -endforeach() -foreach(dep ${LibSourcey_BUILD_DEPENDENCIES}) - set(PKG_CONFIG_LIBS "${PKG_CONFIG_LIBS} -l${dep}") -endforeach() - -status("Creating 'libsourcey.pc'") -set(LibSourcey_PC ${LibSourcey_BUILD_DIR}/libsourcey.pc) -configure_file( - ${LibSourcey_DIR}/cmake/libsourcey.pc.cmake.in - ${LibSourcey_PC} @ONLY) -install(FILES ${LibSourcey_PC} DESTINATION ${LibSourcey_PKGCONFIG_DIR} COMPONENT dev) - -# ---------------------------------------------------------------------------- -# Build our libsourcey.h file -# -# A directory will be created for each platform so the "libsourcey.h" file is -# not overwritten if CMake generates code in the same path. -# ---------------------------------------------------------------------------- - -# Variables for libsourcey.h -set(SCY_ENABLE_LOGGING ${ENABLE_LOGGING}) -set(SCY_EXCEPTION_RECOVERY ${EXCEPTION_RECOVERY}) -set(SCY_SHARED_LIBRARY ${BUILD_SHARED_LIBS}) - -status("Creating 'libsourcey.h'") -set(LibSourcey_CONFIG_FILE ${LibSourcey_BUILD_DIR}/libsourcey.h) -configure_file( - ${LibSourcey_DIR}/cmake/libsourcey.h.cmake.in - ${LibSourcey_CONFIG_FILE}) -install(FILES ${LibSourcey_CONFIG_FILE} DESTINATION ${LibSourcey_INSTALL_DIR}/include COMPONENT dev) +# ============================================================================ +# LibSourcey build orchestrator +# +# Sets options, finds dependencies, discovers modules, generates config files. +# Module targets are created by scy_add_module() in LibSourceyModules.cmake. +# ============================================================================ + +# Paths +set(LibSourcey_DIR ${CMAKE_CURRENT_LIST_DIR}) +set(LibSourcey_SOURCE_DIR ${LibSourcey_DIR}/src) +set(LibSourcey_VENDOR_SOURCE_DIR ${LibSourcey_DIR}/vendor) +set(LibSourcey_VENDOR_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/share/libsourcey/vendor) + +# CMake module path +list(APPEND CMAKE_MODULE_PATH ${LibSourcey_DIR}/cmake) + +# Include build system components +include(GNUInstallDirs) +include(CMakePackageConfigHelpers) +include(LibSourceyModules) +include(LibSourceyCompilerOptions) + +# Debug postfix +if(WIN32) + set(LibSourcey_DEBUG_POSTFIX "d") +else() + set(LibSourcey_DEBUG_POSTFIX "") +endif() + +# ---------------------------------------------------------------------------- +# Build options +# ---------------------------------------------------------------------------- +option(BUILD_SHARED_LIBS "Build shared libraries" OFF) +option(BUILD_MODULES "Build LibSourcey modules" ON) +option(BUILD_APPLICATIONS "Build LibSourcey applications" ON) +option(BUILD_TESTS "Build module tests" OFF) +option(BUILD_SAMPLES "Build module samples" OFF) +option(BUILD_ALPHA "Build alpha development modules" OFF) +option(ENABLE_SOLUTION_FOLDERS "IDE solution folders" ON) +option(ENABLE_LOGGING "Enable internal debug logging" ON) +option(EXCEPTION_RECOVERY "Attempt to recover from internal exceptions" OFF) + +# Platform-specific shared lib default +if(NOT DEFINED BUILD_SHARED_LIBS) + if(WIN32 OR ANDROID OR IOS) + set(BUILD_SHARED_LIBS OFF) + else() + set(BUILD_SHARED_LIBS ON) + endif() +endif() + +# Solution folders +if(ENABLE_SOLUTION_FOLDERS) + set_property(GLOBAL PROPERTY USE_FOLDERS ON) + set_property(GLOBAL PROPERTY PREDEFINED_TARGETS_FOLDER "CMakeTargets") +endif() + +# For vendor define_sourcey_dependency compatibility +set(LibSourcey_LIB_TYPE STATIC) +if(BUILD_SHARED_LIBS) + set(LibSourcey_LIB_TYPE SHARED) +endif() + +# ---------------------------------------------------------------------------- +# External dependency options +# ---------------------------------------------------------------------------- +option(WITH_OPENSSL "Include OpenSSL support" ON) +option(WITH_FFMPEG "Include FFmpeg support" OFF) +option(WITH_OPENCV "Include OpenCV support" OFF) + + +# ---------------------------------------------------------------------------- +# Platform libraries +# ---------------------------------------------------------------------------- +if(MSVC) + set(CMAKE_CXX_STANDARD_LIBRARIES + "${CMAKE_CXX_STANDARD_LIBRARIES} advapi32.lib iphlpapi.lib psapi.lib shell32.lib ws2_32.lib dsound.lib winmm.lib strmiids.lib") + add_definitions(-DNOMINMAX) +elseif(MSYS) + set(CMAKE_CXX_STANDARD_LIBRARIES "${CMAKE_CXX_STANDARD_LIBRARIES} -lws2_32 -liphlpapi") +elseif(APPLE) + set(CMAKE_MACOSX_RPATH ON) + set(CMAKE_CXX_STANDARD_LIBRARIES "${CMAKE_CXX_STANDARD_LIBRARIES} -ldl") + if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + find_library(FOUNDATION Foundation) + find_library(AVFOUNDATION AVFoundation) + endif() +elseif(UNIX) + set(CMAKE_CXX_STANDARD_LIBRARIES "${CMAKE_CXX_STANDARD_LIBRARIES} -lm -ldl -lrt") +endif() + +# ---------------------------------------------------------------------------- +# Fetch dependencies (replaces vendored copies) +# ---------------------------------------------------------------------------- +include(FetchContent) + +# libuv - event loop +FetchContent_Declare(libuv + GIT_REPOSITORY https://github.com/libuv/libuv.git + GIT_TAG v1.50.0 + GIT_SHALLOW TRUE) +set(LIBUV_BUILD_TESTS OFF CACHE BOOL "" FORCE) +set(LIBUV_BUILD_BENCH OFF CACHE BOOL "" FORCE) +FetchContent_MakeAvailable(libuv) + +# llhttp - HTTP parser (replaces http_parser) +FetchContent_Declare(llhttp + URL https://github.com/nodejs/llhttp/archive/refs/tags/release/v9.2.1.tar.gz + URL_HASH SHA256=3c163891446e529604b590f9ad097b2e98b5ef7e4d3ddcf1cf98b62ca668f23e) +set(BUILD_SHARED_LIBS_SAVED ${BUILD_SHARED_LIBS}) +set(BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE) +set(BUILD_STATIC_LIBS ON CACHE BOOL "" FORCE) +FetchContent_MakeAvailable(llhttp) +set(BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS_SAVED} CACHE BOOL "" FORCE) + +# zlib +FetchContent_Declare(zlib + GIT_REPOSITORY https://github.com/madler/zlib.git + GIT_TAG v1.3.1 + GIT_SHALLOW TRUE) +set(ZLIB_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE) +set(SKIP_INSTALL_ALL ON CACHE BOOL "" FORCE) +FetchContent_MakeAvailable(zlib) +set(SKIP_INSTALL_ALL OFF CACHE BOOL "" FORCE) + +# Fix zlib's include_directories (uses raw paths, breaks install/export) +# Replace with generator expressions so it can be exported cleanly +FetchContent_GetProperties(zlib SOURCE_DIR zlib_SOURCE_DIR BINARY_DIR zlib_BINARY_DIR) +set_target_properties(zlibstatic PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "") +target_include_directories(zlibstatic PUBLIC + $ + $ + $) + +install(TARGETS zlibstatic + EXPORT LibSourceyTargets + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT dev) + +# nlohmann/json - header-only JSON library +FetchContent_Declare(nlohmann_json + GIT_REPOSITORY https://github.com/nlohmann/json.git + GIT_TAG v3.11.3 + GIT_SHALLOW TRUE) +set(JSON_BuildTests OFF CACHE BOOL "" FORCE) +set(JSON_Install OFF CACHE BOOL "" FORCE) +FetchContent_MakeAvailable(nlohmann_json) + +# minizip - built from zlib's contrib/minizip +set(MINIZIP_SOURCE_DIR ${zlib_SOURCE_DIR}/contrib/minizip) +set(minizip_SOURCES + ${MINIZIP_SOURCE_DIR}/ioapi.c + ${MINIZIP_SOURCE_DIR}/mztools.c + ${MINIZIP_SOURCE_DIR}/unzip.c + ${MINIZIP_SOURCE_DIR}/zip.c) +set(minizip_HEADERS + ${MINIZIP_SOURCE_DIR}/crypt.h + ${MINIZIP_SOURCE_DIR}/ioapi.h + ${MINIZIP_SOURCE_DIR}/mztools.h + ${MINIZIP_SOURCE_DIR}/unzip.h + ${MINIZIP_SOURCE_DIR}/zip.h) +if(WIN32) + list(APPEND minizip_SOURCES ${MINIZIP_SOURCE_DIR}/iowin32.c) +endif() +add_library(minizip STATIC ${minizip_SOURCES} ${minizip_HEADERS}) +target_link_libraries(minizip PRIVATE zlibstatic) +target_include_directories(minizip PUBLIC + $ + $) +if(ENABLE_SOLUTION_FOLDERS) + set_target_properties(minizip PROPERTIES FOLDER "dependencies") +endif() +install(TARGETS minizip + EXPORT LibSourceyTargets + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT dev) +install(FILES ${minizip_HEADERS} + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} COMPONENT dev) + +# ---------------------------------------------------------------------------- +# Find external dependencies +# ---------------------------------------------------------------------------- +find_package(Threads REQUIRED) + +if(WITH_OPENSSL) + find_package(OpenSSL QUIET) + if(OPENSSL_FOUND) + set(HAVE_OPENSSL ON) + message(STATUS " Found OpenSSL: ${OPENSSL_VERSION}") + else() + message(STATUS " OpenSSL not found, disabling SSL-dependent modules") + endif() +endif() + +if(WITH_FFMPEG) + include(FindFFmpeg) + if(FFMPEG_FOUND) + set(HAVE_FFMPEG ON) + endif() +endif() + +if(WITH_OPENCV) + find_package(OpenCV QUIET) + if(OpenCV_FOUND) + set(HAVE_OPENCV ON) + endif() +endif() + +# ---------------------------------------------------------------------------- +# Auto-discover and build modules +# ---------------------------------------------------------------------------- +if(BUILD_MODULES) + message(STATUS "") + message(STATUS " Modules:") + + subdirlist(_module_dirs ${LibSourcey_SOURCE_DIR}) + foreach(_name ${_module_dirs}) + set(_dir "${LibSourcey_SOURCE_DIR}/${_name}") + if(EXISTS "${_dir}/CMakeLists.txt") + add_subdirectory(${_dir} ${CMAKE_BINARY_DIR}/${_name}) + endif() + endforeach() +endif() + +# ---------------------------------------------------------------------------- +# Generate config header (libsourcey.h) +# ---------------------------------------------------------------------------- +set(SCY_ENABLE_LOGGING ${ENABLE_LOGGING}) +set(SCY_EXCEPTION_RECOVERY ${EXCEPTION_RECOVERY}) +set(SCY_SHARED_LIBRARY ${BUILD_SHARED_LIBS}) + +message(STATUS "") +message(STATUS " Generating libsourcey.h") +configure_file( + ${LibSourcey_DIR}/cmake/libsourcey.h.cmake.in + ${CMAKE_BINARY_DIR}/libsourcey.h) +install(FILES ${CMAKE_BINARY_DIR}/libsourcey.h + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} COMPONENT dev) + +# ---------------------------------------------------------------------------- +# Generate pkg-config file +# ---------------------------------------------------------------------------- +set(PKG_CONFIG_LIBS) +foreach(_mod ${LibSourcey_BUILD_MODULES}) + string(APPEND PKG_CONFIG_LIBS " -lscy_${_mod}") +endforeach() + +message(STATUS " Generating libsourcey.pc") +configure_file( + ${LibSourcey_DIR}/cmake/libsourcey.pc.cmake.in + ${CMAKE_BINARY_DIR}/libsourcey.pc @ONLY) +install(FILES ${CMAKE_BINARY_DIR}/libsourcey.pc + DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig COMPONENT dev) + +# ---------------------------------------------------------------------------- +# Install export set and config package +# ---------------------------------------------------------------------------- +install(EXPORT LibSourceyTargets + NAMESPACE LibSourcey:: + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/LibSourcey + COMPONENT dev) + +configure_package_config_file( + ${LibSourcey_DIR}/cmake/LibSourceyConfig.cmake.in + ${CMAKE_BINARY_DIR}/LibSourceyConfig.cmake + INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/LibSourcey) + +write_basic_package_version_file( + ${CMAKE_BINARY_DIR}/LibSourceyConfigVersion.cmake + VERSION ${PROJECT_VERSION} + COMPATIBILITY SameMajorVersion) + +install(FILES + ${CMAKE_BINARY_DIR}/LibSourceyConfig.cmake + ${CMAKE_BINARY_DIR}/LibSourceyConfigVersion.cmake + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/LibSourcey + COMPONENT dev) + +# nlohmann/json installs via its own CMake config (FetchContent) diff --git a/README.md b/README.md index 3cd5cf337..09a865c27 100644 --- a/README.md +++ b/README.md @@ -1,64 +1,86 @@ # LibSourcey -> C++ Networking Evolved - -[![Circle CI](https://circleci.com/gh/sourcey/libsourcey.svg?style=shield&circle-token=ab142562b19bb857de796d729aab28fa9df7682d)](https://circleci.com/gh/sourcey/libsourcey) -[![Doxygen](https://sourcey.com/images/doxygen.svg)](https://sourcey.com/libsourcey) - - -LibSourcey is a collection of cross platform C++14 modules and classes that provide developers with an arsenal for rapidly developing high performance network based p2p and media streaming applications. Think of it as the power and performance of `libuv` combined with the features of `FFmpeg`, `OpenCV` and `WebRTC`, all integrated with the ease and readability of the `stl` (C++ Standard Library). +[![CI](https://github.com/sourcey/libsourcey/actions/workflows/ci.yml/badge.svg)](https://github.com/sourcey/libsourcey/actions/workflows/ci.yml) +[![License: LGPL-2.1+](https://img.shields.io/badge/license-LGPL--2.1%2B-blue.svg)](LICENSE.md) -* **Documentation**: [https://sourcey.com/libsourcey](https://sourcey.com/libsourcey) -* **Repository**: [https://github.com/sourcey/libsourcey](https://github.com/sourcey/libsourcey) -* **Licence**: [LGPL-2.1+](/LICENSE.md) +> C++ Networking Evolved -## Basic features +LibSourcey is a collection of cross-platform C++20 modules for building high-performance networked and media streaming applications. It combines the async IO of `libuv` with `OpenSSL`, `FFmpeg`, and modern C++ to provide a clean, modular toolkit for servers, clients, and real-time communication. All dependencies are managed via CMake FetchContent - just add LibSourcey to your project and build. -* **Event-based IO** — Core modules are built on top of `libuv` (the underlying C library that powers `nodejs`) and use event-based asynchronous IO throughout to maximize performance and minimize concurrency reliance for building mission critical native and server side apps. +**Version 2.0** - Complete modernisation: C++20, OpenSSL 3.x, FFmpeg 6+, llhttp, smart pointers throughout, zero `assert()` in production code, comprehensive test coverage. See [CHANGELOG.md](CHANGELOG.md) for details. -* **Cross platform** — The codebase is cross platform and should compile on any system with access to a modern C++14 compiler. +* **Documentation**: [doc/](doc/SUMMARY.md) +* **Repository**: [https://github.com/sourcey/libsourcey](https://github.com/sourcey/libsourcey) +* **Licence**: [LGPL-2.1+](LICENSE.md) -* **Modular libraries** — Libraries are modular for easy integration into your existing projects, so you can just "include what you need" without incurring extra incumbent bloat. +## Features -* **Well tested** — Core modules are well tested with unit tests and stress tested daily in production. +* **Event-based IO** - Built on `libuv` for asynchronous, non-blocking IO across all platforms. +* **Cross platform** - Compiles on Linux, macOS and Windows with any C++20 compiler (GCC 12+, Clang 15+, MSVC 2022+, AppleClang 15+). +* **Modular libraries** - Include only what you need. Each module is self-contained with automatic dependency resolution via CMake. +* **Solid networking** - TCP, SSL/TLS, and UDP sockets built on `libuv` and `OpenSSL`. +* **HTTP stack** - Servers, clients, WebSockets, media streaming, file transfers, and authentication. HTTP parsing via `llhttp`. +* **Media encoding** - The `av` module wraps `FFmpeg` for capture, encoding, recording, streaming and analysis. +* **Real-time messaging** - Socket.IO client (protocol revision 4) and Symple messaging protocol. +* **STUN/TURN** - Full RFC 5766 TURN server/client with RFC 5389 STUN for NAT traversal. +* **Docker images** - Multi-stage Ubuntu 24.04 images available via the included `Dockerfile`. -* **Clean and readable code** — Modern C++ design principles have been adhered to throughout for clean and readable code. +## Quick start -* **Networking layer** — A solid network layer is absolutely essential. The networking layer contains TCP, SSL and UDP socket implementations that combine `libuv` under the hood for blazing fast networking, and `openssl` for security and encryption. +### Requirements -* **Media streaming and encoding** — The `av` library consists of thin wrappers around `FFmpeg` and `OpenCV` for media capture, encoding, recording, streaming, analysis and more. +| Platform | Compiler | +|----------|----------| +| Linux | GCC 12+ or Clang 15+ | +| macOS | AppleClang 15+ (Xcode 15+) | +| Windows | MSVC 2022 (Visual Studio 17+) | -* **Easy install** — LibSourcey can be packaged as a `deb`, `rpm`, `tar.gz`, `zip` and many other formats with a [single command](https://sourcey.com/libsourcey/installation#building-packages) for straight forward distribution and integration. +Dependencies: CMake 3.21+, pkg-config (Linux/macOS). The following are fetched automatically via FetchContent if not found on the system: -* **Web servers and clients** — A HTTP stack is provided that includes servers, clients, WebSockets, media streaming, file transfers, and authentication. The HTTP parser is based on the super-fast C code used by `nginx`. +| Dependency | Version | +|------------|---------| +| libuv | 1.50 | +| llhttp | 9.2.1 | +| OpenSSL | 3.x | +| nlohmann/json | 3.11.3 | +| zlib | 1.3.1 | -* **Realtime messaging** — LibSourcey aims to bridge the gap between desktop, mobile and web by providing performance oriented messaging solutions that work across all platforms. - * **Socket.IO** — Socket.IO C++ client that supports the latest protocol revision 4 (>= 1.0). Read more about [Socket.IO](http://socket.io). - * **Symple** — Sourcey's home grown realtime messaging protocol that works over the top of Socket.IO to provide rostering, presence and many other features necessary for building online games and chat applications. [More about Symple](https://sourcey.com/symple). +### CMake FetchContent -* **WebRTC support** — WebRTC native support allows you to build p2p desktop and server side applications that inherit LibSourcey's realtime messaging and media capabilities. Take a look at the [examples](https://sourcey.com/libsourcey/examples/) for how to stream live webcam and microphone streams to the browser, and also how to record live WebRTC streams on the server side. +```cmake +include(FetchContent) +FetchContent_Declare(libsourcey + GIT_REPOSITORY https://github.com/sourcey/libsourcey.git + GIT_TAG master +) +FetchContent_MakeAvailable(libsourcey) +target_link_libraries(myapp PRIVATE scy_base scy_net scy_crypto) +``` - +### Build from source -## Getting started +```bash +git clone https://github.com/sourcey/libsourcey.git +cd libsourcey +cmake -B build -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTS=ON +cmake --build build --parallel $(nproc) +ctest --test-dir build --output-on-failure +``` -See the [installation guides](https://sourcey.com/libsourcey/installation) in the docs to get started playing with LibSourcey. +### find_package -## A few examples +After installing (`cmake --install build`): -What better way to get acquainted with a new library then with some tasty code examples. +```cmake +find_package(LibSourcey REQUIRED) +target_link_libraries(myapp PRIVATE scy_base scy_net scy_http) +``` -#### HTTP echo server +## Examples -Lets start with the classic HTTP echo server, which looks something like this: +### HTTP echo server -~~~cpp +```cpp http::Server srv{ "127.0.0.1", 1337 }; srv.Connection += [](http::ServerConnection::Ptr conn) { conn->Payload += [](http::ServerConnection& conn, const MutableBuffer& buffer) { @@ -67,128 +89,71 @@ srv.Connection += [](http::ServerConnection::Ptr conn) { }; }; srv.start(); -~~~ - -Pretty neat right? Its crazy fast too, especially on Linux kernel 3.9 or newer where its optimized to use of kernel level multicore socket load balancing. Don't take our word for it though, here are some benchmarks using `wrk`: - -**LibSourcey `httpechoserver`** - -~~~bash -$ wrk -d10s --timeout 2s http://localhost:1337 -Running 10s test @ http://localhost:1337 - 2 threads and 10 connections - Thread Stats Avg Stdev Max +/- Stdev - Latency 265.76us 472.62us 12.42ms 97.51% - Req/Sec 18.84k 1.26k 21.57k 74.50% - 375060 requests in 10.01s, 20.39MB read -Requests/sec: 37461.50 -Transfer/sec: 2.04MB -~~~ - -**Nodejs echo server** - -~~~bash -$ wrk -d10s --timeout 2s http://localhost:1337 -Running 10s test @ http://localhost:1337 - 2 threads and 10 connections - Thread Stats Avg Stdev Max +/- Stdev - Latency 502.70us 715.11us 14.83ms 97.90% - Req/Sec 11.69k 1.46k 14.52k 70.50% - 232667 requests in 10.01s, 21.97MB read -Requests/sec: 23236.33 -Transfer/sec: 2.19MB -~~~ - -As you can see the `httpechoserver` is almost twice as fast as the dead simple `nodejs` echo server, which is not a bad performance gain over one of the web's leading technologies thats touted for it's performance. Check the `httpechoserver` sample for the full code, including the `nodejs` echo server we used for benchmarking. - -#### Processes - -Interacting with system processes and piping IO doesn't have to be painful. -The following code will run the `ping sourcey.com` and with `stdio` and exit callbacks: - -~~~cpp -Process proc{ "ping", "sourcey.com" }; -proc.onstdout = [](std::string line) -{ +``` + +### Process IO + +```cpp +Process proc{ "ping", "example.com" }; +proc.onstdout = [](std::string line) { // handle process output }; -proc.onexit = [](std::int64_t status) -{ +proc.onexit = [](std::int64_t status) { // handle process exit }; proc.spawn(); +``` -// write some random data to the stdin pipe -proc.in() << "random data" -~~~ - -#### PacketStream - -A good starting point for learning LibSourcey is the `PacketStream`, which lets you create a dynamic delegate chain for piping, processing and outputting arbitrary data packets. This method of layering packet processors and makes it possible to develop complex data processing applications on the fly. - -For example, the code below captures a live webcam stream, encodes it into H.264, and then finally broadcasts it in realtime over the internet: +### Media streaming -~~~cpp -// Create a PacketStream to pass packets from the -// input device captures -> encoder -> socket +```cpp PacketStream stream; -// Setup the encoder options av::EncoderOptions options; options.oformat = av::Format{"MP4", "mp4", { "H.264", "libx264", 640, 480, 25, 48000, 128000, "yuv420p" }, { "AAC", "aac", 2, 44100, 64000, "fltp" }}; -// Create a device manager instance to enumerate system devices av::DeviceManager devman; av::Device device; -// Create and attach the default video capture -av::VideoCapture::Ptr video; if (devman.getDefaultCamera(device)) { - video.open(device.id, 640, 480); - video.getEncoderFormat(options.iformat); + auto video = std::make_shared(device.id, 640, 480); + video->getEncoderFormat(options.iformat); stream.attachSource(video, true); } -// Create and attach the default audio capture -av::AudioCapture::Ptr audio; -if (devman.getDefaultMicrophone(device)) { - audio.open(device.id, 2, 44100); - audio.getEncoderFormat(options.iformat); - stream.attachSource(audio, true); -} - -// Create and attach the multiplex encoder av::MultiplexPacketEncoder::Ptr encoder(options); stream.attach(encoder); +stream.attach(socket); // broadcast over network +stream.start(); +``` -// Attach the output net::Socket instance (instantiated elsewhere) -// to broadcast encoded packets over the network -stream.attach(socket); +## Regenerating API docs -// Start the stream -// This method call will start the device captures and begin -// pumping encoded media into the output socket -stream.start(); -~~~ +The API reference in `doc/` is generated from source code using [Doxygen](https://www.doxygen.nl/) and [Moxygen](https://github.com/sourcey/moxygen). + +Prerequisites: `doxygen` and `npx` (Node.js). -There are plenty more demos and sample code to play with over on the [examples](https://sourcey.com/libsourcey/examples/) page. +```bash +make docs +``` + +This runs Doxygen to parse the C++ source into XML, then Moxygen to convert it into markdown files (`doc/api-*.md`). ## Contributors A massive thanks to everyone who has contributed to making LibSourcey awesome: -* Kam Low ([@auscaster](https://github.com/auscaster)) — Primary developer -* Yury Shulbn ([@yuryshubin](https://github.com/yuryshubin)) — iOS build toolchain and platform fixes -* Vinci Xu ([@VinciShark](https://github.com/VinciShark)) — Windows documentation, testing and updates -* Michael Fig ([@michael-fig](https://github.com/michael-fig)) — Fixed compiler flags to build without FFmpeg -* Hyunuk Kim ([@surinkim](https://github.com/surinkim)) — Fixed `std::codecvt` unicode character conversion on Windows -* Damian Zelim ([@ZelimDamian](https://github.com/ZelimDamian)) — Fixed compiler flags for OS X build -* Norm Ovenseri ([@normano](https://github.com/normano)) — Added verbose logging output to build system -* Alexey ([@deilos](https://github.com/deilos)) — Fixed cross-platform FFmpeg build script -* Kryton ([@Malesio](https://github.com/Malesio)) — Fixed segfaults in samples and tidied up Valgrind warnings - +* Kam Low ([@auscaster](https://github.com/auscaster)) - Primary developer +* Yury Shulbn ([@yuryshubin](https://github.com/yuryshubin)) - iOS build toolchain and platform fixes +* Vinci Xu ([@VinciShark](https://github.com/VinciShark)) - Windows documentation, testing and updates +* Michael Fig ([@michael-fig](https://github.com/michael-fig)) - Fixed compiler flags to build without FFmpeg +* Hyunuk Kim ([@surinkim](https://github.com/surinkim)) - Fixed `std::codecvt` unicode character conversion on Windows +* Damian Zelim ([@ZelimDamian](https://github.com/ZelimDamian)) - Fixed compiler flags for OS X build +* Norm Ovenseri ([@normano](https://github.com/normano)) - Added verbose logging output to build system +* Alexey ([@deilos](https://github.com/deilos)) - Fixed cross-platform FFmpeg build script +* Kryton ([@Malesio](https://github.com/Malesio)) - Fixed segfaults in samples and tidied up Valgrind warnings ## Contributing @@ -199,9 +164,3 @@ Pull Requests are always welcome, so if you fix or make anything better then fee 3. Commit your changes (`git commit -am 'Add some feature'`) 4. Push to the branch (`git push origin my-new-feature`) 5. Create new Pull Request - - diff --git a/TODO.md b/TODO.md index acf184ef5..0a331ddf9 100644 --- a/TODO.md +++ b/TODO.md @@ -1,19 +1,208 @@ -# TODO +# LibSourcey v2 - Modernisation Plan -BoringSSL not showing in build summary -Copy samples data to install folder and add to packages -Replace the use of CMake LibSourcey_XXX variables and set_target_xxx function to set dependencies on a target specific basis -Move sched to separate repo -Fix deprecated ICE code -Figure out a way for PacketStream chains to integrate with uv::Stream - see uv_link_t +> C++20, modern dependencies, production-ready quality. +**Status:** Ready for 2.0 release. All phases complete. -# Documentation +CMake 3.21 minimum, deps via FetchContent (libuv 1.50, llhttp 9.2.1, zlib 1.3.1, nlohmann/json 3.11.3, OpenSSL 3.x, FFmpeg 5+). -Improve av module documentation +--- +## Completed Work (2.0) -# Tests +### Phase 1: Build System Overhaul - DONE -Video encoder test changing input resolution -WebRTC two way chat demo +Target-based CMake with `scy_add_module()`, `install(EXPORT)`, CMakePresets.json, GNUInstallDirs. WebRTC removed. All dead cmake/vendor files deleted. + +### Phase 2: Dependency Updates - DONE + +- libuv 1.11 -> 1.50 (FetchContent) +- OpenSSL 1.x -> 3.x (full API migration: EVP, TLS_method, removed locking callbacks) +- http_parser -> llhttp 9.2.1 +- nlohmann/json 2.1 -> 3.11.3 +- zlib 1.2.8 -> 1.3.1 +- FFmpeg API migrated to 5+/6+/7+ (send/receive, codecpar, iterator APIs) +- OpenCV FindModule updated for 4.x +- Dead deps removed: Poco, wxWidgets, rtaudio, dshow, msvc headers + +### Phase 3: C++ Modernisation - DONE (2.0 scope) + +- `#pragma once` on all headers +- `[[nodiscard]]`, `noexcept`, `enum class` throughout +- `typedef` -> `using`, `NULL` -> `nullptr` +- `std::string_view` (util, http/url), structured bindings, `constexpr` constants +- `std::filesystem` replaces custom path handling +- `std::chrono` replaces custom timing +- `std::shared_mutex` for read-heavy patterns (collection.h, signal.h) +- Raw `new`/`delete` -> smart pointers across all modules +- Signal `StopPropagation` exception replaced with `bool` return +- `IPacket::source` removed, typed `avptr` for AV pipeline + +### Phase 4: Module-by-Module - DONE + +#### base + +Bugs fixed, asserts replaced with throws throughout (handle, stream, packetqueue, packetstream, datetime, timer, runner, thread, numeric, random, logger, streammanager, diagnosticmanager, application, util). Dead `#if 0` blocks removed. IPC timeout added. Signal slot ID uniqueness enforced. UV_EOF handled as graceful close. Tests: buffer, random, base64, datetime, error, stateful, util strings, platform, filesystem, thread, signal, timer pause/resume, timer one-shot, IPC round-trip, logger filtering. + +#### crypto + +Full OpenSSL 3.x migration. RAII wrappers for EVP_MD_CTX, EVP_CIPHER_CTX, X509. Asserts replaced. Tests: X509, HMAC, SHA-256/512, cipher edge cases, hash edge cases, hex, file checksum. + +#### net + +OpenSSL 3.x migration. ALPN + SNI support added. Hostname verification via `SSL_set1_host()` + `SSLSocket::connect(host, port)`. TLS 1.2 minimum enforced. All asserts replaced across socketemitter, sslsocket, socketadapter, packetsocket, udpsocket, address. Dead `#if 0` blocks removed (socketemitter.h, packetsocket.h/.cpp). Tests: IPv6, address ops, service resolution. + +#### http + +llhttp migration. WebSocket RFC 6455 compliance (RSV, opcode, mask, ping/pong/close). Raw `new`/`delete` -> `unique_ptr` throughout. Download progress tracking via `ClientConnection::IncomingProgress`. Dead `#if 0` removed (client.h, util.cpp). Tests: URL, cookie, authenticator, credentials, StringPart. + +#### json, socketio, symple + +Modernised, tests added for all. + +#### av + +Full FFmpeg 5+/6+/7+ migration (send/receive API, codecpar, iterator APIs, device enumeration). All asserts replaced across encoders, decoders, contexts, buffers, devicemanager, packet. Thread safety: mutex on PTS, atomics on MediaCapture flags, lock guards on create/close. Fixed MediaCapture loop seek bug. RAII via constructor/destructor pattern. Dead code removed (deprecated/ directory, `#if 0` blocks). Tests: Format, FormatRegistry, FPSCounter. + +#### stun/turn + +Fixed ChannelNumber factory bug, permission lifetime, bit shift UB, Server::stop() null. Tests added for both. + +#### util -> merged into base + +Chrono timing fix, UserManager deleted, all headers moved to `include/scy/`. Tests: Timeout, TimedToken, RateLimiter, IRegistry. + +#### sched + +Trigger ownership migrated to `unique_ptr`. Asserts replaced. + +#### archo + +`std::filesystem::path` migration. Path traversal protection in zip extraction. Fixed closeCurrentFile bug. Tests added. + +#### pacm + +SHA256 checksums (was MD5). SSL verification enabled. Path traversal protection. Download progress re-enabled. `latestSDKAsset` logic simplified. All asserts replaced. Dead code removed. + +### Phase 5: Testing - DONE + +Tests added for all 15 modules. Sanitizer builds (ASan, TSan, UBSan). Code coverage reporting. Samples cleaned. + +### Phase 6: CI/CD & Quality - DONE + +GitHub Actions (Linux GCC 13/14 + Clang 18, macOS, Windows MSVC 2022, sanitizers, coverage). Docker Ubuntu 24.04. `.clang-format` + `.clang-tidy`. Entire codebase formatted. + +### Phase 7: Documentation & Packaging - DONE + +README updated. Doxygen config. BUILD.md. vcpkg port. CPack. GitHub Releases with changelog. Version 2.0.0. + +--- + +## Remaining for 2.0 (non-blocking) + +### Test gaps - ALL FILLED + +All tests passing. Standalone VideoEncoder, VideoDecoder, AudioDecoder tests added and verified with FFmpeg 6.1. + +### Tests added for 2.0 + +- PacketStream overflow handling (fast producer stress test with bounded SyncPacketQueue) +- HTTP request/response serialization round-trip (GET, POST, headers, parse-back) +- WebSocket frame encoding/decoding (text, binary, client masking, control frames) +- pacm module tests (Package JSON round-trip, asset selection, LocalPackage state, manifest, errors, InstallationState) + +--- + +## Post-2.0 Roadmap + +Major features deferred to future releases. + +### 2.1 - Networking + +- Connection timeout support (read/write/connect) +- HTTP proxy (CONNECT, SOCKS5) +- HTTP connection pooling and keep-alive +- TLS 1.3 (0-RTT, session tickets, key update) +- Certificate pinning +- OCSP stapling +- ~~WebSocket fragmentation + partial frame buffering~~ DONE (2.0) +- ~~HTTP backpressure signalling~~ DONE (2.0, Stream write queue high water mark) + +### 2.2 - AV + +- Hardware acceleration (NVENC, QuickSync, VideoToolbox, VAAPI) +- HLS/DASH output +- Rate control modes (VBR, CRF, two-pass) +- Subtitle stream handling +- Public seek API +- Encoding statistics/metrics +- VideoPacket/AudioPacket ownership semantics + +### 2.3 - C++ Modernisation + +- `std::jthread` + `std::stop_token` replacing Thread/Runner +- Coroutine-based scheduling (C++20) +- `std::span` for pointer + size pairs +- `std::format` replacing ostringstream +- `concept` constraints replacing SFINAE +- Signal/slot delegate simplification +- GarbageCollector/deleteLater audit +- Error strategy (scy::Error vs std::error_code vs std::expected) +- Mutex deadlock audit +- `std::optional` for nullable returns +- MutableBuffer/ConstBuffer -> `std::span` evaluation +- spdlog evaluation + +### 2.4 - Package Manager + +- Package signature verification (RSA/ECDSA) +- Dependency resolution +- Rollback on failed install +- Mirror failover +- Incremental/delta updates +- Download resume +- Version range constraints +- Remote package caching +- CLI credential handling (not command-line args) + +### 2.5 - Quality + +- Fuzz testing (HTTP, STUN, JSON parsers) +- Benchmark suite (nanobench or Google Benchmark) +- clang-tidy modernize passes +- minizip-ng API update + +--- + +## Module Decisions + +| Module | Status | Decision | +|--------|--------|----------| +| base | Core | Keep | +| net | Core | Keep | +| crypto | Core | Keep | +| http | Core | Keep | +| json | Core | Keep | +| socketio | Active | Keep | +| symple | Active | Evaluate | +| av | Optional | Keep | +| archo | Optional | Keep | +| stun | Optional | Keep | +| turn | Optional | Keep | +| sched | Optional | Keep or extract | +| util | Merged | Into base | +| webrtc | Removed | Dropped | +| pacm | External | Keep | +| pluga | External | Keep | + +--- + +## Architecture Notes + +### Build System + +`scy_add_module(name DEPENDS dep1 dep2 PACKAGES Pkg::Lib)` is the core abstraction. Auto-discovery via `subdirlist`, platform filtering, install/export generation. External module plugin via `src/.gitignore` whitelist. + +### Custom GC & Deferred Deletion + +`GarbageCollector`/`deleteLater` exists because libuv callbacks capture `void* data` - deferred deletion on the event loop thread prevents use-after-free. Post-2.0: evaluate whether modern libuv + smart pointers can replace this. diff --git a/VERSION b/VERSION index 6d7de6e6a..227cea215 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.0.2 +2.0.0 diff --git a/circle.yml b/circle.yml deleted file mode 100644 index 01cdbbcad..000000000 --- a/circle.yml +++ /dev/null @@ -1,19 +0,0 @@ -dependencies: - pre: - - curl -sSL https://cmake.org/files/v3.4/cmake-3.4.0-Linux-x86_64.tar.gz | sudo tar -xzC /opt - - git clone git@github.com:sourcey/pacm.git src/pacm - - git clone git@github.com:sourcey/pluga.git src/pluga - - sudo add-apt-repository --yes ppa:kirillshkrogalev/ffmpeg-next - - sudo add-apt-repository --yes ppa:ubuntu-toolchain-r/test - - sudo apt-get update - - sudo apt-get install --yes libavcodec-ffmpeg-dev libavdevice-ffmpeg-dev libavfilter-ffmpeg-dev libavformat-ffmpeg-dev libswresample-ffmpeg-dev libpostproc-ffmpeg-dev - - sudo apt-get install --yes alsa-base alsa-utils libasound2 libasound2-dev - - sudo apt-get install --yes gcc-5 g++-5 - - sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-5 60 --slave /usr/bin/g++ g++ /usr/bin/g++-5 - - mkdir -p /tmp/webrtc-17657-02ba69d-linux-x64; curl -sSL https://github.com/sourcey/webrtc-precompiled-builds/raw/master/webrtc-17657-02ba69d-linux-x64.tar.gz | sudo tar -xzC /tmp/webrtc-17657-02ba69d-linux-x64 - override: - - mkdir build; cd build; /opt/cmake-3.4.0-Linux-x86_64/bin/cmake .. -DWITH_FFMPEG=ON -DWITH_WEBRTC=ON -DWEBRTC_ROOT_DIR=/tmp/webrtc-17657-02ba69d-linux-x64 - - cd build; make; sudo make install -test: - override: - - cd build; make check diff --git a/cmake/CMakeFindExtensions.cmake b/cmake/CMakeFindExtensions.cmake deleted file mode 100644 index 680d8cf7d..000000000 --- a/cmake/CMakeFindExtensions.cmake +++ /dev/null @@ -1,377 +0,0 @@ -# -### Macro: find_library_extended -# -# Finds libraries with finer control over search paths -# for compilers with multiple configuration types. -# -macro(find_library_extended prefix) - include(CMakeParseArguments REQUIRED) - # cmake_parse_arguments(prefix options singleValueArgs multiValueArgs ${ARGN}) - cmake_parse_arguments(${prefix} "" "" - "NAMES;NAMES_DEBUG;NAMES_RELEASE;PATHS_DEBUG;PATHS_RELEASE;PATHS" - ${ARGN} - ) - - # Reloading to ensure build always passes and picks up changes - # This is more expensive but proves useful for fragmented libraries like WebRTC - unset(${prefix}_LIBRARY_DEBUG CACHE) - find_library(${prefix}_LIBRARY_DEBUG - NAMES - ${${prefix}_NAMES_DEBUG} - ${${prefix}_NAMES} - PATHS - ${${prefix}_PATHS_DEBUG} - ${${prefix}_PATHS} - ) - - #if(NOT ${prefix}_PATHS_RELEASE) - # list(APPEND ${prefix}_PATHS_RELEASE ${${prefix}_PATHS}) - #endif() - - unset(${prefix}_LIBRARY_RELEASE CACHE) - find_library(${prefix}_LIBRARY_RELEASE - NAMES - ${${prefix}_NAMES_RELEASE} - ${${prefix}_NAMES} - PATHS - ${${prefix}_PATHS_RELEASE} - ${${prefix}_PATHS} - ) - - if(${prefix}_LIBRARY_DEBUG OR ${prefix}_PATHS_RELEASE) - include(${CMAKE_ROOT}/Modules/SelectLibraryConfigurations.cmake) - select_library_configurations(${prefix}) - endif() - - # print_module_variables(${prefix}) - - # message("*** Find library for ${prefix}") - # message("Debug Library: ${${prefix}_LIBRARY_DEBUG}") - # message("Release Library: ${${prefix}_LIBRARY_RELEASE}") - # message("Library: ${${prefix}_LIBRARY}") - # message("Debug Paths: ${${prefix}_PATHS_RELEASE}") - # message("Release Paths: ${${prefix}_PATHS_DEBUG}") - # message("Paths: ${${prefix}_PATHS}") - # message("Debug Names: ${${prefix}_NAMES_RELEASE}") - # message("Release Names: ${${prefix}_NAMES_DEBUG}") - # message("Names: ${${prefix}_NAMES}") -endmacro(find_library_extended) - - -# -### Macro: set_component_alias -# -# Sets the current module component alias variables. -# -macro(set_component_alias module component) - set(ALIAS ${module}_${component}) - set(ALIAS_FOUND ${ALIAS}_FOUND) - set(ALIAS_LIBRARIES ${ALIAS}_LIBRARIES) - set(ALIAS_LIBRARY_RELEASE ${ALIAS}_LIBRARY_RELEASE) - set(ALIAS_LIBRARY_DEBUG ${ALIAS}_LIBRARY_DEBUG) - set(ALIAS_INCLUDE_DIRS ${ALIAS}_INCLUDE_DIRS) - set(ALIAS_LIBRARY_DIRS ${ALIAS}_LIBRARY_DIRS) - set(ALIAS_DEFINITIONS ${ALIAS}_CFLAGS_OTHER) - set(ALIAS_VERSION ${ALIAS}_VERSION) - string(TOUPPER ${ALIAS} ALIAS_UPPER) -endmacro() - - -# -### Macro: set_module_found -# -# Marks the given module as found if all required components are present. -# -macro(set_module_found module) - set(${module}_FOUND FALSE) - - # Compile the list of required vars - set(_${module}_REQUIRED_VARS ${module}_LIBRARIES) # ${module}_INCLUDE_DIRS - foreach (component ${${module}_FIND_COMPONENTS}) - # NOTE: Not including XXX_INCLUDE_DIRS as required var since it may be empty - list(APPEND _${module}_REQUIRED_VARS ${module}_${component}_LIBRARIES) # ${module}_${component}_INCLUDE_DIRS - if (NOT ${module}_${component}_FOUND) - if (${module}_FIND_REQUIRED) - message(FATAL_ERROR "Required ${module} component ${component} missing. Please recompile ${module} with ${component} enabled.") - endif() - else() - messageV(" - Required ${module} component ${component} found.") - endif() - endforeach() - - # Cache the vars. - set(${module}_INCLUDE_DIRS ${${module}_INCLUDE_DIRS} CACHE STRING "The ${module} include directories." FORCE) - set(${module}_LIBRARY_DIRS ${${module}_LIBRARY_DIRS} CACHE STRING "The ${module} library directories." FORCE) - set(${module}_LIBRARIES ${${module}_LIBRARIES} CACHE STRING "The ${module} libraries." FORCE) - set(${module}_FOUND ${${module}_FOUND} CACHE BOOLEAN "The ${module} found status." FORCE) - - # Ensure required variables have been set, or fail in error. - # NOTE: Disabling find_package_handle_standard_args check since it's always - # returning false even when variables are set. Maybe an internal CMake issue? - # if (${module}_FIND_REQUIRED) - # - # # Give a nice error message if some of the required vars are missing. - # include(FindPackageHandleStandardArgs) - # find_package_handle_standard_args(${module} DEFAULT_MSG ${_${module}_REQUIRED_VARS}) - # endif() - - # Set the module as found. - if (${module}_LIBRARIES) - set(${module}_FOUND TRUE) - else() - message(WARNING "Failed to locate ${module}. Please specify paths manually.") - endif() - - mark_as_advanced(${module}_INCLUDE_DIRS - ${module}_LIBRARY_DIRS - ${module}_LIBRARIES - ${module}_DEFINITIONS - ${module}_FOUND) -endmacro() - - -# -### Macro: set_component_found -# -# Marks the given component as found if both *_LIBRARIES AND *_INCLUDE_DIRS are present. -# -macro(set_component_found module component) - set_component_alias(${module} ${component}) - - messageV("${ALIAS_LIBRARIES}=${${ALIAS_LIBRARIES}}") - messageV("${ALIAS_INCLUDE_DIRS}=${${ALIAS_INCLUDE_DIRS}}") - messageV("${ALIAS_LIBRARY_DIRS}=${${ALIAS_LIBRARY_DIRS}}") - - #if (${module}_${component}_LIBRARIES AND ${module}_${component}_INCLUDE_DIRS) - if (${ALIAS_LIBRARIES}) # AND ${ALIAS_INCLUDE_DIRS} (XXX_INCLUDE_DIRS may be empty) - messageV(" - ${module} ${component} found.") - set(${ALIAS_FOUND} TRUE) - # set(${ALIAS_FOUND} TRUE PARENT_SCOPE) - - # Add component vars to the parent module lists - append_unique_list(${module}_INCLUDE_DIRS ${ALIAS_INCLUDE_DIRS}) - append_unique_list(${module}_LIBRARY_DIRS ${ALIAS_LIBRARY_DIRS}) - append_unique_list(${module}_LIBRARIES ${ALIAS_LIBRARIES}) - append_unique_list(${module}_DEFINITIONS ${ALIAS_DEFINITIONS}) - - # set(${module}_INCLUDE_DIRS ${${module}_INCLUDE_DIRS} PARENT_SCOPE) - # set(${module}_LIBRARY_DIRS ${${module}_LIBRARY_DIRS} PARENT_SCOPE) - # set(${module}_LIBRARIES ${${module}_LIBRARIES} PARENT_SCOPE) - # set(${module}_DEFINITIONS ${${module}_DEFINITIONS} PARENT_SCOPE) - - # messageV("Find Component Paths=${module}:${component}:${library}:${header}") - # messageV("${ALIAS_INCLUDE_DIRS}=${${ALIAS_INCLUDE_DIRS}}") - # messageV("${ALIAS_LIBRARY_RELEASE}=${${ALIAS_LIBRARY_RELEASE}}") - # messageV("${ALIAS_LIBRARY_DEBUG}=${${ALIAS_LIBRARY_DEBUG}}") - # messageV("${ALIAS_LIBRARIES}=${${ALIAS_LIBRARIES}}") - # messageV("${module}_INCLUDE_DIRS=${${module}_INCLUDE_DIRS}") - # messageV("${module}_LIBRARIES=${${module}_LIBRARIES}") - - # Only mark as advanced when found - mark_as_advanced(${ALIAS_INCLUDE_DIRS} - ${ALIAS_LIBRARY_DIRS}) - - else() - # NOTE: an error message will be displayed in set_module_found - # if the module is REQUIRED - messageV(" - ${module} ${component} not found.") - endif() - - set(HAVE_${ALIAS} ${${ALIAS_FOUND}}) - set(HAVE_${ALIAS_UPPER} ${${ALIAS_FOUND}}) - - get_directory_property(hasParent PARENT_DIRECTORY) - if(hasParent) - set(HAVE_${ALIAS} ${${ALIAS_FOUND}} PARENT_SCOPE) - set(HAVE_${ALIAS_UPPER} ${${ALIAS_FOUND}} PARENT_SCOPE) - endif() - - mark_as_advanced(${ALIAS_FOUND} - ${ALIAS_LIBRARY_DEBUG} - ${ALIAS_LIBRARY_RELEASE} - ${ALIAS_LIBRARIES} - ${ALIAS_DEFINITIONS} - ${ALIAS_VERSION}) -endmacro() - - -# -### Macro: set_module_notfound -# -# Marks the given component as not found, and resets the cache for find_path and find_library results. -# -macro(set_module_notfound module) - #messageV(" - Setting ${module} not found.") - set(${module}_FOUND FALSE) - #set(${module}_FOUND FALSE PARENT_SCOPE) - - if (CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE) - set(${module}_LIBRARY_RELEASE "") - set(${module}_LIBRARY_DEBUG "") - set(${module}_LIBRARIES "") - #set(${module}_LIBRARY_RELEASE "" PARENT_SCOPE) - #set(${module}_LIBRARY_DEBUG "" PARENT_SCOPE) - #set(${module}_LIBRARIES "" PARENT_SCOPE) - else() - set(${module}_LIBRARIES ${ALIAS_LIBRARIES}-NOTFOUND) - #set(${module}_LIBRARIES ${ALIAS_LIBRARIES}-NOTFOUND PARENT_SCOPE) - endif() - -endmacro() - - -# -### Macro: set_component_notfound -# -# Marks the given component as not found, and resets the cache for find_path and find_library results. -# -macro(set_component_notfound module component) - set_component_alias(${module} ${component}) - - #messageV(" - Setting ${module} ${component} not found.") - set(${ALIAS_FOUND} FALSE) - #set(${ALIAS_FOUND} FALSE PARENT_SCOPE) - set(${ALIAS_INCLUDE_DIRS} ${ALIAS_INCLUDE_DIRS}-NOTFOUND) - - if (${module}_MULTI_CONFIGURATION AND (CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE)) - set(${ALIAS_LIBRARY_RELEASE} ${ALIAS_LIBRARY_RELEASE}-NOTFOUND) - set(${ALIAS_LIBRARY_DEBUG} ${ALIAS_LIBRARY_DEBUG}-NOTFOUND) - set(${ALIAS_LIBRARIES} "") #${module}_${component}_LIBRARIES-NOTFOUND) - #set(${ALIAS_LIBRARY_RELEASE} ${ALIAS_LIBRARY_RELEASE}-NOTFOUND PARENT_SCOPE) - #set(${ALIAS_LIBRARY_DEBUG} ${ALIAS_LIBRARY_DEBUG}-NOTFOUND PARENT_SCOPE) - #set(${ALIAS_LIBRARIES} "") #${module}_${component}_LIBRARIES-NOTFOUND PARENT_SCOPE) - else() - set(${ALIAS_LIBRARIES} ${ALIAS_LIBRARIES}-NOTFOUND) - #set(${ALIAS_LIBRARIES} ${ALIAS_LIBRARIES}-NOTFOUND PARENT_SCOPE) - endif() - -endmacro() - - -# -### Macro: find_component_paths -# -# Finds the given component library and include paths. -# -macro(find_component_paths module component library header) - messageV("Find Component Paths=${module}:${component}:${library}:${header}") - messageV("INCLUDE_DIR: ${${module}_INCLUDE_DIR} HINTS: ${${module}_INCLUDE_HINTS}") - - #unset(${ALIAS_LIBRARY} CACHE) - #unset(${ALIAS_LIBRARIES} CACHE) - #unset(${ALIAS_LIBRARY_RELEASE} CACHE) - #unset(${ALIAS_LIBRARY_DEBUG} CACHE) - - # Reset alias namespace (force recheck) - #set_component_alias(${module} ${component}) - #set_component_notfound(${module} ${component}) - - find_path(${ALIAS_INCLUDE_DIRS} ${header} - HINTS - ${${module}_INCLUDE_HINTS} - PATHS - ${${module}_INCLUDE_DIR} - PATH_SUFFIXES - ${${module}_INCLUDE_SUFFIXES} # try find from root module include suffixes - ) - - # Create a Debug and a Release list for multi configuration builds. - # NOTE: _CONFIGURATION_TYPES must be set to use this. - if (${module}_MULTI_CONFIGURATION AND (CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE)) - find_library(${ALIAS_LIBRARY_RELEASE} - NAMES - ${library} - HINTS - ${${module}_LIBRARY_HINTS} - PATHS - ${${ALIAS_LIBRARY_DIRS}} - ${${module}_LIBRARY_DIR} - PATH_SUFFIXES - ${${module}_LIBRARY_SUFFIXES} - ) - find_library(${ALIAS_LIBRARY_DEBUG} - NAMES - ${library}d - HINTS - ${${module}_LIBRARY_HINTS} - PATHS - ${${ALIAS_LIBRARY_DIRS}} - ${${module}_LIBRARY_DIR} - PATH_SUFFIXES - ${${module}_LIBRARY_SUFFIXES} - ) - - if (${ALIAS_LIBRARY_RELEASE}) - list(APPEND ${ALIAS_LIBRARIES} optimized ${${ALIAS_LIBRARY_RELEASE}}) - endif() - if (${ALIAS_LIBRARY_DEBUG}) - list(APPEND ${ALIAS_LIBRARIES} debug ${${ALIAS_LIBRARY_DEBUG}}) - endif() - - #include(${CMAKE_ROOT}/Modules/SelectLibraryConfigurations.cmake) - #select_library_configurations(${ALIAS}) - - # message(STATUS "ALIAS_INCLUDE_DIRS: ${${ALIAS_INCLUDE_DIRS}}") - # message(STATUS "ALIAS_LIBRARY_DEBUG: ${${ALIAS_LIBRARY_DEBUG}}") - # message(STATUS "ALIAS_LIBRARY_RELEASE: ${${ALIAS_LIBRARY_RELEASE}}") - # message(STATUS "ALIAS_LIBRARIES: ${ALIAS_LIBRARIES}: ${${ALIAS_LIBRARIES}}") - # message(STATUS "ALIAS_LIBRARY: ${${ALIAS_LIBRARY}}") - # message(STATUS "ALIAS_LIBRARY_DIRS: ${${ALIAS_LIBRARY_DIRS}}") - # message(STATUS "LIBRARY_HINTS: ${${module}_LIBRARY_DIR}") - # message(STATUS "INCLUDE_DIR: ${${module}_INCLUDE_DIR}") - # message(STATUS "LIBRARY_SUFFIXES: ${${module}_LIBRARY_SUFFIXES}") - else() - find_library(${ALIAS_LIBRARIES} - NAMES - ${library} - ${library}d - HINTS - ${${module}_LIBRARY_HINTS} - PATHS - ${${ALIAS_LIBRARY_DIRS}} - ${${module}_LIBRARY_DIR} - PATH_SUFFIXES - ${${module}_LIBRARY_SUFFIXES} - ) - endif() - - # print_module_variables(${module}) - set_component_found(${module} ${component}) -endmacro() - - -# -### Macro: find_component -# -# Checks for the given component by invoking pkg-config and then looking up the -# libraries and include directories. -# -macro(find_component module component pkgconfig library header) - messageV("Find Component=${module}:${component}:${pkgconfig}:${library}:${header}") - - # Reset component alias values (force recheck) - set_component_alias(${module} ${component}) - - find_component_paths(${module} ${component} ${library} ${header}) - - if(NOT ${ALIAS_FOUND}) - messageV(" - ${module} ${component} not found, searching with pkg-config...") - - # Use pkg-config to obtain directories for the find_path() and find_library() calls. - find_package(PkgConfig QUIET) - if (PKG_CONFIG_FOUND) - pkg_search_module(${ALIAS} ${pkgconfig} QUIET) - messageV("Find Component PkgConfig=${ALIAS}:${${ALIAS}_FOUND}:${${ALIAS}_LIBRARIES}:${${ALIAS}_INCLUDE_DIRS}:${${ALIAS}_LIBRARY_DIRS}:${${ALIAS}_LIBDIR}:${${ALIAS}_INCLUDEDIR}") - endif() - else() - messageV(" - ${module} ${component} found without pkg-config.") - endif() - - # messageV("${ALIAS_FOUND}=${${ALIAS_FOUND}}") - # messageV("${ALIAS_LIBRARIES}=${${ALIAS_LIBRARIES}}") - # messageV("${ALIAS_INCLUDE_DIRS}=${${ALIAS_INCLUDE_DIRS}}") - - if(${ALIAS_FOUND}) - set_component_found(${module} ${component}) - endif() -endmacro() diff --git a/cmake/CMakeHelpers.cmake b/cmake/CMakeHelpers.cmake deleted file mode 100644 index 054d742a5..000000000 --- a/cmake/CMakeHelpers.cmake +++ /dev/null @@ -1,256 +0,0 @@ -# -### Macro: subdirlist -# -# Returns a list of subdirectories. -# -macro(subdirlist result curdir) - file(GLOB children RELATIVE ${curdir} ${curdir}/*) - set(dirlist "") - foreach(child ${children}) - if(IS_DIRECTORY ${curdir}/${child}) - set(dirlist ${dirlist} ${child}) - endif() - endforeach() - set(${result} ${dirlist}) -endmacro() - - -# -### Macro: join -# -# Joins a string array. -# Example: -# SET( letters "" "\;a" b c "d\;d" ) -# JOIN("${letters}" ":" output) -# MESSAGE("${output}") # :;a:b:c:d;d -# -function(JOIN VALUES GLUE OUTPUT) - string (REPLACE ";" "${GLUE}" _TMP_STR "${VALUES}") - set (${OUTPUT} "${_TMP_STR}" PARENT_SCOPE) -endfunction() - - -# -### Macro: list_length -# -# Example: -# SET(MYLIST hello world foo bar) -# LIST_LENGTH(length ${MYLIST}) -# MESSAGE("length: ${length}") -# -macro(LIST_LENGTH var) - set(entries) - foreach(e ${ARGN}) - set(entries "${entries}.") - endforeach(e) - string(LENGTH ${entries} ${var}) -endmacro() - - -# -### Function: append_unique_list -# -# Appends items from the source list to the given target list -# if they are not already contained within the target list -# in flattened string form. -# -function(append_unique_list target source) - if (NOT ${source}) - return() - endif() - if (NOT ${target}) - set(${target} ${${source}} PARENT_SCOPE) - else() - join("${${target}}" ":" target_str) - join("${${source}}" ":" source_str) - if (NOT ${target_str} MATCHES ${source_str}) - set(${target} ${${target}} ${${source}} PARENT_SCOPE) - endif() - endif() -endfunction() - - -# -### Function: filter_list -# -function(filter_list result source regex) - set(items) - foreach(ITR ${source}) - if(NOT ITR MATCHES ${regex}) - list(APPEND items ${ITR}) - endif() - endforeach() - set(${result} ${items} PARENT_SCOPE) -endfunction() - - -# -### Function: find_existing_directory -# -function(find_existing_directory result) - foreach(dir ${ARGN}) - if(EXISTS ${dir}) - get_filename_component(dir ${dir} ABSOLUTE) - set(${result} ${dir} PARENT_SCOPE) - return() - endif() - endforeach() -endfunction() - - -# -### Macro: print_module_variables -# -macro(print_module_variables name) - message(STATUS "${name} Variables:") - message(STATUS "-- Found: ${${name}_FOUND}") - if (${name}_INCLUDE_DIRS) - message(STATUS "-- Include Dirs: ${${name}_INCLUDE_DIRS}") - else() - message(STATUS "-- Include Dir: ${${name}_INCLUDE_DIR}") - endif() - if (${name}_LIBRARIES) - message(STATUS "-- Libraries: ${${name}_LIBRARIES}") - message(STATUS "-- Debug Libraries: ${${name}_LIBRARIES_DEBUG}") - message(STATUS "-- Release Libraries: ${${name}_LIBRARIES_RELEASE}") - else() - message(STATUS "-- Library: ${${name}_LIBRARY}") - message(STATUS "-- Debug Library: ${${name}_LIBRARY_DEBUG}") - message(STATUS "-- Release Library: ${${name}_LIBRARY_RELEASE}") - endif() - message(STATUS "-- Dependencies: ${${name}_DEPENDENCIES}") - - # message("Paths: ${${prefix}_PATHS}") - # message("Debug Paths: ${${prefix}_PATHS_RELEASE}") - # message("Release Paths: ${${prefix}_PATHS_DEBUG}") - # message("Debug Names: ${${prefix}_NAMES_RELEASE}") - # message("Release Names: ${${prefix}_NAMES_DEBUG}") - # message("Names: ${${prefix}_NAMES}") -endmacro() - - -# -### Macro: set_option -# -# Provides an option that the user can optionally select. -# Can accept condition to control when option is available for user. -# Usage: -# option( "help string describing the option" [IF ]) -# -macro(set_option variable description value) - set(__value ${value}) - set(__condition "") - set(__varname "__value") - foreach(arg ${ARGN}) - if(arg STREQUAL "IF" OR arg STREQUAL "if") - set(__varname "__condition") - else() - list(APPEND ${__varname} ${arg}) - endif() - endforeach() - unset(__varname) - if(__condition STREQUAL "") - set(__condition 2 GREATER 1) - endif() - - if(DEFINED ${variable}) - # set the default option value from existing value or command line arguments - option(${variable} "${description}" ${${variable}}) - else() - # if variable not defined set default from condition - if(${__condition}) - if(${__value} MATCHES ";") - if(${__value}) - option(${variable} "${description}" ON) - else() - option(${variable} "${description}" OFF) - endif() - elseif(DEFINED ${__value}) - if(${__value}) - option(${variable} "${description}" ON) - else() - option(${variable} "${description}" OFF) - endif() - else() - option(${variable} "${description}" ${__value}) - endif() - else() - unset(${variable} CACHE) - endif() - endif() - unset(__condition) - unset(__value) -endmacro() - - -# -### Function: status -# -# Status report function. -# Automatically align right column and selects text based on condition. -# Usage: -# status() -# status( [ ...]) -# status( THEN ELSE ) -# -function(status text) - set(status_cond) - set(status_then) - set(status_else) - - set(status_current_name "cond") - foreach(arg ${ARGN}) - if(arg STREQUAL "THEN") - set(status_current_name "then") - elseif(arg STREQUAL "ELSE") - set(status_current_name "else") - else() - list(APPEND status_${status_current_name} ${arg}) - endif() - endforeach() - - if(DEFINED status_cond) - set(status_placeholder_length 32) - string(RANDOM LENGTH ${status_placeholder_length} ALPHABET " " status_placeholder) - string(LENGTH "${text}" status_text_length) - if(status_text_length LESS status_placeholder_length) - string(SUBSTRING "${text}${status_placeholder}" 0 ${status_placeholder_length} status_text) - elseif(DEFINED status_then OR DEFINED status_else) - message(STATUS "${text}") - set(status_text "${status_placeholder}") - else() - set(status_text "${text}") - endif() - - if(DEFINED status_then OR DEFINED status_else) - if(${status_cond}) - string(REPLACE ";" " " status_then "${status_then}") - string(REGEX REPLACE "^[ \t]+" "" status_then "${status_then}") - message(STATUS "${status_text} ${status_then}") - else() - string(REPLACE ";" " " status_else "${status_else}") - string(REGEX REPLACE "^[ \t]+" "" status_else "${status_else}") - message(STATUS "${status_text} ${status_else}") - endif() - else() - string(REPLACE ";" " " status_cond "${status_cond}") - string(REGEX REPLACE "^[ \t]+" "" status_cond "${status_cond}") - message(STATUS "${status_text} ${status_cond}") - endif() - else() - message(STATUS "${text}") - endif() -endfunction() - -# -### Macro: messageV -# -# Prints message only with MSG_VERBOSE=ON -# Usage: -# messageV() -# -function(messageV text) - if(${MSG_VERBOSE}) - message(STATUS "${text}") - endif() -endfunction() diff --git a/cmake/FindFFmpeg.cmake b/cmake/FindFFmpeg.cmake index dbce66b5e..313baf351 100644 --- a/cmake/FindFFmpeg.cmake +++ b/cmake/FindFFmpeg.cmake @@ -1,180 +1,101 @@ -# - Try to find the required ffmpeg components(default: AVFORMAT, AVUTIL, AVCODEC) +# FindFFmpeg.cmake - Find FFmpeg libraries via pkg-config # -# Once done this will define -# FFmpeg_FOUND - System has the all required components. -# FFmpeg_INCLUDE_DIRS - Include directory necessary for using the required components headers. -# FFmpeg_LIBRARIES - Link these to use the required ffmpeg components. -# FFmpeg_DEFINITIONS - Compiler switches required for using the required ffmpeg components. +# Once done this will define: +# FFmpeg_FOUND - System has all required components +# FFmpeg_INCLUDE_DIRS - Include directories +# FFmpeg_LIBRARIES - Libraries to link +# HAVE_FFMPEG - Set if found (for config header) # -# For each of the components it will additionalLy set. -# - AVCODEC -# - AVFORMAT -# - AVFILTER -# - AVUTIL -# - AVDEVICE -# - AVRESAMPLE -# - SWSCALE -# - SWRESAMPLE -# - POSTPROC -# -# the following variables will be defined -# FFmpeg__FOUND - System has -# FFmpeg__INCLUDE_DIRS - Include directory necessary for using the headers -# FFmpeg__LIBRARIES - Link these to use -# FFmpeg__DEFINITIONS - Compiler switches required for using -# FFmpeg__VERSION - The components version +# Per-component variables: +# FFmpeg__FOUND +# FFmpeg__INCLUDE_DIRS +# FFmpeg__LIBRARIES +# FFmpeg__VERSION -# The default components were taken from a survey over other FindFFmpeg.cmake files if (NOT FFmpeg_FIND_COMPONENTS) - set(FFmpeg_FIND_COMPONENTS AVCODEC AVFORMAT AVUTIL AVDEVICE SWSCALE SWRESAMPLE) + set(FFmpeg_FIND_COMPONENTS AVCODEC AVFORMAT AVUTIL SWSCALE SWRESAMPLE) endif() -# Check for cached results. If there are skip the costly part. -set_module_notfound(FFmpeg) -if (NOT FFmpeg_FOUND) - # The FFmpeg compilation guide stores files in an unusual location, - # so let's support that out of the box - # http://trac.ffmpeg.org/wiki/CompilationGuide/Ubuntu - - set(FFMPEG_ROOT_DIR "/tmp/ffmpeg_build" CACHE STRING "FFmpeg root directory (containing `lib` and `include` dirs)") - - set(FFmpeg_LIBRARY_HINTS - ${FFMPEG_ROOT_DIR}/lib - $ENV{HOME}/tmp/ffmpeg_build/lib - $ENV{HOME}/ffmpeg_build/lib) - set(FFmpeg_INCLUDE_HINTS - ${FFMPEG_ROOT_DIR}/include - $ENV{HOME}/tmp/ffmpeg_build/include - $ENV{HOME}/ffmpeg_build/include) - - # Check for all components - find_component(FFmpeg SWRESAMPLE libswresample swresample libswresample/swresample.h) - find_component(FFmpeg AVRESAMPLE libavresample avresample libavresample/avresample.h) - find_component(FFmpeg AVFORMAT libavformat avformat libavformat/avformat.h) - find_component(FFmpeg AVCODEC libavcodec avcodec libavcodec/avcodec.h) - find_component(FFmpeg SWSCALE libswscale swscale libswscale/swscale.h) - find_component(FFmpeg AVUTIL libavutil avutil libavutil/avutil.h) - find_component(FFmpeg AVFILTER libavfilter avfilter libavfilter/avfilter.h) - find_component(FFmpeg AVDEVICE libavdevice avdevice libavdevice/avdevice.h) - find_component(FFmpeg POSTPROC libpostproc postproc libpostproc/postprocess.h) - - # Set FFmpeg as found or not - set_module_found(FFmpeg) # ${FFmpeg_FIND_REQUIRED} - - # Include some dependencies required when linking to FFmpeg static build. - # NOTE: These libraries are required is compiling FFmpeg with default build - # specified in https://trac.ffmpeg.org/wiki/CompilationGuide/Ubuntu - - find_library(BZ2_LIBRARY NAMES bz2) - if(BZ2_LIBRARY) - list(APPEND FFmpeg_DEPENDENCIES ${BZ2_LIBRARY}) - endif() - - find_library(LZMA_LIBRARY NAMES lzma) - if(LZMA_LIBRARY) - list(APPEND FFmpeg_DEPENDENCIES ${LZMA_LIBRARY}) - endif() - - find_library(LIBVPX_LIBRARY NAMES vpx) - if(LIBVPX_LIBRARY) - list(APPEND FFmpeg_DEPENDENCIES ${LIBVPX_LIBRARY}) - endif() - - find_library(LIBX264_LIBRARY NAMES x264) - if(LIBX264_LIBRARY) - list(APPEND FFmpeg_DEPENDENCIES ${LIBX264_LIBRARY}) - endif() - - find_library(LIBX265_LIBRARY NAMES x265) - if(LIBX265_LIBRARY) - list(APPEND FFmpeg_DEPENDENCIES ${LIBX265_LIBRARY}) - endif() +find_package(PkgConfig QUIET) - find_library(LIBVA_LIBRARY NAMES va) - if(LIBVA_LIBRARY) - list(APPEND FFmpeg_DEPENDENCIES ${LIBVA_LIBRARY}) - endif() +set(FFmpeg_FOUND TRUE) +set(FFmpeg_INCLUDE_DIRS "") +set(FFmpeg_LIBRARIES "") - find_library(LIBFDKAAC_LIBRARY NAMES fdk-aac) - if(LIBFDKAAC_LIBRARY) - list(APPEND FFmpeg_DEPENDENCIES ${LIBFDKAAC_LIBRARY}) - endif() - - find_library(LIBMP3LAME_LIBRARY NAMES mp3lame) - if(LIBMP3LAME_LIBRARY) - list(APPEND FFmpeg_DEPENDENCIES ${LIBMP3LAME_LIBRARY}) - endif() +# Map component names to pkg-config module names +set(_FFmpeg_PKG_AVCODEC libavcodec) +set(_FFmpeg_PKG_AVFORMAT libavformat) +set(_FFmpeg_PKG_AVUTIL libavutil) +set(_FFmpeg_PKG_AVFILTER libavfilter) +set(_FFmpeg_PKG_AVDEVICE libavdevice) +set(_FFmpeg_PKG_AVRESAMPLE libavresample) +set(_FFmpeg_PKG_SWSCALE libswscale) +set(_FFmpeg_PKG_SWRESAMPLE libswresample) +set(_FFmpeg_PKG_POSTPROC libpostproc) - #set(LIBVORBIS_LIBRARY LIBVORBIS_LIBRARY-NOTFOUND) - find_library(LIBVORBIS_LIBRARY NAMES vorbis) - if(LIBVORBIS_LIBRARY) - list(APPEND FFmpeg_DEPENDENCIES ${LIBVORBIS_LIBRARY}) - endif() - - #set(LIBVORBISRNC_LIBRARY LIBVORBISRNC_LIBRARY-NOTFOUND) - find_library(LIBVORBISRNC_LIBRARY NAMES vorbisenc) - if(LIBVORBISRNC_LIBRARY) - list(APPEND FFmpeg_DEPENDENCIES ${LIBVORBISRNC_LIBRARY}) - endif() - - #set(LIBTHEORA_LIBRARY LIBTHEORA_LIBRARY-NOTFOUND) - find_library(LIBTHEORA_LIBRARY NAMES theora) - if(LIBTHEORA_LIBRARY) - list(APPEND FFmpeg_DEPENDENCIES ${LIBTHEORA_LIBRARY}) - endif() - - #set(LIBOGG_LIBRARY LIBOGG_LIBRARY-NOTFOUND) - find_library(LIBOGG_LIBRARY NAMES ogg) - if(LIBOGG_LIBRARY) - list(APPEND FFmpeg_DEPENDENCIES ${LIBOGG_LIBRARY}) +foreach(_component ${FFmpeg_FIND_COMPONENTS}) + set(_pkg ${_FFmpeg_PKG_${_component}}) + if (NOT _pkg) + message(WARNING "FindFFmpeg: unknown component ${_component}") + set(FFmpeg_${_component}_FOUND FALSE) + set(FFmpeg_FOUND FALSE) + continue() endif() - find_library(LIBOPUS_LIBRARY NAMES opus) - if(LIBOPUS_LIBRARY) - list(APPEND FFmpeg_DEPENDENCIES ${LIBOPUS_LIBRARY}) - endif() - - # print_module_variables(FFmpeg) -endif() - -# Cache the vars. - set(FFmpeg_INCLUDE_DIRS ${FFmpeg_INCLUDE_DIRS} CACHE STRING "The FFmpeg include directories." FORCE) - set(FFmpeg_LIBRARIES ${FFmpeg_LIBRARIES} CACHE STRING "The FFmpeg libraries." FORCE) - set(FFmpeg_DEFINITIONS ${FFmpeg_DEFINITIONS} CACHE STRING "The FFmpeg cflags." FORCE) - set(FFmpeg_FOUND ${FFmpeg_FOUND} CACHE BOOLEAN "The FFmpeg found status." FORCE) - -# Check that the required components were found. -set(FFmpeg_FOUND 1) -foreach(_component ${FFmpeg_FIND_COMPONENTS}) - if (FFmpeg_${_component}_FOUND) - messageV( "Required component ${_component} present.") - else () - message(WARNING "Required component ${_component} missing.") - set(FFmpeg_FOUND 0) + pkg_check_modules(_FF_${_component} QUIET ${_pkg}) + + if (_FF_${_component}_FOUND) + set(FFmpeg_${_component}_FOUND TRUE) + set(FFmpeg_${_component}_INCLUDE_DIRS ${_FF_${_component}_INCLUDE_DIRS}) + set(FFmpeg_${_component}_LIBRARIES ${_FF_${_component}_LIBRARIES}) + set(FFmpeg_${_component}_VERSION ${_FF_${_component}_VERSION}) + + list(APPEND FFmpeg_INCLUDE_DIRS ${_FF_${_component}_INCLUDE_DIRS}) + list(APPEND FFmpeg_LIBRARIES ${_FF_${_component}_LIBRARIES}) + else() + # Fallback: try find_path + find_library + string(TOLOWER ${_component} _comp_lower) + find_path(_FF_${_component}_INCDIR + NAMES lib${_comp_lower}/${_comp_lower}.h + PATH_SUFFIXES ffmpeg + ) + find_library(_FF_${_component}_LIB + NAMES ${_comp_lower} + ) + if (_FF_${_component}_INCDIR AND _FF_${_component}_LIB) + set(FFmpeg_${_component}_FOUND TRUE) + set(FFmpeg_${_component}_INCLUDE_DIRS ${_FF_${_component}_INCDIR}) + set(FFmpeg_${_component}_LIBRARIES ${_FF_${_component}_LIB}) + list(APPEND FFmpeg_INCLUDE_DIRS ${_FF_${_component}_INCDIR}) + list(APPEND FFmpeg_LIBRARIES ${_FF_${_component}_LIB}) + else() + set(FFmpeg_${_component}_FOUND FALSE) + set(FFmpeg_FOUND FALSE) + endif() endif() endforeach() -# Build the include path with duplicates removed. if (FFmpeg_INCLUDE_DIRS) list(REMOVE_DUPLICATES FFmpeg_INCLUDE_DIRS) -endif () - -# Now set the noncached _FOUND vars for the components. -foreach(_component AVCODEC AVDEVICE AVFORMAT AVUTIL POSTPROC SWSCALE) #AVFILTER - set_component_found(FFmpeg ${_component}) - messageV("FFmpeg component ${_component} FOUND? ${FFmpeg_${_component}_FOUND}") -endforeach() - -# Compile the list of required vars -set(_FFmpeg_REQUIRED_VARS FFmpeg_LIBRARIES FFmpeg_INCLUDE_DIRS) -foreach (_component ${FFmpeg_FIND_COMPONENTS}) - list(APPEND _FFmpeg_REQUIRED_VARS FFmpeg_${_component}_LIBRARIES FFmpeg_${_component}_INCLUDE_DIRS) -endforeach() +endif() +if (FFmpeg_LIBRARIES) + list(REMOVE_DUPLICATES FFmpeg_LIBRARIES) +endif() -# Give a nice error message if some of the required vars are missing. include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(FFmpeg DEFAULT_MSG ${_FFmpeg_REQUIRED_VARS}) -mark_as_advanced(FFmpeg_INCLUDE_DIRS - FFmpeg_LIBRARIES - FFmpeg_DEFINITIONS - FFmpeg_FOUND) +find_package_handle_standard_args(FFmpeg + DEFAULT_MSG + FFmpeg_LIBRARIES + FFmpeg_INCLUDE_DIRS +) + +# Set uppercase aliases for backward compatibility +set(FFMPEG_FOUND ${FFmpeg_FOUND}) +set(FFMPEG_INCLUDE_DIRS ${FFmpeg_INCLUDE_DIRS}) +set(FFMPEG_LIBRARIES ${FFmpeg_LIBRARIES}) + +mark_as_advanced( + FFmpeg_INCLUDE_DIRS + FFmpeg_LIBRARIES + FFmpeg_FOUND +) diff --git a/cmake/FindHttpParser.cmake b/cmake/FindHttpParser.cmake deleted file mode 100644 index e4a983389..000000000 --- a/cmake/FindHttpParser.cmake +++ /dev/null @@ -1,37 +0,0 @@ -######################################################################## -# CMake module for finding HTTPPARSER -# -# The following variables will be defined: -# -# HTTPPARSER_FOUND -# HTTPPARSER_INCLUDE_DIR -# HTTPPARSER_LIBRARIES -# - -find_path(HTTPPARSER_INCLUDE_DIR - NAMES http_parser.h - PATHS ${LibSourcey_DIR}/vendor/http_parser - PATHS ${LibSourcey_DIR}/share/libsourcey/vendor/include - NO_DEFAULT_PATH) - -find_library(HTTPPARSER_LIBRARY_DEBUG - NAMES http_parserd libhttp_parserd - PATHS - ${LibSourcey_BUILD_DIR}/vendor/http_parser - ${LibSourcey_DIR}/share/libsourcey/vendor/lib - PATH_SUFFIXES Debug - NO_DEFAULT_PATH) - -find_library(HTTPPARSER_LIBRARY_RELEASE - NAMES http_parser libhttp_parser - PATHS - ${LibSourcey_BUILD_DIR}/vendor/http_parser - ${LibSourcey_DIR}/share/libsourcey/vendor/lib - PATH_SUFFIXES Release - NO_DEFAULT_PATH) - -include(${CMAKE_ROOT}/Modules/SelectLibraryConfigurations.cmake) -select_library_configurations(HTTPPARSER) - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(HTTPPARSER DEFAULT_MSG HTTPPARSER_LIBRARIES HTTPPARSER_INCLUDE_DIR) diff --git a/cmake/FindJsonCpp.cmake b/cmake/FindJsonCpp.cmake deleted file mode 100644 index 98cf7a759..000000000 --- a/cmake/FindJsonCpp.cmake +++ /dev/null @@ -1,32 +0,0 @@ -######################################################################## -# CMake module for finding JsonCpp -# -# The following variables will be defined: -# -# JSONCPP_FOUND -# JSONCPP_INCLUDE_DIR -# JSONCPP_LIBRARIES -# - -find_path(JSONCPP_INCLUDE_DIR - NAMES json/json.h - PATHS ${LibSourcey_DIR}/vendor/jsoncpp - NO_DEFAULT_PATH) - -find_library(JSONCPP_LIBRARY_DEBUG - NAMES jsoncppd libjsoncppd - PATHS ${LibSourcey_BUILD_DIR}/vendor/jsoncpp - PATH_SUFFIXES Debug - NO_DEFAULT_PATH) - -find_library(JSONCPP_LIBRARY_RELEASE - NAMES jsoncpp libjsoncpp - PATHS ${LibSourcey_BUILD_DIR}/vendor/jsoncpp - PATH_SUFFIXES Release - NO_DEFAULT_PATH) - -include(${CMAKE_ROOT}/Modules/SelectLibraryConfigurations.cmake) -select_library_configurations(JSONCPP) - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(JSONCPP DEFAULT_MSG JSONCPP_LIBRARIES JSONCPP_INCLUDE_DIR) diff --git a/cmake/FindLibSourcey.cmake b/cmake/FindLibSourcey.cmake deleted file mode 100644 index 11dc08db3..000000000 --- a/cmake/FindLibSourcey.cmake +++ /dev/null @@ -1,143 +0,0 @@ -# - Try to find the required LibSourcey components (default: base uv crypto net util) -# -# Once done this will define -# LibSourcey_FOUND - System has the all required components. -# LibSourcey_INCLUDE_DIRS - Include directory necessary for using the required components headers. -# LibSourcey_LIBRARY_DIRS - Library directories necessary for using the required components. -# LibSourcey_LIBRARIES - Link these to use the required components. -# LibSourcey_DEFINITIONS - Compiler switches required for using the required components. -# -# the following variables will be defined -# LibSourcey__FOUND - System has -# LibSourcey__INCLUDE_DIRS - Include directories necessary for using the headers -# LibSourcey__LIBRARY_DIRS - Library directories necessary for using the -# LibSourcey__LIBRARIES - Link these to use -# LibSourcey__DEFINITIONS - Compiler switches required for using -# LibSourcey__VERSION - The components version - -# Set required variables -set(LibSourcey_ROOT_DIR "" CACHE STRING "Where is the LibSourcey root directory located?") -set(LibSourcey_INCLUDE_DIR "${LibSourcey_ROOT_DIR}/src" CACHE STRING "Where are the LibSourcey headers (.h) located?") -set(LibSourcey_LIBRARY_DIR "${LibSourcey_ROOT_DIR}/build" CACHE STRING "Where are the LibSourcey libraries (.dll/.so) located?") #/src - -# Set path variables (used in .cmake files) -set(LibSourcey_DIR ${LibSourcey_ROOT_DIR}) -set(LibSourcey_SOURCE_DIR ${LibSourcey_DIR}/src) -set(LibSourcey_BUILD_DIR ${LibSourcey_DIR}/build) -# set(LibSourcey_DIR ${LibSourcey_ROOT_DIR} PARENT_SCOPE) -# set(LibSourcey_SOURCE_DIR ${LibSourcey_DIR}/src PARENT_SCOPE) -# set(LibSourcey_BUILD_DIR ${LibSourcey_DIR}/build PARENT_SCOPE) - -# message("LibSourcey_SOURCE_DIR=${LibSourcey_SOURCE_DIR}") -# message("LibSourcey_ROOT_DIR=${LibSourcey_ROOT_DIR}") -# message("LibSourcey_LIBRARY_DIR=${LibSourcey_ROOT_DIR}") -# message("LibSourcey_INCLUDE_DIR=${LibSourcey_INCLUDE_DIR}") - -include(CMakeHelpers REQUIRED) -include(CMakeFindExtensions REQUIRED) - -# The default components to find -if (NOT LibSourcey_FIND_COMPONENTS) - set(LibSourcey_FIND_COMPONENTS base uv crypto net util) -endif() - -# Set a list of all available modules -set(LibSourcey_ALL_MODULES - archo - av - base - crypto - http - json - net - pacm - pluga - sked - socketio - stun - symple - turn - util - webrtc -) - -# Check for cached results. If there are then skip the costly part. -# set_module_notfound(LibSourcey) -if (NOT LibSourcey_FOUND) - if(WIN32 AND MSVC) - set(LibSourcey_MULTI_CONFIGURATION TRUE) - endif() - - # Set search path suffixes - foreach(component ${LibSourcey_FIND_COMPONENTS}) - list(APPEND LibSourcey_INCLUDE_SUFFIXES ${component}/include) - list(APPEND LibSourcey_LIBRARY_SUFFIXES ${component}) - list(APPEND LibSourcey_LIBRARY_SUFFIXES ${component}/Release) - list(APPEND LibSourcey_LIBRARY_SUFFIXES ${component}/Debug) - endforeach() - - # Check for all available components - find_component(LibSourcey pacm pacm scy_pacm scy/pacm/config.h) - find_component(LibSourcey pluga pluga scy_pluga scy/pluga/config.h) - find_component(LibSourcey sked sked scy_sked scy/sked/scheduler.h) - find_component(LibSourcey webrtc webrtc scy_webrtc scy/webrtc/webrtc.h) - find_component(LibSourcey turn turn scy_turn scy/turn/turn.h) - find_component(LibSourcey stun stun scy_stun scy/stun/stun.h) - find_component(LibSourcey symple symple scy_symple scy/symple/client.h) - find_component(LibSourcey socketio socketio scy_socketio scy/socketio/client.h) - find_component(LibSourcey av av scy_av scy/av/ffmpeg.h) - find_component(LibSourcey util util scy_util scy/util/ratelimiter.h) - find_component(LibSourcey http http scy_http scy/http/server.h) - find_component(LibSourcey net net scy_net scy/net/socket.h) - find_component(LibSourcey archo archo scy_archo scy/archo/zipfile.h) - find_component(LibSourcey crypto crypto scy_crypto scy/crypto/crypto.h) - find_component(LibSourcey json json scy_json scy/json/json.h) - find_component(LibSourcey base base scy_base scy/base.h) - - # Include the dir with libsourcey.h - list(APPEND LibSourcey_INCLUDE_DIRS ${LibSourcey_LIBRARY_DIR}) - - # Include dependency headers - list(APPEND LibSourcey_INCLUDE_DIRS - ${LibSourcey_DIR}/share/libsourcey/vendor/include - ${LibSourcey_DIR}/vendor/zlib - ${LibSourcey_DIR}/vendor/zlib - ${LibSourcey_DIR}/vendor/minizip - # ${LibSourcey_DIR}/vendor/rtaudio - # ${LibSourcey_DIR}/vendor/rtaudio/include - ${LibSourcey_DIR}/vendor/libuv/include - ${LibSourcey_DIR}/vendor/http_parser - # ${LibSourcey_DIR}/vendor/jsoncpp - ${LibSourcey_DIR}/vendor/json/src) - - # Set LibSourcey as found or not - # print_module_variables(LibSourcey) - set_module_found(LibSourcey) -endif() - -# Include dependencies if found -if (LibSourcey_FOUND) - - # Add required system libraries - if(MSVC) - set(LibSourcey_DEPENDENCIES advapi32.lib iphlpapi.lib psapi.lib shell32.lib ws2_32.lib dsound.lib winmm.lib strmiids.lib) - elseif(APPLE) - set(LibSourcey_DEPENDENCIES -ldl) - elseif(UNIX) - set(LibSourcey_DEPENDENCIES -lm -lrt -ldl) - endif() - - # Third party dependencies - find_package(Threads REQUIRED) - find_package(LibUV REQUIRED) - find_package(HttpParser REQUIRED) - # find_package(SSL REQUIRED) - - list(APPEND LibSourcey_INCLUDE_DIRS ${LIBUV_INCLUDE_DIR} ${HTTPPARSER_INCLUDE_DIR}) - list(APPEND LibSourcey_DEPENDENCIES ${LIBUV_LIBRARIES} ${HTTPPARSER_LIBRARIES}) - - # This is necessary on Linux as well as Threads package - if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread") - endif() -endif() diff --git a/cmake/FindLibUV.cmake b/cmake/FindLibUV.cmake deleted file mode 100644 index 4429116c5..000000000 --- a/cmake/FindLibUV.cmake +++ /dev/null @@ -1,38 +0,0 @@ -######################################################################## -# CMake module for finding libuv -# -# The following variables will be defined: -# -# LIBUV_FOUND -# LIBUV_INCLUDE_DIR -# LIBUV_LIBRARIES -# - -find_path(LIBUV_INCLUDE_DIR - NAMES uv.h - PATHS - ${LibSourcey_DIR}/vendor/libuv/include - ${LibSourcey_DIR}/share/libsourcey/vendor/include - NO_DEFAULT_PATH) - -find_library(LIBUV_LIBRARY_DEBUG - NAMES libuvd uvd - PATHS - ${LibSourcey_BUILD_DIR}/vendor/libuv - ${LibSourcey_DIR}/share/libsourcey/vendor/lib - PATH_SUFFIXES Debug - NO_DEFAULT_PATH) - -find_library(LIBUV_LIBRARY_RELEASE - NAMES libuv uv - PATHS - ${LibSourcey_BUILD_DIR}/vendor/libuv - ${LibSourcey_DIR}/share/libsourcey/vendor/lib - PATH_SUFFIXES Release - NO_DEFAULT_PATH) - -include(${CMAKE_ROOT}/Modules/SelectLibraryConfigurations.cmake) -select_library_configurations(LIBUV) - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(LIBUV DEFAULT_MSG LIBUV_LIBRARIES LIBUV_INCLUDE_DIR) diff --git a/cmake/FindMinizip.cmake b/cmake/FindMinizip.cmake deleted file mode 100644 index a0f99cf34..000000000 --- a/cmake/FindMinizip.cmake +++ /dev/null @@ -1,22 +0,0 @@ -######################################################################## -# CMake module for finding minizip -# -# The following variables will be defined: -# -# MINIZIP_FOUND -# MINIZIP_INCLUDE_DIR -# MINIZIP_LIBRARY -# - -find_path(MINIZIP_INCLUDE_DIR - NAMES zip.h - PATHS ${LibSourcey_SOURCE_DIR}/archo/vendor/minizip - NO_DEFAULT_PATH) - -find_library(MINIZIP_LIBRARY - NAMES minizip libminizip - PATHS ${LibSourcey_BUILD_DIR}/src/archo/vendor/minizip - NO_DEFAULT_PATH) - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(MINIZIP DEFAULT_MSG MINIZIP_LIBRARY MINIZIP_INCLUDE_DIR) diff --git a/cmake/FindOpenCV.cmake b/cmake/FindOpenCV.cmake index 8008a2c53..4c6fc00c1 100644 --- a/cmake/FindOpenCV.cmake +++ b/cmake/FindOpenCV.cmake @@ -1,165 +1,75 @@ -# Try to find OpenCV library installation -# See http://sourceforge.net/projects/opencvlibrary/ +# Find OpenCV library (4.x+) # -# The following variables are optionally searched for defaults -# OPENCV_FIND_COMPONENTS : find_package(OPENCV COMPONENTS ..) -# compatible interface. typically CV CXCORE CVAUX HIGHGUI CVCAM .. etc. +# Uses OpenCV's own CMake config (OpenCVConfig.cmake) which ships with +# all modern OpenCV installations. Falls back to pkg-config. # -# The following are set after configuration is done: -# OPENCV_FOUND -# OPENCV_INCLUDE_DIR -# OPENCV_LIBRARIES -# OPENCV_LIBRARY_DIRS -# ---------------------------------------------------------------------- - -# ---------------------------------------------------------------------- -# Default OpenCV components to include if COMPONENTS is undefined -# ---------------------------------------------------------------------- -if(NOT OPENCV_FIND_COMPONENTS) - set(OPENCV_FIND_COMPONENTS callib3d contrib core features2d flann gpu harrtraining_engine highgui imgproc legacy ml objdetect video) +# Sets: +# OPENCV_FOUND +# OPENCV_INCLUDE_DIRS (alias for OpenCV_INCLUDE_DIRS) +# OPENCV_LIBRARIES (alias for OpenCV_LIBS) +# OPENCV_VERSION (alias for OpenCV_VERSION) + +# Try OpenCV's own config-based find first (preferred) +find_package(OpenCV 4.0 QUIET CONFIG) + +if(OpenCV_FOUND) + set(OPENCV_FOUND TRUE) + set(OPENCV_INCLUDE_DIRS ${OpenCV_INCLUDE_DIRS}) + set(OPENCV_LIBRARIES ${OpenCV_LIBS}) + set(OPENCV_VERSION ${OpenCV_VERSION}) + message(STATUS "Found OpenCV ${OPENCV_VERSION} (config mode)") + return() endif() -# ---------------------------------------------------------------------- -# Options -# ---------------------------------------------------------------------- -set(OPENCV_LINK_SHARED_LIBS ${BUILD_SHARED_LIBS} CACHE BOOL "Link with shared OpenCV libraries (.dll/.so) instead of static ones (.lib/.a)") - -# ---------------------------------------------------------------------- -# Use pkg-config to find OpenCV if available -# ---------------------------------------------------------------------- +# Fallback: pkg-config find_package(PkgConfig QUIET) -if (PKG_CONFIG_FOUND) - pkg_search_module(OPENCV opencv) - - # message("OPENCV_FOUND=${OPENCV_FOUND}") - # message("OPENCV_LIBRARIES=${OPENCV_LIBRARIES}") - # message("OPENCV_STATIC_LIBRARIES=${OPENCV_STATIC_LIBRARIES}") - # message("OPENCV_INCLUDE_DIRS=${OPENCV_INCLUDE_DIRS}") - # message("OPENCV_LIBRARY_DIRS=${OPENCV_LIBRARY_DIRS}") - # message("OPENCV_DEFINITIONS=${OPENCV_DEFINITIONS}") - # message("OPENCV_VERSION=${OPENCV_VERSION}") +if(PKG_CONFIG_FOUND) + pkg_check_modules(OPENCV QUIET opencv4) + if(NOT OPENCV_FOUND) + pkg_check_modules(OPENCV QUIET opencv) + endif() + if(OPENCV_FOUND) + message(STATUS "Found OpenCV ${OPENCV_VERSION} (pkg-config)") + return() + endif() endif() -# ---------------------------------------------------------------------- -# Find component libraries -# ---------------------------------------------------------------------- -#set_module_notfound(OPENCV) -if (NOT OPENCV_FOUND) - set(OPENCV_FOUND 0) - - # Find OpenCV include directory - # set(OPENCV_INCLUDE_DIR OPENCV_INCLUDE_DIR-NOTFOUND) - find_path(OPENCV_INCLUDE_DIR - NAMES - opencv2/core/core.hpp - DOC - "OpenCV Include Directory" - PATHS - /usr/local/include - /usr/include - ) - - # Find OpenCV library directory - # set(OPENCV_LIBRARY_DIRS OPENCV_LIBRARY_DIRS-NOTFOUND) - find_path(OPENCV_LIBRARY_DIRS - NAMES - opencv_core - DOC - "OpenCV Library Directory" - PATHS - /usr/lib - /usr/lib/x86_64-linux-gnu - /usr/lib/i386-linux-gnu - /usr/lib64 - /usr/local/lib - /usr/local/lib/x86_64-linux-gnu - /usr/local/lib/i386-linux-gnu - /usr/local/lib64 - ) - - if(OPENCV_LIBRARY_DIRS) - set(OPENCV_FOUND 1) - - # Glob library files (wish CMake supported "*.{lib|so|a}" syntax :P) - if (WIN32) - file(GLOB_RECURSE libraries "${OPENCV_LIBRARY_DIRS}/*.lib") - else() - if (BUILD_SHARED_LIBS) - file(GLOB_RECURSE libraries "${OPENCV_LIBRARY_DIRS}/*.so") - else() - file(GLOB_RECURSE libraries "${OPENCV_LIBRARY_DIRS}/*.a") - endif() - endif() - - # TODO: Include only OPENCV_FIND_COMPONENTS - set(OPENCV_LIBRARIES "") - foreach(lib ${libraries}) - get_filename_component(filename ${lib} NAME) - if(${filename} MATCHES "opencv_") - if(WIN32 AND (CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE)) - if (${filename} MATCHES "d.lib$") - list(APPEND OPENCV_LIBRARIES "debug" ${filename}) - else() - list(APPEND OPENCV_LIBRARIES "optimized" ${filename}) - endif() - else() - list(APPEND OPENCV_LIBRARIES ${filename}) - endif() - endif() - endforeach() - - if(WIN32) - # Include OpenCV shared libraries - if(NOT OPENCV_LINK_SHARED_LIBS) - set(OPENCV_SHARED_LIBRARY_DIR "") - if(IS_DIRECTORY "${OPENCV_INCLUDE_DIR}/../share/OpenCV/3rdparty/lib") - set(OPENCV_SHARED_LIBRARY_DIR "${OPENCV_INCLUDE_DIR}/../share/OpenCV/3rdparty/lib") - elseif(IS_DIRECTORY "${OPENCV_INCLUDE_DIR}/../3rdparty/lib") - set(OPENCV_SHARED_LIBRARY_DIR "${OPENCV_INCLUDE_DIR}/../3rdparty/lib") - endif() - if(OPENCV_SHARED_LIBRARY_DIR) - list(APPEND OPENCV_LIBRARY_DIRS ${OPENCV_SHARED_LIBRARY_DIR}) - if(CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE) - list(APPEND OPENCV_LIBRARIES debug zlibd.lib) - list(APPEND OPENCV_LIBRARIES optimized zlib.lib) - else() - list(APPEND OPENCV_LIBRARIES zlib.lib) - endif() - endif() - list(APPEND OPENCV_LIBRARIES Vfw32.lib) - endif() - - # LibSourcey requires HighGUI DirectShow to use multithreaded COM. - # Just provide a warning for now, but we really should check the source file itself. - status("IMPORTANT: OpenCV HighGUI DirectShow must be compiled with VI_COM_MULTI_THREADED defined.") - endif() - - #message(STATUS "Found OpenCV libraries: ${OPENCV_LIBRARIES}") - - #set_module_found(OPENCV) +# Manual fallback for non-standard installations +find_path(OPENCV_INCLUDE_DIRS + NAMES opencv2/core.hpp + PATHS + /usr/local/include + /usr/include + $ENV{OPENCV_DIR}/include +) + +find_library(OPENCV_CORE_LIB + NAMES opencv_core + PATHS + /usr/local/lib + /usr/lib + /usr/lib/x86_64-linux-gnu + /usr/lib64 + $ENV{OPENCV_DIR}/lib +) + +if(OPENCV_INCLUDE_DIRS AND OPENCV_CORE_LIB) + set(OPENCV_FOUND TRUE) + get_filename_component(OPENCV_LIBRARY_DIR ${OPENCV_CORE_LIB} DIRECTORY) + + # Find all opencv_ libraries in the directory + file(GLOB _opencv_libs "${OPENCV_LIBRARY_DIR}/libopencv_*.so" "${OPENCV_LIBRARY_DIR}/libopencv_*.a") + set(OPENCV_LIBRARIES "") + foreach(lib ${_opencv_libs}) + list(APPEND OPENCV_LIBRARIES ${lib}) + endforeach() + + message(STATUS "Found OpenCV (manual search) in ${OPENCV_LIBRARY_DIR}") +else() + set(OPENCV_FOUND FALSE) + if(OPENCV_FIND_REQUIRED) + message(FATAL_ERROR "OpenCV >= 4.0 not found. Set OpenCV_DIR or OPENCV_DIR.") endif() endif() -# Cache the vars. -set(OPENCV_INCLUDE_DIR ${OPENCV_INCLUDE_DIR} CACHE STRING "The OpenCV include directory." FORCE) -set(OPENCV_LIBRARY_DIRS ${OPENCV_LIBRARY_DIRS} CACHE STRING "The OpenCV library directories." FORCE) -set(OPENCV_LIBRARIES ${OPENCV_LIBRARIES} CACHE STRING "The OpenCV libraries." FORCE) -set(OPENCV_FOUND ${OPENCV_FOUND} CACHE BOOLEAN "The OpenCV found status." FORCE) - -mark_as_advanced(OPENCV_INCLUDE_DIR - OPENCV_LIBRARY_DIRS - OPENCV_LIBRARIES - OPENCV_FOUND) - -#message("OPENCV_INCLUDE_DIR=${OPENCV_INCLUDE_DIR}") -#message("OPENCV_LIBRARY_DIRS=${OPENCV_LIBRARY_DIRS}") -#message("OPENCV_LIBRARIES=${OPENCV_LIBRARIES}") -#message("OPENCV_VERSION_FILE=${OPENCV_VERSION_FILE}") -#message("OPENCV_VERSION=${OPENCV_VERSION}") - -if(NOT OPENCV_FOUND) - if (OPENCV_FIND_REQUIRED) - message(FATAL_ERROR - "OpenCV was not found, please specify the path manually. Version >= 3.0.0 supported.") - endif() -endif() +mark_as_advanced(OPENCV_INCLUDE_DIRS OPENCV_LIBRARIES OPENCV_CORE_LIB) diff --git a/cmake/FindPoco.cmake b/cmake/FindPoco.cmake deleted file mode 100644 index 7497a1860..000000000 --- a/cmake/FindPoco.cmake +++ /dev/null @@ -1,108 +0,0 @@ -# - Try to find the required Poco components (default: Zip Net NetSSL Crypto Util XML CppParser Foundation) -# -# Once done this will define -# Poco_FOUND - System has the all required components. -# Poco_INCLUDE_DIRS - Include directory necessary for using the required components headers. -# Poco_LIBRARY_DIRS - Library directories necessary for using the required components. -# Poco_LIBRARIES - Link these to use the required components. -# Poco_DEFINITIONS - Compiler switches required for using the required components. -# -# For each of the components it will additionally set. -# - Foundation -# - CppParser -# - CppUnit -# - Net -# - NetSSL -# - Crypto -# - Util -# - XML -# - Zip -# - Data -# - PageCompiler -# -# the following variables will be defined -# Poco__FOUND - System has -# Poco__INCLUDE_DIRS - Include directories necessary for using the headers -# Poco__LIBRARY_DIRS - Library directories necessary for using the -# Poco__LIBRARIES - Link these to use -# Poco__DEFINITIONS - Compiler switches required for using -# Poco__VERSION - The components version - -# The default components to find -if (NOT Poco_FIND_COMPONENTS) - set(Poco_FIND_COMPONENTS Zip Net NetSSL Crypto Util XML CppParser Foundation) -endif() - -# Set required variables -set(Poco_ROOT_DIR "" CACHE STRING "Where is the Poco root directory located?") -set(Poco_INCLUDE_DIR "${Poco_ROOT_DIR}" CACHE STRING "Where are the Poco headers (.h) located?") -set(Poco_LIBRARY_DIR "${Poco_ROOT_DIR}/lib" CACHE STRING "Where are the Poco libraries (.dll/.so) located?") -set(Poco_LINK_SHARED_LIBS FALSE CACHE BOOL "Link with shared Poco libraries (.dll/.so) instead of static ones (.lib/.a)") - -#message("Poco_ROOT_DIR=${Poco_ROOT_DIR}") -#message("Poco_INCLUDE_DIR=${Poco_INCLUDE_DIR}") -#message("Poco_LIBRARY_DIR=${Poco_LIBRARY_DIR}") - -# Check for cached results. If there are then skip the costly part. -set_module_notfound(Poco) -if (NOT Poco_FOUND) - - # Set the library suffix for our build type - set(Poco_LIB_SUFFIX "") - if(WIN32 AND MSVC) - set(Poco_MULTI_CONFIGURATION TRUE) - # add_definitions(-DPOCO_NO_AUTOMATIC_LIBS) - # add_definitions(-DPOCO_NO_UNWINDOWS) - if(Poco_LINK_SHARED_LIBS) - add_definitions(-DPOCO_DLL) - else() - add_definitions(-DPOCO_STATIC) - if(BUILD_WITH_STATIC_CRT) - set(Poco_LIB_SUFFIX "mt") - else() - set(Poco_LIB_SUFFIX "md") - endif() - endif() - endif() - - # Set search path suffixes - set(Poco_INCLUDE_SUFFIXES - CppUnit/include - CppParser/include - Data/include - Data/ODBC/include - Foundation/include - Crypto/include - Net/include - NetSSL_OpenSSL/include - PageCompiler/include - Util/include - JSON/include - XML/include - Zip/include - ) - - set(Poco_LIBRARY_SUFFIXES - Linux/i686 - Linux/x86_64 - ) - - # Check for all available components - find_component(Poco CppParser CppParser PocoCppParser${Poco_LIB_SUFFIX} Poco/CppParser/CppParser.h) - find_component(Poco CppUnit CppUnit PocoCppUnit${Poco_LIB_SUFFIX} Poco/CppUnit/CppUnit.h) - find_component(Poco Net Net PocoNet${Poco_LIB_SUFFIX} Poco/Net/Net.h) - find_component(Poco NetSSL NetSSL PocoNetSSL${Poco_LIB_SUFFIX} Poco/Net/NetSSL.h) - find_component(Poco Crypto Crypto PocoCrypto${Poco_LIB_SUFFIX} Poco/Crypto/Crypto.h) - find_component(Poco Util Util PocoUtil${Poco_LIB_SUFFIX} Poco/Util/Util.h) - find_component(Poco JSON JSON PocoJSON${Poco_LIB_SUFFIX} Poco/JSON/JSON.h) - find_component(Poco XML XML PocoXML${Poco_LIB_SUFFIX} Poco/XML/XML.h) - find_component(Poco Zip Zip PocoZip${Poco_LIB_SUFFIX} Poco/Zip/Zip.h) - find_component(Poco Data Data PocoData${Poco_LIB_SUFFIX} Poco/Data/Data.h) - find_component(Poco ODBC ODBC PocoDataODBC${Poco_LIB_SUFFIX} Poco/Data/ODBC/Connector.h) - find_component(Poco PageCompiler PageCompiler PocoPageCompiler${Poco_LIB_SUFFIX} Poco/PageCompiler/PageCompiler.h) - find_component(Poco Foundation Foundation PocoFoundation${Poco_LIB_SUFFIX} Poco/Foundation.h) - - # Set Poco as found or not - # print_module_variables(Poco) - set_module_found(Poco) -endif () diff --git a/cmake/FindRtAudio.cmake b/cmake/FindRtAudio.cmake deleted file mode 100644 index b1113294c..000000000 --- a/cmake/FindRtAudio.cmake +++ /dev/null @@ -1,22 +0,0 @@ -######################################################################## -# CMake module for finding RtAudio -# -# The following variables will be defined: -# -# RTAUDIO_FOUND -# RTAUDIO_INCLUDE_DIR -# RTAUDIO_LIBRARY -# - -find_path(RTAUDIO_INCLUDE_DIR - NAMES RtAudio.h - PATHS ${LibSourcey_SOURCE_DIR}/media/vendor/rtaudio - NO_DEFAULT_PATH) - -find_library(RTAUDIO_LIBRARY - NAMES rtaudio librtaudio - PATHS ${LibSourcey_BUILD_DIR}/src/media/vendor/rtaudio - NO_DEFAULT_PATH) - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(RTAUDIO DEFAULT_MSG RTAUDIO_LIBRARY RTAUDIO_INCLUDE_DIR) diff --git a/cmake/FindSSL.cmake b/cmake/FindSSL.cmake deleted file mode 100644 index fae281603..000000000 --- a/cmake/FindSSL.cmake +++ /dev/null @@ -1,15 +0,0 @@ -######################################################################## -# CMake module for finding SSL library, either OpenSSL or BoringSSL -# - -if (OPENSSL_IS_BORINGSSL) - # KLUDGE: Dont include all WebRTC dependencies, - # filter only the BoringSSL includes and libs. - include_dependency(WebRTC ${ARGN}) - set(SSL_FOUND ${WEBRTC_FOUND} CACHE INTERNAL "") - message(STATUS "Including BoringSSL ${WEBRTC_FOUND}") -else() - include_dependency(OpenSSL ${ARGN}) - set(SSL_FOUND ${OPENSSL_FOUND} CACHE INTERNAL "") - message(STATUS "Including OpenSSL ${OPENSSL_FOUND}") -endif() diff --git a/cmake/FindWebRTC.cmake b/cmake/FindWebRTC.cmake deleted file mode 100644 index 0ae171a10..000000000 --- a/cmake/FindWebRTC.cmake +++ /dev/null @@ -1,199 +0,0 @@ -######################################################################## -# CMake module for finding WEBRTC -# -# The best way to build WebRTC is with the forked `webrtcbuilds` project here: -# https://github.com/sourcey/webrtcbuilds -# -# The following variables will be defined: -# -# WEBRTC_FOUND -# WEBRTC_INCLUDE_DIR -# WEBRTC_LIBRARIES -# WEBRTC_DEPENDENCIES -# - -# unset(WEBRTC_INCLUDE_DIR) -# unset(WEBRTC_INCLUDE_DIR CACHE) -# unset(WEBRTC_LIBRARY) -# unset(WEBRTC_LIBRARY CACHE) -# unset(WEBRTC_LIBRARIES) -# unset(WEBRTC_LIBRARIES CACHE) -# unset(WEBRTC_LIBRARIES_DEBUG) -# unset(WEBRTC_LIBRARIES_DEBUG CACHE) -# unset(WEBRTC_LIBRARIES_RELEASE) -# unset(WEBRTC_LIBRARIES_RELEASE CACHE) - -# Set required variables -set(WEBRTC_ROOT_DIR "" CACHE STRING "Where is the WebRTC root directory located?") -# set(WEBRTC_BUILD_DIR_SUFFIX_DEBUG "out/Debug" CACHE STRING "What is the WebRTC debug build directory suffix?") -# set(WEBRTC_BUILD_DIR_SUFFIX_RELEASE "out/Release" CACHE STRING "What is the WebRTC release build directory suffix?") - -# ---------------------------------------------------------------------- -# Find WEBRTC include path -# ---------------------------------------------------------------------- -find_path(WEBRTC_INCLUDE_DIR - NAMES - webrtc/config.h - PATHS - ${WEBRTC_ROOT_DIR} - ${WEBRTC_ROOT_DIR}/include - $ENV{HOME}/tmp/webrtcbuilds/out/src - $ENV{HOME}/sourcey/webrtcbuilds/out/src -) - -# ---------------------------------------------------------------------- -# Find WEBRTC libraries -# ---------------------------------------------------------------------- -if(WEBRTC_INCLUDE_DIR) - find_existing_directory(debug_dir - ${WEBRTC_ROOT_DIR}/lib/x64/Debug - ${WEBRTC_ROOT_DIR}/out/x64/Debug - ${WEBRTC_ROOT_DIR}/out/Debug_x64 - ${WEBRTC_ROOT_DIR}/out/Debug-x64 - ${WEBRTC_ROOT_DIR}/out/Debug) - - find_existing_directory(release_dir - ${WEBRTC_ROOT_DIR}/lib/x64/Release - ${WEBRTC_ROOT_DIR}/out/x64/Release - ${WEBRTC_ROOT_DIR}/out/Release_x64 - ${WEBRTC_ROOT_DIR}/out/Release-x64 - ${WEBRTC_ROOT_DIR}/out/Release) - - # Attempt to find the monolithic library built with `webrtcbuilds` - find_library_extended(WEBRTC - NAMES webrtc webrtc_full libwebrtc_full - PATHS_DEBUG ${debug_dir} - PATHS_RELEASE ${release_dir} - ) - - # # Otherwise generate a library from available .o objects - # if(NOT WEBRTC_LIBRARY) - # if(EXISTS ${_WEBRTC_BUILD_DIR_DEBUG}) - # message("Generating WebRTC Debug library") - # set(lib_cmd "${LibSourcey_DIR}/cmake/webrtc_lib_generator.sh" -o ${_WEBRTC_BUILD_DIR_DEBUG} -x ${_WEBRTC_GENERATOR_EXCLUDES}) - # execute_process(COMMAND ${lib_cmd}) - # endif() - # - # if(EXISTS ${_WEBRTC_BUILD_DIR_RELEASE}) - # message("Generating WebRTC Release library") - # set(lib_cmd "${LibSourcey_DIR}/cmake/webrtc_lib_generator.sh" -o ${_WEBRTC_BUILD_DIR_RELEASE} -x ${_WEBRTC_GENERATOR_EXCLUDES}) - # execute_process(COMMAND ${lib_cmd}) - # endif() - # - # # Attempt to find our library again... - # find_library_extended(WEBRTC - # NAMES webrtc_scy - # PATHS_DEBUG ${_WEBRTC_BUILD_DIR_DEBUG} - # PATHS_RELEASE ${_WEBRTC_BUILD_DIR_RELEASE} - # ) - # endif() - - # Otherwise fallback to library objects (slower and unreliable) - if(NOT WEBRTC_LIBRARIES) - #unset(WEBRTC_LIBRARY CACHE) - #unset(WEBRTC_LIBRARIES CACHE) - #set(WEBRTC_LIBRARIES "") - - if(MSVC) - set(lib_suffix "lib") - else() - set(lib_suffix "a") - endif() - - # obj/third_party/boringssl/libboringssl.a - # obj/third_party/protobuf/libprotobuf_full.a - # obj/webrtc/system_wrappers/libfield_trial_default.a - # obj/webrtc/system_wrappers/libmetrics_default.a - # obj/webrtc/libwebrtc.a - - set(_WEBRTC_DEPENDENCY_INCLUDES "webrtc\\.a|boringssl|protobuf_full|field_trial_default|metrics_default") #|common|video|media - - # Debug - if (EXISTS ${debug_dir}) - file(GLOB_RECURSE debug_libs "${debug_dir}/*.${lib_suffix}") - foreach(lib ${debug_libs}) - # if(${lib} NOT MATCHES ${_WEBRTC_DEPENDENCY_EXCLUDES}) - if(${lib} MATCHES ${_WEBRTC_DEPENDENCY_INCLUDES}) - list(APPEND WEBRTC_LIBRARIES_DEBUG ${lib}) - endif() - # endif() - endforeach() - foreach(lib ${WEBRTC_LIBRARIES_DEBUG}) - if(WIN32 AND (CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE)) - list(APPEND WEBRTC_LIBRARIES "debug" ${lib}) - else() - list(APPEND WEBRTC_LIBRARIES ${lib}) - endif() - endforeach() - endif() - - # Release - if (EXISTS ${release_dir}) - file(GLOB_RECURSE release_libs "${release_dir}/*.${lib_suffix}") - foreach(lib ${release_libs}) - # if(${lib} NOT MATCHES ${_WEBRTC_DEPENDENCY_EXCLUDES}) - if(${lib} MATCHES ${_WEBRTC_DEPENDENCY_INCLUDES}) - list(APPEND WEBRTC_LIBRARIES_RELEASE ${lib}) - endif() - endforeach() - foreach(lib ${WEBRTC_LIBRARIES_RELEASE}) - if(WIN32 AND (CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE)) - list(APPEND WEBRTC_LIBRARIES "optimized" ${lib}) - else() - list(APPEND WEBRTC_LIBRARIES ${lib}) - endif() - endforeach() - endif() - endif() - - # Add required system libraries - if(CMAKE_SYSTEM_NAME STREQUAL "Windows" AND MSVC) - add_definitions(-DWEBRTC_WIN) - set(WEBRTC_DEPENDENCIES Secur32.lib Winmm.lib msdmo.lib dmoguids.lib wmcodecdspuuid.lib) # strmbase.lib - elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux") - add_definitions(-DWEBRTC_POSIX) - - # For ABI compatability between precompiled WebRTC libraries using clang and new GCC versions - add_definitions(-D_GLIBCXX_USE_CXX11_ABI=0) - set(WEBRTC_DEPENDENCIES -lrt -lX11 -lGLU) # -lGL - - # Enable libstdc++ debugging if you build WebRTC with `enable_iterator_debugging=true` - # set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_GLIBCXX_DEBUG=1") - endif() - - # Add vendor include directories - if(WEBRTC_INCLUDE_DIR) - list(APPEND WEBRTC_INCLUDE_DIRS ${WEBRTC_INCLUDE_DIR} ${WEBRTC_INCLUDE_DIR}/third_party/boringssl/src/include) - endif() - - # workaround for fixing error WEBRTC_LIBRARY-NOTFOUND - set(WEBRTC_LIBRARY_RELEASE ${WEBRTC_LIBRARIES_RELEASE}) - set(WEBRTC_LIBRARY_DEBUG ${WEBRTC_LIBRARIES_DEBUG}) - include(${CMAKE_ROOT}/Modules/SelectLibraryConfigurations.cmake) - select_library_configurations(WEBRTC) - - # message("WEBRTC_LIBRARIES_DEBUG: ${WEBRTC_LIBRARIES_DEBUG}") - # message("WEBRTC_LIBRARIES_RELEASE: ${WEBRTC_LIBRARIES_RELEASE}") - # message("WEBRTC_LIBRARIES: ${WEBRTC_LIBRARIES}") -endif() - -# ---------------------------------------------------------------------- -# Display status -# ---------------------------------------------------------------------- -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(WEBRTC DEFAULT_MSG WEBRTC_LIBRARIES WEBRTC_INCLUDE_DIR) - -# print_module_variables(WEBRTC) - -# HACK: WEBRTC_LIBRARIES and WEBRTC_DEPENDENCIES not propagating to parent scope -# while the WEBRTC_DEBUG_LIBRARY and WEBRTC_RELEASE_LIBRARY vars are. -# Setting PARENT_SCOPE fixes this solves theis issue for now. -set(WEBRTC_LIBRARIES ${WEBRTC_LIBRARIES} CACHE INTERNAL "") -set(WEBRTC_DEPENDENCIES ${WEBRTC_DEPENDENCIES} CACHE INTERNAL "") -set(WEBRTC_INCLUDE_DIRS ${WEBRTC_INCLUDE_DIRS} CACHE INTERNAL "") -set(WEBRTC_FOUND ${WEBRTC_FOUND} CACHE INTERNAL "") - -mark_as_advanced(WEBRTC_LIBRARIES WEBRTC_INCLUDE_DIR - WEBRTC_LIBRARIES_DEBUG WEBRTC_LIBRARIES_RELEASE - WEBRTC_BUILD_DIR_SUFFIX_DEBUG WEBRTC_BUILD_DIR_SUFFIX_RELEASE - WEBRTC_DEPENDENCIES) diff --git a/cmake/LibSourceyCRTLinkage.cmake b/cmake/LibSourceyCRTLinkage.cmake deleted file mode 100644 index 7514285d9..000000000 --- a/cmake/LibSourceyCRTLinkage.cmake +++ /dev/null @@ -1,65 +0,0 @@ -if(NOT MSVC) - message(FATAL_ERROR "CRT options are available only for MSVC") -endif() - -if(NOT BUILD_SHARED_LIBS AND BUILD_WITH_STATIC_CRT) - foreach(flag_var - CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE - CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO - CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE - CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO) - if(${flag_var} MATCHES "/MD") - string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}") - endif() - if(${flag_var} MATCHES "/MDd") - string(REGEX REPLACE "/MDd" "/MTd" ${flag_var} "${${flag_var}}") - endif() - endforeach(flag_var) - - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /NODEFAULTLIB:atlthunk.lib /NODEFAULTLIB:msvcrt.lib /NODEFAULTLIB:msvcrtd.lib") - set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} /NODEFAULTLIB:libcmt.lib") - set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /NODEFAULTLIB:libcmtd.lib") -else() - foreach(flag_var - CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE - CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO - CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE - CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO) - if(${flag_var} MATCHES "/MT") - string(REGEX REPLACE "/MT" "/MD" ${flag_var} "${${flag_var}}") - endif() - if(${flag_var} MATCHES "/MTd") - string(REGEX REPLACE "/MTd" "/MDd" ${flag_var} "${${flag_var}}") - endif() - endforeach(flag_var) -endif() - -if(NOT ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} LESS 2.8 AND NOT ${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION} LESS 8.6) - include(ProcessorCount) - ProcessorCount(N) - if(NOT N EQUAL 0) - SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /MP${N} ") - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP${N} ") - endif() -endif() - -if(NOT BUILD_WITH_DEBUG_INFO AND NOT MSVC) - string(REPLACE "/debug" "" CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG}") - string(REPLACE "/DEBUG" "" CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG}") - string(REPLACE "/INCREMENTAL:YES" "/INCREMENTAL:NO" CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG}") - string(REPLACE "/INCREMENTAL " "/INCREMENTAL:NO " CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG}") - - string(REPLACE "/debug" "" CMAKE_MODULE_LINKER_FLAGS_DEBUG "${CMAKE_MODULE_LINKER_FLAGS_DEBUG}") - string(REPLACE "/DEBUG" "" CMAKE_MODULE_LINKER_FLAGS_DEBUG "${CMAKE_MODULE_LINKER_FLAGS_DEBUG}") - string(REPLACE "/INCREMENTAL:YES" "/INCREMENTAL:NO" CMAKE_MODULE_LINKER_FLAGS_DEBUG "${CMAKE_MODULE_LINKER_FLAGS_DEBUG}") - string(REPLACE "/INCREMENTAL " "/INCREMENTAL:NO " CMAKE_MODULE_LINKER_FLAGS_DEBUG "${CMAKE_MODULE_LINKER_FLAGS_DEBUG}") - - string(REPLACE "/debug" "" CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG}") - string(REPLACE "/DEBUG" "" CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG}") - string(REPLACE "/INCREMENTAL:YES" "/INCREMENTAL:NO" CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG}") - string(REPLACE "/INCREMENTAL " "/INCREMENTAL:NO " CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG}") - - string(REPLACE "/Zi" "" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}") - string(REPLACE "/Zi" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}") -endif() - diff --git a/cmake/LibSourceyCompilerOptions.cmake b/cmake/LibSourceyCompilerOptions.cmake index 8525e7329..b44726863 100644 --- a/cmake/LibSourceyCompilerOptions.cmake +++ b/cmake/LibSourceyCompilerOptions.cmake @@ -1,268 +1,52 @@ -# Initialize flags -set(LibSourcey_EXTRA_C_FLAGS "") -set(LibSourcey_EXTRA_C_FLAGS_RELEASE "") -set(LibSourcey_EXTRA_C_FLAGS_DEBUG "") -set(LibSourcey_EXTRA_EXE_LINKER_FLAGS "") -set(LibSourcey_EXTRA_EXE_LINKER_FLAGS_RELEASE "") -set(LibSourcey_EXTRA_EXE_LINKER_FLAGS_DEBUG "") - -# Set processor flags -if(CMAKE_SYSTEM_PROCESSOR MATCHES amd64.*|x86_64.*) - set(X86_64 1) -elseif(CMAKE_SYSTEM_PROCESSOR MATCHES i686.*|i386.*|x86.*) - set(X86 1) -endif() - -if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") - # message(STATUS "Detected version of GNU GCC: ${CMAKE_CXX_COMPILER_VERSION}") - - # Require at least gcc 4.9 - if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9) - message(FATAL_ERROR "GCC version must be at least 4.9!") - endif() - - # Using c++14 (CMAKE_CXX_FLAGS only, not for CMAKE_C_FLAGS) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++1y") - - # High level of warnings. - set(LibSourcey_EXTRA_C_FLAGS "${LibSourcey_EXTRA_C_FLAGS} -Wall") - - # The -Wno-long-long is required in 64bit systems when including sytem headers. - if(X86_64) - set(LibSourcey_EXTRA_C_FLAGS "${LibSourcey_EXTRA_C_FLAGS} -Wno-long-long") - endif() - - # We need pthread's - if(UNIX AND NOT ANDROID AND NOT APPLE) - set(LibSourcey_EXTRA_C_FLAGS "${LibSourcey_EXTRA_C_FLAGS} -pthread") - endif() - - # if(BUILD_SHARED_LIBS) - # set(LibSourcey_EXTRA_C_FLAGS "-shared ${LibSourcey_EXTRA_C_FLAGS}") - # else() - # set(LibSourcey_EXTRA_C_FLAGS "-static ${LibSourcey_EXTRA_C_FLAGS}") - # endif() - - if(ENABLE_WARNINGS_ARE_ERRORS) - set(LibSourcey_EXTRA_C_FLAGS "${LibSourcey_EXTRA_C_FLAGS} -Werror") - endif() - - if(X86 AND NOT MINGW64 AND NOT X86_64 AND NOT APPLE) - set(LibSourcey_EXTRA_C_FLAGS "${LibSourcey_EXTRA_C_FLAGS} -march=i686") - endif() - - # Other optimizations - if(ENABLE_OMIT_FRAME_POINTER) - set(LibSourcey_EXTRA_C_FLAGS "${LibSourcey_EXTRA_C_FLAGS} -fomit-frame-pointer") - else() - set(LibSourcey_EXTRA_C_FLAGS "${LibSourcey_EXTRA_C_FLAGS} -fno-omit-frame-pointer") - endif() - if(ENABLE_FAST_MATH) - set(LibSourcey_EXTRA_C_FLAGS "${LibSourcey_EXTRA_C_FLAGS} -ffast-math") - endif() - if(ENABLE_POWERPC) - set(LibSourcey_EXTRA_C_FLAGS "${LibSourcey_EXTRA_C_FLAGS} -mcpu=G3 -mtune=G5") - endif() - if(ENABLE_SSE) - set(LibSourcey_EXTRA_C_FLAGS "${LibSourcey_EXTRA_C_FLAGS} -msse") - endif() - if(ENABLE_SSE2) - set(LibSourcey_EXTRA_C_FLAGS "${LibSourcey_EXTRA_C_FLAGS} -msse2") - endif() - - # SSE3 and further should be disabled under MingW because it generates compiler errors - if(NOT MINGW) - if(ENABLE_SSE3) - set(LibSourcey_EXTRA_C_FLAGS "${LibSourcey_EXTRA_C_FLAGS} -msse3") - endif() - - if(APPLE) - if(ENABLE_SSSE3) - set(LibSourcey_EXTRA_C_FLAGS "${LibSourcey_EXTRA_C_FLAGS} -mssse3") - endif() - if(ENABLE_SSE41) - set(LibSourcey_EXTRA_C_FLAGS "${LibSourcey_EXTRA_C_FLAGS} -msse4.1") - endif() - if(ENABLE_SSE42) - set(LibSourcey_EXTRA_C_FLAGS "${LibSourcey_EXTRA_C_FLAGS} -msse4.2") - endif() - endif() - endif(NOT MINGW) - - if (CMAKE_GENERATOR MATCHES "(MinGW)|(MSYS)") - set(CMAKE_CXX_FLAGS_RELEASE "-O2 -DNDEBUG" CACHE STRING "") - endif() - - if(X86 OR X86_64) - if(NOT APPLE AND CMAKE_SIZEOF_VOID_P EQUAL 4) - if(ENABLE_SSE2) - set(LibSourcey_EXTRA_C_FLAGS "${LibSourcey_EXTRA_C_FLAGS} -mfpmath=sse")# !! important - be on the same wave with x64 compilers - else() - set(LibSourcey_EXTRA_C_FLAGS "${LibSourcey_EXTRA_C_FLAGS} -mfpmath=387") - endif() - endif() - endif() - - # Profiling? - if(ENABLE_PROFILING) - set(LibSourcey_EXTRA_C_FLAGS "${LibSourcey_EXTRA_C_FLAGS} -pg -g") - # turn off incompatible options - foreach(flags CMAKE_CXX_FLAGS CMAKE_C_FLAGS CMAKE_CXX_FLAGS_RELEASE CMAKE_C_FLAGS_RELEASE CMAKE_CXX_FLAGS_DEBUG CMAKE_C_FLAGS_DEBUG LibSourcey_EXTRA_C_FLAGS_RELEASE) - string(REPLACE "-fomit-frame-pointer" "" ${flags} "${${flags}}") - string(REPLACE "-ffunction-sections" "" ${flags} "${${flags}}") - endforeach() - elseif(NOT APPLE AND NOT ANDROID) - # Remove unreferenced functions: function level linking - set(LibSourcey_EXTRA_C_FLAGS "${LibSourcey_EXTRA_C_FLAGS} -ffunction-sections") - endif() - - set(LibSourcey_EXTRA_C_FLAGS_RELEASE "${LibSourcey_EXTRA_C_FLAGS_RELEASE} -DNDEBUG") - set(LibSourcey_EXTRA_C_FLAGS_DEBUG "${LibSourcey_EXTRA_C_FLAGS_DEBUG} -O0 -DDEBUG -D_DEBUG") - if(BUILD_WITH_DEBUG_INFO) - set(LibSourcey_EXTRA_C_FLAGS_DEBUG "${LibSourcey_EXTRA_C_FLAGS_DEBUG} -ggdb3") - endif() - - if(NOT BUILD_SHARED_LIBS AND NOT ANDROID) - # Android does not need these settings because they are already set by toolchain file - set(LibSourcey_LINKER_LIBS ${LibSourcey_LINKER_LIBS} stdc++) - set(LibSourcey_EXTRA_C_FLAGS "-fPIC ${LibSourcey_EXTRA_C_FLAGS}") - endif() -endif() - -# Visual Studio -if(MSVC) - - # Ensure >= 2012 Update 4 for C++11 and Windows XP build support - if(MSVC_VERSION LESS 1700) # VC10-/VS2010- - message(FATAL_ERROR "The project requires C++11 features. " - "You need at least Visual Studio 11 (Microsoft Visual Studio 2012), " - "with Microsoft Visual C++ Compiler 2012 CTP (v110_xp).") - elseif( MSVC_VERSION EQUAL 1700 ) # VC11/VS2012 - #message( "VC11: use Microsoft Visual Studio 2012 " - # "with Microsoft Visual C++ Compiler 2012 CTP (v110_xp)" ) - set(CMAKE_GENERATOR_TOOLSET "v110_xp" CACHE STRING "Platform Toolset" FORCE) - else() # VC12+, assuming C++11 supported. - endif() - - if(CMAKE_CXX_FLAGS STREQUAL CMAKE_CXX_FLAGS_INIT) - # override cmake default exception handling option - string(REPLACE "/EHsc" "/EHa" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" CACHE STRING "Flags used by the compiler during all build types." FORCE) - endif() - - set(LibSourcey_EXTRA_C_FLAGS "${LibSourcey_EXTRA_C_FLAGS} /D _CRT_SECURE_NO_DEPRECATE /D _CRT_NONSTDC_NO_DEPRECATE /D _SCL_SECURE_NO_WARNINGS") - # 64-bit portability warnings, in MSVC80 - if(MSVC80) - set(LibSourcey_EXTRA_C_FLAGS "${LibSourcey_EXTRA_C_FLAGS} /Wp64") - endif() - - if(BUILD_WITH_DEBUG_INFO) - set(LibSourcey_EXTRA_EXE_LINKER_FLAGS_RELEASE "${LibSourcey_EXTRA_EXE_LINKER_FLAGS_RELEASE} /debug") - endif() - - # Remove unreferenced functions: function level linking - set(LibSourcey_EXTRA_C_FLAGS "${LibSourcey_EXTRA_C_FLAGS} /Gy") - if(NOT MSVC_VERSION LESS 1400) - set(LibSourcey_EXTRA_C_FLAGS "${LibSourcey_EXTRA_C_FLAGS} /bigobj") - endif() - if(BUILD_WITH_DEBUG_INFO) - set(LibSourcey_EXTRA_C_FLAGS_RELEASE "${LibSourcey_EXTRA_C_FLAGS_RELEASE} /Zi") - endif() - - # Getting bitten by this bug: https://public.kitware.com/Bug/view.php?id=15496 - if(${CMAKE_GENERATOR} MATCHES "Win64") - #set(CMAKE_GENERATOR_PLATFORM x64) - set(CMAKE_MODULE_LINKER_FLAGS "/machine:x64") - set(CMAKE_SHARED_LINKER_FLAGS "/machine:x64") - set(CMAKE_STATIC_LINKER_FLAGS "/machine:x64") - set(CMAKE_EXE_LINKER_FLAGS "/machine:x64") - endif() - - if(NOT MSVC64) - # 64-bit MSVC compiler uses SSE/SSE2 by default - if(ENABLE_SSE) - set(LibSourcey_EXTRA_C_FLAGS "${LibSourcey_EXTRA_C_FLAGS} /arch:SSE") - endif() - if(ENABLE_SSE2) - set(LibSourcey_EXTRA_C_FLAGS "${LibSourcey_EXTRA_C_FLAGS} /arch:SSE2") - endif() - endif() - - if(ENABLE_SSE3) - set(LibSourcey_EXTRA_C_FLAGS "${LibSourcey_EXTRA_C_FLAGS} /arch:SSE3") - endif() - if(ENABLE_SSE4_1) - set(LibSourcey_EXTRA_C_FLAGS "${LibSourcey_EXTRA_C_FLAGS} /arch:SSE4.1") - endif() - - if(ENABLE_SSE OR ENABLE_SSE2 OR ENABLE_SSE3 OR ENABLE_SSE4_1) - set(LibSourcey_EXTRA_C_FLAGS "${LibSourcey_EXTRA_C_FLAGS} /Oi") - endif() - - if(X86 OR X86_64) - if(CMAKE_SIZEOF_VOID_P EQUAL 4 AND ENABLE_SSE2) - set(LibSourcey_EXTRA_C_FLAGS "${LibSourcey_EXTRA_C_FLAGS} /fp:fast")# !! important - be on the same wave with x64 compilers - endif() - endif() -endif() - -# Extra link libs if the user selects building static libs: -#if(NOT BUILD_SHARED_LIBS AND CMAKE_COMPILER_IS_GNUCXX AND NOT ANDROID) - # Android does not need these settings because they are already set by toolchain file - #set(LibSourcey_LINKER_LIBS ${LibSourcey_LINKER_LIBS} stdc++) - #set(LibSourcey_EXTRA_C_FLAGS "-fPIC ${LibSourcey_EXTRA_C_FLAGS}") -#endif() - -# Add user supplied extra options (optimization, etc...) -# ========================================================== -set(LibSourcey_EXTRA_C_FLAGS "${LibSourcey_EXTRA_C_FLAGS}" CACHE INTERNAL "Extra compiler options") -set(LibSourcey_EXTRA_C_FLAGS_RELEASE "${LibSourcey_EXTRA_C_FLAGS_RELEASE}" CACHE INTERNAL "Extra compiler options for Release build") -set(LibSourcey_EXTRA_C_FLAGS_DEBUG "${LibSourcey_EXTRA_C_FLAGS_DEBUG}" CACHE INTERNAL "Extra compiler options for Debug build") -set(LibSourcey_EXTRA_EXE_LINKER_FLAGS "${LibSourcey_EXTRA_EXE_LINKER_FLAGS}" CACHE INTERNAL "Extra linker flags") -set(LibSourcey_EXTRA_EXE_LINKER_FLAGS_RELEASE "${LibSourcey_EXTRA_EXE_LINKER_FLAGS_RELEASE}" CACHE INTERNAL "Extra linker flags for Release build") -set(LibSourcey_EXTRA_EXE_LINKER_FLAGS_DEBUG "${LibSourcey_EXTRA_EXE_LINKER_FLAGS_DEBUG}" CACHE INTERNAL "Extra linker flags for Debug build") - -# Combine all "extra" options -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${LibSourcey_EXTRA_C_FLAGS}") -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${LibSourcey_EXTRA_C_FLAGS}") -set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${LibSourcey_EXTRA_C_FLAGS_RELEASE}") -set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${LibSourcey_EXTRA_C_FLAGS_RELEASE}") -set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${LibSourcey_EXTRA_C_FLAGS_DEBUG}") -set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${LibSourcey_EXTRA_C_FLAGS_DEBUG}") -set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LibSourcey_EXTRA_EXE_LINKER_FLAGS}") -set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} ${LibSourcey_EXTRA_EXE_LINKER_FLAGS_RELEASE}") -set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} ${LibSourcey_EXTRA_EXE_LINKER_FLAGS_DEBUG}") - -if(MSVC) - # Avoid warnings from MSVC about overriding the /W* option - # We replace /W3 with /W4 only for C++ files, - # since all the 3rd-party libraries LibSourcey uses are in C, - # and we do not care about their warnings. - string(REPLACE "/W3" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") - string(REPLACE "/W3" "/W4" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") - string(REPLACE "/W3" "/W4" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}") - - # Temporary workaround for "error LNK2026: module unsafe for SAFESEH image" - # when compiling with certain externally compiled libraries with VS2012, - # such as http://ffmpeg.zeranoe.com/builds/ - # This disables safe exception handling by default. - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SAFESEH:NO") - set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /SAFESEH:NO") - set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} /SAFESEH:NO") - - # Use x64 by default. This prevents conflicts with dependencies such as OpenSSL - # and FFmpeg on Windows. - # set(CMAKE_GENERATOR_PLATFORM x64) - - # allow extern "C" functions throw exceptions - foreach(flags CMAKE_C_FLAGS CMAKE_C_FLAGS_RELEASE CMAKE_C_FLAGS_RELEASE CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_DEBUG) - string(REPLACE "/EHsc-" "/EHs" ${flags} "${${flags}}") - string(REPLACE "/EHsc" "/EHs" ${flags} "${${flags}}") - - string(REPLACE "/Zm1000" "" ${flags} "${${flags}}") - endforeach() - - if(NOT ENABLE_NOISY_WARNINGS) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4251") #class 'std::XXX' needs to have dll-interface to be used by clients of YYY - endif() -endif() +# LibSourcey compiler options +# Modern compilers: GCC 12+, Clang 15+, MSVC 2022+ + +if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") + add_compile_options( + -Wall + -Wextra + -Wno-unused-parameter + ) + + if(ENABLE_WARNINGS_ARE_ERRORS) + add_compile_options(-Werror) + endif() + + if(NOT BUILD_SHARED_LIBS AND NOT ANDROID) + add_compile_options(-fPIC) + endif() + + if(UNIX AND NOT ANDROID AND NOT APPLE) + add_compile_options(-pthread) + link_libraries(-pthread) + endif() + + # Debug/Release flags + add_compile_options( + $<$:-O0> + $<$:-g> + ) + + if(ENABLE_PROFILING) + add_compile_options(-pg -g) + endif() +endif() + +if(MSVC) + add_compile_options( + /W4 + /wd4251 # needs dll-interface + /wd4100 # unreferenced formal parameter + /bigobj + /EHa # async exception handling + ) + add_compile_definitions( + _CRT_SECURE_NO_DEPRECATE + _CRT_NONSTDC_NO_DEPRECATE + _SCL_SECURE_NO_WARNINGS + ) + + if(ENABLE_WARNINGS_ARE_ERRORS) + add_compile_options(/WX) + endif() +endif() diff --git a/cmake/LibSourceyConfig.cmake.in b/cmake/LibSourceyConfig.cmake.in new file mode 100644 index 000000000..05e26077c --- /dev/null +++ b/cmake/LibSourceyConfig.cmake.in @@ -0,0 +1,23 @@ +@PACKAGE_INIT@ + +include(CMakeFindDependencyMacro) + +# Re-find dependencies that our targets need +find_dependency(Threads) + +if(@HAVE_OPENSSL@) + find_dependency(OpenSSL) +endif() + +if(@HAVE_FFMPEG@) + # FFmpeg doesn't have standard CMake config; consumers need to find it themselves +endif() + +if(@HAVE_OPENCV@) + find_dependency(OpenCV) +endif() + +# Import targets +include("${CMAKE_CURRENT_LIST_DIR}/LibSourceyTargets.cmake") + +check_required_components(LibSourcey) diff --git a/cmake/LibSourceyIncludes.cmake b/cmake/LibSourceyIncludes.cmake deleted file mode 100644 index 16ef86191..000000000 --- a/cmake/LibSourceyIncludes.cmake +++ /dev/null @@ -1,651 +0,0 @@ -# -### Macro: add_vendor_dependency -# -macro(add_vendor_dependency name libname) - set(libdir ${LibSourcey_VENDOR_SOURCE_DIR}/${libname}) - - add_subdirectory(${libdir} ${LibSourcey_VENDOR_BUILD_DIR}/${libname}) - - # Include current directory and existing dependency directories - # include_directories(${libdir}) - - # Cache dependency directories for inclusion by modules and applications - # get_directory_property(lib_directories INCLUDE_DIRECTORIES) - set(LibSourcey_INCLUDE_DIRS ${libdir}) - set(LibSourcey_LINK_LIBRARIES ${LibSourcey_LINK_LIBRARIES} ${libname}) - set(LibSourcey_BUILD_DEPENDENCIES ${LibSourcey_BUILD_DEPENDENCIES} ${libname}) - set(HAVE_${name} TRUE) - - set(LibSourcey_INCLUDE_DIRS ${LibSourcey_INCLUDE_DIRS} CACHE INTERNAL "") - set(LibSourcey_LINK_LIBRARIES ${LibSourcey_LINK_LIBRARIES} CACHE INTERNAL "") - set(LibSourcey_BUILD_DEPENDENCIES ${LibSourcey_BUILD_DEPENDENCIES} CACHE INTERNAL "") - set(HAVE_${name} TRUE CACHE INTERNAL "") - - # get_directory_property(hasParent PARENT_DIRECTORY) - # if(hasParent) - # set(LibSourcey_INCLUDE_DIRS ${libdir} PARENT_SCOPE) - # set(LibSourcey_LINK_LIBRARIES ${LibSourcey_LINK_LIBRARIES} ${libname} PARENT_SCOPE) - # set(LibSourcey_BUILD_DEPENDENCIES ${LibSourcey_BUILD_DEPENDENCIES} ${libname} PARENT_SCOPE) - - # set(HAVE_${name} TRUE PARENT_SCOPE) - # endif() -endmacro() - - -# -### Function: find_dependency -# -# Finds a 3rd party dependency and sets the XXX_FOUND and HAVE_XXX variables. -# -function(find_dependency name) - - # Set the variable scope - set(var_root ${name}) - string(TOUPPER ${var_root} var_root_upper) - - # If the module is disabled then continue - if(DEFINED WITH_${var_root_upper} AND NOT WITH_${var_root_upper}) - return() - endif() - - # start_track_variables() - find_package(${name} ${ARGN}) - # forward_changed_variables_to_parent_scope() #(bla_bla); - - # Try to find standard uppercase variable accessor - set(lib_found 0) - if(${var_root_upper}_FOUND) - set(var_root ${var_root_upper}) - set(lib_found 1) - # else() - # if(${var_root}_FOUND) - # set(lib_found 1) - # endif() - endif() - - # Exit message on failure - if (NOT ${var_root}_FOUND) - - # NOTE: find_package does not always honour REQUIRED flag, so make - # sure the build is cancelled if the dependency wasnt found. - if (${ARGN} MATCHES REQUIRED) - message(FATAL_ERROR "Failed to include dependency: ${name}. Please build and install dependencies before using CMake.") - else() - message("Failed to include dependency: ${name}. Please build and install dependencies before using CMake.") - return() - endif() - endif() - - # Set a HAVE_XXX variable at global scope for the libsourcey.h config sile - set(HAVE_${var_root_upper} TRUE CACHE INTERNAL "") - set(${var_root_upper}_FOUND TRUE CACHE INTERNAL "") - - # HACK: This is also called in `include_dependency`, but for some reason - # valiables set by `find_package`, such as `OPENSSL_LIBRARIES` set by - # are not propagating to the outside `include_dependency` function scope. - # This behaviour was noted with cmake 3.5.2 when calling FindSSL.cmake. - # Expose normal and uppercase variants to LibSourcey - string(TOUPPER ${name} name_upper) - add_dependency_build_variables(${name}) - add_dependency_build_variables(${name_upper}) - - # This is required for multi-level finders such as FindSSL.cmake - # get_directory_property(hasParent PARENT_DIRECTORY) - # if(hasParent) - # set(HAVE_${var_root_upper} TRUE PARENT_SCOPE) - # set(${var_root_upper}_FOUND TRUE PARENT_SCOPE) - # endif() -endfunction() - - -# -### Macro: include_dependency -# -# Includes a 3rd party dependency into the LibSourcey solution. -# -function(include_dependency name) - message(STATUS "Including dependency: ${name}") - find_dependency(${name} ${ARGN}) - - # Expose normal and uppercase variants to LibSourcey - string(TOUPPER ${name} name_upper) - add_dependency_build_variables(${name}) - add_dependency_build_variables(${name_upper}) -endfunction() - - -# -### Macro: add_dependency_build_variables -# -# Adds a dependency variables the LibSourcey build variables. -# -macro(add_dependency_build_variables name) - # print_module_variables(${name}) - - # TODO: Remove the use of global LibSourcey_XXX variables and use - # set_target_xxx function to set dependencies on a target specific basis. - - if(${name}_INCLUDE_DIR) - # message(STATUS "- Found ${name} Inc Dir: ${${name}_INCLUDE_DIR}") - #include_directories(${${name}_INCLUDE_DIR}) - list(APPEND LibSourcey_INCLUDE_DIRS ${${name}_INCLUDE_DIR}) - set(LibSourcey_INCLUDE_DIRS ${LibSourcey_INCLUDE_DIRS} ${${name}_INCLUDE_DIR}) - endif() - if(${name}_INCLUDE_DIRS) - # message(STATUS "- Found ${name} Inc Dirs: ${${name}_INCLUDE_DIRS}") - #include_directories(${${name}_INCLUDE_DIRS}) - list(APPEND LibSourcey_INCLUDE_DIRS ${${name}_INCLUDE_DIRS}) - set(LibSourcey_INCLUDE_DIRS ${LibSourcey_INCLUDE_DIRS} ${${name}_INCLUDE_DIRS}) - endif() - if(${name}_LIBRARY_DIR) - #message(STATUS "- Found ${name} Lib Dir: ${${name}_LIBRARY_DIR}") - #link_directories(${${name}_LIBRARY_DIR}) - list(APPEND LibSourcey_LIBRARY_DIRS ${${name}_LIBRARY_DIR}) - set(LibSourcey_LIBRARY_DIRS ${LibSourcey_LIBRARY_DIRS} ${${name}_LIBRARY_DIR}) - endif() - if(${name}_LIBRARY_DIRS) - #message(STATUS "- Found ${name} Lib Dirs: ${${name}_LIBRARY_DIRS}") - #link_directories(${${name}_LIBRARY_DIRS}) - list(APPEND LibSourcey_LIBRARY_DIRS ${${name}_LIBRARY_DIRS}) - set(LibSourcey_LIBRARY_DIRS ${LibSourcey_LIBRARY_DIRS} ${${name}_LIBRARY_DIRS}) - endif() - if(${name}_LIBRARY) - # message(STATUS "- Found dependency lib ${name}: ${${name}_LIBRARY}") - list(APPEND LibSourcey_INCLUDE_LIBRARIES ${${name}_LIBRARY}) - set(LibSourcey_INCLUDE_LIBRARIES ${LibSourcey_INCLUDE_LIBRARIES} ${${name}_LIBRARY}) - endif() - if(${name}_LIBRARIES) - # message(STATUS "- Found dependency libs ${name}: ${${name}_LIBRARIES}") - list(APPEND LibSourcey_INCLUDE_LIBRARIES ${${name}_LIBRARIES}) - set(LibSourcey_INCLUDE_LIBRARIES ${LibSourcey_INCLUDE_LIBRARIES} ${${name}_LIBRARIES}) - endif() - if(${name}_DEPENDENCIES) - # message(STATUS "- Found external dependency ${name}: ${${name}_DEPENDENCIES}") - list(APPEND LibSourcey_INCLUDE_LIBRARIES ${${name}_DEPENDENCIES}) - set(LibSourcey_INCLUDE_LIBRARIES ${LibSourcey_INCLUDE_LIBRARIES} ${${name}_DEPENDENCIES}) - endif() - - # if(LibSourcey_INCLUDE_DIRS) - # list(REMOVE_DUPLICATES LibSourcey_INCLUDE_DIRS) - # endif() - # if(LibSourcey_LIBRARY_DIRS) - # list(REMOVE_DUPLICATES LibSourcey_LIBRARY_DIRS) - # endif() - # if(LibSourcey_INCLUDE_LIBRARIES) - # list(REMOVE_DUPLICATES LibSourcey_INCLUDE_LIBRARIES) - # endif() - # if(LibSourcey_BUILD_DEPENDENCIES) - # list(REMOVE_DUPLICATES LibSourcey_BUILD_DEPENDENCIES) - # endif() - - set(LibSourcey_LIBRARY_DIRS ${LibSourcey_LIBRARY_DIRS} CACHE INTERNAL "") - set(LibSourcey_INCLUDE_DIRS ${LibSourcey_INCLUDE_DIRS} CACHE INTERNAL "") - set(LibSourcey_INCLUDE_LIBRARIES ${LibSourcey_INCLUDE_LIBRARIES} CACHE INTERNAL "") - - set(LibSourcey_LIBRARY_DIRS ${LibSourcey_LIBRARY_DIRS} PARENT_SCOPE) - set(LibSourcey_INCLUDE_DIRS ${LibSourcey_INCLUDE_DIRS} PARENT_SCOPE) - set(LibSourcey_INCLUDE_LIBRARIES ${LibSourcey_INCLUDE_LIBRARIES} PARENT_SCOPE) -endmacro() - - -# -### Macro: set_default_project_directories -# -# Set the default header and library directories for a LibSourcey project. -# -macro(set_default_project_directories name) - # set(MODULE_${name}) - foreach(module ${ARGN}) - list(APPEND LibSourcey_LIBRARY_DIRS ${LibSourcey_BUILD_DIR}/${module}) - list(APPEND LibSourcey_INCLUDE_DIRS ${LibSourcey_SOURCE_DIR}/${module}/include) - endforeach() - - target_include_directories(${name} PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/include - ${LibSourcey_INCLUDE_DIRS} - ${LibSourcey_VENDOR_INCLUDE_DIRS} - ${CMAKE_BINARY_DIR} - ) - - # include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) - # include_directories(${LibSourcey_INCLUDE_DIRS}) - # include_directories(${LibSourcey_VENDOR_INCLUDE_DIRS}) # include all internal vendor dirs - # include_directories(${CMAKE_BINARY_DIR}) - link_directories(${LibSourcey_LIBRARY_DIRS}) -endmacro() - - -# -### Macro: set_default_project_dependencies -# -# Set the default dependencies for a LibSourcey project. -# -macro(set_default_project_dependencies name) - # foreach(dep ${LibSourcey_BUILD_DEPENDENCIES}) - # add_dependencies(${name} ${dep}) - # endforeach() - - # Include dependent modules - foreach(module ${ARGN}) - add_dependencies(${name} ${module}) - endforeach() - - # Include all linker libraries - set(${name}_LIBRARIES ${ARGN}) - list(APPEND ${name}_LIBRARIES ${LibSourcey_INCLUDE_LIBRARIES}) - list(APPEND ${name}_LIBRARIES ${LibSourcey_BUILD_DEPENDENCIES}) - - # Allow exclusion of specific libraries - if (${name}_EXCLUDE_LIBRARIES) - foreach(lib ${${name}_LIBRARIES}) - if(${lib} MATCHES ${${name}_EXCLUDE_LIBRARIES}) - list(REMOVE_ITEM ${name}_LIBRARIES ${lib}) - endif() - endforeach() - endif() - - #message(STATUS "${name} link libraries: ${LibSourcey_INCLUDE_LIBRARIES}") - target_link_libraries(${name} ${${name}_LIBRARIES}) -endmacro() - - -# -### Macro: include_sourcey_modules -# -# Includes dependent LibSourcey module(s) into a project. -# -#macro(include_sourcey_modules) -# foreach(name ${ARGN}) -# #message(STATUS "Including module: ${name}") -# -# set_scy_libname(${name} lib_name) -# -# # Include the build library directory. -# list(APPEND LibSourcey_LIBRARY_DIRS ${LibSourcey_BUILD_DIR}/src/${name}) -# -# # Include the module headers. -# # These may be located in the "src/" root directory or in a sub directory. -# set(HAVE_SOURCEY_${name} 0) -# if(IS_DIRECTORY "${LibSourcey_SOURCE_DIR}/${name}/include") -# #include_directories("${LibSourcey_SOURCE_DIR}/${name}/include") -# list(APPEND LibSourcey_INCLUDE_DIRS ${LibSourcey_SOURCE_DIR}/${name}/include) -# set(HAVE_SOURCEY_${name} 1) -# else() -# subdirlist(subdirs "${LibSourcey_SOURCE_DIR}") -# foreach(dir ${subdirs}) -# set(dir "${LibSourcey_SOURCE_DIR}/${dir}/${name}/include") -# if(IS_DIRECTORY ${dir}) -# #include_directories(${dir}) -# list(APPEND LibSourcey_INCLUDE_DIRS ${dir}) -# set(HAVE_SOURCEY_${name} 1) -# endif() -# endforeach() -# endif() -# -# if (NOT HAVE_SOURCEY_${name}) -# message(ERROR "Unable to include dependent LibSourcey module ${name}. The build may fail.") -# endif() -# -# # Create a Debug and a Release list for MSVC -# if (MSVC) -# -# # Find the module giving priority to the build output folder, and install folder second. -# # This way we don't have to install updated modules before building applications -# # simplifying the build process. -# -# # Always reset the module folders. -# set(LibSourcey_${name}_RELEASE LibSourcey_${name}_RELEASE-NOTFOUND) -# #set(LibSourcey_${name}_RELEASE LibSourcey_${name}_RELEASE-NOTFOUND PARENT_SCOPE) -# set(LibSourcey_${name}_DEBUG LibSourcey_${name}_DEBUG-NOTFOUND) -# #set(LibSourcey_${name}_DEBUG LibSourcey_${name}_DEBUG-NOTFOUND PARENT_SCOPE) -# -# # Since CMake doesn't give priority to the PATHS parameter, we need to search twice: -# # once using NO_DEFAULT_PATH, and once using default values. -# # TODO: Better handle nested module build dirs, or have all modules build to -# # intermediate directory for easy searching. -# find_library(LibSourcey_${name}_RELEASE "${lib_name}" -# PATHS -# ${LibSourcey_BUILD_DIR}/src/${name} -# ${LibSourcey_BUILD_DIR}/src/anionu-sdk/${name} -# ${LibSourcey_BUILD_DIR}/src/anionu-private/${name} -# PATH_SUFFIXES Release -# NO_DEFAULT_PATH) -# find_library(LibSourcey_${name}_DEBUG "${lib_name}d" -# PATHS -# ${LibSourcey_BUILD_DIR}/src/${name} -# ${LibSourcey_BUILD_DIR}/src/anionu-sdk/${name} -# ${LibSourcey_BUILD_DIR}/src/anionu-private/${name} -# PATH_SUFFIXES Debug -# NO_DEFAULT_PATH) -# -# # Search the module install folder if none was located. -# find_library(LibSourcey_${name}_RELEASE "${lib_name}") -# find_library(LibSourcey_${name}_DEBUG "${lib_name}d") -# -# if(CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE) -# if (LibSourcey_${name}_RELEASE) -# list(APPEND LibSourcey_INCLUDE_LIBRARIES "optimized" ${LibSourcey_${name}_RELEASE}) -# mark_as_advanced(LibSourcey_${name}_RELEASE) -# endif() -# if (LibSourcey_${name}_DEBUG) -# list(APPEND LibSourcey_INCLUDE_LIBRARIES "debug" ${LibSourcey_${name}_DEBUG}) -# mark_as_advanced(LibSourcey_${name}_DEBUG) -# endif() -# else() -# if (LibSourcey_${name}_RELEASE) -# list(APPEND LibSourcey_INCLUDE_LIBRARIES ${LibSourcey_${name}_RELEASE}) -# mark_as_advanced(LibSourcey_${name}_RELEASE) -# endif() -# if (LibSourcey_${name}_DEBUG) -# mark_as_advanced(LibSourcey_${name}_DEBUG) -# endif() -# endif() -# else() -# # Find the module giving preference to the build output folder. -# #find_library(LibSourcey_${name} "${lib_name}" -# # PATHS ${LibSourcey_BUILD_DIR}/lib/${name} -# # NO_DEFAULT_PATH) -# find_library(LibSourcey_${name} "${lib_name}") -# if (LibSourcey_${name}) -# # Prepend module libraries otherwise linking may fail -# # on compilers that require ordering of link libraries. -# set(LibSourcey_INCLUDE_LIBRARIES ${LibSourcey_${name}} ${LibSourcey_INCLUDE_LIBRARIES}) -# mark_as_advanced(LibSourcey_${name}) -# else() -# endif() -# endif() -# endforeach() -#endmacro() - -# # -# ### Macro: set_component_alias -# # -# # Sets the current module component alias variables. -# # -# macro(set_component_alias module component) -# set(ALIAS ${module}_${component}) -# set(ALIAS_FOUND ${ALIAS}_FOUND) -# set(ALIAS_LIBRARIES ${ALIAS}_LIBRARIES) -# set(ALIAS_RELEASE_LIBRARIES ${ALIAS}_RELEASE_LIBRARIES) -# set(ALIAS_DEBUG_LIBRARIES ${ALIAS}_DEBUG_LIBRARIES) -# set(ALIAS_INCLUDE_DIRS ${ALIAS}_INCLUDE_DIRS) -# set(ALIAS_LIBRARY_DIRS ${ALIAS}_LIBRARY_DIRS) -# set(ALIAS_DEFINITIONS ${ALIAS}_CFLAGS_OTHER) -# set(ALIAS_VERSION ${ALIAS}_VERSION) -# endmacro() -# -# -# # -# ### Macro: set_module_found -# # -# # Marks the given module as found if all required components are present. -# # -# macro(set_module_found module) -# set(${module}_FOUND FALSE) -# # set(${module}_FOUND FALSE PARENT_SCOPE) -# -# # Compile the list of required vars -# set(_${module}_REQUIRED_VARS ${module}_LIBRARIES) # ${module}_INCLUDE_DIRS -# foreach (component ${${module}_FIND_COMPONENTS}) -# # NOTE: Not including XXX_INCLUDE_DIRS as required var since it may be empty -# list(APPEND _${module}_REQUIRED_VARS ${module}_${component}_LIBRARIES) # ${module}_${component}_INCLUDE_DIRS -# if (NOT ${module}_${component}_FOUND) -# message(FATAL_ERROR "Required ${module} component ${component} missing. Please recompile ${module} with ${component} enabled.") -# #else() -# # message(STATUS " - Required ${module} component ${component} found.") -# endif() -# endforeach() -# -# # Cache the vars. -# set(${module}_INCLUDE_DIRS ${${module}_INCLUDE_DIRS} CACHE STRING "The ${module} include directories." FORCE) -# set(${module}_LIBRARY_DIRS ${${module}_LIBRARY_DIRS} CACHE STRING "The ${module} library directories." FORCE) -# set(${module}_LIBRARIES ${${module}_LIBRARIES} CACHE STRING "The ${module} libraries." FORCE) -# set(${module}_FOUND ${${module}_FOUND} CACHE BOOLEAN "The ${module} found status." FORCE) -# # set(${module}_INCLUDE_DIRS ${${module}_INCLUDE_DIRS} PARENT_SCOPE) -# # set(${module}_LIBRARY_DIRS ${${module}_LIBRARY_DIRS} PARENT_SCOPE) -# # set(${module}_LIBRARIES ${${module}_LIBRARIES} PARENT_SCOPE) -# # set(${module}_FOUND ${${module}_FOUND} PARENT_SCOPE) -# -# # Ensure required variables have been set, or fail in error. -# # NOTE: Disabling find_package_handle_standard_args check since it's always -# # returning false even when variables are set. Maybe an internal CMake issue? -# # if (${module}_FIND_REQUIRED) -# # -# # # Give a nice error message if some of the required vars are missing. -# # include(FindPackageHandleStandardArgs) -# # find_package_handle_standard_args(${module} DEFAULT_MSG ${_${module}_REQUIRED_VARS}) -# # endif() -# -# # Set the module as found. -# if (${module}_LIBRARIES) -# set(${module}_FOUND TRUE) -# # set(${module}_FOUND TRUE PARENT_SCOPE) -# else() -# message("Failed to locate ${module}. Please specify paths manually.") -# endif() -# -# mark_as_advanced(${module}_INCLUDE_DIRS -# ${module}_LIBRARY_DIRS -# ${module}_LIBRARIES -# ${module}_DEFINITIONS -# ${module}_FOUND) -# endmacro() -# -# -# # -# ### Macro: set_component_found -# # -# # Marks the given component as found if both *_LIBRARIES AND *_INCLUDE_DIRS is present. -# # -# macro(set_component_found module component) -# set_component_alias(${module} ${component}) -# -# # message("${ALIAS_LIBRARIES}=${${ALIAS_LIBRARIES}}") -# # message("${ALIAS_INCLUDE_DIRS}=${${ALIAS_INCLUDE_DIRS}}") -# # message("${ALIAS_LIBRARY_DIRS}=${${ALIAS_LIBRARY_DIRS}}") -# -# #if (${module}_${component}_LIBRARIES AND ${module}_${component}_INCLUDE_DIRS) -# if (${ALIAS_LIBRARIES}) # AND ${ALIAS_INCLUDE_DIRS} (XXX_INCLUDE_DIRS may be empty) -# # message(STATUS " - ${module} ${component} found.") -# set(${ALIAS_FOUND} TRUE) -# # set(${ALIAS_FOUND} TRUE PARENT_SCOPE) -# -# # Add component vars to the parent module lists -# append_unique_list(${module}_INCLUDE_DIRS ${ALIAS_INCLUDE_DIRS}) -# append_unique_list(${module}_LIBRARY_DIRS ${ALIAS_LIBRARY_DIRS}) -# append_unique_list(${module}_LIBRARIES ${ALIAS_LIBRARIES}) -# append_unique_list(${module}_DEFINITIONS ${ALIAS_DEFINITIONS}) -# -# # set(${module}_INCLUDE_DIRS ${${module}_INCLUDE_DIRS} PARENT_SCOPE) -# # set(${module}_LIBRARY_DIRS ${${module}_LIBRARY_DIRS} PARENT_SCOPE) -# # set(${module}_LIBRARIES ${${module}_LIBRARIES} PARENT_SCOPE) -# # set(${module}_DEFINITIONS ${${module}_DEFINITIONS} PARENT_SCOPE) -# -# # message("Find Component Paths=${module}:${component}:${library}:${header}") -# # message("${ALIAS_INCLUDE_DIRS}=${${ALIAS_INCLUDE_DIRS}}") -# # message("${ALIAS_RELEASE_LIBRARIES}=${${ALIAS_RELEASE_LIBRARIES}}") -# # message("${ALIAS_DEBUG_LIBRARIES}=${${ALIAS_DEBUG_LIBRARIES}}") -# # message("${ALIAS_LIBRARIES}=${${ALIAS_LIBRARIES}}") -# # message("${module}_INCLUDE_DIRS=${${module}_INCLUDE_DIRS}") -# # message("${module}_LIBRARIES=${${module}_LIBRARIES}") -# -# # Only mark as advanced when found -# mark_as_advanced( -# ${ALIAS_INCLUDE_DIRS} -# ${ALIAS_LIBRARY_DIRS}) -# -# else() -# # NOTE: an error message will be displayed in set_module_found if the module is REQUIRED -# # message(STATUS " - ${module} ${component} not found.") -# endif() -# -# set(HAVE_${ALIAS} ${${ALIAS_FOUND}}) -# -# get_directory_property(hasParent PARENT_DIRECTORY) -# if(hasParent) -# set(HAVE_${ALIAS} ${${ALIAS_FOUND}} PARENT_SCOPE) -# endif() -# -# mark_as_advanced( -# ${ALIAS_FOUND} -# ${ALIAS_DEBUG_LIBRARIES} -# ${ALIAS_RELEASE_LIBRARIES} -# ${ALIAS_LIBRARIES} -# ${ALIAS_DEFINITIONS} -# ${ALIAS_VERSION}) -# endmacro() -# -# -# # -# ### Macro: set_module_notfound -# # -# # Marks the given component as not found, and resets the cache for find_path and find_library results. -# # -# macro(set_module_notfound module) -# #message(STATUS " - Setting ${module} not found.") -# set(${module}_FOUND FALSE) -# #set(${module}_FOUND FALSE PARENT_SCOPE) -# -# if (CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE) -# set(${module}_RELEASE_LIBRARIES "") -# set(${module}_DEBUG_LIBRARIES "") -# set(${module}_LIBRARIES "") -# #set(${module}_RELEASE_LIBRARIES "" PARENT_SCOPE) -# #set(${module}_DEBUG_LIBRARIES "" PARENT_SCOPE) -# #set(${module}_LIBRARIES "" PARENT_SCOPE) -# else() -# set(${module}_LIBRARIES ${ALIAS_LIBRARIES}-NOTFOUND) -# #set(${module}_LIBRARIES ${ALIAS_LIBRARIES}-NOTFOUND PARENT_SCOPE) -# endif() -# -# endmacro() -# -# -# # -# ### Macro: set_component_notfound -# # -# # Marks the given component as not found, and resets the cache for find_path and find_library results. -# # -# macro(set_component_notfound module component) -# set_component_alias(${module} ${component}) -# -# #message(STATUS " - Setting ${module} ${component} not found.") -# set(${ALIAS_FOUND} FALSE) -# #set(${ALIAS_FOUND} FALSE PARENT_SCOPE) -# -# if (${module}_MULTI_CONFIGURATION AND (CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE)) -# set(${ALIAS_RELEASE_LIBRARIES} ${ALIAS_RELEASE_LIBRARIES}-NOTFOUND) -# set(${ALIAS_DEBUG_LIBRARIES} ${ALIAS_DEBUG_LIBRARIES}-NOTFOUND) -# set(${ALIAS_LIBRARIES} "") #${module}_${component}_LIBRARIES-NOTFOUND) -# #set(${ALIAS_RELEASE_LIBRARIES} ${ALIAS_RELEASE_LIBRARIES}-NOTFOUND PARENT_SCOPE) -# #set(${ALIAS_DEBUG_LIBRARIES} ${ALIAS_DEBUG_LIBRARIES}-NOTFOUND PARENT_SCOPE) -# #set(${ALIAS_LIBRARIES} "") #${module}_${component}_LIBRARIES-NOTFOUND PARENT_SCOPE) -# else() -# set(${ALIAS_LIBRARIES} ${ALIAS_LIBRARIES}-NOTFOUND) -# #set(${ALIAS_LIBRARIES} ${ALIAS_LIBRARIES}-NOTFOUND PARENT_SCOPE) -# endif() -# -# endmacro() -# -# -# # -# ### Macro: find_component_paths -# # -# # Finds the given component library and include paths. -# # -# macro(find_component_paths module component library header) -# # message(STATUS "Find Component Paths=${module}:${component}:${library}:${header}") -# -# # Reset alias namespace (force recheck) -# # set_component_alias(${module} ${component}) -# -# # Reset search paths (force recheck) -# # set_component_notfound(${module} ${component}) -# -# find_path(${ALIAS_INCLUDE_DIRS} ${header} -# PATHS -# ${${module}_INCLUDE_DIR} # try find from root module include dir -# ${${module}_INCLUDE_HINTS} # try find from root module include hints -# PATH_SUFFIXES -# ${${module}_INCLUDE_SUFFIXES} # try find from root module include suffixes -# ) -# -# # Create a Debug and a Release list for multi configuration builds. -# # NOTE: _CONFIGURATION_TYPES must be set to use this. -# if (${module}_MULTI_CONFIGURATION AND (CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE)) -# find_library(${ALIAS_RELEASE_LIBRARIES} -# NAMES -# ${library} -# PATHS -# ${${ALIAS_LIBRARY_DIRS}} -# ${${module}_LIBRARY_DIR} -# ${${module}_LIBRARY_HINTS} -# PATH_SUFFIXES -# ${${module}_LIBRARY_SUFFIXES} -# ) -# find_library(${ALIAS_DEBUG_LIBRARIES} -# NAMES -# ${library}d -# PATHS -# ${${ALIAS_LIBRARY_DIRS}} -# ${${module}_LIBRARY_DIR} -# ${${module}_LIBRARY_HINTS} -# PATH_SUFFIXES -# ${${module}_LIBRARY_SUFFIXES} -# ) -# # if (${ALIAS_RELEASE_LIBRARIES}) -# # list(APPEND ${ALIAS_LIBRARIES} "optimized" ${${ALIAS_RELEASE_LIBRARIES}}) -# # endif() -# # if (${ALIAS_DEBUG_LIBRARIES}) -# # list(APPEND ${ALIAS_LIBRARIES} "debug" ${${ALIAS_DEBUG_LIBRARIES}}) -# # endif() -# include(${CMAKE_ROOT}/Modules/SelectLibraryConfigurations.cmake) -# select_library_configurations(${ALIAS}) -# else() -# find_library(${ALIAS_LIBRARIES} -# NAMES -# ${library} -# PATHS -# ${${ALIAS_LIBRARY_DIRS}} -# ${${module}_LIBRARY_DIR} -# ${${module}_LIBRARY_HINTS} -# PATH_SUFFIXES -# ${${module}_LIBRARY_SUFFIXES} -# ) -# endif() -# -# set_component_found(${module} ${component}) -# endmacro() -# -# -# # -# ### Macro: find_component -# # -# # Checks for the given component by invoking pkgconfig and then looking up the -# # libraries and include directories. -# # -# macro(find_component module component pkgconfig library header) -# # message("Find Component=${module}:${component}:${pkgconfig}:${library}:${header}") -# -# # Reset component alias values (force recheck) -# set_component_alias(${module} ${component}) -# -# # Use pkg-config to obtain directories for the find_path() and find_library() calls. -# find_package(PkgConfig QUIET) -# if (PKG_CONFIG_FOUND) -# pkg_search_module(${ALIAS} ${pkgconfig} QUIET) -# # message(STATUS "Find Component PkgConfig=${ALIAS}:${${ALIAS}_FOUND}:${${ALIAS}_LIBRARIES}:${${ALIAS}_INCLUDE_DIRS}:${${ALIAS}_LIBRARY_DIRS}:${${ALIAS}_LIBDIR}:${${ALIAS}_INCLUDEDIR}") -# endif() -# -# # message(STATUS "${ALIAS_FOUND}=${${ALIAS_FOUND}}") -# # message(STATUS "${ALIAS_LIBRARIES}=${${ALIAS_LIBRARIES}}") -# # message(STATUS "${ALIAS_INCLUDE_DIRS}=${${ALIAS_INCLUDE_DIRS}}") -# -# if(NOT ${ALIAS_FOUND}) -# # message(STATUS " - ${module} ${component} pkg-config not found, searching...") -# find_component_paths(${module} ${component} ${library} ${header}) -# else() -# # message(STATUS " - ${module} ${component} pkg-config found.") -# set_component_found(${module} ${component}) -# endif() -# endmacro() diff --git a/cmake/LibSourceyModules.cmake b/cmake/LibSourceyModules.cmake index 4820c5b21..14bc42f28 100644 --- a/cmake/LibSourceyModules.cmake +++ b/cmake/LibSourceyModules.cmake @@ -1,390 +1,318 @@ +# LibSourcey module system # -### Macro: define_sourcey_module +# Target-based dependency propagation. Each module declares its own dependencies +# via DEPENDS (other scy modules) and PACKAGES (external find_package targets). +# Dependencies flow through targets automatically via PUBLIC linkage. # -# Defines a generic LibSourcey module. +# Usage in module CMakeLists.txt: # -macro(define_sourcey_module name) - project(${name}) +# scy_add_module(http +# DEPENDS base net crypto +# PACKAGES OpenSSL::SSL +# PRETTY_NAME HTTP +# ) +# + +include(GNUInstallDirs) - # Add library source files - file(GLOB_RECURSE lib_srcs "src/*.cpp") - file(GLOB_RECURSE lib_hdrs "include/*.h") +# Tracked lists for build summary and config header +set(LibSourcey_BUILD_MODULES "" CACHE INTERNAL "Modules built") +set(LibSourcey_BUILD_TESTS "" CACHE INTERNAL "Tests built") +set(LibSourcey_BUILD_SAMPLES "" CACHE INTERNAL "Samples built") - # Exclude platform dependent implementations - set(lib_srcs_exclude_regex "") - set(lib_hdrs_exclude_regex "") +# ---------------------------------------------------------------------------- +# Helper: filter platform-specific sources +# ---------------------------------------------------------------------------- +function(scy_filter_platform_sources srcs_var hdrs_var) + set(_srcs ${${srcs_var}}) + set(_hdrs ${${hdrs_var}}) + + # Build exclusion regex based on platform + set(_exclude_patterns "") if(NOT CMAKE_SYSTEM_NAME STREQUAL "Windows") - # set(lib_srcs_exclude_regex ${lib_srcs_exclude_regex} " *_win32.cpp") - # set(lib_hdrs_exclude_regex ${lib_hdrs_exclude_regex} " *_win32.h") - set(lib_srcs_exclude_regex ${lib_srcs_exclude_regex} ".*win32.*") - set(lib_hdrs_exclude_regex ${lib_hdrs_exclude_regex} ".*win32.*") + list(APPEND _exclude_patterns ".*win32.*") endif() if(NOT CMAKE_SYSTEM_NAME STREQUAL "Darwin") - # set(lib_srcs_exclude_regex ${lib_srcs_exclude_regex} " *_mac.cpp") - # set(lib_hdrs_exclude_regex ${lib_hdrs_exclude_regex} " *_mac.h") - set(lib_srcs_exclude_regex ${lib_srcs_exclude_regex} ".*apple.*") - set(lib_hdrs_exclude_regex ${lib_hdrs_exclude_regex} ".*apple.*") + list(APPEND _exclude_patterns ".*apple.*") endif() if(NOT CMAKE_SYSTEM_NAME STREQUAL "Linux") - # set(lib_srcs_exclude_regex ${lib_srcs_exclude_regex} " *_linux.cpp") - # set(lib_hdrs_exclude_regex ${lib_hdrs_exclude_regex} " *_linux.h") - set(lib_srcs_exclude_regex ${lib_srcs_exclude_regex} ".*linux.*") - set(lib_hdrs_exclude_regex ${lib_hdrs_exclude_regex} ".*linux.*") + list(APPEND _exclude_patterns ".*linux.*") endif() - join("${lib_srcs_exclude_regex}" "|" lib_srcs_exclude_regex) - join("${lib_hdrs_exclude_regex}" "|" lib_hdrs_exclude_regex) + if(_exclude_patterns) + list(JOIN _exclude_patterns "|" _exclude_regex) + list(FILTER _srcs EXCLUDE REGEX "${_exclude_regex}") + list(FILTER _hdrs EXCLUDE REGEX "${_exclude_regex}") + endif() - # Include Objective-C files on Apple + # Include Objective-C on Apple if(APPLE) - file(GLOB_RECURSE lib_objectivec_srcs "src/*.mm") - set(lib_srcs ${lib_objectivec_srcs} ${lib_srcs}) + file(GLOB_RECURSE _objc_srcs "src/*.mm") + list(APPEND _srcs ${_objc_srcs}) endif() - filter_list(lib_srcs "${lib_srcs}" ${lib_srcs_exclude_regex}) - filter_list(lib_hdrs "${lib_hdrs}" ${lib_hdrs_exclude_regex}) - - list(APPEND LibSourcey_INCLUDE_DIRS ${dir}/include) - - # string(REGEX REPLACE ${lib_srcs_exclude_regex} "" lib_srcs "${lib_srcs}") - # string(REGEX REPLACE ${lib_hdrs_exclude_regex} "" lib_hdrs "${lib_hdrs}") - - # if(name STREQUAL "media") - # message(FATAL_ERROR "${CMAKE_SYSTEM_NAME} ${lib_srcs}") - # endif() - - source_group("Src" FILES ${lib_srcs}) - source_group("Include" FILES ${lib_hdrs}) - - add_library(${name} ${lib_srcs} ${lib_hdrs}) - - # Include library and header directories - set_default_project_directories(${name} ${ARGN}) + set(${srcs_var} ${_srcs} PARENT_SCOPE) + set(${hdrs_var} ${_hdrs} PARENT_SCOPE) +endfunction() - # Include linker dependencies - set_default_project_dependencies(${name} ${ARGN}) - - message(STATUS "Including module ${name}") - #message(STATUS " Libraries: ${LibSourcey_INCLUDE_LIBRARIES}") - #message(STATUS " Library Dirs: ${LibSourcey_LIBRARY_DIRS}") - #message(STATUS " Include Dirs: ${LibSourcey_INCLUDE_DIRS}") - #message(STATUS " Dependencies: ${LibSourcey__VENDOR_INCLUDE_DIRS}") - - # Specify the library pretty name for shared EXPORT symbols. - # Unless specified, default is `{Name}_EXPORTS` with uppercased - # first letter for vanity, just because it looks better in code. - # NOTE: We could be using `generate_export_header` with - # CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS but doing it ourselves is cleaner. - if (NOT ${name}_PRETTY_NAME) - string(SUBSTRING ${name} 0 1 first_letter) - string(TOUPPER ${first_letter} first_letter) - string(REGEX REPLACE "^.(.*)" "${first_letter}\\1" name_capitalized "${name}") - set(pretty_name ${name_capitalized}) +# ---------------------------------------------------------------------------- +# Helper: set export symbol name +# ---------------------------------------------------------------------------- +function(scy_set_export_symbol target pretty_name) + if(pretty_name) + set(_name ${pretty_name}) else() - set(pretty_name ${${name}_PRETTY_NAME}) + # Capitalise first letter of target name + string(SUBSTRING ${target} 0 1 _first) + string(TOUPPER ${_first} _first) + string(SUBSTRING ${target} 1 -1 _rest) + set(_name "${_first}${_rest}") endif() - target_compile_definitions(${name} PRIVATE ${pretty_name}_EXPORTS) + target_compile_definitions(${target} PRIVATE ${_name}_EXPORTS) +endfunction() + +# ---------------------------------------------------------------------------- +# Helper: set library output name (scy_) +# ---------------------------------------------------------------------------- +function(scy_set_output_properties target) + string(TOLOWER "scy_${target}" _output_name) - # include(GenerateExportHeader) - # generate_export_header(${name} - # EXPORT_FILE_NAME "${CMAKE_BINARY_DIR}/${name}/exports.h" - # EXPORT_MACRO_NAME ${pretty_name}_EXPORT - # NO_EXPORT_MACRO_NAME ${pretty_name}_NO_EXPORT - # DEPRECATED_MACRO_NAME ${pretty_name}_DEPRECATED - # NO_DEPRECATED_MACRO_NAME ${pretty_name}_NO_DEPRECATED) + set_target_properties(${target} PROPERTIES + OUTPUT_NAME ${_output_name} + DEBUG_POSTFIX "${LibSourcey_DEBUG_POSTFIX}" + LINKER_LANGUAGE CXX + ) if(NOT ANDROID) - # Android SDK build scripts can include only .so files into final .apk - # As result we should not set version properties for Android - set_target_properties(${name} PROPERTIES - VERSION "${LibSourcey_VERSION}" - SOVERSION "${LibSourcey_SOVERSION}") + set_target_properties(${target} PROPERTIES + VERSION "${PROJECT_VERSION}" + SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}" + ) endif() - # Additional target properties if(ENABLE_SOLUTION_FOLDERS) - set_target_properties(${name} PROPERTIES FOLDER "modules") + set_target_properties(${target} PROPERTIES FOLDER "modules") endif() - set_scy_libname(${name} lib_name) - set_target_properties(${name} PROPERTIES - OUTPUT_NAME ${lib_name} - DEBUG_POSTFIX "${LibSourcey_DEBUG_POSTFIX}" - #ARCHIVE_OUTPUT_DIRECTORY ${LIBRARY_OUTPUT_PATH} - #RUNTIME_OUTPUT_DIRECTORY ${EXECUTABLE_OUTPUT_PATH} - #DEFINE_SYMBOL "${pretty_name}_EXPORTS" - INSTALL_NAME_DIR lib - LINKER_LANGUAGE CXX) - - # Add install routine, unless lib is header only - if (lib_srcs) - install(TARGETS ${name} - RUNTIME DESTINATION bin COMPONENT libs - LIBRARY DESTINATION lib COMPONENT libs - ARCHIVE DESTINATION lib COMPONENT dev) +endfunction() + +# ---------------------------------------------------------------------------- +# scy_add_module( +# [DEPENDS ...] +# [PACKAGES ...] +# [PRETTY_NAME ] +# ) +# ---------------------------------------------------------------------------- +function(scy_add_module name) + cmake_parse_arguments(MOD "" "PRETTY_NAME" "DEPENDS;PACKAGES" ${ARGN}) + + # Check if module is enabled + if(DEFINED BUILD_MODULE_${name} AND NOT BUILD_MODULE_${name}) + return() endif() - install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include" - DESTINATION "${LibSourcey_INSTALL_DIR}" - COMPONENT dev) - - # Set HAVE_SOURCEY_XXX at parent scope for use in libsourcey.h - set(HAVE_SOURCEY_${name} ON PARENT_SCOPE) - - # set(LibSourcey_MODULE_LIBRARY_DIRS ${LibSourcey_MODULE_LIBRARY_DIRS} ${LibSourcey_BUILD_DIR}/src/${name} PARENT_SCOPE) - set(LibSourcey_MODULE_INCLUDE_DIRS ${LibSourcey_MODULE_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR}/include PARENT_SCOPE) - set(LibSourcey_MODULE_INCLUDE_LIBRARIES ${LibSourcey_MODULE_INCLUDE_LIBRARIES} ${name} PARENT_SCOPE) - - # Build samples - if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/samples) - ask_build_sourcey_sample(${name}) - if(BUILD_SAMPLES OR (NOT BUILD_SAMPLES AND BUILD_SAMPLES_${name})) - add_subdirectory(samples) - endif() + # Collect sources + file(GLOB_RECURSE _srcs "src/*.cpp") + file(GLOB_RECURSE _hdrs "include/*.h") + scy_filter_platform_sources(_srcs _hdrs) + + source_group("Src" FILES ${_srcs}) + source_group("Include" FILES ${_hdrs}) + + # Create library target + add_library(${name} ${_srcs} ${_hdrs}) + add_library(LibSourcey::${name} ALIAS ${name}) + + # Include directories with generator expressions for build vs install + target_include_directories(${name} + PUBLIC + $ + $ + PRIVATE + ${CMAKE_BINARY_DIR} # for libsourcey.h config header + ) + + # Link module dependencies (propagate transitively) + if(MOD_DEPENDS) + target_link_libraries(${name} PUBLIC ${MOD_DEPENDS}) endif() - # Build tests - if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/tests) - ask_build_sourcey_test(${name}) - if(BUILD_TESTS OR (NOT BUILD_TESTS AND BUILD_TESTS_${name})) - # if(BUILD_TESTS AND BUILD_TESTS_${name}) - add_subdirectory(tests) - endif() + # Link external package dependencies + if(MOD_PACKAGES) + target_link_libraries(${name} PUBLIC ${MOD_PACKAGES}) endif() -endmacro() - - -# -### Macro: define_sourcey_module_sample -# -# Defines a generic LibSourcey sample application. -# -macro(define_sourcey_module_sample name) - - project(${name}) - - # Include internal module dependencies - #include_sourcey_modules(${ARGN}) - - # Add source files - file(GLOB lib_hdrs "*.h*") - file(GLOB lib_srcs "*.cpp") - - source_group("Src" FILES ${lib_srcs}) - source_group("Include" FILES ${lib_hdrs}) - message(STATUS "Including module sample ${name}") - #message(STATUS " Libraries: ${LibSourcey_INCLUDE_LIBRARIES}") - #message(STATUS " Library Dirs: ${LibSourcey_LIBRARY_DIRS}") - #message(STATUS " Include Dirs: ${LibSourcey_INCLUDE_DIRS}") + # Export symbol for shared libraries + scy_set_export_symbol(${name} "${MOD_PRETTY_NAME}") - add_executable(${name} ${lib_srcs} ${lib_hdrs}) + # Output properties + scy_set_output_properties(${name}) - # Include library and header directories - set_default_project_directories(${name} ${ARGN}) - - # Include linker dependencies - set_default_project_dependencies(${name} ${ARGN}) - - if(ENABLE_SOLUTION_FOLDERS) - set_target_properties(${name} PROPERTIES FOLDER "samples") + # Install library + if(_srcs) + install(TARGETS ${name} + EXPORT LibSourceyTargets + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT libs + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libs + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT dev + ) endif() - set_target_properties(${name} PROPERTIES DEBUG_POSTFIX "d") - - install(TARGETS ${name} RUNTIME DESTINATION "${LibSourcey_SHARED_INSTALL_DIR}/samples/${name}" COMPONENT samples) -endmacro() + # Install headers + install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/" + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" + COMPONENT dev + ) -# -### Macro: define_libsourcey_test -# -# Defines a generic LibSourcey test application. -# -macro(define_libsourcey_test name) + # Track for build summary and config header + set(HAVE_SOURCEY_${name} ON CACHE INTERNAL "") + set(LibSourcey_BUILD_MODULES ${LibSourcey_BUILD_MODULES} ${name} CACHE INTERNAL "") - project(${name}) + message(STATUS " Module: ${name}") - # Add source files - file(GLOB lib_hdrs "*.h*") - file(GLOB lib_srcs "*.cpp") + # Build tests if requested + if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/tests AND (BUILD_TESTS OR BUILD_TESTS_${name})) + add_subdirectory(tests) + endif() - source_group("Src" FILES ${lib_srcs}) - source_group("Include" FILES ${lib_hdrs}) + # Build samples if requested + if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/samples AND (BUILD_SAMPLES OR BUILD_SAMPLES_${name})) + add_subdirectory(samples) + endif() +endfunction() + +# ---------------------------------------------------------------------------- +# scy_add_test( DEPENDS ... +# [EXCLUDE_CTEST] +# ) +# ---------------------------------------------------------------------------- +function(scy_add_test name) + cmake_parse_arguments(TEST "EXCLUDE_CTEST" "" "DEPENDS" ${ARGN}) + + # Use per-target source file if it exists, otherwise glob all + if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${name}.cpp") + set(_srcs "${CMAKE_CURRENT_SOURCE_DIR}/${name}.cpp") + if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${name}.h") + set(_hdrs "${CMAKE_CURRENT_SOURCE_DIR}/${name}.h") + else() + set(_hdrs "") + endif() + else() + file(GLOB _srcs "*.cpp") + file(GLOB _hdrs "*.h*") + endif() - add_executable(${name} ${lib_srcs} ${lib_hdrs}) + source_group("Src" FILES ${_srcs}) + source_group("Include" FILES ${_hdrs}) - # Include library and header directories - set_default_project_directories(${name} ${ARGN}) + add_executable(${name} ${_srcs} ${_hdrs}) - # Include linker dependencies - set_default_project_dependencies(${name} ${ARGN}) + if(TEST_DEPENDS) + target_link_libraries(${name} PRIVATE ${TEST_DEPENDS}) + endif() - message(STATUS "Including module test ${name}") - # message(STATUS " Libraries: ${LibSourcey_INCLUDE_LIBRARIES}") - # message(STATUS " Library Dirs: ${LibSourcey_LIBRARY_DIRS}") - # message(STATUS " Include Dirs: ${LibSourcey_INCLUDE_DIRS}") + # Config header access + target_include_directories(${name} PRIVATE ${CMAKE_BINARY_DIR}) - # Add ctest support - if(NOT ${name}_EXCLUDE_CTEST) - add_test(${name} ${name}) - #message(STATUS "Adding test ${name}") + if(NOT TEST_EXCLUDE_CTEST) + add_test(NAME ${name} COMMAND ${name}) endif() if(ENABLE_SOLUTION_FOLDERS) set_target_properties(${name} PROPERTIES FOLDER "tests") endif() - set_target_properties(${name} PROPERTIES DEBUG_POSTFIX "") - - install(TARGETS ${name} RUNTIME DESTINATION "${LibSourcey_SHARED_INSTALL_DIR}/tests/${name}" COMPONENT tests) -endmacro() + set(LibSourcey_BUILD_TESTS ${LibSourcey_BUILD_TESTS} ${name} CACHE INTERNAL "") -# -### Macro: define_libsourcey_library -# -# Defines a generic LibSourcey shared library. -# -macro(define_libsourcey_library name) - project(${name}) - - # Add source files - file(GLOB lib_hdrs "*.h*") - file(GLOB lib_srcs "*.cpp") + install(TARGETS ${name} + RUNTIME DESTINATION "${CMAKE_INSTALL_DATADIR}/libsourcey/tests/${name}" + COMPONENT tests + ) +endfunction() - add_definitions(-DSOURCEY_BUILD_SHARED) +# ---------------------------------------------------------------------------- +# scy_add_sample( DEPENDS ...) +# ---------------------------------------------------------------------------- +function(scy_add_sample name) + cmake_parse_arguments(SAMPLE "" "" "DEPENDS" ${ARGN}) - source_group("Src" FILES ${lib_srcs}) - source_group("Include" FILES ${lib_hdrs}) + file(GLOB _srcs "*.cpp") + file(GLOB _hdrs "*.h*") - add_library(${name} MODULE ${lib_srcs} ${lib_hdrs}) + source_group("Src" FILES ${_srcs}) + source_group("Include" FILES ${_hdrs}) - # Include library and header directories - set_default_project_directories(${name} ${ARGN}) + add_executable(${name} ${_srcs} ${_hdrs}) - # Include linker dependencies - set_default_project_dependencies(${name} ${ARGN}) + if(SAMPLE_DEPENDS) + target_link_libraries(${name} PRIVATE ${SAMPLE_DEPENDS}) + endif() - message(STATUS "Including module library ${name}") - #message(STATUS " Libraries: ${LibSourcey_INCLUDE_LIBRARIES}") - #message(STATUS " Library Dirs: ${LibSourcey_LIBRARY_DIRS}") - #message(STATUS " Include Dirs: ${LibSourcey_INCLUDE_DIRS}") + target_include_directories(${name} PRIVATE ${CMAKE_BINARY_DIR}) if(ENABLE_SOLUTION_FOLDERS) - set_target_properties(${name} PROPERTIES FOLDER "libraries") + set_target_properties(${name} PROPERTIES FOLDER "samples") endif() - set_target_properties(${name} PROPERTIES DEBUG_POSTFIX "d") - install(TARGETS ${name} DESTINATION "bin/${name}" COMPONENT libs) -endmacro() + set(LibSourcey_BUILD_SAMPLES ${LibSourcey_BUILD_SAMPLES} ${name} CACHE INTERNAL "") + install(TARGETS ${name} + RUNTIME DESTINATION "${CMAKE_INSTALL_DATADIR}/libsourcey/samples/${name}" + COMPONENT samples + ) +endfunction() -# -### Macro: define_sourcey_application -# -# This template defines a LibSourcey application. -# Optional helper variables: -# _SUBSYSTEM_WINDOWS - Sets SUBSYSTEM:WINDOWS under WIN32 -# _EXECUTABLE_NAME - The name of the executable file -# _DEBUG_POSTFIX - The output file name debum postfix -# -macro(define_sourcey_application name) - project(${name}) +# ---------------------------------------------------------------------------- +# scy_add_application( DEPENDS ...) +# ---------------------------------------------------------------------------- +function(scy_add_application name) + cmake_parse_arguments(APP "" "" "DEPENDS" ${ARGN}) - # Add library source files - file(GLOB_RECURSE lib_srcs "src/*.c*") - file(GLOB_RECURSE lib_hdrs "src/*.h*") + file(GLOB_RECURSE _srcs "src/*.c*") + file(GLOB_RECURSE _hdrs "src/*.h*") - # If we build for windows systems, we also include the resource file - # containing the manifest, icon and other resources + # Windows resource file if(WIN32 AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/src/${name}.rc") - set(lib_srcs ${lib_srcs} src/${name}.rc) + list(APPEND _srcs "src/${name}.rc") endif() - source_group("Source" FILES ${lib_srcs}) - source_group("Include" FILES ${lib_hdrs}) - - # Include all header and library directories - # include_directories(${LibSourcey_INCLUDE_DIRS}) - # ${CMAKE_SOURCE_DIR}/projects/Anionu/ISpot/include - # ${CMAKE_SOURCE_DIR}/projects/AnionuPrivate/SpotImpl/include - # link_directories(${LibSourcey_LIBRARY_DIRS}) + source_group("Source" FILES ${_srcs}) + source_group("Include" FILES ${_hdrs}) - status("Linking application ${name}") - # status(" Libraries: ${LibSourcey_INCLUDE_LIBRARIES}") - # status(" Library Dirs: ${LibSourcey_LIBRARY_DIRS}") - # status(" Include Dirs: ${LibSourcey_INCLUDE_DIRS}") - # status(" Dependencies: ${LibSourcey_BUILD_DEPENDENCIES}") + add_executable(${name} ${_srcs} ${_hdrs}) - # Setting WIN32 sets SUBSYSTEM:WINDOWS - if (${name}_SUBSYSTEM_WINDOWS) - add_executable(${name} WIN32 ${lib_srcs} ${lib_hdrs}) - else() - add_executable(${name} ${lib_srcs} ${lib_hdrs}) + if(APP_DEPENDS) + target_link_libraries(${name} PRIVATE ${APP_DEPENDS}) endif() - # Include library and header directories - set_default_project_directories(${name} ${ARGN}) - - # Include linker dependencies - set_default_project_dependencies(${name} ${ARGN}) - - # Add external dependencies and required libraries for linking. - # target_link_libraries(${name} ${LibSourcey_INCLUDE_LIBRARIES}) + target_include_directories(${name} PRIVATE ${CMAKE_BINARY_DIR}) if(ENABLE_SOLUTION_FOLDERS) set_target_properties(${name} PROPERTIES FOLDER "applications") endif() - if (NOT ${name}_EXECUTABLE_NAME) - set(${name}_EXECUTABLE_NAME ${name}) - endif() - if (NOT ${name}_DEBUG_POSTFIX AND NOT ${name}_DEBUG_POSTFIX STREQUAL "") - set(${name}_DEBUG_POSTFIX ${LibSourcey_DEBUG_POSTFIX}) - endif() - set_target_properties(${name} PROPERTIES - OUTPUT_NAME ${${name}_EXECUTABLE_NAME} - DEBUG_POSTFIX "${${name}_DEBUG_POSTFIX}") - - if (NOT ${name}_INSTALL_DESTINATION) - # Must add /bin for Linux - # This will result in executables being installed to /usr/local/bin - set(${name}_INSTALL_DESTINATION "bin") - endif() install(TARGETS ${name} - RUNTIME DESTINATION ${${name}_INSTALL_DESTINATION} COMPONENT apps) -endmacro() - + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT apps + ) +endfunction() +# ---------------------------------------------------------------------------- +# define_sourcey_dependency() # -### Macro: define_sourcey_dependency -# -# This template defines a LibSourcey dependency. -# Optional helper variables: -# _OUTPUT_NAME - The name of the executable file -# _DEBUG_POSTFIX - The output file name debug postfix -# _SOURCE_PATH - The glob source path -# _HEADER_PATH - The glob header path -# _SOURCE_FILES - The glob source files -# _HEADER_FILES - The glob header files -# +# For vendor/third-party libraries. Preserved for compatibility with existing +# vendor CMakeLists.txt files (libuv, http_parser, zlib, minizip). +# ---------------------------------------------------------------------------- macro(define_sourcey_dependency name) project(${name}) - # Include current directory and existing dependency directories - # include_directories("${CMAKE_CURRENT_SOURCE_DIR}") # "${LibSourcey_INCLUDE_DIRS}" - - # Add library source files - if (NOT ${name}_SOURCE_FILES) - if (NOT ${name}_SOURCE_PATH) + if(NOT ${name}_SOURCE_FILES) + if(NOT ${name}_SOURCE_PATH) set(${name}_SOURCE_PATH "src/*.c*") endif() file(GLOB_RECURSE ${name}_SOURCE_FILES ${${name}_SOURCE_PATH}) - #message("${name}: Globbing source files: ${${name}_SOURCE_FILES}") endif() - #message("${name}: Source files: ${${name}_SOURCE_FILES}") - # Add library header files - if (NOT ${name}_HEADER_FILES) - if (NOT ${name}_HEADER_PATH) + if(NOT ${name}_HEADER_FILES) + if(NOT ${name}_HEADER_PATH) set(${name}_HEADER_PATH "src/*.h*") endif() file(GLOB_RECURSE ${name}_HEADER_FILES ${${name}_HEADER_PATH}) @@ -393,53 +321,66 @@ macro(define_sourcey_dependency name) source_group("Source" FILES ${${name}_SOURCE_FILES}) source_group("Include" FILES ${${name}_HEADER_FILES}) - message(STATUS "- Linking dependency ${name} with libraries: ${LibSourcey_INCLUDE_LIBRARIES}") - # message("${name}: Library Dirs: ${LibSourcey_LIBRARY_DIRS}") - # message("${name}: Include Dirs: ${LibSourcey_INCLUDE_DIRS}") + add_library(${name} ${LibSourcey_LIB_TYPE} ${${name}_SOURCE_FILES}) - add_library(${name} ${LibSourcey_LIB_TYPE} ${${name}_SOURCE_FILES}) # ${${name}_HEADER_FILES} - - if (${name}_DEFINITIONS) + if(${name}_DEFINITIONS) target_compile_definitions(${name} PRIVATE ${${name}_DEFINITIONS}) endif() - if (${name}_FLAGS) + if(${name}_FLAGS) target_compile_options(${name} PRIVATE ${${name}_FLAGS}) endif() - if (${name}_INCLUDE_DIRS) - target_include_directories(${name} PRIVATE ${${name}_INCLUDE_DIRS}) + if(${name}_INCLUDE_DIRS) + foreach(_inc_dir ${${name}_INCLUDE_DIRS}) + if(IS_ABSOLUTE "${_inc_dir}") + target_include_directories(${name} PUBLIC + $) + else() + target_include_directories(${name} PUBLIC + $) + endif() + endforeach() + target_include_directories(${name} PUBLIC + $) endif() - if (${name}_DEPENDENCIES) + if(${name}_DEPENDENCIES) target_link_libraries(${name} PRIVATE ${${name}_DEPENDENCIES} ${CMAKE_DL_LIBS}) - # add_dependencies(${name} ${${name}_DEPENDENCIES}) endif() - # Cache dependency directories for inclusion by modules and applications - # get_directory_property(lib_directories INCLUDE_DIRECTORIES) - # set(LibSourcey_VENDOR_INCLUDE_DIRS ${lib_directories}) - # set(LibSourcey_VENDOR_INCLUDE_DIRS ${lib_directories} PARENT_SCOPE) - # set(LibSourcey_LINK_LIBRARIES ${LibSourcey_LINK_LIBRARIES} ${name} PARENT_SCOPE) - # set(LibSourcey_BUILD_DEPENDENCIES ${LibSourcey_BUILD_DEPENDENCIES} ${name} PARENT_SCOPE) - - if (${name}_OUTPUT_NAME) + if(${name}_OUTPUT_NAME) set_target_properties(${name} PROPERTIES OUTPUT_NAME ${${name}_OUTPUT_NAME}) endif() - if (${name}_DEBUG_POSTFIX) - set_target_properties(${name} PROPERTIES DEBUG_POSTFIX ${${name}_DEBUG_POSTFIX}) - elseif(LibSourcey_DEBUG_POSTFIX) + if(LibSourcey_DEBUG_POSTFIX) set_target_properties(${name} PROPERTIES DEBUG_POSTFIX ${LibSourcey_DEBUG_POSTFIX}) endif() if(ENABLE_SOLUTION_FOLDERS) set_target_properties(${name} PROPERTIES FOLDER "dependencies") endif() - if (NOT INSTALL_DESTINATION) - set(INSTALL_DESTINATION ${LibSourcey_VENDOR_INSTALL_DIR}/lib) - endif() install(TARGETS ${name} - RUNTIME DESTINATION ${INSTALL_DESTINATION} COMPONENT libs - LIBRARY DESTINATION ${INSTALL_DESTINATION} COMPONENT libs - ARCHIVE DESTINATION ${INSTALL_DESTINATION} COMPONENT dev) - - # install header include files - install(FILES ${${name}_HEADER_FILES} DESTINATION ${LibSourcey_VENDOR_INSTALL_DIR}/include COMPONENT dev) + EXPORT LibSourceyTargets + RUNTIME DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libs + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libs + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT dev + ) + + if(${name}_HEADER_FILES) + install(FILES ${${name}_HEADER_FILES} + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + COMPONENT dev + ) + endif() endmacro() + +# ---------------------------------------------------------------------------- +# Utility: list subdirectories +# ---------------------------------------------------------------------------- +function(subdirlist result curdir) + file(GLOB children RELATIVE ${curdir} ${curdir}/*) + set(dirlist "") + foreach(child ${children}) + if(IS_DIRECTORY ${curdir}/${child}) + list(APPEND dirlist ${child}) + endif() + endforeach() + set(${result} ${dirlist} PARENT_SCOPE) +endfunction() diff --git a/cmake/LibSourceyPackage.cmake b/cmake/LibSourceyPackage.cmake index 65cc8f0b1..6fc5d8a1b 100644 --- a/cmake/LibSourceyPackage.cmake +++ b/cmake/LibSourceyPackage.cmake @@ -49,14 +49,14 @@ set(CPACK_SOURCE_PACKAGE_FILE_NAME "libsourcey-${LibSourcey_VERSION}-${LibSource set(CPACK_RPM_COMPONENT_INSTALL TRUE) set(CPACK_RPM_PACKAGE_SUMMARY ${CPACK_PACKAGE_DESCRIPTION_SUMMARY}) set(CPACK_RPM_PACKAGE_DESCRIPTION ${CPACK_PACKAGE_DESCRIPTION}) -set(CPACK_RPM_PACKAGE_URL "https://sourcey.com") +set(CPACK_RPM_PACKAGE_URL "https://github.com/sourcey/libsourcey") set(CPACK_RPM_PACKAGE_LICENSE "LGPL-2.1+") # deb options set(CPACK_DEB_COMPONENT_INSTALL TRUE) # set(CPACK_DEBIAN_PACKAGE_SECTION "devel") # set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional") -set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "https://sourcey.com") +set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "https://github.com/sourcey/libsourcey") # display names set(CPACK_COMPONENT_LIBS_DISPLAY_NAME "Libraries and data") diff --git a/cmake/LibSourceyUtilities.cmake b/cmake/LibSourceyUtilities.cmake deleted file mode 100644 index 3a0d21270..000000000 --- a/cmake/LibSourceyUtilities.cmake +++ /dev/null @@ -1,157 +0,0 @@ -# -### Function: set_scy_libname -# -# Converts a CMake list to a string containing elements separated by spaces -# -function(set_scy_libname module_name output_var) - set(temp_name) - if(WIN32) - # Postfix of DLLs: - string(TOLOWER "scy_${module_name}" temp_name) #_${LibSourcey_DLLVERSION} - else() - # Postfix of so's: - string(TOLOWER "scy_${module_name}" temp_name) - endif() - set(${output_var} "${temp_name}" PARENT_SCOPE) -endfunction() - - -# -### Macro: ask_build_sourcey_dependency -# -# Optionally build a LibSourcey dependency. -# -macro(ask_build_sourcey_dependency name) - if(BUILD_DEPENDENCIES) - set(BUILD_DEPENDENCY_${name} ON CACHE BOOL "Build LibSourcey dependency: ${name}") - endif() - if(BUILD_DEPENDENCY_${name}) - set(LibSourcey_BUILD_DEPENDENCIES ${LibSourcey_BUILD_DEPENDENCIES} ${name} CACHE INTERNAL "") - #message(STATUS "Building dependency: ${name}") - endif() - mark_as_advanced(FORCE BUILD_DEPENDENCY_${name}) -endmacro() - - -# -### Macro: ask_build_sourcey_module -# -# Optionally build a LibSourcey module. -# This should be called before include_dependency and -# define_sourcey_module for each module. -# -macro(ask_build_sourcey_module name) - if(BUILD_MODULES) - set(BUILD_MODULE_${name} ON CACHE BOOL "Build LibSourcey module: ${name}") - endif() - if(BUILD_MODULE_${name}) - #message(STATUS "Building module: ${name}") - set(LibSourcey_BUILD_MODULES ${LibSourcey_BUILD_MODULES} ${name} CACHE INTERNAL "") - endif() - mark_as_advanced(FORCE BUILD_MODULE_${name}) -endmacro() - - -# -### Macro: ask_build_sourcey_test -# -# Optionally build a LibSourcey test. -# This should be called before include_dependency and -# define_sourcey_test for each test. -# -macro(ask_build_sourcey_test name) - if(BUILD_TESTS) - set(BUILD_TESTS_${name} ON CACHE BOOL "Build LibSourcey test: ${name}") - endif() - if(BUILD_TESTS_${name}) - #message(STATUS "Building module test: ${name}") - set(LibSourcey_BUILD_TESTS ${LibSourcey_BUILD_TESTS} ${name} CACHE INTERNAL "") - endif() - mark_as_advanced(FORCE BUILD_TESTS_${name}) -endmacro() - - -# -### Macro: ask_build_sourcey_sample -# -# Optionally build a LibSourcey sample. -# This should be called before include_dependency and -# define_sourcey_sample for each sample. -# -macro(ask_build_sourcey_sample name) - if(BUILD_SAMPLES) - set(BUILD_SAMPLES_${name} ON CACHE BOOL "Build LibSourcey sample: ${name}") - endif() - if(BUILD_SAMPLES_${name}) - #message(STATUS "Building module sample: ${name}") - set(LibSourcey_BUILD_SAMPLES ${LibSourcey_BUILD_SAMPLES} ${name} CACHE INTERNAL "") - endif() - mark_as_advanced(FORCE BUILD_SAMPLES_${name}) -endmacro() - - -# -### Macro: ask_build_sourcey_application -# -# Optionally build a LibSourcey application. -# This should be called before include_dependency for each application. -# -macro(ask_build_sourcey_application name) - if(BUILD_APPLICATIONS) - set(BUILD_APPLICATION_${name} ON CACHE BOOL "Build LibSourcey application: ${name}") - endif() - if(BUILD_APPLICATION_${name}) - #message(STATUS "Building application: ${name}") - set(LibSourcey_BUILD_APPLICATIONS ${LibSourcey_BUILD_APPLICATIONS} ${name} CACHE INTERNAL "") - endif() - mark_as_advanced(FORCE BUILD_APPLICATION_${name}) -endmacro() - - -# -### Macro: start_track_variables -# -# Start to track variables for change or adding. -# Note that variables starting with underscore are ignored. -macro(start_track_variables) - get_cmake_property(_fnvtps_cache_vars CACHE_VARIABLES) - get_cmake_property(_fnvtps_old_vars VARIABLES) - - foreach(_i ${_fnvtps_old_vars}) - if (NOT "x${_i}" MATCHES "^x_.*$") - list(FIND _fnvtps_cache_vars ${_i} _fnvtps_is_in_cache) - if(${_fnvtps_is_in_cache} EQUAL -1) - set("_fnvtps_old${_i}" ${${_i}}) - #message(STATUS "_fnvtps_old${_i} = ${_fnvtps_old${_i}}") - endif() - endif() - endforeach() -endmacro() - - -# -### Macro: forward_changed_variables_to_parent_scope -# -# forward_changed_variables_to_parent_scope([exclusions]) -# Forwards variables that was added/changed since last call to start_track_variables() to the parent scope. -# Note that variables starting with underscore are ignored. -macro(forward_changed_variables_to_parent_scope) - get_cmake_property(_fnvtps_cache_vars CACHE_VARIABLES) - get_cmake_property(_fnvtps_vars VARIABLES) - set(_fnvtps_cache_vars ${_fnvtps_cache_vars} ${ARGN}) - - foreach(_i ${_fnvtps_vars}) - if (NOT "x${_i}" MATCHES "^x_.*$") - list(FIND _fnvtps_cache_vars ${_i} _fnvtps_is_in_cache) - - if (${_fnvtps_is_in_cache} EQUAL -1) - list(FIND _fnvtps_old_vars ${_i} _fnvtps_is_old) - - if(${_fnvtps_is_old} EQUAL -1 OR NOT "${${_i}}" STREQUAL "${_fnvtps_old${_i}}") - set(${_i} ${${_i}} PARENT_SCOPE) - #message(STATUS "forwarded var ${_i}") - endif() - endif() - endif() - endforeach() -endmacro() \ No newline at end of file diff --git a/cmake/LibSourceyVersion.cmake b/cmake/LibSourceyVersion.cmake deleted file mode 100644 index 5f8438d32..000000000 --- a/cmake/LibSourceyVersion.cmake +++ /dev/null @@ -1,24 +0,0 @@ -# ---------------------------------------------------------------------------- -# Define the current LibSourcey version number -# ---------------------------------------------------------------------------- -set(LibSourcey_VERSION_FILE "${LibSourcey_DIR}/VERSION") -if(NOT EXISTS "${LibSourcey_VERSION_FILE}") - message(FATAL_ERROR "Cannot find VERSION file.") -endif() - -file(STRINGS "${LibSourcey_VERSION_FILE}" LibSourcey_VERSION) - -string(REPLACE "." ";" VERSION_LIST ${LibSourcey_VERSION}) -list(GET VERSION_LIST 0 LibSourcey_VERSION_MAJOR) -list(GET VERSION_LIST 1 LibSourcey_VERSION_MINOR) -list(GET VERSION_LIST 2 LibSourcey_VERSION_PATCH) - -if(WIN32) - # Postfix of DLLs: - set(LibSourcey_DLLVERSION "${LibSourcey_VERSION_MAJOR}${LibSourcey_VERSION_MINOR}${LibSourcey_VERSION_PATCH}") - set(LibSourcey_DEBUG_POSTFIX "d") -else() - # Postfix of so's: - set(LibSourcey_SOVERSION "${LibSourcey_VERSION_MAJOR}.${LibSourcey_VERSION_MINOR}") - set(LibSourcey_DEBUG_POSTFIX "") -endif() diff --git a/cmake/libsourcey.h.cmake.in b/cmake/libsourcey.h.cmake.in index 893b78e27..e724f1a38 100644 --- a/cmake/libsourcey.h.cmake.in +++ b/cmake/libsourcey.h.cmake.in @@ -1,60 +1,48 @@ // Name of library -#define SCY_NAME "${LibSourcey_NAME}" +#define SCY_NAME "${PROJECT_NAME}" // Define the library version -#define SCY_VERSION "${LibSourcey_VERSION}" -#define SCY_VERSION_MAJOR ${LibSourcey_VERSION_MAJOR} -#define SCY_VERSION_MINOR ${LibSourcey_VERSION_MINOR} -#define SCY_VERSION_PATCH ${LibSourcey_VERSION_PATCH} +#define SCY_VERSION "${PROJECT_VERSION}" +#define SCY_VERSION_MAJOR ${PROJECT_VERSION_MAJOR} +#define SCY_VERSION_MINOR ${PROJECT_VERSION_MINOR} +#define SCY_VERSION_PATCH ${PROJECT_VERSION_PATCH} // Define the source path #define SCY_SOURCE_DIR "${LibSourcey_SOURCE_DIR}" // Define the build path -#define SCY_BUILD_DIR "${LibSourcey_BUILD_DIR}" +#define SCY_BUILD_DIR "${CMAKE_BINARY_DIR}" // Define the installation path -#define SCY_INSTALL_DIR "${LibSourcey_INSTALL_DIR}" +#define SCY_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}" // Building as shared library (.so or .dll) #cmakedefine SCY_SHARED_LIBRARY -// Disable logging +// Enable logging #cmakedefine SCY_ENABLE_LOGGING // Attempt to recover from internal exceptions -// Exceptions thrown inside thread and stream context will be caught, logged and -// handled via the event loop in an attempt to prevent crashes. #cmakedefine SCY_EXCEPTION_RECOVERY // LibSourcey modules -// cmakedefine HAVE_SCY_base -// cmakedefine HAVE_SCY_http -// cmakedefine HAVE_SCY_json -// cmakedefine HAVE_SCY_av -// cmakedefine HAVE_SCY_net -// cmakedefine HAVE_SCY_rtp -// cmakedefine HAVE_SCY_sdp -// cmakedefine HAVE_SCY_socketio -// cmakedefine HAVE_SCY_stun -// cmakedefine HAVE_SCY_symple -// cmakedefine HAVE_SCY_turn -// cmakedefine HAVE_SCY_xml -// cmakedefine HAVE_SCY_xmpp -// cmakedefine HAVE_SCY_uv -// cmakedefine HAVE_SCY_rtsp -// cmakedefine HAVE_SCY_ice -// cmakedefine HAVE_SCY_pacm -// cmakedefine HAVE_SCY_webrtc -// cmakedefine HAVE_SCY_anionu -// cmakedefine HAVE_SCY_spotapi - -// LibUV library -#cmakedefine HAVE_LIBUV - +#cmakedefine HAVE_SOURCEY_base +#cmakedefine HAVE_SOURCEY_crypto +#cmakedefine HAVE_SOURCEY_net +#cmakedefine HAVE_SOURCEY_http +#cmakedefine HAVE_SOURCEY_json +#cmakedefine HAVE_SOURCEY_av +#cmakedefine HAVE_SOURCEY_socketio +#cmakedefine HAVE_SOURCEY_symple +#cmakedefine HAVE_SOURCEY_stun +#cmakedefine HAVE_SOURCEY_turn +#cmakedefine HAVE_SOURCEY_util +#cmakedefine HAVE_SOURCEY_sched +#cmakedefine HAVE_SOURCEY_archo +#cmakedefine HAVE_SOURCEY_pacm +#cmakedefine HAVE_SOURCEY_pluga // OpenSSL library #cmakedefine HAVE_OPENSSL -#cmakedefine OPENSSL_IS_BORINGSSL // FFmpeg video library #cmakedefine HAVE_FFMPEG @@ -71,19 +59,12 @@ // OpenCV library #cmakedefine HAVE_OPENCV -// RtAudio library -#cmakedefine HAVE_RTAUDIO - // Define to 1 if you have the header file. #cmakedefine HAVE_INTTYPES_H 1 // Enable macros for format specifiers in #define __STDC_FORMAT_MACROS -// Define to 1 if your processor stores words with the most significant byte -// first (like Motorola and SPARC, unlike Intel and VAX). -#cmakedefine WORDS_BIGENDIAN - // /// Platform and compiler definitions diff --git a/cmake/libsourcey.pc.cmake.in b/cmake/libsourcey.pc.cmake.in index cf5093857..0e197b436 100644 --- a/cmake/libsourcey.pc.cmake.in +++ b/cmake/libsourcey.pc.cmake.in @@ -2,13 +2,11 @@ Name: LibSourcey Description: LibSourcey C++ Networking Evolved Version: @LibSourcey_VERSION@ -prefix=@LibSourcey_INSTALL_DIR@ -exec_prefix=@LibSourcey_INSTALL_DIR@/bin -libdir=@LibSourcey_INSTALL_DIR@/lib -includedir=@LibSourcey_INSTALL_DIR@/include -vendorlibdir=@LibSourcey_VENDOR_INSTALL_DIR@/lib -vendorincludedir=@LibSourcey_VENDOR_INSTALL_DIR@/include +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=${prefix} +libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@ +includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@ Requires: -Libs: -L${libdir} -L${vendorlibdir} @PKG_CONFIG_LIBS@ -Cflags: -I${includedir} -I${vendorincludedir} +Libs: -L${libdir} @PKG_CONFIG_LIBS@ +Cflags: -I${includedir} diff --git a/doc/LICENSE.md b/doc/LICENSE.md index 2303e5cd7..7eabdb1c2 120000 --- a/doc/LICENSE.md +++ b/doc/LICENSE.md @@ -1 +1 @@ -IntxLNK. \ No newline at end of file +../LICENSE.md \ No newline at end of file diff --git a/doc/README.md b/doc/README.md index 2303e5cd7..32d46ee88 120000 --- a/doc/README.md +++ b/doc/README.md @@ -1 +1 @@ -IntxLNK. \ No newline at end of file +../README.md \ No newline at end of file diff --git a/doc/SUMMARY.md b/doc/SUMMARY.md index 3171ce8fb..3e988c1f3 100644 --- a/doc/SUMMARY.md +++ b/doc/SUMMARY.md @@ -4,9 +4,10 @@ * [Getting Started](getting-started.md) * [Installation](installation.md) * [Linux Guide](installation-linux.md) - * [OS X Guide](installation-osx.md) + * [macOS Guide](installation-osx.md) * [Windows Guide](installation-windows.md) * [Examples](examples.md) +* [Modules](modules.md) ---- @@ -19,14 +20,11 @@ * [Net](api-net.md) * [Pacm](api-pacm.md) * [Pluga](api-pluga.md) -* [Sked](api-sked.md) +* [Sched](api-sched.md) * [SocketIO](api-socketio.md) * [STUN](api-stun.md) * [Symple](api-symple.md) * [TURN](api-turn.md) -* [Util](api-util.md) -* [UV](api-uv.md) -* [WebRTC](api-webrtc.md) --- diff --git a/doc/api-archo.md b/doc/api-archo.md index de2f45b6f..b683caf2c 100644 --- a/doc/api-archo.md +++ b/doc/api-archo.md @@ -1,173 +1,260 @@ -# Module `archo` +# archo +### Classes +| Name | Description | +|------|-------------| +| [`ZipFile`](#structscy_1_1archo_1_1ZipFile) | | +| [`FileInfo`](#structscy_1_1archo_1_1ZipFile_1_1FileInfo) | | -## Summary +### Members - Members | Descriptions ---------------------------------|--------------------------------------------- -`namespace `[`scy::archo`](#namespacescy_1_1archo) | -`struct `[`scy::archo::ZipFile::FileInfo`](#structscy_1_1archo_1_1ZipFile_1_1FileInfo) | -# namespace `scy::archo` +| Name | Description | +|------|-------------| +| [`Archo_API`](#group__archo_1ga804678b23898d4f64d5686ef544ccfe2) | Shared library exports. | +--- +#### Archo_API -## Summary +```cpp +Archo_API() +``` - Members | Descriptions ---------------------------------|--------------------------------------------- -`struct `[`scy::archo::ZipFile`](#structscy_1_1archo_1_1ZipFile) | -# struct `scy::archo::ZipFile` +Shared library exports. +## ZipFile +> **Defined in:** `zipfile.h` +### Members +| Name | Description | +|------|-------------| +| [`ZipFile`](#group__archo_1gafbd603f7e87970b25761dde6ee43ed53) | | +| [`ZipFile`](#group__archo_1ga83472457ecd60b679786812154a48b2f) | | +| [`~ZipFile`](#group__archo_1ga3526297ee66287bd3392b5496e29e296) | | +| [`open`](#group__archo_1ga4505de4a4b0258c1be3640370790b3e5) | | +| [`opened`](#group__archo_1ga2cb3083919bf19fdc8440681095ad52b) | | +| [`close`](#group__archo_1gad5f16432c7097c4f0f3376ec06d9b8aa) | | +| [`extract`](#group__archo_1ga729b7bfd554bf838c855ad42b9e4039d) | Extracts the archive contents to the given directory path. | +| [`extractCurrentFile`](#group__archo_1gac5f1b12cfb628a7fba60abc3fca6e9dc) | | +| [`goToFirstFile`](#group__archo_1gaa70485384e6dbcc5783b3228e9b9f942) | | +| [`goToNextFile`](#group__archo_1gaa197ae9f0e8e670d365f0cb5e4f2cb94) | | +| [`openCurrentFile`](#group__archo_1ga084ce7163c3a21c4bb905dab42aee7ba) | | +| [`closeCurrentFile`](#group__archo_1gaef2d3fd19db8f1d24987e949b413b927) | | +| [`currentFileName`](#group__archo_1ga4ed5731ad68cd4a8be42342963f245ac) | | +| [`info`](#group__archo_1ga031d3193c306c10b0092e5815aead8cb) | | +| [`fp`](#group__archo_1gaf810f2266baaef1a7c693a1a5df6768e) | | +--- -## Summary +#### ZipFile - Members | Descriptions ---------------------------------|--------------------------------------------- -`public std::vector< `[`FileInfo`](./doc/api-archo.md#structscy_1_1archo_1_1ZipFile_1_1FileInfo)` > info` | -`public unzFile fp` | -`public ZipFile()` | -`public ZipFile(const std::string & file)` | -`public ~ZipFile()` | -`public void open(const std::string & file)` | -`public bool opened() const` | -`public void close()` | -`public void extract(const std::string & path)` | Extracts the archive contents to the given directory path. -`public bool extractCurrentFile(const std::string & path,bool whiny)` | -`public bool goToFirstFile()` | -`public bool goToNextFile()` | -`public void openCurrentFile()` | -`public void closeCurrentFile()` | -`public std::string currentFileName()` | +```cpp +ZipFile() +``` -## Members +--- -#### `public std::vector< `[`FileInfo`](./doc/api-archo.md#structscy_1_1archo_1_1ZipFile_1_1FileInfo)` > info` +#### ZipFile +```cpp +ZipFile(const std::string & file) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `file` | `const std::string &` | | +--- +#### ~ZipFile -#### `public unzFile fp` +```cpp +~ZipFile() +``` +--- +#### open +```cpp +void open(const std::string & file) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `file` | `const std::string &` | | -#### `public ZipFile()` +--- +#### opened +```cpp +bool opened() const +``` +--- +#### close -#### `public ZipFile(const std::string & file)` +```cpp +void close() +``` +--- +#### extract - - -#### `public ~ZipFile()` - - - - - -#### `public void open(const std::string & file)` - - - - - -#### `public bool opened() const` - - - - - -#### `public void close()` - - - - - -#### `public void extract(const std::string & path)` +```cpp +void extract(const std::string & path) +``` Extracts the archive contents to the given directory path. +| Parameter | Type | Description | +|-----------|------|-------------| +| `path` | `const std::string &` | | +--- -#### `public bool extractCurrentFile(const std::string & path,bool whiny)` - - - - +#### extractCurrentFile -#### `public bool goToFirstFile()` +```cpp +bool extractCurrentFile(const std::string & path, bool whiny) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `path` | `const std::string &` | | +| `whiny` | `bool` | | +--- +#### goToFirstFile +```cpp +bool goToFirstFile() +``` -#### `public bool goToNextFile()` +--- +#### goToNextFile +```cpp +bool goToNextFile() +``` +--- +#### openCurrentFile -#### `public void openCurrentFile()` +```cpp +void openCurrentFile() +``` +--- +#### closeCurrentFile +```cpp +void closeCurrentFile() +``` +--- -#### `public void closeCurrentFile()` +#### currentFileName +```cpp +std::string currentFileName() +``` +--- +#### info +```cpp +std::vector< FileInfo > info +``` -#### `public std::string currentFileName()` +--- +#### fp +```cpp +unzFile fp +``` +## FileInfo +> **Defined in:** `zipfile.h` -# struct `scy::archo::ZipFile::FileInfo` +### Members +| Name | Description | +|------|-------------| +| [`path`](#group__archo_1gae91e44aaf9e8629c002ed91ac4e3f8d8) | | +| [`compressedSize`](#group__archo_1gaef7fe29bc86babd96a66766fd07b2733) | | +| [`uncompressedSize`](#group__archo_1ga35738340dd3e5e207c70d700a883abba) | | +--- +#### path +```cpp +std::string path +``` +--- -## Summary +#### compressedSize - Members | Descriptions ---------------------------------|--------------------------------------------- -`public std::string path` | -`public size_t compressedSize` | -`public size_t uncompressedSize` | +```cpp +size_t compressedSize +``` -## Members +--- -#### `public std::string path` +#### uncompressedSize +```cpp +size_t uncompressedSize +``` +## FileInfo +> **Defined in:** `zipfile.h` +### Members -#### `public size_t compressedSize` +| Name | Description | +|------|-------------| +| [`path`](#group__archo_1gae91e44aaf9e8629c002ed91ac4e3f8d8) | | +| [`compressedSize`](#group__archo_1gaef7fe29bc86babd96a66766fd07b2733) | | +| [`uncompressedSize`](#group__archo_1ga35738340dd3e5e207c70d700a883abba) | | +--- +#### path +```cpp +std::string path +``` +--- -#### `public size_t uncompressedSize` +#### compressedSize +```cpp +size_t compressedSize +``` +--- +#### uncompressedSize +```cpp +size_t uncompressedSize +``` diff --git a/doc/api-av.md b/doc/api-av.md index b8cce70d4..2b36b12c0 100644 --- a/doc/api-av.md +++ b/doc/api-av.md @@ -1,2530 +1,7341 @@ -# Module `av` - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`namespace `[`scy::av`](#namespacescy_1_1av) | -`namespace `[`scy::av::legacy`](#namespacescy_1_1av_1_1legacy) | -`struct `[`scy::av::RealtimePacketQueue::MediaPacketTimeCompare`](#structscy_1_1av_1_1RealtimePacketQueue_1_1MediaPacketTimeCompare) | -# namespace `scy::av` - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`class `[`scy::av::DeviceManager`](#classscy_1_1av_1_1DeviceManager) | -`class `[`scy::av::DeviceManagerFactory`](#classscy_1_1av_1_1DeviceManagerFactory) | -`class `[`scy::av::DeviceWatcher`](#classscy_1_1av_1_1DeviceWatcher) | -`class `[`scy::av::FakeDeviceManager`](#classscy_1_1av_1_1FakeDeviceManager) | -`class `[`scy::av::FLVMetadataInjector`](#classscy_1_1av_1_1FLVMetadataInjector) | -`class `[`scy::av::FormatRegistry`](#classscy_1_1av_1_1FormatRegistry) | -`class `[`scy::av::FPSCounter`](#classscy_1_1av_1_1FPSCounter) | FPS counter based on the simple moving average (SMA) algorithm. -`class `[`scy::av::FPSLimiter`](#classscy_1_1av_1_1FPSLimiter) | -`class `[`scy::av::ICapture`](#classscy_1_1av_1_1ICapture) | -`class `[`scy::av::IDeviceManager`](#classscy_1_1av_1_1IDeviceManager) | -`class `[`scy::av::IEncoder`](#classscy_1_1av_1_1IEncoder) | This is the abstract class for all encoders. -`class `[`scy::av::LinuxDeviceManager`](#classscy_1_1av_1_1LinuxDeviceManager) | -`class `[`scy::av::MacDeviceManager`](#classscy_1_1av_1_1MacDeviceManager) | -`class `[`scy::av::MacDeviceWatcher`](#classscy_1_1av_1_1MacDeviceWatcher) | -`class `[`scy::av::RealtimePacketQueue`](#classscy_1_1av_1_1RealtimePacketQueue) | This class emits media packets based on their realtime pts value. -`struct `[`scy::av::AudioCodec`](#structscy_1_1av_1_1AudioCodec) | -`struct `[`scy::av::AudioPacket`](#structscy_1_1av_1_1AudioPacket) | Audio packet for interleaved formats. -`struct `[`scy::av::Codec`](#structscy_1_1av_1_1Codec) | [Codec](#structscy_1_1av_1_1Codec) for encoding/decoding media. -`struct `[`scy::av::Device`](#structscy_1_1av_1_1Device) | Represents a system audio, video or render device. -`struct `[`scy::av::EncoderOptions`](#structscy_1_1av_1_1EncoderOptions) | -`struct `[`scy::av::EncoderState`](#structscy_1_1av_1_1EncoderState) | -`struct `[`scy::av::Format`](#structscy_1_1av_1_1Format) | -`struct `[`scy::av::MediaPacket`](#structscy_1_1av_1_1MediaPacket) | -`struct `[`scy::av::PlanarAudioPacket`](#structscy_1_1av_1_1PlanarAudioPacket) | Audio packet for planar formats. -`struct `[`scy::av::PlanarVideoPacket`](#structscy_1_1av_1_1PlanarVideoPacket) | Video packet for planar formats. -`struct `[`scy::av::VideoCodec`](#structscy_1_1av_1_1VideoCodec) | -`struct `[`scy::av::VideoPacket`](#structscy_1_1av_1_1VideoPacket) | Video packet for interleaved formats. -# class `scy::av::DeviceManager` - -``` -class scy::av::DeviceManager - : public scy::av::IDeviceManager -``` - - - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public `[`NullSignal`](./doc/api-base.md#classscy_1_1Signal)` DevicesChanged` | -`public DeviceManager()` | -`public virtual ~DeviceManager()` | -`public virtual bool initialize()` | Initialization. -`public virtual void uninitialize()` | -`public virtual int getCapabilities()` | Capabilities. -`public virtual bool getAudioInputDevices(std::vector< `[`Device`](#structscy_1_1av_1_1Device)` > & devices)` | [Device](./doc/api-av.md#structscy_1_1av_1_1Device) enumeration. -`public virtual bool getAudioOutputDevices(std::vector< `[`Device`](#structscy_1_1av_1_1Device)` > & devices)` | -`public virtual bool getAudioInputDevice(`[`Device`](#structscy_1_1av_1_1Device)` & out,const std::string & name,int id)` | -`public virtual bool getAudioInputDevice(`[`Device`](#structscy_1_1av_1_1Device)` & out,int id)` | -`public virtual bool getAudioOutputDevice(`[`Device`](#structscy_1_1av_1_1Device)` & out,const std::string & name,int id)` | -`public virtual bool getAudioOutputDevice(`[`Device`](#structscy_1_1av_1_1Device)` & out,int id)` | -`public virtual bool getVideoCaptureDevices(std::vector< `[`Device`](#structscy_1_1av_1_1Device)` > & devs)` | -`public virtual bool getVideoCaptureDevice(`[`Device`](#structscy_1_1av_1_1Device)` & out,const std::string & name,int id)` | -`public virtual bool getVideoCaptureDevice(`[`Device`](#structscy_1_1av_1_1Device)` & out,int id)` | Returns the video capture device at the given system index. -`public virtual bool getDefaultAudioInputDevice(`[`Device`](#structscy_1_1av_1_1Device)` & device)` | -`public virtual bool getDefaultAudioOutputDevice(`[`Device`](#structscy_1_1av_1_1Device)` & device)` | -`public virtual bool getDefaultVideoCaptureDevice(`[`Device`](#structscy_1_1av_1_1Device)` & device)` | -`public inline bool initialized() const` | -`public virtual void print(std::ostream & ost)` | -`public DeviceManager()` | -`public ~DeviceManager()` | -`public bool getCameras(std::vector< `[`Device`](#structscy_1_1av_1_1Device)` > & devices)` | [Device](./doc/api-av.md#structscy_1_1av_1_1Device) enumeration. -`public bool getMicrophones(std::vector< `[`Device`](#structscy_1_1av_1_1Device)` > & devices)` | -`public bool getSpeakers(std::vector< `[`Device`](#structscy_1_1av_1_1Device)` > & devices)` | -`public bool getDefaultMicrophone(`[`Device`](#structscy_1_1av_1_1Device)` & device)` | Default devices. -`public bool getDefaultSpeaker(`[`Device`](#structscy_1_1av_1_1Device)` & device)` | -`public bool getDefaultCamera(`[`Device`](#structscy_1_1av_1_1Device)` & device)` | -`public bool findCamera(const std::string & name,`[`Device`](#structscy_1_1av_1_1Device)` & device)` | Find device by name or id. -`public bool findMicrophone(const std::string & name,`[`Device`](#structscy_1_1av_1_1Device)` & device)` | -`public bool findSpeaker(const std::string & name,`[`Device`](#structscy_1_1av_1_1Device)` & device)` | -`public bool getDeviceList(Device::Type type,std::vector< `[`av::Device`](#structscy_1_1av_1_1Device)` > & devices)` | Base device list. -`public virtual int getCapabilities()` | Capabilities. -`public void setWatcher(`[`DeviceWatcher`](#classscy_1_1av_1_1DeviceWatcher)` * watcher)` | -`public `[`DeviceWatcher`](#classscy_1_1av_1_1DeviceWatcher)` * watcher()` | -`public virtual void print(std::ostream & ost)` | Print all devices to the output stream. -`protected std::unique_ptr< `[`DeviceWatcher`](./doc/api-av.md#classscy_1_1av_1_1DeviceWatcher)` > _watcher` | -`protected virtual bool getDefaultAudioDevice(bool input,`[`Device`](#structscy_1_1av_1_1Device)` & device)` | -`protected virtual bool getAudioDevices(bool input,std::vector< `[`Device`](#structscy_1_1av_1_1Device)` > & devs)` | -`protected virtual bool getAudioDevice(bool input,`[`Device`](#structscy_1_1av_1_1Device)` & out,const std::string & name,int id)` | -`protected virtual bool getAudioDevice(bool input,`[`Device`](#structscy_1_1av_1_1Device)` & out,int id)` | -`protected void setInitialized(bool initialized)` | -`protected void setWatcher(`[`DeviceWatcher`](#classscy_1_1av_1_1DeviceWatcher)` * watcher)` | -`protected `[`DeviceWatcher`](#classscy_1_1av_1_1DeviceWatcher)` * watcher()` | - -## Members - -#### `public `[`NullSignal`](./doc/api-base.md#classscy_1_1Signal)` DevicesChanged` +# av + +### Classes + +| Name | Description | +|------|-------------| +| [`IDeviceManager`](#classscy_1_1av_1_1IDeviceManager) | A platform independent interface to enumerate audio and video devices on the system. | +| [`DeviceWatcher`](#classscy_1_1av_1_1DeviceWatcher) | | +| [`DeviceManagerFactory`](#classscy_1_1av_1_1DeviceManagerFactory) | | +| [`DeviceManager`](#classscy_1_1av_1_1DeviceManager) | | +| [`FakeDeviceManager`](#classscy_1_1av_1_1FakeDeviceManager) | | +| [`LinuxDeviceManager`](#classscy_1_1av_1_1LinuxDeviceManager) | | +| [`MacDeviceManager`](#classscy_1_1av_1_1MacDeviceManager) | | +| [`FLVMetadataInjector`](#classscy_1_1av_1_1FLVMetadataInjector) | This class implements a packetizer which appends correct stream headers and modifies the timestamp of FLV packets so Adobe's Flash Player will play our videos mid-stream. | +| [`VideoAnalyzer`](#classscy_1_1av_1_1VideoAnalyzer) | This class provides basic AV spectrum analysis on a video using the Fourier Transform algorithm. Data is outputted in CSV format. | +| [`MacDeviceWatcher`](#classscy_1_1av_1_1MacDeviceWatcher) | | +| [`AudioCapture`](#classscy_1_1av_1_1AudioCapture) | This class implements a cross platform audio capturer. | +| [`FormatRegistry`](#classscy_1_1av_1_1FormatRegistry) | | +| [`FPSCounter`](#classscy_1_1av_1_1FPSCounter) | FPS counter based on the simple moving average (SMA) algorithm. | +| [`FPSLimiter`](#classscy_1_1av_1_1FPSLimiter) | This class limits the throughput rate of IPackets in a [PacketStream](./doc/api-base.md#classscy_1_1PacketStream). If the throughput rate exceeds the max specified FPS then packets will be dropped. | +| [`ICapture`](#classscy_1_1av_1_1ICapture) | | +| [`IEncoder`](#classscy_1_1av_1_1IEncoder) | This is the abstract class for all encoders. | +| [`MediaCapture`](#classscy_1_1av_1_1MediaCapture) | This class implements a cross platform audio, video, screen and video file capturer. | +| [`MultiplexEncoder`](#classscy_1_1av_1_1MultiplexEncoder) | This class implements a multiplex audio and video encoder. | +| [`MultiplexPacketEncoder`](#classscy_1_1av_1_1MultiplexPacketEncoder) | Encodes and multiplexes a realtime video stream form audio / video capture sources. FFmpeg is used for encoding. | +| [`RealtimePacketQueue`](#classscy_1_1av_1_1RealtimePacketQueue) | This class emits media packets based on their realtime pts value. | +| [`VideoCapture`](#classscy_1_1av_1_1VideoCapture) | This class implements a cross platform audio capturer. | +| [`Device`](#structscy_1_1av_1_1Device) | Represents a system audio, video or render device. | +| [`Options`](#structscy_1_1av_1_1VideoAnalyzer_1_1Options) | | +| [`Stream`](#structscy_1_1av_1_1VideoAnalyzer_1_1Stream) | | +| [`Packet`](#structscy_1_1av_1_1VideoAnalyzer_1_1Packet) | | +| [`AudioBuffer`](#structscy_1_1av_1_1AudioBuffer) | | +| [`AudioContext`](#structscy_1_1av_1_1AudioContext) | | +| [`AudioDecoder`](#structscy_1_1av_1_1AudioDecoder) | | +| [`AudioEncoder`](#structscy_1_1av_1_1AudioEncoder) | | +| [`AudioResampler`](#structscy_1_1av_1_1AudioResampler) | | +| [`Codec`](#structscy_1_1av_1_1Codec) | [Codec](#structscy_1_1av_1_1Codec) for encoding/decoding media. | +| [`AudioCodec`](#structscy_1_1av_1_1AudioCodec) | | +| [`VideoCodec`](#structscy_1_1av_1_1VideoCodec) | | +| [`Deleter`](#structscy_1_1av_1_1Deleter) | Utilites for RAII: | +| [`Deleterp`](#structscy_1_1av_1_1Deleterp) | [Deleter](#structscy_1_1av_1_1Deleter) adaptor for functions like av_freep that take a pointer to a pointer. | +| [`Format`](#structscy_1_1av_1_1Format) | Defines a media container format which is available through the [Format](#structscy_1_1av_1_1Format) Registry for encoding/decoding. A format defined preferred default values for each codec. | +| [`FPSCounter`](#structscy_1_1av_1_1legacy_1_1FPSCounter) | | +| [`EncoderState`](#structscy_1_1av_1_1EncoderState) | | +| [`EncoderOptions`](#structscy_1_1av_1_1EncoderOptions) | | +| [`MediaPacket`](#structscy_1_1av_1_1MediaPacket) | | +| [`VideoPacket`](#structscy_1_1av_1_1VideoPacket) | Video packet for interleaved formats. | +| [`PlanarVideoPacket`](#structscy_1_1av_1_1PlanarVideoPacket) | Video packet for planar formats. | +| [`AudioPacket`](#structscy_1_1av_1_1AudioPacket) | Audio packet for interleaved formats. | +| [`PlanarAudioPacket`](#structscy_1_1av_1_1PlanarAudioPacket) | Audio packet for planar formats. | +| [`MediaPacketTimeCompare`](#structscy_1_1av_1_1RealtimePacketQueue_1_1MediaPacketTimeCompare) | | +| [`VideoContext`](#structscy_1_1av_1_1VideoContext) | Base video context from which all video encoders and decoders derive. | +| [`VideoConverter`](#structscy_1_1av_1_1VideoConverter) | | +| [`VideoDecoder`](#structscy_1_1av_1_1VideoDecoder) | | +| [`VideoEncoder`](#structscy_1_1av_1_1VideoEncoder) | | + +### Members + +| Name | Description | +|------|-------------| +| [`MAX_VIDEO_PACKET_SIZE`](#group__av_1gaca35e31ea0ef7c5ce3514f4ca2c0f5b0) | | +| [`MAX_AUDIO_PACKET_SIZE`](#group__av_1ga5022dc52e9bda86ed266bb7d4c74271b) | 1 second of 48khz 32bit audio | +| [`MAX_ENCODE_DURATION`](#group__av_1ga724e4af8d0f4d376da78d93f9b58754b) | 3 hours | +| [`INT64_C`](#group__av_1ga22369e5d04efcda4162fdb0f5759318e) | | +| [`UINT64_C`](#group__av_1ga26a7bac63d90ef61175acb9f6fc4f2ca) | | +| [`AV_API`](#group__av_1ga532e425a62b8fff224eba130411a911d) | | +| [`DEFAULT_AUDIO_SAMPLE_RATE`](#group__av_1ga359d5a62ed81f83bdf547b4c358c9bcf) | | +| [`DEFAULT_AUDIO_BIT_RATE`](#group__av_1ga43b6ace7b5940e34043d8edb0b8484c6) | | +| [`DEFAULT_AUDIO_CHANNELS`](#group__av_1ga18987a0124b757cfc35978b672cd10d4) | | +| [`DEFAULT_AUDIO_SAMPLE_FMT`](#group__av_1ga2745b7fc66dc97d94254a712e1cdc05b) | | +| [`DEFAULT_VIDEO_SAMPLE_RATE`](#group__av_1ga4c664cf23e7f36fb3976e11becdd5f53) | | +| [`DEFAULT_VIDEO_BIT_RATE`](#group__av_1ga7e716fda85b10b703cc0c3b7ded98df7) | | +| [`DEFAULT_VIDEO_PIXEL_FMT`](#group__av_1ga29987df5370ad83340657e8cdb3ad686) | | + +--- + +#### MAX_VIDEO_PACKET_SIZE + +```cpp +MAX_VIDEO_PACKET_SIZE() +``` + +--- + +#### MAX_AUDIO_PACKET_SIZE + +```cpp +MAX_AUDIO_PACKET_SIZE() +``` + +1 second of 48khz 32bit audio + +--- + +#### MAX_ENCODE_DURATION + +```cpp +MAX_ENCODE_DURATION() +``` + +3 hours + +--- + +#### INT64_C + +```cpp +INT64_C() +``` + +--- + +#### UINT64_C + +```cpp +UINT64_C() +``` + +--- + +#### AV_API + +```cpp +AV_API() +``` + +--- + +#### DEFAULT_AUDIO_SAMPLE_RATE + +```cpp +DEFAULT_AUDIO_SAMPLE_RATE() +``` + +--- + +#### DEFAULT_AUDIO_BIT_RATE + +```cpp +DEFAULT_AUDIO_BIT_RATE() +``` + +--- + +#### DEFAULT_AUDIO_CHANNELS + +```cpp +DEFAULT_AUDIO_CHANNELS() +``` + +--- + +#### DEFAULT_AUDIO_SAMPLE_FMT + +```cpp +DEFAULT_AUDIO_SAMPLE_FMT() +``` + +--- + +#### DEFAULT_VIDEO_SAMPLE_RATE + +```cpp +DEFAULT_VIDEO_SAMPLE_RATE() +``` + +--- + +#### DEFAULT_VIDEO_BIT_RATE + +```cpp +DEFAULT_VIDEO_BIT_RATE() +``` + +--- + +#### DEFAULT_VIDEO_PIXEL_FMT + +```cpp +DEFAULT_VIDEO_PIXEL_FMT() +``` + +## IDeviceManager + +> **Subclasses:** `scy::av::DeviceManager`, `scy::av::FakeDeviceManager` +> **Defined in:** `devicemanager.h` + +A platform independent interface to enumerate audio and video devices on the system. + +### Members + +| Name | Description | +|------|-------------| +| [`~IDeviceManager`](#group__av_1ga99bf003f84ab4e04a07d17185dbf491c) | | +| [`initialize`](#group__av_1ga61c821fe1a7d181dbc439c90fa4524da) | Initialization. | +| [`uninitialize`](#group__av_1ga6438ea5095404fc8ded7619a7863288c) | | +| [`getAudioInputDevices`](#group__av_1ga324ce38356335066bb2cb4fd6a8521ee) | [Device](#structscy_1_1av_1_1Device) enumeration. | +| [`getAudioOutputDevices`](#group__av_1ga389204a9d5fc74dfbfd1179f2cab8fe9) | | +| [`getAudioInputDevice`](#group__av_1ga8eb682c21d928e20252dd682512799eb) | | +| [`getAudioInputDevice`](#group__av_1gadf949c6e35c2d03faeabb78ce72264df) | | +| [`getAudioOutputDevice`](#group__av_1ga294eb11a87c7bf21e263a5080cf86da6) | | +| [`getAudioOutputDevice`](#group__av_1ga44f5d5891ec58d46f964814bdfdb9afc) | | +| [`getVideoCaptureDevices`](#group__av_1gaf8af159e35b82018fe3c62ffd93e99b4) | | +| [`getVideoCaptureDevice`](#group__av_1gaf9ca7d9b804d2fd3b80a66c99a5ce994) | | +| [`getVideoCaptureDevice`](#group__av_1ga519256a027ac96e90434aaed2b84621f) | | +| [`getDefaultAudioInputDevice`](#group__av_1ga3143d54a8029ce31cd3c35aeb458d8ba) | | +| [`getDefaultAudioOutputDevice`](#group__av_1gac7a4388e97359a1456a1d16c582affc5) | | +| [`getDefaultVideoCaptureDevice`](#group__av_1ga0f87a257398f70cb9ad933de0148d110) | | +| [`getCapabilities`](#group__av_1ga96164fb6b34888ccee6930b3c79d5cda) | Capabilities. | +| [`print`](#group__av_1ga0c7df28789555440e61e55b0cf791ec1) | | +| [`DevicesChanged`](#group__av_1ga69dbbe5f5c10c8aba8aac57c9a94e511) | Signals on DevicesChanged. Arg 1 is true when device is video, false for audio Arg 2 is true when device connects, flase on disconnection | +| [`kDefaultDeviceName`](#group__av_1ga02f897f60b7d17eea8b587087f802a53) | | + +--- + +#### ~IDeviceManager + +```cpp +virtual inline ~IDeviceManager() +``` + +--- + +#### initialize + +```cpp +bool initialize() +``` + +Initialization. + +--- + +#### uninitialize + +```cpp +void uninitialize() +``` + +--- + +#### getAudioInputDevices + +```cpp +bool getAudioInputDevices(std::vector< Device > & devices) +``` + +[Device](#structscy_1_1av_1_1Device) enumeration. + +| Parameter | Type | Description | +|-----------|------|-------------| +| `devices` | `std::vector< Device > &` | | + +--- + +#### getAudioOutputDevices + +```cpp +bool getAudioOutputDevices(std::vector< Device > & devices) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `devices` | `std::vector< Device > &` | | + +--- + +#### getAudioInputDevice + +```cpp +bool getAudioInputDevice(Device & out, const std::string & name, int id) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `out` | `Device &` | | +| `name` | `const std::string &` | | +| `id` | `int` | | + +--- + +#### getAudioInputDevice + +```cpp +bool getAudioInputDevice(Device & out, int id) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `out` | `Device &` | | +| `id` | `int` | | + +--- + +#### getAudioOutputDevice + +```cpp +bool getAudioOutputDevice(Device & out, const std::string & name, int id) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `out` | `Device &` | | +| `name` | `const std::string &` | | +| `id` | `int` | | + +--- + +#### getAudioOutputDevice + +```cpp +bool getAudioOutputDevice(Device & out, int id) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `out` | `Device &` | | +| `id` | `int` | | + +--- + +#### getVideoCaptureDevices + +```cpp +bool getVideoCaptureDevices(std::vector< Device > & devs) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `devs` | `std::vector< Device > &` | | + +--- + +#### getVideoCaptureDevice + +```cpp +bool getVideoCaptureDevice(Device & out, int id) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `out` | `Device &` | | +| `id` | `int` | | + +--- + +#### getVideoCaptureDevice + +```cpp +bool getVideoCaptureDevice(Device & out, const std::string & name, int id) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `out` | `Device &` | | +| `name` | `const std::string &` | | +| `id` | `int` | | + +--- + +#### getDefaultAudioInputDevice + +```cpp +bool getDefaultAudioInputDevice(Device & device) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `device` | `Device &` | | + +--- + +#### getDefaultAudioOutputDevice + +```cpp +bool getDefaultAudioOutputDevice(Device & device) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `device` | `Device &` | | + +--- + +#### getDefaultVideoCaptureDevice + +```cpp +bool getDefaultVideoCaptureDevice(Device & device) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `device` | `Device &` | | + +--- + +#### getCapabilities + +```cpp +int getCapabilities() +``` + +Capabilities. + +--- + +#### print + +```cpp +void print(std::ostream & ost) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `ost` | `std::ostream &` | | + +--- + +#### DevicesChanged + +```cpp +Signal< void(bool &, bool &)> DevicesChanged +``` + +Signals on DevicesChanged. Arg 1 is true when device is video, false for audio Arg 2 is true when device connects, flase on disconnection + +--- + +#### kDefaultDeviceName + +```cpp +const char kDefaultDeviceName = "" +``` + +## DeviceWatcher + +> **Subclasses:** `scy::av::MacDeviceWatcher` +> **Defined in:** `devicemanager.h` + +### Members + +| Name | Description | +|------|-------------| +| [`DeviceWatcher`](#group__av_1ga66ffcd817f7ac8bc0a965e018271508c) | | +| [`~DeviceWatcher`](#group__av_1ga191ccb64f6d1985e762bfdd54bb55bba) | | +| [`start`](#group__av_1gab833459b9cf8c1cde8147159f265f7d8) | | +| [`stop`](#group__av_1ga028347525717f62dfccf5bb82031fe79) | | +| [`DeviceWatcher`](#group__av_1gaa9ae4c2ab1984066ac066e4a6cf5f5e5) | | +| [`~DeviceWatcher`](#classscy_1_1av_1_1DeviceWatcher_1ga191ccb64f6d1985e762bfdd54bb55bba) | | +| [`start`](#classscy_1_1av_1_1DeviceWatcher_1gab833459b9cf8c1cde8147159f265f7d8) | | +| [`stop`](#classscy_1_1av_1_1DeviceWatcher_1ga028347525717f62dfccf5bb82031fe79) | | + +--- + +#### DeviceWatcher + +```cpp +inline explicit DeviceWatcher(IDeviceManager *) +``` + +--- + +#### ~DeviceWatcher + +```cpp +virtual inline ~DeviceWatcher() +``` + +--- + +#### start + +```cpp +virtual inline bool start() +``` + +--- + +#### stop + +```cpp +virtual inline void stop() +``` + +--- + +#### DeviceWatcher + +```cpp +inline explicit DeviceWatcher(DeviceManager *) +``` + +--- + +#### ~DeviceWatcher + +```cpp +virtual inline ~DeviceWatcher() +``` + +--- + +#### start + +```cpp +virtual inline bool start() +``` + +--- + +#### stop + +```cpp +virtual inline void stop() +``` + +## DeviceManagerFactory + +> **Defined in:** `devicemanager.h` + +### Members + +| Name | Description | +|------|-------------| +| [`create`](#group__av_1ga262295a8315bd7556241efc6b44219c2) | | +| [`DeviceManagerFactory`](#group__av_1ga63037176ba23a045bb59eea820b6cf21) | | + +--- + +#### create + +```cpp +static IDeviceManager * create() +``` + +--- + +#### DeviceManagerFactory + +```cpp +DeviceManagerFactory() +``` + +## DeviceManager + +> **Extends:** `scy::av::IDeviceManager` +> **Subclasses:** `scy::av::LinuxDeviceManager`, `scy::av::MacDeviceManager` +> **Defined in:** `devicemanager.h` + +### Members + +| Name | Description | +|------|-------------| +| [`DeviceManager`](#group__av_1ga778c03d9b552d40b34bb8f8f9a1255d8) | | +| [`~DeviceManager`](#group__av_1ga3635ac39fa55df574dcb0d98634c8140) | | +| [`initialize`](#group__av_1gabe487635b243c75fae6d1ce1700f1def) | Initialization. | +| [`uninitialize`](#group__av_1gae2fcfc68cc20dedeaa8ce913307faafc) | | +| [`getCapabilities`](#group__av_1ga42f596484bd7234fd92becaac4005e53) | Capabilities. | +| [`getAudioInputDevices`](#group__av_1gafeeaa53b13b8537cfbe903a5a26b890b) | [Device](#structscy_1_1av_1_1Device) enumeration. | +| [`getAudioOutputDevices`](#group__av_1ga2b4cd27667bb3e529de2ff4f3e3fc289) | | +| [`getAudioInputDevice`](#group__av_1gae37c4a33994f7ef8416490531d3d0907) | | +| [`getAudioInputDevice`](#group__av_1ga49d30065d7ecc80f9b768a47868ff505) | | +| [`getAudioOutputDevice`](#group__av_1ga4cb9cac44ba585b23b8b07b3ab33dbb1) | | +| [`getAudioOutputDevice`](#group__av_1ga115cb239e0244a5d40baf2a6239aec2e) | | +| [`getVideoCaptureDevices`](#group__av_1ga70c7a7ff64734a32709d26e345398c52) | | +| [`getVideoCaptureDevice`](#group__av_1ga2820413e3299477fb40fd84aebbf7ec8) | | +| [`getVideoCaptureDevice`](#group__av_1gae4e7d0d99842dc18d5fef8536603ca19) | Returns the video capture device at the given system index. | +| [`getDefaultAudioInputDevice`](#group__av_1gaa87c5fbc8299cf4a82e192d69977b16e) | | +| [`getDefaultAudioOutputDevice`](#group__av_1gab0bbdde6cab23808166819aafc305aa8) | | +| [`getDefaultVideoCaptureDevice`](#group__av_1gac994fdb7f9415bde77421efc8cd84e7f) | | +| [`initialized`](#group__av_1gaabba96ca78dc27e34ccd588ab813f8dc) | | +| [`print`](#group__av_1ga485b4609f4a69f5d603b96deb411b306) | | +| [`getCameras`](#group__av_1gaf2fcff1d7c936454117e453e4c9d6845) | [Device](#structscy_1_1av_1_1Device) enumeration. | +| [`getMicrophones`](#group__av_1gafe7f65212eb9b21f60570c3333d8e4a6) | | +| [`getSpeakers`](#group__av_1ga47505851b38bff2744781a3e6c2f30b7) | | +| [`getDefaultMicrophone`](#group__av_1gac40bea8a47b983fb9a759a4192c1eda7) | Default devices. | +| [`getDefaultSpeaker`](#group__av_1ga32a4b7178aea50fe2660ffe4fc4e8914) | | +| [`getDefaultCamera`](#group__av_1gaa853bd3fb98b67a35c933127f1727dcc) | | +| [`findCamera`](#group__av_1ga73314c79803a2665ec52ff3645930067) | Find device by name or id. | +| [`findMicrophone`](#group__av_1gaae2554630021f04763b96d0f73886724) | | +| [`findSpeaker`](#group__av_1gaa2fd5c9c502a07c5a603ac7cf8725089) | | +| [`getDeviceList`](#group__av_1gac2b135e577c2cca7dc422e226b7dc6f1) | Base device list. | +| [`findVideoInputFormat`](#group__av_1gac91dac73d9705d6d2c4a5e3ba3ef49a9) | Find base FFmpeg formats. | +| [`findAudioInputFormat`](#group__av_1ga3dd5c65e7f727f7befbdd4b51b5c3072) | | +| [`filterDevices`](#group__av_1ga968051eb33e118a8a8a9d7f6a048e040) | The exclusionList MUST be a nullptr terminated list. | +| [`matchID`](#group__av_1ga1b3366864eeafa7f4bed8ff0fa1df7d5) | Returns a device matching the given ID. | +| [`matchNameAndID`](#group__av_1ga22a80ede9d0f8017cc48cc197450328b) | Returns a device matching the given name and ID. If the device name is not available at the given ID then first device of that name will be returned. If the ID should not be matched the given ID should be -1. | +| [`instance`](#group__av_1ga2a3a77dce3f0d2b147c97c34407f542f) | Returns the default `[DeviceManager](#classscy_1_1av_1_1DeviceManager)` singleton. | +| [`shutdown`](#group__av_1ga00aa8e9f2192b9e26bcbb8f1f5cd3342) | Shuts down the `MediaFactory` and deletes the singleton instance. | +| [`getDefaultAudioDevice`](#group__av_1gae9e2effb9514f16af8a0654cf59b2bf1) | | +| [`getAudioDevices`](#group__av_1ga04e3b90e4bac6ad1bb03d00ba8337b6e) | | +| [`getAudioDevice`](#group__av_1ga95c8c01f83b7e0b5450892be78e031eb) | | +| [`getAudioDevice`](#group__av_1gabbe9f702e0082b2fc23f159bedf4fcfc) | | +| [`setInitialized`](#group__av_1gab6cf6a072abd179483f6f7d484f796e4) | | +| [`setWatcher`](#group__av_1ga90edc6121010b8344ebd6a9b8606fdf1) | | +| [`watcher`](#group__av_1ga29bc8a0cfc10633446ae7b9dae73bb0e) | | +| [`shouldDeviceBeIgnored`](#group__av_1ga08a06c5c337bc3ea08af5419860a2476) | The exclusionList MUST be a nullptr terminated list. | +| [`_watcher`](#group__av_1gae595c283673ca36a15dd318a953ecfc1) | | +| [`_initialized`](#group__av_1ga24858dc86635de264ee7d020c1313eaf) | | +| [`DevicesChanged`](#group__av_1ga066016a050182489096ab5920ecb3bca) | Signals when a system device is connecetd or removed. This signal is emitted by the platform specific `[DeviceWatcher](#classscy_1_1av_1_1DeviceWatcher)`. | +| [`_watcher`](#group__av_1gabe3bab2143c2e5739ff74505980f942d) | | +| [`DeviceManager`](#classscy_1_1av_1_1DeviceManager_1ga778c03d9b552d40b34bb8f8f9a1255d8) | | +| [`~DeviceManager`](#classscy_1_1av_1_1DeviceManager_1ga3635ac39fa55df574dcb0d98634c8140) | | +| [`getCapabilities`](#classscy_1_1av_1_1DeviceManager_1ga42f596484bd7234fd92becaac4005e53) | Capabilities. | +| [`setWatcher`](#classscy_1_1av_1_1DeviceManager_1ga90edc6121010b8344ebd6a9b8606fdf1) | | +| [`watcher`](#classscy_1_1av_1_1DeviceManager_1ga29bc8a0cfc10633446ae7b9dae73bb0e) | | +| [`print`](#classscy_1_1av_1_1DeviceManager_1ga485b4609f4a69f5d603b96deb411b306) | Print all devices to the output stream. | + +--- + +#### DeviceManager + +```cpp +DeviceManager() +``` + +--- + +#### ~DeviceManager + +```cpp +virtual ~DeviceManager() +``` + +--- + +#### initialize + +```cpp +virtual bool initialize() +``` + +Initialization. + +--- + +#### uninitialize + +```cpp +virtual void uninitialize() +``` + +--- + +#### getCapabilities + +```cpp +virtual int getCapabilities() +``` + +Capabilities. + +--- + +#### getAudioInputDevices + +```cpp +virtual bool getAudioInputDevices(std::vector< Device > & devices) +``` + +[Device](#structscy_1_1av_1_1Device) enumeration. + +| Parameter | Type | Description | +|-----------|------|-------------| +| `devices` | `std::vector< Device > &` | | + +--- + +#### getAudioOutputDevices + +```cpp +virtual bool getAudioOutputDevices(std::vector< Device > & devices) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `devices` | `std::vector< Device > &` | | + +--- + +#### getAudioInputDevice + +```cpp +virtual bool getAudioInputDevice(Device & out, const std::string & name, int id) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `out` | `Device &` | | +| `name` | `const std::string &` | | +| `id` | `int` | | + +--- + +#### getAudioInputDevice + +```cpp +virtual bool getAudioInputDevice(Device & out, int id) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `out` | `Device &` | | +| `id` | `int` | | + +--- + +#### getAudioOutputDevice + +```cpp +virtual bool getAudioOutputDevice(Device & out, const std::string & name, int id) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `out` | `Device &` | | +| `name` | `const std::string &` | | +| `id` | `int` | | + +--- + +#### getAudioOutputDevice + +```cpp +virtual bool getAudioOutputDevice(Device & out, int id) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `out` | `Device &` | | +| `id` | `int` | | + +--- + +#### getVideoCaptureDevices + +```cpp +virtual bool getVideoCaptureDevices(std::vector< Device > & devs) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `devs` | `std::vector< Device > &` | | + +--- + +#### getVideoCaptureDevice + +```cpp +virtual bool getVideoCaptureDevice(Device & out, const std::string & name, int id) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `out` | `Device &` | | +| `name` | `const std::string &` | | +| `id` | `int` | | + +--- + +#### getVideoCaptureDevice + +```cpp +virtual bool getVideoCaptureDevice(Device & out, int id) +``` + +Returns the video capture device at the given system index. + +| Parameter | Type | Description | +|-----------|------|-------------| +| `out` | `Device &` | | +| `id` | `int` | | + +--- + +#### getDefaultAudioInputDevice + +```cpp +virtual bool getDefaultAudioInputDevice(Device & device) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `device` | `Device &` | | + +--- + +#### getDefaultAudioOutputDevice + +```cpp +virtual bool getDefaultAudioOutputDevice(Device & device) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `device` | `Device &` | | + +--- + +#### getDefaultVideoCaptureDevice + +```cpp +virtual bool getDefaultVideoCaptureDevice(Device & device) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `device` | `Device &` | | + +--- + +#### initialized + +```cpp +inline bool initialized() const +``` + +--- + +#### print + +```cpp +virtual void print(std::ostream & ost) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `ost` | `std::ostream &` | | + +--- + +#### getCameras + +```cpp +bool getCameras(std::vector< Device > & devices) +``` + +[Device](#structscy_1_1av_1_1Device) enumeration. + +| Parameter | Type | Description | +|-----------|------|-------------| +| `devices` | `std::vector< Device > &` | | + +--- + +#### getMicrophones + +```cpp +bool getMicrophones(std::vector< Device > & devices) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `devices` | `std::vector< Device > &` | | + +--- + +#### getSpeakers + +```cpp +bool getSpeakers(std::vector< Device > & devices) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `devices` | `std::vector< Device > &` | | + +--- + +#### getDefaultMicrophone + +```cpp +bool getDefaultMicrophone(Device & device) +``` + +Default devices. + +| Parameter | Type | Description | +|-----------|------|-------------| +| `device` | `Device &` | | + +--- + +#### getDefaultSpeaker + +```cpp +bool getDefaultSpeaker(Device & device) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `device` | `Device &` | | + +--- + +#### getDefaultCamera + +```cpp +bool getDefaultCamera(Device & device) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `device` | `Device &` | | + +--- + +#### findCamera + +```cpp +bool findCamera(const std::string & name, Device & device) +``` + +Find device by name or id. + +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | +| `device` | `Device &` | | + +--- + +#### findMicrophone + +```cpp +bool findMicrophone(const std::string & name, Device & device) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | +| `device` | `Device &` | | + +--- + +#### findSpeaker + +```cpp +bool findSpeaker(const std::string & name, Device & device) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | +| `device` | `Device &` | | + +--- + +#### getDeviceList + +```cpp +bool getDeviceList(Device::Type type, std::vector< av::Device > & devices) +``` + +Base device list. + +| Parameter | Type | Description | +|-----------|------|-------------| +| `type` | `Device::Type` | | +| `devices` | `std::vector< av::Device > &` | | + +--- + +#### findVideoInputFormat + +```cpp +const AVInputFormat * findVideoInputFormat() +``` + +Find base FFmpeg formats. + +--- + +#### findAudioInputFormat + +```cpp +const AVInputFormat * findAudioInputFormat() +``` + +--- + +#### filterDevices + +```cpp +static bool filterDevices(std::vector< Device > & devices, const char *const exclusionList) +``` + +The exclusionList MUST be a nullptr terminated list. + +| Parameter | Type | Description | +|-----------|------|-------------| +| `devices` | `std::vector< Device > &` | | +| `exclusionList` | `const char *const` | | + +--- + +#### matchID + +```cpp +static bool matchID(std::vector< Device > & devices, Device & out, int id) +``` + +Returns a device matching the given ID. + +| Parameter | Type | Description | +|-----------|------|-------------| +| `devices` | `std::vector< Device > &` | | +| `out` | `Device &` | | +| `id` | `int` | | + +--- + +#### matchNameAndID + +```cpp +static bool matchNameAndID(std::vector< Device > & devices, Device & out, const std::string & name, int id) +``` + +Returns a device matching the given name and ID. If the device name is not available at the given ID then first device of that name will be returned. If the ID should not be matched the given ID should be -1. + +| Parameter | Type | Description | +|-----------|------|-------------| +| `devices` | `std::vector< Device > &` | | +| `out` | `Device &` | | +| `name` | `const std::string &` | | +| `id` | `int` | | + +--- + +#### instance + +```cpp +static DeviceManager & instance() +``` + +Returns the default `[DeviceManager](#classscy_1_1av_1_1DeviceManager)` singleton. + +--- + +#### shutdown + +```cpp +static void shutdown() +``` + +Shuts down the `MediaFactory` and deletes the singleton instance. + +--- + +#### getDefaultAudioDevice + +```cpp +virtual bool getDefaultAudioDevice(bool input, Device & device) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `input` | `bool` | | +| `device` | `Device &` | | + +--- + +#### getAudioDevices + +```cpp +virtual bool getAudioDevices(bool input, std::vector< Device > & devs) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `input` | `bool` | | +| `devs` | `std::vector< Device > &` | | + +--- + +#### getAudioDevice + +```cpp +virtual bool getAudioDevice(bool input, Device & out, const std::string & name, int id) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `input` | `bool` | | +| `out` | `Device &` | | +| `name` | `const std::string &` | | +| `id` | `int` | | + +--- + +#### getAudioDevice + +```cpp +virtual bool getAudioDevice(bool input, Device & out, int id) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `input` | `bool` | | +| `out` | `Device &` | | +| `id` | `int` | | + +--- + +#### setInitialized + +```cpp +void setInitialized(bool initialized) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `initialized` | `bool` | | + +--- + +#### setWatcher + +```cpp +void setWatcher(DeviceWatcher * watcher) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `watcher` | `DeviceWatcher *` | | + +--- + +#### watcher + +```cpp +DeviceWatcher * watcher() +``` + +--- + +#### shouldDeviceBeIgnored + +```cpp +static bool shouldDeviceBeIgnored(const std::string & deviceName, const char *const exclusionList) +``` + +The exclusionList MUST be a nullptr terminated list. + +| Parameter | Type | Description | +|-----------|------|-------------| +| `deviceName` | `const std::string &` | | +| `exclusionList` | `const char *const` | | + +--- + +#### _watcher + +```cpp +DeviceWatcher * _watcher +``` + +--- + +#### _initialized + +```cpp +bool _initialized +``` + +--- + +#### DevicesChanged + +```cpp +NullSignal DevicesChanged +``` + +Signals when a system device is connecetd or removed. This signal is emitted by the platform specific `[DeviceWatcher](#classscy_1_1av_1_1DeviceWatcher)`. + +--- + +#### _watcher + +```cpp +std::unique_ptr< DeviceWatcher > _watcher +``` + +--- + +#### DeviceManager + +```cpp +DeviceManager() +``` + +--- + +#### ~DeviceManager + +```cpp +~DeviceManager() +``` + +--- + +#### getCapabilities + +```cpp +virtual int getCapabilities() +``` + +Capabilities. + +--- + +#### setWatcher + +```cpp +void setWatcher([DeviceWatcher](#classscy_1_1av_1_1DeviceWatcher) * watcher) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `watcher` | `[DeviceWatcher](#classscy_1_1av_1_1DeviceWatcher) *` | | + +--- + +#### watcher + +```cpp +[DeviceWatcher](#classscy_1_1av_1_1DeviceWatcher) * watcher() +``` + +--- + +#### print + +```cpp +virtual void print(std::ostream & ost) +``` + +Print all devices to the output stream. + +| Parameter | Type | Description | +|-----------|------|-------------| +| `ost` | `std::ostream &` | | + +## FakeDeviceManager + +> **Extends:** `scy::av::IDeviceManager` +> **Defined in:** `devicemanager_fake.h` + +### Members + +| Name | Description | +|------|-------------| +| [`FakeDeviceManager`](#group__av_1ga006594e6f296225b135e550be80dcb13) | | +| [`initialize`](#group__av_1ga3f83116598bfa3b3d53a4c4c25cf1cee) | Initialization. | +| [`uninitialize`](#group__av_1ga1ba541135e1a1c0039ade4343403a25b) | | +| [`getCapabilities`](#group__av_1gaa72540c5d7eb2f07ad1317944cd28565) | Capabilities. | +| [`getMicrophones`](#group__av_1gaed7a9dee4d3dffe342c52d5d1edbebeb) | | +| [`getSpeakers`](#group__av_1ga89c33c93e68bc6bb55945952b8261f4e) | | +| [`getMicrophone`](#group__av_1gabc947f13611657bf38e64b901449aa1d) | | +| [`getSpeaker`](#group__av_1ga4d7895da9bbbcc0c57480d59c4c45dc4) | | +| [`getCameras`](#group__av_1gad2513f312a81350e6b936fc33ad21405) | | +| [`getDefaultCamera`](#group__av_1gaf3aaf6ebb5675f70bc0cc3acd70875ba) | | +| [`setMicrophones`](#group__av_1gac6f0eef0d4653d05d1ed39ff61c3e775) | | +| [`setSpeakers`](#group__av_1ga063298c41c2f469d96614f1c19d9cd4e) | | +| [`setCameras`](#group__av_1ga7d8d1af543bbb57550820afe9d6d7b2f) | | +| [`getCamera`](#group__av_1ga285e406d330f5c6c0f6ab8cdde3fd634) | | +| [`getAudioDevice`](#group__av_1gaafe3fffef143106836168cc7ac4d0716) | | +| [`findDeviceByName`](#group__av_1ga3ce54e061c6703f51c472734d300bec2) | | +| [`input_devices_`](#group__av_1ga8447f95deb91c759c090f19365852cdc) | | +| [`output_devices_`](#group__av_1ga1a2d888a668bbc0072cf71342df540da) | | +| [`vidcap_devices_`](#group__av_1gabfb8bc40437c73c4ae6a1169916d69e5) | | + +--- + +#### FakeDeviceManager + +```cpp +inline FakeDeviceManager() +``` + +--- + +#### initialize + +```cpp +virtual inline bool initialize() +``` + +Initialization. + +--- + +#### uninitialize + +```cpp +virtual inline void uninitialize() +``` + +--- + +#### getCapabilities + +```cpp +virtual inline int getCapabilities() +``` + +Capabilities. + +--- + +#### getMicrophones + +```cpp +virtual inline bool getMicrophones(std::vector< Device > & devs) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `devs` | `std::vector< Device > &` | | + +--- + +#### getSpeakers + +```cpp +virtual inline bool getSpeakers(std::vector< Device > & devs) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `devs` | `std::vector< Device > &` | | + +--- + +#### getMicrophone + +```cpp +virtual inline bool getMicrophone(const std::string & name, Device & out) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | +| `out` | `Device &` | | + +--- + +#### getSpeaker + +```cpp +virtual inline bool getSpeaker(const std::string & name, Device & out) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | +| `out` | `Device &` | | + +--- + +#### getCameras + +```cpp +virtual inline bool getCameras(std::vector< Device > & devs) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `devs` | `std::vector< Device > &` | | + +--- + +#### getDefaultCamera + +```cpp +virtual inline bool getDefaultCamera(Device & device) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `device` | `Device &` | | + +--- + +#### setMicrophones + +```cpp +inline void setMicrophones(const std::vector< Device > & devices) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `devices` | `const std::vector< Device > &` | | + +--- + +#### setSpeakers + +```cpp +inline void setSpeakers(const std::vector< Device > & devices) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `devices` | `const std::vector< Device > &` | | + +--- + +#### setCameras + +```cpp +inline void setCameras(const std::vector< Device > & devices) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `devices` | `const std::vector< Device > &` | | + +--- + +#### getCamera + +```cpp +virtual inline bool getCamera(const std::string & name, Device & out) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | +| `out` | `Device &` | | + +--- + +#### getAudioDevice + +```cpp +inline bool getAudioDevice(bool input, const std::string & name, Device & out) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `input` | `bool` | | +| `name` | `const std::string &` | | +| `out` | `Device &` | | + +--- + +#### findDeviceByName + +```cpp +static inline bool findDeviceByName(const std::vector< Device > & devices, const std::string & name, Device & out) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `devices` | `const std::vector< Device > &` | | +| `name` | `const std::string &` | | +| `out` | `Device &` | | + +--- + +#### input_devices_ + +```cpp +std::vector< Device > input_devices_ +``` + +--- + +#### output_devices_ + +```cpp +std::vector< Device > output_devices_ +``` + +--- + +#### vidcap_devices_ + +```cpp +std::vector< Device > vidcap_devices_ +``` + +## LinuxDeviceManager + +> **Extends:** `scy::av::DeviceManager` +> **Defined in:** `devicemanager_linux.h` + +### Members + +| Name | Description | +|------|-------------| +| [`LinuxDeviceManager`](#group__av_1ga183809a0da4b49689b13e098f8d0ac03) | | +| [`~LinuxDeviceManager`](#group__av_1gab60b8f07ec657f5cded2956320e10a48) | | +| [`getCameras`](#group__av_1gac931c97e65968e0f46d18038e5789939) | | + +--- + +#### LinuxDeviceManager + +```cpp +LinuxDeviceManager() +``` + +--- + +#### ~LinuxDeviceManager + +```cpp +virtual ~LinuxDeviceManager() +``` + +--- + +#### getCameras + +```cpp +virtual bool getCameras(std::vector< Device > & devs) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `devs` | `std::vector< Device > &` | | + +## MacDeviceManager + +> **Extends:** `scy::av::DeviceManager` +> **Defined in:** `devicemanager_mac.h` + +### Members + +| Name | Description | +|------|-------------| +| [`MacDeviceManager`](#group__av_1gac14003aeb093497f3a2930f26cae0acf) | | +| [`~MacDeviceManager`](#group__av_1gaa0500c9b93a11442e3d505b0e7611848) | | +| [`getCameras`](#group__av_1ga689d89e5f57be3c868009b9ffdd11fe2) | | +| [`FilterDevice`](#group__av_1ga0827c843ec57dffe59c82763bb52af1e) | virtual bool [getAudioDevices(bool input, std::vector& devs)](#group__av_1ga04e3b90e4bac6ad1bb03d00ba8337b6e); | + +--- + +#### MacDeviceManager + +```cpp +MacDeviceManager() +``` + +--- + +#### ~MacDeviceManager + +```cpp +virtual ~MacDeviceManager() +``` + +--- + +#### getCameras + +```cpp +virtual bool getCameras(std::vector< Device > & devs) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `devs` | `std::vector< Device > &` | | + +--- + +#### FilterDevice + +```cpp +bool FilterDevice(const Device & d) +``` + +virtual bool [getAudioDevices(bool input, std::vector& devs)](#group__av_1ga04e3b90e4bac6ad1bb03d00ba8337b6e); + +| Parameter | Type | Description | +|-----------|------|-------------| +| `d` | `const Device &` | | + +## FLVMetadataInjector + +> **Extends:** `scy::PacketProcessor` +> **Defined in:** `flvmetadatainjector.h` + +This class implements a packetizer which appends correct stream headers and modifies the timestamp of FLV packets so Adobe's Flash Player will play our videos mid-stream. + +This adapter is useful for multicast situations where we don't have the option of restarting the encoder stream. + +### Members + +| Name | Description | +|------|-------------| +| [`AMFDataType`](#group__av_1gaa58292d406cc0079da1c7c6c8d362714) | | +| [``](#group__av_1ga5f63483be4c5ad888f60998ab277162c) | | +| [``](#group__av_1ga0c2328096dabc3e7794a0564891e002b) | | +| [`IPacketizer`](#group__av_1ga9f887b63bbd57a16ebea78f42352cf80) | | +| [`_format`](#group__av_1ga00b49e6d76e5c12d79a8b31f7f68aa16) | | +| [`_initial`](#group__av_1ga5341424127e2b262009062d53f14dd89) | | +| [`_modifyingStream`](#group__av_1ga620bcff399fc9e599fdb134d7f164a30) | | +| [`_waitingForKeyframe`](#group__av_1ga595e597a9cb20e8a558501f7bbeff7ed) | | +| [`_timestampOffset`](#group__av_1gae40bbe2c2eda197672f9fad8f13690cb) | | +| [`onStreamStateChange`](#group__av_1gad92da5518ddd902a7136e83dde6ba503) | whenever the stream is restarted. | +| [`process`](#group__av_1gaf7675aec070348fb52657d0bbc81264d) | This method performs processing on the given packet and emits the result. | +| [`fastUpdateTimestamp`](#group__av_1gac6bdf4094f0164d4557b501346fa3f47) | Updates the timestamp in the given FLV tag buffer. No more need to copy data with this method. Caution: this method does not check buffer size. | +| [`fastIsFLVHeader`](#group__av_1gaff079b714922df3458c65ba3ef60a3f6) | Caution: this method does not check buffer size. | +| [`fastIsFLVKeyFrame`](#group__av_1ga34a40b333d9f32b4ef94f3e3f028665a) | Caution: this method does not check buffer size. | +| [`writeFLVHeader`](#group__av_1ga6aa18b140ad46d0e7a2d4ac44afe3e06) | | +| [`doubleToInt`](#group__av_1ga371b1182cbe6cf19c17d7add8cec0274) | | +| [`writeAMFSring`](#group__av_1ga28c5478abb189d041c739068082455c8) | AMF Helpers. | +| [`writeAMFDouble`](#group__av_1gad544d5db35df80ebb048dec5f5f3a286) | | +| [`writeAMFBool`](#group__av_1ga2aa49c8d0d9ccf3602b3fe7bbbfb1b1d) | | +| [`dumpFLVTags`](#group__av_1ga1070f13732cb0431b30509fba615b14e) | | +| [`emitter`](#group__av_1ga8b361da8e252816c458d4987247a06c0) | | +| [`_format`](#group__av_1gad846cf859e5cea50a984de6f9544b165) | | +| [`_initial`](#group__av_1ga1d940a770234cb5ad44e7622110f4fb0) | | +| [`_modifyingStream`](#group__av_1ga0d0de9ad89aeb3c708219b126397d703) | | +| [`_waitingForKeyframe`](#group__av_1ga85b7dc7527c9cce0db4af6440700ffa8) | | +| [`_timestampOffset`](#group__av_1ga612c3a994d9cd6472c5a195215b94b4d) | | +| [`_fpsCounter`](#group__av_1ga73a76b5f863b967f49a85cdc8c72e433) | | + +--- + +#### AMFDataType + +```cpp +enum AMFDataType +``` + +| Value | Description | +|-------|-------------| +| `AMF_DATA_TYPE_NUMBER` | | +| `AMF_DATA_TYPE_BOOL` | | +| `AMF_DATA_TYPE_STRING` | | +| `AMF_DATA_TYPE_OBJECT` | | +| `AMF_DATA_TYPE_NULL` | | +| `AMF_DATA_TYPE_UNDEFINED` | | +| `AMF_DATA_TYPE_REFERENCE` | | +| `AMF_DATA_TYPE_MIXEDARRAY` | | +| `AMF_DATA_TYPE_OBJECT_END` | | +| `AMF_DATA_TYPE_ARRAY` | | +| `AMF_DATA_TYPE_DATE` | | +| `AMF_DATA_TYPE_LONG_STRING` | | +| `AMF_DATA_TYPE_UNSUPPORTED` | | + +--- + +#### + +```cpp +enum +``` + +| Value | Description | +|-------|-------------| +| `FLV_TAG_TYPE_AUDIO` | | +| `FLV_TAG_TYPE_VIDEO` | | +| `FLV_TAG_TYPE_SCRIPT` | | + +--- + +#### + +```cpp +enum +``` + +| Value | Description | +|-------|-------------| +| `FLV_FRAME_KEY` | | +| `FLV_FRAME_INTER` | | +| `FLV_FRAME_DISP_INTER` | | + +--- + +#### IPacketizer + +```cpp +IPacketizer(this-> emitter) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `emitter` | `this->` | | + +--- + +#### _format + +```cpp +_format(format) +``` + +--- + +#### _initial + +```cpp +_initial(true) +``` + +--- + +#### _modifyingStream + +```cpp +_modifyingStream(false) +``` + +--- + +#### _waitingForKeyframe + +```cpp +_waitingForKeyframe(false) +``` + +--- + +#### _timestampOffset + +```cpp +inline _timestampOffset(0) const +``` + +--- + +#### onStreamStateChange + +```cpp +virtual inline void onStreamStateChange(const PacketStreamState & state) +``` + +whenever the stream is restarted. + +This method is called by the Packet [Stream](./doc/api-base.md#classscy_1_1Stream) + +| Parameter | Type | Description | +|-----------|------|-------------| +| `state` | `const PacketStreamState &` | | + +--- + +#### process + +```cpp +virtual inline void process(IPacket & packet) +``` + +This method performs processing on the given packet and emits the result. + +Note: If packet processing is async (the packet is not in the current thread scope) then packet data must be copied. Copied data can be freed directly aFter the async call to [emit()](./doc/api-base.md#group__base_1ga995248310998c29df87051389f52b58c) the outgoing packet. + +| Parameter | Type | Description | +|-----------|------|-------------| +| `packet` | `IPacket &` | | + +--- + +#### fastUpdateTimestamp + +```cpp +virtual inline void fastUpdateTimestamp(char * buf, std::uint32_t timestamp) +``` + +Updates the timestamp in the given FLV tag buffer. No more need to copy data with this method. Caution: this method does not check buffer size. + +| Parameter | Type | Description | +|-----------|------|-------------| +| `buf` | `char *` | | +| `timestamp` | `std::uint32_t` | | + +--- + +#### fastIsFLVHeader + +```cpp +virtual inline bool fastIsFLVHeader(char * buf) +``` + +Caution: this method does not check buffer size. + +| Parameter | Type | Description | +|-----------|------|-------------| +| `buf` | `char *` | | + +--- + +#### fastIsFLVKeyFrame + +```cpp +virtual inline bool fastIsFLVKeyFrame(char * buf) +``` + +Caution: this method does not check buffer size. + +| Parameter | Type | Description | +|-----------|------|-------------| +| `buf` | `char *` | | + +--- + +#### writeFLVHeader + +```cpp +virtual inline void writeFLVHeader(BitWriter & writer) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `writer` | `BitWriter &` | | + +--- + +#### doubleToInt + +```cpp +inline std::int64_t doubleToInt(double d) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `d` | `double` | | + +--- + +#### writeAMFSring + +```cpp +virtual inline void writeAMFSring(BitWriter & writer, const char * val) +``` + +AMF Helpers. + +| Parameter | Type | Description | +|-----------|------|-------------| +| `writer` | `BitWriter &` | | +| `val` | `const char *` | | + +--- + +#### writeAMFDouble + +```cpp +virtual inline void writeAMFDouble(BitWriter & writer, double val) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `writer` | `BitWriter &` | | +| `val` | `double` | | + +--- + +#### writeAMFBool + +```cpp +virtual inline void writeAMFBool(BitWriter & writer, bool val) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `writer` | `BitWriter &` | | +| `val` | `bool` | | + +--- + +#### dumpFLVTags + +```cpp +static inline bool dumpFLVTags(BitReader & reader) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `reader` | `BitReader &` | | + +--- + +#### emitter + +```cpp +PacketSignal emitter +``` + +--- + +#### _format + +```cpp +Format _format +``` + +--- + +#### _initial + +```cpp +bool _initial +``` + +--- + +#### _modifyingStream + +```cpp +bool _modifyingStream +``` + +--- + +#### _waitingForKeyframe + +```cpp +bool _waitingForKeyframe +``` + +--- + +#### _timestampOffset + +```cpp +std::uint32_t _timestampOffset +``` + +--- + +#### _fpsCounter + +```cpp +legacy::FPSCounter _fpsCounter +``` + +## VideoAnalyzer + +> **Defined in:** `videoanalyzer.h` + +This class provides basic AV spectrum analysis on a video using the Fourier Transform algorithm. Data is outputted in CSV format. + +TODO:/// - Pluggable algorithms and processors + +* Normalization (scaling) for output values + +* [Process](./doc/api-base.md#classscy_1_1Process) multiple audio channels properly + +* Inherit from [PacketProcessor](./doc/api-base.md#classscy_1_1PacketProcessor) + +### Members + +| Name | Description | +|------|-------------| +| [`VideoAnalyzer`](#group__av_1gac993a14f178ad54a007326285a81298e) | | +| [`~VideoAnalyzer`](#group__av_1ga8baaaa919a048d47aae1a727f17c54e0) | | +| [`initialize`](#group__av_1ga12c07a7905f57e13e4dd068d66bb1368) | Set everything up, and open the input file. | +| [`uninitialize`](#group__av_1ga8f31eec4f3b34bd581e9a06d723e5ae7) | Stop processing and free everything. | +| [`start`](#group__av_1gad69119157d765c60cfc1e15182403c1e) | Begin processing. | +| [`stop`](#group__av_1ga027a1e0984779cef7815b1ed349f5333) | Stop processing. | +| [`reader`](#group__av_1gafdcd38afd5348de442f3b5acd155df42) | | +| [`options`](#group__av_1ga4e52c919db9335da1ba1b6fa69de9032) | | +| [`error`](#group__av_1ga93f4c712ca703193022cf52d838778ab) | | +| [`getGrayVideoFrame`](#group__av_1ga8e7e0a166943d5172047fa223900f961) | | +| [`onReadComplete`](#group__av_1ga15b69731e04c27a54a8fe2d1f5c2f3c0) | | +| [`onVideo`](#group__av_1gabccd45c480e1118524bd28dbb91f2d15) | | +| [`onAudio`](#group__av_1gad9b3381f6e3189275d050327f42a57bf) | | +| [`className`](#group__av_1ga14432811560e9bf62c137882300c7e03) | | +| [`PacketOut`](#group__av_1gabcf4743d8bd41e4499ccd11191a4fbe2) | Signals on [VideoAnalyzer::Packet](#structscy_1_1av_1_1VideoAnalyzer_1_1Packet) output Raw FFT data is available via [VideoAnalyzer::Stream](#structscy_1_1av_1_1VideoAnalyzer_1_1Stream)->rdftData | +| [`Complete`](#group__av_1ga2f0831ef8267630b861cdc91158864a6) | Signals on analysis complete. | +| [`_mutex`](#group__av_1ga758687490e01b5e0f45eda901ab37ae8) | | +| [`_options`](#group__av_1gae42dec896e9b00a69bcfebede88b3ff6) | | +| [`_error`](#group__av_1ga0cdbb5f6f79191c6a6735d9745e20a78) | | +| [`_reader`](#group__av_1gaa16cee59bc4837a365cd203c149a68f1) | | +| [`_video`](#group__av_1ga3f21224e7f325b64bf3da5500ea28571) | | +| [`_audio`](#group__av_1ga3da1b0cf78f242341edd610b022d83be) | | +| [`_videoConv`](#group__av_1gacd5118e720bd223beb0ee6f7b7b1c3ee) | | + +--- + +#### VideoAnalyzer + +```cpp +VideoAnalyzer(const VideoAnalyzer::Options & options) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `options` | `const VideoAnalyzer::Options &` | | + +--- + +#### ~VideoAnalyzer + +```cpp +virtual ~VideoAnalyzer() +``` + +--- + +#### initialize + +```cpp +virtual void initialize() +``` + +Set everything up, and open the input file. + +--- + +#### uninitialize + +```cpp +virtual void uninitialize() +``` + +Stop processing and free everything. + +--- + +#### start + +```cpp +virtual void start() +``` + +Begin processing. + +--- + +#### stop + +```cpp +virtual void stop() +``` + +Stop processing. + +--- + +#### reader + +```cpp +virtual MediaCapture & reader() +``` + +--- + +#### options + +```cpp +virtual Options & options() +``` + +--- + +#### error + +```cpp +virtual std::string error() const +``` + +--- + +#### getGrayVideoFrame + +```cpp +AVFrame * getGrayVideoFrame() +``` + +--- + +#### onReadComplete + +```cpp +virtual void onReadComplete(void * sender) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `sender` | `void *` | | + +--- + +#### onVideo + +```cpp +virtual void onVideo(void * sender, VideoPacket & packet) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `sender` | `void *` | | +| `packet` | `VideoPacket &` | | + +--- + +#### onAudio + +```cpp +virtual void onAudio(void * sender, AudioPacket & packet) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `sender` | `void *` | | +| `packet` | `AudioPacket &` | | + +--- + +#### className + +```cpp +inline const char * className() const +``` + +--- + +#### PacketOut + +```cpp +Signal< void(const VideoAnalyzer::Stream &, const VideoAnalyzer::Packet &)> PacketOut +``` + +Signals on [VideoAnalyzer::Packet](#structscy_1_1av_1_1VideoAnalyzer_1_1Packet) output Raw FFT data is available via [VideoAnalyzer::Stream](#structscy_1_1av_1_1VideoAnalyzer_1_1Stream)->rdftData + +--- + +#### Complete + +```cpp +NullSignal Complete +``` + +Signals on analysis complete. + +--- + +#### _mutex + +```cpp +std::mutex _mutex +``` + +--- + +#### _options + +```cpp +Options _options +``` + +--- + +#### _error + +```cpp +std::string _error +``` + +--- + +#### _reader + +```cpp +MediaCapture _reader +``` + +--- + +#### _video + +```cpp +VideoAnalyzer::Stream * _video +``` + +--- + +#### _audio + +```cpp +VideoAnalyzer::Stream * _audio +``` + +--- + +#### _videoConv + +```cpp +VideoConverter * _videoConv +``` + +## Options + +> **Defined in:** `videoanalyzer.h` + +### Members + +| Name | Description | +|------|-------------| +| [`Options`](#group__av_1ga0610fd6f6ea8ccc982764e198c4191df) | | +| [`ifile`](#group__av_1ga0588f37bc4a07997c5b52aad94488177) | | +| [`rdftSize`](#group__av_1ga3930c2df8a401e1b6a6cb65d824a1f37) | | + +--- + +#### Options + +```cpp +inline Options() +``` + +--- + +#### ifile + +```cpp +std::string ifile +``` + +--- + +#### rdftSize + +```cpp +int rdftSize +``` + +## Packet + +> **Defined in:** `videoanalyzer.h` + +### Members + +| Name | Description | +|------|-------------| +| [`Packet`](#group__av_1gad1482a53678eb45b010543da58fd75d3) | | +| [`time`](#group__av_1gaf5901e114c3cc04e690f91d4fb7b0b6b) | | +| [`value`](#group__av_1ga35702a4a9df499a661bdf48c5f0a8921) | | + +--- + +#### Packet + +```cpp +Packet(double time, double value) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `time` | `double` | | +| `value` | `double` | | + +--- + +#### time + +```cpp +double time +``` + +--- + +#### value + +```cpp +double value +``` + +## Stream + +> **Defined in:** `videoanalyzer.h` + +### Members + +| Name | Description | +|------|-------------| +| [`Stream`](#group__av_1ga4b11e34ec10c49f9dcdf30a25b2bd5d2) | | +| [`~Stream`](#group__av_1ga523d33f3555c415b63ca428744f814c7) | | +| [`initialize`](#group__av_1gad2da7bdf2d9164a40e83b4cc0acc7a82) | | +| [`uninitialize`](#group__av_1gac92af80fd4eb8ff92e4bab9608c29dc3) | | +| [`fft`](#group__av_1ga67a9547ab771c61d603086a5dd922b0f) | | +| [`name`](#group__av_1ga0273e4f2e768d0daa30719dcf97a9a66) | | +| [`rdft`](#group__av_1ga1c501d438007311a16dfb1d93572f540) | | +| [`rdftData`](#group__av_1ga39711bf7e95a4b07f43c3934643fa930) | | +| [`rdftSize`](#group__av_1gacca84a21ae498fcb9035ad6cb33b9f2b) | | +| [`rdftBits`](#group__av_1ga2979c4b96e03f235536ea6ee7b8a230c) | | +| [`frames`](#group__av_1ga96a21cba5b0e1fbb07eb3dc4236f414f) | | +| [`filled`](#group__av_1gace58db739f0c0dcc61db800cafa2e45e) | | + +--- + +#### Stream + +```cpp +Stream(const std::string & name, int rdftSize) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | +| `rdftSize` | `int` | | + +--- + +#### ~Stream + +```cpp +~Stream() +``` + +--- + +#### initialize + +```cpp +void initialize() +``` + +--- + +#### uninitialize + +```cpp +void uninitialize() +``` + +--- + +#### fft + +```cpp +void fft() +``` + +--- + +#### name + +```cpp +std::string name +``` +--- +#### rdft -Signals when a system device is connecetd or removed. This signal is emitted by the platform specific `[DeviceWatcher](#classscy_1_1av_1_1DeviceWatcher)`. +```cpp +RDFTContext * rdft +``` -#### `public DeviceManager()` +--- +#### rdftData +```cpp +FFTSample * rdftData +``` +--- +#### rdftSize -#### `public virtual ~DeviceManager()` +```cpp +int rdftSize +``` +--- +#### rdftBits +```cpp +int rdftBits +``` +--- -#### `public virtual bool initialize()` +#### frames -Initialization. +```cpp +std::int64_t frames +``` +--- +#### filled -#### `public virtual void uninitialize()` +```cpp +int filled +``` +## MacDeviceWatcher +> **Extends:** `scy::av::DeviceWatcher` +### Members +| Name | Description | +|------|-------------| +| [`MacDeviceWatcher`](#group__av_1gaac48968d26c753ef2eb58b8a5b940221) | | +| [`~MacDeviceWatcher`](#group__av_1ga32910b3b0f011d047bb4521df07b2d67) | | +| [`start`](#group__av_1ga86ba79c6b43c5f35db2f660da0e72147) | | +| [`stop`](#group__av_1ga9133417d7365867fd021e28a52f08c90) | | +| [`manager_`](#group__av_1gaeabaa25080e8af217554a29ddf32e862) | | +| [`impl_`](#group__av_1ga3c7c48673111c854587f4c8d7fc19d8e) | | -#### `public virtual int getCapabilities()` +--- -Capabilities. +#### MacDeviceWatcher +```cpp +explicit MacDeviceWatcher(IDeviceManager * dm) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `dm` | `IDeviceManager *` | | -#### `public virtual bool getAudioInputDevices(std::vector< `[`Device`](#structscy_1_1av_1_1Device)` > & devices)` +--- -[Device](#structscy_1_1av_1_1Device) enumeration. +#### ~MacDeviceWatcher +```cpp +virtual ~MacDeviceWatcher() +``` + +--- +#### start -#### `public virtual bool getAudioOutputDevices(std::vector< `[`Device`](#structscy_1_1av_1_1Device)` > & devices)` +```cpp +virtual bool start() +``` +--- +#### stop +```cpp +virtual void stop() +``` +--- -#### `public virtual bool getAudioInputDevice(`[`Device`](#structscy_1_1av_1_1Device)` & out,const std::string & name,int id)` +#### manager_ +```cpp +IDeviceManager * manager_ +``` +--- +#### impl_ +```cpp +[DeviceWatcherImpl](./doc/api-undefined.md#interfaceDeviceWatcherImpl) * impl_ +``` -#### `public virtual bool getAudioInputDevice(`[`Device`](#structscy_1_1av_1_1Device)` & out,int id)` +## AudioCapture +> **Extends:** `scy::av::MediaCapture` +> **Defined in:** `audiocapture.h` +This class implements a cross platform audio capturer. +### Members +| Name | Description | +|------|-------------| +| [`AudioCapture`](#group__av_1gae078929c2f84b9c78014b9c071c12414) | | +| [`AudioCapture`](#group__av_1gaa98c303de9b4a2e8daaf330c02a6eadd) | | +| [`AudioCapture`](#group__av_1gaf0b333f407a129ff8f499df33744ef5b) | | +| [`~AudioCapture`](#group__av_1ga5c267d2acd4fc853b46cc1db116b3d02) | | +| [`openAudio`](#group__av_1ga7f191e45d9c4190b8ea6f42061e5aa73) | | +| [`openAudio`](#group__av_1gaa845730311774b9f77706723acf6d6ab) | | -#### `public virtual bool getAudioOutputDevice(`[`Device`](#structscy_1_1av_1_1Device)` & out,const std::string & name,int id)` +--- +#### AudioCapture +```cpp +AudioCapture() +``` +--- +#### AudioCapture -#### `public virtual bool getAudioOutputDevice(`[`Device`](#structscy_1_1av_1_1Device)` & out,int id)` +```cpp +AudioCapture(const std::string & device, const av::AudioCodec & params) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `device` | `const std::string &` | | +| `params` | `const av::AudioCodec &` | | +--- +#### AudioCapture +```cpp +AudioCapture(const std::string & device, int channels, int sampleRate, const std::string & sampleFmt) +``` -#### `public virtual bool getVideoCaptureDevices(std::vector< `[`Device`](#structscy_1_1av_1_1Device)` > & devs)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `device` | `const std::string &` | | +| `channels` | `int` | | +| `sampleRate` | `int` | | +| `sampleFmt` | `const std::string &` | | +--- +#### ~AudioCapture +```cpp +virtual ~AudioCapture() +``` +--- -#### `public virtual bool getVideoCaptureDevice(`[`Device`](#structscy_1_1av_1_1Device)` & out,const std::string & name,int id)` +#### openAudio +```cpp +virtual void openAudio(const std::string & device, const av::AudioCodec & params) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `device` | `const std::string &` | | +| `params` | `const av::AudioCodec &` | | +--- +#### openAudio -#### `public virtual bool getVideoCaptureDevice(`[`Device`](#structscy_1_1av_1_1Device)` & out,int id)` +```cpp +virtual void openAudio(const std::string & device, int channels, int sampleRate, const std::string & sampleFmt) +``` -Returns the video capture device at the given system index. +| Parameter | Type | Description | +|-----------|------|-------------| +| `device` | `const std::string &` | | +| `channels` | `int` | | +| `sampleRate` | `int` | | +| `sampleFmt` | `const std::string &` | | + +## FormatRegistry + +> **Defined in:** `formatregistry.h` + +### Members + +| Name | Description | +|------|-------------| +| [`instance`](#group__av_1gaf75e6c54e5e6a2a4c2fc5b51157351ba) | | +| [`FormatRegistry`](#group__av_1gaaf5a5ede3c5909f579a34c56e8186f1c) | | +| [`~FormatRegistry`](#group__av_1gac6f77454c59e8bce0a602d0973f82515) | | +| [`get`](#group__av_1gabd3e9f2a811539d26a8edb4ba4e3ed27) | | +| [`getByID`](#group__av_1ga5139a694c99b22a01dd6cebdcdcf80eb) | | +| [`getOrDefault`](#group__av_1ga0060ffcf37bbd8efa2362c598872c81a) | Returns the default media format. | +| [`getDefault`](#group__av_1gac0c655caad54b6192ecfdc73c04b00e1) | If a default has been specified it will be returned, other the format with the highest priority will take precedence. | +| [`registerFormat`](#group__av_1ga2af81c756b1e9a18b4d9fec1d0aae501) | Registers the given media format overriding existing media formats of the same name. | +| [`unregisterFormat`](#group__av_1ga35d5b38f24071b665dbe0895f9c21840) | Unregisters the media format matching the given name. | +| [`setDefault`](#group__av_1gabf704e68f4ba8ca65eb6ed45a7b7ef7e) | Sets the default fallback media format. | +| [`exists`](#group__av_1ga4723ecceee10ce9b5c10500fcab53da1) | | +| [`clear`](#group__av_1ga11cf8bc02b9f1236a52b8a8ba6f04342) | | +| [`formats`](#group__av_1gac522b25711b01a224f02df815860a9d6) | | +| [`FormatRegistry`](#group__av_1ga462123d2a4f764202f512ebf1e1ca0a3) | | +| [`operator=`](#group__av_1ga5085e598588f063304f60e8456b9333d) | | +| [`_formats`](#group__av_1gae0ccfdf862160fd24575efb58e9ed44a) | | +| [`_default`](#group__av_1gae517ab74c8e87f17673ff47ed95949a9) | | +| [`_mutex`](#group__av_1gaf7a13cd56f063bfc5744099b9a49d825) | | + +--- + +#### instance + +```cpp +static FormatRegistry & instance() +``` +--- +#### FormatRegistry -#### `public virtual bool getDefaultAudioInputDevice(`[`Device`](#structscy_1_1av_1_1Device)` & device)` +```cpp +FormatRegistry() +``` +--- +#### ~FormatRegistry +```cpp +virtual ~FormatRegistry() +``` +--- -#### `public virtual bool getDefaultAudioOutputDevice(`[`Device`](#structscy_1_1av_1_1Device)` & device)` +#### get +```cpp +virtual Format & get(const std::string & name) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | +--- +#### getByID -#### `public virtual bool getDefaultVideoCaptureDevice(`[`Device`](#structscy_1_1av_1_1Device)` & device)` +```cpp +virtual Format & getByID(const std::string & id) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `id` | `const std::string &` | | +--- +#### getOrDefault +```cpp +virtual Format & getOrDefault(const std::string & name) +``` -#### `public inline bool initialized() const` +Returns the default media format. +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | +--- +#### getDefault +```cpp +virtual Format & getDefault() +``` -#### `public virtual void print(std::ostream & ost)` +If a default has been specified it will be returned, other the format with the highest priority will take precedence. +--- +#### registerFormat +```cpp +virtual void registerFormat(const Format & format) +``` +Registers the given media format overriding existing media formats of the same name. -#### `public DeviceManager()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `format` | `const Format &` | | +--- +#### unregisterFormat +```cpp +virtual bool unregisterFormat(const std::string & name) +``` +Unregisters the media format matching the given name. -#### `public ~DeviceManager()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | +--- +#### setDefault +```cpp +virtual void setDefault(const std::string & name) +``` +Sets the default fallback media format. -#### `public bool getCameras(std::vector< `[`Device`](#structscy_1_1av_1_1Device)` > & devices)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | -[Device](#structscy_1_1av_1_1Device) enumeration. +--- +#### exists +```cpp +virtual bool exists(const std::string & name) +``` -#### `public bool getMicrophones(std::vector< `[`Device`](#structscy_1_1av_1_1Device)` > & devices)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | +--- +#### clear +```cpp +virtual void clear() +``` +--- -#### `public bool getSpeakers(std::vector< `[`Device`](#structscy_1_1av_1_1Device)` > & devices)` +#### formats +```cpp +virtual FormatList formats() const +``` +--- +#### FormatRegistry +```cpp +FormatRegistry(FormatRegistry const &) = delete +``` -#### `public bool getDefaultMicrophone(`[`Device`](#structscy_1_1av_1_1Device)` & device)` +--- -Default devices. +#### operator= +```cpp +FormatRegistry & operator=(FormatRegistry const &) = delete +``` +--- -#### `public bool getDefaultSpeaker(`[`Device`](#structscy_1_1av_1_1Device)` & device)` +#### _formats +```cpp +FormatList _formats +``` +--- +#### _default +```cpp +std::string _default +``` -#### `public bool getDefaultCamera(`[`Device`](#structscy_1_1av_1_1Device)` & device)` +--- +#### _mutex +```cpp +std::mutex _mutex +``` +## FPSCounter +> **Defined in:** `fpscounter.h` -#### `public bool findCamera(const std::string & name,`[`Device`](#structscy_1_1av_1_1Device)` & device)` +FPS counter based on the simple moving average (SMA) algorithm. -Find device by name or id. +### Members +| Name | Description | +|------|-------------| +| [`updateAvg`](#group__av_1ga4271e5e2a3cc45859ed77f5aa230e89b) | | +| [`FPSCounter`](#group__av_1ga3a7ac11cae2ba7667dd8ee25c2c09dd7) | | +| [`reset`](#group__av_1ga5e7f4d6a27bcddab6c42387f7fa10b17) | | +| [`tick`](#group__av_1ga462bac68ff4e426f966bb1bf92e426f8) | | +| [`MAX`](#group__av_1ga1ccc52491f07a8187df9b8af7d028acb) | | +| [`tickIndex`](#group__av_1gaff38614aa382382abd783764cfcf3b65) | | +| [`prevTick`](#group__av_1gaf05e8b7251c3159f5bde8c39c6af0a75) | | +| [`tickSum`](#group__av_1ga7dd1926c878fbcc471b3bea0e1f37492) | | +| [`tickList`](#group__av_1ga5a7e8f4511f34e9e550ff2e3276278b0) | | +| [`fps`](#group__av_1ga116ea3077cf60b7a576b59a6564e829d) | | +| [`frames`](#group__av_1ga3aaf0a4591fdce8c91aba11e85a32a73) | | +--- -#### `public bool findMicrophone(const std::string & name,`[`Device`](#structscy_1_1av_1_1Device)` & device)` +#### updateAvg +```cpp +inline double updateAvg(clock_t newTick) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `newTick` | `clock_t` | | +--- +#### FPSCounter -#### `public bool findSpeaker(const std::string & name,`[`Device`](#structscy_1_1av_1_1Device)` & device)` +```cpp +inline FPSCounter() +``` +--- +#### reset +```cpp +inline void reset() +``` +--- -#### `public bool getDeviceList(Device::Type type,std::vector< `[`av::Device`](#structscy_1_1av_1_1Device)` > & devices)` +#### tick -Base device list. +```cpp +inline void tick() +``` +--- +#### MAX -#### `public virtual int getCapabilities()` +```cpp +const int MAX = 100 +``` -Capabilities. +--- +#### tickIndex +```cpp +int tickIndex +``` -#### `public void setWatcher(`[`DeviceWatcher`](#classscy_1_1av_1_1DeviceWatcher)` * watcher)` +--- +#### prevTick +```cpp +clock_t prevTick +``` +--- +#### tickSum -#### `public `[`DeviceWatcher`](#classscy_1_1av_1_1DeviceWatcher)` * watcher()` +```cpp +clock_t tickSum +``` +--- +#### tickList +```cpp +clock_t tickList +``` +--- -#### `public virtual void print(std::ostream & ost)` +#### fps -Print all devices to the output stream. +```cpp +double fps +``` +--- +#### frames -#### `protected std::unique_ptr< `[`DeviceWatcher`](./doc/api-av.md#classscy_1_1av_1_1DeviceWatcher)` > _watcher` +```cpp +int64_t frames +``` + +## FPSLimiter + +> **Extends:** `scy::PacketProcessor` +> **Defined in:** `fpscounter.h` + +This class limits the throughput rate of IPackets in a [PacketStream](./doc/api-base.md#classscy_1_1PacketStream). If the throughput rate exceeds the max specified FPS then packets will be dropped. +Note that revious processors must not fragment packets otherwise this class will not be accurate, and the packet drop rate will be too high. + +### Members +| Name | Description | +|------|-------------| +| [`FPSLimiter`](#group__av_1ga029c9650c19891d96c7d05b720ada193) | | +| [`process`](#group__av_1ga44d11b0258baa981ef71b9b5647de97d) | This method performs processing on the given packet and emits the result. | +| [`onStreamStateChange`](#group__av_1ga159f48189ca69a2e40d20376335249fb) | Called by the [PacketStream](./doc/api-base.md#classscy_1_1PacketStream) to notify when the internal [Stream](./doc/api-base.md#classscy_1_1Stream) state changes. On receiving the Stopped state, it is the responsibility of the adapter to have ceased all outgoing packet transmission, especially in multi-thread scenarios. | +| [`emitter`](#group__av_1ga59db66b46321468598d83db2a52b5495) | | +| [`_max`](#group__av_1ga939b5b9fd83801ddc2fdea386c4e556d) | | +| [`_videoOnly`](#group__av_1ga1d2f345f16e43261b3432d15157e58d6) | | +| [`_counter`](#group__av_1ga5eb5923a12182c1c97382cf9da35f938) | | +--- +#### FPSLimiter -#### `protected virtual bool getDefaultAudioDevice(bool input,`[`Device`](#structscy_1_1av_1_1Device)` & device)` +```cpp +inline FPSLimiter(int max, bool videoOnly) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `max` | `int` | | +| `videoOnly` | `bool` | | +--- +#### process +```cpp +virtual inline void process(IPacket & packet) +``` -#### `protected virtual bool getAudioDevices(bool input,std::vector< `[`Device`](#structscy_1_1av_1_1Device)` > & devs)` +This method performs processing on the given packet and emits the result. +Note: If packet processing is async (the packet is not in the current thread scope) then packet data must be copied. Copied data can be freed directly aFter the async call to [emit()](./doc/api-base.md#group__base_1ga995248310998c29df87051389f52b58c) the outgoing packet. +| Parameter | Type | Description | +|-----------|------|-------------| +| `packet` | `IPacket &` | | +--- +#### onStreamStateChange -#### `protected virtual bool getAudioDevice(bool input,`[`Device`](#structscy_1_1av_1_1Device)` & out,const std::string & name,int id)` +```cpp +virtual inline void onStreamStateChange(const PacketStreamState &) +``` +Called by the [PacketStream](./doc/api-base.md#classscy_1_1PacketStream) to notify when the internal [Stream](./doc/api-base.md#classscy_1_1Stream) state changes. On receiving the Stopped state, it is the responsibility of the adapter to have ceased all outgoing packet transmission, especially in multi-thread scenarios. +--- +#### emitter +```cpp +PacketSignal emitter +``` -#### `protected virtual bool getAudioDevice(bool input,`[`Device`](#structscy_1_1av_1_1Device)` & out,int id)` +--- +#### _max +```cpp +int _max +``` +--- +#### _videoOnly -#### `protected void setInitialized(bool initialized)` +```cpp +bool _videoOnly +``` +--- +#### _counter +```cpp +legacy::FPSCounter _counter +``` +## ICapture -#### `protected void setWatcher(`[`DeviceWatcher`](#classscy_1_1av_1_1DeviceWatcher)` * watcher)` +> **Extends:** `scy::PacketStreamAdapter`, `scy::basic::Startable` +> **Subclasses:** `scy::av::MediaCapture` +> **Defined in:** `icapture.h` +### Members +| Name | Description | +|------|-------------| +| [`ICapture`](#group__av_1ga3f62aa3503362c5540dc612bce32a0b3) | | +| [`~ICapture`](#group__av_1gac520e48bc641b38e050000b860bb6609) | | +| [`start`](#group__av_1ga001da1b367e05e2a1975dd07e6daab35) | | +| [`stop`](#group__av_1gad0feb65608ad2d11078abb46d5918284) | | +| [`getEncoderFormat`](#group__av_1ga909c7fab8e95be80ed78d8e847658183) | Sets the input format for encoding with this capture device. | +| [`onStreamStateChange`](#group__av_1ga1410d332fa091a13dd52ea799f7040de) | Called by the [PacketStream](./doc/api-base.md#classscy_1_1PacketStream) to notify when the internal [Stream](./doc/api-base.md#classscy_1_1Stream) state changes. On receiving the Stopped state, it is the responsibility of the adapter to have ceased all outgoing packet transmission, especially in multi-thread scenarios. | +| [`emitter`](#group__av_1ga3a2c153ddf81cd8be57efe0a784a2339) | | +--- +#### ICapture -#### `protected `[`DeviceWatcher`](#classscy_1_1av_1_1DeviceWatcher)` * watcher()` +```cpp +inline ICapture() +``` +--- +#### ~ICapture +```cpp +virtual ~ICapture() = default +``` +--- -# class `scy::av::DeviceManagerFactory` +#### start +```cpp +void start() +``` +--- +#### stop +```cpp +void stop() +``` +--- -## Summary +#### getEncoderFormat - Members | Descriptions ---------------------------------|--------------------------------------------- +```cpp +void getEncoderFormat(Format & iformat) +``` -## Members +Sets the input format for encoding with this capture device. -# class `scy::av::DeviceWatcher` +| Parameter | Type | Description | +|-----------|------|-------------| +| `iformat` | `Format &` | | +--- +#### onStreamStateChange +```cpp +virtual inline void onStreamStateChange(const PacketStreamState &) +``` +Called by the [PacketStream](./doc/api-base.md#classscy_1_1PacketStream) to notify when the internal [Stream](./doc/api-base.md#classscy_1_1Stream) state changes. On receiving the Stopped state, it is the responsibility of the adapter to have ceased all outgoing packet transmission, especially in multi-thread scenarios. +--- -## Summary +#### emitter - Members | Descriptions ---------------------------------|--------------------------------------------- -`public inline explicit DeviceWatcher(`[`IDeviceManager`](#classscy_1_1av_1_1IDeviceManager)` *)` | -`public inline virtual ~DeviceWatcher()` | -`public inline virtual bool start()` | -`public inline virtual void stop()` | -`public inline explicit DeviceWatcher(`[`DeviceManager`](#classscy_1_1av_1_1DeviceManager)` *)` | -`public inline virtual ~DeviceWatcher()` | -`public inline virtual bool start()` | -`public inline virtual void stop()` | +```cpp +PacketSignal emitter +``` -## Members +## IEncoder -#### `public inline explicit DeviceWatcher(`[`IDeviceManager`](#classscy_1_1av_1_1IDeviceManager)` *)` +> **Extends:** `scy::Stateful< EncoderState >` +> **Subclasses:** `scy::av::MultiplexEncoder` +> **Defined in:** `iencoder.h` +This is the abstract class for all encoders. +### Members +| Name | Description | +|------|-------------| +| [`Type`](#group__av_1ga0fca7b5900200f462d9cf6a9e2ee316e) | | +| [`init`](#group__av_1ga3017292356e589b3d61adca4383c51a0) | | +| [`uninit`](#group__av_1ga06670aeae682d931c9378d0932fbe26b) | | +| [`options`](#group__av_1gabf392bf61c0d255ef49b358624d3442b) | | +| [`isNone`](#group__av_1ga773da7e63fe6afbdf30ad268ee61e512) | | +| [`isReady`](#group__av_1gae6f19cdf4e3c776bdef058997307f208) | | +| [`isEncoding`](#group__av_1ga2450b61a8a20b293a783bab685424285) | | +| [`isActive`](#group__av_1ga7bc5645b62a07a4249de5fdcfe24c5e9) | | +| [`isStopped`](#group__av_1gaa306a4894a57b67f41cc73b68060da93) | | +| [`isError`](#group__av_1gabf096b994cc26365bdc9f4edcfb1045e) | | +--- -#### `public inline virtual ~DeviceWatcher()` +#### Type +```cpp +enum Type +``` +| Value | Description | +|-------|-------------| +| `None` | huh? | +| `Video` | video only | +| `Audio` | audio only | +| `Multiplex` | both video & audio | +--- +#### init -#### `public inline virtual bool start()` +```cpp +void init() +``` +--- +#### uninit +```cpp +void uninit() +``` +--- -#### `public inline virtual void stop()` +#### options +```cpp +EncoderOptions & options() +``` +--- +#### isNone +```cpp +virtual inline bool isNone() const +``` -#### `public inline explicit DeviceWatcher(`[`DeviceManager`](#classscy_1_1av_1_1DeviceManager)` *)` +--- +#### isReady +```cpp +virtual inline bool isReady() const +``` +--- +#### isEncoding -#### `public inline virtual ~DeviceWatcher()` +```cpp +virtual inline bool isEncoding() const +``` +--- +#### isActive +```cpp +virtual inline bool isActive() const +``` +--- -#### `public inline virtual bool start()` +#### isStopped +```cpp +virtual inline bool isStopped() const +``` +--- +#### isError +```cpp +virtual inline bool isError() const +``` -#### `public inline virtual void stop()` +## MediaCapture + +> **Extends:** `scy::av::ICapture`, `scy::basic::Runnable` +> **Subclasses:** `scy::av::AudioCapture`, `scy::av::VideoCapture` +> **Defined in:** `mediacapture.h` + +This class implements a cross platform audio, video, screen and video file capturer. + +### Members + +| Name | Description | +|------|-------------| +| [`MediaCapture`](#group__av_1gafe3b6e3b9e358dd47a87b15362135f24) | | +| [`~MediaCapture`](#group__av_1ga929846316b65d2377adb4a6affca7659) | | +| [`openFile`](#group__av_1gae8bdf5281fce64d2132c2fd6c88ade0a) | | +| [`close`](#group__av_1ga6a17c4e168d20df0e1357440e1ac9ec7) | | +| [`start`](#group__av_1ga6a92a82d5b340cf9e4ca8369912b46f9) | | +| [`stop`](#group__av_1ga8dae2308cae6bb09ae2537290347d6e2) | | +| [`run`](#group__av_1ga7378e32ee0427263f16f630d20fbd3c2) | The run method will be called by the asynchronous context. | +| [`getEncoderFormat`](#group__av_1ga1fb0cc809168b8a715fd7c4e27be5f83) | Sets the input format for encoding with this capture device. | +| [`getEncoderAudioCodec`](#group__av_1ga466938fb1a24ea4ab3baeab7cc705954) | | +| [`getEncoderVideoCodec`](#group__av_1ga5dc8470b740cfd42b9c60ac939f941fd) | | +| [`setLoopInput`](#group__av_1ga397516f5cd21c7bcc07bb314e52252c9) | Continuously loop the input file when set. | +| [`setLimitFramerate`](#group__av_1gab7f834018d8db0c7f2db902b0be2e1e1) | Limit playback to video FPS. | +| [`setRealtimePTS`](#group__av_1gaf13da9d9e9ac1bc0ff99e8071022d271) | Set to use realtime PTS calculation. This is preferred when sing live captures as FFmpeg provided values are not always reliable. | +| [`formatCtx`](#group__av_1ga53559a0c45deab65991e8ae08786cb93) | | +| [`video`](#group__av_1ga7c2ac780ac1c5f72a40478a2027d4f87) | | +| [`audio`](#group__av_1ga2aa4d7bcc8edab38efada2fe3727c743) | | +| [`stopping`](#group__av_1gae1cc728c49af510b91d021ae45c81262) | | +| [`error`](#group__av_1gaa2b86ac2156b751b325221df2c4478a5) | | +| [`openStream`](#group__av_1ga7eb4a7f7ce3ebf15a2d35bb9381b39d8) | Open the underlying media stream. | +| [`emit`](#group__av_1gad6bbe16edf99985bff5c1dd011e4814a) | | +| [`Closing`](#group__av_1ga91af846c0fa6c00c8374bd451a03b411) | Signals that the capture thread is closing. Careful, this signal is emitted from inside the tread contect. | +| [`_mutex`](#group__av_1gad45e032e1e5b0ab7beca04754f066da9) | | +| [`_thread`](#group__av_1gaaa3bffce55a2cc216cca0e0fba602ea6) | | +| [`_formatCtx`](#group__av_1ga42967c34d29b6cfc7bf1d5fe035a809a) | | +| [`_video`](#group__av_1ga7de4163cf1686424121e60c492403ace) | | +| [`_audio`](#group__av_1gacfd70dc3c73cb0d7597d5d2b3e9003fa) | | +| [`_error`](#group__av_1gac459b88f02baf63fe81c8fb2e8c57bac) | | +| [`_stopping`](#group__av_1gae6b0b5339281a6e31bbc7acc96862e6e) | | +| [`_looping`](#group__av_1ga9235aad492dca034b3c788e5b1a755fe) | | +| [`_realtime`](#group__av_1ga256d90ae10187e4310241397d44bc6e5) | | +| [`_ratelimit`](#group__av_1ga28871c47b4adf3dda87648347661874c) | | + +--- + +#### MediaCapture + +```cpp +MediaCapture() +``` +--- +#### ~MediaCapture +```cpp +virtual ~MediaCapture() +``` +--- -# class `scy::av::FakeDeviceManager` +#### openFile +```cpp +virtual void openFile(const std::string & file) ``` -class scy::av::FakeDeviceManager - : public scy::av::IDeviceManager -``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `file` | `const std::string &` | | +--- +#### close +```cpp +virtual void close() +``` -## Summary +--- - Members | Descriptions ---------------------------------|--------------------------------------------- -`public inline FakeDeviceManager()` | -`public inline virtual bool initialize()` | Initialization. -`public inline virtual void uninitialize()` | -`public inline virtual int getCapabilities()` | Capabilities. -`public inline virtual bool getMicrophones(std::vector< `[`Device`](#structscy_1_1av_1_1Device)` > & devs)` | -`public inline virtual bool getSpeakers(std::vector< `[`Device`](#structscy_1_1av_1_1Device)` > & devs)` | -`public inline virtual bool getMicrophone(const std::string & name,`[`Device`](#structscy_1_1av_1_1Device)` & out)` | -`public inline virtual bool getSpeaker(const std::string & name,`[`Device`](#structscy_1_1av_1_1Device)` & out)` | -`public inline virtual bool getCameras(std::vector< `[`Device`](#structscy_1_1av_1_1Device)` > & devs)` | -`public inline virtual bool getDefaultCamera(`[`Device`](#structscy_1_1av_1_1Device)` & device)` | -`public inline void setMicrophones(const std::vector< `[`Device`](#structscy_1_1av_1_1Device)` > & devices)` | -`public inline void setSpeakers(const std::vector< `[`Device`](#structscy_1_1av_1_1Device)` > & devices)` | -`public inline void setCameras(const std::vector< `[`Device`](#structscy_1_1av_1_1Device)` > & devices)` | -`public inline virtual bool getCamera(const std::string & name,`[`Device`](#structscy_1_1av_1_1Device)` & out)` | -`public inline bool getAudioDevice(bool input,const std::string & name,`[`Device`](#structscy_1_1av_1_1Device)` & out)` | +#### start -## Members +```cpp +virtual void start() +``` -#### `public inline FakeDeviceManager()` +--- +#### stop +```cpp +virtual void stop() +``` +--- +#### run -#### `public inline virtual bool initialize()` +```cpp +virtual void run() +``` -Initialization. +The run method will be called by the asynchronous context. +--- +#### getEncoderFormat -#### `public inline virtual void uninitialize()` +```cpp +virtual void getEncoderFormat(Format & iformat) +``` +Sets the input format for encoding with this capture device. +| Parameter | Type | Description | +|-----------|------|-------------| +| `iformat` | `Format &` | | +--- +#### getEncoderAudioCodec -#### `public inline virtual int getCapabilities()` +```cpp +virtual void getEncoderAudioCodec(AudioCodec & params) +``` -Capabilities. +| Parameter | Type | Description | +|-----------|------|-------------| +| `params` | `AudioCodec &` | | +--- +#### getEncoderVideoCodec -#### `public inline virtual bool getMicrophones(std::vector< `[`Device`](#structscy_1_1av_1_1Device)` > & devs)` +```cpp +virtual void getEncoderVideoCodec(VideoCodec & params) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `params` | `VideoCodec &` | | +--- +#### setLoopInput +```cpp +void setLoopInput(bool flag) +``` -#### `public inline virtual bool getSpeakers(std::vector< `[`Device`](#structscy_1_1av_1_1Device)` > & devs)` +Continuously loop the input file when set. +| Parameter | Type | Description | +|-----------|------|-------------| +| `flag` | `bool` | | +--- +#### setLimitFramerate +```cpp +void setLimitFramerate(bool flag) +``` -#### `public inline virtual bool getMicrophone(const std::string & name,`[`Device`](#structscy_1_1av_1_1Device)` & out)` +Limit playback to video FPS. +| Parameter | Type | Description | +|-----------|------|-------------| +| `flag` | `bool` | | +--- +#### setRealtimePTS +```cpp +void setRealtimePTS(bool flag) +``` -#### `public inline virtual bool getSpeaker(const std::string & name,`[`Device`](#structscy_1_1av_1_1Device)` & out)` +Set to use realtime PTS calculation. This is preferred when sing live captures as FFmpeg provided values are not always reliable. +| Parameter | Type | Description | +|-----------|------|-------------| +| `flag` | `bool` | | +--- +#### formatCtx +```cpp +AVFormatContext * formatCtx() const +``` -#### `public inline virtual bool getCameras(std::vector< `[`Device`](#structscy_1_1av_1_1Device)` > & devs)` +--- +#### video +```cpp +VideoDecoder * video() const +``` +--- +#### audio -#### `public inline virtual bool getDefaultCamera(`[`Device`](#structscy_1_1av_1_1Device)` & device)` +```cpp +AudioDecoder * audio() const +``` +--- +#### stopping +```cpp +bool stopping() const +``` +--- -#### `public inline void setMicrophones(const std::vector< `[`Device`](#structscy_1_1av_1_1Device)` > & devices)` +#### error +```cpp +std::string error() const +``` +--- +#### openStream +```cpp +virtual void openStream(const std::string & filename, const AVInputFormat * inputFormat, AVDictionary ** formatParams) +``` -#### `public inline void setSpeakers(const std::vector< `[`Device`](#structscy_1_1av_1_1Device)` > & devices)` +Open the underlying media stream. +#### Parameters +* `filename` The file path or device name to open. +* `inputFormat` The forced input format, or nullptr for auto-detect. +* `formatParams` Optional format parameters; may be updated by FFmpeg on return. +| Parameter | Type | Description | +|-----------|------|-------------| +| `filename` | `const std::string &` | | +| `inputFormat` | `const AVInputFormat *` | | +| `formatParams` | `AVDictionary **` | | -#### `public inline void setCameras(const std::vector< `[`Device`](#structscy_1_1av_1_1Device)` > & devices)` +--- +#### emit +```cpp +virtual void emit(IPacket & packet) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `packet` | `IPacket &` | | +--- -#### `public inline virtual bool getCamera(const std::string & name,`[`Device`](#structscy_1_1av_1_1Device)` & out)` +#### Closing +```cpp +NullSignal Closing +``` +Signals that the capture thread is closing. Careful, this signal is emitted from inside the tread contect. +--- +#### _mutex -#### `public inline bool getAudioDevice(bool input,const std::string & name,`[`Device`](#structscy_1_1av_1_1Device)` & out)` +```cpp +std::mutex _mutex +``` +--- +#### _thread +```cpp +Thread _thread +``` +--- -# class `scy::av::FLVMetadataInjector` +#### _formatCtx +```cpp +AVFormatContext * _formatCtx ``` -class scy::av::FLVMetadataInjector - : public scy::PacketProcessor -``` +--- +#### _video -This class implements a packetizer which appends correct stream headers and modifies the timestamp of FLV packets so Adobe's Flash Player will play our videos mid-stream. +```cpp +VideoDecoder * _video +``` -This adapter is useful for multicast situations where we don't have the option of restarting the encoder stream. +--- + +#### _audio + +```cpp +AudioDecoder * _audio +``` -## Summary +--- - Members | Descriptions ---------------------------------|--------------------------------------------- -`public `[`PacketSignal`](#group__base_1ga3ffb5bda6133fac97f3bed2b567b9b6a)` emitter` | -`public IPacketizer(this-> emitter)` | -`public _format(format)` | -`public _initial(true)` | -`public _modifyingStream(false)` | -`public _waitingForKeyframe(false)` | -`public inline _timestampOffset(0) const` | -`public inline virtual void onStreamStateChange(const `[`PacketStreamState`](#structscy_1_1PacketStreamState)` & state)` | whenever the stream is restarted. -`public inline virtual void process(`[`IPacket`](#classscy_1_1IPacket)` & packet)` | -`public inline virtual void fastUpdateTimestamp(char * buf,std::uint32_t timestamp)` | -`public inline virtual bool fastIsFLVHeader(char * buf)` | Caution: this method does not check buffer size. -`public inline virtual bool fastIsFLVKeyFrame(char * buf)` | Caution: this method does not check buffer size. -`public inline virtual void writeFLVHeader(`[`BitWriter`](#classscy_1_1BitWriter)` & writer)` | -`public inline std::int64_t doubleToInt(double d)` | -`public inline virtual void writeAMFSring(`[`BitWriter`](#classscy_1_1BitWriter)` & writer,const char * val)` | AMF Helpers. -`public inline virtual void writeAMFDouble(`[`BitWriter`](#classscy_1_1BitWriter)` & writer,double val)` | -`public inline virtual void writeAMFBool(`[`BitWriter`](#classscy_1_1BitWriter)` & writer,bool val)` | -`protected `[`Format`](./doc/api-av.md#structscy_1_1av_1_1Format)` _format` | -`protected bool _initial` | -`protected bool _modifyingStream` | -`protected bool _waitingForKeyframe` | -`protected std::uint32_t _timestampOffset` | -`protected `[`legacy::FPSCounter`](./doc/api-av.md#structscy_1_1av_1_1legacy_1_1FPSCounter)` _fpsCounter` | +#### _error -## Members +```cpp +std::string _error +``` -#### `public `[`PacketSignal`](#group__base_1ga3ffb5bda6133fac97f3bed2b567b9b6a)` emitter` +--- +#### _stopping +```cpp +bool _stopping +``` +--- +#### _looping -#### `public IPacketizer(this-> emitter)` +```cpp +bool _looping +``` +--- +#### _realtime +```cpp +bool _realtime +``` +--- -#### `public _format(format)` +#### _ratelimit +```cpp +bool _ratelimit +``` +## MultiplexEncoder + +> **Extends:** `scy::av::IEncoder` +> **Subclasses:** `scy::av::MultiplexPacketEncoder` +> **Defined in:** `multiplexencoder.h` + +This class implements a multiplex audio and video encoder. + +### Members + +| Name | Description | +|------|-------------| +| [`MultiplexEncoder`](#group__av_1gaf1d51958f4658bb7e9a6c4511511113d) | | +| [`~MultiplexEncoder`](#group__av_1gaa064d2da3d35888df805b8ddc40d81aa) | | +| [`init`](#group__av_1gaf48b2533aa945cd87bd97a0217c6993a) | | +| [`uninit`](#group__av_1gac7855959dca2bf0f4b2bdc7a05bb45e5) | | +| [`cleanup`](#group__av_1ga8185447f1ab599d8365c664a7e435130) | | +| [`createVideo`](#group__av_1ga606f3cddfc03b600609068f380c38ec0) | | +| [`freeVideo`](#group__av_1ga897ed265470ca56689ee14a3555887bc) | | +| [`encodeVideo`](#group__av_1ga5457536d13c0108453bbddc39a2679f2) | Encode a single video frame. All frame values must be set, such as size, pizel format and PTS. | +| [`encodeVideo`](#group__av_1gabe192b9a42278fcc8d411a146020d87b) | Encode a single interleaved video frame. If the frame time is specified it should be the microseconds offset since the start of the input stream. If no time is specified a realtime time value will be assigned to the frame. | +| [`encodeVideo`](#group__av_1gaf497ecc4ab62a57ef70c7e7d02ef7420) | Encode a single planar video frame. | +| [`createAudio`](#group__av_1ga00991a66b30b1b007222ef1c4a696888) | | +| [`freeAudio`](#group__av_1gac4853d19572e00b170f5cc55ac0e8daa) | | +| [`encodeAudio`](#group__av_1gae5bb6f95b38149df123992196244cd2c) | Encode a single interleaved audio frame. | +| [`encodeAudio`](#group__av_1ga3cf8da92ac5941f642ec3b14e0135db7) | Encode a single planar audio frame. | +| [`flush`](#group__av_1gae8f1dfdc41fbf65984ed8b50d238eb29) | Flush and beffered or queued packets. | +| [`options`](#group__av_1ga7f3750b53714ca2098d293c8996a7630) | | +| [`video`](#group__av_1ga85053ffee452ba42df42b3640b816136) | | +| [`audio`](#group__av_1ga8ddbbc27769231a406f91de07a527943) | | +| [`writeOutputPacket`](#group__av_1ga37465535671ab007f75646a7591fdc55) | | +| [`updateStreamPts`](#group__av_1ga95dfd99fecd4cfe2e7b95e72cc298f42) | Convert input microseconds to the stream time base. | +| [`onVideoEncoded`](#group__av_1gab889e4258c74a7f7abf67e7494e7da3f) | | +| [`onAudioEncoded`](#group__av_1gae4cea840999e5b11bff4f7d4f344590a) | | +| [`emitter`](#group__av_1gaf593061a8871958488243581b9c837b3) | | +| [`_options`](#group__av_1ga0f8d38890c1f48b4ebadc58106d41b3b) | | +| [`_formatCtx`](#group__av_1ga3ad98660fb4df5e33fd76c69f5638c16) | | +| [`_video`](#group__av_1gacb2c7d2ffc3ddc017acf99e95e8b9795) | | +| [`_audio`](#group__av_1ga57ee884acf9e4e908263270fc7d74512) | | +| [`_ioCtx`](#group__av_1ga9a948562b539af9cd0fa8a37a3c3a7d7) | | +| [`_ioBuffer`](#group__av_1ga6198a189e2a84da5942e9e901bd060e5) | | +| [`_pts`](#group__av_1ga71b53416c479a726dd69f5843f102979) | | +| [`_mutex`](#group__av_1ga679e4f526d3f6c2cf713f1510bef1537) | | + +--- + +#### MultiplexEncoder + +```cpp +MultiplexEncoder(const EncoderOptions & options) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `options` | `const EncoderOptions &` | | +--- -#### `public _initial(true)` +#### ~MultiplexEncoder +```cpp +virtual ~MultiplexEncoder() +``` +--- +#### init +```cpp +virtual void init() +``` -#### `public _modifyingStream(false)` +--- +#### uninit +```cpp +virtual void uninit() +``` +--- +#### cleanup -#### `public _waitingForKeyframe(false)` +```cpp +virtual void cleanup() +``` +--- +#### createVideo +```cpp +virtual void createVideo() +``` +--- -#### `public inline _timestampOffset(0) const` +#### freeVideo +```cpp +virtual void freeVideo() +``` +--- +#### encodeVideo +```cpp +virtual bool encodeVideo(AVFrame * frame) +``` -#### `public inline virtual void onStreamStateChange(const `[`PacketStreamState`](#structscy_1_1PacketStreamState)` & state)` +Encode a single video frame. All frame values must be set, such as size, pizel format and PTS. -whenever the stream is restarted. +| Parameter | Type | Description | +|-----------|------|-------------| +| `frame` | `AVFrame *` | | -This method is called by the Packet [Stream](#classscy_1_1Stream) +--- -#### `public inline virtual void process(`[`IPacket`](#classscy_1_1IPacket)` & packet)` +#### encodeVideo +```cpp +virtual bool encodeVideo(uint8_t * buffer, int bufferSize, int width, int height, int64_t time) +``` +Encode a single interleaved video frame. If the frame time is specified it should be the microseconds offset since the start of the input stream. If no time is specified a realtime time value will be assigned to the frame. -This method performs processing on the given packet and emits the result. +#### Parameters +* `buffer` The raw video frame buffer. -Note: If packet processing is async (the packet is not in the current thread scope) then packet data must be copied. Copied data can be freed directly aFter the async call to emit() the outgoing packet. +* `bufferSize` The buffer size in bytes. -#### `public inline virtual void fastUpdateTimestamp(char * buf,std::uint32_t timestamp)` +* `width` The frame width in pixels. +* `height` The frame height in pixels. +* `time` The timestamp in microseconds, or AV_NOPTS_VALUE for realtime. -Updates the timestamp in the given FLV tag buffer. No more need to copy data with this method. Caution: this method does not check buffer size. +| Parameter | Type | Description | +|-----------|------|-------------| +| `buffer` | `uint8_t *` | | +| `bufferSize` | `int` | | +| `width` | `int` | | +| `height` | `int` | | +| `time` | `int64_t` | | -#### `public inline virtual bool fastIsFLVHeader(char * buf)` +--- -Caution: this method does not check buffer size. +#### encodeVideo +```cpp +virtual bool encodeVideo(uint8_t * data, int linesize, int width, int height, int64_t time) +``` +Encode a single planar video frame. -#### `public inline virtual bool fastIsFLVKeyFrame(char * buf)` +#### Parameters +* `data` Array of per-plane data pointers (up to 4 planes). -Caution: this method does not check buffer size. +* `linesize` Array of per-plane byte strides. +* `width` The frame width in pixels. +* `height` The frame height in pixels. -#### `public inline virtual void writeFLVHeader(`[`BitWriter`](#classscy_1_1BitWriter)` & writer)` +* `time` The timestamp in microseconds, or AV_NOPTS_VALUE for realtime. +| Parameter | Type | Description | +|-----------|------|-------------| +| `data` | `uint8_t *` | | +| `linesize` | `int` | | +| `width` | `int` | | +| `height` | `int` | | +| `time` | `int64_t` | | +--- +#### createAudio +```cpp +virtual void createAudio() +``` -#### `public inline std::int64_t doubleToInt(double d)` +--- +#### freeAudio +```cpp +virtual void freeAudio() +``` +--- +#### encodeAudio -#### `public inline virtual void writeAMFSring(`[`BitWriter`](#classscy_1_1BitWriter)` & writer,const char * val)` +```cpp +virtual bool encodeAudio(uint8_t * buffer, int numSamples, int64_t time) +``` -AMF Helpers. +Encode a single interleaved audio frame. +#### Parameters +* `buffer` The interleaved audio sample buffer. +* `numSamples` The number of samples per channel. -#### `public inline virtual void writeAMFDouble(`[`BitWriter`](#classscy_1_1BitWriter)` & writer,double val)` +* `time` The timestamp in microseconds, or AV_NOPTS_VALUE for realtime. +| Parameter | Type | Description | +|-----------|------|-------------| +| `buffer` | `uint8_t *` | | +| `numSamples` | `int` | | +| `time` | `int64_t` | | +--- +#### encodeAudio +```cpp +virtual bool encodeAudio(uint8_t * data, int numSamples, int64_t time) +``` + +Encode a single planar audio frame. + +#### Parameters +* `data` Array of per-plane sample buffers (one per channel). + +* `numSamples` The number of samples per channel. -#### `public inline virtual void writeAMFBool(`[`BitWriter`](#classscy_1_1BitWriter)` & writer,bool val)` +* `time` The timestamp in microseconds, or AV_NOPTS_VALUE for realtime. +| Parameter | Type | Description | +|-----------|------|-------------| +| `data` | `uint8_t *` | | +| `numSamples` | `int` | | +| `time` | `int64_t` | | +--- +#### flush +```cpp +virtual void flush() +``` -#### `protected `[`Format`](./doc/api-av.md#structscy_1_1av_1_1Format)` _format` +Flush and beffered or queued packets. +--- +#### options +```cpp +virtual EncoderOptions & options() +``` +--- -#### `protected bool _initial` +#### video +```cpp +VideoEncoder * video() +``` +--- +#### audio +```cpp +AudioEncoder * audio() +``` -#### `protected bool _modifyingStream` +--- +#### writeOutputPacket +```cpp +bool writeOutputPacket(AVPacket & packet) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `packet` | `AVPacket &` | | +--- -#### `protected bool _waitingForKeyframe` +#### updateStreamPts +```cpp +bool updateStreamPts(AVStream * stream, int64_t * pts) +``` +Convert input microseconds to the stream time base. +#### Parameters +* `stream` The target stream for time base conversion. +* `pts` Pointer to the timestamp; converted in place. -#### `protected std::uint32_t _timestampOffset` +| Parameter | Type | Description | +|-----------|------|-------------| +| `stream` | `AVStream *` | | +| `pts` | `int64_t *` | | +--- +#### onVideoEncoded +```cpp +void onVideoEncoded(av::VideoPacket & packet) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `packet` | `av::VideoPacket &` | | -#### `protected `[`legacy::FPSCounter`](./doc/api-av.md#structscy_1_1av_1_1legacy_1_1FPSCounter)` _fpsCounter` +--- +#### onAudioEncoded +```cpp +void onAudioEncoded(av::AudioPacket & packet) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `packet` | `av::AudioPacket &` | | +--- -# class `scy::av::FormatRegistry` +#### emitter +```cpp +PacketSignal emitter +``` +--- +#### _options +```cpp +EncoderOptions _options +``` +--- -## Summary +#### _formatCtx - Members | Descriptions ---------------------------------|--------------------------------------------- -`public FormatRegistry()` | -`public virtual ~FormatRegistry()` | -`public virtual `[`Format`](#structscy_1_1av_1_1Format)` & get(const std::string & name)` | -`public virtual `[`Format`](#structscy_1_1av_1_1Format)` & getByID(const std::string & id)` | -`public virtual `[`Format`](#structscy_1_1av_1_1Format)` & getOrDefault(const std::string & name)` | -`public virtual `[`Format`](#structscy_1_1av_1_1Format)` & getDefault()` | -`public virtual void registerFormat(const `[`Format`](#structscy_1_1av_1_1Format)` & format)` | -`public virtual bool unregisterFormat(const std::string & name)` | -`public virtual void setDefault(const std::string & name)` | Sets the default fallback media format. -`public virtual bool exists(const std::string & name)` | -`public virtual void clear()` | -`public virtual FormatList formats() const` | +```cpp +AVFormatContext * _formatCtx +``` -## Members +--- -#### `public FormatRegistry()` +#### _video +```cpp +VideoEncoder * _video +``` +--- +#### _audio +```cpp +AudioEncoder * _audio +``` -#### `public virtual ~FormatRegistry()` +--- +#### _ioCtx +```cpp +AVIOContext * _ioCtx +``` +--- +#### _ioBuffer -#### `public virtual `[`Format`](#structscy_1_1av_1_1Format)` & get(const std::string & name)` +```cpp +uint8_t * _ioBuffer +``` +--- +#### _pts +```cpp +int64_t _pts +``` +--- -#### `public virtual `[`Format`](#structscy_1_1av_1_1Format)` & getByID(const std::string & id)` +#### _mutex +```cpp +std::mutex _mutex +``` +## MultiplexPacketEncoder +> **Extends:** `scy::av::MultiplexEncoder`, `scy::PacketProcessor` +> **Defined in:** `multiplexpacketencoder.h` +Encodes and multiplexes a realtime video stream form audio / video capture sources. FFmpeg is used for encoding. -#### `public virtual `[`Format`](#structscy_1_1av_1_1Format)` & getOrDefault(const std::string & name)` +### Members +| Name | Description | +|------|-------------| +| [`MultiplexPacketEncoder`](#group__av_1ga7594862654f7c36da468484365d21d35) | | +| [`~MultiplexPacketEncoder`](#group__av_1ga7dbc839717bf8a252752ae80c663da1d) | | +| [`encode`](#group__av_1gacb056692a6756d361fbc5a73df5378d2) | | +| [`encode`](#group__av_1ga7db54ef667441a2c57a91193f7ed1b8a) | | +| [`accepts`](#group__av_1ga27b350c01a4362cfde30ffd884a5e34c) | This method ensures compatibility with the given packet type. Return false to reject the packet. | +| [`process`](#group__av_1ga993f962cb2fa800af7c2902e474196f1) | This method performs processing on the given packet and emits the result. | +| [`onStreamStateChange`](#group__av_1ga8d0ee54bb9b2e3bfff877dcf9aef8b26) | Called by the [PacketStream](./doc/api-base.md#classscy_1_1PacketStream) to notify when the internal [Stream](./doc/api-base.md#classscy_1_1Stream) state changes. On receiving the Stopped state, it is the responsibility of the adapter to have ceased all outgoing packet transmission, especially in multi-thread scenarios. | +| [`_mutex`](#group__av_1ga41b95d96e26fa281735483efd3955956) | | +--- +#### MultiplexPacketEncoder +```cpp +MultiplexPacketEncoder(const EncoderOptions & options) +``` -#### `public virtual `[`Format`](#structscy_1_1av_1_1Format)` & getDefault()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `options` | `const EncoderOptions &` | | +--- +#### ~MultiplexPacketEncoder -If a default has been specified it will be returned, other the format with the highest priority will take precedence. +```cpp +virtual ~MultiplexPacketEncoder() +``` -#### `public virtual void registerFormat(const `[`Format`](#structscy_1_1av_1_1Format)` & format)` +--- +#### encode +```cpp +virtual void encode(VideoPacket & packet) +``` -Registers the given media format overriding existing media formats of the same name. +| Parameter | Type | Description | +|-----------|------|-------------| +| `packet` | `VideoPacket &` | | -#### `public virtual bool unregisterFormat(const std::string & name)` +--- +#### encode +```cpp +virtual void encode(AudioPacket & packet) +``` -Unregisters the media format matching the given name. +| Parameter | Type | Description | +|-----------|------|-------------| +| `packet` | `AudioPacket &` | | -#### `public virtual void setDefault(const std::string & name)` +--- -Sets the default fallback media format. +#### accepts +```cpp +virtual bool accepts(IPacket *) +``` +This method ensures compatibility with the given packet type. Return false to reject the packet. -#### `public virtual bool exists(const std::string & name)` +--- +#### process +```cpp +virtual void process(IPacket & packet) +``` +This method performs processing on the given packet and emits the result. +Note: If packet processing is async (the packet is not in the current thread scope) then packet data must be copied. Copied data can be freed directly aFter the async call to [emit()](./doc/api-base.md#group__base_1ga995248310998c29df87051389f52b58c) the outgoing packet. -#### `public virtual void clear()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `packet` | `IPacket &` | | +--- +#### onStreamStateChange +```cpp +virtual void onStreamStateChange(const PacketStreamState &) +``` +Called by the [PacketStream](./doc/api-base.md#classscy_1_1PacketStream) to notify when the internal [Stream](./doc/api-base.md#classscy_1_1Stream) state changes. On receiving the Stopped state, it is the responsibility of the adapter to have ceased all outgoing packet transmission, especially in multi-thread scenarios. -#### `public virtual FormatList formats() const` +--- +#### _mutex +```cpp +std::mutex _mutex +``` +## RealtimePacketQueue +> **Extends:** `scy::AsyncPacketQueue< PacketT >` +> **Defined in:** `realtimepacketqueue.h` -# class `scy::av::FPSCounter` +This class emits media packets based on their realtime pts value. +### Members -FPS counter based on the simple moving average (SMA) algorithm. +| Name | Description | +|------|-------------| +| [`RealtimePacketQueue`](#group__av_1ga2fb259d001893d803875ed5d0c34ef31) | | +| [`~RealtimePacketQueue`](#group__av_1ga72e0189b06eaa7b0a1d142adfc39b4cd) | | +| [`push`](#group__av_1ga139e6f5a0132f139ad53f478c811cea5) | | +| [`realTime`](#group__av_1gae25eec661e079ffaf5377ceaf5f74619) | | +| [`popNext`](#group__av_1gae94830422713dfb9b8c18e5e4ebdc758) | Pops the next waiting item. | +| [`onStreamStateChange`](#group__av_1gaa323b0bd9935c88d9c5abe9109245a15) | Called by the [PacketStream](./doc/api-base.md#classscy_1_1PacketStream) to notify when the internal [Stream](./doc/api-base.md#classscy_1_1Stream) state changes. On receiving the Stopped state, it is the responsibility of the adapter to have ceased all outgoing packet transmission, especially in multi-thread scenarios. | +| [`_startTime`](#group__av_1gaf638e19a348745002a5c13c26dfea851) | | +--- +#### RealtimePacketQueue -## Summary +```cpp +inline RealtimePacketQueue(int maxSize) +``` - Members | Descriptions ---------------------------------|--------------------------------------------- -`public double fps` | -`public int64_t frames` | -`public inline FPSCounter()` | -`public inline void reset()` | -`public inline void tick()` | +| Parameter | Type | Description | +|-----------|------|-------------| +| `maxSize` | `int` | | -## Members +--- -#### `public double fps` +#### ~RealtimePacketQueue +```cpp +virtual inline ~RealtimePacketQueue() +``` +--- +#### push +```cpp +virtual inline void push(PacketT * item) +``` -#### `public int64_t frames` +| Parameter | Type | Description | +|-----------|------|-------------| +| `item` | `PacketT *` | | +--- +#### realTime +```cpp +inline int64_t realTime() +``` +--- -#### `public inline FPSCounter()` +#### popNext +```cpp +virtual inline PacketT * popNext() +``` +Pops the next waiting item. +--- +#### onStreamStateChange -#### `public inline void reset()` +```cpp +virtual inline void onStreamStateChange(const PacketStreamState &) +``` +Called by the [PacketStream](./doc/api-base.md#classscy_1_1PacketStream) to notify when the internal [Stream](./doc/api-base.md#classscy_1_1Stream) state changes. On receiving the Stopped state, it is the responsibility of the adapter to have ceased all outgoing packet transmission, especially in multi-thread scenarios. +--- +#### _startTime +```cpp +int64_t _startTime +``` -#### `public inline void tick()` +## MediaPacketTimeCompare +> **Defined in:** `realtimepacketqueue.h` +### Members +| Name | Description | +|------|-------------| +| [`operator()`](#group__av_1gaae0732616533ecf4d9869a7751eae614) | | +--- -# class `scy::av::FPSLimiter` +#### operator() +```cpp +inline bool operator()(const MediaPacket * a, const MediaPacket * b) ``` -class scy::av::FPSLimiter - : public scy::PacketProcessor -``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `a` | `const MediaPacket *` | | +| `b` | `const MediaPacket *` | | +## VideoCapture -This class limits the throughput rate of IPackets in a [PacketStream](#classscy_1_1PacketStream). If the throughput rate exceeds the max specified FPS then packets will be dropped. +> **Extends:** `scy::av::MediaCapture` +> **Defined in:** `videocapture.h` -Note that revious processors must not fragment packets otherwise this class will not be accurate, and the packet drop rate will be too high. +This class implements a cross platform audio capturer. -## Summary +### Members - Members | Descriptions ---------------------------------|--------------------------------------------- -`public `[`PacketSignal`](#group__base_1ga3ffb5bda6133fac97f3bed2b567b9b6a)` emitter` | -`public inline FPSLimiter(int max,bool videoOnly)` | -`public inline virtual void process(`[`IPacket`](#classscy_1_1IPacket)` & packet)` | -`public inline virtual void onStreamStateChange(const `[`PacketStreamState`](#structscy_1_1PacketStreamState)` &)` | -`protected int _max` | -`protected bool _videoOnly` | -`protected `[`legacy::FPSCounter`](./doc/api-av.md#structscy_1_1av_1_1legacy_1_1FPSCounter)` _counter` | +| Name | Description | +|------|-------------| +| [`VideoCapture`](#group__av_1ga01e25e9c7ad589b2868861d40b6c2e0e) | | +| [`VideoCapture`](#group__av_1gadffd637bc51d2f530b77250eb68a3007) | | +| [`VideoCapture`](#group__av_1ga9a1818c1388b213e163eee6ec4d9da72) | | +| [`~VideoCapture`](#group__av_1ga2dbd2571544143012cc8927236c3ebdf) | | +| [`openVideo`](#group__av_1ga780a0453f9f44df2f2c56a7451dd9789) | | +| [`openVideo`](#group__av_1ga6e06d59e636d2506dc2c72f36bd6959a) | | -## Members +--- -#### `public `[`PacketSignal`](#group__base_1ga3ffb5bda6133fac97f3bed2b567b9b6a)` emitter` +#### VideoCapture +```cpp +VideoCapture() +``` +--- +#### VideoCapture +```cpp +VideoCapture(const std::string & device, const av::VideoCodec & params) +``` -#### `public inline FPSLimiter(int max,bool videoOnly)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `device` | `const std::string &` | | +| `params` | `const av::VideoCodec &` | | +--- +#### VideoCapture +```cpp +VideoCapture(const std::string & device, int width, int height, double framerate, const std::string & pixelFmt) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `device` | `const std::string &` | | +| `width` | `int` | | +| `height` | `int` | | +| `framerate` | `double` | | +| `pixelFmt` | `const std::string &` | | -#### `public inline virtual void process(`[`IPacket`](#classscy_1_1IPacket)` & packet)` +--- +#### ~VideoCapture +```cpp +virtual ~VideoCapture() +``` -This method performs processing on the given packet and emits the result. +--- -Note: If packet processing is async (the packet is not in the current thread scope) then packet data must be copied. Copied data can be freed directly aFter the async call to emit() the outgoing packet. +#### openVideo -#### `public inline virtual void onStreamStateChange(const `[`PacketStreamState`](#structscy_1_1PacketStreamState)` &)` +```cpp +virtual void openVideo(const std::string & device, const av::VideoCodec & params) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `device` | `const std::string &` | | +| `params` | `const av::VideoCodec &` | | +--- -Called by the [PacketStream](#classscy_1_1PacketStream) to notify when the internal [Stream](#classscy_1_1Stream) state changes. On receiving the Stopped state, it is the responsibility of the adapter to have ceased all outgoing packet transmission, especially in multi-thread scenarios. +#### openVideo -#### `protected int _max` +```cpp +virtual void openVideo(const std::string & device, int width, int height, double framerate, const std::string & pixelFmt) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `device` | `const std::string &` | | +| `width` | `int` | | +| `height` | `int` | | +| `framerate` | `double` | | +| `pixelFmt` | `const std::string &` | | +## Device +> **Defined in:** `devicemanager.h` +Represents a system audio, video or render device. -#### `protected bool _videoOnly` +### Members + +| Name | Description | +|------|-------------| +| [`Type`](#group__av_1gab88aea620eee238d583c96974d871c15) | | +| [`Device`](#group__av_1ga53ea1e4acdb14bfacf39b439fbee83fb) | | +| [`Device`](#group__av_1ga31dad4b6f0da95ac54d49666db8f8377) | | +| [`print`](#group__av_1ga212e9032eac9a85662e69714b9a2d349) | | +| [`operator==`](#group__av_1ga686faeba93e2f49350e5d317dab86a2c) | | +| [`Device`](#group__av_1ga69f2c24d58a00f3d4f69bc468d8ad721) | | +| [`type`](#group__av_1ga0844c85f6319f6213ea026ca35732e1f) | | +| [`id`](#group__av_1gab7545dfaea8360e3bd2c071e5906e82e) | | +| [`name`](#group__av_1ga2aa878bff3aa5e36fc6f904eb36d9ddd) | | +| [`guid`](#group__av_1ga000efaabb0352c7d86870e649e2131c8) | | +| [`isDefault`](#group__av_1gabf1ce9150645f511dd0b78dfbcc83522) | | +| [`isAvailable`](#group__av_1ga1e1cd71321a4a5bf06474398eb14a39f) | | +| [`type`](#group__av_1ga5895253619f5d138ac222469a70b81cb) | | +| [`id`](#group__av_1gac2a5481204b6eb660c3116fae797de7a) | | +| [`Device`](#structscy_1_1av_1_1Device_1ga53ea1e4acdb14bfacf39b439fbee83fb) | | +| [`print`](#structscy_1_1av_1_1Device_1ga212e9032eac9a85662e69714b9a2d349) | | +| [`operator==`](#structscy_1_1av_1_1Device_1ga686faeba93e2f49350e5d317dab86a2c) | | + +--- + +#### Type + +```cpp +enum Type +``` +| Value | Description | +|-------|-------------| +| `Unknown` | | +| `VideoInput` | | +| `VideoOutput` | | +| `AudioInput` | | +| `AudioOutput` | | +--- +#### Device +```cpp +Device() +``` -#### `protected `[`legacy::FPSCounter`](./doc/api-av.md#structscy_1_1av_1_1legacy_1_1FPSCounter)` _counter` +--- +#### Device +```cpp +Device(const std::string & type, int id, const std::string & name, const std::string & guid, bool isDefault, bool isAvailable) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `type` | `const std::string &` | | +| `id` | `int` | | +| `name` | `const std::string &` | | +| `guid` | `const std::string &` | | +| `isDefault` | `bool` | | +| `isAvailable` | `bool` | | +--- -# class `scy::av::ICapture` +#### print +```cpp +void print(std::ostream & os) ``` -class scy::av::ICapture - : public scy::PacketStreamAdapter - : public scy::basic::Startable -``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `os` | `std::ostream &` | | +--- +#### operator== +```cpp +inline bool operator==(const Device & that) const +``` -## Summary +| Parameter | Type | Description | +|-----------|------|-------------| +| `that` | `const Device &` | | - Members | Descriptions ---------------------------------|--------------------------------------------- -`public `[`PacketSignal`](#group__base_1ga3ffb5bda6133fac97f3bed2b567b9b6a)` emitter` | -`public inline ICapture()` | -`public inline virtual ~ICapture()` | -`public void start()` | -`public void stop()` | -`public void getEncoderFormat(`[`Format`](#structscy_1_1av_1_1Format)` & iformat)` | Sets the input format for encoding with this capture device. -`public inline virtual void onStreamStateChange(const `[`PacketStreamState`](#structscy_1_1PacketStreamState)` &)` | +--- -## Members +#### Device -#### `public `[`PacketSignal`](#group__base_1ga3ffb5bda6133fac97f3bed2b567b9b6a)` emitter` +```cpp +Device(Type type, const std::string & id, const std::string & name, bool isDefault) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `type` | `Type` | | +| `id` | `const std::string &` | | +| `name` | `const std::string &` | | +| `isDefault` | `bool` | | +--- +#### type +```cpp +std::string type +``` -#### `public inline ICapture()` +--- +#### id +```cpp +int id +``` +--- +#### name -#### `public inline virtual ~ICapture()` +```cpp +std::string name +``` +--- +#### guid +```cpp +std::string guid +``` +--- -#### `public void start()` +#### isDefault +```cpp +bool isDefault +``` +--- +#### isAvailable +```cpp +bool isAvailable +``` -#### `public void stop()` +--- +#### type +```cpp +Type type +``` +--- +#### id -#### `public void getEncoderFormat(`[`Format`](#structscy_1_1av_1_1Format)` & iformat)` +```cpp +std::string id +``` -Sets the input format for encoding with this capture device. +--- +#### Device +```cpp +Device() +``` -#### `public inline virtual void onStreamStateChange(const `[`PacketStreamState`](#structscy_1_1PacketStreamState)` &)` +--- +#### print +```cpp +void print(std::ostream & os) +``` -Called by the [PacketStream](#classscy_1_1PacketStream) to notify when the internal [Stream](#classscy_1_1Stream) state changes. On receiving the Stopped state, it is the responsibility of the adapter to have ceased all outgoing packet transmission, especially in multi-thread scenarios. +| Parameter | Type | Description | +|-----------|------|-------------| +| `os` | `std::ostream &` | | -# class `scy::av::IDeviceManager` +--- +#### operator== +```cpp +inline bool operator==(const [Device](#structscy_1_1av_1_1Device) & that) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `that` | `const [Device](#structscy_1_1av_1_1Device) &` | | -A platform independent interface to enumerate audio and video devices on the system. +## Options -## Summary +> **Defined in:** `videoanalyzer.h` - Members | Descriptions ---------------------------------|--------------------------------------------- -`public `[`Signal`](#classscy_1_1Signal)< void(bool &, bool &)`> DevicesChanged` | -`public inline virtual ~IDeviceManager()` | -`public bool initialize()` | Initialization. -`public void uninitialize()` | -`public bool getAudioInputDevices(std::vector< `[`Device`](#structscy_1_1av_1_1Device)` > & devices)` | [Device](./doc/api-av.md#structscy_1_1av_1_1Device) enumeration. -`public bool getAudioOutputDevices(std::vector< `[`Device`](#structscy_1_1av_1_1Device)` > & devices)` | -`public bool getAudioInputDevice(`[`Device`](#structscy_1_1av_1_1Device)` & out,const std::string & name,int id)` | -`public bool getAudioInputDevice(`[`Device`](#structscy_1_1av_1_1Device)` & out,int id)` | -`public bool getAudioOutputDevice(`[`Device`](#structscy_1_1av_1_1Device)` & out,const std::string & name,int id)` | -`public bool getAudioOutputDevice(`[`Device`](#structscy_1_1av_1_1Device)` & out,int id)` | -`public bool getVideoCaptureDevices(std::vector< `[`Device`](#structscy_1_1av_1_1Device)` > & devs)` | -`public bool getVideoCaptureDevice(`[`Device`](#structscy_1_1av_1_1Device)` & out,int id)` | -`public bool getVideoCaptureDevice(`[`Device`](#structscy_1_1av_1_1Device)` & out,const std::string & name,int id)` | -`public bool getDefaultAudioInputDevice(`[`Device`](#structscy_1_1av_1_1Device)` & device)` | -`public bool getDefaultAudioOutputDevice(`[`Device`](#structscy_1_1av_1_1Device)` & device)` | -`public bool getDefaultVideoCaptureDevice(`[`Device`](#structscy_1_1av_1_1Device)` & device)` | -`public int getCapabilities()` | Capabilities. -`public void print(std::ostream & ost)` | +### Members -## Members +| Name | Description | +|------|-------------| +| [`Options`](#group__av_1ga0610fd6f6ea8ccc982764e198c4191df) | | +| [`ifile`](#group__av_1ga0588f37bc4a07997c5b52aad94488177) | | +| [`rdftSize`](#group__av_1ga3930c2df8a401e1b6a6cb65d824a1f37) | | -#### `public `[`Signal`](#classscy_1_1Signal)< void(bool &, bool &)`> DevicesChanged` +--- +#### Options +```cpp +inline Options() +``` -Signals on DevicesChanged. Arg 1 is true when device is video, false for audio Arg 2 is true when device connects, flase on disconnection +--- -#### `public inline virtual ~IDeviceManager()` +#### ifile +```cpp +std::string ifile +``` +--- +#### rdftSize +```cpp +int rdftSize +``` -#### `public bool initialize()` +## Stream -Initialization. +> **Defined in:** `videoanalyzer.h` +### Members +| Name | Description | +|------|-------------| +| [`Stream`](#group__av_1ga4b11e34ec10c49f9dcdf30a25b2bd5d2) | | +| [`~Stream`](#group__av_1ga523d33f3555c415b63ca428744f814c7) | | +| [`initialize`](#group__av_1gad2da7bdf2d9164a40e83b4cc0acc7a82) | | +| [`uninitialize`](#group__av_1gac92af80fd4eb8ff92e4bab9608c29dc3) | | +| [`fft`](#group__av_1ga67a9547ab771c61d603086a5dd922b0f) | | +| [`name`](#group__av_1ga0273e4f2e768d0daa30719dcf97a9a66) | | +| [`rdft`](#group__av_1ga1c501d438007311a16dfb1d93572f540) | | +| [`rdftData`](#group__av_1ga39711bf7e95a4b07f43c3934643fa930) | | +| [`rdftSize`](#group__av_1gacca84a21ae498fcb9035ad6cb33b9f2b) | | +| [`rdftBits`](#group__av_1ga2979c4b96e03f235536ea6ee7b8a230c) | | +| [`frames`](#group__av_1ga96a21cba5b0e1fbb07eb3dc4236f414f) | | +| [`filled`](#group__av_1gace58db739f0c0dcc61db800cafa2e45e) | | -#### `public void uninitialize()` +--- +#### Stream +```cpp +Stream(const std::string & name, int rdftSize) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | +| `rdftSize` | `int` | | +--- -#### `public bool getAudioInputDevices(std::vector< `[`Device`](#structscy_1_1av_1_1Device)` > & devices)` +#### ~Stream -[Device](#structscy_1_1av_1_1Device) enumeration. +```cpp +~Stream() +``` +--- +#### initialize -#### `public bool getAudioOutputDevices(std::vector< `[`Device`](#structscy_1_1av_1_1Device)` > & devices)` +```cpp +void initialize() +``` +--- +#### uninitialize +```cpp +void uninitialize() +``` +--- -#### `public bool getAudioInputDevice(`[`Device`](#structscy_1_1av_1_1Device)` & out,const std::string & name,int id)` +#### fft +```cpp +void fft() +``` +--- +#### name +```cpp +std::string name +``` -#### `public bool getAudioInputDevice(`[`Device`](#structscy_1_1av_1_1Device)` & out,int id)` +--- +#### rdft +```cpp +RDFTContext * rdft +``` +--- +#### rdftData -#### `public bool getAudioOutputDevice(`[`Device`](#structscy_1_1av_1_1Device)` & out,const std::string & name,int id)` +```cpp +FFTSample * rdftData +``` +--- +#### rdftSize +```cpp +int rdftSize +``` +--- -#### `public bool getAudioOutputDevice(`[`Device`](#structscy_1_1av_1_1Device)` & out,int id)` +#### rdftBits +```cpp +int rdftBits +``` +--- +#### frames +```cpp +std::int64_t frames +``` -#### `public bool getVideoCaptureDevices(std::vector< `[`Device`](#structscy_1_1av_1_1Device)` > & devs)` +--- +#### filled +```cpp +int filled +``` +## Packet +> **Defined in:** `videoanalyzer.h` -#### `public bool getVideoCaptureDevice(`[`Device`](#structscy_1_1av_1_1Device)` & out,int id)` +### Members +| Name | Description | +|------|-------------| +| [`Packet`](#group__av_1gad1482a53678eb45b010543da58fd75d3) | | +| [`time`](#group__av_1gaf5901e114c3cc04e690f91d4fb7b0b6b) | | +| [`value`](#group__av_1ga35702a4a9df499a661bdf48c5f0a8921) | | +--- +#### Packet +```cpp +Packet(double time, double value) +``` -#### `public bool getVideoCaptureDevice(`[`Device`](#structscy_1_1av_1_1Device)` & out,const std::string & name,int id)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `time` | `double` | | +| `value` | `double` | | +--- +#### time +```cpp +double time +``` +--- -#### `public bool getDefaultAudioInputDevice(`[`Device`](#structscy_1_1av_1_1Device)` & device)` +#### value +```cpp +double value +``` +## AudioBuffer +> **Defined in:** `audiobuffer.h` +### Members -#### `public bool getDefaultAudioOutputDevice(`[`Device`](#structscy_1_1av_1_1Device)` & device)` +| Name | Description | +|------|-------------| +| [`AudioBuffer`](#group__av_1ga54e24e704368e437595732ec4d787b66) | | +| [`~AudioBuffer`](#group__av_1ga183f5848e3216a98acbc8f98b1d75c5b) | | +| [`alloc`](#group__av_1ga50782855bc3552a230530af683a5b1d1) | Allocate the audio FIFO buffer. | +| [`reset`](#group__av_1ga2c58be0d24a1523ba648932a75bb7ae4) | | +| [`close`](#group__av_1ga3d5266c893d39885a4d2cbdf6ba5f3e2) | | +| [`write`](#group__av_1gacf729dae184fbf799a2d87aabea490f5) | Write samples into the FIFO buffer. | +| [`read`](#group__av_1ga3aa2daaba75aae7d54585d6fad29b8f4) | Read samples from the FIFO buffer. | +| [`available`](#group__av_1ga84628a7fca7c64327f9d3fcf52467954) | | +| [`fifo`](#group__av_1gae438b0740faf59aff51b83e8e140a026) | | +--- +#### AudioBuffer +```cpp +AudioBuffer() +``` +--- -#### `public bool getDefaultVideoCaptureDevice(`[`Device`](#structscy_1_1av_1_1Device)` & device)` +#### ~AudioBuffer +```cpp +~AudioBuffer() +``` +--- +#### alloc +```cpp +void alloc(const std::string & sampleFmt, int channels, int numSamples) +``` -#### `public int getCapabilities()` +Allocate the audio FIFO buffer. -Capabilities. +#### Parameters +* `sampleFmt` The sample format name (e.g. "s16", "fltp"). +* `channels` The number of audio channels. +* `numSamples` The initial buffer capacity in samples per channel. -#### `public void print(std::ostream & ost)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `sampleFmt` | `const std::string &` | | +| `channels` | `int` | | +| `numSamples` | `int` | | +--- +#### reset +```cpp +void reset() +``` +--- -# class `scy::av::IEncoder` +#### close +```cpp +void close() ``` -class scy::av::IEncoder - : public scy::Stateful< EncoderState > -``` -This is the abstract class for all encoders. +--- + +#### write + +```cpp +void write(void ** samples, int numSamples) +``` +Write samples into the FIFO buffer. +#### Parameters +* `samples` Array of per-channel sample buffers. -## Summary +* `numSamples` The number of samples per channel to write. - Members | Descriptions ---------------------------------|--------------------------------------------- -`public void init()` | -`public void uninit()` | -`public `[`EncoderOptions`](#structscy_1_1av_1_1EncoderOptions)` & options()` | -`public inline virtual bool isNone() const` | -`public inline virtual bool isReady() const` | -`public inline virtual bool isEncoding() const` | -`public inline virtual bool isActive() const` | -`public inline virtual bool isStopped() const` | -`public inline virtual bool isError() const` | +| Parameter | Type | Description | +|-----------|------|-------------| +| `samples` | `void **` | | +| `numSamples` | `int` | | -## Members +--- -#### `public void init()` +#### read +```cpp +bool read(void ** samples, int numSamples) +``` +Read samples from the FIFO buffer. +#### Parameters +* `samples` Array of per-channel sample buffers to fill. +* `numSamples` The number of samples per channel to read. -#### `public void uninit()` +#### Returns +True if enough samples were available. +| Parameter | Type | Description | +|-----------|------|-------------| +| `samples` | `void **` | | +| `numSamples` | `int` | | +--- +#### available +```cpp +int available() const +``` -#### `public `[`EncoderOptions`](#structscy_1_1av_1_1EncoderOptions)` & options()` +--- +#### fifo +```cpp +AVAudioFifo * fifo +``` +## AudioContext + +> **Subclasses:** `scy::av::AudioDecoder`, `scy::av::AudioEncoder` +> **Defined in:** `audiocontext.h` + +### Members + +| Name | Description | +|------|-------------| +| [`AudioContext`](#group__av_1gae8e7d079f730e9b536bd874b835aa185) | | +| [`~AudioContext`](#group__av_1ga1a8c4d6264230eeebb4c700c673f06c5) | | +| [`create`](#group__av_1ga0fb23e6630fb7fbc72d2052f41f893c9) | Initialize the `AVCodecContext` with default values. | +| [`open`](#group__av_1gae6b206d9ba8c7fac839c061a2c014e92) | Open the AVCodecContext. | +| [`close`](#group__av_1gaef855c8fd3ca00b2ca309383106d86f4) | Close the AVCodecContext. | +| [`recreateResampler`](#group__av_1ga5c013628754b96eca69d6f018af884d7) | Create the audio resampling context. | +| [`emitter`](#group__av_1ga053c8542ccd8bf42d37203d910f849ca) | | +| [`iparams`](#group__av_1ga066bc978752208f55e97f8df22af7cbf) | input parameters | +| [`oparams`](#group__av_1ga6768d9c0ddfdd36aecabeeb9ac16bba4) | output parameters | +| [`stream`](#group__av_1ga581e1f8ee20e84030fcc4386ccee52f9) | encoder or decoder stream | +| [`ctx`](#group__av_1gaebaea3fe2880fc7532291d9a3b6973a5) | encoder or decoder context | +| [`codec`](#group__av_1ga678094612d9636c92a5eed82ee8eeed3) | encoder or decoder codec | +| [`frame`](#group__av_1ga3fbc59cc52dd1afe38fa668ce744fed3) | last encoded or decoded frame | +| [`resampler`](#group__av_1ga86e526926949fc6c714e3a497a4fd146) | audio resampler | +| [`outputFrameSize`](#group__av_1ga159d8eedc606078055df3d368157f048) | encoder or decoder output frame size | +| [`time`](#group__av_1gaf1201cde2d8461b486a7b7684e4e923f) | stream time in codec time base | +| [`pts`](#group__av_1gacc84d8066a6154bdfb5883fa7c13e0f6) | last packet pts value | +| [`seconds`](#group__av_1gacd28170140313e31de9d73129b5f8d54) | audio time in seconds | +| [`error`](#group__av_1ga9c0b887f963fb41bb91620ca2dcf9a0f) | error message | + +--- + +#### AudioContext + +```cpp +AudioContext() +``` +--- -#### `public inline virtual bool isNone() const` +#### ~AudioContext +```cpp +virtual ~AudioContext() +``` +--- +#### create +```cpp +void create() +``` -#### `public inline virtual bool isReady() const` +Initialize the `AVCodecContext` with default values. +--- +#### open +```cpp +virtual void open() +``` +Open the AVCodecContext. -#### `public inline virtual bool isEncoding() const` +--- +#### close +```cpp +virtual void close() +``` +Close the AVCodecContext. +--- -#### `public inline virtual bool isActive() const` +#### recreateResampler +```cpp +virtual bool recreateResampler() +``` +Create the audio resampling context. +--- +#### emitter -#### `public inline virtual bool isStopped() const` +```cpp +PacketSignal emitter +``` +--- +#### iparams +```cpp +AudioCodec iparams +``` +input parameters -#### `public inline virtual bool isError() const` +--- +#### oparams +```cpp +AudioCodec oparams +``` +output parameters +--- -# class `scy::av::LinuxDeviceManager` +#### stream +```cpp +AVStream * stream ``` -class scy::av::LinuxDeviceManager - : public scy::av::DeviceManager -``` +encoder or decoder stream +--- +#### ctx +```cpp +AVCodecContext * ctx +``` -## Summary +encoder or decoder context - Members | Descriptions ---------------------------------|--------------------------------------------- -`public LinuxDeviceManager()` | -`public virtual ~LinuxDeviceManager()` | -`public virtual bool getCameras(std::vector< `[`Device`](#structscy_1_1av_1_1Device)` > & devs)` | +--- -## Members +#### codec -#### `public LinuxDeviceManager()` +```cpp +const AVCodec * codec +``` +encoder or decoder codec +--- +#### frame +```cpp +AVFrame * frame +``` -#### `public virtual ~LinuxDeviceManager()` +last encoded or decoded frame +--- +#### resampler +```cpp +std::unique_ptr< AudioResampler > resampler +``` +audio resampler -#### `public virtual bool getCameras(std::vector< `[`Device`](#structscy_1_1av_1_1Device)` > & devs)` +--- +#### outputFrameSize +```cpp +int outputFrameSize +``` +encoder or decoder output frame size +--- -# class `scy::av::MacDeviceManager` +#### time +```cpp +int64_t time ``` -class scy::av::MacDeviceManager - : public scy::av::DeviceManager -``` +stream time in codec time base +--- +#### pts +```cpp +int64_t pts +``` -## Summary +last packet pts value - Members | Descriptions ---------------------------------|--------------------------------------------- -`public MacDeviceManager()` | -`public virtual ~MacDeviceManager()` | -`public virtual bool getCameras(std::vector< `[`Device`](#structscy_1_1av_1_1Device)` > & devs)` | +--- -## Members +#### seconds -#### `public MacDeviceManager()` +```cpp +double seconds +``` +audio time in seconds +--- +#### error +```cpp +std::string error +``` -#### `public virtual ~MacDeviceManager()` +error message +## AudioDecoder +> **Extends:** `scy::av::AudioContext` +> **Defined in:** `audiodecoder.h` +### Members +| Name | Description | +|------|-------------| +| [`AudioDecoder`](#group__av_1ga7ee29a239fffcde30f03ae74f409a941) | | +| [`~AudioDecoder`](#group__av_1gacf2b2e8976e564ad308cf5fa291bd4ca) | | +| [`create`](#group__av_1gac8d6012d59e2fdca98d88299ded32c0b) | Initialize the `AVCodecContext` with default values. | +| [`close`](#group__av_1gaf48be78d1c755a5b01240a604bb7c845) | Close the AVCodecContext. | +| [`decode`](#group__av_1ga1efd688cf09b41b183e18dd7c43e31ea) | Decodes a the given input packet. Returns true an output packet was created, false otherwise. | +| [`flush`](#group__av_1ga890c75160dd7216e8b531fec26fb9c1b) | Flushes buffered frames. This method should be called once after decoding. | -#### `public virtual bool getCameras(std::vector< `[`Device`](#structscy_1_1av_1_1Device)` > & devs)` +--- +#### AudioDecoder +```cpp +AudioDecoder(AVStream * stream) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `stream` | `AVStream *` | | +--- -# class `scy::av::MacDeviceWatcher` +#### ~AudioDecoder +```cpp +virtual ~AudioDecoder() ``` -class scy::av::MacDeviceWatcher - : public scy::av::DeviceWatcher -``` - +--- +#### create +```cpp +virtual void create() +``` -## Summary +Initialize the `AVCodecContext` with default values. - Members | Descriptions ---------------------------------|--------------------------------------------- -`public explicit MacDeviceWatcher(`[`IDeviceManager`](#classscy_1_1av_1_1IDeviceManager)` * dm)` | -`public virtual ~MacDeviceWatcher()` | -`public virtual bool start()` | -`public virtual void stop()` | +--- -## Members +#### close -#### `public explicit MacDeviceWatcher(`[`IDeviceManager`](#classscy_1_1av_1_1IDeviceManager)` * dm)` +```cpp +virtual void close() +``` +Close the AVCodecContext. +--- +#### decode +```cpp +virtual bool decode(AVPacket & ipacket) +``` -#### `public virtual ~MacDeviceWatcher()` +Decodes a the given input packet. Returns true an output packet was created, false otherwise. +| Parameter | Type | Description | +|-----------|------|-------------| +| `ipacket` | `AVPacket &` | | +--- +#### flush +```cpp +virtual void flush() +``` -#### `public virtual bool start()` +Flushes buffered frames. This method should be called once after decoding. +## AudioEncoder +> **Extends:** `scy::av::AudioContext` +> **Defined in:** `audioencoder.h` +### Members +| Name | Description | +|------|-------------| +| [`AudioEncoder`](#group__av_1ga02819ded2a5745e255cc84b72abc8117) | | +| [`~AudioEncoder`](#group__av_1ga11cee62e83aa74840d58b098cea1d8fd) | | +| [`create`](#group__av_1ga2fc0a6bfdf50c6a244eb81e755c4ca98) | Initialize the `AVCodecContext` with default values. | +| [`close`](#group__av_1ga5bf457ec1389fb3f57f617fce3b70062) | Close the AVCodecContext. | +| [`encode`](#group__av_1ga2764e5766d3983744099fd244f119fdb) | Encode interleaved audio samples. | +| [`encode`](#group__av_1ga4d3190bfcc040c5ce01074b09ec3627b) | Encode planar audio samples. | +| [`encode`](#group__av_1ga1876deb14c7a94731f0482b707b1b652) | Encode a single AVFrame from the decoder. | +| [`flush`](#group__av_1gaa24448659b5df37e3f096660e4853164) | Flush remaining packets to be encoded. This method should be called once before stream closure. | +| [`fifo`](#group__av_1gaf230c718da64fb580621c0ff7f4ae69c) | | +| [`format`](#group__av_1ga5401890103e86f78a2b37e428d63a1bd) | | -#### `public virtual void stop()` +--- +#### AudioEncoder +```cpp +AudioEncoder(AVFormatContext * format) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `format` | `AVFormatContext *` | | +--- -# class `scy::av::RealtimePacketQueue` +#### ~AudioEncoder +```cpp +virtual ~AudioEncoder() ``` -class scy::av::RealtimePacketQueue - : public scy::AsyncPacketQueue< PacketT > -``` -This class emits media packets based on their realtime pts value. +--- + +#### create +```cpp +virtual void create() +``` +Initialize the `AVCodecContext` with default values. -## Summary +--- - Members | Descriptions ---------------------------------|--------------------------------------------- -`public inline RealtimePacketQueue(int maxSize)` | -`public inline virtual ~RealtimePacketQueue()` | -`public inline virtual void push(PacketT * item)` | -`public inline int64_t realTime()` | -`protected int64_t _startTime` | -`protected inline virtual PacketT * popNext()` | Pops the next waiting item. -`protected inline virtual void onStreamStateChange(const `[`PacketStreamState`](#structscy_1_1PacketStreamState)` &)` | +#### close -## Members +```cpp +virtual void close() +``` -#### `public inline RealtimePacketQueue(int maxSize)` +Close the AVCodecContext. +--- +#### encode +```cpp +virtual bool encode(uint8_t * samples, const int numSamples, const int64_t pts) +``` +Encode interleaved audio samples. -#### `public inline virtual ~RealtimePacketQueue()` +#### Parameters +* `samples` The input samples to encode. +* `numSamples` The number of input samples per channel. +* `pts` The input samples presentation timestamp. +* `opacket` The output packet data will be encoded to. +| Parameter | Type | Description | +|-----------|------|-------------| +| `samples` | `uint8_t *` | | +| `numSamples` | `const int` | | +| `pts` | `const int64_t` | | -#### `public inline virtual void push(PacketT * item)` +--- +#### encode +```cpp +virtual bool encode(uint8_t * samples, const int numSamples, const int64_t pts) +``` -Push an item onto the queue. The queue takes ownership of the item pointer. +Encode planar audio samples. -#### `public inline int64_t realTime()` +#### Parameters +* `samples` The input samples to encode. +* `numSamples` The number of input samples per channel. +* `pts` The input samples presentation timestamp. +* `opacket` The output packet data will be encoded to. +| Parameter | Type | Description | +|-----------|------|-------------| +| `samples` | `uint8_t *` | | +| `numSamples` | `const int` | | +| `pts` | `const int64_t` | | -#### `protected int64_t _startTime` +--- +#### encode +```cpp +virtual bool encode(AVFrame * iframe) +``` +Encode a single AVFrame from the decoder. +| Parameter | Type | Description | +|-----------|------|-------------| +| `iframe` | `AVFrame *` | | -#### `protected inline virtual PacketT * popNext()` +--- -Pops the next waiting item. +#### flush +```cpp +virtual void flush() +``` +Flush remaining packets to be encoded. This method should be called once before stream closure. -#### `protected inline virtual void onStreamStateChange(const `[`PacketStreamState`](#structscy_1_1PacketStreamState)` &)` +--- +#### fifo +```cpp +av::AudioBuffer fifo +``` -Called by the [PacketStream](#classscy_1_1PacketStream) to notify when the internal [Stream](#classscy_1_1Stream) state changes. On receiving the Stopped state, it is the responsibility of the adapter to have ceased all outgoing packet transmission, especially in multi-thread scenarios. +--- -# struct `scy::av::AudioCodec` +#### format +```cpp +AVFormatContext * format ``` -struct scy::av::AudioCodec - : public scy::av::Codec -``` +## AudioResampler +> **Defined in:** `audioresampler.h` +### Members +| Name | Description | +|------|-------------| +| [`AudioResampler`](#group__av_1gac1e2b031ed1c126010aa3c0ce96f4a59) | | +| [`~AudioResampler`](#group__av_1ga838aa389dcc162d2d61aa595f61568c9) | | +| [`open`](#group__av_1ga4ab47b82613b5d7d47a3880b350b1b5d) | | +| [`close`](#group__av_1ga01bbe4d56a06dbfaaf11de4647b8bd81) | | +| [`resample`](#group__av_1ga1756cc112e2502191d9c20a54273d9c5) | Convert the input samples to the output format. NOTE: Input buffers must be contiguous, therefore only interleaved input formats are accepted at this point. | +| [`ctx`](#group__av_1ga65a5c08ebb05b0790edc9c953298a4be) | the conversion context | +| [`iparams`](#group__av_1ga1222d77faf8e8d8f234bba69cf9fb9ad) | input audio parameters | +| [`oparams`](#group__av_1ga464b81f63fad692ecdfd72fb5c84c56c) | output audio parameters | +| [`outSamples`](#group__av_1ga67e76d39e36500f28b1d20753cbee2f0) | the output samples buffer | +| [`outNumSamples`](#group__av_1ga1fc4193f2a49fa6b33319f371015bffc) | the number of samples currently in the output buffer | +| [`outBufferSize`](#group__av_1gadcdf08a8cd007d67f271b924cf5dec98) | the number of bytes currently in the buffer | +| [`maxNumSamples`](#group__av_1ga47217cebf4e6262730fa223066a3a472) | the maximum number of samples that can be stored in | +| [`inSampleFmt`](#group__av_1gaac653caa68acf8f87d7e59cac9ca48b1) | input sample format | +| [`outSampleFmt`](#group__av_1ga01811a58ed47e08fce724b7a1e197ce6) | output sample format | -## Summary +--- - Members | Descriptions ---------------------------------|--------------------------------------------- -`public int channels` | -`public std::string sampleFmt` | One of: u8, s16, s32, flt, dbl, u8p, s16p, s32p, fltp, dblp. -`public AudioCodec()` | -`public AudioCodec(int channels,int sampleRate,const std::string & sampleFmt,int bitRate)` | -`public AudioCodec(const std::string & name,int channels,int sampleRate,int bitRate,const std::string & sampleFmt)` | -`public AudioCodec(const std::string & name,const std::string & encoder,int channels,int sampleRate,int bitRate,const std::string & sampleFmt)` | -`public virtual ~AudioCodec()` | -`public virtual std::string toString() const` | -`public virtual void print(std::ostream & ost)` | +#### AudioResampler -## Members +```cpp +AudioResampler(const AudioCodec & iparams, const AudioCodec & oparams) +``` -#### `public int channels` +| Parameter | Type | Description | +|-----------|------|-------------| +| `iparams` | `const AudioCodec &` | | +| `oparams` | `const AudioCodec &` | | +--- +#### ~AudioResampler +```cpp +~AudioResampler() +``` +--- -#### `public std::string sampleFmt` +#### open -One of: u8, s16, s32, flt, dbl, u8p, s16p, s32p, fltp, dblp. +```cpp +void open() +``` +--- +#### close -#### `public AudioCodec()` +```cpp +void close() +``` +--- +#### resample +```cpp +int resample(uint8_t ** inSamples, int inNumSamples) +``` +Convert the input samples to the output format. NOTE: Input buffers must be contiguous, therefore only interleaved input formats are accepted at this point. -#### `public AudioCodec(int channels,int sampleRate,const std::string & sampleFmt,int bitRate)` +Converted samples are accessible via the `outSamples` class member. +#### Parameters +* `inSamples` Pointer to the input sample buffer array. +* `inNumSamples` The number of input samples per channel. +#### Returns +The number of converted samples, or zero if samples were internally buffered. +| Parameter | Type | Description | +|-----------|------|-------------| +| `inSamples` | `uint8_t **` | | +| `inNumSamples` | `int` | | -#### `public AudioCodec(const std::string & name,int channels,int sampleRate,int bitRate,const std::string & sampleFmt)` +--- +#### ctx +```cpp +SwrContext * ctx +``` +the conversion context +--- -#### `public AudioCodec(const std::string & name,const std::string & encoder,int channels,int sampleRate,int bitRate,const std::string & sampleFmt)` +#### iparams +```cpp +AudioCodec iparams +``` +input audio parameters +--- +#### oparams -#### `public virtual ~AudioCodec()` +```cpp +AudioCodec oparams +``` +output audio parameters +--- +#### outSamples +```cpp +uint8_t ** outSamples +``` -#### `public virtual std::string toString() const` +the output samples buffer +--- +#### outNumSamples +```cpp +int outNumSamples +``` +the number of samples currently in the output buffer -#### `public virtual void print(std::ostream & ost)` +--- +#### outBufferSize +```cpp +int outBufferSize +``` +the number of bytes currently in the buffer +--- -# struct `scy::av::AudioPacket` +#### maxNumSamples +```cpp +int maxNumSamples ``` -struct scy::av::AudioPacket - : public scy::av::MediaPacket -``` -Audio packet for interleaved formats. +the maximum number of samples that can be stored in +--- +#### inSampleFmt -## Summary +```cpp +enum AVSampleFormat inSampleFmt +``` - Members | Descriptions ---------------------------------|--------------------------------------------- -`public size_t numSamples` | -`public inline AudioPacket(uint8_t * data,size_t size,size_t numSamples,int64_t time)` | -`public inline virtual ~AudioPacket()` | -`public inline virtual `[`IPacket`](#classscy_1_1IPacket)` * clone() const` | -`public inline virtual uint8_t * samples() const` | -`public inline virtual const char * className() const` | +input sample format -## Members +--- -#### `public size_t numSamples` +#### outSampleFmt +```cpp +enum AVSampleFormat outSampleFmt +``` +output sample format +## Codec +> **Subclasses:** `scy::av::AudioCodec`, `scy::av::VideoCodec` +> **Defined in:** `codec.h` -#### `public inline AudioPacket(uint8_t * data,size_t size,size_t numSamples,int64_t time)` +[Codec](#structscy_1_1av_1_1Codec) for encoding/decoding media. +### Members + +| Name | Description | +|------|-------------| +| [`Codec`](#group__av_1ga8b9bea5abd6c627618a66f5bb0cacdda) | | +| [`Codec`](#group__av_1ga7e7561a995faa17643c97a585f92f042) | | +| [`Codec`](#group__av_1ga168efa478447f30e8f6c4921016335f6) | | +| [`~Codec`](#group__av_1gad5850bf5554a8187668d0480d340f01d) | Codec(const Codec& r);. | +| [`toString`](#group__av_1ga8b8296b25c3b401f87f21090fd8de249) | | +| [`print`](#group__av_1gadc2b86e08e23d3201f0c3430ae795f5d) | | +| [`name`](#group__av_1ga6844966d0cc504e1a19d138e4787bc26) | The display name for this codec. | +| [`encoder`](#group__av_1ga5552a927640813c68b25c07c89786f79) | The encoder name for FFmpeg. | +| [`sampleRate`](#group__av_1gad3b634766c2f3458c07803c6d9036b47) | The sampling rate or RTP clock rate. | +| [`bitRate`](#group__av_1ga1600230a934a25fb9d280681e16b0b98) | The bit rate to encode at. | +| [`quality`](#group__av_1gab28adf6739a1653c39cd6b004f9f3e8f) | Optional quality value, variable range depending on codec. | +| [`enabled`](#group__av_1gab6735b630af06c573029766f5944be93) | Weather or not the codec is available for use. | + +--- + +#### Codec + +```cpp +Codec() +``` +--- +#### Codec +```cpp +Codec(const std::string & name, int sampleRate, int bitRate, bool enabled) +``` -#### `public inline virtual ~AudioPacket()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | +| `sampleRate` | `int` | | +| `bitRate` | `int` | | +| `enabled` | `bool` | | +--- +#### Codec +```cpp +Codec(const std::string & name, const std::string & encoder, int sampleRate, int bitRate, bool enabled) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | +| `encoder` | `const std::string &` | | +| `sampleRate` | `int` | | +| `bitRate` | `int` | | +| `enabled` | `bool` | | -#### `public inline virtual `[`IPacket`](#classscy_1_1IPacket)` * clone() const` +--- +#### ~Codec +```cpp +virtual ~Codec() +``` +Codec(const Codec& r);. +--- -#### `public inline virtual uint8_t * samples() const` +#### toString +```cpp +virtual std::string toString() const +``` +--- +#### print +```cpp +virtual void print(std::ostream & ost) +``` -#### `public inline virtual const char * className() const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `ost` | `std::ostream &` | | +--- +#### name +```cpp +std::string name +``` +The display name for this codec. -# struct `scy::av::Codec` +--- +#### encoder -[Codec](#structscy_1_1av_1_1Codec) for encoding/decoding media. +```cpp +std::string encoder +``` +The encoder name for FFmpeg. +--- -## Summary +#### sampleRate - Members | Descriptions ---------------------------------|--------------------------------------------- -`public std::string name` | The display name for this codec. -`public std::string encoder` | The encoder name for FFmpeg. -`public int sampleRate` | The sampling rate or RTP clock rate. -`public int bitRate` | The bit rate to encode at. -`public int quality` | Optional quality value, variable range depending on codec. -`public bool enabled` | Weather or not the codec is available for use. -`public Codec()` | -`public Codec(const std::string & name,int sampleRate,int bitRate,bool enabled)` | -`public Codec(const std::string & name,const std::string & encoder,int sampleRate,int bitRate,bool enabled)` | -`public virtual ~Codec()` | Codec(const Codec& r);. -`public virtual std::string toString() const` | -`public virtual void print(std::ostream & ost)` | +```cpp +int sampleRate +``` -## Members +The sampling rate or RTP clock rate. -#### `public std::string name` +--- -The display name for this codec. +#### bitRate +```cpp +int bitRate +``` +The bit rate to encode at. -#### `public std::string encoder` +--- -The encoder name for FFmpeg. +#### quality +```cpp +int quality +``` +Optional quality value, variable range depending on codec. -#### `public int sampleRate` +--- -The sampling rate or RTP clock rate. +#### enabled +```cpp +bool enabled +``` +Weather or not the codec is available for use. -#### `public int bitRate` +## AudioCodec -The bit rate to encode at. +> **Extends:** `scy::av::Codec` +> **Defined in:** `codec.h` +### Members +| Name | Description | +|------|-------------| +| [`AudioCodec`](#group__av_1gac7015ec1976fd68879c0af8e22c14de0) | | +| [`AudioCodec`](#group__av_1ga57d52948e2e4de60591a72c6753823aa) | | +| [`AudioCodec`](#group__av_1ga3c0da0a206873c832f0f7fdd83ac4ca4) | | +| [`AudioCodec`](#group__av_1gafac2a4dbaf98eec7a3a09184ecee2af1) | | +| [`~AudioCodec`](#group__av_1gacef753a31b9526ed27724a3fa9edf9b5) | | +| [`toString`](#group__av_1ga1ac4331d3b1f81838009713165ed4f00) | | +| [`print`](#group__av_1gabc909bb0d48bc67ad06763fbad49c13d) | | +| [`channels`](#group__av_1ga6127b16a7d5e1329e88e124366015071) | | +| [`sampleFmt`](#group__av_1ga4f3070e09c5d36971189f42402984670) | One of: u8, s16, s32, flt, dbl, u8p, s16p, s32p, fltp, dblp. | -#### `public int quality` +--- -Optional quality value, variable range depending on codec. +#### AudioCodec +```cpp +AudioCodec() +``` +--- -#### `public bool enabled` +#### AudioCodec -Weather or not the codec is available for use. +```cpp +AudioCodec(int channels, int sampleRate, const std::string & sampleFmt, int bitRate) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `channels` | `int` | | +| `sampleRate` | `int` | | +| `sampleFmt` | `const std::string &` | | +| `bitRate` | `int` | | +--- -#### `public Codec()` +#### AudioCodec +```cpp +AudioCodec(const std::string & name, int channels, int sampleRate, int bitRate, const std::string & sampleFmt) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | +| `channels` | `int` | | +| `sampleRate` | `int` | | +| `bitRate` | `int` | | +| `sampleFmt` | `const std::string &` | | +--- +#### AudioCodec -#### `public Codec(const std::string & name,int sampleRate,int bitRate,bool enabled)` +```cpp +AudioCodec(const std::string & name, const std::string & encoder, int channels, int sampleRate, int bitRate, const std::string & sampleFmt) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | +| `encoder` | `const std::string &` | | +| `channels` | `int` | | +| `sampleRate` | `int` | | +| `bitRate` | `int` | | +| `sampleFmt` | `const std::string &` | | +--- +#### ~AudioCodec +```cpp +virtual ~AudioCodec() +``` -#### `public Codec(const std::string & name,const std::string & encoder,int sampleRate,int bitRate,bool enabled)` +--- +#### toString +```cpp +virtual std::string toString() const +``` +--- +#### print -#### `public virtual ~Codec()` +```cpp +virtual void print(std::ostream & ost) +``` -Codec(const Codec& r);. +| Parameter | Type | Description | +|-----------|------|-------------| +| `ost` | `std::ostream &` | | +--- +#### channels -#### `public virtual std::string toString() const` +```cpp +int channels +``` +--- +#### sampleFmt +```cpp +std::string sampleFmt +``` +One of: u8, s16, s32, flt, dbl, u8p, s16p, s32p, fltp, dblp. -#### `public virtual void print(std::ostream & ost)` +## VideoCodec +> **Extends:** `scy::av::Codec` +> **Defined in:** `codec.h` +### Members +| Name | Description | +|------|-------------| +| [`VideoCodec`](#group__av_1gaa44f4cc846f8b9aad8557078822c327a) | | +| [`VideoCodec`](#group__av_1ga587fce7885e91f4f9ff83ca6f13577b3) | | +| [`VideoCodec`](#group__av_1gaa6ed9271c03b9a9835702c211042d699) | | +| [`VideoCodec`](#group__av_1gafd3818c6f3ee6e2521fa7748314d1a78) | | +| [`VideoCodec`](#group__av_1gada45746b74cf8b5c55f69c4a1ae29aec) | | +| [`~VideoCodec`](#group__av_1ga97e3ee1f4ba76c2ef660b8ca79443c8b) | | +| [`toString`](#group__av_1gaa21213668b8e41b7532c82637e454762) | | +| [`print`](#group__av_1ga2fb6dd668b213d39137cbe3b1d5fc34f) | | +| [`width`](#group__av_1ga0d2a616eaac095f875d8f2a0bd98091f) | | +| [`height`](#group__av_1ga6cbce4c67a21bce1e6a7ecee4d7b83b7) | | +| [`fps`](#group__av_1gab5abeb6ba9ae28522af6da214811592b) | | +| [`pixelFmt`](#group__av_1ga94555d9553e04922c805d3a4661462d2) | | +--- -# struct `scy::av::Device` +#### VideoCodec +```cpp +VideoCodec() +``` -Represents a system audio, video or render device. +--- +#### VideoCodec +```cpp +VideoCodec(int width, int height, double fps, const std::string & pixelFmt, int bitRate, int sampleRate) +``` -## Summary +| Parameter | Type | Description | +|-----------|------|-------------| +| `width` | `int` | | +| `height` | `int` | | +| `fps` | `double` | | +| `pixelFmt` | `const std::string &` | | +| `bitRate` | `int` | | +| `sampleRate` | `int` | | - Members | Descriptions ---------------------------------|--------------------------------------------- -`public std::string type` | -`public int id` | -`public std::string name` | -`public std::string guid` | -`public bool isDefault` | -`public bool isAvailable` | -`public Type type` | -`public std::string id` | -`public Device()` | -`public Device(const std::string & type,int id,const std::string & name,const std::string & guid,bool isDefault,bool isAvailable)` | -`public void print(std::ostream & os)` | -`public inline bool operator==(const `[`Device`](#structscy_1_1av_1_1Device)` & that) const` | -`public Device()` | -`public Device(Type type,const std::string & id,const std::string & name,bool isDefault)` | -`public void print(std::ostream & os)` | -`public inline bool operator==(const `[`Device`](#structscy_1_1av_1_1Device)` & that) const` | +--- -## Members +#### VideoCodec -#### `public std::string type` +```cpp +VideoCodec(const std::string & name, int width, int height, double fps, int bitRate, int sampleRate, const std::string & pixelFmt) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | +| `width` | `int` | | +| `height` | `int` | | +| `fps` | `double` | | +| `bitRate` | `int` | | +| `sampleRate` | `int` | | +| `pixelFmt` | `const std::string &` | | +--- +#### VideoCodec +```cpp +VideoCodec(const std::string & name, const std::string & encoder, int width, int height, double fps, int bitRate, int sampleRatee, const std::string & pixelFmt) +``` -#### `public int id` +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | +| `encoder` | `const std::string &` | | +| `width` | `int` | | +| `height` | `int` | | +| `fps` | `double` | | +| `bitRate` | `int` | | +| `sampleRatee` | `int` | | +| `pixelFmt` | `const std::string &` | | +--- +#### VideoCodec +```cpp +VideoCodec(const VideoCodec & r) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `r` | `const VideoCodec &` | | -#### `public std::string name` +--- +#### ~VideoCodec +```cpp +virtual ~VideoCodec() +``` +--- +#### toString -#### `public std::string guid` +```cpp +virtual std::string toString() const +``` +--- +#### print +```cpp +virtual void print(std::ostream & ost) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `ost` | `std::ostream &` | | -#### `public bool isDefault` +--- +#### width +```cpp +int width +``` +--- +#### height -#### `public bool isAvailable` +```cpp +int height +``` +--- +#### fps +```cpp +double fps +``` +--- -#### `public Type type` +#### pixelFmt +```cpp +std::string pixelFmt +``` +## Deleter +> **Defined in:** `ffmpeg.h` +Utilites for RAII: -#### `public std::string id` +[Deleter](#structscy_1_1av_1_1Deleter) adaptor for functions like av_free that take a pointer. +### Members +| Name | Description | +|------|-------------| +| [`operator()`](#group__av_1ga43be0299f292908f86655a404dec15bd) | | +--- +#### operator() -#### `public Device()` +```cpp +inline void operator()(T * p) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `p` | `T *` | | +## Deleterp +> **Defined in:** `ffmpeg.h` +[Deleter](#structscy_1_1av_1_1Deleter) adaptor for functions like av_freep that take a pointer to a pointer. -#### `public Device(const std::string & type,int id,const std::string & name,const std::string & guid,bool isDefault,bool isAvailable)` +### Members +| Name | Description | +|------|-------------| +| [`operator()`](#group__av_1ga32ab3d485566a5de359e2615e817263b) | | +--- +#### operator() +```cpp +inline void operator()(T * p) const +``` -#### `public void print(std::ostream & os)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `p` | `T *` | | +## Format +> **Defined in:** `format.h` +Defines a media container format which is available through the [Format](#structscy_1_1av_1_1Format) Registry for encoding/decoding. A format defined preferred default values for each codec. +### Members + +| Name | Description | +|------|-------------| +| [`Type`](#group__av_1gaee45ab380f3ab82ddee6a904902e441a) | | +| [`Format`](#group__av_1gadc07003ad1a442a1a1f6430e46b07545) | Ctors/Dtors. | +| [`Format`](#group__av_1ga6dfaf2481d30bc3a9172e3cd0fdfb021) | | +| [`Format`](#group__av_1ga3b8c3f30d4bf073ae393bbce6d1b46f1) | | +| [`Format`](#group__av_1ga5b4c8a4300f9436641f5ae2e4934cf1c) | | +| [`Format`](#group__av_1gac534811daa5a3274f418f327b1d24f55) | | +| [`type`](#group__av_1ga8cce3276f2c5399b7f7f86b2f3d431f8) | The format type. | +| [`toString`](#group__av_1ga55f0817773eba2440856dcac9cc8db04) | | +| [`print`](#group__av_1gac2a467b9b251cc8274c3900360e9c58d) | | +| [`preferable`](#group__av_1gac0061edac2d666861ddfe6f5171aeb87) | | +| [`name`](#group__av_1gab23291d998e8eeeaf780711adb47f279) | Base [Format](#structscy_1_1av_1_1Format) Variables. | +| [`id`](#group__av_1gae301eb6d3562a0593b3cba4645944965) | The short name of this format. | +| [`video`](#group__av_1ga8c72beb62c31705f7954bb74941165f8) | The video codec. | +| [`audio`](#group__av_1ga2d7a7c6b006a17245c5e232d059f59be) | The audio codec. | +| [`priority`](#group__av_1gad33f46119d0512791b3116b07af86423) | The priority this format will be displayed on the list. | + +--- + +#### Type + +```cpp +enum Type +``` -#### `public inline bool operator==(const `[`Device`](#structscy_1_1av_1_1Device)` & that) const` +| Value | Description | +|-------|-------------| +| `None` | | +| `Video` | video only | +| `Audio` | audio only | +| `Multiplex` | both video & audio | +--- +#### Format +```cpp +Format() +``` +Ctors/Dtors. -#### `public Device()` +--- +#### Format +```cpp +Format(const std::string & name, const std::string & id, const VideoCodec & video, const AudioCodec & audio, int priority) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | +| `id` | `const std::string &` | | +| `video` | `const VideoCodec &` | | +| `audio` | `const AudioCodec &` | | +| `priority` | `int` | | +--- -#### `public Device(Type type,const std::string & id,const std::string & name,bool isDefault)` +#### Format +```cpp +Format(const std::string & name, const std::string & id, const VideoCodec & video, int priority) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | +| `id` | `const std::string &` | | +| `video` | `const VideoCodec &` | | +| `priority` | `int` | | +--- +#### Format -#### `public void print(std::ostream & os)` +```cpp +Format(const std::string & name, const std::string & id, const AudioCodec & audio, int priority) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | +| `id` | `const std::string &` | | +| `audio` | `const AudioCodec &` | | +| `priority` | `int` | | +--- +#### Format +```cpp +Format(const Format & r) +``` -#### `public inline bool operator==(const `[`Device`](#structscy_1_1av_1_1Device)` & that) const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `r` | `const Format &` | | +--- +#### type +```cpp +Type type() const +``` +The format type. -# struct `scy::av::EncoderOptions` +--- +#### toString +```cpp +virtual std::string toString() const +``` +--- +#### print +```cpp +virtual void print(std::ostream & ost) +``` -## Summary +| Parameter | Type | Description | +|-----------|------|-------------| +| `ost` | `std::ostream &` | | - Members | Descriptions ---------------------------------|--------------------------------------------- -`public `[`Format`](./doc/api-av.md#structscy_1_1av_1_1Format)` iformat` | input media format. -`public `[`Format`](./doc/api-av.md#structscy_1_1av_1_1Format)` oformat` | output media format. -`public std::string ifile` | input file path. -`public std::string ofile` | output file path. -`public long duration` | duration of time to record in nanoseconds. -`public inline EncoderOptions(const `[`Format`](#structscy_1_1av_1_1Format)` & iformat,const `[`Format`](#structscy_1_1av_1_1Format)` & oformat,const std::string & ifile,const std::string & ofile,long duration)` | -`public inline virtual ~EncoderOptions()` | +--- -## Members +#### preferable -#### `public `[`Format`](./doc/api-av.md#structscy_1_1av_1_1Format)` iformat` +```cpp +static inline bool preferable(const Format & first, const Format & second) +``` -input media format. +| Parameter | Type | Description | +|-----------|------|-------------| +| `first` | `const Format &` | | +| `second` | `const Format &` | | +--- +#### name -#### `public `[`Format`](./doc/api-av.md#structscy_1_1av_1_1Format)` oformat` +```cpp +std::string name +``` -output media format. +Base [Format](#structscy_1_1av_1_1Format) Variables. +The display name of this format. +--- -#### `public std::string ifile` +#### id -input file path. +```cpp +std::string id +``` +The short name of this format. +--- -#### `public std::string ofile` +#### video -output file path. +```cpp +VideoCodec video +``` +The video codec. +--- -#### `public long duration` +#### audio -duration of time to record in nanoseconds. +```cpp +AudioCodec audio +``` +The audio codec. + +--- +#### priority -#### `public inline EncoderOptions(const `[`Format`](#structscy_1_1av_1_1Format)` & iformat,const `[`Format`](#structscy_1_1av_1_1Format)` & oformat,const std::string & ifile,const std::string & ofile,long duration)` +```cpp +int priority +``` +The priority this format will be displayed on the list. +## FPSCounter +> **Defined in:** `fpscounter.h` +### Members -#### `public inline virtual ~EncoderOptions()` +| Name | Description | +|------|-------------| +| [`FPSCounter`](#group__av_1ga08e60283f72b88f8ac4470e99b6c6a29) | | +| [`tick`](#group__av_1ga8482fcfaf1b6130986021e717a31480f) | | +| [`reset`](#group__av_1ga69069625ebaad7c2650f8b5694d9d236) | | +| [`started`](#group__av_1ga957474be4397f33d4de755fd6a6dfa35) | | +| [`startFrame`](#group__av_1ga3a5def4cade260d217e3d04f612be349) | | +| [`endFrame`](#group__av_1ga5a038d317369a4f232ed373d5248bf42) | | +| [`start`](#group__av_1gab8adff3b20da64480d14945b72c9f103) | | +| [`end`](#group__av_1ga4c0df024844c9f7d93f9a211e8280d7b) | | +| [`frames`](#group__av_1ga2ae1b95710ddb1c8b27353b1bc83aa8a) | | +| [`total`](#group__av_1ga1c3c6dfc7993518d31340a13b3ce6f6f) | | +| [`fps`](#group__av_1ga1371516475e42a8a82e150a0374b7ddd) | | +--- +#### FPSCounter +```cpp +inline FPSCounter() +``` +--- -# struct `scy::av::EncoderState` +#### tick +```cpp +inline void tick() ``` -struct scy::av::EncoderState - : public scy::State -``` +--- + +#### reset +```cpp +inline void reset() +``` +--- +#### started -## Summary +```cpp +inline bool started() +``` - Members | Descriptions ---------------------------------|--------------------------------------------- -`public inline std::string str(unsigned int id) const` | +--- -## Members +#### startFrame -#### `public inline std::string str(unsigned int id) const` +```cpp +inline void startFrame() +``` +--- +#### endFrame +```cpp +inline double endFrame() +``` +--- -# struct `scy::av::Format` +#### start +```cpp +clock_t start +``` +--- +#### end -Defines a media container format which is available through the [Format](#structscy_1_1av_1_1Format) Registry for encoding/decoding. A format defined preferred default values for each codec. +```cpp +clock_t end +``` -## Summary +--- - Members | Descriptions ---------------------------------|--------------------------------------------- -`public std::string name` | Base [Format](./doc/api-av.md#structscy_1_1av_1_1Format) Variables. -`public std::string id` | The short name of this format. -`public `[`VideoCodec`](./doc/api-av.md#structscy_1_1av_1_1VideoCodec)` video` | The video codec. -`public `[`AudioCodec`](./doc/api-av.md#structscy_1_1av_1_1AudioCodec)` audio` | The audio codec. -`public int priority` | The priority this format will be displayed on the list. -`public Format()` | Ctors/Dtors. -`public Format(const std::string & name,const std::string & id,const `[`VideoCodec`](#structscy_1_1av_1_1VideoCodec)` & video,const `[`AudioCodec`](#structscy_1_1av_1_1AudioCodec)` & audio,int priority)` | -`public Format(const std::string & name,const std::string & id,const `[`VideoCodec`](#structscy_1_1av_1_1VideoCodec)` & video,int priority)` | -`public Format(const std::string & name,const std::string & id,const `[`AudioCodec`](#structscy_1_1av_1_1AudioCodec)` & audio,int priority)` | -`public Format(const `[`Format`](#structscy_1_1av_1_1Format)` & r)` | -`public `[`Type`](#group__av_1gaee45ab380f3ab82ddee6a904902e441a)` type() const` | The format type. -`public virtual std::string toString() const` | -`public virtual void print(std::ostream & ost)` | +#### frames -## Members +```cpp +int64_t frames +``` -#### `public std::string name` +--- -Base [Format](#structscy_1_1av_1_1Format) Variables. +#### total -The display name of this format. +```cpp +double total +``` -#### `public std::string id` +--- -The short name of this format. +#### fps +```cpp +double fps +``` +## EncoderState -#### `public `[`VideoCodec`](./doc/api-av.md#structscy_1_1av_1_1VideoCodec)` video` +> **Extends:** `scy::State` +> **Defined in:** `iencoder.h` -The video codec. +### Members +| Name | Description | +|------|-------------| +| [`Type`](#group__av_1gad24c76e0eb2d570f08ebb767d565ed38) | | +| [`str`](#group__av_1ga1b8ea9145750488a74eb407a32fe90ba) | | +--- -#### `public `[`AudioCodec`](./doc/api-av.md#structscy_1_1av_1_1AudioCodec)` audio` +#### Type -The audio codec. +```cpp +enum Type +``` +| Value | Description | +|-------|-------------| +| `None` | | +| `Ready` | | +| `Encoding` | | +| `Stopped` | | +| `Error` | | +--- -#### `public int priority` +#### str -The priority this format will be displayed on the list. +```cpp +inline std::string str(unsigned int id) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `id` | `unsigned int` | | +## EncoderOptions -#### `public Format()` +> **Defined in:** `iencoder.h` -Ctors/Dtors. +### Members + +| Name | Description | +|------|-------------| +| [`EncoderOptions`](#group__av_1ga387141c363e2ab3a4f500549fe359dd5) | | +| [`~EncoderOptions`](#group__av_1gaa16b0ea452e4064444fac3c678a1ef0c) | | +| [`iformat`](#group__av_1ga54c813e9943c855171e8279e8085548a) | input media format. | +| [`oformat`](#group__av_1gaaa1c4adc23b0755d9633cff732d931e9) | output media format. | +| [`ifile`](#group__av_1gaca1d7ab6e72cc562ef90860a01461b8a) | input file path. | +| [`ofile`](#group__av_1gae6f1fb56ae68ac24395c4f51dcf7c85b) | output file path. | +| [`duration`](#group__av_1ga65a112623aedce6dbb8f6a0f244dea05) | duration of time to record in nanoseconds. | +--- +#### EncoderOptions -#### `public Format(const std::string & name,const std::string & id,const `[`VideoCodec`](#structscy_1_1av_1_1VideoCodec)` & video,const `[`AudioCodec`](#structscy_1_1av_1_1AudioCodec)` & audio,int priority)` +```cpp +inline EncoderOptions(const Format & iformat, const Format & oformat, const std::string & ifile, const std::string & ofile, long duration) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `iformat` | `const Format &` | | +| `oformat` | `const Format &` | | +| `ifile` | `const std::string &` | | +| `ofile` | `const std::string &` | | +| `duration` | `long` | | +--- +#### ~EncoderOptions +```cpp +virtual ~EncoderOptions() = default +``` -#### `public Format(const std::string & name,const std::string & id,const `[`VideoCodec`](#structscy_1_1av_1_1VideoCodec)` & video,int priority)` +--- +#### iformat +```cpp +Format iformat +``` +input media format. +--- -#### `public Format(const std::string & name,const std::string & id,const `[`AudioCodec`](#structscy_1_1av_1_1AudioCodec)` & audio,int priority)` +#### oformat +```cpp +Format oformat +``` +output media format. +--- +#### ifile -#### `public Format(const `[`Format`](#structscy_1_1av_1_1Format)` & r)` +```cpp +std::string ifile +``` +input file path. +--- +#### ofile +```cpp +std::string ofile +``` -#### `public `[`Type`](#group__av_1gaee45ab380f3ab82ddee6a904902e441a)` type() const` +output file path. -The format type. +--- +#### duration +```cpp +long duration +``` -#### `public virtual std::string toString() const` +duration of time to record in nanoseconds. +## MediaPacket +> **Extends:** `scy::RawPacket` +> **Subclasses:** `scy::av::AudioPacket`, `scy::av::VideoPacket` +> **Defined in:** `packet.h` +### Members +| Name | Description | +|------|-------------| +| [`MediaPacket`](#group__av_1gac9d853208831fdf8fcc3201cf9b0c28d) | | +| [`MediaPacket`](#group__av_1ga0f8e4b7ec8dc735257864bd80302a318) | Construct with const data (copied, owning). | +| [`MediaPacket`](#group__av_1gaebb222de1256c5f9a53d3754634abf55) | | +| [`~MediaPacket`](#group__av_1gaf8e865fc115d6d8b610ae363377e75ab) | | +| [`clone`](#group__av_1ga074433f3edf7a433f683add7c24bf264) | | +| [`className`](#group__av_1ga54de449000362cb481e49231dfffea58) | | +| [`time`](#group__av_1gabb9a7542ea30867ed0749c549b452684) | | -#### `public virtual void print(std::ostream & ost)` +--- +#### MediaPacket +```cpp +inline MediaPacket(uint8_t * data, size_t size, int64_t time) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `data` | `uint8_t *` | | +| `size` | `size_t` | | +| `time` | `int64_t` | | +--- -# struct `scy::av::MediaPacket` +#### MediaPacket +```cpp +inline MediaPacket(const uint8_t * data, size_t size, int64_t time) ``` -struct scy::av::MediaPacket - : public scy::RawPacket -``` +Construct with const data (copied, owning). +| Parameter | Type | Description | +|-----------|------|-------------| +| `data` | `const uint8_t *` | | +| `size` | `size_t` | | +| `time` | `int64_t` | | +--- +#### MediaPacket -## Summary +```cpp +inline MediaPacket(const MediaPacket & r) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `r` | `const MediaPacket &` | | - Members | Descriptions ---------------------------------|--------------------------------------------- -`public int64_t time` | -`public inline MediaPacket(uint8_t * data,size_t size,int64_t time)` | -`public inline MediaPacket(const `[`MediaPacket`](#structscy_1_1av_1_1MediaPacket)` & r)` | -`public inline virtual ~MediaPacket()` | -`public inline virtual `[`IPacket`](#classscy_1_1IPacket)` * clone() const` | -`public inline virtual const char * className() const` | +--- -## Members +#### ~MediaPacket -#### `public int64_t time` +```cpp +virtual ~MediaPacket() = default +``` +--- +#### clone +```cpp +virtual inline IPacket * clone() const +``` +--- -#### `public inline MediaPacket(uint8_t * data,size_t size,int64_t time)` +#### className +```cpp +virtual inline const char * className() const +``` +--- +#### time +```cpp +int64_t time +``` -#### `public inline MediaPacket(const `[`MediaPacket`](#structscy_1_1av_1_1MediaPacket)` & r)` +## VideoPacket +> **Extends:** `scy::av::MediaPacket` +> **Subclasses:** `scy::av::PlanarVideoPacket` +> **Defined in:** `packet.h` +Video packet for interleaved formats. +### Members +| Name | Description | +|------|-------------| +| [`VideoPacket`](#group__av_1gaff046f16e26635e322445cdf872ab8f5) | | +| [`VideoPacket`](#group__av_1ga04b7a866edebd63332a1a852eba039e3) | | +| [`~VideoPacket`](#group__av_1ga9756c5718969ab42329bfb31890da41a) | | +| [`clone`](#group__av_1gad8b50045a88a7e594f11984f612cf9b5) | | +| [`className`](#group__av_1ga9c572f1d81439fff33b4acf7d9c773b7) | | +| [`width`](#group__av_1ga73d26deb4e00050f9db4a1fd99e58cce) | | +| [`height`](#group__av_1ga25f5e1546e384451aef0d0e645e25a35) | | +| [`iframe`](#group__av_1gaba12f8bdb6b1fe073f8a424dc59bc799) | | -#### `public inline virtual ~MediaPacket()` +--- +#### VideoPacket +```cpp +inline VideoPacket(uint8_t * data, size_t size, int width, int height, int64_t time) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `data` | `uint8_t *` | | +| `size` | `size_t` | | +| `width` | `int` | | +| `height` | `int` | | +| `time` | `int64_t` | | +--- -#### `public inline virtual `[`IPacket`](#classscy_1_1IPacket)` * clone() const` +#### VideoPacket +```cpp +inline VideoPacket(const VideoPacket & r) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `r` | `const VideoPacket &` | | +--- +#### ~VideoPacket -#### `public inline virtual const char * className() const` +```cpp +virtual ~VideoPacket() = default +``` +--- +#### clone +```cpp +virtual inline IPacket * clone() const +``` +--- -# struct `scy::av::PlanarAudioPacket` +#### className +```cpp +virtual inline const char * className() const ``` -struct scy::av::PlanarAudioPacket - : public scy::av::AudioPacket -``` -Audio packet for planar formats. +--- +#### width +```cpp +int width +``` + +--- -## Summary +#### height - Members | Descriptions ---------------------------------|--------------------------------------------- -`public uint8_t * buffer` | -`public int linesize` | -`public int channels` | -`public std::string sampleFmt` | -`public PlanarAudioPacket(uint8_t * data,int channels,size_t numSamples,const std::string & sampleFmt,int64_t time)` | -`public PlanarAudioPacket(const `[`PlanarAudioPacket`](#structscy_1_1av_1_1PlanarAudioPacket)` & r)` | -`public virtual ~PlanarAudioPacket()` | -`public inline virtual `[`IPacket`](#classscy_1_1IPacket)` * clone() const` | -`public inline virtual const char * className() const` | +```cpp +int height +``` -## Members +--- -#### `public uint8_t * buffer` +#### iframe +```cpp +bool iframe +``` +## PlanarVideoPacket +> **Extends:** `scy::av::VideoPacket` +> **Defined in:** `packet.h` +Video packet for planar formats. -#### `public int linesize` +#### Parameters +* `data` Array of per-plane data pointers (up to 4 planes). +* `linesize` Array of per-plane byte strides. +* `pixelFmt` The pixel format name (e.g. "yuv420p"). +* `width` The frame width in pixels. +* `height` The frame height in pixels. -#### `public int channels` +* `time` The timestamp in microseconds. +### Members +| Name | Description | +|------|-------------| +| [`PlanarVideoPacket`](#group__av_1gaf8d9ac2e7fdf39ee4d73d0d0886b1ceb) | | +| [`PlanarVideoPacket`](#group__av_1ga4abea12a09aa43ce4954e372baef7a8c) | | +| [`~PlanarVideoPacket`](#group__av_1ga2aae877fb4dfd5691c0d666e18a28859) | | +| [`clone`](#group__av_1ga03d18f5a75de381e3b7ce4b9e4a75d9a) | | +| [`className`](#group__av_1gac9986c1091ed255c4614641e6e00f7e6) | | +| [`buffer`](#group__av_1ga9a3c69a22b590d040cbbaab468c01bdb) | | +| [`linesize`](#group__av_1ga7e7bfca3306f5509d135b114da83c5bc) | | +| [`pixelFmt`](#group__av_1ga116fa37a9f36f2fa6f00c0ac93f68418) | | +--- +#### PlanarVideoPacket -#### `public std::string sampleFmt` +```cpp +PlanarVideoPacket(uint8_t * data, const int linesize, const std::string & pixelFmt, int width, int height, int64_t time) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `data` | `uint8_t *` | | +| `linesize` | `const int` | | +| `pixelFmt` | `const std::string &` | | +| `width` | `int` | | +| `height` | `int` | | +| `time` | `int64_t` | | +--- +#### PlanarVideoPacket +```cpp +PlanarVideoPacket(const PlanarVideoPacket & r) +``` -#### `public PlanarAudioPacket(uint8_t * data,int channels,size_t numSamples,const std::string & sampleFmt,int64_t time)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `r` | `const PlanarVideoPacket &` | | +--- +#### ~PlanarVideoPacket +```cpp +virtual ~PlanarVideoPacket() +``` +--- -#### `public PlanarAudioPacket(const `[`PlanarAudioPacket`](#structscy_1_1av_1_1PlanarAudioPacket)` & r)` +#### clone +```cpp +virtual inline IPacket * clone() const +``` +--- +#### className +```cpp +virtual inline const char * className() const +``` -#### `public virtual ~PlanarAudioPacket()` +--- +#### buffer +```cpp +uint8_t * buffer = { nullptr } +``` +--- +#### linesize -#### `public inline virtual `[`IPacket`](#classscy_1_1IPacket)` * clone() const` +```cpp +int linesize +``` +--- +#### pixelFmt +```cpp +std::string pixelFmt +``` +## AudioPacket -#### `public inline virtual const char * className() const` +> **Extends:** `scy::av::MediaPacket` +> **Subclasses:** `scy::av::PlanarAudioPacket` +> **Defined in:** `packet.h` +Audio packet for interleaved formats. +### Members +| Name | Description | +|------|-------------| +| [`AudioPacket`](#group__av_1ga195ac44889de6c61aaa6199f46e9dda5) | | +| [`~AudioPacket`](#group__av_1ga89e0700ad79770d6dc344e5aabdfa890) | | +| [`clone`](#group__av_1ga7e4bead8a7be118c1350e0ad11772df5) | | +| [`samples`](#group__av_1gade6d4ffffca5ac7d08930e75cbbf5c10) | | +| [`className`](#group__av_1ga11b528a4f6076f007177bdf29b35d207) | | +| [`numSamples`](#group__av_1gaef38d5a53938b523ac986cb148afc245) | | +--- -# struct `scy::av::PlanarVideoPacket` +#### AudioPacket +```cpp +inline AudioPacket(uint8_t * data, size_t size, size_t numSamples, int64_t time) ``` -struct scy::av::PlanarVideoPacket - : public scy::av::VideoPacket -``` -Video packet for planar formats. +| Parameter | Type | Description | +|-----------|------|-------------| +| `data` | `uint8_t *` | | +| `size` | `size_t` | | +| `numSamples` | `size_t` | | +| `time` | `int64_t` | | +--- +#### ~AudioPacket -## Summary +```cpp +virtual ~AudioPacket() = default +``` - Members | Descriptions ---------------------------------|--------------------------------------------- -`public uint8_t * buffer` | -`public int linesize` | -`public std::string pixelFmt` | -`public PlanarVideoPacket(uint8_t * data,const int linesize,const std::string & pixelFmt,int width,int height,int64_t time)` | -`public PlanarVideoPacket(const `[`PlanarVideoPacket`](#structscy_1_1av_1_1PlanarVideoPacket)` & r)` | -`public virtual ~PlanarVideoPacket()` | -`public inline virtual `[`IPacket`](#classscy_1_1IPacket)` * clone() const` | -`public inline virtual const char * className() const` | +--- -## Members +#### clone -#### `public uint8_t * buffer` +```cpp +virtual inline IPacket * clone() const +``` +--- +#### samples +```cpp +virtual inline uint8_t * samples() const +``` +--- -#### `public int linesize` +#### className +```cpp +virtual inline const char * className() const +``` +--- +#### numSamples +```cpp +size_t numSamples +``` -#### `public std::string pixelFmt` +## PlanarAudioPacket +> **Extends:** `scy::av::AudioPacket` +> **Defined in:** `packet.h` +Audio packet for planar formats. +#### Parameters +* `data` Array of per-plane sample buffers (one per channel). +* `channels` The number of audio channels. -#### `public PlanarVideoPacket(uint8_t * data,const int linesize,const std::string & pixelFmt,int width,int height,int64_t time)` +* `numSamples` The number of samples per channel. +* `sampleFmt` The sample format name (e.g. "fltp"). +* `time` The timestamp in microseconds. +### Members +| Name | Description | +|------|-------------| +| [`PlanarAudioPacket`](#group__av_1ga3b900377bd05251506e88ca2257701b3) | | +| [`PlanarAudioPacket`](#group__av_1ga51c7846e448e42ada6b920923a011e96) | | +| [`~PlanarAudioPacket`](#group__av_1ga0613354409c88d2899e1e15a63512a21) | | +| [`clone`](#group__av_1gaeea01ec76767635cbde78bf3e42a1c75) | | +| [`className`](#group__av_1ga52925e8a703f1f2e7adc6822f3f6054e) | | +| [`buffer`](#group__av_1ga4fe84e8d523089c8ac8227428675184d) | | +| [`linesize`](#group__av_1gacb99bf2c2e1c52464ed2e8f5d713d7a7) | | +| [`channels`](#group__av_1gad042ae63d86adce90c2089377ce37dee) | | +| [`sampleFmt`](#group__av_1gae6212664c4b0dfd2a1a26a3b09365e86) | | -#### `public PlanarVideoPacket(const `[`PlanarVideoPacket`](#structscy_1_1av_1_1PlanarVideoPacket)` & r)` +--- +#### PlanarAudioPacket +```cpp +PlanarAudioPacket(uint8_t * data, int channels, size_t numSamples, const std::string & sampleFmt, int64_t time) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `data` | `uint8_t *` | | +| `channels` | `int` | | +| `numSamples` | `size_t` | | +| `sampleFmt` | `const std::string &` | | +| `time` | `int64_t` | | +--- -#### `public virtual ~PlanarVideoPacket()` +#### PlanarAudioPacket +```cpp +PlanarAudioPacket(const PlanarAudioPacket & r) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `r` | `const PlanarAudioPacket &` | | +--- +#### ~PlanarAudioPacket -#### `public inline virtual `[`IPacket`](#classscy_1_1IPacket)` * clone() const` +```cpp +virtual ~PlanarAudioPacket() +``` +--- +#### clone +```cpp +virtual inline IPacket * clone() const +``` +--- -#### `public inline virtual const char * className() const` +#### className +```cpp +virtual inline const char * className() const +``` +--- +#### buffer +```cpp +uint8_t * buffer = { nullptr } +``` -# struct `scy::av::VideoCodec` +--- -``` -struct scy::av::VideoCodec - : public scy::av::Codec -``` +#### linesize +```cpp +int linesize +``` +--- +#### channels +```cpp +int channels +``` -## Summary +--- - Members | Descriptions ---------------------------------|--------------------------------------------- -`public int width` | -`public int height` | -`public double fps` | -`public std::string pixelFmt` | -`public VideoCodec()` | -`public VideoCodec(int width,int height,double fps,const std::string & pixelFmt,int bitRate,int sampleRate)` | -`public VideoCodec(const std::string & name,int width,int height,double fps,int bitRate,int sampleRate,const std::string & pixelFmt)` | -`public VideoCodec(const std::string & name,const std::string & encoder,int width,int height,double fps,int bitRate,int sampleRatee,const std::string & pixelFmt)` | -`public VideoCodec(const `[`VideoCodec`](#structscy_1_1av_1_1VideoCodec)` & r)` | -`public virtual ~VideoCodec()` | -`public virtual std::string toString() const` | -`public virtual void print(std::ostream & ost)` | +#### sampleFmt -## Members +```cpp +std::string sampleFmt +``` -#### `public int width` +## MediaPacketTimeCompare +> **Defined in:** `realtimepacketqueue.h` +### Members +| Name | Description | +|------|-------------| +| [`operator()`](#group__av_1gaae0732616533ecf4d9869a7751eae614) | | +--- -#### `public int height` +#### operator() +```cpp +inline bool operator()(const MediaPacket * a, const MediaPacket * b) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `a` | `const MediaPacket *` | | +| `b` | `const MediaPacket *` | | + +## VideoContext + +> **Subclasses:** `scy::av::VideoDecoder`, `scy::av::VideoEncoder` +> **Defined in:** `videocontext.h` + +Base video context from which all video encoders and decoders derive. + +### Members + +| Name | Description | +|------|-------------| +| [`VideoContext`](#group__av_1gad6a1f87160fb60f7a2a003565931dab1) | | +| [`~VideoContext`](#group__av_1ga56d1e423ba71d70cc3c4e71bc089bc44) | | +| [`create`](#group__av_1gab3f5a2d0c17a8cd21cf78d0d0b85ccc5) | Create the `AVCodecContext` using default values. | +| [`open`](#group__av_1gac11a4a1ec6e53e4bfcabd5fdd4ab405b) | Open the `AVCodecContext` | +| [`close`](#group__av_1ga90c4aa947a1fd5cdb599027bf1fcc3d7) | Close the `AVCodecContext` | +| [`convert`](#group__av_1gaca7b0edc59811fcd33ace4314830ba59) | Convert the video frame and return the result. | +| [`recreateConverter`](#group__av_1ga25a0643fc77c96a00f4739a5b89b2d64) | | +| [`emitter`](#group__av_1ga4b2399a155aef55e06b3b1161ef64c03) | | +| [`iparams`](#group__av_1ga538caf74e90bbd3a5f89ddef10c21d8b) | input parameters | +| [`oparams`](#group__av_1ga6c2ffdffb62ea3590b2eee59821591b0) | output parameters | +| [`stream`](#group__av_1ga165fcfeea3b363b8d8584a1ee3fcd5d2) | encoder or decoder stream | +| [`ctx`](#group__av_1gae16196ccc02da8601dffcb1a76a22625) | encoder or decoder context | +| [`codec`](#group__av_1ga52c9688a8df25c77655e9f6815f18149) | encoder or decoder codec | +| [`frame`](#group__av_1gac9f0269a331589ae180b564de79ba1d6) | encoder or decoder frame | +| [`conv`](#group__av_1ga9d9a72086b8fc56058415fce010410ae) | video conversion context | +| [`time`](#group__av_1gafbef89eda47bfd2b4b4669f2d086286c) | stream time in codec time base | +| [`pts`](#group__av_1ga390bb6f03ef0d9607c1de75c1e7e8641) | last packet pts value | +| [`seconds`](#group__av_1ga9cca27f02f5a0a23e7ebd5acfc00aac7) | video time in seconds | +| [`error`](#group__av_1gaccb84925702ba5b2b196327db38a3dfe) | error message | + +--- + +#### VideoContext + +```cpp +VideoContext() +``` +--- +#### ~VideoContext -#### `public double fps` +```cpp +virtual ~VideoContext() +``` +--- +#### create +```cpp +virtual void create() +``` +Create the `AVCodecContext` using default values. -#### `public std::string pixelFmt` +--- +#### open +```cpp +virtual void open() +``` +Open the `AVCodecContext` +--- -#### `public VideoCodec()` +#### close +```cpp +virtual void close() +``` +Close the `AVCodecContext` +--- +#### convert -#### `public VideoCodec(int width,int height,double fps,const std::string & pixelFmt,int bitRate,int sampleRate)` +```cpp +virtual AVFrame * convert(AVFrame * iframe) +``` +Convert the video frame and return the result. +The input frame will only be converted if it doesn't match the output format. If the frame is not converted the input frame will be returned. If the input frame format does not match the `[VideoConverter](#structscy_1_1av_1_1VideoConverter)` context then the `[VideoConverter](#structscy_1_1av_1_1VideoConverter)` will be recreated with the input frame params. +| Parameter | Type | Description | +|-----------|------|-------------| +| `iframe` | `AVFrame *` | | +--- -#### `public VideoCodec(const std::string & name,int width,int height,double fps,int bitRate,int sampleRate,const std::string & pixelFmt)` +#### recreateConverter +```cpp +virtual bool recreateConverter() +``` +--- +#### emitter +```cpp +PacketSignal emitter +``` -#### `public VideoCodec(const std::string & name,const std::string & encoder,int width,int height,double fps,int bitRate,int sampleRatee,const std::string & pixelFmt)` +--- +#### iparams +```cpp +VideoCodec iparams +``` +input parameters +--- -#### `public VideoCodec(const `[`VideoCodec`](#structscy_1_1av_1_1VideoCodec)` & r)` +#### oparams +```cpp +VideoCodec oparams +``` +output parameters +--- +#### stream -#### `public virtual ~VideoCodec()` +```cpp +AVStream * stream +``` +encoder or decoder stream +--- +#### ctx +```cpp +AVCodecContext * ctx +``` -#### `public virtual std::string toString() const` +encoder or decoder context +--- +#### codec +```cpp +const AVCodec * codec +``` +encoder or decoder codec -#### `public virtual void print(std::ostream & ost)` +--- +#### frame +```cpp +AVFrame * frame +``` +encoder or decoder frame +--- -# struct `scy::av::VideoPacket` +#### conv +```cpp +std::unique_ptr< VideoConverter > conv ``` -struct scy::av::VideoPacket - : public scy::av::MediaPacket -``` -Video packet for interleaved formats. +video conversion context +--- +#### time -## Summary +```cpp +int64_t time +``` - Members | Descriptions ---------------------------------|--------------------------------------------- -`public int width` | -`public int height` | -`public bool iframe` | -`public inline VideoPacket(uint8_t * data,size_t size,int width,int height,int64_t time)` | -`public inline VideoPacket(const `[`VideoPacket`](#structscy_1_1av_1_1VideoPacket)` & r)` | -`public inline virtual ~VideoPacket()` | -`public inline virtual `[`IPacket`](#classscy_1_1IPacket)` * clone() const` | -`public inline virtual const char * className() const` | +stream time in codec time base -## Members +--- -#### `public int width` +#### pts +```cpp +int64_t pts +``` +last packet pts value +--- +#### seconds -#### `public int height` +```cpp +double seconds +``` +video time in seconds +--- +#### error +```cpp +std::string error +``` -#### `public bool iframe` +error message +## VideoConverter +> **Defined in:** `videoconverter.h` +### Members +| Name | Description | +|------|-------------| +| [`VideoConverter`](#group__av_1gaf23c8c6da3e8c134d2732611511b0971) | | +| [`~VideoConverter`](#group__av_1ga219316cbdf4731474d84a7c6968816d2) | | +| [`create`](#group__av_1gaf043126e335328df0dea9122aba1adab) | | +| [`close`](#group__av_1ga03d0157af35129547a87d6c21431a9f4) | | +| [`convert`](#group__av_1ga3a3f64ca7f046bfab8f805753b644606) | | +| [`ctx`](#group__av_1ga862efcfb9c461be2de819548b8315c2b) | | +| [`oframe`](#group__av_1gaa02822cf5189d7f220247c6aab786898) | | +| [`iparams`](#group__av_1ga4869c5f4963a6f42cbc91e5000efa23c) | | +| [`oparams`](#group__av_1gafee51c12b018305ff22d056aed1dfd70) | | -#### `public inline VideoPacket(uint8_t * data,size_t size,int width,int height,int64_t time)` +--- +#### VideoConverter +```cpp +VideoConverter() +``` +--- +#### ~VideoConverter -#### `public inline VideoPacket(const `[`VideoPacket`](#structscy_1_1av_1_1VideoPacket)` & r)` +```cpp +virtual ~VideoConverter() +``` +--- +#### create +```cpp +virtual void create() +``` +--- -#### `public inline virtual ~VideoPacket()` +#### close +```cpp +virtual void close() +``` +--- +#### convert +```cpp +virtual AVFrame * convert(AVFrame * iframe) +``` -#### `public inline virtual `[`IPacket`](#classscy_1_1IPacket)` * clone() const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `iframe` | `AVFrame *` | | +--- +#### ctx +```cpp +SwsContext * ctx +``` +--- -#### `public inline virtual const char * className() const` +#### oframe +```cpp +AVFrame * oframe +``` +--- +#### iparams +```cpp +VideoCodec iparams +``` -# namespace `scy::av::legacy` +--- +#### oparams +```cpp +VideoCodec oparams +``` -## Summary +## VideoDecoder - Members | Descriptions ---------------------------------|--------------------------------------------- -`struct `[`scy::av::legacy::FPSCounter`](#structscy_1_1av_1_1legacy_1_1FPSCounter) | -# struct `scy::av::legacy::FPSCounter` +> **Extends:** `scy::av::VideoContext` +> **Defined in:** `videodecoder.h` +### Members +| Name | Description | +|------|-------------| +| [`VideoDecoder`](#group__av_1gaccadd97127e3ce1fd3f24ca533dee773) | | +| [`~VideoDecoder`](#group__av_1ga72037b0014cde348ee674b1cdd7c1f28) | | +| [`create`](#group__av_1ga302c5f9838c3770f1759455cbb684aeb) | Create the `AVCodecContext` using default values. | +| [`open`](#group__av_1ga015206763eca1d62ea6314a743cc1f23) | Open the `AVCodecContext` | +| [`close`](#group__av_1ga87067bb74819811c42d87a0cbd773c0e) | Close the `AVCodecContext` | +| [`decode`](#group__av_1ga8675b973c95f9231e3e3d8711776acac) | Decodes a the given input packet. Input packets should use the raw `AVStream` time base. Time base conversion will happen internally. Returns true an output packet was was decoded, false otherwise. | +| [`flush`](#group__av_1ga2c6f150d843783ca66fe0881a9f8192a) | Flushes buffered frames. This method should be called after decoding until false is returned. | +--- +#### VideoDecoder +```cpp +VideoDecoder(AVStream * stream) +``` -## Summary +| Parameter | Type | Description | +|-----------|------|-------------| +| `stream` | `AVStream *` | | - Members | Descriptions ---------------------------------|--------------------------------------------- -`public clock_t start` | -`public clock_t end` | -`public int64_t frames` | -`public double total` | -`public double fps` | -`public inline FPSCounter()` | -`public inline void tick()` | -`public inline void reset()` | -`public inline bool started()` | -`public inline void startFrame()` | -`public inline double endFrame()` | +--- -## Members +#### ~VideoDecoder -#### `public clock_t start` +```cpp +virtual ~VideoDecoder() +``` +--- +#### create +```cpp +virtual void create() +``` +Create the `AVCodecContext` using default values. -#### `public clock_t end` +--- +#### open +```cpp +virtual void open() +``` +Open the `AVCodecContext` +--- -#### `public int64_t frames` +#### close +```cpp +virtual void close() +``` +Close the `AVCodecContext` +--- +#### decode -#### `public double total` +```cpp +virtual bool decode(AVPacket & ipacket) +``` +Decodes a the given input packet. Input packets should use the raw `AVStream` time base. Time base conversion will happen internally. Returns true an output packet was was decoded, false otherwise. +| Parameter | Type | Description | +|-----------|------|-------------| +| `ipacket` | `AVPacket &` | | +--- +#### flush -#### `public double fps` +```cpp +virtual void flush() +``` +Flushes buffered frames. This method should be called after decoding until false is returned. +## VideoEncoder +> **Extends:** `scy::av::VideoContext` +> **Defined in:** `videoencoder.h` +### Members -#### `public inline FPSCounter()` +| Name | Description | +|------|-------------| +| [`VideoEncoder`](#group__av_1gab3440fe9140ed31e166d57692cd95e1b) | | +| [`~VideoEncoder`](#group__av_1ga5b4833959dc5406ae4119ed3e657d795) | | +| [`create`](#group__av_1gaa3eec3187025c245fd4958b6a376e99b) | Create the `AVCodecContext` using default values. | +| [`close`](#group__av_1gaf5cbf120cc0c08fb599a0ea002aa4427) | Close the `AVCodecContext` | +| [`encode`](#group__av_1gaf40c6ac2cee66007cf626350be51834c) | Encode a single video frame. This method is for interleaved video formats. | +| [`encode`](#group__av_1gaa0a72afd76c223b926107f6499fa93f3) | Encode a single video frame. This method is for planar video formats. | +| [`encode`](#group__av_1gac695c7a28cd3eabe9ec19c8abee1b2a9) | Encode a single AVFrame. | +| [`flush`](#group__av_1ga863e6269fe257b1261ee58db99305fb5) | Flush remaining packets to be encoded. This method should be called once before stream closure. | +| [`format`](#group__av_1gab300963e81559e48fd22562211edea3c) | | +--- +#### VideoEncoder +```cpp +VideoEncoder(AVFormatContext * format) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `format` | `AVFormatContext *` | | -#### `public inline void tick()` +--- +#### ~VideoEncoder +```cpp +virtual ~VideoEncoder() +``` +--- +#### create -#### `public inline void reset()` +```cpp +virtual void create() +``` +Create the `AVCodecContext` using default values. +--- +#### close +```cpp +virtual void close() +``` -#### `public inline bool started()` +Close the `AVCodecContext` +--- +#### encode +```cpp +virtual bool encode(uint8_t * data, int size, int64_t pts) +``` +Encode a single video frame. This method is for interleaved video formats. -#### `public inline void startFrame()` +#### Parameters +* `data` The raw video frame buffer. +* `size` The buffer size in bytes. +* `pts` The presentation timestamp in stream time base units. +| Parameter | Type | Description | +|-----------|------|-------------| +| `data` | `uint8_t *` | | +| `size` | `int` | | +| `pts` | `int64_t` | | +--- -#### `public inline double endFrame()` +#### encode +```cpp +virtual bool encode(uint8_t * data, int linesize, int64_t pts) +``` +Encode a single video frame. This method is for planar video formats. +#### Parameters +* `data` Array of per-plane data pointers (up to 4 planes). +* `linesize` Array of per-plane byte strides. -# struct `scy::av::RealtimePacketQueue::MediaPacketTimeCompare` +* `pts` The presentation timestamp in stream time base units. +| Parameter | Type | Description | +|-----------|------|-------------| +| `data` | `uint8_t *` | | +| `linesize` | `int` | | +| `pts` | `int64_t` | | +--- +#### encode +```cpp +virtual bool encode(AVFrame * iframe) +``` +Encode a single AVFrame. -## Summary +| Parameter | Type | Description | +|-----------|------|-------------| +| `iframe` | `AVFrame *` | | - Members | Descriptions ---------------------------------|--------------------------------------------- -`public inline bool operator()(const `[`MediaPacket`](#structscy_1_1av_1_1MediaPacket)` * a,const `[`MediaPacket`](#structscy_1_1av_1_1MediaPacket)` * b)` | +--- -## Members +#### flush -#### `public inline bool operator()(const `[`MediaPacket`](#structscy_1_1av_1_1MediaPacket)` * a,const `[`MediaPacket`](#structscy_1_1av_1_1MediaPacket)` * b)` +```cpp +virtual void flush() +``` +Flush remaining packets to be encoded. This method should be called once before stream closure. +--- +#### format +```cpp +AVFormatContext * format +``` diff --git a/doc/api-base.md b/doc/api-base.md index 26871ca59..b91bbd9aa 100644 --- a/doc/api-base.md +++ b/doc/api-base.md @@ -1,10435 +1,16710 @@ -# Module `base` +# base The `base` module contains reusable cross platform tools and utilities. -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`namespace `[`scy`](#namespacescy) | -`namespace `[`scy::base64`](#namespacescy_1_1base64) | -`namespace `[`scy::hex`](#namespacescy_1_1hex) | -`namespace `[`scy::basic`](#namespacescy_1_1basic) | Interface classes. -`namespace `[`scy::ipc`](#namespacescy_1_1ipc) | Classes for inter-process communication. -`namespace `[`scy::deleter`](#namespacescy_1_1deleter) | Deleter Functors. -`namespace `[`scy::test`](#namespacescy_1_1test) | Modern unit testing framework. -`namespace `[`scy::util`](#namespacescy_1_1util) | -`class `[`scy::GarbageCollector::Cleaner`](#classscy_1_1GarbageCollector_1_1Cleaner) | -`struct `[`scy::NVCollection::ILT`](#structscy_1_1NVCollection_1_1ILT) | -`struct `[`scy::Runner::Context`](#structscy_1_1Runner_1_1Context) | -# namespace `scy` - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`class `[`scy::AbstractCollection`](#classscy_1_1AbstractCollection) | -`class `[`scy::Application`](#classscy_1_1Application) | -`class `[`scy::AsyncLogWriter`](#classscy_1_1AsyncLogWriter) | [Thread](#classscy_1_1Thread) based log output stream writer. -`class `[`scy::AsyncPacketQueue`](#classscy_1_1AsyncPacketQueue) | -`class `[`scy::AsyncQueue`](#classscy_1_1AsyncQueue) | -`class `[`scy::BitReader`](#classscy_1_1BitReader) | Class for reading binary streams. -`class `[`scy::BitWriter`](#classscy_1_1BitWriter) | -`class `[`scy::Configuration`](#classscy_1_1Configuration) | -`class `[`scy::ConsoleChannel`](#classscy_1_1ConsoleChannel) | -`class `[`scy::ConstBuffer`](#classscy_1_1ConstBuffer) | -`class `[`scy::DateTime`](#classscy_1_1DateTime) | -`class `[`scy::DateTimeFormat`](#classscy_1_1DateTimeFormat) | -`class `[`scy::DateTimeFormatter`](#classscy_1_1DateTimeFormatter) | -`class `[`scy::DateTimeParser`](#classscy_1_1DateTimeParser) | -`class `[`scy::DynamicBitWriter`](#classscy_1_1DynamicBitWriter) | -`class `[`scy::FileChannel`](#classscy_1_1FileChannel) | -`class `[`scy::FlagPacket`](#classscy_1_1FlagPacket) | Packet for sending bitwise flags along the packet stream. -`class `[`scy::GarbageCollector`](#classscy_1_1GarbageCollector) | Garbage collector for safe memory management and deferred pointer deletion. -`class `[`scy::Idler`](#classscy_1_1Idler) | -`class `[`scy::IPacket`](#classscy_1_1IPacket) | -`class `[`scy::IPacketCreationStrategy`](#classscy_1_1IPacketCreationStrategy) | -`class `[`scy::KVCollection`](#classscy_1_1KVCollection) | Reusable stack based unique key-value store for DRY coding. -`class `[`scy::LiveCollection`](#classscy_1_1LiveCollection) | -`class `[`scy::LocalDateTime`](#classscy_1_1LocalDateTime) | -`class `[`scy::LogChannel`](#classscy_1_1LogChannel) | -`class `[`scy::Logger`](#classscy_1_1Logger) | [Logger](#classscy_1_1Logger) class. -`class `[`scy::LogWriter`](#classscy_1_1LogWriter) | Log output stream writer. -`class `[`scy::MutableBuffer`](#classscy_1_1MutableBuffer) | -`class `[`scy::Mutex`](#classscy_1_1Mutex) | -`class `[`scy::NVCollection`](#classscy_1_1NVCollection) | -`class `[`scy::PacketFactory`](#classscy_1_1PacketFactory) | -`class `[`scy::PacketProcessor`](#classscy_1_1PacketProcessor) | -`class `[`scy::PacketStream`](#classscy_1_1PacketStream) | -`class `[`scy::PacketStreamAdapter`](#classscy_1_1PacketStreamAdapter) | -`class `[`scy::PacketTransaction`](#classscy_1_1PacketTransaction) | -`class `[`scy::Pipe`](#classscy_1_1Pipe) | [Pipe](#classscy_1_1Pipe) implementation for process stdio. -`class `[`scy::PointerCollection`](#classscy_1_1PointerCollection) | -`class `[`scy::Process`](#classscy_1_1Process) | -`class `[`scy::Queue`](#classscy_1_1Queue) | Thread-safe queue container. -`class `[`scy::Random`](#classscy_1_1Random) | -`class `[`scy::RawPacket`](#classscy_1_1RawPacket) | -`class `[`scy::RotatingFileChannel`](#classscy_1_1RotatingFileChannel) | -`class `[`scy::RunnableQueue`](#classscy_1_1RunnableQueue) | -`class `[`scy::Runner`](#classscy_1_1Runner) | -`class `[`scy::ScopedConfiguration`](#classscy_1_1ScopedConfiguration) | -`class `[`scy::ScopedLock`](#classscy_1_1ScopedLock) | -`class `[`scy::ScopedPointer`](#classscy_1_1ScopedPointer) | Scoped Pointer Classes. -`class `[`scy::ScopedRawPointer`](#classscy_1_1ScopedRawPointer) | -`class `[`scy::ScopedSharedPointer`](#classscy_1_1ScopedSharedPointer) | -`class `[`scy::Signal`](#classscy_1_1Signal) | -`class `[`scy::Signal< RT(Args...)>`](#classscy_1_1Signal_3_01RT_07Args_8_8_8_08_4) | -`class `[`scy::Singleton`](#classscy_1_1Singleton) | -`class `[`scy::State`](#classscy_1_1State) | -`class `[`scy::Stateful`](#classscy_1_1Stateful) | -`class `[`scy::StopPropagation`](#classscy_1_1StopPropagation) | Exception to break out of the current [Signal](#classscy_1_1Signal) callback scope. -`class `[`scy::Stopwatch`](#classscy_1_1Stopwatch) | -`class `[`scy::Stream`](#classscy_1_1Stream) | Basic stream type for sockets and pipes. -`class `[`scy::StreamWriter`](#classscy_1_1StreamWriter) | -`class `[`scy::Synchronizer`](#classscy_1_1Synchronizer) | -`class `[`scy::SyncPacketQueue`](#classscy_1_1SyncPacketQueue) | -`class `[`scy::SyncQueue`](#classscy_1_1SyncQueue) | -`class `[`scy::Task`](#classscy_1_1Task) | -`class `[`scy::TaskRunner`](#classscy_1_1TaskRunner) | -`class `[`scy::Thread`](#classscy_1_1Thread) | -`class `[`scy::ThreadedStreamReader`](#classscy_1_1ThreadedStreamReader) | -`class `[`scy::TimedToken`](#classscy_1_1TimedToken) | Token that expires after the specified duration. -`class `[`scy::Timeout`](#classscy_1_1Timeout) | [Timeout](#classscy_1_1Timeout) counter which expires after a given delay. -`class `[`scy::Timer`](#classscy_1_1Timer) | Asynchronous event based timer. -`class `[`scy::Timespan`](#classscy_1_1Timespan) | A class that represents time spans up to microsecond resolution. -`class `[`scy::Timestamp`](#classscy_1_1Timestamp) | -`class `[`scy::Timezone`](#classscy_1_1Timezone) | This class provides information about the current timezone. -`class `[`scy::TZInfo`](#classscy_1_1TZInfo) | -`struct `[`scy::AbstractDelegate`](#structscy_1_1AbstractDelegate) | -`struct `[`scy::Bitwise`](#structscy_1_1Bitwise) | Container for smart management of bitwise integer flags. -`struct `[`scy::ClassDelegate`](#structscy_1_1ClassDelegate) | -`struct `[`scy::ConnectReq`](#structscy_1_1ConnectReq) | [Stream](#classscy_1_1Stream) connection request for sockets and pipes. -`struct `[`scy::ConstClassDelegate`](#structscy_1_1ConstClassDelegate) | -`struct `[`scy::Error`](#structscy_1_1Error) | -`struct `[`scy::FunctionDelegate`](#structscy_1_1FunctionDelegate) | -`struct `[`scy::IPacketInfo`](#structscy_1_1IPacketInfo) | -`struct `[`scy::LogStream`](#structscy_1_1LogStream) | -`struct `[`scy::OptionParser`](#structscy_1_1OptionParser) | -`struct `[`scy::PacketAdapterReference`](#structscy_1_1PacketAdapterReference) | For 0.8.x compatibility. -`struct `[`scy::PacketCreationStrategy`](#structscy_1_1PacketCreationStrategy) | -`struct `[`scy::PacketStreamState`](#structscy_1_1PacketStreamState) | -`struct `[`scy::PolymorphicDelegate`](#structscy_1_1PolymorphicDelegate) | -`struct `[`scy::SharedLibrary`](#structscy_1_1SharedLibrary) | -`struct `[`scy::ShutdownCmd`](#structscy_1_1ShutdownCmd) | -`struct `[`scy::TransactionState`](#structscy_1_1TransactionState) | -# class `scy::AbstractCollection` - +### Classes + +| Name | Description | +|------|-------------| +| [`Thread`](#classscy_1_1Thread) | This class implements a platform-independent wrapper around an operating system thread. | +| [`Application`](#classscy_1_1Application) | Main LibSourcey application class. | +| [`MutableBuffer`](#classscy_1_1MutableBuffer) | The [MutableBuffer](#classscy_1_1MutableBuffer) class provides a safe representation of a buffer that can be modified. It does not own the underlying data, and so is cheap to copy or assign. | +| [`ConstBuffer`](#classscy_1_1ConstBuffer) | The [ConstBuffer](#classscy_1_1ConstBuffer) class provides a safe representation of a buffer that cannot be modified. It does not own the underlying data, and so is cheap to copy or assign. | +| [`BitReader`](#classscy_1_1BitReader) | Class for reading binary streams. | +| [`BitWriter`](#classscy_1_1BitWriter) | Class for reading/writing binary streams. | +| [`DynamicBitWriter`](#classscy_1_1DynamicBitWriter) | Class for reading/writing dynamically resizable binary streams. | +| [`AbstractCollection`](#classscy_1_1AbstractCollection) | [AbstractCollection](#classscy_1_1AbstractCollection) is an abstract interface for managing a key-value store of indexed pointers. | +| [`PointerCollection`](#classscy_1_1PointerCollection) | This collection is used to maintain a map of unique_ptr values indexed by key in a thread-safe way. | +| [`LiveCollection`](#classscy_1_1LiveCollection) | | +| [`KVCollection`](#classscy_1_1KVCollection) | Reusable stack based unique key-value store for DRY coding. | +| [`NVCollection`](#classscy_1_1NVCollection) | A storage container for a name value collections. This collection can store multiple entries for each name, and it's getters are case-insensitive. | +| [`Configuration`](#classscy_1_1Configuration) | [Configuration](#classscy_1_1Configuration) is an abstract base class for managing different kinds of configuration storage back ends such as JSON, XML, or database. | +| [`ScopedConfiguration`](#classscy_1_1ScopedConfiguration) | [ScopedConfiguration](#classscy_1_1ScopedConfiguration) provides multiple levels of configuration for a module. Multiple levels means that there is a module level scope, and a default scope. When a property is accessed, the module scope value will be used if available, otherwise the default scope value will be used. | +| [`Timestamp`](#classscy_1_1Timestamp) | A [Timestamp](#classscy_1_1Timestamp) stores a monotonic* time value with (theoretical) microseconds resolution. Timestamps can be compared with each other and simple arithmetics are supported. | +| [`Timespan`](#classscy_1_1Timespan) | A class that represents time spans up to microsecond resolution. | +| [`DateTime`](#classscy_1_1DateTime) | This class represents an instant in time, expressed in years, months, days, hours, minutes, seconds and milliseconds based on the Gregorian calendar. The class is mainly useful for conversions between UTC, Julian day and Gregorian calendar dates. | +| [`Timezone`](#classscy_1_1Timezone) | This class provides information about the current timezone. | +| [`LocalDateTime`](#classscy_1_1LocalDateTime) | This class represents an instant in local time (as opposed to UTC), expressed in years, months, days, hours, minutes, seconds and milliseconds based on the Gregorian calendar. | +| [`DateTimeFormat`](#classscy_1_1DateTimeFormat) | Definition of date/time formats and various constants used by [DateTimeFormatter](#classscy_1_1DateTimeFormatter) and [DateTimeParser](#classscy_1_1DateTimeParser). | +| [`DateTimeFormatter`](#classscy_1_1DateTimeFormatter) | This class converts dates and times into strings, supporting a variety of standard and custom formats. | +| [`DateTimeParser`](#classscy_1_1DateTimeParser) | This class provides a method for parsing dates and times from strings. All parsing methods do their best to parse a meaningful result, even from malformed input strings. | +| [`Stopwatch`](#classscy_1_1Stopwatch) | A simple facility to measure time intervals with microsecond resolution. | +| [`Idler`](#classscy_1_1Idler) | Asynchronous type that triggers callbacks when the event loop is idle. | +| [`Decoder`](#classscy_1_1basic_1_1Decoder) | | +| [`Encoder`](#classscy_1_1basic_1_1Encoder) | | +| [`Runnable`](#classscy_1_1basic_1_1Runnable) | Abstract interface for classes that can be run and cancelled. | +| [`Startable`](#classscy_1_1basic_1_1Startable) | Abstract interface for a classes that can be started and stopped. | +| [`Sendable`](#classscy_1_1basic_1_1Sendable) | Abstract interface for classes that can be sent and cancelled. | +| [`Queue`](#classscy_1_1ipc_1_1Queue) | IPC queue is for safely passing templated actions between threads and processes. | +| [`SyncQueue`](#classscy_1_1ipc_1_1SyncQueue) | IPC synchronization queue is for passing templated actions between threads and the event loop we are synchronizing with. | +| [`LogWriter`](#classscy_1_1LogWriter) | Log output stream writer. | +| [`AsyncLogWriter`](#classscy_1_1AsyncLogWriter) | [Thread](#classscy_1_1Thread) based log output stream writer. | +| [`Logger`](#classscy_1_1Logger) | [Logger](#classscy_1_1Logger) class. | +| [`LogChannel`](#classscy_1_1LogChannel) | | +| [`ConsoleChannel`](#classscy_1_1ConsoleChannel) | | +| [`FileChannel`](#classscy_1_1FileChannel) | | +| [`RotatingFileChannel`](#classscy_1_1RotatingFileChannel) | | +| [`IPacket`](#classscy_1_1IPacket) | The basic packet type which is passed around the LibSourcey system. [IPacket](#classscy_1_1IPacket) can be extended for each protocol to enable polymorphic processing and callbacks using [PacketStream](#classscy_1_1PacketStream) and friends. | +| [`FlagPacket`](#classscy_1_1FlagPacket) | Packet for sending bitwise flags along the packet stream. | +| [`RawPacket`](#classscy_1_1RawPacket) | [RawPacket](#classscy_1_1RawPacket) is the default data packet type which consists of an optionally managed char pointer and a size value. | +| [`IPacketCreationStrategy`](#classscy_1_1IPacketCreationStrategy) | | +| [`PacketFactory`](#classscy_1_1PacketFactory) | | +| [`ThreadedStreamReader`](#classscy_1_1ThreadedStreamReader) | Threaded stream reader class. | +| [`StreamWriter`](#classscy_1_1StreamWriter) | Packet stream writer class. | +| [`SyncPacketQueue`](#classscy_1_1SyncPacketQueue) | | +| [`AsyncPacketQueue`](#classscy_1_1AsyncPacketQueue) | | +| [`PacketStreamAdapter`](#classscy_1_1PacketStreamAdapter) | This class is a wrapper for integrating external classes with the a [PacketStream](#classscy_1_1PacketStream)'s data flow and state machine. | +| [`PacketProcessor`](#classscy_1_1PacketProcessor) | This class is a virtual interface for creating PacketStreamAdapters which process that and emit the [IPacket](#classscy_1_1IPacket) type. | +| [`PacketStream`](#classscy_1_1PacketStream) | This class is used for processing and boradcasting IPackets in a flexible way. A [PacketStream](#classscy_1_1PacketStream) consists of one or many PacketSources, one or many PacketProcessors, and one or many delegate receivers. | +| [`PacketTransaction`](#classscy_1_1PacketTransaction) | This class provides request/response functionality for [IPacket](#classscy_1_1IPacket) types. | +| [`Pipe`](#classscy_1_1Pipe) | [Pipe](#classscy_1_1Pipe) implementation for process stdio. | +| [`Process`](#classscy_1_1Process) | | +| [`Queue`](#classscy_1_1Queue) | Thread-safe queue container. | +| [`RunnableQueue`](#classscy_1_1RunnableQueue) | | +| [`SyncQueue`](#classscy_1_1SyncQueue) | [SyncQueue](#classscy_1_1SyncQueue) extends [Synchronizer](#classscy_1_1Synchronizer) to implement a synchronized FIFO queue which receives T objects from any thread and synchronizes them for safe consumption by the associated event loop. | +| [`AsyncQueue`](#classscy_1_1AsyncQueue) | [AsyncQueue](#classscy_1_1AsyncQueue) is a thread-based queue which receives packets from any thread source and dispatches them asynchronously. | +| [`Random`](#classscy_1_1Random) | [Random](#classscy_1_1Random) implements a pseudo random number generator (PRNG). The PRNG is a nonlinear additive feedback random number generator using 256 bytes of state information and a period of up to 2^69. | +| [`Runner`](#classscy_1_1Runner) | [Runner](#classscy_1_1Runner) is a virtual interface for implementing asynchronous objects such as threads and futures. | +| [`StopPropagation`](#classscy_1_1StopPropagation) | Exception to break out of the current [Signal](#classscy_1_1Signal) callback scope. | +| [`Signal`](#classscy_1_1Signal) | [Signal](#classscy_1_1Signal) and slots implementation. | +| [`Signal< RT(Args...)>`](#classscy_1_1Signal_3_01RT_07Args_8_8_8_08_4) | | +| [`Singleton`](#classscy_1_1Singleton) | Helper template class for managing singleton objects allocated on the heap. | +| [`State`](#classscy_1_1State) | [State](#classscy_1_1State) class for state machines. | +| [`Stateful`](#classscy_1_1Stateful) | [State](#classscy_1_1State) machine implementation. | +| [`Stream`](#classscy_1_1Stream) | Basic stream type for sockets and pipes. | +| [`Synchronizer`](#classscy_1_1Synchronizer) | [Synchronizer](#classscy_1_1Synchronizer) enables any thread to communicate with the associated event loop via synchronized callbacks. | +| [`Task`](#classscy_1_1Task) | Abstract class is for implementing any kind asyncronous task. | +| [`TaskRunner`](#classscy_1_1TaskRunner) | [Runner](#classscy_1_1Runner) for tasks that inherit the `[Task](#classscy_1_1Task)` interface. | +| [`Test`](#classscy_1_1test_1_1Test) | [Test](#classscy_1_1test_1_1Test) wrapper class. | +| [`FunctionTest`](#classscy_1_1test_1_1FunctionTest) | | +| [`TestRunner`](#classscy_1_1test_1_1TestRunner) | [Test](#classscy_1_1test_1_1Test) manager queue. | +| [`Timer`](#classscy_1_1Timer) | Asynchronous event based timer. | +| [`TZInfo`](#classscy_1_1TZInfo) | | +| [`Timeout`](#classscy_1_1Timeout) | [Timeout](#classscy_1_1Timeout) counter which expires after a given delay. | +| [`TimedToken`](#classscy_1_1TimedToken) | Token that expires after the specified duration. | +| [`OptionParser`](#structscy_1_1OptionParser) | | +| [`ShutdownCmd`](#structscy_1_1ShutdownCmd) | | +| [`Encoder`](#structscy_1_1base64_1_1Encoder) | Base64 encoder. | +| [`Decoder`](#structscy_1_1base64_1_1Decoder) | Base64 decoder. | +| [`Bitwise`](#structscy_1_1Bitwise) | Container for smart management of bitwise integer flags. | +| [`ILT`](#structscy_1_1NVCollection_1_1ILT) | | +| [`AbstractDelegate`](#structscy_1_1AbstractDelegate) | Abstract delegate interface. | +| [`FunctionDelegate`](#structscy_1_1FunctionDelegate) | The `[FunctionDelegate](#structscy_1_1FunctionDelegate)` contains a `std::function`. | +| [`ClassDelegate`](#structscy_1_1ClassDelegate) | The `[ClassDelegate](#structscy_1_1ClassDelegate)` contains a pointer to a class member. | +| [`ConstClassDelegate`](#structscy_1_1ConstClassDelegate) | The `[ConstClassDelegate](#structscy_1_1ConstClassDelegate)` contains a pointer to a `const` class member. | +| [`PolymorphicDelegate`](#structscy_1_1PolymorphicDelegate) | Polymorphic function delegate. | +| [`Error`](#structscy_1_1Error) | Basic error type. | +| [`Encoder`](#structscy_1_1hex_1_1Encoder) | Hex encoder. | +| [`Decoder`](#structscy_1_1hex_1_1Decoder) | Hex decoder. | +| [`Action`](#structscy_1_1ipc_1_1Action) | Default action type for executing synchronized callbacks. | +| [`LogStream`](#structscy_1_1LogStream) | | +| [`Dispose`](#structscy_1_1deleter_1_1Dispose) | Deleter functor that calls dispose() on the pointer. | +| [`Array`](#structscy_1_1deleter_1_1Array) | Deleter functor for array pointers. | +| [`IPacketInfo`](#structscy_1_1IPacketInfo) | An abstract interface for packet sources to provide extra information about packets. | +| [`PacketCreationStrategy`](#structscy_1_1PacketCreationStrategy) | This template class implements an adapter that sits between an SignalBase and an object receiving notifications from it. | +| [`PacketAdapterReference`](#structscy_1_1PacketAdapterReference) | Provides a reference to a [PacketStreamAdapter](#classscy_1_1PacketStreamAdapter) with optional ownership. | +| [`PacketStreamState`](#structscy_1_1PacketStreamState) | | +| [`TransactionState`](#structscy_1_1TransactionState) | | +| [`Context`](#structscy_1_1Runner_1_1Context) | [Context](#structscy_1_1Runner_1_1Context) object which we send to the thread context. | +| [`SharedLibrary`](#structscy_1_1SharedLibrary) | | +| [`Deleter`](#structscy_1_1Singleton_1_1Deleter) | Custom deleter that can access private destructors via friendship. | +| [`Version`](#structscy_1_1util_1_1Version) | | + +### Members + +| Name | Description | +|------|-------------| +| [`__CLASS_FUNCTION__`](#group__base_1ga59a5ffd42b19d28fe2cdd703647ea267) | | +| [`STrace`](#group__base_1ga8fa36ad681be913ccc80568b5e1b707e) | | +| [`SDebug`](#group__base_1ga994543ef28923f7e79a42280b974e57a) | | +| [`SInfo`](#group__base_1ga428be2b940a54979e08fe97c9511f70f) | | +| [`SWarn`](#group__base_1ga4e70a349e149eaf8d719346d98ccc3e8) | | +| [`SError`](#group__base_1ga3d49c78b4f5f794c1fb59e44fc3cdefc) | | +| [`LTrace`](#group__base_1gad99562e79a8f5d76e2a364dee4b0ac9c) | | +| [`LDebug`](#group__base_1ga8f15acfec2db055b15d9dab7b6975210) | | +| [`LInfo`](#group__base_1gaaec3c38855627fda219c81a8cd509a68) | | +| [`LWarn`](#group__base_1ga487f424982fc03d4a52e0b03efedc855) | | +| [`LError`](#group__base_1ga10b47e965290e0f238a4e6ce711b1b3e) | | +| [`expect`](#group__base_1ga92645105a4c87ac01db7587df58caca6) | | +| [`TYPE_0`](#group__base_1ga7684fdb8b359fbbbcaa5e149704024b3) | | +| [`BREAK_0`](#group__base_1ga3c1b328e567007cf8b2a488f7da20cd2) | | +| [`DEG_0`](#group__base_1ga4b02509c5d048cb2525e0066d7c2f191) | | +| [`SEP_0`](#group__base_1gae66d150b37bdc4fb534c6cf4fd6927f5) | | +| [`TYPE_1`](#group__base_1gadf00e147e54d287fe67232fc3c03881f) | | +| [`BREAK_1`](#group__base_1ga2f8ab1a0f7425aaa202c501115ac97ac) | | +| [`DEG_1`](#group__base_1ga0be2834c56b0aaa7a6d34986f7921200) | | +| [`SEP_1`](#group__base_1ga706a88d02086f617d9a4112903e47e41) | | +| [`TYPE_2`](#group__base_1ga8fde5bf4966bf8bead39337acde60635) | | +| [`BREAK_2`](#group__base_1ga05b3315f5cfe0296dcd69a52f1655c6d) | | +| [`DEG_2`](#group__base_1ga3ac87cdf960466ff1225acc151e1b990) | | +| [`SEP_2`](#group__base_1ga7af722c75c13c22d73bbcca1088b8dfa) | | +| [`TYPE_3`](#group__base_1ga625df8982f188845257d31ea0e6c59e3) | | +| [`BREAK_3`](#group__base_1gae301c8961d39d5bb4f771779e7f892a5) | | +| [`DEG_3`](#group__base_1ga551433e25d99861799734a5d64404a75) | | +| [`SEP_3`](#group__base_1ga2edba143f3e114a7eb2e12e87cd22168) | | +| [`TYPE_4`](#group__base_1ga1eea18b6fa0e026859776264e7b70d06) | | +| [`BREAK_4`](#group__base_1ga5b20d74b1c51063cf48aac12871c508b) | | +| [`DEG_4`](#group__base_1gaa5908dcf53ecbe2f7e9ba5c3ffca01c1) | | +| [`SEP_4`](#group__base_1ga579e3bd1ae8bb600f9eab886a82bf075) | | + +--- + +#### __CLASS_FUNCTION__ + +```cpp +__CLASS_FUNCTION__() +``` +--- +#### STrace -[AbstractCollection](#classscy_1_1AbstractCollection) is an abstract interface for managing a key-value store of indexed pointers. +```cpp +STrace() +``` -## Summary +--- - Members | Descriptions ---------------------------------|--------------------------------------------- -`public inline AbstractCollection()` | -`public inline virtual ~AbstractCollection()` | -`public bool add(const TKey & key,TValue * item,bool whiny)` | -`public bool remove(const TValue * item)` | -`public TValue * remove(const TKey & key)` | -`public bool exists(const TKey & key) const` | -`public bool exists(const TValue * item) const` | -`public bool free(const TKey & key)` | -`public bool empty() const` | -`public size_t size() const` | -`public TValue * get(const TKey & key,bool whiny) const` | -`public void clear()` | +#### SDebug -## Members +```cpp +SDebug() +``` -#### `public inline AbstractCollection()` +--- +#### SInfo +```cpp +SInfo() +``` +--- +#### SWarn -#### `public inline virtual ~AbstractCollection()` +```cpp +SWarn() +``` +--- +#### SError +```cpp +SError() +``` +--- -#### `public bool add(const TKey & key,TValue * item,bool whiny)` +#### LTrace +```cpp +LTrace() +``` +--- +#### LDebug +```cpp +LDebug() +``` -#### `public bool remove(const TValue * item)` +--- +#### LInfo +```cpp +LInfo() +``` +--- +#### LWarn -#### `public TValue * remove(const TKey & key)` +```cpp +LWarn() +``` +--- +#### LError +```cpp +LError() +``` +--- -#### `public bool exists(const TKey & key) const` +#### expect +```cpp +expect() +``` +--- +#### TYPE_0 +```cpp +TYPE_0() +``` -#### `public bool exists(const TValue * item) const` +--- +#### BREAK_0 +```cpp +BREAK_0() +``` +--- +#### DEG_0 -#### `public bool free(const TKey & key)` +```cpp +DEG_0() +``` +--- +#### SEP_0 +```cpp +SEP_0() +``` +--- -#### `public bool empty() const` +#### TYPE_1 +```cpp +TYPE_1() +``` +--- +#### BREAK_1 +```cpp +BREAK_1() +``` -#### `public size_t size() const` +--- +#### DEG_1 +```cpp +DEG_1() +``` +--- +#### SEP_1 -#### `public TValue * get(const TKey & key,bool whiny) const` +```cpp +SEP_1() +``` +--- +#### TYPE_2 +```cpp +TYPE_2() +``` +--- -#### `public void clear()` +#### BREAK_2 +```cpp +BREAK_2() +``` +--- +#### DEG_2 +```cpp +DEG_2() +``` -# class `scy::Application` +--- +#### SEP_2 +```cpp +SEP_2() +``` +--- -Main LibSourcey application class. +#### TYPE_3 -This class exposes basic features required by most applications: +```cpp +TYPE_3() +``` +--- +#### BREAK_3 -* Running the event loop +```cpp +BREAK_3() +``` +--- -* Command line option parsing -**See also**: [OptionParser](#structscy_1_1OptionParser) +#### DEG_3 +```cpp +DEG_3() +``` +--- +#### SEP_3 -* Shutdown signal (Ctrl-C) handling +```cpp +SEP_3() +``` +--- -* Garbage collection +#### TYPE_4 -## Summary +```cpp +TYPE_4() +``` - Members | Descriptions ---------------------------------|--------------------------------------------- -`public uv::Loop * loop` | -`public Application(uv::Loop * loop)` | Constructor. -`public ~Application()` | Destructor. -`public void run()` | Run the application event loop. -`public void stop()` | Stop the application event loop. -`public void finalize()` | -`public void waitForShutdown(std::function< void(void *)> callback,void * opaque)` | Bind the shutdown signal and run the main event loop. -`public void bindShutdownSignal(std::function< void(void *)> callback,void * opaque)` | Bind the shutdown signal. -`protected Application(const `[`Application`](#classscy_1_1Application)` &) = delete` | -`protected `[`Application`](#classscy_1_1Application)` & operator=(const `[`Application`](#classscy_1_1Application)` &) = delete` | +--- -## Members +#### BREAK_4 -#### `public uv::Loop * loop` +```cpp +BREAK_4() +``` +--- +#### DEG_4 -Active event loop. +```cpp +DEG_4() +``` -The event loop may be assigned on construction, otherwise the default event loop will be used. +--- -#### `public Application(uv::Loop * loop)` +#### SEP_4 -Constructor. +```cpp +SEP_4() +``` +## Thread +> **Extends:** `scy::Runner`, `scy::Runner` +> **Defined in:** `thread.h` -#### `public ~Application()` +This class implements a platform-independent wrapper around an operating system thread. -Destructor. +Platform-independent wrapper around an operating system thread. +This class inherits the `[Runner](#classscy_1_1Runner)` interface and may be used with any implementation that's powered by an asynchronous `[Runner](#classscy_1_1Runner)`. +### Members + +| Name | Description | +|------|-------------| +| [`Thread`](#group__base_1ga54fd807dcf46e13b7740713f24487816) | | +| [`Thread`](#group__base_1gabed246ada7fd8383ba003ddfaff44673) | | +| [`Thread`](#group__base_1gab5b31ddaa4aac8464c14ff69a30ff8e0) | | +| [`Thread`](#group__base_1gae77a1fdf6ad50532ade119cfad1fff28) | | +| [`~Thread`](#group__base_1gaf8d1a393d2f0130b0e8d3e634f50c125) | | +| [`join`](#group__base_1gad5b13af2dd59884809566c8f95a99f16) | Waits until the thread exits. | +| [`waitForExit`](#group__base_1ga60b2ef4860d9cb68ec601d95a35b38b5) | Waits until the thread exits. | +| [`id`](#group__base_1gad3ac929d47e0dcadc5f106473d11a148) | Returns the native thread handle. | +| [`Thread`](#group__base_1ga03f23cddda2cf51b3306eb94f24492bc) | Templated constructor. | +| [`start`](#group__base_1gac61d598778274d3c6b8342cad1d869c7) | Start a function with veradic arguments. | +| [`start`](#group__base_1ga5f7fb6da8dc9da113fdc20de6f336c3b) | Start the asynchronous context with the given void function. | +| [`currentID`](#group__base_1ga5c4c221bb4c25036320d22087f72a355) | Returns the native thread ID of the current thread. | +| [`Thread`](#group__base_1ga2db47dac5c43119f6254de56f3c1c7ad) | NonCopyable and NonMovable. | +| [`operator=`](#group__base_1ga5eb15190777fefe4728f8bc2eaf1817e) | | +| [`async`](#group__base_1gac9ec059f9ffbd29d9790a7f95c5c5d21) | Returns true if the implementation is thread-based, or false if it belongs to an event loop. | +| [`startAsync`](#group__base_1gaf0bc2b6aec6123dc914966507326c61d) | | +| [`mainID`](#group__base_1ga61fbd13a4564ad111609b13ec008ef91) | Accessor for the main thread ID. | +| [`_handle`](#group__base_1ga4f306e5416331b9b4131adfc0f45c908) | | +| [`_thread`](#group__base_1gac600f9a3aefe15106420b37be988b062) | | +| [`Thread`](#classscy_1_1Thread_1ga54fd807dcf46e13b7740713f24487816) | Default constructor. | +| [`~Thread`](#classscy_1_1Thread_1gaf8d1a393d2f0130b0e8d3e634f50c125) | Destructor. | +| [`join`](#classscy_1_1Thread_1gad5b13af2dd59884809566c8f95a99f16) | Wait until the thread exits. | +| [`id`](#classscy_1_1Thread_1gad3ac929d47e0dcadc5f106473d11a148) | Return the native thread handle. | +| [`currentID`](#classscy_1_1Thread_1ga5c4c221bb4c25036320d22087f72a355) | Return the native thread ID of the current thread. | +| [`Thread`](#classscy_1_1Thread_1ga2db47dac5c43119f6254de56f3c1c7ad) | NonCopyable and NonMovable. | +| [`operator=`](#classscy_1_1Thread_1ga5eb15190777fefe4728f8bc2eaf1817e) | | +| [`async`](#classscy_1_1Thread_1gac9ec059f9ffbd29d9790a7f95c5c5d21) | Returns true if the implementation is thread-based, or false if it belongs to an event loop. | + +--- + +#### Thread + +```cpp +Thread() +``` -#### `public void run()` +--- -Run the application event loop. +#### Thread +```cpp +Thread(basic::Runnable & target) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `target` | `basic::Runnable &` | | -#### `public void stop()` +--- -Stop the application event loop. +#### Thread +```cpp +Thread(std::function< void()> target) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `target` | `std::function< void()>` | | -#### `public void finalize()` +--- +#### Thread +```cpp +Thread(std::function< void(void *)> target, void * arg) +``` -Finalize and free any remaining pointers still held by the application event loop. +| Parameter | Type | Description | +|-----------|------|-------------| +| `target` | `std::function< void(void *)>` | | +| `arg` | `void *` | | -#### `public void waitForShutdown(std::function< void(void *)> callback,void * opaque)` +--- -Bind the shutdown signal and run the main event loop. +#### ~Thread +```cpp +virtual ~Thread() +``` +--- -#### `public void bindShutdownSignal(std::function< void(void *)> callback,void * opaque)` +#### join -Bind the shutdown signal. +```cpp +void join() +``` +Waits until the thread exits. +--- -#### `protected Application(const `[`Application`](#classscy_1_1Application)` &) = delete` +#### waitForExit +```cpp +bool waitForExit(int timeout) +``` +Waits until the thread exits. +The thread should be cancelled beore calling this method. This method must be called from outside the current thread context or deadlock will ensue. +| Parameter | Type | Description | +|-----------|------|-------------| +| `timeout` | `int` | | -#### `protected `[`Application`](#classscy_1_1Application)` & operator=(const `[`Application`](#classscy_1_1Application)` &) = delete` +--- +#### id +```cpp +uv_thread_t id() const +``` +Returns the native thread handle. +--- -# class `scy::AsyncLogWriter` +#### Thread +```cpp +template inline explicit Thread(Function && func, Args &&... args) ``` -class scy::AsyncLogWriter - : public scy::LogWriter - : public scy::basic::Runnable -``` - -[Thread](#classscy_1_1Thread) based log output stream writer. +Templated constructor. +This constructor starts the thread with the given function. -## Summary +| Parameter | Type | Description | +|-----------|------|-------------| +| `func` | `Function &&` | | +| `args` | `Args &&...` | | - Members | Descriptions ---------------------------------|--------------------------------------------- -`public AsyncLogWriter()` | -`public virtual ~AsyncLogWriter()` | -`public virtual void write(`[`LogStream`](#structscy_1_1LogStream)` * stream)` | Queues the given log message stream. -`public void flush()` | Flushes queued messages. -`public virtual void run()` | Writes queued messages asynchronously. -`public void clear()` | Clears all queued messages. -`protected `[`Thread`](./doc/api-base.md#classscy_1_1Thread)` _thread` | -`protected std::deque< `[`LogStream`](./doc/api-base.md#structscy_1_1LogStream)` * > _pending` | -`protected mutable std::mutex _mutex` | -`protected bool writeNext()` | +--- -## Members +#### start -#### `public AsyncLogWriter()` +```cpp +template inline void start(Function && func, Args &&... args) +``` +Start a function with veradic arguments. +This method starts the thread with the given function. +| Parameter | Type | Description | +|-----------|------|-------------| +| `func` | `Function &&` | | +| `args` | `Args &&...` | | +--- -#### `public virtual ~AsyncLogWriter()` +#### start +```cpp +virtual void start(std::function< void()> func) +``` +Start the asynchronous context with the given void function. +| Parameter | Type | Description | +|-----------|------|-------------| +| `func` | `std::function< void()>` | | +--- -#### `public virtual void write(`[`LogStream`](#structscy_1_1LogStream)` * stream)` +#### currentID -Queues the given log message stream. +```cpp +static uv_thread_t currentID() +``` +Returns the native thread ID of the current thread. +--- -#### `public void flush()` +#### Thread -Flushes queued messages. +```cpp +Thread(const Thread &) = delete +``` +NonCopyable and NonMovable. +--- -#### `public virtual void run()` +#### operator= -Writes queued messages asynchronously. +```cpp +Thread & operator=(const Thread &) = delete +``` +--- +#### async -#### `public void clear()` +```cpp +virtual bool async() const +``` -Clears all queued messages. +Returns true if the implementation is thread-based, or false if it belongs to an event loop. +--- +#### startAsync -#### `protected `[`Thread`](./doc/api-base.md#classscy_1_1Thread)` _thread` +```cpp +virtual void startAsync() +``` +--- +#### mainID +```cpp +const std::thread::id mainID = uv_thread_self() +``` +Accessor for the main thread ID. -#### `protected std::deque< `[`LogStream`](./doc/api-base.md#structscy_1_1LogStream)` * > _pending` +--- +#### _handle +```cpp +uv_thread_t _handle +``` +--- +#### _thread -#### `protected mutable std::mutex _mutex` +```cpp +std::thread _thread +``` +--- +#### Thread +```cpp +Thread() +``` +Default constructor. -#### `protected bool writeNext()` +--- +#### ~Thread +```cpp +virtual ~Thread() +``` +Destructor. +--- -# class `scy::AsyncPacketQueue` +#### join +```cpp +void join() ``` -class scy::AsyncPacketQueue - : public scy::AsyncQueue< T > - : public scy::PacketProcessor -``` +Wait until the thread exits. + +--- +#### id + +```cpp +std::thread::id id() const +``` + +Return the native thread handle. +--- +#### currentID -## Summary +```cpp +static std::thread::id currentID() +``` - Members | Descriptions ---------------------------------|--------------------------------------------- -`public `[`PacketSignal`](#group__base_1ga3ffb5bda6133fac97f3bed2b567b9b6a)` emitter` | -`public inline AsyncPacketQueue(int maxSize)` | -`public inline virtual ~AsyncPacketQueue()` | -`public inline virtual void close()` | -`public inline virtual void process(`[`IPacket`](#classscy_1_1IPacket)` & packet)` | -`public inline virtual bool accepts(`[`IPacket`](#classscy_1_1IPacket)` * packet)` | -`protected inline virtual void dispatch(T & item)` | Dispatch a single item to listeners. -`protected inline virtual void onStreamStateChange(const `[`PacketStreamState`](#structscy_1_1PacketStreamState)` &)` | +Return the native thread ID of the current thread. -## Members +--- -#### `public `[`PacketSignal`](#group__base_1ga3ffb5bda6133fac97f3bed2b567b9b6a)` emitter` +#### Thread +```cpp +Thread(const [Thread](#classscy_1_1Thread) &) = delete +``` +NonCopyable and NonMovable. +--- +#### operator= -#### `public inline AsyncPacketQueue(int maxSize)` +```cpp +[Thread](#classscy_1_1Thread) & operator=(const [Thread](#classscy_1_1Thread) &) = delete +``` +--- +#### async +```cpp +virtual bool async() const +``` +Returns true if the implementation is thread-based, or false if it belongs to an event loop. -#### `public inline virtual ~AsyncPacketQueue()` +## Application +> **Defined in:** `application.h` +Main LibSourcey application class. +This class exposes basic features required by most applications: +* Running the event loop -#### `public inline virtual void close()` +* Command line option parsing **See also**: [OptionParser](#structscy_1_1OptionParser) +* Shutdown signal (Ctrl-C) handling +* Garbage collection +### Members + +| Name | Description | +|------|-------------| +| [`Application`](#group__base_1gadb808e26528e18856d2896a3ce7947ca) | Constructor. | +| [`~Application`](#group__base_1ga0aafa241a2debe7409ae096420068d1e) | Destructor. | +| [`run`](#group__base_1gacf3f29800455e5d360a19b9c8fe66241) | Run the application event loop. | +| [`stop`](#group__base_1ga830f616291457503049f9fc9d1a3f8ba) | Stop the application event loop. | +| [`finalize`](#group__base_1gae94cf187f38a9accf0abdffc868e700a) | Finalize and free any remaining pointers still held by the application event loop. | +| [`waitForShutdown`](#group__base_1ga648ccd97eb0acd73cb4dc0b2b4ae030a) | Bind the shutdown signal and run the main event loop. | +| [`bindShutdownSignal`](#group__base_1ga80ca3367db09fde58ffec5b3b17ce960) | Bind the shutdown signal. | +| [`getDefault`](#group__base_1ga5db9db61083ba33fdfdbd5c8082aba19) | Returns the default [Application](#classscy_1_1Application) singleton, although [Application](#classscy_1_1Application) instances may be initialized individually. | +| [`Application`](#group__base_1gad2a86916a222902d29c639cc5daa9d5b) | | +| [`operator=`](#group__base_1ga18e7eaa27695f7846fb43289b47b6ee1) | | +| [`onShutdownSignal`](#group__base_1gabec6f73a14b517119f8e29b749d783f6) | | +| [`onPrintHandle`](#group__base_1ga53e5c35202a822d72f44b7582ff07d5f) | | +| [`loop`](#group__base_1ga0cf54187707ea8b8f88324f045fbc797) | Active event loop. | + +--- + +#### Application + +```cpp +Application(uv::Loop * loop) +``` +Constructor. -#### `public inline virtual void process(`[`IPacket`](#classscy_1_1IPacket)` & packet)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `loop` | `uv::Loop *` | | +--- +#### ~Application -This method performs processing on the given packet and emits the result. +```cpp +~Application() +``` -Note: If packet processing is async (the packet is not in the current thread scope) then packet data must be copied. Copied data can be freed directly aFter the async call to emit() the outgoing packet. +Destructor. -#### `public inline virtual bool accepts(`[`IPacket`](#classscy_1_1IPacket)` * packet)` +--- +#### run +```cpp +void run() +``` +Run the application event loop. +--- -#### `protected inline virtual void dispatch(T & item)` +#### stop -Dispatch a single item to listeners. +```cpp +void stop() +``` +Stop the application event loop. +--- -#### `protected inline virtual void onStreamStateChange(const `[`PacketStreamState`](#structscy_1_1PacketStreamState)` &)` +#### finalize +```cpp +void finalize() +``` +Finalize and free any remaining pointers still held by the application event loop. -Called by the [PacketStream](#classscy_1_1PacketStream) to notify when the internal [Stream](#classscy_1_1Stream) state changes. On receiving the Stopped state, it is the responsibility of the adapter to have ceased all outgoing packet transmission, especially in multi-thread scenarios. +--- -# class `scy::AsyncQueue` +#### waitForShutdown +```cpp +void waitForShutdown(std::function< void(void *)> callback, void * opaque) ``` -class scy::AsyncQueue - : public scy::RunnableQueue< T > -``` +Bind the shutdown signal and run the main event loop. +| Parameter | Type | Description | +|-----------|------|-------------| +| `callback` | `std::function< void(void *)>` | | +| `opaque` | `void *` | | -[AsyncQueue](#classscy_1_1AsyncQueue) is a thread-based queue which receives packets from any thread source and dispatches them asynchronously. +--- -This queue is useful for deferring load from operation critical system devices before performing long running tasks. +#### bindShutdownSignal -The thread will call the [RunnableQueue](#classscy_1_1RunnableQueue)'s [run()](#group__base_1ga372c52aa2d9b4c33f9b620dfb2c2af23) method to constantly flush outgoing packets until cancel() is called. +```cpp +void bindShutdownSignal(std::function< void(void *)> callback, void * opaque) +``` -## Summary +Bind the shutdown signal. - Members | Descriptions ---------------------------------|--------------------------------------------- -`public inline AsyncQueue(int limit)` | -`public inline virtual void cancel()` | -`protected `[`Thread`](./doc/api-base.md#classscy_1_1Thread)` _thread` | -`protected inline virtual ~AsyncQueue()` | +| Parameter | Type | Description | +|-----------|------|-------------| +| `callback` | `std::function< void(void *)>` | | +| `opaque` | `void *` | | -## Members +--- -#### `public inline AsyncQueue(int limit)` +#### getDefault +```cpp +static Application & getDefault() +``` +Returns the default [Application](#classscy_1_1Application) singleton, although [Application](#classscy_1_1Application) instances may be initialized individually. +--- +#### Application -#### `public inline virtual void cancel()` +```cpp +Application(const Application &) = delete +``` +--- +#### operator= +```cpp +Application & operator=(const Application &) = delete +``` +--- -#### `protected `[`Thread`](./doc/api-base.md#classscy_1_1Thread)` _thread` +#### onShutdownSignal +```cpp +static void onShutdownSignal(uv_signal_t * req, int signum) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `req` | `uv_signal_t *` | | +| `signum` | `int` | | +--- +#### onPrintHandle -#### `protected inline virtual ~AsyncQueue()` +```cpp +static void onPrintHandle(uv_handle_t * handle, void * arg) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `handle` | `uv_handle_t *` | | +| `arg` | `void *` | | +--- +#### loop +```cpp +uv::Loop * loop +``` -# class `scy::BitReader` +Active event loop. +The event loop may be assigned on construction, otherwise the default event loop will be used. -Class for reading binary streams. +## MutableBuffer +> **Defined in:** `buffer.h` +The [MutableBuffer](#classscy_1_1MutableBuffer) class provides a safe representation of a buffer that can be modified. It does not own the underlying data, and so is cheap to copy or assign. -## Summary +### Members - Members | Descriptions ---------------------------------|--------------------------------------------- -`public BitReader(const char * bytes,size_t size,`[`ByteOrder`](#group__base_1gaa934c0972c743983462716b01df7dc32)` order)` | -`public BitReader(const `[`Buffer`](#group__base_1gab10b36b080deb583ed703fca6b63ffdd)` & buf,`[`ByteOrder`](#group__base_1gaa934c0972c743983462716b01df7dc32)` order)` | -`public BitReader(const `[`ConstBuffer`](#classscy_1_1ConstBuffer)` & pod,`[`ByteOrder`](#group__base_1gaa934c0972c743983462716b01df7dc32)` order)` | -`public ~BitReader()` | -`public void get(char * val,size_t len)` | -`public void get(std::string & val,size_t len)` | -`public void getU8(uint8_t & val)` | -`public void getU16(uint16_t & val)` | -`public void getU24(uint32_t & val)` | -`public void getU32(uint32_t & val)` | -`public void getU64(uint64_t & val)` | -`public const char peek()` | -`public const uint8_t peekU8()` | -`public const uint16_t peekU16()` | -`public const uint32_t peekU24()` | -`public const uint32_t peekU32()` | -`public const uint64_t peekU64()` | -`public size_t skipToChar(char c)` | -`public size_t skipWhitespace()` | -`public size_t skipToNextLine()` | -`public size_t skipNextWord()` | -`public size_t readNextWord(std::string & val)` | -`public size_t readNextNumber(unsigned int & val)` | -`public size_t readLine(std::string & val)` | -`public size_t readToNext(std::string & val,char c)` | -`public void seek(size_t val)` | -`public void skip(size_t size)` | -`public size_t limit() const` | Returns the read limit. -`public inline size_t position() const` | Returns the current read position. -`public size_t available() const` | -`public inline const char * begin() const` | -`public inline const char * current() const` | -`public inline `[`ByteOrder`](#group__base_1gaa934c0972c743983462716b01df7dc32)` order() const` | -`public std::string toString()` | -`protected size_t _position` | -`protected size_t _limit` | -`protected `[`ByteOrder`](#group__base_1gaa934c0972c743983462716b01df7dc32)` _order` | -`protected const char * _bytes` | -`protected void init(const char * bytes,size_t size,`[`ByteOrder`](#group__base_1gaa934c0972c743983462716b01df7dc32)` order)` | +| Name | Description | +|------|-------------| +| [`MutableBuffer`](#group__base_1ga6305583f6d3eb711d61bdfbb0d3ccbea) | Construct an empty buffer. | +| [`MutableBuffer`](#group__base_1gaa7382ec91da7e891ae4579b4092dcb89) | Construct a buffer to represent the given memory range. | +| [`data`](#group__base_1ga2a8d6e86c032207fee491787fbee3fa6) | | +| [`size`](#group__base_1ga6d8abadd0bc97709ff7bb5e3fa13a6a7) | | +| [`cstr`](#group__base_1ga63b3387bb3327e2cd5a01f886aa16e4d) | Cast the buffer as a char pointer. | +| [`str`](#group__base_1ga5ed8318956c72abfcd85d9f36643e94d) | Returns the buffer as a string. | +| [`_data`](#group__base_1ga40dd0ba9bacac375ac14b439bc5f230f) | | +| [`_size`](#group__base_1gacac6cdcfc5b21505e1159c8750cb96e8) | | -## Members +--- -#### `public BitReader(const char * bytes,size_t size,`[`ByteOrder`](#group__base_1gaa934c0972c743983462716b01df7dc32)` order)` +#### MutableBuffer +```cpp +inline MutableBuffer() +``` +Construct an empty buffer. +--- +#### MutableBuffer -#### `public BitReader(const `[`Buffer`](#group__base_1gab10b36b080deb583ed703fca6b63ffdd)` & buf,`[`ByteOrder`](#group__base_1gaa934c0972c743983462716b01df7dc32)` order)` +```cpp +inline MutableBuffer(void * data, size_t size) +``` +Construct a buffer to represent the given memory range. +| Parameter | Type | Description | +|-----------|------|-------------| +| `data` | `void *` | | +| `size` | `size_t` | | +--- +#### data -#### `public BitReader(const `[`ConstBuffer`](#classscy_1_1ConstBuffer)` & pod,`[`ByteOrder`](#group__base_1gaa934c0972c743983462716b01df7dc32)` order)` +```cpp +inline void * data() const +``` +--- +#### size +```cpp +inline size_t size() const +``` +--- -#### `public ~BitReader()` +#### cstr +```cpp +inline char * cstr() const +``` +Cast the buffer as a char pointer. +--- +#### str -#### `public void get(char * val,size_t len)` +```cpp +inline std::string str() const +``` +Returns the buffer as a string. +--- -Reads a value from the [BitReader](#classscy_1_1BitReader). Returns false if there isn't enough data left for the specified type. Throws a std::out_of_range exception if reading past the limit. +#### _data -#### `public void get(std::string & val,size_t len)` +```cpp +void * _data +``` +--- +#### _size +```cpp +size_t _size +``` +## ConstBuffer -#### `public void getU8(uint8_t & val)` +> **Defined in:** `buffer.h` +The [ConstBuffer](#classscy_1_1ConstBuffer) class provides a safe representation of a buffer that cannot be modified. It does not own the underlying data, and so is cheap to copy or assign. +### Members +| Name | Description | +|------|-------------| +| [`ConstBuffer`](#group__base_1ga9ee27b72f04bbf0a7012a2f56542f8ef) | Construct an empty buffer. | +| [`ConstBuffer`](#group__base_1gab0397dd96489a351a71fdc0213deac11) | Construct a buffer to represent the given memory range. | +| [`ConstBuffer`](#group__base_1ga217c5af0a20a4a11cfa451a389997ad9) | Construct a non-modifiable buffer from a modifiable one. | +| [`data`](#group__base_1gae7face6730ab3f32a4b204c03529b865) | | +| [`size`](#group__base_1ga20f090f293422b51279b9de74f3d8dea) | | +| [`cstr`](#group__base_1gab363d3fa459eb61194c5489530884552) | Cast the buffer as a const char pointer. | +| [`str`](#group__base_1gab94b7a54497431189aeae02fe254c2c8) | Returns the buffer as a string. | +| [`_data`](#group__base_1gacade139b3e2d38ca09b382ae15b47cc5) | | +| [`_size`](#group__base_1gae20401d38018eb75ae74cd23c94a0c45) | | +--- -#### `public void getU16(uint16_t & val)` +#### ConstBuffer +```cpp +inline ConstBuffer() +``` +Construct an empty buffer. +--- +#### ConstBuffer -#### `public void getU24(uint32_t & val)` +```cpp +inline ConstBuffer(const void * data, size_t size) +``` +Construct a buffer to represent the given memory range. +| Parameter | Type | Description | +|-----------|------|-------------| +| `data` | `const void *` | | +| `size` | `size_t` | | +--- +#### ConstBuffer -#### `public void getU32(uint32_t & val)` +```cpp +inline ConstBuffer(const MutableBuffer & b) +``` +Construct a non-modifiable buffer from a modifiable one. +| Parameter | Type | Description | +|-----------|------|-------------| +| `b` | `const MutableBuffer &` | | +--- +#### data -#### `public void getU64(uint64_t & val)` +```cpp +inline const void * data() const +``` +--- +#### size +```cpp +inline size_t size() const +``` +--- -#### `public const char peek()` +#### cstr +```cpp +inline const char * cstr() const +``` +Cast the buffer as a const char pointer. +--- +#### str -#### `public const uint8_t peekU8()` +```cpp +inline std::string str() const +``` +Returns the buffer as a string. +--- +#### _data +```cpp +const void * _data +``` -#### `public const uint16_t peekU16()` +--- +#### _size +```cpp +size_t _size +``` +## BitReader +> **Defined in:** `buffer.h` -#### `public const uint32_t peekU24()` +Class for reading binary streams. +### Members + +| Name | Description | +|------|-------------| +| [`BitReader`](#group__base_1ga72905d506783acd42a98dcee7f959e57) | | +| [`BitReader`](#group__base_1gabf0db9bf938b95829322f00935eb6092) | | +| [`BitReader`](#group__base_1ga4d25c7558ec919c38a2aa2bb2d3d549e) | | +| [`~BitReader`](#group__base_1ga2b0a8e18dd144d85baaf44b4711ef57f) | | +| [`get`](#group__base_1gaeb43583e35589cbf38d5ce90ee77c37d) | Reads a value from the [BitReader](#classscy_1_1BitReader). Returns false if there isn't enough data left for the specified type. Throws a std::out_of_range exception if reading past the limit. | +| [`get`](#group__base_1ga8c868edd08c6881b78fb7b455fbfd4c3) | | +| [`getU8`](#group__base_1ga071979552c567a13fe0723ae659cfcbc) | | +| [`getU16`](#group__base_1ga7235dad48ba744d85a2ba57b794fe456) | | +| [`getU24`](#group__base_1gac9f87a05f5faca590b71cd5562794e65) | | +| [`getU32`](#group__base_1ga393e2366848a14541c2084e17230f529) | | +| [`getU64`](#group__base_1ga9b0440dcaf68c5b17e02cc00290c467e) | | +| [`peek`](#group__base_1gae207340c2735276d75374184da016fe2) | | +| [`peekU8`](#group__base_1gab561d29c0ddd0224fbd26f07fecc0903) | | +| [`peekU16`](#group__base_1ga48fd6095876041c6835c1b9c8827e2fe) | | +| [`peekU24`](#group__base_1ga163dd7b966ff9cfdbb60e9cab30a1eb6) | | +| [`peekU32`](#group__base_1gae1f697546db37d27ea8c1f1862af4e3c) | | +| [`peekU64`](#group__base_1gad7e4e58bf5874f3ef4c02f639401ce45) | Peeks data from the [BitReader](#classscy_1_1BitReader). -1 is returned if reading past boundary. | +| [`skipToChar`](#group__base_1ga04c8225dd818b9b318695305516e99c0) | | +| [`skipWhitespace`](#group__base_1ga4796e1bd18cae8e4ae8c62398557c74c) | | +| [`skipToNextLine`](#group__base_1ga31f4b884ce29c3dcbc6898fde862a5e2) | | +| [`skipNextWord`](#group__base_1ga18d93cf6404f0e76811f670ccc596290) | | +| [`readNextWord`](#group__base_1ga33e3ee1da159e557e66cf554b7e7111e) | | +| [`readNextNumber`](#group__base_1ga7c0ecb36592167964d0283f9cc2a8b6a) | | +| [`readLine`](#group__base_1gaf844ec2228b8a663f8573b5f1c4f1608) | | +| [`readToNext`](#group__base_1ga5aab9beb7804826ae778577507b3a10e) | | +| [`seek`](#group__base_1gabeacae46cca18859f2d5ff07374f46c9) | Set position pointer to absolute position. Throws a std::out_of_range exception if the value exceeds the limit. | +| [`skip`](#group__base_1gacc13c5b3a4389c9db9e5d05ffc717a86) | Set position pointer to relative position. Throws a std::out_of_range exception if the value exceeds the limit. | +| [`limit`](#group__base_1ga33617f1db650063c3601b39baa3d8380) | Returns the read limit. | +| [`position`](#group__base_1gac3bd978ba8558d4d120bd47376834e43) | Returns the current read position. | +| [`available`](#group__base_1ga4e553e8007d836fab027def3ab087288) | Returns the number of elements between the current position and the limit. | +| [`begin`](#group__base_1gae951c0fa5f76bba0e7468dcb7a2f7344) | | +| [`current`](#group__base_1gadaf5501e315046c2ae8e988fa596ab70) | | +| [`order`](#group__base_1ga82d4b93cc1c3c8a9bbfd0937b7f59aeb) | | +| [`toString`](#group__base_1gac5342f8fbc0fa5e1c49615e530a9c5fe) | | +| [`init`](#group__base_1gaeb106bc617ebfa66b53bd40197e91af3) | | +| [`_position`](#group__base_1gad7302306c40922de5ec9fd8c94e616bc) | | +| [`_limit`](#group__base_1ga6188ac62b1e66762fdd2473335205262) | | +| [`_order`](#group__base_1ga4ee4b2b3556e5937a1a24d61d53d0513) | | +| [`_bytes`](#group__base_1gae3aca9ee141c803928c047813d3f4a8c) | | + +--- + +#### BitReader + +```cpp +BitReader(const char * bytes, size_t size, ByteOrder order) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `bytes` | `const char *` | | +| `size` | `size_t` | | +| `order` | `ByteOrder` | | +--- +#### BitReader -#### `public const uint32_t peekU32()` +```cpp +BitReader(const Buffer & buf, ByteOrder order) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `buf` | `const Buffer &` | | +| `order` | `ByteOrder` | | +--- +#### BitReader +```cpp +BitReader(const ConstBuffer & pod, ByteOrder order) +``` -#### `public const uint64_t peekU64()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `pod` | `const ConstBuffer &` | | +| `order` | `ByteOrder` | | +--- +#### ~BitReader -Peeks data from the [BitReader](#classscy_1_1BitReader). -1 is returned if reading past boundary. +```cpp +~BitReader() +``` -#### `public size_t skipToChar(char c)` +--- +#### get +```cpp +void get(char * val, size_t len) +``` +Reads a value from the [BitReader](#classscy_1_1BitReader). Returns false if there isn't enough data left for the specified type. Throws a std::out_of_range exception if reading past the limit. +| Parameter | Type | Description | +|-----------|------|-------------| +| `val` | `char *` | | +| `len` | `size_t` | | -#### `public size_t skipWhitespace()` +--- +#### get +```cpp +void get(std::string & val, size_t len) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `val` | `std::string &` | | +| `len` | `size_t` | | +--- -#### `public size_t skipToNextLine()` +#### getU8 +```cpp +void getU8(uint8_t & val) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `val` | `uint8_t &` | | +--- +#### getU16 -#### `public size_t skipNextWord()` +```cpp +void getU16(uint16_t & val) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `val` | `uint16_t &` | | +--- +#### getU24 +```cpp +void getU24(uint32_t & val) +``` -#### `public size_t readNextWord(std::string & val)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `val` | `uint32_t &` | | +--- +#### getU32 +```cpp +void getU32(uint32_t & val) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `val` | `uint32_t &` | | -#### `public size_t readNextNumber(unsigned int & val)` +--- +#### getU64 +```cpp +void getU64(uint64_t & val) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `val` | `uint64_t &` | | +--- -#### `public size_t readLine(std::string & val)` +#### peek +```cpp +const char peek() +``` +--- +#### peekU8 +```cpp +const uint8_t peekU8() +``` -#### `public size_t readToNext(std::string & val,char c)` +--- +#### peekU16 +```cpp +const uint16_t peekU16() +``` +--- +#### peekU24 -#### `public void seek(size_t val)` +```cpp +const uint32_t peekU24() +``` +--- +#### peekU32 -Set position pointer to absolute position. Throws a std::out_of_range exception if the value exceeds the limit. +```cpp +const uint32_t peekU32() +``` -#### `public void skip(size_t size)` +--- +#### peekU64 +```cpp +const uint64_t peekU64() +``` -Set position pointer to relative position. Throws a std::out_of_range exception if the value exceeds the limit. +Peeks data from the [BitReader](#classscy_1_1BitReader). -1 is returned if reading past boundary. -#### `public size_t limit() const` +--- -Returns the read limit. +#### skipToChar +```cpp +size_t skipToChar(char c) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `c` | `char` | | -#### `public inline size_t position() const` +--- -Returns the current read position. +#### skipWhitespace +```cpp +size_t skipWhitespace() +``` +--- -#### `public size_t available() const` +#### skipToNextLine +```cpp +size_t skipToNextLine() +``` +--- -Returns the number of elements between the current position and the limit. +#### skipNextWord -#### `public inline const char * begin() const` +```cpp +size_t skipNextWord() +``` +--- +#### readNextWord +```cpp +size_t readNextWord(std::string & val) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `val` | `std::string &` | | -#### `public inline const char * current() const` +--- +#### readNextNumber +```cpp +size_t readNextNumber(unsigned int & val) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `val` | `unsigned int &` | | +--- -#### `public inline `[`ByteOrder`](#group__base_1gaa934c0972c743983462716b01df7dc32)` order() const` +#### readLine +```cpp +size_t readLine(std::string & val) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `val` | `std::string &` | | +--- +#### readToNext -#### `public std::string toString()` +```cpp +size_t readToNext(std::string & val, char c) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `val` | `std::string &` | | +| `c` | `char` | | +--- +#### seek +```cpp +void seek(size_t val) +``` -#### `protected size_t _position` +Set position pointer to absolute position. Throws a std::out_of_range exception if the value exceeds the limit. +| Parameter | Type | Description | +|-----------|------|-------------| +| `val` | `size_t` | | +--- +#### skip +```cpp +void skip(size_t size) +``` -#### `protected size_t _limit` +Set position pointer to relative position. Throws a std::out_of_range exception if the value exceeds the limit. +| Parameter | Type | Description | +|-----------|------|-------------| +| `size` | `size_t` | | +--- +#### limit +```cpp +size_t limit() const +``` -#### `protected `[`ByteOrder`](#group__base_1gaa934c0972c743983462716b01df7dc32)` _order` +Returns the read limit. +--- +#### position +```cpp +inline size_t position() const +``` +Returns the current read position. -#### `protected const char * _bytes` +--- +#### available +```cpp +size_t available() const +``` +Returns the number of elements between the current position and the limit. +--- -#### `protected void init(const char * bytes,size_t size,`[`ByteOrder`](#group__base_1gaa934c0972c743983462716b01df7dc32)` order)` +#### begin +```cpp +inline const char * begin() const +``` +--- +#### current +```cpp +inline const char * current() const +``` -# class `scy::BitWriter` +--- +#### order +```cpp +inline ByteOrder order() const +``` +--- -Class for reading/writing binary streams. +#### toString -Note that when using the constructor with the Buffer reference as an argument, the writer will dynamically expand the given buffer when writing passed the buffer capacity. All other cases will throw a std::out_of_range error when writing past the buffer capacity. +```cpp +std::string toString() +``` -## Summary +--- - Members | Descriptions ---------------------------------|--------------------------------------------- -`public BitWriter(char * bytes,size_t size,`[`ByteOrder`](#group__base_1gaa934c0972c743983462716b01df7dc32)` order)` | -`public BitWriter(`[`Buffer`](#group__base_1gab10b36b080deb583ed703fca6b63ffdd)` & buf,`[`ByteOrder`](#group__base_1gaa934c0972c743983462716b01df7dc32)` order)` | -`public BitWriter(`[`MutableBuffer`](#classscy_1_1MutableBuffer)` & pod,`[`ByteOrder`](#group__base_1gaa934c0972c743983462716b01df7dc32)` order)` | -`public virtual ~BitWriter()` | -`public virtual void put(const char * val,size_t len)` | -`public void put(const std::string & val)` | -`public void putU8(uint8_t val)` | -`public void putU16(uint16_t val)` | -`public void putU24(uint32_t val)` | -`public void putU32(uint32_t val)` | -`public void putU64(uint64_t val)` | -`public virtual bool update(const char * val,size_t len,size_t pos)` | -`public bool update(const std::string & val,size_t pos)` | -`public bool updateU8(uint8_t val,size_t pos)` | -`public bool updateU16(uint16_t val,size_t pos)` | -`public bool updateU24(uint32_t val,size_t pos)` | -`public bool updateU32(uint32_t val,size_t pos)` | -`public bool updateU64(uint64_t val,size_t pos)` | -`public void seek(size_t val)` | -`public void skip(size_t size)` | -`public size_t limit() const` | Returns the write limit. -`public inline size_t position() const` | Returns the current write position. -`public size_t available() const` | -`public inline char * begin()` | -`public inline char * current()` | -`public inline const char * begin() const` | -`public inline const char * current() const` | -`public inline `[`ByteOrder`](#group__base_1gaa934c0972c743983462716b01df7dc32)` order() const` | -`public std::string toString()` | Returns written bytes as a string. -`protected size_t _position` | -`protected size_t _limit` | -`protected `[`ByteOrder`](#group__base_1gaa934c0972c743983462716b01df7dc32)` _order` | -`protected char * _bytes` | -`protected virtual void init(char * bytes,size_t size,`[`ByteOrder`](#group__base_1gaa934c0972c743983462716b01df7dc32)` order)` | +#### init -## Members +```cpp +void init(const char * bytes, size_t size, ByteOrder order) +``` -#### `public BitWriter(char * bytes,size_t size,`[`ByteOrder`](#group__base_1gaa934c0972c743983462716b01df7dc32)` order)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `bytes` | `const char *` | | +| `size` | `size_t` | | +| `order` | `ByteOrder` | | +--- +#### _position +```cpp +size_t _position +``` +--- -#### `public BitWriter(`[`Buffer`](#group__base_1gab10b36b080deb583ed703fca6b63ffdd)` & buf,`[`ByteOrder`](#group__base_1gaa934c0972c743983462716b01df7dc32)` order)` +#### _limit +```cpp +size_t _limit +``` +--- +#### _order +```cpp +ByteOrder _order +``` -#### `public BitWriter(`[`MutableBuffer`](#classscy_1_1MutableBuffer)` & pod,`[`ByteOrder`](#group__base_1gaa934c0972c743983462716b01df7dc32)` order)` +--- +#### _bytes +```cpp +const char * _bytes +``` +## BitWriter +> **Subclasses:** `scy::DynamicBitWriter` +> **Defined in:** `buffer.h` -#### `public virtual ~BitWriter()` +Class for reading/writing binary streams. +Note that when using the constructor with the Buffer reference as an argument, the writer will dynamically expand the given buffer when writing passed the buffer capacity. All other cases will throw a std::out_of_range error when writing past the buffer capacity. +### Members + +| Name | Description | +|------|-------------| +| [`BitWriter`](#group__base_1gab2dd71d855d182099b857a741b5d304a) | | +| [`BitWriter`](#group__base_1ga9197ef38d9bcd9c796da1ef8ae70bb8c) | | +| [`BitWriter`](#group__base_1ga0d30b3f7a40f306e24b5f905c692356e) | | +| [`~BitWriter`](#group__base_1ga18cd74cab24e3aafc649ec3fa700611c) | | +| [`put`](#group__base_1ga6f9a39d105c71a454ff1654881f760cb) | Append bytes to the buffer. Throws a `std::out_of_range` exception if reading past the limit. | +| [`put`](#group__base_1ga74ae0af5b9c1456fe21e5d7d8dc8c0b0) | | +| [`putU8`](#group__base_1ga46dce3e3b73e40e84efb0e3764e66255) | | +| [`putU16`](#group__base_1gace97db79776cfed401191e62154dbdc3) | | +| [`putU24`](#group__base_1ga1bbad9337122aba95fcd1c7c136c1f34) | | +| [`putU32`](#group__base_1ga07067c29ece34bd0e74497c841c66ebd) | | +| [`putU64`](#group__base_1gae52010b9de5b44800d09d2ba6a4d4a13) | | +| [`update`](#group__base_1gaf078f080a4b1844c55af4ef5f2c6492c) | Update a byte range. Throws a `std::out_of_range` exception if reading past the limit. | +| [`update`](#group__base_1ga29f24c588d65384b16ca1b290c925f2d) | | +| [`updateU8`](#group__base_1gadb08f97afe9929995bab4e0050370ec0) | | +| [`updateU16`](#group__base_1gaea07f0367babbfdeb63a3974e522457e) | | +| [`updateU24`](#group__base_1ga543249a93a5b97f95c0ee23fc4c76ae1) | | +| [`updateU32`](#group__base_1gac4ad85bdffd63789f9a55f4ea5043fc7) | | +| [`updateU64`](#group__base_1gaf3f88c70e2da140a92662033ebbf32b6) | | +| [`seek`](#group__base_1ga89948f0917a17ae6685542fcf6cd89a0) | Set position pointer to absolute position. Throws a `std::out_of_range` exception if the value exceeds the limit. | +| [`skip`](#group__base_1ga1ba542529f0e43e8ebfb0c49686ad63e) | Set position pointer to relative position. Throws a `std::out_of_range` exception if the value exceeds the limit. | +| [`limit`](#group__base_1gabee4a577412bb95082447e33b0e85225) | Returns the write limit. | +| [`position`](#group__base_1ga20daa94564eb9c24623e284275881baf) | Returns the current write position. | +| [`available`](#group__base_1ga221694bbd90c92d62f083413868448f0) | Returns the number of elements between the current write position and the limit. | +| [`begin`](#group__base_1gae9e198a59900c23e454b0df968ded299) | | +| [`current`](#group__base_1gaf71f7b8e2e5778e3fe3457b40c4e3cea) | | +| [`begin`](#group__base_1gaad1f7fe521048b1805076c34b435a57c) | | +| [`current`](#group__base_1ga6e07f702615163b589ea0d840ed5da94) | | +| [`order`](#group__base_1gaf577c3165d6bea6a49e49f33e056b56a) | | +| [`toString`](#group__base_1ga4d4c2a107262e4dc586917646c69ed31) | Returns written bytes as a string. | +| [`init`](#group__base_1gac7dfaab4eee54c93c128af5f1bacc63b) | | +| [`_position`](#group__base_1gae603a7273b54ba11f2a3c8a0651b6a4f) | | +| [`_limit`](#group__base_1ga2855d1965aeb98fa431ce444c5cf850d) | | +| [`_order`](#group__base_1gae89b790e3d037ddbed2683e37316ff74) | | +| [`_bytes`](#group__base_1gac290f14abeca0508bd045a35e79cb4f6) | | + +--- + +#### BitWriter + +```cpp +BitWriter(char * bytes, size_t size, ByteOrder order) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `bytes` | `char *` | | +| `size` | `size_t` | | +| `order` | `ByteOrder` | | +--- -#### `public virtual void put(const char * val,size_t len)` +#### BitWriter +```cpp +BitWriter(Buffer & buf, ByteOrder order) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `buf` | `Buffer &` | | +| `order` | `ByteOrder` | | -Append bytes to the buffer. Throws a `std::out_of_range` exception if reading past the limit. +--- -#### `public void put(const std::string & val)` +#### BitWriter +```cpp +BitWriter(MutableBuffer & pod, ByteOrder order) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `pod` | `MutableBuffer &` | | +| `order` | `ByteOrder` | | +--- +#### ~BitWriter -#### `public void putU8(uint8_t val)` +```cpp +virtual ~BitWriter() +``` +--- +#### put +```cpp +virtual void put(const char * val, size_t len) +``` +Append bytes to the buffer. Throws a `std::out_of_range` exception if reading past the limit. -#### `public void putU16(uint16_t val)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `val` | `const char *` | | +| `len` | `size_t` | | +--- +#### put +```cpp +void put(const std::string & val) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `val` | `const std::string &` | | -#### `public void putU24(uint32_t val)` +--- +#### putU8 +```cpp +void putU8(uint8_t val) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `val` | `uint8_t` | | +--- -#### `public void putU32(uint32_t val)` +#### putU16 +```cpp +void putU16(uint16_t val) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `val` | `uint16_t` | | +--- +#### putU24 -#### `public void putU64(uint64_t val)` +```cpp +void putU24(uint32_t val) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `val` | `uint32_t` | | +--- +#### putU32 +```cpp +void putU32(uint32_t val) +``` -#### `public virtual bool update(const char * val,size_t len,size_t pos)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `val` | `uint32_t` | | +--- +#### putU64 -Update a byte range. Throws a `std::out_of_range` exception if reading past the limit. +```cpp +void putU64(uint64_t val) +``` -#### `public bool update(const std::string & val,size_t pos)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `val` | `uint64_t` | | +--- +#### update +```cpp +virtual bool update(const char * val, size_t len, size_t pos) +``` +Update a byte range. Throws a `std::out_of_range` exception if reading past the limit. -#### `public bool updateU8(uint8_t val,size_t pos)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `val` | `const char *` | | +| `len` | `size_t` | | +| `pos` | `size_t` | | +--- +#### update +```cpp +bool update(const std::string & val, size_t pos) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `val` | `const std::string &` | | +| `pos` | `size_t` | | -#### `public bool updateU16(uint16_t val,size_t pos)` +--- +#### updateU8 +```cpp +bool updateU8(uint8_t val, size_t pos) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `val` | `uint8_t` | | +| `pos` | `size_t` | | +--- -#### `public bool updateU24(uint32_t val,size_t pos)` +#### updateU16 +```cpp +bool updateU16(uint16_t val, size_t pos) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `val` | `uint16_t` | | +| `pos` | `size_t` | | +--- +#### updateU24 -#### `public bool updateU32(uint32_t val,size_t pos)` +```cpp +bool updateU24(uint32_t val, size_t pos) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `val` | `uint32_t` | | +| `pos` | `size_t` | | +--- +#### updateU32 +```cpp +bool updateU32(uint32_t val, size_t pos) +``` -#### `public bool updateU64(uint64_t val,size_t pos)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `val` | `uint32_t` | | +| `pos` | `size_t` | | +--- +#### updateU64 +```cpp +bool updateU64(uint64_t val, size_t pos) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `val` | `uint64_t` | | +| `pos` | `size_t` | | -#### `public void seek(size_t val)` +--- +#### seek +```cpp +void seek(size_t val) +``` Set position pointer to absolute position. Throws a `std::out_of_range` exception if the value exceeds the limit. -#### `public void skip(size_t size)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `val` | `size_t` | | + +--- +#### skip +```cpp +void skip(size_t size) +``` Set position pointer to relative position. Throws a `std::out_of_range` exception if the value exceeds the limit. -#### `public size_t limit() const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `size` | `size_t` | | -Returns the write limit. +--- +#### limit + +```cpp +size_t limit() const +``` +Returns the write limit. -#### `public inline size_t position() const` +--- -Returns the current write position. +#### position +```cpp +inline size_t position() const +``` +Returns the current write position. -#### `public size_t available() const` +--- +#### available +```cpp +size_t available() const +``` Returns the number of elements between the current write position and the limit. -#### `public inline char * begin()` +--- +#### begin +```cpp +inline char * begin() +``` +--- +#### current -#### `public inline char * current()` +```cpp +inline char * current() +``` +--- +#### begin +```cpp +inline const char * begin() const +``` +--- -#### `public inline const char * begin() const` - - - - - -#### `public inline const char * current() const` - - - +#### current +```cpp +inline const char * current() const +``` -#### `public inline `[`ByteOrder`](#group__base_1gaa934c0972c743983462716b01df7dc32)` order() const` +--- +#### order +```cpp +inline ByteOrder order() const +``` +--- +#### toString -#### `public std::string toString()` +```cpp +std::string toString() +``` Returns written bytes as a string. +--- +#### init -#### `protected size_t _position` - - - - - -#### `protected size_t _limit` - - - - - -#### `protected `[`ByteOrder`](#group__base_1gaa934c0972c743983462716b01df7dc32)` _order` - - - - - -#### `protected char * _bytes` - - - - - -#### `protected virtual void init(char * bytes,size_t size,`[`ByteOrder`](#group__base_1gaa934c0972c743983462716b01df7dc32)` order)` - - - - - -# class `scy::Configuration` - - - - -[Configuration](#classscy_1_1Configuration) is an abstract base class for managing different kinds of configuration storage back ends such as JSON, XML, or database. - -Subclasses must override the [getRaw()](#group__base_1ga1246d954823215df6d932e78a08bc23b) and [setRaw()](#group__base_1gac6a4023c271c2357334275f15329310d) and methods. - -This class is safe for multithreaded use. - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public `[`Signal`](#classscy_1_1Signal)< void(const std::string &, const std::string &)`> PropertyChanged` | The Key and Value of the changed configuration property. -`public Configuration()` | Creates the [Configuration](./doc/api-base.md#classscy_1_1Configuration). -`public virtual ~Configuration()` | Destroys the [Configuration](./doc/api-base.md#classscy_1_1Configuration). -`public bool exists(const std::string & key) const` | Returns true if the property with the given key exists. -`public std::string getString(const std::string & key) const` | -`public std::string getString(const std::string & key,const std::string & defaultValue) const` | -`public std::string getRawString(const std::string & key) const` | -`public std::string getRawString(const std::string & key,const std::string & defaultValue) const` | -`public int getInt(const std::string & key) const` | -`public int getInt(const std::string & key,int defaultValue) const` | -`public std::int64_t getLargeInt(const std::string & key) const` | -`public std::int64_t getLargeInt(const std::string & key,std::int64_t defaultValue) const` | -`public double getDouble(const std::string & key) const` | -`public double getDouble(const std::string & key,double defaultValue) const` | -`public bool getBool(const std::string & key) const` | -`public bool getBool(const std::string & key,bool defaultValue) const` | -`public void setString(const std::string & key,const std::string & value)` | -`public void setInt(const std::string & key,int value)` | -`public void setLargeInt(const std::string & key,std::int64_t value)` | -`public void setDouble(const std::string & key,double value)` | -`public void setBool(const std::string & key,bool value)` | -`protected bool getRaw(const std::string & key,std::string & value) const` | -`protected void setRaw(const std::string & key,const std::string & value)` | -`protected Configuration(const `[`Configuration`](#classscy_1_1Configuration)` &) = delete` | -`protected `[`Configuration`](#classscy_1_1Configuration)` & operator=(const `[`Configuration`](#classscy_1_1Configuration)` &) = delete` | - -## Members - -#### `public `[`Signal`](#classscy_1_1Signal)< void(const std::string &, const std::string &)`> PropertyChanged` - -The Key and Value of the changed configuration property. - - - -#### `public Configuration()` - -Creates the [Configuration](#classscy_1_1Configuration). - - - -#### `public virtual ~Configuration()` - -Destroys the [Configuration](#classscy_1_1Configuration). - - - -#### `public bool exists(const std::string & key) const` - -Returns true if the property with the given key exists. - - - -#### `public std::string getString(const std::string & key) const` - - - -Returns the string value of the property with the given name. Throws a NotFoundException if the key does not exist. - -#### `public std::string getString(const std::string & key,const std::string & defaultValue) const` - - +```cpp +virtual void init(char * bytes, size_t size, ByteOrder order) +``` -If a property with the given key exists, returns the property's string value, otherwise returns the given default value. +| Parameter | Type | Description | +|-----------|------|-------------| +| `bytes` | `char *` | | +| `size` | `size_t` | | +| `order` | `ByteOrder` | | -#### `public std::string getRawString(const std::string & key) const` +--- +#### _position +```cpp +size_t _position +``` -Returns the raw string value of the property with the given name. Throws a NotFoundException if the key does not exist. References to other properties are not expanded. +--- -#### `public std::string getRawString(const std::string & key,const std::string & defaultValue) const` +#### _limit +```cpp +size_t _limit +``` +--- -If a property with the given key exists, returns the property's raw string value, otherwise returns the given default value. References to other properties are not expanded. +#### _order -#### `public int getInt(const std::string & key) const` +```cpp +ByteOrder _order +``` +--- +#### _bytes -Returns the int value of the property with the given name. Throws a NotFoundException if the key does not exist. Throws a SyntaxException if the property can not be converted to an int. Numbers starting with 0x are treated as hexadecimal. +```cpp +char * _bytes +``` -#### `public int getInt(const std::string & key,int defaultValue) const` +## DynamicBitWriter +> **Extends:** `scy::BitWriter` +> **Defined in:** `buffer.h` +Class for reading/writing dynamically resizable binary streams. -If a property with the given key exists, returns the property's int value, otherwise returns the given default value. Throws a SyntaxException if the property can not be converted to an int. Numbers starting with 0x are treated as hexadecimal. +Note that when using the constructor with the Buffer reference as an argument, the writer will dynamically expand the given buffer when writing passed the buffer capacity. All other cases will throw a std::out_of_range error when writing past the buffer capacity. -#### `public std::int64_t getLargeInt(const std::string & key) const` +### Members +| Name | Description | +|------|-------------| +| [`DynamicBitWriter`](#group__base_1ga49a2d410780afa3e2147f7860e774533) | | +| [`DynamicBitWriter`](#group__base_1gab8bd9f094a9a88adc83305428d6414cd) | | +| [`~DynamicBitWriter`](#group__base_1ga3d894b26b22905a62cb71cabf747db47) | | +| [`put`](#group__base_1ga24ba1cf5b5f9ce0b0299946b7b673df2) | Append bytes to the buffer. Throws a `std::out_of_range` exception if reading past the limit. | +| [`update`](#group__base_1ga6e09d70eb7d0892345b0d669645fa1fa) | Update a byte range. Throws a `std::out_of_range` exception if reading past the limit. | +| [`_buffer`](#group__base_1ga5198320e1d2b20c6bed0a38f9168695a) | | +| [`_offset`](#group__base_1gaef9c3c368088675470dd483e92987c70) | | +--- -Returns the int value of the property with the given name. Throws a NotFoundException if the key does not exist. Throws a SyntaxException if the property can not be converted to an int. Numbers starting with 0x are treated as hexadecimal. +#### DynamicBitWriter -#### `public std::int64_t getLargeInt(const std::string & key,std::int64_t defaultValue) const` +```cpp +DynamicBitWriter(Buffer & buf, ByteOrder order) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `buf` | `Buffer &` | | +| `order` | `ByteOrder` | | +--- -If a property with the given key exists, returns the property's int value, otherwise returns the given default value. Throws a SyntaxException if the property can not be converted to an int. Numbers starting with 0x are treated as hexadecimal. +#### DynamicBitWriter -#### `public double getDouble(const std::string & key) const` +```cpp +DynamicBitWriter(Buffer & buf, Buffer::iterator offset, ByteOrder order) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `buf` | `Buffer &` | | +| `offset` | `Buffer::iterator` | | +| `order` | `ByteOrder` | | +--- -Returns the double value of the property with the given name. Throws a NotFoundException if the key does not exist. Throws a SyntaxException if the property can not be converted to a double. +#### ~DynamicBitWriter -#### `public double getDouble(const std::string & key,double defaultValue) const` +```cpp +virtual ~DynamicBitWriter() +``` +--- +#### put -If a property with the given key exists, returns the property's double value, otherwise returns the given default value. Throws a SyntaxException if the property can not be converted to an double. +```cpp +virtual void put(const char * val, size_t len) +``` -#### `public bool getBool(const std::string & key) const` +Append bytes to the buffer. Throws a `std::out_of_range` exception if reading past the limit. +| Parameter | Type | Description | +|-----------|------|-------------| +| `val` | `const char *` | | +| `len` | `size_t` | | +--- -Returns the double value of the property with the given name. Throws a NotFoundException if the key does not exist. Throws a SyntaxException if the property can not be converted to a double. +#### update -#### `public bool getBool(const std::string & key,bool defaultValue) const` +```cpp +virtual bool update(const char * val, size_t len, size_t pos) +``` +Update a byte range. Throws a `std::out_of_range` exception if reading past the limit. +| Parameter | Type | Description | +|-----------|------|-------------| +| `val` | `const char *` | | +| `len` | `size_t` | | +| `pos` | `size_t` | | -If a property with the given key exists, returns the property's bool value, otherwise returns the given default value. Throws a SyntaxException if the property can not be converted to a boolean. The following string values can be converted into a boolean: +--- -* numerical values: non zero becomes true, zero becomes false +#### _buffer +```cpp +Buffer & _buffer +``` -* strings: true, yes, on become true, false, no, off become false Case does not matter. +--- -#### `public void setString(const std::string & key,const std::string & value)` +#### _offset +```cpp +size_t _offset +``` +## AbstractCollection -Sets the property with the given key to the given value. An already existing value for the key is overwritten. +> **Subclasses:** `scy::PointerCollection< std::string, IUser >`, `scy::PointerCollection< std::string, Peer >`, `scy::PointerCollection< std::string, LocalPackage >`, `scy::PointerCollection< std::string, RemotePackage >`, `scy::PointerCollection< std::string, Message >`, `scy::PointerCollection< uint32_t, TCPConnectionPair >`, `scy::PointerCollection< TKey, TValue >` +> **Defined in:** `collection.h` -#### `public void setInt(const std::string & key,int value)` +[AbstractCollection](#classscy_1_1AbstractCollection) is an abstract interface for managing a key-value store of indexed pointers. +### Members + +| Name | Description | +|------|-------------| +| [`AbstractCollection`](#group__base_1ga890f80336ad1fc7036ef91c7c4006723) | | +| [`~AbstractCollection`](#group__base_1gadb44ca86f52d6229148fab898575ba5f) | | +| [`add`](#group__base_1gaaee10ff4d5a246d2b62d3e1f4deb799d) | | +| [`remove`](#group__base_1ga7688d5f1a92a829835e39144fa703383) | | +| [`remove`](#group__base_1ga950a0e97583716495ccf83e68563eda3) | | +| [`exists`](#group__base_1ga862bf994fa6f95c49563528a1dc7f320) | | +| [`exists`](#group__base_1gaadc51ac08f83c7fd416067d31488fc4e) | | +| [`free`](#group__base_1gad1fb3be3451f07f6a6c2841a71105657) | | +| [`empty`](#group__base_1gaa145cb6f2956777b6da95c31750645b8) | | +| [`size`](#group__base_1ga82ead0d2085900b857d6e25b729eac8e) | | +| [`get`](#group__base_1ga798a0d970cc984132442f082d6e80484) | | +| [`clear`](#group__base_1gaff3c5cd97f75e7f56401aa18d13b39c3) | | + +--- + +#### AbstractCollection + +```cpp +inline AbstractCollection() +``` +--- -Sets the property with the given key to the given value. An already existing value for the key is overwritten. +#### ~AbstractCollection -#### `public void setLargeInt(const std::string & key,std::int64_t value)` +```cpp +virtual inline ~AbstractCollection() +``` +--- +#### add -Sets the property with the given key to the given value. An already existing value for the key is overwritten. +```cpp +bool add(const TKey & key, TValue * item, bool whiny) +``` -#### `public void setDouble(const std::string & key,double value)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `const TKey &` | | +| `item` | `TValue *` | | +| `whiny` | `bool` | | +--- +#### remove -Sets the property with the given key to the given value. An already existing value for the key is overwritten. +```cpp +bool remove(const TValue * item) +``` -#### `public void setBool(const std::string & key,bool value)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `item` | `const TValue *` | | +--- +#### remove -Sets the property with the given key to the given value. An already existing value for the key is overwritten. +```cpp +TValue * remove(const TKey & key) +``` -#### `protected bool getRaw(const std::string & key,std::string & value) const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `const TKey &` | | +--- +#### exists -If the property with the given key exists, stores the property's value in value and returns true. Otherwise, returns false. +```cpp +bool exists(const TKey & key) const +``` -Must be overridden by subclasses. +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `const TKey &` | | -#### `protected void setRaw(const std::string & key,const std::string & value)` +--- +#### exists +```cpp +bool exists(const TValue * item) const +``` -Sets the property with the given key to the given value. An already existing value for the key is overwritten. +| Parameter | Type | Description | +|-----------|------|-------------| +| `item` | `const TValue *` | | -The implementation is responsible for emitting the PropertyChanged signal. +--- -#### `protected Configuration(const `[`Configuration`](#classscy_1_1Configuration)` &) = delete` +#### free +```cpp +bool free(const TKey & key) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `const TKey &` | | +--- +#### empty -#### `protected `[`Configuration`](#classscy_1_1Configuration)` & operator=(const `[`Configuration`](#classscy_1_1Configuration)` &) = delete` +```cpp +bool empty() const +``` +--- +#### size +```cpp +size_t size() const +``` +--- -# class `scy::ConsoleChannel` +#### get +```cpp +TValue * get(const TKey & key, bool whiny) const ``` -class scy::ConsoleChannel - : public scy::LogChannel -``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `const TKey &` | | +| `whiny` | `bool` | | +--- +#### clear +```cpp +void clear() +``` -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public ConsoleChannel(const std::string & name,LogLevel level,const std::string & timeFormat)` | -`public inline virtual ~ConsoleChannel()` | -`public virtual void write(const `[`LogStream`](#structscy_1_1LogStream)` & stream)` | +## PointerCollection + +> **Extends:** `scy::AbstractCollection< TKey, TValue >` +> **Subclasses:** `scy::LiveCollection< std::string, IUser >`, `scy::LiveCollection< std::string, Peer >`, `scy::LiveCollection< std::string, LocalPackage >`, `scy::LiveCollection< std::string, RemotePackage >`, `scy::TimedManager< std::string, Message >`, `scy::DiagnosticManager`, `scy::LiveCollection< TKey, TValue >`, `scy::TimedManager< TKey, TValue >` +> **Defined in:** `collection.h` + +This collection is used to maintain a map of unique_ptr values indexed by key in a thread-safe way. + +### Members + +| Name | Description | +|------|-------------| +| [`PointerCollection`](#group__base_1ga4eb0b556b5bba9468b6bbc2930e264e6) | | +| [`~PointerCollection`](#group__base_1ga04848af4625edc5ccbbbf719e6c17443) | | +| [`add`](#group__base_1gaec876210d229bc9b9bf90bfe2926fb5f) | | +| [`add`](#group__base_1ga62ff0911c59aa1a9aeac9d7698f1ab17) | | +| [`update`](#group__base_1ga01b529a06faff43645cb5c67368d8e99) | | +| [`get`](#group__base_1ga329a6bf84cb48cfab9250a608e35f691) | | +| [`free`](#group__base_1ga67ee7cebf96b422b4584fe123b800f41) | | +| [`remove`](#group__base_1ga5efa219cb476f3a59a592386f6a16081) | | +| [`remove`](#group__base_1gaa37d26de497e938147192a5d668b34ae) | | +| [`exists`](#group__base_1gaa950f6b1d1e040da88873be453eda1b5) | | +| [`exists`](#group__base_1ga8fe0e3813f6a30ecd11702bba3e1514d) | | +| [`empty`](#group__base_1gace7b19f0e9bad5510467a46596e13d37) | | +| [`size`](#group__base_1ga3ba7fedd8251e52569ff8e6baaf93b30) | | +| [`clear`](#group__base_1ga8b8ccb87af37bfe3a6053b804cbe24c8) | | +| [`map`](#group__base_1ga14adc685db1957fe0bed158aa837c4c5) | | +| [`map`](#group__base_1gab1e7530c91ffd91d4c06bbc3038f0a62) | | +| [`onAdd`](#group__base_1gac3a8305d5d3342ed8e4b9771458eac36) | | +| [`onRemove`](#group__base_1ga95c4d1eb5fdb1b79c6fbe5fa1ee65f37) | | +| [`_mutex`](#group__base_1ga8fe93e84c7b64c29650da99cb6be530e) | | +| [`_map`](#group__base_1ga46a0cda25005bad73a3b8e8751cb21da) | | + +--- + +#### PointerCollection + +```cpp +inline PointerCollection() +``` -## Members +--- -#### `public ConsoleChannel(const std::string & name,LogLevel level,const std::string & timeFormat)` +#### ~PointerCollection +```cpp +virtual inline ~PointerCollection() +``` +--- +#### add +```cpp +virtual inline bool add(const TKey & key, TValue * item, bool whiny) +``` -#### `public inline virtual ~ConsoleChannel()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `const TKey &` | | +| `item` | `TValue *` | | +| `whiny` | `bool` | | +--- +#### add +```cpp +virtual inline bool add(const TKey & key, std::unique_ptr< TValue > item, bool whiny) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `const TKey &` | | +| `item` | `std::unique_ptr< TValue >` | | +| `whiny` | `bool` | | -#### `public virtual void write(const `[`LogStream`](#structscy_1_1LogStream)` & stream)` +--- +#### update +```cpp +virtual inline void update(const TKey & key, std::unique_ptr< TValue > item) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `const TKey &` | | +| `item` | `std::unique_ptr< TValue >` | | +--- -# class `scy::ConstBuffer` +#### get +```cpp +virtual inline TValue * get(const TKey & key, bool whiny) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `const TKey &` | | +| `whiny` | `bool` | | +--- -The [ConstBuffer](#classscy_1_1ConstBuffer) class provides a safe representation of a buffer that cannot be modified. It does not own the underlying data, and so is cheap to copy or assign. +#### free -## Summary +```cpp +virtual inline bool free(const TKey & key) +``` - Members | Descriptions ---------------------------------|--------------------------------------------- -`public inline ConstBuffer()` | Construct an empty buffer. -`public inline ConstBuffer(const void * data,size_t size)` | Construct a buffer to represent the given memory range. -`public inline ConstBuffer(const `[`MutableBuffer`](#classscy_1_1MutableBuffer)` & b)` | Construct a non-modifiable buffer from a modifiable one. -`public inline const void * data() const` | -`public inline size_t size() const` | -`public inline const char * cstr() const` | Cast the buffer as a const char pointer. -`public inline std::string str() const` | Returns the buffer as a string. -`protected const void * _data` | -`protected size_t _size` | +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `const TKey &` | | -## Members +--- -#### `public inline ConstBuffer()` +#### remove -Construct an empty buffer. +```cpp +virtual inline TValue * remove(const TKey & key) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `const TKey &` | | +--- -#### `public inline ConstBuffer(const void * data,size_t size)` +#### remove -Construct a buffer to represent the given memory range. +```cpp +virtual inline bool remove(const TValue * item) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `item` | `const TValue *` | | +--- -#### `public inline ConstBuffer(const `[`MutableBuffer`](#classscy_1_1MutableBuffer)` & b)` +#### exists -Construct a non-modifiable buffer from a modifiable one. +```cpp +virtual inline bool exists(const TKey & key) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `const TKey &` | | +--- -#### `public inline const void * data() const` +#### exists +```cpp +virtual inline bool exists(const TValue * item) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `item` | `const TValue *` | | +--- +#### empty -#### `public inline size_t size() const` +```cpp +virtual inline bool empty() const +``` +--- +#### size +```cpp +virtual inline size_t size() const +``` +--- -#### `public inline const char * cstr() const` +#### clear -Cast the buffer as a const char pointer. +```cpp +virtual inline void clear() +``` +--- +#### map -#### `public inline std::string str() const` +```cpp +virtual inline Map & map() +``` -Returns the buffer as a string. +--- +#### map +```cpp +virtual inline const Map & map() const +``` -#### `protected const void * _data` +--- +#### onAdd +```cpp +virtual inline void onAdd(const TKey &, TValue *) +``` +--- +#### onRemove -#### `protected size_t _size` +```cpp +virtual inline void onRemove(const TKey &, TValue *) +``` +--- +#### _mutex +```cpp +std::mutex _mutex +``` +--- -# class `scy::DateTime` +#### _map +```cpp +Map _map +``` +## LiveCollection +> **Extends:** `scy::PointerCollection< TKey, TValue >` +> **Subclasses:** `scy::StreamManager` +> **Defined in:** `collection.h` -This class represents an instant in time, expressed in years, months, days, hours, minutes, seconds and milliseconds based on the Gregorian calendar. The class is mainly useful for conversions between UTC, Julian day and Gregorian calendar dates. +### Members -The date and time stored in a [DateTime](#classscy_1_1DateTime) is always in UTC (Coordinated Universal Time) and thus independent of the timezone in effect on the system. +| Name | Description | +|------|-------------| +| [`onAdd`](#group__base_1gaae1485c677aab1d47b09ff809c7fc9dd) | | +| [`onRemove`](#group__base_1ga27214e644373169b247aa87e8603b761) | | +| [`ItemAdded`](#group__base_1gae557422bf75d0ad6c0a2c2910b8833ec) | | +| [`ItemRemoved`](#group__base_1ga37d011126f82ca545769f0fd8d3859d5) | | -Conversion calculations are based on algorithms collected and described by Peter Baum at [http://vsg.cape.com/~pbaum/date/date0.htm](http://vsg.cape.com/~pbaum/date/date0.htm) +--- -Internally, this class stores a date/time in two forms (UTC and broken down) for performance reasons. Only use this class for conversions between date/time representations. Use the [Timestamp](#classscy_1_1Timestamp) class for everything else. +#### onAdd -Notes: +```cpp +virtual inline void onAdd(const TKey &, TValue * item) +``` -* Zero is a valid year (in accordance with ISO 8601 and astronomical year numbering) +| Parameter | Type | Description | +|-----------|------|-------------| +| `item` | `TValue *` | | +--- -* Year zero (0) is a leap year +#### onRemove +```cpp +virtual inline void onRemove(const TKey &, TValue * item) +``` -* Negative years (years preceding 1 BC) are not supported +| Parameter | Type | Description | +|-----------|------|-------------| +| `item` | `TValue *` | | +--- +#### ItemAdded +```cpp +Signal< void(TValue &)> ItemAdded +``` +--- -For more information, please see: +#### ItemRemoved -* [http://en.wikipedia.org/wiki/Gregorian_Calendar](http://en.wikipedia.org/wiki/Gregorian_Calendar) +```cpp +Signal< void(const TValue &)> ItemRemoved +``` +## KVCollection -* [http://en.wikipedia.org/wiki/Julian_day](http://en.wikipedia.org/wiki/Julian_day) +> **Defined in:** `collection.h` +Reusable stack based unique key-value store for DRY coding. -* [http://en.wikipedia.org/wiki/UTC](http://en.wikipedia.org/wiki/UTC) +### Members + +| Name | Description | +|------|-------------| +| [`KVCollection`](#group__base_1ga91a2efa7efe06f01164d4cf805381851) | | +| [`~KVCollection`](#group__base_1gac9ac9c331dc55310741b1f3b87b5269a) | | +| [`add`](#group__base_1gaee5cb65f2a4800e23984ac012fc50c73) | | +| [`get`](#group__base_1ga4b943a0998cb16a67d6a0b525b9dc536) | | +| [`get`](#group__base_1ga7979bc09410a279c804927f41d16dae5) | | +| [`remove`](#group__base_1ga3fdb425c32ea35e45a5577955ec3bdd4) | | +| [`has`](#group__base_1ga8b8c96f803ae6b0c701fd02e29104f66) | | +| [`empty`](#group__base_1ga6f9493de942d040964118ce00feb208a) | | +| [`size`](#group__base_1gac38f3417c1421b8e889a283ee657261c) | | +| [`clear`](#group__base_1gaeb411422a7704fd35374f0d931095e69) | | +| [`map`](#group__base_1ga29c7802b4df2c44c170ccd5e66b0ac0d) | | +| [`_map`](#group__base_1gaacf1b4202998f2ba32b06e6e340c1643) | | + +--- + +#### KVCollection + +```cpp +inline KVCollection() +``` +--- -* [http://en.wikipedia.org/wiki/ISO_8601](http://en.wikipedia.org/wiki/ISO_8601) +#### ~KVCollection -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public DateTime()` | Creates a [DateTime](./doc/api-base.md#classscy_1_1DateTime) for the current date and time. -`public DateTime(const `[`Timestamp`](#classscy_1_1Timestamp)` & timestamp)` | -`public DateTime(int year,int month,int day,int hour,int minute,int second,int millisecond,int microsecond)` | -`public DateTime(double julianDay)` | Creates a [DateTime](./doc/api-base.md#classscy_1_1DateTime) for the given Julian day. -`public DateTime(`[`Timestamp::UtcTimeVal`](#group__base_1gaec8ace0f25db0ce91c10b30270c3dc24)` utcTime,`[`Timestamp::TimeDiff`](#group__base_1ga9f06831e4e9b9cbc6f061cc61dc91fd0)` diff)` | -`public DateTime(const `[`DateTime`](#classscy_1_1DateTime)` & dateTime)` | Copy constructor. Creates the [DateTime](./doc/api-base.md#classscy_1_1DateTime) from another one. -`public ~DateTime()` | Destroys the [DateTime](./doc/api-base.md#classscy_1_1DateTime). -`public `[`DateTime`](#classscy_1_1DateTime)` & operator=(const `[`DateTime`](#classscy_1_1DateTime)` & dateTime)` | Assigns another [DateTime](./doc/api-base.md#classscy_1_1DateTime). -`public `[`DateTime`](#classscy_1_1DateTime)` & operator=(const `[`Timestamp`](#classscy_1_1Timestamp)` & timestamp)` | Assigns a [Timestamp](./doc/api-base.md#classscy_1_1Timestamp). -`public `[`DateTime`](#classscy_1_1DateTime)` & operator=(double julianDay)` | Assigns a Julian day. -`public `[`DateTime`](#classscy_1_1DateTime)` & assign(int year,int month,int day,int hour,int minute,int second,int millisecond,int microseconds)` | -`public void swap(`[`DateTime`](#classscy_1_1DateTime)` & dateTime)` | Swaps the [DateTime](./doc/api-base.md#classscy_1_1DateTime) with another one. -`public inline int year() const` | Returns the year. -`public inline int month() const` | Returns the month (1 to 12). -`public int week(int firstDayOfWeek) const` | -`public inline int day() const` | Returns the day witin the month (1 to 31). -`public int dayOfWeek() const` | -`public int dayOfYear() const` | -`public inline int hour() const` | Returns the hour (0 to 23). -`public inline int hourAMPM() const` | Returns the hour (0 to 12). -`public inline bool isAM() const` | Returns true if hour < 12;. -`public inline bool isPM() const` | Returns true if hour >= 12. -`public inline int minute() const` | Returns the minute (0 to 59). -`public inline int second() const` | Returns the second (0 to 59). -`public inline int millisecond() const` | Returns the millisecond (0 to 999) -`public inline int microsecond() const` | Returns the microsecond (0 to 999) -`public double julianDay() const` | Returns the julian day for the date and time. -`public inline `[`Timestamp`](#classscy_1_1Timestamp)` timestamp() const` | Returns the date and time expressed as a [Timestamp](./doc/api-base.md#classscy_1_1Timestamp). -`public inline `[`Timestamp::UtcTimeVal`](#group__base_1gaec8ace0f25db0ce91c10b30270c3dc24)` utcTime() const` | -`public inline bool operator==(const `[`DateTime`](#classscy_1_1DateTime)` & dateTime) const` | -`public inline bool operator!=(const `[`DateTime`](#classscy_1_1DateTime)` & dateTime) const` | -`public inline bool operator<(const `[`DateTime`](#classscy_1_1DateTime)` & dateTime) const` | -`public inline bool operator<=(const `[`DateTime`](#classscy_1_1DateTime)` & dateTime) const` | -`public inline bool operator>(const `[`DateTime`](#classscy_1_1DateTime)` & dateTime) const` | -`public inline bool operator>=(const `[`DateTime`](#classscy_1_1DateTime)` & dateTime) const` | -`public `[`DateTime`](#classscy_1_1DateTime)` operator+(const `[`Timespan`](#classscy_1_1Timespan)` & span) const` | -`public `[`DateTime`](#classscy_1_1DateTime)` operator-(const `[`Timespan`](#classscy_1_1Timespan)` & span) const` | -`public `[`Timespan`](#classscy_1_1Timespan)` operator-(const `[`DateTime`](#classscy_1_1DateTime)` & dateTime) const` | -`public `[`DateTime`](#classscy_1_1DateTime)` & operator+=(const `[`Timespan`](#classscy_1_1Timespan)` & span)` | -`public `[`DateTime`](#classscy_1_1DateTime)` & operator-=(const `[`Timespan`](#classscy_1_1Timespan)` & span)` | -`public void makeUTC(int tzd)` | -`public void makeLocal(int tzd)` | -`protected void computeGregorian(double julianDay)` | -`protected void computeDaytime()` | - -## Members - -#### `public DateTime()` +```cpp +virtual inline ~KVCollection() +``` -Creates a [DateTime](#classscy_1_1DateTime) for the current date and time. +--- +#### add +```cpp +virtual inline bool add(const TKey & key, const TValue & item, bool update, bool whiny) +``` -#### `public DateTime(const `[`Timestamp`](#classscy_1_1Timestamp)` & timestamp)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `const TKey &` | | +| `item` | `const TValue &` | | +| `update` | `bool` | | +| `whiny` | `bool` | | +--- +#### get -Creates a [DateTime](#classscy_1_1DateTime) for the date and time given in a [Timestamp](#classscy_1_1Timestamp). +```cpp +virtual inline TValue & get(const TKey & key) +``` -#### `public DateTime(int year,int month,int day,int hour,int minute,int second,int millisecond,int microsecond)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `const TKey &` | | +--- +#### get -Creates a [DateTime](#classscy_1_1DateTime) for the given Gregorian date and time. +```cpp +virtual inline const TValue & get(const TKey & key, const TValue & defaultValue) const +``` -* year is from 0 to 9999. +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `const TKey &` | | +| `defaultValue` | `const TValue &` | | +--- -* month is from 1 to 12. +#### remove +```cpp +virtual inline bool remove(const TKey & key) +``` -* day is from 1 to 31. +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `const TKey &` | | +--- -* hour is from 0 to 23. +#### has +```cpp +virtual inline bool has(const TKey & key) const +``` -* minute is from 0 to 59. +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `const TKey &` | | +--- -* second is from 0 to 59. +#### empty +```cpp +virtual inline bool empty() const +``` -* millisecond is from 0 to 999. +--- +#### size -* microsecond is from 0 to 999. +```cpp +virtual inline size_t size() const +``` -#### `public DateTime(double julianDay)` +--- -Creates a [DateTime](#classscy_1_1DateTime) for the given Julian day. +#### clear +```cpp +virtual inline void clear() +``` +--- -#### `public DateTime(`[`Timestamp::UtcTimeVal`](#group__base_1gaec8ace0f25db0ce91c10b30270c3dc24)` utcTime,`[`Timestamp::TimeDiff`](#group__base_1ga9f06831e4e9b9cbc6f061cc61dc91fd0)` diff)` +#### map +```cpp +virtual inline Map & map() +``` +--- -Creates a [DateTime](#classscy_1_1DateTime) from an UtcTimeVal and a TimeDiff. +#### _map -Mainly used internally by [DateTime](#classscy_1_1DateTime) and friends. +```cpp +Map _map +``` -#### `public DateTime(const `[`DateTime`](#classscy_1_1DateTime)` & dateTime)` +## NVCollection -Copy constructor. Creates the [DateTime](#classscy_1_1DateTime) from another one. +> **Subclasses:** `scy::http::FormWriter`, `scy::http::Message` +> **Defined in:** `collection.h` +A storage container for a name value collections. This collection can store multiple entries for each name, and it's getters are case-insensitive. +### Members + +| Name | Description | +|------|-------------| +| [`NVCollection`](#group__base_1ga41eb71d1735c8238b24dcda700c23d21) | | +| [`NVCollection`](#group__base_1gaca0d4928654fd5b79fd06612222080b9) | | +| [`~NVCollection`](#group__base_1gaed8abfccd111eea9b5cabe59ef8aac46) | | +| [`operator=`](#group__base_1ga6e9938e6b926c62d4ccbea0c7a623dec) | Assigns the name-value pairs of another [NVCollection](#classscy_1_1NVCollection) to this one. | +| [`operator[]`](#group__base_1gab76fc12abf8a9f13ac81e32d9788cea3) | Returns the value of the (first) name-value pair with the given name. | +| [`set`](#group__base_1ga36860b3fb325b24ed969668192d2d5ad) | Sets the value of the (first) name-value pair with the given name. | +| [`add`](#group__base_1gae0cbccd7da15dd37eed7631c853c2565) | Adds a new name-value pair with the given name and value. | +| [`get`](#group__base_1ga02db5c5230e78a2f8272b0380ac8fe2b) | Returns the value of the first name-value pair with the given name. | +| [`get`](#group__base_1ga5b609c360028a9ec67aee8fb1c6e543d) | Returns the value of the first name-value pair with the given name. If no value with the given name has been found, the defaultValue is returned. | +| [`has`](#group__base_1ga01251074fc906db8ec5abaaaf084fdad) | Returns true if there is at least one name-value pair with the given name. | +| [`find`](#group__base_1ga07ca18d979f83a19bcf526357e45d2e8) | Returns an iterator pointing to the first name-value pair with the given name. | +| [`begin`](#group__base_1gaef153806a4bf20b97530fcb8c0cb0c5f) | Returns an iterator pointing to the begin of the name-value pair collection. | +| [`end`](#group__base_1ga5de16e354315a6c291156deef03b3229) | Returns an iterator pointing to the end of the name-value pair collection. | +| [`empty`](#group__base_1gaf563c36905a2529054785a1734d46f67) | Returns true iff the header does not have any content. | +| [`size`](#group__base_1gae1a0d58fc01bd230cf5497d8e5ae398f) | Returns the number of name-value pairs in the collection. | +| [`erase`](#group__base_1gab295478be7ae8a444d0071c96f4108ff) | Removes all name-value pairs with the given name. | +| [`clear`](#group__base_1ga73d773429898c1c3ba526155b6cc0b90) | Removes all name-value pairs and their values. | +| [`_map`](#group__base_1ga7d5555328212afe80f3421437edc5dd5) | | + +--- + +#### NVCollection + +```cpp +inline NVCollection() +``` -#### `public ~DateTime()` +--- -Destroys the [DateTime](#classscy_1_1DateTime). +#### NVCollection +```cpp +inline NVCollection(const NVCollection & nvc) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `nvc` | `const NVCollection &` | | -#### `public `[`DateTime`](#classscy_1_1DateTime)` & operator=(const `[`DateTime`](#classscy_1_1DateTime)` & dateTime)` +--- -Assigns another [DateTime](#classscy_1_1DateTime). +#### ~NVCollection +```cpp +virtual inline ~NVCollection() +``` +--- -#### `public `[`DateTime`](#classscy_1_1DateTime)` & operator=(const `[`Timestamp`](#classscy_1_1Timestamp)` & timestamp)` +#### operator= -Assigns a [Timestamp](#classscy_1_1Timestamp). +```cpp +NVCollection & operator=(const NVCollection & nvc) +``` +Assigns the name-value pairs of another [NVCollection](#classscy_1_1NVCollection) to this one. +| Parameter | Type | Description | +|-----------|------|-------------| +| `nvc` | `const NVCollection &` | | -#### `public `[`DateTime`](#classscy_1_1DateTime)` & operator=(double julianDay)` +--- -Assigns a Julian day. +#### operator[] +```cpp +const std::string & operator[](const std::string & name) const +``` +Returns the value of the (first) name-value pair with the given name. -#### `public `[`DateTime`](#classscy_1_1DateTime)` & assign(int year,int month,int day,int hour,int minute,int second,int millisecond,int microseconds)` +Throws a NotFoundException if the name-value pair does not exist. +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | +--- -Assigns a Gregorian date and time. +#### set -* year is from 0 to 9999. +```cpp +void set(const std::string & name, const std::string & value) +``` +Sets the value of the (first) name-value pair with the given name. -* month is from 1 to 12. +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | +| `value` | `const std::string &` | | +--- -* day is from 1 to 31. +#### add +```cpp +void add(const std::string & name, const std::string & value) +``` -* hour is from 0 to 23. +Adds a new name-value pair with the given name and value. +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | +| `value` | `const std::string &` | | -* minute is from 0 to 59. +--- +#### get -* second is from 0 to 59. +```cpp +const std::string & get(const std::string & name) const +``` +Returns the value of the first name-value pair with the given name. -* millisecond is from 0 to 999. +Throws a NotFoundException if the name-value pair does not exist. +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | -* microsecond is from 0 to 999. +--- -#### `public void swap(`[`DateTime`](#classscy_1_1DateTime)` & dateTime)` +#### get -Swaps the [DateTime](#classscy_1_1DateTime) with another one. +```cpp +const std::string & get(const std::string & name, const std::string & defaultValue) const +``` +Returns the value of the first name-value pair with the given name. If no value with the given name has been found, the defaultValue is returned. +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | +| `defaultValue` | `const std::string &` | | -#### `public inline int year() const` +--- -Returns the year. +#### has +```cpp +bool has(const std::string & name) const +``` +Returns true if there is at least one name-value pair with the given name. -#### `public inline int month() const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | -Returns the month (1 to 12). +--- +#### find +```cpp +ConstIterator find(const std::string & name) const +``` -#### `public int week(int firstDayOfWeek) const` +Returns an iterator pointing to the first name-value pair with the given name. +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | +--- -Returns the week number within the year. FirstDayOfWeek should be either SUNDAY (0) or MONDAY (1). The returned week number will be from 0 to 53. Week number 1 is the week containing January 4. This is in accordance to ISO 8601. +#### begin -The following example assumes that firstDayOfWeek is MONDAY. For 2005, which started on a Saturday, week 1 will be the week starting on Monday, January 3. January 1 and 2 will fall within week 0 (or the last week of the previous year). +```cpp +ConstIterator begin() const +``` -For 2007, which starts on a Monday, week 1 will be the week startung on Monday, January 1. There will be no week 0 in 2007. +Returns an iterator pointing to the begin of the name-value pair collection. -#### `public inline int day() const` +--- -Returns the day witin the month (1 to 31). +#### end +```cpp +ConstIterator end() const +``` +Returns an iterator pointing to the end of the name-value pair collection. -#### `public int dayOfWeek() const` +--- +#### empty +```cpp +bool empty() const +``` -Returns the weekday (0 to 6, where 0 = Sunday, 1 = Monday, ..., 6 = Saturday). +Returns true iff the header does not have any content. -#### `public int dayOfYear() const` +--- +#### size +```cpp +int size() const +``` -Returns the number of the day in the year. January 1 is 1, February 1 is 32, etc. +Returns the number of name-value pairs in the collection. -#### `public inline int hour() const` +--- -Returns the hour (0 to 23). +#### erase +```cpp +void erase(const std::string & name) +``` +Removes all name-value pairs with the given name. -#### `public inline int hourAMPM() const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | -Returns the hour (0 to 12). +--- +#### clear +```cpp +void clear() +``` -#### `public inline bool isAM() const` +Removes all name-value pairs and their values. -Returns true if hour < 12;. +--- +#### _map +```cpp +Map _map +``` -#### `public inline bool isPM() const` +## ILT -Returns true if hour >= 12. +> **Defined in:** `collection.h` +### Members +| Name | Description | +|------|-------------| +| [`operator()`](#group__base_1ga966ae0464dd2d1011bcd55702729b5eb) | | -#### `public inline int minute() const` +--- -Returns the minute (0 to 59). - - - -#### `public inline int second() const` - -Returns the second (0 to 59). - - - -#### `public inline int millisecond() const` - -Returns the millisecond (0 to 999) - - - -#### `public inline int microsecond() const` - -Returns the microsecond (0 to 999) - - - -#### `public double julianDay() const` - -Returns the julian day for the date and time. - - - -#### `public inline `[`Timestamp`](#classscy_1_1Timestamp)` timestamp() const` - -Returns the date and time expressed as a [Timestamp](#classscy_1_1Timestamp). - - - -#### `public inline `[`Timestamp::UtcTimeVal`](#group__base_1gaec8ace0f25db0ce91c10b30270c3dc24)` utcTime() const` - - - -Returns the date and time expressed in UTC-based time. UTC base time is midnight, October 15, 1582. Resolution is 100 nanoseconds. - -#### `public inline bool operator==(const `[`DateTime`](#classscy_1_1DateTime)` & dateTime) const` - - - - - -#### `public inline bool operator!=(const `[`DateTime`](#classscy_1_1DateTime)` & dateTime) const` - - - - - -#### `public inline bool operator<(const `[`DateTime`](#classscy_1_1DateTime)` & dateTime) const` - - - - - -#### `public inline bool operator<=(const `[`DateTime`](#classscy_1_1DateTime)` & dateTime) const` - - - - - -#### `public inline bool operator>(const `[`DateTime`](#classscy_1_1DateTime)` & dateTime) const` - - - - - -#### `public inline bool operator>=(const `[`DateTime`](#classscy_1_1DateTime)` & dateTime) const` - - - - - -#### `public `[`DateTime`](#classscy_1_1DateTime)` operator+(const `[`Timespan`](#classscy_1_1Timespan)` & span) const` - - - - - -#### `public `[`DateTime`](#classscy_1_1DateTime)` operator-(const `[`Timespan`](#classscy_1_1Timespan)` & span) const` - - - - - -#### `public `[`Timespan`](#classscy_1_1Timespan)` operator-(const `[`DateTime`](#classscy_1_1DateTime)` & dateTime) const` - - - - - -#### `public `[`DateTime`](#classscy_1_1DateTime)` & operator+=(const `[`Timespan`](#classscy_1_1Timespan)` & span)` - - - - - -#### `public `[`DateTime`](#classscy_1_1DateTime)` & operator-=(const `[`Timespan`](#classscy_1_1Timespan)` & span)` - - - - - -#### `public void makeUTC(int tzd)` - - - -Converts a local time into UTC, by applying the given time zone differential. - -#### `public void makeLocal(int tzd)` - - - -Converts a UTC time into a local time, by applying the given time zone differential. - -#### `protected void computeGregorian(double julianDay)` - - - -Computes the Gregorian date for the given Julian day. See [http://vsg.cape.com/~pbaum/date/injdimp.htm](http://vsg.cape.com/~pbaum/date/injdimp.htm), section 3.3.1 for the algorithm. - -#### `protected void computeDaytime()` - - - -Extracts the daytime (hours, minutes, seconds, etc.) from the stored utcTime. - -# class `scy::DateTimeFormat` - - - - -Definition of date/time formats and various constants used by [DateTimeFormatter](#classscy_1_1DateTimeFormatter) and [DateTimeParser](#classscy_1_1DateTimeParser). - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- - -## Members - -# class `scy::DateTimeFormatter` - - - - -This class converts dates and times into strings, supporting a variety of standard and custom formats. - -There are two kind of static member functions: - -* format* functions return a std::string containin the formatted value. - - -* append* functions append the formatted value to an existing string. - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- - -## Members - -# class `scy::DateTimeParser` - - - - -This class provides a method for parsing dates and times from strings. All parsing methods do their best to parse a meaningful result, even from malformed input strings. - -The returned [DateTime](#classscy_1_1DateTime) will always contain a time in the same timezone as the time in the string. Call [DateTime::makeUTC()](#group__base_1gaef85751cde47a0e909aeddae1775b805) with the timeZoneDifferential returned by [parse()](#group__base_1ga7249fe6e774b64ab401a6f3f97311f26) to convert the [DateTime](#classscy_1_1DateTime) to UTC. - -Note: When parsing a time in 12-hour (AM/PM) format, the hour (h) must be parsed before the AM/PM designator (a, A), otherwise the AM/PM designator will be ignored. - -See the [DateTimeFormatter](#classscy_1_1DateTimeFormatter) class for a list of supported format specifiers. In addition to the format specifiers supported by [DateTimeFormatter](#classscy_1_1DateTimeFormatter), an additional specifier is supported: r will parse a year given by either two or four digits. Years 69-00 are interpreted in the 20th century (1969-2000), years 01-68 in the 21th century (2001-2068). - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- - -## Members - -# class `scy::DynamicBitWriter` - -``` -class scy::DynamicBitWriter - : public scy::BitWriter -``` - - - -Class for reading/writing dynamically resizable binary streams. - -Note that when using the constructor with the Buffer reference as an argument, the writer will dynamically expand the given buffer when writing passed the buffer capacity. All other cases will throw a std::out_of_range error when writing past the buffer capacity. - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public DynamicBitWriter(`[`Buffer`](#group__base_1gab10b36b080deb583ed703fca6b63ffdd)` & buf,`[`ByteOrder`](#group__base_1gaa934c0972c743983462716b01df7dc32)` order)` | -`public DynamicBitWriter(`[`Buffer`](#group__base_1gab10b36b080deb583ed703fca6b63ffdd)` & buf,Buffer::iterator offset,`[`ByteOrder`](#group__base_1gaa934c0972c743983462716b01df7dc32)` order)` | -`public virtual ~DynamicBitWriter()` | -`public virtual void put(const char * val,size_t len)` | -`public virtual bool update(const char * val,size_t len,size_t pos)` | -`protected `[`Buffer`](#group__base_1gab10b36b080deb583ed703fca6b63ffdd)` & _buffer` | -`protected size_t _offset` | - -## Members - -#### `public DynamicBitWriter(`[`Buffer`](#group__base_1gab10b36b080deb583ed703fca6b63ffdd)` & buf,`[`ByteOrder`](#group__base_1gaa934c0972c743983462716b01df7dc32)` order)` - - - - - -#### `public DynamicBitWriter(`[`Buffer`](#group__base_1gab10b36b080deb583ed703fca6b63ffdd)` & buf,Buffer::iterator offset,`[`ByteOrder`](#group__base_1gaa934c0972c743983462716b01df7dc32)` order)` - - - - - -#### `public virtual ~DynamicBitWriter()` - - - - - -#### `public virtual void put(const char * val,size_t len)` - - - -Append bytes to the buffer. Throws a `std::out_of_range` exception if reading past the limit. - -#### `public virtual bool update(const char * val,size_t len,size_t pos)` - - - -Update a byte range. Throws a `std::out_of_range` exception if reading past the limit. - -#### `protected `[`Buffer`](#group__base_1gab10b36b080deb583ed703fca6b63ffdd)` & _buffer` - - - - - -#### `protected size_t _offset` - - - - - -# class `scy::FileChannel` - -``` -class scy::FileChannel - : public scy::LogChannel -``` - - - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public FileChannel(const std::string & name,const std::string & path,LogLevel level,const char * timeFormat)` | -`public virtual ~FileChannel()` | -`public virtual void write(const `[`LogStream`](#structscy_1_1LogStream)` & stream)` | -`public void setPath(const std::string & path)` | -`public std::string path() const` | -`protected std::ofstream _fstream` | -`protected std::string _path` | -`protected virtual void open()` | -`protected virtual void close()` | - -## Members - -#### `public FileChannel(const std::string & name,const std::string & path,LogLevel level,const char * timeFormat)` - - - - - -#### `public virtual ~FileChannel()` - - - - - -#### `public virtual void write(const `[`LogStream`](#structscy_1_1LogStream)` & stream)` - - - - - -#### `public void setPath(const std::string & path)` - - - - - -#### `public std::string path() const` - - - - - -#### `protected std::ofstream _fstream` - - - - - -#### `protected std::string _path` - - - - - -#### `protected virtual void open()` - - - - - -#### `protected virtual void close()` - - - - - -# class `scy::FlagPacket` - -``` -class scy::FlagPacket - : public scy::IPacket -``` - -Packet for sending bitwise flags along the packet stream. - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public inline FlagPacket(unsigned flags)` | -`public inline virtual `[`IPacket`](#classscy_1_1IPacket)` * clone() const` | -`public inline FlagPacket(const `[`FlagPacket`](#classscy_1_1FlagPacket)` & that)` | -`public inline virtual ~FlagPacket()` | -`public inline virtual ssize_t read(const `[`ConstBuffer`](#classscy_1_1ConstBuffer)` &)` | -`public inline virtual void write(`[`Buffer`](#group__base_1gab10b36b080deb583ed703fca6b63ffdd)` &) const` | -`public inline virtual const char * className() const` | - -## Members - -#### `public inline FlagPacket(unsigned flags)` - - - - - -#### `public inline virtual `[`IPacket`](#classscy_1_1IPacket)` * clone() const` - - - - - -#### `public inline FlagPacket(const `[`FlagPacket`](#classscy_1_1FlagPacket)` & that)` - - - - - -#### `public inline virtual ~FlagPacket()` - - - - - -#### `public inline virtual ssize_t read(const `[`ConstBuffer`](#classscy_1_1ConstBuffer)` &)` - - - -Read/parse to the packet from the given input buffer. The number of bytes read is returned. - -#### `public inline virtual void write(`[`Buffer`](#group__base_1gab10b36b080deb583ed703fca6b63ffdd)` &) const` - - - -Copy/generate to the packet given output buffer. The number of bytes written can be obtained from the buffer. - -Todo: It may be prefferable to use our pod types here instead of buffer input, but the current codebase requires that the buffer be dynamically resizable for some protocols... - -#### `public inline virtual const char * className() const` - - - - - -# class `scy::GarbageCollector` - - -Garbage collector for safe memory management and deferred pointer deletion. - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public GarbageCollector()` | -`public ~GarbageCollector()` | -`public template`
`inline void deleteLater(C * ptr,uv::Loop * loop)` | Schedules a pointer for deferred deletion. -`public template`
`inline void deleteLater(std::shared_ptr< C > ptr,uv::Loop * loop)` | Schedules a shared pointer for deferred deletion. -`public void finalize()` | -`public std::thread::id tid()` | Returns the TID of the main garbage collector thread. -`protected mutable std::mutex _mutex` | -`protected std::vector< `[`Cleaner`](./doc/api-base.md#classscy_1_1GarbageCollector_1_1Cleaner)` * > _cleaners` | -`protected std::thread::id _tid` | -`protected `[`Cleaner`](#classscy_1_1GarbageCollector_1_1Cleaner)` * getCleaner(uv::Loop * loop)` | Get the cleaner context for the given loop. - -## Members - -#### `public GarbageCollector()` - - - - - -#### `public ~GarbageCollector()` - - - - - -#### `public template`
`inline void deleteLater(C * ptr,uv::Loop * loop)` - -Schedules a pointer for deferred deletion. - - - -#### `public template`
`inline void deleteLater(std::shared_ptr< C > ptr,uv::Loop * loop)` - -Schedules a shared pointer for deferred deletion. - - - -#### `public void finalize()` - - - -Frees all scheduled pointers now. This method must be called from the main thread while the event loop is inactive. - -#### `public std::thread::id tid()` - -Returns the TID of the main garbage collector thread. - - - -#### `protected mutable std::mutex _mutex` - - - - - -#### `protected std::vector< `[`Cleaner`](./doc/api-base.md#classscy_1_1GarbageCollector_1_1Cleaner)` * > _cleaners` - - - - - -#### `protected std::thread::id _tid` - - - - - -#### `protected `[`Cleaner`](#classscy_1_1GarbageCollector_1_1Cleaner)` * getCleaner(uv::Loop * loop)` - -Get the cleaner context for the given loop. - - - -# class `scy::Idler` - -``` -class scy::Idler - : public scy::Runner -``` - - - -Asynchronous type that triggers callbacks when the event loop is idle. - -This class inherits the `[Runner](#classscy_1_1Runner)` interface and may be used with any implementation that's powered by an asynchronous `[Runner](#classscy_1_1Runner)`. - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public Idler(uv::Loop * loop)` | Create the idler with the given event loop. -`public template`
`inline explicit Idler(Function && func,Args &&... args)` | Create and start the idler with the given callback. -`public template`
`inline explicit Idler(uv::Loop * loop,Function && func,Args &&... args)` | Create and start the idler with the given callback and event loop. -`public template`
`inline void start(Function && func,Args &&... args)` | Start the idler with the given callback function. -`public virtual void start(std::function< void()> func)` | Start the idler with the given callback function. -`public virtual ~Idler()` | -`public `[`uv::Handle`](#classscy_1_1uv_1_1Handle)`< uv_idle_t > & handle()` | -`protected `[`uv::Handle`](./doc/api-uv.md#classscy_1_1uv_1_1Handle)`< uv_idle_t > _handle` | -`protected virtual void init()` | -`protected virtual bool async() const` | - -## Members - -#### `public Idler(uv::Loop * loop)` - -Create the idler with the given event loop. - - - -#### `public template`
`inline explicit Idler(Function && func,Args &&... args)` - -Create and start the idler with the given callback. - - - -#### `public template`
`inline explicit Idler(uv::Loop * loop,Function && func,Args &&... args)` - -Create and start the idler with the given callback and event loop. - - - -#### `public template`
`inline void start(Function && func,Args &&... args)` - -Start the idler with the given callback function. - - - -#### `public virtual void start(std::function< void()> func)` - -Start the idler with the given callback function. - - - -#### `public virtual ~Idler()` - - - - - -#### `public `[`uv::Handle`](#classscy_1_1uv_1_1Handle)`< uv_idle_t > & handle()` - - - - - -#### `protected `[`uv::Handle`](./doc/api-uv.md#classscy_1_1uv_1_1Handle)`< uv_idle_t > _handle` - - - - - -#### `protected virtual void init()` - - - - - -#### `protected virtual bool async() const` - - - -Returns true if the implementation is thread-based, or false if it belongs to an event loop. - -# class `scy::IPacket` - - - - -The basic packet type which is passed around the LibSourcey system. [IPacket](#classscy_1_1IPacket) can be extended for each protocol to enable polymorphic processing and callbacks using [PacketStream](#classscy_1_1PacketStream) and friends. - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public void * source` | -`public void * opaque` | -`public `[`IPacketInfo`](./doc/api-base.md#structscy_1_1IPacketInfo)` * info` | -`public `[`Bitwise`](./doc/api-base.md#structscy_1_1Bitwise)` flags` | Provides basic information about the packet. -`public inline IPacket(void * source,void * opaque,`[`IPacketInfo`](#structscy_1_1IPacketInfo)` * info,unsigned flags)` | -`public inline IPacket(const `[`IPacket`](#classscy_1_1IPacket)` & r)` | -`public inline `[`IPacket`](#classscy_1_1IPacket)` & operator=(const `[`IPacket`](#classscy_1_1IPacket)` & r)` | -`public `[`IPacket`](#classscy_1_1IPacket)` * clone() const` | -`public inline virtual ~IPacket()` | -`public ssize_t read(const `[`ConstBuffer`](#classscy_1_1ConstBuffer)` &)` | -`public void write(`[`Buffer`](#group__base_1gab10b36b080deb583ed703fca6b63ffdd)` &) const` | -`public inline virtual size_t size() const` | -`public inline virtual bool hasData() const` | -`public inline virtual char * data() const` | The packet data pointer for buffered packets. -`public inline virtual const void * constData() const` | The const packet data pointer for buffered packets. -`public const char * className() const` | -`public inline virtual void print(std::ostream & os) const` | - -## Members - -#### `public void * source` - - - -Packet source pointer reference which enables processors along the signal chain can determine the packet origin. Often a subclass of PacketStreamSource. - -#### `public void * opaque` - - - -Optional client data pointer. This pointer is not managed by the packet. - -#### `public `[`IPacketInfo`](./doc/api-base.md#structscy_1_1IPacketInfo)` * info` - - - -Optional extra information about the packet. This pointer is managed by the packet. - -#### `public `[`Bitwise`](./doc/api-base.md#structscy_1_1Bitwise)` flags` - -Provides basic information about the packet. - - - -#### `public inline IPacket(void * source,void * opaque,`[`IPacketInfo`](#structscy_1_1IPacketInfo)` * info,unsigned flags)` - - - - - -#### `public inline IPacket(const `[`IPacket`](#classscy_1_1IPacket)` & r)` - - - - - -#### `public inline `[`IPacket`](#classscy_1_1IPacket)` & operator=(const `[`IPacket`](#classscy_1_1IPacket)` & r)` - - - - - -#### `public `[`IPacket`](#classscy_1_1IPacket)` * clone() const` - - - - - -#### `public inline virtual ~IPacket()` - - - - - -#### `public ssize_t read(const `[`ConstBuffer`](#classscy_1_1ConstBuffer)` &)` - - - -Read/parse to the packet from the given input buffer. The number of bytes read is returned. - -#### `public void write(`[`Buffer`](#group__base_1gab10b36b080deb583ed703fca6b63ffdd)` &) const` - - - -Copy/generate to the packet given output buffer. The number of bytes written can be obtained from the buffer. - -Todo: It may be prefferable to use our pod types here instead of buffer input, but the current codebase requires that the buffer be dynamically resizable for some protocols... - -#### `public inline virtual size_t size() const` - - - -The size of the packet in bytes. - -This is the nember of bytes that will be written on a call to [write()](#group__base_1gabdcb765c58d74be25e190680bf7483d6), but may not be the number of bytes that will be consumed by [read()](#group__base_1ga17dec4307d132f37add42674fbfc18f1). - -#### `public inline virtual bool hasData() const` - - - - - -#### `public inline virtual char * data() const` - -The packet data pointer for buffered packets. - - - -#### `public inline virtual const void * constData() const` - -The const packet data pointer for buffered packets. - - - -#### `public const char * className() const` - - - - - -#### `public inline virtual void print(std::ostream & os) const` - - - - - -# class `scy::IPacketCreationStrategy` - - - - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public inline IPacketCreationStrategy()` | -`public inline virtual ~IPacketCreationStrategy()` | -`public `[`IPacket`](#classscy_1_1IPacket)` * create(const `[`ConstBuffer`](#classscy_1_1ConstBuffer)` & buffer,size_t & nread) const` | -`public int priority() const` | - -## Members - -#### `public inline IPacketCreationStrategy()` - - - - - -#### `public inline virtual ~IPacketCreationStrategy()` - - - - - -#### `public `[`IPacket`](#classscy_1_1IPacket)` * create(const `[`ConstBuffer`](#classscy_1_1ConstBuffer)` & buffer,size_t & nread) const` - - - - - -#### `public int priority() const` - - - - - -# class `scy::KVCollection` - - -Reusable stack based unique key-value store for DRY coding. - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public inline KVCollection()` | -`public inline virtual ~KVCollection()` | -`public inline virtual bool add(const TKey & key,const TValue & item,bool update,bool whiny)` | -`public inline virtual TValue & get(const TKey & key)` | -`public inline virtual const TValue & get(const TKey & key,const TValue & defaultValue) const` | -`public inline virtual bool remove(const TKey & key)` | -`public inline virtual bool has(const TKey & key) const` | -`public inline virtual bool empty() const` | -`public inline virtual size_t size() const` | -`public inline virtual void clear()` | -`public inline virtual Map & map()` | -`protected Map _map` | - -## Members - -#### `public inline KVCollection()` - - - - - -#### `public inline virtual ~KVCollection()` - - - - - -#### `public inline virtual bool add(const TKey & key,const TValue & item,bool update,bool whiny)` - - - - - -#### `public inline virtual TValue & get(const TKey & key)` - - - - - -#### `public inline virtual const TValue & get(const TKey & key,const TValue & defaultValue) const` - - - - - -#### `public inline virtual bool remove(const TKey & key)` - - - - - -#### `public inline virtual bool has(const TKey & key) const` - - - - - -#### `public inline virtual bool empty() const` - - - - - -#### `public inline virtual size_t size() const` - - - - - -#### `public inline virtual void clear()` - - - - - -#### `public inline virtual Map & map()` - - - - - -#### `protected Map _map` - - - - - -# class `scy::LiveCollection` - -``` -class scy::LiveCollection - : public scy::PointerCollection< TKey, TValue, TDeleter > -``` - - - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public `[`Signal`](#classscy_1_1Signal)< void(TValue &)`> ItemAdded` | -`public `[`Signal`](#classscy_1_1Signal)< void(const TValue &)`> ItemRemoved` | -`public inline virtual void onAdd(const TKey &,TValue * item)` | -`public inline virtual void onRemove(const TKey &,TValue * item)` | - -## Members - -#### `public `[`Signal`](#classscy_1_1Signal)< void(TValue &)`> ItemAdded` - - - - - -#### `public `[`Signal`](#classscy_1_1Signal)< void(const TValue &)`> ItemRemoved` - - - - - -#### `public inline virtual void onAdd(const TKey &,TValue * item)` - - - - - -#### `public inline virtual void onRemove(const TKey &,TValue * item)` - - - - - -# class `scy::LocalDateTime` - - - - -This class represents an instant in local time (as opposed to UTC), expressed in years, months, days, hours, minutes, seconds and milliseconds based on the Gregorian calendar. - -In addition to the date and time, the class also maintains a time zone differential, which denotes the difference in seconds from UTC to local time, i.e. UTC = local time - time zone differential. - -Although [LocalDateTime](#classscy_1_1LocalDateTime) supports relational and arithmetic operators, all date/time comparisons and date/time arithmetics should be done in UTC, using the [DateTime](#classscy_1_1DateTime) or [Timestamp](#classscy_1_1Timestamp) class for better performance. The relational operators normalize the dates/times involved to UTC before carrying out the comparison. - -The time zone differential is based on the input date and time and current time zone. A number of constructors accept an explicit time zone differential parameter. These should not be used since daylight savings time processing is impossible since the time zone is unknown. Each of the constructors accepting a tzd parameter have been marked as deprecated and may be removed in a future revision. - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public LocalDateTime()` | -`public LocalDateTime(int year,int month,int day,int hour,int minute,int second,int millisecond,int microsecond)` | -`public LocalDateTime(int tzd,int year,int month,int day,int hour,int minute,int second,int millisecond,int microsecond)` | -`public LocalDateTime(const `[`DateTime`](#classscy_1_1DateTime)` & dateTime)` | -`public LocalDateTime(int tzd,const `[`DateTime`](#classscy_1_1DateTime)` & dateTime)` | -`public LocalDateTime(int tzd,const `[`DateTime`](#classscy_1_1DateTime)` & dateTime,bool adjust)` | -`public LocalDateTime(double julianDay)` | Creates a [LocalDateTime](./doc/api-base.md#classscy_1_1LocalDateTime) for the given Julian day in the local time zone. -`public LocalDateTime(int tzd,double julianDay)` | -`public LocalDateTime(const `[`LocalDateTime`](#classscy_1_1LocalDateTime)` & dateTime)` | Copy constructor. Creates the [LocalDateTime](./doc/api-base.md#classscy_1_1LocalDateTime) from another one. -`public ~LocalDateTime()` | Destroys the [LocalDateTime](./doc/api-base.md#classscy_1_1LocalDateTime). -`public `[`LocalDateTime`](#classscy_1_1LocalDateTime)` & operator=(const `[`LocalDateTime`](#classscy_1_1LocalDateTime)` & dateTime)` | Assigns another [LocalDateTime](./doc/api-base.md#classscy_1_1LocalDateTime). -`public `[`LocalDateTime`](#classscy_1_1LocalDateTime)` & operator=(const `[`Timestamp`](#classscy_1_1Timestamp)` & timestamp)` | Assigns a timestamp. -`public `[`LocalDateTime`](#classscy_1_1LocalDateTime)` & operator=(double julianDay)` | Assigns a Julian day in the local time zone. -`public `[`LocalDateTime`](#classscy_1_1LocalDateTime)` & assign(int year,int month,int day,int hour,int minute,int second,int millisecond,int microseconds)` | -`public `[`LocalDateTime`](#classscy_1_1LocalDateTime)` & assign(int tzd,int year,int month,int day,int hour,int minute,int second,int millisecond,int microseconds)` | -`public `[`LocalDateTime`](#classscy_1_1LocalDateTime)` & assign(int tzd,double julianDay)` | -`public void swap(`[`LocalDateTime`](#classscy_1_1LocalDateTime)` & dateTime)` | Swaps the [LocalDateTime](./doc/api-base.md#classscy_1_1LocalDateTime) with another one. -`public inline int year() const` | Returns the year. -`public inline int month() const` | Returns the month (1 to 12). -`public inline int week(int firstDayOfWeek) const` | -`public inline int day() const` | Returns the day witin the month (1 to 31). -`public inline int dayOfWeek() const` | -`public inline int dayOfYear() const` | -`public inline int hour() const` | Returns the hour (0 to 23). -`public inline int hourAMPM() const` | Returns the hour (0 to 12). -`public inline bool isAM() const` | Returns true if hour < 12;. -`public inline bool isPM() const` | Returns true if hour >= 12. -`public inline int minute() const` | Returns the minute (0 to 59). -`public inline int second() const` | Returns the second (0 to 59). -`public inline int millisecond() const` | Returns the millisecond (0 to 999) -`public inline int microsecond() const` | Returns the microsecond (0 to 999) -`public inline double julianDay() const` | Returns the julian day for the date. -`public inline int tzd() const` | Returns the time zone differential. -`public `[`DateTime`](#classscy_1_1DateTime)` utc() const` | Returns the UTC equivalent for the local date and time. -`public inline `[`Timestamp`](#classscy_1_1Timestamp)` timestamp() const` | Returns the date and time expressed as a [Timestamp](./doc/api-base.md#classscy_1_1Timestamp). -`public inline `[`Timestamp::UtcTimeVal`](#group__base_1gaec8ace0f25db0ce91c10b30270c3dc24)` utcTime() const` | Returns the UTC equivalent for the local date and time. -`public bool operator==(const `[`LocalDateTime`](#classscy_1_1LocalDateTime)` & dateTime) const` | -`public bool operator!=(const `[`LocalDateTime`](#classscy_1_1LocalDateTime)` & dateTime) const` | -`public bool operator<(const `[`LocalDateTime`](#classscy_1_1LocalDateTime)` & dateTime) const` | -`public bool operator<=(const `[`LocalDateTime`](#classscy_1_1LocalDateTime)` & dateTime) const` | -`public bool operator>(const `[`LocalDateTime`](#classscy_1_1LocalDateTime)` & dateTime) const` | -`public bool operator>=(const `[`LocalDateTime`](#classscy_1_1LocalDateTime)` & dateTime) const` | -`public `[`LocalDateTime`](#classscy_1_1LocalDateTime)` operator+(const `[`Timespan`](#classscy_1_1Timespan)` & span) const` | -`public `[`LocalDateTime`](#classscy_1_1LocalDateTime)` operator-(const `[`Timespan`](#classscy_1_1Timespan)` & span) const` | -`public `[`Timespan`](#classscy_1_1Timespan)` operator-(const `[`LocalDateTime`](#classscy_1_1LocalDateTime)` & dateTime) const` | -`public `[`LocalDateTime`](#classscy_1_1LocalDateTime)` & operator+=(const `[`Timespan`](#classscy_1_1Timespan)` & span)` | -`public `[`LocalDateTime`](#classscy_1_1LocalDateTime)` & operator-=(const `[`Timespan`](#classscy_1_1Timespan)` & span)` | -`protected LocalDateTime(`[`Timestamp::UtcTimeVal`](#group__base_1gaec8ace0f25db0ce91c10b30270c3dc24)` utcTime,`[`Timestamp::TimeDiff`](#group__base_1ga9f06831e4e9b9cbc6f061cc61dc91fd0)` diff,int tzd)` | -`protected void determineTzd(bool adjust)` | -`protected inline void adjustForTzd()` | Adjust the _dateTime member based on the _tzd member. -`protected std::time_t dstOffset(int & dstOffset) const` | Determine the DST offset for the current date/time. - -## Members - -#### `public LocalDateTime()` - - - -Creates a [LocalDateTime](#classscy_1_1LocalDateTime) with the current date/time for the current time zone. - -#### `public LocalDateTime(int year,int month,int day,int hour,int minute,int second,int millisecond,int microsecond)` - - - -Creates a [LocalDateTime](#classscy_1_1LocalDateTime) for the given Gregorian local date and time. - -* year is from 0 to 9999. - - -* month is from 1 to 12. - - -* day is from 1 to 31. - - -* hour is from 0 to 23. - - -* minute is from 0 to 59. - - -* second is from 0 to 59. - - -* millisecond is from 0 to 999. - - -* microsecond is from 0 to 999. - -#### `public LocalDateTime(int tzd,int year,int month,int day,int hour,int minute,int second,int millisecond,int microsecond)` - - - -@ deprecated Creates a [LocalDateTime](#classscy_1_1LocalDateTime) for the given Gregorian date and time in the time zone denoted by the time zone differential in tzd. - -* tzd is in seconds. - - -* year is from 0 to 9999. - - -* month is from 1 to 12. - - -* day is from 1 to 31. - - -* hour is from 0 to 23. - - -* minute is from 0 to 59. - - -* second is from 0 to 59. - - -* millisecond is from 0 to 999. - - -* microsecond is from 0 to 999. - -#### `public LocalDateTime(const `[`DateTime`](#classscy_1_1DateTime)` & dateTime)` - - - -Creates a [LocalDateTime](#classscy_1_1LocalDateTime) from the UTC time given in dateTime, using the time zone differential of the current time zone. - -#### `public LocalDateTime(int tzd,const `[`DateTime`](#classscy_1_1DateTime)` & dateTime)` - - - -@ deprecated Creates a [LocalDateTime](#classscy_1_1LocalDateTime) from the UTC time given in dateTime, using the given time zone differential. Adjusts dateTime for the given time zone differential. - -#### `public LocalDateTime(int tzd,const `[`DateTime`](#classscy_1_1DateTime)` & dateTime,bool adjust)` - - - -@ deprecated Creates a [LocalDateTime](#classscy_1_1LocalDateTime) from the UTC time given in dateTime, using the given time zone differential. If adjust is true, adjusts dateTime for the given time zone differential. - -#### `public LocalDateTime(double julianDay)` - -Creates a [LocalDateTime](#classscy_1_1LocalDateTime) for the given Julian day in the local time zone. - - - -#### `public LocalDateTime(int tzd,double julianDay)` - - - -@ deprecated Creates a [LocalDateTime](#classscy_1_1LocalDateTime) for the given Julian day in the time zone denoted by the time zone differential in tzd. - -#### `public LocalDateTime(const `[`LocalDateTime`](#classscy_1_1LocalDateTime)` & dateTime)` - -Copy constructor. Creates the [LocalDateTime](#classscy_1_1LocalDateTime) from another one. - - - -#### `public ~LocalDateTime()` - -Destroys the [LocalDateTime](#classscy_1_1LocalDateTime). - - - -#### `public `[`LocalDateTime`](#classscy_1_1LocalDateTime)` & operator=(const `[`LocalDateTime`](#classscy_1_1LocalDateTime)` & dateTime)` - -Assigns another [LocalDateTime](#classscy_1_1LocalDateTime). - - - -#### `public `[`LocalDateTime`](#classscy_1_1LocalDateTime)` & operator=(const `[`Timestamp`](#classscy_1_1Timestamp)` & timestamp)` - -Assigns a timestamp. - - - -#### `public `[`LocalDateTime`](#classscy_1_1LocalDateTime)` & operator=(double julianDay)` - -Assigns a Julian day in the local time zone. - - - -#### `public `[`LocalDateTime`](#classscy_1_1LocalDateTime)` & assign(int year,int month,int day,int hour,int minute,int second,int millisecond,int microseconds)` - - - -Assigns a Gregorian local date and time. - -* year is from 0 to 9999. - - -* month is from 1 to 12. - - -* day is from 1 to 31. - - -* hour is from 0 to 23. - - -* minute is from 0 to 59. - - -* second is from 0 to 59. - - -* millisecond is from 0 to 999. - - -* microsecond is from 0 to 999. - -#### `public `[`LocalDateTime`](#classscy_1_1LocalDateTime)` & assign(int tzd,int year,int month,int day,int hour,int minute,int second,int millisecond,int microseconds)` - - - -@ deprecated Assigns a Gregorian local date and time in the time zone denoted by the time zone differential in tzd. - -* tzd is in seconds. - - -* year is from 0 to 9999. - - -* month is from 1 to 12. - - -* day is from 1 to 31. - - -* hour is from 0 to 23. - - -* minute is from 0 to 59. - - -* second is from 0 to 59. - - -* millisecond is from 0 to 999. - - -* microsecond is from 0 to 999. - -#### `public `[`LocalDateTime`](#classscy_1_1LocalDateTime)` & assign(int tzd,double julianDay)` - - - -@ deprecated Assigns a Julian day in the time zone denoted by the time zone differential in tzd. - -#### `public void swap(`[`LocalDateTime`](#classscy_1_1LocalDateTime)` & dateTime)` - -Swaps the [LocalDateTime](#classscy_1_1LocalDateTime) with another one. - - - -#### `public inline int year() const` - -Returns the year. - - - -#### `public inline int month() const` - -Returns the month (1 to 12). - - - -#### `public inline int week(int firstDayOfWeek) const` - - - -Returns the week number within the year. FirstDayOfWeek should be either SUNDAY (0) or MONDAY (1). The returned week number will be from 0 to 53. Week number 1 is the week containing January 4. This is in accordance to ISO 8601. - -The following example assumes that firstDayOfWeek is MONDAY. For 2005, which started on a Saturday, week 1 will be the week starting on Monday, January 3. January 1 and 2 will fall within week 0 (or the last week of the previous year). - -For 2007, which starts on a Monday, week 1 will be the week startung on Monday, January 1. There will be no week 0 in 2007. - -#### `public inline int day() const` - -Returns the day witin the month (1 to 31). - - - -#### `public inline int dayOfWeek() const` - - - -Returns the weekday (0 to 6, where 0 = Sunday, 1 = Monday, ..., 6 = Saturday). - -#### `public inline int dayOfYear() const` - - - -Returns the number of the day in the year. January 1 is 1, February 1 is 32, etc. - -#### `public inline int hour() const` - -Returns the hour (0 to 23). - - - -#### `public inline int hourAMPM() const` - -Returns the hour (0 to 12). - - - -#### `public inline bool isAM() const` - -Returns true if hour < 12;. - - - -#### `public inline bool isPM() const` - -Returns true if hour >= 12. - - - -#### `public inline int minute() const` - -Returns the minute (0 to 59). - - - -#### `public inline int second() const` - -Returns the second (0 to 59). - - - -#### `public inline int millisecond() const` - -Returns the millisecond (0 to 999) - - - -#### `public inline int microsecond() const` - -Returns the microsecond (0 to 999) - - - -#### `public inline double julianDay() const` - -Returns the julian day for the date. - - - -#### `public inline int tzd() const` - -Returns the time zone differential. - - - -#### `public `[`DateTime`](#classscy_1_1DateTime)` utc() const` - -Returns the UTC equivalent for the local date and time. - - - -#### `public inline `[`Timestamp`](#classscy_1_1Timestamp)` timestamp() const` - -Returns the date and time expressed as a [Timestamp](#classscy_1_1Timestamp). - - - -#### `public inline `[`Timestamp::UtcTimeVal`](#group__base_1gaec8ace0f25db0ce91c10b30270c3dc24)` utcTime() const` - -Returns the UTC equivalent for the local date and time. - - - -#### `public bool operator==(const `[`LocalDateTime`](#classscy_1_1LocalDateTime)` & dateTime) const` - - - - - -#### `public bool operator!=(const `[`LocalDateTime`](#classscy_1_1LocalDateTime)` & dateTime) const` - - - - - -#### `public bool operator<(const `[`LocalDateTime`](#classscy_1_1LocalDateTime)` & dateTime) const` - - - - - -#### `public bool operator<=(const `[`LocalDateTime`](#classscy_1_1LocalDateTime)` & dateTime) const` - - - - - -#### `public bool operator>(const `[`LocalDateTime`](#classscy_1_1LocalDateTime)` & dateTime) const` - - - - - -#### `public bool operator>=(const `[`LocalDateTime`](#classscy_1_1LocalDateTime)` & dateTime) const` - - - - - -#### `public `[`LocalDateTime`](#classscy_1_1LocalDateTime)` operator+(const `[`Timespan`](#classscy_1_1Timespan)` & span) const` - - - - - -#### `public `[`LocalDateTime`](#classscy_1_1LocalDateTime)` operator-(const `[`Timespan`](#classscy_1_1Timespan)` & span) const` - - - - - -#### `public `[`Timespan`](#classscy_1_1Timespan)` operator-(const `[`LocalDateTime`](#classscy_1_1LocalDateTime)` & dateTime) const` - - - - - -#### `public `[`LocalDateTime`](#classscy_1_1LocalDateTime)` & operator+=(const `[`Timespan`](#classscy_1_1Timespan)` & span)` - - - - - -#### `public `[`LocalDateTime`](#classscy_1_1LocalDateTime)` & operator-=(const `[`Timespan`](#classscy_1_1Timespan)` & span)` - - - - - -#### `protected LocalDateTime(`[`Timestamp::UtcTimeVal`](#group__base_1gaec8ace0f25db0ce91c10b30270c3dc24)` utcTime,`[`Timestamp::TimeDiff`](#group__base_1ga9f06831e4e9b9cbc6f061cc61dc91fd0)` diff,int tzd)` - - - - - -#### `protected void determineTzd(bool adjust)` - - - -Recalculate the tzd based on the _dateTime member based on the current timezone using the Standard C runtime functions. If adjust is true, then [adjustForTzd()](#group__base_1gad0d104ecf1aa081650b681f2afe5718d) is called after the differential is calculated. - -#### `protected inline void adjustForTzd()` - -Adjust the _dateTime member based on the _tzd member. - - - -#### `protected std::time_t dstOffset(int & dstOffset) const` - -Determine the DST offset for the current date/time. - - - -# class `scy::LogChannel` - - - - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public LogChannel(const std::string & name,LogLevel level,const std::string & timeFormat)` | -`public inline virtual ~LogChannel()` | -`public virtual void write(const `[`LogStream`](#structscy_1_1LogStream)` & stream)` | -`public virtual void write(const std::string & message,LogLevel level,const char * realm,const void * ptr)` | -`public virtual void format(const `[`LogStream`](#structscy_1_1LogStream)` & stream,std::ostream & ost)` | -`public inline std::string name() const` | -`public inline LogLevel level() const` | -`public inline std::string timeFormat() const` | -`public inline void setLevel(LogLevel level)` | -`public inline void setDateFormat(const std::string & format)` | -`public inline void setFilter(const std::string & filter)` | -`protected std::string _name` | -`protected LogLevel _level` | -`protected std::string _timeFormat` | -`protected std::string _filter` | - -## Members - -#### `public LogChannel(const std::string & name,LogLevel level,const std::string & timeFormat)` - - - - - -#### `public inline virtual ~LogChannel()` - - - - - -#### `public virtual void write(const `[`LogStream`](#structscy_1_1LogStream)` & stream)` - - - - - -#### `public virtual void write(const std::string & message,LogLevel level,const char * realm,const void * ptr)` - - - - - -#### `public virtual void format(const `[`LogStream`](#structscy_1_1LogStream)` & stream,std::ostream & ost)` - - - - - -#### `public inline std::string name() const` - - - - - -#### `public inline LogLevel level() const` - - - - - -#### `public inline std::string timeFormat() const` - - - - - -#### `public inline void setLevel(LogLevel level)` - - - - - -#### `public inline void setDateFormat(const std::string & format)` - - - - - -#### `public inline void setFilter(const std::string & filter)` - - - - - -#### `protected std::string _name` - - - - - -#### `protected LogLevel _level` - - - - - -#### `protected std::string _timeFormat` - - - - - -#### `protected std::string _filter` - - - - - -# class `scy::Logger` - - -[Logger](#classscy_1_1Logger) class. - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public Logger()` | -`public ~Logger()` | -`public void add(`[`LogChannel`](#classscy_1_1LogChannel)` * channel)` | Adds the given log channel. -`public void remove(const std::string & name,bool freePointer)` | -`public `[`LogChannel`](#classscy_1_1LogChannel)` * get(const std::string & name,bool whiny) const` | -`public void setDefault(const std::string & name)` | Sets the default log to the specified log channel. -`public void setWriter(`[`LogWriter`](#classscy_1_1LogWriter)` * writer)` | Sets the log writer instance. -`public `[`LogChannel`](#classscy_1_1LogChannel)` * getDefault() const` | -`public void write(const `[`LogStream`](#structscy_1_1LogStream)` & stream)` | -`public void write(`[`LogStream`](#structscy_1_1LogStream)` * stream)` | -`public `[`LogStream`](#structscy_1_1LogStream)` & send(const char * level,const char * realm,const void * ptr,const char * channel) const` | -`protected mutable std::mutex _mutex` | -`protected LogChannelMap _channels` | -`protected `[`LogChannel`](./doc/api-base.md#classscy_1_1LogChannel)` * _defaultChannel` | -`protected `[`LogWriter`](./doc/api-base.md#classscy_1_1LogWriter)` * _writer` | -`protected Logger(const `[`Logger`](#classscy_1_1Logger)` &) = delete` | NonCopyable and NonMovable. -`protected `[`Logger`](#classscy_1_1Logger)` & operator=(const `[`Logger`](#classscy_1_1Logger)` &) = delete` | - -## Members - -#### `public Logger()` - - - - - -#### `public ~Logger()` - - - - - -#### `public void add(`[`LogChannel`](#classscy_1_1LogChannel)` * channel)` - -Adds the given log channel. - - - -#### `public void remove(const std::string & name,bool freePointer)` - - - -Removes the given log channel by name, and optionally frees the pointer. - -#### `public `[`LogChannel`](#classscy_1_1LogChannel)` * get(const std::string & name,bool whiny) const` - - - -Returns the specified log channel. Throws an exception if the channel doesn't exist. - -#### `public void setDefault(const std::string & name)` - -Sets the default log to the specified log channel. - - - -#### `public void setWriter(`[`LogWriter`](#classscy_1_1LogWriter)` * writer)` - -Sets the log writer instance. - - - -#### `public `[`LogChannel`](#classscy_1_1LogChannel)` * getDefault() const` - - - -Returns the default log channel, or the nullptr channel if no default channel has been set. +#### operator() -#### `public void write(const `[`LogStream`](#structscy_1_1LogStream)` & stream)` +```cpp +inline bool operator()(const std::string & s1, const std::string & s2) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `s1` | `const std::string &` | | +| `s2` | `const std::string &` | | +## Configuration -Writes the given message to the default log channel. The message will be copied. +> **Subclasses:** `scy::json::Configuration` +> **Defined in:** `configuration.h` -#### `public void write(`[`LogStream`](#structscy_1_1LogStream)` * stream)` +[Configuration](#classscy_1_1Configuration) is an abstract base class for managing different kinds of configuration storage back ends such as JSON, XML, or database. +Subclasses must override the [getRaw()](#group__base_1ga1246d954823215df6d932e78a08bc23b) and [setRaw()](#group__base_1gac6a4023c271c2357334275f15329310d) and methods. +This class is safe for multithreaded use. -Writes the given message to the default log channel. The stream pointer will be deleted when appropriate. +### Members + +| Name | Description | +|------|-------------| +| [`Configuration`](#group__base_1ga17ab598f09508375af5c81bcca2f7adf) | Creates the [Configuration](#classscy_1_1Configuration). | +| [`~Configuration`](#group__base_1ga92fedd22f2c662f1fd5ba513dedaad45) | Destroys the [Configuration](#classscy_1_1Configuration). | +| [`exists`](#group__base_1ga46b7b29d78f0cf2939e9ffb3e561652c) | Returns true if the property with the given key exists. | +| [`getString`](#group__base_1ga05bb2078ab85e6d01e07bd0339e7f051) | Returns the string value of the property with the given name. Throws a NotFoundException if the key does not exist. | +| [`getString`](#group__base_1ga759bde263c84572e2dca86974b79abe0) | If a property with the given key exists, returns the property's string value, otherwise returns the given default value. | +| [`getRawString`](#group__base_1ga32c5e46d389028da0c63b71059b261f1) | Returns the raw string value of the property with the given name. Throws a NotFoundException if the key does not exist. References to other properties are not expanded. | +| [`getRawString`](#group__base_1ga39dea64c1f5a83216ed7f1de59fbc1ce) | If a property with the given key exists, returns the property's raw string value, otherwise returns the given default value. References to other properties are not expanded. | +| [`getInt`](#group__base_1gae4002dbb61ede2e81e518474ebc49057) | Returns the int value of the property with the given name. Throws a NotFoundException if the key does not exist. Throws a SyntaxException if the property can not be converted to an int. Numbers starting with 0x are treated as hexadecimal. | +| [`getInt`](#group__base_1ga8b3ab025bfee6fdd2b9e83a75f892ca4) | If a property with the given key exists, returns the property's int value, otherwise returns the given default value. Throws a SyntaxException if the property can not be converted to an int. Numbers starting with 0x are treated as hexadecimal. | +| [`getLargeInt`](#group__base_1gad069788603d90de791b983999d127f88) | Returns the int value of the property with the given name. Throws a NotFoundException if the key does not exist. Throws a SyntaxException if the property can not be converted to an int. Numbers starting with 0x are treated as hexadecimal. | +| [`getLargeInt`](#group__base_1ga4048a586cef122d39c1553228c407524) | If a property with the given key exists, returns the property's int value, otherwise returns the given default value. Throws a SyntaxException if the property can not be converted to an int. Numbers starting with 0x are treated as hexadecimal. | +| [`getDouble`](#group__base_1gabb0a768d637e028d16bd14ddb3c6eeeb) | Returns the double value of the property with the given name. Throws a NotFoundException if the key does not exist. Throws a SyntaxException if the property can not be converted to a double. | +| [`getDouble`](#group__base_1gaa570bb19020ae6f6d1afa8b5e099da84) | If a property with the given key exists, returns the property's double value, otherwise returns the given default value. Throws a SyntaxException if the property can not be converted to an double. | +| [`getBool`](#group__base_1ga18f5f14dbe585841a2c97e3e6fabe923) | Returns the double value of the property with the given name. Throws a NotFoundException if the key does not exist. Throws a SyntaxException if the property can not be converted to a double. | +| [`getBool`](#group__base_1gacf0956fc36e268cbc074e11ac8975b54) | If a property with the given key exists, returns the property's bool value, otherwise returns the given default value. Throws a SyntaxException if the property can not be converted to a boolean. The following string values can be converted into a boolean: | +| [`setString`](#group__base_1gaa6619e41320857455ea04e4cf5dc5ada) | Sets the property with the given key to the given value. An already existing value for the key is overwritten. | +| [`setInt`](#group__base_1ga9668ea52c509d5ee335ca194402b0a8c) | Sets the property with the given key to the given value. An already existing value for the key is overwritten. | +| [`setLargeInt`](#group__base_1ga82ff1ce7b02ab4989669913175970cd2) | Sets the property with the given key to the given value. An already existing value for the key is overwritten. | +| [`setDouble`](#group__base_1ga0c39abf4df23106c7b47221fe9cc3252) | Sets the property with the given key to the given value. An already existing value for the key is overwritten. | +| [`setBool`](#group__base_1ga6130c066e06d2f3c8554160d216058bf) | Sets the property with the given key to the given value. An already existing value for the key is overwritten. | +| [`getRaw`](#group__base_1ga1246d954823215df6d932e78a08bc23b) | If the property with the given key exists, stores the property's value in value and returns true. Otherwise, returns false. | +| [`setRaw`](#group__base_1gac6a4023c271c2357334275f15329310d) | Sets the property with the given key to the given value. An already existing value for the key is overwritten. | +| [`Configuration`](#group__base_1ga138e9fc74cc2ade87e6786cb0423be9a) | | +| [`operator=`](#group__base_1ga917d8e07fffa63872970f751ea20eab6) | | +| [`parseInt`](#group__base_1ga3953767cc1696a6d52453c3c5ed9fc29) | | +| [`parseLargeInt`](#group__base_1gaefe4edd971f9b5156ba539a93d0a4bae) | | +| [`parseBool`](#group__base_1gac311aca82c3ab375ae07e099f7889761) | | +| [`PropertyChanged`](#group__base_1ga885286a3a5e03556d0aab503afa8952d) | The Key and Value of the changed configuration property. | +| [`_mutex`](#group__base_1gaad886cabbbd16422e1cf70c146d2cae1) | | + +--- + +#### Configuration + +```cpp +Configuration() +``` -#### `public `[`LogStream`](#structscy_1_1LogStream)` & send(const char * level,const char * realm,const void * ptr,const char * channel) const` +Creates the [Configuration](#classscy_1_1Configuration). +--- +#### ~Configuration -Sends to the default log using the given class instance. Recommend using write(LogStream&) to avoid copying data. +```cpp +virtual ~Configuration() +``` -#### `protected mutable std::mutex _mutex` +Destroys the [Configuration](#classscy_1_1Configuration). +--- +#### exists +```cpp +bool exists(const std::string & key) const +``` +Returns true if the property with the given key exists. -#### `protected LogChannelMap _channels` +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `const std::string &` | | +--- +#### getString +```cpp +std::string getString(const std::string & key) const +``` +Returns the string value of the property with the given name. Throws a NotFoundException if the key does not exist. -#### `protected `[`LogChannel`](./doc/api-base.md#classscy_1_1LogChannel)` * _defaultChannel` +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `const std::string &` | | +--- +#### getString +```cpp +std::string getString(const std::string & key, const std::string & defaultValue) const +``` +If a property with the given key exists, returns the property's string value, otherwise returns the given default value. -#### `protected `[`LogWriter`](./doc/api-base.md#classscy_1_1LogWriter)` * _writer` +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `const std::string &` | | +| `defaultValue` | `const std::string &` | | +--- +#### getRawString +```cpp +std::string getRawString(const std::string & key) const +``` +Returns the raw string value of the property with the given name. Throws a NotFoundException if the key does not exist. References to other properties are not expanded. -#### `protected Logger(const `[`Logger`](#classscy_1_1Logger)` &) = delete` +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `const std::string &` | | -NonCopyable and NonMovable. +--- +#### getRawString +```cpp +std::string getRawString(const std::string & key, const std::string & defaultValue) const +``` -#### `protected `[`Logger`](#classscy_1_1Logger)` & operator=(const `[`Logger`](#classscy_1_1Logger)` &) = delete` +If a property with the given key exists, returns the property's raw string value, otherwise returns the given default value. References to other properties are not expanded. +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `const std::string &` | | +| `defaultValue` | `const std::string &` | | +--- +#### getInt +```cpp +int getInt(const std::string & key) const +``` -# class `scy::LogWriter` +Returns the int value of the property with the given name. Throws a NotFoundException if the key does not exist. Throws a SyntaxException if the property can not be converted to an int. Numbers starting with 0x are treated as hexadecimal. +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `const std::string &` | | -Log output stream writer. +--- +#### getInt +```cpp +int getInt(const std::string & key, int defaultValue) const +``` -## Summary +If a property with the given key exists, returns the property's int value, otherwise returns the given default value. Throws a SyntaxException if the property can not be converted to an int. Numbers starting with 0x are treated as hexadecimal. - Members | Descriptions ---------------------------------|--------------------------------------------- -`public LogWriter()` | -`public virtual ~LogWriter()` | -`public virtual void write(`[`LogStream`](#structscy_1_1LogStream)` * stream)` | Writes the given log message stream. +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `const std::string &` | | +| `defaultValue` | `int` | | -## Members +--- -#### `public LogWriter()` +#### getLargeInt +```cpp +std::int64_t getLargeInt(const std::string & key) const +``` +Returns the int value of the property with the given name. Throws a NotFoundException if the key does not exist. Throws a SyntaxException if the property can not be converted to an int. Numbers starting with 0x are treated as hexadecimal. +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `const std::string &` | | +--- -#### `public virtual ~LogWriter()` +#### getLargeInt +```cpp +std::int64_t getLargeInt(const std::string & key, std::int64_t defaultValue) const +``` +If a property with the given key exists, returns the property's int value, otherwise returns the given default value. Throws a SyntaxException if the property can not be converted to an int. Numbers starting with 0x are treated as hexadecimal. +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `const std::string &` | | +| `defaultValue` | `std::int64_t` | | +--- -#### `public virtual void write(`[`LogStream`](#structscy_1_1LogStream)` * stream)` +#### getDouble -Writes the given log message stream. +```cpp +double getDouble(const std::string & key) const +``` +Returns the double value of the property with the given name. Throws a NotFoundException if the key does not exist. Throws a SyntaxException if the property can not be converted to a double. +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `const std::string &` | | -# class `scy::MutableBuffer` +--- +#### getDouble +```cpp +double getDouble(const std::string & key, double defaultValue) const +``` +If a property with the given key exists, returns the property's double value, otherwise returns the given default value. Throws a SyntaxException if the property can not be converted to an double. -The [MutableBuffer](#classscy_1_1MutableBuffer) class provides a safe representation of a buffer that can be modified. It does not own the underlying data, and so is cheap to copy or assign. +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `const std::string &` | | +| `defaultValue` | `double` | | -## Summary +--- - Members | Descriptions ---------------------------------|--------------------------------------------- -`public inline MutableBuffer()` | Construct an empty buffer. -`public inline MutableBuffer(void * data,size_t size)` | Construct a buffer to represent the given memory range. -`public inline void * data() const` | -`public inline size_t size() const` | -`public inline char * cstr() const` | Cast the buffer as a char pointer. -`public inline std::string str() const` | Returns the buffer as a string. -`protected void * _data` | -`protected size_t _size` | +#### getBool -## Members +```cpp +bool getBool(const std::string & key) const +``` -#### `public inline MutableBuffer()` +Returns the double value of the property with the given name. Throws a NotFoundException if the key does not exist. Throws a SyntaxException if the property can not be converted to a double. -Construct an empty buffer. +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `const std::string &` | | +--- +#### getBool -#### `public inline MutableBuffer(void * data,size_t size)` +```cpp +bool getBool(const std::string & key, bool defaultValue) const +``` -Construct a buffer to represent the given memory range. +If a property with the given key exists, returns the property's bool value, otherwise returns the given default value. Throws a SyntaxException if the property can not be converted to a boolean. The following string values can be converted into a boolean: +* numerical values: non zero becomes true, zero becomes false +* strings: true, yes, on become true, false, no, off become false Case does not matter. -#### `public inline void * data() const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `const std::string &` | | +| `defaultValue` | `bool` | | +--- +#### setString +```cpp +void setString(const std::string & key, const std::string & value) +``` +Sets the property with the given key to the given value. An already existing value for the key is overwritten. -#### `public inline size_t size() const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `const std::string &` | | +| `value` | `const std::string &` | | +--- +#### setInt +```cpp +void setInt(const std::string & key, int value) +``` +Sets the property with the given key to the given value. An already existing value for the key is overwritten. -#### `public inline char * cstr() const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `const std::string &` | | +| `value` | `int` | | -Cast the buffer as a char pointer. +--- +#### setLargeInt +```cpp +void setLargeInt(const std::string & key, std::int64_t value) +``` -#### `public inline std::string str() const` +Sets the property with the given key to the given value. An already existing value for the key is overwritten. -Returns the buffer as a string. +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `const std::string &` | | +| `value` | `std::int64_t` | | +--- +#### setDouble -#### `protected void * _data` +```cpp +void setDouble(const std::string & key, double value) +``` +Sets the property with the given key to the given value. An already existing value for the key is overwritten. +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `const std::string &` | | +| `value` | `double` | | +--- +#### setBool -#### `protected size_t _size` +```cpp +void setBool(const std::string & key, bool value) +``` +Sets the property with the given key to the given value. An already existing value for the key is overwritten. +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `const std::string &` | | +| `value` | `bool` | | +--- +#### getRaw -# class `scy::Mutex` +```cpp +bool getRaw(const std::string & key, std::string & value) const +``` +If the property with the given key exists, stores the property's value in value and returns true. Otherwise, returns false. +Must be overridden by subclasses. +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `const std::string &` | | +| `value` | `std::string &` | | -This class is a wrapper around uv_mutex_t. +--- -A [Mutex](#classscy_1_1Mutex) (mutual exclusion) is a synchronization mechanism used to control access to a shared resource in a concurrent (multithreaded) scenario. +#### setRaw -The [ScopedLock](#classscy_1_1ScopedLock) class is usually used to obtain a [Mutex](#classscy_1_1Mutex) lock, since it makes locking exception-safe. +```cpp +void setRaw(const std::string & key, const std::string & value) +``` -## Summary +Sets the property with the given key to the given value. An already existing value for the key is overwritten. - Members | Descriptions ---------------------------------|--------------------------------------------- -`public Mutex()` | -`public ~Mutex()` | -`public void lock()` | -`public bool tryLock()` | -`public void unlock()` | +The implementation is responsible for emitting the PropertyChanged signal. -## Members +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `const std::string &` | | +| `value` | `const std::string &` | | -#### `public Mutex()` +--- +#### Configuration +```cpp +Configuration(const Configuration &) = delete +``` +--- +#### operator= -#### `public ~Mutex()` +```cpp +Configuration & operator=(const Configuration &) = delete +``` +--- +#### parseInt +```cpp +static int parseInt(const std::string & value) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `value` | `const std::string &` | | -#### `public void lock()` +--- +#### parseLargeInt +```cpp +static std::int64_t parseLargeInt(const std::string & value) +``` -Locks the mutex. Blocks if the mutex is held by another thread. +| Parameter | Type | Description | +|-----------|------|-------------| +| `value` | `const std::string &` | | -#### `public bool tryLock()` +--- +#### parseBool +```cpp +static bool parseBool(const std::string & value) +``` -Tries to lock the mutex. Returns false if the mutex is already held by another thread. Returns true if the mutex was successfully locked. +| Parameter | Type | Description | +|-----------|------|-------------| +| `value` | `const std::string &` | | -#### `public void unlock()` +--- +#### PropertyChanged +```cpp +Signal< void(const std::string &, const std::string &)> PropertyChanged +``` -Unlocks the mutex so that it can be acquired by other threads. +The Key and Value of the changed configuration property. -# class `scy::NVCollection` +--- +#### _mutex +```cpp +std::mutex _mutex +``` +## ScopedConfiguration -A storage container for a name value collections. This collection can store multiple entries for each name, and it's getters are case-insensitive. +> **Defined in:** `configuration.h` -## Summary +[ScopedConfiguration](#classscy_1_1ScopedConfiguration) provides multiple levels of configuration for a module. Multiple levels means that there is a module level scope, and a default scope. When a property is accessed, the module scope value will be used if available, otherwise the default scope value will be used. - Members | Descriptions ---------------------------------|--------------------------------------------- -`public inline NVCollection()` | -`public inline NVCollection(const `[`NVCollection`](#classscy_1_1NVCollection)` & nvc)` | -`public inline virtual ~NVCollection()` | -`public `[`NVCollection`](#classscy_1_1NVCollection)` & operator=(const `[`NVCollection`](#classscy_1_1NVCollection)` & nvc)` | Assigns the name-value pairs of another [NVCollection](./doc/api-base.md#classscy_1_1NVCollection) to this one. -`public const std::string & operator[](const std::string & name) const` | -`public void set(const std::string & name,const std::string & value)` | Sets the value of the (first) name-value pair with the given name. -`public void add(const std::string & name,const std::string & value)` | Adds a new name-value pair with the given name and value. -`public const std::string & get(const std::string & name) const` | -`public const std::string & get(const std::string & name,const std::string & defaultValue) const` | -`public bool has(const std::string & name) const` | -`public ConstIterator find(const std::string & name) const` | -`public ConstIterator begin() const` | -`public ConstIterator end() const` | -`public bool empty() const` | Returns true iff the header does not have any content. -`public int size() const` | -`public void erase(const std::string & name)` | Removes all name-value pairs with the given name. -`public void clear()` | Removes all name-value pairs and their values. +Example scoping: Module: channels.[name].modes.[name].[value] Default: modes.[name].[value] -## Members +### Members + +| Name | Description | +|------|-------------| +| [`ScopedConfiguration`](#group__base_1gab5e9573cc6a94c6b942aeb8fa75982bf) | | +| [`ScopedConfiguration`](#group__base_1ga2d9a45d573b97ec8d2fa4c5496bdedfa) | | +| [`getString`](#group__base_1ga815efb31af29d03a283bd511d73865e1) | | +| [`getInt`](#group__base_1ga054a3db8ef6052a2c244dfbb13309b9f) | | +| [`getDouble`](#group__base_1ga2b3857cbbca439b3b825ce7f521fa061) | | +| [`getBool`](#group__base_1ga7fe7def68b732c44e7c3835b89cc53dd) | | +| [`setString`](#group__base_1ga4d0ed2a990ce5ab5b28c2ba2e06b13ad) | | +| [`setInt`](#group__base_1ga94aac2d52d9eb5689797986c40edfabf) | | +| [`setDouble`](#group__base_1ga72aa7eab9ef3496e461b5593b5edb8bf) | | +| [`setBool`](#group__base_1ga018ae27a4b9d4d2344df5723b1b01635) | | +| [`getCurrentScope`](#group__base_1ga36f148de5018eff36e52c0c990b039dc) | | +| [`getDafaultKey`](#group__base_1gac6effdc628b5f325c4585d0a06322894) | | +| [`getScopedKey`](#group__base_1ga1b6e232dfd5b13c1eaff4408adc03b77) | | +| [`operator=`](#group__base_1gac4d499e6d6ffa9b911bddebb027dcc38) | | +| [`config`](#group__base_1gab789db5bbe6952f38128f6a477b6cb45) | | +| [`currentScope`](#group__base_1gae55030c57f6402acba43d7d3ea38a415) | | +| [`defaultScope`](#group__base_1ga77d05f9ce766ee3f0a84a313ae83426b) | | + +--- + +#### ScopedConfiguration + +```cpp +ScopedConfiguration(Configuration & config, const std::string & currentScope, const std::string & defaultScope) +``` -#### `public inline NVCollection()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `config` | `Configuration &` | | +| `currentScope` | `const std::string &` | | +| `defaultScope` | `const std::string &` | | +--- +#### ScopedConfiguration +```cpp +ScopedConfiguration(const ScopedConfiguration & that) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `that` | `const ScopedConfiguration &` | | -#### `public inline NVCollection(const `[`NVCollection`](#classscy_1_1NVCollection)` & nvc)` +--- +#### getString +```cpp +std::string getString(const std::string & key, const std::string & defaultValue, bool forceDefaultScope) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `const std::string &` | | +| `defaultValue` | `const std::string &` | | +| `forceDefaultScope` | `bool` | | +--- -#### `public inline virtual ~NVCollection()` +#### getInt +```cpp +int getInt(const std::string & key, int defaultValue, bool forceDefaultScope) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `const std::string &` | | +| `defaultValue` | `int` | | +| `forceDefaultScope` | `bool` | | +--- +#### getDouble -#### `public `[`NVCollection`](#classscy_1_1NVCollection)` & operator=(const `[`NVCollection`](#classscy_1_1NVCollection)` & nvc)` +```cpp +double getDouble(const std::string & key, double defaultValue, bool forceDefaultScope) const +``` -Assigns the name-value pairs of another [NVCollection](#classscy_1_1NVCollection) to this one. +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `const std::string &` | | +| `defaultValue` | `double` | | +| `forceDefaultScope` | `bool` | | +--- +#### getBool -#### `public const std::string & operator[](const std::string & name) const` +```cpp +bool getBool(const std::string & key, bool defaultValue, bool forceDefaultScope) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `const std::string &` | | +| `defaultValue` | `bool` | | +| `forceDefaultScope` | `bool` | | +--- -Returns the value of the (first) name-value pair with the given name. +#### setString -Throws a NotFoundException if the name-value pair does not exist. +```cpp +void setString(const std::string & key, const std::string & value, bool defaultScope) +``` -#### `public void set(const std::string & name,const std::string & value)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `const std::string &` | | +| `value` | `const std::string &` | | +| `defaultScope` | `bool` | | -Sets the value of the (first) name-value pair with the given name. +--- +#### setInt +```cpp +void setInt(const std::string & key, int value, bool defaultScope) +``` -#### `public void add(const std::string & name,const std::string & value)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `const std::string &` | | +| `value` | `int` | | +| `defaultScope` | `bool` | | -Adds a new name-value pair with the given name and value. +--- +#### setDouble +```cpp +void setDouble(const std::string & key, double value, bool defaultScope) +``` -#### `public const std::string & get(const std::string & name) const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `const std::string &` | | +| `value` | `double` | | +| `defaultScope` | `bool` | | +--- +#### setBool -Returns the value of the first name-value pair with the given name. +```cpp +void setBool(const std::string & key, bool value, bool defaultScope) +``` -Throws a NotFoundException if the name-value pair does not exist. +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `const std::string &` | | +| `value` | `bool` | | +| `defaultScope` | `bool` | | -#### `public const std::string & get(const std::string & name,const std::string & defaultValue) const` +--- +#### getCurrentScope +```cpp +std::string getCurrentScope(const std::string & key) const +``` -Returns the value of the first name-value pair with the given name. If no value with the given name has been found, the defaultValue is returned. +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `const std::string &` | | -#### `public bool has(const std::string & name) const` +--- +#### getDafaultKey +```cpp +std::string getDafaultKey(const std::string & key) const +``` -Returns true if there is at least one name-value pair with the given name. +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `const std::string &` | | -#### `public ConstIterator find(const std::string & name) const` +--- +#### getScopedKey +```cpp +std::string getScopedKey(const std::string & key, bool defaultScope) const +``` -Returns an iterator pointing to the first name-value pair with the given name. +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `const std::string &` | | +| `defaultScope` | `bool` | | -#### `public ConstIterator begin() const` +--- +#### operator= +```cpp +ScopedConfiguration & operator=(const ScopedConfiguration &) +``` -Returns an iterator pointing to the begin of the name-value pair collection. +--- -#### `public ConstIterator end() const` +#### config +```cpp +Configuration & config +``` +--- -Returns an iterator pointing to the end of the name-value pair collection. +#### currentScope -#### `public bool empty() const` +```cpp +std::string currentScope +``` -Returns true iff the header does not have any content. +--- +#### defaultScope +```cpp +std::string defaultScope +``` -#### `public int size() const` +## Timestamp +> **Defined in:** `datetime.h` +A [Timestamp](#classscy_1_1Timestamp) stores a monotonic* time value with (theoretical) microseconds resolution. Timestamps can be compared with each other and simple arithmetics are supported. -Returns the number of name-value pairs in the collection. +[*] Note that [Timestamp](#classscy_1_1Timestamp) values are only monotonic as long as the systems's clock is monotonic as well (and not, e.g. set back). -#### `public void erase(const std::string & name)` +Timestamps are UTC (Coordinated Universal Time) based and thus independent of the timezone in effect on the system. -Removes all name-value pairs with the given name. +### Members + +| Name | Description | +|------|-------------| +| [`Timestamp`](#group__base_1ga59eb0caf11a4b42805be30b575c64685) | Creates a timestamp with the current time. | +| [`Timestamp`](#group__base_1ga634322242b4d434f27d0b549e6a2d02a) | Creates a timestamp from the given time value. | +| [`Timestamp`](#group__base_1gaee8a093ba4e7d09969d6e9d66d39c98c) | Copy constructor. | +| [`~Timestamp`](#group__base_1ga9454ae9b51eef4ddfd6a5fc517d5fb89) | Destroys the timestamp. | +| [`operator=`](#group__base_1gaa6f065d2bafe45160d5830ec7f3fea03) | | +| [`operator=`](#group__base_1gad270942977ff386b8295e92d32a4247a) | | +| [`swap`](#group__base_1ga051b185aa50b85119422c8069b31f9b1) | Swaps the [Timestamp](#classscy_1_1Timestamp) with another one. | +| [`update`](#group__base_1gae851ba7fcabd33ddf4b69029b93e7da1) | Updates the [Timestamp](#classscy_1_1Timestamp) with the current time. | +| [`operator==`](#group__base_1gaaff90e64401ed08703d4bab0b09bc5bd) | | +| [`operator!=`](#group__base_1ga70b120698ef0ca3429d5e6035e03ab51) | | +| [`operator>`](#group__base_1gacdc27b968a6f92a38dfa29f4ce0639ca) | | +| [`operator>=`](#group__base_1gae4ddc243de02e4d233f681d9df760111) | | +| [`operator<`](#group__base_1gae1ae154f8dc65bb9966411801d514f88) | | +| [`operator<=`](#group__base_1ga18146b0b77bdc63ad3eaee69a460e38b) | | +| [`operator+`](#group__base_1gaae2bf2fef867c4856c03637c4eaa6916) | | +| [`operator-`](#group__base_1gafb9644c6db3560126efd053dfca80f7f) | | +| [`operator-`](#group__base_1gaf904d00bddad7f6dd1ad05c7fd8592ee) | | +| [`operator+=`](#group__base_1gab575836d90b63b74515022efa909b261) | | +| [`operator-=`](#group__base_1ga4a845176e12d2116809c4c7b9b3fd940) | | +| [`epochTime`](#group__base_1ga018ebc0e980ee7e467da6238010a4313) | Returns the timestamp expressed in time_t. time_t base time is midnight, January 1, 1970. Resolution is one second. | +| [`utcTime`](#group__base_1gac3ec372fc5bc417e7d38a7849d3bd173) | Returns the timestamp expressed in UTC-based time. UTC base time is midnight, October 15, 1582. Resolution is 100 nanoseconds. | +| [`epochMicroseconds`](#group__base_1ga9ed38faa45afc53468343bc1c89c6000) | Returns the timestamp expressed in microseconds since the Unix epoch, midnight, January 1, 1970. | +| [`elapsed`](#group__base_1gaee70f8a34b9712e25310f2bb642305b4) | Returns the time elapsed since the time denoted by the timestamp. Equivalent to [Timestamp()](#group__base_1ga59eb0caf11a4b42805be30b575c64685) - *this. | +| [`isElapsed`](#group__base_1gadf63758d952b2ee7aa4e00238e89e950) | Returns true iff the given interval has passed since the time denoted by the timestamp. | +| [`fromEpochTime`](#group__base_1gab8199d2f7572ad52e05e74512f402307) | Creates a timestamp from a std::time_t. | +| [`fromUtcTime`](#group__base_1gacef58d2de9fa06c922c0a8e2853d93c7) | Creates a timestamp from a UTC time value. | +| [`resolution`](#group__base_1ga66994444da248ff6b2dfd3f72768768d) | Returns the resolution in units per second. Since the timestamp has microsecond resolution, the returned value is always 1000000. | +| [`_ts`](#group__base_1gac3b48ed8bc4dbfb2de54ea9d3a4c2d04) | | + +--- + +#### Timestamp + +```cpp +Timestamp() +``` +Creates a timestamp with the current time. +--- -#### `public void clear()` +#### Timestamp -Removes all name-value pairs and their values. +```cpp +Timestamp(TimeVal tv) +``` +Creates a timestamp from the given time value. +| Parameter | Type | Description | +|-----------|------|-------------| +| `tv` | `TimeVal` | | -# class `scy::PacketFactory` +--- +#### Timestamp +```cpp +Timestamp(const Timestamp & other) +``` +Copy constructor. +| Parameter | Type | Description | +|-----------|------|-------------| +| `other` | `const Timestamp &` | | +--- -## Summary +#### ~Timestamp - Members | Descriptions ---------------------------------|--------------------------------------------- -`public inline PacketFactory()` | -`public inline virtual ~PacketFactory()` | -`public template`
`inline void registerPacketType(int priority)` | -`public template`
`inline void unregisterPacketType()` | -`public template`
`inline void registerStrategy(int priority)` | -`public template`
`inline void unregisterStrategy()` | -`public inline PacketCreationStrategyList & types()` | -`public inline PacketCreationStrategyList types() const` | -`public inline virtual bool onPacketCreated(`[`IPacket`](#classscy_1_1IPacket)` *)` | returning false will stop packet propagation -`public inline virtual `[`IPacket`](#classscy_1_1IPacket)` * createPacket(const `[`ConstBuffer`](#classscy_1_1ConstBuffer)` & buffer,size_t & nread)` | -`protected PacketCreationStrategyList _types` | +```cpp +~Timestamp() +``` -## Members +Destroys the timestamp. -#### `public inline PacketFactory()` +--- +#### operator= +```cpp +Timestamp & operator=(const Timestamp & other) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `other` | `const Timestamp &` | | +--- -#### `public inline virtual ~PacketFactory()` +#### operator= +```cpp +Timestamp & operator=(TimeVal tv) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `tv` | `TimeVal` | | +--- +#### swap -#### `public template`
`inline void registerPacketType(int priority)` +```cpp +void swap(Timestamp & timestamp) +``` +Swaps the [Timestamp](#classscy_1_1Timestamp) with another one. +| Parameter | Type | Description | +|-----------|------|-------------| +| `timestamp` | `Timestamp &` | | +--- +#### update -#### `public template`
`inline void unregisterPacketType()` +```cpp +void update() +``` +Updates the [Timestamp](#classscy_1_1Timestamp) with the current time. +--- +#### operator== +```cpp +inline bool operator==(const Timestamp & ts) const +``` -#### `public template`
`inline void registerStrategy(int priority)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `ts` | `const Timestamp &` | | +--- +#### operator!= +```cpp +inline bool operator!=(const Timestamp & ts) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `ts` | `const Timestamp &` | | -#### `public template`
`inline void unregisterStrategy()` +--- +#### operator> +```cpp +inline bool operator>(const Timestamp & ts) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `ts` | `const Timestamp &` | | +--- -#### `public inline PacketCreationStrategyList & types()` +#### operator>= +```cpp +inline bool operator>=(const Timestamp & ts) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `ts` | `const Timestamp &` | | +--- +#### operator< -#### `public inline PacketCreationStrategyList types() const` +```cpp +inline bool operator<(const Timestamp & ts) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `ts` | `const Timestamp &` | | +--- +#### operator<= +```cpp +inline bool operator<=(const Timestamp & ts) const +``` -#### `public inline virtual bool onPacketCreated(`[`IPacket`](#classscy_1_1IPacket)` *)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `ts` | `const Timestamp &` | | -returning false will stop packet propagation +--- +#### operator+ +```cpp +inline Timestamp operator+(TimeDiff d) const +``` -#### `public inline virtual `[`IPacket`](#classscy_1_1IPacket)` * createPacket(const `[`ConstBuffer`](#classscy_1_1ConstBuffer)` & buffer,size_t & nread)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `d` | `TimeDiff` | | +--- +#### operator- +```cpp +inline Timestamp operator-(TimeDiff d) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `d` | `TimeDiff` | | -#### `protected PacketCreationStrategyList _types` +--- +#### operator- +```cpp +inline TimeDiff operator-(const Timestamp & ts) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `ts` | `const Timestamp &` | | +--- -# class `scy::PacketProcessor` +#### operator+= +```cpp +inline Timestamp & operator+=(TimeDiff d) ``` -class scy::PacketProcessor - : public scy::PacketStreamAdapter -``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `d` | `TimeDiff` | | +--- -This class is a virtual interface for creating PacketStreamAdapters which process that and emit the [IPacket](#classscy_1_1IPacket) type. +#### operator-= -## Summary +```cpp +inline Timestamp & operator-=(TimeDiff d) +``` - Members | Descriptions ---------------------------------|--------------------------------------------- -`public inline PacketProcessor(`[`PacketSignal`](#group__base_1ga3ffb5bda6133fac97f3bed2b567b9b6a)` & emitter)` | -`public void process(`[`IPacket`](#classscy_1_1IPacket)` & packet)` | -`public inline virtual bool accepts(`[`IPacket`](#classscy_1_1IPacket)` &)` | -`public inline virtual void operator<<(`[`IPacket`](#classscy_1_1IPacket)` & packet)` | [Stream](#classscy_1_1Stream) operator alias for [process()](#group__base_1gad7adc3fd78dce41f0f96744dfe6d1d50) +| Parameter | Type | Description | +|-----------|------|-------------| +| `d` | `TimeDiff` | | -## Members +--- -#### `public inline PacketProcessor(`[`PacketSignal`](#group__base_1ga3ffb5bda6133fac97f3bed2b567b9b6a)` & emitter)` +#### epochTime +```cpp +inline std::time_t epochTime() const +``` +Returns the timestamp expressed in time_t. time_t base time is midnight, January 1, 1970. Resolution is one second. +--- +#### utcTime -#### `public void process(`[`IPacket`](#classscy_1_1IPacket)` & packet)` +```cpp +inline UtcTimeVal utcTime() const +``` +Returns the timestamp expressed in UTC-based time. UTC base time is midnight, October 15, 1582. Resolution is 100 nanoseconds. +--- -This method performs processing on the given packet and emits the result. +#### epochMicroseconds -Note: If packet processing is async (the packet is not in the current thread scope) then packet data must be copied. Copied data can be freed directly aFter the async call to emit() the outgoing packet. +```cpp +inline TimeVal epochMicroseconds() const +``` -#### `public inline virtual bool accepts(`[`IPacket`](#classscy_1_1IPacket)` &)` +Returns the timestamp expressed in microseconds since the Unix epoch, midnight, January 1, 1970. +--- +#### elapsed -This method ensures compatibility with the given packet type. Return false to reject the packet. +```cpp +inline TimeDiff elapsed() const +``` -#### `public inline virtual void operator<<(`[`IPacket`](#classscy_1_1IPacket)` & packet)` +Returns the time elapsed since the time denoted by the timestamp. Equivalent to [Timestamp()](#group__base_1ga59eb0caf11a4b42805be30b575c64685) - *this. -[Stream](#classscy_1_1Stream) operator alias for [process()](#group__base_1gad7adc3fd78dce41f0f96744dfe6d1d50) +--- +#### isElapsed +```cpp +inline bool isElapsed(TimeDiff interval) const +``` -# class `scy::PacketStream` +Returns true iff the given interval has passed since the time denoted by the timestamp. -``` -class scy::PacketStream - : public scy::Stateful< PacketStreamState > -``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `interval` | `TimeDiff` | | +--- +#### fromEpochTime -This class is used for processing and boradcasting IPackets in a flexible way. A [PacketStream](#classscy_1_1PacketStream) consists of one or many PacketSources, one or many PacketProcessors, and one or many delegate receivers. +```cpp +static Timestamp fromEpochTime(std::time_t t) +``` -This class enables the developer to setup a processor chain in order to perform arbitrary processing on data packets using interchangeable packet adapters, and pump the output to any delegate function,/// or even another [PacketStream](#classscy_1_1PacketStream). +Creates a timestamp from a std::time_t. -Note that [PacketStream](#classscy_1_1PacketStream) itself inherits from [PacketStreamAdapter](#classscy_1_1PacketStreamAdapter),/// so a [PacketStream](#classscy_1_1PacketStream) be the source of another [PacketStream](#classscy_1_1PacketStream). +| Parameter | Type | Description | +|-----------|------|-------------| +| `t` | `std::time_t` | | -All [PacketStream](#classscy_1_1PacketStream) methods are thread-safe, but once the stream is running you will not be able to attach or detach stream adapters. +--- -In order to synchronize output packets with the application event loop take a look at the [SyncPacketQueue](#classscy_1_1SyncPacketQueue) class. For lengthy operations you can add an [AsyncPacketQueue](#classscy_1_1AsyncPacketQueue) to the start of the stream to defer processing from the PacketSource thread. +#### fromUtcTime -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public `[`PacketSignal`](#group__base_1ga3ffb5bda6133fac97f3bed2b567b9b6a)` emitter` | Signals to delegates on outgoing packets. -`public `[`Signal](#classscy_1_1Signal)< void([PacketStream`](#classscy_1_1PacketStream) &, const std::exception_ptr &)`> Error` | -`public `[`Signal](#classscy_1_1Signal)< void([PacketStream`](#classscy_1_1PacketStream) &)`> Close` | -`public void * opaque` | -`public PacketStream(const std::string & name)` | -`public virtual ~PacketStream()` | -`public virtual void start()` | Start the stream and synchronized sources. -`public virtual void stop()` | Stop the stream and synchronized sources. -`public virtual void pause()` | Pause the stream. -`public virtual void resume()` | Resume the stream. -`public virtual void close()` | Close the stream and transition the internal state to Closed. -`public virtual void reset()` | Cleanup all managed stream adapters and reset the stream state. -`public virtual bool active() const` | Returns true when the stream is in the Active state. -`public virtual bool stopped() const` | Returns true when the stream is in the Stopping or Stopped state. -`public virtual bool closed() const` | Returns true when the stream is in the Closed or [Error](./doc/api-base.md#structscy_1_1Error) state. -`public virtual bool lock()` | -`public virtual bool locked() const` | Returns true is the stream is currently locked. -`public virtual void write(char * data,size_t len)` | Writes data to the stream (nocopy). -`public virtual void write(const char * data,size_t len)` | Writes data to the stream (copied). -`public virtual void write(`[`IPacket`](#classscy_1_1IPacket)` && packet)` | Writes an incoming packet onto the stream. -`public virtual void attachSource(`[`PacketSignal`](#group__base_1ga3ffb5bda6133fac97f3bed2b567b9b6a)` & source)` | -`public virtual void attachSource(`[`PacketStreamAdapter`](#classscy_1_1PacketStreamAdapter)` * source,bool freePointer,bool syncState)` | -`public template`
`inline void attachSource(std::shared_ptr< C > ptr,bool syncState)` | -`public virtual bool detachSource(`[`PacketSignal`](#group__base_1ga3ffb5bda6133fac97f3bed2b567b9b6a)` & source)` | Detaches the given source packet signal from the stream. -`public virtual bool detachSource(`[`PacketStreamAdapter`](#classscy_1_1PacketStreamAdapter)` * source)` | -`public virtual void attach(`[`PacketProcessor`](#classscy_1_1PacketProcessor)` * proc,int order,bool freePointer)` | -`public template`
`inline void attach(std::shared_ptr< C > ptr,bool syncState)` | -`public virtual bool detach(`[`PacketProcessor`](#classscy_1_1PacketProcessor)` * proc)` | -`public virtual void synchronizeOutput(uv::Loop * loop)` | Synchronize stream output packets with the given event loop. -`public virtual void autoStart(bool flag)` | -`public virtual void closeOnError(bool flag)` | -`public const std::exception_ptr & error()` | Accessors for the unmanaged client data pointer. -`public std::string name() const` | Returns the name of the packet stream. -`public PacketAdapterVec adapters() const` | Returns a combined list of all stream sources and processors. -`public PacketAdapterVec sources() const` | Returns a list of all stream sources. -`public PacketAdapterVec processors() const` | Returns a list of all stream processors. -`public int numSources() const` | -`public int numProcessors() const` | -`public int numAdapters() const` | -`public template`
`inline AdapterT * getSource(int index)` | -`public template`
`inline AdapterT * getProcessor(int index)` | -`public inline `[`PacketProcessor`](#classscy_1_1PacketProcessor)` * getProcessor(int order)` | Returns the [PacketProcessor](./doc/api-base.md#classscy_1_1PacketProcessor) at the given position. -`protected mutable std::mutex _mutex` | -`protected mutable std::mutex _procMutex` | -`protected std::string _name` | -`protected PacketAdapterVec _sources` | -`protected PacketAdapterVec _processors` | -`protected std::deque< `[`PacketStreamState`](./doc/api-base.md#structscy_1_1PacketStreamState)` > _states` | -`protected std::exception_ptr _error` | -`protected bool _autoStart` | -`protected bool _closeOnError` | -`protected void setup()` | Attach the source and processor delegate chain. -`protected void teardown()` | Detach the source and processor delegate chain. -`protected void attachSource(PacketAdapterReference::Ptr ref)` | -`protected void attach(PacketAdapterReference::Ptr ref)` | -`protected void startSources()` | Start synchronized sources. -`protected void stopSources()` | Stop synchronized sources. -`protected virtual void process(`[`IPacket`](#classscy_1_1IPacket)` & packet)` | [Process](./doc/api-base.md#classscy_1_1Process) incoming packets. -`protected void emit(`[`IPacket`](#classscy_1_1IPacket)` & packet)` | -`protected void synchronizeStates()` | Synchronize queued states with adapters. -`protected virtual void onStateChange(`[`PacketStreamState`](#structscy_1_1PacketStreamState)` & state,const `[`PacketStreamState`](#structscy_1_1PacketStreamState)` & oldState)` | Override the [Stateful::onStateChange](#group__base_1ga3c88b4aa8e9343f9bdc1a8c2ae2a5452) method. -`protected void assertCanModify()` | Returns true if the given state ID is queued. -`protected void handleException(std::exception & exc)` | Handle an internal exception. - -## Members - -#### `public `[`PacketSignal`](#group__base_1ga3ffb5bda6133fac97f3bed2b567b9b6a)` emitter` +```cpp +static Timestamp fromUtcTime(UtcTimeVal val) +``` -Signals to delegates on outgoing packets. +Creates a timestamp from a UTC time value. +| Parameter | Type | Description | +|-----------|------|-------------| +| `val` | `UtcTimeVal` | | +--- -#### `public `[`Signal](#classscy_1_1Signal)< void([PacketStream`](#classscy_1_1PacketStream) &, const std::exception_ptr &)`> Error` +#### resolution +```cpp +static inline TimeVal resolution() +``` +Returns the resolution in units per second. Since the timestamp has microsecond resolution, the returned value is always 1000000. -Signals that the [PacketStream](#classscy_1_1PacketStream) is in [Error](#structscy_1_1Error) state. If stream output is synchronized then the [Error](#structscy_1_1Error) signal will be sent from the synchronization context, otherwise it will be sent from the async processor context. See [synchronizeOutput()](#group__base_1ga27a797846a098946cf73d80726302a9e) +--- -#### `public `[`Signal](#classscy_1_1Signal)< void([PacketStream`](#classscy_1_1PacketStream) &)`> Close` +#### _ts +```cpp +TimeVal _ts +``` +## Timespan -Signals that the [PacketStream](#classscy_1_1PacketStream) is in Close state. This signal is sent immediately via the [close()](#group__base_1gac0eec4eda5ff0571b46b4a39af9f7dcf) method, and as such will be sent from the calling thread context. +> **Defined in:** `datetime.h` -#### `public void * opaque` +A class that represents time spans up to microsecond resolution. +### Members + +| Name | Description | +|------|-------------| +| [`Timespan`](#group__base_1ga183ab023a03182a6b62287f31ba4667c) | Creates a zero [Timespan](#classscy_1_1Timespan). | +| [`Timespan`](#group__base_1ga36bd62906099ad73b6411bbee9df4687) | Creates a [Timespan](#classscy_1_1Timespan). | +| [`Timespan`](#group__base_1ga9281640ae0cfdf1af90bf219e3ab2502) | Creates a [Timespan](#classscy_1_1Timespan). Useful for creating a [Timespan](#classscy_1_1Timespan) from a struct timeval. | +| [`Timespan`](#group__base_1gad7c52f4c3f97829b1a2184819c6fdb78) | Creates a [Timespan](#classscy_1_1Timespan). | +| [`Timespan`](#group__base_1gad644dad5d9fcc72c753fb207aa0f7799) | Creates a [Timespan](#classscy_1_1Timespan) from another one. | +| [`~Timespan`](#group__base_1ga58f2185a33f9adf2043381a216e7e3d0) | Destroys the [Timespan](#classscy_1_1Timespan). | +| [`operator=`](#group__base_1gacb09eb0c421d3ee1567221bbcbfa1686) | Assignment operator. | +| [`operator=`](#group__base_1ga53a89a4c0d074d07a69651f9b1390ca2) | Assignment operator. | +| [`assign`](#group__base_1ga8aeb84fe300f38a39ec0ee7cd4a2c463) | Assigns a new span. | +| [`assign`](#group__base_1ga326e06380b6c271143dd53261061e0a7) | Assigns a new span. Useful for assigning from a struct timeval. | +| [`swap`](#group__base_1ga3289402362d3f09413c7e27c8a5f84a7) | Swaps the [Timespan](#classscy_1_1Timespan) with another one. | +| [`operator==`](#group__base_1ga6901eaae07320f3bbf4cbcbdcba58788) | | +| [`operator!=`](#group__base_1gac44da14b266ce4dbf80779330cb7090d) | | +| [`operator>`](#group__base_1ga7add4d0610dc0b197739f9b3d68dc39f) | | +| [`operator>=`](#group__base_1gad19debbff7b0f7cad21fab77e589e982) | | +| [`operator<`](#group__base_1ga11f56482aeb54a4a1e787750d8e1bd5d) | | +| [`operator<=`](#group__base_1gaf862e58fa751b510a38233b11aa2c658) | | +| [`operator==`](#group__base_1ga337882f65d1c794d461573d928877ad9) | | +| [`operator!=`](#group__base_1gab46f76d0e8a8ed7a150a20ffeb02d337) | | +| [`operator>`](#group__base_1ga3c356ed1db34e4a04abfdf8dae5d0a7f) | | +| [`operator>=`](#group__base_1ga6a10617e981175a0672fc9532edf5fd6) | | +| [`operator<`](#group__base_1ga57fa8c22b3b06fa8884b1dae53b2974d) | | +| [`operator<=`](#group__base_1gaa9c1dfaca2cac4fe2da24ca6e835e808) | | +| [`operator+`](#group__base_1gacdafb69117cce505b5c3290eff82e231) | | +| [`operator-`](#group__base_1ga036be956f49e4ee5b3c7974c49c84689) | | +| [`operator+=`](#group__base_1gac6abe30a87d689470bce966fe2bca4f1) | | +| [`operator-=`](#group__base_1gab466c189ee0189435fda807fce532333) | | +| [`operator+`](#group__base_1gae336ef6426d9886f13f62e3e0326a92b) | | +| [`operator-`](#group__base_1ga96a28c1241b0c065e3c213ab4cc44cf4) | | +| [`operator+=`](#group__base_1gadfd1a60c223de14e723fbb03e15f157f) | | +| [`operator-=`](#group__base_1ga476bf78a0dea511c9dbe6c99ec86ca6c) | | +| [`days`](#group__base_1gab39bf74d96f285b9502b0411321c2c40) | Returns the number of days. | +| [`hours`](#group__base_1ga6887a573816f2fdc9019e1e42b15a1fa) | Returns the number of hours (0 to 23). | +| [`totalHours`](#group__base_1ga4c78c96a19b68218bc1ec9056870dd48) | Returns the total number of hours. | +| [`minutes`](#group__base_1ga9b4fa5de6b469773c139d3992c368580) | Returns the number of minutes (0 to 59). | +| [`totalMinutes`](#group__base_1ga8dc72898fece5e76f4e89de4a60483ca) | Returns the total number of minutes. | +| [`seconds`](#group__base_1ga6a1f8b3aaadca7e4092b76e860e11473) | Returns the number of seconds (0 to 59). | +| [`totalSeconds`](#group__base_1ga2d936ac7dd1d8c6e3b445992c08fb0da) | Returns the total number of seconds. | +| [`milliseconds`](#group__base_1ga2d17d492ef454811b4487c210f6f4fa4) | Returns the number of milliseconds (0 to 999). | +| [`totalMilliseconds`](#group__base_1ga5301028400cc25b3ff5f1f34e85e3612) | Returns the total number of milliseconds. | +| [`microseconds`](#group__base_1ga038a3be32de4ebe87b3fe3676a327a04) | Returns the fractions of a millisecond in microseconds (0 to 999). | +| [`useconds`](#group__base_1ga4dbdae0aa5912a70c8f3497560fce318) | Returns the fractions of a second in microseconds (0 to 999999). | +| [`totalMicroseconds`](#group__base_1ga9fe3ab13665735f41ab6fd8ed8ae477b) | Returns the total number of microseconds. | +| [`MILLISECONDS`](#group__base_1gaf9dfc80ff279a8e33a4590fc66103084) | The number of microseconds in a millisecond. | +| [`SECONDS`](#group__base_1ga17ba35f40e7272d4491d98da4d79a31c) | The number of microseconds in a second. | +| [`MINUTES`](#group__base_1gacecea48ab9088a739906f31ad1cbcb1c) | The number of microseconds in a minute. | +| [`HOURS`](#group__base_1ga1414c0cb94c9e31c48cea196aa6bfef2) | The number of microseconds in a hour. | +| [`DAYS`](#group__base_1ga71586bb12510718ac92b58daf6b26795) | The number of microseconds in a day. | +| [`_span`](#group__base_1gaa2e7e7aebeb68bd2ccdf5431fc3a6bb3) | | + +--- + +#### Timespan + +```cpp +Timespan() +``` +Creates a zero [Timespan](#classscy_1_1Timespan). +--- +#### Timespan -#### `public PacketStream(const std::string & name)` +```cpp +Timespan(TimeDiff microseconds) +``` +Creates a [Timespan](#classscy_1_1Timespan). +| Parameter | Type | Description | +|-----------|------|-------------| +| `microseconds` | `TimeDiff` | | +--- +#### Timespan -#### `public virtual ~PacketStream()` +```cpp +Timespan(long seconds, long microseconds) +``` +Creates a [Timespan](#classscy_1_1Timespan). Useful for creating a [Timespan](#classscy_1_1Timespan) from a struct timeval. +| Parameter | Type | Description | +|-----------|------|-------------| +| `seconds` | `long` | | +| `microseconds` | `long` | | +--- +#### Timespan -#### `public virtual void start()` +```cpp +Timespan(int days, int hours, int minutes, int seconds, int microseconds) +``` -Start the stream and synchronized sources. +Creates a [Timespan](#classscy_1_1Timespan). +| Parameter | Type | Description | +|-----------|------|-------------| +| `days` | `int` | | +| `hours` | `int` | | +| `minutes` | `int` | | +| `seconds` | `int` | | +| `microseconds` | `int` | | +--- -#### `public virtual void stop()` +#### Timespan -Stop the stream and synchronized sources. +```cpp +Timespan(const Timespan & timespan) +``` +Creates a [Timespan](#classscy_1_1Timespan) from another one. +| Parameter | Type | Description | +|-----------|------|-------------| +| `timespan` | `const Timespan &` | | -#### `public virtual void pause()` +--- -Pause the stream. +#### ~Timespan +```cpp +~Timespan() +``` +Destroys the [Timespan](#classscy_1_1Timespan). -#### `public virtual void resume()` +--- -Resume the stream. +#### operator= +```cpp +Timespan & operator=(const Timespan & timespan) +``` +Assignment operator. -#### `public virtual void close()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `timespan` | `const Timespan &` | | -Close the stream and transition the internal state to Closed. +--- +#### operator= +```cpp +Timespan & operator=(TimeDiff microseconds) +``` -#### `public virtual void reset()` +Assignment operator. -Cleanup all managed stream adapters and reset the stream state. +| Parameter | Type | Description | +|-----------|------|-------------| +| `microseconds` | `TimeDiff` | | +--- +#### assign -#### `public virtual bool active() const` +```cpp +Timespan & assign(int days, int hours, int minutes, int seconds, int microseconds) +``` -Returns true when the stream is in the Active state. +Assigns a new span. +| Parameter | Type | Description | +|-----------|------|-------------| +| `days` | `int` | | +| `hours` | `int` | | +| `minutes` | `int` | | +| `seconds` | `int` | | +| `microseconds` | `int` | | +--- -#### `public virtual bool stopped() const` +#### assign -Returns true when the stream is in the Stopping or Stopped state. +```cpp +Timespan & assign(long seconds, long microseconds) +``` +Assigns a new span. Useful for assigning from a struct timeval. +| Parameter | Type | Description | +|-----------|------|-------------| +| `seconds` | `long` | | +| `microseconds` | `long` | | -#### `public virtual bool closed() const` +--- -Returns true when the stream is in the Closed or [Error](#structscy_1_1Error) state. +#### swap +```cpp +void swap(Timespan & timespan) +``` +Swaps the [Timespan](#classscy_1_1Timespan) with another one. -#### `public virtual bool lock()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `timespan` | `Timespan &` | | +--- +#### operator== -Sets the stream to locked state. In a locked state no new adapters can be added or removed from the stream until the stream is stopped. +```cpp +inline bool operator==(const Timespan & ts) const +``` -#### `public virtual bool locked() const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `ts` | `const Timespan &` | | -Returns true is the stream is currently locked. +--- +#### operator!= +```cpp +inline bool operator!=(const Timespan & ts) const +``` -#### `public virtual void write(char * data,size_t len)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `ts` | `const Timespan &` | | -Writes data to the stream (nocopy). +--- +#### operator> +```cpp +inline bool operator>(const Timespan & ts) const +``` -#### `public virtual void write(const char * data,size_t len)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `ts` | `const Timespan &` | | -Writes data to the stream (copied). +--- +#### operator>= +```cpp +inline bool operator>=(const Timespan & ts) const +``` -#### `public virtual void write(`[`IPacket`](#classscy_1_1IPacket)` && packet)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `ts` | `const Timespan &` | | -Writes an incoming packet onto the stream. +--- +#### operator< +```cpp +inline bool operator<(const Timespan & ts) const +``` -#### `public virtual void attachSource(`[`PacketSignal`](#group__base_1ga3ffb5bda6133fac97f3bed2b567b9b6a)` & source)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `ts` | `const Timespan &` | | +--- +#### operator<= -Attaches a source packet emitter to the stream. The source packet adapter can be another [PacketStream::emitter](#group__base_1ga3d4fa2d39446cd24ce5d8281834b70db). +```cpp +inline bool operator<=(const Timespan & ts) const +``` -#### `public virtual void attachSource(`[`PacketStreamAdapter`](#classscy_1_1PacketStreamAdapter)` * source,bool freePointer,bool syncState)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `ts` | `const Timespan &` | | +--- +#### operator== -Attaches a source packet emitter to the stream. If freePointer is true, the pointer will be deleted when the stream is closed. If syncState is true and the source is a basic::Stratable, then the source's [start()](#group__base_1gaa07075299f2271e58f78de3fd7e62b10)/stop() methods will be synchronized when calling [startSources()](#group__base_1gaeb9605f5d35a6aaa92bf427e0989827c)/stopSources(). +```cpp +inline bool operator==(TimeDiff microseconds) const +``` -#### `public template`
`inline void attachSource(std::shared_ptr< C > ptr,bool syncState)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `microseconds` | `TimeDiff` | | +--- +#### operator!= -Attaches a source packet emitter to the stream. This method enables compatibility with shared_ptr managed adapter instances. +```cpp +inline bool operator!=(TimeDiff microseconds) const +``` -#### `public virtual bool detachSource(`[`PacketSignal`](#group__base_1ga3ffb5bda6133fac97f3bed2b567b9b6a)` & source)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `microseconds` | `TimeDiff` | | -Detaches the given source packet signal from the stream. +--- +#### operator> +```cpp +inline bool operator>(TimeDiff microseconds) const +``` -#### `public virtual bool detachSource(`[`PacketStreamAdapter`](#classscy_1_1PacketStreamAdapter)` * source)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `microseconds` | `TimeDiff` | | +--- +#### operator>= -Detaches the given source packet adapter from the stream. Note: The pointer will be forgotten about, so if the freePointer flag set when calling [attachSource()](#group__base_1ga16adec5b00a33070556dd8531e1825c0) will have no effect. +```cpp +inline bool operator>=(TimeDiff microseconds) const +``` -#### `public virtual void attach(`[`PacketProcessor`](#classscy_1_1PacketProcessor)` * proc,int order,bool freePointer)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `microseconds` | `TimeDiff` | | +--- +#### operator< -Attaches a packet processor to the stream. Order determines the position of the processor in the stream queue. If freePointer is true, the pointer will be deleted when the stream closes. +```cpp +inline bool operator<(TimeDiff microseconds) const +``` -#### `public template`
`inline void attach(std::shared_ptr< C > ptr,bool syncState)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `microseconds` | `TimeDiff` | | +--- +#### operator<= -Attaches a packet processor to the stream. This method enables compatibility with shared_ptr managed adapter instances. +```cpp +inline bool operator<=(TimeDiff microseconds) const +``` -#### `public virtual bool detach(`[`PacketProcessor`](#classscy_1_1PacketProcessor)` * proc)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `microseconds` | `TimeDiff` | | +--- +#### operator+ -Detaches a packet processor from the stream. Note: The pointer will be forgotten about, so if the freePointer flag set when calling [attach()](#group__base_1gaeff06c27d0ed0174f7f19ff61b3ff2fe) will have no effect. +```cpp +Timespan operator+(const Timespan & d) const +``` -#### `public virtual void synchronizeOutput(uv::Loop * loop)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `d` | `const Timespan &` | | -Synchronize stream output packets with the given event loop. +--- +#### operator- +```cpp +Timespan operator-(const Timespan & d) const +``` -#### `public virtual void autoStart(bool flag)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `d` | `const Timespan &` | | +--- +#### operator+= -Set the stream to auto start if inactive (default: false). +```cpp +Timespan & operator+=(const Timespan & d) +``` -With this flag set the stream will automatically transition to Active state if the in either the None or Locaked state. +| Parameter | Type | Description | +|-----------|------|-------------| +| `d` | `const Timespan &` | | -#### `public virtual void closeOnError(bool flag)` +--- +#### operator-= +```cpp +Timespan & operator-=(const Timespan & d) +``` -Set the stream to be closed on error (default: true). +| Parameter | Type | Description | +|-----------|------|-------------| +| `d` | `const Timespan &` | | -With this flag set the stream will be automatically transitioned to Closed state from [Error](#structscy_1_1Error) state. +--- -#### `public const std::exception_ptr & error()` +#### operator+ -Accessors for the unmanaged client data pointer. +```cpp +Timespan operator+(TimeDiff microseconds) const +``` -Returns the stream error (if any). +| Parameter | Type | Description | +|-----------|------|-------------| +| `microseconds` | `TimeDiff` | | -#### `public std::string name() const` +--- -Returns the name of the packet stream. +#### operator- +```cpp +Timespan operator-(TimeDiff microseconds) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `microseconds` | `TimeDiff` | | -#### `public PacketAdapterVec adapters() const` +--- -Returns a combined list of all stream sources and processors. +#### operator+= +```cpp +Timespan & operator+=(TimeDiff microseconds) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `microseconds` | `TimeDiff` | | -#### `public PacketAdapterVec sources() const` +--- -Returns a list of all stream sources. +#### operator-= +```cpp +Timespan & operator-=(TimeDiff microseconds) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `microseconds` | `TimeDiff` | | -#### `public PacketAdapterVec processors() const` +--- -Returns a list of all stream processors. +#### days +```cpp +inline int days() const +``` +Returns the number of days. -#### `public int numSources() const` +--- +#### hours +```cpp +inline int hours() const +``` +Returns the number of hours (0 to 23). +--- -#### `public int numProcessors() const` +#### totalHours +```cpp +inline int totalHours() const +``` +Returns the total number of hours. +--- +#### minutes -#### `public int numAdapters() const` +```cpp +inline int minutes() const +``` +Returns the number of minutes (0 to 59). +--- +#### totalMinutes +```cpp +inline int totalMinutes() const +``` -#### `public template`
`inline AdapterT * getSource(int index)` +Returns the total number of minutes. +--- +#### seconds +```cpp +inline int seconds() const +``` +Returns the number of seconds (0 to 59). -#### `public template`
`inline AdapterT * getProcessor(int index)` +--- +#### totalSeconds +```cpp +inline int totalSeconds() const +``` +Returns the total number of seconds. +--- -#### `public inline `[`PacketProcessor`](#classscy_1_1PacketProcessor)` * getProcessor(int order)` +#### milliseconds -Returns the [PacketProcessor](#classscy_1_1PacketProcessor) at the given position. +```cpp +inline int milliseconds() const +``` +Returns the number of milliseconds (0 to 999). +--- -#### `protected mutable std::mutex _mutex` +#### totalMilliseconds +```cpp +inline TimeDiff totalMilliseconds() const +``` +Returns the total number of milliseconds. +--- +#### microseconds -#### `protected mutable std::mutex _procMutex` +```cpp +inline int microseconds() const +``` +Returns the fractions of a millisecond in microseconds (0 to 999). +--- +#### useconds +```cpp +inline int useconds() const +``` -#### `protected std::string _name` +Returns the fractions of a second in microseconds (0 to 999999). +--- +#### totalMicroseconds +```cpp +inline TimeDiff totalMicroseconds() const +``` +Returns the total number of microseconds. -#### `protected PacketAdapterVec _sources` +--- +#### MILLISECONDS +```cpp +const TimeDiff MILLISECONDS = 1000 +``` +The number of microseconds in a millisecond. +--- -#### `protected PacketAdapterVec _processors` +#### SECONDS +```cpp +const TimeDiff SECONDS = 1000 * Timespan::MILLISECONDS +``` +The number of microseconds in a second. +--- +#### MINUTES -#### `protected std::deque< `[`PacketStreamState`](./doc/api-base.md#structscy_1_1PacketStreamState)` > _states` +```cpp +const TimeDiff MINUTES = 60 * Timespan::SECONDS +``` +The number of microseconds in a minute. +--- +#### HOURS +```cpp +const TimeDiff HOURS = 60 * Timespan::MINUTES +``` -#### `protected std::exception_ptr _error` +The number of microseconds in a hour. +--- +#### DAYS +```cpp +const TimeDiff DAYS = 24 * Timespan::HOURS +``` +The number of microseconds in a day. -#### `protected bool _autoStart` +--- +#### _span +```cpp +TimeDiff _span +``` +## DateTime +> **Defined in:** `datetime.h` -#### `protected bool _closeOnError` +This class represents an instant in time, expressed in years, months, days, hours, minutes, seconds and milliseconds based on the Gregorian calendar. The class is mainly useful for conversions between UTC, Julian day and Gregorian calendar dates. +The date and time stored in a [DateTime](#classscy_1_1DateTime) is always in UTC (Coordinated Universal Time) and thus independent of the timezone in effect on the system. +Conversion calculations are based on algorithms collected and described by Peter Baum at [http://vsg.cape.com/~pbaum/date/date0.htm](http://vsg.cape.com/~pbaum/date/date0.htm) +Internally, this class stores a date/time in two forms (UTC and broken down) for performance reasons. Only use this class for conversions between date/time representations. Use the [Timestamp](#classscy_1_1Timestamp) class for everything else. +Notes: -#### `protected void setup()` +* Zero is a valid year (in accordance with ISO 8601 and astronomical year numbering) -Attach the source and processor delegate chain. +* Year zero (0) is a leap year +* Negative years (years preceding 1 BC) are not supported +For more information, please see: -#### `protected void teardown()` +* [http://en.wikipedia.org/wiki/Gregorian_Calendar](http://en.wikipedia.org/wiki/Gregorian_Calendar) -Detach the source and processor delegate chain. +* [http://en.wikipedia.org/wiki/Julian_day](http://en.wikipedia.org/wiki/Julian_day) +* [http://en.wikipedia.org/wiki/UTC](http://en.wikipedia.org/wiki/UTC) +* [http://en.wikipedia.org/wiki/ISO_8601](http://en.wikipedia.org/wiki/ISO_8601) -#### `protected void attachSource(PacketAdapterReference::Ptr ref)` +### Members + +| Name | Description | +|------|-------------| +| [`Months`](#group__base_1ga9e6c37f4daad98cbb93b264905eaf498) | Symbolic names for month numbers (1 to 12). | +| [`DaysOfWeek`](#group__base_1ga2113d4a106804ff86e3e9e4c144542e7) | Symbolic names for week day numbers (0 to 6). | +| [`DateTime`](#group__base_1gafc8db97ad1127e27ea8cc055d64bacdc) | Creates a [DateTime](#classscy_1_1DateTime) for the current date and time. | +| [`DateTime`](#group__base_1ga8757497c5f7df732cc6f84d2c31e997d) | Creates a [DateTime](#classscy_1_1DateTime) for the date and time given in a [Timestamp](#classscy_1_1Timestamp). | +| [`DateTime`](#group__base_1ga0723f5d0fb69a9f9f2231723b4712c2b) | Creates a [DateTime](#classscy_1_1DateTime) for the given Gregorian date and time. | +| [`DateTime`](#group__base_1gaa8d974aeec2eaea35d48ac2860c6cfa6) | Creates a [DateTime](#classscy_1_1DateTime) for the given Julian day. | +| [`DateTime`](#group__base_1gae8ca8fe73a37b81ea207f21115a3218a) | Creates a [DateTime](#classscy_1_1DateTime) from an UtcTimeVal and a TimeDiff. | +| [`DateTime`](#group__base_1gaa8c6129e0263af535cd47eace907e8da) | Copy constructor. Creates the [DateTime](#classscy_1_1DateTime) from another one. | +| [`~DateTime`](#group__base_1gaab8ba2987dd09faf606927a8c5c8d57b) | Destroys the [DateTime](#classscy_1_1DateTime). | +| [`operator=`](#group__base_1gaacf8c5cbf1e8b62928a397989844ca51) | Assigns another [DateTime](#classscy_1_1DateTime). | +| [`operator=`](#group__base_1gae5bfb492a3b5469b672ab3c8c60ca2b4) | Assigns a [Timestamp](#classscy_1_1Timestamp). | +| [`operator=`](#group__base_1ga40a6a5696a62415686d4ba0f8a36d52c) | Assigns a Julian day. | +| [`assign`](#group__base_1ga60d82a180ce48c06261f324e8aa32615) | Assigns a Gregorian date and time. | +| [`swap`](#group__base_1ga2d52b10410733fc42b1d222b78b546f3) | Swaps the [DateTime](#classscy_1_1DateTime) with another one. | +| [`year`](#group__base_1ga8ee24f2380b3a6f0728f1451cec5b846) | Returns the year. | +| [`month`](#group__base_1ga36843329b8b306cb82a733b46f4d49c7) | Returns the month (1 to 12). | +| [`week`](#group__base_1gaf5ad099452341c3b5682a8f7352f8422) | Returns the week number within the year. FirstDayOfWeek should be either SUNDAY (0) or MONDAY (1). The returned week number will be from 0 to 53. Week number 1 is the week containing January 4. This is in accordance to ISO 8601. | +| [`day`](#group__base_1ga78029b135e06449cf535f2ae8c7ab497) | Returns the day witin the month (1 to 31). | +| [`dayOfWeek`](#group__base_1ga2ea7a5f2314c97c367867fc550d61a5d) | Returns the weekday (0 to 6, where 0 = Sunday, 1 = Monday, ..., 6 = Saturday). | +| [`dayOfYear`](#group__base_1gad9924403dc634f1e1ba699498d5c9c61) | Returns the number of the day in the year. January 1 is 1, February 1 is 32, etc. | +| [`hour`](#group__base_1ga885ca6176737aff2dfa2443a10512c12) | Returns the hour (0 to 23). | +| [`hourAMPM`](#group__base_1gad73305d05775a09b0fbd4c8db3c96923) | Returns the hour (0 to 12). | +| [`isAM`](#group__base_1gab9661f01a53099540cb71b23c0c1871d) | Returns true if hour < 12;. | +| [`isPM`](#group__base_1ga12d69cfbf155b6f294785aa0b9c49fe9) | Returns true if hour >= 12. | +| [`minute`](#group__base_1gac124db7fe3f0fb9980087d09ed5abde6) | Returns the minute (0 to 59). | +| [`second`](#group__base_1gab5062725edc5fb0dea2d9ea62dbdaa85) | Returns the second (0 to 59). | +| [`millisecond`](#group__base_1gaa7bd963176ae54f61301fca30e02592a) | Returns the millisecond (0 to 999) | +| [`microsecond`](#group__base_1gad4dbddbc0255cc26c9fd9dafaed353b9) | Returns the microsecond (0 to 999) | +| [`julianDay`](#group__base_1ga48a04a535ae9290933994bfe0084b176) | Returns the julian day for the date and time. | +| [`timestamp`](#group__base_1ga591c0712a8e1250820532510a54a49b3) | Returns the date and time expressed as a [Timestamp](#classscy_1_1Timestamp). | +| [`utcTime`](#group__base_1gaa67be192392537cf1674d41f56704ab9) | Returns the date and time expressed in UTC-based time. UTC base time is midnight, October 15, 1582. Resolution is 100 nanoseconds. | +| [`operator==`](#group__base_1ga4262a88ba878383b2b4e0a1712b11649) | | +| [`operator!=`](#group__base_1ga82a285c08ba0e9221127a4421211ba75) | | +| [`operator<`](#group__base_1ga4968d25e134d2f9992866d797e27b7e3) | | +| [`operator<=`](#group__base_1ga4bea2b52f94d03908e2b0e82c8f3bd29) | | +| [`operator>`](#group__base_1ga35693ffc981a1608ed24246f1162ffa3) | | +| [`operator>=`](#group__base_1ga2d2264fc51381c3f29b95e51433a96c1) | | +| [`operator+`](#group__base_1gaed9c5e50f2543472847ca0675f6f87ca) | | +| [`operator-`](#group__base_1ga46b10a0779e2e09a0be2630832412a47) | | +| [`operator-`](#group__base_1gaae40c16a2b2f6f2c63e93efe904d38dd) | | +| [`operator+=`](#group__base_1gaa56672df917ae0e0e5a02f73a3f1e94a) | | +| [`operator-=`](#group__base_1gadb7d7dc23a9eaa6e054f2383a21bb388) | | +| [`makeUTC`](#group__base_1gaef85751cde47a0e909aeddae1775b805) | Converts a local time into UTC, by applying the given time zone differential. | +| [`makeLocal`](#group__base_1ga82ce62343d007567544418aed404dcd9) | Converts a UTC time into a local time, by applying the given time zone differential. | +| [`isLeapYear`](#group__base_1gab7ceaf8d08c284eb209ad6e370e6961f) | Returns true if the given year is a leap year; false otherwise. | +| [`daysOfMonth`](#group__base_1ga544d4bee671c5c6680867452263fcc6c) | Returns the number of days in the given month and year. Month is from 1 to 12. | +| [`isValid`](#group__base_1ga463d516bd237f7c943e25c3f69d33e95) | Checks if the given date and time is valid (all arguments are within a proper range). | +| [`toJulianDay`](#group__base_1gae96017b4e44c759d2fd5dc8dd919641a) | Computes the Julian day for an UTC time. | +| [`toJulianDay`](#group__base_1ga36713db7db011080de64cdc28ec6fae7) | Computes the Julian day for a gregorian calendar date and time. See [http://vsg.cape.com/~pbaum/date/jdimp.htm](http://vsg.cape.com/~pbaum/date/jdimp.htm), section 2.3.1 for the algorithm. | +| [`toUtcTime`](#group__base_1ga39589bb35dd881e229d1e82474b59fec) | Computes the UTC time for a Julian day. | +| [`computeGregorian`](#group__base_1ga6f59bebcde64cc028cdbcde61b7eb619) | Computes the Gregorian date for the given Julian day. See [http://vsg.cape.com/~pbaum/date/injdimp.htm](http://vsg.cape.com/~pbaum/date/injdimp.htm), section 3.3.1 for the algorithm. | +| [`computeDaytime`](#group__base_1ga57cdba4dec7b53c448c56545d0c0a8fb) | Extracts the daytime (hours, minutes, seconds, etc.) from the stored utcTime. | +| [`checkLimit`](#group__base_1ga10a738833c77e5ad0d146bd61bca9337) | Utility functions used to correct the overflow in computeGregorian. | +| [`normalize`](#group__base_1ga4d52d557202e5c4bdce44f45db8035f4) | | +| [`_utcTime`](#group__base_1ga14e6532e1a7944987d9adfb1c7852512) | | +| [`_year`](#group__base_1ga7f8ffc73810bbfbcf2d53c019b6c44c8) | | +| [`_month`](#group__base_1ga0a721136b7c47d19f61f6734a49a3800) | | +| [`_day`](#group__base_1gacd8e4b76482ac75bdeda1592ac01f73a) | | +| [`_hour`](#group__base_1ga91bcdb7cf4accb4367f2602465067b19) | | +| [`_minute`](#group__base_1gaebc63e2d4d9be134dd59521eaf884b3a) | | +| [`_second`](#group__base_1ga85225b668528291f7903fe8e2ade16ec) | | +| [`_millisecond`](#group__base_1ga09a330dab1c5465b0ae79e26bd3561ab) | | +| [`_microsecond`](#group__base_1gaf24f7557bd0c588a709ececbc818e3ce) | | + +--- + +#### Months + +```cpp +enum Months +``` +Symbolic names for month numbers (1 to 12). + +| Value | Description | +|-------|-------------| +| `JANUARY` | | +| `FEBRUARY` | | +| `MARCH` | | +| `APRIL` | | +| `MAY` | | +| `JUNE` | | +| `JULY` | | +| `AUGUST` | | +| `SEPTEMBER` | | +| `OCTOBER` | | +| `NOVEMBER` | | +| `DECEMBER` | | + +--- + +#### DaysOfWeek + +```cpp +enum DaysOfWeek +``` +Symbolic names for week day numbers (0 to 6). +| Value | Description | +|-------|-------------| +| `SUNDAY` | | +| `MONDAY` | | +| `TUESDAY` | | +| `WEDNESDAY` | | +| `THURSDAY` | | +| `FRIDAY` | | +| `SATURDAY` | | +--- -#### `protected void attach(PacketAdapterReference::Ptr ref)` +#### DateTime +```cpp +DateTime() +``` +Creates a [DateTime](#classscy_1_1DateTime) for the current date and time. +--- +#### DateTime -#### `protected void startSources()` +```cpp +DateTime(const Timestamp & timestamp) +``` -Start synchronized sources. +Creates a [DateTime](#classscy_1_1DateTime) for the date and time given in a [Timestamp](#classscy_1_1Timestamp). +| Parameter | Type | Description | +|-----------|------|-------------| +| `timestamp` | `const Timestamp &` | | +--- -#### `protected void stopSources()` +#### DateTime -Stop synchronized sources. +```cpp +DateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int microsecond) +``` +Creates a [DateTime](#classscy_1_1DateTime) for the given Gregorian date and time. +* year is from 0 to 9999. -#### `protected virtual void process(`[`IPacket`](#classscy_1_1IPacket)` & packet)` +* month is from 1 to 12. -[Process](#classscy_1_1Process) incoming packets. +* day is from 1 to 31. +* hour is from 0 to 23. +* minute is from 0 to 59. -#### `protected void emit(`[`IPacket`](#classscy_1_1IPacket)` & packet)` +* second is from 0 to 59. +* millisecond is from 0 to 999. +* microsecond is from 0 to 999. -Emit the final packet to listeners. +| Parameter | Type | Description | +|-----------|------|-------------| +| `year` | `int` | | +| `month` | `int` | | +| `day` | `int` | | +| `hour` | `int` | | +| `minute` | `int` | | +| `second` | `int` | | +| `millisecond` | `int` | | +| `microsecond` | `int` | | -Synchronized signals such as Close and [Error](#structscy_1_1Error) are sent from this method. See [synchronizeOutput()](#group__base_1ga27a797846a098946cf73d80726302a9e) +--- -#### `protected void synchronizeStates()` +#### DateTime -Synchronize queued states with adapters. +```cpp +DateTime(double julianDay) +``` +Creates a [DateTime](#classscy_1_1DateTime) for the given Julian day. +| Parameter | Type | Description | +|-----------|------|-------------| +| `julianDay` | `double` | | -#### `protected virtual void onStateChange(`[`PacketStreamState`](#structscy_1_1PacketStreamState)` & state,const `[`PacketStreamState`](#structscy_1_1PacketStreamState)` & oldState)` +--- -Override the [Stateful::onStateChange](#group__base_1ga3c88b4aa8e9343f9bdc1a8c2ae2a5452) method. +#### DateTime +```cpp +DateTime(Timestamp::UtcTimeVal utcTime, Timestamp::TimeDiff diff) +``` +Creates a [DateTime](#classscy_1_1DateTime) from an UtcTimeVal and a TimeDiff. -#### `protected void assertCanModify()` +Mainly used internally by [DateTime](#classscy_1_1DateTime) and friends. -Returns true if the given state ID is queued. +| Parameter | Type | Description | +|-----------|------|-------------| +| `utcTime` | `Timestamp::UtcTimeVal` | | +| `diff` | `Timestamp::TimeDiff` | | -Asserts that the stream can be modified, ie is not in the Locked, Stopping or Active states. +--- -#### `protected void handleException(std::exception & exc)` +#### DateTime -Handle an internal exception. +```cpp +DateTime(const DateTime & dateTime) +``` +Copy constructor. Creates the [DateTime](#classscy_1_1DateTime) from another one. +| Parameter | Type | Description | +|-----------|------|-------------| +| `dateTime` | `const DateTime &` | | -# class `scy::PacketStreamAdapter` +--- +#### ~DateTime +```cpp +~DateTime() +``` +Destroys the [DateTime](#classscy_1_1DateTime). -This class is a wrapper for integrating external classes with the a [PacketStream](#classscy_1_1PacketStream)'s data flow and state machine. +--- -## Summary +#### operator= - Members | Descriptions ---------------------------------|--------------------------------------------- -`public PacketStreamAdapter(`[`PacketSignal`](#group__base_1ga3ffb5bda6133fac97f3bed2b567b9b6a)` & emitter)` | -`public inline virtual ~PacketStreamAdapter()` | -`public virtual void emit(char * data,size_t len,unsigned flags)` | -`public virtual void emit(const char * data,size_t len,unsigned flags)` | -`public virtual void emit(const std::string & str,unsigned flags)` | -`public virtual void emit(unsigned flags)` | -`public virtual void emit(`[`IPacket`](#classscy_1_1IPacket)` & packet)` | -`public `[`PacketSignal`](#group__base_1ga3ffb5bda6133fac97f3bed2b567b9b6a)` & getEmitter()` | Returns a reference to the outgoing packet signal. -`public inline virtual void onStreamStateChange(const `[`PacketStreamState`](#structscy_1_1PacketStreamState)` &)` | -`protected `[`PacketSignal`](#group__base_1ga3ffb5bda6133fac97f3bed2b567b9b6a)` & _emitter` | -`protected PacketStreamAdapter(const `[`PacketStreamAdapter`](#classscy_1_1PacketStreamAdapter)` &) = delete` | NonCopyable and NonMovable. -`protected `[`PacketStreamAdapter`](#classscy_1_1PacketStreamAdapter)` & operator=(const `[`PacketStreamAdapter`](#classscy_1_1PacketStreamAdapter)` &) = delete` | +```cpp +DateTime & operator=(const DateTime & dateTime) +``` -## Members +Assigns another [DateTime](#classscy_1_1DateTime). -#### `public PacketStreamAdapter(`[`PacketSignal`](#group__base_1ga3ffb5bda6133fac97f3bed2b567b9b6a)` & emitter)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `dateTime` | `const DateTime &` | | +--- +#### operator= +```cpp +DateTime & operator=(const Timestamp & timestamp) +``` +Assigns a [Timestamp](#classscy_1_1Timestamp). -#### `public inline virtual ~PacketStreamAdapter()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `timestamp` | `const Timestamp &` | | +--- +#### operator= +```cpp +DateTime & operator=(double julianDay) +``` +Assigns a Julian day. -#### `public virtual void emit(char * data,size_t len,unsigned flags)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `julianDay` | `double` | | +--- +#### assign +```cpp +DateTime & assign(int year, int month, int day, int hour, int minute, int second, int millisecond, int microseconds) +``` +Assigns a Gregorian date and time. -#### `public virtual void emit(const char * data,size_t len,unsigned flags)` +* year is from 0 to 9999. +* month is from 1 to 12. +* day is from 1 to 31. +* hour is from 0 to 23. +* minute is from 0 to 59. -#### `public virtual void emit(const std::string & str,unsigned flags)` +* second is from 0 to 59. +* millisecond is from 0 to 999. +* microsecond is from 0 to 999. +| Parameter | Type | Description | +|-----------|------|-------------| +| `year` | `int` | | +| `month` | `int` | | +| `day` | `int` | | +| `hour` | `int` | | +| `minute` | `int` | | +| `second` | `int` | | +| `millisecond` | `int` | | +| `microseconds` | `int` | | +--- -#### `public virtual void emit(unsigned flags)` +#### swap +```cpp +void swap(DateTime & dateTime) +``` +Swaps the [DateTime](#classscy_1_1DateTime) with another one. +| Parameter | Type | Description | +|-----------|------|-------------| +| `dateTime` | `DateTime &` | | +--- -#### `public virtual void emit(`[`IPacket`](#classscy_1_1IPacket)` & packet)` +#### year +```cpp +inline int year() const +``` +Returns the year. +--- +#### month -#### `public `[`PacketSignal`](#group__base_1ga3ffb5bda6133fac97f3bed2b567b9b6a)` & getEmitter()` +```cpp +inline int month() const +``` -Returns a reference to the outgoing packet signal. +Returns the month (1 to 12). +--- +#### week -#### `public inline virtual void onStreamStateChange(const `[`PacketStreamState`](#structscy_1_1PacketStreamState)` &)` +```cpp +int week(int firstDayOfWeek) const +``` +Returns the week number within the year. FirstDayOfWeek should be either SUNDAY (0) or MONDAY (1). The returned week number will be from 0 to 53. Week number 1 is the week containing January 4. This is in accordance to ISO 8601. +The following example assumes that firstDayOfWeek is MONDAY. For 2005, which started on a Saturday, week 1 will be the week starting on Monday, January 3. January 1 and 2 will fall within week 0 (or the last week of the previous year). -Called by the [PacketStream](#classscy_1_1PacketStream) to notify when the internal [Stream](#classscy_1_1Stream) state changes. On receiving the Stopped state, it is the responsibility of the adapter to have ceased all outgoing packet transmission, especially in multi-thread scenarios. +For 2007, which starts on a Monday, week 1 will be the week startung on Monday, January 1. There will be no week 0 in 2007. -#### `protected `[`PacketSignal`](#group__base_1ga3ffb5bda6133fac97f3bed2b567b9b6a)` & _emitter` +| Parameter | Type | Description | +|-----------|------|-------------| +| `firstDayOfWeek` | `int` | | +--- +#### day +```cpp +inline int day() const +``` +Returns the day witin the month (1 to 31). -#### `protected PacketStreamAdapter(const `[`PacketStreamAdapter`](#classscy_1_1PacketStreamAdapter)` &) = delete` +--- -NonCopyable and NonMovable. +#### dayOfWeek +```cpp +int dayOfWeek() const +``` +Returns the weekday (0 to 6, where 0 = Sunday, 1 = Monday, ..., 6 = Saturday). -#### `protected `[`PacketStreamAdapter`](#classscy_1_1PacketStreamAdapter)` & operator=(const `[`PacketStreamAdapter`](#classscy_1_1PacketStreamAdapter)` &) = delete` +--- +#### dayOfYear +```cpp +int dayOfYear() const +``` +Returns the number of the day in the year. January 1 is 1, February 1 is 32, etc. +--- -# class `scy::PacketTransaction` +#### hour +```cpp +inline int hour() const ``` -class scy::PacketTransaction - : public scy::basic::Sendable - : public scy::Stateful< TransactionState > -``` +Returns the hour (0 to 23). +--- -This class provides request/response functionality for [IPacket](#classscy_1_1IPacket) types. - -PacketTransactions are fire and forget. The object will be deleted after a successful response or a timeout. - -## Summary +#### hourAMPM - Members | Descriptions ---------------------------------|--------------------------------------------- -`public inline PacketTransaction(long timeout,int retries,uv::Loop * loop)` | -`public inline PacketTransaction(const PacketT & request,long timeout,int retries,uv::Loop * loop)` | -`public inline virtual bool send()` | -`public inline virtual void cancel()` | -`public inline bool cancelled() const` | -`public inline virtual void dispose()` | -`public inline virtual bool canResend()` | -`public inline int attempts() const` | -`public inline int retries() const` | -`public inline PacketT & request()` | -`public inline PacketT request() const` | -`public inline PacketT & response()` | -`public inline PacketT response() const` | -`protected PacketT _request` | -`protected PacketT _response` | -`protected `[`Timer`](./doc/api-base.md#classscy_1_1Timer)` _timer` | The request timeout callback. -`protected int _retries` | The maximum number of attempts before the transaction is considered failed. -`protected int _attempts` | The number of times the transaction has been sent. -`protected bool _destroyed` | -`protected inline virtual ~PacketTransaction()` | -`protected inline virtual void onStateChange(`[`TransactionState`](#structscy_1_1TransactionState)` & state,const `[`TransactionState`](#structscy_1_1TransactionState)` &)` | Override to handle post state change logic. -`protected inline virtual bool handlePotentialResponse(const PacketT & packet)` | -`protected bool checkResponse(const PacketT & packet)` | -`protected inline virtual void onResponse()` | Called when a successful response is received. -`protected inline virtual void onTimeout()` | +```cpp +inline int hourAMPM() const +``` -## Members +Returns the hour (0 to 12). -#### `public inline PacketTransaction(long timeout,int retries,uv::Loop * loop)` +--- +#### isAM +```cpp +inline bool isAM() const +``` +Returns true if hour < 12;. +--- -#### `public inline PacketTransaction(const PacketT & request,long timeout,int retries,uv::Loop * loop)` +#### isPM +```cpp +inline bool isPM() const +``` +Returns true if hour >= 12. +--- +#### minute -#### `public inline virtual bool send()` +```cpp +inline int minute() const +``` +Returns the minute (0 to 59). +--- -Starts the transaction timer and sends the request. Overriding classes should implement send logic here. +#### second -#### `public inline virtual void cancel()` +```cpp +inline int second() const +``` +Returns the second (0 to 59). +--- -Cancellation means that the agent will not retransmit the request, will not treat the lack of response to be a failure, but will wait the duration of the transaction timeout for a response. +#### millisecond -#### `public inline bool cancelled() const` +```cpp +inline int millisecond() const +``` +Returns the millisecond (0 to 999) +--- +#### microsecond +```cpp +inline int microsecond() const +``` -#### `public inline virtual void dispose()` +Returns the microsecond (0 to 999) +--- +#### julianDay -Schedules the transaction for deferred deletion. +```cpp +double julianDay() const +``` -It is safe to call this function while the transaction is still active, providing the call is made from the same loop thread which the timer is running on. +Returns the julian day for the date and time. -Protected by the base implementation as this is called by the internal state machine. +--- -#### `public inline virtual bool canResend()` +#### timestamp +```cpp +inline Timestamp timestamp() const +``` +Returns the date and time expressed as a [Timestamp](#classscy_1_1Timestamp). +--- +#### utcTime -#### `public inline int attempts() const` +```cpp +inline Timestamp::UtcTimeVal utcTime() const +``` +Returns the date and time expressed in UTC-based time. UTC base time is midnight, October 15, 1582. Resolution is 100 nanoseconds. +--- +#### operator== +```cpp +inline bool operator==(const DateTime & dateTime) const +``` -#### `public inline int retries() const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `dateTime` | `const DateTime &` | | +--- +#### operator!= +```cpp +inline bool operator!=(const DateTime & dateTime) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `dateTime` | `const DateTime &` | | -#### `public inline PacketT & request()` +--- +#### operator< +```cpp +inline bool operator<(const DateTime & dateTime) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `dateTime` | `const DateTime &` | | +--- -#### `public inline PacketT request() const` +#### operator<= +```cpp +inline bool operator<=(const DateTime & dateTime) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `dateTime` | `const DateTime &` | | +--- +#### operator> -#### `public inline PacketT & response()` +```cpp +inline bool operator>(const DateTime & dateTime) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `dateTime` | `const DateTime &` | | +--- +#### operator>= +```cpp +inline bool operator>=(const DateTime & dateTime) const +``` -#### `public inline PacketT response() const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `dateTime` | `const DateTime &` | | +--- +#### operator+ +```cpp +DateTime operator+(const Timespan & span) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `span` | `const Timespan &` | | -#### `protected PacketT _request` +--- +#### operator- +```cpp +DateTime operator-(const Timespan & span) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `span` | `const Timespan &` | | +--- -#### `protected PacketT _response` +#### operator- +```cpp +Timespan operator-(const DateTime & dateTime) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `dateTime` | `const DateTime &` | | +--- +#### operator+= -#### `protected `[`Timer`](./doc/api-base.md#classscy_1_1Timer)` _timer` +```cpp +DateTime & operator+=(const Timespan & span) +``` -The request timeout callback. +| Parameter | Type | Description | +|-----------|------|-------------| +| `span` | `const Timespan &` | | +--- +#### operator-= -#### `protected int _retries` +```cpp +DateTime & operator-=(const Timespan & span) +``` -The maximum number of attempts before the transaction is considered failed. +| Parameter | Type | Description | +|-----------|------|-------------| +| `span` | `const Timespan &` | | +--- +#### makeUTC -#### `protected int _attempts` +```cpp +void makeUTC(int tzd) +``` -The number of times the transaction has been sent. +Converts a local time into UTC, by applying the given time zone differential. +| Parameter | Type | Description | +|-----------|------|-------------| +| `tzd` | `int` | | +--- -#### `protected bool _destroyed` +#### makeLocal +```cpp +void makeLocal(int tzd) +``` +Converts a UTC time into a local time, by applying the given time zone differential. +| Parameter | Type | Description | +|-----------|------|-------------| +| `tzd` | `int` | | +--- -#### `protected inline virtual ~PacketTransaction()` +#### isLeapYear +```cpp +static inline bool isLeapYear(int year) +``` +Returns true if the given year is a leap year; false otherwise. +| Parameter | Type | Description | +|-----------|------|-------------| +| `year` | `int` | | +--- -#### `protected inline virtual void onStateChange(`[`TransactionState`](#structscy_1_1TransactionState)` & state,const `[`TransactionState`](#structscy_1_1TransactionState)` &)` +#### daysOfMonth -Override to handle post state change logic. +```cpp +static int daysOfMonth(int year, int month) +``` +Returns the number of days in the given month and year. Month is from 1 to 12. +| Parameter | Type | Description | +|-----------|------|-------------| +| `year` | `int` | | +| `month` | `int` | | -#### `protected inline virtual bool handlePotentialResponse(const PacketT & packet)` +--- +#### isValid +```cpp +static bool isValid(int year, int month, int day, int hour, int minute, int second, int millisecond, int microsecond) +``` -Processes a potential response candidate and updates the state accordingly. +Checks if the given date and time is valid (all arguments are within a proper range). -#### `protected bool checkResponse(const PacketT & packet)` +Returns true if all arguments are valid, false otherwise. +| Parameter | Type | Description | +|-----------|------|-------------| +| `year` | `int` | | +| `month` | `int` | | +| `day` | `int` | | +| `hour` | `int` | | +| `minute` | `int` | | +| `second` | `int` | | +| `millisecond` | `int` | | +| `microsecond` | `int` | | +--- -Checks a potential response candidate and returns true on successful match. +#### toJulianDay -#### `protected inline virtual void onResponse()` +```cpp +static inline double toJulianDay(Timestamp::UtcTimeVal utcTime) +``` -Called when a successful response is received. +Computes the Julian day for an UTC time. +| Parameter | Type | Description | +|-----------|------|-------------| +| `utcTime` | `Timestamp::UtcTimeVal` | | +--- -#### `protected inline virtual void onTimeout()` +#### toJulianDay +```cpp +static double toJulianDay(int year, int month, int day, int hour, int minute, int second, int millisecond, int microsecond) +``` +Computes the Julian day for a gregorian calendar date and time. See [http://vsg.cape.com/~pbaum/date/jdimp.htm](http://vsg.cape.com/~pbaum/date/jdimp.htm), section 2.3.1 for the algorithm. +| Parameter | Type | Description | +|-----------|------|-------------| +| `year` | `int` | | +| `month` | `int` | | +| `day` | `int` | | +| `hour` | `int` | | +| `minute` | `int` | | +| `second` | `int` | | +| `millisecond` | `int` | | +| `microsecond` | `int` | | +--- -# class `scy::Pipe` +#### toUtcTime +```cpp +static inline Timestamp::UtcTimeVal toUtcTime(double julianDay) ``` -class scy::Pipe - : public scy::Stream< uv_pipe_t > -``` -[Pipe](#classscy_1_1Pipe) implementation for process stdio. +Computes the UTC time for a Julian day. +| Parameter | Type | Description | +|-----------|------|-------------| +| `julianDay` | `double` | | +--- -## Summary +#### computeGregorian - Members | Descriptions ---------------------------------|--------------------------------------------- -`public Pipe(uv::Loop * loop)` | -`public virtual ~Pipe()` | -`public virtual void init(bool ipc)` | -`public virtual bool readStart()` | +```cpp +void computeGregorian(double julianDay) +``` -## Members +Computes the Gregorian date for the given Julian day. See [http://vsg.cape.com/~pbaum/date/injdimp.htm](http://vsg.cape.com/~pbaum/date/injdimp.htm), section 3.3.1 for the algorithm. -#### `public Pipe(uv::Loop * loop)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `julianDay` | `double` | | +--- +#### computeDaytime +```cpp +void computeDaytime() +``` +Extracts the daytime (hours, minutes, seconds, etc.) from the stored utcTime. -#### `public virtual ~Pipe()` +--- +#### checkLimit +```cpp +void checkLimit(short & lower, short & higher, short limit) +``` +Utility functions used to correct the overflow in computeGregorian. +| Parameter | Type | Description | +|-----------|------|-------------| +| `lower` | `short &` | | +| `higher` | `short &` | | +| `limit` | `short` | | -#### `public virtual void init(bool ipc)` +--- +#### normalize +```cpp +void normalize() +``` +--- +#### _utcTime -#### `public virtual bool readStart()` +```cpp +Timestamp::UtcTimeVal _utcTime +``` +--- +#### _year +```cpp +short _year +``` +--- -# class `scy::PointerCollection` +#### _month +```cpp +short _month ``` -class scy::PointerCollection - : public scy::AbstractCollection< TKey, TValue > -``` +--- +#### _day -This collection is used to maintain an map of any pointer type indexed by key value in a thread-safe way. +```cpp +short _day +``` -This class allows for custom memory handling of managed pointers via the TDeleter argument. +--- -## Summary +#### _hour - Members | Descriptions ---------------------------------|--------------------------------------------- -`public inline PointerCollection()` | -`public inline virtual ~PointerCollection()` | -`public inline virtual bool add(const TKey & key,TValue * item,bool whiny)` | -`public inline virtual void update(const TKey & key,TValue * item)` | -`public inline virtual TValue * get(const TKey & key,bool whiny) const` | -`public inline virtual bool free(const TKey & key)` | -`public inline virtual TValue * remove(const TKey & key)` | -`public inline virtual bool remove(const TValue * item)` | -`public inline virtual bool exists(const TKey & key) const` | -`public inline virtual bool exists(const TValue * item) const` | -`public inline virtual bool empty() const` | -`public inline virtual size_t size() const` | -`public inline virtual void clear()` | -`public inline virtual Map map() const` | -`public inline virtual Map & map()` | -`public inline virtual void onAdd(const TKey &,TValue *)` | -`public inline virtual void onRemove(const TKey &,TValue *)` | -`protected Map _map` | -`protected mutable std::mutex _mutex` | +```cpp +short _hour +``` -## Members +--- -#### `public inline PointerCollection()` +#### _minute +```cpp +short _minute +``` +--- +#### _second +```cpp +short _second +``` -#### `public inline virtual ~PointerCollection()` +--- +#### _millisecond +```cpp +short _millisecond +``` +--- +#### _microsecond -#### `public inline virtual bool add(const TKey & key,TValue * item,bool whiny)` +```cpp +short _microsecond +``` +## Timezone +> **Defined in:** `datetime.h` +This class provides information about the current timezone. +### Members -#### `public inline virtual void update(const TKey & key,TValue * item)` +| Name | Description | +|------|-------------| +| [`utcOffset`](#group__base_1gad3222adfbb30111556179a35f05aab7f) | Returns the offset of local time to UTC, in seconds. local time = UTC + [utcOffset()](#group__base_1gad3222adfbb30111556179a35f05aab7f) + [dst()](#group__base_1ga06df217abf17778cace33570327b859b). | +| [`dst`](#group__base_1ga06df217abf17778cace33570327b859b) | Returns the daylight saving time offset in seconds if daylight saving time is in use. local time = UTC + [utcOffset()](#group__base_1gad3222adfbb30111556179a35f05aab7f) + [dst()](#group__base_1ga06df217abf17778cace33570327b859b). | +| [`isDst`](#group__base_1ga71aaa73c0b0a54c8f42d95efeed7e9b4) | Returns true if daylight saving time is in effect for the given time. Depending on the operating system platform this might only work reliably for certain date ranges, as the C library's localtime() function is used. | +| [`tzd`](#group__base_1gac940583482d1cd15b3abb37acbf224d4) | Returns the time zone differential for the current timezone. The timezone differential is computed as [utcOffset()](#group__base_1gad3222adfbb30111556179a35f05aab7f) + [dst()](#group__base_1ga06df217abf17778cace33570327b859b) /// and is expressed in seconds. | +| [`name`](#group__base_1ga56a345cbd893fd081c9d0e838e551a12) | Returns the timezone name currently in effect. | +| [`standardName`](#group__base_1ga810a32bd323905cc8a42cc4fb39e1e80) | Returns the timezone name if not daylight saving time is in effect. | +| [`dstName`](#group__base_1ga09d7845c9aae79917a9d510288590d2d) | Returns the timezone name if daylight saving time is in effect. | +--- +#### utcOffset +```cpp +static int utcOffset() +``` +Returns the offset of local time to UTC, in seconds. local time = UTC + [utcOffset()](#group__base_1gad3222adfbb30111556179a35f05aab7f) + [dst()](#group__base_1ga06df217abf17778cace33570327b859b). -#### `public inline virtual TValue * get(const TKey & key,bool whiny) const` +--- +#### dst +```cpp +static int dst() +``` +Returns the daylight saving time offset in seconds if daylight saving time is in use. local time = UTC + [utcOffset()](#group__base_1gad3222adfbb30111556179a35f05aab7f) + [dst()](#group__base_1ga06df217abf17778cace33570327b859b). +--- -#### `public inline virtual bool free(const TKey & key)` +#### isDst +```cpp +static bool isDst(const Timestamp & timestamp) +``` +Returns true if daylight saving time is in effect for the given time. Depending on the operating system platform this might only work reliably for certain date ranges, as the C library's localtime() function is used. +| Parameter | Type | Description | +|-----------|------|-------------| +| `timestamp` | `const Timestamp &` | | +--- -#### `public inline virtual TValue * remove(const TKey & key)` +#### tzd +```cpp +static int tzd() +``` +Returns the time zone differential for the current timezone. The timezone differential is computed as [utcOffset()](#group__base_1gad3222adfbb30111556179a35f05aab7f) + [dst()](#group__base_1ga06df217abf17778cace33570327b859b) /// and is expressed in seconds. +--- +#### name -#### `public inline virtual bool remove(const TValue * item)` +```cpp +static std::string name() +``` +Returns the timezone name currently in effect. +--- +#### standardName +```cpp +static std::string standardName() +``` -#### `public inline virtual bool exists(const TKey & key) const` +Returns the timezone name if not daylight saving time is in effect. +--- +#### dstName +```cpp +static std::string dstName() +``` +Returns the timezone name if daylight saving time is in effect. -#### `public inline virtual bool exists(const TValue * item) const` +## LocalDateTime +> **Defined in:** `datetime.h` +This class represents an instant in local time (as opposed to UTC), expressed in years, months, days, hours, minutes, seconds and milliseconds based on the Gregorian calendar. +In addition to the date and time, the class also maintains a time zone differential, which denotes the difference in seconds from UTC to local time, i.e. UTC = local time - time zone differential. +Although [LocalDateTime](#classscy_1_1LocalDateTime) supports relational and arithmetic operators, all date/time comparisons and date/time arithmetics should be done in UTC, using the [DateTime](#classscy_1_1DateTime) or [Timestamp](#classscy_1_1Timestamp) class for better performance. The relational operators normalize the dates/times involved to UTC before carrying out the comparison. -#### `public inline virtual bool empty() const` +The time zone differential is based on the input date and time and current time zone. A number of constructors accept an explicit time zone differential parameter. These should not be used since daylight savings time processing is impossible since the time zone is unknown. Each of the constructors accepting a tzd parameter have been marked as deprecated and may be removed in a future revision. +### Members + +| Name | Description | +|------|-------------| +| [`LocalDateTime`](#group__base_1gaf8f507cd5b10d8089d263b12e34e14fc) | Creates a [LocalDateTime](#classscy_1_1LocalDateTime) with the current date/time for the current time zone. | +| [`LocalDateTime`](#group__base_1gaa6b69743391798f50ba00facb3b344b8) | Creates a [LocalDateTime](#classscy_1_1LocalDateTime) for the given Gregorian local date and time. | +| [`LocalDateTime`](#group__base_1gac25cdf7cf37094a68feccb09da251a63) | @ deprecated Creates a [LocalDateTime](#classscy_1_1LocalDateTime) for the given Gregorian date and time in the time zone denoted by the time zone differential in tzd. | +| [`LocalDateTime`](#group__base_1ga8541afcbe851e21828977693c1130b5b) | Creates a [LocalDateTime](#classscy_1_1LocalDateTime) from the UTC time given in dateTime, using the time zone differential of the current time zone. | +| [`LocalDateTime`](#group__base_1gab8d6a8ba8d4ce3c43821dc4d8561aa0d) | @ deprecated Creates a [LocalDateTime](#classscy_1_1LocalDateTime) from the UTC time given in dateTime, using the given time zone differential. Adjusts dateTime for the given time zone differential. | +| [`LocalDateTime`](#group__base_1ga8aaa4e3e37cbac08e70d41e9eff399d0) | @ deprecated Creates a [LocalDateTime](#classscy_1_1LocalDateTime) from the UTC time given in dateTime, using the given time zone differential. If adjust is true, adjusts dateTime for the given time zone differential. | +| [`LocalDateTime`](#group__base_1gabe29c1922e6895d2d3b7aa1a01c5a40a) | Creates a [LocalDateTime](#classscy_1_1LocalDateTime) for the given Julian day in the local time zone. | +| [`LocalDateTime`](#group__base_1ga20abd6e936deee4ce9d14af620c008d7) | @ deprecated Creates a [LocalDateTime](#classscy_1_1LocalDateTime) for the given Julian day in the time zone denoted by the time zone differential in tzd. | +| [`LocalDateTime`](#group__base_1gae63da0ed0e40399b8986a776a3043053) | Copy constructor. Creates the [LocalDateTime](#classscy_1_1LocalDateTime) from another one. | +| [`~LocalDateTime`](#group__base_1ga173cd6cde153c287ed6c83691329be4e) | Destroys the [LocalDateTime](#classscy_1_1LocalDateTime). | +| [`operator=`](#group__base_1ga6e18acbc0937ed82dc958f9372504e33) | Assigns another [LocalDateTime](#classscy_1_1LocalDateTime). | +| [`operator=`](#group__base_1gafa3356c42a95457524c27c2be9a717fd) | Assigns a timestamp. | +| [`operator=`](#group__base_1ga344e356fccab4631853d9f5cd37de8c6) | Assigns a Julian day in the local time zone. | +| [`assign`](#group__base_1gaac91b6bebab01e9b755e5b72e9137107) | Assigns a Gregorian local date and time. | +| [`assign`](#group__base_1ga5a05f078a0a5b372ad43aad8f8505a77) | @ deprecated Assigns a Gregorian local date and time in the time zone denoted by the time zone differential in tzd. | +| [`assign`](#group__base_1ga1ad03bada11f55c902dbec05d2fc20ba) | @ deprecated Assigns a Julian day in the time zone denoted by the time zone differential in tzd. | +| [`swap`](#group__base_1ga6bc1c879e4d7b3b04a976c1161ecd5fc) | Swaps the [LocalDateTime](#classscy_1_1LocalDateTime) with another one. | +| [`year`](#group__base_1ga8b67a920a92e22ea2b6d4e8a306566c9) | Returns the year. | +| [`month`](#group__base_1ga8bb9094aac43c17269669b6422448932) | Returns the month (1 to 12). | +| [`week`](#group__base_1gaad9976490f29168f69b842eda06653cc) | Returns the week number within the year. FirstDayOfWeek should be either SUNDAY (0) or MONDAY (1). The returned week number will be from 0 to 53. Week number 1 is the week containing January 4. This is in accordance to ISO 8601. | +| [`day`](#group__base_1gadced33febfae85988662db9b42e56b02) | Returns the day witin the month (1 to 31). | +| [`dayOfWeek`](#group__base_1gaf0b1cfda4f34b38a3f030a43cb935499) | Returns the weekday (0 to 6, where 0 = Sunday, 1 = Monday, ..., 6 = Saturday). | +| [`dayOfYear`](#group__base_1ga4591a15d833c10a3a6ba391721bba9b6) | Returns the number of the day in the year. January 1 is 1, February 1 is 32, etc. | +| [`hour`](#group__base_1ga03a3ac243fec29a048966cb9d3f2c84e) | Returns the hour (0 to 23). | +| [`hourAMPM`](#group__base_1ga715ce88ba0720784ffb6d029be23929f) | Returns the hour (0 to 12). | +| [`isAM`](#group__base_1ga3dcd5082e83dfdf1fb448ca809abe23a) | Returns true if hour < 12;. | +| [`isPM`](#group__base_1gae32597d36b509e031d2c85e0f585cf33) | Returns true if hour >= 12. | +| [`minute`](#group__base_1ga1dbfbad9d0753b0ff904994b486a34b3) | Returns the minute (0 to 59). | +| [`second`](#group__base_1ga5767718a9fb2343d45d3b3c199a2a19e) | Returns the second (0 to 59). | +| [`millisecond`](#group__base_1gaad844e44442901f267a5de9c79992374) | Returns the millisecond (0 to 999) | +| [`microsecond`](#group__base_1ga23ed596d25ee1cd738810c7053e41ce9) | Returns the microsecond (0 to 999) | +| [`julianDay`](#group__base_1gabe283094aa6c16646c54b712f299c040) | Returns the julian day for the date. | +| [`tzd`](#group__base_1gaf4c12ad2150d60db15fae7b272eab06d) | Returns the time zone differential. | +| [`utc`](#group__base_1ga416f298027e9fbb02fbbbb59280bce06) | Returns the UTC equivalent for the local date and time. | +| [`timestamp`](#group__base_1gab031a9c8c582592f94857d03e9732c08) | Returns the date and time expressed as a [Timestamp](#classscy_1_1Timestamp). | +| [`utcTime`](#group__base_1ga59f8e28c14dce3c650e5127f5aa9b304) | Returns the UTC equivalent for the local date and time. | +| [`operator==`](#group__base_1ga33d47d51a7701e0b275500adf395df1a) | | +| [`operator!=`](#group__base_1gad10f335463ae82abbc089fc6194e90f7) | | +| [`operator<`](#group__base_1gaf569d4c7514648e90ebd3837ba4dde95) | | +| [`operator<=`](#group__base_1gad2528f970817d96c39323bad3dcdb259) | | +| [`operator>`](#group__base_1gae0861580c425aee3e4bba0c269e32d17) | | +| [`operator>=`](#group__base_1gac7cd53d72b4af340dae23afb3d727925) | | +| [`operator+`](#group__base_1gacd5f92bb4a0cd7ded64e7fb3ffa6396e) | | +| [`operator-`](#group__base_1gad7a1bbae9e178124fa09a1e2a5bc0571) | | +| [`operator-`](#group__base_1ga216a8affb2ff0334d51f57ee0ca81dd7) | | +| [`operator+=`](#group__base_1ga8a0e1e554f15d276630225f97fd59961) | | +| [`operator-=`](#group__base_1ga11a3cfaef5f0d1ffb66f802646eb29a6) | | +| [`LocalDateTime`](#group__base_1ga1ab5b8d9c17a7ca56e8949c890d45004) | | +| [`determineTzd`](#group__base_1ga290ea5b1aee903968e51eed129b287f7) | Recalculate the tzd based on the _dateTime member based on the current timezone using the Standard C runtime functions. If adjust is true, then [adjustForTzd()](#group__base_1gad0d104ecf1aa081650b681f2afe5718d) is called after the differential is calculated. | +| [`adjustForTzd`](#group__base_1gad0d104ecf1aa081650b681f2afe5718d) | Adjust the _dateTime member based on the _tzd member. | +| [`dstOffset`](#group__base_1ga764a663d49040c03389b398732cec64b) | Determine the DST offset for the current date/time. | +| [`_dateTime`](#group__base_1ga8925e6e312f69cf44a74d1984214f72c) | | +| [`_tzd`](#group__base_1ga3a1982a7b47ea6217612c1ebe42bc4da) | | + +--- + +#### LocalDateTime + +```cpp +LocalDateTime() +``` +Creates a [LocalDateTime](#classscy_1_1LocalDateTime) with the current date/time for the current time zone. +--- +#### LocalDateTime -#### `public inline virtual size_t size() const` +```cpp +LocalDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int microsecond) +``` +Creates a [LocalDateTime](#classscy_1_1LocalDateTime) for the given Gregorian local date and time. +* year is from 0 to 9999. +* month is from 1 to 12. +* day is from 1 to 31. -#### `public inline virtual void clear()` +* hour is from 0 to 23. +* minute is from 0 to 59. +* second is from 0 to 59. +* millisecond is from 0 to 999. +* microsecond is from 0 to 999. -#### `public inline virtual Map map() const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `year` | `int` | | +| `month` | `int` | | +| `day` | `int` | | +| `hour` | `int` | | +| `minute` | `int` | | +| `second` | `int` | | +| `millisecond` | `int` | | +| `microsecond` | `int` | | +--- +#### LocalDateTime +```cpp +LocalDateTime(int tzd, int year, int month, int day, int hour, int minute, int second, int millisecond, int microsecond) +``` +@ deprecated Creates a [LocalDateTime](#classscy_1_1LocalDateTime) for the given Gregorian date and time in the time zone denoted by the time zone differential in tzd. -#### `public inline virtual Map & map()` +* tzd is in seconds. +* year is from 0 to 9999. +* month is from 1 to 12. +* day is from 1 to 31. +* hour is from 0 to 23. -#### `public inline virtual void onAdd(const TKey &,TValue *)` +* minute is from 0 to 59. +* second is from 0 to 59. +* millisecond is from 0 to 999. +* microsecond is from 0 to 999. +| Parameter | Type | Description | +|-----------|------|-------------| +| `tzd` | `int` | | +| `year` | `int` | | +| `month` | `int` | | +| `day` | `int` | | +| `hour` | `int` | | +| `minute` | `int` | | +| `second` | `int` | | +| `millisecond` | `int` | | +| `microsecond` | `int` | | -#### `public inline virtual void onRemove(const TKey &,TValue *)` +--- +#### LocalDateTime +```cpp +LocalDateTime(const DateTime & dateTime) +``` +Creates a [LocalDateTime](#classscy_1_1LocalDateTime) from the UTC time given in dateTime, using the time zone differential of the current time zone. +| Parameter | Type | Description | +|-----------|------|-------------| +| `dateTime` | `const DateTime &` | | -#### `protected Map _map` +--- +#### LocalDateTime +```cpp +LocalDateTime(int tzd, const DateTime & dateTime) +``` +@ deprecated Creates a [LocalDateTime](#classscy_1_1LocalDateTime) from the UTC time given in dateTime, using the given time zone differential. Adjusts dateTime for the given time zone differential. +| Parameter | Type | Description | +|-----------|------|-------------| +| `tzd` | `int` | | +| `dateTime` | `const DateTime &` | | -#### `protected mutable std::mutex _mutex` +--- +#### LocalDateTime +```cpp +LocalDateTime(int tzd, const DateTime & dateTime, bool adjust) +``` +@ deprecated Creates a [LocalDateTime](#classscy_1_1LocalDateTime) from the UTC time given in dateTime, using the given time zone differential. If adjust is true, adjusts dateTime for the given time zone differential. +| Parameter | Type | Description | +|-----------|------|-------------| +| `tzd` | `int` | | +| `dateTime` | `const DateTime &` | | +| `adjust` | `bool` | | -# class `scy::Process` +--- +#### LocalDateTime +```cpp +LocalDateTime(double julianDay) +``` +Creates a [LocalDateTime](#classscy_1_1LocalDateTime) for the given Julian day in the local time zone. +| Parameter | Type | Description | +|-----------|------|-------------| +| `julianDay` | `double` | | +--- -## Summary +#### LocalDateTime - Members | Descriptions ---------------------------------|--------------------------------------------- -`public std::string file` | -`public std::string cwd` | -`public std::vector< std::string > args` | -`public std::function< void(std::string)> onstdout` | -`public std::function< void(std::int64_t)> onexit` | -`public ProcessOptions options` | -`public Process(uv::Loop * loop)` | Default constructor. -`public Process(std::initializer_list< std::string > args,uv::Loop * loop)` | Constructor with command line arguments. -`public ~Process()` | Destructor. -`public void spawn()` | -`public bool kill(int signum)` | Kills the process. -`public int pid() const` | Returns the process PID. -`public `[`Pipe`](#classscy_1_1Pipe)` & in()` | Returns the stdin pipe. -`public `[`Pipe`](#classscy_1_1Pipe)` & out()` | Returns the stdout pipe. -`protected `[`uv::Handle`](./doc/api-uv.md#classscy_1_1uv_1_1Handle)`< uv_process_t > _handle` | -`protected `[`Pipe`](./doc/api-base.md#classscy_1_1Pipe)` _stdin` | -`protected `[`Pipe`](./doc/api-base.md#classscy_1_1Pipe)` _stdout` | -`protected uv_stdio_container_t _stdio` | -`protected std::vector< char * > _cargs` | -`protected void init()` | +```cpp +LocalDateTime(int tzd, double julianDay) +``` -## Members +@ deprecated Creates a [LocalDateTime](#classscy_1_1LocalDateTime) for the given Julian day in the time zone denoted by the time zone differential in tzd. -#### `public std::string file` +| Parameter | Type | Description | +|-----------|------|-------------| +| `tzd` | `int` | | +| `julianDay` | `double` | | +--- +#### LocalDateTime -Path to the program to execute. Cenvenience proxy for options.file. Must be set before `[spawn()](#group__base_1ga2b8587f848160ac9f84743a27cc28151)` +```cpp +LocalDateTime(const LocalDateTime & dateTime) +``` -#### `public std::string cwd` +Copy constructor. Creates the [LocalDateTime](#classscy_1_1LocalDateTime) from another one. +| Parameter | Type | Description | +|-----------|------|-------------| +| `dateTime` | `const LocalDateTime &` | | +--- -Set the current working directory. Cenvenience proxy for options.cwd. Must be set before `[spawn()](#group__base_1ga2b8587f848160ac9f84743a27cc28151)` +#### ~LocalDateTime -#### `public std::vector< std::string > args` +```cpp +~LocalDateTime() +``` +Destroys the [LocalDateTime](#classscy_1_1LocalDateTime). +--- -Command line agruments to pass to the process. Cenvenience proxy for options.args. Must be set before `[spawn()](#group__base_1ga2b8587f848160ac9f84743a27cc28151)` +#### operator= -#### `public std::function< void(std::string)> onstdout` +```cpp +LocalDateTime & operator=(const LocalDateTime & dateTime) +``` +Assigns another [LocalDateTime](#classscy_1_1LocalDateTime). +| Parameter | Type | Description | +|-----------|------|-------------| +| `dateTime` | `const LocalDateTime &` | | -Stdout signal. Signals when a line has been output from the process. +--- -#### `public std::function< void(std::int64_t)> onexit` +#### operator= +```cpp +LocalDateTime & operator=(const Timestamp & timestamp) +``` +Assigns a timestamp. -Exit stgnals. Signals process exit status code. +| Parameter | Type | Description | +|-----------|------|-------------| +| `timestamp` | `const Timestamp &` | | -#### `public ProcessOptions options` +--- +#### operator= +```cpp +LocalDateTime & operator=(double julianDay) +``` -LibUV C options. Available for advanced use cases. +Assigns a Julian day in the local time zone. -#### `public Process(uv::Loop * loop)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `julianDay` | `double` | | -Default constructor. +--- +#### assign +```cpp +LocalDateTime & assign(int year, int month, int day, int hour, int minute, int second, int millisecond, int microseconds) +``` -#### `public Process(std::initializer_list< std::string > args,uv::Loop * loop)` +Assigns a Gregorian local date and time. -Constructor with command line arguments. +* year is from 0 to 9999. +* month is from 1 to 12. +* day is from 1 to 31. -#### `public ~Process()` +* hour is from 0 to 23. -Destructor. +* minute is from 0 to 59. +* second is from 0 to 59. +* millisecond is from 0 to 999. -#### `public void spawn()` +* microsecond is from 0 to 999. +| Parameter | Type | Description | +|-----------|------|-------------| +| `year` | `int` | | +| `month` | `int` | | +| `day` | `int` | | +| `hour` | `int` | | +| `minute` | `int` | | +| `second` | `int` | | +| `millisecond` | `int` | | +| `microseconds` | `int` | | +--- -Spawns the process. Options must be properly set. Throws and exception on error. +#### assign -#### `public bool kill(int signum)` +```cpp +LocalDateTime & assign(int tzd, int year, int month, int day, int hour, int minute, int second, int millisecond, int microseconds) +``` -Kills the process. +@ deprecated Assigns a Gregorian local date and time in the time zone denoted by the time zone differential in tzd. +* tzd is in seconds. +* year is from 0 to 9999. -#### `public int pid() const` +* month is from 1 to 12. -Returns the process PID. +* day is from 1 to 31. +* hour is from 0 to 23. +* minute is from 0 to 59. -#### `public `[`Pipe`](#classscy_1_1Pipe)` & in()` +* second is from 0 to 59. -Returns the stdin pipe. +* millisecond is from 0 to 999. +* microsecond is from 0 to 999. +| Parameter | Type | Description | +|-----------|------|-------------| +| `tzd` | `int` | | +| `year` | `int` | | +| `month` | `int` | | +| `day` | `int` | | +| `hour` | `int` | | +| `minute` | `int` | | +| `second` | `int` | | +| `millisecond` | `int` | | +| `microseconds` | `int` | | -#### `public `[`Pipe`](#classscy_1_1Pipe)` & out()` +--- -Returns the stdout pipe. +#### assign +```cpp +LocalDateTime & assign(int tzd, double julianDay) +``` +@ deprecated Assigns a Julian day in the time zone denoted by the time zone differential in tzd. -#### `protected `[`uv::Handle`](./doc/api-uv.md#classscy_1_1uv_1_1Handle)`< uv_process_t > _handle` +| Parameter | Type | Description | +|-----------|------|-------------| +| `tzd` | `int` | | +| `julianDay` | `double` | | +--- +#### swap +```cpp +void swap(LocalDateTime & dateTime) +``` +Swaps the [LocalDateTime](#classscy_1_1LocalDateTime) with another one. -#### `protected `[`Pipe`](./doc/api-base.md#classscy_1_1Pipe)` _stdin` +| Parameter | Type | Description | +|-----------|------|-------------| +| `dateTime` | `LocalDateTime &` | | +--- +#### year +```cpp +inline int year() const +``` +Returns the year. -#### `protected `[`Pipe`](./doc/api-base.md#classscy_1_1Pipe)` _stdout` +--- +#### month +```cpp +inline int month() const +``` +Returns the month (1 to 12). +--- -#### `protected uv_stdio_container_t _stdio` +#### week +```cpp +inline int week(int firstDayOfWeek) const +``` +Returns the week number within the year. FirstDayOfWeek should be either SUNDAY (0) or MONDAY (1). The returned week number will be from 0 to 53. Week number 1 is the week containing January 4. This is in accordance to ISO 8601. +The following example assumes that firstDayOfWeek is MONDAY. For 2005, which started on a Saturday, week 1 will be the week starting on Monday, January 3. January 1 and 2 will fall within week 0 (or the last week of the previous year). +For 2007, which starts on a Monday, week 1 will be the week startung on Monday, January 1. There will be no week 0 in 2007. -#### `protected std::vector< char * > _cargs` +| Parameter | Type | Description | +|-----------|------|-------------| +| `firstDayOfWeek` | `int` | | +--- +#### day +```cpp +inline int day() const +``` +Returns the day witin the month (1 to 31). -#### `protected void init()` +--- +#### dayOfWeek +```cpp +inline int dayOfWeek() const +``` +Returns the weekday (0 to 6, where 0 = Sunday, 1 = Monday, ..., 6 = Saturday). +--- -# class `scy::Queue` +#### dayOfYear +```cpp +inline int dayOfYear() const +``` -Thread-safe queue container. +Returns the number of the day in the year. January 1 is 1, February 1 is 32, etc. +--- +#### hour -## Summary +```cpp +inline int hour() const +``` - Members | Descriptions ---------------------------------|--------------------------------------------- -`public inline void push(const T & data)` | -`public inline bool empty() const` | -`public inline T & front()` | -`public inline T const & front() const` | -`public inline T & back()` | -`public inline T const & back() const` | -`public inline void pop()` | -`public template`
`inline void sort()` | -`public inline size_t size()` | -`public inline std::deque< T > & queue()` | -`protected std::deque< T > _queue` | -`protected mutable std::mutex _mutex` | +Returns the hour (0 to 23). -## Members +--- -#### `public inline void push(const T & data)` +#### hourAMPM +```cpp +inline int hourAMPM() const +``` +Returns the hour (0 to 12). +--- +#### isAM -#### `public inline bool empty() const` +```cpp +inline bool isAM() const +``` +Returns true if hour < 12;. +--- +#### isPM +```cpp +inline bool isPM() const +``` -#### `public inline T & front()` +Returns true if hour >= 12. +--- +#### minute +```cpp +inline int minute() const +``` +Returns the minute (0 to 59). -#### `public inline T const & front() const` +--- +#### second +```cpp +inline int second() const +``` +Returns the second (0 to 59). +--- -#### `public inline T & back()` +#### millisecond +```cpp +inline int millisecond() const +``` +Returns the millisecond (0 to 999) +--- +#### microsecond -#### `public inline T const & back() const` +```cpp +inline int microsecond() const +``` +Returns the microsecond (0 to 999) +--- +#### julianDay +```cpp +inline double julianDay() const +``` -#### `public inline void pop()` +Returns the julian day for the date. +--- +#### tzd +```cpp +inline int tzd() const +``` +Returns the time zone differential. -#### `public template`
`inline void sort()` +--- +#### utc +```cpp +DateTime utc() const +``` +Returns the UTC equivalent for the local date and time. +--- -#### `public inline size_t size()` +#### timestamp +```cpp +inline Timestamp timestamp() const +``` +Returns the date and time expressed as a [Timestamp](#classscy_1_1Timestamp). +--- +#### utcTime -#### `public inline std::deque< T > & queue()` +```cpp +inline Timestamp::UtcTimeVal utcTime() const +``` +Returns the UTC equivalent for the local date and time. +--- +#### operator== +```cpp +bool operator==(const LocalDateTime & dateTime) const +``` -#### `protected std::deque< T > _queue` +| Parameter | Type | Description | +|-----------|------|-------------| +| `dateTime` | `const LocalDateTime &` | | +--- +#### operator!= +```cpp +bool operator!=(const LocalDateTime & dateTime) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `dateTime` | `const LocalDateTime &` | | -#### `protected mutable std::mutex _mutex` +--- +#### operator< +```cpp +bool operator<(const LocalDateTime & dateTime) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `dateTime` | `const LocalDateTime &` | | +--- -# class `scy::Random` +#### operator<= +```cpp +bool operator<=(const LocalDateTime & dateTime) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `dateTime` | `const LocalDateTime &` | | +--- -[Random](#classscy_1_1Random) implements a pseudo random number generator (PRNG). The PRNG is a nonlinear additive feedback random number generator using 256 bytes of state information and a period of up to 2^69. +#### operator> -## Summary +```cpp +bool operator>(const LocalDateTime & dateTime) const +``` - Members | Descriptions ---------------------------------|--------------------------------------------- -`public Random(int stateSize)` | -`public ~Random()` | Destroys the PRNG. -`public void seed(uint32_t seed)` | Seeds the pseudo random generator with the given seed. -`public void seed()` | -`public uint32_t next()` | Returns the next 31-bit pseudo random number. -`public uint32_t next(uint32_t n)` | Returns the next 31-bit pseudo random number modulo n. -`public char nextChar()` | Returns the next pseudo random character. -`public bool nextBool()` | Returns the next boolean pseudo random value. -`public float nextFloat()` | Returns the next float pseudo random number between 0.0 and 1.0. -`public double nextDouble()` | Returns the next double pseudo random number between 0.0 and 1.0. -`protected void initState(uint32_t seed,char * arg_state,std::int32_t n)` | +| Parameter | Type | Description | +|-----------|------|-------------| +| `dateTime` | `const LocalDateTime &` | | -## Members +--- -#### `public Random(int stateSize)` +#### operator>= +```cpp +bool operator>=(const LocalDateTime & dateTime) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `dateTime` | `const LocalDateTime &` | | -Creates and initializes the PRNG. Specify either a state buffer size (8 to 256 bytes) or one of the Type values. +--- -#### `public ~Random()` +#### operator+ -Destroys the PRNG. +```cpp +LocalDateTime operator+(const Timespan & span) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `span` | `const Timespan &` | | +--- -#### `public void seed(uint32_t seed)` +#### operator- -Seeds the pseudo random generator with the given seed. +```cpp +LocalDateTime operator-(const Timespan & span) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `span` | `const Timespan &` | | +--- -#### `public void seed()` +#### operator- +```cpp +Timespan operator-(const LocalDateTime & dateTime) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `dateTime` | `const LocalDateTime &` | | -Seeds the pseudo random generator with a random seed obtained from a RandomInputStream. +--- -#### `public uint32_t next()` +#### operator+= -Returns the next 31-bit pseudo random number. +```cpp +LocalDateTime & operator+=(const Timespan & span) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `span` | `const Timespan &` | | +--- -#### `public uint32_t next(uint32_t n)` +#### operator-= -Returns the next 31-bit pseudo random number modulo n. +```cpp +LocalDateTime & operator-=(const Timespan & span) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `span` | `const Timespan &` | | +--- -#### `public char nextChar()` +#### LocalDateTime -Returns the next pseudo random character. +```cpp +LocalDateTime(Timestamp::UtcTimeVal utcTime, Timestamp::TimeDiff diff, int tzd) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `utcTime` | `Timestamp::UtcTimeVal` | | +| `diff` | `Timestamp::TimeDiff` | | +| `tzd` | `int` | | +--- -#### `public bool nextBool()` +#### determineTzd -Returns the next boolean pseudo random value. +```cpp +void determineTzd(bool adjust) +``` +Recalculate the tzd based on the _dateTime member based on the current timezone using the Standard C runtime functions. If adjust is true, then [adjustForTzd()](#group__base_1gad0d104ecf1aa081650b681f2afe5718d) is called after the differential is calculated. +| Parameter | Type | Description | +|-----------|------|-------------| +| `adjust` | `bool` | | -#### `public float nextFloat()` +--- -Returns the next float pseudo random number between 0.0 and 1.0. +#### adjustForTzd +```cpp +inline void adjustForTzd() +``` +Adjust the _dateTime member based on the _tzd member. -#### `public double nextDouble()` +--- -Returns the next double pseudo random number between 0.0 and 1.0. +#### dstOffset +```cpp +std::time_t dstOffset(int & dstOffset) const +``` +Determine the DST offset for the current date/time. -#### `protected void initState(uint32_t seed,char * arg_state,std::int32_t n)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `dstOffset` | `int &` | | +--- +#### _dateTime +```cpp +DateTime _dateTime +``` +--- -# class `scy::RawPacket` +#### _tzd +```cpp +int _tzd ``` -class scy::RawPacket - : public scy::IPacket -``` - +## DateTimeFormat -[RawPacket](#classscy_1_1RawPacket) is the default data packet type which consists of an optionally managed char pointer and a size value. +> **Defined in:** `datetime.h` -## Summary +Definition of date/time formats and various constants used by [DateTimeFormatter](#classscy_1_1DateTimeFormatter) and [DateTimeParser](#classscy_1_1DateTimeParser). - Members | Descriptions ---------------------------------|--------------------------------------------- -`public inline RawPacket(char * data,size_t size,unsigned flags,void * source,void * opaque,`[`IPacketInfo`](#structscy_1_1IPacketInfo)` * info)` | -`public inline RawPacket(const char * data,size_t size,unsigned flags,void * source,void * opaque,`[`IPacketInfo`](#structscy_1_1IPacketInfo)` * info)` | -`public inline RawPacket(const `[`RawPacket`](#classscy_1_1RawPacket)` & that)` | -`public inline virtual ~RawPacket()` | -`public inline virtual `[`IPacket`](#classscy_1_1IPacket)` * clone() const` | -`public inline virtual void copyData(const void * data,size_t size)` | -`public inline virtual ssize_t read(const `[`ConstBuffer`](#classscy_1_1ConstBuffer)` &)` | -`public inline virtual void write(`[`Buffer`](#group__base_1gab10b36b080deb583ed703fca6b63ffdd)` &) const` | -`public inline virtual char * data() const` | The packet data pointer for buffered packets. -`public inline virtual size_t size() const` | -`public inline virtual const char * className() const` | -`public inline virtual bool ownsBuffer() const` | -`public inline virtual void assignDataOwnership()` | -`protected char * _data` | -`protected size_t _size` | -`protected bool _free` | +### Members -## Members +| Name | Description | +|------|-------------| +| [`ISO8601_FORMAT`](#group__base_1ga109ea0bf73c13b30bf07e646dde1a202) | predefined date formats The date/time format defined in the ISO 8601 standard. | +| [`ISO8601_FRAC_FORMAT`](#group__base_1gafc5610125c46f81c8b37a33a8275e930) | The date/time format defined in the ISO 8601 standard, with fractional seconds. | +| [`RFC822_FORMAT`](#group__base_1ga3a5787e700549b3a93a70dcaa02056ae) | The date/time format defined in RFC 822 (obsoleted by RFC 1123). | +| [`RFC1123_FORMAT`](#group__base_1ga68d1b1aa6350fc40f88249069113fd4b) | The date/time format defined in RFC 1123 (obsoletes RFC 822). | +| [`HTTP_FORMAT`](#group__base_1ga359715c473f222e8f0dab4a2ebc7d863) | The date/time format defined in the HTTP specification (RFC 2616), which is basically a variant of RFC 1036 with a zero-padded day field. | +| [`RFC850_FORMAT`](#group__base_1ga8fa14f9a2948c74f48b694783b866f7c) | The date/time format defined in RFC 850 (obsoleted by RFC 1036). | +| [`RFC1036_FORMAT`](#group__base_1gae7c168c83eccc9fa22db1160794815d8) | The date/time format defined in RFC 1036 (obsoletes RFC 850). | +| [`ASCTIME_FORMAT`](#group__base_1ga8812f0ba04cfeb783b657aa24235243f) | The date/time format produced by the ANSI C asctime() function. | +| [`SORTABLE_FORMAT`](#group__base_1ga58bb4a2c89da2c6ea330b5db58ef81e0) | A simple, sortable date/time format. | +| [`WEEKDAY_NAMES`](#group__base_1gaa7b8ce2185d3976007545a5bc01c3806) | names used by formatter and parser English names of week days (Sunday, Monday, Tuesday, ...). | +| [`MONTH_NAMES`](#group__base_1ga5ab8b86c3b61513e25ad206a6d3e61f9) | English names of months (January, February, ...). | -#### `public inline RawPacket(char * data,size_t size,unsigned flags,void * source,void * opaque,`[`IPacketInfo`](#structscy_1_1IPacketInfo)` * info)` +--- +#### ISO8601_FORMAT +```cpp +const std::string ISO8601_FORMAT +``` +predefined date formats The date/time format defined in the ISO 8601 standard. +Examples: 2005-01-01T12:00:00+01:00 2005-01-01T11:00:00Z -#### `public inline RawPacket(const char * data,size_t size,unsigned flags,void * source,void * opaque,`[`IPacketInfo`](#structscy_1_1IPacketInfo)` * info)` +--- +#### ISO8601_FRAC_FORMAT +```cpp +const std::string ISO8601_FRAC_FORMAT +``` +The date/time format defined in the ISO 8601 standard, with fractional seconds. +Examples: 2005-01-01T12:00:00.000000+01:00 2005-01-01T11:00:00.000000Z -#### `public inline RawPacket(const `[`RawPacket`](#classscy_1_1RawPacket)` & that)` +--- +#### RFC822_FORMAT +```cpp +const std::string RFC822_FORMAT +``` +The date/time format defined in RFC 822 (obsoleted by RFC 1123). +Examples: Sat, 1 Jan 05 12:00:00 +0100 Sat, 1 Jan 05 11:00:00 GMT -#### `public inline virtual ~RawPacket()` +--- +#### RFC1123_FORMAT +```cpp +const std::string RFC1123_FORMAT +``` +The date/time format defined in RFC 1123 (obsoletes RFC 822). +Examples: Sat, 1 Jan 2005 12:00:00 +0100 Sat, 1 Jan 2005 11:00:00 GMT -#### `public inline virtual `[`IPacket`](#classscy_1_1IPacket)` * clone() const` +--- +#### HTTP_FORMAT +```cpp +const std::string HTTP_FORMAT +``` +The date/time format defined in the HTTP specification (RFC 2616), which is basically a variant of RFC 1036 with a zero-padded day field. +Examples: Sat, 01 Jan 2005 12:00:00 +0100 Sat, 01 Jan 2005 11:00:00 GMT -#### `public inline virtual void copyData(const void * data,size_t size)` +--- +#### RFC850_FORMAT +```cpp +const std::string RFC850_FORMAT +``` +The date/time format defined in RFC 850 (obsoleted by RFC 1036). +Examples: Saturday, 1-Jan-05 12:00:00 +0100 Saturday, 1-Jan-05 11:00:00 GMT -#### `public inline virtual ssize_t read(const `[`ConstBuffer`](#classscy_1_1ConstBuffer)` &)` +--- +#### RFC1036_FORMAT +```cpp +const std::string RFC1036_FORMAT +``` -Read/parse to the packet from the given input buffer. The number of bytes read is returned. +The date/time format defined in RFC 1036 (obsoletes RFC 850). -#### `public inline virtual void write(`[`Buffer`](#group__base_1gab10b36b080deb583ed703fca6b63ffdd)` &) const` +Examples: Saturday, 1 Jan 05 12:00:00 +0100 Saturday, 1 Jan 05 11:00:00 GMT +--- +#### ASCTIME_FORMAT -Copy/generate to the packet given output buffer. The number of bytes written can be obtained from the buffer. +```cpp +const std::string ASCTIME_FORMAT +``` -Todo: It may be prefferable to use our pod types here instead of buffer input, but the current codebase requires that the buffer be dynamically resizable for some protocols... +The date/time format produced by the ANSI C asctime() function. -#### `public inline virtual char * data() const` +Example: Sat Jan 1 12:00:00 2005 -The packet data pointer for buffered packets. +--- +#### SORTABLE_FORMAT +```cpp +const std::string SORTABLE_FORMAT +``` -#### `public inline virtual size_t size() const` +A simple, sortable date/time format. +Example: 2005-01-01 12:00:00 +--- -The size of the packet in bytes. +#### WEEKDAY_NAMES -This is the nember of bytes that will be written on a call to [write()](#group__base_1gaa237661815dfe9a2879a816a851b8329), but may not be the number of bytes that will be consumed by [read()](#group__base_1gae18a47214f67197af1d4ff4f32d4bfd7). +```cpp +const std::string WEEKDAY_NAMES = { + "Sunday", "Monday", "Tuesday", "Wednesday", + "Thursday", "Friday", "Saturday"} +``` -#### `public inline virtual const char * className() const` +names used by formatter and parser English names of week days (Sunday, Monday, Tuesday, ...). +--- +#### MONTH_NAMES +```cpp +const std::string MONTH_NAMES = { + "January", "February", "March", "April", "May", "June", + "July", "August", "September", "October", "November", "December"} +``` +English names of months (January, February, ...). -#### `public inline virtual bool ownsBuffer() const` +## DateTimeFormatter +> **Defined in:** `datetime.h` +This class converts dates and times into strings, supporting a variety of standard and custom formats. +There are two kind of static member functions: +* format* functions return a std::string containin the formatted value. -#### `public inline virtual void assignDataOwnership()` +* append* functions append the formatted value to an existing string. +### Members + +| Name | Description | +|------|-------------| +| [``](#group__base_1ga762f4ef4f609c78cca375e743c5b47fc) | | +| [`format`](#group__base_1ga321b8e51f548b4e27bbdd2f54168228a) | Formats the given timestamp according to the given format. The format string is used as a template to format the date and is copied character by character except for the following special characters, which are replaced by the corresponding value. | +| [`format`](#group__base_1ga3b9d02f1929b6213d8e05653dd790338) | Formats the given date and time according to the given format. See [format(const Timestamp&, const std::string&, int)](#group__base_1ga321b8e51f548b4e27bbdd2f54168228a) for more information. | +| [`format`](#group__base_1gaaf0ee3821ccd348d4a3300e5084f35db) | Formats the given local date and time according to the given format. See [format(const Timestamp&, const std::string&, int)](#group__base_1ga321b8e51f548b4e27bbdd2f54168228a) for more information. | +| [`format`](#group__base_1ga14b073e3e8e082e5d85bd2e55a47481c) | Formats the given timespan according to the given format. The format string is used as a template to format the date and is copied character by character except for the following special characters, which are replaced by the corresponding value. | +| [`append`](#group__base_1ga6cdc1d2ab5c778931ba07201f233ca12) | Formats the given timestamp according to the given format and appends it to str. | +| [`append`](#group__base_1gafa1da4e0959d36bed21fcb1e98206bd3) | Formats the given date and time according to the given format and appends it to str. | +| [`append`](#group__base_1ga566b4b57f0c04d33b75482fd9c7ed0c8) | Formats the given local date and time according to the given format and appends it to str. | +| [`append`](#group__base_1ga6155681cf2b57eaad1260053a3b07def) | Formats the given timespan according to the given format and appends it to str. | +| [`tzdISO`](#group__base_1ga709ac3bdd21971e1fd2a86363b1caba8) | Formats the given timezone differential in ISO format. If timeZoneDifferential is UTC, "Z" is returned, otherwise, +HH.MM (or -HH.MM) is returned. | +| [`tzdRFC`](#group__base_1ga56de331398bdfad483c2870ff4ece483) | Formats the given timezone differential in RFC format. If timeZoneDifferential is UTC, "GMT" is returned, otherwise ++HHMM (or -HHMM) is returned. | +| [`tzdISO`](#group__base_1ga6feb30c9395ec3415dd62beb4403d7e9) | Formats the given timezone differential in ISO format and appends it to the given string. If timeZoneDifferential is UTC, "Z" is returned, otherwise, +HH.MM (or -HH.MM) is returned. | +| [`tzdRFC`](#group__base_1gad71eec1009915e80215e20a6528f7c43) | Formats the given timezone differential in RFC format and appends it to the given string. If timeZoneDifferential is UTC, "GMT" is returned, otherwise ++HHMM (or -HHMM) is returned. | + +--- + +#### + +```cpp +enum +``` +| Value | Description | +|-------|-------------| +| `UTC` | Special value for timeZoneDifferential denoting UTC. | +--- +#### format -#### `protected char * _data` +```cpp +static inline std::string format(const Timestamp & timestamp, const std::string & fmt, int timeZoneDifferential) +``` +Formats the given timestamp according to the given format. The format string is used as a template to format the date and is copied character by character except for the following special characters, which are replaced by the corresponding value. +* w - abbreviated weekday (Mon, Tue, ...) +* W - full weekday (Monday, Tuesday, ...) +* b - abbreviated month (Jan, Feb, ...) -#### `protected size_t _size` +* B - full month (January, February, ...) +* d - zero-padded day of month (01 .. 31) +* e - day of month (1 .. 31) +* f - space-padded day of month ( 1 .. 31) +* m - zero-padded month (01 .. 12) -#### `protected bool _free` +* n - month (1 .. 12) +* o - space-padded month ( 1 .. 12) +* y - year without century (70) +* Y - year with century (1970) +* H - hour (00 .. 23) -# class `scy::RotatingFileChannel` +* h - hour (00 .. 12) -``` -class scy::RotatingFileChannel - : public scy::LogChannel -``` +* a - am/pm +* A - AM/PM +* M - minute (00 .. 59) +* S - second (00 .. 59) +* s - seconds and microseconds (equivalent to S.F) -## Summary +* i - millisecond (000 .. 999) - Members | Descriptions ---------------------------------|--------------------------------------------- -`public RotatingFileChannel(const std::string & name,const std::string & dir,LogLevel level,const std::string & extension,int rotationInterval,const char * timeFormat)` | -`public virtual ~RotatingFileChannel()` | -`public virtual void write(const `[`LogStream`](#structscy_1_1LogStream)` & stream)` | -`public virtual void rotate()` | -`public inline std::string dir() const` | -`public inline std::string filename() const` | -`public inline int rotationInterval() const` | -`public inline void setDir(const std::string & dir)` | -`public inline void setExtension(const std::string & ext)` | -`public inline void setRotationInterval(int interval)` | -`protected std::ofstream * _fstream` | -`protected std::string _dir` | -`protected std::string _filename` | -`protected std::string _extension` | -`protected int _rotationInterval` | The log rotation interval in seconds. -`protected time_t _rotatedAt` | The time the log was last rotated. +* c - centisecond (0 .. 9) -## Members +* F - fractional seconds/microseconds (000000 - 999999) -#### `public RotatingFileChannel(const std::string & name,const std::string & dir,LogLevel level,const std::string & extension,int rotationInterval,const char * timeFormat)` +* z - time zone differential in ISO 8601 format (Z or +NN.NN) +* Z - time zone differential in RFC format (GMT or +NNNN) +* %% - percent sign +Class [DateTimeFormat](#classscy_1_1DateTimeFormat) defines format strings for various standard date/time formats. +| Parameter | Type | Description | +|-----------|------|-------------| +| `timestamp` | `const Timestamp &` | | +| `fmt` | `const std::string &` | | +| `timeZoneDifferential` | `int` | | -#### `public virtual ~RotatingFileChannel()` +--- +#### format +```cpp +static inline std::string format(const DateTime & dateTime, const std::string & fmt, int timeZoneDifferential) +``` +Formats the given date and time according to the given format. See [format(const Timestamp&, const std::string&, int)](#group__base_1ga321b8e51f548b4e27bbdd2f54168228a) for more information. +| Parameter | Type | Description | +|-----------|------|-------------| +| `dateTime` | `const DateTime &` | | +| `fmt` | `const std::string &` | | +| `timeZoneDifferential` | `int` | | -#### `public virtual void write(const `[`LogStream`](#structscy_1_1LogStream)` & stream)` +--- +#### format +```cpp +static inline std::string format(const LocalDateTime & dateTime, const std::string & fmt) +``` +Formats the given local date and time according to the given format. See [format(const Timestamp&, const std::string&, int)](#group__base_1ga321b8e51f548b4e27bbdd2f54168228a) for more information. +| Parameter | Type | Description | +|-----------|------|-------------| +| `dateTime` | `const LocalDateTime &` | | +| `fmt` | `const std::string &` | | -#### `public virtual void rotate()` +--- +#### format +```cpp +static inline std::string format(const Timespan & timespan, const std::string & fmt) +``` +Formats the given timespan according to the given format. The format string is used as a template to format the date and is copied character by character except for the following special characters, which are replaced by the corresponding value. +* d - days -#### `public inline std::string dir() const` +* H - hours (00 .. 23) +* h - total hours (0 .. n) +* M - minutes (00 .. 59) +* m - total minutes (0 .. n) +* S - seconds (00 .. 59) -#### `public inline std::string filename() const` +* s - total seconds (0 .. n) +* i - milliseconds (000 .. 999) +* c - centisecond (0 .. 9) +* F - fractional seconds/microseconds (000000 - 999999) +* %% - percent sign -#### `public inline int rotationInterval() const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `timespan` | `const Timespan &` | | +| `fmt` | `const std::string &` | | +--- +#### append +```cpp +static inline void append(std::string & str, const Timestamp & timestamp, const std::string & fmt, int timeZoneDifferential) +``` +Formats the given timestamp according to the given format and appends it to str. -#### `public inline void setDir(const std::string & dir)` +See [format()](#group__base_1ga321b8e51f548b4e27bbdd2f54168228a) for documentation of the formatting string. +| Parameter | Type | Description | +|-----------|------|-------------| +| `str` | `std::string &` | | +| `timestamp` | `const Timestamp &` | | +| `fmt` | `const std::string &` | | +| `timeZoneDifferential` | `int` | | +--- +#### append +```cpp +static void append(std::string & str, const DateTime & dateTime, const std::string & fmt, int timeZoneDifferential) +``` -#### `public inline void setExtension(const std::string & ext)` +Formats the given date and time according to the given format and appends it to str. +See [format()](#group__base_1ga321b8e51f548b4e27bbdd2f54168228a) for documentation of the formatting string. +| Parameter | Type | Description | +|-----------|------|-------------| +| `str` | `std::string &` | | +| `dateTime` | `const DateTime &` | | +| `fmt` | `const std::string &` | | +| `timeZoneDifferential` | `int` | | +--- +#### append -#### `public inline void setRotationInterval(int interval)` +```cpp +static void append(std::string & str, const LocalDateTime & dateTime, const std::string & fmt) +``` +Formats the given local date and time according to the given format and appends it to str. +See [format()](#group__base_1ga321b8e51f548b4e27bbdd2f54168228a) for documentation of the formatting string. +| Parameter | Type | Description | +|-----------|------|-------------| +| `str` | `std::string &` | | +| `dateTime` | `const LocalDateTime &` | | +| `fmt` | `const std::string &` | | +--- -#### `protected std::ofstream * _fstream` +#### append +```cpp +static void append(std::string & str, const Timespan & timespan, const std::string & fmt) +``` +Formats the given timespan according to the given format and appends it to str. +See [format()](#group__base_1ga321b8e51f548b4e27bbdd2f54168228a) for documentation of the formatting string. +| Parameter | Type | Description | +|-----------|------|-------------| +| `str` | `std::string &` | | +| `timespan` | `const Timespan &` | | +| `fmt` | `const std::string &` | | -#### `protected std::string _dir` +--- +#### tzdISO +```cpp +static inline std::string tzdISO(int timeZoneDifferential) +``` +Formats the given timezone differential in ISO format. If timeZoneDifferential is UTC, "Z" is returned, otherwise, +HH.MM (or -HH.MM) is returned. +| Parameter | Type | Description | +|-----------|------|-------------| +| `timeZoneDifferential` | `int` | | -#### `protected std::string _filename` +--- +#### tzdRFC +```cpp +static inline std::string tzdRFC(int timeZoneDifferential) +``` +Formats the given timezone differential in RFC format. If timeZoneDifferential is UTC, "GMT" is returned, otherwise ++HHMM (or -HHMM) is returned. +| Parameter | Type | Description | +|-----------|------|-------------| +| `timeZoneDifferential` | `int` | | -#### `protected std::string _extension` +--- +#### tzdISO +```cpp +static void tzdISO(std::string & str, int timeZoneDifferential) +``` +Formats the given timezone differential in ISO format and appends it to the given string. If timeZoneDifferential is UTC, "Z" is returned, otherwise, +HH.MM (or -HH.MM) is returned. +| Parameter | Type | Description | +|-----------|------|-------------| +| `str` | `std::string &` | | +| `timeZoneDifferential` | `int` | | -#### `protected int _rotationInterval` +--- -The log rotation interval in seconds. +#### tzdRFC +```cpp +static void tzdRFC(std::string & str, int timeZoneDifferential) +``` +Formats the given timezone differential in RFC format and appends it to the given string. If timeZoneDifferential is UTC, "GMT" is returned, otherwise ++HHMM (or -HHMM) is returned. -#### `protected time_t _rotatedAt` +| Parameter | Type | Description | +|-----------|------|-------------| +| `str` | `std::string &` | | +| `timeZoneDifferential` | `int` | | -The time the log was last rotated. +## DateTimeParser +> **Defined in:** `datetime.h` +This class provides a method for parsing dates and times from strings. All parsing methods do their best to parse a meaningful result, even from malformed input strings. -# class `scy::RunnableQueue` +The returned [DateTime](#classscy_1_1DateTime) will always contain a time in the same timezone as the time in the string. Call [DateTime::makeUTC()](#group__base_1gaef85751cde47a0e909aeddae1775b805) with the timeZoneDifferential returned by [parse()](#group__base_1ga7249fe6e774b64ab401a6f3f97311f26) to convert the [DateTime](#classscy_1_1DateTime) to UTC. -``` -class scy::RunnableQueue - : public scy::Queue< T *> - : public scy::basic::Runnable -``` +Note: When parsing a time in 12-hour (AM/PM) format, the hour (h) must be parsed before the AM/PM designator (a, A), otherwise the AM/PM designator will be ignored. +See the [DateTimeFormatter](#classscy_1_1DateTimeFormatter) class for a list of supported format specifiers. In addition to the format specifiers supported by [DateTimeFormatter](#classscy_1_1DateTimeFormatter), an additional specifier is supported: r will parse a year given by either two or four digits. Years 69-00 are interpreted in the 20th century (1969-2000), years 01-68 in the 21th century (2001-2068). +### Members +| Name | Description | +|------|-------------| +| [`parse`](#group__base_1ga7249fe6e774b64ab401a6f3f97311f26) | Parses a date and time in the given format from the given string. Throws a SyntaxException if the string cannot be successfully parsed. Please see [DateTimeFormatter::format()](#group__base_1ga321b8e51f548b4e27bbdd2f54168228a) for a description of the format string. Class [DateTimeFormat](#classscy_1_1DateTimeFormat) defines format strings for various standard date/time formats. | +| [`parse`](#group__base_1ga7f26e4baca235538426f02338c3342fc) | Parses a date and time in the given format from the given string. Throws a SyntaxException if the string cannot be successfully parsed. Please see [DateTimeFormatter::format()](#group__base_1ga321b8e51f548b4e27bbdd2f54168228a) for a description of the format string. Class [DateTimeFormat](#classscy_1_1DateTimeFormat) defines format strings for various standard date/time formats. | +| [`tryParse`](#group__base_1ga56574df84989361f4a604e46b46d85b7) | Parses a date and time in the given format from the given string. Returns true if the string has been successfully parsed, false otherwise. Please see [DateTimeFormatter::format()](#group__base_1ga321b8e51f548b4e27bbdd2f54168228a) for a description of the format string. Class [DateTimeFormat](#classscy_1_1DateTimeFormat) defines format strings for various standard date/time formats. | +| [`parse`](#group__base_1ga3724f5eae88f6d685735d51732eeef1a) | Parses a date and time from the given dateTime string. Before parsing, the method examines the dateTime string for a known date/time format. Throws a SyntaxException if the string cannot be successfully parsed. Please see [DateTimeFormatter::format()](#group__base_1ga321b8e51f548b4e27bbdd2f54168228a) for a description of the format string. Class [DateTimeFormat](#classscy_1_1DateTimeFormat) defines format strings for various standard date/time formats. | +| [`parse`](#group__base_1ga61d6cfa09678ba2987fe32ba4b54a032) | Parses a date and time from the given dateTime string. Before parsing, the method examines the dateTime string for a known date/time format. Please see [DateTimeFormatter::format()](#group__base_1ga321b8e51f548b4e27bbdd2f54168228a) for a description of the format string. Class [DateTimeFormat](#classscy_1_1DateTimeFormat) defines format strings for various standard date/time formats. | +| [`tryParse`](#group__base_1ga1fa3ddbd5eac453273f03100e14b4b95) | Parses a date and time from the given dateTime string. Before parsing, the method examines the dateTime string for a known date/time format. Please see [DateTimeFormatter::format()](#group__base_1ga321b8e51f548b4e27bbdd2f54168228a) for a description of the format string. Class [DateTimeFormat](#classscy_1_1DateTimeFormat) defines format strings for various standard date/time formats. | +| [`parseMonth`](#group__base_1ga4901cfc35835848ebd0026032039fcaf) | Tries to interpret the given range as a month name. The range must be at least three characters long. Returns the month number (1 .. 12) if the month name is valid. Otherwise throws a SyntaxException. | +| [`parseDayOfWeek`](#group__base_1gad11bed124776792fd833d6347cbc8e0f) | Tries to interpret the given range as a weekday name. The range must be at least three characters long. Returns the weekday number (0 .. 6, where 0 = Synday, 1 = Monday, etc.) if the weekday name is valid. Otherwise throws a SyntaxException. | +| [`parseTZD`](#group__base_1gab1f9c2e9e62a2704bf88762ab4706b48) | | +| [`parseAMPM`](#group__base_1ga0f80915827b85ccdb6fd92ffff25b728) | | +--- -## Summary +#### parse - Members | Descriptions ---------------------------------|--------------------------------------------- -`public std::function< void(T &)> ondispatch` | -`public inline RunnableQueue(int limit,int timeout)` | -`public inline virtual ~RunnableQueue()` | -`public inline virtual void push(T * item)` | -`public inline virtual void flush()` | Flush all outgoing items. -`public inline void clear()` | -`public inline virtual void run()` | -`public inline virtual void runTimeout()` | -`public inline virtual void dispatch(T & item)` | Dispatch a single item to listeners. -`public inline int timeout()` | -`public inline void setTimeout(int milliseconds)` | -`protected int _limit` | -`protected int _timeout` | -`protected mutable std::mutex _mutex` | -`protected RunnableQueue(const `[`RunnableQueue`](#classscy_1_1RunnableQueue)` &) = delete` | -`protected `[`RunnableQueue`](#classscy_1_1RunnableQueue)` & operator=(const `[`RunnableQueue`](#classscy_1_1RunnableQueue)` &) = delete` | -`protected inline virtual T * popNext()` | Pops the next waiting item. -`protected inline virtual bool dispatchNext()` | Pops and dispatches the next waiting item. +```cpp +static void parse(const std::string & fmt, const std::string & str, DateTime & dateTime, int & timeZoneDifferential) +``` -## Members +Parses a date and time in the given format from the given string. Throws a SyntaxException if the string cannot be successfully parsed. Please see [DateTimeFormatter::format()](#group__base_1ga321b8e51f548b4e27bbdd2f54168228a) for a description of the format string. Class [DateTimeFormat](#classscy_1_1DateTimeFormat) defines format strings for various standard date/time formats. -#### `public std::function< void(T &)> ondispatch` +| Parameter | Type | Description | +|-----------|------|-------------| +| `fmt` | `const std::string &` | | +| `str` | `const std::string &` | | +| `dateTime` | `DateTime &` | | +| `timeZoneDifferential` | `int &` | | +--- +#### parse -The default dispatch function. Must be set before the queue is running. +```cpp +static DateTime parse(const std::string & fmt, const std::string & str, int & timeZoneDifferential) +``` -#### `public inline RunnableQueue(int limit,int timeout)` +Parses a date and time in the given format from the given string. Throws a SyntaxException if the string cannot be successfully parsed. Please see [DateTimeFormatter::format()](#group__base_1ga321b8e51f548b4e27bbdd2f54168228a) for a description of the format string. Class [DateTimeFormat](#classscy_1_1DateTimeFormat) defines format strings for various standard date/time formats. +| Parameter | Type | Description | +|-----------|------|-------------| +| `fmt` | `const std::string &` | | +| `str` | `const std::string &` | | +| `timeZoneDifferential` | `int &` | | +--- +#### tryParse +```cpp +static bool tryParse(const std::string & fmt, const std::string & str, DateTime & dateTime, int & timeZoneDifferential) +``` -#### `public inline virtual ~RunnableQueue()` +Parses a date and time in the given format from the given string. Returns true if the string has been successfully parsed, false otherwise. Please see [DateTimeFormatter::format()](#group__base_1ga321b8e51f548b4e27bbdd2f54168228a) for a description of the format string. Class [DateTimeFormat](#classscy_1_1DateTimeFormat) defines format strings for various standard date/time formats. +| Parameter | Type | Description | +|-----------|------|-------------| +| `fmt` | `const std::string &` | | +| `str` | `const std::string &` | | +| `dateTime` | `DateTime &` | | +| `timeZoneDifferential` | `int &` | | +--- +#### parse +```cpp +static void parse(const std::string & str, DateTime & dateTime, int & timeZoneDifferential) +``` -#### `public inline virtual void push(T * item)` +Parses a date and time from the given dateTime string. Before parsing, the method examines the dateTime string for a known date/time format. Throws a SyntaxException if the string cannot be successfully parsed. Please see [DateTimeFormatter::format()](#group__base_1ga321b8e51f548b4e27bbdd2f54168228a) for a description of the format string. Class [DateTimeFormat](#classscy_1_1DateTimeFormat) defines format strings for various standard date/time formats. +| Parameter | Type | Description | +|-----------|------|-------------| +| `str` | `const std::string &` | | +| `dateTime` | `DateTime &` | | +| `timeZoneDifferential` | `int &` | | +--- -Push an item onto the queue. The queue takes ownership of the item pointer. +#### parse -#### `public inline virtual void flush()` +```cpp +static DateTime parse(const std::string & str, int & timeZoneDifferential) +``` -Flush all outgoing items. +Parses a date and time from the given dateTime string. Before parsing, the method examines the dateTime string for a known date/time format. Please see [DateTimeFormatter::format()](#group__base_1ga321b8e51f548b4e27bbdd2f54168228a) for a description of the format string. Class [DateTimeFormat](#classscy_1_1DateTimeFormat) defines format strings for various standard date/time formats. +| Parameter | Type | Description | +|-----------|------|-------------| +| `str` | `const std::string &` | | +| `timeZoneDifferential` | `int &` | | +--- -#### `public inline void clear()` +#### tryParse +```cpp +static bool tryParse(const std::string & str, DateTime & dateTime, int & timeZoneDifferential) +``` +Parses a date and time from the given dateTime string. Before parsing, the method examines the dateTime string for a known date/time format. Please see [DateTimeFormatter::format()](#group__base_1ga321b8e51f548b4e27bbdd2f54168228a) for a description of the format string. Class [DateTimeFormat](#classscy_1_1DateTimeFormat) defines format strings for various standard date/time formats. +| Parameter | Type | Description | +|-----------|------|-------------| +| `str` | `const std::string &` | | +| `dateTime` | `DateTime &` | | +| `timeZoneDifferential` | `int &` | | +--- -#### `public inline virtual void run()` +#### parseMonth +```cpp +static int parseMonth(std::string::const_iterator & it, const std::string::const_iterator & end) +``` +Tries to interpret the given range as a month name. The range must be at least three characters long. Returns the month number (1 .. 12) if the month name is valid. Otherwise throws a SyntaxException. -Called asynchronously to dispatch queued items. If not timeout is set this method blocks until [cancel()](#group__base_1ga0443ed87de7952461d0948c88c8b003f) is called, otherwise [runTimeout()](#group__base_1ga834803a488030d079458bc67563ce927) will be called. Pseudo protected for std::bind compatability. +| Parameter | Type | Description | +|-----------|------|-------------| +| `it` | `std::string::const_iterator &` | | +| `end` | `const std::string::const_iterator &` | | -#### `public inline virtual void runTimeout()` +--- +#### parseDayOfWeek +```cpp +static int parseDayOfWeek(std::string::const_iterator & it, const std::string::const_iterator & end) +``` -Called asynchronously to dispatch queued items until the queue is empty or the timeout expires. Pseudo protected for std::bind compatability. +Tries to interpret the given range as a weekday name. The range must be at least three characters long. Returns the weekday number (0 .. 6, where 0 = Synday, 1 = Monday, etc.) if the weekday name is valid. Otherwise throws a SyntaxException. -#### `public inline virtual void dispatch(T & item)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `it` | `std::string::const_iterator &` | | +| `end` | `const std::string::const_iterator &` | | -Dispatch a single item to listeners. +--- +#### parseTZD +```cpp +static int parseTZD(std::string::const_iterator & it, const std::string::const_iterator & end) +``` -#### `public inline int timeout()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `it` | `std::string::const_iterator &` | | +| `end` | `const std::string::const_iterator &` | | +--- +#### parseAMPM +```cpp +static int parseAMPM(std::string::const_iterator & it, const std::string::const_iterator & end, int hour) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `it` | `std::string::const_iterator &` | | +| `end` | `const std::string::const_iterator &` | | +| `hour` | `int` | | -#### `public inline void setTimeout(int milliseconds)` +## Stopwatch +> **Defined in:** `datetime.h` +A simple facility to measure time intervals with microsecond resolution. +The [Stopwatch](#classscy_1_1Stopwatch) uses the current system time, so if the system time changes the measured time will be incorrect. +### Members + +| Name | Description | +|------|-------------| +| [`Stopwatch`](#group__base_1gac4e0a026e16191af82dd820b98d10dfb) | | +| [`~Stopwatch`](#group__base_1ga8c4cf8243072ce31339f003a06a7f2e6) | | +| [`start`](#group__base_1ga668b373cd0428065e574eb0f8bf591a5) | Starts (or restarts) the stopwatch. | +| [`stop`](#group__base_1ga4843077bf122dca1078f9fa84c5a9b84) | Stops or pauses the stopwatch. | +| [`reset`](#group__base_1ga8d1261800ad12511d76821ea78c76611) | Resets the stopwatch. | +| [`restart`](#group__base_1ga67dc5bd64beea0d85f8a691b0bb2f7fb) | Resets and starts the stopwatch. | +| [`elapsed`](#group__base_1ga2faaf087859f8cd8443a9b0dc61e2fbb) | Returns the elapsed time in microseconds since the stopwatch started. | +| [`elapsedSeconds`](#group__base_1ga004d96123d0dd9f3ddb14e1c6d5ea9a3) | Returns the number of seconds elapsed since the stopwatch started. | +| [`elapsedMilliseconds`](#group__base_1ga1a1d93858e58200b50061d20d3f8f0e6) | Returns the number of milliseconds elapsed since the stopwatch started. | +| [`resolution`](#group__base_1ga2a0ddf3cd805c968a72dabab9faebdd9) | Returns the resolution of the stopwatch. | +| [`Stopwatch`](#group__base_1ga2835ead121dae5fe2ec03d178e34d4f8) | | +| [`operator=`](#group__base_1ga8235704317a8ecaf2af18d8cfb5b78e3) | | +| [`_start`](#group__base_1ga282c91a1ad8ab7cc457fd3787a16e232) | | +| [`_elapsed`](#group__base_1ga96484d48f351cf9862574351323f7833) | | +| [`_running`](#group__base_1ga099c4db05c71b0c9f7c10c8a2147496f) | | + +--- + +#### Stopwatch + +```cpp +Stopwatch() +``` -#### `protected int _limit` +--- +#### ~Stopwatch +```cpp +~Stopwatch() +``` +--- +#### start -#### `protected int _timeout` +```cpp +void start() +``` +Starts (or restarts) the stopwatch. +--- +#### stop +```cpp +void stop() +``` -#### `protected mutable std::mutex _mutex` +Stops or pauses the stopwatch. +--- +#### reset +```cpp +void reset() +``` +Resets the stopwatch. -#### `protected RunnableQueue(const `[`RunnableQueue`](#classscy_1_1RunnableQueue)` &) = delete` +--- +#### restart +```cpp +void restart() +``` +Resets and starts the stopwatch. +--- -#### `protected `[`RunnableQueue`](#classscy_1_1RunnableQueue)` & operator=(const `[`RunnableQueue`](#classscy_1_1RunnableQueue)` &) = delete` +#### elapsed +```cpp +Timestamp::TimeDiff elapsed() const +``` +Returns the elapsed time in microseconds since the stopwatch started. +--- +#### elapsedSeconds -#### `protected inline virtual T * popNext()` +```cpp +int elapsedSeconds() const +``` -Pops the next waiting item. +Returns the number of seconds elapsed since the stopwatch started. +--- +#### elapsedMilliseconds -#### `protected inline virtual bool dispatchNext()` +```cpp +int elapsedMilliseconds() const +``` -Pops and dispatches the next waiting item. +Returns the number of milliseconds elapsed since the stopwatch started. +--- +#### resolution -# class `scy::Runner` +```cpp +static Timestamp::TimeVal resolution() +``` +Returns the resolution of the stopwatch. +--- +#### Stopwatch -[Runner](#classscy_1_1Runner) is a virtual interface for implementing asynchronous objects such as threads and futures. +```cpp +Stopwatch(const Stopwatch &) = delete +``` -## Summary +--- - Members | Descriptions ---------------------------------|--------------------------------------------- -`public Runner()` | -`public virtual ~Runner()` | -`public void start(std::function< void()> target)` | -`public bool running() const` | Returns true if the async context is currently running. -`public void cancel()` | Cancels the async context. -`public bool cancelled() const` | -`public bool repeating() const` | Returns true if the [Runner](./doc/api-base.md#classscy_1_1Runner) is operating in repeating mode. -`public void setRepeating(bool flag)` | -`public bool async() const` | -`public std::thread::id tid() const` | Return the native thread ID. -`public bool waitForExit(int timeout)` | -`protected std::shared_ptr< `[`Context`](./doc/api-base.md#structscy_1_1Runner_1_1Context)` > _context` | Shared pointer to the internal [Context](./doc/api-base.md#structscy_1_1Runner_1_1Context). -`protected Runner(const `[`Runner`](#classscy_1_1Runner)` &) = delete` | NonCopyable and NonMovable. -`protected `[`Runner`](#classscy_1_1Runner)` & operator=(const `[`Runner`](#classscy_1_1Runner)` &) = delete` | +#### operator= -## Members +```cpp +Stopwatch & operator=(const Stopwatch &) = delete +``` -#### `public Runner()` +--- +#### _start +```cpp +Timestamp _start +``` +--- +#### _elapsed -#### `public virtual ~Runner()` +```cpp +Timestamp::TimeDiff _elapsed +``` +--- +#### _running +```cpp +bool _running +``` +## Idler -#### `public void start(std::function< void()> target)` +> **Extends:** `scy::Runner` +> **Defined in:** `idler.h` +Asynchronous type that triggers callbacks when the event loop is idle. +This class inherits the `[Runner](#classscy_1_1Runner)` interface and may be used with any implementation that's powered by an asynchronous `[Runner](#classscy_1_1Runner)`. -Start the asynchronous context with the given invokeback. +### Members -The target `Runnable` instance must outlive the `[Runner](#classscy_1_1Runner)`. +| Name | Description | +|------|-------------| +| [`Idler`](#group__base_1ga739bc010da58a894a3645ff96a4d952b) | Create the idler with the given event loop. | +| [`Idler`](#group__base_1ga5668cd56a3f7b9e94dd156ed16c81daf) | Create and start the idler with the given callback. | +| [`Idler`](#group__base_1ga436dab9be6d7df1fcbd7648231f2b7b5) | Create and start the idler with the given callback and event loop. | +| [`start`](#group__base_1ga08c0528ddb37409dbc34a605c66a0e32) | Start the idler with the given callback function. | +| [`start`](#group__base_1gae20b7dc946cc87b954d55ee98b13e42d) | Start the idler with the given callback function. | +| [`~Idler`](#group__base_1ga11188502419543dad55d458c911517f3) | | +| [`handle`](#group__base_1ga93b2d76ea0682c2cf152393d3e36c34f) | | +| [`init`](#group__base_1ga331ca6dc143e20e5520d09d6db3e6f46) | | +| [`async`](#group__base_1ga234255f1e2a998e67d9749ef9451ec8c) | Returns true if the implementation is thread-based, or false if it belongs to an event loop. | +| [`_handle`](#group__base_1gaffe75a6686ac64a54381ce771fc72846) | | -#### `public bool running() const` +--- -Returns true if the async context is currently running. +#### Idler +```cpp +Idler(uv::Loop * loop) +``` +Create the idler with the given event loop. -#### `public void cancel()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `loop` | `uv::Loop *` | | -Cancels the async context. +--- +#### Idler +```cpp +template inline explicit Idler(Function && func, Args &&... args) +``` -#### `public bool cancelled() const` +Create and start the idler with the given callback. +| Parameter | Type | Description | +|-----------|------|-------------| +| `func` | `Function &&` | | +| `args` | `Args &&...` | | +--- -True when the task has been cancelled. It is up to the implementation to return at the earliest possible time. +#### Idler -#### `public bool repeating() const` +```cpp +template inline explicit Idler(uv::Loop * loop, Function && func, Args &&... args) +``` -Returns true if the [Runner](#classscy_1_1Runner) is operating in repeating mode. +Create and start the idler with the given callback and event loop. +| Parameter | Type | Description | +|-----------|------|-------------| +| `loop` | `uv::Loop *` | | +| `func` | `Function &&` | | +| `args` | `Args &&...` | | +--- -#### `public void setRepeating(bool flag)` +#### start +```cpp +template inline void start(Function && func, Args &&... args) +``` +Start the idler with the given callback function. -This setting means the implementation should invoke the target function repeatedly until cancelled. The importance of this method to normalize the functionality of threadded and event loop driven [Runner](#classscy_1_1Runner) models. +| Parameter | Type | Description | +|-----------|------|-------------| +| `func` | `Function &&` | | +| `args` | `Args &&...` | | -#### `public bool async() const` +--- +#### start +```cpp +virtual void start(std::function< void()> func) +``` -Returns true if the implementation is thread-based, or false if it belongs to an event loop. +Start the idler with the given callback function. -#### `public std::thread::id tid() const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `func` | `std::function< void()>` | | -Return the native thread ID. +--- +#### ~Idler +```cpp +virtual ~Idler() = default +``` -#### `public bool waitForExit(int timeout)` +--- +#### handle +```cpp +uv::Handle< uv_idle_t > & handle() +``` -Wait until the thread exits. +--- -The thread should be cancelled beore invokeing this method. This method must be invokeed from outside the current thread context or deadlock will ensue. +#### init -#### `protected std::shared_ptr< `[`Context`](./doc/api-base.md#structscy_1_1Runner_1_1Context)` > _context` +```cpp +virtual void init() +``` -Shared pointer to the internal [Context](#structscy_1_1Runner_1_1Context). +--- +#### async +```cpp +virtual bool async() const +``` -#### `protected Runner(const `[`Runner`](#classscy_1_1Runner)` &) = delete` +Returns true if the implementation is thread-based, or false if it belongs to an event loop. -NonCopyable and NonMovable. +--- +#### _handle +```cpp +uv::Handle< uv_idle_t > _handle +``` -#### `protected `[`Runner`](#classscy_1_1Runner)` & operator=(const `[`Runner`](#classscy_1_1Runner)` &) = delete` +## Decoder +> **Subclasses:** `scy::base64::Decoder`, `scy::hex::Decoder` +> **Defined in:** `interface.h` +### Members +| Name | Description | +|------|-------------| +| [`Decoder`](#group__base_1gade9cc166b3b0ef9ff1f0b50b77e7274e) | | +| [`~Decoder`](#group__base_1ga50e48ec8e55949e65a6982499bfc10a8) | | +| [`decode`](#group__base_1gac65b84911c78dd1a08a1a6350598574f) | | +| [`finalize`](#group__base_1ga47f23ea47df219cfdcd17139e0d699d8) | | +--- -# class `scy::ScopedConfiguration` +#### Decoder +```cpp +Decoder() = default +``` +--- +#### ~Decoder -[ScopedConfiguration](#classscy_1_1ScopedConfiguration) provides multiple levels of configuration for a module. Multiple levels means that there is a module level scope, and a default scope. When a property is accessed, the module scope value will be used if available, otherwise the default scope value will be used. +```cpp +virtual ~Decoder() = default +``` -Example scoping: Module: channels.[name].modes.[name].[value] Default: modes.[name].[value] +--- -## Summary +#### decode - Members | Descriptions ---------------------------------|--------------------------------------------- -`public `[`Configuration`](./doc/api-base.md#classscy_1_1Configuration)` & config` | -`public std::string currentScope` | -`public std::string defaultScope` | -`public ScopedConfiguration(`[`Configuration`](#classscy_1_1Configuration)` & config,const std::string & currentScope,const std::string & defaultScope)` | -`public ScopedConfiguration(const `[`ScopedConfiguration`](#classscy_1_1ScopedConfiguration)` & that)` | -`public std::string getString(const std::string & key,const std::string & defaultValue,bool forceDefaultScope) const` | -`public int getInt(const std::string & key,int defaultValue,bool forceDefaultScope) const` | -`public double getDouble(const std::string & key,double defaultValue,bool forceDefaultScope) const` | -`public bool getBool(const std::string & key,bool defaultValue,bool forceDefaultScope) const` | -`public void setString(const std::string & key,const std::string & value,bool defaultScope)` | -`public void setInt(const std::string & key,int value,bool defaultScope)` | -`public void setDouble(const std::string & key,double value,bool defaultScope)` | -`public void setBool(const std::string & key,bool value,bool defaultScope)` | -`public std::string getCurrentScope(const std::string & key) const` | -`public std::string getDafaultKey(const std::string & key) const` | -`public std::string getScopedKey(const std::string & key,bool defaultScope) const` | +```cpp +ssize_t decode(const char * inbuf, size_t nread, char * outbuf) +``` -## Members +| Parameter | Type | Description | +|-----------|------|-------------| +| `inbuf` | `const char *` | | +| `nread` | `size_t` | | +| `outbuf` | `char *` | | -#### `public `[`Configuration`](./doc/api-base.md#classscy_1_1Configuration)` & config` +--- +#### finalize +```cpp +virtual inline ssize_t finalize(char *) +``` +## Encoder +> **Subclasses:** `scy::base64::Encoder`, `scy::hex::Encoder` +> **Defined in:** `interface.h` -#### `public std::string currentScope` +### Members +| Name | Description | +|------|-------------| +| [`Encoder`](#group__base_1gaf17b2ede23093905c0053f9026ed6d27) | | +| [`~Encoder`](#group__base_1ga66430a3e3d8cf10fb45792b86c11b1da) | | +| [`encode`](#group__base_1ga0568bf005c544b0ba6a51e2aec7b27f7) | | +| [`finalize`](#group__base_1gae834fb2c3fc0400200e8668967487271) | | +--- +#### Encoder +```cpp +Encoder() = default +``` -#### `public std::string defaultScope` +--- +#### ~Encoder +```cpp +virtual ~Encoder() = default +``` +--- +#### encode -#### `public ScopedConfiguration(`[`Configuration`](#classscy_1_1Configuration)` & config,const std::string & currentScope,const std::string & defaultScope)` +```cpp +ssize_t encode(const char * inbuf, size_t nread, char * outbuf) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `inbuf` | `const char *` | | +| `nread` | `size_t` | | +| `outbuf` | `char *` | | +--- +#### finalize +```cpp +virtual inline ssize_t finalize(char *) +``` -#### `public ScopedConfiguration(const `[`ScopedConfiguration`](#classscy_1_1ScopedConfiguration)` & that)` +## Runnable +> **Subclasses:** `scy::RunnableQueue< IPacket >`, `scy::RunnableQueue< PacketT >`, `scy::AsyncDiagnostic`, `scy::AsyncLogWriter`, `scy::RunnableQueue< T >`, `scy::Task`, `scy::TaskRunner`, `scy::av::MediaCapture`, `scy::pacm::InstallTask` +> **Defined in:** `interface.h` +Abstract interface for classes that can be run and cancelled. +### Members +| Name | Description | +|------|-------------| +| [`Runnable`](#group__base_1ga24989581d30677599fd7049641aad045) | | +| [`~Runnable`](#group__base_1gaf7dbd42fb236f2bb1a9148a295ee9e15) | | +| [`run`](#group__base_1ga58cbd03f96d0fcbac2441437f5325e5e) | The run method will be called by the asynchronous context. | +| [`cancel`](#group__base_1ga0443ed87de7952461d0948c88c8b003f) | Cancel the current task. The [run()](#group__base_1ga58cbd03f96d0fcbac2441437f5325e5e) method should return ASAP. | +| [`cancelled`](#group__base_1gab3795d080eae2e58a57f2c63524c8ef3) | Returns true when the task has been cancelled. | +| [`exit`](#group__base_1gaccdc67bba64aeb38d3c7a6c4f07d9964) | | -#### `public std::string getString(const std::string & key,const std::string & defaultValue,bool forceDefaultScope) const` +--- +#### Runnable +```cpp +inline Runnable() +``` +--- +#### ~Runnable -#### `public int getInt(const std::string & key,int defaultValue,bool forceDefaultScope) const` +```cpp +virtual ~Runnable() = default +``` +--- +#### run +```cpp +void run() +``` +The run method will be called by the asynchronous context. -#### `public double getDouble(const std::string & key,double defaultValue,bool forceDefaultScope) const` +--- +#### cancel +```cpp +virtual inline void cancel(bool flag) +``` +Cancel the current task. The [run()](#group__base_1ga58cbd03f96d0fcbac2441437f5325e5e) method should return ASAP. +| Parameter | Type | Description | +|-----------|------|-------------| +| `flag` | `bool` | | -#### `public bool getBool(const std::string & key,bool defaultValue,bool forceDefaultScope) const` +--- +#### cancelled +```cpp +virtual inline bool cancelled() const +``` +Returns true when the task has been cancelled. +--- -#### `public void setString(const std::string & key,const std::string & value,bool defaultScope)` +#### exit +```cpp +std::atomic< bool > exit +``` +## Startable +> **Subclasses:** `scy::ThreadedStreamReader`, `scy::av::ICapture`, `scy::http::FormWriter` +> **Defined in:** `interface.h` +Abstract interface for a classes that can be started and stopped. -#### `public void setInt(const std::string & key,int value,bool defaultScope)` +### Members +| Name | Description | +|------|-------------| +| [`start`](#group__base_1gaccc9e2a0d97f8a69d75f3970e1ccbd78) | | +| [`stop`](#group__base_1ga8c7cffc58e6830dade1d8434f7b5822d) | | +--- +#### start +```cpp +void start() +``` -#### `public void setDouble(const std::string & key,double value,bool defaultScope)` +--- +#### stop +```cpp +void stop() +``` +## Sendable +> **Subclasses:** `scy::PacketTransaction< sockio::Packet >`, `scy::PacketTransaction< Message >`, `scy::PacketTransaction< PacketT >` +> **Defined in:** `interface.h` -#### `public void setBool(const std::string & key,bool value,bool defaultScope)` +Abstract interface for classes that can be sent and cancelled. +### Members +| Name | Description | +|------|-------------| +| [`send`](#group__base_1ga2bd0718ede40baace8487cd06b87fcff) | | +| [`cancel`](#group__base_1gaf2764466a92113997b48d40baf2403e0) | | +--- +#### send -#### `public std::string getCurrentScope(const std::string & key) const` +```cpp +bool send() +``` +--- +#### cancel +```cpp +void cancel() +``` +## Queue -#### `public std::string getDafaultKey(const std::string & key) const` +> **Subclasses:** `scy::ipc::SyncQueue< TAction >` +> **Defined in:** `ipc.h` +IPC queue is for safely passing templated actions between threads and processes. +### Members +| Name | Description | +|------|-------------| +| [`Queue`](#group__base_1gac93ef0838e9baed8333908c8d65e7b8d) | | +| [`~Queue`](#group__base_1ga9546d7f27045e6717afa2125dfafd053) | | +| [`push`](#group__base_1ga9c786634a41240b2c27b2bf3de496f9c) | | +| [`pop`](#group__base_1ga02cdcc43483f08820b6eea3866d01c9d) | | +| [`runSync`](#group__base_1ga1e0208d28978fee4cb039205a0fbc020) | | +| [`close`](#group__base_1ga0efb103e4e82dc199cba8c3908183ea4) | | +| [`post`](#group__base_1ga3bb872c395705ae78b72cfafc188e1fd) | | +| [`waitForSync`](#group__base_1ga394493f310e54d4bb33265cb840fefdf) | | +| [`_mutex`](#group__base_1gabe0c2735e26749941052787051bb44bd) | | +| [`_actions`](#group__base_1ga238c51fb2dd7bf29152e4863d13fa1e5) | | +--- -#### `public std::string getScopedKey(const std::string & key,bool defaultScope) const` +#### Queue +```cpp +inline Queue() +``` +--- +#### ~Queue +```cpp +virtual inline ~Queue() +``` -# class `scy::ScopedLock` +--- +#### push +```cpp +virtual inline void push(TAction * action) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `action` | `TAction *` | | -[ScopedLock](#classscy_1_1ScopedLock) simplifies thread synchronization with a [Mutex](#classscy_1_1Mutex) or similar lockable object. The given [Mutex](#classscy_1_1Mutex) is locked in the constructor, and unlocked it in the destructor. T can be any class with lock() and unlock() functions. +--- -## Summary +#### pop - Members | Descriptions ---------------------------------|--------------------------------------------- -`public inline explicit ScopedLock(T & m)` | -`public inline ~ScopedLock()` | +```cpp +virtual inline TAction * pop() +``` -## Members +--- -#### `public inline explicit ScopedLock(T & m)` +#### runSync +```cpp +virtual inline void runSync() +``` +--- +#### close +```cpp +virtual inline void close() +``` -#### `public inline ~ScopedLock()` +--- +#### post +```cpp +virtual inline void post() +``` +--- +#### waitForSync -# class `scy::ScopedPointer` +```cpp +inline void waitForSync() +``` +--- -Scoped Pointer Classes. +#### _mutex -[ScopedPointer](#classscy_1_1ScopedPointer) provides an interface for holding and ansynchronously deleting a pointer in various ways. +```cpp +std::mutex _mutex +``` -## Summary +--- - Members | Descriptions ---------------------------------|--------------------------------------------- -`public inline ScopedPointer()` | -`public inline virtual ~ScopedPointer()` | +#### _actions -## Members +```cpp +std::deque< TAction * > _actions +``` -#### `public inline ScopedPointer()` +## SyncQueue +> **Extends:** `scy::ipc::Queue< ipc::Action >` +> **Defined in:** `ipc.h` +IPC synchronization queue is for passing templated actions between threads and the event loop we are synchronizing with. +### Members +| Name | Description | +|------|-------------| +| [`SyncQueue`](#group__base_1ga5d75b88fd48fd9b14a1300775471fcbb) | | +| [`~SyncQueue`](#group__base_1gae3f23ea3eb42ed63fbb0850d43805178) | | +| [`close`](#group__base_1ga8546519d8077f5c05a52d9f2b926b233) | | +| [`post`](#group__base_1gabbb1f498c837051e29c0553ed4127db8) | | +| [`sync`](#group__base_1ga88b2c8e4905f07f99f5e36573eb9ac4c) | | +| [`_sync`](#group__base_1gad6b153706fc24a42c70b32def9f2f6aa) | | -#### `public inline virtual ~ScopedPointer()` +--- +#### SyncQueue +```cpp +inline SyncQueue(uv::Loop * loop) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `loop` | `uv::Loop *` | | +--- -# class `scy::ScopedRawPointer` +#### ~SyncQueue +```cpp +virtual inline ~SyncQueue() ``` -class scy::ScopedRawPointer - : public scy::ScopedPointer -``` +--- +#### close -[ScopedRawPointer](#classscy_1_1ScopedRawPointer) implements the [ScopedPointer](#classscy_1_1ScopedPointer) interface to provide a method for deleting a raw pointer. +```cpp +virtual inline void close() +``` -## Summary +--- - Members | Descriptions ---------------------------------|--------------------------------------------- -`public void * ptr` | -`public inline ScopedRawPointer(void * p)` | -`public inline virtual ~ScopedRawPointer()` | +#### post -## Members +```cpp +virtual inline void post() +``` -#### `public void * ptr` +--- +#### sync +```cpp +virtual inline Synchronizer & sync() +``` +--- +#### _sync -#### `public inline ScopedRawPointer(void * p)` +```cpp +Synchronizer _sync +``` +## LogWriter +> **Subclasses:** `scy::AsyncLogWriter` +> **Defined in:** `logger.h` +Log output stream writer. +### Members -#### `public inline virtual ~ScopedRawPointer()` +| Name | Description | +|------|-------------| +| [`LogWriter`](#group__base_1gad880791856a3ee0c440304b8ad6aa0fd) | | +| [`~LogWriter`](#group__base_1ga7059e18a3a0c69fe8333f2bbf9a9e6d0) | | +| [`write`](#group__base_1gafd98afb4e7030c196f9e167460336c1f) | Writes the given log message stream. | +--- +#### LogWriter +```cpp +LogWriter() +``` +--- -# class `scy::ScopedSharedPointer` +#### ~LogWriter +```cpp +virtual ~LogWriter() ``` -class scy::ScopedSharedPointer - : public scy::ScopedPointer -``` +--- +#### write -[ScopedSharedPointer](#classscy_1_1ScopedSharedPointer) implements the [ScopedPointer](#classscy_1_1ScopedPointer) interface to provide deferred deletion for shared_ptr managed pointers. Note that this class does not guarantee deletion of the managed pointer; all it does is copy the shared_ptr and release it when the [ScopedSharedPointer](#classscy_1_1ScopedSharedPointer) instance is deleted, which makes it useful for certain asyncronous scenarios. +```cpp +virtual void write(std::unique_ptr< LogStream > stream) +``` + +Writes the given log message stream. -## Summary +| Parameter | Type | Description | +|-----------|------|-------------| +| `stream` | `std::unique_ptr< LogStream >` | | - Members | Descriptions ---------------------------------|--------------------------------------------- -`public std::shared_ptr< T > ptr` | -`public inline ScopedSharedPointer(std::shared_ptr< T > p)` | -`public inline virtual ~ScopedSharedPointer()` | +## AsyncLogWriter -## Members +> **Extends:** `scy::LogWriter`, `scy::basic::Runnable` +> **Defined in:** `logger.h` -#### `public std::shared_ptr< T > ptr` +[Thread](#classscy_1_1Thread) based log output stream writer. +### Members +| Name | Description | +|------|-------------| +| [`AsyncLogWriter`](#group__base_1ga0188ef05599b6dda991e15a125926a93) | | +| [`~AsyncLogWriter`](#group__base_1ga94107b494835580b0e435f9c7ef870fe) | | +| [`write`](#group__base_1gaeaa026442c5927b21b599ded87601908) | Queues the given log message stream. | +| [`flush`](#group__base_1ga6af94a2ef68c7b0114f6d91684a2aca7) | Flushes queued messages. | +| [`run`](#group__base_1gaa38a45dab3b692894a6d1753dadb7164) | Writes queued messages asynchronously. | +| [`clear`](#group__base_1gad918ab56f2652c0df2a0b4c74823fc18) | Clears all queued messages. | +| [`writeNext`](#group__base_1ga05d6ccb870b82f130810f3c9d002d9bb) | | +| [`_thread`](#group__base_1ga75dcded0c2370591afb489f4892b7b54) | | +| [`_pending`](#group__base_1ga60cdd0b73b13f1d27e06a9e4fedea209) | | +| [`_mutex`](#group__base_1ga6a888007ca6e0e1bddd6a6378b9f36e0) | | +--- +#### AsyncLogWriter -#### `public inline ScopedSharedPointer(std::shared_ptr< T > p)` +```cpp +AsyncLogWriter() +``` +--- +#### ~AsyncLogWriter +```cpp +virtual ~AsyncLogWriter() +``` +--- -#### `public inline virtual ~ScopedSharedPointer()` +#### write +```cpp +virtual void write(std::unique_ptr< LogStream > stream) +``` +Queues the given log message stream. +| Parameter | Type | Description | +|-----------|------|-------------| +| `stream` | `std::unique_ptr< LogStream >` | | +--- -# class `scy::Signal` +#### flush +```cpp +void flush() +``` +Flushes queued messages. +--- -[Signal](#classscy_1_1Signal) and slots implementation. +#### run -To create a signal, declare member variables of type `[Signal](#classscy_1_1Signal)<...>` in your class. The template parameter is the argument types that will be passed to the callback functions. +```cpp +virtual void run() +``` -Here's a simple example with a class `MyClass` that has a single signal `my_signal` which takes a single `int` argument: class MyClass -{ -public: - Signal my_signal; - ... -}; +Writes queued messages asynchronously. +--- -To connect to a signal, call its `attach()` member function, passing a function (in the `std::function` sense) as the argument. The function can be a function pointer, a functor object, or an anonymous lambda function. +#### clear -Here's an example connecting to the above signal to a lambda function: MyClass my_class; -my_class.my_signal.attach([](int x) { - cout << "value: " << x << endl; -}); +```cpp +void clear() +``` +Clears all queued messages. -The `attach()` function returns a unique ID of type `int` which can be used later to disconnect the callback function. +--- -Here's an example using the above code to then immediately disconnect the signal connection with the `detach()` member function: MyClass my_class; -auto id = my_class.my_signal.attach([](int x) { - cout << "value: " << x << endl; -}); -my_class.my_signal.detach(id); +#### writeNext +```cpp +bool writeNext() +``` -The `detach()` function is passed the callback ID and will return `true` if a callback was disconnected or `false` if the ID wasn't found. Note that `detach()` can be safely called from within the callback scope. +--- -In the case of class members there is a `slot()` helper that can be used to bind the signal like so: class TargetClass -{ -public: - Signal my_signal; +#### _thread - int print(int x) - { - cout << "say: " << x << endl; - } -}; +```cpp +Thread _thread +``` -MyClass my_class; +--- -TargetClass target_class; -my_class.my_signal += slot(&target_class, &TargetClass::print) +#### _pending +```cpp +std::deque< std::unique_ptr< LogStream > > _pending +``` -The `slot()` helper can also be used to disconnect class member callbacks like so: my_class.my_signal -= slot(&target_class, &TargetClass::print) +--- +#### _mutex -To emit the signal, call its `emit()` member function passing arguments matching the types of those in the signal variable declaration. +```cpp +std::mutex _mutex +``` -Using the above example code, here's an example showing how to emit `my_signal`: my_class.my_signal.emit(42); +## Logger +> **Defined in:** `logger.h` -Since the signal was declared to take a single `int` argument, this will cause any callbacks connected to the signal to be called, passing the integer `42` as the only argument. +[Logger](#classscy_1_1Logger) class. -## Summary +### Members + +| Name | Description | +|------|-------------| +| [`Logger`](#group__base_1gaa58d26b288c4baf5595bbbcb71653b95) | | +| [`~Logger`](#group__base_1ga84c1d5e6cd7053bd476eca1eca9e8030) | | +| [`add`](#group__base_1ga05923e337fd59d892c096ad31afa3801) | Adds the given log channel. Takes ownership. | +| [`remove`](#group__base_1ga72971c94e65ab1660ec9bb00a1bcd54e) | Removes the given log channel by name. | +| [`get`](#group__base_1ga91e6c5fd7fa7340056fe8ba8935c2641) | Returns the specified log channel. Throws an exception if the channel doesn't exist. | +| [`setDefault`](#group__base_1ga7ec2b37dc4de80b4790a522f8c08f0a8) | Sets the default log to the specified log channel. | +| [`setWriter`](#group__base_1ga4f547043311cd4aa045d67b156d6575d) | Sets the log writer instance. Takes ownership. | +| [`getDefault`](#group__base_1ga5a48a75f4ee17d6bc3fa81b92331d64d) | Returns the default log channel, or the nullptr channel if no default channel has been set. | +| [`write`](#group__base_1gadea484eefd15977b355c26107cd325df) | Writes the given message to the default log channel. The message will be copied. | +| [`write`](#group__base_1ga267674b14b4556d9acd86e16ef8b331c) | Writes the given message to the default log channel. | +| [`instance`](#group__base_1ga803744d1eb81ca3ba367c5e0081c1e98) | Returns the default logger singleton. [Logger](#classscy_1_1Logger) instances may be created separately as needed. | +| [`setInstance`](#group__base_1ga89d453d2d992f8dde3b57732f3c204c5) | Sets the default logger singleton instance. | +| [`destroy`](#group__base_1ga5972c9db1f70e5a85b85e48401e9168a) | Destroys the default logger singleton instance. | +| [`Logger`](#group__base_1gae25ba15fd8c92541a296f5be97f0ece8) | NonCopyable and NonMovable. | +| [`operator=`](#group__base_1gacb35ed074bb58c0d6f69109ee331d95d) | | +| [`_mutex`](#group__base_1ga01d897e3d08b06665c99e2a4fe27fc12) | | +| [`_channels`](#group__base_1ga9477bfaa930adfd93c981708c72fff5f) | | +| [`_defaultChannel`](#group__base_1ga0bc50bd2da990173ed15e251b7df2e9c) | | +| [`_writer`](#group__base_1gacf4bad357409e6cee0c4d0c0594c7bb8) | | + +--- + +#### Logger + +```cpp +Logger() +``` - Members | Descriptions ---------------------------------|--------------------------------------------- +--- -## Members +#### ~Logger -# class `scy::Signal< RT(Args...)>` +```cpp +~Logger() +``` +--- +#### add +```cpp +void add(std::unique_ptr< LogChannel > channel) +``` +Adds the given log channel. Takes ownership. +| Parameter | Type | Description | +|-----------|------|-------------| +| `channel` | `std::unique_ptr< LogChannel >` | | -## Summary +--- - Members | Descriptions ---------------------------------|--------------------------------------------- -`public inline int attach(Function const & func,void * instance,int id,int priority) const` | -`public inline int attach(SlotPtr slot) const` | -`public inline bool detach(int id) const` | Detaches a previously attached slot. -`public inline bool detach(const void * instance) const` | Detaches all slots for the given instance. -`public inline bool detach(SlotPtr other) const` | Detaches all attached functions for the given instance. -`public inline void detachAll() const` | Detaches all previously attached functions. -`public inline virtual void emit(Args... args)` | Emits the signal to all attached functions. -`public inline std::vector< SlotPtr > slots() const` | Returns the managed slot list. -`public inline size_t nslots() const` | Returns the number of active slots. -`public inline int operator+=(Function const & func)` | Convenience operators. -`public inline int operator+=(SlotPtr slot)` | -`public inline bool operator-=(int id)` | -`public inline bool operator-=(const void * instance)` | -`public inline bool operator-=(SlotPtr slot)` | -`public inline Signal()` | Default constructor. -`public inline Signal(const `[`Signal`](#classscy_1_1Signal)` & r)` | Copy constructor. -`public inline `[`Signal`](#classscy_1_1Signal)` & operator=(const `[`Signal`](#classscy_1_1Signal)` & r)` | Assignment operator. +#### remove -## Members +```cpp +void remove(const std::string & name) +``` -#### `public inline int attach(Function const & func,void * instance,int id,int priority) const` +Removes the given log channel by name. +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | +--- -Connects a `lambda` or `std::function` to the `[Signal](#classscy_1_1Signal)`. The returned value can be used to detach the slot. +#### get -#### `public inline int attach(SlotPtr slot) const` +```cpp +LogChannel * get(const std::string & name, bool whiny) const +``` +Returns the specified log channel. Throws an exception if the channel doesn't exist. +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | +| `whiny` | `bool` | | -Connects a `SlotPtr` instance to the `[Signal](#classscy_1_1Signal)`. The returned value can be used to detach the slot. +--- -#### `public inline bool detach(int id) const` +#### setDefault -Detaches a previously attached slot. +```cpp +void setDefault(const std::string & name) +``` +Sets the default log to the specified log channel. +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | -#### `public inline bool detach(const void * instance) const` +--- -Detaches all slots for the given instance. +#### setWriter +```cpp +void setWriter(std::unique_ptr< LogWriter > writer) +``` +Sets the log writer instance. Takes ownership. -#### `public inline bool detach(SlotPtr other) const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `writer` | `std::unique_ptr< LogWriter >` | | -Detaches all attached functions for the given instance. +--- +#### getDefault +```cpp +LogChannel * getDefault() const +``` -#### `public inline void detachAll() const` +Returns the default log channel, or the nullptr channel if no default channel has been set. -Detaches all previously attached functions. +--- +#### write +```cpp +void write(const LogStream & stream) +``` -#### `public inline virtual void emit(Args... args)` +Writes the given message to the default log channel. The message will be copied. -Emits the signal to all attached functions. +| Parameter | Type | Description | +|-----------|------|-------------| +| `stream` | `const LogStream &` | | +--- +#### write -#### `public inline std::vector< SlotPtr > slots() const` +```cpp +void write(std::unique_ptr< LogStream > stream) +``` -Returns the managed slot list. +Writes the given message to the default log channel. +| Parameter | Type | Description | +|-----------|------|-------------| +| `stream` | `std::unique_ptr< LogStream >` | | +--- -#### `public inline size_t nslots() const` +#### instance -Returns the number of active slots. +```cpp +static Logger & instance() +``` +Returns the default logger singleton. [Logger](#classscy_1_1Logger) instances may be created separately as needed. +--- -#### `public inline int operator+=(Function const & func)` +#### setInstance -Convenience operators. +```cpp +static void setInstance(Logger * logger, bool freeExisting) +``` +Sets the default logger singleton instance. +| Parameter | Type | Description | +|-----------|------|-------------| +| `logger` | `Logger *` | | +| `freeExisting` | `bool` | | -#### `public inline int operator+=(SlotPtr slot)` +--- +#### destroy +```cpp +static void destroy() +``` +Destroys the default logger singleton instance. +--- -#### `public inline bool operator-=(int id)` +#### Logger +```cpp +Logger(const Logger &) = delete +``` +NonCopyable and NonMovable. +--- +#### operator= -#### `public inline bool operator-=(const void * instance)` +```cpp +Logger & operator=(const Logger &) = delete +``` +--- +#### _mutex +```cpp +std::mutex _mutex +``` +--- -#### `public inline bool operator-=(SlotPtr slot)` +#### _channels +```cpp +LogChannelMap _channels +``` +--- +#### _defaultChannel +```cpp +LogChannel * _defaultChannel +``` -#### `public inline Signal()` +--- -Default constructor. +#### _writer +```cpp +std::unique_ptr< LogWriter > _writer +``` +## LogChannel + +> **Subclasses:** `scy::ConsoleChannel`, `scy::FileChannel`, `scy::RotatingFileChannel` +> **Defined in:** `logger.h` + +### Members + +| Name | Description | +|------|-------------| +| [`LogChannel`](#group__base_1ga6eb210d878e572311225b015a9cb0bf1) | | +| [`~LogChannel`](#group__base_1gadd94d58dca0580ff476c68e3526f3aff) | | +| [`write`](#group__base_1gac8341cc041aa699d3e7ee7f41d37f568) | | +| [`write`](#group__base_1gaf330bc738bee8077756d40cb366c3aee) | | +| [`format`](#group__base_1gafff619cedc1fa6a263b64f198b100307) | | +| [`name`](#group__base_1gafa0ee6ecc108c2f153760696afc335b8) | | +| [`level`](#group__base_1gaf151e272e61eb39e9d29bb973eac88f0) | | +| [`timeFormat`](#group__base_1gad20ec0d479792546f08423b0631cff9d) | | +| [`setLevel`](#group__base_1ga6d3ccc136614e8aee1b811b42ac1013c) | | +| [`setTimeFormat`](#group__base_1ga8a169d04776fc4c28bd7e1b22e22895a) | | +| [`setFilter`](#group__base_1ga897e0402cc8b441489deff693575a444) | | +| [`_name`](#group__base_1ga36f066b53b2c1afe8928bfd882011fbb) | | +| [`_level`](#group__base_1gad78b4c8b505efe909158ee7e52828a15) | | +| [`_timeFormat`](#group__base_1gaf59b0b2da184acb4d50f9bba96221d70) | | +| [`_filter`](#group__base_1ga40e25f529270dfc4ec4a40b14e514a02) | | + +--- + +#### LogChannel + +```cpp +LogChannel(std::string name, Level level, std::string timeFormat) +``` -#### `public inline Signal(const `[`Signal`](#classscy_1_1Signal)` & r)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `std::string` | | +| `level` | `Level` | | +| `timeFormat` | `std::string` | | -Copy constructor. +--- +#### ~LogChannel +```cpp +virtual ~LogChannel() = default +``` -#### `public inline `[`Signal`](#classscy_1_1Signal)` & operator=(const `[`Signal`](#classscy_1_1Signal)` & r)` +--- -Assignment operator. +#### write +```cpp +virtual void write(const LogStream & stream) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `stream` | `const LogStream &` | | -# class `scy::Singleton` +--- +#### write +```cpp +virtual void write(std::string message, Level level, std::string realm) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `message` | `std::string` | | +| `level` | `Level` | | +| `realm` | `std::string` | | -This is a helper template class for managing singleton objects allocated on the heap. +--- -## Summary +#### format - Members | Descriptions ---------------------------------|--------------------------------------------- -`public inline Singleton()` | Creates the [Singleton](./doc/api-base.md#classscy_1_1Singleton) wrapper. -`public inline ~Singleton()` | -`public inline S * get()` | -`public inline S * swap(S * newPtr)` | -`public inline void destroy()` | Destroys the managed singleton instance. +```cpp +virtual void format(const LogStream & stream, std::ostream & ost) +``` -## Members +| Parameter | Type | Description | +|-----------|------|-------------| +| `stream` | `const LogStream &` | | +| `ost` | `std::ostream &` | | -#### `public inline Singleton()` +--- -Creates the [Singleton](#classscy_1_1Singleton) wrapper. +#### name +```cpp +inline std::string name() const +``` +--- -#### `public inline ~Singleton()` +#### level +```cpp +inline Level level() const +``` +--- -Destroys the [Singleton](#classscy_1_1Singleton) wrapper and the managed singleton instance it holds. +#### timeFormat -#### `public inline S * get()` +```cpp +inline std::string timeFormat() const +``` +--- +#### setLevel -Returns a pointer to the singleton object hold by the [Singleton](#classscy_1_1Singleton). The first call to get on a nullptr singleton will instantiate the singleton. +```cpp +inline void setLevel(Level level) +``` -#### `public inline S * swap(S * newPtr)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `level` | `Level` | | +--- +#### setTimeFormat -Swaps the old pointer with the new one and returns the old instance. +```cpp +inline void setTimeFormat(std::string format) +``` -#### `public inline void destroy()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `format` | `std::string` | | -Destroys the managed singleton instance. +--- +#### setFilter +```cpp +inline void setFilter(std::string filter) +``` -# class `scy::State` +| Parameter | Type | Description | +|-----------|------|-------------| +| `filter` | `std::string` | | +--- +#### _name +```cpp +std::string _name +``` -[State](#classscy_1_1State) class for state machines. +--- -This class defined the state for a state machine, and should be extended and passed to implementations of the `[Stateful](#classscy_1_1Stateful)` template. +#### _level -For an example -**See also**: [PacketStreamState](#structscy_1_1PacketStreamState) +```cpp +Level _level +``` -## Summary +--- - Members | Descriptions ---------------------------------|--------------------------------------------- -`public State(ID id)` | -`public State(const `[`State`](#classscy_1_1State)` & that)` | -`public `[`State`](#classscy_1_1State)` & operator=(const `[`State`](#classscy_1_1State)` & that)` | -`public inline virtual ~State()` | -`public ID id() const` | -`public void set(ID id)` | -`public virtual std::string str(ID id) const` | -`public virtual std::string toString() const` | -`public bool equals(ID id) const` | -`public bool between(ID lid,ID rid) const` | -`public inline bool operator==(const `[`State`](#classscy_1_1State)` & that)` | -`public inline bool operator==(const State::ID & that)` | -`protected std::atomic< ID > _id` | +#### _timeFormat -## Members +```cpp +std::string _timeFormat +``` -#### `public State(ID id)` +--- +#### _filter +```cpp +std::string _filter +``` +## ConsoleChannel +> **Extends:** `scy::LogChannel` +> **Defined in:** `logger.h` -#### `public State(const `[`State`](#classscy_1_1State)` & that)` +### Members +| Name | Description | +|------|-------------| +| [`ConsoleChannel`](#group__base_1ga53bca70103bf1cc5384c49d5e8f2ccdc) | | +| [`~ConsoleChannel`](#group__base_1gaadb6451f2e487ad09f037f89bf964d46) | | +| [`write`](#group__base_1ga0929915fd0556254dcdaa1d49cc34758) | | +--- +#### ConsoleChannel +```cpp +ConsoleChannel(std::string name, Level level, std::string timeFormat) +``` -#### `public `[`State`](#classscy_1_1State)` & operator=(const `[`State`](#classscy_1_1State)` & that)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `std::string` | | +| `level` | `Level` | | +| `timeFormat` | `std::string` | | +--- +#### ~ConsoleChannel +```cpp +virtual ~ConsoleChannel() = default +``` +--- -#### `public inline virtual ~State()` +#### write +```cpp +virtual void write(const LogStream & stream) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `stream` | `const LogStream &` | | +## FileChannel +> **Extends:** `scy::LogChannel` +> **Defined in:** `logger.h` -#### `public ID id() const` +### Members +| Name | Description | +|------|-------------| +| [`FileChannel`](#group__base_1gab4f92ce254f7bf2252fba993ea320429) | | +| [`~FileChannel`](#group__base_1gaeb8131af118653a2b09bca46660fc2b1) | | +| [`write`](#group__base_1gabf845ee5a13c4e4662566764d7cc2d0f) | | +| [`setPath`](#group__base_1ga2ae18223e682fc74ced9f079b9473f64) | | +| [`path`](#group__base_1ga4399a5666e22bab99beba14926b6db56) | | +| [`open`](#group__base_1gac96f91229ba9e1d0566f6402aae8c294) | | +| [`close`](#group__base_1ga69982cecf5699940fd17ef9852d88ea8) | | +| [`_fstream`](#group__base_1ga4f6cafce9cad0d449da791f4a8ff6416) | | +| [`_path`](#group__base_1gaee5340f4b20b5361e05e84cb3eca9fd3) | | +--- +#### FileChannel +```cpp +FileChannel(std::string name, std::string path, Level level, std::string timeFormat) +``` -#### `public void set(ID id)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `std::string` | | +| `path` | `std::string` | | +| `level` | `Level` | | +| `timeFormat` | `std::string` | | +--- +#### ~FileChannel +```cpp +virtual ~FileChannel() +``` +--- -#### `public virtual std::string str(ID id) const` +#### write +```cpp +virtual void write(const LogStream & stream) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `stream` | `const LogStream &` | | +--- +#### setPath -#### `public virtual std::string toString() const` +```cpp +void setPath(const std::string & path) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `path` | `const std::string &` | | +--- +#### path +```cpp +std::string path() const +``` -#### `public bool equals(ID id) const` +--- +#### open +```cpp +virtual void open() +``` +--- +#### close -#### `public bool between(ID lid,ID rid) const` +```cpp +virtual void close() +``` +--- +#### _fstream +```cpp +std::ofstream _fstream +``` +--- -#### `public inline bool operator==(const `[`State`](#classscy_1_1State)` & that)` +#### _path +```cpp +std::string _path +``` +## RotatingFileChannel + +> **Extends:** `scy::LogChannel` +> **Defined in:** `logger.h` + +### Members + +| Name | Description | +|------|-------------| +| [`RotatingFileChannel`](#group__base_1ga84f26cb25b2c0891d75871b6716168a3) | | +| [`~RotatingFileChannel`](#group__base_1gaac06718485f99a815fea1794918add66) | | +| [`write`](#group__base_1gad7ae8aa634cf62b9218c1db4a9e94036) | | +| [`rotate`](#group__base_1ga6987d2d74c5bf0d806b910262dafc18b) | | +| [`dir`](#group__base_1gad734c262397421ebe099d6e721cc1825) | | +| [`filename`](#group__base_1gadd1ee0bd5e6a7b8e3c81dcb7d599e0a7) | | +| [`rotationInterval`](#group__base_1ga9507632f6b9471837ebcf1220ce9bee6) | | +| [`setDir`](#group__base_1ga2cfa616f69cd79ace910e9b67658e70e) | | +| [`setExtension`](#group__base_1ga394e6a3fee41f0629b5101d185a4197c) | | +| [`setRotationInterval`](#group__base_1gadeb5c1ec6bed59029009039ebe623ef0) | | +| [`_fstream`](#group__base_1ga4f6cc715458e53fae26d2d7562e3e8b5) | | +| [`_dir`](#group__base_1gaccead79b2337cea1e03927f09cc6eb2f) | | +| [`_filename`](#group__base_1ga997dcf71593d8450e25f5f33b1e41dd4) | | +| [`_extension`](#group__base_1gacbb348e159c2da3ce607710957a39bfb) | | +| [`_rotationInterval`](#group__base_1ga6fcee513ef9e7648ca8b83691fcf8fe6) | The log rotation interval in seconds. | +| [`_rotatedAt`](#group__base_1gad6355b7ebfeeb0605c24c4934d45e912) | The time the log was last rotated. | + +--- + +#### RotatingFileChannel + +```cpp +RotatingFileChannel(std::string name, std::string dir, Level level, std::string extension, int rotationInterval, std::string timeFormat) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `std::string` | | +| `dir` | `std::string` | | +| `level` | `Level` | | +| `extension` | `std::string` | | +| `rotationInterval` | `int` | | +| `timeFormat` | `std::string` | | +--- -#### `public inline bool operator==(const State::ID & that)` +#### ~RotatingFileChannel +```cpp +virtual ~RotatingFileChannel() +``` +--- +#### write +```cpp +virtual void write(const LogStream & stream) +``` -#### `protected std::atomic< ID > _id` +| Parameter | Type | Description | +|-----------|------|-------------| +| `stream` | `const LogStream &` | | +--- +#### rotate +```cpp +virtual void rotate() +``` +--- -# class `scy::Stateful` +#### dir +```cpp +inline std::string dir() const +``` +--- +#### filename -[State](#classscy_1_1State) machine implementation. +```cpp +inline std::string filename() const +``` -For an example -**See also**: [PacketStream](#classscy_1_1PacketStream) +--- +#### rotationInterval -#### Parameters -* `The` derived `[State](#classscy_1_1State)` type. +```cpp +inline int rotationInterval() const +``` -## Summary +--- - Members | Descriptions ---------------------------------|--------------------------------------------- -`public `[`Signal`](#classscy_1_1Signal)< void(void *, T &, const T &)`> StateChange` | Signals when the state changes. -`public inline Stateful()` | -`public inline virtual ~Stateful()` | -`public inline virtual bool stateEquals(typename T::ID id) const` | -`public inline virtual bool stateBetween(typename T::ID lid,typename T::ID rid) const` | -`public inline virtual T & state()` | -`public inline virtual const T state() const` | -`protected T _state` | -`protected inline virtual bool beforeStateChange(const T & state)` | -`protected inline virtual void onStateChange(T &,const T &)` | Override to handle post state change logic. -`protected inline virtual bool setState(void * sender,typename T::ID id)` | -`protected inline virtual bool setState(void * sender,const T & state)` | +#### setDir -## Members +```cpp +inline void setDir(std::string dir) +``` -#### `public `[`Signal`](#classscy_1_1Signal)< void(void *, T &, const T &)`> StateChange` +| Parameter | Type | Description | +|-----------|------|-------------| +| `dir` | `std::string` | | -Signals when the state changes. +--- +#### setExtension +```cpp +inline void setExtension(std::string ext) +``` -#### `public inline Stateful()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `ext` | `std::string` | | +--- +#### setRotationInterval +```cpp +inline void setRotationInterval(int interval) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `interval` | `int` | | -#### `public inline virtual ~Stateful()` +--- +#### _fstream +```cpp +std::unique_ptr< std::ofstream > _fstream +``` +--- +#### _dir -#### `public inline virtual bool stateEquals(typename T::ID id) const` +```cpp +std::string _dir +``` +--- +#### _filename +```cpp +std::string _filename +``` +--- -#### `public inline virtual bool stateBetween(typename T::ID lid,typename T::ID rid) const` +#### _extension +```cpp +std::string _extension +``` +--- +#### _rotationInterval +```cpp +int _rotationInterval +``` -#### `public inline virtual T & state()` +The log rotation interval in seconds. +--- +#### _rotatedAt +```cpp +time_t _rotatedAt +``` +The time the log was last rotated. -#### `public inline virtual const T state() const` +## IPacket +> **Subclasses:** `scy::FlagPacket`, `scy::RawPacket`, `scy::smpl::Message`, `scy::sockio::Packet`, `scy::stun::Message` +> **Defined in:** `packet.h` +The basic packet type which is passed around the LibSourcey system. [IPacket](#classscy_1_1IPacket) can be extended for each protocol to enable polymorphic processing and callbacks using [PacketStream](#classscy_1_1PacketStream) and friends. +### Members + +| Name | Description | +|------|-------------| +| [`IPacket`](#group__base_1ga18264ec6de7582fc121a467e3ea7183c) | | +| [`IPacket`](#group__base_1gaadf363596a491bcfa114040d3e5f1ce5) | | +| [`operator=`](#group__base_1gae6bef3dd34fec6b60b3f399d7646fee6) | | +| [`clone`](#group__base_1ga55fb6c9a605afc8f788d517db17f5c94) | | +| [`~IPacket`](#group__base_1gafc24256c3b16380ba4556a82ea721971) | | +| [`read`](#group__base_1ga17dec4307d132f37add42674fbfc18f1) | Read/parse to the packet from the given input buffer. The number of bytes read is returned. | +| [`write`](#group__base_1gabdcb765c58d74be25e190680bf7483d6) | Copy/generate to the packet given output buffer. The number of bytes written can be obtained from the buffer. | +| [`size`](#group__base_1ga2fe3e4a722ab42218066bd6ae91bf336) | The size of the packet in bytes. | +| [`hasData`](#group__base_1ga4fc1159e6f71b7231f8de2220f6f0a83) | | +| [`data`](#group__base_1gaf62b3af8177804474ca7270c44a08809) | The packet data pointer for buffered packets. | +| [`constData`](#group__base_1ga459a655ebf7651ddf0f7c5ebf8d3d6dc) | The const packet data pointer for buffered packets. | +| [`className`](#group__base_1ga7fbf025db89783335cb7296e35531ccb) | | +| [`print`](#group__base_1gad23b82ac26af7d46ca3828f1116ee9d7) | | +| [`source`](#group__base_1gad3f9d5b27d476a5e693dd752036e2aa9) | Packet source pointer reference which enables processors along the signal chain can determine the packet origin. Often a subclass of PacketStreamSource. | +| [`opaque`](#group__base_1gaf6b50b2656e3dfc60907b366b35fb1c0) | Optional client data pointer. This pointer is not managed by the packet. | +| [`info`](#group__base_1gaa3bc87e58c6c9b2dce8a4e8a661236d0) | Optional extra information about the packet. | +| [`flags`](#group__base_1ga9eb92d88fc9705ff304ddd382c7588fa) | Provides basic information about the packet. | + +--- + +#### IPacket + +```cpp +inline IPacket(void * source, void * opaque, std::unique_ptr< IPacketInfo > info, unsigned flags) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `source` | `void *` | | +| `opaque` | `void *` | | +| `info` | `std::unique_ptr< IPacketInfo >` | | +| `flags` | `unsigned` | | -#### `protected T _state` +--- +#### IPacket +```cpp +inline IPacket(const IPacket & r) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `r` | `const IPacket &` | | +--- -#### `protected inline virtual bool beforeStateChange(const T & state)` +#### operator= +```cpp +inline IPacket & operator=(const IPacket & r) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `r` | `const IPacket &` | | -Override to handle pre state change logic. Return false to prevent state change. +--- -#### `protected inline virtual void onStateChange(T &,const T &)` +#### clone -Override to handle post state change logic. +```cpp +IPacket * clone() const +``` +--- +#### ~IPacket -#### `protected inline virtual bool setState(void * sender,typename T::ID id)` +```cpp +virtual ~IPacket() = default +``` +--- +#### read -Sets the state and sends the state signal if the state change was successful. +```cpp +ssize_t read(const ConstBuffer &) +``` -#### `protected inline virtual bool setState(void * sender,const T & state)` +Read/parse to the packet from the given input buffer. The number of bytes read is returned. +--- +#### write -Sets the state and sends the state signal if the state change was successful. +```cpp +void write(Buffer &) const +``` -# class `scy::StopPropagation` +Copy/generate to the packet given output buffer. The number of bytes written can be obtained from the buffer. -``` -class scy::StopPropagation - : public exception -``` +Todo: It may be prefferable to use our pod types here instead of buffer input, but the current codebase requires that the buffer be dynamically resizable for some protocols... -Exception to break out of the current [Signal](#classscy_1_1Signal) callback scope. +--- +#### size +```cpp +virtual inline size_t size() const +``` -## Summary +The size of the packet in bytes. - Members | Descriptions ---------------------------------|--------------------------------------------- -`public inline virtual ~StopPropagation()` | +This is the nember of bytes that will be written on a call to [write()](#group__base_1gabdcb765c58d74be25e190680bf7483d6), but may not be the number of bytes that will be consumed by [read()](#group__base_1ga17dec4307d132f37add42674fbfc18f1). -## Members +--- -#### `public inline virtual ~StopPropagation()` +#### hasData +```cpp +virtual inline bool hasData() const +``` +--- +#### data +```cpp +virtual inline char * data() const +``` -# class `scy::Stopwatch` +The packet data pointer for buffered packets. +--- +#### constData +```cpp +virtual inline const void * constData() const +``` -A simple facility to measure time intervals with microsecond resolution. +The const packet data pointer for buffered packets. -The [Stopwatch](#classscy_1_1Stopwatch) uses the current system time, so if the system time changes the measured time will be incorrect. +--- -## Summary +#### className - Members | Descriptions ---------------------------------|--------------------------------------------- -`public Stopwatch()` | -`public ~Stopwatch()` | -`public void start()` | Starts (or restarts) the stopwatch. -`public void stop()` | Stops or pauses the stopwatch. -`public void reset()` | Resets the stopwatch. -`public void restart()` | Resets and starts the stopwatch. -`public `[`Timestamp::TimeDiff`](#group__base_1ga9f06831e4e9b9cbc6f061cc61dc91fd0)` elapsed() const` | -`public int elapsedSeconds() const` | -`public int elapsedMilliseconds() const` | +```cpp +const char * className() const +``` -## Members +--- -#### `public Stopwatch()` +#### print +```cpp +virtual inline void print(std::ostream & os) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `os` | `std::ostream &` | | +--- +#### source -#### `public ~Stopwatch()` +```cpp +void * source +``` +Packet source pointer reference which enables processors along the signal chain can determine the packet origin. Often a subclass of PacketStreamSource. +--- +#### opaque +```cpp +void * opaque +``` -#### `public void start()` +Optional client data pointer. This pointer is not managed by the packet. -Starts (or restarts) the stopwatch. +--- +#### info +```cpp +std::unique_ptr< IPacketInfo > info +``` -#### `public void stop()` +Optional extra information about the packet. -Stops or pauses the stopwatch. +--- +#### flags + +```cpp +Bitwise flags +``` +Provides basic information about the packet. -#### `public void reset()` +## FlagPacket -Resets the stopwatch. +> **Extends:** `scy::IPacket` +> **Defined in:** `packet.h` +Packet for sending bitwise flags along the packet stream. +### Members -#### `public void restart()` +| Name | Description | +|------|-------------| +| [`FlagPacket`](#group__base_1ga653e36ffe31957974caf6d74eac86ada) | | +| [`clone`](#group__base_1ga9787ee63af30cbd45b90120954dea731) | | +| [`FlagPacket`](#group__base_1ga2fe2b6ce02c8780ccb958867d7b40f68) | | +| [`~FlagPacket`](#group__base_1ga2533d0666de1de52036a90928753baab) | | +| [`read`](#group__base_1gae9244ad486c645bf78967acf967567e7) | Read/parse to the packet from the given input buffer. The number of bytes read is returned. | +| [`write`](#group__base_1ga47591bd1b58f3f6b996dc968144bc855) | Copy/generate to the packet given output buffer. The number of bytes written can be obtained from the buffer. | +| [`className`](#group__base_1ga38299df2b1e45317582db01f127a7d33) | | -Resets and starts the stopwatch. +--- +#### FlagPacket +```cpp +inline FlagPacket(unsigned flags) +``` -#### `public `[`Timestamp::TimeDiff`](#group__base_1ga9f06831e4e9b9cbc6f061cc61dc91fd0)` elapsed() const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `flags` | `unsigned` | | +--- +#### clone -Returns the elapsed time in microseconds since the stopwatch started. +```cpp +virtual inline IPacket * clone() const +``` -#### `public int elapsedSeconds() const` +--- +#### FlagPacket +```cpp +inline FlagPacket(const FlagPacket & that) +``` -Returns the number of seconds elapsed since the stopwatch started. +| Parameter | Type | Description | +|-----------|------|-------------| +| `that` | `const FlagPacket &` | | -#### `public int elapsedMilliseconds() const` +--- +#### ~FlagPacket +```cpp +virtual ~FlagPacket() = default +``` -Returns the number of milliseconds elapsed since the stopwatch started. +--- -# class `scy::Stream` +#### read +```cpp +virtual inline ssize_t read(const ConstBuffer &) ``` -class scy::Stream - : public scy::uv::Handle< T > -``` -Basic stream type for sockets and pipes. +Read/parse to the packet from the given input buffer. The number of bytes read is returned. + +--- +#### write +```cpp +virtual inline void write(Buffer &) const +``` -## Summary +Copy/generate to the packet given output buffer. The number of bytes written can be obtained from the buffer. - Members | Descriptions ---------------------------------|--------------------------------------------- -`public `[`Signal`](#classscy_1_1Signal)< void(const char *, const int &)`> Read` | [Signal](./doc/api-base.md#classscy_1_1Signal) the notifies when data is available for read. -`public inline Stream(uv::Loop * loop)` | -`public inline virtual ~Stream()` | -`public inline virtual void close()` | -`public inline bool shutdown()` | -`public inline bool write(const char * data,size_t len)` | -`public inline bool write(const char * data,size_t len,uv_stream_t * send)` | -`public inline virtual bool closed() const` | Return true if the native stream handle is closed. -`public inline uv_stream_t * stream()` | Return the uv_stream_t pointer. -`protected `[`Buffer`](#group__base_1gab10b36b080deb583ed703fca6b63ffdd)` _buffer` | -`protected bool _started` | -`protected inline virtual bool readStart()` | -`protected inline virtual bool readStop()` | -`protected inline virtual void onRead(const char * data,size_t len)` | +Todo: It may be prefferable to use our pod types here instead of buffer input, but the current codebase requires that the buffer be dynamically resizable for some protocols... -## Members +--- -#### `public `[`Signal`](#classscy_1_1Signal)< void(const char *, const int &)`> Read` +#### className -[Signal](#classscy_1_1Signal) the notifies when data is available for read. +```cpp +virtual inline const char * className() const +``` +## RawPacket +> **Extends:** `scy::IPacket` +> **Subclasses:** `scy::av::MediaPacket`, `scy::net::SocketPacket` +> **Defined in:** `packet.h` -#### `public inline Stream(uv::Loop * loop)` +[RawPacket](#classscy_1_1RawPacket) is the default data packet type which consists of an optionally managed char pointer and a size value. +### Members + +| Name | Description | +|------|-------------| +| [`RawPacket`](#group__base_1ga8bbe5592ab4c6990427a9f5d0aaacd56) | Construct with borrowed (non-owning) buffer. | +| [`RawPacket`](#group__base_1ga29a1c6212a4b355ea9f0af2fe2df5540) | Construct with const data (copied, owning). | +| [`RawPacket`](#group__base_1ga8e345ba779f5ac06df86e2a6c7ec2ead) | Copy constructor (always copies data). | +| [`~RawPacket`](#group__base_1ga7323a9ff445c569f2fdbab4c3eca348d) | | +| [`clone`](#group__base_1ga4df70dab414133565b2ca3491ba7bfa4) | | +| [`copyData`](#group__base_1ga45af5d87430a9c3f899dbbfedd5e6997) | | +| [`read`](#group__base_1ga27d4b98e4dabc04b7fe1986a9e1c03bb) | Read/parse to the packet from the given input buffer. The number of bytes read is returned. | +| [`write`](#group__base_1ga8d7ce1ab0cac231c74c0daaa0c01fcaf) | Copy/generate to the packet given output buffer. The number of bytes written can be obtained from the buffer. | +| [`data`](#group__base_1ga699d6504e49924674c57d4f028aa162c) | The packet data pointer for buffered packets. | +| [`size`](#group__base_1ga052fc05cf75fe7162a9fe9c4923d11a5) | The size of the packet in bytes. | +| [`className`](#group__base_1ga84508aba2ea50772f03fc76bbb97fa3d) | | +| [`ownsBuffer`](#group__base_1gad11ad552cf59a9bf88d54644bd1c0259) | | +| [`_data`](#group__base_1ga846efb5bb786079552a8d91617ddf1d2) | | +| [`_size`](#group__base_1ga236b72d805511afae7400d6543df19fb) | | +| [`_owned`](#group__base_1gaf735f77b6cce15dbf19a3dd4ca9b7470) | | + +--- + +#### RawPacket + +```cpp +inline RawPacket(char * data, size_t size, unsigned flags, void * source, void * opaque, std::unique_ptr< IPacketInfo > info) +``` +Construct with borrowed (non-owning) buffer. +| Parameter | Type | Description | +|-----------|------|-------------| +| `data` | `char *` | | +| `size` | `size_t` | | +| `flags` | `unsigned` | | +| `source` | `void *` | | +| `opaque` | `void *` | | +| `info` | `std::unique_ptr< IPacketInfo >` | | +--- -#### `public inline virtual ~Stream()` +#### RawPacket +```cpp +inline RawPacket(const char * data, size_t size, unsigned flags, void * source, void * opaque, std::unique_ptr< IPacketInfo > info) +``` +Construct with const data (copied, owning). +| Parameter | Type | Description | +|-----------|------|-------------| +| `data` | `const char *` | | +| `size` | `size_t` | | +| `flags` | `unsigned` | | +| `source` | `void *` | | +| `opaque` | `void *` | | +| `info` | `std::unique_ptr< IPacketInfo >` | | +--- -#### `public inline virtual void close()` +#### RawPacket +```cpp +inline RawPacket(const RawPacket & that) +``` +Copy constructor (always copies data). -Closes and resets the stream handle. This will close the active socket/pipe and destroy the handle. +| Parameter | Type | Description | +|-----------|------|-------------| +| `that` | `const RawPacket &` | | -If the stream is already closed this call will have no side-effects. +--- -#### `public inline bool shutdown()` +#### ~RawPacket +```cpp +virtual ~RawPacket() = default +``` +--- -Sends a shutdown packet to the connected peer. Return true if the shutdown packet was sent. +#### clone -#### `public inline bool write(const char * data,size_t len)` +```cpp +virtual inline IPacket * clone() const +``` +--- +#### copyData -Writes data to the stream. +```cpp +virtual inline void copyData(const void * data, size_t size) +``` -Return false if the underlying socket is closed. This method does not throw an exception. +| Parameter | Type | Description | +|-----------|------|-------------| +| `data` | `const void *` | | +| `size` | `size_t` | | -#### `public inline bool write(const char * data,size_t len,uv_stream_t * send)` +--- +#### read +```cpp +virtual inline ssize_t read(const ConstBuffer &) +``` -Write data to the target stream. +Read/parse to the packet from the given input buffer. The number of bytes read is returned. -This method is only valid for IPC streams. +--- -#### `public inline virtual bool closed() const` +#### write -Return true if the native stream handle is closed. +```cpp +virtual inline void write(Buffer &) const +``` +Copy/generate to the packet given output buffer. The number of bytes written can be obtained from the buffer. +Todo: It may be prefferable to use our pod types here instead of buffer input, but the current codebase requires that the buffer be dynamically resizable for some protocols... -#### `public inline uv_stream_t * stream()` +--- -Return the uv_stream_t pointer. +#### data +```cpp +virtual inline char * data() const +``` +The packet data pointer for buffered packets. -#### `protected `[`Buffer`](#group__base_1gab10b36b080deb583ed703fca6b63ffdd)` _buffer` +--- +#### size +```cpp +virtual inline size_t size() const +``` +The size of the packet in bytes. +This is the nember of bytes that will be written on a call to [write()](#group__base_1ga8d7ce1ab0cac231c74c0daaa0c01fcaf), but may not be the number of bytes that will be consumed by [read()](#group__base_1ga27d4b98e4dabc04b7fe1986a9e1c03bb). -#### `protected bool _started` +--- +#### className +```cpp +virtual inline const char * className() const +``` +--- +#### ownsBuffer -#### `protected inline virtual bool readStart()` +```cpp +inline bool ownsBuffer() const +``` +--- +#### _data +```cpp +char * _data +``` +--- -#### `protected inline virtual bool readStop()` +#### _size +```cpp +size_t _size +``` +--- +#### _owned +```cpp +std::unique_ptr< char[]> _owned +``` -#### `protected inline virtual void onRead(const char * data,size_t len)` +## IPacketCreationStrategy +> **Subclasses:** `scy::PacketCreationStrategy< PacketT >` +> **Defined in:** `packetfactory.h` +### Members +| Name | Description | +|------|-------------| +| [`IPacketCreationStrategy`](#group__base_1ga50f56327263cb8d8ee572496ea9a7a3b) | | +| [`~IPacketCreationStrategy`](#group__base_1gaaefe166ced07d6decb2b9f8072e12d1b) | | +| [`create`](#group__base_1gae4853a278a11b59b96d02789a78a3ba7) | | +| [`priority`](#group__base_1gaba808d34edb6272253418c30210f25ec) | | +| [`compareProiroty`](#group__base_1ga66ee4fd6b354dd7f97e954a03af23c13) | | +--- -# class `scy::StreamWriter` +#### IPacketCreationStrategy +```cpp +inline IPacketCreationStrategy() ``` -class scy::StreamWriter - : public scy::PacketProcessor -``` +--- +#### ~IPacketCreationStrategy -Packet stream writer class. +```cpp +virtual ~IPacketCreationStrategy() = default +``` -This class can be connected to a `[PacketStream](#classscy_1_1PacketStream)` to write output to any class that derives from `std::ostream`. It's most regularly used for writing output files. +--- + +#### create -## Summary +```cpp +IPacket * create(const ConstBuffer & buffer, size_t & nread) const +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `buffer` | `const ConstBuffer &` | | +| `nread` | `size_t &` | | - Members | Descriptions ---------------------------------|--------------------------------------------- -`public `[`PacketSignal`](#group__base_1ga3ffb5bda6133fac97f3bed2b567b9b6a)` emitter` | -`public inline StreamWriter(std::ostream * stream)` | -`public inline virtual ~StreamWriter()` | -`public inline virtual void process(`[`IPacket`](#classscy_1_1IPacket)` & packet)` | -`public template`
`inline StreamT & stream()` | -`public inline virtual void onStreamStateChange(const `[`PacketStreamState`](#structscy_1_1PacketStreamState)` &)` | -`public inline std::ostream & stream()` | -`protected std::ostream * _ostream` | +--- -## Members +#### priority -#### `public `[`PacketSignal`](#group__base_1ga3ffb5bda6133fac97f3bed2b567b9b6a)` emitter` +```cpp +int priority() const +``` +--- +#### compareProiroty +```cpp +static inline bool compareProiroty(const IPacketCreationStrategy * l, const IPacketCreationStrategy * r) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `l` | `const IPacketCreationStrategy *` | | +| `r` | `const IPacketCreationStrategy *` | | -#### `public inline StreamWriter(std::ostream * stream)` +## PacketFactory +> **Defined in:** `packetfactory.h` +### Members +| Name | Description | +|------|-------------| +| [`PacketFactory`](#group__base_1gac108d58054dccbf3736c7ecb2a968d58) | | +| [`~PacketFactory`](#group__base_1ga803341e3fb9567e3017ad1774acda0fd) | | +| [`registerPacketType`](#group__base_1ga362ade3e31ecca2015cdb85cec6c9e4f) | | +| [`unregisterPacketType`](#group__base_1ga6e1ee51199e2b5241afb8f872120f48a) | | +| [`registerStrategy`](#group__base_1gaec4ee2b41f920d44c5e3276992e16a48) | | +| [`unregisterStrategy`](#group__base_1gabdbc79c8ee73048b8cff7ece2f465b30) | | +| [`types`](#group__base_1gac5f739f1472bd97d68629ceadd27c9c7) | | +| [`types`](#group__base_1ga78324767a673d825a34e6b6e02a29036) | | +| [`onPacketCreated`](#group__base_1ga86ec412fa2a46187ddf8154cab0afd5c) | | +| [`createPacket`](#group__base_1ga63cd252d598c9a379bb9de996d450f4d) | | +| [`_types`](#group__base_1gac2bbd50d6da749659cc25265ba3b13e6) | | +--- -#### `public inline virtual ~StreamWriter()` +#### PacketFactory +```cpp +inline PacketFactory() +``` +--- +#### ~PacketFactory +```cpp +virtual inline ~PacketFactory() +``` -#### `public inline virtual void process(`[`IPacket`](#classscy_1_1IPacket)` & packet)` +--- +#### registerPacketType +```cpp +template inline void registerPacketType(int priority) +``` -This method performs processing on the given packet and emits the result. +| Parameter | Type | Description | +|-----------|------|-------------| +| `priority` | `int` | | -Note: If packet processing is async (the packet is not in the current thread scope) then packet data must be copied. Copied data can be freed directly aFter the async call to emit() the outgoing packet. +--- -#### `public template`
`inline StreamT & stream()` +#### unregisterPacketType +```cpp +template inline void unregisterPacketType() +``` +--- +#### registerStrategy +```cpp +template inline void registerStrategy(int priority) +``` -#### `public inline virtual void onStreamStateChange(const `[`PacketStreamState`](#structscy_1_1PacketStreamState)` &)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `priority` | `int` | | +--- +#### unregisterStrategy -Called by the [PacketStream](#classscy_1_1PacketStream) to notify when the internal [Stream](#classscy_1_1Stream) state changes. On receiving the Stopped state, it is the responsibility of the adapter to have ceased all outgoing packet transmission, especially in multi-thread scenarios. +```cpp +template inline void unregisterStrategy() +``` -#### `public inline std::ostream & stream()` +--- +#### types +```cpp +inline PacketCreationStrategyList & types() +``` +--- +#### types -#### `protected std::ostream * _ostream` +```cpp +inline PacketCreationStrategyList types() const +``` +--- +#### onPacketCreated +```cpp +virtual inline bool onPacketCreated(IPacket *) +``` +--- -# class `scy::Synchronizer` +#### createPacket +```cpp +virtual inline IPacket * createPacket(const ConstBuffer & buffer, size_t & nread) ``` -class scy::Synchronizer - : public scy::Runner -``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `buffer` | `const ConstBuffer &` | | +| `nread` | `size_t &` | | +--- -[Synchronizer](#classscy_1_1Synchronizer) enables any thread to communicate with the associated event loop via synchronized callbacks. +#### _types -This class inherits the `[Runner](#classscy_1_1Runner)` interface and may be used with any implementation that's powered by an asynchronous `[Runner](#classscy_1_1Runner)`. +```cpp +PacketCreationStrategyList _types +``` -## Summary +## ThreadedStreamReader - Members | Descriptions ---------------------------------|--------------------------------------------- -`public Synchronizer(uv::Loop * loop)` | Create the synchronization context the given event loop. -`public Synchronizer(std::function< void()> target,uv::Loop * loop)` | -`public template`
`inline explicit Synchronizer(Function && func,Args &&... args,uv::Loop * loop)` | Create the synchronization context the given event loop and method. -`public virtual ~Synchronizer()` | Destructor. -`public void post()` | -`public template`
`inline void start(Function && func,Args &&... args)` | Start the synchronizer with the given callback. -`public virtual void start(std::function< void()> func)` | Start the synchronizer with the given callback function. -`public virtual void cancel()` | -`public virtual void close()` | -`public `[`uv::Handle`](#classscy_1_1uv_1_1Handle)`< uv_async_t > & handle()` | -`protected `[`uv::Handle`](./doc/api-uv.md#classscy_1_1uv_1_1Handle)`< uv_async_t > _handle` | -`protected virtual bool async() const` | +> **Extends:** `scy::PacketStreamAdapter`, `scy::basic::Startable` +> **Defined in:** `packetio.h` -## Members +Threaded stream reader class. -#### `public Synchronizer(uv::Loop * loop)` +This class can be connected to a `[PacketStream](#classscy_1_1PacketStream)` to read input from any class that derives from `std::istream`. It's most regularly used for reading input files. -Create the synchronization context the given event loop. +### Members +| Name | Description | +|------|-------------| +| [`ThreadedStreamReader`](#group__base_1ga145262d7cc0e8082313771c78d719a93) | | +| [`~ThreadedStreamReader`](#group__base_1ga39fe2eb7ff89764e1bdea0dd6c391b09) | | +| [`start`](#group__base_1ga199b9b2a213b92b4e81a735d457f82ac) | | +| [`stop`](#group__base_1ga447294977952a774ce6abafed560c3d7) | | +| [`stream`](#group__base_1ga8887679c8111b21d63686450bb62eead) | | +| [`stream`](#group__base_1gaaa188157fe727154da089d04ff924aa0) | | +| [`emitter`](#group__base_1ga567cb288d73e8913f61ba6d76008b22f) | | +| [`_runner`](#group__base_1ga209b1d5e46545ea7ed88bc0f0492f22d) | | +| [`_istream`](#group__base_1gaf859c1452a438a01f7faf1771f4f8463) | | +--- -#### `public Synchronizer(std::function< void()> target,uv::Loop * loop)` +#### ThreadedStreamReader +```cpp +inline ThreadedStreamReader(std::istream * is) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `is` | `std::istream *` | | -Create the synchronization context the given event loop and method. The target method will be called from the event loop context. +--- -#### `public template`
`inline explicit Synchronizer(Function && func,Args &&... args,uv::Loop * loop)` +#### ~ThreadedStreamReader -Create the synchronization context the given event loop and method. +```cpp +inline ~ThreadedStreamReader() +``` +--- +#### start -#### `public virtual ~Synchronizer()` +```cpp +virtual inline void start() +``` -Destructor. +--- +#### stop +```cpp +virtual inline void stop() +``` -#### `public void post()` +--- +#### stream +```cpp +template inline StreamT & stream() +``` -Send a synchronization request to the event loop. Call this each time you want the target method called synchronously. The synchronous method will be called on next iteration. This is not atomic, so do not expect a callback for every request. +--- -#### `public template`
`inline void start(Function && func,Args &&... args)` +#### stream -Start the synchronizer with the given callback. +```cpp +inline std::istream & stream() +``` +--- +#### emitter -#### `public virtual void start(std::function< void()> func)` +```cpp +PacketSignal emitter +``` -Start the synchronizer with the given callback function. +--- + +#### _runner + +```cpp +Thread _runner +``` +--- +#### _istream -#### `public virtual void cancel()` +```cpp +std::istream * _istream +``` +## StreamWriter +> **Extends:** `scy::PacketProcessor` +> **Defined in:** `packetio.h` +Packet stream writer class. +This class can be connected to a `[PacketStream](#classscy_1_1PacketStream)` to write output to any class that derives from `std::ostream`. It's most regularly used for writing output files. -#### `public virtual void close()` +### Members +| Name | Description | +|------|-------------| +| [`StreamWriter`](#group__base_1gad15868ece5ffa0a63ae71ab555b0d43f) | | +| [`~StreamWriter`](#group__base_1ga0bdd60e6b4e56dcde24d2b7f372d55e2) | | +| [`process`](#group__base_1gae8a1107b09b3644ef7c69ac70bb88459) | This method performs processing on the given packet and emits the result. | +| [`stream`](#group__base_1gac2501915ffeb2643615ae43936d8aedc) | | +| [`onStreamStateChange`](#group__base_1ga22f372f88ca99f812be3e888a40fba77) | Called by the [PacketStream](#classscy_1_1PacketStream) to notify when the internal [Stream](#classscy_1_1Stream) state changes. On receiving the Stopped state, it is the responsibility of the adapter to have ceased all outgoing packet transmission, especially in multi-thread scenarios. | +| [`stream`](#group__base_1gaa16cb5b70ea5470206bec6e56ae43b23) | | +| [`emitter`](#group__base_1ga1996908eb8e6301955ff4df97c5a22a7) | | +| [`_ostream`](#group__base_1ga2e9fe16cc8bec4c2ab33673eda06f4ff) | | +--- +#### StreamWriter +```cpp +inline StreamWriter(std::ostream * stream) +``` -#### `public `[`uv::Handle`](#classscy_1_1uv_1_1Handle)`< uv_async_t > & handle()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `stream` | `std::ostream *` | | +--- +#### ~StreamWriter +```cpp +virtual inline ~StreamWriter() +``` +--- -#### `protected `[`uv::Handle`](./doc/api-uv.md#classscy_1_1uv_1_1Handle)`< uv_async_t > _handle` +#### process +```cpp +virtual inline void process(IPacket & packet) +``` +This method performs processing on the given packet and emits the result. +Note: If packet processing is async (the packet is not in the current thread scope) then packet data must be copied. Copied data can be freed directly aFter the async call to [emit()](#group__base_1ga995248310998c29df87051389f52b58c) the outgoing packet. +| Parameter | Type | Description | +|-----------|------|-------------| +| `packet` | `IPacket &` | | -#### `protected virtual bool async() const` +--- +#### stream +```cpp +template inline StreamT & stream() +``` -Returns true if the implementation is thread-based, or false if it belongs to an event loop. +--- -# class `scy::SyncPacketQueue` +#### onStreamStateChange +```cpp +virtual inline void onStreamStateChange(const PacketStreamState &) ``` -class scy::SyncPacketQueue - : public scy::SyncQueue< T > - : public scy::PacketProcessor -``` +Called by the [PacketStream](#classscy_1_1PacketStream) to notify when the internal [Stream](#classscy_1_1Stream) state changes. On receiving the Stopped state, it is the responsibility of the adapter to have ceased all outgoing packet transmission, especially in multi-thread scenarios. +--- +#### stream +```cpp +inline std::ostream & stream() +``` -## Summary +--- - Members | Descriptions ---------------------------------|--------------------------------------------- -`public `[`PacketSignal`](#group__base_1ga3ffb5bda6133fac97f3bed2b567b9b6a)` emitter` | -`public inline SyncPacketQueue(uv::Loop * loop,int maxSize)` | -`public inline SyncPacketQueue(int maxSize)` | -`public inline virtual ~SyncPacketQueue()` | -`public inline virtual void process(`[`IPacket`](#classscy_1_1IPacket)` & packet)` | -`public inline virtual bool accepts(`[`IPacket`](#classscy_1_1IPacket)` * packet)` | -`protected inline virtual void dispatch(T & item)` | Dispatch a single item to listeners. -`protected inline virtual void onStreamStateChange(const `[`PacketStreamState`](#structscy_1_1PacketStreamState)` &)` | +#### emitter -## Members +```cpp +PacketSignal emitter +``` -#### `public `[`PacketSignal`](#group__base_1ga3ffb5bda6133fac97f3bed2b567b9b6a)` emitter` +--- +#### _ostream +```cpp +std::ostream * _ostream +``` +## SyncPacketQueue +> **Extends:** `scy::SyncQueue< IPacket >`, `scy::PacketProcessor` +> **Defined in:** `packetqueue.h` -#### `public inline SyncPacketQueue(uv::Loop * loop,int maxSize)` +### Members +| Name | Description | +|------|-------------| +| [`SyncPacketQueue`](#group__base_1gae6d88a8cc455a3fcc463e302a4fa1b1f) | | +| [`SyncPacketQueue`](#group__base_1ga10b57a26379bac19ff0f4c48b367ab18) | | +| [`~SyncPacketQueue`](#group__base_1gaaddebcff191f315fa84dd988bb9f9f64) | | +| [`process`](#group__base_1ga75df139f954f41a0d315009a2ae5e000) | This method performs processing on the given packet and emits the result. | +| [`accepts`](#group__base_1ga00793d12f0252f6f4b2e439ecb725829) | This method ensures compatibility with the given packet type. Return false to reject the packet. | +| [`dispatch`](#group__base_1ga11c2c12c52dd842cd37d83ea8f05147c) | Dispatch a single item to listeners. | +| [`onStreamStateChange`](#group__base_1ga37f27e601fe6cd6e73c5b3da83b7634d) | Called by the [PacketStream](#classscy_1_1PacketStream) to notify when the internal [Stream](#classscy_1_1Stream) state changes. On receiving the Stopped state, it is the responsibility of the adapter to have ceased all outgoing packet transmission, especially in multi-thread scenarios. | +| [`emitter`](#group__base_1ga9cb2e51e85e32907283c98c62fc5967d) | | +--- +#### SyncPacketQueue +```cpp +inline SyncPacketQueue(uv::Loop * loop, int maxSize) +``` -#### `public inline SyncPacketQueue(int maxSize)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `loop` | `uv::Loop *` | | +| `maxSize` | `int` | | +--- +#### SyncPacketQueue +```cpp +inline SyncPacketQueue(int maxSize) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `maxSize` | `int` | | -#### `public inline virtual ~SyncPacketQueue()` +--- +#### ~SyncPacketQueue +```cpp +virtual inline ~SyncPacketQueue() +``` +--- +#### process -#### `public inline virtual void process(`[`IPacket`](#classscy_1_1IPacket)` & packet)` +```cpp +virtual inline void process(IPacket & packet) +``` +This method performs processing on the given packet and emits the result. +Note: If packet processing is async (the packet is not in the current thread scope) then packet data must be copied. Copied data can be freed directly aFter the async call to [emit()](#group__base_1ga995248310998c29df87051389f52b58c) the outgoing packet. -This method performs processing on the given packet and emits the result. +| Parameter | Type | Description | +|-----------|------|-------------| +| `packet` | `IPacket &` | | -Note: If packet processing is async (the packet is not in the current thread scope) then packet data must be copied. Copied data can be freed directly aFter the async call to emit() the outgoing packet. +--- -#### `public inline virtual bool accepts(`[`IPacket`](#classscy_1_1IPacket)` * packet)` +#### accepts +```cpp +virtual inline bool accepts(IPacket *) +``` +This method ensures compatibility with the given packet type. Return false to reject the packet. +--- +#### dispatch -#### `protected inline virtual void dispatch(T & item)` +```cpp +virtual inline void dispatch(T & item) +``` Dispatch a single item to listeners. +| Parameter | Type | Description | +|-----------|------|-------------| +| `item` | `T &` | | +--- -#### `protected inline virtual void onStreamStateChange(const `[`PacketStreamState`](#structscy_1_1PacketStreamState)` &)` - +#### onStreamStateChange +```cpp +virtual inline void onStreamStateChange(const PacketStreamState &) +``` Called by the [PacketStream](#classscy_1_1PacketStream) to notify when the internal [Stream](#classscy_1_1Stream) state changes. On receiving the Stopped state, it is the responsibility of the adapter to have ceased all outgoing packet transmission, especially in multi-thread scenarios. -# class `scy::SyncQueue` +--- + +#### emitter +```cpp +PacketSignal emitter ``` -class scy::SyncQueue - : public scy::RunnableQueue< T > -``` +## AsyncPacketQueue +> **Extends:** `scy::AsyncQueue< IPacket >`, `scy::PacketProcessor` +> **Defined in:** `packetqueue.h` -[SyncQueue](#classscy_1_1SyncQueue) extends [Synchronizer](#classscy_1_1Synchronizer) to implement a synchronized FIFO queue which receives T objects from any thread and synchronizes them for safe consumption by the associated event loop. +### Members -## Summary +| Name | Description | +|------|-------------| +| [`AsyncPacketQueue`](#group__base_1gab12334be9597666d9ccdbd8c1dc2b8b6) | | +| [`~AsyncPacketQueue`](#group__base_1ga1d52cb92da8849a198e4c47aea73876c) | | +| [`close`](#group__base_1gab25027fe2c2a2cb00edf378a4e314ea0) | | +| [`process`](#group__base_1ga7566b9cd568c49a13b63816ced79121f) | This method performs processing on the given packet and emits the result. | +| [`accepts`](#group__base_1ga5076d28d49bf343e866c5014e538e8af) | This method ensures compatibility with the given packet type. Return false to reject the packet. | +| [`dispatch`](#group__base_1gaf6e78ca0279615319d33d7e6aa624e55) | Dispatch a single item to listeners. | +| [`onStreamStateChange`](#group__base_1gae72126b2b0f118975423119a3ddd6978) | Called by the [PacketStream](#classscy_1_1PacketStream) to notify when the internal [Stream](#classscy_1_1Stream) state changes. On receiving the Stopped state, it is the responsibility of the adapter to have ceased all outgoing packet transmission, especially in multi-thread scenarios. | +| [`emitter`](#group__base_1gaf462c1a658ea10a25f0159c3adf22054) | | - Members | Descriptions ---------------------------------|--------------------------------------------- -`public inline SyncQueue(uv::Loop * loop,int limit,int timeout)` | -`public inline virtual ~SyncQueue()` | -`public inline virtual void push(T * item)` | -`public inline virtual void cancel()` | -`public inline `[`Synchronizer`](#classscy_1_1Synchronizer)` & sync()` | -`protected `[`Synchronizer`](./doc/api-base.md#classscy_1_1Synchronizer)` _sync` | +--- -## Members +#### AsyncPacketQueue -#### `public inline SyncQueue(uv::Loop * loop,int limit,int timeout)` +```cpp +inline AsyncPacketQueue(int maxSize) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `maxSize` | `int` | | +--- +#### ~AsyncPacketQueue +```cpp +virtual inline ~AsyncPacketQueue() +``` -#### `public inline virtual ~SyncQueue()` +--- +#### close +```cpp +virtual inline void close() +``` -Destruction is deferred to allow enough time for all callbacks to return. +--- -#### `public inline virtual void push(T * item)` +#### process +```cpp +virtual inline void process(IPacket & packet) +``` +This method performs processing on the given packet and emits the result. -Pushes an item onto the queue. Item pointers are now managed by the [SyncQueue](#classscy_1_1SyncQueue). +Note: If packet processing is async (the packet is not in the current thread scope) then packet data must be copied. Copied data can be freed directly aFter the async call to [emit()](#group__base_1ga995248310998c29df87051389f52b58c) the outgoing packet. -#### `public inline virtual void cancel()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `packet` | `IPacket &` | | +--- +#### accepts +```cpp +virtual inline bool accepts(IPacket *) +``` +This method ensures compatibility with the given packet type. Return false to reject the packet. -#### `public inline `[`Synchronizer`](#classscy_1_1Synchronizer)` & sync()` +--- +#### dispatch +```cpp +virtual inline void dispatch(T & item) +``` +Dispatch a single item to listeners. +| Parameter | Type | Description | +|-----------|------|-------------| +| `item` | `T &` | | -#### `protected `[`Synchronizer`](./doc/api-base.md#classscy_1_1Synchronizer)` _sync` +--- +#### onStreamStateChange +```cpp +virtual inline void onStreamStateChange(const PacketStreamState &) +``` +Called by the [PacketStream](#classscy_1_1PacketStream) to notify when the internal [Stream](#classscy_1_1Stream) state changes. On receiving the Stopped state, it is the responsibility of the adapter to have ceased all outgoing packet transmission, especially in multi-thread scenarios. +--- -# class `scy::Task` +#### emitter +```cpp +PacketSignal emitter ``` -class scy::Task - : public scy::basic::Runnable -``` +## PacketStreamAdapter +> **Subclasses:** `scy::PacketProcessor`, `scy::ThreadedStreamReader`, `scy::av::ICapture`, `scy::http::FormWriter` +> **Defined in:** `packetstream.h` -Abstract class is for implementing any kind asyncronous task. +This class is a wrapper for integrating external classes with the a [PacketStream](#classscy_1_1PacketStream)'s data flow and state machine. -Tasks are designed to be run by a [TaskRunner](#classscy_1_1TaskRunner). +### Members + +| Name | Description | +|------|-------------| +| [`PacketStreamAdapter`](#group__base_1ga33639caa7975d01430b01643da0f3ddb) | | +| [`~PacketStreamAdapter`](#group__base_1ga6223fd3eac5802d6efa67b37515c7c3f) | | +| [`emit`](#group__base_1ga995248310998c29df87051389f52b58c) | | +| [`emit`](#group__base_1ga298c0975355b11dfc09669d4663a0260) | | +| [`emit`](#group__base_1gaefade7945aa72cd6b1fee74746fda713) | | +| [`emit`](#group__base_1ga4f329880c10ea2492479ddd90df48b09) | | +| [`emit`](#group__base_1ga3b302bbd1b8c8eb21d549eda77ab2e58) | | +| [`getEmitter`](#group__base_1ga3c56e12afc6c4863d9f70258dfe6c2a5) | Returns a reference to the outgoing packet signal. | +| [`onStreamStateChange`](#group__base_1gacaab737ce646207471c5f7bb3b6b794e) | Called by the [PacketStream](#classscy_1_1PacketStream) to notify when the internal [Stream](#classscy_1_1Stream) state changes. On receiving the Stopped state, it is the responsibility of the adapter to have ceased all outgoing packet transmission, especially in multi-thread scenarios. | +| [`PacketStreamAdapter`](#group__base_1ga2e52c68e66f76569dacf29a41cf8a73b) | NonCopyable and NonMovable. | +| [`operator=`](#group__base_1gab56d24063e6015ea655f22ba9d5723f1) | | +| [`_emitter`](#group__base_1ga080cfd0707ca633ed93b77aa066c6e8b) | | + +--- + +#### PacketStreamAdapter + +```cpp +PacketStreamAdapter(PacketSignal & emitter) +``` -## Summary +| Parameter | Type | Description | +|-----------|------|-------------| +| `emitter` | `PacketSignal &` | | - Members | Descriptions ---------------------------------|--------------------------------------------- -`public Task(bool repeat)` | Constructor. -`public virtual void destroy()` | Sets the task to destroyed state. -`public virtual bool destroyed() const` | Signals that the task should be disposed of. -`public virtual bool repeating() const` | -`public virtual uint32_t id() const` | Unique task ID. -`protected uint32_t _id` | -`protected bool _repeating` | -`protected bool _destroyed` | -`protected Task(const `[`Task`](#classscy_1_1Task)` & task) = delete` | -`protected `[`Task`](#classscy_1_1Task)` & operator=(`[`Task`](#classscy_1_1Task)` const &) = delete` | -`protected virtual ~Task()` | -`protected void run()` | +--- -## Members +#### ~PacketStreamAdapter -#### `public Task(bool repeat)` +```cpp +virtual inline ~PacketStreamAdapter() +``` -Constructor. +--- +#### emit +```cpp +virtual void emit(char * data, size_t len, unsigned flags) +``` -#### `public virtual void destroy()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `data` | `char *` | | +| `len` | `size_t` | | +| `flags` | `unsigned` | | -Sets the task to destroyed state. +--- +#### emit +```cpp +virtual void emit(const char * data, size_t len, unsigned flags) +``` -#### `public virtual bool destroyed() const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `data` | `const char *` | | +| `len` | `size_t` | | +| `flags` | `unsigned` | | -Signals that the task should be disposed of. +--- +#### emit +```cpp +virtual void emit(const std::string & str, unsigned flags) +``` -#### `public virtual bool repeating() const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `str` | `const std::string &` | | +| `flags` | `unsigned` | | +--- +#### emit -Signals that the task's should be called repeatedly by the [TaskRunner](#classscy_1_1TaskRunner). If this returns false the task will be [cancelled()](#group__base_1gab3795d080eae2e58a57f2c63524c8ef3) +```cpp +virtual void emit(unsigned flags) +``` -#### `public virtual uint32_t id() const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `flags` | `unsigned` | | -Unique task ID. +--- + +#### emit + +```cpp +virtual void emit(IPacket & packet) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `packet` | `IPacket &` | | +--- -#### `protected uint32_t _id` +#### getEmitter +```cpp +PacketSignal & getEmitter() +``` +Returns a reference to the outgoing packet signal. +--- +#### onStreamStateChange -#### `protected bool _repeating` +```cpp +virtual inline void onStreamStateChange(const PacketStreamState &) +``` +Called by the [PacketStream](#classscy_1_1PacketStream) to notify when the internal [Stream](#classscy_1_1Stream) state changes. On receiving the Stopped state, it is the responsibility of the adapter to have ceased all outgoing packet transmission, especially in multi-thread scenarios. +--- +#### PacketStreamAdapter +```cpp +PacketStreamAdapter(const PacketStreamAdapter &) = delete +``` -#### `protected bool _destroyed` +NonCopyable and NonMovable. +--- +#### operator= +```cpp +PacketStreamAdapter & operator=(const PacketStreamAdapter &) = delete +``` +--- -#### `protected Task(const `[`Task`](#classscy_1_1Task)` & task) = delete` +#### _emitter +```cpp +PacketSignal & _emitter +``` +## PacketProcessor +> **Extends:** `scy::PacketStreamAdapter` +> **Subclasses:** `scy::AsyncPacketQueue< PacketT >`, `scy::AsyncPacketQueue< T >`, `scy::Base64PacketEncoder`, `scy::StreamWriter`, `scy::SyncPacketQueue< T >`, `scy::av::FLVMetadataInjector`, `scy::av::FPSLimiter`, `scy::av::MultiplexPacketEncoder`, `scy::http::ChunkedAdapter`, `scy::http::MultipartAdapter` +> **Defined in:** `packetstream.h` +This class is a virtual interface for creating PacketStreamAdapters which process that and emit the [IPacket](#classscy_1_1IPacket) type. -#### `protected `[`Task`](#classscy_1_1Task)` & operator=(`[`Task`](#classscy_1_1Task)` const &) = delete` +### Members +| Name | Description | +|------|-------------| +| [`PacketProcessor`](#group__base_1gaf3ab7df2c2416fdb3bd4e2b313c8b772) | | +| [`process`](#group__base_1gad7adc3fd78dce41f0f96744dfe6d1d50) | This method performs processing on the given packet and emits the result. | +| [`accepts`](#group__base_1gacb581741dd22cc5c0191397b32419ddc) | This method ensures compatibility with the given packet type. Return false to reject the packet. | +| [`operator<<`](#group__base_1ga0b09928130bd267d58273ea85be1891a) | [Stream](#classscy_1_1Stream) operator alias for [process()](#group__base_1gad7adc3fd78dce41f0f96744dfe6d1d50) | +--- +#### PacketProcessor +```cpp +inline PacketProcessor(PacketSignal & emitter) +``` -#### `protected virtual ~Task()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `emitter` | `PacketSignal &` | | +--- +#### process -Destroctor. Should remain protected. +```cpp +void process(IPacket & packet) +``` -#### `protected void run()` +This method performs processing on the given packet and emits the result. +Note: If packet processing is async (the packet is not in the current thread scope) then packet data must be copied. Copied data can be freed directly aFter the async call to [emit()](#group__base_1ga995248310998c29df87051389f52b58c) the outgoing packet. +| Parameter | Type | Description | +|-----------|------|-------------| +| `packet` | `IPacket &` | | -Called by the [TaskRunner](#classscy_1_1TaskRunner) to run the task. Override this method to implement task action. Returning true means the true should be called again, and false will cause the task to be destroyed. The task will similarly be destroyed id [destroy()](#group__base_1gaecd8a85018f8f75ae802dcbf3749bdef) was called during the current task iteration. +--- -# class `scy::TaskRunner` +#### accepts +```cpp +virtual inline bool accepts(IPacket *) ``` -class scy::TaskRunner - : public scy::basic::Runnable -``` +This method ensures compatibility with the given packet type. Return false to reject the packet. +--- -[Runner](#classscy_1_1Runner) for tasks that inherit the `[Task](#classscy_1_1Task)` interface. +#### operator<< -The `[TaskRunner](#classscy_1_1TaskRunner)` continually loops through each task in the task list calling the task's `[run()](#group__base_1ga07a481d667f1a9c67e881eedcffc10a5)` method. +```cpp +virtual inline void operator<<(IPacket & packet) +``` -The `[TaskRunner](#classscy_1_1TaskRunner)` is powered by an abstract `[Runner](#classscy_1_1Runner)` instance, which means that tasks can be executed in a thread or event loop context. +[Stream](#classscy_1_1Stream) operator alias for [process()](#group__base_1gad7adc3fd78dce41f0f96744dfe6d1d50) -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public `[`NullSignal`](./doc/api-base.md#classscy_1_1Signal)` Idle` | Fires after completing an iteration of all tasks. -`public `[`NullSignal`](./doc/api-base.md#classscy_1_1Signal)` Shutdown` | Signals when the `[TaskRunner](./doc/api-base.md#classscy_1_1TaskRunner)` is shutting down. -`public TaskRunner(std::shared_ptr< `[`Runner`](#classscy_1_1Runner)` > runner)` | -`public virtual ~TaskRunner()` | -`public virtual bool start(`[`Task`](#classscy_1_1Task)` * task)` | Starts a task, adding it if it doesn't exist. -`public virtual bool cancel(`[`Task`](#classscy_1_1Task)` * task)` | -`public virtual bool destroy(`[`Task`](#classscy_1_1Task)` * task)` | Queues a task for destruction. -`public virtual bool exists(`[`Task`](#classscy_1_1Task)` * task) const` | Returns weather or not a task exists. -`public virtual `[`Task`](#classscy_1_1Task)` * get(uint32_t id) const` | -`public virtual void setRunner(std::shared_ptr< `[`Runner`](#classscy_1_1Runner)` > runner)` | -`public inline virtual const char * className() const` | -`protected mutable std::mutex _mutex` | -`protected std::shared_ptr< `[`Runner`](./doc/api-base.md#classscy_1_1Runner)` > _runner` | -`protected TaskList _tasks` | -`protected virtual void run()` | Called by the async context to run the next task. -`protected virtual bool add(`[`Task`](#classscy_1_1Task)` * task)` | Adds a task to the runner. -`protected virtual bool remove(`[`Task`](#classscy_1_1Task)` * task)` | Removes a task from the runner. -`protected virtual `[`Task`](#classscy_1_1Task)` * next() const` | Returns the next task to be run. -`protected virtual void clear()` | Destroys and clears all manages tasks. -`protected virtual void onAdd(`[`Task`](#classscy_1_1Task)` * task)` | Called after a task is added. -`protected virtual void onStart(`[`Task`](#classscy_1_1Task)` * task)` | Called after a task is started. -`protected virtual void onCancel(`[`Task`](#classscy_1_1Task)` * task)` | Called after a task is cancelled. -`protected virtual void onRemove(`[`Task`](#classscy_1_1Task)` * task)` | Called after a task is removed. -`protected virtual void onRun(`[`Task`](#classscy_1_1Task)` * task)` | Called after a task has run. - -## Members - -#### `public `[`NullSignal`](./doc/api-base.md#classscy_1_1Signal)` Idle` +| Parameter | Type | Description | +|-----------|------|-------------| +| `packet` | `IPacket &` | | -Fires after completing an iteration of all tasks. +## PacketStream +> **Extends:** `scy::Stateful< PacketStreamState >` +> **Defined in:** `packetstream.h` +This class is used for processing and boradcasting IPackets in a flexible way. A [PacketStream](#classscy_1_1PacketStream) consists of one or many PacketSources, one or many PacketProcessors, and one or many delegate receivers. -#### `public `[`NullSignal`](./doc/api-base.md#classscy_1_1Signal)` Shutdown` +This class enables the developer to setup a processor chain in order to perform arbitrary processing on data packets using interchangeable packet adapters, and pump the output to any delegate function,/// or even another [PacketStream](#classscy_1_1PacketStream). -Signals when the `[TaskRunner](#classscy_1_1TaskRunner)` is shutting down. +Note that [PacketStream](#classscy_1_1PacketStream) itself inherits from [PacketStreamAdapter](#classscy_1_1PacketStreamAdapter),/// so a [PacketStream](#classscy_1_1PacketStream) be the source of another [PacketStream](#classscy_1_1PacketStream). +All [PacketStream](#classscy_1_1PacketStream) methods are thread-safe, but once the stream is running you will not be able to attach or detach stream adapters. +In order to synchronize output packets with the application event loop take a look at the [SyncPacketQueue](#classscy_1_1SyncPacketQueue) class. For lengthy operations you can add an [AsyncPacketQueue](#classscy_1_1AsyncPacketQueue) to the start of the stream to defer processing from the PacketSource thread. -#### `public TaskRunner(std::shared_ptr< `[`Runner`](#classscy_1_1Runner)` > runner)` +### Members + +| Name | Description | +|------|-------------| +| [`PacketStream`](#group__base_1ga7313ef8bb9b19b1b8cf88698e77cbb92) | | +| [`~PacketStream`](#group__base_1ga2b6dffb019c4da42da8fea435623568e) | | +| [`start`](#group__base_1gaa07075299f2271e58f78de3fd7e62b10) | Start the stream and synchronized sources. | +| [`stop`](#group__base_1ga5ace99af3f0ff1e93483a7f5dd5dca69) | Stop the stream and synchronized sources. | +| [`pause`](#group__base_1ga866ba120ec05be813d82a6e05827292e) | Pause the stream. | +| [`resume`](#group__base_1ga2e27223e238aa0174180abd379e3149c) | Resume the stream. | +| [`close`](#group__base_1gac0eec4eda5ff0571b46b4a39af9f7dcf) | Close the stream and transition the internal state to Closed. | +| [`reset`](#group__base_1gabf0b20944de791715e6891520fd6784b) | Cleanup all managed stream adapters and reset the stream state. | +| [`active`](#group__base_1ga6f53641239172c34777c6fae3c96fc98) | Returns true when the stream is in the Active state. | +| [`stopped`](#group__base_1gaa1485ea7e14fd0d929886604930a4092) | Returns true when the stream is in the Stopping or Stopped state. | +| [`closed`](#group__base_1ga45d9514c5da12522e7e672f46f433d27) | Returns true when the stream is in the Closed or [Error](#structscy_1_1Error) state. | +| [`lock`](#group__base_1gaa49be3aec494af1412f80a0613d5dc77) | Sets the stream to locked state. In a locked state no new adapters can be added or removed from the stream until the stream is stopped. | +| [`locked`](#group__base_1gad0ff7534821aebeda8731d5840cef8bb) | Returns true is the stream is currently locked. | +| [`write`](#group__base_1ga74422f101e021e1eea6ebab7cd36098d) | Writes data to the stream (nocopy). | +| [`write`](#group__base_1gad7b06d811db22b5c08aa4fce2d86eb19) | Writes data to the stream (copied). | +| [`write`](#group__base_1ga4bd4ad751e112c62f93db2920677e75b) | Writes an incoming packet onto the stream. | +| [`attachSource`](#group__base_1ga16adec5b00a33070556dd8531e1825c0) | Attaches a source packet emitter to the stream. The source packet adapter can be another [PacketStream::emitter](#group__base_1ga3d4fa2d39446cd24ce5d8281834b70db). | +| [`attachSource`](#group__base_1ga42e243c7a6bf9cb7a53725e7ca268e64) | Attaches a source packet emitter to the stream. If owned is true, the stream takes ownership and will delete the pointer. If syncState is true and the source is a [basic::Startable](#classscy_1_1basic_1_1Startable), then the source's [start()](#group__base_1gaa07075299f2271e58f78de3fd7e62b10)/stop() methods will be synchronized when calling [startSources()](#group__base_1gaeb9605f5d35a6aaa92bf427e0989827c)/stopSources(). | +| [`attachSource`](#group__base_1gae6f1bb5accd371bd151cfbabc141b331) | Attaches a source packet emitter to the stream. This method enables compatibility with shared_ptr managed adapter instances. | +| [`detachSource`](#group__base_1ga06e1aa0b843f233d6dc71ca293a24945) | Detaches the given source packet signal from the stream. | +| [`detachSource`](#group__base_1ga4f77bef24858fbb7bf31b43899c6fd27) | Detaches the given source packet adapter from the stream. | +| [`attach`](#group__base_1ga7f94960094b20d385f932c915b24c508) | Attaches a packet processor to the stream. Order determines the position of the processor in the stream queue. If owned is true, the stream takes ownership and will delete the pointer. | +| [`attach`](#group__base_1ga9ddf204e9fa1db2aca165f4d4bd04132) | Attaches a packet processor to the stream. This method enables compatibility with shared_ptr managed adapter instances. | +| [`detach`](#group__base_1ga879c4077767fcbd5def56f4398202d63) | Detaches a packet processor from the stream. | +| [`synchronizeOutput`](#group__base_1ga27a797846a098946cf73d80726302a9e) | Synchronize stream output packets with the given event loop. | +| [`autoStart`](#group__base_1ga2042eee4cb00925265abeaef5cbb2588) | Set the stream to auto start if inactive (default: false). | +| [`closeOnError`](#group__base_1ga58995f68cf550280612199862a7dba84) | Set the stream to be closed on error (default: true). | +| [`error`](#group__base_1ga894d3a083f545aa5d4eb001819ce79f7) | Accessors for the unmanaged client data pointer. | +| [`name`](#group__base_1gacf6a0e6b50acb9575a6cda69863c43f3) | Returns the name of the packet stream. | +| [`adapters`](#group__base_1ga847517ada8ae4492b1fa54eb75fe7d0b) | Returns a combined list of all stream sources and processors. | +| [`sources`](#group__base_1ga95efa9dc101b1ddd2a37f587931a45bc) | Returns a list of all stream sources. | +| [`processors`](#group__base_1ga7c3ddf305de8bff9d02e00338f6a6792) | Returns a list of all stream processors. | +| [`numSources`](#group__base_1ga846914577fbf526e0389ee36820865d8) | | +| [`numProcessors`](#group__base_1ga7e1d39ba8a8aca30b86c693937dde258) | | +| [`numAdapters`](#group__base_1gacd6972c47d4945735771841b16163a46) | | +| [`getSource`](#group__base_1ga6921d9eb5ad3fcd1541093db094b47eb) | | +| [`getProcessor`](#group__base_1ga54f24499988940ed9dd77f9409cdcf8f) | | +| [`getProcessor`](#group__base_1ga74ea091cd48ca43f5a04c8cdf1124c77) | Returns the [PacketProcessor](#classscy_1_1PacketProcessor) at the given position. | +| [`setup`](#group__base_1ga2e71c28fac4871d262138e58e048c641) | Attach the source and processor delegate chain. | +| [`teardown`](#group__base_1ga7529aa1efb6d052d08b1aa9d64988a03) | Detach the source and processor delegate chain. | +| [`attachSource`](#group__base_1ga4187fed0c3f68c220a9bb2779481e2db) | | +| [`attach`](#group__base_1ga6ab3b5c164ac0bab8137ae0e293b7f99) | | +| [`startSources`](#group__base_1gaeb9605f5d35a6aaa92bf427e0989827c) | Start synchronized sources. | +| [`stopSources`](#group__base_1ga73955535a0312cd3371c3317c1bfa1f0) | Stop synchronized sources. | +| [`process`](#group__base_1ga379f518fe7c1a50af177b738e0b28f17) | [Process](#classscy_1_1Process) incoming packets. | +| [`emit`](#group__base_1ga2ec0154d38011167b59aa54a2cdddd98) | Emit the final packet to listeners. | +| [`synchronizeStates`](#group__base_1ga4abe768801f8b39876834e45ead0ac1e) | Synchronize queued states with adapters. | +| [`onStateChange`](#group__base_1gae5e38cf390b7ac651342801d09a3e0bb) | Override the [Stateful::onStateChange](#group__base_1ga3c88b4aa8e9343f9bdc1a8c2ae2a5452) method. | +| [`assertCanModify`](#group__base_1ga8222585fd3f575c67b6b28f1e7cb5217) | Returns true if the given state ID is queued. | +| [`handleException`](#group__base_1ga40d1f91b9b8cb5216ce132998eaae458) | Handle an internal exception. | +| [`emitter`](#group__base_1ga3d4fa2d39446cd24ce5d8281834b70db) | Signals to delegates on outgoing packets. | +| [`Error`](#group__base_1ga91c28709d238b0cfa21ba0929296d981) | Signals that the [PacketStream](#classscy_1_1PacketStream) is in [Error](#structscy_1_1Error) state. If stream output is synchronized then the [Error](#structscy_1_1Error) signal will be sent from the synchronization context, otherwise it will be sent from the async processor context. See [synchronizeOutput()](#group__base_1ga27a797846a098946cf73d80726302a9e) | +| [`Close`](#group__base_1ga1a7296d92dbedd388ea99ff6436e5037) | Signals that the [PacketStream](#classscy_1_1PacketStream) is in Close state. This signal is sent immediately via the [close()](#group__base_1gac0eec4eda5ff0571b46b4a39af9f7dcf) method, and as such will be sent from the calling thread context. | +| [`_mutex`](#group__base_1ga07b9e3677e5d7811efeee61017ea91f4) | | +| [`_procMutex`](#group__base_1gacb611f82818fdbd6cbd316240c2e13eb) | | +| [`_name`](#group__base_1ga928ac73b404916c524349f82b837a251) | | +| [`_sources`](#group__base_1ga884fa29fc53edcca06ff84997b48cfd5) | | +| [`_processors`](#group__base_1ga06fe5e28961a3352db8f80138eb30564) | | +| [`_states`](#group__base_1ga6cdb9717a975c66542a88ce34586265b) | | +| [`_error`](#group__base_1gaabf4120335505da2f373b7afb64cf156) | | +| [`_autoStart`](#group__base_1gabc12f096a88953028521259790bae93f) | | +| [`_closeOnError`](#group__base_1ga255d1421e03dfac4aafbe763c759f85a) | | + +--- + +#### PacketStream + +```cpp +PacketStream(const std::string & name) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | +--- +#### ~PacketStream +```cpp +virtual ~PacketStream() +``` -#### `public virtual ~TaskRunner()` +--- +#### start +```cpp +virtual void start() +``` +Start the stream and synchronized sources. +--- -#### `public virtual bool start(`[`Task`](#classscy_1_1Task)` * task)` +#### stop -Starts a task, adding it if it doesn't exist. +```cpp +virtual void stop() +``` +Stop the stream and synchronized sources. +--- -#### `public virtual bool cancel(`[`Task`](#classscy_1_1Task)` * task)` +#### pause +```cpp +virtual void pause() +``` +Pause the stream. -Cancels a task. +--- -The task reference will be managed the [TaskRunner](#classscy_1_1TaskRunner) until the task is destroyed. +#### resume -#### `public virtual bool destroy(`[`Task`](#classscy_1_1Task)` * task)` +```cpp +virtual void resume() +``` -Queues a task for destruction. +Resume the stream. +--- +#### close -#### `public virtual bool exists(`[`Task`](#classscy_1_1Task)` * task) const` +```cpp +virtual void close() +``` -Returns weather or not a task exists. +Close the stream and transition the internal state to Closed. +--- +#### reset -#### `public virtual `[`Task`](#classscy_1_1Task)` * get(uint32_t id) const` +```cpp +virtual void reset() +``` +Cleanup all managed stream adapters and reset the stream state. +--- -Returns the task pointer matching the given ID, or nullptr if no task exists. +#### active -#### `public virtual void setRunner(std::shared_ptr< `[`Runner`](#classscy_1_1Runner)` > runner)` +```cpp +virtual bool active() const +``` +Returns true when the stream is in the Active state. +--- -Set the asynchronous context for packet processing. This may be a [Thread](#classscy_1_1Thread) or another derivative of Async. Must be set before the stream is activated. +#### stopped -#### `public inline virtual const char * className() const` +```cpp +virtual bool stopped() const +``` +Returns true when the stream is in the Stopping or Stopped state. +--- +#### closed +```cpp +virtual bool closed() const +``` -#### `protected mutable std::mutex _mutex` +Returns true when the stream is in the Closed or [Error](#structscy_1_1Error) state. +--- +#### lock +```cpp +virtual bool lock() +``` +Sets the stream to locked state. In a locked state no new adapters can be added or removed from the stream until the stream is stopped. -#### `protected std::shared_ptr< `[`Runner`](./doc/api-base.md#classscy_1_1Runner)` > _runner` +--- +#### locked +```cpp +virtual bool locked() const +``` +Returns true is the stream is currently locked. +--- -#### `protected TaskList _tasks` +#### write +```cpp +virtual void write(char * data, size_t len) +``` +Writes data to the stream (nocopy). +| Parameter | Type | Description | +|-----------|------|-------------| +| `data` | `char *` | | +| `len` | `size_t` | | +--- -#### `protected virtual void run()` +#### write -Called by the async context to run the next task. +```cpp +virtual void write(const char * data, size_t len) +``` +Writes data to the stream (copied). +| Parameter | Type | Description | +|-----------|------|-------------| +| `data` | `const char *` | | +| `len` | `size_t` | | -#### `protected virtual bool add(`[`Task`](#classscy_1_1Task)` * task)` +--- -Adds a task to the runner. +#### write +```cpp +virtual void write(IPacket && packet) +``` +Writes an incoming packet onto the stream. -#### `protected virtual bool remove(`[`Task`](#classscy_1_1Task)` * task)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `packet` | `IPacket &&` | | -Removes a task from the runner. +--- +#### attachSource +```cpp +virtual void attachSource(PacketSignal & source) +``` -#### `protected virtual `[`Task`](#classscy_1_1Task)` * next() const` +Attaches a source packet emitter to the stream. The source packet adapter can be another [PacketStream::emitter](#group__base_1ga3d4fa2d39446cd24ce5d8281834b70db). -Returns the next task to be run. +| Parameter | Type | Description | +|-----------|------|-------------| +| `source` | `PacketSignal &` | | +--- +#### attachSource -#### `protected virtual void clear()` +```cpp +virtual void attachSource(PacketStreamAdapter * source, bool owned, bool syncState) +``` -Destroys and clears all manages tasks. +Attaches a source packet emitter to the stream. If owned is true, the stream takes ownership and will delete the pointer. If syncState is true and the source is a [basic::Startable](#classscy_1_1basic_1_1Startable), then the source's [start()](#group__base_1gaa07075299f2271e58f78de3fd7e62b10)/stop() methods will be synchronized when calling [startSources()](#group__base_1gaeb9605f5d35a6aaa92bf427e0989827c)/stopSources(). +| Parameter | Type | Description | +|-----------|------|-------------| +| `source` | `PacketStreamAdapter *` | | +| `owned` | `bool` | | +| `syncState` | `bool` | | +--- -#### `protected virtual void onAdd(`[`Task`](#classscy_1_1Task)` * task)` +#### attachSource -Called after a task is added. +```cpp +template inline void attachSource(std::shared_ptr< C > ptr, bool syncState) +``` +Attaches a source packet emitter to the stream. This method enables compatibility with shared_ptr managed adapter instances. +| Parameter | Type | Description | +|-----------|------|-------------| +| `ptr` | `std::shared_ptr< C >` | | +| `syncState` | `bool` | | -#### `protected virtual void onStart(`[`Task`](#classscy_1_1Task)` * task)` +--- -Called after a task is started. +#### detachSource +```cpp +virtual bool detachSource(PacketSignal & source) +``` +Detaches the given source packet signal from the stream. -#### `protected virtual void onCancel(`[`Task`](#classscy_1_1Task)` * task)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `source` | `PacketSignal &` | | -Called after a task is cancelled. +--- +#### detachSource +```cpp +virtual bool detachSource(PacketStreamAdapter * source) +``` -#### `protected virtual void onRemove(`[`Task`](#classscy_1_1Task)` * task)` +Detaches the given source packet adapter from the stream. -Called after a task is removed. +| Parameter | Type | Description | +|-----------|------|-------------| +| `source` | `PacketStreamAdapter *` | | +--- +#### attach -#### `protected virtual void onRun(`[`Task`](#classscy_1_1Task)` * task)` +```cpp +virtual void attach(PacketProcessor * proc, int order, bool owned) +``` -Called after a task has run. +Attaches a packet processor to the stream. Order determines the position of the processor in the stream queue. If owned is true, the stream takes ownership and will delete the pointer. +| Parameter | Type | Description | +|-----------|------|-------------| +| `proc` | `PacketProcessor *` | | +| `order` | `int` | | +| `owned` | `bool` | | +--- -# class `scy::Thread` +#### attach +```cpp +template inline void attach(std::shared_ptr< C > ptr, int order, bool syncState) ``` -class scy::Thread - : public scy::Runner - : public scy::Runner -``` +Attaches a packet processor to the stream. This method enables compatibility with shared_ptr managed adapter instances. +| Parameter | Type | Description | +|-----------|------|-------------| +| `ptr` | `std::shared_ptr< C >` | | +| `order` | `int` | | +| `syncState` | `bool` | | -This class implements a platform-independent wrapper around an operating system thread. +--- -Platform-independent wrapper around an operating system thread. +#### detach -This class inherits the `[Runner](#classscy_1_1Runner)` interface and may be used with any implementation that's powered by an asynchronous `[Runner](#classscy_1_1Runner)`. +```cpp +virtual bool detach(PacketProcessor * proc) +``` -## Summary +Detaches a packet processor from the stream. - Members | Descriptions ---------------------------------|--------------------------------------------- -`public Thread()` | -`public Thread(`[`basic::Runnable`](#classscy_1_1basic_1_1Runnable)` & target)` | -`public Thread(std::function< void()> target)` | -`public Thread(std::function< void(void *)> target,void * arg)` | -`public virtual ~Thread()` | -`public void join()` | Waits until the thread exits. -`public bool waitForExit(int timeout)` | -`public uv_thread_t id() const` | Returns the native thread handle. -`public Thread()` | Default constructor. -`public template`
`inline explicit Thread(Function && func,Args &&... args)` | -`public virtual ~Thread()` | Destructor. -`public template`
`inline void start(Function && func,Args &&... args)` | -`public virtual void start(std::function< void()> func)` | Start the asynchronous context with the given void function. -`public void join()` | Wait until the thread exits. -`public std::thread::id id() const` | Return the native thread handle. -`protected uv_thread_t _handle` | -`protected std::thread _thread` | -`protected Thread(const `[`Thread`](#classscy_1_1Thread)` &) = delete` | NonCopyable and NonMovable. -`protected `[`Thread`](#classscy_1_1Thread)` & operator=(const `[`Thread`](#classscy_1_1Thread)` &) = delete` | -`protected virtual bool async() const` | -`protected virtual void startAsync()` | -`protected Thread(const `[`Thread`](#classscy_1_1Thread)` &) = delete` | NonCopyable and NonMovable. -`protected `[`Thread`](#classscy_1_1Thread)` & operator=(const `[`Thread`](#classscy_1_1Thread)` &) = delete` | -`protected virtual bool async() const` | +| Parameter | Type | Description | +|-----------|------|-------------| +| `proc` | `PacketProcessor *` | | -## Members +--- -#### `public Thread()` +#### synchronizeOutput +```cpp +virtual void synchronizeOutput(uv::Loop * loop) +``` +Synchronize stream output packets with the given event loop. +| Parameter | Type | Description | +|-----------|------|-------------| +| `loop` | `uv::Loop *` | | +--- -#### `public Thread(`[`basic::Runnable`](#classscy_1_1basic_1_1Runnable)` & target)` +#### autoStart +```cpp +virtual void autoStart(bool flag) +``` +Set the stream to auto start if inactive (default: false). +With this flag set the stream will automatically transition to Active state if the in either the None or Locaked state. +| Parameter | Type | Description | +|-----------|------|-------------| +| `flag` | `bool` | | -#### `public Thread(std::function< void()> target)` +--- +#### closeOnError +```cpp +virtual void closeOnError(bool flag) +``` +Set the stream to be closed on error (default: true). +With this flag set the stream will be automatically transitioned to Closed state from [Error](#structscy_1_1Error) state. -#### `public Thread(std::function< void(void *)> target,void * arg)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `flag` | `bool` | | +--- +#### error +```cpp +const std::exception_ptr & error() +``` +Accessors for the unmanaged client data pointer. -#### `public virtual ~Thread()` +Returns the stream error (if any). +--- +#### name +```cpp +std::string name() const +``` +Returns the name of the packet stream. -#### `public void join()` +--- -Waits until the thread exits. +#### adapters +```cpp +PacketAdapterVec adapters() const +``` +Returns a combined list of all stream sources and processors. -#### `public bool waitForExit(int timeout)` +--- +#### sources +```cpp +PacketAdapterVec sources() const +``` -Waits until the thread exits. +Returns a list of all stream sources. -The thread should be cancelled beore calling this method. This method must be called from outside the current thread context or deadlock will ensue. +--- -#### `public uv_thread_t id() const` +#### processors -Returns the native thread handle. +```cpp +PacketAdapterVec processors() const +``` +Returns a list of all stream processors. +--- -#### `public Thread()` +#### numSources -Default constructor. +```cpp +int numSources() const +``` +--- +#### numProcessors -#### `public template`
`inline explicit Thread(Function && func,Args &&... args)` +```cpp +int numProcessors() const +``` +--- +#### numAdapters -Templated constructor. +```cpp +int numAdapters() const +``` -This constructor starts the thread with the given function. +--- -#### `public virtual ~Thread()` +#### getSource -Destructor. +```cpp +template inline AdapterT * getSource(int index) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `index` | `int` | | +--- -#### `public template`
`inline void start(Function && func,Args &&... args)` +#### getProcessor +```cpp +template inline AdapterT * getProcessor(int index) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `index` | `int` | | -Start a function with veradic arguments. +--- -This method starts the thread with the given function. +#### getProcessor -#### `public virtual void start(std::function< void()> func)` +```cpp +inline PacketProcessor * getProcessor(int order) +``` -Start the asynchronous context with the given void function. +Returns the [PacketProcessor](#classscy_1_1PacketProcessor) at the given position. +| Parameter | Type | Description | +|-----------|------|-------------| +| `order` | `int` | | +--- -#### `public void join()` +#### setup -Wait until the thread exits. +```cpp +void setup() +``` +Attach the source and processor delegate chain. +--- -#### `public std::thread::id id() const` +#### teardown -Return the native thread handle. +```cpp +void teardown() +``` +Detach the source and processor delegate chain. +--- -#### `protected uv_thread_t _handle` +#### attachSource +```cpp +void attachSource(PacketAdapterReference::Ptr ref) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `ref` | `PacketAdapterReference::Ptr` | | +--- +#### attach -#### `protected std::thread _thread` +```cpp +void attach(PacketAdapterReference::Ptr ref) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `ref` | `PacketAdapterReference::Ptr` | | +--- +#### startSources +```cpp +void startSources() +``` -#### `protected Thread(const `[`Thread`](#classscy_1_1Thread)` &) = delete` +Start synchronized sources. -NonCopyable and NonMovable. +--- +#### stopSources +```cpp +void stopSources() +``` -#### `protected `[`Thread`](#classscy_1_1Thread)` & operator=(const `[`Thread`](#classscy_1_1Thread)` &) = delete` +Stop synchronized sources. +--- +#### process +```cpp +virtual void process(IPacket & packet) +``` +[Process](#classscy_1_1Process) incoming packets. -#### `protected virtual bool async() const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `packet` | `IPacket &` | | +--- +#### emit -Returns true if the implementation is thread-based, or false if it belongs to an event loop. +```cpp +void emit(IPacket & packet) +``` -#### `protected virtual void startAsync()` +Emit the final packet to listeners. +Synchronized signals such as Close and [Error](#structscy_1_1Error) are sent from this method. See [synchronizeOutput()](#group__base_1ga27a797846a098946cf73d80726302a9e) +| Parameter | Type | Description | +|-----------|------|-------------| +| `packet` | `IPacket &` | | +--- +#### synchronizeStates -#### `protected Thread(const `[`Thread`](#classscy_1_1Thread)` &) = delete` +```cpp +void synchronizeStates() +``` -NonCopyable and NonMovable. +Synchronize queued states with adapters. +--- +#### onStateChange -#### `protected `[`Thread`](#classscy_1_1Thread)` & operator=(const `[`Thread`](#classscy_1_1Thread)` &) = delete` +```cpp +virtual void onStateChange(PacketStreamState & state, const PacketStreamState & oldState) +``` +Override the [Stateful::onStateChange](#group__base_1ga3c88b4aa8e9343f9bdc1a8c2ae2a5452) method. +| Parameter | Type | Description | +|-----------|------|-------------| +| `state` | `PacketStreamState &` | | +| `oldState` | `const PacketStreamState &` | | +--- +#### assertCanModify -#### `protected virtual bool async() const` +```cpp +void assertCanModify() +``` +Returns true if the given state ID is queued. +Asserts that the stream can be modified, ie is not in the Locked, Stopping or Active states. -Returns true if the implementation is thread-based, or false if it belongs to an event loop. +--- -# class `scy::ThreadedStreamReader` +#### handleException +```cpp +void handleException(std::exception & exc) ``` -class scy::ThreadedStreamReader - : public scy::PacketStreamAdapter - : public scy::basic::Startable -``` +Handle an internal exception. +| Parameter | Type | Description | +|-----------|------|-------------| +| `exc` | `std::exception &` | | -Threaded stream reader class. +--- -This class can be connected to a `[PacketStream](#classscy_1_1PacketStream)` to read input from any class that derives from `std::istream`. It's most regularly used for reading input files. +#### emitter -## Summary +```cpp +PacketSignal emitter +``` - Members | Descriptions ---------------------------------|--------------------------------------------- -`public `[`PacketSignal`](#group__base_1ga3ffb5bda6133fac97f3bed2b567b9b6a)` emitter` | -`public inline ThreadedStreamReader(std::istream * is)` | -`public inline ~ThreadedStreamReader()` | -`public inline virtual void start()` | -`public inline virtual void stop()` | -`public template`
`inline StreamT & stream()` | -`public inline std::istream & stream()` | -`protected `[`Thread`](./doc/api-base.md#classscy_1_1Thread)` _runner` | -`protected std::istream * _istream` | +Signals to delegates on outgoing packets. -## Members +--- -#### `public `[`PacketSignal`](#group__base_1ga3ffb5bda6133fac97f3bed2b567b9b6a)` emitter` +#### Error +```cpp +Signal< void(PacketStream &, const std::exception_ptr &)> Error +``` +Signals that the [PacketStream](#classscy_1_1PacketStream) is in [Error](#structscy_1_1Error) state. If stream output is synchronized then the [Error](#structscy_1_1Error) signal will be sent from the synchronization context, otherwise it will be sent from the async processor context. See [synchronizeOutput()](#group__base_1ga27a797846a098946cf73d80726302a9e) +--- +#### Close -#### `public inline ThreadedStreamReader(std::istream * is)` +```cpp +Signal< void(PacketStream &)> Close +``` +Signals that the [PacketStream](#classscy_1_1PacketStream) is in Close state. This signal is sent immediately via the [close()](#group__base_1gac0eec4eda5ff0571b46b4a39af9f7dcf) method, and as such will be sent from the calling thread context. +--- +#### _mutex +```cpp +std::mutex _mutex +``` -#### `public inline ~ThreadedStreamReader()` +--- +#### _procMutex +```cpp +std::mutex _procMutex +``` +--- +#### _name -#### `public inline virtual void start()` +```cpp +std::string _name +``` +--- +#### _sources +```cpp +PacketAdapterVec _sources +``` +--- -#### `public inline virtual void stop()` +#### _processors +```cpp +PacketAdapterVec _processors +``` +--- +#### _states +```cpp +std::deque< PacketStreamState > _states +``` -#### `public template`
`inline StreamT & stream()` +--- +#### _error +```cpp +std::exception_ptr _error +``` +--- +#### _autoStart -#### `public inline std::istream & stream()` +```cpp +bool _autoStart +``` +--- +#### _closeOnError +```cpp +bool _closeOnError +``` +## PacketTransaction -#### `protected `[`Thread`](./doc/api-base.md#classscy_1_1Thread)` _runner` +> **Extends:** `scy::basic::Sendable`, `scy::Stateful< TransactionState >` +> **Subclasses:** `scy::net::Transaction< Message >`, `scy::net::Transaction< PacketT >` +> **Defined in:** `packettransaction.h` +This class provides request/response functionality for [IPacket](#classscy_1_1IPacket) types. +PacketTransactions are fire and forget. The object will be deleted after a successful response or a timeout. +### Members + +| Name | Description | +|------|-------------| +| [`PacketTransaction`](#group__base_1gadb8e26b65b3a60f24db3a0e8183a66a3) | | +| [`PacketTransaction`](#group__base_1gaf6a92e72b87b249648ccd46fc433f09c) | | +| [`send`](#group__base_1gad94b9acb3f91d3a32499b86340b72d2e) | Starts the transaction timer and sends the request. Overriding classes should implement send logic here. | +| [`cancel`](#group__base_1ga49c75e9316f50f660872dd4b249c28ca) | Cancellation means that the agent will not retransmit the request, will not treat the lack of response to be a failure, but will wait the duration of the transaction timeout for a response. | +| [`cancelled`](#group__base_1gaa54ffbb88648bcc1bba5c768bf86b74f) | | +| [`dispose`](#group__base_1ga620cd3aada050a2cd54a9ea34400c847) | Schedules the transaction for deferred deletion. | +| [`canResend`](#group__base_1ga08ff3ee8b0be3e16a84699c44ea6a2a6) | | +| [`attempts`](#group__base_1ga4f6506c8e89b3d125fd7c08464c63688) | | +| [`retries`](#group__base_1ga34cb6bd2af610a3d8c8639a47d0713ef) | | +| [`request`](#group__base_1gaa5c37750d66412b497c9130b5ad58cc2) | | +| [`request`](#group__base_1ga44b16598078348c741c8903dfda2b848) | | +| [`response`](#group__base_1gaa086ddf7d95b1866e89721c0c3ef0e5c) | | +| [`response`](#group__base_1gaafd5b5bae5829fffac6d6f2bf81204bb) | | +| [`~PacketTransaction`](#group__base_1gac52c12fac214bb76b7b61c510672ed55) | | +| [`onStateChange`](#group__base_1ga3f025f9c6286905e0ef499ff3b6c5607) | Override to handle post state change logic. | +| [`handlePotentialResponse`](#group__base_1ga5111866a3ab35fdf98dab7b21a8cbb3d) | Processes a potential response candidate and updates the state accordingly. | +| [`checkResponse`](#group__base_1ga2c0fb5cd9cd4f64f9600d04f2fc5cb34) | Checks a potential response candidate and returns true on successful match. | +| [`onResponse`](#group__base_1ga738b44f24205411c26bcb0ffe8ce6a80) | Called when a successful response is received. | +| [`onTimeout`](#group__base_1ga6c44b73210c0d856a72380a00403c486) | | +| [`_request`](#group__base_1ga062276bf6ecdca9a64f8b89b6ba8e268) | | +| [`_response`](#group__base_1ga4c36f743181e84dedf6b71cd6acb5c04) | | +| [`_timer`](#group__base_1ga56cf3ef1cde1ed234a81adbc534a4d0c) | The request timeout callback. | +| [`_retries`](#group__base_1ga3c72d7ce16d3b6defff73f7fb572ed2b) | The maximum number of attempts before the transaction is considered failed. | +| [`_attempts`](#group__base_1ga15a0177855becd97f06df6f4b24d59a9) | The number of times the transaction has been sent. | +| [`_destroyed`](#group__base_1gae22c00abf59f34d7274f98bbd8e140f0) | | + +--- + +#### PacketTransaction + +```cpp +inline PacketTransaction(long timeout, int retries, uv::Loop * loop) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `timeout` | `long` | | +| `retries` | `int` | | +| `loop` | `uv::Loop *` | | -#### `protected std::istream * _istream` +--- +#### PacketTransaction +```cpp +inline PacketTransaction(const PacketT & request, long timeout, int retries, uv::Loop * loop) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `request` | `const PacketT &` | | +| `timeout` | `long` | | +| `retries` | `int` | | +| `loop` | `uv::Loop *` | | +--- -# class `scy::TimedToken` +#### send +```cpp +virtual inline bool send() ``` -class scy::TimedToken - : public scy::Timeout -``` - -Token that expires after the specified duration. - +Starts the transaction timer and sends the request. Overriding classes should implement send logic here. -## Summary +--- - Members | Descriptions ---------------------------------|--------------------------------------------- -`public TimedToken(long duration)` | -`public TimedToken(const std::string & id,long duration)` | -`public inline std::string id() const` | -`public inline bool operator==(const `[`TimedToken`](#classscy_1_1TimedToken)` & r) const` | -`public inline bool operator==(const std::string & r) const` | -`protected std::string _id` | +#### cancel -## Members +```cpp +virtual inline void cancel() +``` -#### `public TimedToken(long duration)` +Cancellation means that the agent will not retransmit the request, will not treat the lack of response to be a failure, but will wait the duration of the transaction timeout for a response. +--- +#### cancelled +```cpp +inline bool cancelled() const +``` +--- -#### `public TimedToken(const std::string & id,long duration)` +#### dispose +```cpp +virtual inline void dispose() +``` +Schedules the transaction for deferred deletion. +It is safe to call this function while the transaction is still active, providing the call is made from the same loop thread which the timer is running on. +Protected by the base implementation as this is called by the internal state machine. -#### `public inline std::string id() const` +--- +#### canResend +```cpp +virtual inline bool canResend() +``` +--- +#### attempts -#### `public inline bool operator==(const `[`TimedToken`](#classscy_1_1TimedToken)` & r) const` +```cpp +inline int attempts() const +``` +--- +#### retries +```cpp +inline int retries() const +``` +--- -#### `public inline bool operator==(const std::string & r) const` +#### request +```cpp +inline PacketT & request() +``` +--- +#### request +```cpp +inline PacketT request() const +``` -#### `protected std::string _id` +--- +#### response +```cpp +inline PacketT & response() +``` +--- +#### response -# class `scy::Timeout` +```cpp +inline PacketT response() const +``` +--- -[Timeout](#classscy_1_1Timeout) counter which expires after a given delay. +#### ~PacketTransaction +```cpp +virtual inline ~PacketTransaction() +``` +--- -## Summary +#### onStateChange - Members | Descriptions ---------------------------------|--------------------------------------------- -`public Timeout(long delay,bool autoStart)` | -`public Timeout(const `[`Timeout`](#classscy_1_1Timeout)` & src)` | -`public ~Timeout()` | -`public bool running() const` | -`public void start()` | -`public void stop()` | -`public void reset()` | -`public long remaining() const` | -`public bool expired() const` | -`public inline void setDelay(long delay)` | -`public inline clock_t startAt() const` | -`public inline long delay() const` | -`public `[`Timeout`](#classscy_1_1Timeout)` & operator=(const `[`Timeout`](#classscy_1_1Timeout)` & src)` | -`protected clock_t _startAt` | -`protected long _delay` | +```cpp +virtual inline void onStateChange(TransactionState & state, const TransactionState &) +``` -## Members +Override to handle post state change logic. -#### `public Timeout(long delay,bool autoStart)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `state` | `TransactionState &` | | +--- +#### handlePotentialResponse +```cpp +virtual inline bool handlePotentialResponse(const PacketT & packet) +``` +Processes a potential response candidate and updates the state accordingly. -#### `public Timeout(const `[`Timeout`](#classscy_1_1Timeout)` & src)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `packet` | `const PacketT &` | | +--- +#### checkResponse +```cpp +bool checkResponse(const PacketT & packet) +``` +Checks a potential response candidate and returns true on successful match. -#### `public ~Timeout()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `packet` | `const PacketT &` | | +--- +#### onResponse +```cpp +virtual inline void onResponse() +``` +Called when a successful response is received. -#### `public bool running() const` +--- +#### onTimeout +```cpp +virtual inline void onTimeout() +``` +--- +#### _request -#### `public void start()` +```cpp +PacketT _request +``` +--- +#### _response +```cpp +PacketT _response +``` +--- -#### `public void stop()` +#### _timer +```cpp +Timer _timer +``` +The request timeout callback. +--- +#### _retries -#### `public void reset()` +```cpp +int _retries +``` +The maximum number of attempts before the transaction is considered failed. +--- +#### _attempts +```cpp +int _attempts +``` -#### `public long remaining() const` +The number of times the transaction has been sent. +--- +#### _destroyed +```cpp +bool _destroyed +``` +## Pipe -#### `public bool expired() const` +> **Extends:** `scy::Stream< uv_pipe_t >` +> **Defined in:** `pipe.h` +[Pipe](#classscy_1_1Pipe) implementation for process stdio. +### Members +| Name | Description | +|------|-------------| +| [`Pipe`](#group__base_1ga0bda328195d87f2aafedad6a5edb5891) | | +| [`~Pipe`](#group__base_1gab94d527ad3579a1e7c7681ea8f8292aa) | | +| [`init`](#group__base_1ga92c41af5c2e2cc2c7bf99235efdb743f) | | +| [`readStart`](#group__base_1ga12f86b98a2d7ffc42ae666e8e5a8f8b9) | | +--- -#### `public inline void setDelay(long delay)` +#### Pipe +```cpp +Pipe(uv::Loop * loop) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `loop` | `uv::Loop *` | | +--- +#### ~Pipe -#### `public inline clock_t startAt() const` +```cpp +virtual ~Pipe() +``` +--- +#### init +```cpp +virtual void init(bool ipc) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `ipc` | `bool` | | -#### `public inline long delay() const` +--- +#### readStart +```cpp +virtual bool readStart() +``` +## Process + +> **Defined in:** `process.h` + +### Members + +| Name | Description | +|------|-------------| +| [`Process`](#group__base_1ga21555aabd6288aeb0e2b7ef13dbc40ce) | Default constructor. | +| [`Process`](#group__base_1ga826344e39c8f9b525f590bb68e5923f8) | Constructor with command line arguments. | +| [`~Process`](#group__base_1ga2a922cfd98eae176afd280f9c645588d) | Destructor. | +| [`spawn`](#group__base_1ga2b8587f848160ac9f84743a27cc28151) | Spawns the process. Options must be properly set. Throws and exception on error. | +| [`kill`](#group__base_1gaebe1f79e3d47b3863573f8ad5a550d50) | Kills the process. | +| [`pid`](#group__base_1gab6b488740e07c049371ccdbac53ab50c) | Returns the process PID. | +| [`in`](#group__base_1ga704930d325b7403884a1e2e7e0748feb) | Returns the stdin pipe. | +| [`out`](#group__base_1gaf6f1b01781af6acfa1f31b904978bf5d) | Returns the stdout pipe. | +| [`init`](#group__base_1ga304d9596e4cdb66929e937691a15a225) | | +| [`file`](#group__base_1ga3a1ca1c79dedddcf650a2a75d495cac8) | Path to the program to execute. Cenvenience proxy for options.file. Must be set before `[spawn()](#group__base_1ga2b8587f848160ac9f84743a27cc28151)` | +| [`cwd`](#group__base_1gac8c553f362862e81791ad95d81811834) | Set the current working directory. Cenvenience proxy for options.cwd. Must be set before `[spawn()](#group__base_1ga2b8587f848160ac9f84743a27cc28151)` | +| [`args`](#group__base_1gab717c10f12861cb06e94570f6e3cc955) | Command line agruments to pass to the process. Cenvenience proxy for options.args. Must be set before `[spawn()](#group__base_1ga2b8587f848160ac9f84743a27cc28151)` | +| [`onstdout`](#group__base_1ga31ab2cc3c0bd7ac0904536df48a7d579) | Stdout signal. Signals when a line has been output from the process. | +| [`onexit`](#group__base_1gacc4d49ab33dc77b331248ada30fd576e) | Exit stgnals. Signals process exit status code. | +| [`options`](#group__base_1ga8fa7a36e401ff6b282c6a65cad8461ef) | LibUV C options. Available for advanced use cases. | +| [`_handle`](#group__base_1ga46a6bb5aa18927d34008eaf77e83c335) | | +| [`_stdin`](#group__base_1ga8d3b4922f4c4afc6fa1a4df3b4b7354c) | | +| [`_stdout`](#group__base_1gaa986e17a53f2201fa837a0b678543c31) | | +| [`_stdio`](#group__base_1ga4230cffe8750a9e74e8314fd53ef2658) | | +| [`_cargs`](#group__base_1ga34b82a517a54bfcf781679804c7db705) | | + +--- + +#### Process + +```cpp +Process(uv::Loop * loop) +``` +Default constructor. -#### `public `[`Timeout`](#classscy_1_1Timeout)` & operator=(const `[`Timeout`](#classscy_1_1Timeout)` & src)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `loop` | `uv::Loop *` | | +--- +#### Process +```cpp +Process(std::initializer_list< std::string > args, uv::Loop * loop) +``` +Constructor with command line arguments. -#### `protected clock_t _startAt` +| Parameter | Type | Description | +|-----------|------|-------------| +| `args` | `std::initializer_list< std::string >` | | +| `loop` | `uv::Loop *` | | +--- +#### ~Process +```cpp +~Process() +``` +Destructor. -#### `protected long _delay` +--- +#### spawn +```cpp +void spawn() +``` +Spawns the process. Options must be properly set. Throws and exception on error. +--- -# class `scy::Timer` +#### kill +```cpp +bool kill(int signum) ``` -class scy::Timer - : public scy::Runner -``` -Asynchronous event based timer. +Kills the process. +| Parameter | Type | Description | +|-----------|------|-------------| +| `signum` | `int` | | +--- -## Summary +#### pid - Members | Descriptions ---------------------------------|--------------------------------------------- -`public `[`NullSignal`](./doc/api-base.md#classscy_1_1Signal)` Timeout` | -`public Timer(uv::Loop * loop)` | Create a timer. -`public Timer(std::int64_t timeout,uv::Loop * loop,std::function< void()> func)` | -`public Timer(std::int64_t timeout,std::int64_t interval,uv::Loop * loop,std::function< void()> func)` | -`public virtual ~Timer()` | Destructor. -`public virtual void start()` | Start the timer. -`public virtual void start(std::function< void()> func)` | Start the timer with the given callback function. -`public virtual void stop()` | Stop the timer. -`public virtual void restart()` | -`public virtual void again()` | -`public virtual void setTimeout(std::int64_t timeout)` | -`public virtual void setInterval(std::int64_t interval)` | -`public bool active() const` | -`public virtual bool async() const` | -`public std::int64_t timeout() const` | -`public std::int64_t interval() const` | -`public std::int64_t count()` | -`public `[`uv::Handle`](#classscy_1_1uv_1_1Handle)`< uv_timer_t > & handle()` | -`protected `[`uv::Handle`](./doc/api-uv.md#classscy_1_1uv_1_1Handle)`< uv_timer_t > _handle` | -`protected std::int64_t _timeout` | -`protected std::int64_t _interval` | -`protected std::int64_t _count` | -`protected Timer(const `[`Timer`](#classscy_1_1Timer)` &) = delete` | -`protected `[`Timer`](#classscy_1_1Timer)` & operator=(const `[`Timer`](#classscy_1_1Timer)` &) = delete` | -`protected virtual void init()` | +```cpp +int pid() const +``` -## Members +Returns the process PID. -#### `public `[`NullSignal`](./doc/api-base.md#classscy_1_1Signal)` Timeout` +--- +#### in +```cpp +Pipe & in() +``` +Returns the stdin pipe. +--- -#### `public Timer(uv::Loop * loop)` +#### out -Create a timer. +```cpp +Pipe & out() +``` +Returns the stdout pipe. +--- -#### `public Timer(std::int64_t timeout,uv::Loop * loop,std::function< void()> func)` +#### init +```cpp +void init() +``` +--- -Create a timeout timer. +#### file -The timeout timer will trigger once after `timeout` milliseconds. +```cpp +std::string file +``` -#### `public Timer(std::int64_t timeout,std::int64_t interval,uv::Loop * loop,std::function< void()> func)` +Path to the program to execute. Cenvenience proxy for options.file. Must be set before `[spawn()](#group__base_1ga2b8587f848160ac9f84743a27cc28151)` +--- +#### cwd -Create a repeating interval timer. +```cpp +std::string cwd +``` -The interval timer will trigger once after `timeout` milliseconds, and continue to trigger after the `interval` milliseconds. +Set the current working directory. Cenvenience proxy for options.cwd. Must be set before `[spawn()](#group__base_1ga2b8587f848160ac9f84743a27cc28151)` -#### `public virtual ~Timer()` +--- -Destructor. +#### args +```cpp +std::vector< std::string > args +``` +Command line agruments to pass to the process. Cenvenience proxy for options.args. Must be set before `[spawn()](#group__base_1ga2b8587f848160ac9f84743a27cc28151)` -#### `public virtual void start()` +--- -Start the timer. +#### onstdout +```cpp +std::function< void(std::string)> onstdout +``` +Stdout signal. Signals when a line has been output from the process. -#### `public virtual void start(std::function< void()> func)` +--- -Start the timer with the given callback function. +#### onexit +```cpp +std::function< void(std::int64_t)> onexit +``` +Exit stgnals. Signals process exit status code. -#### `public virtual void stop()` +--- -Stop the timer. +#### options +```cpp +ProcessOptions options +``` +LibUV C options. Available for advanced use cases. -#### `public virtual void restart()` +--- +#### _handle +```cpp +uv::Handle< uv_process_t > _handle +``` -Restart the timer. +--- -This method works even if it hasn't been started yet. An interval or interval must be set or an exception will be thrown. +#### _stdin -#### `public virtual void again()` +```cpp +Pipe _stdin +``` +--- +#### _stdout -Trigger the timer again. +```cpp +Pipe _stdout +``` -If the timer is repeating restart it using the repeat value as the `timeout`. If the timer has never been started before it returns -1 and sets the error to `UV_EINVAL`. +--- -#### `public virtual void setTimeout(std::int64_t timeout)` +#### _stdio +```cpp +uv_stdio_container_t _stdio +``` +--- -Set the timeout value. +#### _cargs -The timer must not be active when this value is set. +```cpp +std::vector< char * > _cargs +``` -#### `public virtual void setInterval(std::int64_t interval)` +## Queue +> **Subclasses:** `scy::RunnableQueue< IPacket >`, `scy::RunnableQueue< PacketT >` +> **Defined in:** `queue.h` +Thread-safe queue container. -Set the repeat value. +### Members + +| Name | Description | +|------|-------------| +| [`push`](#group__base_1ga80ab35a22c083c80a6a7c717c2174c6a) | | +| [`empty`](#group__base_1ga1bad28bab5f78677918cc73ceff03312) | | +| [`front`](#group__base_1ga5d8c71ff5fcddff9a376aa8d3b74a1d1) | | +| [`front`](#group__base_1gad7727ff38467b28de1f68dc32187bbac) | | +| [`back`](#group__base_1ga9b4d0f0de452cb1f729f492f292635d8) | | +| [`back`](#group__base_1gae59ccc30d8974fa4229ce743255c9470) | | +| [`pop`](#group__base_1gaca35447c62090eb344640f15d75fd0b3) | | +| [`sort`](#group__base_1ga3e9d6104c9eed0124e2a38da6de52fbc) | | +| [`size`](#group__base_1ga246b30f749f103846c41b4a80e06b646) | | +| [`queue`](#group__base_1ga6f087595e41336ffb5353d7ab03c4954) | | +| [`_queue`](#group__base_1gac8bf28a8573f46c65292f5dfedfad510) | | +| [`_mutex`](#group__base_1gaa1d5ef5979b813608de21b6c4e88d452) | | + +--- + +#### push + +```cpp +inline void push(const T & data) +``` -Note that if the repeat value is set from a timer callback it does not immediately take effect. If the timer was non-repeating before, it will have been stopped. If it was repeating, then the old repeat value will have been used to schedule the next timeout. +| Parameter | Type | Description | +|-----------|------|-------------| +| `data` | `const T &` | | -#### `public bool active() const` +--- +#### empty +```cpp +inline bool empty() const +``` +--- +#### front -#### `public virtual bool async() const` +```cpp +inline T & front() +``` +--- +#### front -Returns true if the implementation is thread-based, or false if it belongs to an event loop. +```cpp +inline T const & front() const +``` -#### `public std::int64_t timeout() const` +--- +#### back +```cpp +inline T & back() +``` +--- +#### back -#### `public std::int64_t interval() const` +```cpp +inline T const & back() const +``` +--- +#### pop +```cpp +inline void pop() +``` +--- -#### `public std::int64_t count()` +#### sort +```cpp +template inline void sort() +``` +--- +#### size +```cpp +inline size_t size() +``` -#### `public `[`uv::Handle`](#classscy_1_1uv_1_1Handle)`< uv_timer_t > & handle()` +--- +#### queue +```cpp +inline std::deque< T > & queue() +``` +--- +#### _queue -#### `protected `[`uv::Handle`](./doc/api-uv.md#classscy_1_1uv_1_1Handle)`< uv_timer_t > _handle` +```cpp +std::deque< T > _queue +``` +--- +#### _mutex +```cpp +std::mutex _mutex +``` +## RunnableQueue + +> **Extends:** `scy::Queue< T * >`, `scy::basic::Runnable` +> **Subclasses:** `scy::AsyncQueue< IPacket >`, `scy::AsyncQueue< PacketT >`, `scy::SyncQueue< IPacket >`, `scy::AsyncQueue< T >`, `scy::SyncQueue< T >` +> **Defined in:** `queue.h` + +### Members + +| Name | Description | +|------|-------------| +| [`RunnableQueue`](#group__base_1ga04ba6cebdaf72214752e3cb1ce867461) | | +| [`~RunnableQueue`](#group__base_1ga52f804f6571e308e1dcba1c948969c23) | | +| [`push`](#group__base_1gac870c5b8456c3509e144517d055757dd) | Push an item onto the queue. The queue takes ownership of the item pointer. | +| [`flush`](#group__base_1gaacc8fe709fdfef37c09b0a4b4223435e) | Flush all outgoing items. | +| [`clear`](#group__base_1ga5a36945ff1d15379b4ae6de4046fb05c) | | +| [`run`](#group__base_1ga372c52aa2d9b4c33f9b620dfb2c2af23) | Called asynchronously to dispatch queued items. If not timeout is set this method blocks until [cancel()](#group__base_1ga0443ed87de7952461d0948c88c8b003f) is called, otherwise [runTimeout()](#group__base_1ga834803a488030d079458bc67563ce927) will be called. Pseudo protected for std::bind compatability. | +| [`runTimeout`](#group__base_1ga834803a488030d079458bc67563ce927) | Called asynchronously to dispatch queued items until the queue is empty or the timeout expires. Pseudo protected for std::bind compatability. | +| [`dispatch`](#group__base_1gac8b4857c7505c81466387b3dc29c39e0) | Dispatch a single item to listeners. | +| [`timeout`](#group__base_1ga77f03651312f779c34fe066e1625f7b5) | | +| [`setTimeout`](#group__base_1gad0dfa024d9a58c4d98191c2fa52b8778) | | +| [`RunnableQueue`](#group__base_1ga002019b63e3d4e0c2f978ab5fa27682d) | | +| [`operator=`](#group__base_1ga00552f5279e435b0beb97e8d98c70898) | | +| [`popNext`](#group__base_1ga49f0c25f9709b4be2b934265244cade9) | Pops the next waiting item. | +| [`dispatchNext`](#group__base_1ga94ba51c70d311ed6ac2e8310de616e85) | Pops and dispatches the next waiting item. | +| [`ondispatch`](#group__base_1gaffe98a4f91bf2bc8131b59cb94006c9b) | The default dispatch function. Must be set before the queue is running. | +| [`_limit`](#group__base_1gac4231be4ccc33b05adef9052c6b70938) | | +| [`_timeout`](#group__base_1ga21cf39b5892920945baa2b2fff5c14e4) | | +| [`_mutex`](#group__base_1ga81f6b512f77af4e07e110c45db23f0b8) | | + +--- + +#### RunnableQueue + +```cpp +inline RunnableQueue(int limit, int timeout) +``` -#### `protected std::int64_t _timeout` +| Parameter | Type | Description | +|-----------|------|-------------| +| `limit` | `int` | | +| `timeout` | `int` | | +--- +#### ~RunnableQueue +```cpp +virtual inline ~RunnableQueue() +``` +--- -#### `protected std::int64_t _interval` +#### push +```cpp +virtual inline void push(T * item) +``` +Push an item onto the queue. The queue takes ownership of the item pointer. +| Parameter | Type | Description | +|-----------|------|-------------| +| `item` | `T *` | | +--- -#### `protected std::int64_t _count` +#### flush +```cpp +virtual inline void flush() +``` +Flush all outgoing items. +--- +#### clear -#### `protected Timer(const `[`Timer`](#classscy_1_1Timer)` &) = delete` +```cpp +inline void clear() +``` +--- +#### run +```cpp +virtual inline void run() +``` +Called asynchronously to dispatch queued items. If not timeout is set this method blocks until [cancel()](#group__base_1ga0443ed87de7952461d0948c88c8b003f) is called, otherwise [runTimeout()](#group__base_1ga834803a488030d079458bc67563ce927) will be called. Pseudo protected for std::bind compatability. -#### `protected `[`Timer`](#classscy_1_1Timer)` & operator=(const `[`Timer`](#classscy_1_1Timer)` &) = delete` +--- +#### runTimeout +```cpp +virtual inline void runTimeout() +``` +Called asynchronously to dispatch queued items until the queue is empty or the timeout expires. Pseudo protected for std::bind compatability. +--- -#### `protected virtual void init()` +#### dispatch +```cpp +virtual inline void dispatch(T & item) +``` +Dispatch a single item to listeners. +| Parameter | Type | Description | +|-----------|------|-------------| +| `item` | `T &` | | +--- -# class `scy::Timespan` +#### timeout +```cpp +inline int timeout() +``` -A class that represents time spans up to microsecond resolution. +--- +#### setTimeout +```cpp +inline void setTimeout(int milliseconds) +``` -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public Timespan()` | Creates a zero [Timespan](./doc/api-base.md#classscy_1_1Timespan). -`public Timespan(TimeDiff microseconds)` | Creates a [Timespan](./doc/api-base.md#classscy_1_1Timespan). -`public Timespan(long seconds,long microseconds)` | -`public Timespan(int days,int hours,int minutes,int seconds,int microseconds)` | Creates a [Timespan](./doc/api-base.md#classscy_1_1Timespan). -`public Timespan(const `[`Timespan`](#classscy_1_1Timespan)` & timespan)` | Creates a [Timespan](./doc/api-base.md#classscy_1_1Timespan) from another one. -`public ~Timespan()` | Destroys the [Timespan](./doc/api-base.md#classscy_1_1Timespan). -`public `[`Timespan`](#classscy_1_1Timespan)` & operator=(const `[`Timespan`](#classscy_1_1Timespan)` & timespan)` | Assignment operator. -`public `[`Timespan`](#classscy_1_1Timespan)` & operator=(TimeDiff microseconds)` | Assignment operator. -`public `[`Timespan`](#classscy_1_1Timespan)` & assign(int days,int hours,int minutes,int seconds,int microseconds)` | Assigns a new span. -`public `[`Timespan`](#classscy_1_1Timespan)` & assign(long seconds,long microseconds)` | -`public void swap(`[`Timespan`](#classscy_1_1Timespan)` & timespan)` | Swaps the [Timespan](./doc/api-base.md#classscy_1_1Timespan) with another one. -`public inline bool operator==(const `[`Timespan`](#classscy_1_1Timespan)` & ts) const` | -`public inline bool operator!=(const `[`Timespan`](#classscy_1_1Timespan)` & ts) const` | -`public inline bool operator>(const `[`Timespan`](#classscy_1_1Timespan)` & ts) const` | -`public inline bool operator>=(const `[`Timespan`](#classscy_1_1Timespan)` & ts) const` | -`public inline bool operator<(const `[`Timespan`](#classscy_1_1Timespan)` & ts) const` | -`public inline bool operator<=(const `[`Timespan`](#classscy_1_1Timespan)` & ts) const` | -`public inline bool operator==(TimeDiff microseconds) const` | -`public inline bool operator!=(TimeDiff microseconds) const` | -`public inline bool operator>(TimeDiff microseconds) const` | -`public inline bool operator>=(TimeDiff microseconds) const` | -`public inline bool operator<(TimeDiff microseconds) const` | -`public inline bool operator<=(TimeDiff microseconds) const` | -`public `[`Timespan`](#classscy_1_1Timespan)` operator+(const `[`Timespan`](#classscy_1_1Timespan)` & d) const` | -`public `[`Timespan`](#classscy_1_1Timespan)` operator-(const `[`Timespan`](#classscy_1_1Timespan)` & d) const` | -`public `[`Timespan`](#classscy_1_1Timespan)` & operator+=(const `[`Timespan`](#classscy_1_1Timespan)` & d)` | -`public `[`Timespan`](#classscy_1_1Timespan)` & operator-=(const `[`Timespan`](#classscy_1_1Timespan)` & d)` | -`public `[`Timespan`](#classscy_1_1Timespan)` operator+(TimeDiff microseconds) const` | -`public `[`Timespan`](#classscy_1_1Timespan)` operator-(TimeDiff microseconds) const` | -`public `[`Timespan`](#classscy_1_1Timespan)` & operator+=(TimeDiff microseconds)` | -`public `[`Timespan`](#classscy_1_1Timespan)` & operator-=(TimeDiff microseconds)` | -`public inline int days() const` | Returns the number of days. -`public inline int hours() const` | Returns the number of hours (0 to 23). -`public inline int totalHours() const` | Returns the total number of hours. -`public inline int minutes() const` | Returns the number of minutes (0 to 59). -`public inline int totalMinutes() const` | Returns the total number of minutes. -`public inline int seconds() const` | Returns the number of seconds (0 to 59). -`public inline int totalSeconds() const` | Returns the total number of seconds. -`public inline int milliseconds() const` | Returns the number of milliseconds (0 to 999). -`public inline TimeDiff totalMilliseconds() const` | Returns the total number of milliseconds. -`public inline int microseconds() const` | -`public inline int useconds() const` | -`public inline TimeDiff totalMicroseconds() const` | Returns the total number of microseconds. - -## Members - -#### `public Timespan()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `milliseconds` | `int` | | -Creates a zero [Timespan](#classscy_1_1Timespan). +--- +#### RunnableQueue +```cpp +RunnableQueue(const RunnableQueue &) = delete +``` -#### `public Timespan(TimeDiff microseconds)` +--- -Creates a [Timespan](#classscy_1_1Timespan). +#### operator= +```cpp +RunnableQueue & operator=(const RunnableQueue &) = delete +``` +--- -#### `public Timespan(long seconds,long microseconds)` +#### popNext +```cpp +virtual inline T * popNext() +``` +Pops the next waiting item. -Creates a [Timespan](#classscy_1_1Timespan). Useful for creating a [Timespan](#classscy_1_1Timespan) from a struct timeval. +--- -#### `public Timespan(int days,int hours,int minutes,int seconds,int microseconds)` +#### dispatchNext -Creates a [Timespan](#classscy_1_1Timespan). +```cpp +virtual inline bool dispatchNext() +``` +Pops and dispatches the next waiting item. +--- -#### `public Timespan(const `[`Timespan`](#classscy_1_1Timespan)` & timespan)` +#### ondispatch -Creates a [Timespan](#classscy_1_1Timespan) from another one. +```cpp +std::function< void(T &)> ondispatch +``` +The default dispatch function. Must be set before the queue is running. +--- -#### `public ~Timespan()` +#### _limit -Destroys the [Timespan](#classscy_1_1Timespan). +```cpp +int _limit +``` +--- +#### _timeout -#### `public `[`Timespan`](#classscy_1_1Timespan)` & operator=(const `[`Timespan`](#classscy_1_1Timespan)` & timespan)` +```cpp +int _timeout +``` -Assignment operator. +--- +#### _mutex +```cpp +std::mutex _mutex +``` -#### `public `[`Timespan`](#classscy_1_1Timespan)` & operator=(TimeDiff microseconds)` +## SyncQueue -Assignment operator. +> **Extends:** `scy::RunnableQueue< T >` +> **Subclasses:** `scy::SyncPacketQueue< T >` +> **Defined in:** `queue.h` +[SyncQueue](#classscy_1_1SyncQueue) extends [Synchronizer](#classscy_1_1Synchronizer) to implement a synchronized FIFO queue which receives T objects from any thread and synchronizes them for safe consumption by the associated event loop. +### Members -#### `public `[`Timespan`](#classscy_1_1Timespan)` & assign(int days,int hours,int minutes,int seconds,int microseconds)` +| Name | Description | +|------|-------------| +| [`SyncQueue`](#group__base_1gae1cf6a31580baa5e4455d193ba3c0b54) | | +| [`~SyncQueue`](#group__base_1ga9539ee4bbac1c32eb8c315a15ee0c9b3) | Destruction is deferred to allow enough time for all callbacks to return. | +| [`push`](#group__base_1ga807c4a3d7d9adf4c15fd9b78121ca830) | Pushes an item onto the queue. Item pointers are now managed by the [SyncQueue](#classscy_1_1SyncQueue). | +| [`cancel`](#group__base_1gafd7fe7eff78132084172f272e76c37b7) | | +| [`sync`](#group__base_1ga1e3c839536b14db6be1846e40cd16fd4) | | +| [`_sync`](#group__base_1gacf0e3e74f572918437858efc1f769a26) | | -Assigns a new span. +--- +#### SyncQueue +```cpp +inline SyncQueue(uv::Loop * loop, int limit, int timeout) +``` -#### `public `[`Timespan`](#classscy_1_1Timespan)` & assign(long seconds,long microseconds)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `loop` | `uv::Loop *` | | +| `limit` | `int` | | +| `timeout` | `int` | | +--- +#### ~SyncQueue -Assigns a new span. Useful for assigning from a struct timeval. +```cpp +virtual inline ~SyncQueue() +``` -#### `public void swap(`[`Timespan`](#classscy_1_1Timespan)` & timespan)` +Destruction is deferred to allow enough time for all callbacks to return. -Swaps the [Timespan](#classscy_1_1Timespan) with another one. +--- +#### push +```cpp +virtual inline void push(T * item) +``` -#### `public inline bool operator==(const `[`Timespan`](#classscy_1_1Timespan)` & ts) const` +Pushes an item onto the queue. Item pointers are now managed by the [SyncQueue](#classscy_1_1SyncQueue). +| Parameter | Type | Description | +|-----------|------|-------------| +| `item` | `T *` | | +--- +#### cancel +```cpp +virtual inline void cancel() +``` -#### `public inline bool operator!=(const `[`Timespan`](#classscy_1_1Timespan)` & ts) const` +--- +#### sync +```cpp +inline Synchronizer & sync() +``` +--- +#### _sync -#### `public inline bool operator>(const `[`Timespan`](#classscy_1_1Timespan)` & ts) const` +```cpp +Synchronizer _sync +``` +## AsyncQueue +> **Extends:** `scy::RunnableQueue< T >` +> **Subclasses:** `scy::AsyncPacketQueue< PacketT >`, `scy::AsyncPacketQueue< T >` +> **Defined in:** `queue.h` +[AsyncQueue](#classscy_1_1AsyncQueue) is a thread-based queue which receives packets from any thread source and dispatches them asynchronously. +This queue is useful for deferring load from operation critical system devices before performing long running tasks. -#### `public inline bool operator>=(const `[`Timespan`](#classscy_1_1Timespan)` & ts) const` +The thread will call the [RunnableQueue](#classscy_1_1RunnableQueue)'s [run()](#group__base_1ga372c52aa2d9b4c33f9b620dfb2c2af23) method to constantly flush outgoing packets until [cancel()](#group__base_1ga0096428c7d684eb39f378784ee868fa1) is called. +### Members +| Name | Description | +|------|-------------| +| [`AsyncQueue`](#group__base_1ga1e59a5d7850526b3bb9226e707552a87) | | +| [`cancel`](#group__base_1ga0096428c7d684eb39f378784ee868fa1) | | +| [`~AsyncQueue`](#group__base_1gad02ee332589a016e4864aba8e75b3194) | | +| [`_thread`](#group__base_1ga43d70d35f82a4c1286108cc14b6b8066) | | +--- +#### AsyncQueue -#### `public inline bool operator<(const `[`Timespan`](#classscy_1_1Timespan)` & ts) const` +```cpp +inline AsyncQueue(int limit) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `limit` | `int` | | +--- +#### cancel +```cpp +virtual inline void cancel() +``` -#### `public inline bool operator<=(const `[`Timespan`](#classscy_1_1Timespan)` & ts) const` +--- +#### ~AsyncQueue +```cpp +virtual inline ~AsyncQueue() +``` +--- +#### _thread -#### `public inline bool operator==(TimeDiff microseconds) const` +```cpp +Thread _thread +``` +## Random +> **Defined in:** `random.h` +[Random](#classscy_1_1Random) implements a pseudo random number generator (PRNG). The PRNG is a nonlinear additive feedback random number generator using 256 bytes of state information and a period of up to 2^69. +### Members + +| Name | Description | +|------|-------------| +| [`Type`](#group__base_1gafda9e80241e992379938503a8d5bb9ae) | | +| [``](#group__base_1ga87e817337573c060b8dd31a319069ef1) | | +| [`Random`](#group__base_1ga658f3a6766a2f0207f378aef3e6a5f79) | Creates and initializes the PRNG. Specify either a state buffer size (8 to 256 bytes) or one of the Type values. | +| [`~Random`](#group__base_1gae5781de4f82f83eb1d90b6a44a3d6a8f) | Destroys the PRNG. | +| [`seed`](#group__base_1ga7ed905c8f70572e16fc55f5afaaccf98) | Seeds the pseudo random generator with the given seed. | +| [`seed`](#group__base_1ga088b5bbefdc56704ad059271355d0087) | Seeds the pseudo random generator with a random seed obtained from a RandomInputStream. | +| [`next`](#group__base_1ga7251a36332b0ed1e2dcc0cde2d484f29) | Returns the next 31-bit pseudo random number. | +| [`next`](#group__base_1ga326e0f261aa051c98cf495f0b1f52da7) | Returns the next 31-bit pseudo random number modulo n. | +| [`nextChar`](#group__base_1ga539b6e8002927588265e941ff166d6ae) | Returns the next pseudo random character. | +| [`nextBool`](#group__base_1gadc7c49f9a915ca4c8af9527bceefbffb) | Returns the next boolean pseudo random value. | +| [`nextFloat`](#group__base_1gac6ac62ca9dfb0e6566c3b8078a661032) | Returns the next float pseudo random number between 0.0 and 1.0. | +| [`nextDouble`](#group__base_1gadba7f18dddf46b7b34deeddf57fa5f74) | Returns the next double pseudo random number between 0.0 and 1.0. | +| [`getSeed`](#group__base_1ga1c11a090bf29cb6f69e8c389d1eee114) | Generates a random seed using native OS functions. | +| [`initState`](#group__base_1ga4eb708ad8fbe9515b56501dcaa1c7940) | | +| [`goodRand`](#group__base_1ga087d152820fd220b26bfcfe6d3863132) | | +| [`_fptr`](#group__base_1ga4934f0731699b432415c424c1925d957) | | +| [`_rptr`](#group__base_1ga962a0cedac6a414b67edb313e289c073) | | +| [`_state`](#group__base_1ga4b2bad7a096c8871073fa372491ca88c) | | +| [`_randType`](#group__base_1ga0308d48427d49885271c4e0b98e9ba63) | | +| [`_randDeg`](#group__base_1ga09d0b983160aa081c30c26d140ccf0d7) | | +| [`_randSep`](#group__base_1gadad904ab8da1d3dbdc91721b2c593825) | | +| [`_endPtr`](#group__base_1gaae39b7248a27747ba740f49eca8e6821) | | +| [`_buffer`](#group__base_1ga76382c414bf0465627c388c287c4873a) | | + +--- + +#### Type + +```cpp +enum Type +``` -#### `public inline bool operator!=(TimeDiff microseconds) const` +| Value | Description | +|-------|-------------| +| `RND_STATE_0` | | +| `RND_STATE_32` | linear congruential | +| `RND_STATE_64` | x**7 + x**3 + 1 | +| `RND_STATE_128` | x**15 + x + 1 | +| `RND_STATE_256` | x**31 + x**3 + 1 | +--- +#### +```cpp +enum +``` +| Value | Description | +|-------|-------------| +| `MAX_TYPES` | | +| `NSHUFF` | | -#### `public inline bool operator>(TimeDiff microseconds) const` +--- +#### Random +```cpp +Random(int stateSize) +``` +Creates and initializes the PRNG. Specify either a state buffer size (8 to 256 bytes) or one of the Type values. +| Parameter | Type | Description | +|-----------|------|-------------| +| `stateSize` | `int` | | -#### `public inline bool operator>=(TimeDiff microseconds) const` +--- +#### ~Random +```cpp +~Random() +``` +Destroys the PRNG. +--- -#### `public inline bool operator<(TimeDiff microseconds) const` +#### seed +```cpp +void seed(uint32_t seed) +``` +Seeds the pseudo random generator with the given seed. +| Parameter | Type | Description | +|-----------|------|-------------| +| `seed` | `uint32_t` | | +--- -#### `public inline bool operator<=(TimeDiff microseconds) const` +#### seed +```cpp +void seed() +``` +Seeds the pseudo random generator with a random seed obtained from a RandomInputStream. +--- +#### next -#### `public `[`Timespan`](#classscy_1_1Timespan)` operator+(const `[`Timespan`](#classscy_1_1Timespan)` & d) const` +```cpp +uint32_t next() +``` +Returns the next 31-bit pseudo random number. +--- +#### next +```cpp +uint32_t next(uint32_t n) +``` -#### `public `[`Timespan`](#classscy_1_1Timespan)` operator-(const `[`Timespan`](#classscy_1_1Timespan)` & d) const` +Returns the next 31-bit pseudo random number modulo n. +| Parameter | Type | Description | +|-----------|------|-------------| +| `n` | `uint32_t` | | +--- +#### nextChar +```cpp +char nextChar() +``` -#### `public `[`Timespan`](#classscy_1_1Timespan)` & operator+=(const `[`Timespan`](#classscy_1_1Timespan)` & d)` +Returns the next pseudo random character. +--- +#### nextBool +```cpp +bool nextBool() +``` +Returns the next boolean pseudo random value. -#### `public `[`Timespan`](#classscy_1_1Timespan)` & operator-=(const `[`Timespan`](#classscy_1_1Timespan)` & d)` +--- +#### nextFloat +```cpp +float nextFloat() +``` +Returns the next float pseudo random number between 0.0 and 1.0. +--- -#### `public `[`Timespan`](#classscy_1_1Timespan)` operator+(TimeDiff microseconds) const` +#### nextDouble +```cpp +double nextDouble() +``` +Returns the next double pseudo random number between 0.0 and 1.0. +--- +#### getSeed -#### `public `[`Timespan`](#classscy_1_1Timespan)` operator-(TimeDiff microseconds) const` +```cpp +static void getSeed(char * seed, unsigned length) +``` +Generates a random seed using native OS functions. +| Parameter | Type | Description | +|-----------|------|-------------| +| `seed` | `char *` | | +| `length` | `unsigned` | | +--- +#### initState -#### `public `[`Timespan`](#classscy_1_1Timespan)` & operator+=(TimeDiff microseconds)` +```cpp +void initState(uint32_t seed, char * arg_state, std::int32_t n) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `seed` | `uint32_t` | | +| `arg_state` | `char *` | | +| `n` | `std::int32_t` | | +--- +#### goodRand +```cpp +static uint32_t goodRand(std::int32_t x) +``` -#### `public `[`Timespan`](#classscy_1_1Timespan)` & operator-=(TimeDiff microseconds)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `x` | `std::int32_t` | | +--- +#### _fptr +```cpp +uint32_t * _fptr +``` +--- -#### `public inline int days() const` +#### _rptr -Returns the number of days. +```cpp +uint32_t * _rptr +``` +--- +#### _state -#### `public inline int hours() const` +```cpp +uint32_t * _state +``` -Returns the number of hours (0 to 23). +--- +#### _randType +```cpp +int _randType +``` -#### `public inline int totalHours() const` +--- -Returns the total number of hours. +#### _randDeg +```cpp +int _randDeg +``` +--- -#### `public inline int minutes() const` +#### _randSep -Returns the number of minutes (0 to 59). +```cpp +int _randSep +``` +--- +#### _endPtr -#### `public inline int totalMinutes() const` +```cpp +uint32_t * _endPtr +``` -Returns the total number of minutes. +--- +#### _buffer +```cpp +std::unique_ptr< char[]> _buffer +``` -#### `public inline int seconds() const` +## Runner -Returns the number of seconds (0 to 59). +> **Subclasses:** `scy::Idler`, `scy::Synchronizer`, `scy::Thread`, `scy::Thread`, `scy::Timer` +> **Defined in:** `runner.h` +[Runner](#classscy_1_1Runner) is a virtual interface for implementing asynchronous objects such as threads and futures. +### Members + +| Name | Description | +|------|-------------| +| [`Runner`](#group__base_1ga4c9c5568422630b80d7bcec186d7f9ae) | | +| [`~Runner`](#group__base_1gabfc107d7db7140257b4dfa2a4e2cd647) | | +| [`start`](#group__base_1gabe54278718ed31b12d3f97e2e57c56ed) | Start the asynchronous context with the given invokeback. | +| [`running`](#group__base_1ga82d2c9fecae021a80e3568fc440ba446) | Returns true if the async context is currently running. | +| [`cancel`](#group__base_1ga679d52263009759d6c7fd77c53972a0a) | Cancels the async context. | +| [`cancelled`](#group__base_1ga5374eaf1369a6623367db28f9472e956) | True when the task has been cancelled. It is up to the implementation to return at the earliest possible time. | +| [`repeating`](#group__base_1gaebdf1e6504e226fc910cd839b4bc1e51) | Returns true if the [Runner](#classscy_1_1Runner) is operating in repeating mode. | +| [`setRepeating`](#group__base_1ga12c1000762cde5b41c2412ba9172d436) | This setting means the implementation should invoke the target function repeatedly until cancelled. The importance of this method to normalize the functionality of threadded and event loop driven [Runner](#classscy_1_1Runner) models. | +| [`async`](#group__base_1ga61903ea9f01179265132953f56ca8a3b) | Returns true if the implementation is thread-based, or false if it belongs to an event loop. | +| [`tid`](#group__base_1ga8c0368bae16c191ce1f4effd1003fccd) | Return the native thread ID. | +| [`waitForExit`](#group__base_1ga871cd630b94c2bafee226866b52b0c9c) | Wait until the thread exits. | +| [`Runner`](#group__base_1ga6f3ded568733fb97244b4f51ffd0ea2c) | NonCopyable and NonMovable. | +| [`operator=`](#group__base_1gaf76d61099580638ce024f452decf76f4) | | +| [`_context`](#group__base_1ga2dea91abc5566c9a613c6cdf253f6aa0) | Shared pointer to the internal [Context](#structscy_1_1Runner_1_1Context). | + +--- + +#### Runner + +```cpp +Runner() +``` -#### `public inline int totalSeconds() const` +--- -Returns the total number of seconds. +#### ~Runner +```cpp +virtual ~Runner() +``` +--- -#### `public inline int milliseconds() const` +#### start -Returns the number of milliseconds (0 to 999). +```cpp +void start(std::function< void()> target) +``` +Start the asynchronous context with the given invokeback. +The target `Runnable` instance must outlive the `[Runner](#classscy_1_1Runner)`. -#### `public inline TimeDiff totalMilliseconds() const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `target` | `std::function< void()>` | | -Returns the total number of milliseconds. +--- +#### running +```cpp +bool running() const +``` -#### `public inline int microseconds() const` +Returns true if the async context is currently running. +--- +#### cancel -Returns the fractions of a millisecond in microseconds (0 to 999). +```cpp +void cancel() +``` -#### `public inline int useconds() const` +Cancels the async context. +--- +#### cancelled -Returns the fractions of a second in microseconds (0 to 999999). +```cpp +bool cancelled() const +``` -#### `public inline TimeDiff totalMicroseconds() const` +True when the task has been cancelled. It is up to the implementation to return at the earliest possible time. -Returns the total number of microseconds. +--- +#### repeating +```cpp +bool repeating() const +``` -# class `scy::Timestamp` +Returns true if the [Runner](#classscy_1_1Runner) is operating in repeating mode. +--- +#### setRepeating +```cpp +void setRepeating(bool flag) +``` -A [Timestamp](#classscy_1_1Timestamp) stores a monotonic* time value with (theoretical) microseconds resolution. Timestamps can be compared with each other and simple arithmetics are supported. +This setting means the implementation should invoke the target function repeatedly until cancelled. The importance of this method to normalize the functionality of threadded and event loop driven [Runner](#classscy_1_1Runner) models. -[*] Note that [Timestamp](#classscy_1_1Timestamp) values are only monotonic as long as the systems's clock is monotonic as well (and not, e.g. set back). +| Parameter | Type | Description | +|-----------|------|-------------| +| `flag` | `bool` | | -Timestamps are UTC (Coordinated Universal Time) based and thus independent of the timezone in effect on the system. +--- -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public Timestamp()` | Creates a timestamp with the current time. -`public Timestamp(`[`TimeVal`](#group__base_1ga7da2b2da9cd1e096cbb146da027f17dc)` tv)` | Creates a timestamp from the given time value. -`public Timestamp(const `[`Timestamp`](#classscy_1_1Timestamp)` & other)` | Copy constructor. -`public ~Timestamp()` | Destroys the timestamp. -`public `[`Timestamp`](#classscy_1_1Timestamp)` & operator=(const `[`Timestamp`](#classscy_1_1Timestamp)` & other)` | -`public `[`Timestamp`](#classscy_1_1Timestamp)` & operator=(`[`TimeVal`](#group__base_1ga7da2b2da9cd1e096cbb146da027f17dc)` tv)` | -`public void swap(`[`Timestamp`](#classscy_1_1Timestamp)` & timestamp)` | Swaps the [Timestamp](./doc/api-base.md#classscy_1_1Timestamp) with another one. -`public void update()` | Updates the [Timestamp](./doc/api-base.md#classscy_1_1Timestamp) with the current time. -`public inline bool operator==(const `[`Timestamp`](#classscy_1_1Timestamp)` & ts) const` | -`public inline bool operator!=(const `[`Timestamp`](#classscy_1_1Timestamp)` & ts) const` | -`public inline bool operator>(const `[`Timestamp`](#classscy_1_1Timestamp)` & ts) const` | -`public inline bool operator>=(const `[`Timestamp`](#classscy_1_1Timestamp)` & ts) const` | -`public inline bool operator<(const `[`Timestamp`](#classscy_1_1Timestamp)` & ts) const` | -`public inline bool operator<=(const `[`Timestamp`](#classscy_1_1Timestamp)` & ts) const` | -`public inline `[`Timestamp`](#classscy_1_1Timestamp)` operator+(`[`TimeDiff`](#group__base_1ga9f06831e4e9b9cbc6f061cc61dc91fd0)` d) const` | -`public inline `[`Timestamp`](#classscy_1_1Timestamp)` operator-(`[`TimeDiff`](#group__base_1ga9f06831e4e9b9cbc6f061cc61dc91fd0)` d) const` | -`public inline `[`TimeDiff`](#group__base_1ga9f06831e4e9b9cbc6f061cc61dc91fd0)` operator-(const `[`Timestamp`](#classscy_1_1Timestamp)` & ts) const` | -`public inline `[`Timestamp`](#classscy_1_1Timestamp)` & operator+=(`[`TimeDiff`](#group__base_1ga9f06831e4e9b9cbc6f061cc61dc91fd0)` d)` | -`public inline `[`Timestamp`](#classscy_1_1Timestamp)` & operator-=(`[`TimeDiff`](#group__base_1ga9f06831e4e9b9cbc6f061cc61dc91fd0)` d)` | -`public inline std::time_t epochTime() const` | -`public inline `[`UtcTimeVal`](#group__base_1gaec8ace0f25db0ce91c10b30270c3dc24)` utcTime() const` | -`public inline `[`TimeVal`](#group__base_1ga7da2b2da9cd1e096cbb146da027f17dc)` epochMicroseconds() const` | -`public inline `[`TimeDiff`](#group__base_1ga9f06831e4e9b9cbc6f061cc61dc91fd0)` elapsed() const` | -`public inline bool isElapsed(`[`TimeDiff`](#group__base_1ga9f06831e4e9b9cbc6f061cc61dc91fd0)` interval) const` | - -## Members - -#### `public Timestamp()` +#### async -Creates a timestamp with the current time. +```cpp +bool async() const +``` +Returns true if the implementation is thread-based, or false if it belongs to an event loop. +--- -#### `public Timestamp(`[`TimeVal`](#group__base_1ga7da2b2da9cd1e096cbb146da027f17dc)` tv)` +#### tid -Creates a timestamp from the given time value. +```cpp +std::thread::id tid() const +``` +Return the native thread ID. +--- -#### `public Timestamp(const `[`Timestamp`](#classscy_1_1Timestamp)` & other)` +#### waitForExit -Copy constructor. +```cpp +bool waitForExit(int timeout) +``` +Wait until the thread exits. +The thread should be cancelled beore invokeing this method. This method must be invokeed from outside the current thread context or deadlock will ensue. -#### `public ~Timestamp()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `timeout` | `int` | | -Destroys the timestamp. +--- +#### Runner +```cpp +Runner(const Runner &) = delete +``` -#### `public `[`Timestamp`](#classscy_1_1Timestamp)` & operator=(const `[`Timestamp`](#classscy_1_1Timestamp)` & other)` +NonCopyable and NonMovable. +--- +#### operator= +```cpp +Runner & operator=(const Runner &) = delete +``` +--- -#### `public `[`Timestamp`](#classscy_1_1Timestamp)` & operator=(`[`TimeVal`](#group__base_1ga7da2b2da9cd1e096cbb146da027f17dc)` tv)` +#### _context +```cpp +std::shared_ptr< Context > _context +``` +Shared pointer to the internal [Context](#structscy_1_1Runner_1_1Context). +## Context +> **Defined in:** `runner.h` -#### `public void swap(`[`Timestamp`](#classscy_1_1Timestamp)` & timestamp)` +[Context](#structscy_1_1Runner_1_1Context) object which we send to the thread context. -Swaps the [Timestamp](#classscy_1_1Timestamp) with another one. +This intermediate object allows us to garecefully handle late invokebacks and so avoid the need for deferred destruction of `[Runner](#classscy_1_1Runner)` objects. +### Members +| Name | Description | +|------|-------------| +| [`reset`](#group__base_1ga85d58cf01bb21e0f0280ee99f5053dfb) | | +| [`Context`](#group__base_1ga8b65b067b317daa79442b0235f22df77) | | +| [`tid`](#group__base_1gaa43dd023235e42c86f9aa2b5d2d3211b) | | +| [`running`](#group__base_1ga26e1db2bf00f40be908b6facce006e4f) | | +| [`cancelled`](#group__base_1ga66278b215dabb449abe3f1f5a5afd8cb) | | +| [`repeating`](#group__base_1ga2a3f06bbc8956c474960af89e3d6a0b1) | | -#### `public void update()` +--- -Updates the [Timestamp](#classscy_1_1Timestamp) with the current time. +#### reset +```cpp +inline void reset() +``` +--- -#### `public inline bool operator==(const `[`Timestamp`](#classscy_1_1Timestamp)` & ts) const` +#### Context +```cpp +inline Context() +``` +--- +#### tid +```cpp +std::thread::id tid +``` -#### `public inline bool operator!=(const `[`Timestamp`](#classscy_1_1Timestamp)` & ts) const` +--- +#### running +```cpp +std::atomic< bool > running +``` +--- +#### cancelled -#### `public inline bool operator>(const `[`Timestamp`](#classscy_1_1Timestamp)` & ts) const` +```cpp +std::atomic< bool > cancelled +``` +--- +#### repeating +```cpp +bool repeating = false +``` +## StopPropagation -#### `public inline bool operator>=(const `[`Timestamp`](#classscy_1_1Timestamp)` & ts) const` +> **Extends:** `std::exception` +> **Defined in:** `signal.h` +Exception to break out of the current [Signal](#classscy_1_1Signal) callback scope. +### Members +| Name | Description | +|------|-------------| +| [`~StopPropagation`](#group__base_1ga62918948c39bc8a834fda3faaa498d7b) | | +--- -#### `public inline bool operator<(const `[`Timestamp`](#classscy_1_1Timestamp)` & ts) const` +#### ~StopPropagation +```cpp +virtual ~StopPropagation() = default +``` +## Signal +[Signal](#classscy_1_1Signal) and slots implementation. +To create a signal, declare member variables of type `[Signal](#classscy_1_1Signal)<...>` in your class. The template parameter is the argument types that will be passed to the callback functions. -#### `public inline bool operator<=(const `[`Timestamp`](#classscy_1_1Timestamp)` & ts) const` +Here's a simple example with a class `MyClass` that has a single signal `my_signal` which takes a single `int` argument: class MyClass +{ +public: + Signal my_signal; + ... +}; + To connect to a signal, call its `attach()` member function, passing a function (in the `std::function` sense) as the argument. The function can be a function pointer, a functor object, or an anonymous lambda function. +Here's an example connecting to the above signal to a lambda function: MyClass my_class; +my_class.my_signal.attach([](int x) { + cout << "value: " << x << endl; +}); + The `attach()` function returns a unique ID of type `int` which can be used later to disconnect the callback function. +Here's an example using the above code to then immediately disconnect the signal connection with the `detach()` member function: MyClass my_class; +auto id = my_class.my_signal.attach([](int x) { + cout << "value: " << x << endl; +}); +my_class.my_signal.detach(id); + The `detach()` function is passed the callback ID and will return `true` if a callback was disconnected or `false` if the ID wasn't found. Note that `detach()` can be safely called from within the callback scope. +In the case of class members there is a `[slot()](#group__base_1gac8a25d21946945c9244ec49f540177c1)` helper that can be used to bind the signal like so: class TargetClass +{ +public: + Signal my_signal; + int print(int x) + { + cout << "say: " << x << endl; + } +}; -#### `public inline `[`Timestamp`](#classscy_1_1Timestamp)` operator+(`[`TimeDiff`](#group__base_1ga9f06831e4e9b9cbc6f061cc61dc91fd0)` d) const` +MyClass my_class; +TargetClass target_class; +my_class.my_signal += slot(&target_class, &TargetClass::print) + The `[slot()](#group__base_1gac8a25d21946945c9244ec49f540177c1)` helper can also be used to disconnect class member callbacks like so: my_class.my_signal -= slot(&target_class, &TargetClass::print) + To emit the signal, call its `emit()` member function passing arguments matching the types of those in the signal variable declaration. +Using the above example code, here's an example showing how to emit `my_signal`: my_class.my_signal.emit(42); + Since the signal was declared to take a single `int` argument, this will cause any callbacks connected to the signal to be called, passing the integer `42` as the only argument. + +## Signal< RT(Args...)> + +> **Defined in:** `signal.h` + +### Members + +| Name | Description | +|------|-------------| +| [`attach`](#group__base_1gac2a3756f75e8e9a1bccb3303ec491dff) | Connects a `lambda` or `std::function` to the `[Signal](#classscy_1_1Signal)`. The returned value can be used to detach the slot. | +| [`attach`](#group__base_1ga77af5fd67dc1c8929ce0041fa1b573d0) | Connects a `SlotPtr` instance to the `[Signal](#classscy_1_1Signal)`. The returned value can be used to detach the slot. | +| [`detach`](#group__base_1gaea38b0b03fb3e5a21d5d9514964e7608) | Detaches a previously attached slot. | +| [`detach`](#group__base_1ga80430b9e160632b7227a1eabfca56213) | Detaches all slots for the given instance. | +| [`detach`](#group__base_1ga2450e3597bcba5e05d70d99d4e8da569) | Detaches all attached functions for the given instance. | +| [`detachAll`](#group__base_1ga587e054f0a2a0c5c478d418490d53972) | Detaches all previously attached functions. | +| [`emit`](#group__base_1ga16ee016345c12463e640b889a618da48) | Emits the signal to all attached functions. | +| [`slots`](#group__base_1gaff2ff00aa6f20acf8a2fbeef57948f5f) | Returns the managed slot list. | +| [`nslots`](#group__base_1ga662662b9450d80b7699bbe2f7c4ae83c) | Returns the number of active slots. | +| [`operator+=`](#group__base_1ga7711cffea5254d8c5ef372f0343e40af) | Convenience operators. | +| [`operator+=`](#group__base_1ga4eb920126905b5f6d5f2bb7fcf8c4477) | | +| [`operator-=`](#group__base_1gab4fd251624562e056ef80c3d15dd5688) | | +| [`operator-=`](#group__base_1ga710960eba97189f8a7981ede5d8b96a2) | | +| [`operator-=`](#group__base_1ga1379909a60fe721c20b601b9f1cd5f62) | | +| [`Signal`](#group__base_1ga5892a3865b373642deff22ebb05b105d) | Default constructor. | +| [`Signal`](#group__base_1gaedc57c0c91f9383f924b9e77239572d6) | Copy constructor. | +| [`operator=`](#group__base_1ga2d05970fba425e5b71a179a7fa7b21c5) | Assignment operator. | +| [`_mutex`](#group__base_1ga8990e916c761cfdd551c9408b8f76100) | | +| [`_slots`](#group__base_1ga73b22c1ee61122fc06510242c04a253f) | | +| [`_lastId`](#group__base_1ga965406210a208b6eb6fa4fe9ad2fb44b) | | + +--- + +#### attach + +```cpp +inline int attach(Function const & func, void * instance, int id, int priority) const +``` +Connects a `lambda` or `std::function` to the `[Signal](#classscy_1_1Signal)`. The returned value can be used to detach the slot. +| Parameter | Type | Description | +|-----------|------|-------------| +| `func` | `Function const &` | | +| `instance` | `void *` | | +| `id` | `int` | | +| `priority` | `int` | | -#### `public inline `[`Timestamp`](#classscy_1_1Timestamp)` operator-(`[`TimeDiff`](#group__base_1ga9f06831e4e9b9cbc6f061cc61dc91fd0)` d) const` +--- +#### attach +```cpp +inline int attach(SlotPtr slot) const +``` +Connects a `SlotPtr` instance to the `[Signal](#classscy_1_1Signal)`. The returned value can be used to detach the slot. +| Parameter | Type | Description | +|-----------|------|-------------| +| `slot` | `SlotPtr` | | -#### `public inline `[`TimeDiff`](#group__base_1ga9f06831e4e9b9cbc6f061cc61dc91fd0)` operator-(const `[`Timestamp`](#classscy_1_1Timestamp)` & ts) const` +--- +#### detach +```cpp +inline bool detach(int id) const +``` +Detaches a previously attached slot. +| Parameter | Type | Description | +|-----------|------|-------------| +| `id` | `int` | | -#### `public inline `[`Timestamp`](#classscy_1_1Timestamp)` & operator+=(`[`TimeDiff`](#group__base_1ga9f06831e4e9b9cbc6f061cc61dc91fd0)` d)` +--- +#### detach +```cpp +inline bool detach(const void * instance) const +``` +Detaches all slots for the given instance. +| Parameter | Type | Description | +|-----------|------|-------------| +| `instance` | `const void *` | | -#### `public inline `[`Timestamp`](#classscy_1_1Timestamp)` & operator-=(`[`TimeDiff`](#group__base_1ga9f06831e4e9b9cbc6f061cc61dc91fd0)` d)` +--- +#### detach +```cpp +inline bool detach(SlotPtr other) const +``` +Detaches all attached functions for the given instance. +| Parameter | Type | Description | +|-----------|------|-------------| +| `other` | `SlotPtr` | | -#### `public inline std::time_t epochTime() const` +--- +#### detachAll +```cpp +inline void detachAll() const +``` -Returns the timestamp expressed in time_t. time_t base time is midnight, January 1, 1970. Resolution is one second. +Detaches all previously attached functions. -#### `public inline `[`UtcTimeVal`](#group__base_1gaec8ace0f25db0ce91c10b30270c3dc24)` utcTime() const` +--- +#### emit +```cpp +virtual inline void emit(Args... args) +``` -Returns the timestamp expressed in UTC-based time. UTC base time is midnight, October 15, 1582. Resolution is 100 nanoseconds. +Emits the signal to all attached functions. -#### `public inline `[`TimeVal`](#group__base_1ga7da2b2da9cd1e096cbb146da027f17dc)` epochMicroseconds() const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `args` | `Args...` | | +--- +#### slots -Returns the timestamp expressed in microseconds since the Unix epoch, midnight, January 1, 1970. +```cpp +inline std::vector< SlotPtr > slots() const +``` -#### `public inline `[`TimeDiff`](#group__base_1ga9f06831e4e9b9cbc6f061cc61dc91fd0)` elapsed() const` +Returns the managed slot list. +--- +#### nslots -Returns the time elapsed since the time denoted by the timestamp. Equivalent to [Timestamp()](#group__base_1ga59eb0caf11a4b42805be30b575c64685) - *this. +```cpp +inline size_t nslots() const +``` -#### `public inline bool isElapsed(`[`TimeDiff`](#group__base_1ga9f06831e4e9b9cbc6f061cc61dc91fd0)` interval) const` +Returns the number of active slots. +--- +#### operator+= -Returns true iff the given interval has passed since the time denoted by the timestamp. +```cpp +inline int operator+=(Function const & func) +``` -# class `scy::Timezone` +Convenience operators. +| Parameter | Type | Description | +|-----------|------|-------------| +| `func` | `Function const &` | | -This class provides information about the current timezone. +--- +#### operator+= +```cpp +inline int operator+=(SlotPtr slot) +``` -## Summary +| Parameter | Type | Description | +|-----------|------|-------------| +| `slot` | `SlotPtr` | | - Members | Descriptions ---------------------------------|--------------------------------------------- +--- -## Members +#### operator-= -# class `scy::TZInfo` +```cpp +inline bool operator-=(int id) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `id` | `int` | | +--- +#### operator-= +```cpp +inline bool operator-=(const void * instance) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `instance` | `const void *` | | -## Summary +--- - Members | Descriptions ---------------------------------|--------------------------------------------- -`public inline TZInfo()` | -`public inline int timeZone()` | -`public inline const char * name(bool dst)` | +#### operator-= -## Members +```cpp +inline bool operator-=(SlotPtr slot) +``` -#### `public inline TZInfo()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `slot` | `SlotPtr` | | +--- +#### Signal +```cpp +inline Signal() +``` +Default constructor. -#### `public inline int timeZone()` +--- +#### Signal +```cpp +inline Signal(const Signal & r) +``` +Copy constructor. +| Parameter | Type | Description | +|-----------|------|-------------| +| `r` | `const Signal &` | | -#### `public inline const char * name(bool dst)` +--- +#### operator= +```cpp +inline Signal & operator=(const Signal & r) +``` +Assignment operator. +| Parameter | Type | Description | +|-----------|------|-------------| +| `r` | `const Signal &` | | -# struct `scy::AbstractDelegate` +--- +#### _mutex +```cpp +std::mutex _mutex +``` +--- -Abstract delegate interface. +#### _slots -The `Delegate` class contains a pointer to a function. This wrapper class is used instead of `std::function` since it is interchangable with fast delegates and also provides an equality operator for comparing the underlying function where supported. +```cpp +std::vector< SlotPtr > _slots +``` -## Summary +--- - Members | Descriptions ---------------------------------|--------------------------------------------- -`public RT operator()(Args... args) const` | -`public bool operator==(const `[`AbstractDelegate`](#structscy_1_1AbstractDelegate)`< RT, Args... > & that) const` | +#### _lastId -## Members +```cpp +int _lastId = 0 +``` -#### `public RT operator()(Args... args) const` +## Singleton +> **Defined in:** `singleton.h` +Helper template class for managing singleton objects allocated on the heap. +### Members +| Name | Description | +|------|-------------| +| [`Singleton`](#group__base_1ga4041a0d028f806012cfe48040f903e76) | | +| [`~Singleton`](#group__base_1gac1e0a1036a9f0eb917e31a4a43a33f8b) | | +| [`get`](#group__base_1ga116fecf0951357c605749cd1ecfcbdf0) | Returns a pointer to the singleton object held by the [Singleton](#classscy_1_1Singleton). The first call to get will instantiate the singleton. | +| [`swap`](#group__base_1ga68ed207f0d38a3a8ba424977b06af3c4) | Swaps the old pointer with the new one and returns the old instance. | +| [`destroy`](#group__base_1ga30845630ba9bebeb153d5519f46e9aef) | Destroys the managed singleton instance. | +| [`_ptr`](#group__base_1ga5de7a3516a5f2f911e6b7e5b29448a65) | | +| [`_m`](#group__base_1gad94e69e7905e096a586d3b5118ce4e8d) | | -#### `public bool operator==(const `[`AbstractDelegate`](#structscy_1_1AbstractDelegate)`< RT, Args... > & that) const` +--- +#### Singleton +```cpp +Singleton() = default +``` +--- +#### ~Singleton -# struct `scy::Bitwise` +```cpp +~Singleton() = default +``` +--- -Container for smart management of bitwise integer flags. +#### get +```cpp +inline S * get() +``` +Returns a pointer to the singleton object held by the [Singleton](#classscy_1_1Singleton). The first call to get will instantiate the singleton. -## Summary +--- - Members | Descriptions ---------------------------------|--------------------------------------------- -`public unsigned data` | -`public inline Bitwise(unsigned flags)` | -`public inline virtual void reset()` | -`public inline virtual void set(unsigned flag)` | -`public inline virtual void add(unsigned flag)` | -`public inline virtual void remove(unsigned flag)` | -`public inline virtual void toggle(unsigned flag)` | -`public inline virtual bool has(unsigned flag) const` | +#### swap -## Members +```cpp +inline S * swap(S * newPtr) +``` -#### `public unsigned data` +Swaps the old pointer with the new one and returns the old instance. +| Parameter | Type | Description | +|-----------|------|-------------| +| `newPtr` | `S *` | | +--- +#### destroy +```cpp +inline void destroy() +``` -#### `public inline Bitwise(unsigned flags)` +Destroys the managed singleton instance. +--- +#### _ptr +```cpp +std::unique_ptr< S, Deleter > _ptr +``` +--- -#### `public inline virtual void reset()` +#### _m +```cpp +std::mutex _m +``` +## Deleter +Custom deleter that can access private destructors via friendship. +### Members -#### `public inline virtual void set(unsigned flag)` +| Name | Description | +|------|-------------| +| [`operator()`](#group__base_1gafef1cfec1d364ba3d428ffb409aed1e8) | | +--- +#### operator() +```cpp +inline void operator()(S * p) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `p` | `S *` | | -#### `public inline virtual void add(unsigned flag)` +## State +> **Subclasses:** `scy::DiagnosticState`, `scy::PacketStreamState`, `scy::TransactionState`, `scy::av::EncoderState`, `scy::pacm::InstallationState`, `scy::sockio::ClientState`, `scy::turn::ClientState` +> **Defined in:** `stateful.h` +[State](#classscy_1_1State) class for state machines. +This class defined the state for a state machine, and should be extended and passed to implementations of the `[Stateful](#classscy_1_1Stateful)` template. +For an example **See also**: [PacketStreamState](#structscy_1_1PacketStreamState) -#### `public inline virtual void remove(unsigned flag)` +### Members +| Name | Description | +|------|-------------| +| [`State`](#group__base_1ga62afd904ca2b19a794832408b1952d40) | | +| [`State`](#group__base_1ga7db01e0c12d75a6aa8b14e63ed81ebb6) | | +| [`operator=`](#group__base_1ga62a59f3d8aa97fd4361f7f55b3fa445b) | | +| [`~State`](#group__base_1gaa7be0fe7a375c27073cc5c9dc063269f) | | +| [`id`](#group__base_1gad5b4dd779ec160d101eb3f780c24d04f) | | +| [`set`](#group__base_1gac7b685fc2715f9cac21d14310fbd08c6) | | +| [`str`](#group__base_1gaf08ad3e3c5e32fddda195ff37115278b) | | +| [`toString`](#group__base_1ga328e6a3b702375b0ebcf56dafceadda0) | | +| [`equals`](#group__base_1gabe8d32bfca4f473ca60b5d41f0d03bda) | | +| [`between`](#group__base_1ga27f326095da9f4eca2584bda0e3179d4) | | +| [`operator==`](#group__base_1gae2bc129ba4fa926d9b782863d8bf3813) | | +| [`operator==`](#group__base_1ga0f17f91af6980a8c4446ff8a556b07fc) | | +| [`_id`](#group__base_1ga7dc89cb74e42f44177e294a105f93f15) | | +--- +#### State +```cpp +State(ID id) +``` -#### `public inline virtual void toggle(unsigned flag)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `id` | `ID` | | +--- +#### State +```cpp +State(const State & that) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `that` | `const State &` | | -#### `public inline virtual bool has(unsigned flag) const` +--- +#### operator= +```cpp +State & operator=(const State & that) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `that` | `const State &` | | +--- -# struct `scy::ClassDelegate` +#### ~State +```cpp +virtual ~State() = default ``` -struct scy::ClassDelegate - : public scy::AbstractDelegate< RT, Args... > -``` +--- +#### id -The `[ClassDelegate](#structscy_1_1ClassDelegate)` contains a pointer to a class member. - -This class implements fast delegates and function comparison. +```cpp +ID id() const +``` -## Summary +--- - Members | Descriptions ---------------------------------|--------------------------------------------- -`public Class * instance` | -`public RT(Class::* method` | -`public inline ClassDelegate(Class * instance,RT(Class::*)(Args...) method)` | -`public inline virtual RT operator()(Args... args) const` | -`public inline virtual bool operator==(const `[`AbstractDelegate`](#structscy_1_1AbstractDelegate)`< RT, Args... > & that) const` | +#### set -## Members +```cpp +void set(ID id) +``` -#### `public Class * instance` +| Parameter | Type | Description | +|-----------|------|-------------| +| `id` | `ID` | | +--- +#### str +```cpp +virtual std::string str(ID id) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `id` | `ID` | | -#### `public RT(Class::* method` +--- +#### toString +```cpp +virtual std::string toString() const +``` +--- +#### equals -#### `public inline ClassDelegate(Class * instance,RT(Class::*)(Args...) method)` +```cpp +bool equals(ID id) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `id` | `ID` | | +--- +#### between +```cpp +bool between(ID lid, ID rid) const +``` -#### `public inline virtual RT operator()(Args... args) const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `lid` | `ID` | | +| `rid` | `ID` | | +--- +#### operator== +```cpp +inline bool operator==(const State & that) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `that` | `const State &` | | -#### `public inline virtual bool operator==(const `[`AbstractDelegate`](#structscy_1_1AbstractDelegate)`< RT, Args... > & that) const` +--- +#### operator== +```cpp +inline bool operator==(const State::ID & that) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `that` | `const State::ID &` | | +--- -# struct `scy::ConnectReq` +#### _id +```cpp +std::atomic< ID > _id ``` -struct scy::ConnectReq - : public scy::uv::Request< uv_connect_t > -``` - -[Stream](#classscy_1_1Stream) connection request for sockets and pipes. +## Stateful +> **Defined in:** `stateful.h` -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public inline ConnectReq()` | -`public inline bool connect(uv_tcp_t * handle,const struct sockaddr * addr)` | +[State](#classscy_1_1State) machine implementation. -## Members +For an example **See also**: [PacketStream](#classscy_1_1PacketStream) -#### `public inline ConnectReq()` +#### Parameters +* `The` derived `[State](#classscy_1_1State)` type. +### Members + +| Name | Description | +|------|-------------| +| [`Stateful`](#group__base_1ga17f56a2225eb139ebf730715844ae093) | | +| [`~Stateful`](#group__base_1ga88e8a5a4d0be0a7c8b4bcf8283e8118a) | | +| [`stateEquals`](#group__base_1ga46c34eb0102b150761777244d09a3105) | | +| [`stateBetween`](#group__base_1gab9afafcff1b0f56dc4908ffefffa0951) | | +| [`state`](#group__base_1ga25a3dd6324c6a4937e3be09a5db5c6e9) | | +| [`state`](#group__base_1gaf74b1907ca291f0fe0288e7fed013a33) | | +| [`beforeStateChange`](#group__base_1gaa8d284c63cb789cd53c36b06ff3bcc6f) | Override to handle pre state change logic. Return false to prevent state change. | +| [`onStateChange`](#group__base_1ga3c88b4aa8e9343f9bdc1a8c2ae2a5452) | Override to handle post state change logic. | +| [`setState`](#group__base_1ga391c2db9587462e05885b9bb4203825b) | Sets the state and sends the state signal if the state change was successful. | +| [`setState`](#group__base_1gab22136dc42f0b6352249274fd13d4ef0) | Sets the state and sends the state signal if the state change was successful. | +| [`StateChange`](#group__base_1ga822472b26b7dcdce4e5d1b2095983ca9) | Signals when the state changes. | +| [`_state`](#group__base_1gaa772242e3f30125cb5006f757f6d9021) | | + +--- + +#### Stateful + +```cpp +inline Stateful() +``` +--- +#### ~Stateful +```cpp +virtual inline ~Stateful() +``` -#### `public inline bool connect(uv_tcp_t * handle,const struct sockaddr * addr)` +--- +#### stateEquals +```cpp +virtual inline bool stateEquals(typename T::ID id) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `id` | `typename T::ID` | | +--- -# struct `scy::ConstClassDelegate` +#### stateBetween +```cpp +virtual inline bool stateBetween(typename T::ID lid, typename T::ID rid) const ``` -struct scy::ConstClassDelegate - : public scy::AbstractDelegate< RT, Args... > -``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `lid` | `typename T::ID` | | +| `rid` | `typename T::ID` | | +--- -The `[ConstClassDelegate](#structscy_1_1ConstClassDelegate)` contains a pointer to a `const` class member. +#### state -This class implements fast delegates and function comparison. +```cpp +virtual inline T & state() +``` -## Summary +--- - Members | Descriptions ---------------------------------|--------------------------------------------- -`public Class * instance` | -`public RT(Class::* method` | -`public inline ConstClassDelegate(Class * instance,RT(Class::*)(Args...) const method)` | -`public inline virtual RT operator()(Args... args) const` | -`public inline virtual bool operator==(const `[`AbstractDelegate`](#structscy_1_1AbstractDelegate)`< RT, Args... > & that) const` | +#### state -## Members +```cpp +virtual inline const T state() const +``` -#### `public Class * instance` +--- +#### beforeStateChange +```cpp +virtual inline bool beforeStateChange(const T & state) +``` +Override to handle pre state change logic. Return false to prevent state change. +| Parameter | Type | Description | +|-----------|------|-------------| +| `state` | `const T &` | | -#### `public RT(Class::* method` +--- +#### onStateChange +```cpp +virtual inline void onStateChange(T &, const T &) +``` +Override to handle post state change logic. +--- -#### `public inline ConstClassDelegate(Class * instance,RT(Class::*)(Args...) const method)` +#### setState +```cpp +virtual inline bool setState(void * sender, typename T::ID id) +``` +Sets the state and sends the state signal if the state change was successful. +| Parameter | Type | Description | +|-----------|------|-------------| +| `sender` | `void *` | | +| `id` | `typename T::ID` | | +--- -#### `public inline virtual RT operator()(Args... args) const` +#### setState +```cpp +virtual inline bool setState(void * sender, const T & state) +``` +Sets the state and sends the state signal if the state change was successful. +| Parameter | Type | Description | +|-----------|------|-------------| +| `sender` | `void *` | | +| `state` | `const T &` | | +--- -#### `public inline virtual bool operator==(const `[`AbstractDelegate`](#structscy_1_1AbstractDelegate)`< RT, Args... > & that) const` +#### StateChange +```cpp +Signal< void(void *, T &, const T &)> StateChange +``` +Signals when the state changes. +--- +#### _state -# struct `scy::Error` +```cpp +T _state +``` +## Stream +> **Extends:** `scy::uv::Handle< T >` +> **Defined in:** `stream.h` +Basic stream type for sockets and pipes. -Basic error type. +### Members + +| Name | Description | +|------|-------------| +| [`Stream`](#group__base_1ga573ab3d7b0726931ef779f1f3316d729) | | +| [`~Stream`](#group__base_1ga139967e399937a37bac0659df012050d) | | +| [`close`](#group__base_1ga2daec2bd06cc428828b644b836833c6f) | Closes and resets the stream handle. This will close the active socket/pipe and destroy the handle. | +| [`shutdown`](#group__base_1ga8198a3529459f9628609369beed52be7) | Sends a shutdown packet to the connected peer. Return true if the shutdown packet was sent. | +| [`write`](#group__base_1gaca313829afc5741744191f1d72a081fe) | Writes data to the stream. | +| [`write`](#group__base_1ga8ed161ca9c9a5eb606af66db61d4462d) | Write data to the target stream. | +| [`stream`](#group__base_1ga4af2e803567d28d0da339fe09fd34a24) | Return the uv_stream_t pointer. | +| [`readStart`](#group__base_1ga0d44541ca0615c3f7905354f635a87f3) | | +| [`readStop`](#group__base_1ga5ce90e446eb2588dbec48749c8ab47de) | | +| [`onRead`](#group__base_1ga0dca15710b5b129077bf165933fc9fd5) | | +| [`handleRead`](#group__base_1ga5a41a97f6002d8f5a2b5a455a748e754) | UV callbacks. | +| [`allocReadBuffer`](#group__base_1gae046b67a5834f8ba7a1c7356e7720e9d) | | +| [`Read`](#group__base_1gaa4b7ae83d45685339e7ac7f8308e8555) | [Signal](#classscy_1_1Signal) the notifies when data is available for read. | +| [`_buffer`](#group__base_1gabc5b1ed474e8c4e04bedef0c05df5e13) | | +| [`_started`](#group__base_1ga3d0d3973d5f49cd52a42642b46ff576e) | | + +--- + +#### Stream + +```cpp +inline Stream(uv::Loop * loop) +``` -Errors contain an error code, message, and exception pointer. +| Parameter | Type | Description | +|-----------|------|-------------| +| `loop` | `uv::Loop *` | | -## Summary +--- - Members | Descriptions ---------------------------------|--------------------------------------------- -`public int errorno` | -`public std::string message` | -`public std::exception_ptr exception` | -`public inline Error()` | -`public inline Error(const std::string & msg)` | -`public inline Error(const char * msg)` | -`public inline bool any() const` | -`public inline void reset()` | -`public inline void rethrow()` | +#### ~Stream -## Members +```cpp +virtual inline ~Stream() +``` -#### `public int errorno` +--- +#### close +```cpp +virtual inline void close() +``` +Closes and resets the stream handle. This will close the active socket/pipe and destroy the handle. +If the stream is already closed this call will have no side-effects. -#### `public std::string message` +--- +#### shutdown +```cpp +inline bool shutdown() +``` +Sends a shutdown packet to the connected peer. Return true if the shutdown packet was sent. +--- -#### `public std::exception_ptr exception` +#### write +```cpp +inline bool write(const char * data, size_t len) +``` +Writes data to the stream. +Return false if the underlying socket is closed. This method does not throw an exception. +| Parameter | Type | Description | +|-----------|------|-------------| +| `data` | `const char *` | | +| `len` | `size_t` | | -#### `public inline Error()` +--- +#### write +```cpp +inline bool write(const char * data, size_t len, uv_stream_t * send) +``` +Write data to the target stream. +This method is only valid for IPC streams. -#### `public inline Error(const std::string & msg)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `data` | `const char *` | | +| `len` | `size_t` | | +| `send` | `uv_stream_t *` | | +--- +#### stream +```cpp +inline uv_stream_t * stream() +``` +Return the uv_stream_t pointer. -#### `public inline Error(const char * msg)` +--- +#### readStart +```cpp +virtual inline bool readStart() +``` +--- +#### readStop -#### `public inline bool any() const` +```cpp +virtual inline bool readStop() +``` +--- +#### onRead +```cpp +virtual inline void onRead(const char * data, size_t len) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `data` | `const char *` | | +| `len` | `size_t` | | -#### `public inline void reset()` +--- +#### handleRead +```cpp +static inline void handleRead(uv_stream_t * handle, ssize_t nread, const uv_buf_t * buf) +``` +UV callbacks. +| Parameter | Type | Description | +|-----------|------|-------------| +| `handle` | `uv_stream_t *` | | +| `nread` | `ssize_t` | | +| `buf` | `const uv_buf_t *` | | -#### `public inline void rethrow()` +--- +#### allocReadBuffer +```cpp +static inline void allocReadBuffer(uv_handle_t * handle, size_t suggested_size, uv_buf_t * buf) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `handle` | `uv_handle_t *` | | +| `suggested_size` | `size_t` | | +| `buf` | `uv_buf_t *` | | +--- -# struct `scy::FunctionDelegate` +#### Read +```cpp +Signal< void(const char *, const int &)> Read ``` -struct scy::FunctionDelegate - : public scy::AbstractDelegate< RT, Args... > -``` - +[Signal](#classscy_1_1Signal) the notifies when data is available for read. -The `[FunctionDelegate](#structscy_1_1FunctionDelegate)` contains a `std::function`. +--- -## Summary +#### _buffer - Members | Descriptions ---------------------------------|--------------------------------------------- -`public std::function< RT(Args...)> func` | -`public inline FunctionDelegate(std::function< RT(Args...)> func)` | -`public inline virtual RT operator()(Args... args) const` | -`public inline virtual bool operator==(const `[`AbstractDelegate`](#structscy_1_1AbstractDelegate)`< RT, Args... > &) const` | +```cpp +Buffer _buffer +``` -## Members +--- -#### `public std::function< RT(Args...)> func` +#### _started +```cpp +bool _started {false} +``` +## Synchronizer +> **Extends:** `scy::Runner` +> **Defined in:** `synchronizer.h` +[Synchronizer](#classscy_1_1Synchronizer) enables any thread to communicate with the associated event loop via synchronized callbacks. -#### `public inline FunctionDelegate(std::function< RT(Args...)> func)` +This class inherits the `[Runner](#classscy_1_1Runner)` interface and may be used with any implementation that's powered by an asynchronous `[Runner](#classscy_1_1Runner)`. +### Members + +| Name | Description | +|------|-------------| +| [`Synchronizer`](#group__base_1ga444b58b7cd15aa6177aab2550551e9d1) | Create the synchronization context the given event loop. | +| [`Synchronizer`](#group__base_1ga3b654ca58a890cc899b528e7792457d6) | Create the synchronization context the given event loop and method. The target method will be called from the event loop context. | +| [`Synchronizer`](#group__base_1ga83229baca61a3bb8d619049434d7ef63) | Create the synchronization context the given event loop and method. | +| [`~Synchronizer`](#group__base_1ga78f28955aaa877686204db051ff098a3) | Destructor. | +| [`post`](#group__base_1ga3ad0d439617049c785f89a03dd8064cf) | Send a synchronization request to the event loop. Call this each time you want the target method called synchronously. The synchronous method will be called on next iteration. This is not atomic, so do not expect a callback for every request. | +| [`start`](#group__base_1ga30af5bd71957b34eaf6127c2a6eae8ea) | Start the synchronizer with the given callback. | +| [`start`](#group__base_1gaebac12640f586042e138e25a24b25c72) | Start the synchronizer with the given callback function. | +| [`cancel`](#group__base_1ga9305feda357ecdbc54c55fc493cada4b) | | +| [`close`](#group__base_1ga0580bcfe1a059a5a1b75b235065ba2b1) | | +| [`handle`](#group__base_1gabd4d17feef12768ead54b96df39f18cd) | | +| [`async`](#group__base_1gaa598621d521e3e8757f678a4ba025936) | Returns true if the implementation is thread-based, or false if it belongs to an event loop. | +| [`_handle`](#group__base_1ga7e421f1a449033592d904e89650c8ddd) | | + +--- + +#### Synchronizer + +```cpp +Synchronizer(uv::Loop * loop) +``` +Create the synchronization context the given event loop. +| Parameter | Type | Description | +|-----------|------|-------------| +| `loop` | `uv::Loop *` | | +--- -#### `public inline virtual RT operator()(Args... args) const` +#### Synchronizer +```cpp +Synchronizer(std::function< void()> target, uv::Loop * loop) +``` +Create the synchronization context the given event loop and method. The target method will be called from the event loop context. +| Parameter | Type | Description | +|-----------|------|-------------| +| `target` | `std::function< void()>` | | +| `loop` | `uv::Loop *` | | +--- -#### `public inline virtual bool operator==(const `[`AbstractDelegate`](#structscy_1_1AbstractDelegate)`< RT, Args... > &) const` +#### Synchronizer +```cpp +template inline explicit Synchronizer(Function && func, Args &&... args, uv::Loop * loop) +``` +Create the synchronization context the given event loop and method. +| Parameter | Type | Description | +|-----------|------|-------------| +| `func` | `Function &&` | | +| `args` | `Args &&...` | | +| `loop` | `uv::Loop *` | | +--- -# struct `scy::IPacketInfo` +#### ~Synchronizer +```cpp +virtual ~Synchronizer() +``` +Destructor. +--- -An abstract interface for packet sources to provide extra information about packets. +#### post -## Summary +```cpp +void post() +``` - Members | Descriptions ---------------------------------|--------------------------------------------- -`public inline IPacketInfo()` | -`public inline virtual ~IPacketInfo()` | -`public `[`IPacketInfo`](#structscy_1_1IPacketInfo)` * clone() const` | +Send a synchronization request to the event loop. Call this each time you want the target method called synchronously. The synchronous method will be called on next iteration. This is not atomic, so do not expect a callback for every request. -## Members +--- -#### `public inline IPacketInfo()` +#### start +```cpp +template inline void start(Function && func, Args &&... args) +``` +Start the synchronizer with the given callback. +| Parameter | Type | Description | +|-----------|------|-------------| +| `func` | `Function &&` | | +| `args` | `Args &&...` | | +--- -#### `public inline virtual ~IPacketInfo()` +#### start +```cpp +virtual void start(std::function< void()> func) +``` +Start the synchronizer with the given callback function. +| Parameter | Type | Description | +|-----------|------|-------------| +| `func` | `std::function< void()>` | | +--- -#### `public `[`IPacketInfo`](#structscy_1_1IPacketInfo)` * clone() const` +#### cancel +```cpp +virtual void cancel() +``` +--- +#### close +```cpp +virtual void close() +``` -# struct `scy::LogStream` +--- +#### handle +```cpp +uv::Handle< uv_async_t > & handle() +``` +--- +#### async +```cpp +virtual bool async() const +``` -## Summary +Returns true if the implementation is thread-based, or false if it belongs to an event loop. - Members | Descriptions ---------------------------------|--------------------------------------------- -`public inline LogStream(LogLevel level,const std::string & realm,int line,const void * ptr,const char * channel)` | -`public inline LogStream(const `[`LogStream`](#structscy_1_1LogStream)` & that)` | -`public template`
`inline void write(Args... args)` | -`public template`
`inline `[`LogStream`](#structscy_1_1LogStream)` & operator<<(const T &)` | -`public inline `[`LogStream`](#structscy_1_1LogStream)` & operator<<(std::ostream &(*)(std::ostream &) f)` | +--- -## Members +#### _handle -#### `public inline LogStream(LogLevel level,const std::string & realm,int line,const void * ptr,const char * channel)` +```cpp +uv::Handle< uv_async_t > _handle +``` +## Task +> **Extends:** `scy::basic::Runnable` +> **Subclasses:** `scy::sched::Task` +> **Defined in:** `task.h` +Abstract class is for implementing any kind asyncronous task. +Tasks are designed to be run by a [TaskRunner](#classscy_1_1TaskRunner). -#### `public inline LogStream(const `[`LogStream`](#structscy_1_1LogStream)` & that)` +### Members + +| Name | Description | +|------|-------------| +| [`Task`](#group__base_1ga785465536aec43f179f47c7439e44aa8) | Constructor. | +| [`destroy`](#group__base_1gaecd8a85018f8f75ae802dcbf3749bdef) | Sets the task to destroyed state. | +| [`destroyed`](#group__base_1ga7a28372139954b0ff0c96f99be0418f2) | Signals that the task should be disposed of. | +| [`repeating`](#group__base_1gaed5e6c02f8118ab86c7ff620ee2ddf48) | Signals that the task's should be called repeatedly by the [TaskRunner](#classscy_1_1TaskRunner). If this returns false the task will be [cancelled()](#group__base_1gab3795d080eae2e58a57f2c63524c8ef3) | +| [`id`](#group__base_1ga4ffbff2b4bfdc71d9a278f9693297bc1) | Unique task ID. | +| [`Task`](#group__base_1gac513ae573567b9f7708c278c614c7e44) | | +| [`operator=`](#group__base_1ga7bdbb1d628d2e2f2865cc2aad59480f2) | | +| [`~Task`](#group__base_1gac05de8a5d56fb224bee75277714de893) | Destroctor. Should remain protected. | +| [`run`](#group__base_1ga0bfb09779b8f6aa9c5e3ce7dd7e4cfe3) | Called by the [TaskRunner](#classscy_1_1TaskRunner) to run the task. Override this method to implement task action. Returning true means the true should be called again, and false will cause the task to be destroyed. The task will similarly be destroyed id [destroy()](#group__base_1gaecd8a85018f8f75ae802dcbf3749bdef) was called during the current task iteration. | +| [`_id`](#group__base_1ga1d20300119a652f0ce185bc1510b041f) | | +| [`_repeating`](#group__base_1gae5fcfd4789448c078bbc04a24b00849a) | | +| [`_destroyed`](#group__base_1ga930e56a65dfd577c40fe7d30f3018e68) | | + +--- + +#### Task + +```cpp +Task(bool repeat) +``` +Constructor. +| Parameter | Type | Description | +|-----------|------|-------------| +| `repeat` | `bool` | | +--- +#### destroy -#### `public template`
`inline void write(Args... args)` +```cpp +virtual void destroy() +``` +Sets the task to destroyed state. +--- +#### destroyed +```cpp +virtual bool destroyed() const +``` -#### `public template`
`inline `[`LogStream`](#structscy_1_1LogStream)` & operator<<(const T &)` +Signals that the task should be disposed of. +--- +#### repeating +```cpp +virtual bool repeating() const +``` +Signals that the task's should be called repeatedly by the [TaskRunner](#classscy_1_1TaskRunner). If this returns false the task will be [cancelled()](#group__base_1gab3795d080eae2e58a57f2c63524c8ef3) -#### `public inline `[`LogStream`](#structscy_1_1LogStream)` & operator<<(std::ostream &(*)(std::ostream &) f)` +--- +#### id +```cpp +virtual uint32_t id() const +``` +Unique task ID. +--- -# struct `scy::OptionParser` +#### Task +```cpp +Task(const Task & task) = delete +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `task` | `const Task &` | | +--- +#### operator= +```cpp +Task & operator=(Task const &) = delete +``` -## Summary +--- - Members | Descriptions ---------------------------------|--------------------------------------------- -`public std::string exepath` | -`public `[`OptionMap`](#group__base_1gafa6d19403eb9f91c90706b10170f0f75)` args` | -`public OptionParser(int argc,char * argv,const char * delim)` | -`public inline bool has(const char * key)` | -`public inline std::string get(const char * key)` | -`public template`
`inline NumericType get(const char * key)` | +#### ~Task -## Members +```cpp +virtual ~Task() +``` -#### `public std::string exepath` +Destroctor. Should remain protected. +--- +#### run +```cpp +void run() +``` +Called by the [TaskRunner](#classscy_1_1TaskRunner) to run the task. Override this method to implement task action. Returning true means the true should be called again, and false will cause the task to be destroyed. The task will similarly be destroyed id [destroy()](#group__base_1gaecd8a85018f8f75ae802dcbf3749bdef) was called during the current task iteration. -#### `public `[`OptionMap`](#group__base_1gafa6d19403eb9f91c90706b10170f0f75)` args` +--- +#### _id +```cpp +uint32_t _id +``` +--- +#### _repeating -#### `public OptionParser(int argc,char * argv,const char * delim)` +```cpp +bool _repeating +``` +--- +#### _destroyed +```cpp +bool _destroyed +``` +## TaskRunner -#### `public inline bool has(const char * key)` +> **Extends:** `scy::basic::Runnable` +> **Subclasses:** `scy::sched::Scheduler` +> **Defined in:** `task.h` +[Runner](#classscy_1_1Runner) for tasks that inherit the `[Task](#classscy_1_1Task)` interface. +The `[TaskRunner](#classscy_1_1TaskRunner)` continually loops through each task in the task list calling the task's `[run()](#group__base_1ga07a481d667f1a9c67e881eedcffc10a5)` method. +The `[TaskRunner](#classscy_1_1TaskRunner)` is powered by an abstract `[Runner](#classscy_1_1Runner)` instance, which means that tasks can be executed in a thread or event loop context. +### Members + +| Name | Description | +|------|-------------| +| [`TaskRunner`](#group__base_1ga68fea71b30b2732252bf31bf34f34b13) | | +| [`~TaskRunner`](#group__base_1ga7f694f4681bee437fffd58ad6e21f09e) | | +| [`start`](#group__base_1ga3f30dc3d3e1f68ada87091a2f1ca73d1) | Starts a task, adding it if it doesn't exist. | +| [`cancel`](#group__base_1ga429b24f441d2f86b7dcddc6764359d49) | Cancels a task. | +| [`destroy`](#group__base_1ga44547fd3858f512ea07c71676059ca7e) | Queues a task for destruction. | +| [`exists`](#group__base_1ga6f2cdcb41929fb914cdf288e1a00358e) | Returns weather or not a task exists. | +| [`get`](#group__base_1ga0c78d8e9196bc74fe1a5120974f4c8b9) | Returns the task pointer matching the given ID, or nullptr if no task exists. | +| [`setRunner`](#group__base_1ga9fe00258dfd9bef1fc91c5a944c6b754) | Set the asynchronous context for packet processing. This may be a [Thread](#classscy_1_1Thread) or another derivative of Async. Must be set before the stream is activated. | +| [`className`](#group__base_1ga710f2dcbc11de260c76c16b8c8600ca3) | | +| [`getDefault`](#group__base_1ga216b6da5a3e0ae72bebf7371ef0e4725) | Returns the default `[TaskRunner](#classscy_1_1TaskRunner)` singleton, although [TaskRunner](#classscy_1_1TaskRunner) instances may be initialized individually. The default runner should be kept for short running tasks such as timers in order to maintain performance. | +| [`run`](#group__base_1ga07a481d667f1a9c67e881eedcffc10a5) | Called by the async context to run the next task. | +| [`add`](#group__base_1ga3cf9ff9159b170aa7e413bf0b0d0703e) | Adds a task to the runner. | +| [`remove`](#group__base_1gaca2341833adec925d50db8a5e128f679) | Removes a task from the runner. | +| [`next`](#group__base_1ga5c318e730939bf4b63072ebcdac5e9ee) | Returns the next task to be run. | +| [`clear`](#group__base_1gaa92a25f1d62e16bc40642688f569d5bd) | Destroys and clears all manages tasks. | +| [`onAdd`](#group__base_1gad6fc274ed81e757dba96db8f24fb2420) | Called after a task is added. | +| [`onStart`](#group__base_1ga2178d212993fd101fbe839afaaa0f79f) | Called after a task is started. | +| [`onCancel`](#group__base_1gab28a8ded043ae47ecace8c79512ec31a) | Called after a task is cancelled. | +| [`onRemove`](#group__base_1ga3c19020b93c4abaf5006c67a8b1ae474) | Called after a task is removed. | +| [`onRun`](#group__base_1ga0851ff27ae76aeb33d8d4f289844aa61) | Called after a task has run. | +| [`Idle`](#group__base_1gabf058e5fccd90bd4c65e22a5bc542ddf) | Fires after completing an iteration of all tasks. | +| [`Shutdown`](#group__base_1gaf3afae0333fb5b248c320f07a876c682) | Signals when the `[TaskRunner](#classscy_1_1TaskRunner)` is shutting down. | +| [`_mutex`](#group__base_1ga0f479eb77e6349c2d7db94bd1776b578) | | +| [`_runner`](#group__base_1gaac415837586c91449e3ef85c33a2e6f3) | | +| [`_tasks`](#group__base_1ga0d19424a7b9506240e72da3a45a4b08c) | | + +--- + +#### TaskRunner + +```cpp +TaskRunner(std::shared_ptr< Runner > runner) +``` -#### `public inline std::string get(const char * key)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `runner` | `std::shared_ptr< Runner >` | | +--- +#### ~TaskRunner +```cpp +virtual ~TaskRunner() +``` +--- -#### `public template`
`inline NumericType get(const char * key)` +#### start +```cpp +virtual bool start(Task * task) +``` +Starts a task, adding it if it doesn't exist. +| Parameter | Type | Description | +|-----------|------|-------------| +| `task` | `Task *` | | +--- -# struct `scy::PacketAdapterReference` +#### cancel +```cpp +virtual bool cancel(Task * task) +``` -For 0.8.x compatibility. +Cancels a task. -Provides a reference to a PacketSignal instance. +The task reference will be managed the [TaskRunner](#classscy_1_1TaskRunner) until the task is destroyed. -## Summary +| Parameter | Type | Description | +|-----------|------|-------------| +| `task` | `Task *` | | - Members | Descriptions ---------------------------------|--------------------------------------------- -`public `[`PacketStreamAdapter`](./doc/api-base.md#classscy_1_1PacketStreamAdapter)` * ptr` | -`public `[`ScopedPointer`](./doc/api-base.md#classscy_1_1ScopedPointer)` * deleter` | -`public int order` | -`public bool syncState` | -`public inline PacketAdapterReference(`[`PacketStreamAdapter`](#classscy_1_1PacketStreamAdapter)` * ptr,`[`ScopedPointer`](#classscy_1_1ScopedPointer)` * deleter,int order,bool syncState)` | -`public inline ~PacketAdapterReference()` | +--- -## Members +#### destroy -#### `public `[`PacketStreamAdapter`](./doc/api-base.md#classscy_1_1PacketStreamAdapter)` * ptr` +```cpp +virtual bool destroy(Task * task) +``` +Queues a task for destruction. +| Parameter | Type | Description | +|-----------|------|-------------| +| `task` | `Task *` | | +--- +#### exists -#### `public `[`ScopedPointer`](./doc/api-base.md#classscy_1_1ScopedPointer)` * deleter` +```cpp +virtual bool exists(Task * task) const +``` +Returns weather or not a task exists. +| Parameter | Type | Description | +|-----------|------|-------------| +| `task` | `Task *` | | +--- +#### get -#### `public int order` +```cpp +virtual Task * get(uint32_t id) const +``` +Returns the task pointer matching the given ID, or nullptr if no task exists. +| Parameter | Type | Description | +|-----------|------|-------------| +| `id` | `uint32_t` | | +--- +#### setRunner -#### `public bool syncState` +```cpp +virtual void setRunner(std::shared_ptr< Runner > runner) +``` +Set the asynchronous context for packet processing. This may be a [Thread](#classscy_1_1Thread) or another derivative of Async. Must be set before the stream is activated. +| Parameter | Type | Description | +|-----------|------|-------------| +| `runner` | `std::shared_ptr< Runner >` | | +--- +#### className -#### `public inline PacketAdapterReference(`[`PacketStreamAdapter`](#classscy_1_1PacketStreamAdapter)` * ptr,`[`ScopedPointer`](#classscy_1_1ScopedPointer)` * deleter,int order,bool syncState)` +```cpp +virtual inline const char * className() const +``` +--- +#### getDefault +```cpp +static TaskRunner & getDefault() +``` +Returns the default `[TaskRunner](#classscy_1_1TaskRunner)` singleton, although [TaskRunner](#classscy_1_1TaskRunner) instances may be initialized individually. The default runner should be kept for short running tasks such as timers in order to maintain performance. -#### `public inline ~PacketAdapterReference()` +--- +#### run +```cpp +virtual void run() +``` +Called by the async context to run the next task. +--- -# struct `scy::PacketCreationStrategy` +#### add +```cpp +virtual bool add(Task * task) ``` -struct scy::PacketCreationStrategy - : public scy::IPacketCreationStrategy -``` +Adds a task to the runner. +| Parameter | Type | Description | +|-----------|------|-------------| +| `task` | `Task *` | | -This template class implements an adapter that sits between an SignalBase and an object receiving notifications from it. +--- -## Summary +#### remove - Members | Descriptions ---------------------------------|--------------------------------------------- -`public inline PacketCreationStrategy(int priority)` | -`public inline virtual ~PacketCreationStrategy()` | -`public inline virtual `[`IPacket`](#classscy_1_1IPacket)` * create(const `[`ConstBuffer`](#classscy_1_1ConstBuffer)` & buffer,size_t & nread) const` | -`public inline virtual int priority() const` | -`protected int _priority` | +```cpp +virtual bool remove(Task * task) +``` -## Members +Removes a task from the runner. -#### `public inline PacketCreationStrategy(int priority)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `task` | `Task *` | | +--- +#### next +```cpp +virtual Task * next() const +``` +Returns the next task to be run. -#### `public inline virtual ~PacketCreationStrategy()` +--- +#### clear +```cpp +virtual void clear() +``` +Destroys and clears all manages tasks. +--- -#### `public inline virtual `[`IPacket`](#classscy_1_1IPacket)` * create(const `[`ConstBuffer`](#classscy_1_1ConstBuffer)` & buffer,size_t & nread) const` +#### onAdd +```cpp +virtual void onAdd(Task * task) +``` +Called after a task is added. +| Parameter | Type | Description | +|-----------|------|-------------| +| `task` | `Task *` | | +--- -#### `public inline virtual int priority() const` +#### onStart +```cpp +virtual void onStart(Task * task) +``` +Called after a task is started. +| Parameter | Type | Description | +|-----------|------|-------------| +| `task` | `Task *` | | +--- -#### `protected int _priority` +#### onCancel +```cpp +virtual void onCancel(Task * task) +``` +Called after a task is cancelled. +| Parameter | Type | Description | +|-----------|------|-------------| +| `task` | `Task *` | | +--- -# struct `scy::PacketStreamState` +#### onRemove +```cpp +virtual void onRemove(Task * task) ``` -struct scy::PacketStreamState - : public scy::State -``` +Called after a task is removed. +| Parameter | Type | Description | +|-----------|------|-------------| +| `task` | `Task *` | | +--- +#### onRun -## Summary +```cpp +virtual void onRun(Task * task) +``` - Members | Descriptions ---------------------------------|--------------------------------------------- -`public inline std::string str(unsigned int id) const` | +Called after a task has run. -## Members +| Parameter | Type | Description | +|-----------|------|-------------| +| `task` | `Task *` | | -#### `public inline std::string str(unsigned int id) const` +--- +#### Idle +```cpp +NullSignal Idle +``` +Fires after completing an iteration of all tasks. +--- -# struct `scy::PolymorphicDelegate` +#### Shutdown +```cpp +NullSignal Shutdown ``` -struct scy::PolymorphicDelegate - : public scy::AbstractDelegate< RT, IT &> -``` +Signals when the `[TaskRunner](#classscy_1_1TaskRunner)` is shutting down. + +--- +#### _mutex -Polymorphic function delegate. +```cpp +std::mutex _mutex +``` -Theis class contains a pointer to a class member that receices a derived subclass (`PT`) of the base type specified by the `IT` param. +--- -## Summary +#### _runner - Members | Descriptions ---------------------------------|--------------------------------------------- -`public Class * instance` | -`public RT(Class::* method` | -`public inline PolymorphicDelegate(Class * instance,RT(Class::*)(PT &) method)` | -`public inline virtual RT operator()(IT & object) const` | -`public inline virtual bool operator==(const `[`AbstractDelegate`](#structscy_1_1AbstractDelegate)`< RT, IT &> & that) const` | +```cpp +std::shared_ptr< Runner > _runner +``` -## Members +--- -#### `public Class * instance` +#### _tasks +```cpp +TaskList _tasks +``` +## Test +> **Subclasses:** `scy::test::FunctionTest` +> **Defined in:** `test.h` +[Test](#classscy_1_1test_1_1Test) wrapper class. -#### `public RT(Class::* method` +This class is for implementing any kind of unit test that can be executed by a `[TestRunner](#classscy_1_1test_1_1TestRunner)`. +### Members +| Name | Description | +|------|-------------| +| [`Test`](#group__base_1ga77ec963c31149717e725fb25a0d9c3e2) | | +| [`~Test`](#group__base_1ga190692773ad0ccef364dbfcd5a10b2a8) | Should remain protected. | +| [`run`](#group__base_1ga4b2e88e8a32def45844c9fdcf1b4bc5e) | Called by the [TestRunner](#classscy_1_1test_1_1TestRunner) to run the test. | +| [`passed`](#group__base_1ga7136d60a9c295927a26d1eee662a9112) | Return true when the test passed without errors. | +| [`Test`](#group__base_1ga53e1fc6fb63e2228193a074b44f2ae8c) | | +| [`operator=`](#group__base_1ga80fa2a2d52c286fd031b8620e2395a42) | | +| [`name`](#group__base_1ga05c0192e474a337da0822200d2ad8084) | The name of the test. | +| [`errors`](#group__base_1ga97c97aa995efb443d470f235a08275a9) | A list of test errors. | +| [`duration`](#group__base_1gac56aeb8b24a0ad4d6ac4d5c8f8f2a260) | The test run duration for benchmarking. | +--- +#### Test -#### `public inline PolymorphicDelegate(Class * instance,RT(Class::*)(PT &) method)` +```cpp +Test(const std::string & name) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | +--- +#### ~Test +```cpp +virtual ~Test() +``` -#### `public inline virtual RT operator()(IT & object) const` +Should remain protected. +--- +#### run +```cpp +void run() +``` +Called by the [TestRunner](#classscy_1_1test_1_1TestRunner) to run the test. -#### `public inline virtual bool operator==(const `[`AbstractDelegate`](#structscy_1_1AbstractDelegate)`< RT, IT &> & that) const` +--- +#### passed +```cpp +bool passed() +``` +Return true when the test passed without errors. +--- -# struct `scy::SharedLibrary` +#### Test +```cpp +Test(const Test & test) = delete +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `test` | `const Test &` | | +--- +#### operator= +```cpp +Test & operator=(Test const &) = delete +``` -## Summary +--- - Members | Descriptions ---------------------------------|--------------------------------------------- -`public inline bool open(const std::string & path)` | -`public inline void close()` | Closes the shared library. -`public inline bool sym(const char * name,void ** ptr)` | -`public inline void setError(const std::string & prefix)` | -`public inline std::string error() const` | -`protected uv_lib_t _lib` | -`protected std::string _error` | +#### name -## Members +```cpp +std::string name +``` -#### `public inline bool open(const std::string & path)` +The name of the test. +--- +#### errors -Opens a shared library. The filename is in utf-8. Returns true on success and false on error. Call `SharedLibrary::error()` to get the error message. +```cpp +SErrorist errors +``` -#### `public inline void close()` +A list of test errors. -Closes the shared library. +--- +#### duration +```cpp +double duration +``` -#### `public inline bool sym(const char * name,void ** ptr)` +The test run duration for benchmarking. +## FunctionTest +> **Extends:** `scy::test::Test` +> **Defined in:** `test.h` -Retrieves a data pointer from a dynamic library. It is legal for a symbol to map to nullptr. Returns 0 on success and -1 if the symbol was not found. +### Members -#### `public inline void setError(const std::string & prefix)` +| Name | Description | +|------|-------------| +| [`FunctionTest`](#group__base_1gac840656d94f9442624c1b15f4d72bf78) | | +| [`~FunctionTest`](#group__base_1gacc32a5204646832c258c30892449531e) | | +| [`run`](#group__base_1ga5d3c89ca30abab0fe4020db97ed6e513) | Called by the [TestRunner](#classscy_1_1test_1_1TestRunner) to run the test. | +| [`target`](#group__base_1gabc68dd3cfbefe5af9544fb34b9edb6d7) | | +--- +#### FunctionTest +```cpp +inline FunctionTest(std::function< void()> target, const std::string & name) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `target` | `std::function< void()>` | | +| `name` | `const std::string &` | | -#### `public inline std::string error() const` +--- +#### ~FunctionTest +```cpp +virtual inline ~FunctionTest() +``` +--- +#### run -#### `protected uv_lib_t _lib` +```cpp +virtual inline void run() +``` +Called by the [TestRunner](#classscy_1_1test_1_1TestRunner) to run the test. +--- +#### target +```cpp +std::function< void()> target +``` -#### `protected std::string _error` +## TestRunner +> **Defined in:** `test.h` +[Test](#classscy_1_1test_1_1Test) manager queue. +The `[TestRunner](#classscy_1_1test_1_1TestRunner)` is a queue in charge of running one or many tests. +When `[run()](#group__base_1gae237ec747f0a785fb2514154a46022b3)` the `[TestRunner](#classscy_1_1test_1_1TestRunner)` loops through each test in the list calling the test's `[run()](#group__base_1gae237ec747f0a785fb2514154a46022b3)` method. -# struct `scy::ShutdownCmd` +### Members + +| Name | Description | +|------|-------------| +| [`TestRunner`](#group__base_1gaa969f22aa934715fccb037572de9d51b) | | +| [`~TestRunner`](#group__base_1ga816353a412bed8f169ecfaf82b34cd8b) | | +| [`add`](#group__base_1ga576996da07db6bf6de177586530c352c) | Add a test to the runner. | +| [`get`](#group__base_1gae6eae9609b3a4b78e8508e930e924220) | Return a pointer to the test matching the given name, or nullptr if no matching test exists. | +| [`run`](#group__base_1gae237ec747f0a785fb2514154a46022b3) | Called by the async context to run the next test. | +| [`clear`](#group__base_1ga6dd3a9bc14a7c4223d8811bc11651f82) | Destroy and clears all managed tests. | +| [`current`](#group__base_1gad5960442871ffed66bf6d14a159ec29f) | Return the currently active [Test](#classscy_1_1test_1_1Test) or nullptr. | +| [`tests`](#group__base_1ga63d7bb169e8987b0ef42e032a5c15dec) | Return the list of tests. | +| [`errors`](#group__base_1ga3f6c0d4bd8239546c2ffb09baf3c6d17) | Return a map of tests and errors. | +| [`passed`](#group__base_1gaa899250db70a6f7d3855a58ac46b9385) | Return true if all tests passed. | +| [`getDefault`](#group__base_1gac6a1b7a3bb9090c9426d5f785f0979e3) | Return the default `[TestRunner](#classscy_1_1test_1_1TestRunner)` singleton, although `[TestRunner](#classscy_1_1test_1_1TestRunner)` instances may also be initialized individually. | +| [`_mutex`](#group__base_1ga55aaec3e17a75e9df9a1640a4830d674) | | +| [`_tests`](#group__base_1ga07642f477365332784394b083e0878ec) | | +| [`_current`](#group__base_1ga3e5f349d8600497eca5acacd6e853ad7) | | + +--- + +#### TestRunner + +```cpp +TestRunner() +``` +--- +#### ~TestRunner +```cpp +virtual ~TestRunner() +``` +--- +#### add -## Summary +```cpp +void add(Test * test) +``` - Members | Descriptions ---------------------------------|--------------------------------------------- -`public void * opaque` | -`public std::function< void(void *)> callback` | +Add a test to the runner. -## Members +| Parameter | Type | Description | +|-----------|------|-------------| +| `test` | `Test *` | | -#### `public void * opaque` +--- +#### get +```cpp +Test * get(const std::string & name) const +``` +Return a pointer to the test matching the given name, or nullptr if no matching test exists. +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | -#### `public std::function< void(void *)> callback` +--- +#### run +```cpp +void run() +``` +Called by the async context to run the next test. +--- -# struct `scy::TransactionState` +#### clear +```cpp +void clear() ``` -struct scy::TransactionState - : public scy::State -``` +Destroy and clears all managed tests. + +--- + +#### current +```cpp +Test * current() const +``` +Return the currently active [Test](#classscy_1_1test_1_1Test) or nullptr. +--- -## Summary +#### tests - Members | Descriptions ---------------------------------|--------------------------------------------- -`public inline std::string str(unsigned int id) const` | +```cpp +TestList tests() const +``` -## Members +Return the list of tests. -#### `public inline std::string str(unsigned int id) const` +--- +#### errors +```cpp +ErrorMap errors() const +``` +Return a map of tests and errors. +--- -# namespace `scy::base64` +#### passed +```cpp +bool passed() const +``` +Return true if all tests passed. -## Summary +--- - Members | Descriptions ---------------------------------|--------------------------------------------- -`struct `[`scy::base64::Decoder`](#structscy_1_1base64_1_1Decoder) | Base64 decoder. -`struct `[`scy::base64::Encoder`](#structscy_1_1base64_1_1Encoder) | Base64 encoder. -# struct `scy::base64::Decoder` +#### getDefault +```cpp +static TestRunner & getDefault() ``` -struct scy::base64::Decoder - : public scy::basic::Decoder -``` -Base64 decoder. +Return the default `[TestRunner](#classscy_1_1test_1_1TestRunner)` singleton, although `[TestRunner](#classscy_1_1test_1_1TestRunner)` instances may also be initialized individually. + +--- +#### _mutex +```cpp +std::mutex _mutex +``` -## Summary +--- - Members | Descriptions ---------------------------------|--------------------------------------------- -`public internal::decodestate _state` | -`public int _buffersize` | -`public inline Decoder(int buffersize)` | -`public inline ssize_t decode(char value_in)` | -`public inline virtual ssize_t decode(const char * inbuf,size_t nread,char * outbuf)` | -`public inline void decode(std::istream & istrm,std::ostream & ostrm)` | +#### _tests -## Members +```cpp +TestList _tests +``` -#### `public internal::decodestate _state` +--- +#### _current +```cpp +Test * _current +``` +## Timer +> **Extends:** `scy::Runner` +> **Defined in:** `timer.h` -#### `public int _buffersize` +Asynchronous event based timer. +### Members + +| Name | Description | +|------|-------------| +| [`Timer`](#group__base_1ga1fae10ff8c5f7967f91cde97229af7f9) | Create a timer. | +| [`Timer`](#group__base_1ga2371f483389963e2b6634835452c5f5f) | Create a timeout timer. | +| [`Timer`](#group__base_1gac5f14edef0a9c3a7e5109db6a56133dc) | Create a repeating interval timer. | +| [`~Timer`](#group__base_1ga64a91b7e8c9c4145058cf2088b3221a4) | Destructor. | +| [`start`](#group__base_1gabf583d65fae824bb07ed66885491f916) | Start the timer. | +| [`start`](#group__base_1gaa7be3558a210ba5a963f8b4ae05cfbf8) | Start the timer with the given callback function. | +| [`stop`](#group__base_1ga13edfe3f0b4efd439cf640377624b5be) | Stop the timer. | +| [`restart`](#group__base_1ga0e9afbcacb03261ee441b0631e2dccf1) | Restart the timer. | +| [`again`](#group__base_1gab91426f1cb86e09423775e6ee59a2b8e) | Trigger the timer again. | +| [`setTimeout`](#group__base_1gabbfdeaba8dbf67e79d2635660fc10551) | Set the timeout value. | +| [`setInterval`](#group__base_1gab2ba3bfa336276158867c017b39f24e4) | Set the repeat value. | +| [`active`](#group__base_1ga3bc8f6a117d6982ea125f7d1f26ad67f) | | +| [`timeout`](#group__base_1ga731fc5f29c10ef7237494b5fef7063d5) | | +| [`interval`](#group__base_1gae80ec21a3b77a186e8781179e478a623) | | +| [`count`](#group__base_1ga3e4978ac6eb64b151c670a68980ff11d) | | +| [`handle`](#group__base_1gac14b1d3b7ddd6fc5e30146cd4f40ed28) | | +| [`async`](#group__base_1ga4fd229d3c1db2fd45362cf0861b5e359) | Returns true if the implementation is thread-based, or false if it belongs to an event loop. | +| [`Timer`](#group__base_1ga7757e24daa73bdf095e93d94050adf57) | | +| [`operator=`](#group__base_1gab242b0701daeebee901b2b8b1ceaea9d) | | +| [`init`](#group__base_1ga4d7d19830efea92f0944f972caba2fdb) | | +| [`Timeout`](#group__base_1ga70ab283148e5fb200fe84f75ea9ea138) | [Signal](#classscy_1_1Signal) that gets triggered on timeout. | +| [`_handle`](#group__base_1gaf4b35f98a8978d847315e8f3415cc639) | | +| [`_timeout`](#group__base_1ga146dcd71f59664feead6e84c971c6b9a) | | +| [`_interval`](#group__base_1ga0a84a02412fc3e3fe9fed3ce4ff8b7fa) | | +| [`_count`](#group__base_1gad7d0505734bb3683560456c3a5fea546) | | + +--- + +#### Timer + +```cpp +Timer(uv::Loop * loop) +``` +Create a timer. +| Parameter | Type | Description | +|-----------|------|-------------| +| `loop` | `uv::Loop *` | | +--- -#### `public inline Decoder(int buffersize)` +#### Timer +```cpp +Timer(std::int64_t timeout, uv::Loop * loop, std::function< void()> func) +``` +Create a timeout timer. +The timeout timer will trigger once after `timeout` milliseconds. +| Parameter | Type | Description | +|-----------|------|-------------| +| `timeout` | `std::int64_t` | | +| `loop` | `uv::Loop *` | | +| `func` | `std::function< void()>` | | -#### `public inline ssize_t decode(char value_in)` +--- +#### Timer +```cpp +Timer(std::int64_t timeout, std::int64_t interval, uv::Loop * loop, std::function< void()> func) +``` +Create a repeating interval timer. +The interval timer will trigger once after `timeout` milliseconds, and continue to trigger after the `interval` milliseconds. -#### `public inline virtual ssize_t decode(const char * inbuf,size_t nread,char * outbuf)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `timeout` | `std::int64_t` | | +| `interval` | `std::int64_t` | | +| `loop` | `uv::Loop *` | | +| `func` | `std::function< void()>` | | +--- +#### ~Timer +```cpp +virtual ~Timer() +``` +Destructor. -#### `public inline void decode(std::istream & istrm,std::ostream & ostrm)` +--- +#### start +```cpp +void start() +``` +Start the timer. +--- -# struct `scy::base64::Encoder` +#### start +```cpp +virtual void start(std::function< void()> func) ``` -struct scy::base64::Encoder - : public scy::basic::Encoder -``` - -Base64 encoder. - +Start the timer with the given callback function. -## Summary +| Parameter | Type | Description | +|-----------|------|-------------| +| `func` | `std::function< void()>` | | - Members | Descriptions ---------------------------------|--------------------------------------------- -`public internal::encodestate _state` | -`public int _buffersize` | -`public inline Encoder(int buffersize)` | -`public inline void encode(std::istream & istrm,std::ostream & ostrm)` | -`public inline void encode(const std::string & in,std::string & out)` | -`public inline virtual ssize_t encode(const char * inbuf,size_t nread,char * outbuf)` | -`public inline virtual ssize_t finalize(char * outbuf)` | -`public inline void setLineLength(int lineLength)` | +--- -## Members +#### stop -#### `public internal::encodestate _state` +```cpp +void stop() +``` +Stop the timer. +--- +#### restart +```cpp +void restart() +``` -#### `public int _buffersize` +Restart the timer. +This method works even if it hasn't been started yet. An interval or interval must be set or an exception will be thrown. +--- +#### again +```cpp +void again() +``` -#### `public inline Encoder(int buffersize)` +Trigger the timer again. +If the timer is repeating restart it using the repeat value as the `timeout`. If the timer has never been started before it returns -1 and sets the error to `UV_EINVAL`. +--- +#### setTimeout +```cpp +void setTimeout(std::int64_t timeout) +``` -#### `public inline void encode(std::istream & istrm,std::ostream & ostrm)` +Set the timeout value. +The timer must not be active when this value is set. +| Parameter | Type | Description | +|-----------|------|-------------| +| `timeout` | `std::int64_t` | | +--- +#### setInterval -#### `public inline void encode(const std::string & in,std::string & out)` +```cpp +void setInterval(std::int64_t interval) +``` +Set the repeat value. +Note that if the repeat value is set from a timer callback it does not immediately take effect. If the timer was non-repeating before, it will have been stopped. If it was repeating, then the old repeat value will have been used to schedule the next timeout. +| Parameter | Type | Description | +|-----------|------|-------------| +| `interval` | `std::int64_t` | | +--- -#### `public inline virtual ssize_t encode(const char * inbuf,size_t nread,char * outbuf)` +#### active +```cpp +bool active() const +``` +--- +#### timeout +```cpp +std::int64_t timeout() const +``` -#### `public inline virtual ssize_t finalize(char * outbuf)` +--- +#### interval +```cpp +std::int64_t interval() const +``` +--- +#### count -#### `public inline void setLineLength(int lineLength)` +```cpp +std::int64_t count() +``` +--- +#### handle +```cpp +uv::Handle< uv_timer_t > & handle() +``` +--- -# namespace `scy::hex` +#### async +```cpp +virtual bool async() const +``` +Returns true if the implementation is thread-based, or false if it belongs to an event loop. -## Summary +--- - Members | Descriptions ---------------------------------|--------------------------------------------- -`struct `[`scy::hex::Decoder`](#structscy_1_1hex_1_1Decoder) | Hex decoder. -`struct `[`scy::hex::Encoder`](#structscy_1_1hex_1_1Encoder) | Hex encoder. -# struct `scy::hex::Decoder` +#### Timer +```cpp +Timer(const Timer &) = delete ``` -struct scy::hex::Decoder - : public scy::basic::Decoder -``` - -Hex decoder. +--- +#### operator= -## Summary +```cpp +Timer & operator=(const Timer &) = delete +``` - Members | Descriptions ---------------------------------|--------------------------------------------- -`public char lastbyte` | -`public inline Decoder()` | -`public inline virtual ~Decoder()` | -`public inline virtual ssize_t decode(const char * inbuf,size_t nread,char * outbuf)` | -`public inline virtual ssize_t finalize(char *)` | -`public inline bool readnext(const char * inbuf,size_t nread,size_t & rpos,char & c)` | -`public inline int nybble(const int n)` | -`public inline bool iswspace(const char c)` | +--- -## Members +#### init -#### `public char lastbyte` +```cpp +void init() +``` +--- +#### Timeout +```cpp +NullSignal Timeout +``` +[Signal](#classscy_1_1Signal) that gets triggered on timeout. -#### `public inline Decoder()` +--- +#### _handle +```cpp +uv::Handle< uv_timer_t > _handle +``` +--- +#### _timeout -#### `public inline virtual ~Decoder()` +```cpp +std::int64_t _timeout +``` +--- +#### _interval +```cpp +std::int64_t _interval +``` +--- -#### `public inline virtual ssize_t decode(const char * inbuf,size_t nread,char * outbuf)` +#### _count +```cpp +std::int64_t _count +``` +## TZInfo +### Members +| Name | Description | +|------|-------------| +| [`TZInfo`](#group__base_1ga6491a626255da59420f4e79f135bec79) | | +| [`timeZone`](#group__base_1ga2a6e305f50e4018b7a4f8cd97a4f579e) | | +| [`name`](#group__base_1ga4f6e3fa6eb45afcecab5a279e0e98dcb) | | -#### `public inline virtual ssize_t finalize(char *)` +--- +#### TZInfo +```cpp +inline TZInfo() +``` +--- +#### timeZone -#### `public inline bool readnext(const char * inbuf,size_t nread,size_t & rpos,char & c)` +```cpp +inline int timeZone() +``` +--- +#### name +```cpp +inline const char * name(bool dst) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `dst` | `bool` | | -#### `public inline int nybble(const int n)` +## Timeout +> **Subclasses:** `scy::TimedToken` +> **Defined in:** `timeout.h` +[Timeout](#classscy_1_1Timeout) counter which expires after a given delay. +### Members + +| Name | Description | +|------|-------------| +| [`Timeout`](#group__base_1ga7a0c9d99bcece690d28b3568a532c8bb) | | +| [`Timeout`](#group__base_1gafd9ba1a97e117625f6c87121c5b1bb53) | | +| [`~Timeout`](#group__base_1ga96b82e3575fe7a5d18d46f9e409e3883) | | +| [`running`](#group__base_1ga451634c2144d1adda5a9301dcef6c118) | | +| [`start`](#group__base_1ga4de922b575fa908ce89b978f26ef4059) | | +| [`stop`](#group__base_1gafb82ee057268b469694dc2aa8c72bc36) | | +| [`reset`](#group__base_1gaddc18501ce642ff8724d15fc41939ac8) | | +| [`remaining`](#group__base_1gae7eafa18334cdd1def62b1cd9504a5ed) | | +| [`expired`](#group__base_1ga434bc816acdc562bd4434b853d2252f9) | | +| [`setDelay`](#group__base_1ga29f93b01c146d755a6f46bb1f6ec8cee) | | +| [`startAt`](#group__base_1ga82eac31b0527400086bbe0c2414ad9b5) | | +| [`delay`](#group__base_1ga5d32e6ba4780efe685496b6d6ef95c62) | | +| [`operator=`](#group__base_1ga3f4396dde53c6f38869c40b1a1ee1074) | | +| [`_startAt`](#group__base_1gac8610fab1717accf992e597d12a904c1) | | +| [`_delay`](#group__base_1ga94fe2854e36942ecf3abff5a1f19769e) | | + +--- + +#### Timeout + +```cpp +Timeout(long delay, bool autoStart) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `delay` | `long` | | +| `autoStart` | `bool` | | -#### `public inline bool iswspace(const char c)` +--- +#### Timeout +```cpp +Timeout(const Timeout & src) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `src` | `const Timeout &` | | +--- -# struct `scy::hex::Encoder` +#### ~Timeout +```cpp +~Timeout() ``` -struct scy::hex::Encoder - : public scy::basic::Encoder -``` - -Hex encoder. +--- +#### running -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public int _linePos` | -`public int _lineLength` | -`public int _uppercase` | -`public inline Encoder()` | -`public inline virtual ssize_t encode(const char * inbuf,size_t nread,char * outbuf)` | -`public inline virtual ssize_t finalize(char *)` | -`public inline void setUppercase(bool flag)` | -`public inline void setLineLength(int lineLength)` | +```cpp +bool running() const +``` -## Members +--- -#### `public int _linePos` +#### start +```cpp +void start() +``` +--- +#### stop +```cpp +void stop() +``` -#### `public int _lineLength` +--- +#### reset +```cpp +void reset() +``` +--- +#### remaining -#### `public int _uppercase` +```cpp +long remaining() const +``` +--- +#### expired +```cpp +bool expired() const +``` +--- -#### `public inline Encoder()` +#### setDelay +```cpp +inline void setDelay(long delay) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `delay` | `long` | | +--- +#### startAt -#### `public inline virtual ssize_t encode(const char * inbuf,size_t nread,char * outbuf)` +```cpp +inline clock_t startAt() const +``` +--- +#### delay +```cpp +inline long delay() const +``` +--- -#### `public inline virtual ssize_t finalize(char *)` +#### operator= +```cpp +Timeout & operator=(const Timeout & src) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `src` | `const Timeout &` | | +--- +#### _startAt -#### `public inline void setUppercase(bool flag)` +```cpp +clock_t _startAt +``` +--- +#### _delay +```cpp +long _delay +``` +## TimedToken -#### `public inline void setLineLength(int lineLength)` +> **Extends:** `scy::Timeout` +> **Defined in:** `timeout.h` +Token that expires after the specified duration. +### Members +| Name | Description | +|------|-------------| +| [`TimedToken`](#group__base_1ga3172961c6e661451b64bc60c935c2e30) | | +| [`TimedToken`](#group__base_1ga00d0a09459c0d5b2de18de73ccf1eda7) | | +| [`id`](#group__base_1ga468f28c2d15d97b85ed6687bec10ce37) | | +| [`operator==`](#group__base_1ga36b8cadb6d6ccc57b725b530d8f92f47) | | +| [`operator==`](#group__base_1ga44476c978974979e4cb079b8562ce724) | | +| [`_id`](#group__base_1ga7d90971c34ef4d63f00a5153c74cc1c3) | | +--- -# namespace `scy::basic` +#### TimedToken -Interface classes. +```cpp +TimedToken(long duration) +``` -## Summary +| Parameter | Type | Description | +|-----------|------|-------------| +| `duration` | `long` | | - Members | Descriptions ---------------------------------|--------------------------------------------- -`class `[`scy::basic::Decoder`](#classscy_1_1basic_1_1Decoder) | -`class `[`scy::basic::Encoder`](#classscy_1_1basic_1_1Encoder) | -`class `[`scy::basic::Runnable`](#classscy_1_1basic_1_1Runnable) | Abstract interface for classes that can be run and cancelled. -`class `[`scy::basic::Sendable`](#classscy_1_1basic_1_1Sendable) | Abstract interface for classes that can be sent and cancelled. -`class `[`scy::basic::Startable`](#classscy_1_1basic_1_1Startable) | Abstract interface for a classes that can be started and stopped. -# class `scy::basic::Decoder` +--- +#### TimedToken +```cpp +TimedToken(const std::string & id, long duration) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `id` | `const std::string &` | | +| `duration` | `long` | | +--- +#### id -## Summary +```cpp +inline std::string id() const +``` - Members | Descriptions ---------------------------------|--------------------------------------------- -`public inline Decoder()` | -`public inline virtual ~Decoder()` | -`public ssize_t decode(const char * inbuf,size_t nread,char * outbuf)` | -`public inline virtual ssize_t finalize(char *)` | +--- -## Members +#### operator== -#### `public inline Decoder()` +```cpp +inline bool operator==(const TimedToken & r) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `r` | `const TimedToken &` | | +--- +#### operator== +```cpp +inline bool operator==(const std::string & r) const +``` -#### `public inline virtual ~Decoder()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `r` | `const std::string &` | | +--- +#### _id +```cpp +std::string _id +``` +## OptionParser -#### `public ssize_t decode(const char * inbuf,size_t nread,char * outbuf)` +> **Defined in:** `application.h` +### Members +| Name | Description | +|------|-------------| +| [`OptionParser`](#group__base_1gacfaf92525d5f46c8c4165b4e9687a01e) | | +| [`has`](#group__base_1gadce3a04bb7896063238940156056e18e) | | +| [`get`](#group__base_1ga975b86adb62cff3250a769a9e63d2d7c) | | +| [`get`](#group__base_1gadc8dc1da69c345f00ee501b8b163da3b) | | +| [`exepath`](#group__base_1gacf94798c87c7e8a3d9c0fee9f0b9b021) | | +| [`args`](#group__base_1ga3f72252b7f830d90de66dcefa2372585) | | +--- +#### OptionParser -#### `public inline virtual ssize_t finalize(char *)` +```cpp +OptionParser(int argc, char * argv, const char * delim) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `argc` | `int` | | +| `argv` | `char *` | | +| `delim` | `const char *` | | +--- +#### has +```cpp +inline bool has(const char * key) +``` -# class `scy::basic::Encoder` +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `const char *` | | +--- +#### get +```cpp +inline std::string get(const char * key) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `const char *` | | +--- -## Summary +#### get - Members | Descriptions ---------------------------------|--------------------------------------------- -`public inline Encoder()` | -`public inline virtual ~Encoder()` | -`public ssize_t encode(const char * inbuf,size_t nread,char * outbuf)` | -`public inline virtual ssize_t finalize(char *)` | +```cpp +template inline NumericType get(const char * key) +``` -## Members +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `const char *` | | -#### `public inline Encoder()` +--- +#### exepath +```cpp +std::string exepath +``` +--- +#### args -#### `public inline virtual ~Encoder()` +```cpp +OptionMap args +``` +## ShutdownCmd +> **Defined in:** `application.h` +### Members +| Name | Description | +|------|-------------| +| [`opaque`](#group__base_1gaf060b2f1e83d40f1648fed0eae5a3083) | | +| [`callback`](#group__base_1gad5fcf4a4368d6d70bafa19fe339edfcc) | | -#### `public ssize_t encode(const char * inbuf,size_t nread,char * outbuf)` +--- +#### opaque +```cpp +void * opaque +``` +--- +#### callback -#### `public inline virtual ssize_t finalize(char *)` +```cpp +std::function< void(void *)> callback +``` +## Encoder +> **Extends:** `scy::basic::Encoder` +> **Defined in:** `base64.h` +Base64 encoder. +### Members -# class `scy::basic::Runnable` +| Name | Description | +|------|-------------| +| [`Encoder`](#group__base_1ga0b4bbf5fe617990a4044d61a5aa4d9b5) | | +| [`encode`](#group__base_1ga8cd9623054dd2d6eebee7561feeeaec5) | | +| [`encode`](#group__base_1ga169108c69ec1b416d1bdc1a21eb2114d) | | +| [`encode`](#group__base_1ga7466c9aec36a67c1f41a20841f09192c) | | +| [`finalize`](#group__base_1ga203b9c249c5a45dc281d85b74588f8ee) | | +| [`setLineLength`](#group__base_1gaa95988d443bebd458b3c2e421a46d799) | | +| [`_state`](#group__base_1gad85db3c5637d5b339034826bdbc0e786) | | +| [`_buffersize`](#group__base_1ga759e0716429cb47740e4a65ab28acc6b) | | +--- -Abstract interface for classes that can be run and cancelled. +#### Encoder +```cpp +inline Encoder(int buffersize) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `buffersize` | `int` | | -## Summary +--- - Members | Descriptions ---------------------------------|--------------------------------------------- -`public inline Runnable()` | -`public inline virtual ~Runnable()` | -`public void run()` | The run method will be called by the asynchronous context. -`public inline virtual void cancel(bool flag)` | -`public inline virtual bool cancelled() const` | Returns true when the task has been cancelled. -`protected std::atomic< bool > exit` | +#### encode -## Members +```cpp +inline void encode(std::istream & istrm, std::ostream & ostrm) +``` -#### `public inline Runnable()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `istrm` | `std::istream &` | | +| `ostrm` | `std::ostream &` | | +--- +#### encode +```cpp +inline void encode(const std::string & in, std::string & out) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `in` | `const std::string &` | | +| `out` | `std::string &` | | -#### `public inline virtual ~Runnable()` +--- +#### encode +```cpp +virtual inline ssize_t encode(const char * inbuf, size_t nread, char * outbuf) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `inbuf` | `const char *` | | +| `nread` | `size_t` | | +| `outbuf` | `char *` | | +--- -#### `public void run()` +#### finalize -The run method will be called by the asynchronous context. +```cpp +virtual inline ssize_t finalize(char * outbuf) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `outbuf` | `char *` | | +--- -#### `public inline virtual void cancel(bool flag)` +#### setLineLength +```cpp +inline void setLineLength(int lineLength) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `lineLength` | `int` | | -Cancel the current task. The [run()](#group__base_1ga58cbd03f96d0fcbac2441437f5325e5e) method should return ASAP. +--- -#### `public inline virtual bool cancelled() const` +#### _state -Returns true when the task has been cancelled. +```cpp +internal::encodestate _state +``` +--- +#### _buffersize -#### `protected std::atomic< bool > exit` +```cpp +int _buffersize +``` +## Decoder +> **Extends:** `scy::basic::Decoder` +> **Defined in:** `base64.h` +Base64 decoder. +### Members -# class `scy::basic::Sendable` +| Name | Description | +|------|-------------| +| [`Decoder`](#group__base_1ga3a55fbfacbfe7fb8ea87b7788d02f7b7) | | +| [`decode`](#group__base_1ga6ebfa454300eb5794cee27ce14d2210a) | | +| [`decode`](#group__base_1ga8156e5a9480a2c87dadc098e7827ac73) | | +| [`decode`](#group__base_1gaee095eb1f717a873862271efdf8b78f5) | | +| [`_state`](#group__base_1ga852ccfc6b149bdbf6158bd830a00fb8f) | | +| [`_buffersize`](#group__base_1gae44073b77993e4a6a1461d75960aaa61) | | +--- -Abstract interface for classes that can be sent and cancelled. +#### Decoder +```cpp +inline Decoder(int buffersize) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `buffersize` | `int` | | -## Summary +--- - Members | Descriptions ---------------------------------|--------------------------------------------- -`public bool send()` | -`public inline virtual void cancel()` | +#### decode -## Members +```cpp +inline ssize_t decode(char value_in) +``` -#### `public bool send()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `value_in` | `char` | | +--- +#### decode +```cpp +virtual inline ssize_t decode(const char * inbuf, size_t nread, char * outbuf) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `inbuf` | `const char *` | | +| `nread` | `size_t` | | +| `outbuf` | `char *` | | -#### `public inline virtual void cancel()` +--- +#### decode +```cpp +inline void decode(std::istream & istrm, std::ostream & ostrm) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `istrm` | `std::istream &` | | +| `ostrm` | `std::ostream &` | | +--- -# class `scy::basic::Startable` +#### _state +```cpp +internal::decodestate _state +``` -Abstract interface for a classes that can be started and stopped. +--- +#### _buffersize +```cpp +int _buffersize +``` -## Summary +## Bitwise - Members | Descriptions ---------------------------------|--------------------------------------------- -`public void start()` | -`public void stop()` | +> **Defined in:** `bitwise.h` -## Members +Container for smart management of bitwise integer flags. -#### `public void start()` +### Members +| Name | Description | +|------|-------------| +| [`Bitwise`](#group__base_1gab17fe0dc48af357d997ba8bcce089def) | | +| [`reset`](#group__base_1ga61f01af4d27436a26ef0c336f9d0dd23) | | +| [`set`](#group__base_1ga73020121e07e2201909bf45030ef28c9) | | +| [`add`](#group__base_1ga3ff03ce689fc75d83c0fd12e25f4e489) | | +| [`remove`](#group__base_1ga8fbd08d9008b713faa32830f3f164075) | | +| [`toggle`](#group__base_1ga34695eee0b63a6118ef4af65f9dbf081) | | +| [`has`](#group__base_1ga84fb5bee9780f9ed4f6417adf378a039) | | +| [`data`](#group__base_1ga561f756550e5240f615043453f77912b) | | +--- +#### Bitwise +```cpp +inline Bitwise(unsigned flags) +``` -#### `public void stop()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `flags` | `unsigned` | | +--- +#### reset +```cpp +virtual inline void reset() +``` +--- -# namespace `scy::ipc` +#### set -Classes for inter-process communication. +```cpp +virtual inline void set(unsigned flag) +``` -## Summary +| Parameter | Type | Description | +|-----------|------|-------------| +| `flag` | `unsigned` | | - Members | Descriptions ---------------------------------|--------------------------------------------- -`class `[`scy::ipc::Queue`](#classscy_1_1ipc_1_1Queue) | -`class `[`scy::ipc::SyncQueue`](#classscy_1_1ipc_1_1SyncQueue) | -`struct `[`scy::ipc::Action`](#structscy_1_1ipc_1_1Action) | Default action type for executing synchronized callbacks. -# class `scy::ipc::Queue` +--- +#### add +```cpp +virtual inline void add(unsigned flag) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `flag` | `unsigned` | | -IPC queue is for safely passing templated actions between threads and processes. +--- -## Summary +#### remove - Members | Descriptions ---------------------------------|--------------------------------------------- -`public inline Queue()` | -`public inline virtual ~Queue()` | -`public inline virtual void push(TAction * action)` | -`public inline virtual TAction * pop()` | -`public inline virtual void runSync()` | -`public inline virtual void close()` | -`public inline virtual void post()` | -`public inline void waitForSync()` | -`protected mutable std::mutex _mutex` | -`protected std::deque< TAction * > _actions` | +```cpp +virtual inline void remove(unsigned flag) +``` -## Members +| Parameter | Type | Description | +|-----------|------|-------------| +| `flag` | `unsigned` | | -#### `public inline Queue()` +--- +#### toggle +```cpp +virtual inline void toggle(unsigned flag) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `flag` | `unsigned` | | +--- -#### `public inline virtual ~Queue()` +#### has +```cpp +virtual inline bool has(unsigned flag) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `flag` | `unsigned` | | +--- +#### data -#### `public inline virtual void push(TAction * action)` +```cpp +unsigned data +``` +## ILT +> **Defined in:** `collection.h` +### Members +| Name | Description | +|------|-------------| +| [`operator()`](#group__base_1ga966ae0464dd2d1011bcd55702729b5eb) | | -#### `public inline virtual TAction * pop()` +--- +#### operator() +```cpp +inline bool operator()(const std::string & s1, const std::string & s2) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `s1` | `const std::string &` | | +| `s2` | `const std::string &` | | +## AbstractDelegate -#### `public inline virtual void runSync()` +> **Defined in:** `delegate.h` +Abstract delegate interface. +The `Delegate` class contains a pointer to a function. This wrapper class is used instead of `std::function` since it is interchangable with fast delegates and also provides an equality operator for comparing the underlying function where supported. +### Members +| Name | Description | +|------|-------------| +| [`~AbstractDelegate`](#group__base_1ga1af7274ae4df82deae9da6ee4ae98fe5) | | +| [`operator()`](#group__base_1ga3b6d651d76d2b08df99ea910dcc102d2) | | +| [`operator==`](#group__base_1ga1680a6dd4d3a54f5e52189e3d7d043bd) | | -#### `public inline virtual void close()` +--- +#### ~AbstractDelegate +```cpp +virtual inline ~AbstractDelegate() +``` +--- +#### operator() -#### `public inline virtual void post()` +```cpp +RT operator()(Args... args) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `args` | `Args...` | | +--- +#### operator== +```cpp +bool operator==(const AbstractDelegate< RT, Args... > & that) const +``` -#### `public inline void waitForSync()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `that` | `const AbstractDelegate< RT, Args... > &` | | +## FunctionDelegate +> **Extends:** `scy::AbstractDelegate< RT, Args... >` +> **Defined in:** `delegate.h` +The `[FunctionDelegate](#structscy_1_1FunctionDelegate)` contains a `std::function`. +### Members -#### `protected mutable std::mutex _mutex` +| Name | Description | +|------|-------------| +| [`FunctionDelegate`](#group__base_1gafcbadf834f7a4d0a40ca4e5db7e34f14) | | +| [`operator()`](#group__base_1gad7c59caa9745234db4724fc1ea3d9501) | | +| [`operator==`](#group__base_1ga09fee8d97f33cb5b1ae140177a689810) | | +| [`func`](#group__base_1gaca57bf731778089faea714a0a8fcf078) | | +--- +#### FunctionDelegate +```cpp +inline FunctionDelegate(std::function< RT(Args...)> func) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `func` | `std::function< RT(Args...)>` | | -#### `protected std::deque< TAction * > _actions` +--- +#### operator() +```cpp +virtual inline RT operator()(Args... args) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `args` | `Args...` | | +--- -# class `scy::ipc::SyncQueue` +#### operator== +```cpp +virtual inline bool operator==(const AbstractDelegate< RT, Args... > &) const ``` -class scy::ipc::SyncQueue - : public scy::ipc::Queue< TAction > -``` +--- +#### func -IPC synchronization queue is for passing templated actions between threads and the event loop we are synchronizing with. +```cpp +std::function< RT(Args...)> func +``` + +## ClassDelegate -## Summary +> **Extends:** `scy::AbstractDelegate< RT, Args... >` +> **Defined in:** `delegate.h` - Members | Descriptions ---------------------------------|--------------------------------------------- -`public inline SyncQueue(uv::Loop * loop)` | -`public inline virtual ~SyncQueue()` | -`public inline virtual void close()` | -`public inline virtual void post()` | -`public inline virtual `[`Synchronizer`](#classscy_1_1Synchronizer)` & sync()` | -`protected `[`Synchronizer`](./doc/api-base.md#classscy_1_1Synchronizer)` _sync` | +The `[ClassDelegate](#structscy_1_1ClassDelegate)` contains a pointer to a class member. -## Members +This class implements fast delegates and function comparison. -#### `public inline SyncQueue(uv::Loop * loop)` +### Members +| Name | Description | +|------|-------------| +| [`ClassDelegate`](#group__base_1ga1e015d5de17fee08ea68dd5718984608) | | +| [`operator()`](#group__base_1gaca4d987f9321f3916c722bf583d75c06) | | +| [`operator==`](#group__base_1ga7d0d05b24bab289f378cc0cebd3a47d0) | | +| [`instance`](#group__base_1gaa13b69a5686d1236aa09f96ed2fe35e2) | | +| [`method`](#group__base_1ga48f7cfa04f8bce9a3a4361015f5572a8) | | +--- +#### ClassDelegate +```cpp +inline ClassDelegate(Class * instance, RT(Class::*)(Args...) method) +``` -#### `public inline virtual ~SyncQueue()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `instance` | `Class *` | | +| `method` | `RT(Class::*)(Args...)` | | +--- +#### operator() +```cpp +virtual inline RT operator()(Args... args) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `args` | `Args...` | | -#### `public inline virtual void close()` +--- +#### operator== +```cpp +virtual inline bool operator==(const AbstractDelegate< RT, Args... > & that) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `that` | `const AbstractDelegate< RT, Args... > &` | | +--- -#### `public inline virtual void post()` +#### instance +```cpp +Class * instance +``` +--- +#### method +```cpp +RT(Class::* method +``` -#### `public inline virtual `[`Synchronizer`](#classscy_1_1Synchronizer)` & sync()` +## ConstClassDelegate +> **Extends:** `scy::AbstractDelegate< RT, Args... >` +> **Defined in:** `delegate.h` +The `[ConstClassDelegate](#structscy_1_1ConstClassDelegate)` contains a pointer to a `const` class member. +This class implements fast delegates and function comparison. +### Members -#### `protected `[`Synchronizer`](./doc/api-base.md#classscy_1_1Synchronizer)` _sync` +| Name | Description | +|------|-------------| +| [`ConstClassDelegate`](#group__base_1ga5fac63979562f15b65f25a483ab0f169) | | +| [`operator()`](#group__base_1ga762fd100320822342b42ed13377c1654) | | +| [`operator==`](#group__base_1ga3e792075d3ee46ae33399d3be3ff7474) | | +| [`instance`](#group__base_1ga4bee6cef9aa2f40ca5e2135acb7792a4) | | +| [`method`](#group__base_1ga6a3575991488c6157ecb7b8136259bbe) | | +--- +#### ConstClassDelegate +```cpp +inline ConstClassDelegate(Class * instance, RT(Class::*)(Args...) const method) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `instance` | `Class *` | | +| `method` | `RT(Class::*)(Args...) const` | | -# struct `scy::ipc::Action` +--- +#### operator() -Default action type for executing synchronized callbacks. +```cpp +virtual inline RT operator()(Args... args) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `args` | `Args...` | | +--- -## Summary +#### operator== - Members | Descriptions ---------------------------------|--------------------------------------------- -`public Callback target` | -`public void * arg` | -`public std::string data` | -`public inline Action(Callback target,void * arg,const std::string & data)` | +```cpp +virtual inline bool operator==(const AbstractDelegate< RT, Args... > & that) const +``` -## Members +| Parameter | Type | Description | +|-----------|------|-------------| +| `that` | `const AbstractDelegate< RT, Args... > &` | | -#### `public Callback target` +--- +#### instance +```cpp +Class * instance +``` +--- +#### method -#### `public void * arg` +```cpp +RT(Class::* method +``` +## PolymorphicDelegate +> **Extends:** `scy::AbstractDelegate< RT, IT & >` +> **Defined in:** `delegate.h` +Polymorphic function delegate. +Theis class contains a pointer to a class member that receices a derived subclass (`PT`) of the base type specified by the `IT` param. -#### `public std::string data` +### Members +| Name | Description | +|------|-------------| +| [`PolymorphicDelegate`](#group__base_1ga053ed6d6ff8aaaf7a3d5e5f890470877) | | +| [`operator()`](#group__base_1ga180cb44cb8588e1cb8ed2d8532944903) | | +| [`operator==`](#group__base_1ga5d574d1759ddc6b92fb3252e445896d2) | | +| [`instance`](#group__base_1gad74b599904e1a50cc05d2a4ab2f20a03) | | +| [`method`](#group__base_1ga8efb24a32f5f596d1aeefba40af69b3d) | | +--- +#### PolymorphicDelegate +```cpp +inline PolymorphicDelegate(Class * instance, RT(Class::*)(PT &) method) +``` -#### `public inline Action(Callback target,void * arg,const std::string & data)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `instance` | `Class *` | | +| `method` | `RT(Class::*)(PT &)` | | +--- +#### operator() +```cpp +virtual inline RT operator()(IT & object) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `object` | `IT &` | | -# namespace `scy::deleter` +--- -Deleter Functors. +#### operator== -## Summary +```cpp +virtual inline bool operator==(const AbstractDelegate< RT, IT & > & that) const +``` - Members | Descriptions ---------------------------------|--------------------------------------------- -`struct `[`scy::deleter::Array`](#structscy_1_1deleter_1_1Array) | -`struct `[`scy::deleter::Deferred`](#structscy_1_1deleter_1_1Deferred) | -`struct `[`scy::deleter::Dispose`](#structscy_1_1deleter_1_1Dispose) | -# struct `scy::deleter::Array` +| Parameter | Type | Description | +|-----------|------|-------------| +| `that` | `const AbstractDelegate< RT, IT & > &` | | +--- +#### instance +```cpp +Class * instance +``` +--- +#### method -## Summary +```cpp +RT(Class::* method +``` - Members | Descriptions ---------------------------------|--------------------------------------------- -`public inline void operator()(T * ptr)` | +## Error -## Members +> **Defined in:** `error.h` -#### `public inline void operator()(T * ptr)` +Basic error type. +Errors contain an error code, message, and exception pointer. +### Members +| Name | Description | +|------|-------------| +| [`Error`](#group__base_1gaab8c612dc5997bbf6b57397ec1a0e6d9) | | +| [`Error`](#group__base_1ga75e04b5142b2bcec58bf418dd15253c7) | | +| [`Error`](#group__base_1gab773389bc3179a4587bb57fba06addbe) | | +| [`any`](#group__base_1ga6acffca8b048905bbc39b40a9f6a589c) | | +| [`reset`](#group__base_1ga55e9f6b538f9526c20ccafe8df691f7d) | | +| [`rethrow`](#group__base_1gabe0a98baa3810d0e0ed301c4ce44b3b1) | | +| [`err`](#group__base_1ga87426c8d146710ad14ed03a6d6dd5ff7) | | +| [`message`](#group__base_1ga2c262d00d0cfd95c2d7326a6907269da) | | +| [`exception`](#group__base_1gafa6e4615e88233c1ec0d1f0cb56b05f7) | | +--- -# struct `scy::deleter::Deferred` +#### Error +```cpp +inline Error() +``` +--- +#### Error +```cpp +inline Error(const std::string & msg) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `msg` | `const std::string &` | | -## Summary +--- - Members | Descriptions ---------------------------------|--------------------------------------------- -`public inline void operator()(T * ptr)` | +#### Error -## Members +```cpp +inline Error(const char * msg) +``` -#### `public inline void operator()(T * ptr)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `msg` | `const char *` | | +--- +#### any +```cpp +inline bool any() const +``` +--- -# struct `scy::deleter::Dispose` +#### reset +```cpp +inline void reset() +``` +--- +#### rethrow +```cpp +inline void rethrow() +``` +--- -## Summary +#### err - Members | Descriptions ---------------------------------|--------------------------------------------- -`public inline void operator()(T * ptr)` | +```cpp +int err +``` -## Members +--- -#### `public inline void operator()(T * ptr)` +#### message +```cpp +std::string message +``` +--- +#### exception +```cpp +std::exception_ptr exception +``` -# namespace `scy::test` +## Encoder -Modern unit testing framework. +> **Extends:** `scy::basic::Encoder` +> **Defined in:** `hex.h` -## Summary +Hex encoder. - Members | Descriptions ---------------------------------|--------------------------------------------- -`class `[`scy::test::FunctionTest`](#classscy_1_1test_1_1FunctionTest) | -`class `[`scy::test::Test`](#classscy_1_1test_1_1Test) | -`class `[`scy::test::TestRunner`](#classscy_1_1test_1_1TestRunner) | -# class `scy::test::FunctionTest` +### Members -``` -class scy::test::FunctionTest - : public scy::test::Test -``` +| Name | Description | +|------|-------------| +| [`Encoder`](#group__base_1gaa0343ef0f07c144b4a50748750004aee) | | +| [`encode`](#group__base_1ga013a8ad2abd63a127a87106d2b115a77) | | +| [`finalize`](#group__base_1gad6a22c7c309534c6f8f484ce86e1445c) | | +| [`setUppercase`](#group__base_1gaf3135b7edfac6b752a05686c193e2495) | | +| [`setLineLength`](#group__base_1ga9c23084ff0fc0b186777ca003e30deda) | | +| [`_linePos`](#group__base_1ga288899d48739dcf0378d6b9f11dfe58f) | | +| [`_lineLength`](#group__base_1ga064c41e567fdbeb17a86c98f2bd278ff) | | +| [`_uppercase`](#group__base_1ga4c6c6ece9aee62f7edbe81a4462b6f9f) | | +--- +#### Encoder +```cpp +inline Encoder() +``` +--- -## Summary +#### encode - Members | Descriptions ---------------------------------|--------------------------------------------- -`public std::function< void()> target` | -`public inline FunctionTest(std::function< void()> target,const std::string & name)` | -`protected inline virtual ~FunctionTest()` | -`protected inline virtual void run()` | Called by the [TestRunner](./doc/api-base.md#classscy_1_1test_1_1TestRunner) to run the test. +```cpp +virtual inline ssize_t encode(const char * inbuf, size_t nread, char * outbuf) +``` -## Members +| Parameter | Type | Description | +|-----------|------|-------------| +| `inbuf` | `const char *` | | +| `nread` | `size_t` | | +| `outbuf` | `char *` | | -#### `public std::function< void()> target` +--- +#### finalize +```cpp +virtual inline ssize_t finalize(char *) +``` +--- +#### setUppercase -#### `public inline FunctionTest(std::function< void()> target,const std::string & name)` +```cpp +inline void setUppercase(bool flag) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `flag` | `bool` | | +--- +#### setLineLength +```cpp +inline void setLineLength(int lineLength) +``` -#### `protected inline virtual ~FunctionTest()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `lineLength` | `int` | | +--- +#### _linePos +```cpp +int _linePos +``` +--- -#### `protected inline virtual void run()` +#### _lineLength -Called by the [TestRunner](#classscy_1_1test_1_1TestRunner) to run the test. +```cpp +int _lineLength +``` +--- +#### _uppercase -# class `scy::test::Test` +```cpp +int _uppercase +``` +## Decoder +> **Extends:** `scy::basic::Decoder` +> **Defined in:** `hex.h` +Hex decoder. -[Test](#classscy_1_1test_1_1Test) wrapper class. +### Members -This class is for implementing any kind of unit test that can be executed by a `[TestRunner](#classscy_1_1test_1_1TestRunner)`. +| Name | Description | +|------|-------------| +| [`Decoder`](#group__base_1ga5998a95cdfedea8b8ab0a02065f0a624) | | +| [`~Decoder`](#group__base_1ga9d6d431cf4d0739cf304afcbc2962b2d) | | +| [`decode`](#group__base_1gacf9b20b34b833cc8cb7d0db55de85b2e) | | +| [`finalize`](#group__base_1ga9ed7367746cf1fa8291da4aecdf3cf79) | | +| [`readnext`](#group__base_1ga2bdf4e0671eae619854ec7788e23afa1) | | +| [`nybble`](#group__base_1gad58c78f2177b39304b7e910d56eac83d) | | +| [`iswspace`](#group__base_1ga19c548e3b173984aba506a7f8a837d6f) | | +| [`lastbyte`](#group__base_1gacf494fcbc21eb2ff254940ad66e3da68) | | -## Summary +--- - Members | Descriptions ---------------------------------|--------------------------------------------- -`public std::string name` | The name of the test. -`public ErrorList errors` | A list of test errors. -`public double duration` | The test run duration for benchmarking. -`public Test(const std::string & name)` | -`public virtual ~Test()` | Should remain protected. -`public void run()` | Called by the [TestRunner](./doc/api-base.md#classscy_1_1test_1_1TestRunner) to run the test. -`public bool passed()` | Return true when the test passed without errors. -`protected Test(const `[`Test`](#classscy_1_1test_1_1Test)` & test) = delete` | -`protected `[`Test`](#classscy_1_1test_1_1Test)` & operator=(`[`Test`](#classscy_1_1test_1_1Test)` const &) = delete` | +#### Decoder -## Members +```cpp +inline Decoder() +``` -#### `public std::string name` +--- -The name of the test. +#### ~Decoder +```cpp +virtual inline ~Decoder() +``` +--- -#### `public ErrorList errors` +#### decode -A list of test errors. +```cpp +virtual inline ssize_t decode(const char * inbuf, size_t nread, char * outbuf) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `inbuf` | `const char *` | | +| `nread` | `size_t` | | +| `outbuf` | `char *` | | +--- -#### `public double duration` +#### finalize -The test run duration for benchmarking. +```cpp +virtual inline ssize_t finalize(char *) +``` +--- +#### readnext -#### `public Test(const std::string & name)` +```cpp +inline bool readnext(const char * inbuf, size_t nread, size_t & rpos, char & c) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `inbuf` | `const char *` | | +| `nread` | `size_t` | | +| `rpos` | `size_t &` | | +| `c` | `char &` | | +--- +#### nybble +```cpp +inline int nybble(const int n) +``` -#### `public virtual ~Test()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `n` | `const int` | | -Should remain protected. +--- +#### iswspace +```cpp +inline bool iswspace(const char c) +``` -#### `public void run()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `c` | `const char` | | -Called by the [TestRunner](#classscy_1_1test_1_1TestRunner) to run the test. +--- +#### lastbyte +```cpp +char lastbyte +``` -#### `public bool passed()` +## Action -Return true when the test passed without errors. +> **Defined in:** `ipc.h` +Default action type for executing synchronized callbacks. +### Members -#### `protected Test(const `[`Test`](#classscy_1_1test_1_1Test)` & test) = delete` +| Name | Description | +|------|-------------| +| [`Action`](#group__base_1gad514b31a48c3cbdbbe22285058efc830) | | +| [`target`](#group__base_1ga2f7b67072f4348a827abba8403d02ace) | | +| [`arg`](#group__base_1ga7bfadcacf4497ab86260402b2f4129e7) | | +| [`data`](#group__base_1gaaf3ce54c7827ef8b2958a6caa8f9fbab) | | +--- +#### Action +```cpp +inline Action(Callback target, void * arg, const std::string & data) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `target` | `Callback` | | +| `arg` | `void *` | | +| `data` | `const std::string &` | | -#### `protected `[`Test`](#classscy_1_1test_1_1Test)` & operator=(`[`Test`](#classscy_1_1test_1_1Test)` const &) = delete` +--- +#### target +```cpp +Callback target +``` +--- +#### arg -# class `scy::test::TestRunner` +```cpp +void * arg +``` +--- +#### data +```cpp +std::string data +``` -[Test](#classscy_1_1test_1_1Test) manager queue. +## LogStream -The `[TestRunner](#classscy_1_1test_1_1TestRunner)` is a queue in charge of running one or many tests. +> **Defined in:** `logger.h` -When `[run()](#group__base_1gae237ec747f0a785fb2514154a46022b3)` the `[TestRunner](#classscy_1_1test_1_1TestRunner)` loops through each test in the list calling the test's `[run()](#group__base_1gae237ec747f0a785fb2514154a46022b3)` method. +### Members -## Summary +| Name | Description | +|------|-------------| +| [`LogStream`](#group__base_1ga0b017d90cac27462656e4fed47a7a914) | | +| [`LogStream`](#group__base_1ga234f0a55d2faddf5b97dca2ae579c23b) | | +| [`write`](#group__base_1ga6fa8f529dcd3bad150c2f55115842917) | | +| [`operator<<`](#group__base_1ga1cba951b82630ad2f0e5f5fe6e19c901) | | +| [`operator<<`](#group__base_1gaf934f45be9fbd983294e2ba9e4d50ece) | | - Members | Descriptions ---------------------------------|--------------------------------------------- -`public TestRunner()` | -`public virtual ~TestRunner()` | -`public void add(`[`Test`](#classscy_1_1test_1_1Test)` * test)` | Add a test to the runner. -`public `[`Test`](#classscy_1_1test_1_1Test)` * get(const std::string & name) const` | -`public void run()` | Called by the async context to run the next test. -`public void clear()` | Destroy and clears all managed tests. -`public `[`Test`](#classscy_1_1test_1_1Test)` * current() const` | Return the currently active [Test](./doc/api-base.md#classscy_1_1test_1_1Test) or nullptr. -`public TestList tests() const` | Return the list of tests. -`public ErrorMap errors() const` | Return a map of tests and errors. -`public bool passed() const` | Return true if all tests passed. -`protected mutable std::mutex _mutex` | -`protected TestList _tests` | -`protected `[`Test`](./doc/api-base.md#classscy_1_1test_1_1Test)` * _current` | +--- -## Members +#### LogStream -#### `public TestRunner()` +```cpp +inline LogStream(Level level, std::string realm, int line, const char * channel) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `level` | `Level` | | +| `realm` | `std::string` | | +| `line` | `int` | | +| `channel` | `const char *` | | +--- +#### LogStream +```cpp +inline LogStream(const LogStream & that) +``` -#### `public virtual ~TestRunner()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `that` | `const LogStream &` | | +--- +#### write +```cpp +template inline void write(Args... args) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `args` | `Args...` | | -#### `public void add(`[`Test`](#classscy_1_1test_1_1Test)` * test)` +--- -Add a test to the runner. +#### operator<< +```cpp +template inline LogStream & operator<<(const T &) +``` +--- -#### `public `[`Test`](#classscy_1_1test_1_1Test)` * get(const std::string & name) const` +#### operator<< +```cpp +inline LogStream & operator<<(std::ostream &(*)(std::ostream &) f) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `f` | `std::ostream &(*)(std::ostream &)` | | -Return a pointer to the test matching the given name, or nullptr if no matching test exists. +## Dispose -#### `public void run()` +> **Defined in:** `memory.h` -Called by the async context to run the next test. +Deleter functor that calls dispose() on the pointer. +### Members +| Name | Description | +|------|-------------| +| [`operator()`](#group__base_1ga83955b9220bdccdbaac1ca7923c3ad65) | | -#### `public void clear()` +--- -Destroy and clears all managed tests. +#### operator() +```cpp +inline void operator()(T * ptr) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `ptr` | `T *` | | -#### `public `[`Test`](#classscy_1_1test_1_1Test)` * current() const` +## Array -Return the currently active [Test](#classscy_1_1test_1_1Test) or nullptr. +> **Defined in:** `memory.h` +Deleter functor for array pointers. +### Members -#### `public TestList tests() const` +| Name | Description | +|------|-------------| +| [`operator()`](#group__base_1ga2b9a2ee44aca9d8171c8188d1caa5e53) | | -Return the list of tests. +--- +#### operator() +```cpp +inline void operator()(T * ptr) +``` -#### `public ErrorMap errors() const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `ptr` | `T *` | | -Return a map of tests and errors. +## IPacketInfo +> **Subclasses:** `scy::net::PacketInfo` +> **Defined in:** `packet.h` +An abstract interface for packet sources to provide extra information about packets. -#### `public bool passed() const` +### Members -Return true if all tests passed. +| Name | Description | +|------|-------------| +| [`IPacketInfo`](#group__base_1ga992e069cee48907d6df5da25f484e868) | | +| [`~IPacketInfo`](#group__base_1ga2a4f88eda361491c5ab8b2ca3f8b8199) | | +| [`clone`](#group__base_1gaa21cf32fa208d94f1848dd747de03500) | | +--- +#### IPacketInfo -#### `protected mutable std::mutex _mutex` +```cpp +IPacketInfo() = default +``` +--- +#### ~IPacketInfo +```cpp +virtual ~IPacketInfo() = default +``` +--- -#### `protected TestList _tests` +#### clone +```cpp +IPacketInfo * clone() const +``` +## PacketCreationStrategy +> **Extends:** `scy::IPacketCreationStrategy` +> **Defined in:** `packetfactory.h` +This template class implements an adapter that sits between an SignalBase and an object receiving notifications from it. -#### `protected `[`Test`](./doc/api-base.md#classscy_1_1test_1_1Test)` * _current` +### Members +| Name | Description | +|------|-------------| +| [`PacketCreationStrategy`](#group__base_1gaf5895e8457d4d23df0a521026546ca73) | | +| [`~PacketCreationStrategy`](#group__base_1gafad0e19b9e69c85139949c859da8ac1f) | | +| [`create`](#group__base_1ga894eabd43c26cb9ff8930f3de6acd06d) | | +| [`priority`](#group__base_1ga6fdf4baa67285b1c4cecea31598edd42) | | +| [`_priority`](#group__base_1ga192649e00c46e3d9ce641e448f207ea9) | | +--- +#### PacketCreationStrategy +```cpp +inline PacketCreationStrategy(int priority) +``` -# namespace `scy::util` +| Parameter | Type | Description | +|-----------|------|-------------| +| `priority` | `int` | | +--- +#### ~PacketCreationStrategy -## Summary +```cpp +virtual inline ~PacketCreationStrategy() +``` - Members | Descriptions ---------------------------------|--------------------------------------------- -`struct `[`scy::util::Version`](#structscy_1_1util_1_1Version) | -# struct `scy::util::Version` +--- +#### create +```cpp +virtual inline IPacket * create(const ConstBuffer & buffer, size_t & nread) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `buffer` | `const ConstBuffer &` | | +| `nread` | `size_t &` | | +--- +#### priority -## Summary +```cpp +virtual inline int priority() const +``` - Members | Descriptions ---------------------------------|--------------------------------------------- -`public int major` | -`public int minor` | -`public int revision` | -`public int build` | -`public inline Version(const std::string & version)` | -`public inline bool operator<(const `[`Version`](#structscy_1_1util_1_1Version)` & other)` | -`public inline bool operator==(const `[`Version`](#structscy_1_1util_1_1Version)` & other)` | +--- -## Members +#### _priority -#### `public int major` +```cpp +int _priority +``` +## PacketAdapterReference +> **Defined in:** `packetstream.h` +Provides a reference to a [PacketStreamAdapter](#classscy_1_1PacketStreamAdapter) with optional ownership. +### Members -#### `public int minor` +| Name | Description | +|------|-------------| +| [`PacketAdapterReference`](#group__base_1ga91bc371499cd7aa33df43e0d0e7092c4) | Construct with raw pointer (non-owning). | +| [`PacketAdapterReference`](#group__base_1ga1e47fed55e3ab3d6a75c05a22f66205d) | Construct with shared_ptr ownership. | +| [`compareOrder`](#group__base_1gab82d5838221a0af7d6722446e3f9e49c) | | +| [`ptr`](#group__base_1ga91ef0542de1409ffa2a4a55d735abc99) | | +| [`_prevent_deletion`](#group__base_1ga32fa567738d15daed55ad4e7c66fd485) | | +| [`order`](#group__base_1ga1ede9883ce7a84245fd2ed7b6428ff1d) | | +| [`syncState`](#group__base_1ga67b82c55538ee173a9305b0dad953f3f) | | +--- +#### PacketAdapterReference +```cpp +inline PacketAdapterReference(PacketStreamAdapter * ptr, int order, bool syncState) +``` +Construct with raw pointer (non-owning). -#### `public int revision` +| Parameter | Type | Description | +|-----------|------|-------------| +| `ptr` | `PacketStreamAdapter *` | | +| `order` | `int` | | +| `syncState` | `bool` | | +--- +#### PacketAdapterReference +```cpp +template inline PacketAdapterReference(std::shared_ptr< C > owned, int order, bool syncState) +``` +Construct with shared_ptr ownership. -#### `public int build` +| Parameter | Type | Description | +|-----------|------|-------------| +| `owned` | `std::shared_ptr< C >` | | +| `order` | `int` | | +| `syncState` | `bool` | | +--- +#### compareOrder +```cpp +static inline bool compareOrder(const PacketAdapterReference::Ptr & l, const PacketAdapterReference::Ptr & r) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `l` | `const PacketAdapterReference::Ptr &` | | +| `r` | `const PacketAdapterReference::Ptr &` | | -#### `public inline Version(const std::string & version)` +--- +#### ptr +```cpp +PacketStreamAdapter * ptr +``` +--- +#### _prevent_deletion -#### `public inline bool operator<(const `[`Version`](#structscy_1_1util_1_1Version)` & other)` +```cpp +std::shared_ptr< void > _prevent_deletion +``` +--- +#### order +```cpp +int order +``` +--- -#### `public inline bool operator==(const `[`Version`](#structscy_1_1util_1_1Version)` & other)` +#### syncState +```cpp +bool syncState +``` +## PacketStreamState +> **Extends:** `scy::State` +> **Defined in:** `packetstream.h` +### Members -# class `scy::GarbageCollector::Cleaner` +| Name | Description | +|------|-------------| +| [`Type`](#group__base_1ga1d08d6ddfd64ec3fcb406a75a059d3a9) | | +| [`str`](#group__base_1gaaee1b46215fbe13176a0de4c4b926cc4) | | +--- +#### Type +```cpp +enum Type +``` -Garbage collector cleaner context. +| Value | Description | +|-------|-------------| +| `None` | | +| `Locked` | | +| `Active` | | +| `Paused` | | +| `Stopping` | | +| `Stopped` | | +| `Closed` | | +| `Error` | | -The grabage collector maintains a single cleaner context per event loop. +--- -## Summary +#### str - Members | Descriptions ---------------------------------|--------------------------------------------- -`public mutable std::mutex _mutex` | -`public std::vector< `[`ScopedPointer`](./doc/api-base.md#classscy_1_1ScopedPointer)` * > _pending` | -`public std::vector< `[`ScopedPointer`](./doc/api-base.md#classscy_1_1ScopedPointer)` * > _ready` | -`public `[`Timer`](./doc/api-base.md#classscy_1_1Timer)` _timer` | -`public uv::Loop * _loop` | -`public bool _finalize` | -`public Cleaner(uv::Loop * loop)` | -`public ~Cleaner()` | -`public void work()` | -`public void finalize()` | +```cpp +inline std::string str(unsigned int id) const +``` -## Members +| Parameter | Type | Description | +|-----------|------|-------------| +| `id` | `unsigned int` | | -#### `public mutable std::mutex _mutex` +## TransactionState +> **Extends:** `scy::State` +> **Defined in:** `packettransaction.h` +### Members +| Name | Description | +|------|-------------| +| [`Type`](#group__base_1gaf0133ba73a52562d30e404efa5935058) | | +| [`str`](#group__base_1ga3bc0a991c145f88c468ef75cf3be51be) | | +--- -#### `public std::vector< `[`ScopedPointer`](./doc/api-base.md#classscy_1_1ScopedPointer)` * > _pending` +#### Type +```cpp +enum Type +``` +| Value | Description | +|-------|-------------| +| `Waiting` | | +| `Running` | | +| `Success` | | +| `Cancelled` | | +| `Failed` | | +--- +#### str -#### `public std::vector< `[`ScopedPointer`](./doc/api-base.md#classscy_1_1ScopedPointer)` * > _ready` +```cpp +inline std::string str(unsigned int id) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `id` | `unsigned int` | | +## Context +> **Defined in:** `runner.h` +[Context](#structscy_1_1Runner_1_1Context) object which we send to the thread context. -#### `public `[`Timer`](./doc/api-base.md#classscy_1_1Timer)` _timer` +This intermediate object allows us to garecefully handle late invokebacks and so avoid the need for deferred destruction of `[Runner](#classscy_1_1Runner)` objects. +### Members +| Name | Description | +|------|-------------| +| [`reset`](#group__base_1ga85d58cf01bb21e0f0280ee99f5053dfb) | | +| [`Context`](#group__base_1ga8b65b067b317daa79442b0235f22df77) | | +| [`tid`](#group__base_1gaa43dd023235e42c86f9aa2b5d2d3211b) | | +| [`running`](#group__base_1ga26e1db2bf00f40be908b6facce006e4f) | | +| [`cancelled`](#group__base_1ga66278b215dabb449abe3f1f5a5afd8cb) | | +| [`repeating`](#group__base_1ga2a3f06bbc8956c474960af89e3d6a0b1) | | +--- +#### reset -#### `public uv::Loop * _loop` +```cpp +inline void reset() +``` +--- +#### Context +```cpp +inline Context() +``` +--- -#### `public bool _finalize` +#### tid +```cpp +std::thread::id tid +``` +--- +#### running +```cpp +std::atomic< bool > running +``` -#### `public Cleaner(uv::Loop * loop)` +--- +#### cancelled +```cpp +std::atomic< bool > cancelled +``` +--- +#### repeating -#### `public ~Cleaner()` +```cpp +bool repeating = false +``` +## SharedLibrary +> **Defined in:** `sharedlibrary.h` +### Members +| Name | Description | +|------|-------------| +| [`open`](#group__base_1ga21dfcbd8f0adda4d0bebd1a317570783) | Opens a shared library. The filename is in utf-8. Returns true on success and false on error. Call `[SharedLibrary::error()](#group__base_1gad238435837ffd636d54e7b18973c64a9)` to get the error message. | +| [`close`](#group__base_1gac139b2afe33befeb2079d60327729f26) | Closes the shared library. | +| [`sym`](#group__base_1ga8028a3c607dfd1df3f5cb3614bd00a8b) | Retrieves a data pointer from a dynamic library. It is legal for a symbol to map to nullptr. Returns 0 on success and -1 if the symbol was not found. | +| [`setError`](#group__base_1gaa72dbffb419561d3330b00086846d43b) | | +| [`error`](#group__base_1gad238435837ffd636d54e7b18973c64a9) | | +| [`_lib`](#group__base_1ga69563904f0fb50a897c217c372110244) | | +| [`_error`](#group__base_1gaa920397bfdf4e812eef6fcd8d03c4455) | | -#### `public void work()` +--- +#### open +```cpp +inline bool open(const std::string & path) +``` +Opens a shared library. The filename is in utf-8. Returns true on success and false on error. Call `[SharedLibrary::error()](#group__base_1gad238435837ffd636d54e7b18973c64a9)` to get the error message. +| Parameter | Type | Description | +|-----------|------|-------------| +| `path` | `const std::string &` | | -#### `public void finalize()` +--- +#### close +```cpp +inline void close() +``` +Closes the shared library. +--- -# struct `scy::NVCollection::ILT` +#### sym +```cpp +inline bool sym(const char * name, void ** ptr) +``` +Retrieves a data pointer from a dynamic library. It is legal for a symbol to map to nullptr. Returns 0 on success and -1 if the symbol was not found. +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const char *` | | +| `ptr` | `void **` | | +--- +#### setError -## Summary +```cpp +inline void setError(const std::string & prefix) +``` - Members | Descriptions ---------------------------------|--------------------------------------------- -`public inline bool operator()(const std::string & s1,const std::string & s2) const` | +| Parameter | Type | Description | +|-----------|------|-------------| +| `prefix` | `const std::string &` | | -## Members +--- -#### `public inline bool operator()(const std::string & s1,const std::string & s2) const` +#### error +```cpp +inline std::string error() const +``` +--- +#### _lib +```cpp +uv_lib_t _lib +``` -# struct `scy::Runner::Context` +--- +#### _error +```cpp +std::string _error +``` +## Deleter -[Context](#structscy_1_1Runner_1_1Context) object which we send to the thread context. +Custom deleter that can access private destructors via friendship. -This intermediate object allows us to garecefully handle late invokebacks and so avoid the need for deferred destruction of `[Runner](#classscy_1_1Runner)` objects. +### Members -## Summary +| Name | Description | +|------|-------------| +| [`operator()`](#group__base_1gafef1cfec1d364ba3d428ffb409aed1e8) | | - Members | Descriptions ---------------------------------|--------------------------------------------- -`public std::thread::id tid` | -`public std::atomic< bool > running` | -`public std::atomic< bool > cancelled` | -`public bool repeating` | -`public inline void reset()` | -`public inline Context()` | +--- -## Members +#### operator() -#### `public std::thread::id tid` +```cpp +inline void operator()(S * p) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `p` | `S *` | | +## Version +> **Defined in:** `util.h` +### Members -#### `public std::atomic< bool > running` +| Name | Description | +|------|-------------| +| [`Version`](#group__base_1gabefe33fadbd31c287b84c33a34c0cdb4) | | +| [`operator<`](#group__base_1gac7dbfa8df99679fc2fc161523dc89d50) | | +| [`operator==`](#group__base_1ga11b1e27149c742ffb0b9c6b3fe2405a9) | | +| [`major`](#group__base_1ga05e06561c82da53755f84c1a0e52282b) | | +| [`minor`](#group__base_1ga51722ff9365a52c346ee5a2b500ef719) | | +| [`revision`](#group__base_1ga9fd57e2361545ed40ea4c7a19240d10b) | | +| [`build`](#group__base_1gad20634ae741953afa2129e82bfdbdd8a) | | +--- +#### Version +```cpp +inline Version(const std::string & version) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `version` | `const std::string &` | | -#### `public std::atomic< bool > cancelled` +--- +#### operator< +```cpp +inline bool operator<(const Version & other) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `other` | `const Version &` | | +--- -#### `public bool repeating` +#### operator== +```cpp +inline bool operator==(const Version & other) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `other` | `const Version &` | | +--- +#### major -#### `public inline void reset()` +```cpp +int major +``` +--- +#### minor +```cpp +int minor +``` +--- -#### `public inline Context()` +#### revision +```cpp +int revision +``` +--- +#### build +```cpp +int build +``` diff --git a/doc/api-crypto.md b/doc/api-crypto.md index ad9ae3ffb..5b3da0dc6 100644 --- a/doc/api-crypto.md +++ b/doc/api-crypto.md @@ -1,582 +1,1047 @@ -# Module `crypto` +# crypto +### Classes +| Name | Description | +|------|-------------| +| [`Cipher`](#classscy_1_1crypto_1_1Cipher) | Provides symmetric algorithms for encryption and decryption. The algorithms that are available depend on the particular version of OpenSSL that is installed. | +| [`Hash`](#classscy_1_1crypto_1_1Hash) | | +| [`X509Certificate`](#classscy_1_1crypto_1_1X509Certificate) | This class represents a X509 Certificate. | -## Summary +### Members - Members | Descriptions ---------------------------------|--------------------------------------------- -`namespace `[`scy::crypto`](#namespacescy_1_1crypto) | -`struct `[`CRYPTO_dynlock_value`](#structCRYPTO__dynlock__value) | -# namespace `scy::crypto` +| Name | Description | +|------|-------------| +| [`Crypto_API`](#group__crypto_1ga5b6282a38265a398bb16794294a91f94) | | +--- +#### Crypto_API -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`class `[`scy::crypto::Cipher`](#classscy_1_1crypto_1_1Cipher) | -`class `[`scy::crypto::Hash`](#classscy_1_1crypto_1_1Hash) | -`class `[`scy::crypto::X509Certificate`](#classscy_1_1crypto_1_1X509Certificate) | This class represents a X509 Certificate. -# class `scy::crypto::Cipher` - +```cpp +Crypto_API() +``` +## Cipher +> **Defined in:** `cipher.h` Provides symmetric algorithms for encryption and decryption. The algorithms that are available depend on the particular version of OpenSSL that is installed. -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public Cipher(const std::string & name)` | -`public Cipher(const std::string & name,const `[`ByteVec`](#group__crypto_1ga54c835992b731d8c7ec3e6a3c991ec97)` & key,const `[`ByteVec`](#group__crypto_1ga54c835992b731d8c7ec3e6a3c991ec97)` & iv)` | -`public Cipher(const std::string & name,const std::string & passphrase,const std::string & salt,int iterationCount)` | -`public ~Cipher()` | Destroys the [Cipher](./doc/api-crypto.md#classscy_1_1crypto_1_1Cipher). -`public void initEncryptor()` | Initializes the [Cipher](./doc/api-crypto.md#classscy_1_1crypto_1_1Cipher) for encryption. -`public void initDecryptor()` | Initializes the [Cipher](./doc/api-crypto.md#classscy_1_1crypto_1_1Cipher) for decryption. -`public ssize_t update(const unsigned char * input,size_t inputLength,unsigned char * output,size_t outputLength)` | -`public template`
`inline ssize_t update(const I & input,O & output)` | Alias for [update()](#group__crypto_1ga3041433d718ba3d7d7b47b4b40afac42) which accepts a range of buffer types. -`public ssize_t final(unsigned char * output,size_t length)` | -`public template`
`inline ssize_t final(O & output)` | Alias for [final()](#group__crypto_1ga67e162bd2a71957d98cb1e0e2675e4ea) which accepts a range of buffer types. -`public ssize_t encrypt(const unsigned char * inbuf,size_t inlen,unsigned char * outbuf,size_t outlen,`[`Encoding`](#group__crypto_1ga44fda7872beb30a68bbc8f2cac9271ae)` encoding)` | -`public template`
`inline ssize_t encrypt(const I & input,O & output,`[`Encoding`](#group__crypto_1ga44fda7872beb30a68bbc8f2cac9271ae)` encoding)` | Alias for [encrypt()](#group__crypto_1ga7cd265c66a382e6b9b396db93875a54c) which accepts a range of buffer types. -`public virtual std::string encryptString(const std::string & str,`[`Encoding`](#group__crypto_1ga44fda7872beb30a68bbc8f2cac9271ae)` encoding)` | Encrypts a string and encodes it using the given encoding. -`public virtual std::string decryptString(const std::string & str,`[`Encoding`](#group__crypto_1ga44fda7872beb30a68bbc8f2cac9271ae)` encoding)` | Decrypts a string that is encoded with the given encoding. -`public virtual void encryptStream(std::istream & source,std::ostream & sink,`[`Encoding`](#group__crypto_1ga44fda7872beb30a68bbc8f2cac9271ae)` encoding)` | Encrypts an input stream and encodes it using the given encoding. -`public virtual void decryptStream(std::istream & source,std::ostream & sink,`[`Encoding`](#group__crypto_1ga44fda7872beb30a68bbc8f2cac9271ae)` encoding)` | Decrypts an input stream that is encoded with the given encoding. -`public template`
`inline void setKey(const T & key)` | Sets the key for the [Cipher](./doc/api-crypto.md#classscy_1_1crypto_1_1Cipher). -`public template`
`inline void setIV(const T & iv)` | Sets the initialization vector (IV) for the [Cipher](./doc/api-crypto.md#classscy_1_1crypto_1_1Cipher). -`public int setPadding(int padding)` | -`public const `[`ByteVec`](#group__crypto_1ga54c835992b731d8c7ec3e6a3c991ec97)` & getKey() const` | Returns the key for the [Cipher](./doc/api-crypto.md#classscy_1_1crypto_1_1Cipher). -`public const `[`ByteVec`](#group__crypto_1ga54c835992b731d8c7ec3e6a3c991ec97)` & getIV() const` | Returns the initialization vector (IV) for the [Cipher](./doc/api-crypto.md#classscy_1_1crypto_1_1Cipher). -`public const std::string & name() const` | Returns the name of the [Cipher](./doc/api-crypto.md#classscy_1_1crypto_1_1Cipher). -`public int blockSize() const` | Returns the block size of the [Cipher](./doc/api-crypto.md#classscy_1_1crypto_1_1Cipher). -`public int keySize() const` | Returns the key size of the [Cipher](./doc/api-crypto.md#classscy_1_1crypto_1_1Cipher). -`public int ivSize() const` | Returns the IV size of the [Cipher](./doc/api-crypto.md#classscy_1_1crypto_1_1Cipher). -`public const EVP_CIPHER * cipher()` | Returns the cipher object. -`protected bool _initialized` | -`protected bool _encrypt` | -`protected const EVP_CIPHER * _cipher` | -`protected EVP_CIPHER_CTX * _ctx` | -`protected std::string _name` | -`protected `[`ByteVec`](#group__crypto_1ga54c835992b731d8c7ec3e6a3c991ec97)` _key` | -`protected `[`ByteVec`](#group__crypto_1ga54c835992b731d8c7ec3e6a3c991ec97)` _iv` | -`protected inline Cipher()` | -`protected Cipher(const `[`Cipher`](#classscy_1_1crypto_1_1Cipher)` &) = delete` | -`protected `[`Cipher`](#classscy_1_1crypto_1_1Cipher)` & operator=(const `[`Cipher`](#classscy_1_1crypto_1_1Cipher)` &) = delete` | -`protected void generateKey(const std::string & passphrase,const std::string & salt,int iterationCount)` | Generates and sets the key and IV from a password and optional salt string. -`protected void setRandomKey()` | Generates and sets key from random data. -`protected void setRandomIV()` | Generates and sets IV from random data. -`protected void init(bool encrypt)` | Initializes the [Cipher](./doc/api-crypto.md#classscy_1_1crypto_1_1Cipher) using the given direction. - -## Members - -#### `public Cipher(const std::string & name)` - - +### Members + +| Name | Description | +|------|-------------| +| [`Encoding`](#group__crypto_1ga44fda7872beb30a68bbc8f2cac9271ae) | Transport encoding to use for [encrypt()](#group__crypto_1ga7cd265c66a382e6b9b396db93875a54c) and decrypt(). | +| [`Cipher`](#group__crypto_1ga29c00ec7db3b341e2a40fb34324a6d00) | Creates a new [Cipher](#classscy_1_1crypto_1_1Cipher) object. Auto initializes the key and initialization vector with random bytes. | +| [`Cipher`](#group__crypto_1ga3084b42100789d88220012f926e60504) | Creates a new [Cipher](#classscy_1_1crypto_1_1Cipher) object, using the given cipher name, key and initialization vector. | +| [`Cipher`](#group__crypto_1gafa9fbfd0ac80c3e5fe6ee9d939e44907) | Creates a new [Cipher](#classscy_1_1crypto_1_1Cipher) object, using the given cipher name, passphrase, salt value and iteration count. | +| [`~Cipher`](#group__crypto_1gabae774949c196156b08b3e62c997516f) | Destroys the [Cipher](#classscy_1_1crypto_1_1Cipher). | +| [`initEncryptor`](#group__crypto_1ga144dd6c25b7d3d0ec97da382829cf636) | Initializes the [Cipher](#classscy_1_1crypto_1_1Cipher) for encryption. | +| [`initDecryptor`](#group__crypto_1ga0677c7dac45328f0517b35cb32e3d48c) | Initializes the [Cipher](#classscy_1_1crypto_1_1Cipher) for decryption. | +| [`update`](#group__crypto_1ga3041433d718ba3d7d7b47b4b40afac42) | Encrypts data in a streaming fashion. Hand consecutive blocks of data to the update method in order to encrypt it. Returns the encrypted data chunk. When done, the output of [final()](#group__crypto_1ga67e162bd2a71957d98cb1e0e2675e4ea) should be additionally added to the result. | +| [`update`](#group__crypto_1ga04c53b48009782e244a2a468a7109c0d) | Alias for [update()](#group__crypto_1ga3041433d718ba3d7d7b47b4b40afac42) which accepts a range of buffer types. | +| [`final`](#group__crypto_1ga67e162bd2a71957d98cb1e0e2675e4ea) | Returns the remaining data held in the cipher object. Further calls to [update()](#group__crypto_1ga3041433d718ba3d7d7b47b4b40afac42) or [final()](#group__crypto_1ga67e162bd2a71957d98cb1e0e2675e4ea) will return garbage. | +| [`final`](#group__crypto_1gadcd86bffcf3501416c9114574b377b18) | Alias for [final()](#group__crypto_1ga67e162bd2a71957d98cb1e0e2675e4ea) which accepts a range of buffer types. | +| [`encrypt`](#group__crypto_1ga7cd265c66a382e6b9b396db93875a54c) | Encrypts a buffer and encode it using the given encoding. This method performs the encryption, and calls [final()](#group__crypto_1ga67e162bd2a71957d98cb1e0e2675e4ea) internally. | +| [`encrypt`](#group__crypto_1gaeb0d5c7ccfc327728ef33957822682f3) | Alias for [encrypt()](#group__crypto_1ga7cd265c66a382e6b9b396db93875a54c) which accepts a range of buffer types. | +| [`encryptString`](#group__crypto_1ga8c440edf0d347751a1d1b9f43e99bd43) | Encrypts a string and encodes it using the given encoding. | +| [`decryptString`](#group__crypto_1gaa51a187bd02ae8d71aa58686f738ff9b) | Decrypts a string that is encoded with the given encoding. | +| [`encryptStream`](#group__crypto_1ga77107e1458845773e1ea7d3a81a6a3c3) | Encrypts an input stream and encodes it using the given encoding. | +| [`decryptStream`](#group__crypto_1gada68a82360e3eb8853efe26e55fee509) | Decrypts an input stream that is encoded with the given encoding. | +| [`setKey`](#group__crypto_1gaeec7a89c1fc12a93e00f2a119d67fc58) | Sets the key for the [Cipher](#classscy_1_1crypto_1_1Cipher). | +| [`setIV`](#group__crypto_1ga0368e6675a26e93d69beea3a090b7908) | Sets the initialization vector (IV) for the [Cipher](#classscy_1_1crypto_1_1Cipher). | +| [`setPadding`](#group__crypto_1ga4f8d10556e26c93af353a79d4f5bf65f) | Enables or disables padding. By default encryption operations are padded using standard block padding and the padding is checked and removed when decrypting. If the pad parameter is zero then no padding is performed, the total amount of data encrypted or decrypted must then be a multiple of the block size or an error will occur. | +| [`getKey`](#group__crypto_1gad9b197b9bc698da0defede327f66aad6) | Returns the key for the [Cipher](#classscy_1_1crypto_1_1Cipher). | +| [`getIV`](#group__crypto_1gacb5497a7ce6d4a39a57147cdf0b39f7c) | Returns the initialization vector (IV) for the [Cipher](#classscy_1_1crypto_1_1Cipher). | +| [`name`](#group__crypto_1gaa230464d6fc653fde4b08afcd75242cf) | Returns the name of the [Cipher](#classscy_1_1crypto_1_1Cipher). | +| [`blockSize`](#group__crypto_1gaddae447539926bb35a9394ad96dec391) | Returns the block size of the [Cipher](#classscy_1_1crypto_1_1Cipher). | +| [`keySize`](#group__crypto_1ga25f3530bbbd017c9fc219c538a50726e) | Returns the key size of the [Cipher](#classscy_1_1crypto_1_1Cipher). | +| [`ivSize`](#group__crypto_1ga50eab14578b8d9404f38276136514ea2) | Returns the IV size of the [Cipher](#classscy_1_1crypto_1_1Cipher). | +| [`cipher`](#group__crypto_1ga51844517077a71950e7f384ccb2dd8b1) | Returns the cipher object. | +| [`Cipher`](#group__crypto_1ga82b3135d1ca065df49483bba540ea3de) | | +| [`Cipher`](#group__crypto_1ga4113c32229f659416f774e08426d9488) | | +| [`operator=`](#group__crypto_1gacabc90b6f083892e54ffa99cc41552b0) | | +| [`generateKey`](#group__crypto_1ga6edba619802b9ca520bc4f8dd1b5d8b2) | Generates and sets the key and IV from a password and optional salt string. | +| [`setRandomKey`](#group__crypto_1gad71d5cde5fea40cfeab6b08518ddbc95) | Generates and sets key from random data. | +| [`setRandomIV`](#group__crypto_1gab3206763d10ce4674eb7e05f0390913a) | Generates and sets IV from random data. | +| [`init`](#group__crypto_1ga84b340347deeb58f81292539edd90c0c) | Initializes the [Cipher](#classscy_1_1crypto_1_1Cipher) using the given direction. | +| [`_initialized`](#group__crypto_1gaef37db5562b977395a89945b02e3b684) | | +| [`_encrypt`](#group__crypto_1ga234fb383e465ae6c7f322a4be0ba6a2f) | | +| [`_cipher`](#group__crypto_1ga6234e02c10a2a4be511fb2caaa7180b0) | | +| [`_ctx`](#group__crypto_1ga6d959336eca73fd8e1ba012de98de928) | | +| [`_name`](#group__crypto_1gae8bceb0c5aab20317421d37ccdf9b046) | | +| [`_key`](#group__crypto_1ga88a997190e8cd5880718fdbe4a613109) | | +| [`_iv`](#group__crypto_1ga9fb992dd64b02eaa38cac541d5072ac3) | | + +--- + +#### Encoding + +```cpp +enum Encoding +``` + +Transport encoding to use for [encrypt()](#group__crypto_1ga7cd265c66a382e6b9b396db93875a54c) and decrypt(). + +| Value | Description | +|-------|-------------| +| `Binary` | Plain binary output. | +| `Base64` | Base64-encoded output. | +| `BinHex` | BinHex-encoded output. | +| `Base64_NoLF` | Base64-encoded output, no linefeeds. | +| `BinHex_NoLF` | BinHex-encoded output, no linefeeds. | + +--- + +#### Cipher + +```cpp +Cipher(const std::string & name) +``` Creates a new [Cipher](#classscy_1_1crypto_1_1Cipher) object. Auto initializes the key and initialization vector with random bytes. -#### `public Cipher(const std::string & name,const `[`ByteVec`](#group__crypto_1ga54c835992b731d8c7ec3e6a3c991ec97)` & key,const `[`ByteVec`](#group__crypto_1ga54c835992b731d8c7ec3e6a3c991ec97)` & iv)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | +--- +#### Cipher + +```cpp +Cipher(const std::string & name, const ByteVec & key, const ByteVec & iv) +``` Creates a new [Cipher](#classscy_1_1crypto_1_1Cipher) object, using the given cipher name, key and initialization vector. -#### `public Cipher(const std::string & name,const std::string & passphrase,const std::string & salt,int iterationCount)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | +| `key` | `const ByteVec &` | | +| `iv` | `const ByteVec &` | | + +--- +#### Cipher +```cpp +Cipher(const std::string & name, const std::string & passphrase, const std::string & salt, int iterationCount) +``` Creates a new [Cipher](#classscy_1_1crypto_1_1Cipher) object, using the given cipher name, passphrase, salt value and iteration count. -#### `public ~Cipher()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | +| `passphrase` | `const std::string &` | | +| `salt` | `const std::string &` | | +| `iterationCount` | `int` | | + +--- + +#### ~Cipher + +```cpp +~Cipher() +``` Destroys the [Cipher](#classscy_1_1crypto_1_1Cipher). +--- +#### initEncryptor -#### `public void initEncryptor()` +```cpp +void initEncryptor() +``` Initializes the [Cipher](#classscy_1_1crypto_1_1Cipher) for encryption. +--- +#### initDecryptor -#### `public void initDecryptor()` +```cpp +void initDecryptor() +``` Initializes the [Cipher](#classscy_1_1crypto_1_1Cipher) for decryption. +--- +#### update -#### `public ssize_t update(const unsigned char * input,size_t inputLength,unsigned char * output,size_t outputLength)` +```cpp +ssize_t update(const unsigned char * input, size_t inputLength, unsigned char * output, size_t outputLength) +``` +Encrypts data in a streaming fashion. Hand consecutive blocks of data to the update method in order to encrypt it. Returns the encrypted data chunk. When done, the output of [final()](#group__crypto_1ga67e162bd2a71957d98cb1e0e2675e4ea) should be additionally added to the result. +| Parameter | Type | Description | +|-----------|------|-------------| +| `input` | `const unsigned char *` | | +| `inputLength` | `size_t` | | +| `output` | `unsigned char *` | | +| `outputLength` | `size_t` | | -Encrypts data in a streaming fashion. Hand consecutive blocks of data to the update method in order to encrypt it. Returns the encrypted data chunk. When done, the output of [final()](#group__crypto_1ga67e162bd2a71957d98cb1e0e2675e4ea) should be additionally added to the result. +--- -#### `public template`
`inline ssize_t update(const I & input,O & output)` +#### update -Alias for [update()](#group__crypto_1ga3041433d718ba3d7d7b47b4b40afac42) which accepts a range of buffer types. +```cpp +template inline ssize_t update(const I & input, O & output) +``` +Alias for [update()](#group__crypto_1ga3041433d718ba3d7d7b47b4b40afac42) which accepts a range of buffer types. +| Parameter | Type | Description | +|-----------|------|-------------| +| `input` | `const I &` | | +| `output` | `O &` | | -#### `public ssize_t final(unsigned char * output,size_t length)` +--- +#### final +```cpp +ssize_t final(unsigned char * output, size_t length) +``` Returns the remaining data held in the cipher object. Further calls to [update()](#group__crypto_1ga3041433d718ba3d7d7b47b4b40afac42) or [final()](#group__crypto_1ga67e162bd2a71957d98cb1e0e2675e4ea) will return garbage. See EVP_CipherFinal_ex for further information. -#### `public template`
`inline ssize_t final(O & output)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `output` | `unsigned char *` | | +| `length` | `size_t` | | -Alias for [final()](#group__crypto_1ga67e162bd2a71957d98cb1e0e2675e4ea) which accepts a range of buffer types. +--- +#### final +```cpp +template inline ssize_t final(O & output) +``` -#### `public ssize_t encrypt(const unsigned char * inbuf,size_t inlen,unsigned char * outbuf,size_t outlen,`[`Encoding`](#group__crypto_1ga44fda7872beb30a68bbc8f2cac9271ae)` encoding)` +Alias for [final()](#group__crypto_1ga67e162bd2a71957d98cb1e0e2675e4ea) which accepts a range of buffer types. +| Parameter | Type | Description | +|-----------|------|-------------| +| `output` | `O &` | | +--- + +#### encrypt + +```cpp +ssize_t encrypt(const unsigned char * inbuf, size_t inlen, unsigned char * outbuf, size_t outlen, Encoding encoding) +``` Encrypts a buffer and encode it using the given encoding. This method performs the encryption, and calls [final()](#group__crypto_1ga67e162bd2a71957d98cb1e0e2675e4ea) internally. -#### `public template`
`inline ssize_t encrypt(const I & input,O & output,`[`Encoding`](#group__crypto_1ga44fda7872beb30a68bbc8f2cac9271ae)` encoding)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `inbuf` | `const unsigned char *` | | +| `inlen` | `size_t` | | +| `outbuf` | `unsigned char *` | | +| `outlen` | `size_t` | | +| `encoding` | `Encoding` | | + +--- + +#### encrypt + +```cpp +template inline ssize_t encrypt(const I & input, O & output, Encoding encoding) +``` Alias for [encrypt()](#group__crypto_1ga7cd265c66a382e6b9b396db93875a54c) which accepts a range of buffer types. +| Parameter | Type | Description | +|-----------|------|-------------| +| `input` | `const I &` | | +| `output` | `O &` | | +| `encoding` | `Encoding` | | + +--- +#### encryptString -#### `public virtual std::string encryptString(const std::string & str,`[`Encoding`](#group__crypto_1ga44fda7872beb30a68bbc8f2cac9271ae)` encoding)` +```cpp +virtual std::string encryptString(const std::string & str, Encoding encoding) +``` Encrypts a string and encodes it using the given encoding. +| Parameter | Type | Description | +|-----------|------|-------------| +| `str` | `const std::string &` | | +| `encoding` | `Encoding` | | + +--- +#### decryptString -#### `public virtual std::string decryptString(const std::string & str,`[`Encoding`](#group__crypto_1ga44fda7872beb30a68bbc8f2cac9271ae)` encoding)` +```cpp +virtual std::string decryptString(const std::string & str, Encoding encoding) +``` Decrypts a string that is encoded with the given encoding. +| Parameter | Type | Description | +|-----------|------|-------------| +| `str` | `const std::string &` | | +| `encoding` | `Encoding` | | +--- -#### `public virtual void encryptStream(std::istream & source,std::ostream & sink,`[`Encoding`](#group__crypto_1ga44fda7872beb30a68bbc8f2cac9271ae)` encoding)` +#### encryptStream + +```cpp +virtual void encryptStream(std::istream & source, std::ostream & sink, Encoding encoding) +``` Encrypts an input stream and encodes it using the given encoding. +| Parameter | Type | Description | +|-----------|------|-------------| +| `source` | `std::istream &` | | +| `sink` | `std::ostream &` | | +| `encoding` | `Encoding` | | + +--- +#### decryptStream -#### `public virtual void decryptStream(std::istream & source,std::ostream & sink,`[`Encoding`](#group__crypto_1ga44fda7872beb30a68bbc8f2cac9271ae)` encoding)` +```cpp +virtual void decryptStream(std::istream & source, std::ostream & sink, Encoding encoding) +``` Decrypts an input stream that is encoded with the given encoding. +| Parameter | Type | Description | +|-----------|------|-------------| +| `source` | `std::istream &` | | +| `sink` | `std::ostream &` | | +| `encoding` | `Encoding` | | +--- -#### `public template`
`inline void setKey(const T & key)` +#### setKey + +```cpp +template inline void setKey(const T & key) +``` Sets the key for the [Cipher](#classscy_1_1crypto_1_1Cipher). +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `const T &` | | +--- -#### `public template`
`inline void setIV(const T & iv)` +#### setIV -Sets the initialization vector (IV) for the [Cipher](#classscy_1_1crypto_1_1Cipher). +```cpp +template inline void setIV(const T & iv) +``` +Sets the initialization vector (IV) for the [Cipher](#classscy_1_1crypto_1_1Cipher). +| Parameter | Type | Description | +|-----------|------|-------------| +| `iv` | `const T &` | | -#### `public int setPadding(int padding)` +--- +#### setPadding +```cpp +int setPadding(int padding) +``` Enables or disables padding. By default encryption operations are padded using standard block padding and the padding is checked and removed when decrypting. If the pad parameter is zero then no padding is performed, the total amount of data encrypted or decrypted must then be a multiple of the block size or an error will occur. See EVP_CIPHER_CTX_set_padding for further information. -#### `public const `[`ByteVec`](#group__crypto_1ga54c835992b731d8c7ec3e6a3c991ec97)` & getKey() const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `padding` | `int` | | + +--- + +#### getKey + +```cpp +const ByteVec & getKey() const +``` Returns the key for the [Cipher](#classscy_1_1crypto_1_1Cipher). +--- +#### getIV -#### `public const `[`ByteVec`](#group__crypto_1ga54c835992b731d8c7ec3e6a3c991ec97)` & getIV() const` +```cpp +const ByteVec & getIV() const +``` Returns the initialization vector (IV) for the [Cipher](#classscy_1_1crypto_1_1Cipher). +--- +#### name -#### `public const std::string & name() const` +```cpp +const std::string & name() const +``` Returns the name of the [Cipher](#classscy_1_1crypto_1_1Cipher). +--- +#### blockSize -#### `public int blockSize() const` +```cpp +int blockSize() const +``` Returns the block size of the [Cipher](#classscy_1_1crypto_1_1Cipher). +--- +#### keySize -#### `public int keySize() const` +```cpp +int keySize() const +``` Returns the key size of the [Cipher](#classscy_1_1crypto_1_1Cipher). +--- +#### ivSize -#### `public int ivSize() const` +```cpp +int ivSize() const +``` Returns the IV size of the [Cipher](#classscy_1_1crypto_1_1Cipher). +--- +#### cipher -#### `public const EVP_CIPHER * cipher()` +```cpp +const EVP_CIPHER * cipher() +``` Returns the cipher object. +--- +#### Cipher -#### `protected bool _initialized` - - - - - -#### `protected bool _encrypt` - - - - - -#### `protected const EVP_CIPHER * _cipher` - - - - - -#### `protected EVP_CIPHER_CTX * _ctx` - - - - - -#### `protected std::string _name` - - - - - -#### `protected `[`ByteVec`](#group__crypto_1ga54c835992b731d8c7ec3e6a3c991ec97)` _key` - - +```cpp +Cipher() = default +``` +--- +#### Cipher -#### `protected `[`ByteVec`](#group__crypto_1ga54c835992b731d8c7ec3e6a3c991ec97)` _iv` +```cpp +Cipher(const Cipher &) = delete +``` +--- +#### operator= +```cpp +Cipher & operator=(const Cipher &) = delete +``` +--- -#### `protected inline Cipher()` +#### generateKey +```cpp +void generateKey(const std::string & passphrase, const std::string & salt, int iterationCount) +``` +Generates and sets the key and IV from a password and optional salt string. +| Parameter | Type | Description | +|-----------|------|-------------| +| `passphrase` | `const std::string &` | | +| `salt` | `const std::string &` | | +| `iterationCount` | `int` | | +--- -#### `protected Cipher(const `[`Cipher`](#classscy_1_1crypto_1_1Cipher)` &) = delete` +#### setRandomKey +```cpp +void setRandomKey() +``` +Generates and sets key from random data. +--- +#### setRandomIV -#### `protected `[`Cipher`](#classscy_1_1crypto_1_1Cipher)` & operator=(const `[`Cipher`](#classscy_1_1crypto_1_1Cipher)` &) = delete` +```cpp +void setRandomIV() +``` +Generates and sets IV from random data. +--- +#### init +```cpp +void init(bool encrypt) +``` -#### `protected void generateKey(const std::string & passphrase,const std::string & salt,int iterationCount)` +Initializes the [Cipher](#classscy_1_1crypto_1_1Cipher) using the given direction. -Generates and sets the key and IV from a password and optional salt string. +| Parameter | Type | Description | +|-----------|------|-------------| +| `encrypt` | `bool` | | +--- +#### _initialized -#### `protected void setRandomKey()` +```cpp +bool _initialized +``` -Generates and sets key from random data. +--- +#### _encrypt +```cpp +bool _encrypt +``` -#### `protected void setRandomIV()` +--- -Generates and sets IV from random data. +#### _cipher +```cpp +const EVP_CIPHER * _cipher +``` +--- -#### `protected void init(bool encrypt)` +#### _ctx -Initializes the [Cipher](#classscy_1_1crypto_1_1Cipher) using the given direction. +```cpp +EVP_CIPHER_CTX * _ctx +``` +--- +#### _name -# class `scy::crypto::Hash` +```cpp +std::string _name +``` +--- +#### _key +```cpp +ByteVec _key +``` +--- +#### _iv -## Summary +```cpp +ByteVec _iv +``` - Members | Descriptions ---------------------------------|--------------------------------------------- -`public Hash(const std::string & algorithm)` | -`public ~Hash()` | -`public void update(char data)` | -`public void update(const std::string & data)` | -`public void update(const void * data,size_t length)` | -`public const `[`ByteVec`](#group__crypto_1ga54c835992b731d8c7ec3e6a3c991ec97)` & digest()` | Finish up the digest operation and return the result. -`public std::string digestStr()` | Finish up the digest operation and return the result as a string. -`public void reset()` | Resets the engine and digest state ready for the next computation. -`public const std::string & algorithm(void) const` | Returns the hash algorithm being used. -`protected EVP_MD_CTX _ctx` | -`protected const EVP_MD * _md` | -`protected `[`crypto::ByteVec`](#group__crypto_1ga54c835992b731d8c7ec3e6a3c991ec97)` _digest` | -`protected std::string _algorithm` | -`protected `[`Hash`](#classscy_1_1crypto_1_1Hash)` & operator=(`[`Hash`](#classscy_1_1crypto_1_1Hash)` const &)` | +## Hash -## Members +> **Defined in:** `hash.h` -#### `public Hash(const std::string & algorithm)` +### Members +| Name | Description | +|------|-------------| +| [`Hash`](#group__crypto_1gaed22bcaf84b35efc1815a03903541da4) | | +| [`~Hash`](#group__crypto_1gaf1bea9c52e354b7b97550e1715105ee0) | | +| [`update`](#group__crypto_1ga7389984a20183881be045ff427036ce8) | | +| [`update`](#group__crypto_1ga8b68b47d859b92608a2ac7295c3ef702) | | +| [`update`](#group__crypto_1ga23679ad362d7a4a21f0ee73a61795161) | This function may (and normally will) be called many times for large blocks of data. | +| [`digest`](#group__crypto_1gacbc12b3d6816140c2e5033fe32efafca) | Finish up the digest operation and return the result. | +| [`digestStr`](#group__crypto_1gad11ff9012ce5157206e0a05a7c3f7347) | Finish up the digest operation and return the result as a string. | +| [`reset`](#group__crypto_1ga58abad9c8210a2882d69dceb3883a973) | Resets the engine and digest state ready for the next computation. | +| [`algorithm`](#group__crypto_1ga6f4e22146b390772a4d2c1d4ef6352c7) | Returns the hash algorithm being used. | +| [`operator=`](#group__crypto_1gab33fa99f39b8f58fb69008442f1245b4) | | +| [`_ctx`](#group__crypto_1gaed86aa72bb57df7c08d903a6c1bf5621) | | +| [`_md`](#group__crypto_1gada899a7cc6726572e494dfa2e0aa4838) | | +| [`_digest`](#group__crypto_1gaa8321b86e61d992786de9a8be63630a7) | | +| [`_algorithm`](#group__crypto_1ga778a1b93ea54aff4e5b1b1b80ccbcb6f) | | +--- +#### Hash +```cpp +Hash(const std::string & algorithm) +``` -#### `public ~Hash()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `algorithm` | `const std::string &` | | +--- +#### ~Hash +```cpp +~Hash() +``` +--- -#### `public void update(char data)` +#### update +```cpp +void update(char data) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `data` | `char` | | +--- +#### update -#### `public void update(const std::string & data)` +```cpp +void update(const std::string & data) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `data` | `const std::string &` | | +--- +#### update +```cpp +void update(const void * data, size_t length) +``` -#### `public void update(const void * data,size_t length)` +This function may (and normally will) be called many times for large blocks of data. +| Parameter | Type | Description | +|-----------|------|-------------| +| `data` | `const void *` | | +| `length` | `size_t` | | +--- -This function may (and normally will) be called many times for large blocks of data. +#### digest -#### `public const `[`ByteVec`](#group__crypto_1ga54c835992b731d8c7ec3e6a3c991ec97)` & digest()` +```cpp +const ByteVec & digest() +``` Finish up the digest operation and return the result. +--- +#### digestStr -#### `public std::string digestStr()` +```cpp +std::string digestStr() +``` Finish up the digest operation and return the result as a string. +--- +#### reset -#### `public void reset()` +```cpp +void reset() +``` Resets the engine and digest state ready for the next computation. +--- +#### algorithm -#### `public const std::string & algorithm(void) const` +```cpp +const std::string & algorithm(void) const +``` Returns the hash algorithm being used. +--- +#### operator= -#### `protected EVP_MD_CTX _ctx` - - - - - -#### `protected const EVP_MD * _md` +```cpp +Hash & operator=(Hash const &) +``` +--- +#### _ctx +```cpp +EVP_MD_CTX * _ctx +``` +--- -#### `protected `[`crypto::ByteVec`](#group__crypto_1ga54c835992b731d8c7ec3e6a3c991ec97)` _digest` +#### _md +```cpp +const EVP_MD * _md +``` +--- +#### _digest +```cpp +crypto::ByteVec _digest +``` -#### `protected std::string _algorithm` +--- +#### _algorithm +```cpp +std::string _algorithm +``` +## X509Certificate - -#### `protected `[`Hash`](#classscy_1_1crypto_1_1Hash)` & operator=(`[`Hash`](#classscy_1_1crypto_1_1Hash)` const &)` - - - - - -# class `scy::crypto::X509Certificate` - +> **Defined in:** `x509certificate.h` This class represents a X509 Certificate. +### Members + +| Name | Description | +|------|-------------| +| [`NID`](#group__crypto_1gaf15888f0ebe57ab7978cb91f7bbd40d7) | Name identifier for extracting information from a certificate subject's or issuer's distinguished name. | +| [``](#group__crypto_1ga16824404470aa043a22a79b9ca9a68c0) | | +| [`X509Certificate`](#group__crypto_1ga459ca16eab567ab22d1b675f6a334ced) | Creates the [X509Certificate](#classscy_1_1crypto_1_1X509Certificate) object by reading a certificate in PEM format from the given buffer. | +| [`X509Certificate`](#group__crypto_1ga417bdf3f76dfecef89626b6cb71a9a32) | Creates the [X509Certificate](#classscy_1_1crypto_1_1X509Certificate) object by reading a certificate in PEM format from a file. | +| [`X509Certificate`](#group__crypto_1ga2aa7feaea1f6c99c994fcc6fb7bea0ac) | Creates the [X509Certificate](#classscy_1_1crypto_1_1X509Certificate) from an existing OpenSSL certificate. Ownership is taken of the certificate. | +| [`X509Certificate`](#group__crypto_1gaf7e31eac8d3095866847b5af0db366fa) | Creates the [X509Certificate](#classscy_1_1crypto_1_1X509Certificate) from an existing OpenSSL certificate. Ownership is taken of the certificate. If shared is true, the certificate's reference count is incremented. | +| [`X509Certificate`](#group__crypto_1ga9aaeb1e01fbc97752b90be697230a504) | Creates the certificate by copying another one. | +| [`operator=`](#group__crypto_1ga1516b536eadd451c76ecafa299f63d7c) | Assigns a certificate. | +| [`swap`](#group__crypto_1gac487d92721c8e2bca13f0d13edcf942d) | Exchanges the certificate with another one. | +| [`~X509Certificate`](#group__crypto_1ga9bca014de92bf3dcb7988eea0a41b92f) | Destroys the [X509Certificate](#classscy_1_1crypto_1_1X509Certificate). | +| [`issuerName`](#group__crypto_1ga59be81cc1b19268c8c3f9b1fd046b20d) | Returns the certificate issuer's distinguished name. | +| [`issuerName`](#group__crypto_1gade700582f523d36f9ba35b4ff42ae9da) | Extracts the information specified by the given NID (name identifier) from the certificate issuer's distinguished name. | +| [`subjectName`](#group__crypto_1ga08cbb2a291c084ac15d427f2a75bed51) | Returns the certificate subject's distinguished name. | +| [`subjectName`](#group__crypto_1ga448f08e983b8fc5e93bbd1de5f33d0ca) | Extracts the information specified by the given NID (name identifier) from the certificate subject's distinguished name. | +| [`commonName`](#group__crypto_1ga5c8fd7098b3c4114b414a737ad5b10f8) | Returns the common name stored in the certificate subject's distinguished name. | +| [`extractNames`](#group__crypto_1gacfd53defe5a0eb4329622b02f0725221) | Extracts the common name and the alias domain names from the certificate. | +| [`validFrom`](#group__crypto_1ga79d4899027eb85cfad01e892f3595e33) | Returns the date and time the certificate is valid from. | +| [`expiresOn`](#group__crypto_1gad2d8ba7bc9502843db12690f6ed24646) | Returns the date and time the certificate expires. | +| [`save`](#group__crypto_1gaf0aaafac5aa2869c52d19b34f8768c0b) | Writes the certificate to the given stream. The certificate is written in PEM format. | +| [`save`](#group__crypto_1ga0cea8f317ad0371de4a05ae1f4c4387d) | Writes the certificate to the file given by path. The certificate is written in PEM format. | +| [`issuedBy`](#group__crypto_1ga8e93fd651db9982f6178b5fae9447fcc) | Checks whether the certificate has been issued by the issuer given by issuerCertificate. This can be used to validate a certificate chain. | +| [`certificate`](#group__crypto_1ga351a6a8c90b667597ab6ddb1233be511) | Returns the underlying OpenSSL certificate. | +| [`load`](#group__crypto_1ga0472559c4633b117e91bc68b50bb7de6) | Loads the certificate from the given buffer. The certificate must be in PEM format. | +| [`load`](#group__crypto_1ga3d18050527eb8fd86b4b63924ecc7ca5) | Loads the certificate from the given file. The certificate must be in PEM format. | +| [`init`](#group__crypto_1gaaf8694ec9aa62ec67324253b9456ba2e) | Extracts issuer and subject name from the certificate. | +| [`_issuerName`](#group__crypto_1ga079edf7060b186eab27aa557db2021bf) | | +| [`_subjectName`](#group__crypto_1ga01c347e1866e5c461bf888093d7b78f8) | | +| [`_certificate`](#group__crypto_1ga8b1647c17acdec201f9247c9c43de2bc) | | + +--- + +#### NID + +```cpp +enum NID +``` + +Name identifier for extracting information from a certificate subject's or issuer's distinguished name. + +| Value | Description | +|-------|-------------| +| `NID_COMMON_NAME` | | +| `NID_COUNTRY` | | +| `NID_LOCALITY_NAME` | | +| `NID_STATE_OR_PROVINCE` | | +| `NID_ORGANIZATION_NAME` | | +| `NID_ORGANIZATION_UNIT_NAME` | | + +--- + +#### + +```cpp +enum +``` + +| Value | Description | +|-------|-------------| +| `NAME_BUFFER_SIZE` | | + +--- + +#### X509Certificate + +```cpp +explicit X509Certificate(const char * data, size_t length) +``` +Creates the [X509Certificate](#classscy_1_1crypto_1_1X509Certificate) object by reading a certificate in PEM format from the given buffer. -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public explicit X509Certificate(const char * data,size_t length)` | -`public explicit X509Certificate(const std::string & path)` | -`public explicit X509Certificate(X509 * pCert)` | -`public X509Certificate(X509 * pCert,bool shared)` | -`public X509Certificate(const `[`X509Certificate`](#classscy_1_1crypto_1_1X509Certificate)` & cert)` | Creates the certificate by copying another one. -`public `[`X509Certificate`](#classscy_1_1crypto_1_1X509Certificate)` & operator=(const `[`X509Certificate`](#classscy_1_1crypto_1_1X509Certificate)` & cert)` | Assigns a certificate. -`public void swap(`[`X509Certificate`](#classscy_1_1crypto_1_1X509Certificate)` & cert)` | Exchanges the certificate with another one. -`public ~X509Certificate()` | Destroys the [X509Certificate](./doc/api-crypto.md#classscy_1_1crypto_1_1X509Certificate). -`public const std::string & issuerName() const` | Returns the certificate issuer's distinguished name. -`public std::string issuerName(`[`NID`](#group__crypto_1gaf15888f0ebe57ab7978cb91f7bbd40d7)` nid) const` | -`public const std::string & subjectName() const` | Returns the certificate subject's distinguished name. -`public std::string subjectName(`[`NID`](#group__crypto_1gaf15888f0ebe57ab7978cb91f7bbd40d7)` nid) const` | -`public std::string commonName() const` | -`public void extractNames(std::string & commonName,std::set< std::string > & domainNames) const` | -`public `[`DateTime`](#classscy_1_1DateTime)` validFrom() const` | Returns the date and time the certificate is valid from. -`public `[`DateTime`](#classscy_1_1DateTime)` expiresOn() const` | Returns the date and time the certificate expires. -`public void save(std::ostream & stream) const` | -`public void save(const std::string & path) const` | -`public bool issuedBy(const `[`X509Certificate`](#classscy_1_1crypto_1_1X509Certificate)` & issuerCertificate) const` | -`public const X509 * certificate() const` | Returns the underlying OpenSSL certificate. -`protected void load(const char * data,size_t length)` | -`protected void load(const std::string & path)` | -`protected void init()` | Extracts issuer and subject name from the certificate. +| Parameter | Type | Description | +|-----------|------|-------------| +| `data` | `const char *` | | +| `length` | `size_t` | | -## Members +--- -#### `public explicit X509Certificate(const char * data,size_t length)` +#### X509Certificate +```cpp +explicit X509Certificate(const std::string & path) +``` +Creates the [X509Certificate](#classscy_1_1crypto_1_1X509Certificate) object by reading a certificate in PEM format from a file. -Creates the [X509Certificate](#classscy_1_1crypto_1_1X509Certificate) object by reading a certificate in PEM format from the given buffer. +| Parameter | Type | Description | +|-----------|------|-------------| +| `path` | `const std::string &` | | -#### `public explicit X509Certificate(const std::string & path)` +--- +#### X509Certificate +```cpp +explicit X509Certificate(X509 * pCert) +``` -Creates the [X509Certificate](#classscy_1_1crypto_1_1X509Certificate) object by reading a certificate in PEM format from a file. +Creates the [X509Certificate](#classscy_1_1crypto_1_1X509Certificate) from an existing OpenSSL certificate. Ownership is taken of the certificate. -#### `public explicit X509Certificate(X509 * pCert)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `pCert` | `X509 *` | | +--- +#### X509Certificate -Creates the [X509Certificate](#classscy_1_1crypto_1_1X509Certificate) from an existing OpenSSL certificate. Ownership is taken of the certificate. +```cpp +X509Certificate(X509 * pCert, bool shared) +``` -#### `public X509Certificate(X509 * pCert,bool shared)` +Creates the [X509Certificate](#classscy_1_1crypto_1_1X509Certificate) from an existing OpenSSL certificate. Ownership is taken of the certificate. If shared is true, the certificate's reference count is incremented. +| Parameter | Type | Description | +|-----------|------|-------------| +| `pCert` | `X509 *` | | +| `shared` | `bool` | | +--- -Creates the [X509Certificate](#classscy_1_1crypto_1_1X509Certificate) from an existing OpenSSL certificate. Ownership is taken of the certificate. If shared is true, the certificate's reference count is incremented. +#### X509Certificate -#### `public X509Certificate(const `[`X509Certificate`](#classscy_1_1crypto_1_1X509Certificate)` & cert)` +```cpp +X509Certificate(const X509Certificate & cert) +``` Creates the certificate by copying another one. +| Parameter | Type | Description | +|-----------|------|-------------| +| `cert` | `const X509Certificate &` | | +--- -#### `public `[`X509Certificate`](#classscy_1_1crypto_1_1X509Certificate)` & operator=(const `[`X509Certificate`](#classscy_1_1crypto_1_1X509Certificate)` & cert)` +#### operator= + +```cpp +X509Certificate & operator=(const X509Certificate & cert) +``` Assigns a certificate. +| Parameter | Type | Description | +|-----------|------|-------------| +| `cert` | `const X509Certificate &` | | + +--- +#### swap -#### `public void swap(`[`X509Certificate`](#classscy_1_1crypto_1_1X509Certificate)` & cert)` +```cpp +void swap(X509Certificate & cert) +``` Exchanges the certificate with another one. +| Parameter | Type | Description | +|-----------|------|-------------| +| `cert` | `X509Certificate &` | | +--- -#### `public ~X509Certificate()` +#### ~X509Certificate + +```cpp +~X509Certificate() +``` Destroys the [X509Certificate](#classscy_1_1crypto_1_1X509Certificate). +--- +#### issuerName -#### `public const std::string & issuerName() const` +```cpp +const std::string & issuerName() const +``` Returns the certificate issuer's distinguished name. +--- +#### issuerName -#### `public std::string issuerName(`[`NID`](#group__crypto_1gaf15888f0ebe57ab7978cb91f7bbd40d7)` nid) const` - - +```cpp +std::string issuerName(NID nid) const +``` Extracts the information specified by the given NID (name identifier) from the certificate issuer's distinguished name. -#### `public const std::string & subjectName() const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `nid` | `NID` | | -Returns the certificate subject's distinguished name. +--- + +#### subjectName +```cpp +const std::string & subjectName() const +``` +Returns the certificate subject's distinguished name. -#### `public std::string subjectName(`[`NID`](#group__crypto_1gaf15888f0ebe57ab7978cb91f7bbd40d7)` nid) const` +--- +#### subjectName +```cpp +std::string subjectName(NID nid) const +``` Extracts the information specified by the given NID (name identifier) from the certificate subject's distinguished name. -#### `public std::string commonName() const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `nid` | `NID` | | + +--- +#### commonName +```cpp +std::string commonName() const +``` Returns the common name stored in the certificate subject's distinguished name. -#### `public void extractNames(std::string & commonName,std::set< std::string > & domainNames) const` +--- +#### extractNames +```cpp +void extractNames(std::string & commonName, std::set< std::string > & domainNames) const +``` Extracts the common name and the alias domain names from the certificate. -#### `public `[`DateTime`](#classscy_1_1DateTime)` validFrom() const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `commonName` | `std::string &` | | +| `domainNames` | `std::set< std::string > &` | | -Returns the date and time the certificate is valid from. +--- +#### validFrom +```cpp +DateTime validFrom() const +``` -#### `public `[`DateTime`](#classscy_1_1DateTime)` expiresOn() const` +Returns the date and time the certificate is valid from. -Returns the date and time the certificate expires. +--- +#### expiresOn +```cpp +DateTime expiresOn() const +``` -#### `public void save(std::ostream & stream) const` +Returns the date and time the certificate expires. + +--- +#### save +```cpp +void save(std::ostream & stream) const +``` Writes the certificate to the given stream. The certificate is written in PEM format. -#### `public void save(const std::string & path) const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `stream` | `std::ostream &` | | +--- +#### save + +```cpp +void save(const std::string & path) const +``` Writes the certificate to the file given by path. The certificate is written in PEM format. -#### `public bool issuedBy(const `[`X509Certificate`](#classscy_1_1crypto_1_1X509Certificate)` & issuerCertificate) const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `path` | `const std::string &` | | + +--- +#### issuedBy +```cpp +bool issuedBy(const X509Certificate & issuerCertificate) const +``` Checks whether the certificate has been issued by the issuer given by issuerCertificate. This can be used to validate a certificate chain. @@ -584,48 +1049,80 @@ Verifies if the certificate has been signed with the issuer's private key, using Returns true if verification against the issuer certificate was successful, false otherwise. -#### `public const X509 * certificate() const` - -Returns the underlying OpenSSL certificate. - +| Parameter | Type | Description | +|-----------|------|-------------| +| `issuerCertificate` | `const X509Certificate &` | | +--- -#### `protected void load(const char * data,size_t length)` +#### certificate +```cpp +const X509 * certificate() const +``` +Returns the underlying OpenSSL certificate. -Loads the certificate from the given buffer. The certificate must be in PEM format. +--- -#### `protected void load(const std::string & path)` +#### load +```cpp +void load(const char * data, size_t length) +``` +Loads the certificate from the given buffer. The certificate must be in PEM format. -Loads the certificate from the given file. The certificate must be in PEM format. +| Parameter | Type | Description | +|-----------|------|-------------| +| `data` | `const char *` | | +| `length` | `size_t` | | -#### `protected void init()` +--- -Extracts issuer and subject name from the certificate. +#### load +```cpp +void load(const std::string & path) +``` +Loads the certificate from the given file. The certificate must be in PEM format. -# struct `CRYPTO_dynlock_value` +| Parameter | Type | Description | +|-----------|------|-------------| +| `path` | `const std::string &` | | +--- +#### init +```cpp +void init() +``` +Extracts issuer and subject name from the certificate. +--- -## Summary +#### _issuerName - Members | Descriptions ---------------------------------|--------------------------------------------- -`public std::mutex _mutex` | +```cpp +std::string _issuerName +``` -## Members +--- -#### `public std::mutex _mutex` +#### _subjectName +```cpp +std::string _subjectName +``` +--- +#### _certificate +```cpp +X509 * _certificate +``` diff --git a/doc/api-http.md b/doc/api-http.md index 97c3d2c34..2ff1e2956 100644 --- a/doc/api-http.md +++ b/doc/api-http.md @@ -1,3908 +1,3787 @@ -# Module `http` - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`namespace `[`scy::http`](#namespacescy_1_1http) | -`namespace `[`scy::http::ws`](#namespacescy_1_1http_1_1ws) | -`struct `[`scy::http::FormWriter::Part`](#structscy_1_1http_1_1FormWriter_1_1Part) | -# namespace `scy::http` - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`class `[`scy::http::Authenticator`](#classscy_1_1http_1_1Authenticator) | -`class `[`scy::http::BasicAuthenticator`](#classscy_1_1http_1_1BasicAuthenticator) | -`class `[`scy::http::ChunkedAdapter`](#classscy_1_1http_1_1ChunkedAdapter) | -`class `[`scy::http::Client`](#classscy_1_1http_1_1Client) | -`class `[`scy::http::ClientConnection`](#classscy_1_1http_1_1ClientConnection) | -`class `[`scy::http::Connection`](#classscy_1_1http_1_1Connection) | -`class `[`scy::http::ConnectionAdapter`](#classscy_1_1http_1_1ConnectionAdapter) | Default HTTP socket adapter for reading and writing HTTP messages. -`class `[`scy::http::ConnectionStream`](#classscy_1_1http_1_1ConnectionStream) | Packet stream wrapper for a HTTP connection. -`class `[`scy::http::Cookie`](#classscy_1_1http_1_1Cookie) | -`class `[`scy::http::FilePart`](#classscy_1_1http_1_1FilePart) | An implementation of [FilePart](#classscy_1_1http_1_1FilePart) for plain files. -`class `[`scy::http::FormPart`](#classscy_1_1http_1_1FormPart) | An implementation of [FormPart](#classscy_1_1http_1_1FormPart). -`class `[`scy::http::FormWriter`](#classscy_1_1http_1_1FormWriter) | -`class `[`scy::http::Message`](#classscy_1_1http_1_1Message) | -`class `[`scy::http::MultipartAdapter`](#classscy_1_1http_1_1MultipartAdapter) | -`class `[`scy::http::Parser`](#classscy_1_1http_1_1Parser) | -`class `[`scy::http::ParserObserver`](#classscy_1_1http_1_1ParserObserver) | -`class `[`scy::http::ProgressSignal`](#classscy_1_1http_1_1ProgressSignal) | -`class `[`scy::http::Request`](#classscy_1_1http_1_1Request) | -`class `[`scy::http::Response`](#classscy_1_1http_1_1Response) | This class encapsulates an HTTP response message. -`class `[`scy::http::Server`](#classscy_1_1http_1_1Server) | -`class `[`scy::http::ServerConnection`](#classscy_1_1http_1_1ServerConnection) | HTTP server connection. -`class `[`scy::http::ServerConnectionFactory`](#classscy_1_1http_1_1ServerConnectionFactory) | -`class `[`scy::http::ServerResponder`](#classscy_1_1http_1_1ServerResponder) | -`class `[`scy::http::StringPart`](#classscy_1_1http_1_1StringPart) | An implementation of [StringPart](#classscy_1_1http_1_1StringPart) for plain files. -`class `[`scy::http::URL`](#classscy_1_1http_1_1URL) | -`struct `[`scy::http::Method`](#structscy_1_1http_1_1Method) | HTTP request methods. -# class `scy::http::Authenticator` - - - - -This is a utility class for working with HTTP authentication (basic or digest) in [http::Request](http::Request) objects. - -Note: Do not forget to read the entire response stream from the 401 response before sending the authenticated request, otherwise there may be problems if a persistent connection is used. - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public Authenticator()` | Creates an empty [Authenticator](./doc/api-http.md#classscy_1_1http_1_1Authenticator) object. -`public Authenticator(const std::string & username,const std::string & password)` | Creates an [Authenticator](./doc/api-http.md#classscy_1_1http_1_1Authenticator) object with the given username and password. -`public ~Authenticator()` | Destroys the [Authenticator](./doc/api-http.md#classscy_1_1http_1_1Authenticator). -`public void fromUserInfo(const std::string & userInfo)` | -`public void fromURI(const `[`http::URL`](#classscy_1_1http_1_1URL)` & uri)` | -`public inline void setUsername(const std::string & username)` | Sets the username. -`public inline const std::string & username() const` | Returns the username. -`public inline void setPassword(const std::string & password)` | Sets the password. -`public inline const std::string & password() const` | Returns the password. -`public void authenticate(`[`http::Request`](#classscy_1_1http_1_1Request)` & request,const `[`http::Response`](#classscy_1_1http_1_1Response)` & response)` | -`public void updateAuthInfo(`[`http::Request`](#classscy_1_1http_1_1Request)` & request)` | -`public void proxyAuthenticate(`[`http::Request`](#classscy_1_1http_1_1Request)` & request,const `[`http::Response`](#classscy_1_1http_1_1Response)` & response)` | -`public void updateProxyAuthInfo(`[`http::Request`](#classscy_1_1http_1_1Request)` & request)` | - -## Members - -#### `public Authenticator()` - -Creates an empty [Authenticator](#classscy_1_1http_1_1Authenticator) object. - - - -#### `public Authenticator(const std::string & username,const std::string & password)` - -Creates an [Authenticator](#classscy_1_1http_1_1Authenticator) object with the given username and password. - - - -#### `public ~Authenticator()` - -Destroys the [Authenticator](#classscy_1_1http_1_1Authenticator). - - - -#### `public void fromUserInfo(const std::string & userInfo)` - - - -Parses username:password std::string and sets username and password of the credentials object. Throws SyntaxException on invalid user information. - -#### `public void fromURI(const `[`http::URL`](#classscy_1_1http_1_1URL)` & uri)` - - - -Extracts username and password from the given URI and sets username and password of the credentials object. Does nothing if URI has no user info part. - -#### `public inline void setUsername(const std::string & username)` - -Sets the username. - - - -#### `public inline const std::string & username() const` - -Returns the username. - - - -#### `public inline void setPassword(const std::string & password)` - -Sets the password. - - - -#### `public inline const std::string & password() const` - -Returns the password. - - - -#### `public void authenticate(`[`http::Request`](#classscy_1_1http_1_1Request)` & request,const `[`http::Response`](#classscy_1_1http_1_1Response)` & response)` - - - -Inspects WWW-Authenticate header of the response, initializes the internal state (in case of digest authentication) and adds required information to the given [http::Request](http::Request). - -Does nothing if there is no WWW-Authenticate header in the [http::Response](http::Response). - -#### `public void updateAuthInfo(`[`http::Request`](#classscy_1_1http_1_1Request)` & request)` - - - -Updates internal state (in case of digest authentication) and replaces authentication information in the request accordingly. - -#### `public void proxyAuthenticate(`[`http::Request`](#classscy_1_1http_1_1Request)` & request,const `[`http::Response`](#classscy_1_1http_1_1Response)` & response)` - - - -Inspects Proxy-Authenticate header of the response, initializes the internal state (in case of digest authentication) and adds required information to the given [http::Request](http::Request). - -Does nothing if there is no Proxy-Authenticate header in the [http::Response](http::Response). - -#### `public void updateProxyAuthInfo(`[`http::Request`](#classscy_1_1http_1_1Request)` & request)` - - - -Updates internal state (in case of digest authentication) and replaces proxy authentication information in the request accordingly. - -# class `scy::http::BasicAuthenticator` - - - - -This is a utility class for working with HTTP Basic Authentication in [http::Request](http::Request) objects. - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public BasicAuthenticator()` | Creates an empty [BasicAuthenticator](./doc/api-http.md#classscy_1_1http_1_1BasicAuthenticator) object. -`public BasicAuthenticator(const std::string & username,const std::string & password)` | -`public explicit BasicAuthenticator(const `[`http::Request`](#classscy_1_1http_1_1Request)` & request)` | -`public explicit BasicAuthenticator(const std::string & authInfo)` | -`public ~BasicAuthenticator()` | Destroys the [BasicAuthenticator](./doc/api-http.md#classscy_1_1http_1_1BasicAuthenticator). -`public void setUsername(const std::string & username)` | Sets the username. -`public const std::string & username() const` | Returns the username. -`public void setPassword(const std::string & password)` | Sets the password. -`public const std::string & password() const` | Returns the password. -`public void authenticate(`[`http::Request`](#classscy_1_1http_1_1Request)` & request) const` | Adds authentication information to the given [http::Request](http::Request). -`public void proxyAuthenticate(`[`http::Request`](#classscy_1_1http_1_1Request)` & request) const` | Adds proxy authentication information to the given [http::Request](http::Request). -`protected void parseAuthInfo(const std::string & authInfo)` | - -## Members - -#### `public BasicAuthenticator()` - -Creates an empty [BasicAuthenticator](#classscy_1_1http_1_1BasicAuthenticator) object. - - - -#### `public BasicAuthenticator(const std::string & username,const std::string & password)` - - - -Creates a [BasicAuthenticator](#classscy_1_1http_1_1BasicAuthenticator) object with the given username and password. - -#### `public explicit BasicAuthenticator(const `[`http::Request`](#classscy_1_1http_1_1Request)` & request)` - - - -Creates a [BasicAuthenticator](#classscy_1_1http_1_1BasicAuthenticator) object with the authentication information from the given request. - -Throws a NotAuthenticatedException if the request does not contain basic authentication information. - -#### `public explicit BasicAuthenticator(const std::string & authInfo)` - - - -Creates a [BasicAuthenticator](#classscy_1_1http_1_1BasicAuthenticator) object with the authentication information in the given std::string. The authentication information can be extracted from a [http::Request](http::Request) object by calling [http::Request::getCredentials()](http::Request::getCredentials()). - -#### `public ~BasicAuthenticator()` - -Destroys the [BasicAuthenticator](#classscy_1_1http_1_1BasicAuthenticator). - - - -#### `public void setUsername(const std::string & username)` - -Sets the username. - - - -#### `public const std::string & username() const` - -Returns the username. - - - -#### `public void setPassword(const std::string & password)` - -Sets the password. - - - -#### `public const std::string & password() const` - -Returns the password. - - - -#### `public void authenticate(`[`http::Request`](#classscy_1_1http_1_1Request)` & request) const` - -Adds authentication information to the given [http::Request](http::Request). - - - -#### `public void proxyAuthenticate(`[`http::Request`](#classscy_1_1http_1_1Request)` & request) const` - -Adds proxy authentication information to the given [http::Request](http::Request). - - - -#### `protected void parseAuthInfo(const std::string & authInfo)` - - - -Extracts username and password from Basic authentication info by base64-decoding authInfo and splitting the resulting std::string at the ':' delimiter. - -# class `scy::http::ChunkedAdapter` - -``` -class scy::http::ChunkedAdapter - : public scy::PacketProcessor -``` - - - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public Connection::Ptr connection` | -`public std::string contentType` | -`public std::string frameSeparator` | -`public bool initial` | -`public bool nocopy` | -`public `[`PacketSignal`](#group__base_1ga3ffb5bda6133fac97f3bed2b567b9b6a)` emitter` | -`public inline ChunkedAdapter(Connection::Ptr connection,const std::string & frameSeparator,bool nocopy)` | -`public inline ChunkedAdapter(const std::string & contentType,const std::string & frameSeparator,bool nocopy)` | -`public inline virtual ~ChunkedAdapter()` | -`public inline virtual void emitHeader()` | -`public inline virtual void process(`[`IPacket`](#classscy_1_1IPacket)` & packet)` | - -## Members - -#### `public Connection::Ptr connection` - - - - - -#### `public std::string contentType` - - - - - -#### `public std::string frameSeparator` - - - - - -#### `public bool initial` - - - - - -#### `public bool nocopy` - - - - - -#### `public `[`PacketSignal`](#group__base_1ga3ffb5bda6133fac97f3bed2b567b9b6a)` emitter` - - - - - -#### `public inline ChunkedAdapter(Connection::Ptr connection,const std::string & frameSeparator,bool nocopy)` - - - - - -#### `public inline ChunkedAdapter(const std::string & contentType,const std::string & frameSeparator,bool nocopy)` - - - - - -#### `public inline virtual ~ChunkedAdapter()` - - - - - -#### `public inline virtual void emitHeader()` - - - -Sets HTTP headers for the initial response. This method must not include the final carriage return. - -#### `public inline virtual void process(`[`IPacket`](#classscy_1_1IPacket)` & packet)` - - - -This method performs processing on the given packet and emits the result. - -Note: If packet processing is async (the packet is not in the current thread scope) then packet data must be copied. Copied data can be freed directly aFter the async call to emit() the outgoing packet. - -# class `scy::http::Client` - - - - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public `[`NullSignal`](./doc/api-base.md#classscy_1_1Signal)` Shutdown` | -`public Client()` | -`public virtual ~Client()` | -`public void shutdown()` | Shutdown the [Client](./doc/api-http.md#classscy_1_1http_1_1Client) and close all connections. -`public template`
`inline ClientConnection::Ptr createConnectionT(const `[`URL`](#classscy_1_1http_1_1URL)` & url,uv::Loop * loop)` | -`public inline ClientConnection::Ptr createConnection(const `[`URL`](#classscy_1_1http_1_1URL)` & url,uv::Loop * loop)` | -`public virtual void addConnection(ClientConnection::Ptr conn)` | -`public virtual void removeConnection(`[`ClientConnection`](#classscy_1_1http_1_1ClientConnection)` * conn)` | -`protected ClientConnectionPtrVec _connections` | -`protected void onConnectionClose(`[`Connection`](#classscy_1_1http_1_1Connection)` & conn)` | - -## Members - -#### `public `[`NullSignal`](./doc/api-base.md#classscy_1_1Signal)` Shutdown` - - - - - -#### `public Client()` - - - - - -#### `public virtual ~Client()` - - - - - -#### `public void shutdown()` - -Shutdown the [Client](#classscy_1_1http_1_1Client) and close all connections. - - - -#### `public template`
`inline ClientConnection::Ptr createConnectionT(const `[`URL`](#classscy_1_1http_1_1URL)` & url,uv::Loop * loop)` - - - - - -#### `public inline ClientConnection::Ptr createConnection(const `[`URL`](#classscy_1_1http_1_1URL)` & url,uv::Loop * loop)` - - - - - -#### `public virtual void addConnection(ClientConnection::Ptr conn)` - - - - - -#### `public virtual void removeConnection(`[`ClientConnection`](#classscy_1_1http_1_1ClientConnection)` * conn)` - - - - - -#### `protected ClientConnectionPtrVec _connections` - - - - - -#### `protected void onConnectionClose(`[`Connection`](#classscy_1_1http_1_1Connection)` & conn)` - - - - - -# class `scy::http::ClientConnection` - -``` -class scy::http::ClientConnection - : public scy::http::Connection -``` - - - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public void * opaque` | Optional unmanaged client data pointer. -`public `[`NullSignal`](./doc/api-base.md#classscy_1_1Signal)` Connect` | Status signals. -`public `[`Signal](#classscy_1_1Signal)< void([Response`](#classscy_1_1http_1_1Response) &)`> Headers` | Signals when the response HTTP header has been received. -`public `[`Signal](#classscy_1_1Signal)< void(const [MutableBuffer`](#classscy_1_1MutableBuffer) &)`> Payload` | Signals when raw data is received. -`public `[`Signal](#classscy_1_1Signal)< void(const [Response`](#classscy_1_1http_1_1Response) &)`> Complete` | Signals when the HTTP transaction is complete. -`public `[`Signal](#classscy_1_1Signal)< void([Connection`](#classscy_1_1http_1_1Connection) &)`> Close` | Signals when the connection is closed. -`public ClientConnection(const `[`URL`](#classscy_1_1http_1_1URL)` & url,const net::TCPSocket::Ptr & socket)` | Create a standalone connection with the given host. -`public virtual ~ClientConnection()` | -`public virtual void send()` | -`public virtual void send(`[`http::Request`](#classscy_1_1http_1_1Request)` & req)` | -`public virtual ssize_t send(const char * data,size_t len,int flags)` | -`public virtual void setReadStream(std::ostream * os)` | Forcefully closes the HTTP connection. -`public template`
`inline StreamT & readStream()` | Return the cast read stream pointer or nullptr. -`public virtual void onHeaders()` | [Connection](./doc/api-http.md#classscy_1_1http_1_1Connection) interface. -`public virtual void onPayload(const `[`MutableBuffer`](#classscy_1_1MutableBuffer)` & buffer)` | -`public virtual void onComplete()` | -`public virtual void onClose()` | -`protected `[`URL`](./doc/api-http.md#classscy_1_1http_1_1URL)` _url` | -`protected bool _connect` | -`protected bool _active` | -`protected bool _complete` | -`protected std::vector< std::string > _outgoingBuffer` | -`protected std::unique_ptr< std::ostream > _readStream` | -`protected virtual void connect()` | -`protected virtual `[`http::Message`](#classscy_1_1http_1_1Message)` * incomingHeader()` | -`protected virtual `[`http::Message`](#classscy_1_1http_1_1Message)` * outgoingHeader()` | -`protected virtual void onSocketConnect(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket)` | [net::SocketAdapter](./doc/api-net.md#classscy_1_1net_1_1SocketAdapter) interface - -## Members - -#### `public void * opaque` - -Optional unmanaged client data pointer. - - - -#### `public `[`NullSignal`](./doc/api-base.md#classscy_1_1Signal)` Connect` - -Status signals. - -Signals when the client socket is connected and data can flow - -#### `public `[`Signal](#classscy_1_1Signal)< void([Response`](#classscy_1_1http_1_1Response) &)`> Headers` - -Signals when the response HTTP header has been received. - - - -#### `public `[`Signal](#classscy_1_1Signal)< void(const [MutableBuffer`](#classscy_1_1MutableBuffer) &)`> Payload` - -Signals when raw data is received. - - - -#### `public `[`Signal](#classscy_1_1Signal)< void(const [Response`](#classscy_1_1http_1_1Response) &)`> Complete` - -Signals when the HTTP transaction is complete. - - - -#### `public `[`Signal](#classscy_1_1Signal)< void([Connection`](#classscy_1_1http_1_1Connection) &)`> Close` - -Signals when the connection is closed. - - - -#### `public ClientConnection(const `[`URL`](#classscy_1_1http_1_1URL)` & url,const net::TCPSocket::Ptr & socket)` - -Create a standalone connection with the given host. - - - -#### `public virtual ~ClientConnection()` - - - - - -#### `public virtual void send()` - - - -Send the HTTP request. - -Calls [connect()](#group__http_1ga3fe2e8385f1720882a418cbd6aa59766) internally if the socket is not already connecting or connected. The actual request will be sent when the socket is connected. - -#### `public virtual void send(`[`http::Request`](#classscy_1_1http_1_1Request)` & req)` - - - -Send the given HTTP request. The given request will overwrite the internal HTTP request object. - -Calls [connect()](#group__http_1ga3fe2e8385f1720882a418cbd6aa59766) internally if the socket is not already connecting or connected. The actual request will be sent when the socket is connected. - -#### `public virtual ssize_t send(const char * data,size_t len,int flags)` - - - -Send raw data to the peer. Calls [send()](#group__http_1ga4129126653843e0ee325ecac057e58fd) internally. - -Throws an exception if the socket is not already or connected. - -#### `public virtual void setReadStream(std::ostream * os)` - -Forcefully closes the HTTP connection. - -Set the output stream for writing response data to. The stream pointer is managed internally, and will be freed along with the connection. - -#### `public template`
`inline StreamT & readStream()` - -Return the cast read stream pointer or nullptr. - - - -#### `public virtual void onHeaders()` - -[Connection](#classscy_1_1http_1_1Connection) interface. - - - -#### `public virtual void onPayload(const `[`MutableBuffer`](#classscy_1_1MutableBuffer)` & buffer)` - - - - - -#### `public virtual void onComplete()` - - - - - -#### `public virtual void onClose()` - - - - - -#### `protected `[`URL`](./doc/api-http.md#classscy_1_1http_1_1URL)` _url` - - - - - -#### `protected bool _connect` - - - - - -#### `protected bool _active` - - - - - -#### `protected bool _complete` - - - - - -#### `protected std::vector< std::string > _outgoingBuffer` - - - - - -#### `protected std::unique_ptr< std::ostream > _readStream` - - - - - -#### `protected virtual void connect()` - - - -Connects to the server endpoint. All sent data is buffered until the connection is made. - -#### `protected virtual `[`http::Message`](#classscy_1_1http_1_1Message)` * incomingHeader()` - - - - - -#### `protected virtual `[`http::Message`](#classscy_1_1http_1_1Message)` * outgoingHeader()` - - - - - -#### `protected virtual void onSocketConnect(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket)` - -[net::SocketAdapter](#classscy_1_1net_1_1SocketAdapter) interface - - - -# class `scy::http::Connection` - -``` -class scy::http::Connection - : public scy::net::SocketAdapter -``` - - - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public Connection(const net::TCPSocket::Ptr & socket)` | -`public virtual ~Connection()` | -`public void onHeaders()` | -`public void onPayload(const `[`MutableBuffer`](#classscy_1_1MutableBuffer)` &)` | -`public void onComplete()` | -`public void onClose()` | -`public virtual ssize_t send(const char * data,size_t len,int flags)` | Send raw data to the peer. -`public virtual ssize_t sendHeader()` | Send the outdoing HTTP header. -`public virtual void close()` | -`public bool closed() const` | Return true if the connection is closed. -`public `[`scy::Error`](#structscy_1_1Error)` error() const` | Return the error object if any. -`public bool shouldSendHeader() const` | Return true if headers should be automatically sent. -`public void shouldSendHeader(bool flag)` | Set true to prevent auto-sending HTTP headers. -`public virtual void replaceAdapter(`[`net::SocketAdapter`](#classscy_1_1net_1_1SocketAdapter)` * adapter)` | -`public net::TCPSocket::Ptr & socket()` | Return the underlying socket pointer. -`public `[`net::SocketAdapter`](#classscy_1_1net_1_1SocketAdapter)` * adapter() const` | Return the underlying adapter pointer. -`public `[`Request`](#classscy_1_1http_1_1Request)` & request()` | The HTTP request headers. -`public `[`Response`](#classscy_1_1http_1_1Response)` & response()` | The HTTP response headers. -`public `[`http::Message`](#classscy_1_1http_1_1Message)` * incomingHeader()` | -`public `[`http::Message`](#classscy_1_1http_1_1Message)` * outgoingHeader()` | -`protected net::TCPSocket::Ptr _socket` | -`protected `[`net::SocketAdapter`](./doc/api-net.md#classscy_1_1net_1_1SocketAdapter)` * _adapter` | -`protected `[`Request`](./doc/api-http.md#classscy_1_1http_1_1Request)` _request` | -`protected `[`Response`](./doc/api-http.md#classscy_1_1http_1_1Response)` _response` | -`protected `[`scy::Error`](./doc/api-base.md#structscy_1_1Error)` _error` | -`protected bool _closed` | -`protected bool _shouldSendHeader` | -`protected virtual void setError(const `[`scy::Error`](#structscy_1_1Error)` & err)` | -`protected virtual void onSocketConnect(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket)` | [net::SocketAdapter](./doc/api-net.md#classscy_1_1net_1_1SocketAdapter) interface -`protected virtual void onSocketRecv(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket,const `[`MutableBuffer`](#classscy_1_1MutableBuffer)` & buffer,const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddress)` | -`protected virtual void onSocketError(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket,const `[`scy::Error`](#structscy_1_1Error)` & error)` | -`protected virtual void onSocketClose(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket)` | - -## Members - -#### `public Connection(const net::TCPSocket::Ptr & socket)` - - - - - -#### `public virtual ~Connection()` - - - - - -#### `public void onHeaders()` - - - - - -#### `public void onPayload(const `[`MutableBuffer`](#classscy_1_1MutableBuffer)` &)` - - - - - -#### `public void onComplete()` - - - - - -#### `public void onClose()` - - - - - -#### `public virtual ssize_t send(const char * data,size_t len,int flags)` - -Send raw data to the peer. - - - -#### `public virtual ssize_t sendHeader()` - -Send the outdoing HTTP header. - - - -#### `public virtual void close()` - - - -Close the connection and schedule the object for deferred deletion. - -#### `public bool closed() const` - -Return true if the connection is closed. - - - -#### `public `[`scy::Error`](#structscy_1_1Error)` error() const` - -Return the error object if any. - - - -#### `public bool shouldSendHeader() const` - -Return true if headers should be automatically sent. - -Return true if the server did not give us a proper response within the allotted time. bool expired() const; - -#### `public void shouldSendHeader(bool flag)` - -Set true to prevent auto-sending HTTP headers. - - - -#### `public virtual void replaceAdapter(`[`net::SocketAdapter`](#classscy_1_1net_1_1SocketAdapter)` * adapter)` - - - -Assign the new [ConnectionAdapter](#classscy_1_1http_1_1ConnectionAdapter) and setup the chain The flow is: [Connection](#classscy_1_1http_1_1Connection) <-> [ConnectionAdapter](#classscy_1_1http_1_1ConnectionAdapter) <-> Socket - -#### `public net::TCPSocket::Ptr & socket()` - -Return the underlying socket pointer. - - - -#### `public `[`net::SocketAdapter`](#classscy_1_1net_1_1SocketAdapter)` * adapter() const` - -Return the underlying adapter pointer. - - - -#### `public `[`Request`](#classscy_1_1http_1_1Request)` & request()` - -The HTTP request headers. - - - -#### `public `[`Response`](#classscy_1_1http_1_1Response)` & response()` - -The HTTP response headers. - - - -#### `public `[`http::Message`](#classscy_1_1http_1_1Message)` * incomingHeader()` - - - - - -#### `public `[`http::Message`](#classscy_1_1http_1_1Message)` * outgoingHeader()` - - - - - -#### `protected net::TCPSocket::Ptr _socket` - - - - - -#### `protected `[`net::SocketAdapter`](./doc/api-net.md#classscy_1_1net_1_1SocketAdapter)` * _adapter` - - - - - -#### `protected `[`Request`](./doc/api-http.md#classscy_1_1http_1_1Request)` _request` - - - - - -#### `protected `[`Response`](./doc/api-http.md#classscy_1_1http_1_1Response)` _response` - - - - - -#### `protected `[`scy::Error`](./doc/api-base.md#structscy_1_1Error)` _error` - - - - - -#### `protected bool _closed` - - - - - -#### `protected bool _shouldSendHeader` - - - - - -#### `protected virtual void setError(const `[`scy::Error`](#structscy_1_1Error)` & err)` - - - -Set the internal error. Note: Setting the error does not `[close()](#group__http_1ga7c40813c43b7e09e0b52ec8f33378dc9)` the connection. - -#### `protected virtual void onSocketConnect(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket)` - -[net::SocketAdapter](#classscy_1_1net_1_1SocketAdapter) interface - - - -#### `protected virtual void onSocketRecv(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket,const `[`MutableBuffer`](#classscy_1_1MutableBuffer)` & buffer,const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddress)` - - - - - -#### `protected virtual void onSocketError(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket,const `[`scy::Error`](#structscy_1_1Error)` & error)` - - - - - -#### `protected virtual void onSocketClose(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket)` - - - - - -# class `scy::http::ConnectionAdapter` - -``` -class scy::http::ConnectionAdapter - : public scy::http::ParserObserver - : public scy::net::SocketAdapter -``` - -Default HTTP socket adapter for reading and writing HTTP messages. - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public ConnectionAdapter(`[`Connection`](#classscy_1_1http_1_1Connection)` * connection,http_parser_type type)` | -`public virtual ~ConnectionAdapter()` | -`public virtual ssize_t send(const char * data,size_t len,int flags)` | -`public virtual void removeReceiver(`[`SocketAdapter`](#group__net_1ga35ca78ac04abbd6828af02fb1b65e6d1)` * adapter)` | -`public `[`Parser`](#classscy_1_1http_1_1Parser)` & parser()` | -`public `[`Connection`](#classscy_1_1http_1_1Connection)` * connection()` | -`protected `[`Connection`](./doc/api-http.md#classscy_1_1http_1_1Connection)` * _connection` | -`protected `[`Parser`](./doc/api-http.md#classscy_1_1http_1_1Parser)` _parser` | -`protected virtual void onSocketRecv(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket,const `[`MutableBuffer`](#classscy_1_1MutableBuffer)` & buffer,const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddress)` | SocketAdapter interface. -`protected virtual void onParserHeader(const std::string & name,const std::string & value)` | HTTP [Parser](./doc/api-http.md#classscy_1_1http_1_1Parser) interface. -`protected virtual void onParserHeadersEnd(bool upgrade)` | -`protected virtual void onParserChunk(const char * buf,size_t len)` | -`protected virtual void onParserError(const `[`scy::Error`](#structscy_1_1Error)` & err)` | -`protected virtual void onParserEnd()` | - -## Members - -#### `public ConnectionAdapter(`[`Connection`](#classscy_1_1http_1_1Connection)` * connection,http_parser_type type)` - - - - - -#### `public virtual ~ConnectionAdapter()` - - - - - -#### `public virtual ssize_t send(const char * data,size_t len,int flags)` - - - -Sends the given data buffer to the connected peer. Returns the number of bytes sent or -1 on error. No exception will be thrown. For TCP sockets the given peer address must match the connected peer address. - -#### `public virtual void removeReceiver(`[`SocketAdapter`](#group__net_1ga35ca78ac04abbd6828af02fb1b65e6d1)` * adapter)` - - - -Remove the given receiver. - -By default this function does nothing unless the given receiver matches the current receiver. - -#### `public `[`Parser`](#classscy_1_1http_1_1Parser)` & parser()` - - - - - -#### `public `[`Connection`](#classscy_1_1http_1_1Connection)` * connection()` - - - - - -#### `protected `[`Connection`](./doc/api-http.md#classscy_1_1http_1_1Connection)` * _connection` - - - - - -#### `protected `[`Parser`](./doc/api-http.md#classscy_1_1http_1_1Parser)` _parser` - - - - - -#### `protected virtual void onSocketRecv(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket,const `[`MutableBuffer`](#classscy_1_1MutableBuffer)` & buffer,const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddress)` - -SocketAdapter interface. - - - -#### `protected virtual void onParserHeader(const std::string & name,const std::string & value)` - -HTTP [Parser](#classscy_1_1http_1_1Parser) interface. - - - -#### `protected virtual void onParserHeadersEnd(bool upgrade)` - - - - - -#### `protected virtual void onParserChunk(const char * buf,size_t len)` - - - - - -#### `protected virtual void onParserError(const `[`scy::Error`](#structscy_1_1Error)` & err)` - - - - - -#### `protected virtual void onParserEnd()` - - - - - -# class `scy::http::ConnectionStream` - -``` -class scy::http::ConnectionStream - : public scy::net::SocketAdapter -``` - -Packet stream wrapper for a HTTP connection. - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public `[`PacketStream`](./doc/api-base.md#classscy_1_1PacketStream)` Outgoing` | -`public `[`PacketStream`](./doc/api-base.md#classscy_1_1PacketStream)` Incoming` | -`public `[`ProgressSignal`](./doc/api-http.md#classscy_1_1http_1_1ProgressSignal)` IncomingProgress` | Fired on download progress. -`public `[`ProgressSignal`](./doc/api-http.md#classscy_1_1http_1_1ProgressSignal)` OutgoingProgress` | Fired on upload progress. -`public ConnectionStream(Connection::Ptr connection)` | -`public virtual ~ConnectionStream()` | -`public virtual ssize_t send(const char * data,size_t len,int flags)` | Send data via the Outgoing stream. -`public Connection::Ptr connection()` | Return a reference to the underlying connection. -`protected Connection::Ptr _connection` | -`protected virtual void onSocketRecv(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket,const `[`MutableBuffer`](#classscy_1_1MutableBuffer)` & buffer,const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddress)` | - -## Members - -#### `public `[`PacketStream`](./doc/api-base.md#classscy_1_1PacketStream)` Outgoing` - - - -The Outgoing stream is responsible for packetizing raw application data into the agreed upon HTTP format and sending it to the peer. - -#### `public `[`PacketStream`](./doc/api-base.md#classscy_1_1PacketStream)` Incoming` - - - -The Incoming stream emits incoming HTTP packets for processing by the application. - -This is useful for example when writing incoming data to a file. - -#### `public `[`ProgressSignal`](./doc/api-http.md#classscy_1_1http_1_1ProgressSignal)` IncomingProgress` - -Fired on download progress. - - - -#### `public `[`ProgressSignal`](./doc/api-http.md#classscy_1_1http_1_1ProgressSignal)` OutgoingProgress` - -Fired on upload progress. - - - -#### `public ConnectionStream(Connection::Ptr connection)` - - - - - -#### `public virtual ~ConnectionStream()` - - - - - -#### `public virtual ssize_t send(const char * data,size_t len,int flags)` - -Send data via the Outgoing stream. - - - -#### `public Connection::Ptr connection()` - -Return a reference to the underlying connection. - - - -#### `protected Connection::Ptr _connection` - - - - - -#### `protected virtual void onSocketRecv(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket,const `[`MutableBuffer`](#classscy_1_1MutableBuffer)` & buffer,const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddress)` - - - - - -# class `scy::http::Cookie` - - - - -This class represents a HTTP [Cookie](#classscy_1_1http_1_1Cookie). - -A cookie is a small amount of information sent by a Web server to a Web browser, saved by the browser, and later sent back to the server. A cookie's value can uniquely identify a client, so cookies are commonly used for session management. - -A cookie has a name, a single value, and optional attributes such as a comment, path and domain qualifiers, a maximum age, and a version number. - -This class supports both the Version 0 (by Netscape) and Version 1 (by RFC 2109) cookie specifications. By default, cookies are created using Version 0 to ensure the best interoperability. - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public Cookie()` | Creates an empty [Cookie](./doc/api-http.md#classscy_1_1http_1_1Cookie). -`public explicit Cookie(const std::string & name)` | -`public explicit Cookie(const `[`NVCollection`](#classscy_1_1NVCollection)` & nvc)` | Creates a cookie from the given [NVCollection](./doc/api-base.md#classscy_1_1NVCollection). -`public Cookie(const std::string & name,const std::string & value)` | -`public Cookie(const `[`Cookie`](#classscy_1_1http_1_1Cookie)` & cookie)` | Creates the [Cookie](./doc/api-http.md#classscy_1_1http_1_1Cookie) by copying another one. -`public ~Cookie()` | Destroys the [Cookie](./doc/api-http.md#classscy_1_1http_1_1Cookie). -`public `[`Cookie`](#classscy_1_1http_1_1Cookie)` & operator=(const `[`Cookie`](#classscy_1_1http_1_1Cookie)` & cookie)` | Assigns a cookie. -`public void setVersion(int version)` | -`public inline int getVersion() const` | -`public void setName(const std::string & name)` | Sets the name of the cookie. -`public inline const std::string & getName() const` | Returns the name of the cookie. -`public void setValue(const std::string & value)` | -`public inline const std::string & getValue() const` | Returns the value of the cookie. -`public void setComment(const std::string & comment)` | -`public inline const std::string & getComment() const` | Returns the comment for the cookie. -`public void setDomain(const std::string & domain)` | Sets the domain for the cookie. -`public inline const std::string & getDomain() const` | Returns the domain for the cookie. -`public void setPath(const std::string & path)` | Sets the path for the cookie. -`public inline const std::string & getPath() const` | Returns the path for the cookie. -`public void setSecure(bool secure)` | -`public inline bool getSecure() const` | -`public void setMaxAge(int maxAge)` | -`public inline int getMaxAge() const` | -`public void setHttpOnly(bool flag)` | Sets the HttpOnly flag for the cookie. -`public inline bool getHttpOnly() const` | Returns true if the cookie's HttpOnly flag is set. -`public std::string toString() const` | - -## Members - -#### `public Cookie()` - -Creates an empty [Cookie](#classscy_1_1http_1_1Cookie). - - - -#### `public explicit Cookie(const std::string & name)` - - - -Creates a cookie with the given name. The cookie never expires. - -#### `public explicit Cookie(const `[`NVCollection`](#classscy_1_1NVCollection)` & nvc)` - -Creates a cookie from the given [NVCollection](#classscy_1_1NVCollection). - - - -#### `public Cookie(const std::string & name,const std::string & value)` - - - -Creates a cookie with the given name and value. The cookie never expires. - -Note: If value contains whitespace or non-alphanumeric characters, the value should be escaped by calling [escape()](#group__http_1ga5dc9fb3d11c40a91b69c562135a4a5f8) before passing it to the constructor. - -#### `public Cookie(const `[`Cookie`](#classscy_1_1http_1_1Cookie)` & cookie)` - -Creates the [Cookie](#classscy_1_1http_1_1Cookie) by copying another one. - - - -#### `public ~Cookie()` - -Destroys the [Cookie](#classscy_1_1http_1_1Cookie). - - - -#### `public `[`Cookie`](#classscy_1_1http_1_1Cookie)` & operator=(const `[`Cookie`](#classscy_1_1http_1_1Cookie)` & cookie)` - -Assigns a cookie. - - - -#### `public void setVersion(int version)` - - - -Sets the version of the cookie. - -Version must be either 0 (denoting a Netscape cookie) or 1 (denoting a RFC 2109 cookie). - -#### `public inline int getVersion() const` - - - -Returns the version of the cookie, which is either 0 or 1. - -#### `public void setName(const std::string & name)` - -Sets the name of the cookie. - - - -#### `public inline const std::string & getName() const` - -Returns the name of the cookie. - - - -#### `public void setValue(const std::string & value)` - - - -Sets the value of the cookie. - -According to the cookie specification, the size of the value should not exceed 4 Kbytes. - -Note: If value contains whitespace or non-alphanumeric characters, the value should be escaped by calling [escape()](#group__http_1ga5dc9fb3d11c40a91b69c562135a4a5f8) prior to passing it to [setName()](#group__http_1gad8867c1d8c54497acc3b251b9086f73d). - -#### `public inline const std::string & getValue() const` - -Returns the value of the cookie. - - - -#### `public void setComment(const std::string & comment)` - - - -Sets the comment for the cookie. - -Comments are only supported for version 1 cookies. - -#### `public inline const std::string & getComment() const` - -Returns the comment for the cookie. - - - -#### `public void setDomain(const std::string & domain)` - -Sets the domain for the cookie. - - - -#### `public inline const std::string & getDomain() const` - -Returns the domain for the cookie. - - - -#### `public void setPath(const std::string & path)` - -Sets the path for the cookie. - - - -#### `public inline const std::string & getPath() const` - -Returns the path for the cookie. - - - -#### `public void setSecure(bool secure)` - - - -Sets the value of the secure flag for the cookie. - -#### `public inline bool getSecure() const` - - - -Returns the value of the secure flag for the cookie. - -#### `public void setMaxAge(int maxAge)` - - - -Sets the maximum age in seconds for the cookie. - -A value of -1 causes the cookie to never expire on the client. - -A value of 0 deletes the cookie on the client. - -#### `public inline int getMaxAge() const` - - - -Returns the maximum age in seconds for the cookie. - -#### `public void setHttpOnly(bool flag)` - -Sets the HttpOnly flag for the cookie. - - - -#### `public inline bool getHttpOnly() const` - -Returns true if the cookie's HttpOnly flag is set. - - - -#### `public std::string toString() const` - - - -Returns a std::string representation of the cookie, suitable for use in a Set-Cookie header. - -# class `scy::http::FilePart` - -``` -class scy::http::FilePart - : public scy::http::FormPart -``` - -An implementation of [FilePart](#classscy_1_1http_1_1FilePart) for plain files. - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public FilePart(const std::string & path)` | -`public FilePart(const std::string & path,const std::string & contentType)` | -`public FilePart(const std::string & path,const std::string & filename,const std::string & contentType)` | -`public virtual ~FilePart()` | Destroys the [FilePart](./doc/api-http.md#classscy_1_1http_1_1FilePart). -`public virtual void open()` | -`public virtual void reset()` | Reset the internal state and write position to the start. -`public virtual bool writeChunk(`[`FormWriter`](#classscy_1_1http_1_1FormWriter)` & writer)` | -`public virtual void write(`[`FormWriter`](#classscy_1_1http_1_1FormWriter)` & writer)` | Writes the form data to the given HTTP client connection. -`public virtual void write(std::ostream & ostr)` | Writes the form data to the given output stream. -`public const std::string & filename() const` | Returns the filename portion of the path. -`public std::ifstream & stream()` | Returns the file input stream. -`public virtual uint64_t length() const` | Returns the length of the current part. -`protected std::string _path` | -`protected std::string _filename` | -`protected std::ifstream _istr` | -`protected uint64_t _fileSize` | - -## Members - -#### `public FilePart(const std::string & path)` - - - -Creates the [FilePart](#classscy_1_1http_1_1FilePart) for the given path. - -The MIME type is set to application/octet-stream. - -Throws an FileException if the file cannot be opened. - -#### `public FilePart(const std::string & path,const std::string & contentType)` - - - -Creates the [FilePart](#classscy_1_1http_1_1FilePart) for the given path and MIME type. - -Throws an FileException if the file cannot be opened. - -#### `public FilePart(const std::string & path,const std::string & filename,const std::string & contentType)` - - - -Creates the [FilePart](#classscy_1_1http_1_1FilePart) for the given path and MIME type. The given filename is used as part filename (see [filename()](#group__http_1gad2765df66b173afe804630d0294b57d2)) only. - -Throws an FileException if the file cannot be opened. - -#### `public virtual ~FilePart()` - -Destroys the [FilePart](#classscy_1_1http_1_1FilePart). - - - -#### `public virtual void open()` - - - -Opens the file. - -Throws an FileException if the file cannot be opened. - -#### `public virtual void reset()` - -Reset the internal state and write position to the start. - - - -#### `public virtual bool writeChunk(`[`FormWriter`](#classscy_1_1http_1_1FormWriter)` & writer)` - - - -Writes a form data chunk to the given HTTP client connection. Returns true if there is more data to be written. - -#### `public virtual void write(`[`FormWriter`](#classscy_1_1http_1_1FormWriter)` & writer)` - -Writes the form data to the given HTTP client connection. - - - -#### `public virtual void write(std::ostream & ostr)` - -Writes the form data to the given output stream. - - - -#### `public const std::string & filename() const` - -Returns the filename portion of the path. - - - -#### `public std::ifstream & stream()` - -Returns the file input stream. - - - -#### `public virtual uint64_t length() const` - -Returns the length of the current part. - - - -#### `protected std::string _path` - - - - - -#### `protected std::string _filename` - - - - - -#### `protected std::ifstream _istr` - - - - - -#### `protected uint64_t _fileSize` - - - - - -# class `scy::http::FormPart` - - -An implementation of [FormPart](#classscy_1_1http_1_1FormPart). - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public FormPart(const std::string & contentType)` | Creates the [FormPart](./doc/api-http.md#classscy_1_1http_1_1FormPart) with the given MIME type. -`public virtual ~FormPart()` | Destroys the [FormPart](./doc/api-http.md#classscy_1_1http_1_1FormPart). -`public virtual void reset()` | Reset the internal state and write position to the start. -`public bool writeChunk(`[`FormWriter`](#classscy_1_1http_1_1FormWriter)` & writer)` | -`public void write(`[`FormWriter`](#classscy_1_1http_1_1FormWriter)` & writer)` | Writes the form data to the given HTTP client connection. -`public void write(std::ostream & ostr)` | Writes the form data to the given output stream. -`public `[`NVCollection`](#classscy_1_1NVCollection)` & headers()` | -`public virtual bool initialWrite() const` | Returns true if this is the initial write. -`public const std::string & contentType() const` | Returns the MIME type for this part or attachment. -`public uint64_t length() const` | Returns the length of the current part. -`protected std::string _contentType` | -`protected uint64_t _length` | -`protected `[`NVCollection`](./doc/api-base.md#classscy_1_1NVCollection)` _headers` | -`protected bool _initialWrite` | - -## Members - -#### `public FormPart(const std::string & contentType)` - -Creates the [FormPart](#classscy_1_1http_1_1FormPart) with the given MIME type. - - - -#### `public virtual ~FormPart()` - -Destroys the [FormPart](#classscy_1_1http_1_1FormPart). - - - -#### `public virtual void reset()` - -Reset the internal state and write position to the start. - - - -#### `public bool writeChunk(`[`FormWriter`](#classscy_1_1http_1_1FormWriter)` & writer)` - - - -Writes a form data chunk to the given HTTP client connection. Returns true if there is more data to be written. - -#### `public void write(`[`FormWriter`](#classscy_1_1http_1_1FormWriter)` & writer)` - -Writes the form data to the given HTTP client connection. - - - -#### `public void write(std::ostream & ostr)` - -Writes the form data to the given output stream. - - - -#### `public `[`NVCollection`](#classscy_1_1NVCollection)` & headers()` - - - -Returns a [NVCollection](#classscy_1_1NVCollection) containing additional header fields for the part. - -#### `public virtual bool initialWrite() const` - -Returns true if this is the initial write. - - - -#### `public const std::string & contentType() const` - -Returns the MIME type for this part or attachment. - - - -#### `public uint64_t length() const` - -Returns the length of the current part. - - - -#### `protected std::string _contentType` - - - - - -#### `protected uint64_t _length` - - - - - -#### `protected `[`NVCollection`](./doc/api-base.md#classscy_1_1NVCollection)` _headers` - - - - - -#### `protected bool _initialWrite` - - - - - -# class `scy::http::FormWriter` - -``` -class scy::http::FormWriter - : public scy::NVCollection - : public scy::PacketStreamAdapter - : public scy::basic::Startable -``` - - - -[FormWriter](#classscy_1_1http_1_1FormWriter) is a HTTP client connection adapter for writing HTML forms. - -This class runs in its own thread so as not to block the event loop while uploading big files. Class members are not synchronized hence they should not be accessed while the form is sending, not that there would be any reason to do so. - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public `[`PacketSignal`](#group__base_1ga3ffb5bda6133fac97f3bed2b567b9b6a)` emitter` | The outgoing packet emitter. -`public virtual ~FormWriter()` | Destroys the [FormWriter](./doc/api-http.md#classscy_1_1http_1_1FormWriter). -`public void addPart(const std::string & name,`[`FormPart`](#classscy_1_1http_1_1FormPart)` * part)` | -`public virtual void start()` | Starts the sending thread. -`public virtual void stop()` | Stops the sending thread. -`public bool complete() const` | Returns true if the request is complete. -`public bool cancelled() const` | Returns true if the request is cancelled. -`public void prepareSubmit()` | -`public uint64_t calculateMultipartContentLength()` | -`public void writeUrl(std::ostream & ostr)` | -`public void writeMultipartChunk()` | -`public void writeAsync()` | -`public void setEncoding(const std::string & encoding)` | -`public const std::string & encoding() const` | Returns the encoding used for posting the form. -`public void setBoundary(const std::string & boundary)` | -`public const std::string & boundary() const` | Returns the MIME boundary used for writing multipart form data. -`public `[`ConnectionStream`](#classscy_1_1http_1_1ConnectionStream)` & connection()` | The associated HTTP client connection. -`protected `[`ConnectionStream`](./doc/api-http.md#classscy_1_1http_1_1ConnectionStream)` & _stream` | -`protected std::shared_ptr< `[`Runner`](./doc/api-base.md#classscy_1_1Runner)` > _runner` | -`protected std::string _encoding` | -`protected std::string _boundary` | -`protected PartQueue _parts` | -`protected uint64_t _filesLength` | -`protected int _writeState` | -`protected bool _initial` | -`protected bool _complete` | -`protected FormWriter(`[`ConnectionStream`](#classscy_1_1http_1_1ConnectionStream)` & conn,std::shared_ptr< `[`Runner`](#classscy_1_1Runner)` > runner,const std::string & encoding)` | -`protected FormWriter(const `[`FormWriter`](#classscy_1_1http_1_1FormWriter)` &) = delete` | -`protected `[`FormWriter`](#classscy_1_1http_1_1FormWriter)` & operator=(const `[`FormWriter`](#classscy_1_1http_1_1FormWriter)` &) = delete` | -`protected void writePartHeader(const `[`NVCollection`](#classscy_1_1NVCollection)` & header,std::ostream & ostr)` | -`protected void writeEnd(std::ostream & ostr)` | Writes the final boundary std::string to the output stream. -`protected virtual void updateProgress(int nread)` | - -## Members - -#### `public `[`PacketSignal`](#group__base_1ga3ffb5bda6133fac97f3bed2b567b9b6a)` emitter` - -The outgoing packet emitter. - - - -#### `public virtual ~FormWriter()` - -Destroys the [FormWriter](#classscy_1_1http_1_1FormWriter). - - - -#### `public void addPart(const std::string & name,`[`FormPart`](#classscy_1_1http_1_1FormPart)` * part)` - - - -Adds an part/attachment (file upload) to the form. - -The form takes ownership of the [FilePart](#classscy_1_1http_1_1FilePart) and deletes it when it is no longer needed. The part will only be sent if the encoding set for the form is "multipart/form-data" - -#### `public virtual void start()` - -Starts the sending thread. - - - -#### `public virtual void stop()` - -Stops the sending thread. - - - -#### `public bool complete() const` - -Returns true if the request is complete. - - - -#### `public bool cancelled() const` - -Returns true if the request is cancelled. - - - -#### `public void prepareSubmit()` - - - -Prepares the outgoing HTTP request object for submitting the form. - -If the request method is GET, the encoded form is appended to the request URI as query std::string. Otherwise (the method is POST), the form's content type is set to the form's encoding. The form's parameters must be written to the request body separately, with a call to write. If the request's HTTP version is HTTP/1.0: - -* persistent connections are disabled - - -* the content transfer encoding is set to identity encoding Otherwise, if the request's HTTP version is HTTP/1.1: - - -* the request's persistent connection state is left unchanged - - -* the content transfer encoding is set to chunked - -#### `public uint64_t calculateMultipartContentLength()` - - - -Processes the entire stream and calculates the content length. Not used for chunked encoding. - -#### `public void writeUrl(std::ostream & ostr)` - - - -Writes "application/x-www-form-urlencoded" encoded data to the client connection. - -#### `public void writeMultipartChunk()` - - - -Writes the next multipart "multipart/form-data" encoded to the client connection. This method is non-blocking, // and is suitable for use with the event loop. - -#### `public void writeAsync()` - - - -Called asynchronously by the [Runner](#classscy_1_1Runner) to write the next message chunk. If "multipart/form-data" the next multipart chunk will be written. If "application/x-www-form-urlencoded" the entire message will be written. The complete flag will be set when the entire request has been written. - -#### `public void setEncoding(const std::string & encoding)` - - - -Sets the encoding used for posting the form. - -Encoding must be either "application/x-www-form-urlencoded" (which is the default) or "multipart/form-data". - -#### `public const std::string & encoding() const` - -Returns the encoding used for posting the form. - - - -#### `public void setBoundary(const std::string & boundary)` - - - -Sets the boundary to use for separating form parts. Must be set before [prepareSubmit()](#group__http_1gaa5769359cbcdf8addf6da8dc3f45d283) is called. - -#### `public const std::string & boundary() const` - -Returns the MIME boundary used for writing multipart form data. - - - -#### `public `[`ConnectionStream`](#classscy_1_1http_1_1ConnectionStream)` & connection()` - -The associated HTTP client connection. - - - -#### `protected `[`ConnectionStream`](./doc/api-http.md#classscy_1_1http_1_1ConnectionStream)` & _stream` - - - - - -#### `protected std::shared_ptr< `[`Runner`](./doc/api-base.md#classscy_1_1Runner)` > _runner` - - - - - -#### `protected std::string _encoding` - - - - - -#### `protected std::string _boundary` - - - - - -#### `protected PartQueue _parts` - - - - - -#### `protected uint64_t _filesLength` - - - - - -#### `protected int _writeState` - - - - - -#### `protected bool _initial` - - - - - -#### `protected bool _complete` - - - - - -#### `protected FormWriter(`[`ConnectionStream`](#classscy_1_1http_1_1ConnectionStream)` & conn,std::shared_ptr< `[`Runner`](#classscy_1_1Runner)` > runner,const std::string & encoding)` - - - -Creates the [FormWriter](#classscy_1_1http_1_1FormWriter) that uses the given encoding. - -Encoding must be either "application/x-www-form-urlencoded" (which is the default) or "multipart/form-data". - -#### `protected FormWriter(const `[`FormWriter`](#classscy_1_1http_1_1FormWriter)` &) = delete` - - - - - -#### `protected `[`FormWriter`](#classscy_1_1http_1_1FormWriter)` & operator=(const `[`FormWriter`](#classscy_1_1http_1_1FormWriter)` &) = delete` - - - - - -#### `protected void writePartHeader(const `[`NVCollection`](#classscy_1_1NVCollection)` & header,std::ostream & ostr)` - - - -Writes the message boundary std::string, followed by the message header to the output stream. - -#### `protected void writeEnd(std::ostream & ostr)` - -Writes the final boundary std::string to the output stream. - - - -#### `protected virtual void updateProgress(int nread)` - - - -Updates the upload progress via the associated [ConnectionStream](#classscy_1_1http_1_1ConnectionStream) object. - -# class `scy::http::Message` - -``` -class scy::http::Message - : public scy::NVCollection -``` - - - -The base class for [Request](#classscy_1_1http_1_1Request) and [Response](#classscy_1_1http_1_1Response). - -Defines the common properties of all HTTP messages. These are version, content length, content type and transfer encoding. - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public void setVersion(const std::string & version)` | Sets the HTTP version for this message. -`public const std::string & getVersion() const` | Returns the HTTP version for this message. -`public void setContentLength(uint64_t length)` | -`public uint64_t getContentLength() const` | -`public bool hasContentLength() const` | Returns true if a Content-Length header is present. -`public void setTransferEncoding(const std::string & transferEncoding)` | -`public const std::string & getTransferEncoding() const` | -`public void setChunkedTransferEncoding(bool flag)` | -`public bool isChunkedTransferEncoding() const` | -`public void setContentType(const std::string & contentType)` | -`public const std::string & getContentType() const` | -`public void setKeepAlive(bool keepAlive)` | -`public bool getKeepAlive() const` | -`public virtual void write(std::ostream & ostr) const` | -`public virtual void write(std::string & str) const` | Writes the message header to the given output string. -`protected std::string _version` | -`protected Message()` | Creates the [Message](./doc/api-http.md#classscy_1_1http_1_1Message) with version HTTP/1.0. -`protected Message(const std::string & version)` | -`protected virtual ~Message()` | Destroys the [Message](./doc/api-http.md#classscy_1_1http_1_1Message). - -## Members - -#### `public void setVersion(const std::string & version)` - -Sets the HTTP version for this message. - - - -#### `public const std::string & getVersion() const` - -Returns the HTTP version for this message. - - - -#### `public void setContentLength(uint64_t length)` - - - -Sets the Content-Length header. - -If length is UNKNOWN_CONTENT_LENGTH, removes the Content-Length header. - -#### `public uint64_t getContentLength() const` - - - -Returns the content length for this message, which may be UNKNOWN_CONTENT_LENGTH if no Content-Length header is present. - -#### `public bool hasContentLength() const` - -Returns true if a Content-Length header is present. - - - -#### `public void setTransferEncoding(const std::string & transferEncoding)` - - - -Sets the transfer encoding for this message. - -The value should be either IDENTITY_TRANSFER_CODING or CHUNKED_TRANSFER_CODING. - -#### `public const std::string & getTransferEncoding() const` - - - -Returns the transfer encoding used for this message. - -Normally, this is the value of the Transfer-Encoding header field. If no such field is present, returns IDENTITY_TRANSFER_CODING. - -#### `public void setChunkedTransferEncoding(bool flag)` - - - -If flag is true, sets the Transfer-Encoding header to chunked. Otherwise, removes the Transfer-Encoding header. - -#### `public bool isChunkedTransferEncoding() const` - - - -Returns true if the Transfer-Encoding header is set and its value is chunked. - -#### `public void setContentType(const std::string & contentType)` - - - -Sets the content type for this message. - -Specify NO_CONTENT_TYPE to remove the Content-Type header. - -#### `public const std::string & getContentType() const` - - - -Returns the content type for this message. - -If no Content-Type header is present, returns UNKNOWN_CONTENT_TYPE. - -#### `public void setKeepAlive(bool keepAlive)` - - +# http + +### Classes + +| Name | Description | +|------|-------------| +| [`Authenticator`](#classscy_1_1http_1_1Authenticator) | This is a utility class for working with HTTP authentication (basic or digest) in [http::Request](http::Request) objects. | +| [`BasicAuthenticator`](#classscy_1_1http_1_1BasicAuthenticator) | This is a utility class for working with HTTP Basic Authentication in [http::Request](http::Request) objects. | +| [`Connection`](#classscy_1_1http_1_1Connection) | | +| [`ConnectionAdapter`](#classscy_1_1http_1_1ConnectionAdapter) | Default HTTP socket adapter for reading and writing HTTP messages | +| [`ProgressSignal`](#classscy_1_1http_1_1ProgressSignal) | HTTP progress signal for upload and download progress notifications. | +| [`ConnectionStream`](#classscy_1_1http_1_1ConnectionStream) | Packet stream wrapper for a HTTP connection. | +| [`Cookie`](#classscy_1_1http_1_1Cookie) | This class represents a HTTP [Cookie](#classscy_1_1http_1_1Cookie). | +| [`FormWriter`](#classscy_1_1http_1_1FormWriter) | [FormWriter](#classscy_1_1http_1_1FormWriter) is a HTTP client connection adapter for writing HTML forms. | +| [`FormPart`](#classscy_1_1http_1_1FormPart) | An implementation of [FormPart](#classscy_1_1http_1_1FormPart). | +| [`FilePart`](#classscy_1_1http_1_1FilePart) | An implementation of [FilePart](#classscy_1_1http_1_1FilePart) for plain files. | +| [`StringPart`](#classscy_1_1http_1_1StringPart) | An implementation of [StringPart](#classscy_1_1http_1_1StringPart) for plain files. | +| [`Message`](#classscy_1_1http_1_1Message) | The base class for [Request](./doc/api-undefined.md#classscy_1_1http_1_1Request) and [Response](./doc/api-undefined.md#classscy_1_1http_1_1Response). | +| [`ChunkedAdapter`](#classscy_1_1http_1_1ChunkedAdapter) | HTTP chunked transfer encoding adapter for streaming responses. | +| [`MultipartAdapter`](#classscy_1_1http_1_1MultipartAdapter) | HTTP multipart encoding adapter for multipart/x-mixed-replace streaming. | +| [`ParserObserver`](#classscy_1_1http_1_1ParserObserver) | Abstract observer interface for HTTP parser events. | +| [`Parser`](#classscy_1_1http_1_1Parser) | HTTP request/response parser using the llhttp library. | + +### Members + +| Name | Description | +|------|-------------| +| [`HTTP_API`](#group__http_1gacf879ba207cfe7e6b02da3fe19e29047) | | + +--- + +#### HTTP_API + +```cpp +HTTP_API() +``` -Sets the value of the [Connection](#classscy_1_1http_1_1Connection) header field. +## Authenticator -The value is set to "Keep-Alive" if keepAlive is true, or to "Close" otherwise. +> **Defined in:** `authenticator.h` -#### `public bool getKeepAlive() const` +This is a utility class for working with HTTP authentication (basic or digest) in [http::Request](http::Request) objects. +Note: Do not forget to read the entire response stream from the 401 response before sending the authenticated request, otherwise there may be problems if a persistent connection is used. +### Members + +| Name | Description | +|------|-------------| +| [`Authenticator`](#group__http_1ga6214df1c0d604a6925a4ff5341a2570e) | Creates an empty [Authenticator](#classscy_1_1http_1_1Authenticator) object. | +| [`Authenticator`](#group__http_1gaab5bbd50fb1b1d53a321ba47b294e2c8) | Creates an [Authenticator](#classscy_1_1http_1_1Authenticator) object with the given username and password. | +| [`~Authenticator`](#group__http_1gaed3172ab7db55f51397c6230f32dea08) | Destroys the [Authenticator](#classscy_1_1http_1_1Authenticator). | +| [`fromUserInfo`](#group__http_1gad1ee6dffdb0fdd9a8276425ea40fafca) | Parses username:password std::string and sets username and password of the credentials object. Throws SyntaxException on invalid user information. | +| [`fromURI`](#group__http_1ga12f51f7f097ca4e3cfc5d434e754a01d) | Extracts username and password from the given URI and sets username and password of the credentials object. Does nothing if URI has no user info part. | +| [`setUsername`](#group__http_1ga7944c4a74c6a4e5dbd3b2c2c1f252fc6) | Sets the username. | +| [`username`](#group__http_1ga365097004eb19ff11797471edaba7a11) | Returns the username. | +| [`setPassword`](#group__http_1ga4699ccc9f01adab04a81a389b3367e80) | Sets the password. | +| [`password`](#group__http_1ga7eeb4f10098784269c96fc6a3146fac8) | Returns the password. | +| [`authenticate`](#group__http_1ga653edb8897e31620c3f51e3b3241dd27) | Inspects WWW-Authenticate header of the response, initializes the internal state (in case of digest authentication) and adds required information to the given [http::Request](http::Request). | +| [`updateAuthInfo`](#group__http_1ga518fc10b748ab74fa1d907b16f623802) | Updates internal state (in case of digest authentication) and replaces authentication information in the request accordingly. | +| [`proxyAuthenticate`](#group__http_1gaf3d04876711434a0ec46b0ed92063415) | Inspects Proxy-Authenticate header of the response, initializes the internal state (in case of digest authentication) and adds required information to the given [http::Request](http::Request). | +| [`updateProxyAuthInfo`](#group__http_1ga312f80e580ffd52a53e00df22105c0d0) | Updates internal state (in case of digest authentication) and replaces proxy authentication information in the request accordingly. | +| [`_username`](#classscy_1_1http_1_1Authenticator_1a64a71053942ececa00fe9b9cf268587b) | | +| [`_password`](#classscy_1_1http_1_1Authenticator_1ae53555ba1c43a70dcb204ce2c444f326) | | +| [`Authenticator`](#classscy_1_1http_1_1Authenticator_1abd2eb9f36c15630e9a53dea83e7f6f6d) | | +| [`operator=`](#classscy_1_1http_1_1Authenticator_1a24de65ab7924d093c169017739e50808) | | + +--- + +#### Authenticator + +```cpp +Authenticator() +``` -Returns true if +Creates an empty [Authenticator](#classscy_1_1http_1_1Authenticator) object. -* the message has a [Connection](#classscy_1_1http_1_1Connection) header field and its value is "Keep-Alive" +--- +#### Authenticator -* the message is a HTTP/1.1 message and not [Connection](#classscy_1_1http_1_1Connection) header is set Returns false otherwise. +```cpp +Authenticator(const std::string & username, const std::string & password) +``` -#### `public virtual void write(std::ostream & ostr) const` +Creates an [Authenticator](#classscy_1_1http_1_1Authenticator) object with the given username and password. +| Parameter | Type | Description | +|-----------|------|-------------| +| `username` | `const std::string &` | | +| `password` | `const std::string &` | | +--- -Writes the message header to the given output stream. +#### ~Authenticator -The format is one name-value pair per line, with name and value separated by a colon and lines delimited by a carriage return and a linefeed character. See RFC 2822 for details. +```cpp +~Authenticator() +``` -#### `public virtual void write(std::string & str) const` +Destroys the [Authenticator](#classscy_1_1http_1_1Authenticator). -Writes the message header to the given output string. +--- +#### fromUserInfo +```cpp +void fromUserInfo(const std::string & userInfo) +``` -#### `protected std::string _version` +Parses username:password std::string and sets username and password of the credentials object. Throws SyntaxException on invalid user information. +| Parameter | Type | Description | +|-----------|------|-------------| +| `userInfo` | `const std::string &` | | +--- +#### fromURI +```cpp +void fromURI(const http::URL & uri) +``` -#### `protected Message()` +Extracts username and password from the given URI and sets username and password of the credentials object. Does nothing if URI has no user info part. -Creates the [Message](#classscy_1_1http_1_1Message) with version HTTP/1.0. +| Parameter | Type | Description | +|-----------|------|-------------| +| `uri` | `const http::URL &` | | +--- +#### setUsername -#### `protected Message(const std::string & version)` +```cpp +inline void setUsername(const std::string & username) +``` +Sets the username. +| Parameter | Type | Description | +|-----------|------|-------------| +| `username` | `const std::string &` | | -Creates the [Message](#classscy_1_1http_1_1Message) and sets the version. +--- -#### `protected virtual ~Message()` +#### username -Destroys the [Message](#classscy_1_1http_1_1Message). +```cpp +inline const std::string & username() const +``` +Returns the username. +--- -# class `scy::http::MultipartAdapter` +#### setPassword +```cpp +inline void setPassword(const std::string & password) ``` -class scy::http::MultipartAdapter - : public scy::PacketProcessor -``` +Sets the password. +| Parameter | Type | Description | +|-----------|------|-------------| +| `password` | `const std::string &` | | +--- +#### password -## Summary +```cpp +inline const std::string & password() const +``` - Members | Descriptions ---------------------------------|--------------------------------------------- -`public Connection::Ptr connection` | -`public std::string contentType` | -`public bool isBase64` | -`public bool initial` | -`public `[`PacketSignal`](#group__base_1ga3ffb5bda6133fac97f3bed2b567b9b6a)` emitter` | -`public inline MultipartAdapter(Connection::Ptr connection,bool base64)` | -`public inline MultipartAdapter(const std::string & contentType,bool base64)` | -`public inline virtual ~MultipartAdapter()` | -`public inline virtual void emitHeader()` | -`public inline virtual void emitChunkHeader()` | Sets HTTP header for the current chunk. -`public inline virtual void process(`[`IPacket`](#classscy_1_1IPacket)` & packet)` | +Returns the password. -## Members +--- -#### `public Connection::Ptr connection` +#### authenticate +```cpp +void authenticate(http::Request & request, const http::Response & response) +``` +Inspects WWW-Authenticate header of the response, initializes the internal state (in case of digest authentication) and adds required information to the given [http::Request](http::Request). +| Parameter | Type | Description | +|-----------|------|-------------| +| `request` | `http::Request &` | | +| `response` | `const http::Response &` | | +--- -#### `public std::string contentType` +#### updateAuthInfo +```cpp +void updateAuthInfo(http::Request & request) +``` +Updates internal state (in case of digest authentication) and replaces authentication information in the request accordingly. +| Parameter | Type | Description | +|-----------|------|-------------| +| `request` | `http::Request &` | | +--- -#### `public bool isBase64` +#### proxyAuthenticate +```cpp +void proxyAuthenticate(http::Request & request, const http::Response & response) +``` +Inspects Proxy-Authenticate header of the response, initializes the internal state (in case of digest authentication) and adds required information to the given [http::Request](http::Request). +| Parameter | Type | Description | +|-----------|------|-------------| +| `request` | `http::Request &` | | +| `response` | `const http::Response &` | | +--- -#### `public bool initial` +#### updateProxyAuthInfo +```cpp +void updateProxyAuthInfo(http::Request & request) +``` +Updates internal state (in case of digest authentication) and replaces proxy authentication information in the request accordingly. +| Parameter | Type | Description | +|-----------|------|-------------| +| `request` | `http::Request &` | | +--- -#### `public `[`PacketSignal`](#group__base_1ga3ffb5bda6133fac97f3bed2b567b9b6a)` emitter` +#### _username +```cpp +std::string _username +``` +--- +#### _password +```cpp +std::string _password +``` -#### `public inline MultipartAdapter(Connection::Ptr connection,bool base64)` +--- +#### Authenticator +```cpp +Authenticator(const [Authenticator](#classscy_1_1http_1_1Authenticator) &) = delete +``` +--- +#### operator= -#### `public inline MultipartAdapter(const std::string & contentType,bool base64)` +```cpp +[Authenticator](#classscy_1_1http_1_1Authenticator) & operator=(const [Authenticator](#classscy_1_1http_1_1Authenticator) &) = delete +``` +## BasicAuthenticator +> **Defined in:** `authenticator.h` +This is a utility class for working with HTTP Basic Authentication in [http::Request](http::Request) objects. +### Members + +| Name | Description | +|------|-------------| +| [`BasicAuthenticator`](#group__http_1ga4e2fd63defaafd17ae03fb754c2da8c1) | Creates an empty [BasicAuthenticator](#classscy_1_1http_1_1BasicAuthenticator) object. | +| [`BasicAuthenticator`](#group__http_1gad6de1b1584d452ed7e06bedc87ca1021) | Creates a [BasicAuthenticator](#classscy_1_1http_1_1BasicAuthenticator) object with the given username and password. | +| [`BasicAuthenticator`](#group__http_1gaf36d893fa18c895ad0b2fe1f8316de10) | Creates a [BasicAuthenticator](#classscy_1_1http_1_1BasicAuthenticator) object with the authentication information from the given request. | +| [`BasicAuthenticator`](#group__http_1gae38dcdedcd5cdcd1c3ffd5fe28a7b1a2) | Creates a [BasicAuthenticator](#classscy_1_1http_1_1BasicAuthenticator) object with the authentication information in the given std::string. The authentication information can be extracted from a [http::Request](http::Request) object by calling [http::Request::getCredentials()](http::Request::getCredentials()). | +| [`~BasicAuthenticator`](#group__http_1ga5f94ae51fc1c7c593b84a03fef64bde4) | Destroys the [BasicAuthenticator](#classscy_1_1http_1_1BasicAuthenticator). | +| [`setUsername`](#group__http_1ga25effc506bb6d0904b86bd4d20add8c7) | Sets the username. | +| [`username`](#group__http_1ga674869333bed1c65b2e38c7700a98a1e) | Returns the username. | +| [`setPassword`](#group__http_1gabc1db19a45f0501e8ca2b29355c14fe0) | Sets the password. | +| [`password`](#group__http_1ga1ed5b0686db8c1701f515e1a41b3d323) | Returns the password. | +| [`authenticate`](#group__http_1gaaae8a1c5cadebe43bb512bac3974c0bc) | Adds authentication information to the given [http::Request](http::Request). | +| [`proxyAuthenticate`](#group__http_1ga4e342080880e1ce658f95e4bf4c6fb23) | Adds proxy authentication information to the given [http::Request](http::Request). | +| [`parseAuthInfo`](#group__http_1ga2e24fc651b06a3d5f24acc93c13039dd) | Extracts username and password from Basic authentication info by base64-decoding authInfo and splitting the resulting std::string at the ':' delimiter. | +| [`_username`](#classscy_1_1http_1_1BasicAuthenticator_1ae250f9409cedb854b665743b54f4ebe1) | | +| [`_password`](#classscy_1_1http_1_1BasicAuthenticator_1a68885442e186421e6593e67efa0b851c) | | +| [`BasicAuthenticator`](#classscy_1_1http_1_1BasicAuthenticator_1a888b7294916e29d0b991becccc8397ad) | | +| [`operator=`](#classscy_1_1http_1_1BasicAuthenticator_1af91ed4021f657eadf41474f6116b3798) | | + +--- + +#### BasicAuthenticator + +```cpp +BasicAuthenticator() +``` -#### `public inline virtual ~MultipartAdapter()` +Creates an empty [BasicAuthenticator](#classscy_1_1http_1_1BasicAuthenticator) object. +--- +#### BasicAuthenticator +```cpp +BasicAuthenticator(const std::string & username, const std::string & password) +``` +Creates a [BasicAuthenticator](#classscy_1_1http_1_1BasicAuthenticator) object with the given username and password. -#### `public inline virtual void emitHeader()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `username` | `const std::string &` | | +| `password` | `const std::string &` | | +--- +#### BasicAuthenticator +```cpp +explicit BasicAuthenticator(const http::Request & request) +``` +Creates a [BasicAuthenticator](#classscy_1_1http_1_1BasicAuthenticator) object with the authentication information from the given request. -#### `public inline virtual void emitChunkHeader()` +Throws a NotAuthenticatedException if the request does not contain basic authentication information. -Sets HTTP header for the current chunk. +| Parameter | Type | Description | +|-----------|------|-------------| +| `request` | `const http::Request &` | | +--- +#### BasicAuthenticator -#### `public inline virtual void process(`[`IPacket`](#classscy_1_1IPacket)` & packet)` +```cpp +explicit BasicAuthenticator(const std::string & authInfo) +``` +Creates a [BasicAuthenticator](#classscy_1_1http_1_1BasicAuthenticator) object with the authentication information in the given std::string. The authentication information can be extracted from a [http::Request](http::Request) object by calling [http::Request::getCredentials()](http::Request::getCredentials()). +| Parameter | Type | Description | +|-----------|------|-------------| +| `authInfo` | `const std::string &` | | -This method performs processing on the given packet and emits the result. +--- -Note: If packet processing is async (the packet is not in the current thread scope) then packet data must be copied. Copied data can be freed directly aFter the async call to emit() the outgoing packet. +#### ~BasicAuthenticator -# class `scy::http::Parser` +```cpp +~BasicAuthenticator() +``` +Destroys the [BasicAuthenticator](#classscy_1_1http_1_1BasicAuthenticator). +--- +#### setUsername +```cpp +void setUsername(const std::string & username) +``` +Sets the username. -## Summary +| Parameter | Type | Description | +|-----------|------|-------------| +| `username` | `const std::string &` | | - Members | Descriptions ---------------------------------|--------------------------------------------- -`public Parser(`[`http::Response`](#classscy_1_1http_1_1Response)` * response)` | -`public Parser(`[`http::Request`](#classscy_1_1http_1_1Request)` * request)` | -`public Parser(http_parser_type type)` | -`public ~Parser()` | -`public size_t parse(const char * data,size_t length)` | -`public void reset()` | Reset the internal state. -`public bool complete() const` | -`public bool upgrade() const` | Returns true if the connection should be upgraded. -`public void setRequest(`[`http::Request`](#classscy_1_1http_1_1Request)` * request)` | -`public void setResponse(`[`http::Response`](#classscy_1_1http_1_1Response)` * response)` | -`public void setObserver(`[`ParserObserver`](#classscy_1_1http_1_1ParserObserver)` * observer)` | -`public `[`http::Message`](#classscy_1_1http_1_1Message)` * message()` | -`public `[`ParserObserver`](#classscy_1_1http_1_1ParserObserver)` * observer() const` | -`protected `[`ParserObserver`](./doc/api-http.md#classscy_1_1http_1_1ParserObserver)` * _observer` | -`protected `[`http::Request`](./doc/api-http.md#classscy_1_1http_1_1Request)` * _request` | -`protected `[`http::Response`](./doc/api-http.md#classscy_1_1http_1_1Response)` * _response` | -`protected `[`http::Message`](./doc/api-http.md#classscy_1_1http_1_1Message)` * _message` | -`protected http_parser _parser` | -`protected http_parser_settings _settings` | -`protected http_parser_type _type` | -`protected bool _wasHeaderValue` | -`protected std::string _lastHeaderField` | -`protected std::string _lastHeaderValue` | -`protected bool _complete` | -`protected bool _upgrade` | -`protected `[`Error`](./doc/api-base.md#structscy_1_1Error)` _error` | -`protected void init()` | -`protected void onURL(const std::string & value)` | Callbacks. -`protected void onHeader(const std::string & name,const std::string & value)` | -`protected void onHeadersEnd()` | -`protected void onBody(const char * buf,size_t len)` | -`protected void onMessageEnd()` | -`protected void onError(unsigned errnum,const std::string & message)` | +--- -## Members +#### username -#### `public Parser(`[`http::Response`](#classscy_1_1http_1_1Response)` * response)` +```cpp +const std::string & username() const +``` +Returns the username. +--- +#### setPassword +```cpp +void setPassword(const std::string & password) +``` -#### `public Parser(`[`http::Request`](#classscy_1_1http_1_1Request)` * request)` +Sets the password. +| Parameter | Type | Description | +|-----------|------|-------------| +| `password` | `const std::string &` | | +--- +#### password +```cpp +const std::string & password() const +``` -#### `public Parser(http_parser_type type)` +Returns the password. +--- +#### authenticate +```cpp +void authenticate(http::Request & request) const +``` +Adds authentication information to the given [http::Request](http::Request). -#### `public ~Parser()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `request` | `http::Request &` | | +--- +#### proxyAuthenticate +```cpp +void proxyAuthenticate(http::Request & request) const +``` +Adds proxy authentication information to the given [http::Request](http::Request). -#### `public size_t parse(const char * data,size_t length)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `request` | `http::Request &` | | +--- +#### parseAuthInfo -Parse a HTTP packet. +```cpp +void parseAuthInfo(const std::string & authInfo) +``` -Returns true of the message is complete, false if incomplete. Reset the parser state for a new message +Extracts username and password from Basic authentication info by base64-decoding authInfo and splitting the resulting std::string at the ':' delimiter. -#### `public void reset()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `authInfo` | `const std::string &` | | -Reset the internal state. +--- +#### _username +```cpp +std::string _username +``` -#### `public bool complete() const` +--- +#### _password +```cpp +std::string _password +``` -Returns true if parsing is complete, either in success or error. +--- -#### `public bool upgrade() const` +#### BasicAuthenticator -Returns true if the connection should be upgraded. +```cpp +BasicAuthenticator(const [BasicAuthenticator](#classscy_1_1http_1_1BasicAuthenticator) &) = delete +``` +--- +#### operator= -#### `public void setRequest(`[`http::Request`](#classscy_1_1http_1_1Request)` * request)` +```cpp +[BasicAuthenticator](#classscy_1_1http_1_1BasicAuthenticator) & operator=(const [BasicAuthenticator](#classscy_1_1http_1_1BasicAuthenticator) &) = delete +``` +## Connection + +> **Extends:** `scy::net::SocketAdapter` +> **Subclasses:** `scy::http::ClientConnection`, `scy::http::ServerConnection` +> **Defined in:** `connection.h` + +### Members + +| Name | Description | +|------|-------------| +| [`Connection`](#classscy_1_1http_1_1Connection_1a5c3755531888c5d1117a5191da11d031) | | +| [`~Connection`](#classscy_1_1http_1_1Connection_1a34b5926baf06240530f2194af8865071) | | +| [`onHeaders`](#classscy_1_1http_1_1Connection_1a336fbc30418a29d18531050fab48823a) | | +| [`onPayload`](#classscy_1_1http_1_1Connection_1ac1f37546ff78e3af23bc14d22f89a332) | | +| [`onComplete`](#classscy_1_1http_1_1Connection_1a6eb7d0d86a109307c1549eaf9316daa7) | | +| [`onClose`](#classscy_1_1http_1_1Connection_1ab597f00ecbf6ddd4e9582f98eff9e34b) | | +| [`send`](#classscy_1_1http_1_1Connection_1ae8aa01bb6b3c6bb53c484e04f391a4d7) | Send raw data to the peer. | +| [`sendHeader`](#classscy_1_1http_1_1Connection_1a1de9285b70b16e7301ef399dea4e4fe8) | Send the outdoing HTTP header. | +| [`close`](#classscy_1_1http_1_1Connection_1a7c40813c43b7e09e0b52ec8f33378dc9) | Close the connection and schedule the object for deferred deletion. | +| [`closed`](#classscy_1_1http_1_1Connection_1aeaf613f9c94f3e93b981b4929f5a2406) | Return true if the connection is closed. | +| [`error`](#classscy_1_1http_1_1Connection_1ae097a4b0be0ce96f55adb7f099eb21d4) | Return the error object if any. | +| [`shouldSendHeader`](#classscy_1_1http_1_1Connection_1a38cfd15a7f82a369eaebddf5e4d5bc0c) | Return true if headers should be automatically sent. | +| [`shouldSendHeader`](#classscy_1_1http_1_1Connection_1ad8e7071bd3cd8162ddfa739ed4a30f94) | Set true to prevent auto-sending HTTP headers. | +| [`replaceAdapter`](#classscy_1_1http_1_1Connection_1a0eb7c6200dd3c7e6d78a96f0100b1d9c) | Assign the new [ConnectionAdapter](#classscy_1_1http_1_1ConnectionAdapter) and setup the chain The flow is: [Connection](#classscy_1_1http_1_1Connection) <-> [ConnectionAdapter](#classscy_1_1http_1_1ConnectionAdapter) <-> Socket | +| [`secure`](#classscy_1_1http_1_1Connection_1a48910a2f80c7b8a69c9507085fee7849) | Return true if the connection uses TLS/SSL. | +| [`socket`](#classscy_1_1http_1_1Connection_1a3394e7681197ee4ba5e481a6a5b24d7b) | Return the underlying socket pointer. | +| [`adapter`](#classscy_1_1http_1_1Connection_1a653678bd18a45bca9f28e127b9e16b6c) | Return the underlying adapter pointer. | +| [`request`](#classscy_1_1http_1_1Connection_1a43cc676959b5eb284d9f67a911bbca36) | The HTTP request headers. | +| [`response`](#classscy_1_1http_1_1Connection_1a69d78cf331ae34a8f57a226f4c78d6f6) | The HTTP response headers. | +| [`incomingHeader`](#classscy_1_1http_1_1Connection_1ab004764f209c4825536cd3a7d2c6d87e) | | +| [`outgoingHeader`](#classscy_1_1http_1_1Connection_1a26be5aa620c2b5e98f33b6216c2921ab) | | +| [`_socket`](#classscy_1_1http_1_1Connection_1a384c77e03a59df46c65e8b1895b03ff3) | | +| [`_adapter`](#classscy_1_1http_1_1Connection_1a1433532f714a93503af92757c7a1c0e9) | | +| [`_request`](#classscy_1_1http_1_1Connection_1aa8acc765dd7da86268d4534053be3497) | | +| [`_response`](#classscy_1_1http_1_1Connection_1a6bce4856f6f0f6daba2ae58e620dd392) | | +| [`_error`](#classscy_1_1http_1_1Connection_1a65dddb1c2b352b6e129457c70f762b7c) | | +| [`_closed`](#classscy_1_1http_1_1Connection_1a930e46e3b07a1919b617a6e037959e99) | | +| [`_shouldSendHeader`](#classscy_1_1http_1_1Connection_1a4895da546cdb23fbd3fd8be4fe2f6bb9) | | +| [`setError`](#classscy_1_1http_1_1Connection_1aebeaf7cb7d32b02026a0f608d4ffd4a9) | Set the internal error. Note: Setting the error does not `[close()](#classscy_1_1http_1_1Connection_1a7c40813c43b7e09e0b52ec8f33378dc9)` the connection. | +| [`onSocketConnect`](#classscy_1_1http_1_1Connection_1a80bb29189a18393f6d758bff6532bd7a) | [net::SocketAdapter](./doc/api-net.md#classscy_1_1net_1_1SocketAdapter) interface | +| [`onSocketRecv`](#classscy_1_1http_1_1Connection_1aec7195288b5ec70dc9013727ec06660d) | | +| [`onSocketError`](#classscy_1_1http_1_1Connection_1aa7caac1e4f068bd8d95d3bccdd8eda08) | | +| [`onSocketClose`](#classscy_1_1http_1_1Connection_1a6b8fcdccf44d735c04c9d705192a0ed6) | | +| [`Ptr`](#classscy_1_1http_1_1Connection_1a2143146501601ea9816068f83731e1fb) | | + +--- + +#### Connection + +```cpp +Connection(const [net::TCPSocket::Ptr](./doc/api-net.md#group__net_1ga2ac4375e7cda1d8bffa0b1750f84bc22) & socket) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `socket` | `const [net::TCPSocket::Ptr](./doc/api-net.md#group__net_1ga2ac4375e7cda1d8bffa0b1750f84bc22) &` | | +--- +#### ~Connection -#### `public void setResponse(`[`http::Response`](#classscy_1_1http_1_1Response)` * response)` +```cpp +virtual ~Connection() +``` +--- +#### onHeaders +```cpp +void onHeaders() +``` +--- -#### `public void setObserver(`[`ParserObserver`](#classscy_1_1http_1_1ParserObserver)` * observer)` +#### onPayload +```cpp +void onPayload(const [MutableBuffer](./doc/api-base.md#classscy_1_1MutableBuffer) &) +``` +--- +#### onComplete +```cpp +void onComplete() +``` -#### `public `[`http::Message`](#classscy_1_1http_1_1Message)` * message()` +--- +#### onClose +```cpp +void onClose() +``` +--- +#### send -#### `public `[`ParserObserver`](#classscy_1_1http_1_1ParserObserver)` * observer() const` +```cpp +virtual ssize_t send(const char * data, size_t len, int flags) +``` +Send raw data to the peer. +| Parameter | Type | Description | +|-----------|------|-------------| +| `data` | `const char *` | | +| `len` | `size_t` | | +| `flags` | `int` | | +--- +#### sendHeader -#### `protected `[`ParserObserver`](./doc/api-http.md#classscy_1_1http_1_1ParserObserver)` * _observer` +```cpp +virtual ssize_t sendHeader() +``` +Send the outdoing HTTP header. +--- +#### close +```cpp +virtual void close() +``` -#### `protected `[`http::Request`](./doc/api-http.md#classscy_1_1http_1_1Request)` * _request` +Close the connection and schedule the object for deferred deletion. +--- +#### closed +```cpp +bool closed() const +``` +Return true if the connection is closed. -#### `protected `[`http::Response`](./doc/api-http.md#classscy_1_1http_1_1Response)` * _response` +--- +#### error +```cpp +[scy::Error](./doc/api-base.md#structscy_1_1Error) error() const +``` +Return the error object if any. +--- -#### `protected `[`http::Message`](./doc/api-http.md#classscy_1_1http_1_1Message)` * _message` +#### shouldSendHeader +```cpp +bool shouldSendHeader() const +``` +Return true if headers should be automatically sent. +--- +#### shouldSendHeader -#### `protected http_parser _parser` +```cpp +void shouldSendHeader(bool flag) +``` +Set true to prevent auto-sending HTTP headers. +| Parameter | Type | Description | +|-----------|------|-------------| +| `flag` | `bool` | | +--- +#### replaceAdapter -#### `protected http_parser_settings _settings` +```cpp +virtual void replaceAdapter([net::SocketAdapter](./doc/api-net.md#classscy_1_1net_1_1SocketAdapter) * adapter) +``` +Assign the new [ConnectionAdapter](#classscy_1_1http_1_1ConnectionAdapter) and setup the chain The flow is: [Connection](#classscy_1_1http_1_1Connection) <-> [ConnectionAdapter](#classscy_1_1http_1_1ConnectionAdapter) <-> Socket +| Parameter | Type | Description | +|-----------|------|-------------| +| `adapter` | `[net::SocketAdapter](./doc/api-net.md#classscy_1_1net_1_1SocketAdapter) *` | | +--- +#### secure -#### `protected http_parser_type _type` +```cpp +bool secure() const +``` +Return true if the connection uses TLS/SSL. +--- +#### socket +```cpp +[net::TCPSocket::Ptr](./doc/api-net.md#group__net_1ga2ac4375e7cda1d8bffa0b1750f84bc22) & socket() +``` -#### `protected bool _wasHeaderValue` +Return the underlying socket pointer. +--- +#### adapter +```cpp +[net::SocketAdapter](./doc/api-net.md#classscy_1_1net_1_1SocketAdapter) * adapter() const +``` +Return the underlying adapter pointer. -#### `protected std::string _lastHeaderField` +--- +#### request +```cpp +[Request](./doc/api-undefined.md#classscy_1_1http_1_1Request) & request() +``` +The HTTP request headers. +--- -#### `protected std::string _lastHeaderValue` +#### response +```cpp +[Response](./doc/api-undefined.md#classscy_1_1http_1_1Response) & response() +``` +The HTTP response headers. +--- +#### incomingHeader -#### `protected bool _complete` +```cpp +[http::Message](#classscy_1_1http_1_1Message) * incomingHeader() +``` +--- +#### outgoingHeader +```cpp +[http::Message](#classscy_1_1http_1_1Message) * outgoingHeader() +``` +--- -#### `protected bool _upgrade` +#### _socket +```cpp +[net::TCPSocket::Ptr](./doc/api-net.md#group__net_1ga2ac4375e7cda1d8bffa0b1750f84bc22) _socket +``` +--- +#### _adapter +```cpp +[net::SocketAdapter](./doc/api-net.md#classscy_1_1net_1_1SocketAdapter) * _adapter +``` -#### `protected `[`Error`](./doc/api-base.md#structscy_1_1Error)` _error` +--- +#### _request +```cpp +[Request](./doc/api-undefined.md#classscy_1_1http_1_1Request) _request +``` +--- +#### _response -#### `protected void init()` +```cpp +[Response](./doc/api-undefined.md#classscy_1_1http_1_1Response) _response +``` +--- +#### _error +```cpp +[scy::Error](./doc/api-base.md#structscy_1_1Error) _error +``` +--- -#### `protected void onURL(const std::string & value)` +#### _closed -Callbacks. +```cpp +bool _closed +``` +--- +#### _shouldSendHeader -#### `protected void onHeader(const std::string & name,const std::string & value)` +```cpp +bool _shouldSendHeader +``` +--- +#### setError +```cpp +virtual void setError(const [scy::Error](./doc/api-base.md#structscy_1_1Error) & err) +``` +Set the internal error. Note: Setting the error does not `[close()](#classscy_1_1http_1_1Connection_1a7c40813c43b7e09e0b52ec8f33378dc9)` the connection. -#### `protected void onHeadersEnd()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `err` | `const [scy::Error](./doc/api-base.md#structscy_1_1Error) &` | | +--- +#### onSocketConnect +```cpp +virtual void onSocketConnect([net::Socket](./doc/api-net.md#classscy_1_1net_1_1Socket) & socket) +``` +[net::SocketAdapter](./doc/api-net.md#classscy_1_1net_1_1SocketAdapter) interface -#### `protected void onBody(const char * buf,size_t len)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `socket` | `[net::Socket](./doc/api-net.md#classscy_1_1net_1_1Socket) &` | | +--- +#### onSocketRecv +```cpp +virtual void onSocketRecv([net::Socket](./doc/api-net.md#classscy_1_1net_1_1Socket) & socket, const [MutableBuffer](./doc/api-base.md#classscy_1_1MutableBuffer) & buffer, const [net::Address](./doc/api-net.md#classscy_1_1net_1_1Address) & peerAddress) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `socket` | `[net::Socket](./doc/api-net.md#classscy_1_1net_1_1Socket) &` | | +| `buffer` | `const [MutableBuffer](./doc/api-base.md#classscy_1_1MutableBuffer) &` | | +| `peerAddress` | `const [net::Address](./doc/api-net.md#classscy_1_1net_1_1Address) &` | | -#### `protected void onMessageEnd()` +--- +#### onSocketError +```cpp +virtual void onSocketError([net::Socket](./doc/api-net.md#classscy_1_1net_1_1Socket) & socket, const [scy::Error](./doc/api-base.md#structscy_1_1Error) & error) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `socket` | `[net::Socket](./doc/api-net.md#classscy_1_1net_1_1Socket) &` | | +| `error` | `const [scy::Error](./doc/api-base.md#structscy_1_1Error) &` | | +--- -#### `protected void onError(unsigned errnum,const std::string & message)` +#### onSocketClose +```cpp +virtual void onSocketClose([net::Socket](./doc/api-net.md#classscy_1_1net_1_1Socket) & socket) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `socket` | `[net::Socket](./doc/api-net.md#classscy_1_1net_1_1Socket) &` | | +--- +#### Ptr -# class `scy::http::ParserObserver` +```cpp +std::shared_ptr< [Connection](#classscy_1_1http_1_1Connection) > Ptr() +``` +## ConnectionAdapter +> **Extends:** `scy::http::ParserObserver`, `scy::net::SocketAdapter` +> **Defined in:** `connection.h` +Default HTTP socket adapter for reading and writing HTTP messages +### Members +| Name | Description | +|------|-------------| +| [`ConnectionAdapter`](#classscy_1_1http_1_1ConnectionAdapter_1a38b33fa02e3469a0f2ed662bfd5475ce) | | +| [`~ConnectionAdapter`](#classscy_1_1http_1_1ConnectionAdapter_1adf323289c48fe19dddc2bd2b9eab9329) | | +| [`send`](#classscy_1_1http_1_1ConnectionAdapter_1a616bb6dad71a6d043ed3bb5fdc578452) | Sends the given data buffer to the connected peer. Returns the number of bytes sent or -1 on error. No exception will be thrown. For TCP sockets the given peer address must match the connected peer address. | +| [`removeReceiver`](#classscy_1_1http_1_1ConnectionAdapter_1a41260efb10ce48a72c8f412b81d47fb0) | Remove the given receiver. | +| [`parser`](#classscy_1_1http_1_1ConnectionAdapter_1a1a4df38a8eb53687fbdf13177dd9cc1c) | | +| [`connection`](#classscy_1_1http_1_1ConnectionAdapter_1a19a7b1d36d33282658598c7f76c3e29c) | | +| [`_connection`](#classscy_1_1http_1_1ConnectionAdapter_1a65d1641ca2afc4b4bb93e841dd6b1658) | | +| [`_parser`](#classscy_1_1http_1_1ConnectionAdapter_1a02352190d724739060c896e0acc743c0) | | +| [`onSocketRecv`](#classscy_1_1http_1_1ConnectionAdapter_1af675696c310d06f65e3110c206b1991c) | SocketAdapter interface. | +| [`onParserHeader`](#classscy_1_1http_1_1ConnectionAdapter_1a611f889d794434f91f6b36c60a995bc5) | HTTP [Parser](#classscy_1_1http_1_1Parser) interface. | +| [`onParserHeadersEnd`](#classscy_1_1http_1_1ConnectionAdapter_1a0c0c55b0735b96facd54a715841f83d5) | | +| [`onParserChunk`](#classscy_1_1http_1_1ConnectionAdapter_1a5c1792adab1361782d3492b8701b80f2) | | +| [`onParserError`](#classscy_1_1http_1_1ConnectionAdapter_1ae7b5f7ab06604e51f8feee248df8aaa1) | | +| [`onParserEnd`](#classscy_1_1http_1_1ConnectionAdapter_1ac45acb1992c50b24b438f830f4e8a245) | | -## Summary +--- - Members | Descriptions ---------------------------------|--------------------------------------------- -`public void onParserHeader(const std::string & name,const std::string & value)` | -`public void onParserHeadersEnd(bool upgrade)` | -`public void onParserChunk(const char * data,size_t len)` | -`public void onParserEnd()` | -`public void onParserError(const `[`Error`](#structscy_1_1Error)` & err)` | +#### ConnectionAdapter -## Members +```cpp +ConnectionAdapter([Connection](#classscy_1_1http_1_1Connection) * connection, llhttp_type_t type) +``` -#### `public void onParserHeader(const std::string & name,const std::string & value)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `connection` | `[Connection](#classscy_1_1http_1_1Connection) *` | | +| `type` | `llhttp_type_t` | | +--- +#### ~ConnectionAdapter +```cpp +virtual ~ConnectionAdapter() +``` +--- -#### `public void onParserHeadersEnd(bool upgrade)` +#### send +```cpp +virtual ssize_t send(const char * data, size_t len, int flags) +``` +Sends the given data buffer to the connected peer. Returns the number of bytes sent or -1 on error. No exception will be thrown. For TCP sockets the given peer address must match the connected peer address. +| Parameter | Type | Description | +|-----------|------|-------------| +| `data` | `const char *` | | +| `len` | `size_t` | | +| `flags` | `int` | | +--- -#### `public void onParserChunk(const char * data,size_t len)` +#### removeReceiver +```cpp +virtual void removeReceiver([SocketAdapter](./doc/api-net.md#group__net_1ga35ca78ac04abbd6828af02fb1b65e6d1) * adapter) +``` +Remove the given receiver. +By default this function does nothing unless the given receiver matches the current receiver. +| Parameter | Type | Description | +|-----------|------|-------------| +| `adapter` | `[SocketAdapter](./doc/api-net.md#group__net_1ga35ca78ac04abbd6828af02fb1b65e6d1) *` | | -#### `public void onParserEnd()` +--- +#### parser +```cpp +[Parser](#classscy_1_1http_1_1Parser) & parser() +``` +--- +#### connection -#### `public void onParserError(const `[`Error`](#structscy_1_1Error)` & err)` +```cpp +[Connection](#classscy_1_1http_1_1Connection) * connection() +``` +--- +#### _connection +```cpp +[Connection](#classscy_1_1http_1_1Connection) * _connection +``` +--- -# class `scy::http::ProgressSignal` +#### _parser +```cpp +[Parser](#classscy_1_1http_1_1Parser) _parser ``` -class scy::http::ProgressSignal - : public scy::Signal< void(const double &)> -``` +--- +#### onSocketRecv +```cpp +virtual void onSocketRecv([net::Socket](./doc/api-net.md#classscy_1_1net_1_1Socket) & socket, const [MutableBuffer](./doc/api-base.md#classscy_1_1MutableBuffer) & buffer, const [net::Address](./doc/api-net.md#classscy_1_1net_1_1Address) & peerAddress) +``` +SocketAdapter interface. -## Summary +| Parameter | Type | Description | +|-----------|------|-------------| +| `socket` | `[net::Socket](./doc/api-net.md#classscy_1_1net_1_1Socket) &` | | +| `buffer` | `const [MutableBuffer](./doc/api-base.md#classscy_1_1MutableBuffer) &` | | +| `peerAddress` | `const [net::Address](./doc/api-net.md#classscy_1_1net_1_1Address) &` | | - Members | Descriptions ---------------------------------|--------------------------------------------- -`public void * sender` | -`public uint64_t current` | -`public uint64_t total` | -`public inline ProgressSignal()` | -`public inline double progress() const` | -`public inline void update(int nread)` | +--- -## Members +#### onParserHeader -#### `public void * sender` +```cpp +virtual void onParserHeader(const std::string & name, const std::string & value) +``` +HTTP [Parser](#classscy_1_1http_1_1Parser) interface. +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | +| `value` | `const std::string &` | | +--- +#### onParserHeadersEnd -#### `public uint64_t current` +```cpp +virtual void onParserHeadersEnd(bool upgrade) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `upgrade` | `bool` | | +--- +#### onParserChunk +```cpp +virtual void onParserChunk(const char * buf, size_t len) +``` -#### `public uint64_t total` +| Parameter | Type | Description | +|-----------|------|-------------| +| `buf` | `const char *` | | +| `len` | `size_t` | | +--- +#### onParserError +```cpp +virtual void onParserError(const [scy::Error](./doc/api-base.md#structscy_1_1Error) & err) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `err` | `const [scy::Error](./doc/api-base.md#structscy_1_1Error) &` | | -#### `public inline ProgressSignal()` +--- +#### onParserEnd +```cpp +virtual void onParserEnd() +``` +## ProgressSignal +> **Extends:** `scy::Signal< void(const double &)>` +> **Defined in:** `connection.h` -#### `public inline double progress() const` +HTTP progress signal for upload and download progress notifications. +### Members +| Name | Description | +|------|-------------| +| [`sender`](#classscy_1_1http_1_1ProgressSignal_1aac7fe5b5998e92c2ebfc4be61490f7ba) | | +| [`current`](#classscy_1_1http_1_1ProgressSignal_1a8b1acf12889f7fe46ffac81a07802e7a) | | +| [`total`](#classscy_1_1http_1_1ProgressSignal_1abae987c641001e503f4df3e4901f74f3) | | +| [`ProgressSignal`](#classscy_1_1http_1_1ProgressSignal_1a096bf69d4c5dfdb71eb5e16c84b14d91) | | +| [`progress`](#classscy_1_1http_1_1ProgressSignal_1a312d627b4aa2afa7922d352c21803c04) | | +| [`update`](#classscy_1_1http_1_1ProgressSignal_1ac3373e381f6b191a3e88d7b449ab7b94) | | +--- +#### sender -#### `public inline void update(int nread)` +```cpp +void * sender +``` +--- +#### current +```cpp +uint64_t current +``` +--- -# class `scy::http::Request` +#### total +```cpp +uint64_t total ``` -class scy::http::Request - : public scy::http::Message -``` +--- +#### ProgressSignal -This class encapsulates an HTTP request message. +```cpp +inline ProgressSignal() +``` -In addition to the properties common to all HTTP messages, a HTTP request has a method (e.g. GET, HEAD, POST, etc.) and a request URI. +--- -## Summary +#### progress - Members | Descriptions ---------------------------------|--------------------------------------------- -`public Request()` | Creates a GET / HTTP/1.1 HTTP request. -`public Request(const std::string & version)` | -`public Request(const std::string & method,const std::string & uri)` | Creates a HTTP/1.0 request with the given method and URI. -`public Request(const std::string & method,const std::string & uri,const std::string & version)` | Creates a HTTP request with the given method, URI and version. -`public virtual ~Request()` | Destroys the [Request](./doc/api-http.md#classscy_1_1http_1_1Request). -`public void setMethod(const std::string & method)` | Sets the method. -`public const std::string & getMethod() const` | Returns the method. -`public void setURI(const std::string & uri)` | Sets the request URI. -`public const std::string & getURI() const` | Returns the request URI. -`public void setHost(const std::string & host)` | Sets the value of the Host header field. -`public void setHost(const std::string & host,uint16_t port)` | -`public const std::string & getHost() const` | -`public void setCookies(const `[`NVCollection`](#classscy_1_1NVCollection)` & cookies)` | -`public void getCookies(`[`NVCollection`](#classscy_1_1NVCollection)` & cookies) const` | -`public void getURIParameters(`[`NVCollection`](#classscy_1_1NVCollection)` & params) const` | Returns the request URI parameters. -`public bool hasCredentials() const` | -`public void getCredentials(std::string & scheme,std::string & authInfo) const` | -`public void setCredentials(const std::string & scheme,const std::string & authInfo)` | -`public bool hasProxyCredentials() const` | -`public void getProxyCredentials(std::string & scheme,std::string & authInfo) const` | -`public void setProxyCredentials(const std::string & scheme,const std::string & authInfo)` | Sets the proxy authentication scheme and information for this request. -`public virtual void write(std::ostream & ostr) const` | Writes the HTTP request to the given output stream. -`public virtual void write(std::string & str) const` | Writes the HTTP request to the given output string. -`protected void getCredentials(const std::string & header,std::string & scheme,std::string & authInfo) const` | -`protected void setCredentials(const std::string & header,const std::string & scheme,const std::string & authInfo)` | +```cpp +inline double progress() const +``` -## Members +--- -#### `public Request()` +#### update -Creates a GET / HTTP/1.1 HTTP request. +```cpp +inline void update(int nread) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `nread` | `int` | | +## ConnectionStream -#### `public Request(const std::string & version)` +> **Extends:** `scy::net::SocketAdapter` +> **Defined in:** `connection.h` +Packet stream wrapper for a HTTP connection. +### Members -Creates a GET / HTTP/1.x request with the given version (HTTP/1.0 or HTTP/1.1). +| Name | Description | +|------|-------------| +| [`Outgoing`](#classscy_1_1http_1_1ConnectionStream_1adc72f42dbbaddafd85a2d69cc80cecaf) | The Outgoing stream is responsible for packetizing raw application data into the agreed upon HTTP format and sending it to the peer. | +| [`Incoming`](#classscy_1_1http_1_1ConnectionStream_1a4e3af4a978d6dd5ec04653634226dcb5) | The Incoming stream emits incoming HTTP packets for processing by the application. | +| [`IncomingProgress`](#classscy_1_1http_1_1ConnectionStream_1a5b613af4b34bbecd05d8c059a12b032d) | Fired on download progress. | +| [`OutgoingProgress`](#classscy_1_1http_1_1ConnectionStream_1a7aa44deb62021bc3e2aa65c295f9c843) | Fired on upload progress. | +| [`ConnectionStream`](#classscy_1_1http_1_1ConnectionStream_1a107853c5a7d4f01a61caaae580c9ef7e) | | +| [`~ConnectionStream`](#classscy_1_1http_1_1ConnectionStream_1aede98da6f993e7e012fd07f4de282c6a) | | +| [`send`](#classscy_1_1http_1_1ConnectionStream_1aa2f2b6fecfbdead658d483c5870bf599) | Send data via the Outgoing stream. | +| [`connection`](#classscy_1_1http_1_1ConnectionStream_1a8e5f5ce43a3b7a6e642e4ef764cd5e5c) | Return a reference to the underlying connection. | +| [`_connection`](#classscy_1_1http_1_1ConnectionStream_1a49879d5fc6bf781f090fe04e48170030) | | +| [`onSocketRecv`](#classscy_1_1http_1_1ConnectionStream_1ace624b22e27976e49e405f61772ffc6d) | | -#### `public Request(const std::string & method,const std::string & uri)` +--- -Creates a HTTP/1.0 request with the given method and URI. +#### Outgoing +```cpp +[PacketStream](./doc/api-base.md#classscy_1_1PacketStream) Outgoing +``` +The Outgoing stream is responsible for packetizing raw application data into the agreed upon HTTP format and sending it to the peer. -#### `public Request(const std::string & method,const std::string & uri,const std::string & version)` +--- -Creates a HTTP request with the given method, URI and version. +#### Incoming +```cpp +[PacketStream](./doc/api-base.md#classscy_1_1PacketStream) Incoming +``` +The Incoming stream emits incoming HTTP packets for processing by the application. -#### `public virtual ~Request()` +This is useful for example when writing incoming data to a file. -Destroys the [Request](#classscy_1_1http_1_1Request). +--- +#### IncomingProgress +```cpp +[ProgressSignal](#classscy_1_1http_1_1ProgressSignal) IncomingProgress +``` -#### `public void setMethod(const std::string & method)` +Fired on download progress. -Sets the method. +--- +#### OutgoingProgress +```cpp +[ProgressSignal](#classscy_1_1http_1_1ProgressSignal) OutgoingProgress +``` -#### `public const std::string & getMethod() const` +Fired on upload progress. -Returns the method. +--- +#### ConnectionStream +```cpp +ConnectionStream([Connection::Ptr](#classscy_1_1http_1_1Connection_1a2143146501601ea9816068f83731e1fb) connection) +``` -#### `public void setURI(const std::string & uri)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `connection` | `[Connection::Ptr](#classscy_1_1http_1_1Connection_1a2143146501601ea9816068f83731e1fb)` | | -Sets the request URI. +--- +#### ~ConnectionStream +```cpp +virtual ~ConnectionStream() +``` -#### `public const std::string & getURI() const` +--- -Returns the request URI. +#### send +```cpp +virtual ssize_t send(const char * data, size_t len, int flags) +``` +Send data via the Outgoing stream. -#### `public void setHost(const std::string & host)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `data` | `const char *` | | +| `len` | `size_t` | | +| `flags` | `int` | | -Sets the value of the Host header field. +--- +#### connection +```cpp +[Connection::Ptr](#classscy_1_1http_1_1Connection_1a2143146501601ea9816068f83731e1fb) connection() +``` -#### `public void setHost(const std::string & host,uint16_t port)` +Return a reference to the underlying connection. +--- +#### _connection -Sets the value of the Host header field. +```cpp +[Connection::Ptr](#classscy_1_1http_1_1Connection_1a2143146501601ea9816068f83731e1fb) _connection +``` -If the given port number is a non-standard port number (other than 80 or 443), it is included in the Host header field. +--- -#### `public const std::string & getHost() const` +#### onSocketRecv +```cpp +virtual void onSocketRecv([net::Socket](./doc/api-net.md#classscy_1_1net_1_1Socket) & socket, const [MutableBuffer](./doc/api-base.md#classscy_1_1MutableBuffer) & buffer, const [net::Address](./doc/api-net.md#classscy_1_1net_1_1Address) & peerAddress) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `socket` | `[net::Socket](./doc/api-net.md#classscy_1_1net_1_1Socket) &` | | +| `buffer` | `const [MutableBuffer](./doc/api-base.md#classscy_1_1MutableBuffer) &` | | +| `peerAddress` | `const [net::Address](./doc/api-net.md#classscy_1_1net_1_1Address) &` | | -Returns the value of the Host header field. +## Cookie -Throws a NotFoundException if the request does not have a Host header field. +> **Defined in:** `cookie.h` -#### `public void setCookies(const `[`NVCollection`](#classscy_1_1NVCollection)` & cookies)` +This class represents a HTTP [Cookie](#classscy_1_1http_1_1Cookie). +A cookie is a small amount of information sent by a Web server to a Web browser, saved by the browser, and later sent back to the server. A cookie's value can uniquely identify a client, so cookies are commonly used for session management. +A cookie has a name, a single value, and optional attributes such as a comment, path and domain qualifiers, a maximum age, and a version number. -Adds a [Cookie](#classscy_1_1http_1_1Cookie) header with the names and values from cookies. +This class supports both the Version 0 (by Netscape) and Version 1 (by RFC 2109) cookie specifications. By default, cookies are created using Version 0 to ensure the best interoperability. -#### `public void getCookies(`[`NVCollection`](#classscy_1_1NVCollection)` & cookies) const` +### Members + +| Name | Description | +|------|-------------| +| [`Cookie`](#group__http_1ga7fe027bf50ad3e074e3394cee3da9f08) | Creates an empty [Cookie](#classscy_1_1http_1_1Cookie). | +| [`Cookie`](#group__http_1ga027e2a2f4f74f8a9908e4558c7749912) | Creates a cookie with the given name. The cookie never expires. | +| [`Cookie`](#group__http_1ga691e1a1ad74b1dcb68045335491965b5) | Creates a cookie from the given [NVCollection](./doc/api-base.md#classscy_1_1NVCollection). | +| [`Cookie`](#group__http_1gaa2944b0e82cf14e9001cb33706aa1197) | Creates a cookie with the given name and value. The cookie never expires. | +| [`Cookie`](#group__http_1ga12f322ffcbc6b333f022ea1c646a89c9) | Creates the [Cookie](#classscy_1_1http_1_1Cookie) by copying another one. | +| [`~Cookie`](#group__http_1gaa1237673ec2466ff08022b689b3149ab) | Destroys the [Cookie](#classscy_1_1http_1_1Cookie). | +| [`operator=`](#group__http_1gaf79ee72cc2c039956c3b383b51ba67f6) | Assigns a cookie. | +| [`setVersion`](#group__http_1ga0503c149157a6c1f7d3c2d4232e91eff) | Sets the version of the cookie. | +| [`setName`](#group__http_1gad8867c1d8c54497acc3b251b9086f73d) | Sets the name of the cookie. | +| [`setValue`](#group__http_1gae819d97814ae5c7b225e5678215a8c93) | Sets the value of the cookie. | +| [`setComment`](#group__http_1ga2ab87e18725de24a714047755a571624) | Sets the comment for the cookie. | +| [`setDomain`](#group__http_1gada05d2d453ce8bd5ce9b98fe78344af5) | Sets the domain for the cookie. | +| [`setPath`](#group__http_1gac36b773a25ed2a55dfd327218d42d2d1) | Sets the path for the cookie. | +| [`setSecure`](#group__http_1ga6f7cc92be1f67f178283bdf898f93cee) | Sets the value of the secure flag for the cookie. | +| [`setMaxAge`](#group__http_1ga9cbe3e7dcb2b1ddfd5b5ef015dc3d04d) | Sets the maximum age in seconds for the cookie. | +| [`setHttpOnly`](#group__http_1gabe8656c52f52eaf3efe62df8144bfe72) | Sets the HttpOnly flag for the cookie. | +| [`toString`](#group__http_1ga687bf0e8583f850b75df212a4daf25a2) | Returns a std::string representation of the cookie, suitable for use in a Set-Cookie header. | +| [`escape`](#group__http_1ga5dc9fb3d11c40a91b69c562135a4a5f8) | Escapes the given std::string by replacing all non-alphanumeric characters with escape sequences in the form xx, where xx is the hexadecimal character code. | +| [`unescape`](#group__http_1gaae63bf7998ccc36d20ed8dbea8da6961) | Unescapes the given std::string by replacing all escape sequences in the form xx with the respective characters. | +| [`getVersion`](#classscy_1_1http_1_1Cookie_1a6bba92249ab2db70324e8563e944de61) | Returns the version of the cookie, which is either 0 or 1. | +| [`getName`](#classscy_1_1http_1_1Cookie_1a19a1d78ead5a8f7bd2e857dcaeb01afe) | Returns the name of the cookie. | +| [`getValue`](#classscy_1_1http_1_1Cookie_1a2ce5ad4ace4ef72042b5d66ba1073e52) | Returns the value of the cookie. | +| [`getComment`](#classscy_1_1http_1_1Cookie_1ada9b4df4051c57243a739984aa91941e) | Returns the comment for the cookie. | +| [`getDomain`](#classscy_1_1http_1_1Cookie_1a0b19831c3a5651e2b168445dbb324d09) | Returns the domain for the cookie. | +| [`getPath`](#classscy_1_1http_1_1Cookie_1a15927613e58d7b0020941fb0f26560ad) | Returns the path for the cookie. | +| [`getSecure`](#classscy_1_1http_1_1Cookie_1af1af920b2dc5cc4d2e12d12ab7221b2f) | Returns the value of the secure flag for the cookie. | +| [`getMaxAge`](#classscy_1_1http_1_1Cookie_1acf9466fafc045014b7a8645b9e02d0ed) | Returns the maximum age in seconds for the cookie. | +| [`getHttpOnly`](#classscy_1_1http_1_1Cookie_1a1ed3b24d77125d5162c70c744912005c) | Returns true if the cookie's HttpOnly flag is set. | +| [`_version`](#classscy_1_1http_1_1Cookie_1a61ce322d16cd4c14ec21d1ea06a2cb56) | | +| [`_name`](#classscy_1_1http_1_1Cookie_1a728a3510c99e41f6cff7ce31b3f5283c) | | +| [`_value`](#classscy_1_1http_1_1Cookie_1a4d80ecfe24a6851659a012cc453e2ee5) | | +| [`_comment`](#classscy_1_1http_1_1Cookie_1a572f89925a594ecbc5376ea49c633a07) | | +| [`_domain`](#classscy_1_1http_1_1Cookie_1a885055b5581eefb8aef0d661f69093a2) | | +| [`_path`](#classscy_1_1http_1_1Cookie_1add987dcc3bb598b21d90b5e5e5018e77) | | +| [`_secure`](#classscy_1_1http_1_1Cookie_1a90e66610d5aee9f2d6fc79dedbcd60c9) | | +| [`_maxAge`](#classscy_1_1http_1_1Cookie_1a42224de596cc7c463e3ed2ca48c50376) | | +| [`_httpOnly`](#classscy_1_1http_1_1Cookie_1adc9af08a4ec098de43dd4264a3c028f7) | | + +--- + +#### Cookie + +```cpp +Cookie() +``` +Creates an empty [Cookie](#classscy_1_1http_1_1Cookie). +--- -Fills cookies with the cookies extracted from the [Cookie](#classscy_1_1http_1_1Cookie) headers in the request. +#### Cookie -#### `public void getURIParameters(`[`NVCollection`](#classscy_1_1NVCollection)` & params) const` +```cpp +explicit Cookie(const std::string & name) +``` -Returns the request URI parameters. +Creates a cookie with the given name. The cookie never expires. +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | +--- -#### `public bool hasCredentials() const` +#### Cookie +```cpp +explicit Cookie(const NVCollection & nvc) +``` +Creates a cookie from the given [NVCollection](./doc/api-base.md#classscy_1_1NVCollection). -Returns true if the request contains authentication information in the form of an Authorization header. +| Parameter | Type | Description | +|-----------|------|-------------| +| `nvc` | `const NVCollection &` | | -#### `public void getCredentials(std::string & scheme,std::string & authInfo) const` +--- +#### Cookie +```cpp +Cookie(const std::string & name, const std::string & value) +``` -Returns the authentication scheme and additional authentication information contained in this request. +Creates a cookie with the given name and value. The cookie never expires. -Throws a std::exception if no authentication information is contained in the request. +Note: If value contains whitespace or non-alphanumeric characters, the value should be escaped by calling [escape()](#group__http_1ga5dc9fb3d11c40a91b69c562135a4a5f8) before passing it to the constructor. -#### `public void setCredentials(const std::string & scheme,const std::string & authInfo)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | +| `value` | `const std::string &` | | +--- +#### Cookie -Sets the authentication scheme and information for this request. +```cpp +Cookie(const Cookie & cookie) +``` -#### `public bool hasProxyCredentials() const` +Creates the [Cookie](#classscy_1_1http_1_1Cookie) by copying another one. +| Parameter | Type | Description | +|-----------|------|-------------| +| `cookie` | `const Cookie &` | | +--- -Returns true if the request contains proxy authentication information in the form of an Proxy-Authorization header. +#### ~Cookie -#### `public void getProxyCredentials(std::string & scheme,std::string & authInfo) const` +```cpp +~Cookie() +``` +Destroys the [Cookie](#classscy_1_1http_1_1Cookie). +--- -Returns the proxy authentication scheme and additional proxy authentication information contained in this request. +#### operator= -Throws a std::exception if no proxy authentication information is contained in the request. +```cpp +Cookie & operator=(const Cookie & cookie) +``` -#### `public void setProxyCredentials(const std::string & scheme,const std::string & authInfo)` +Assigns a cookie. -Sets the proxy authentication scheme and information for this request. +| Parameter | Type | Description | +|-----------|------|-------------| +| `cookie` | `const Cookie &` | | +--- +#### setVersion -#### `public virtual void write(std::ostream & ostr) const` +```cpp +void setVersion(int version) +``` -Writes the HTTP request to the given output stream. +Sets the version of the cookie. +Version must be either 0 (denoting a Netscape cookie) or 1 (denoting a RFC 2109 cookie). +| Parameter | Type | Description | +|-----------|------|-------------| +| `version` | `int` | | -#### `public virtual void write(std::string & str) const` +--- -Writes the HTTP request to the given output string. +#### setName +```cpp +void setName(const std::string & name) +``` +Sets the name of the cookie. -#### `protected void getCredentials(const std::string & header,std::string & scheme,std::string & authInfo) const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | +--- +#### setValue -Returns the authentication scheme and additional authentication information contained in the given header of request. +```cpp +void setValue(const std::string & value) +``` -Throws a NotAuthenticatedException if no authentication information is contained in the request. +Sets the value of the cookie. -#### `protected void setCredentials(const std::string & header,const std::string & scheme,const std::string & authInfo)` +According to the cookie specification, the size of the value should not exceed 4 Kbytes. +Note: If value contains whitespace or non-alphanumeric characters, the value should be escaped by calling [escape()](#group__http_1ga5dc9fb3d11c40a91b69c562135a4a5f8) prior to passing it to [setName()](#group__http_1gad8867c1d8c54497acc3b251b9086f73d). +| Parameter | Type | Description | +|-----------|------|-------------| +| `value` | `const std::string &` | | -Writes the authentication scheme and information for this request to the given header. +--- -# class `scy::http::Response` +#### setComment +```cpp +void setComment(const std::string & comment) ``` -class scy::http::Response - : public scy::http::Message -``` -This class encapsulates an HTTP response message. +Sets the comment for the cookie. + +Comments are only supported for version 1 cookies. + +| Parameter | Type | Description | +|-----------|------|-------------| +| `comment` | `const std::string &` | | +--- +#### setDomain -## Summary +```cpp +void setDomain(const std::string & domain) +``` - Members | Descriptions ---------------------------------|--------------------------------------------- -`public Response()` | typedef std::shared_ptr Ptr; -`public Response(`[`StatusCode`](#group__http_1ga557c5bc8f0990c42f31cbaca9b756f2b)` status,const std::string & reason)` | Creates the [Response](./doc/api-http.md#classscy_1_1http_1_1Response) with the given status and reason phrase. -`public Response(const std::string & version,`[`StatusCode`](#group__http_1ga557c5bc8f0990c42f31cbaca9b756f2b)` status,const std::string & reason)` | Creates the [Response](./doc/api-http.md#classscy_1_1http_1_1Response) with the given version, status and reason phrase. -`public Response(`[`StatusCode`](#group__http_1ga557c5bc8f0990c42f31cbaca9b756f2b)` status)` | -`public Response(const std::string & version,`[`StatusCode`](#group__http_1ga557c5bc8f0990c42f31cbaca9b756f2b)` status)` | -`public virtual ~Response()` | Destroys the [Response](./doc/api-http.md#classscy_1_1http_1_1Response). -`public void setStatus(`[`StatusCode`](#group__http_1ga557c5bc8f0990c42f31cbaca9b756f2b)` status)` | -`public `[`StatusCode`](#group__http_1ga557c5bc8f0990c42f31cbaca9b756f2b)` getStatus() const` | Returns the HTTP status code. -`public void setReason(const std::string & reason)` | Sets the HTTP reason phrase. -`public const std::string & getReason() const` | Returns the HTTP reason phrase. -`public void setStatusAndReason(`[`StatusCode`](#group__http_1ga557c5bc8f0990c42f31cbaca9b756f2b)` status,const std::string & reason)` | Sets the HTTP status code and reason phrase. -`public void setDate(const `[`Timestamp`](#classscy_1_1Timestamp)` & dateTime)` | Sets the Date header to the given date/time value. -`public `[`Timestamp`](#classscy_1_1Timestamp)` getDate() const` | Returns the value of the Date header. -`public void addCookie(const `[`Cookie`](#classscy_1_1http_1_1Cookie)` & cookie)` | -`public void getCookies(std::vector< `[`Cookie`](#classscy_1_1http_1_1Cookie)` > & cookies) const` | -`public virtual void write(std::ostream & ostr) const` | Writes the HTTP response headers to the given output stream. -`public virtual void write(std::string & str) const` | Writes the HTTP response headers to the given output string. -`public virtual bool success() const` | Returns true if the HTTP response code was successful (>= 400). +Sets the domain for the cookie. -## Members +| Parameter | Type | Description | +|-----------|------|-------------| +| `domain` | `const std::string &` | | -#### `public Response()` +--- -typedef std::shared_ptr Ptr; +#### setPath -Creates the [Response](#classscy_1_1http_1_1Response) with OK status. +```cpp +void setPath(const std::string & path) +``` -#### `public Response(`[`StatusCode`](#group__http_1ga557c5bc8f0990c42f31cbaca9b756f2b)` status,const std::string & reason)` +Sets the path for the cookie. -Creates the [Response](#classscy_1_1http_1_1Response) with the given status and reason phrase. +| Parameter | Type | Description | +|-----------|------|-------------| +| `path` | `const std::string &` | | +--- +#### setSecure -#### `public Response(const std::string & version,`[`StatusCode`](#group__http_1ga557c5bc8f0990c42f31cbaca9b756f2b)` status,const std::string & reason)` +```cpp +void setSecure(bool secure) +``` -Creates the [Response](#classscy_1_1http_1_1Response) with the given version, status and reason phrase. +Sets the value of the secure flag for the cookie. +| Parameter | Type | Description | +|-----------|------|-------------| +| `secure` | `bool` | | +--- -#### `public Response(`[`StatusCode`](#group__http_1ga557c5bc8f0990c42f31cbaca9b756f2b)` status)` +#### setMaxAge +```cpp +void setMaxAge(int maxAge) +``` +Sets the maximum age in seconds for the cookie. -Creates the [Response](#classscy_1_1http_1_1Response) with the given status an an appropriate reason phrase. +A value of -1 causes the cookie to never expire on the client. -#### `public Response(const std::string & version,`[`StatusCode`](#group__http_1ga557c5bc8f0990c42f31cbaca9b756f2b)` status)` +A value of 0 deletes the cookie on the client. +| Parameter | Type | Description | +|-----------|------|-------------| +| `maxAge` | `int` | | +--- -Creates the [Response](#classscy_1_1http_1_1Response) with the given version, status an an appropriate reason phrase. +#### setHttpOnly -#### `public virtual ~Response()` +```cpp +void setHttpOnly(bool flag) +``` -Destroys the [Response](#classscy_1_1http_1_1Response). +Sets the HttpOnly flag for the cookie. +| Parameter | Type | Description | +|-----------|------|-------------| +| `flag` | `bool` | | +--- -#### `public void setStatus(`[`StatusCode`](#group__http_1ga557c5bc8f0990c42f31cbaca9b756f2b)` status)` +#### toString +```cpp +std::string toString() const +``` +Returns a std::string representation of the cookie, suitable for use in a Set-Cookie header. -Sets the HTTP status code. +--- -The reason phrase is set according to the status code. +#### escape -#### `public `[`StatusCode`](#group__http_1ga557c5bc8f0990c42f31cbaca9b756f2b)` getStatus() const` +```cpp +static std::string escape(const std::string & str) +``` -Returns the HTTP status code. +Escapes the given std::string by replacing all non-alphanumeric characters with escape sequences in the form xx, where xx is the hexadecimal character code. +| Parameter | Type | Description | +|-----------|------|-------------| +| `str` | `const std::string &` | | +--- -#### `public void setReason(const std::string & reason)` +#### unescape -Sets the HTTP reason phrase. +```cpp +static std::string unescape(const std::string & str) +``` +Unescapes the given std::string by replacing all escape sequences in the form xx with the respective characters. +| Parameter | Type | Description | +|-----------|------|-------------| +| `str` | `const std::string &` | | -#### `public const std::string & getReason() const` +--- -Returns the HTTP reason phrase. +#### getVersion +```cpp +inline int getVersion() const +``` +Returns the version of the cookie, which is either 0 or 1. -#### `public void setStatusAndReason(`[`StatusCode`](#group__http_1ga557c5bc8f0990c42f31cbaca9b756f2b)` status,const std::string & reason)` +--- -Sets the HTTP status code and reason phrase. +#### getName +```cpp +inline const std::string & getName() const +``` +Returns the name of the cookie. -#### `public void setDate(const `[`Timestamp`](#classscy_1_1Timestamp)` & dateTime)` +--- -Sets the Date header to the given date/time value. +#### getValue +```cpp +inline const std::string & getValue() const +``` +Returns the value of the cookie. -#### `public `[`Timestamp`](#classscy_1_1Timestamp)` getDate() const` +--- -Returns the value of the Date header. +#### getComment +```cpp +inline const std::string & getComment() const +``` +Returns the comment for the cookie. -#### `public void addCookie(const `[`Cookie`](#classscy_1_1http_1_1Cookie)` & cookie)` +--- +#### getDomain +```cpp +inline const std::string & getDomain() const +``` -Adds the cookie to the response by adding a Set-Cookie header. +Returns the domain for the cookie. -#### `public void getCookies(std::vector< `[`Cookie`](#classscy_1_1http_1_1Cookie)` > & cookies) const` +--- +#### getPath +```cpp +inline const std::string & getPath() const +``` -Returns a vector with all the cookies set in the response header. +Returns the path for the cookie. -May throw an exception in case of a malformed Set-Cookie header. +--- -#### `public virtual void write(std::ostream & ostr) const` +#### getSecure -Writes the HTTP response headers to the given output stream. +```cpp +inline bool getSecure() const +``` +Returns the value of the secure flag for the cookie. +--- -#### `public virtual void write(std::string & str) const` +#### getMaxAge -Writes the HTTP response headers to the given output string. +```cpp +inline int getMaxAge() const +``` +Returns the maximum age in seconds for the cookie. +--- -#### `public virtual bool success() const` +#### getHttpOnly -Returns true if the HTTP response code was successful (>= 400). +```cpp +inline bool getHttpOnly() const +``` +Returns true if the cookie's HttpOnly flag is set. +--- -# class `scy::http::Server` +#### _version +```cpp +int _version ``` -class scy::http::Server - : public scy::net::SocketAdapter -``` +--- +#### _name -HTTP server implementation. - -This HTTP server is not strictly standards compliant. It was created to be a fast (nocopy where possible) solution for streaming media to web browsers. +```cpp +std::string _name +``` -## Summary +--- - Members | Descriptions ---------------------------------|--------------------------------------------- -`public `[`Signal`](#classscy_1_1Signal)< void(ServerConnection::Ptr)`> Connection` | -`public `[`NullSignal`](./doc/api-base.md#classscy_1_1Signal)` Shutdown` | Signals when the server is shutting down. -`public Server(const std::string & host,short port,net::TCPSocket::Ptr socket,`[`ServerConnectionFactory`](#classscy_1_1http_1_1ServerConnectionFactory)` * factory)` | -`public Server(const `[`net::Address`](#classscy_1_1net_1_1Address)` & address,net::TCPSocket::Ptr socket,`[`ServerConnectionFactory`](#classscy_1_1http_1_1ServerConnectionFactory)` * factory)` | -`public virtual ~Server()` | -`public void start()` | Start the HTTP server. -`public void shutdown()` | Shutdown the HTTP server. -`public `[`net::Address`](#classscy_1_1net_1_1Address)` & address()` | Return the server bind address. -`protected `[`net::Address`](./doc/api-net.md#classscy_1_1net_1_1Address)` _address` | -`protected net::TCPSocket::Ptr _socket` | -`protected `[`Timer`](./doc/api-base.md#classscy_1_1Timer)` _timer` | -`protected `[`ServerConnectionFactory`](./doc/api-http.md#classscy_1_1http_1_1ServerConnectionFactory)` * _factory` | -`protected std::vector< ServerConnection::Ptr > _connections` | -`protected `[`ServerResponder`](#classscy_1_1http_1_1ServerResponder)` * createResponder(`[`ServerConnection`](#classscy_1_1http_1_1ServerConnection)` & conn)` | -`protected void onClientSocketAccept(const net::TCPSocket::Ptr & socket)` | -`protected void onConnectionReady(`[`ServerConnection`](#classscy_1_1http_1_1ServerConnection)` & conn)` | -`protected void onConnectionClose(`[`ServerConnection`](#classscy_1_1http_1_1ServerConnection)` & conn)` | -`protected virtual void onSocketClose(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket)` | -`protected void onTimer()` | +#### _value -## Members +```cpp +std::string _value +``` -#### `public `[`Signal`](#classscy_1_1Signal)< void(ServerConnection::Ptr)`> Connection` +--- +#### _comment +```cpp +std::string _comment +``` -Signals when a new connection has been created. A reference to the new connection object is provided. +--- -#### `public `[`NullSignal`](./doc/api-base.md#classscy_1_1Signal)` Shutdown` +#### _domain -Signals when the server is shutting down. +```cpp +std::string _domain +``` +--- +#### _path -#### `public Server(const std::string & host,short port,net::TCPSocket::Ptr socket,`[`ServerConnectionFactory`](#classscy_1_1http_1_1ServerConnectionFactory)` * factory)` +```cpp +std::string _path +``` +--- +#### _secure +```cpp +bool _secure +``` +--- -#### `public Server(const `[`net::Address`](#classscy_1_1net_1_1Address)` & address,net::TCPSocket::Ptr socket,`[`ServerConnectionFactory`](#classscy_1_1http_1_1ServerConnectionFactory)` * factory)` +#### _maxAge +```cpp +int _maxAge +``` +--- +#### _httpOnly +```cpp +bool _httpOnly +``` -#### `public virtual ~Server()` +## FormWriter +> **Extends:** `scy::NVCollection`, `scy::PacketStreamAdapter`, `scy::basic::Startable` +> **Defined in:** `form.h` +[FormWriter](#classscy_1_1http_1_1FormWriter) is a HTTP client connection adapter for writing HTML forms. +This class runs in its own thread so as not to block the event loop while uploading big files. Class members are not synchronized hence they should not be accessed while the form is sending, not that there would be any reason to do so. +### Members + +| Name | Description | +|------|-------------| +| [`emitter`](#classscy_1_1http_1_1FormWriter_1ab2466a31197f14952d9591b1d5c4a1ad) | The outgoing packet emitter. | +| [`~FormWriter`](#classscy_1_1http_1_1FormWriter_1ab41f26d58a5eceed4d3dca809b2fffd6) | Destroys the [FormWriter](#classscy_1_1http_1_1FormWriter). | +| [`addPart`](#classscy_1_1http_1_1FormWriter_1aa9e9d1c89a622c3411d899249e66c95f) | Adds an part/attachment (file upload) to the form. | +| [`start`](#classscy_1_1http_1_1FormWriter_1aa5f7896cd6fdc03332ca24ce61a21cc9) | Starts the sending thread. | +| [`stop`](#classscy_1_1http_1_1FormWriter_1ada956df3e4d829e6f8089bcb8131f4b6) | Stops the sending thread. | +| [`complete`](#classscy_1_1http_1_1FormWriter_1ac09b25eb5461de108430eec710d68675) | Returns true if the request is complete. | +| [`cancelled`](#classscy_1_1http_1_1FormWriter_1a9f19254603100e55352b7550d76d5c73) | Returns true if the request is cancelled. | +| [`prepareSubmit`](#classscy_1_1http_1_1FormWriter_1aa5769359cbcdf8addf6da8dc3f45d283) | Prepares the outgoing HTTP request object for submitting the form. | +| [`calculateMultipartContentLength`](#classscy_1_1http_1_1FormWriter_1a98bac9fd0d6a81bfda140833d5c8856d) | Processes the entire stream and calculates the content length. Not used for chunked encoding. | +| [`writeUrl`](#classscy_1_1http_1_1FormWriter_1ae991f982b59ea236144c4afc93a1f212) | Writes "application/x-www-form-urlencoded" encoded data to the client connection. | +| [`writeMultipartChunk`](#classscy_1_1http_1_1FormWriter_1a52a768c3b4f38dd4d626f9d3f0e69c9f) | Writes the next multipart "multipart/form-data" encoded to the client connection. This method is non-blocking, and is suitable for use with the event loop. | +| [`writeAsync`](#classscy_1_1http_1_1FormWriter_1a316ac15771f371e398cd9897cf983675) | Called asynchronously by the [Runner](./doc/api-base.md#classscy_1_1Runner) to write the next message chunk. | +| [`setEncoding`](#classscy_1_1http_1_1FormWriter_1aff90cfef483b9111d1ecd987744e0371) | Sets the encoding used for posting the form. | +| [`encoding`](#classscy_1_1http_1_1FormWriter_1a3d3d1bd0b01df47b5e02abe86cccd03b) | Returns the encoding used for posting the form. | +| [`setBoundary`](#classscy_1_1http_1_1FormWriter_1a385dfb4313fd4b63c90326edb3d8bf2a) | Sets the boundary to use for separating form parts. Must be set before [prepareSubmit()](#classscy_1_1http_1_1FormWriter_1aa5769359cbcdf8addf6da8dc3f45d283) is called. | +| [`boundary`](#classscy_1_1http_1_1FormWriter_1a08c75f60ff2b194f6eca60124cd5ac7c) | Returns the MIME boundary used for writing multipart form data. | +| [`connection`](#classscy_1_1http_1_1FormWriter_1a98c95aa2b0d393861ff17d32dcb28a8e) | The associated HTTP client connection. | +| [`ENCODING_URL`](#classscy_1_1http_1_1FormWriter_1ab1279705132688896d236c8bf2834c73) | "application/x-www-form-urlencoded" | +| [`ENCODING_MULTIPART_FORM`](#classscy_1_1http_1_1FormWriter_1a75a64c9f952d48e6ae3d9b5f0c5505bc) | "multipart/form-data" | +| [`ENCODING_MULTIPART_RELATED`](#classscy_1_1http_1_1FormWriter_1ab0414bdc2f08c691369b5b22147f6067) | "multipart/related" [http://tools.ietf.org/html/rfc2387](http://tools.ietf.org/html/rfc2387) | +| [`create`](#classscy_1_1http_1_1FormWriter_1ad38b14995dac6b4b9b571dbb8b395d5a) | Creates the [FormWriter](#classscy_1_1http_1_1FormWriter) that uses the given connection and encoding type. | +| [`_stream`](#classscy_1_1http_1_1FormWriter_1afc74cd5d30a0746914dbb46425dc577d) | | +| [`_runner`](#classscy_1_1http_1_1FormWriter_1a4e248609907dafe539ecedc19742fc20) | | +| [`_encoding`](#classscy_1_1http_1_1FormWriter_1affbac44d4b4e31504c159879ad4aeeea) | | +| [`_boundary`](#classscy_1_1http_1_1FormWriter_1a6bdb766483b5dc3ec566ba5dd8c62d0a) | | +| [`_parts`](#classscy_1_1http_1_1FormWriter_1a203d49a219f8dd1db20b68d5c8f7f762) | | +| [`_filesLength`](#classscy_1_1http_1_1FormWriter_1a80fe080459a5ab2bd023748d81173c4c) | | +| [`_writeState`](#classscy_1_1http_1_1FormWriter_1a6d4721907f8d77d40d79b97a522c2ac0) | | +| [`_initial`](#classscy_1_1http_1_1FormWriter_1ae9379de89bcbc2827acc2e98834b592f) | | +| [`_complete`](#classscy_1_1http_1_1FormWriter_1a0937540b2e3ebfa1b33cdb955384cbb3) | | +| [`FormWriter`](#classscy_1_1http_1_1FormWriter_1adf5052c2ffe130f08be80851af30a8bf) | Creates the [FormWriter](#classscy_1_1http_1_1FormWriter) that uses the given encoding. | +| [`FormWriter`](#classscy_1_1http_1_1FormWriter_1ab3749cfb874876b80cab0409f6dfada9) | | +| [`operator=`](#classscy_1_1http_1_1FormWriter_1ab01743f0fd0b5cd020c691f58d90df0f) | | +| [`writePartHeader`](#classscy_1_1http_1_1FormWriter_1a284dfa7aaa9df8733b3478c50f7cc1aa) | Writes the message boundary std::string, followed by the message header to the output stream. | +| [`writeEnd`](#classscy_1_1http_1_1FormWriter_1ae821aa326c6156c6ab81809b75bfdff9) | Writes the final boundary std::string to the output stream. | +| [`updateProgress`](#classscy_1_1http_1_1FormWriter_1a8d47d8f0ecc8dfe4cab1ce61c90a091f) | Updates the upload progress via the associated [ConnectionStream](#classscy_1_1http_1_1ConnectionStream) object. | + +--- + +#### emitter + +```cpp +[PacketSignal](./doc/api-base.md#group__base_1ga979ef14c59bd1db94d095fed71247f79) emitter +``` -#### `public void start()` +The outgoing packet emitter. -Start the HTTP server. +--- +#### ~FormWriter +```cpp +virtual ~FormWriter() +``` -#### `public void shutdown()` +Destroys the [FormWriter](#classscy_1_1http_1_1FormWriter). -Shutdown the HTTP server. +--- +#### addPart +```cpp +void addPart(const std::string & name, [FormPart](#classscy_1_1http_1_1FormPart) * part) +``` -#### `public `[`net::Address`](#classscy_1_1net_1_1Address)` & address()` +Adds an part/attachment (file upload) to the form. -Return the server bind address. +The form takes ownership of the [FilePart](#classscy_1_1http_1_1FilePart) and deletes it when it is no longer needed. The part will only be sent if the encoding set for the form is "multipart/form-data" +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | +| `part` | `[FormPart](#classscy_1_1http_1_1FormPart) *` | | +--- -#### `protected `[`net::Address`](./doc/api-net.md#classscy_1_1net_1_1Address)` _address` +#### start +```cpp +virtual void start() +``` +Starts the sending thread. +--- +#### stop -#### `protected net::TCPSocket::Ptr _socket` +```cpp +virtual void stop() +``` +Stops the sending thread. +--- +#### complete +```cpp +bool complete() const +``` -#### `protected `[`Timer`](./doc/api-base.md#classscy_1_1Timer)` _timer` +Returns true if the request is complete. +--- +#### cancelled +```cpp +bool cancelled() const +``` +Returns true if the request is cancelled. -#### `protected `[`ServerConnectionFactory`](./doc/api-http.md#classscy_1_1http_1_1ServerConnectionFactory)` * _factory` +--- +#### prepareSubmit +```cpp +void prepareSubmit() +``` +Prepares the outgoing HTTP request object for submitting the form. +--- -#### `protected std::vector< ServerConnection::Ptr > _connections` +#### calculateMultipartContentLength +```cpp +uint64_t calculateMultipartContentLength() +``` +Processes the entire stream and calculates the content length. Not used for chunked encoding. +--- +#### writeUrl -#### `protected `[`ServerResponder`](#classscy_1_1http_1_1ServerResponder)` * createResponder(`[`ServerConnection`](#classscy_1_1http_1_1ServerConnection)` & conn)` +```cpp +void writeUrl(std::ostream & ostr) +``` +Writes "application/x-www-form-urlencoded" encoded data to the client connection. +| Parameter | Type | Description | +|-----------|------|-------------| +| `ostr` | `std::ostream &` | | +--- +#### writeMultipartChunk -#### `protected void onClientSocketAccept(const net::TCPSocket::Ptr & socket)` +```cpp +void writeMultipartChunk() +``` +Writes the next multipart "multipart/form-data" encoded to the client connection. This method is non-blocking, and is suitable for use with the event loop. +--- +#### writeAsync +```cpp +void writeAsync() +``` -#### `protected void onConnectionReady(`[`ServerConnection`](#classscy_1_1http_1_1ServerConnection)` & conn)` +Called asynchronously by the [Runner](./doc/api-base.md#classscy_1_1Runner) to write the next message chunk. +--- +#### setEncoding +```cpp +void setEncoding(const std::string & encoding) +``` +Sets the encoding used for posting the form. -#### `protected void onConnectionClose(`[`ServerConnection`](#classscy_1_1http_1_1ServerConnection)` & conn)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `encoding` | `const std::string &` | | +--- +#### encoding +```cpp +const std::string & encoding() const +``` +Returns the encoding used for posting the form. -#### `protected virtual void onSocketClose(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket)` +--- +#### setBoundary +```cpp +void setBoundary(const std::string & boundary) +``` +Sets the boundary to use for separating form parts. Must be set before [prepareSubmit()](#classscy_1_1http_1_1FormWriter_1aa5769359cbcdf8addf6da8dc3f45d283) is called. +| Parameter | Type | Description | +|-----------|------|-------------| +| `boundary` | `const std::string &` | | -#### `protected void onTimer()` +--- +#### boundary +```cpp +const std::string & boundary() const +``` +Returns the MIME boundary used for writing multipart form data. +--- -# class `scy::http::ServerConnection` +#### connection +```cpp +[ConnectionStream](#classscy_1_1http_1_1ConnectionStream) & connection() ``` -class scy::http::ServerConnection - : public scy::http::Connection -``` - -HTTP server connection. +The associated HTTP client connection. +--- -## Summary +#### ENCODING_URL - Members | Descriptions ---------------------------------|--------------------------------------------- -`public `[`Signal](#classscy_1_1Signal)< void([ServerConnection](#classscy_1_1http_1_1ServerConnection) &, const [MutableBuffer`](#classscy_1_1MutableBuffer) &)`> Payload` | Signals when raw data is received. -`public `[`Signal](#classscy_1_1Signal)< void([ServerConnection`](#classscy_1_1http_1_1ServerConnection) &)`> Close` | Signals when the connection is closed. -`public ServerConnection(`[`Server`](#classscy_1_1http_1_1Server)` & server,net::TCPSocket::Ptr socket)` | -`public virtual ~ServerConnection()` | -`public `[`Server`](#classscy_1_1http_1_1Server)` & server()` | -`protected `[`Server`](./doc/api-http.md#classscy_1_1http_1_1Server)` & _server` | -`protected `[`ServerResponder`](./doc/api-http.md#classscy_1_1http_1_1ServerResponder)` * _responder` | -`protected bool _upgrade` | -`protected virtual void onHeaders()` | -`protected virtual void onPayload(const `[`MutableBuffer`](#classscy_1_1MutableBuffer)` & buffer)` | -`protected virtual void onComplete()` | -`protected virtual void onClose()` | -`protected virtual `[`http::Message`](#classscy_1_1http_1_1Message)` * incomingHeader()` | -`protected virtual `[`http::Message`](#classscy_1_1http_1_1Message)` * outgoingHeader()` | +```cpp +const char * ENCODING_URL = "application/x-www-form-urlencoded" +``` -## Members +"application/x-www-form-urlencoded" -#### `public `[`Signal](#classscy_1_1Signal)< void([ServerConnection](#classscy_1_1http_1_1ServerConnection) &, const [MutableBuffer`](#classscy_1_1MutableBuffer) &)`> Payload` +--- -Signals when raw data is received. +#### ENCODING_MULTIPART_FORM +```cpp +const char * ENCODING_MULTIPART_FORM = "multipart/form-data" +``` +"multipart/form-data" -#### `public `[`Signal](#classscy_1_1Signal)< void([ServerConnection`](#classscy_1_1http_1_1ServerConnection) &)`> Close` +--- -Signals when the connection is closed. +#### ENCODING_MULTIPART_RELATED +```cpp +const char * ENCODING_MULTIPART_RELATED = "multipart/related" +``` +"multipart/related" [http://tools.ietf.org/html/rfc2387](http://tools.ietf.org/html/rfc2387) -#### `public ServerConnection(`[`Server`](#classscy_1_1http_1_1Server)` & server,net::TCPSocket::Ptr socket)` +--- +#### create +```cpp +static [FormWriter](#classscy_1_1http_1_1FormWriter) * create([ConnectionStream](#classscy_1_1http_1_1ConnectionStream) & conn, const std::string & encoding) +``` +Creates the [FormWriter](#classscy_1_1http_1_1FormWriter) that uses the given connection and encoding type. +Encoding must be either "application/x-www-form-urlencoded" (which is the default) or "multipart/form-data". -#### `public virtual ~ServerConnection()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `conn` | `[ConnectionStream](#classscy_1_1http_1_1ConnectionStream) &` | | +| `encoding` | `const std::string &` | | +--- +#### _stream +```cpp +[ConnectionStream](#classscy_1_1http_1_1ConnectionStream) & _stream +``` +--- -#### `public `[`Server`](#classscy_1_1http_1_1Server)` & server()` +#### _runner +```cpp +std::shared_ptr< [Runner](./doc/api-base.md#classscy_1_1Runner) > _runner +``` +--- +#### _encoding +```cpp +std::string _encoding +``` -#### `protected `[`Server`](./doc/api-http.md#classscy_1_1http_1_1Server)` & _server` +--- +#### _boundary +```cpp +std::string _boundary +``` +--- +#### _parts -#### `protected `[`ServerResponder`](./doc/api-http.md#classscy_1_1http_1_1ServerResponder)` * _responder` +```cpp +[PartQueue](#classscy_1_1http_1_1FormWriter_1a29ed3d4115741fce5e6460464f9ea1c3) _parts +``` +--- +#### _filesLength +```cpp +uint64_t _filesLength +``` +--- -#### `protected bool _upgrade` +#### _writeState +```cpp +int _writeState +``` +--- +#### _initial +```cpp +bool _initial +``` -#### `protected virtual void onHeaders()` +--- +#### _complete +```cpp +bool _complete +``` +--- +#### FormWriter -#### `protected virtual void onPayload(const `[`MutableBuffer`](#classscy_1_1MutableBuffer)` & buffer)` +```cpp +FormWriter([ConnectionStream](#classscy_1_1http_1_1ConnectionStream) & conn, std::shared_ptr< [Runner](./doc/api-base.md#classscy_1_1Runner) > runner, const std::string & encoding) +``` +Creates the [FormWriter](#classscy_1_1http_1_1FormWriter) that uses the given encoding. +| Parameter | Type | Description | +|-----------|------|-------------| +| `conn` | `[ConnectionStream](#classscy_1_1http_1_1ConnectionStream) &` | | +| `runner` | `std::shared_ptr< [Runner](./doc/api-base.md#classscy_1_1Runner) >` | | +| `encoding` | `const std::string &` | | +--- +#### FormWriter -#### `protected virtual void onComplete()` +```cpp +FormWriter(const [FormWriter](#classscy_1_1http_1_1FormWriter) &) = delete +``` +--- +#### operator= +```cpp +[FormWriter](#classscy_1_1http_1_1FormWriter) & operator=(const [FormWriter](#classscy_1_1http_1_1FormWriter) &) = delete +``` +--- -#### `protected virtual void onClose()` +#### writePartHeader +```cpp +void writePartHeader(const [NVCollection](./doc/api-base.md#classscy_1_1NVCollection) & header, std::ostream & ostr) +``` +Writes the message boundary std::string, followed by the message header to the output stream. +| Parameter | Type | Description | +|-----------|------|-------------| +| `header` | `const [NVCollection](./doc/api-base.md#classscy_1_1NVCollection) &` | | +| `ostr` | `std::ostream &` | | +--- -#### `protected virtual `[`http::Message`](#classscy_1_1http_1_1Message)` * incomingHeader()` +#### writeEnd +```cpp +void writeEnd(std::ostream & ostr) +``` +Writes the final boundary std::string to the output stream. +| Parameter | Type | Description | +|-----------|------|-------------| +| `ostr` | `std::ostream &` | | +--- -#### `protected virtual `[`http::Message`](#classscy_1_1http_1_1Message)` * outgoingHeader()` +#### updateProgress +```cpp +virtual void updateProgress(int nread) +``` +Updates the upload progress via the associated [ConnectionStream](#classscy_1_1http_1_1ConnectionStream) object. +| Parameter | Type | Description | +|-----------|------|-------------| +| `nread` | `int` | | +## FormPart -# class `scy::http::ServerConnectionFactory` +> **Subclasses:** `scy::http::FilePart`, `scy::http::StringPart` +> **Defined in:** `form.h` +An implementation of [FormPart](#classscy_1_1http_1_1FormPart). +### Members + +| Name | Description | +|------|-------------| +| [`FormPart`](#classscy_1_1http_1_1FormPart_1addfd1e7e0464b40e773a806e1d30ec4f) | Creates the [FormPart](#classscy_1_1http_1_1FormPart) with the given MIME type. | +| [`~FormPart`](#classscy_1_1http_1_1FormPart_1a1771d5947b6f1c8d4595f70d6d2ba79a) | Destroys the [FormPart](#classscy_1_1http_1_1FormPart). | +| [`reset`](#classscy_1_1http_1_1FormPart_1ac1b2db21062b5770195b6217da2ee7f6) | Reset the internal state and write position to the start. | +| [`writeChunk`](#classscy_1_1http_1_1FormPart_1a10b82f2f86dbd9dd27fdd3321d4d09f0) | Writes a form data chunk to the given HTTP client connection. Returns true if there is more data to be written. | +| [`write`](#classscy_1_1http_1_1FormPart_1afcc4b878645c0b9b1a25986827f8002a) | Writes the form data to the given HTTP client connection. | +| [`write`](#classscy_1_1http_1_1FormPart_1a9364dc83c243a4334a3157f7d7856bca) | Writes the form data to the given output stream. | +| [`headers`](#classscy_1_1http_1_1FormPart_1a16a42c613efc74d90591aad48992c5f2) | Returns a [NVCollection](./doc/api-base.md#classscy_1_1NVCollection) containing additional header fields for the part. | +| [`initialWrite`](#classscy_1_1http_1_1FormPart_1a0aeef9590266d57540c1c381f81bc3d9) | Returns true if this is the initial write. | +| [`contentType`](#classscy_1_1http_1_1FormPart_1a5b33a860f6532933b853ef1bb79b53fe) | Returns the MIME type for this part or attachment. | +| [`length`](#classscy_1_1http_1_1FormPart_1ab2077d4568fc862c92a28f690553670e) | Returns the length of the current part. | +| [`_contentType`](#classscy_1_1http_1_1FormPart_1a99b49cdefb7941eaa59014a6ffac990c) | | +| [`_length`](#classscy_1_1http_1_1FormPart_1aafe2123975b4ceb0be87e6ee57593d11) | | +| [`_headers`](#classscy_1_1http_1_1FormPart_1a1610eaa082d3154399710dba0bc4b1e4) | | +| [`_initialWrite`](#classscy_1_1http_1_1FormPart_1a4e0d100858d98915b243591998133d4a) | | + +--- + +#### FormPart + +```cpp +FormPart(const std::string & contentType) +``` +Creates the [FormPart](#classscy_1_1http_1_1FormPart) with the given MIME type. -This implementation of a [ServerConnectionFactory](#classscy_1_1http_1_1ServerConnectionFactory) is used by HTTP [Server](#classscy_1_1http_1_1Server) to create [ServerConnection](#classscy_1_1http_1_1ServerConnection) objects. +| Parameter | Type | Description | +|-----------|------|-------------| +| `contentType` | `const std::string &` | | -## Summary +--- - Members | Descriptions ---------------------------------|--------------------------------------------- -`public inline ServerConnectionFactory()` | -`public inline virtual ~ServerConnectionFactory()` | -`public inline virtual ServerConnection::Ptr createConnection(`[`Server`](#classscy_1_1http_1_1Server)` & server,const net::TCPSocket::Ptr & socket)` | -`public inline virtual `[`ServerResponder`](#classscy_1_1http_1_1ServerResponder)` * createResponder(`[`ServerConnection`](#classscy_1_1http_1_1ServerConnection)` & connection)` | +#### ~FormPart -## Members +```cpp +virtual ~FormPart() +``` -#### `public inline ServerConnectionFactory()` +Destroys the [FormPart](#classscy_1_1http_1_1FormPart). +--- +#### reset +```cpp +virtual void reset() +``` +Reset the internal state and write position to the start. -#### `public inline virtual ~ServerConnectionFactory()` +--- +#### writeChunk +```cpp +bool writeChunk([FormWriter](#classscy_1_1http_1_1FormWriter) & writer) +``` +Writes a form data chunk to the given HTTP client connection. Returns true if there is more data to be written. +| Parameter | Type | Description | +|-----------|------|-------------| +| `writer` | `[FormWriter](#classscy_1_1http_1_1FormWriter) &` | | -#### `public inline virtual ServerConnection::Ptr createConnection(`[`Server`](#classscy_1_1http_1_1Server)` & server,const net::TCPSocket::Ptr & socket)` +--- +#### write +```cpp +void write([FormWriter](#classscy_1_1http_1_1FormWriter) & writer) +``` -Factory method for instantiating the [ServerConnection](#classscy_1_1http_1_1ServerConnection) instance using the given Socket. +Writes the form data to the given HTTP client connection. -#### `public inline virtual `[`ServerResponder`](#classscy_1_1http_1_1ServerResponder)` * createResponder(`[`ServerConnection`](#classscy_1_1http_1_1ServerConnection)` & connection)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `writer` | `[FormWriter](#classscy_1_1http_1_1FormWriter) &` | | +--- +#### write -Factory method for instantiating the [ServerResponder](#classscy_1_1http_1_1ServerResponder) instance using the given [ServerConnection](#classscy_1_1http_1_1ServerConnection). +```cpp +void write(std::ostream & ostr) +``` -# class `scy::http::ServerResponder` +Writes the form data to the given output stream. +| Parameter | Type | Description | +|-----------|------|-------------| +| `ostr` | `std::ostream &` | | +--- +#### headers -The abstract base class for HTTP ServerResponders created by HTTP [Server](#classscy_1_1http_1_1Server). +```cpp +[NVCollection](./doc/api-base.md#classscy_1_1NVCollection) & headers() +``` -Derived classes should override the onRequest() method. +Returns a [NVCollection](./doc/api-base.md#classscy_1_1NVCollection) containing additional header fields for the part. -A new [ServerResponder](#classscy_1_1http_1_1ServerResponder) object can be created for each new HTTP request that is received by the HTTP [Server](#classscy_1_1http_1_1Server). +--- -## Summary +#### initialWrite - Members | Descriptions ---------------------------------|--------------------------------------------- -`public inline ServerResponder(`[`ServerConnection`](#classscy_1_1http_1_1ServerConnection)` & connection)` | -`public inline virtual ~ServerResponder()` | -`public inline virtual void onHeaders(`[`Request`](#classscy_1_1http_1_1Request)` &)` | -`public inline virtual void onPayload(const `[`MutableBuffer`](#classscy_1_1MutableBuffer)` &)` | -`public inline virtual void onRequest(`[`Request`](#classscy_1_1http_1_1Request)` &,`[`Response`](#classscy_1_1http_1_1Response)` &)` | -`public inline virtual void onClose()` | -`public inline `[`ServerConnection`](#classscy_1_1http_1_1ServerConnection)` & connection()` | -`public inline `[`Request`](#classscy_1_1http_1_1Request)` & request()` | -`public inline `[`Response`](#classscy_1_1http_1_1Response)` & response()` | -`protected `[`ServerConnection`](./doc/api-http.md#classscy_1_1http_1_1ServerConnection)` & _connection` | +```cpp +virtual bool initialWrite() const +``` -## Members +Returns true if this is the initial write. -#### `public inline ServerResponder(`[`ServerConnection`](#classscy_1_1http_1_1ServerConnection)` & connection)` +--- +#### contentType +```cpp +const std::string & contentType() const +``` +Returns the MIME type for this part or attachment. +--- -#### `public inline virtual ~ServerResponder()` +#### length +```cpp +uint64_t length() const +``` +Returns the length of the current part. +--- +#### _contentType -#### `public inline virtual void onHeaders(`[`Request`](#classscy_1_1http_1_1Request)` &)` +```cpp +std::string _contentType +``` +--- +#### _length +```cpp +uint64_t _length +``` +--- -#### `public inline virtual void onPayload(const `[`MutableBuffer`](#classscy_1_1MutableBuffer)` &)` +#### _headers +```cpp +[NVCollection](./doc/api-base.md#classscy_1_1NVCollection) _headers +``` +--- +#### _initialWrite +```cpp +bool _initialWrite +``` -#### `public inline virtual void onRequest(`[`Request`](#classscy_1_1http_1_1Request)` &,`[`Response`](#classscy_1_1http_1_1Response)` &)` +## FilePart +> **Extends:** `scy::http::FormPart` +> **Defined in:** `form.h` +An implementation of [FilePart](#classscy_1_1http_1_1FilePart) for plain files. +### Members + +| Name | Description | +|------|-------------| +| [`FilePart`](#classscy_1_1http_1_1FilePart_1a3965f033a1a66974801bf1ecb2a65e43) | Creates the [FilePart](#classscy_1_1http_1_1FilePart) for the given path. | +| [`FilePart`](#classscy_1_1http_1_1FilePart_1a0543f767567ba948d3f02b3de6020011) | Creates the [FilePart](#classscy_1_1http_1_1FilePart) for the given path and MIME type. | +| [`FilePart`](#classscy_1_1http_1_1FilePart_1a18dea4dba60832a3b9ab08fd1fc0a6fe) | Creates the [FilePart](#classscy_1_1http_1_1FilePart) for the given path and MIME type. The given filename is used as part filename (see [filename()](#classscy_1_1http_1_1FilePart_1ad2765df66b173afe804630d0294b57d2)) only. | +| [`~FilePart`](#classscy_1_1http_1_1FilePart_1ad1cba409e3ebbb99a8d90a70eaf68938) | Destroys the [FilePart](#classscy_1_1http_1_1FilePart). | +| [`open`](#classscy_1_1http_1_1FilePart_1a3254f30104cd2cba62847b430ba1a6b7) | Opens the file. | +| [`reset`](#classscy_1_1http_1_1FilePart_1a8e47a18cf77f0ddfbbdb95e4be54502d) | Reset the internal state and write position to the start. | +| [`writeChunk`](#classscy_1_1http_1_1FilePart_1a79720d0fc2bd52c655162db91b154605) | Writes a form data chunk to the given HTTP client connection. Returns true if there is more data to be written. | +| [`write`](#classscy_1_1http_1_1FilePart_1a4aed2e1707e335c71c14a974aeaad47e) | Writes the form data to the given HTTP client connection. | +| [`write`](#classscy_1_1http_1_1FilePart_1ac83ece1e9f7236b20b7c17fe885ab6d9) | Writes the form data to the given output stream. | +| [`filename`](#classscy_1_1http_1_1FilePart_1ad2765df66b173afe804630d0294b57d2) | Returns the filename portion of the path. | +| [`stream`](#classscy_1_1http_1_1FilePart_1a8ef4a43e06b5e9aecd8e008fe06bbd41) | Returns the file input stream. | +| [`length`](#classscy_1_1http_1_1FilePart_1a7ffcef3b5fb5e96d86e6f8de0e84aab1) | Returns the length of the current part. | +| [`_path`](#classscy_1_1http_1_1FilePart_1ac84b6cb214c304f0685e3db164c5e9d4) | | +| [`_filename`](#classscy_1_1http_1_1FilePart_1a5a022ac797b9194b540ce9e5128f54d4) | | +| [`_istr`](#classscy_1_1http_1_1FilePart_1ac44819c6c5d495ad370e0773ba15f341) | | +| [`_fileSize`](#classscy_1_1http_1_1FilePart_1a732d6ec638877661788fcd8ffbf7d23a) | | + +--- + +#### FilePart + +```cpp +FilePart(const std::string & path) +``` +Creates the [FilePart](#classscy_1_1http_1_1FilePart) for the given path. -#### `public inline virtual void onClose()` +The MIME type is set to application/octet-stream. +Throws an FileException if the file cannot be opened. +| Parameter | Type | Description | +|-----------|------|-------------| +| `path` | `const std::string &` | | +--- +#### FilePart -#### `public inline `[`ServerConnection`](#classscy_1_1http_1_1ServerConnection)` & connection()` +```cpp +FilePart(const std::string & path, const std::string & contentType) +``` +Creates the [FilePart](#classscy_1_1http_1_1FilePart) for the given path and MIME type. +Throws an FileException if the file cannot be opened. +| Parameter | Type | Description | +|-----------|------|-------------| +| `path` | `const std::string &` | | +| `contentType` | `const std::string &` | | +--- -#### `public inline `[`Request`](#classscy_1_1http_1_1Request)` & request()` +#### FilePart +```cpp +FilePart(const std::string & path, const std::string & filename, const std::string & contentType) +``` +Creates the [FilePart](#classscy_1_1http_1_1FilePart) for the given path and MIME type. The given filename is used as part filename (see [filename()](#classscy_1_1http_1_1FilePart_1ad2765df66b173afe804630d0294b57d2)) only. +Throws an FileException if the file cannot be opened. +| Parameter | Type | Description | +|-----------|------|-------------| +| `path` | `const std::string &` | | +| `filename` | `const std::string &` | | +| `contentType` | `const std::string &` | | -#### `public inline `[`Response`](#classscy_1_1http_1_1Response)` & response()` +--- +#### ~FilePart +```cpp +virtual ~FilePart() +``` +Destroys the [FilePart](#classscy_1_1http_1_1FilePart). +--- -#### `protected `[`ServerConnection`](./doc/api-http.md#classscy_1_1http_1_1ServerConnection)` & _connection` +#### open +```cpp +virtual void open() +``` +Opens the file. +Throws an FileException if the file cannot be opened. +--- -# class `scy::http::StringPart` +#### reset +```cpp +virtual void reset() ``` -class scy::http::StringPart - : public scy::http::FormPart -``` -An implementation of [StringPart](#classscy_1_1http_1_1StringPart) for plain files. +Reset the internal state and write position to the start. +--- +#### writeChunk -## Summary +```cpp +virtual bool writeChunk([FormWriter](#classscy_1_1http_1_1FormWriter) & writer) +``` - Members | Descriptions ---------------------------------|--------------------------------------------- -`public StringPart(const std::string & path)` | Creates the [StringPart](./doc/api-http.md#classscy_1_1http_1_1StringPart) for the given string. -`public StringPart(const std::string & data,const std::string & contentType)` | Creates the [StringPart](./doc/api-http.md#classscy_1_1http_1_1StringPart) for the given string and MIME type. -`public virtual ~StringPart()` | Destroys the [StringPart](./doc/api-http.md#classscy_1_1http_1_1StringPart). -`public virtual bool writeChunk(`[`FormWriter`](#classscy_1_1http_1_1FormWriter)` & writer)` | -`public virtual void write(`[`FormWriter`](#classscy_1_1http_1_1FormWriter)` & writer)` | Writes the form data to the given HTTP client connection. -`public virtual void write(std::ostream & ostr)` | Writes the form data to the given output stream. -`public virtual uint64_t length() const` | Returns the length of the current part. -`protected std::string _data` | +Writes a form data chunk to the given HTTP client connection. Returns true if there is more data to be written. -## Members +| Parameter | Type | Description | +|-----------|------|-------------| +| `writer` | `[FormWriter](#classscy_1_1http_1_1FormWriter) &` | | -#### `public StringPart(const std::string & path)` +--- -Creates the [StringPart](#classscy_1_1http_1_1StringPart) for the given string. +#### write +```cpp +virtual void write([FormWriter](#classscy_1_1http_1_1FormWriter) & writer) +``` +Writes the form data to the given HTTP client connection. -#### `public StringPart(const std::string & data,const std::string & contentType)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `writer` | `[FormWriter](#classscy_1_1http_1_1FormWriter) &` | | -Creates the [StringPart](#classscy_1_1http_1_1StringPart) for the given string and MIME type. +--- +#### write +```cpp +virtual void write(std::ostream & ostr) +``` -#### `public virtual ~StringPart()` +Writes the form data to the given output stream. -Destroys the [StringPart](#classscy_1_1http_1_1StringPart). +| Parameter | Type | Description | +|-----------|------|-------------| +| `ostr` | `std::ostream &` | | +--- +#### filename -#### `public virtual bool writeChunk(`[`FormWriter`](#classscy_1_1http_1_1FormWriter)` & writer)` +```cpp +const std::string & filename() const +``` +Returns the filename portion of the path. +--- -Writes a form data chunk to the given HTTP client connection. Returns true if there is more data to be written. +#### stream -#### `public virtual void write(`[`FormWriter`](#classscy_1_1http_1_1FormWriter)` & writer)` +```cpp +std::ifstream & stream() +``` -Writes the form data to the given HTTP client connection. +Returns the file input stream. +--- +#### length -#### `public virtual void write(std::ostream & ostr)` +```cpp +virtual uint64_t length() const +``` -Writes the form data to the given output stream. +Returns the length of the current part. +--- +#### _path -#### `public virtual uint64_t length() const` +```cpp +std::string _path +``` -Returns the length of the current part. +--- +#### _filename +```cpp +std::string _filename +``` -#### `protected std::string _data` +--- +#### _istr +```cpp +std::ifstream _istr +``` +--- +#### _fileSize -# class `scy::http::URL` +```cpp +uint64_t _fileSize +``` +## StringPart +> **Extends:** `scy::http::FormPart` +> **Defined in:** `form.h` +An implementation of [StringPart](#classscy_1_1http_1_1StringPart) for plain files. -An RFC 3986 based [URL](#classscy_1_1http_1_1URL) which uses an external c library to do the heavy lifting. Constructors and assignment operators will throw a SyntaxException if the [URL](#classscy_1_1http_1_1URL) is invalid. +### Members -## Summary +| Name | Description | +|------|-------------| +| [`StringPart`](#classscy_1_1http_1_1StringPart_1a0b5884a2d863ceb7cce47c351d4de3cf) | Creates the [StringPart](#classscy_1_1http_1_1StringPart) for the given string. | +| [`StringPart`](#classscy_1_1http_1_1StringPart_1a54d19c7cbabf1a1052dcdbb9c7bce61c) | Creates the [StringPart](#classscy_1_1http_1_1StringPart) for the given string and MIME type. | +| [`~StringPart`](#classscy_1_1http_1_1StringPart_1a377cfef62f1d4c5088d4dc61b9a2689e) | Destroys the [StringPart](#classscy_1_1http_1_1StringPart). | +| [`writeChunk`](#classscy_1_1http_1_1StringPart_1a1a8a1a3f648f0edb715cf5ac42275f14) | Writes a form data chunk to the given HTTP client connection. Returns true if there is more data to be written. | +| [`write`](#classscy_1_1http_1_1StringPart_1a73600ffb13f790118e3ae97ca028f88d) | Writes the form data to the given HTTP client connection. | +| [`write`](#classscy_1_1http_1_1StringPart_1a346d908a6b89c22a370ae88c616d48a1) | Writes the form data to the given output stream. | +| [`length`](#classscy_1_1http_1_1StringPart_1a25bbb142d981ca318d46c212d56a7faa) | Returns the length of the current part. | +| [`_data`](#classscy_1_1http_1_1StringPart_1a96f0a59bb5b72c46ec183f3e490b9071) | | - Members | Descriptions ---------------------------------|--------------------------------------------- -`public URL()` | -`public URL(const char * url)` | -`public URL(const std::string & url)` | -`public URL(const std::string & scheme,const std::string & authority)` | -`public URL(const std::string & scheme,const std::string & authority,const std::string & pathEtc)` | -`public URL(const std::string & scheme,const std::string & authority,const std::string & path,const std::string & query,const std::string & fragment)` | -`public ~URL()` | -`public `[`URL`](#classscy_1_1http_1_1URL)` & operator=(const `[`URL`](#classscy_1_1http_1_1URL)` & uri)` | -`public `[`URL`](#classscy_1_1http_1_1URL)` & operator=(const std::string & uri)` | -`public `[`URL`](#classscy_1_1http_1_1URL)` & operator=(const char * uri)` | -`public bool parse(const std::string & url,bool whiny)` | -`public std::string scheme() const` | -`public std::string userInfo() const` | -`public std::string host() const` | -`public uint16_t port() const` | -`public std::string authority() const` | -`public std::string path() const` | -`public std::string pathEtc() const` | -`public std::string query() const` | -`public std::string fragment() const` | -`public bool hasSchema() const` | -`public bool hasUserInfo() const` | -`public bool hasHost() const` | -`public bool hasPort() const` | -`public bool hasPath() const` | -`public bool hasQuery() const` | -`public bool hasFragment() const` | -`public bool valid() const` | -`public std::string str() const` | -`protected http_parser_url _parser` | -`protected std::string _buf` | +--- -## Members +#### StringPart -#### `public URL()` +```cpp +StringPart(const std::string & path) +``` +Creates the [StringPart](#classscy_1_1http_1_1StringPart) for the given string. +| Parameter | Type | Description | +|-----------|------|-------------| +| `path` | `const std::string &` | | +--- +#### StringPart -#### `public URL(const char * url)` +```cpp +StringPart(const std::string & data, const std::string & contentType) +``` +Creates the [StringPart](#classscy_1_1http_1_1StringPart) for the given string and MIME type. +| Parameter | Type | Description | +|-----------|------|-------------| +| `data` | `const std::string &` | | +| `contentType` | `const std::string &` | | +--- +#### ~StringPart -#### `public URL(const std::string & url)` +```cpp +virtual ~StringPart() +``` +Destroys the [StringPart](#classscy_1_1http_1_1StringPart). +--- +#### writeChunk +```cpp +virtual bool writeChunk([FormWriter](#classscy_1_1http_1_1FormWriter) & writer) +``` -#### `public URL(const std::string & scheme,const std::string & authority)` +Writes a form data chunk to the given HTTP client connection. Returns true if there is more data to be written. +| Parameter | Type | Description | +|-----------|------|-------------| +| `writer` | `[FormWriter](#classscy_1_1http_1_1FormWriter) &` | | +--- +#### write +```cpp +virtual void write([FormWriter](#classscy_1_1http_1_1FormWriter) & writer) +``` -#### `public URL(const std::string & scheme,const std::string & authority,const std::string & pathEtc)` +Writes the form data to the given HTTP client connection. +| Parameter | Type | Description | +|-----------|------|-------------| +| `writer` | `[FormWriter](#classscy_1_1http_1_1FormWriter) &` | | +--- +#### write +```cpp +virtual void write(std::ostream & ostr) +``` -#### `public URL(const std::string & scheme,const std::string & authority,const std::string & path,const std::string & query,const std::string & fragment)` +Writes the form data to the given output stream. +| Parameter | Type | Description | +|-----------|------|-------------| +| `ostr` | `std::ostream &` | | +--- +#### length +```cpp +virtual uint64_t length() const +``` -#### `public ~URL()` +Returns the length of the current part. +--- +#### _data +```cpp +std::string _data +``` +## Message -#### `public `[`URL`](#classscy_1_1http_1_1URL)` & operator=(const `[`URL`](#classscy_1_1http_1_1URL)` & uri)` +> **Extends:** `scy::NVCollection` +> **Subclasses:** `scy::http::Request`, `scy::http::Response` +> **Defined in:** `message.h` +The base class for [Request](./doc/api-undefined.md#classscy_1_1http_1_1Request) and [Response](./doc/api-undefined.md#classscy_1_1http_1_1Response). +Defines the common properties of all HTTP messages. These are version, content length, content type and transfer encoding. +### Members + +| Name | Description | +|------|-------------| +| [`setVersion`](#group__http_1ga723cfacd1de2e59acd576eb63010d6fc) | Sets the HTTP version for this message. | +| [`getVersion`](#group__http_1gaeaf5238f777cf31201cb8bc342283221) | Returns the HTTP version for this message. | +| [`setContentLength`](#group__http_1ga831735515c44e91de1ffc304f30c9d49) | Sets the Content-Length header. | +| [`getContentLength`](#group__http_1ga9fbd841b869e2f71c976f26e42848ed7) | Returns the content length for this message, which may be UNKNOWN_CONTENT_LENGTH if no Content-Length header is present. | +| [`hasContentLength`](#group__http_1gad90dd4a412c227b05b071b26c71aaf35) | Returns true if a Content-Length header is present. | +| [`setTransferEncoding`](#group__http_1ga44b4439cc2b005a82ad7d118a53e0e0b) | Sets the transfer encoding for this message. | +| [`getTransferEncoding`](#group__http_1ga886838e78abe992b994489cd5809285f) | Returns the transfer encoding used for this message. | +| [`setChunkedTransferEncoding`](#group__http_1ga1093aa082297c1b15f018f7cda41096e) | If flag is true, sets the Transfer-Encoding header to chunked. Otherwise, removes the Transfer-Encoding header. | +| [`isChunkedTransferEncoding`](#group__http_1gac8677cc8b307cf7172a3299116acad30) | Returns true if the Transfer-Encoding header is set and its value is chunked. | +| [`setContentType`](#group__http_1ga0bc22314e98367be2ef4a72ddc626b94) | Sets the content type for this message. | +| [`getContentType`](#group__http_1gaab4a46e024093c712047548b6297f5f1) | Returns the content type for this message. | +| [`setKeepAlive`](#group__http_1ga093099a4721005e4705804f0f9aa096e) | Sets the value of the [Connection](#classscy_1_1http_1_1Connection) header field. | +| [`getKeepAlive`](#group__http_1ga12e6a3de621471dbf9fa8576902f972c) | Returns true if | +| [`write`](#group__http_1ga9ebc2305bb2173419345a1d2e21efd19) | Writes the message header to the given output stream. | +| [`write`](#group__http_1ga2e51af3e0cfe140aa95411b1c14e22a9) | Writes the message header to the given output string. | +| [`Message`](#group__http_1ga928fa708b89d544c3b6f5039b787bb7e) | Creates the [Message](#classscy_1_1http_1_1Message) with version HTTP/1.0. | +| [`Message`](#group__http_1gabcb10a4c47593f94c9431c0f21cbf114) | Creates the [Message](#classscy_1_1http_1_1Message) and sets the version. | +| [`~Message`](#group__http_1ga71ef669503290a7f386ee2dc91e09b53) | Destroys the [Message](#classscy_1_1http_1_1Message). | +| [`HTTP_1_0`](#group__http_1ga8c0f2b43a4b1c18ba98968d142739a37) | | +| [`HTTP_1_1`](#group__http_1gaa38f6879b68e53a02cdee386dbf340f9) | | +| [`IDENTITY_TRANSFER_ENCODING`](#group__http_1ga627d303cd0ebef230387cd3b6ddad541) | | +| [`CHUNKED_TRANSFER_ENCODING`](#group__http_1gad3eaedbb64235c47e3c7b6faef5a2e35) | | +| [`UNKNOWN_CONTENT_LENGTH`](#group__http_1ga256c2a1ecf1f2aa9ef6207b5c41c81f7) | | +| [`UNKNOWN_CONTENT_TYPE`](#group__http_1gaacddb05e323c1d3fd83ee313be6299ea) | | +| [`CONTENT_LENGTH`](#group__http_1gab76ed9f16753de667e4f9597e0c4a330) | | +| [`CONTENT_TYPE`](#group__http_1ga4c8e78b1c7b3c89e89b552b4b8988ef6) | | +| [`TRANSFER_ENCODING`](#group__http_1ga5504149b9e387202df43caa69891bab0) | | +| [`CONNECTION`](#group__http_1ga53ce770c798004418fdea2d965337af8) | | +| [`CONNECTION_KEEP_ALIVE`](#group__http_1gaa3b3ded50adcca5eb9c5af3ea1ec19b2) | | +| [`CONNECTION_CLOSE`](#group__http_1ga5a7acda79eab95b2987e9f96162e0a77) | | +| [`EMPTY`](#group__http_1ga51519fdace0bc2b729421d86fedbfe18) | | +| [`_version`](#classscy_1_1http_1_1Message_1aa2feba1d1b0438c328d36653d09b05d1) | | + +--- + +#### setVersion + +```cpp +void setVersion(const std::string & version) +``` +Sets the HTTP version for this message. -#### `public `[`URL`](#classscy_1_1http_1_1URL)` & operator=(const std::string & uri)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `version` | `const std::string &` | | +--- +#### getVersion +```cpp +const std::string & getVersion() const +``` +Returns the HTTP version for this message. -#### `public `[`URL`](#classscy_1_1http_1_1URL)` & operator=(const char * uri)` +--- +#### setContentLength +```cpp +void setContentLength(uint64_t length) +``` +Sets the Content-Length header. +If length is UNKNOWN_CONTENT_LENGTH, removes the Content-Length header. -#### `public bool parse(const std::string & url,bool whiny)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `length` | `uint64_t` | | +--- +#### getContentLength -Parses and assigns an URI from the given std::string. Throws a SyntaxException if whiny is set and the given url is invalid. +```cpp +uint64_t getContentLength() const +``` -#### `public std::string scheme() const` +Returns the content length for this message, which may be UNKNOWN_CONTENT_LENGTH if no Content-Length header is present. +--- +#### hasContentLength +```cpp +bool hasContentLength() const +``` +Returns true if a Content-Length header is present. -#### `public std::string userInfo() const` +--- +#### setTransferEncoding +```cpp +void setTransferEncoding(const std::string & transferEncoding) +``` +Sets the transfer encoding for this message. +The value should be either IDENTITY_TRANSFER_CODING or CHUNKED_TRANSFER_CODING. -#### `public std::string host() const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `transferEncoding` | `const std::string &` | | +--- +#### getTransferEncoding +```cpp +const std::string & getTransferEncoding() const +``` +Returns the transfer encoding used for this message. -#### `public uint16_t port() const` +Normally, this is the value of the Transfer-Encoding header field. If no such field is present, returns IDENTITY_TRANSFER_CODING. +--- +#### setChunkedTransferEncoding +```cpp +void setChunkedTransferEncoding(bool flag) +``` +If flag is true, sets the Transfer-Encoding header to chunked. Otherwise, removes the Transfer-Encoding header. -#### `public std::string authority() const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `flag` | `bool` | | +--- +#### isChunkedTransferEncoding +```cpp +bool isChunkedTransferEncoding() const +``` +Returns true if the Transfer-Encoding header is set and its value is chunked. -#### `public std::string path() const` +--- +#### setContentType +```cpp +void setContentType(const std::string & contentType) +``` +Sets the content type for this message. +Specify NO_CONTENT_TYPE to remove the Content-Type header. -#### `public std::string pathEtc() const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `contentType` | `const std::string &` | | +--- +#### getContentType +```cpp +const std::string & getContentType() const +``` +Returns the content type for this message. -#### `public std::string query() const` +If no Content-Type header is present, returns UNKNOWN_CONTENT_TYPE. +--- +#### setKeepAlive +```cpp +void setKeepAlive(bool keepAlive) +``` +Sets the value of the [Connection](#classscy_1_1http_1_1Connection) header field. -#### `public std::string fragment() const` +The value is set to "Keep-Alive" if keepAlive is true, or to "Close" otherwise. +| Parameter | Type | Description | +|-----------|------|-------------| +| `keepAlive` | `bool` | | +--- +#### getKeepAlive +```cpp +bool getKeepAlive() const +``` -#### `public bool hasSchema() const` +Returns true if +* the message has a [Connection](#classscy_1_1http_1_1Connection) header field and its value is "Keep-Alive" +* the message is a HTTP/1.1 message and not [Connection](#classscy_1_1http_1_1Connection) header is set Returns false otherwise. +--- +#### write -#### `public bool hasUserInfo() const` +```cpp +virtual void write(std::ostream & ostr) const +``` +Writes the message header to the given output stream. +The format is one name-value pair per line, with name and value separated by a colon and lines delimited by a carriage return and a linefeed character. See RFC 2822 for details. +| Parameter | Type | Description | +|-----------|------|-------------| +| `ostr` | `std::ostream &` | | +--- -#### `public bool hasHost() const` +#### write +```cpp +virtual void write(std::string & str) const +``` +Writes the message header to the given output string. +| Parameter | Type | Description | +|-----------|------|-------------| +| `str` | `std::string &` | | +--- -#### `public bool hasPort() const` +#### Message +```cpp +Message() +``` +Creates the [Message](#classscy_1_1http_1_1Message) with version HTTP/1.0. +--- +#### Message -#### `public bool hasPath() const` +```cpp +Message(const std::string & version) +``` +Creates the [Message](#classscy_1_1http_1_1Message) and sets the version. +| Parameter | Type | Description | +|-----------|------|-------------| +| `version` | `const std::string &` | | +--- +#### ~Message -#### `public bool hasQuery() const` +```cpp +virtual ~Message() +``` +Destroys the [Message](#classscy_1_1http_1_1Message). +--- +#### HTTP_1_0 +```cpp +const std::string HTTP_1_0 = "HTTP/1.0" +``` -#### `public bool hasFragment() const` +--- +#### HTTP_1_1 +```cpp +const std::string HTTP_1_1 = "HTTP/1.1" +``` +--- +#### IDENTITY_TRANSFER_ENCODING -#### `public bool valid() const` +```cpp +const std::string IDENTITY_TRANSFER_ENCODING = "identity" +``` +--- +#### CHUNKED_TRANSFER_ENCODING +```cpp +const std::string CHUNKED_TRANSFER_ENCODING = "chunked" +``` +--- -#### `public std::string str() const` +#### UNKNOWN_CONTENT_LENGTH +```cpp +const int UNKNOWN_CONTENT_LENGTH = -1 +``` +--- +#### UNKNOWN_CONTENT_TYPE +```cpp +const std::string UNKNOWN_CONTENT_TYPE +``` -#### `protected http_parser_url _parser` +--- +#### CONTENT_LENGTH +```cpp +const std::string CONTENT_LENGTH = "Content-Length" +``` +--- +#### CONTENT_TYPE -#### `protected std::string _buf` +```cpp +const std::string CONTENT_TYPE = "Content-Type" +``` +--- +#### TRANSFER_ENCODING +```cpp +const std::string TRANSFER_ENCODING = "Transfer-Encoding" +``` +--- -# struct `scy::http::Method` +#### CONNECTION +```cpp +const std::string CONNECTION = "Connection" +``` -HTTP request methods. +--- +#### CONNECTION_KEEP_ALIVE +```cpp +const std::string CONNECTION_KEEP_ALIVE = "Keep-Alive" +``` -## Summary +--- - Members | Descriptions ---------------------------------|--------------------------------------------- +#### CONNECTION_CLOSE -## Members +```cpp +const std::string CONNECTION_CLOSE = "Close" +``` -# namespace `scy::http::ws` +--- +#### EMPTY +```cpp +const std::string EMPTY +``` -## Summary +--- - Members | Descriptions ---------------------------------|--------------------------------------------- -`class `[`scy::http::ws::ConnectionAdapter`](#classscy_1_1http_1_1ws_1_1ConnectionAdapter) | [WebSocket](#classscy_1_1http_1_1ws_1_1WebSocket) class which belongs to a HTTP [Connection](#classscy_1_1http_1_1Connection). -`class `[`scy::http::ws::WebSocket`](#classscy_1_1http_1_1ws_1_1WebSocket) | Standalone [WebSocket](#classscy_1_1http_1_1ws_1_1WebSocket) class. -`class `[`scy::http::ws::WebSocketAdapter`](#classscy_1_1http_1_1ws_1_1WebSocketAdapter) | -`class `[`scy::http::ws::WebSocketFramer`](#classscy_1_1http_1_1ws_1_1WebSocketFramer) | -# class `scy::http::ws::ConnectionAdapter` +#### _version +```cpp +std::string _version ``` -class scy::http::ws::ConnectionAdapter - : public scy::http::ws::WebSocketAdapter -``` -[WebSocket](#classscy_1_1http_1_1ws_1_1WebSocket) class which belongs to a HTTP [Connection](#classscy_1_1http_1_1Connection). +## ChunkedAdapter +> **Extends:** `scy::PacketProcessor` +> **Defined in:** `packetizers.h` +HTTP chunked transfer encoding adapter for streaming responses. -## Summary +### Members - Members | Descriptions ---------------------------------|--------------------------------------------- -`public ConnectionAdapter(`[`Connection`](#classscy_1_1http_1_1Connection)` * connection,`[`ws::Mode`](#group__http_1gaa9edb02676fb90927487e1de2afa287e)` mode)` | -`public virtual ~ConnectionAdapter()` | -`public virtual void onHandshakeComplete()` | -`protected `[`Connection`](./doc/api-http.md#classscy_1_1http_1_1Connection)` * _connection` | - -## Members - -#### `public ConnectionAdapter(`[`Connection`](#classscy_1_1http_1_1Connection)` * connection,`[`ws::Mode`](#group__http_1gaa9edb02676fb90927487e1de2afa287e)` mode)` +| Name | Description | +|------|-------------| +| [`connection`](#classscy_1_1http_1_1ChunkedAdapter_1aab1ffaf4caf52c43f9a886f613626ee7) | | +| [`contentType`](#classscy_1_1http_1_1ChunkedAdapter_1a42c0bc9dd9c269c4cb07f4312757e27b) | | +| [`frameSeparator`](#classscy_1_1http_1_1ChunkedAdapter_1a1ab13fa89e2582407844aeff3c47b3a9) | | +| [`initial`](#classscy_1_1http_1_1ChunkedAdapter_1a8c694d7668b8ac9062561d57f764c8df) | | +| [`nocopy`](#classscy_1_1http_1_1ChunkedAdapter_1a35f74aabaea9e37fb8b90f8880fa9e15) | | +| [`emitter`](#classscy_1_1http_1_1ChunkedAdapter_1abcc47b70a4402dcdf6544143881fed7d) | | +| [`ChunkedAdapter`](#classscy_1_1http_1_1ChunkedAdapter_1a38782e1645dd6fc4f62637cc38bf5cbd) | | +| [`ChunkedAdapter`](#classscy_1_1http_1_1ChunkedAdapter_1a0992d011faef2ac9b957753eccb9523f) | | +| [`~ChunkedAdapter`](#classscy_1_1http_1_1ChunkedAdapter_1abf8b0cdc814e1c8f0c8f98d8afdf1397) | | +| [`emitHeader`](#classscy_1_1http_1_1ChunkedAdapter_1a994d502823366aaef2833945c6f9d555) | Sets HTTP headers for the initial response. This method must not include the final carriage return. | +| [`process`](#classscy_1_1http_1_1ChunkedAdapter_1a2d56caf2f5823f852b640663968d57f4) | This method performs processing on the given packet and emits the result. | +--- +#### connection +```cpp +[Connection::Ptr](#classscy_1_1http_1_1Connection_1a2143146501601ea9816068f83731e1fb) connection +``` +--- -#### `public virtual ~ConnectionAdapter()` +#### contentType +```cpp +std::string contentType +``` +--- +#### frameSeparator +```cpp +std::string frameSeparator +``` -#### `public virtual void onHandshakeComplete()` +--- +#### initial +```cpp +bool initial +``` +--- +#### nocopy -#### `protected `[`Connection`](./doc/api-http.md#classscy_1_1http_1_1Connection)` * _connection` +```cpp +bool nocopy +``` +--- +#### emitter +```cpp +[PacketSignal](./doc/api-base.md#group__base_1ga979ef14c59bd1db94d095fed71247f79) emitter +``` +--- -# class `scy::http::ws::WebSocket` +#### ChunkedAdapter +```cpp +inline ChunkedAdapter([Connection::Ptr](#classscy_1_1http_1_1Connection_1a2143146501601ea9816068f83731e1fb) connection, const std::string & frameSeparator, bool nocopy) ``` -class scy::http::ws::WebSocket - : public scy::http::ws::WebSocketAdapter -``` -Standalone [WebSocket](#classscy_1_1http_1_1ws_1_1WebSocket) class. +| Parameter | Type | Description | +|-----------|------|-------------| +| `connection` | `[Connection::Ptr](#classscy_1_1http_1_1Connection_1a2143146501601ea9816068f83731e1fb)` | | +| `frameSeparator` | `const std::string &` | | +| `nocopy` | `bool` | | +--- +#### ChunkedAdapter -## Summary +```cpp +inline ChunkedAdapter(const std::string & contentType, const std::string & frameSeparator, bool nocopy) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `contentType` | `const std::string &` | | +| `frameSeparator` | `const std::string &` | | +| `nocopy` | `bool` | | - Members | Descriptions ---------------------------------|--------------------------------------------- -`public WebSocket(const net::Socket::Ptr & socket)` | -`public virtual ~WebSocket()` | -`public `[`http::Request`](#classscy_1_1http_1_1Request)` & request()` | -`public `[`http::Response`](#classscy_1_1http_1_1Response)` & response()` | -`protected `[`http::Request`](./doc/api-http.md#classscy_1_1http_1_1Request)` _request` | -`protected `[`http::Response`](./doc/api-http.md#classscy_1_1http_1_1Response)` _response` | +--- -## Members +#### ~ChunkedAdapter -#### `public WebSocket(const net::Socket::Ptr & socket)` +```cpp +virtual inline ~ChunkedAdapter() +``` +--- +#### emitHeader -Creates the [WebSocket](#classscy_1_1http_1_1ws_1_1WebSocket) with the given Socket. The Socket should be a TCPSocket or a SSLSocket, depending on the protocol used (ws or wss). +```cpp +virtual inline void emitHeader() +``` -#### `public virtual ~WebSocket()` +Sets HTTP headers for the initial response. This method must not include the final carriage return. +--- +#### process +```cpp +virtual inline void process([IPacket](./doc/api-base.md#classscy_1_1IPacket) & packet) +``` +This method performs processing on the given packet and emits the result. -#### `public `[`http::Request`](#classscy_1_1http_1_1Request)` & request()` +Note: If packet processing is async (the packet is not in the current thread scope) then packet data must be copied. Copied data can be freed directly aFter the async call to [emit()](./doc/api-base.md#group__base_1ga995248310998c29df87051389f52b58c) the outgoing packet. +| Parameter | Type | Description | +|-----------|------|-------------| +| `packet` | `[IPacket](./doc/api-base.md#classscy_1_1IPacket) &` | | +## MultipartAdapter +> **Extends:** `scy::PacketProcessor` +> **Defined in:** `packetizers.h` +HTTP multipart encoding adapter for multipart/x-mixed-replace streaming. -#### `public `[`http::Response`](#classscy_1_1http_1_1Response)` & response()` +### Members +| Name | Description | +|------|-------------| +| [`connection`](#classscy_1_1http_1_1MultipartAdapter_1a907005a65c54c74e58cdba7c529aa107) | | +| [`contentType`](#classscy_1_1http_1_1MultipartAdapter_1a28482bfd82b764ab36ebba40465d6bd8) | | +| [`isBase64`](#classscy_1_1http_1_1MultipartAdapter_1a9d95a8cdd1e6a1d164aeaba94b986c3f) | | +| [`initial`](#classscy_1_1http_1_1MultipartAdapter_1a7c8957e88432dbaad3f86ae512c3e23e) | | +| [`emitter`](#classscy_1_1http_1_1MultipartAdapter_1a73a88cc955c203e10227dc1e72319fc6) | | +| [`MultipartAdapter`](#classscy_1_1http_1_1MultipartAdapter_1a299d4d132f1778bfadc62dff2a0ed210) | | +| [`MultipartAdapter`](#classscy_1_1http_1_1MultipartAdapter_1a3a4c616e3dbe183d1ba9f08043a47987) | | +| [`~MultipartAdapter`](#classscy_1_1http_1_1MultipartAdapter_1aa60e5cd062c7768f7636a851f5154076) | | +| [`emitHeader`](#classscy_1_1http_1_1MultipartAdapter_1a5c48095fcace4608150c12d3e918a4b7) | | +| [`emitChunkHeader`](#classscy_1_1http_1_1MultipartAdapter_1a98b86bd888dc6d41962ab88c46d3729d) | Sets HTTP header for the current chunk. | +| [`process`](#classscy_1_1http_1_1MultipartAdapter_1aafa137c5fc3cfa81a0ed7bb3de2ba3c4) | This method performs processing on the given packet and emits the result. | +--- +#### connection +```cpp +[Connection::Ptr](#classscy_1_1http_1_1Connection_1a2143146501601ea9816068f83731e1fb) connection +``` -#### `protected `[`http::Request`](./doc/api-http.md#classscy_1_1http_1_1Request)` _request` +--- +#### contentType +```cpp +std::string contentType +``` +--- +#### isBase64 -#### `protected `[`http::Response`](./doc/api-http.md#classscy_1_1http_1_1Response)` _response` +```cpp +bool isBase64 +``` +--- +#### initial +```cpp +bool initial +``` +--- -# class `scy::http::ws::WebSocketAdapter` +#### emitter +```cpp +[PacketSignal](./doc/api-base.md#group__base_1ga979ef14c59bd1db94d095fed71247f79) emitter ``` -class scy::http::ws::WebSocketAdapter - : public scy::net::SocketEmitter -``` +--- +#### MultipartAdapter +```cpp +inline MultipartAdapter([Connection::Ptr](#classscy_1_1http_1_1Connection_1a2143146501601ea9816068f83731e1fb) connection, bool base64) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `connection` | `[Connection::Ptr](#classscy_1_1http_1_1Connection_1a2143146501601ea9816068f83731e1fb)` | | +| `base64` | `bool` | | -## Summary +--- - Members | Descriptions ---------------------------------|--------------------------------------------- -`public net::Socket::Ptr socket` | -`public WebSocketAdapter(const net::Socket::Ptr & socket,`[`ws::Mode`](#group__http_1gaa9edb02676fb90927487e1de2afa287e)` mode,`[`http::Request`](#classscy_1_1http_1_1Request)` & request,`[`http::Response`](#classscy_1_1http_1_1Response)` & response)` | -`public virtual ssize_t send(const char * data,size_t len,int flags)` | -`public virtual ssize_t send(const char * data,size_t len,const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddr,int flags)` | -`public virtual bool shutdown(uint16_t statusCode,const std::string & statusMessage)` | -`public virtual void sendClientRequest()` | [Client](./doc/api-http.md#classscy_1_1http_1_1Client) side. -`public virtual void handleClientResponse(const `[`MutableBuffer`](#classscy_1_1MutableBuffer)` & buffer,const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddr)` | -`public virtual void handleServerRequest(const `[`MutableBuffer`](#classscy_1_1MutableBuffer)` & buffer,const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddr)` | [Server](./doc/api-http.md#classscy_1_1http_1_1Server) side. -`public virtual void onSocketConnect(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket)` | Internal callback events. -`public virtual void onSocketRecv(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket,const `[`MutableBuffer`](#classscy_1_1MutableBuffer)` & buffer,const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddress)` | -`public virtual void onSocketClose(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket)` | -`public virtual void onHandshakeComplete()` | -`protected `[`WebSocketFramer`](./doc/api-http.md#classscy_1_1http_1_1ws_1_1WebSocketFramer)` framer` | -`protected `[`http::Request`](./doc/api-http.md#classscy_1_1http_1_1Request)` & _request` | -`protected `[`http::Response`](./doc/api-http.md#classscy_1_1http_1_1Response)` & _response` | -`protected virtual ~WebSocketAdapter()` | +#### MultipartAdapter -## Members +```cpp +inline MultipartAdapter(const std::string & contentType, bool base64) +``` -#### `public net::Socket::Ptr socket` +| Parameter | Type | Description | +|-----------|------|-------------| +| `contentType` | `const std::string &` | | +| `base64` | `bool` | | +--- +#### ~MultipartAdapter -Pointer to the underlying socket. Sent data will be proxied to this socket. +```cpp +virtual inline ~MultipartAdapter() +``` -#### `public WebSocketAdapter(const net::Socket::Ptr & socket,`[`ws::Mode`](#group__http_1gaa9edb02676fb90927487e1de2afa287e)` mode,`[`http::Request`](#classscy_1_1http_1_1Request)` & request,`[`http::Response`](#classscy_1_1http_1_1Response)` & response)` +--- +#### emitHeader +```cpp +virtual inline void emitHeader() +``` +--- +#### emitChunkHeader -#### `public virtual ssize_t send(const char * data,size_t len,int flags)` +```cpp +virtual inline void emitChunkHeader() +``` +Sets HTTP header for the current chunk. +--- -Sends the given data buffer to the connected peer. Returns the number of bytes sent or -1 on error. No exception will be thrown. For TCP sockets the given peer address must match the connected peer address. +#### process -#### `public virtual ssize_t send(const char * data,size_t len,const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddr,int flags)` +```cpp +virtual inline void process([IPacket](./doc/api-base.md#classscy_1_1IPacket) & packet) +``` +This method performs processing on the given packet and emits the result. +Note: If packet processing is async (the packet is not in the current thread scope) then packet data must be copied. Copied data can be freed directly aFter the async call to [emit()](./doc/api-base.md#group__base_1ga995248310998c29df87051389f52b58c) the outgoing packet. +| Parameter | Type | Description | +|-----------|------|-------------| +| `packet` | `[IPacket](./doc/api-base.md#classscy_1_1IPacket) &` | | +## ParserObserver -#### `public virtual bool shutdown(uint16_t statusCode,const std::string & statusMessage)` +> **Subclasses:** `scy::http::ConnectionAdapter` +> **Defined in:** `parser.h` +Abstract observer interface for HTTP parser events. +### Members +| Name | Description | +|------|-------------| +| [`onParserHeader`](#classscy_1_1http_1_1ParserObserver_1a510985b7152fedee52ebb93488faf6c7) | | +| [`onParserHeadersEnd`](#classscy_1_1http_1_1ParserObserver_1a7988d91facef489ffb4f39419a788f13) | | +| [`onParserChunk`](#classscy_1_1http_1_1ParserObserver_1a2dca049067fa3587f1ab3e1756b00202) | | +| [`onParserEnd`](#classscy_1_1http_1_1ParserObserver_1ae2b96db1a35fd47c09a4d1b9c2eca40c) | | +| [`onParserError`](#classscy_1_1http_1_1ParserObserver_1a7f55842368057de8a80ecf698f19bf1c) | | +--- -#### `public virtual void sendClientRequest()` +#### onParserHeader -[Client](#classscy_1_1http_1_1Client) side. +```cpp +void onParserHeader(const std::string & name, const std::string & value) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | +| `value` | `const std::string &` | | +--- -#### `public virtual void handleClientResponse(const `[`MutableBuffer`](#classscy_1_1MutableBuffer)` & buffer,const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddr)` +#### onParserHeadersEnd +```cpp +void onParserHeadersEnd(bool upgrade) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `upgrade` | `bool` | | +--- +#### onParserChunk -#### `public virtual void handleServerRequest(const `[`MutableBuffer`](#classscy_1_1MutableBuffer)` & buffer,const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddr)` +```cpp +void onParserChunk(const char * data, size_t len) +``` -[Server](#classscy_1_1http_1_1Server) side. +| Parameter | Type | Description | +|-----------|------|-------------| +| `data` | `const char *` | | +| `len` | `size_t` | | +--- +#### onParserEnd -#### `public virtual void onSocketConnect(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket)` +```cpp +void onParserEnd() +``` -Internal callback events. +--- +#### onParserError +```cpp +void onParserError(const [Error](./doc/api-base.md#structscy_1_1Error) & err) +``` -#### `public virtual void onSocketRecv(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket,const `[`MutableBuffer`](#classscy_1_1MutableBuffer)` & buffer,const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddress)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `err` | `const [Error](./doc/api-base.md#structscy_1_1Error) &` | | + +## Parser + +> **Defined in:** `parser.h` + +HTTP request/response parser using the llhttp library. + +### Members + +| Name | Description | +|------|-------------| +| [`Parser`](#classscy_1_1http_1_1Parser_1aa8e33ac970406b210115f11bf311b264) | | +| [`Parser`](#classscy_1_1http_1_1Parser_1a3ec4c7513082d1c024cbbb9bb3643ed8) | | +| [`Parser`](#classscy_1_1http_1_1Parser_1a71919167f74dc474380e6e9d6c11fb2a) | | +| [`~Parser`](#classscy_1_1http_1_1Parser_1a5a5601800541bf19f61a711a95c3eb3d) | | +| [`parse`](#classscy_1_1http_1_1Parser_1af7b1e45278cbc1581daad785b1cedab5) | Parse a HTTP packet. | +| [`reset`](#classscy_1_1http_1_1Parser_1a78f9760a7041e1abf6c18b7bfe45f372) | Reset the internal state. | +| [`complete`](#classscy_1_1http_1_1Parser_1a5d34867367516a57d5c7b66419ef5f2d) | Returns true if parsing is complete, either in success or error. | +| [`upgrade`](#classscy_1_1http_1_1Parser_1a1c61be572464f18b0859c5642617b4ff) | Returns true if the connection should be upgraded. | +| [`setRequest`](#classscy_1_1http_1_1Parser_1a88ddd77c698950e4f1dc67808e680da8) | | +| [`setResponse`](#classscy_1_1http_1_1Parser_1ad6aed0467f8fcdbd9b9a2caa885401ac) | | +| [`setObserver`](#classscy_1_1http_1_1Parser_1ae102cf86a6376a3cdaab320bf5eaefae) | | +| [`message`](#classscy_1_1http_1_1Parser_1a4fee2c58d459db5eb9d51d19ba903543) | | +| [`observer`](#classscy_1_1http_1_1Parser_1ab3c0294c7cf94c797f36232579e73fac) | | +| [`_observer`](#classscy_1_1http_1_1Parser_1ab42977a9639b8058d82de95625466afc) | | +| [`_request`](#classscy_1_1http_1_1Parser_1a4981cb205d6bb8d818da9f83335894ec) | | +| [`_response`](#classscy_1_1http_1_1Parser_1a65ae85b18c21ebe24f566e625e1fa649) | | +| [`_message`](#classscy_1_1http_1_1Parser_1ad783cae492f8af491ac50f84ed46a0ba) | | +| [`_parser`](#classscy_1_1http_1_1Parser_1afed4d47dd0d25723bf57c9caebc45754) | | +| [`_settings`](#classscy_1_1http_1_1Parser_1ab557933e9caf9a34373696696b5d1dba) | | +| [`_type`](#classscy_1_1http_1_1Parser_1a9c96529de5705acd6a648e49a90c88a6) | | +| [`_wasHeaderValue`](#classscy_1_1http_1_1Parser_1a1355086b7cec9416fe9bc0769d252053) | | +| [`_lastHeaderField`](#classscy_1_1http_1_1Parser_1aeeac236dee38ff52b5582052dcd32564) | | +| [`_lastHeaderValue`](#classscy_1_1http_1_1Parser_1ad5a5ae35c21488224635872e273967bb) | | +| [`_complete`](#classscy_1_1http_1_1Parser_1a3f868ba7ed8140a65dcc88d30d149440) | | +| [`_upgrade`](#classscy_1_1http_1_1Parser_1acabe4267aa0ac4a5dbf190d2ed72fc48) | | +| [`_error`](#classscy_1_1http_1_1Parser_1a382f5184f8e9ed9bd52267dca6c62495) | | +| [`init`](#classscy_1_1http_1_1Parser_1a73260ac0e403453672228fd6547866ff) | | +| [`onURL`](#classscy_1_1http_1_1Parser_1aa5cb6c93db76ffce3859f110ef859cba) | Callbacks. | +| [`onHeader`](#classscy_1_1http_1_1Parser_1a39c3e8ebe19b3fc465ab97450c357a86) | | +| [`onHeadersEnd`](#classscy_1_1http_1_1Parser_1a2f638fec24c8fd048b9c18c9455fe5d5) | | +| [`onBody`](#classscy_1_1http_1_1Parser_1a8ce2f4f80661f8571b99f1e4cf461f4e) | | +| [`onMessageEnd`](#classscy_1_1http_1_1Parser_1aabdf6e5c001616ca452b8ca11731314a) | | +| [`onError`](#classscy_1_1http_1_1Parser_1ad7b06c0d34c03998b252e8c2120141bc) | | + +--- + +#### Parser + +```cpp +Parser([http::Response](./doc/api-undefined.md#classscy_1_1http_1_1Response) * response) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `response` | `[http::Response](./doc/api-undefined.md#classscy_1_1http_1_1Response) *` | | +--- +#### Parser +```cpp +Parser([http::Request](./doc/api-undefined.md#classscy_1_1http_1_1Request) * request) +``` -#### `public virtual void onSocketClose(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `request` | `[http::Request](./doc/api-undefined.md#classscy_1_1http_1_1Request) *` | | +--- +#### Parser +```cpp +Parser(llhttp_type_t type) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `type` | `llhttp_type_t` | | -#### `public virtual void onHandshakeComplete()` +--- +#### ~Parser +```cpp +~Parser() +``` +--- +#### parse -#### `protected `[`WebSocketFramer`](./doc/api-http.md#classscy_1_1http_1_1ws_1_1WebSocketFramer)` framer` +```cpp +size_t parse(const char * data, size_t length) +``` +Parse a HTTP packet. +Returns true of the message is complete, false if incomplete. Reset the parser state for a new message +| Parameter | Type | Description | +|-----------|------|-------------| +| `data` | `const char *` | | +| `length` | `size_t` | | +--- -#### `protected `[`http::Request`](./doc/api-http.md#classscy_1_1http_1_1Request)` & _request` +#### reset +```cpp +void reset() +``` +Reset the internal state. +--- +#### complete -#### `protected `[`http::Response`](./doc/api-http.md#classscy_1_1http_1_1Response)` & _response` +```cpp +bool complete() const +``` +Returns true if parsing is complete, either in success or error. +--- +#### upgrade +```cpp +bool upgrade() const +``` -#### `protected virtual ~WebSocketAdapter()` +Returns true if the connection should be upgraded. +--- +#### setRequest +```cpp +void setRequest([http::Request](./doc/api-undefined.md#classscy_1_1http_1_1Request) * request) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `request` | `[http::Request](./doc/api-undefined.md#classscy_1_1http_1_1Request) *` | | -# class `scy::http::ws::WebSocketFramer` +--- +#### setResponse +```cpp +void setResponse([http::Response](./doc/api-undefined.md#classscy_1_1http_1_1Response) * response) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `response` | `[http::Response](./doc/api-undefined.md#classscy_1_1http_1_1Response) *` | | -This class implements a [WebSocket](#classscy_1_1http_1_1ws_1_1WebSocket) parser according to the [WebSocket](#classscy_1_1http_1_1ws_1_1WebSocket) protocol described in RFC 6455. +--- -## Summary +#### setObserver - Members | Descriptions ---------------------------------|--------------------------------------------- -`public WebSocketFramer(`[`ws::Mode`](#group__http_1gaa9edb02676fb90927487e1de2afa287e)` mode)` | Creates a Socket using the given Socket. -`public virtual ~WebSocketFramer()` | -`public virtual size_t writeFrame(const char * data,size_t len,int flags,`[`BitWriter`](#classscy_1_1BitWriter)` & frame)` | Writes a [WebSocket](./doc/api-http.md#classscy_1_1http_1_1ws_1_1WebSocket) protocol frame from the given data. -`public virtual uint64_t readFrame(`[`BitReader`](#classscy_1_1BitReader)` & frame,char *& payload)` | -`public bool handshakeComplete() const` | -`public void acceptServerRequest(`[`http::Request`](#classscy_1_1http_1_1Request)` & request,`[`http::Response`](#classscy_1_1http_1_1Response)` & response)` | [Server](./doc/api-http.md#classscy_1_1http_1_1Server) side. -`public void createClientHandshakeRequest(`[`http::Request`](#classscy_1_1http_1_1Request)` & request)` | [Client](./doc/api-http.md#classscy_1_1http_1_1Client) side. -`public bool checkClientHandshakeResponse(`[`http::Response`](#classscy_1_1http_1_1Response)` & response)` | -`public void completeClientHandshake(`[`http::Response`](#classscy_1_1http_1_1Response)` & response)` | Verifies the handshake response or thrown and exception. -`protected int frameFlags() const` | -`protected bool mustMaskPayload() const` | -`protected `[`ws::Mode`](#group__http_1gaa9edb02676fb90927487e1de2afa287e)` mode() const` | +```cpp +void setObserver([ParserObserver](#classscy_1_1http_1_1ParserObserver) * observer) +``` -## Members +| Parameter | Type | Description | +|-----------|------|-------------| +| `observer` | `[ParserObserver](#classscy_1_1http_1_1ParserObserver) *` | | -#### `public WebSocketFramer(`[`ws::Mode`](#group__http_1gaa9edb02676fb90927487e1de2afa287e)` mode)` +--- -Creates a Socket using the given Socket. +#### message +```cpp +[http::Message](#classscy_1_1http_1_1Message) * message() +``` +--- -#### `public virtual ~WebSocketFramer()` +#### observer +```cpp +[ParserObserver](#classscy_1_1http_1_1ParserObserver) * observer() const +``` +--- +#### _observer +```cpp +[ParserObserver](#classscy_1_1http_1_1ParserObserver) * _observer +``` -#### `public virtual size_t writeFrame(const char * data,size_t len,int flags,`[`BitWriter`](#classscy_1_1BitWriter)` & frame)` +--- -Writes a [WebSocket](#classscy_1_1http_1_1ws_1_1WebSocket) protocol frame from the given data. +#### _request +```cpp +[http::Request](./doc/api-undefined.md#classscy_1_1http_1_1Request) * _request +``` +--- -#### `public virtual uint64_t readFrame(`[`BitReader`](#classscy_1_1BitReader)` & frame,char *& payload)` +#### _response +```cpp +[http::Response](./doc/api-undefined.md#classscy_1_1http_1_1Response) * _response +``` +--- -Reads a single [WebSocket](#classscy_1_1http_1_1ws_1_1WebSocket) frame from the given buffer (frame). +#### _message -The actual payload length is returned, and the beginning of the payload buffer will be assigned in the second (payload) argument. No data is copied. +```cpp +[http::Message](#classscy_1_1http_1_1Message) * _message +``` -If the frame is invalid or too big an exception will be thrown. Return true when the handshake has completed successfully. +--- -#### `public bool handshakeComplete() const` +#### _parser +```cpp +llhttp_t _parser +``` +--- +#### _settings +```cpp +llhttp_settings_t _settings +``` -#### `public void acceptServerRequest(`[`http::Request`](#classscy_1_1http_1_1Request)` & request,`[`http::Response`](#classscy_1_1http_1_1Response)` & response)` +--- -[Server](#classscy_1_1http_1_1Server) side. +#### _type +```cpp +llhttp_type_t _type +``` +--- -#### `public void createClientHandshakeRequest(`[`http::Request`](#classscy_1_1http_1_1Request)` & request)` +#### _wasHeaderValue -[Client](#classscy_1_1http_1_1Client) side. +```cpp +bool _wasHeaderValue +``` -Sends the initial WS handshake HTTP request. void sendHandshakeRequest(); Appends the WS hanshake HTTP request hearers. +--- -#### `public bool checkClientHandshakeResponse(`[`http::Response`](#classscy_1_1http_1_1Response)` & response)` +#### _lastHeaderField +```cpp +std::string _lastHeaderField +``` +--- -Checks the veracity the HTTP handshake response. Returns true on success, false if the request should be resent (in case of authentication), or throws on error. +#### _lastHeaderValue -#### `public void completeClientHandshake(`[`http::Response`](#classscy_1_1http_1_1Response)` & response)` +```cpp +std::string _lastHeaderValue +``` -Verifies the handshake response or thrown and exception. +--- +#### _complete +```cpp +bool _complete +``` -#### `protected int frameFlags() const` +--- +#### _upgrade +```cpp +bool _upgrade +``` -Returns the frame flags of the most recently received frame. Set by [readFrame()](#group__http_1ga9088a641582a5c63bf051b85a10c510b) +--- -#### `protected bool mustMaskPayload() const` +#### _error +```cpp +[Error](./doc/api-base.md#structscy_1_1Error) _error +``` +--- -Returns true if the payload must be masched. Used by [writeFrame()](#group__http_1ga14798654e2c7216c3fddc827944f5482) +#### init -#### `protected `[`ws::Mode`](#group__http_1gaa9edb02676fb90927487e1de2afa287e)` mode() const` +```cpp +void init() +``` +--- +#### onURL +```cpp +void onURL(const std::string & value) +``` +Callbacks. -# struct `scy::http::FormWriter::Part` +| Parameter | Type | Description | +|-----------|------|-------------| +| `value` | `const std::string &` | | +--- +#### onHeader +```cpp +void onHeader(const std::string & name, const std::string & value) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | +| `value` | `const std::string &` | | +--- -## Summary +#### onHeadersEnd - Members | Descriptions ---------------------------------|--------------------------------------------- -`public std::string name` | -`public `[`FormPart`](./doc/api-http.md#classscy_1_1http_1_1FormPart)` * part` | +```cpp +void onHeadersEnd() +``` -## Members +--- -#### `public std::string name` +#### onBody +```cpp +void onBody(const char * buf, size_t len) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `buf` | `const char *` | | +| `len` | `size_t` | | +--- +#### onMessageEnd -#### `public `[`FormPart`](./doc/api-http.md#classscy_1_1http_1_1FormPart)` * part` +```cpp +void onMessageEnd() +``` +--- +#### onError +```cpp +void onError(llhttp_errno_t errnum, const std::string & message) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `errnum` | `llhttp_errno_t` | | +| `message` | `const std::string &` | | diff --git a/doc/api-json.md b/doc/api-json.md index 382d018a6..5dcc3f6dc 100644 --- a/doc/api-json.md +++ b/doc/api-json.md @@ -1,204 +1,295 @@ -# Module `json` +# json +### Classes +| Name | Description | +|------|-------------| +| [`Configuration`](#classscy_1_1json_1_1Configuration) | JSON configuration file | +| [`ISerializable`](#classscy_1_1json_1_1ISerializable) | | -## Summary +### Members - Members | Descriptions ---------------------------------|--------------------------------------------- -`namespace `[`scy::json`](#namespacescy_1_1json) | -# namespace `scy::json` +| Name | Description | +|------|-------------| +| [`JSON_API`](#group__json_1ga1d61ffde86ce1a18fd83194ff0d9a206) | | +--- +#### JSON_API -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`class `[`scy::json::Configuration`](#classscy_1_1json_1_1Configuration) | -`class `[`scy::json::ISerializable`](#classscy_1_1json_1_1ISerializable) | -# class `scy::json::Configuration` - +```cpp +JSON_API() ``` -class scy::json::Configuration - : public scy::Configuration -``` +## Configuration +> **Extends:** `scy::Configuration` +> **Defined in:** `configuration.h` JSON configuration file See base [Configuration](#classscy_1_1json_1_1Configuration) for all accessors -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public json::value root` | -`public Configuration()` | -`public virtual ~Configuration()` | Destroys the [Configuration](./doc/api-json.md#classscy_1_1json_1_1Configuration). -`public virtual void load(const std::string & path,bool create)` | -`public virtual void load(bool create)` | -`public virtual void save()` | -`public virtual bool remove(const std::string & key)` | -`public virtual void removeAll(const std::string & baseKey)` | -`public virtual void replace(const std::string & from,const std::string & to)` | -`public virtual void keys(std::vector< std::string > & keys,const std::string & baseKey)` | -`public virtual void print(std::ostream & ost)` | -`public virtual std::string path()` | -`public virtual bool loaded()` | -`protected bool _loaded` | -`protected std::string _path` | -`protected mutable std::mutex _mutex` | -`protected virtual bool getRaw(const std::string & key,std::string & value) const` | -`protected virtual void setRaw(const std::string & key,const std::string & value)` | - -## Members - -#### `public json::value root` - - - - - -#### `public Configuration()` - - +### Members + +| Name | Description | +|------|-------------| +| [`Configuration`](#group__json_1gac214c65bca41dbeb2b93de599bf33860) | | +| [`~Configuration`](#group__json_1ga041eaafa3e57334159495db3f7c8f31a) | Destroys the [Configuration](#classscy_1_1json_1_1Configuration). | +| [`load`](#group__json_1gaa92c45c4c4628a4edb8a3d7652e07750) | | +| [`load`](#group__json_1ga28c81762c1884c20e06818b09d2ea74a) | | +| [`save`](#group__json_1ga561f1c272c7e613c15b4827b5be26112) | | +| [`remove`](#group__json_1gaf79b732c4b7700e0aa93fe276e7e11d7) | | +| [`removeAll`](#group__json_1gaef6d50b63ce07b1137162050e5181520) | | +| [`replace`](#group__json_1ga81c6e1be7c048f7df27f45b04fe4c80b) | | +| [`keys`](#group__json_1gaeb8525cb4022f0c4925e7152c0153af4) | | +| [`print`](#group__json_1ga248b47860e2324f01700bf297946c5ea) | | +| [`path`](#group__json_1ga6950af9e99dc2356093aed42c82590c6) | | +| [`loaded`](#group__json_1gaf4f7ea24a9de424f59d67691aa5c5f06) | | +| [`getRaw`](#group__json_1ga27463b4236f4ecd5f89e0498f09f2bd5) | If the property with the given key exists, stores the property's value in value and returns true. Otherwise, returns false. | +| [`setRaw`](#group__json_1ga5ac3caa222d6790fbb20813854d75422) | Sets the property with the given key to the given value. An already existing value for the key is overwritten. | +| [`root`](#group__json_1ga01612f32586de58aae915bd75e4108c9) | | +| [`_loaded`](#group__json_1gabec246e99680f82539c83c0f3a6337ee) | | +| [`_path`](#group__json_1gafb9956baead97160a9feb7a1e06d8ae5) | | +| [`_mutex`](#group__json_1ga9d2faff42865fcde1d78319414cc520a) | | + +--- + +#### Configuration + +```cpp +Configuration() +``` +--- +#### ~Configuration -#### `public virtual ~Configuration()` +```cpp +virtual ~Configuration() +``` Destroys the [Configuration](#classscy_1_1json_1_1Configuration). +--- +#### load -#### `public virtual void load(const std::string & path,bool create)` - - - - - -#### `public virtual void load(bool create)` - - - - - -#### `public virtual void save()` - - - - - -#### `public virtual bool remove(const std::string & key)` - - - - - -#### `public virtual void removeAll(const std::string & baseKey)` - - - - - -#### `public virtual void replace(const std::string & from,const std::string & to)` +```cpp +virtual void load(const std::string & path, bool create) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `path` | `const std::string &` | | +| `create` | `bool` | | +--- +#### load +```cpp +virtual void load(bool create) +``` -#### `public virtual void keys(std::vector< std::string > & keys,const std::string & baseKey)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `create` | `bool` | | +--- +#### save +```cpp +virtual void save() +``` +--- -#### `public virtual void print(std::ostream & ost)` +#### remove +```cpp +virtual bool remove(const std::string & key) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `const std::string &` | | +--- +#### removeAll -#### `public virtual std::string path()` +```cpp +virtual void removeAll(const std::string & baseKey) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `baseKey` | `const std::string &` | | +--- +#### replace +```cpp +virtual void replace(const std::string & from, const std::string & to) +``` -#### `public virtual bool loaded()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `from` | `const std::string &` | | +| `to` | `const std::string &` | | +--- +#### keys +```cpp +virtual void keys(std::vector< std::string > & keys, const std::string & baseKey) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `keys` | `std::vector< std::string > &` | | +| `baseKey` | `const std::string &` | | -#### `protected bool _loaded` +--- +#### print +```cpp +virtual void print(std::ostream & ost) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `ost` | `std::ostream &` | | +--- -#### `protected std::string _path` +#### path +```cpp +virtual std::string path() +``` +--- +#### loaded +```cpp +virtual bool loaded() +``` -#### `protected mutable std::mutex _mutex` +--- +#### getRaw +```cpp +virtual bool getRaw(const std::string & key, std::string & value) const +``` +If the property with the given key exists, stores the property's value in value and returns true. Otherwise, returns false. +Must be overridden by subclasses. -#### `protected virtual bool getRaw(const std::string & key,std::string & value) const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `const std::string &` | | +| `value` | `std::string &` | | +--- +#### setRaw -If the property with the given key exists, stores the property's value in value and returns true. Otherwise, returns false. +```cpp +virtual void setRaw(const std::string & key, const std::string & value) +``` -Must be overridden by subclasses. +Sets the property with the given key to the given value. An already existing value for the key is overwritten. -#### `protected virtual void setRaw(const std::string & key,const std::string & value)` +The implementation is responsible for emitting the PropertyChanged signal. +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `const std::string &` | | +| `value` | `const std::string &` | | +--- -Sets the property with the given key to the given value. An already existing value for the key is overwritten. +#### root -The implementation is responsible for emitting the PropertyChanged signal. +```cpp +json::value root +``` -# class `scy::json::ISerializable` +--- +#### _loaded +```cpp +bool _loaded +``` +--- +#### _path +```cpp +std::string _path +``` -## Summary +--- - Members | Descriptions ---------------------------------|--------------------------------------------- -`public inline virtual ~ISerializable()` | -`public void serialize(json::value & root)` | -`public void deserialize(json::value & root)` | +#### _mutex -## Members +```cpp +std::mutex _mutex +``` -#### `public inline virtual ~ISerializable()` +## ISerializable +> **Subclasses:** `scy::sched::Scheduler`, `scy::sched::Task`, `scy::sched::Trigger` +> **Defined in:** `iserializable.h` +### Members +| Name | Description | +|------|-------------| +| [`~ISerializable`](#group__json_1ga7e3dfbdaff8b91b43dfb537330faf659) | | +| [`serialize`](#group__json_1gaaedc895394aa41a56ea12c1640ef3c34) | | +| [`deserialize`](#group__json_1ga033850497ce6bbae62f3690af1bcb10e) | | +--- -#### `public void serialize(json::value & root)` +#### ~ISerializable +```cpp +virtual ~ISerializable() = default +``` +--- +#### serialize +```cpp +void serialize(json::value & root) +``` -#### `public void deserialize(json::value & root)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `root` | `json::value &` | | +--- +#### deserialize +```cpp +void deserialize(json::value & root) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `root` | `json::value &` | | diff --git a/doc/api-net.md b/doc/api-net.md index 2a3b61473..ee5541879 100644 --- a/doc/api-net.md +++ b/doc/api-net.md @@ -1,105 +1,168 @@ -# Module `net` - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`namespace `[`scy::net`](#namespacescy_1_1net) | -`struct `[`scy::net::SocketAdapter::Ref`](#structscy_1_1net_1_1SocketAdapter_1_1Ref) | -# namespace `scy::net` - - - -## Summary +# net + +### Classes + +| Name | Description | +|------|-------------| +| [`Address`](#classscy_1_1net_1_1Address) | | +| [`PacketSocketEmitter`](#classscy_1_1net_1_1PacketSocketEmitter) | | +| [`Socket`](#classscy_1_1net_1_1Socket) | Base socket implementation from which all sockets derive. | +| [`SocketPacket`](#classscy_1_1net_1_1SocketPacket) | [SocketPacket](#classscy_1_1net_1_1SocketPacket) is the default packet type emitted by sockets. [SocketPacket](#classscy_1_1net_1_1SocketPacket) provides peer address information and a buffer reference for nocopy binary operations. | +| [`SocketAdapter`](#classscy_1_1net_1_1SocketAdapter) | [SocketAdapter](#classscy_1_1net_1_1SocketAdapter) is the abstract interface for all socket classes. A [SocketAdapter](#classscy_1_1net_1_1SocketAdapter) can also be attached to a [Socket](#classscy_1_1net_1_1Socket) in order to override default [Socket](#classscy_1_1net_1_1Socket) callbacks and behaviour, while still maintaining the default [Socket](#classscy_1_1net_1_1Socket) interface (see Socket::setAdapter). | +| [`SocketEmitter`](#classscy_1_1net_1_1SocketEmitter) | [SocketAdapter](#classscy_1_1net_1_1SocketAdapter) class that adds signal callbacks for sockets. Asde from adding a signal interface the class works as a wrapper for the socket instance, and is designed to be used the same way as a `std::unique_ptr` by overriding the ->() operator. | +| [`SSLAdapter`](#classscy_1_1net_1_1SSLAdapter) | | +| [`SSLContext`](#classscy_1_1net_1_1SSLContext) | This class encapsulates context information for an SSL server or client, such as the certificate verification mode and the location of certificates and private key files, as well as the list of supported ciphers. | +| [`SSLManager`](#classscy_1_1net_1_1SSLManager) | [SSLManager](#classscy_1_1net_1_1SSLManager) is a singleton for holding the default server/client Context and handling callbacks for certificate verification errors and private key passphrases. | +| [`VerificationErrorDetails`](#classscy_1_1net_1_1VerificationErrorDetails) | A utility class for certificate error handling. | +| [`SSLSession`](#classscy_1_1net_1_1SSLSession) | This class encapsulates a SSL session object used with session caching on the client side. | +| [`SSLSocket`](#classscy_1_1net_1_1SSLSocket) | SSL socket implementation. | +| [`TCPSocket`](#classscy_1_1net_1_1TCPSocket) | TCP socket implementation. | +| [`Transaction`](#classscy_1_1net_1_1Transaction) | This class provides request/response functionality for [IPacket](./doc/api-base.md#classscy_1_1IPacket) types emitted from a [Socket](#classscy_1_1net_1_1Socket). | +| [`UDPSocket`](#classscy_1_1net_1_1UDPSocket) | UDP socket implementation. | +| [`AddressBase`](#classscy_1_1net_1_1AddressBase) | | +| [`IPv4AddressBase`](#classscy_1_1net_1_1IPv4AddressBase) | | +| [`PacketInfo`](#structscy_1_1net_1_1PacketInfo) | Provides information about packets emitted from a socket. See [SocketPacket](#classscy_1_1net_1_1SocketPacket). | +| [`Ref`](#structscy_1_1net_1_1SocketAdapter_1_1Ref) | | + +### Members + +| Name | Description | +|------|-------------| +| [`SCY_HAVE_IPv6`](#group__net_1gab13f08bf90488904c8a33b55bd07d704) | Windows. | +| [`Net_API`](#group__net_1gae68e75c96e9669ffa526fadc5d953721) | Linux. | + +--- + +#### SCY_HAVE_IPv6 + +```cpp +SCY_HAVE_IPv6() +``` - Members | Descriptions ---------------------------------|--------------------------------------------- -`class `[`scy::net::Address`](#classscy_1_1net_1_1Address) | -`class `[`scy::net::AddressBase`](#classscy_1_1net_1_1AddressBase) | -`class `[`scy::net::IPv4AddressBase`](#classscy_1_1net_1_1IPv4AddressBase) | -`class `[`scy::net::PacketSocketEmitter`](#classscy_1_1net_1_1PacketSocketEmitter) | -`class `[`scy::net::Socket`](#classscy_1_1net_1_1Socket) | Base socket implementation from which all sockets derive. -`class `[`scy::net::SocketAdapter`](#classscy_1_1net_1_1SocketAdapter) | -`class `[`scy::net::SocketEmitter`](#classscy_1_1net_1_1SocketEmitter) | [SocketAdapter](#classscy_1_1net_1_1SocketAdapter) class that adds signal callbacks for sockets. -`class `[`scy::net::SocketPacket`](#classscy_1_1net_1_1SocketPacket) | -`class `[`scy::net::SSLAdapter`](#classscy_1_1net_1_1SSLAdapter) | -`class `[`scy::net::SSLContext`](#classscy_1_1net_1_1SSLContext) | -`class `[`scy::net::SSLManager`](#classscy_1_1net_1_1SSLManager) | -`class `[`scy::net::SSLSession`](#classscy_1_1net_1_1SSLSession) | -`class `[`scy::net::SSLSocket`](#classscy_1_1net_1_1SSLSocket) | SSL socket implementation. -`class `[`scy::net::TCPSocket`](#classscy_1_1net_1_1TCPSocket) | TCP socket implementation. -`class `[`scy::net::Transaction`](#classscy_1_1net_1_1Transaction) | -`class `[`scy::net::UDPSocket`](#classscy_1_1net_1_1UDPSocket) | UDP socket implementation. -`class `[`scy::net::VerificationErrorDetails`](#classscy_1_1net_1_1VerificationErrorDetails) | A utility class for certificate error handling. -`struct `[`scy::net::GetAddrInfoEvent`](#structscy_1_1net_1_1GetAddrInfoEvent) | Get address info request callback event. -`struct `[`scy::net::GetAddrInfoReq`](#structscy_1_1net_1_1GetAddrInfoReq) | DNS resolver request to get the IP address of a hostname. -`struct `[`scy::net::PacketInfo`](#structscy_1_1net_1_1PacketInfo) | -# class `scy::net::Address` +Windows. +--- +#### Net_API +```cpp +Net_API() +``` +Linux. + +## Address + +> **Defined in:** `address.h` + +### Members + +| Name | Description | +|------|-------------| +| [`Family`](#group__net_1gaf91e77d155f2852974bbae5a2da34106) | Possible address families for IP addresses. | +| [`Address`](#group__net_1ga4376b5c4c7a0390b9148741c61331775) | Creates a wildcard (all zero) IPv4 [Address](#classscy_1_1net_1_1Address). | +| [`Address`](#group__net_1ga9738fe42686a855ffaa0ceb14541c42c) | Creates a [Address](#classscy_1_1net_1_1Address) from an IP address and a port number. | +| [`Address`](#group__net_1ga1ebca1dc763be19d20ec69be97bbb3d7) | Creates a [Address](#classscy_1_1net_1_1Address) by copying another one. | +| [`Address`](#group__net_1gac57cc836572c64291fe739745be8e25e) | Creates a [Address](#classscy_1_1net_1_1Address) from a native socket address. | +| [`Address`](#group__net_1gacde53f645ce818600709e240dbf510eb) | Creates a [Address](#classscy_1_1net_1_1Address) from an IP address and a service name or port number. | +| [`Address`](#group__net_1ga94e2bed4c55e369c97a2d229d2b591e6) | Creates a [Address](#classscy_1_1net_1_1Address) from an IP address or host name and a port number/service name. Host name/address and port number must be separated by a colon. In case of an IPv6 address, the address part must be enclosed in brackets. | +| [`~Address`](#group__net_1ga5b9e05ed6187c478f65d0d57ad4cdb35) | Destroys the [Address](#classscy_1_1net_1_1Address). | +| [`operator=`](#group__net_1ga3b3ec108da40cf5fafd15cc21b4388bd) | Assigns another [Address](#classscy_1_1net_1_1Address). | +| [`swap`](#group__net_1ga877434e8e2b5a266d99f9f35be0882b0) | Swaps the [Address](#classscy_1_1net_1_1Address) with another one. | +| [`host`](#group__net_1gad8fbd6353a1f03ef3e0346ef1be64800) | Returns the host IP address. | +| [`port`](#group__net_1ga36e14fd72aceb8470cb7e6d2931ca622) | Returns the port number. | +| [`length`](#group__net_1ga474b01eea594bde98f3dca27ca6d09bd) | Returns the length of the internal native socket address. | +| [`addr`](#group__net_1ga6ea740a58361a1e81ed6319d6529dcf4) | Returns a pointer to the internal native socket address. | +| [`af`](#group__net_1gac1036c47a13a55df8cae09cf4ca82137) | Returns the address family (AF_INET or AF_INET6) of the address. | +| [`toString`](#group__net_1gacc785d126d40fabb5af3e6f71c835084) | Returns a string representation of the address. | +| [`family`](#group__net_1ga7683b700d696248f25f2a125a1e0f645) | Returns the address family of the host's address. | +| [`valid`](#group__net_1ga657136484ebe9fedce2ce01cb5c4497e) | Returns true when the port is set and the address is valid ie. not wildcard. | +| [`operator<`](#group__net_1ga7a1cc2425e33d40740dd5d706de9ebd6) | | +| [`operator==`](#group__net_1gaa0f9e31b04a54f297c6b970ad8c6719f) | | +| [`operator!=`](#group__net_1gadf21121f417c9ef8ea3ebd441e6ee72e) | | +| [`resolveService`](#group__net_1gaef529a989e8e83bfab2cf62b87e6f024) | | +| [`validateIP`](#group__net_1gabe7ed7441d105e3a4b878594a2d051c1) | | +| [`init`](#group__net_1ga945edbcf0846406f0ef4e2a09dcf43cf) | | +| [`_base`](#group__net_1gacff7149edafcdf3b5879a7211175c5b7) | | + +--- + +#### Family + +```cpp +enum Family +``` +Possible address families for IP addresses. -## Summary +| Value | Description | +|-------|-------------| +| `IPv4` | | +| `IPv6` | | - Members | Descriptions ---------------------------------|--------------------------------------------- -`public Address()` | Creates a wildcard (all zero) IPv4 [Address](./doc/api-net.md#classscy_1_1net_1_1Address). -`public Address(const std::string & host,uint16_t port)` | -`public Address(const `[`Address`](#classscy_1_1net_1_1Address)` & addr)` | Creates a [Address](./doc/api-net.md#classscy_1_1net_1_1Address) by copying another one. -`public Address(const struct sockaddr * addr,socklen_t length)` | Creates a [Address](./doc/api-net.md#classscy_1_1net_1_1Address) from a native socket address. -`public Address(const std::string & host,const std::string & port)` | -`public explicit Address(const std::string & hostAndPort)` | -`public ~Address()` | Destroys the [Address](./doc/api-net.md#classscy_1_1net_1_1Address). -`public `[`Address`](#classscy_1_1net_1_1Address)` & operator=(const `[`Address`](#classscy_1_1net_1_1Address)` & addr)` | Assigns another [Address](./doc/api-net.md#classscy_1_1net_1_1Address). -`public void swap(`[`Address`](#classscy_1_1net_1_1Address)` & addr)` | Swaps the [Address](./doc/api-net.md#classscy_1_1net_1_1Address) with another one. -`public std::string host() const` | Returns the host IP address. -`public uint16_t port() const` | Returns the port number. -`public socklen_t length() const` | Returns the length of the internal native socket address. -`public const struct sockaddr * addr() const` | Returns a pointer to the internal native socket address. -`public int af() const` | Returns the address family (AF_INET or AF_INET6) of the address. -`public std::string toString() const` | Returns a string representation of the address. -`public `[`Address::Family`](#group__net_1gaf91e77d155f2852974bbae5a2da34106)` family() const` | Returns the address family of the host's address. -`public bool valid() const` | -`public bool operator<(const `[`Address`](#classscy_1_1net_1_1Address)` & addr) const` | -`public bool operator==(const `[`Address`](#classscy_1_1net_1_1Address)` & addr) const` | -`public bool operator!=(const `[`Address`](#classscy_1_1net_1_1Address)` & addr) const` | -`protected void init(const std::string & host,uint16_t port)` | +--- -## Members +#### Address -#### `public Address()` +```cpp +Address() +``` Creates a wildcard (all zero) IPv4 [Address](#classscy_1_1net_1_1Address). +--- +#### Address -#### `public Address(const std::string & host,uint16_t port)` - - +```cpp +Address(const std::string & host, uint16_t port) +``` Creates a [Address](#classscy_1_1net_1_1Address) from an IP address and a port number. The IP address must either be a domain name, or it must be in dotted decimal (IPv4) or hex string (IPv6) format. -#### `public Address(const `[`Address`](#classscy_1_1net_1_1Address)` & addr)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `host` | `const std::string &` | | +| `port` | `uint16_t` | | + +--- + +#### Address + +```cpp +Address(const Address & addr) +``` Creates a [Address](#classscy_1_1net_1_1Address) by copying another one. +| Parameter | Type | Description | +|-----------|------|-------------| +| `addr` | `const Address &` | | +--- -#### `public Address(const struct sockaddr * addr,socklen_t length)` +#### Address -Creates a [Address](#classscy_1_1net_1_1Address) from a native socket address. +```cpp +Address(const struct sockaddr * addr, socklen_t length) +``` +Creates a [Address](#classscy_1_1net_1_1Address) from a native socket address. +| Parameter | Type | Description | +|-----------|------|-------------| +| `addr` | `const struct sockaddr *` | | +| `length` | `socklen_t` | | -#### `public Address(const std::string & host,const std::string & port)` +--- +#### Address +```cpp +Address(const std::string & host, const std::string & port) +``` Creates a [Address](#classscy_1_1net_1_1Address) from an IP address and a service name or port number. @@ -107,9 +170,18 @@ The IP address must either be a domain name, or it must be in dotted decimal (IP The given port must either be a decimal port number, or a service name. -#### `public explicit Address(const std::string & hostAndPort)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `host` | `const std::string &` | | +| `port` | `const std::string &` | | +--- +#### Address + +```cpp +explicit Address(const std::string & hostAndPort) +``` Creates a [Address](#classscy_1_1net_1_1Address) from an IP address or host name and a port number/service name. Host name/address and port number must be separated by a colon. In case of an IPv6 address, the address part must be enclosed in brackets. @@ -117,1454 +189,2468 @@ Examples: 192.168.1.10:80 www.sourcey.com:8080 -#### `public ~Address()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `hostAndPort` | `const std::string &` | | + +--- + +#### ~Address + +```cpp +~Address() +``` Destroys the [Address](#classscy_1_1net_1_1Address). +--- +#### operator= -#### `public `[`Address`](#classscy_1_1net_1_1Address)` & operator=(const `[`Address`](#classscy_1_1net_1_1Address)` & addr)` +```cpp +Address & operator=(const Address & addr) +``` Assigns another [Address](#classscy_1_1net_1_1Address). +| Parameter | Type | Description | +|-----------|------|-------------| +| `addr` | `const Address &` | | + +--- +#### swap -#### `public void swap(`[`Address`](#classscy_1_1net_1_1Address)` & addr)` +```cpp +void swap(Address & addr) +``` Swaps the [Address](#classscy_1_1net_1_1Address) with another one. +| Parameter | Type | Description | +|-----------|------|-------------| +| `addr` | `Address &` | | + +--- +#### host -#### `public std::string host() const` +```cpp +std::string host() const +``` Returns the host IP address. +--- +#### port -#### `public uint16_t port() const` +```cpp +uint16_t port() const +``` Returns the port number. +--- +#### length -#### `public socklen_t length() const` +```cpp +socklen_t length() const +``` Returns the length of the internal native socket address. +--- +#### addr -#### `public const struct sockaddr * addr() const` +```cpp +const struct sockaddr * addr() const +``` Returns a pointer to the internal native socket address. +--- +#### af -#### `public int af() const` +```cpp +int af() const +``` Returns the address family (AF_INET or AF_INET6) of the address. +--- +#### toString -#### `public std::string toString() const` +```cpp +std::string toString() const +``` Returns a string representation of the address. +--- +#### family -#### `public `[`Address::Family`](#group__net_1gaf91e77d155f2852974bbae5a2da34106)` family() const` +```cpp +Address::Family family() const +``` Returns the address family of the host's address. +--- +#### valid -#### `public bool valid() const` +```cpp +bool valid() const +``` +Returns true when the port is set and the address is valid ie. not wildcard. +--- -Returns true when the port is set and the address is valid ie. not wildcard. +#### operator< -#### `public bool operator<(const `[`Address`](#classscy_1_1net_1_1Address)` & addr) const` +```cpp +bool operator<(const Address & addr) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `addr` | `const Address &` | | +--- +#### operator== +```cpp +bool operator==(const Address & addr) const +``` -#### `public bool operator==(const `[`Address`](#classscy_1_1net_1_1Address)` & addr) const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `addr` | `const Address &` | | +--- +#### operator!= +```cpp +bool operator!=(const Address & addr) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `addr` | `const Address &` | | -#### `public bool operator!=(const `[`Address`](#classscy_1_1net_1_1Address)` & addr) const` +--- +#### resolveService +```cpp +static uint16_t resolveService(const std::string & service) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `service` | `const std::string &` | | +--- -#### `protected void init(const std::string & host,uint16_t port)` +#### validateIP +```cpp +static bool validateIP(const std::string & address) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `address` | `const std::string &` | | +--- +#### init -# class `scy::net::AddressBase` +```cpp +void init(const std::string & host, uint16_t port) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `host` | `const std::string &` | | +| `port` | `uint16_t` | | +--- +#### _base +```cpp +std::shared_ptr< AddressBase > _base +``` +## PacketSocketEmitter -## Summary +> **Extends:** `scy::net::SocketEmitter`, `scy::Signal< void(IPacket &)>` +> **Subclasses:** `scy::net::Transaction< Message >`, `scy::net::Transaction< PacketT >` +> **Defined in:** `packetsocket.h` - Members | Descriptions ---------------------------------|--------------------------------------------- -`public std::string host() const` | -`public uint16_t port() const` | -`public `[`Address::Family`](#group__net_1gaf91e77d155f2852974bbae5a2da34106)` family() const` | -`public socklen_t length() const` | -`public const struct sockaddr * addr() const` | -`public int af() const` | -`protected inline AddressBase()` | -`protected inline virtual ~AddressBase()` | +### Members -## Members +| Name | Description | +|------|-------------| +| [`PacketSocketEmitter`](#group__net_1ga3140a2a25a6ce7db74108f3111235015) | Creates the [PacketSocketEmitter](#classscy_1_1net_1_1PacketSocketEmitter) This class should have a higher priority than standard sockets so we can parse data packets first. Creates and dispatches a packet utilizing the available creation strategies. For best performance the most used strategies should have the highest priority. | +| [`~PacketSocketEmitter`](#group__net_1ga9d770233ff68edeace9e64b262a61abc) | | +| [`onSocketRecv`](#group__net_1gadc517059efc11e7b96c9aac48d3621f4) | | +| [`onPacket`](#group__net_1ga0de3859d43f868dbbdb88fda6e713092) | | +| [`factory`](#group__net_1gaed6e38fcedd99dba4ad9cb4aee59b071) | The packet factory. | -#### `public std::string host() const` +--- +#### PacketSocketEmitter +```cpp +PacketSocketEmitter(const Socket::Ptr & socket) +``` +Creates the [PacketSocketEmitter](#classscy_1_1net_1_1PacketSocketEmitter) This class should have a higher priority than standard sockets so we can parse data packets first. Creates and dispatches a packet utilizing the available creation strategies. For best performance the most used strategies should have the highest priority. +| Parameter | Type | Description | +|-----------|------|-------------| +| `socket` | `const Socket::Ptr &` | | -#### `public uint16_t port() const` +--- +#### ~PacketSocketEmitter +```cpp +virtual ~PacketSocketEmitter() +``` +--- +#### onSocketRecv -#### `public `[`Address::Family`](#group__net_1gaf91e77d155f2852974bbae5a2da34106)` family() const` +```cpp +virtual void onSocketRecv(Socket & socket, const MutableBuffer & buffer, const Address & peerAddress) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `socket` | `Socket &` | | +| `buffer` | `const MutableBuffer &` | | +| `peerAddress` | `const Address &` | | +--- +#### onPacket +```cpp +virtual void onPacket(IPacket & pkt) +``` -#### `public socklen_t length() const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `pkt` | `IPacket &` | | +--- +#### factory +```cpp +PacketFactory factory +``` +The packet factory. -#### `public const struct sockaddr * addr() const` +## Socket +> **Extends:** `scy::net::SocketAdapter` +> **Subclasses:** `scy::net::TCPSocket`, `scy::net::UDPSocket` +> **Defined in:** `socket.h` +Base socket implementation from which all sockets derive. +### Members + +| Name | Description | +|------|-------------| +| [`Socket`](#group__net_1ga0d1fd3c6568df4d23baf8bac3443b031) | | +| [`~Socket`](#group__net_1ga6d1ec3118de86711205b220fae9228c5) | | +| [`connect`](#group__net_1ga26b4c04fb14fb521c3777966f5500814) | Connects to the given peer IP address. | +| [`connect`](#group__net_1gad8ed2e347065221848364977f3f4b0ad) | Resolves and connects to the given host address. | +| [`bind`](#group__net_1gad12fbab04fa447ab0104325d7062af03) | Bind a local address to the socket. The address may be IPv4 or IPv6 (if supported). | +| [`listen`](#group__net_1ga3f113f66f6dcbb1fc2a2c25a86833eaa) | Listens the socket on the given address. | +| [`shutdown`](#group__net_1ga68cca230e61d94ddcb530c8236b8b65a) | Sends the shutdown packet which should result is socket closure via callback. | +| [`close`](#group__net_1gaef3e9d763d40129224c70087c0b8660b) | Closes the underlying socket. | +| [`address`](#group__net_1gadb57bf71ea7475434e304193495a22f8) | The locally bound address. | +| [`peerAddress`](#group__net_1gaa7aad8f6cdfc70fd2d993cc99e65f73c) | The connected peer address. | +| [`transport`](#group__net_1ga1e1b0fbbf92bb3dd962783a8c0e94b3d) | The transport protocol: TCP, UDP or SSLTCP. | +| [`setError`](#group__net_1gaed1d2e8ca6eb5140528c044b675299b4) | Sets the socket error. | +| [`error`](#group__net_1gad2a2feb9ea2e6069d6f7b283b44b2e34) | Return the socket error if any. | +| [`closed`](#group__net_1ga9bf8cf75403f7f833c37ed7fb16443a6) | Returns true if the native socket handle is closed. | +| [`loop`](#group__net_1ga1c0302f62375661291b891972a178b09) | Returns the socket event loop. | +| [`init`](#group__net_1ga0b9b76689ad2ca6a398e909a5424c24b) | Initializes the underlying socket context. | +| [`reset`](#group__net_1ga07e4b137f7019e83ce21fcd2441ddc9b) | Resets the socket context for reuse. | +| [`opaque`](#group__net_1ga1379e3c59f9934f2b2668a5014ab6d6c) | Optional client data pointer. | +| [`_af`](#group__net_1gae27f31658bb7c71f26afd113b066465a) | | + +--- + +#### Socket + +```cpp +Socket() = default +``` +--- -#### `public int af() const` +#### ~Socket +```cpp +virtual ~Socket() = default +``` +--- +#### connect +```cpp +void connect(const Address & address) +``` -#### `protected inline AddressBase()` +Connects to the given peer IP address. +Throws an exception if the address is malformed. Connection errors can be handled via the [Error](./doc/api-base.md#structscy_1_1Error) signal. +| Parameter | Type | Description | +|-----------|------|-------------| +| `address` | `const Address &` | | +--- +#### connect -#### `protected inline virtual ~AddressBase()` +```cpp +void connect(const std::string & host, uint16_t port) +``` +Resolves and connects to the given host address. +Throws an Exception if the host is malformed. Since the DNS callback is asynchronous implementations need to listen for the [Error](./doc/api-base.md#structscy_1_1Error) signal for handling connection errors. +| Parameter | Type | Description | +|-----------|------|-------------| +| `host` | `const std::string &` | | +| `port` | `uint16_t` | | +--- -# class `scy::net::IPv4AddressBase` +#### bind +```cpp +void bind(const Address & address, unsigned flags) ``` -class scy::net::IPv4AddressBase - : public scy::net::AddressBase -``` +Bind a local address to the socket. The address may be IPv4 or IPv6 (if supported). + +Throws an Exception on error. + +| Parameter | Type | Description | +|-----------|------|-------------| +| `address` | `const Address &` | | +| `flags` | `unsigned` | | +--- +#### listen +```cpp +virtual inline void listen(int backlog) +``` -## Summary +Listens the socket on the given address. - Members | Descriptions ---------------------------------|--------------------------------------------- -`public inline IPv4AddressBase()` | -`public inline IPv4AddressBase(const struct sockaddr_in * addr)` | -`public inline IPv4AddressBase(const void * addr,uint16_t port)` | -`public inline virtual std::string host() const` | -`public inline virtual uint16_t port() const` | -`public inline virtual `[`Address::Family`](#group__net_1gaf91e77d155f2852974bbae5a2da34106)` family() const` | -`public inline virtual socklen_t length() const` | -`public inline virtual const struct sockaddr * addr() const` | -`public inline virtual int af() const` | +Throws an Exception on error. -## Members +| Parameter | Type | Description | +|-----------|------|-------------| +| `backlog` | `int` | | -#### `public inline IPv4AddressBase()` +--- +#### shutdown +```cpp +virtual inline bool shutdown() +``` +Sends the shutdown packet which should result is socket closure via callback. +--- -#### `public inline IPv4AddressBase(const struct sockaddr_in * addr)` +#### close +```cpp +void close() +``` +Closes the underlying socket. +--- +#### address -#### `public inline IPv4AddressBase(const void * addr,uint16_t port)` +```cpp +Address address() const +``` +The locally bound address. +This function will not throw. A Wildcard 0.0.0.0:0 address is returned if the socket is closed or invalid. +--- +#### peerAddress -#### `public inline virtual std::string host() const` +```cpp +Address peerAddress() const +``` +The connected peer address. +This function will not throw. A Wildcard 0.0.0.0:0 address is returned if the socket is closed or invalid. +--- +#### transport -#### `public inline virtual uint16_t port() const` +```cpp +net::TransportType transport() const +``` +The transport protocol: TCP, UDP or SSLTCP. +--- +#### setError +```cpp +void setError(const [scy::Error](./doc/api-base.md#structscy_1_1Error) & err) +``` -#### `public inline virtual `[`Address::Family`](#group__net_1gaf91e77d155f2852974bbae5a2da34106)` family() const` +Sets the socket error. +Setting the error will result in socket closure. +| Parameter | Type | Description | +|-----------|------|-------------| +| `err` | `const [scy::Error](./doc/api-base.md#structscy_1_1Error) &` | | +--- +#### error -#### `public inline virtual socklen_t length() const` +```cpp +const [scy::Error](./doc/api-base.md#structscy_1_1Error) & error() const +``` +Return the socket error if any. +--- +#### closed +```cpp +bool closed() const +``` -#### `public inline virtual const struct sockaddr * addr() const` +Returns true if the native socket handle is closed. +--- +#### loop +```cpp +uv::Loop * loop() const +``` +Returns the socket event loop. -#### `public inline virtual int af() const` +--- +#### init +```cpp +void init() +``` +Initializes the underlying socket context. +--- -# class `scy::net::PacketSocketEmitter` +#### reset +```cpp +void reset() ``` -class scy::net::PacketSocketEmitter - : public scy::net::SocketEmitter - : public scy::Signal< void(IPacket &)> -``` +Resets the socket context for reuse. + +--- +#### opaque +```cpp +void * opaque { nullptr } +``` +Optional client data pointer. -## Summary +The pointer is set to null on initialization but not managed. - Members | Descriptions ---------------------------------|--------------------------------------------- -`public `[`PacketFactory`](./doc/api-base.md#classscy_1_1PacketFactory)` factory` | The packet factory. -`public PacketSocketEmitter(const Socket::Ptr & socket)` | -`public virtual ~PacketSocketEmitter()` | -`public virtual void onSocketRecv(`[`Socket`](#classscy_1_1net_1_1Socket)` & socket,const `[`MutableBuffer`](#classscy_1_1MutableBuffer)` & buffer,const `[`Address`](#classscy_1_1net_1_1Address)` & peerAddress)` | -`public virtual void onPacket(`[`IPacket`](#classscy_1_1IPacket)` & pkt)` | +--- -## Members +#### _af -#### `public `[`PacketFactory`](./doc/api-base.md#classscy_1_1PacketFactory)` factory` +```cpp +int _af { AF_UNSPEC } +``` -The packet factory. +## SocketPacket +> **Extends:** `scy::RawPacket` +> **Defined in:** `socket.h` +[SocketPacket](#classscy_1_1net_1_1SocketPacket) is the default packet type emitted by sockets. [SocketPacket](#classscy_1_1net_1_1SocketPacket) provides peer address information and a buffer reference for nocopy binary operations. -#### `public PacketSocketEmitter(const Socket::Ptr & socket)` +The referenced packet buffer lifetime is only guaranteed for the duration of the receiver callback. +### Members +| Name | Description | +|------|-------------| +| [`SocketPacket`](#group__net_1gaec154054d8c54269655aa062d8fe1ffd) | | +| [`SocketPacket`](#group__net_1gad327456520e77574cd3cb730ccc0a75a) | | +| [`packetInfo`](#group__net_1gaf192ea8a4488fdb7ff04961999496954) | Returns the [PacketInfo](#structscy_1_1net_1_1PacketInfo) for this socket packet. | +| [`~SocketPacket`](#group__net_1ga3e883a20f382b845e90c1047e8ff03f1) | | +| [`print`](#group__net_1ga319694029ed98f048cdaf68330e31807) | | +| [`clone`](#group__net_1gad4dc225d63a642fb0eb1b43c271c796c) | | +| [`read`](#group__net_1gae771cf7b5b4a141bb898acb1cafddc62) | Read/parse to the packet from the given input buffer. The number of bytes read is returned. | +| [`write`](#group__net_1gaac943003d23e0dbbedbf120a45ab3078) | Copy/generate to the packet given output buffer. The number of bytes written can be obtained from the buffer. | +| [`className`](#group__net_1ga69704ee8a377cbcd6e06ec3d44d93a24) | | -Creates the [PacketSocketEmitter](#classscy_1_1net_1_1PacketSocketEmitter) This class should have a higher priority than standard sockets so we can parse data packets first. Creates and dispatches a packet utilizing the available creation strategies. For best performance the most used strategies should have the highest priority. +--- -#### `public virtual ~PacketSocketEmitter()` +#### SocketPacket +```cpp +inline SocketPacket(const Socket::Ptr & socket, const MutableBuffer & buffer, const Address & peerAddress) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `socket` | `const Socket::Ptr &` | | +| `buffer` | `const MutableBuffer &` | | +| `peerAddress` | `const Address &` | | +--- +#### SocketPacket -#### `public virtual void onSocketRecv(`[`Socket`](#classscy_1_1net_1_1Socket)` & socket,const `[`MutableBuffer`](#classscy_1_1MutableBuffer)` & buffer,const `[`Address`](#classscy_1_1net_1_1Address)` & peerAddress)` +```cpp +inline SocketPacket(const SocketPacket & that) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `that` | `const SocketPacket &` | | +--- +#### packetInfo +```cpp +inline PacketInfo * packetInfo() const +``` -#### `public virtual void onPacket(`[`IPacket`](#classscy_1_1IPacket)` & pkt)` +Returns the [PacketInfo](#structscy_1_1net_1_1PacketInfo) for this socket packet. +--- +#### ~SocketPacket +```cpp +virtual inline ~SocketPacket() +``` +--- -# class `scy::net::Socket` +#### print +```cpp +virtual inline void print(std::ostream & os) const ``` -class scy::net::Socket - : public scy::net::SocketAdapter -``` -Base socket implementation from which all sockets derive. +| Parameter | Type | Description | +|-----------|------|-------------| +| `os` | `std::ostream &` | | +--- +#### clone -## Summary +```cpp +virtual inline IPacket * clone() const +``` - Members | Descriptions ---------------------------------|--------------------------------------------- -`public void * opaque` | -`public Socket() = default` | -`public virtual ~Socket() = default` | -`public void connect(const `[`Address`](#classscy_1_1net_1_1Address)` & address)` | -`public void connect(const std::string & host,uint16_t port)` | -`public void bind(const `[`Address`](#classscy_1_1net_1_1Address)` & address,unsigned flags)` | -`public inline virtual void listen(int backlog)` | -`public inline virtual bool shutdown()` | -`public void close()` | Closes the underlying socket. -`public `[`Address`](#classscy_1_1net_1_1Address)` address() const` | -`public `[`Address`](#classscy_1_1net_1_1Address)` peerAddress() const` | -`public net::TransportType transport() const` | The transport protocol: TCP, UDP or SSLTCP. -`public void setError(const `[`scy::Error`](#structscy_1_1Error)` & err)` | -`public const `[`scy::Error`](#structscy_1_1Error)` & error() const` | Return the socket error if any. -`public bool closed() const` | Returns true if the native socket handle is closed. -`public uv::Loop * loop() const` | Returns the socket event loop. -`protected int _af` | -`protected void init()` | Initializes the underlying socket context. -`protected void reset()` | Resets the socket context for reuse. +--- -## Members +#### read -#### `public void * opaque` +```cpp +virtual inline ssize_t read(const ConstBuffer &) +``` +Read/parse to the packet from the given input buffer. The number of bytes read is returned. +--- -Optional client data pointer. +#### write -The pointer is set to null on initialization but not managed. +```cpp +virtual inline void write(Buffer &) const +``` -#### `public Socket() = default` +Copy/generate to the packet given output buffer. The number of bytes written can be obtained from the buffer. +Todo: It may be prefferable to use our pod types here instead of buffer input, but the current codebase requires that the buffer be dynamically resizable for some protocols... +--- +#### className +```cpp +virtual inline const char * className() const +``` -#### `public virtual ~Socket() = default` +## SocketAdapter +> **Subclasses:** `scy::http::Connection`, `scy::http::ConnectionAdapter`, `scy::http::ConnectionStream`, `scy::http::Server`, `scy::net::Socket`, `scy::net::SocketEmitter`, `scy::sockio::Client` +> **Defined in:** `socketadapter.h` +[SocketAdapter](#classscy_1_1net_1_1SocketAdapter) is the abstract interface for all socket classes. A [SocketAdapter](#classscy_1_1net_1_1SocketAdapter) can also be attached to a [Socket](#classscy_1_1net_1_1Socket) in order to override default [Socket](#classscy_1_1net_1_1Socket) callbacks and behaviour, while still maintaining the default [Socket](#classscy_1_1net_1_1Socket) interface (see Socket::setAdapter). +This class also be extended to implement custom processing for received socket data before it is dispatched to the application (see [PacketSocketEmitter](#classscy_1_1net_1_1PacketSocketEmitter) and [Transaction](#classscy_1_1net_1_1Transaction) classes). +### Members + +| Name | Description | +|------|-------------| +| [`SocketAdapter`](#group__net_1ga35ca78ac04abbd6828af02fb1b65e6d1) | Creates the [SocketAdapter](#classscy_1_1net_1_1SocketAdapter). | +| [`~SocketAdapter`](#group__net_1gac06480990b5301cb185000fe8bf860e4) | Destroys the [SocketAdapter](#classscy_1_1net_1_1SocketAdapter). | +| [`send`](#group__net_1gae0701649bbdbe02ac987c21dbf180745) | Sends the given data buffer to the connected peer. Returns the number of bytes sent or -1 on error. No exception will be thrown. For TCP sockets the given peer address must match the connected peer address. | +| [`send`](#group__net_1ga4d695c349c6c483b36bc2a406ffa8554) | | +| [`sendPacket`](#group__net_1ga51b07fc133c1761959118191f392509e) | Sends the given packet to the connected peer. Returns the number of bytes sent or -1 on error. No exception will be thrown. For TCP sockets the given peer address must match the connected peer address. | +| [`sendPacket`](#group__net_1ga7ef73b7c3d563756f492e9abc196c77d) | | +| [`sendPacket`](#group__net_1ga6d7c711236a3570235353f634f9d1a77) | Sends the given packet to the connected peer. This method provides delegate compatability, and unlike other send methods throws an exception if the underlying socket is closed. | +| [`setSender`](#group__net_1ga566fd551c24638ab22d42f6c6082d85f) | Sets the pointer to the outgoing data adapter. Send methods proxy data to this adapter by default. | +| [`sender`](#group__net_1gaf327b8e4712403322638ea10151dc1d6) | Returns the output [SocketAdapter](#classscy_1_1net_1_1SocketAdapter) pointer. | +| [`addReceiver`](#group__net_1ga255f77677b0e9b2d95b663c413f16fee) | Sets the pointer to the incoming data adapter. Events proxy data to this adapter by default. | +| [`removeReceiver`](#group__net_1ga523f50c94ac42d49d81efb8a4ff81629) | Remove the given receiver. | +| [`hasReceiver`](#group__net_1ga083660a332c15c43e6a1945d59b3f0d7) | Returns true if the given receiver is connected. | +| [`receivers`](#group__net_1ga1e96c66f9d52faadb197b59c75cefb67) | Returns the input [SocketAdapter](#classscy_1_1net_1_1SocketAdapter) pointer. | +| [`onSocketConnect`](#group__net_1ga8dae1c179274b0571d1b5d8040f5afd8) | These virtual methods can be overridden as necessary to intercept socket events before they hit the application. | +| [`onSocketRecv`](#group__net_1ga48f8129547ba9eaac88094e059205529) | | +| [`onSocketError`](#group__net_1ga5658d5b01a3ff4cbad6010190aefe3b7) | | +| [`onSocketClose`](#group__net_1gab5d5c13b628ba6a010785f447f9e4fdc) | | +| [`cleanupReceivers`](#group__net_1gacd031591dc8a642107aeb1f16ad55764) | | +| [`priority`](#group__net_1ga66462899a27420bf50af004887355e83) | The priority of this adapter for STL sort operations. | +| [`_sender`](#group__net_1ga17dc4823b85f24d94b5127681006439f) | | +| [`_receivers`](#group__net_1ga16be0b8461e4aeb9bc6fa0acf0447288) | | +| [`_dirty`](#group__net_1ga69b4294f637aa586d0e247e5c4b8b2a9) | | + +--- + +#### SocketAdapter + +```cpp +SocketAdapter(SocketAdapter * sender) +``` -#### `public void connect(const `[`Address`](#classscy_1_1net_1_1Address)` & address)` +Creates the [SocketAdapter](#classscy_1_1net_1_1SocketAdapter). +| Parameter | Type | Description | +|-----------|------|-------------| +| `sender` | `SocketAdapter *` | | +--- -Connects to the given peer IP address. +#### ~SocketAdapter -Throws an exception if the address is malformed. Connection errors can be handled via the [Error](#structscy_1_1Error) signal. +```cpp +virtual ~SocketAdapter() +``` -#### `public void connect(const std::string & host,uint16_t port)` +Destroys the [SocketAdapter](#classscy_1_1net_1_1SocketAdapter). +--- +#### send -Resolves and connects to the given host address. +```cpp +virtual ssize_t send(const char * data, size_t len, int flags) +``` -Throws an Exception if the host is malformed. Since the DNS callback is asynchronous implementations need to listen for the [Error](#structscy_1_1Error) signal for handling connection errors. +Sends the given data buffer to the connected peer. Returns the number of bytes sent or -1 on error. No exception will be thrown. For TCP sockets the given peer address must match the connected peer address. -#### `public void bind(const `[`Address`](#classscy_1_1net_1_1Address)` & address,unsigned flags)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `data` | `const char *` | | +| `len` | `size_t` | | +| `flags` | `int` | | +--- +#### send -Bind a local address to the socket. The address may be IPv4 or IPv6 (if supported). +```cpp +virtual ssize_t send(const char * data, size_t len, const Address & peerAddress, int flags) +``` -Throws an Exception on error. +| Parameter | Type | Description | +|-----------|------|-------------| +| `data` | `const char *` | | +| `len` | `size_t` | | +| `peerAddress` | `const Address &` | | +| `flags` | `int` | | -#### `public inline virtual void listen(int backlog)` +--- +#### sendPacket +```cpp +virtual ssize_t sendPacket(const IPacket & packet, int flags) +``` -Listens the socket on the given address. +Sends the given packet to the connected peer. Returns the number of bytes sent or -1 on error. No exception will be thrown. For TCP sockets the given peer address must match the connected peer address. -Throws an Exception on error. +| Parameter | Type | Description | +|-----------|------|-------------| +| `packet` | `const IPacket &` | | +| `flags` | `int` | | -#### `public inline virtual bool shutdown()` +--- +#### sendPacket +```cpp +virtual ssize_t sendPacket(const IPacket & packet, const Address & peerAddress, int flags) +``` -Sends the shutdown packet which should result is socket closure via callback. +| Parameter | Type | Description | +|-----------|------|-------------| +| `packet` | `const IPacket &` | | +| `peerAddress` | `const Address &` | | +| `flags` | `int` | | -#### `public void close()` +--- -Closes the underlying socket. +#### sendPacket +```cpp +virtual void sendPacket(IPacket & packet) +``` +Sends the given packet to the connected peer. This method provides delegate compatability, and unlike other send methods throws an exception if the underlying socket is closed. -#### `public `[`Address`](#classscy_1_1net_1_1Address)` address() const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `packet` | `IPacket &` | | +--- +#### setSender -The locally bound address. +```cpp +virtual void setSender(SocketAdapter * adapter) +``` -This function will not throw. A Wildcard 0.0.0.0:0 address is returned if the socket is closed or invalid. +Sets the pointer to the outgoing data adapter. Send methods proxy data to this adapter by default. -#### `public `[`Address`](#classscy_1_1net_1_1Address)` peerAddress() const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `adapter` | `SocketAdapter *` | | +--- +#### sender -The connected peer address. +```cpp +SocketAdapter * sender() +``` -This function will not throw. A Wildcard 0.0.0.0:0 address is returned if the socket is closed or invalid. +Returns the output [SocketAdapter](#classscy_1_1net_1_1SocketAdapter) pointer. -#### `public net::TransportType transport() const` +--- -The transport protocol: TCP, UDP or SSLTCP. +#### addReceiver +```cpp +virtual void addReceiver(SocketAdapter * adapter) +``` +Sets the pointer to the incoming data adapter. Events proxy data to this adapter by default. -#### `public void setError(const `[`scy::Error`](#structscy_1_1Error)` & err)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `adapter` | `SocketAdapter *` | | +--- +#### removeReceiver -Sets the socket error. +```cpp +virtual void removeReceiver(SocketAdapter * adapter) +``` -Setting the error will result in socket closure. +Remove the given receiver. -#### `public const `[`scy::Error`](#structscy_1_1Error)` & error() const` +By default this function does nothing unless the given receiver matches the current receiver. -Return the socket error if any. +| Parameter | Type | Description | +|-----------|------|-------------| +| `adapter` | `SocketAdapter *` | | +--- +#### hasReceiver -#### `public bool closed() const` +```cpp +virtual bool hasReceiver(SocketAdapter * adapter) +``` -Returns true if the native socket handle is closed. +Returns true if the given receiver is connected. +| Parameter | Type | Description | +|-----------|------|-------------| +| `adapter` | `SocketAdapter *` | | +--- -#### `public uv::Loop * loop() const` +#### receivers -Returns the socket event loop. +```cpp +std::vector< SocketAdapter * > receivers() +``` +Returns the input [SocketAdapter](#classscy_1_1net_1_1SocketAdapter) pointer. +--- -#### `protected int _af` +#### onSocketConnect +```cpp +virtual void onSocketConnect(Socket & socket) +``` +These virtual methods can be overridden as necessary to intercept socket events before they hit the application. +| Parameter | Type | Description | +|-----------|------|-------------| +| `socket` | `Socket &` | | +--- -#### `protected void init()` +#### onSocketRecv -Initializes the underlying socket context. +```cpp +virtual void onSocketRecv(Socket & socket, const MutableBuffer & buffer, const Address & peerAddress) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `socket` | `Socket &` | | +| `buffer` | `const MutableBuffer &` | | +| `peerAddress` | `const Address &` | | +--- -#### `protected void reset()` +#### onSocketError -Resets the socket context for reuse. +```cpp +virtual void onSocketError(Socket & socket, const Error & error) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `socket` | `Socket &` | | +| `error` | `const Error &` | | +--- -# class `scy::net::SocketAdapter` +#### onSocketClose +```cpp +virtual void onSocketClose(Socket & socket) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `socket` | `Socket &` | | +--- -[SocketAdapter](#classscy_1_1net_1_1SocketAdapter) is the abstract interface for all socket classes. A [SocketAdapter](#classscy_1_1net_1_1SocketAdapter) can also be attached to a [Socket](#classscy_1_1net_1_1Socket) in order to override default [Socket](#classscy_1_1net_1_1Socket) callbacks and behaviour, while still maintaining the default [Socket](#classscy_1_1net_1_1Socket) interface (see Socket::setAdapter). +#### cleanupReceivers -This class also be extended to implement custom processing for received socket data before it is dispatched to the application (see [PacketSocketEmitter](#classscy_1_1net_1_1PacketSocketEmitter) and [Transaction](#classscy_1_1net_1_1Transaction) classes). +```cpp +virtual void cleanupReceivers() +``` -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public int priority` | The priority of this adapter for STL sort operations. -`public SocketAdapter(`[`SocketAdapter`](#classscy_1_1net_1_1SocketAdapter)` * sender)` | Creates the [SocketAdapter](./doc/api-net.md#classscy_1_1net_1_1SocketAdapter). -`public virtual ~SocketAdapter()` | Destroys the [SocketAdapter](./doc/api-net.md#classscy_1_1net_1_1SocketAdapter). -`public virtual ssize_t send(const char * data,size_t len,int flags)` | -`public virtual ssize_t send(const char * data,size_t len,const `[`Address`](#classscy_1_1net_1_1Address)` & peerAddress,int flags)` | -`public virtual ssize_t sendPacket(const `[`IPacket`](#classscy_1_1IPacket)` & packet,int flags)` | -`public virtual ssize_t sendPacket(const `[`IPacket`](#classscy_1_1IPacket)` & packet,const `[`Address`](#classscy_1_1net_1_1Address)` & peerAddress,int flags)` | -`public virtual void sendPacket(`[`IPacket`](#classscy_1_1IPacket)` & packet)` | -`public virtual void setSender(`[`SocketAdapter`](#classscy_1_1net_1_1SocketAdapter)` * adapter)` | -`public `[`SocketAdapter`](#classscy_1_1net_1_1SocketAdapter)` * sender()` | Returns the output [SocketAdapter](./doc/api-net.md#classscy_1_1net_1_1SocketAdapter) pointer. -`public virtual void addReceiver(`[`SocketAdapter`](#classscy_1_1net_1_1SocketAdapter)` * adapter)` | -`public virtual void removeReceiver(`[`SocketAdapter`](#classscy_1_1net_1_1SocketAdapter)` * adapter)` | -`public virtual bool hasReceiver(`[`SocketAdapter`](#classscy_1_1net_1_1SocketAdapter)` * adapter)` | Returns true if the given receiver is connected. -`public std::vector< `[`SocketAdapter`](#classscy_1_1net_1_1SocketAdapter)` * > receivers()` | Returns the input [SocketAdapter](./doc/api-net.md#classscy_1_1net_1_1SocketAdapter) pointer. -`public virtual void onSocketConnect(`[`Socket`](#classscy_1_1net_1_1Socket)` & socket)` | -`public virtual void onSocketRecv(`[`Socket`](#classscy_1_1net_1_1Socket)` & socket,const `[`MutableBuffer`](#classscy_1_1MutableBuffer)` & buffer,const `[`Address`](#classscy_1_1net_1_1Address)` & peerAddress)` | -`public virtual void onSocketError(`[`Socket`](#classscy_1_1net_1_1Socket)` & socket,const `[`Error`](#structscy_1_1Error)` & error)` | -`public virtual void onSocketClose(`[`Socket`](#classscy_1_1net_1_1Socket)` & socket)` | -`protected `[`SocketAdapter`](./doc/api-net.md#classscy_1_1net_1_1SocketAdapter)` * _sender` | -`protected std::vector< `[`Ref`](./doc/api-net.md#structscy_1_1net_1_1SocketAdapter_1_1Ref)` * > _receivers` | -`protected bool _dirty` | -`protected virtual void cleanupReceivers()` | - -## Members - -#### `public int priority` +--- -The priority of this adapter for STL sort operations. +#### priority +```cpp +int priority = 0 +``` +The priority of this adapter for STL sort operations. -#### `public SocketAdapter(`[`SocketAdapter`](#classscy_1_1net_1_1SocketAdapter)` * sender)` +--- -Creates the [SocketAdapter](#classscy_1_1net_1_1SocketAdapter). +#### _sender +```cpp +SocketAdapter * _sender +``` +--- -#### `public virtual ~SocketAdapter()` +#### _receivers -Destroys the [SocketAdapter](#classscy_1_1net_1_1SocketAdapter). +```cpp +std::vector< Ref::ptr_t > _receivers +``` +--- +#### _dirty -#### `public virtual ssize_t send(const char * data,size_t len,int flags)` +```cpp +bool _dirty = false +``` +## Ref +> **Defined in:** `socketadapter.h` -Sends the given data buffer to the connected peer. Returns the number of bytes sent or -1 on error. No exception will be thrown. For TCP sockets the given peer address must match the connected peer address. +### Members -#### `public virtual ssize_t send(const char * data,size_t len,const `[`Address`](#classscy_1_1net_1_1Address)` & peerAddress,int flags)` +| Name | Description | +|------|-------------| +| [`ptr`](#group__net_1ga7850ea3acb3330d7fb974c45f780f1c4) | | +| [`alive`](#group__net_1ga5e0d22008a914828d87ecd623872db05) | | +--- +#### ptr +```cpp +SocketAdapter * ptr +``` +--- -#### `public virtual ssize_t sendPacket(const `[`IPacket`](#classscy_1_1IPacket)` & packet,int flags)` +#### alive +```cpp +bool alive +``` +## SocketEmitter + +> **Extends:** `scy::net::SocketAdapter` +> **Subclasses:** `scy::http::ws::WebSocketAdapter`, `scy::net::PacketSocketEmitter` +> **Defined in:** `socketemitter.h` + +[SocketAdapter](#classscy_1_1net_1_1SocketAdapter) class that adds signal callbacks for sockets. Asde from adding a signal interface the class works as a wrapper for the socket instance, and is designed to be used the same way as a `std::unique_ptr` by overriding the ->() operator. + +### Members + +| Name | Description | +|------|-------------| +| [`SocketEmitter`](#group__net_1ga6a57fd61fe37d7d7aae29fb85d708d0f) | Creates the [SocketEmitter](#classscy_1_1net_1_1SocketEmitter). | +| [`SocketEmitter`](#group__net_1gac0c6fd442346109bae43fd86e490268a) | Copy constructor. | +| [`~SocketEmitter`](#group__net_1ga371482dd5151aea7cb88803946a09144) | Destroys the [SocketAdapter](#classscy_1_1net_1_1SocketAdapter). | +| [`addReceiver`](#group__net_1ga33c730a0439c41d71c1bd673320f71bf) | Adds an input [SocketAdapter](#classscy_1_1net_1_1SocketAdapter) for receiving socket signals. | +| [`removeReceiver`](#group__net_1gaa962167a885ba5f15a3420771f861204) | Removes an input [SocketAdapter](#classscy_1_1net_1_1SocketAdapter). | +| [`swap`](#group__net_1gae5c17082651ccf5847bbec840fa89443) | Swap the underlying socket pointer. | +| [`as`](#group__net_1ga9a944688f65c76fa9fda90d4927e2b3d) | Cast getter for the underlying socket. | +| [`operator->`](#group__net_1gaa66861023d067035a62030280a7c36e6) | Accessor to the underlying socket. | +| [`onSocketConnect`](#group__net_1gaf3ef9945319491216f42833e5791a678) | Internal callback events. | +| [`onSocketRecv`](#group__net_1ga9157f82d8c9d2d849aa173f06a143ddd) | | +| [`onSocketError`](#group__net_1gaea46a3b9af1d0bed4bd708c1e5f59cbe) | | +| [`onSocketClose`](#group__net_1ga8b6d7dcdd05f2f7a21f19733239f083e) | | +| [`Connect`](#group__net_1gaf6b9705a3bd3faf2bfb550dbc7c5249e) | Signals that the socket is connected. | +| [`Recv`](#group__net_1ga6a2406c9364edbff61e1d559e5b6576c) | Signals when data is received by the socket. | +| [`Error`](#group__net_1gaa0ff0673de03635fc0ea26c2be3c2daa) | Signals that the socket is closed in error. This signal will be sent just before the Closed signal. | +| [`Close`](#group__net_1ga950604a2babd224d2b2c7b1f5e00d101) | Signals that the underlying socket is closed. | +| [`impl`](#group__net_1ga0b423a8b6597057e39dcd3dcb0222364) | Pointer to the underlying socket. Sent data will be proxied to this socket. | + +--- + +#### SocketEmitter + +```cpp +SocketEmitter(const Socket::Ptr & socket) +``` -Sends the given packet to the connected peer. Returns the number of bytes sent or -1 on error. No exception will be thrown. For TCP sockets the given peer address must match the connected peer address. +Creates the [SocketEmitter](#classscy_1_1net_1_1SocketEmitter). -#### `public virtual ssize_t sendPacket(const `[`IPacket`](#classscy_1_1IPacket)` & packet,const `[`Address`](#classscy_1_1net_1_1Address)` & peerAddress,int flags)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `socket` | `const Socket::Ptr &` | | +--- +#### SocketEmitter +```cpp +SocketEmitter(const SocketEmitter & that) +``` +Copy constructor. -#### `public virtual void sendPacket(`[`IPacket`](#classscy_1_1IPacket)` & packet)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `that` | `const SocketEmitter &` | | +--- +#### ~SocketEmitter -Sends the given packet to the connected peer. This method provides delegate compatability, and unlike other send methods throws an exception if the underlying socket is closed. +```cpp +virtual ~SocketEmitter() +``` -#### `public virtual void setSender(`[`SocketAdapter`](#classscy_1_1net_1_1SocketAdapter)` * adapter)` +Destroys the [SocketAdapter](#classscy_1_1net_1_1SocketAdapter). +--- +#### addReceiver -Sets the pointer to the outgoing data adapter. Send methods proxy data to this adapter by default. +```cpp +virtual void addReceiver(SocketAdapter * adapter) +``` -#### `public `[`SocketAdapter`](#classscy_1_1net_1_1SocketAdapter)` * sender()` +Adds an input [SocketAdapter](#classscy_1_1net_1_1SocketAdapter) for receiving socket signals. -Returns the output [SocketAdapter](#classscy_1_1net_1_1SocketAdapter) pointer. +| Parameter | Type | Description | +|-----------|------|-------------| +| `adapter` | `SocketAdapter *` | | +--- +#### removeReceiver -#### `public virtual void addReceiver(`[`SocketAdapter`](#classscy_1_1net_1_1SocketAdapter)` * adapter)` +```cpp +virtual void removeReceiver(SocketAdapter * adapter) +``` +Removes an input [SocketAdapter](#classscy_1_1net_1_1SocketAdapter). +| Parameter | Type | Description | +|-----------|------|-------------| +| `adapter` | `SocketAdapter *` | | -Sets the pointer to the incoming data adapter. Events proxy data to this adapter by default. +--- -#### `public virtual void removeReceiver(`[`SocketAdapter`](#classscy_1_1net_1_1SocketAdapter)` * adapter)` +#### swap +```cpp +virtual void swap(const Socket::Ptr & socket) +``` +Swap the underlying socket pointer. -Remove the given receiver. +| Parameter | Type | Description | +|-----------|------|-------------| +| `socket` | `const Socket::Ptr &` | | -By default this function does nothing unless the given receiver matches the current receiver. +--- -#### `public virtual bool hasReceiver(`[`SocketAdapter`](#classscy_1_1net_1_1SocketAdapter)` * adapter)` +#### as -Returns true if the given receiver is connected. +```cpp +template inline T * as() +``` +Cast getter for the underlying socket. +--- -#### `public std::vector< `[`SocketAdapter`](#classscy_1_1net_1_1SocketAdapter)` * > receivers()` +#### operator-> -Returns the input [SocketAdapter](#classscy_1_1net_1_1SocketAdapter) pointer. +```cpp +inline Socket * operator->() const +``` +Accessor to the underlying socket. +--- -#### `public virtual void onSocketConnect(`[`Socket`](#classscy_1_1net_1_1Socket)` & socket)` +#### onSocketConnect +```cpp +virtual void onSocketConnect(Socket & socket) +``` +Internal callback events. -These virtual methods can be overridden as necessary to intercept socket events before they hit the application. +| Parameter | Type | Description | +|-----------|------|-------------| +| `socket` | `Socket &` | | -#### `public virtual void onSocketRecv(`[`Socket`](#classscy_1_1net_1_1Socket)` & socket,const `[`MutableBuffer`](#classscy_1_1MutableBuffer)` & buffer,const `[`Address`](#classscy_1_1net_1_1Address)` & peerAddress)` +--- +#### onSocketRecv +```cpp +virtual void onSocketRecv(Socket & socket, const MutableBuffer & buffer, const Address & peerAddress) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `socket` | `Socket &` | | +| `buffer` | `const MutableBuffer &` | | +| `peerAddress` | `const Address &` | | +--- -#### `public virtual void onSocketError(`[`Socket`](#classscy_1_1net_1_1Socket)` & socket,const `[`Error`](#structscy_1_1Error)` & error)` +#### onSocketError +```cpp +virtual void onSocketError(Socket & socket, const [scy::Error](./doc/api-base.md#structscy_1_1Error) & error) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `socket` | `Socket &` | | +| `error` | `const [scy::Error](./doc/api-base.md#structscy_1_1Error) &` | | +--- +#### onSocketClose -#### `public virtual void onSocketClose(`[`Socket`](#classscy_1_1net_1_1Socket)` & socket)` +```cpp +virtual void onSocketClose(Socket & socket) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `socket` | `Socket &` | | +--- +#### Connect +```cpp +Signal< void(Socket &)> Connect +``` -#### `protected `[`SocketAdapter`](./doc/api-net.md#classscy_1_1net_1_1SocketAdapter)` * _sender` +Signals that the socket is connected. +--- +#### Recv +```cpp +Signal< void(Socket &, const MutableBuffer &, const Address &)> Recv +``` +Signals when data is received by the socket. -#### `protected std::vector< `[`Ref`](./doc/api-net.md#structscy_1_1net_1_1SocketAdapter_1_1Ref)` * > _receivers` +--- +#### Error +```cpp +Signal< void(Socket &, const [scy::Error](./doc/api-base.md#structscy_1_1Error) &)> Error +``` +Signals that the socket is closed in error. This signal will be sent just before the Closed signal. +--- -#### `protected bool _dirty` +#### Close +```cpp +Signal< void(Socket &)> Close +``` +Signals that the underlying socket is closed. +--- +#### impl -#### `protected virtual void cleanupReceivers()` +```cpp +Socket::Ptr impl +``` +Pointer to the underlying socket. Sent data will be proxied to this socket. +## SSLAdapter + +> **Defined in:** `ssladapter.h` + +### Members + +| Name | Description | +|------|-------------| +| [`SSLAdapter`](#group__net_1ga26cc38aebf1d0d1846ae6603ba2be64f) | | +| [`~SSLAdapter`](#group__net_1ga4639bd49bcad7899337f22ba0ec68084) | | +| [`initClient`](#group__net_1gaebf891ed98b4c4f2c5edeccfd98cef03) | Initializes the SSL context as a client. | +| [`initServer`](#group__net_1ga707dd2a10f4541d9a38205083a60c08f) | Initializes the SSL context as a server. | +| [`initialized`](#group__net_1ga3051dc8e9a424368aeb91027d4b9d8be) | Returns true when SSL context has been initialized. | +| [`ready`](#group__net_1ga05e325d251acd31625116021c4abcf4a) | Returns true when the handshake is complete. | +| [`handshake`](#group__net_1ga16c72dfccd9cc787ca4d570179de7bb9) | Start/continue the SSL handshake process. | +| [`available`](#group__net_1gaebf583d1844bb5eb37b6c7d94a7cdca1) | Returns the number of bytes available in the SSL buffer for immediate reading. | +| [`shutdown`](#group__net_1gaa2a689ba83da2bcc9d3b8b4b3bab303e) | Issues an orderly SSL shutdown. | +| [`flush`](#group__net_1gabf462204b841bac2edbc2d9c12d36d59) | Flushes the SSL read/write buffers. | +| [`addIncomingData`](#group__net_1ga17018e5db975debd3765e5611a6c5c66) | | +| [`addOutgoingData`](#group__net_1ga80a755a8a5a1369ace2d8f95740767f7) | | +| [`addOutgoingData`](#group__net_1ga9d0f1cb4beaf061be33cb162ad674571) | | +| [`handleError`](#group__net_1ga37281519a34b937cbf763e587e5675c4) | | +| [`flushReadBIO`](#group__net_1ga8c32288c3e5badc7985dcc0f58ac8336) | | +| [`flushWriteBIO`](#group__net_1ga5949d6d6339de68d4d38f1b4b07e3360) | | +| [`_socket`](#group__net_1gae207495c52da9720625af1c1a8234ca0) | | +| [`_ssl`](#group__net_1gab767ae04b5ac979a1e2d0d337b4c4028) | | +| [`_readBIO`](#group__net_1ga0a542283ee6c57fcc584a1315cd0b9a7) | The incoming buffer we write encrypted SSL data into. | +| [`_writeBIO`](#group__net_1ga7837fb89f6f46ab90a408290f308ee2a) | The outgoing buffer we write to the socket. | +| [`_bufferOut`](#group__net_1ga3c2e88ec5aa5631dedaf5179bf8dbfa0) | The outgoing payload to be encrypted and sent. | + +--- + +#### SSLAdapter + +```cpp +SSLAdapter(net::SSLSocket * socket) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `socket` | `net::SSLSocket *` | | +--- -# class `scy::net::SocketEmitter` +#### ~SSLAdapter +```cpp +~SSLAdapter() ``` -class scy::net::SocketEmitter - : public scy::net::SocketAdapter -``` -[SocketAdapter](#classscy_1_1net_1_1SocketAdapter) class that adds signal callbacks for sockets. +--- +#### initClient +```cpp +void initClient() +``` -## Summary +Initializes the SSL context as a client. - Members | Descriptions ---------------------------------|--------------------------------------------- -`public `[`Signal](#classscy_1_1Signal)< void([Socket`](#classscy_1_1net_1_1Socket) &)`> Connect` | Signals that the socket is connected. -`public `[`Signal](#classscy_1_1Signal)< void([Socket](#classscy_1_1net_1_1Socket) &, const [MutableBuffer](#classscy_1_1MutableBuffer) &, const [Address`](#classscy_1_1net_1_1Address) &)`> Recv` | Signals when data is received by the socket. -`public `[`Signal](#classscy_1_1Signal)< void([Socket](#classscy_1_1net_1_1Socket) &, const [scy::Error`](#structscy_1_1Error) &)`> Error` | -`public `[`Signal](#classscy_1_1Signal)< void([Socket`](#classscy_1_1net_1_1Socket) &)`> Close` | Signals that the underlying socket is closed. -`public Socket::Ptr impl` | -`public SocketEmitter(const Socket::Ptr & socket)` | Creates the [SocketEmitter](./doc/api-net.md#classscy_1_1net_1_1SocketEmitter). -`public SocketEmitter(const `[`SocketEmitter`](#classscy_1_1net_1_1SocketEmitter)` & that)` | Copy constructor. -`public virtual ~SocketEmitter()` | Destroys the [SocketAdapter](./doc/api-net.md#classscy_1_1net_1_1SocketAdapter). -`public virtual void addReceiver(`[`SocketAdapter`](#classscy_1_1net_1_1SocketAdapter)` * adapter)` | Adds an input [SocketAdapter](./doc/api-net.md#classscy_1_1net_1_1SocketAdapter) for receiving socket signals. -`public virtual void removeReceiver(`[`SocketAdapter`](#classscy_1_1net_1_1SocketAdapter)` * adapter)` | Removes an input [SocketAdapter](./doc/api-net.md#classscy_1_1net_1_1SocketAdapter). -`public virtual void swap(const Socket::Ptr & socket)` | Swap the underlying socket pointer. -`public template`
`inline T * as()` | Cast getter for the underlying socket. -`public inline `[`Socket`](#classscy_1_1net_1_1Socket)` * operator->() const` | Accessor to the underlying socket. -`protected virtual void onSocketConnect(`[`Socket`](#classscy_1_1net_1_1Socket)` & socket)` | Internal callback events. -`protected virtual void onSocketRecv(`[`Socket`](#classscy_1_1net_1_1Socket)` & socket,const `[`MutableBuffer`](#classscy_1_1MutableBuffer)` & buffer,const `[`Address`](#classscy_1_1net_1_1Address)` & peerAddress)` | -`protected virtual void onSocketError(`[`Socket`](#classscy_1_1net_1_1Socket)` & socket,const `[`scy::Error`](#structscy_1_1Error)` & error)` | -`protected virtual void onSocketClose(`[`Socket`](#classscy_1_1net_1_1Socket)` & socket)` | +--- -## Members +#### initServer -#### `public `[`Signal](#classscy_1_1Signal)< void([Socket`](#classscy_1_1net_1_1Socket) &)`> Connect` +```cpp +void initServer() +``` -Signals that the socket is connected. +Initializes the SSL context as a server. +--- +#### initialized -#### `public `[`Signal](#classscy_1_1Signal)< void([Socket](#classscy_1_1net_1_1Socket) &, const [MutableBuffer](#classscy_1_1MutableBuffer) &, const [Address`](#classscy_1_1net_1_1Address) &)`> Recv` +```cpp +bool initialized() const +``` -Signals when data is received by the socket. +Returns true when SSL context has been initialized. +--- +#### ready -#### `public `[`Signal](#classscy_1_1Signal)< void([Socket](#classscy_1_1net_1_1Socket) &, const [scy::Error`](#structscy_1_1Error) &)`> Error` +```cpp +bool ready() const +``` +Returns true when the handshake is complete. +--- -Signals that the socket is closed in error. This signal will be sent just before the Closed signal. +#### handshake -#### `public `[`Signal](#classscy_1_1Signal)< void([Socket`](#classscy_1_1net_1_1Socket) &)`> Close` +```cpp +void handshake() +``` -Signals that the underlying socket is closed. +Start/continue the SSL handshake process. +--- +#### available -#### `public Socket::Ptr impl` +```cpp +int available() const +``` +Returns the number of bytes available in the SSL buffer for immediate reading. +--- -Pointer to the underlying socket. Sent data will be proxied to this socket. +#### shutdown -#### `public SocketEmitter(const Socket::Ptr & socket)` +```cpp +void shutdown() +``` -Creates the [SocketEmitter](#classscy_1_1net_1_1SocketEmitter). +Issues an orderly SSL shutdown. +--- +#### flush -#### `public SocketEmitter(const `[`SocketEmitter`](#classscy_1_1net_1_1SocketEmitter)` & that)` +```cpp +void flush() +``` -Copy constructor. +Flushes the SSL read/write buffers. +--- +#### addIncomingData -#### `public virtual ~SocketEmitter()` +```cpp +void addIncomingData(const char * data, size_t len) +``` -Destroys the [SocketAdapter](#classscy_1_1net_1_1SocketAdapter). +| Parameter | Type | Description | +|-----------|------|-------------| +| `data` | `const char *` | | +| `len` | `size_t` | | +--- +#### addOutgoingData -#### `public virtual void addReceiver(`[`SocketAdapter`](#classscy_1_1net_1_1SocketAdapter)` * adapter)` +```cpp +void addOutgoingData(const std::string & data) +``` -Adds an input [SocketAdapter](#classscy_1_1net_1_1SocketAdapter) for receiving socket signals. +| Parameter | Type | Description | +|-----------|------|-------------| +| `data` | `const std::string &` | | +--- +#### addOutgoingData -#### `public virtual void removeReceiver(`[`SocketAdapter`](#classscy_1_1net_1_1SocketAdapter)` * adapter)` +```cpp +void addOutgoingData(const char * data, size_t len) +``` -Removes an input [SocketAdapter](#classscy_1_1net_1_1SocketAdapter). +| Parameter | Type | Description | +|-----------|------|-------------| +| `data` | `const char *` | | +| `len` | `size_t` | | +--- +#### handleError -#### `public virtual void swap(const Socket::Ptr & socket)` +```cpp +void handleError(int rc) +``` -Swap the underlying socket pointer. +| Parameter | Type | Description | +|-----------|------|-------------| +| `rc` | `int` | | +--- +#### flushReadBIO -#### `public template`
`inline T * as()` - -Cast getter for the underlying socket. - - - -#### `public inline `[`Socket`](#classscy_1_1net_1_1Socket)` * operator->() const` - -Accessor to the underlying socket. - - - -#### `protected virtual void onSocketConnect(`[`Socket`](#classscy_1_1net_1_1Socket)` & socket)` - -Internal callback events. - - - -#### `protected virtual void onSocketRecv(`[`Socket`](#classscy_1_1net_1_1Socket)` & socket,const `[`MutableBuffer`](#classscy_1_1MutableBuffer)` & buffer,const `[`Address`](#classscy_1_1net_1_1Address)` & peerAddress)` - - - - - -#### `protected virtual void onSocketError(`[`Socket`](#classscy_1_1net_1_1Socket)` & socket,const `[`scy::Error`](#structscy_1_1Error)` & error)` - - - - - -#### `protected virtual void onSocketClose(`[`Socket`](#classscy_1_1net_1_1Socket)` & socket)` - - - - - -# class `scy::net::SocketPacket` - +```cpp +void flushReadBIO() ``` -class scy::net::SocketPacket - : public scy::RawPacket -``` - - - -[SocketPacket](#classscy_1_1net_1_1SocketPacket) is the default packet type emitted by sockets. [SocketPacket](#classscy_1_1net_1_1SocketPacket) provides peer address information and a buffer reference for nocopy binary operations. - -The referenced packet buffer lifetime is only guaranteed for the duration of the receiver callback. - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public `[`PacketInfo`](./doc/api-net.md#structscy_1_1net_1_1PacketInfo)` * info` | [PacketInfo](./doc/api-net.md#structscy_1_1net_1_1PacketInfo) pointer. -`public inline SocketPacket(const Socket::Ptr & socket,const `[`MutableBuffer`](#classscy_1_1MutableBuffer)` & buffer,const `[`Address`](#classscy_1_1net_1_1Address)` & peerAddress)` | -`public inline SocketPacket(const `[`SocketPacket`](#classscy_1_1net_1_1SocketPacket)` & that)` | -`public inline virtual ~SocketPacket()` | -`public inline virtual void print(std::ostream & os) const` | -`public inline virtual `[`IPacket`](#classscy_1_1IPacket)` * clone() const` | -`public inline virtual ssize_t read(const `[`ConstBuffer`](#classscy_1_1ConstBuffer)` &)` | -`public inline virtual void write(`[`Buffer`](#group__base_1gab10b36b080deb583ed703fca6b63ffdd)` &) const` | -`public inline virtual const char * className() const` | - -## Members - -#### `public `[`PacketInfo`](./doc/api-net.md#structscy_1_1net_1_1PacketInfo)` * info` - -[PacketInfo](#structscy_1_1net_1_1PacketInfo) pointer. - - - -#### `public inline SocketPacket(const Socket::Ptr & socket,const `[`MutableBuffer`](#classscy_1_1MutableBuffer)` & buffer,const `[`Address`](#classscy_1_1net_1_1Address)` & peerAddress)` - - - - - -#### `public inline SocketPacket(const `[`SocketPacket`](#classscy_1_1net_1_1SocketPacket)` & that)` - - - - - -#### `public inline virtual ~SocketPacket()` - - - - - -#### `public inline virtual void print(std::ostream & os) const` - - - - - -#### `public inline virtual `[`IPacket`](#classscy_1_1IPacket)` * clone() const` - +--- +#### flushWriteBIO +```cpp +void flushWriteBIO() +``` -#### `public inline virtual ssize_t read(const `[`ConstBuffer`](#classscy_1_1ConstBuffer)` &)` +--- +#### _socket +```cpp +net::SSLSocket * _socket +``` -Read/parse to the packet from the given input buffer. The number of bytes read is returned. +--- -#### `public inline virtual void write(`[`Buffer`](#group__base_1gab10b36b080deb583ed703fca6b63ffdd)` &) const` +#### _ssl +```cpp +SSL * _ssl +``` +--- -Copy/generate to the packet given output buffer. The number of bytes written can be obtained from the buffer. +#### _readBIO -Todo: It may be prefferable to use our pod types here instead of buffer input, but the current codebase requires that the buffer be dynamically resizable for some protocols... +```cpp +BIO * _readBIO +``` -#### `public inline virtual const char * className() const` +The incoming buffer we write encrypted SSL data into. +--- +#### _writeBIO +```cpp +BIO * _writeBIO +``` +The outgoing buffer we write to the socket. -# class `scy::net::SSLAdapter` +--- +#### _bufferOut +```cpp +std::vector< char > _bufferOut +``` +The outgoing payload to be encrypted and sent. +## SSLContext +> **Defined in:** `sslcontext.h` -## Summary +This class encapsulates context information for an SSL server or client, such as the certificate verification mode and the location of certificates and private key files, as well as the list of supported ciphers. - Members | Descriptions ---------------------------------|--------------------------------------------- -`public SSLAdapter(`[`net::SSLSocket`](#classscy_1_1net_1_1SSLSocket)` * socket)` | -`public ~SSLAdapter()` | -`public void initClient()` | Initializes the SSL context as a client. -`public void initServer()` | Initializes the SSL context as a server. -`public bool initialized() const` | Returns true when SSL context has been initialized. -`public bool ready() const` | Returns true when the handshake is complete. -`public void handshake()` | Start/continue the SSL handshake process. -`public int available() const` | -`public void shutdown()` | Issues an orderly SSL shutdown. -`public void flush()` | Flushes the SSL read/write buffers. -`public void addIncomingData(const char * data,size_t len)` | -`public void addOutgoingData(const std::string & data)` | -`public void addOutgoingData(const char * data,size_t len)` | -`protected `[`net::SSLSocket`](./doc/api-net.md#classscy_1_1net_1_1SSLSocket)` * _socket` | -`protected SSL * _ssl` | -`protected BIO * _readBIO` | The incoming buffer we write encrypted SSL data into. -`protected BIO * _writeBIO` | The outgoing buffer we write to the socket. -`protected std::vector< char > _bufferOut` | The outgoing payload to be encrypted and sent. -`protected void handleError(int rc)` | -`protected void flushReadBIO()` | -`protected void flushWriteBIO()` | +The Context class is also used to control SSL session caching on the server and client side. -## Members +### Members + +| Name | Description | +|------|-------------| +| [`Usage`](#group__net_1ga2e13fff7d4c75c080e515a427bf15c71) | | +| [`VerificationMode`](#group__net_1gafd7da63f7077511ce8d4da68f37d255e) | | +| [`SSLContext`](#group__net_1ga9bc5bae0a271799c171b37d3e6e13735) | Creates a Context. | +| [`SSLContext`](#group__net_1ga9fe3fe5f358b95a71a49a42798ec36ce) | Creates a Context. | +| [`~SSLContext`](#group__net_1gaf88baeb14fd0ee8d539e960f81142043) | Destroys the Context. | +| [`useCertificate`](#group__net_1ga840711ee078f8ee6432aaef8b50b48b9) | Sets the certificate to be used by the Context. | +| [`addChainCertificate`](#group__net_1gac4fe7dff44de813dcdf7daf80ea48d5f) | Adds a certificate for certificate chain validation. | +| [`addVerificationCertificate`](#group__net_1ga553376bb332952ef5c1829fb3600d554) | Sets the private key to be used by the Context. | +| [`sslContext`](#group__net_1ga88c101c4f8f5b4fe3ff3a4e50ff7ccfd) | Returns the underlying OpenSSL SSL Context object. | +| [`usage`](#group__net_1ga9b4562b3b554ae7b584a1cb2ab3825df) | Returns whether the context is for use by a client or by a server and whether TLSv1 is required. | +| [`isForServerUse`](#group__net_1ga5b018180ca35ce83c8d5efa9a33b3d35) | Returns true if the context is for use by a server. | +| [`verificationMode`](#group__net_1ga134311a6874bd856a4ad24fb7605784f) | Returns the verification mode. | +| [`enableSessionCache`](#group__net_1gabcb6479878cbc88959c819b4315d9d5b) | Enable or disable SSL/TLS session caching. For session caching to work, it must be enabled on the server, as well as on the client side. | +| [`enableSessionCache`](#group__net_1gafc6d7cc2fd93fb8e85f793e00b5d2926) | Enables or disables SSL/TLS session caching on the server. For session caching to work, it must be enabled on the server, as well as on the client side. | +| [`sessionCacheEnabled`](#group__net_1ga660b36fa2986687c39716fbf170d5284) | Returns true if the session cache is enabled. | +| [`setSessionCacheSize`](#group__net_1ga866c6d92313d85c8c580e742a722964b) | Sets the maximum size of the server session cache, in number of sessions. The default size (according to OpenSSL documentation) is 1024*20, which may be too large for many applications, especially on embedded platforms with limited memory. | +| [`getSessionCacheSize`](#group__net_1ga57776ff4697488efe841f32fd6334c0e) | Returns the current maximum size of the server session cache. | +| [`setSessionTimeout`](#group__net_1ga4f769feef9c5e604a5f66121e3618e14) | Sets the timeout (in seconds) of cached sessions on the server. A cached session will be removed from the cache if it has not been used for the given number of seconds. | +| [`getSessionTimeout`](#group__net_1ga00d5531a1264b6dbb8079779ba864eca) | Returns the timeout (in seconds) of cached sessions on the server. | +| [`flushSessionCache`](#group__net_1ga9d5e8a57a06cdaa54a8c5782785848c8) | Flushes the SSL session cache on the server. | +| [`disableStatelessSessionResumption`](#group__net_1gae16a7eff1253b2924e5254066e151c6b) | Newer versions of OpenSSL support RFC 4507 tickets for stateless session resumption. | +| [`createSSLContext`](#group__net_1ga93f1f41e4374901ebba9a13a07e6d851) | Create a SSL_CTX object according to Context configuration. | +| [`_usage`](#group__net_1ga171ace8794c0f1b9ff4ceb91ec887cd1) | | +| [`_mode`](#group__net_1ga9afa80a0f6ca11b832a906cb95180399) | | +| [`_sslContext`](#group__net_1ga7b1415c11d5ba729dfd704a0ea7183b6) | | +| [`_extendedVerificationErrorDetails`](#group__net_1gaecb958e393d9723c5fad530d024f1c51) | | + +--- + +#### Usage + +```cpp +enum Usage +``` -#### `public SSLAdapter(`[`net::SSLSocket`](#classscy_1_1net_1_1SSLSocket)` * socket)` +| Value | Description | +|-------|-------------| +| `CLIENT_USE` | Context is used by a client. | +| `SERVER_USE` | Context is used by a server. | +| `TLSV1_CLIENT_USE` | Context is used by a client requiring TLSv1. | +| `TLSV1_SERVER_USE` | Context is used by a server requiring TLSv2. | +--- +#### VerificationMode +```cpp +enum VerificationMode +``` +| Value | Description | +|-------|-------------| +| `VERIFY_NONE` | Server: The server will not send a client certificate request to the client, so the client will not send a certificate. | +| `VERIFY_RELAXED` | Server: The server sends a client certificate request to the client. The certificate returned (if any) is checked. If the verification process fails, the TLS/SSL handshake is immediately terminated with an alert message containing the reason for the verification failure. | +| `VERIFY_STRICT` | Server: If the client did not return a certificate, the TLS/SSL handshake is immediately terminated with a handshake failure alert. | +| `VERIFY_ONCE` | Server: Only request a client certificate on the initial TLS/SSL handshake. Do not ask for a client certificate again in case of a renegotiation. | -#### `public ~SSLAdapter()` +--- +#### SSLContext +```cpp +SSLContext(Usage usage, const std::string & privateKeyFile, const std::string & certificateFile, const std::string & caLocation, VerificationMode verificationMode, int verificationDepth, bool loadDefaultCAs, const std::string & cipherList) +``` +Creates a Context. +* usage specifies whether the context is used by a client or server. -#### `public void initClient()` +* privateKeyFile contains the path to the private key file used for encryption. Can be empty if no private key file is used. -Initializes the SSL context as a client. +* certificateFile contains the path to the certificate file (in PEM format). If the private key and the certificate are stored in the same file, this can be empty if privateKeyFile is given. +* caLocation contains the path to the file or directory containing the CA/root certificates. Can be empty if the OpenSSL builtin CA certificates are used (see loadDefaultCAs). +* verificationMode specifies whether and how peer certificates are validated. -#### `public void initServer()` +* verificationDepth sets the upper limit for verification chain sizes. Verification will fail if a certificate chain larger than this is encountered. -Initializes the SSL context as a server. +* loadDefaultCAs specifies wheter the builtin CA certificates from OpenSSL are used. +* cipherList specifies the supported ciphers in OpenSSL notation. +Note: If the private key is protected by a passphrase, a PrivateKeyPassphraseHandler must have been setup with the [SSLManager](#classscy_1_1net_1_1SSLManager), or the [SSLManager](#classscy_1_1net_1_1SSLManager)'s PrivateKeyPassphraseRequired event must be handled. -#### `public bool initialized() const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `usage` | `Usage` | | +| `privateKeyFile` | `const std::string &` | | +| `certificateFile` | `const std::string &` | | +| `caLocation` | `const std::string &` | | +| `verificationMode` | `VerificationMode` | | +| `verificationDepth` | `int` | | +| `loadDefaultCAs` | `bool` | | +| `cipherList` | `const std::string &` | | -Returns true when SSL context has been initialized. +--- +#### SSLContext +```cpp +SSLContext(Usage usage, const std::string & caLocation, VerificationMode verificationMode, int verificationDepth, bool loadDefaultCAs, const std::string & cipherList) +``` -#### `public bool ready() const` +Creates a Context. -Returns true when the handshake is complete. +* usage specifies whether the context is used by a client or server. +* caLocation contains the path to the file or directory containing the CA/root certificates. Can be empty if the OpenSSL builtin CA certificates are used (see loadDefaultCAs). +* verificationMode specifies whether and how peer certificates are validated. -#### `public void handshake()` +* verificationDepth sets the upper limit for verification chain sizes. Verification will fail if a certificate chain larger than this is encountered. -Start/continue the SSL handshake process. +* loadDefaultCAs specifies weather the builtin CA certificates from OpenSSL are used. +* cipherList specifies the supported ciphers in OpenSSL notation. +Note that a private key and/or certificate must be specified with usePrivateKey()/useCertificate() before the Context can be used. -#### `public int available() const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `usage` | `Usage` | | +| `caLocation` | `const std::string &` | | +| `verificationMode` | `VerificationMode` | | +| `verificationDepth` | `int` | | +| `loadDefaultCAs` | `bool` | | +| `cipherList` | `const std::string &` | | +--- +#### ~SSLContext -Returns the number of bytes available in the SSL buffer for immediate reading. +```cpp +~SSLContext() +``` -#### `public void shutdown()` +Destroys the Context. -Issues an orderly SSL shutdown. +--- +#### useCertificate +```cpp +void useCertificate(const crypto::X509Certificate & certificate) +``` -#### `public void flush()` +Sets the certificate to be used by the Context. -Flushes the SSL read/write buffers. +To set-up a complete certificate chain, it might be necessary to call [addChainCertificate()](#group__net_1gac4fe7dff44de813dcdf7daf80ea48d5f) to specify additional certificates. +Note that [useCertificate()](#group__net_1ga840711ee078f8ee6432aaef8b50b48b9) must always be called before usePrivateKey(). +| Parameter | Type | Description | +|-----------|------|-------------| +| `certificate` | `const crypto::X509Certificate &` | | -#### `public void addIncomingData(const char * data,size_t len)` +--- +#### addChainCertificate +```cpp +void addChainCertificate(const crypto::X509Certificate & certificate) +``` +Adds a certificate for certificate chain validation. +| Parameter | Type | Description | +|-----------|------|-------------| +| `certificate` | `const crypto::X509Certificate &` | | -#### `public void addOutgoingData(const std::string & data)` +--- +#### addVerificationCertificate +```cpp +void addVerificationCertificate(const crypto::X509Certificate & certificate) +``` +Sets the private key to be used by the Context. +Note that [useCertificate()](#group__net_1ga840711ee078f8ee6432aaef8b50b48b9) must always be called before usePrivateKey(). -#### `public void addOutgoingData(const char * data,size_t len)` +Note: If the private key is protected by a passphrase, a PrivateKeyPassphraseHandler must have been setup with the [SSLManager](#classscy_1_1net_1_1SSLManager), or the [SSLManager](#classscy_1_1net_1_1SSLManager)'s PrivateKeyPassphraseRequired event must be handled. Adds the given certificate to the list of trusted certificates that will be used for verification. +| Parameter | Type | Description | +|-----------|------|-------------| +| `certificate` | `const crypto::X509Certificate &` | | +--- +#### sslContext +```cpp +inline SSL_CTX * sslContext() const +``` -#### `protected `[`net::SSLSocket`](./doc/api-net.md#classscy_1_1net_1_1SSLSocket)` * _socket` +Returns the underlying OpenSSL SSL Context object. +--- +#### usage +```cpp +inline Usage usage() const +``` +Returns whether the context is for use by a client or by a server and whether TLSv1 is required. -#### `protected SSL * _ssl` +--- +#### isForServerUse +```cpp +inline bool isForServerUse() const +``` +Returns true if the context is for use by a server. +--- -#### `protected BIO * _readBIO` +#### verificationMode -The incoming buffer we write encrypted SSL data into. +```cpp +inline SSLContext::VerificationMode verificationMode() const +``` +Returns the verification mode. +--- -#### `protected BIO * _writeBIO` +#### enableSessionCache -The outgoing buffer we write to the socket. +```cpp +void enableSessionCache(bool flag) +``` +Enable or disable SSL/TLS session caching. For session caching to work, it must be enabled on the server, as well as on the client side. +The default is disabled session caching. -#### `protected std::vector< char > _bufferOut` +To enable session caching on the server side, use the two-argument version of this method to specify a session ID context. -The outgoing payload to be encrypted and sent. +| Parameter | Type | Description | +|-----------|------|-------------| +| `flag` | `bool` | | +--- +#### enableSessionCache -#### `protected void handleError(int rc)` +```cpp +void enableSessionCache(bool flag, const std::string & sessionIdContext) +``` +Enables or disables SSL/TLS session caching on the server. For session caching to work, it must be enabled on the server, as well as on the client side. +SessionIdContext contains the application's unique session ID context, which becomes part of each session identifier generated by the server within this context. SessionIdContext can be an arbitrary sequence of bytes with a maximum length of SSL_MAX_SSL_SESSION_ID_LENGTH. +A non-empty sessionIdContext should be specified even if session caching is disabled to avoid problems with clients requesting to reuse a session (e.g. Firefox 3.6). +This method may only be called on SERVER_USE Context objects. -#### `protected void flushReadBIO()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `flag` | `bool` | | +| `sessionIdContext` | `const std::string &` | | +--- +#### sessionCacheEnabled +```cpp +bool sessionCacheEnabled() const +``` +Returns true if the session cache is enabled. -#### `protected void flushWriteBIO()` +--- +#### setSessionCacheSize +```cpp +void setSessionCacheSize(size_t size) +``` +Sets the maximum size of the server session cache, in number of sessions. The default size (according to OpenSSL documentation) is 1024*20, which may be too large for many applications, especially on embedded platforms with limited memory. +Specifying a size of 0 will set an unlimited cache size. -# class `scy::net::SSLContext` +This method may only be called on SERVER_USE Context objects. +| Parameter | Type | Description | +|-----------|------|-------------| +| `size` | `size_t` | | +--- +#### getSessionCacheSize -This class encapsulates context information for an SSL server or client, such as the certificate verification mode and the location of certificates and private key files, as well as the list of supported ciphers. +```cpp +size_t getSessionCacheSize() const +``` -The Context class is also used to control SSL session caching on the server and client side. +Returns the current maximum size of the server session cache. -## Summary +This method may only be called on SERVER_USE Context objects. - Members | Descriptions ---------------------------------|--------------------------------------------- -`public SSLContext(`[`Usage`](#group__net_1ga2e13fff7d4c75c080e515a427bf15c71)` usage,const std::string & privateKeyFile,const std::string & certificateFile,const std::string & caLocation,`[`VerificationMode`](#group__net_1gafd7da63f7077511ce8d4da68f37d255e)` verificationMode,int verificationDepth,bool loadDefaultCAs,const std::string & cipherList)` | -`public SSLContext(`[`Usage`](#group__net_1ga2e13fff7d4c75c080e515a427bf15c71)` usage,const std::string & caLocation,`[`VerificationMode`](#group__net_1gafd7da63f7077511ce8d4da68f37d255e)` verificationMode,int verificationDepth,bool loadDefaultCAs,const std::string & cipherList)` | -`public ~SSLContext()` | Destroys the Context. -`public void useCertificate(const `[`crypto::X509Certificate`](#classscy_1_1crypto_1_1X509Certificate)` & certificate)` | -`public void addChainCertificate(const `[`crypto::X509Certificate`](#classscy_1_1crypto_1_1X509Certificate)` & certificate)` | Adds a certificate for certificate chain validation. -`public void addVerificationCertificate(const `[`crypto::X509Certificate`](#classscy_1_1crypto_1_1X509Certificate)` & certificate)` | -`public inline SSL_CTX * sslContext() const` | Returns the underlying OpenSSL SSL Context object. -`public inline `[`Usage`](#group__net_1ga2e13fff7d4c75c080e515a427bf15c71)` usage() const` | -`public inline bool isForServerUse() const` | Returns true if the context is for use by a server. -`public inline `[`SSLContext::VerificationMode`](#group__net_1gafd7da63f7077511ce8d4da68f37d255e)` verificationMode() const` | Returns the verification mode. -`public void enableSessionCache(bool flag)` | -`public void enableSessionCache(bool flag,const std::string & sessionIdContext)` | -`public bool sessionCacheEnabled() const` | Returns true if the session cache is enabled. -`public void setSessionCacheSize(size_t size)` | -`public size_t getSessionCacheSize() const` | -`public void setSessionTimeout(long seconds)` | -`public long getSessionTimeout() const` | -`public void flushSessionCache()` | -`public void disableStatelessSessionResumption()` | +--- -## Members +#### setSessionTimeout -#### `public SSLContext(`[`Usage`](#group__net_1ga2e13fff7d4c75c080e515a427bf15c71)` usage,const std::string & privateKeyFile,const std::string & certificateFile,const std::string & caLocation,`[`VerificationMode`](#group__net_1gafd7da63f7077511ce8d4da68f37d255e)` verificationMode,int verificationDepth,bool loadDefaultCAs,const std::string & cipherList)` +```cpp +void setSessionTimeout(long seconds) +``` +Sets the timeout (in seconds) of cached sessions on the server. A cached session will be removed from the cache if it has not been used for the given number of seconds. +This method may only be called on SERVER_USE Context objects. -Creates a Context. +| Parameter | Type | Description | +|-----------|------|-------------| +| `seconds` | `long` | | +--- +#### getSessionTimeout -* usage specifies whether the context is used by a client or server. +```cpp +long getSessionTimeout() const +``` +Returns the timeout (in seconds) of cached sessions on the server. -* privateKeyFile contains the path to the private key file used for encryption. Can be empty if no private key file is used. +This method may only be called on SERVER_USE Context objects. +--- -* certificateFile contains the path to the certificate file (in PEM format). If the private key and the certificate are stored in the same file, this can be empty if privateKeyFile is given. +#### flushSessionCache +```cpp +void flushSessionCache() +``` -* caLocation contains the path to the file or directory containing the CA/root certificates. Can be empty if the OpenSSL builtin CA certificates are used (see loadDefaultCAs). +Flushes the SSL session cache on the server. +This method may only be called on SERVER_USE Context objects. -* verificationMode specifies whether and how peer certificates are validated. +--- +#### disableStatelessSessionResumption -* verificationDepth sets the upper limit for verification chain sizes. Verification will fail if a certificate chain larger than this is encountered. +```cpp +void disableStatelessSessionResumption() +``` +Newer versions of OpenSSL support RFC 4507 tickets for stateless session resumption. -* loadDefaultCAs specifies wheter the builtin CA certificates from OpenSSL are used. +The feature can be disabled by calling this method. +--- -* cipherList specifies the supported ciphers in OpenSSL notation. +#### createSSLContext +```cpp +void createSSLContext() +``` +Create a SSL_CTX object according to Context configuration. +--- +#### _usage -Note: If the private key is protected by a passphrase, a PrivateKeyPassphraseHandler must have been setup with the [SSLManager](#classscy_1_1net_1_1SSLManager), or the [SSLManager](#classscy_1_1net_1_1SSLManager)'s PrivateKeyPassphraseRequired event must be handled. +```cpp +Usage _usage +``` -#### `public SSLContext(`[`Usage`](#group__net_1ga2e13fff7d4c75c080e515a427bf15c71)` usage,const std::string & caLocation,`[`VerificationMode`](#group__net_1gafd7da63f7077511ce8d4da68f37d255e)` verificationMode,int verificationDepth,bool loadDefaultCAs,const std::string & cipherList)` +--- +#### _mode +```cpp +VerificationMode _mode +``` -Creates a Context. +--- +#### _sslContext +```cpp +SSL_CTX * _sslContext +``` -* usage specifies whether the context is used by a client or server. +--- +#### _extendedVerificationErrorDetails -* caLocation contains the path to the file or directory containing the CA/root certificates. Can be empty if the OpenSSL builtin CA certificates are used (see loadDefaultCAs). +```cpp +bool _extendedVerificationErrorDetails +``` +## SSLManager -* verificationMode specifies whether and how peer certificates are validated. +> **Defined in:** `sslmanager.h` +[SSLManager](#classscy_1_1net_1_1SSLManager) is a singleton for holding the default server/client Context and handling callbacks for certificate verification errors and private key passphrases. -* verificationDepth sets the upper limit for verification chain sizes. Verification will fail if a certificate chain larger than this is encountered. +### Members + +| Name | Description | +|------|-------------| +| [`initializeServer`](#group__net_1ga5476ccf3e346e493c3d053a21f3f2b29) | Initializes the server side of the [SSLManager](#classscy_1_1net_1_1SSLManager) server-side [SSLContext](#classscy_1_1net_1_1SSLContext). | +| [`initializeClient`](#group__net_1ga4472c80b8b9152947333589515621051) | Initializes the client side of the [SSLManager](#classscy_1_1net_1_1SSLManager) with a default client-side [SSLContext](#classscy_1_1net_1_1SSLContext). | +| [`defaultServerContext`](#group__net_1ga5888698b042c4c4a16d69fc98cb0e582) | Returns the default Context used by the server if initialized. | +| [`defaultClientContext`](#group__net_1gaf06768dcfa955ebdd5b9c3977682e6ea) | Returns the default Context used by the client if initialized. | +| [`shutdown`](#group__net_1ga4061d56eaf906bf79a0713310a3841c5) | Shuts down the [SSLManager](#classscy_1_1net_1_1SSLManager) and releases the default Context objects. After a call to [shutdown()](#group__net_1ga4061d56eaf906bf79a0713310a3841c5), the [SSLManager](#classscy_1_1net_1_1SSLManager) can no longer be used. | +| [`instance`](#group__net_1gad3081151d10c5c6c4247f891925f93a7) | Returns the instance of the [SSLManager](#classscy_1_1net_1_1SSLManager) singleton. | +| [`destroy`](#group__net_1ga64402426d6371b93d7a3544da637621f) | Shuts down and destroys the [SSLManager](#classscy_1_1net_1_1SSLManager) singleton instance. | +| [`initNoVerifyClient`](#group__net_1ga9ea94e19abecb2e8227dbda1d577f093) | Initializes a default no verify client context that's useful for testing. | +| [`initNoVerifyServer`](#group__net_1ga71aad45fb6aceb1a551c247c90523e8d) | Initializes a default no verify server context that's useful for testing. | +| [`verifyClientCallback`](#group__net_1gaf4e686f568fceeba5b78df815a050745) | The return value of this method defines how errors in verification are handled. Return 0 to terminate the handshake, or 1 to continue despite the error. | +| [`verifyServerCallback`](#group__net_1gacc7394320818b4d2fe6c75f486876d76) | The return value of this method defines how errors in verification are handled. Return 0 to terminate the handshake, ' or 1 to continue despite the error. | +| [`privateKeyPassphraseCallback`](#group__net_1ga5266f886ac5eb14dcd5e3df0f80c5dc0) | Method is invoked by OpenSSL to retrieve a passwd for an encrypted certificate. The request is delegated to the PrivatekeyPassword event. This method returns the length of the password. | +| [`SSLManager`](#group__net_1gac04b1f45008ee73e39c9e05e3f86c7c8) | Creates the [SSLManager](#classscy_1_1net_1_1SSLManager). | +| [`~SSLManager`](#group__net_1gaa643df995c0323b8c4e4d5f6e0cd8558) | Destroys the [SSLManager](#classscy_1_1net_1_1SSLManager). | +| [`verifyCallback`](#group__net_1gaaca523b350828a78b7dfbd7792e50868) | The return value of this method defines how errors in verification are handled. Return 0 to terminate the handshake, or 1 to continue despite the error. | +| [`ServerVerificationError`](#group__net_1ga5c8d1a58ad63cfe7fd8c6ef8da2bc7bc) | Fired whenever a certificate verification error is detected by the server during a handshake. | +| [`ClientVerificationError`](#group__net_1ga79cecc2be9b8293b79f9dc92b3ab967d) | Fired whenever a certificate verification error is detected by the client during a handshake. | +| [`PrivateKeyPassphraseRequired`](#group__net_1gac92a4d1a788ac605e000055f0c2d1f0b) | Fired when a encrypted certificate is loaded. Not setting the password in the event parameter will result in a failure to load the certificate. | +| [`_defaultServerContext`](#group__net_1ga24b0830bf753c01e75d4fcf73cfb29d5) | | +| [`_defaultClientContext`](#group__net_1ga800460ae0a45bca4054a039e64475d13) | | +| [`_mutex`](#group__net_1ga59eebca4de704e16e969adf52f602d68) | | + +--- + +#### initializeServer + +```cpp +void initializeServer(SSLContext::Ptr ptrContext) +``` +Initializes the server side of the [SSLManager](#classscy_1_1net_1_1SSLManager) server-side [SSLContext](#classscy_1_1net_1_1SSLContext). -* loadDefaultCAs specifies weather the builtin CA certificates from OpenSSL are used. +| Parameter | Type | Description | +|-----------|------|-------------| +| `ptrContext` | `SSLContext::Ptr` | | +--- -* cipherList specifies the supported ciphers in OpenSSL notation. +#### initializeClient +```cpp +void initializeClient(SSLContext::Ptr ptrContext) +``` +Initializes the client side of the [SSLManager](#classscy_1_1net_1_1SSLManager) with a default client-side [SSLContext](#classscy_1_1net_1_1SSLContext). +| Parameter | Type | Description | +|-----------|------|-------------| +| `ptrContext` | `SSLContext::Ptr` | | +--- -Note that a private key and/or certificate must be specified with usePrivateKey()/useCertificate() before the Context can be used. +#### defaultServerContext -#### `public ~SSLContext()` +```cpp +SSLContext::Ptr defaultServerContext() +``` -Destroys the Context. +Returns the default Context used by the server if initialized. +--- +#### defaultClientContext -#### `public void useCertificate(const `[`crypto::X509Certificate`](#classscy_1_1crypto_1_1X509Certificate)` & certificate)` +```cpp +SSLContext::Ptr defaultClientContext() +``` +Returns the default Context used by the client if initialized. +--- -Sets the certificate to be used by the Context. +#### shutdown -To set-up a complete certificate chain, it might be necessary to call [addChainCertificate()](#group__net_1gac4fe7dff44de813dcdf7daf80ea48d5f) to specify additional certificates. +```cpp +void shutdown() +``` -Note that [useCertificate()](#group__net_1ga840711ee078f8ee6432aaef8b50b48b9) must always be called before usePrivateKey(). +Shuts down the [SSLManager](#classscy_1_1net_1_1SSLManager) and releases the default Context objects. After a call to [shutdown()](#group__net_1ga4061d56eaf906bf79a0713310a3841c5), the [SSLManager](#classscy_1_1net_1_1SSLManager) can no longer be used. -#### `public void addChainCertificate(const `[`crypto::X509Certificate`](#classscy_1_1crypto_1_1X509Certificate)` & certificate)` +Normally, it's not necessary to call this method directly, as this will be called either by [uninitializeSSL()](#group__net_1gab2698107bdb6a2b9a2bcea869e26d50b), or when the [SSLManager](#classscy_1_1net_1_1SSLManager) instance is destroyed. -Adds a certificate for certificate chain validation. +--- +#### instance +```cpp +static SSLManager & instance() +``` -#### `public void addVerificationCertificate(const `[`crypto::X509Certificate`](#classscy_1_1crypto_1_1X509Certificate)` & certificate)` +Returns the instance of the [SSLManager](#classscy_1_1net_1_1SSLManager) singleton. +--- +#### destroy -Sets the private key to be used by the Context. +```cpp +static void destroy() +``` -Note that [useCertificate()](#group__net_1ga840711ee078f8ee6432aaef8b50b48b9) must always be called before usePrivateKey(). +Shuts down and destroys the [SSLManager](#classscy_1_1net_1_1SSLManager) singleton instance. -Note: If the private key is protected by a passphrase, a PrivateKeyPassphraseHandler must have been setup with the [SSLManager](#classscy_1_1net_1_1SSLManager), or the [SSLManager](#classscy_1_1net_1_1SSLManager)'s PrivateKeyPassphraseRequired event must be handled. Adds the given certificate to the list of trusted certificates that will be used for verification. +--- -#### `public inline SSL_CTX * sslContext() const` +#### initNoVerifyClient -Returns the underlying OpenSSL SSL Context object. +```cpp +static void initNoVerifyClient() +``` +Initializes a default no verify client context that's useful for testing. +--- -#### `public inline `[`Usage`](#group__net_1ga2e13fff7d4c75c080e515a427bf15c71)` usage() const` +#### initNoVerifyServer +```cpp +static void initNoVerifyServer(const std::string & privateKeyFile, const std::string & certificateFile) +``` +Initializes a default no verify server context that's useful for testing. -Returns whether the context is for use by a client or by a server and whether TLSv1 is required. +| Parameter | Type | Description | +|-----------|------|-------------| +| `privateKeyFile` | `const std::string &` | | +| `certificateFile` | `const std::string &` | | -#### `public inline bool isForServerUse() const` +--- -Returns true if the context is for use by a server. +#### verifyClientCallback +```cpp +static int verifyClientCallback(int ok, X509_STORE_CTX * pStore) +``` +The return value of this method defines how errors in verification are handled. Return 0 to terminate the handshake, or 1 to continue despite the error. -#### `public inline `[`SSLContext::VerificationMode`](#group__net_1gafd7da63f7077511ce8d4da68f37d255e)` verificationMode() const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `ok` | `int` | | +| `pStore` | `X509_STORE_CTX *` | | -Returns the verification mode. +--- +#### verifyServerCallback +```cpp +static int verifyServerCallback(int ok, X509_STORE_CTX * pStore) +``` -#### `public void enableSessionCache(bool flag)` +The return value of this method defines how errors in verification are handled. Return 0 to terminate the handshake, ' or 1 to continue despite the error. +| Parameter | Type | Description | +|-----------|------|-------------| +| `ok` | `int` | | +| `pStore` | `X509_STORE_CTX *` | | +--- -Enable or disable SSL/TLS session caching. For session caching to work, it must be enabled on the server, as well as on the client side. +#### privateKeyPassphraseCallback -The default is disabled session caching. +```cpp +static int privateKeyPassphraseCallback(char * pBuf, int size, int flag, void * userData) +``` -To enable session caching on the server side, use the two-argument version of this method to specify a session ID context. +Method is invoked by OpenSSL to retrieve a passwd for an encrypted certificate. The request is delegated to the PrivatekeyPassword event. This method returns the length of the password. -#### `public void enableSessionCache(bool flag,const std::string & sessionIdContext)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `pBuf` | `char *` | | +| `size` | `int` | | +| `flag` | `int` | | +| `userData` | `void *` | | +--- +#### SSLManager -Enables or disables SSL/TLS session caching on the server. For session caching to work, it must be enabled on the server, as well as on the client side. +```cpp +SSLManager() +``` -SessionIdContext contains the application's unique session ID context, which becomes part of each session identifier generated by the server within this context. SessionIdContext can be an arbitrary sequence of bytes with a maximum length of SSL_MAX_SSL_SESSION_ID_LENGTH. +Creates the [SSLManager](#classscy_1_1net_1_1SSLManager). -A non-empty sessionIdContext should be specified even if session caching is disabled to avoid problems with clients requesting to reuse a session (e.g. Firefox 3.6). +--- -This method may only be called on SERVER_USE Context objects. +#### ~SSLManager -#### `public bool sessionCacheEnabled() const` +```cpp +~SSLManager() +``` -Returns true if the session cache is enabled. +Destroys the [SSLManager](#classscy_1_1net_1_1SSLManager). +--- +#### verifyCallback -#### `public void setSessionCacheSize(size_t size)` +```cpp +static int verifyCallback(bool server, int ok, X509_STORE_CTX * pStore) +``` +The return value of this method defines how errors in verification are handled. Return 0 to terminate the handshake, or 1 to continue despite the error. +| Parameter | Type | Description | +|-----------|------|-------------| +| `server` | `bool` | | +| `ok` | `int` | | +| `pStore` | `X509_STORE_CTX *` | | -Sets the maximum size of the server session cache, in number of sessions. The default size (according to OpenSSL documentation) is 1024*20, which may be too large for many applications, especially on embedded platforms with limited memory. +--- -Specifying a size of 0 will set an unlimited cache size. +#### ServerVerificationError -This method may only be called on SERVER_USE Context objects. +```cpp +Signal< void(VerificationErrorDetails &)> ServerVerificationError +``` -#### `public size_t getSessionCacheSize() const` +Fired whenever a certificate verification error is detected by the server during a handshake. +--- +#### ClientVerificationError -Returns the current maximum size of the server session cache. +```cpp +Signal< void(VerificationErrorDetails &)> ClientVerificationError +``` -This method may only be called on SERVER_USE Context objects. +Fired whenever a certificate verification error is detected by the client during a handshake. -#### `public void setSessionTimeout(long seconds)` +--- +#### PrivateKeyPassphraseRequired +```cpp +Signal< void(std::string &)> PrivateKeyPassphraseRequired +``` -Sets the timeout (in seconds) of cached sessions on the server. A cached session will be removed from the cache if it has not been used for the given number of seconds. +Fired when a encrypted certificate is loaded. Not setting the password in the event parameter will result in a failure to load the certificate. -This method may only be called on SERVER_USE Context objects. +--- -#### `public long getSessionTimeout() const` +#### _defaultServerContext +```cpp +SSLContext::Ptr _defaultServerContext +``` +--- -Returns the timeout (in seconds) of cached sessions on the server. +#### _defaultClientContext -This method may only be called on SERVER_USE Context objects. +```cpp +SSLContext::Ptr _defaultClientContext +``` -#### `public void flushSessionCache()` +--- +#### _mutex +```cpp +std::mutex _mutex +``` -Flushes the SSL session cache on the server. +## VerificationErrorDetails -This method may only be called on SERVER_USE Context objects. +> **Defined in:** `sslmanager.h` -#### `public void disableStatelessSessionResumption()` +A utility class for certificate error handling. +### Members + +| Name | Description | +|------|-------------| +| [`VerificationErrorDetails`](#group__net_1ga6149cde284d053bbb8ea7f7d4febf260) | Creates the [VerificationErrorDetails](#classscy_1_1net_1_1VerificationErrorDetails). _ignoreError is per default set to false. | +| [`~VerificationErrorDetails`](#group__net_1ga341d067a4369d88415b30f9d6acf9516) | Destroys the [VerificationErrorDetails](#classscy_1_1net_1_1VerificationErrorDetails). | +| [`certificate`](#group__net_1gaa61f1bc21123f77329fcc4c2e9c1b3a5) | Returns the certificate that caused the error. | +| [`errorDepth`](#group__net_1ga7f64fe88500e3df99bd0bd7cd8d2d598) | Returns the position of the certificate in the certificate chain. | +| [`errorNumber`](#group__net_1gac0130d1cbbca92575e2259000f792cef) | Returns the id of the error. | +| [`errorMessage`](#group__net_1gaa13f824914ad36284036dcf6a07d6b2c) | Returns the textual presentation of the errorNumber. | +| [`setIgnoreError`](#group__net_1ga762c71561020eb2eae6842f5cfc6dcd4) | setIgnoreError to true, if a verification error is judged non-fatal by the user. | +| [`getIgnoreError`](#group__net_1ga682fc13cdc647b176d2e0d3ef3e783fb) | returns the value of _ignoreError | +| [`_cert`](#group__net_1ga7bd145c098bbf10aa7b8887a0927dfed) | | +| [`_errorDepth`](#group__net_1gacaa650f5c1a9317c9e18cb33468aec10) | | +| [`_errorNumber`](#group__net_1gad62239805ea4bfee112162f09b203163) | | +| [`_errorMessage`](#group__net_1ga24a7e119f990bdc4965004d070588c30) | | +| [`_ignoreError`](#group__net_1ga32ad9d20fe3b08310d3b4152ec840bc5) | | + +--- + +#### VerificationErrorDetails + +```cpp +VerificationErrorDetails(const crypto::X509Certificate & cert, int errDepth, int errNum, const std::string & errMsg) +``` +Creates the [VerificationErrorDetails](#classscy_1_1net_1_1VerificationErrorDetails). _ignoreError is per default set to false. -Newer versions of OpenSSL support RFC 4507 tickets for stateless session resumption. +| Parameter | Type | Description | +|-----------|------|-------------| +| `cert` | `const crypto::X509Certificate &` | | +| `errDepth` | `int` | | +| `errNum` | `int` | | +| `errMsg` | `const std::string &` | | -The feature can be disabled by calling this method. +--- -# class `scy::net::SSLManager` +#### ~VerificationErrorDetails +```cpp +~VerificationErrorDetails() +``` +Destroys the [VerificationErrorDetails](#classscy_1_1net_1_1VerificationErrorDetails). +--- -[SSLManager](#classscy_1_1net_1_1SSLManager) is a singleton for holding the default server/client Context and handling callbacks for certificate verification errors and private key passphrases. +#### certificate -## Summary +```cpp +inline const crypto::X509Certificate & certificate() const +``` - Members | Descriptions ---------------------------------|--------------------------------------------- -`public `[`Signal](#classscy_1_1Signal)< void([VerificationErrorDetails`](#classscy_1_1net_1_1VerificationErrorDetails) &)`> ServerVerificationError` | -`public `[`Signal](#classscy_1_1Signal)< void([VerificationErrorDetails`](#classscy_1_1net_1_1VerificationErrorDetails) &)`> ClientVerificationError` | -`public `[`Signal`](#classscy_1_1Signal)< void(std::string &)`> PrivateKeyPassphraseRequired` | -`public void initializeServer(SSLContext::Ptr ptrContext)` | Initializes the server side of the [SSLManager](#classscy_1_1net_1_1SSLManager) server-side [SSLContext](#classscy_1_1net_1_1SSLContext). -`public void initializeClient(SSLContext::Ptr ptrContext)` | -`public SSLContext::Ptr defaultServerContext()` | Returns the default Context used by the server if initialized. -`public SSLContext::Ptr defaultClientContext()` | Returns the default Context used by the client if initialized. -`public void shutdown()` | +Returns the certificate that caused the error. -## Members +--- -#### `public `[`Signal](#classscy_1_1Signal)< void([VerificationErrorDetails`](#classscy_1_1net_1_1VerificationErrorDetails) &)`> ServerVerificationError` +#### errorDepth +```cpp +inline int errorDepth() const +``` +Returns the position of the certificate in the certificate chain. -Fired whenever a certificate verification error is detected by the server during a handshake. +--- -#### `public `[`Signal](#classscy_1_1Signal)< void([VerificationErrorDetails`](#classscy_1_1net_1_1VerificationErrorDetails) &)`> ClientVerificationError` +#### errorNumber +```cpp +inline int errorNumber() const +``` +Returns the id of the error. -Fired whenever a certificate verification error is detected by the client during a handshake. +--- -#### `public `[`Signal`](#classscy_1_1Signal)< void(std::string &)`> PrivateKeyPassphraseRequired` +#### errorMessage +```cpp +inline const std::string & errorMessage() const +``` +Returns the textual presentation of the errorNumber. -Fired when a encrypted certificate is loaded. Not setting the password in the event parameter will result in a failure to load the certificate. +--- -#### `public void initializeServer(SSLContext::Ptr ptrContext)` +#### setIgnoreError -Initializes the server side of the [SSLManager](#classscy_1_1net_1_1SSLManager) server-side [SSLContext](#classscy_1_1net_1_1SSLContext). +```cpp +inline void setIgnoreError(bool ignoreError) +``` +setIgnoreError to true, if a verification error is judged non-fatal by the user. +| Parameter | Type | Description | +|-----------|------|-------------| +| `ignoreError` | `bool` | | -#### `public void initializeClient(SSLContext::Ptr ptrContext)` +--- +#### getIgnoreError +```cpp +inline bool getIgnoreError() const +``` -Initializes the client side of the [SSLManager](#classscy_1_1net_1_1SSLManager) with a default client-side [SSLContext](#classscy_1_1net_1_1SSLContext). +returns the value of _ignoreError -#### `public SSLContext::Ptr defaultServerContext()` +--- -Returns the default Context used by the server if initialized. +#### _cert +```cpp +crypto::X509Certificate _cert +``` +--- -#### `public SSLContext::Ptr defaultClientContext()` +#### _errorDepth -Returns the default Context used by the client if initialized. +```cpp +int _errorDepth +``` +--- +#### _errorNumber -#### `public void shutdown()` +```cpp +int _errorNumber +``` +--- +#### _errorMessage -Shuts down the [SSLManager](#classscy_1_1net_1_1SSLManager) and releases the default Context objects. After a call to [shutdown()](#group__net_1ga4061d56eaf906bf79a0713310a3841c5), the [SSLManager](#classscy_1_1net_1_1SSLManager) can no longer be used. +```cpp +std::string _errorMessage +``` -Normally, it's not necessary to call this method directly, as this will be called either by uninitializeSSL(), or when the [SSLManager](#classscy_1_1net_1_1SSLManager) instance is destroyed. +--- -# class `scy::net::SSLSession` +#### _ignoreError +```cpp +bool _ignoreError +``` +## SSLSession +> **Defined in:** `sslsession.h` This class encapsulates a SSL session object used with session caching on the client side. For session caching to work, a client must save the session object from an existing connection, if it wants to reuse it with a future connection. -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public SSL_SESSION * sslSession() const` | Returns the stored OpenSSL SSL_SESSION object. -`public SSLSession(SSL_SESSION * ptr)` | -`public ~SSLSession()` | -`public SSLSession()` | -`protected SSL_SESSION * _ptr` | +### Members -## Members +| Name | Description | +|------|-------------| +| [`sslSession`](#group__net_1ga6581d3ef3c9d2cb11707fcd0f1848b7e) | Returns the stored OpenSSL SSL_SESSION object. | +| [`SSLSession`](#group__net_1ga432cb2d0fa33e99be752e2f67b05b24e) | Creates a new Session object, using the given SSL_SESSION object. | +| [`~SSLSession`](#group__net_1ga46203b77ac08b39a29c45bd4cb616f96) | Destroys the Session. | +| [`SSLSession`](#group__net_1ga9e95112e1b50fd581979c940f7024655) | | +| [`_ptr`](#group__net_1ga304e950ce3ef764e602a67033539de62) | | -#### `public SSL_SESSION * sslSession() const` +--- -Returns the stored OpenSSL SSL_SESSION object. +#### sslSession +```cpp +SSL_SESSION * sslSession() const +``` +Returns the stored OpenSSL SSL_SESSION object. -#### `public SSLSession(SSL_SESSION * ptr)` +--- +#### SSLSession +```cpp +SSLSession(SSL_SESSION * ptr) +``` Creates a new Session object, using the given SSL_SESSION object. The SSL_SESSION's reference count is not changed. -#### `public ~SSLSession()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `ptr` | `SSL_SESSION *` | | + +--- +#### ~SSLSession +```cpp +~SSLSession() +``` Destroys the Session. Calls SSL_SESSION_free() on the stored SSL_SESSION object. -#### `public SSLSession()` - +--- +#### SSLSession - - -#### `protected SSL_SESSION * _ptr` - - - - - -# class `scy::net::SSLSocket` - +```cpp +SSLSession() ``` -class scy::net::SSLSocket - : public scy::net::TCPSocket -``` - -SSL socket implementation. +--- +#### _ptr -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public SSLSocket(uv::Loop * loop)` | -`public SSLSocket(SSLContext::Ptr sslContext,uv::Loop * loop)` | -`public SSLSocket(SSLContext::Ptr sslContext,SSLSession::Ptr session,uv::Loop * loop)` | -`public virtual ~SSLSocket()` | -`public virtual void bind(const `[`net::Address`](#classscy_1_1net_1_1Address)` & address,unsigned flags)` | Initialize the [SSLSocket](#classscy_1_1net_1_1SSLSocket) with the given [SSLContext](#classscy_1_1net_1_1SSLContext). -`public virtual void listen(int backlog)` | -`public virtual bool shutdown()` | -`public virtual void close()` | Closes the socket forcefully. -`public virtual ssize_t send(const char * data,size_t len,int flags)` | -`public virtual ssize_t send(const char * data,size_t len,const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddress,int flags)` | -`public void useContext(SSLContext::Ptr context)` | Use the given SSL context for this socket. -`public SSLContext::Ptr context() const` | Returns the SSL context used for this socket. -`public void useSession(SSLSession::Ptr session)` | -`public SSLSession::Ptr currentSession()` | -`public bool sessionWasReused()` | -`public int available() const` | -`public X509 * peerCertificate() const` | Returns the peer's certificate. -`public virtual net::TransportType transport() const` | The transport protocol: TCP, UDP or SSLTCP. -`public virtual void acceptConnection()` | -`public virtual void onConnect()` | -`public virtual void onRead(const char * data,size_t len)` | Reads raw encrypted SSL data. -`protected net::SSLContext::Ptr _sslContext` | -`protected net::SSLSession::Ptr _sslSession` | -`protected `[`net::SSLAdapter`](./doc/api-net.md#classscy_1_1net_1_1SSLAdapter)` _sslAdapter` | - -## Members - -#### `public SSLSocket(uv::Loop * loop)` - +```cpp +SSL_SESSION * _ptr +``` +## SSLSocket +> **Extends:** `scy::net::TCPSocket` +> **Defined in:** `sslsocket.h` +SSL socket implementation. -#### `public SSLSocket(SSLContext::Ptr sslContext,uv::Loop * loop)` +### Members + +| Name | Description | +|------|-------------| +| [`SSLSocket`](#group__net_1ga621415db5b8ff309cec65201efc086bf) | | +| [`SSLSocket`](#group__net_1ga6ef56420a681a95cd42e066a842b1b63) | | +| [`SSLSocket`](#group__net_1ga0d27d1f822710a64478dffc4fad17f98) | | +| [`~SSLSocket`](#group__net_1ga55a2e9ca93a9fcaddbf2bad40a57966b) | | +| [`bind`](#group__net_1gaa16ace2e62e4b075bba8920cfbd098ad) | Initialize the [SSLSocket](#classscy_1_1net_1_1SSLSocket) with the given [SSLContext](#classscy_1_1net_1_1SSLContext). | +| [`listen`](#group__net_1ga68e4327abb9e2bdb1ed7e3a6e7c0e49b) | Listens the socket on the given address. | +| [`shutdown`](#group__net_1ga8d6ff3564619b9ea9cb1cc0aa54aa760) | Shuts down the connection by attempting an orderly SSL shutdown, then actually shutting down the TCP connection. | +| [`close`](#group__net_1ga0fe89adb626dcd2aeaba9b941ea3c6cf) | Closes the socket forcefully. | +| [`send`](#group__net_1gabd0a71795b9bfe30bf29447d750c8617) | Sends the given data buffer to the connected peer. Returns the number of bytes sent or -1 on error. No exception will be thrown. For TCP sockets the given peer address must match the connected peer address. | +| [`send`](#group__net_1gace69dc9e5072193cbc7c7a84efd3ad84) | | +| [`useContext`](#group__net_1ga25cdc10ce54de6edcf57b5612788e23d) | Use the given SSL context for this socket. | +| [`context`](#group__net_1gacd6970a43ee59539f56d29cc503f78ab) | Returns the SSL context used for this socket. | +| [`useSession`](#group__net_1ga73a2c547fb422f580065091121dcba3c) | Sets the SSL session to use for the next connection. Setting a previously saved Session object is necessary to enable session caching. | +| [`currentSession`](#group__net_1gab2d4b703c76423909dd34f47f46e73fe) | Returns the SSL session of the current connection, for reuse in a future connection (if session caching is enabled). | +| [`sessionWasReused`](#group__net_1gab713d571c3f619b39d09686f6299ce14) | Returns true if a reused session was negotiated during the handshake. | +| [`available`](#group__net_1gacbbee7806e51d77e9cbe79c104806f17) | Returns the number of bytes available from the SSL buffer for immediate reading. | +| [`peerCertificate`](#group__net_1ga6d0638ab3739dbb622be0dccf39c5002) | Returns the peer's certificate. | +| [`transport`](#group__net_1ga5c1ccbcbd95f4ffed016be3e42a3e238) | The transport protocol: TCP, UDP or SSLTCP. | +| [`acceptConnection`](#group__net_1ga7192db6b478429219e604abf05c191b9) | | +| [`onConnect`](#group__net_1ga71746677601b346f690890cdff280fcb) | | +| [`onRead`](#group__net_1gaeb276dae5d2dd0009507a0fd85aabab2) | Reads raw encrypted SSL data. | +| [`_sslContext`](#group__net_1ga765115a8e31c43eb06a1468685942dd9) | | +| [`_sslSession`](#group__net_1ga387514f7edb5f125120b2db1e3caffa2) | | +| [`_sslAdapter`](#group__net_1ga6d18c18a5cf420456474c9e55736a1ac) | | + +--- + +#### SSLSocket + +```cpp +SSLSocket(uv::Loop * loop) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `loop` | `uv::Loop *` | | +--- +#### SSLSocket +```cpp +SSLSocket(SSLContext::Ptr sslContext, uv::Loop * loop) +``` -#### `public SSLSocket(SSLContext::Ptr sslContext,SSLSession::Ptr session,uv::Loop * loop)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `sslContext` | `SSLContext::Ptr` | | +| `loop` | `uv::Loop *` | | +--- +#### SSLSocket +```cpp +SSLSocket(SSLContext::Ptr sslContext, SSLSession::Ptr session, uv::Loop * loop) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `sslContext` | `SSLContext::Ptr` | | +| `session` | `SSLSession::Ptr` | | +| `loop` | `uv::Loop *` | | -#### `public virtual ~SSLSocket()` +--- +#### ~SSLSocket +```cpp +virtual ~SSLSocket() +``` +--- +#### bind -#### `public virtual void bind(const `[`net::Address`](#classscy_1_1net_1_1Address)` & address,unsigned flags)` +```cpp +virtual void bind(const net::Address & address, unsigned flags) +``` Initialize the [SSLSocket](#classscy_1_1net_1_1SSLSocket) with the given [SSLContext](#classscy_1_1net_1_1SSLContext). @@ -1572,53 +2658,109 @@ Initializes the socket and establishes a secure connection to the TCP server at The SSL handshake is performed when the socket is connected. -#### `public virtual void listen(int backlog)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `address` | `const net::Address &` | | +| `flags` | `unsigned` | | +--- +#### listen + +```cpp +virtual void listen(int backlog) +``` Listens the socket on the given address. Throws an Exception on error. -#### `public virtual bool shutdown()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `backlog` | `int` | | +--- +#### shutdown + +```cpp +virtual bool shutdown() +``` Shuts down the connection by attempting an orderly SSL shutdown, then actually shutting down the TCP connection. -#### `public virtual void close()` +--- -Closes the socket forcefully. +#### close +```cpp +virtual void close() +``` +Closes the socket forcefully. -#### `public virtual ssize_t send(const char * data,size_t len,int flags)` +--- +#### send +```cpp +virtual ssize_t send(const char * data, size_t len, int flags) +``` Sends the given data buffer to the connected peer. Returns the number of bytes sent or -1 on error. No exception will be thrown. For TCP sockets the given peer address must match the connected peer address. -#### `public virtual ssize_t send(const char * data,size_t len,const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddress,int flags)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `data` | `const char *` | | +| `len` | `size_t` | | +| `flags` | `int` | | +--- +#### send +```cpp +virtual ssize_t send(const char * data, size_t len, const net::Address & peerAddress, int flags) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `data` | `const char *` | | +| `len` | `size_t` | | +| `peerAddress` | `const net::Address &` | | +| `flags` | `int` | | -#### `public void useContext(SSLContext::Ptr context)` +--- -Use the given SSL context for this socket. +#### useContext +```cpp +void useContext(SSLContext::Ptr context) +``` + +Use the given SSL context for this socket. +| Parameter | Type | Description | +|-----------|------|-------------| +| `context` | `SSLContext::Ptr` | | -#### `public SSLContext::Ptr context() const` +--- -Returns the SSL context used for this socket. +#### context +```cpp +SSLContext::Ptr context() const +``` +Returns the SSL context used for this socket. -#### `public void useSession(SSLSession::Ptr session)` +--- +#### useSession +```cpp +void useSession(SSLSession::Ptr session) +``` Sets the SSL session to use for the next connection. Setting a previously saved Session object is necessary to enable session caching. @@ -1626,391 +2768,617 @@ To remove the currently set session, a nullptr pointer can be given. Must be called before [connect()](#group__net_1ga54a8edb09f593627d120d15339b4a04d) to be effective. -#### `public SSLSession::Ptr currentSession()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `session` | `SSLSession::Ptr` | | + +--- +#### currentSession +```cpp +SSLSession::Ptr currentSession() +``` Returns the SSL session of the current connection, for reuse in a future connection (if session caching is enabled). If no connection is established, returns nullptr. -#### `public bool sessionWasReused()` +--- +#### sessionWasReused +```cpp +bool sessionWasReused() +``` Returns true if a reused session was negotiated during the handshake. -#### `public int available() const` +--- +#### available +```cpp +int available() const +``` Returns the number of bytes available from the SSL buffer for immediate reading. -#### `public X509 * peerCertificate() const` - -Returns the peer's certificate. - +--- +#### peerCertificate -#### `public virtual net::TransportType transport() const` +```cpp +X509 * peerCertificate() const +``` -The transport protocol: TCP, UDP or SSLTCP. +Returns the peer's certificate. +--- +#### transport -#### `public virtual void acceptConnection()` +```cpp +virtual net::TransportType transport() const +``` +The transport protocol: TCP, UDP or SSLTCP. +--- +#### acceptConnection +```cpp +virtual void acceptConnection() +``` -#### `public virtual void onConnect()` +--- +#### onConnect +```cpp +virtual void onConnect() +``` +--- +#### onRead -#### `public virtual void onRead(const char * data,size_t len)` +```cpp +virtual void onRead(const char * data, size_t len) +``` Reads raw encrypted SSL data. +| Parameter | Type | Description | +|-----------|------|-------------| +| `data` | `const char *` | | +| `len` | `size_t` | | +--- -#### `protected net::SSLContext::Ptr _sslContext` - - - - - -#### `protected net::SSLSession::Ptr _sslSession` - - - - - -#### `protected `[`net::SSLAdapter`](./doc/api-net.md#classscy_1_1net_1_1SSLAdapter)` _sslAdapter` - - - - - -# class `scy::net::TCPSocket` +#### _sslContext +```cpp +net::SSLContext::Ptr _sslContext ``` -class scy::net::TCPSocket - : public scy::Stream< uv_tcp_t > - : public scy::net::Socket -``` - -TCP socket implementation. - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public `[`Signal`](#classscy_1_1Signal)< void(const net::TCPSocket::Ptr &)`> AcceptConnection` | -`public TCPSocket(uv::Loop * loop)` | -`public virtual ~TCPSocket()` | -`public virtual bool shutdown()` | -`public virtual void close()` | Closes the underlying socket. -`public virtual void connect(const `[`net::Address`](#classscy_1_1net_1_1Address)` & address)` | -`public virtual void connect(const std::string & host,uint16_t port)` | -`public virtual ssize_t send(const char * data,size_t len,int flags)` | -`public virtual ssize_t send(const char * data,size_t len,const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddress,int flags)` | -`public virtual void bind(const `[`net::Address`](#classscy_1_1net_1_1Address)` & address,unsigned flags)` | -`public virtual void listen(int backlog)` | -`public virtual void acceptConnection()` | -`public bool setReusePort()` | -`public bool setNoDelay(bool enable)` | -`public bool setKeepAlive(bool enable,int delay)` | -`public bool setSimultaneousAccepts(bool enable)` | -`public void setMode(`[`SocketMode`](#group__net_1gadfa90186218954a86b7d57d02c563da2)` mode)` | -`public const `[`SocketMode`](#group__net_1gadfa90186218954a86b7d57d02c563da2)` mode() const` | -`public virtual void setError(const `[`scy::Error`](#structscy_1_1Error)` & err)` | -`public virtual const `[`scy::Error`](#structscy_1_1Error)` & error() const` | Return the socket error if any. -`public virtual bool closed() const` | Returns true if the native socket handle is closed. -`public virtual `[`net::Address`](#classscy_1_1net_1_1Address)` address() const` | -`public virtual `[`net::Address`](#classscy_1_1net_1_1Address)` peerAddress() const` | -`public virtual net::TransportType transport() const` | Returns the TCP transport protocol. -`public virtual uv::Loop * loop() const` | Returns the socket event loop. -`public virtual void * self()` | Return a pointer to the current or derived instance. -`public virtual void onConnect()` | -`public virtual void onRead(const char * data,size_t len)` | -`public virtual void onRecv(const `[`MutableBuffer`](#classscy_1_1MutableBuffer)` & buf)` | -`public virtual void onError(const `[`scy::Error`](#structscy_1_1Error)` & error)` | -`public virtual void onClose()` | -`protected `[`SocketMode`](#group__net_1gadfa90186218954a86b7d57d02c563da2)` _mode` | -`protected virtual void init()` | Initializes the underlying socket context. -`protected virtual void reset()` | Resets the socket context for reuse. - -## Members - -#### `public `[`Signal`](#classscy_1_1Signal)< void(const net::TCPSocket::Ptr &)`> AcceptConnection` +--- +#### _sslSession +```cpp +net::SSLSession::Ptr _sslSession +``` +--- -#### `public TCPSocket(uv::Loop * loop)` +#### _sslAdapter +```cpp +net::SSLAdapter _sslAdapter +``` +## TCPSocket +> **Extends:** `scy::Stream< uv_tcp_t >`, `scy::net::Socket` +> **Subclasses:** `scy::net::SSLSocket` +> **Defined in:** `tcpsocket.h` +TCP socket implementation. -#### `public virtual ~TCPSocket()` +### Members + +| Name | Description | +|------|-------------| +| [`TCPSocket`](#group__net_1gaec3b1c6ef0978a45b92a3941550d34cc) | | +| [`~TCPSocket`](#group__net_1gaf96b67205dcf571df23d167589688858) | | +| [`shutdown`](#group__net_1gaf4823d66f85cfa1b9fc59a786244c948) | Sends the shutdown packet which should result is socket closure via callback. | +| [`close`](#group__net_1gab486aed3b742f783104b2af9e2d1fd53) | Closes and resets the stream handle. This will close the active socket/pipe and destroy the handle. | +| [`connect`](#group__net_1ga54a8edb09f593627d120d15339b4a04d) | Connects to the given peer IP address. | +| [`connect`](#group__net_1gabdf25f4a4b76b89510b9ac02b50c350c) | Resolves and connects to the given host address. | +| [`send`](#group__net_1gac358d98a73620318e8b8c5774668cb2e) | Sends the given data buffer to the connected peer. Returns the number of bytes sent or -1 on error. No exception will be thrown. For TCP sockets the given peer address must match the connected peer address. | +| [`send`](#group__net_1gac8210c5420cc804749543b3be2d10500) | | +| [`bind`](#group__net_1gac4f44d12fc31ac77b739e8bb4b68b73c) | Bind a local address to the socket. The address may be IPv4 or IPv6 (if supported). | +| [`listen`](#group__net_1ga3ec7b2814a110d4c6e01ea304ed35f87) | Listens the socket on the given address. | +| [`acceptConnection`](#group__net_1ga32b031a136c7083ed70b9586dbf4cb6c) | | +| [`setReusePort`](#group__net_1gaca8530109419dfe268c82c22dcc9bcfb) | | +| [`setNoDelay`](#group__net_1gadded4f43faf2734dfc0a56e1b875c997) | | +| [`setKeepAlive`](#group__net_1ga159fae0ed680e7c7b981bfab570f3597) | | +| [`setSimultaneousAccepts`](#group__net_1ga11872bd792fd0a3c7864c04be7c81035) | | +| [`setMode`](#group__net_1gaecf346cd0d3f3d3b4cd560b5776f84d9) | | +| [`mode`](#group__net_1ga3415e01ef65890d3e03c6c4bcb716cce) | | +| [`setError`](#group__net_1ga5f09190f5a798aa81aafe6e14d863f5b) | Set the error and triggers callbacks. | +| [`error`](#group__net_1ga390828725a5262b7d50943d66e511f03) | Return the socket error if any. | +| [`closed`](#group__net_1gad537da936506f40a1750d43f07ceaea5) | Returns true if the native socket handle is closed. | +| [`address`](#group__net_1ga9ca4f02f521e88d7ff93b7da9a817027) | Returns the IP address and port number of the socket. A wildcard address is returned if the socket is not connected. | +| [`peerAddress`](#group__net_1ga452e885bdd0ac8e601c6f8c8d6fd2cc1) | Returns the IP address and port number of the peer socket. A wildcard address is returned if the socket is not connected. | +| [`transport`](#group__net_1gaef3175a72fb606864dc49509992be0f8) | Returns the TCP transport protocol. | +| [`loop`](#group__net_1ga809e5e9d55cf1c9111882f7acfa07909) | Returns the socket event loop. | +| [`self`](#group__net_1gae60bb4b285ed6cf6bbe2a7952dbb33bc) | Return a pointer to the current or derived instance. | +| [`onConnect`](#group__net_1gac2ec475984519b881e9756cf6a2d5cac) | | +| [`onRead`](#group__net_1gad149233e10e70b3d978e949201eda69d) | | +| [`onRecv`](#group__net_1ga5cddc3672cd38ebb92e2b699c68599bf) | | +| [`onError`](#group__net_1ga0f18b40e4845de47e56d67df0ae40b86) | [Error](./doc/api-base.md#structscy_1_1Error) callback. Override to handle errors. The error may be a UV error, or a custom error. | +| [`onClose`](#group__net_1ga9123b0743cd6eb593b093a9ee20fe319) | Close callback. Override to handle closure. | +| [`init`](#group__net_1gab18632622e10ee1c7324b2704cf0a03e) | Initializes the underlying socket context. | +| [`reset`](#group__net_1ga2b0d3646563e08be2697a365e1157e9e) | Resets the socket context for reuse. | +| [`AcceptConnection`](#group__net_1ga22c24cb537c35dbdd0443b5b2d96b374) | | +| [`_mode`](#group__net_1ga27a244b308b0d1632172cd2a5ebeb8aa) | | + +--- + +#### TCPSocket + +```cpp +TCPSocket(uv::Loop * loop) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `loop` | `uv::Loop *` | | +--- +#### ~TCPSocket +```cpp +virtual ~TCPSocket() +``` -#### `public virtual bool shutdown()` +--- +#### shutdown +```cpp +virtual bool shutdown() +``` Sends the shutdown packet which should result is socket closure via callback. -#### `public virtual void close()` +--- -Closes the underlying socket. +#### close +```cpp +virtual void close() +``` + +Closes and resets the stream handle. This will close the active socket/pipe and destroy the handle. +If the stream is already closed this call will have no side-effects. -#### `public virtual void connect(const `[`net::Address`](#classscy_1_1net_1_1Address)` & address)` +--- +#### connect +```cpp +virtual void connect(const net::Address & address) +``` Connects to the given peer IP address. -Throws an exception if the address is malformed. Connection errors can be handled via the [Error](#structscy_1_1Error) signal. +Throws an exception if the address is malformed. Connection errors can be handled via the [Error](./doc/api-base.md#structscy_1_1Error) signal. + +| Parameter | Type | Description | +|-----------|------|-------------| +| `address` | `const net::Address &` | | -#### `public virtual void connect(const std::string & host,uint16_t port)` +--- +#### connect +```cpp +virtual void connect(const std::string & host, uint16_t port) +``` Resolves and connects to the given host address. -Throws an Exception if the host is malformed. Since the DNS callback is asynchronous implementations need to listen for the [Error](#structscy_1_1Error) signal for handling connection errors. +Throws an Exception if the host is malformed. Since the DNS callback is asynchronous implementations need to listen for the [Error](./doc/api-base.md#structscy_1_1Error) signal for handling connection errors. + +| Parameter | Type | Description | +|-----------|------|-------------| +| `host` | `const std::string &` | | +| `port` | `uint16_t` | | -#### `public virtual ssize_t send(const char * data,size_t len,int flags)` +--- +#### send +```cpp +virtual ssize_t send(const char * data, size_t len, int flags) +``` Sends the given data buffer to the connected peer. Returns the number of bytes sent or -1 on error. No exception will be thrown. For TCP sockets the given peer address must match the connected peer address. -#### `public virtual ssize_t send(const char * data,size_t len,const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddress,int flags)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `data` | `const char *` | | +| `len` | `size_t` | | +| `flags` | `int` | | +--- +#### send +```cpp +virtual ssize_t send(const char * data, size_t len, const net::Address & peerAddress, int flags) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `data` | `const char *` | | +| `len` | `size_t` | | +| `peerAddress` | `const net::Address &` | | +| `flags` | `int` | | -#### `public virtual void bind(const `[`net::Address`](#classscy_1_1net_1_1Address)` & address,unsigned flags)` +--- +#### bind +```cpp +virtual void bind(const net::Address & address, unsigned flags) +``` Bind a local address to the socket. The address may be IPv4 or IPv6 (if supported). Throws an Exception on error. -#### `public virtual void listen(int backlog)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `address` | `const net::Address &` | | +| `flags` | `unsigned` | | + +--- +#### listen +```cpp +virtual void listen(int backlog) +``` Listens the socket on the given address. Throws an Exception on error. -#### `public virtual void acceptConnection()` - - - - - -#### `public bool setReusePort()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `backlog` | `int` | | +--- +#### acceptConnection +```cpp +virtual void acceptConnection() +``` +--- -#### `public bool setNoDelay(bool enable)` - - +#### setReusePort +```cpp +bool setReusePort() +``` +--- -#### `public bool setKeepAlive(bool enable,int delay)` +#### setNoDelay +```cpp +bool setNoDelay(bool enable) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `enable` | `bool` | | +--- +#### setKeepAlive -#### `public bool setSimultaneousAccepts(bool enable)` +```cpp +bool setKeepAlive(bool enable, int delay) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `enable` | `bool` | | +| `delay` | `int` | | +--- +#### setSimultaneousAccepts +```cpp +bool setSimultaneousAccepts(bool enable) +``` -#### `public void setMode(`[`SocketMode`](#group__net_1gadfa90186218954a86b7d57d02c563da2)` mode)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `enable` | `bool` | | +--- +#### setMode +```cpp +void setMode(SocketMode mode) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `mode` | `SocketMode` | | -#### `public const `[`SocketMode`](#group__net_1gadfa90186218954a86b7d57d02c563da2)` mode() const` +--- +#### mode +```cpp +const SocketMode mode() const +``` +--- +#### setError -#### `public virtual void setError(const `[`scy::Error`](#structscy_1_1Error)` & err)` +```cpp +virtual void setError(const [scy::Error](./doc/api-base.md#structscy_1_1Error) & error) +``` +Set the error and triggers callbacks. +| Parameter | Type | Description | +|-----------|------|-------------| +| `error` | `const [scy::Error](./doc/api-base.md#structscy_1_1Error) &` | | -Sets the socket error. +--- -Setting the error will result in socket closure. +#### error -#### `public virtual const `[`scy::Error`](#structscy_1_1Error)` & error() const` +```cpp +virtual const [scy::Error](./doc/api-base.md#structscy_1_1Error) & error() const +``` Return the socket error if any. +--- +#### closed -#### `public virtual bool closed() const` +```cpp +virtual bool closed() const +``` Returns true if the native socket handle is closed. +--- +#### address -#### `public virtual `[`net::Address`](#classscy_1_1net_1_1Address)` address() const` - - +```cpp +virtual net::Address address() const +``` Returns the IP address and port number of the socket. A wildcard address is returned if the socket is not connected. -#### `public virtual `[`net::Address`](#classscy_1_1net_1_1Address)` peerAddress() const` +--- +#### peerAddress +```cpp +virtual net::Address peerAddress() const +``` Returns the IP address and port number of the peer socket. A wildcard address is returned if the socket is not connected. -#### `public virtual net::TransportType transport() const` +--- + +#### transport + +```cpp +virtual net::TransportType transport() const +``` Returns the TCP transport protocol. +--- +#### loop -#### `public virtual uv::Loop * loop() const` +```cpp +virtual uv::Loop * loop() const +``` Returns the socket event loop. +--- +#### self -#### `public virtual void * self()` +```cpp +virtual void * self() +``` Return a pointer to the current or derived instance. +--- +#### onConnect -#### `public virtual void onConnect()` - - - - - -#### `public virtual void onRead(const char * data,size_t len)` +```cpp +virtual void onConnect() +``` +--- +#### onRead +```cpp +virtual void onRead(const char * data, size_t len) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `data` | `const char *` | | +| `len` | `size_t` | | -#### `public virtual void onRecv(const `[`MutableBuffer`](#classscy_1_1MutableBuffer)` & buf)` +--- +#### onRecv +```cpp +virtual void onRecv(const MutableBuffer & buf) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `buf` | `const MutableBuffer &` | | +--- -#### `public virtual void onError(const `[`scy::Error`](#structscy_1_1Error)` & error)` +#### onError +```cpp +virtual void onError(const [scy::Error](./doc/api-base.md#structscy_1_1Error) & error) +``` +[Error](./doc/api-base.md#structscy_1_1Error) callback. Override to handle errors. The error may be a UV error, or a custom error. -[Error](#structscy_1_1Error) callback. Override to handle errors. The error may be a UV error, or a custom error. +| Parameter | Type | Description | +|-----------|------|-------------| +| `error` | `const [scy::Error](./doc/api-base.md#structscy_1_1Error) &` | | -#### `public virtual void onClose()` +--- +#### onClose +```cpp +virtual void onClose() +``` Close callback. Override to handle closure. -#### `protected `[`SocketMode`](#group__net_1gadfa90186218954a86b7d57d02c563da2)` _mode` - - - +--- +#### init -#### `protected virtual void init()` +```cpp +virtual void init() +``` Initializes the underlying socket context. +--- +#### reset -#### `protected virtual void reset()` +```cpp +virtual void reset() +``` Resets the socket context for reuse. +--- +#### AcceptConnection -# class `scy::net::Transaction` - +```cpp +Signal< void(const net::TCPSocket::Ptr &)> AcceptConnection ``` -class scy::net::Transaction - : public scy::PacketTransaction< PacketT > - : public scy::net::PacketSocketEmitter -``` +--- + +#### _mode +```cpp +SocketMode _mode +``` -This class provides request/response functionality for [IPacket](#classscy_1_1IPacket) types emitted from a [Socket](#classscy_1_1net_1_1Socket). +## Transaction -## Summary +> **Extends:** `scy::PacketTransaction< PacketT >`, `scy::net::PacketSocketEmitter` +> **Defined in:** `transaction.h` - Members | Descriptions ---------------------------------|--------------------------------------------- -`public inline Transaction(const net::Socket::Ptr & socket,const `[`Address`](#classscy_1_1net_1_1Address)` & peerAddress,int timeout,int retries)` | -`public inline virtual bool send()` | -`public inline virtual void cancel()` | -`public inline virtual void dispose()` | -`public inline `[`Address`](#classscy_1_1net_1_1Address)` peerAddress() const` | -`protected `[`Address`](./doc/api-net.md#classscy_1_1net_1_1Address)` _peerAddress` | -`protected inline virtual ~Transaction()` | -`protected inline virtual void onPacket(`[`IPacket`](#classscy_1_1IPacket)` & packet)` | -`protected inline virtual void onResponse()` | Called when a successful response match is received. -`protected inline virtual bool checkResponse(const PacketT & packet)` | +This class provides request/response functionality for [IPacket](./doc/api-base.md#classscy_1_1IPacket) types emitted from a [Socket](#classscy_1_1net_1_1Socket). -## Members +### Members -#### `public inline Transaction(const net::Socket::Ptr & socket,const `[`Address`](#classscy_1_1net_1_1Address)` & peerAddress,int timeout,int retries)` +| Name | Description | +|------|-------------| +| [`Transaction`](#group__net_1gae43259e00099a144f7179053f01b2f01) | | +| [`send`](#group__net_1ga1571d979ca34fd821ec55540a69201dd) | Starts the transaction timer and sends the request. Overriding classes should implement send logic here. | +| [`cancel`](#group__net_1ga92a0c808ddb8bc5cde490c5f6927b129) | Cancellation means that the agent will not retransmit the request, will not treat the lack of response to be a failure, but will wait the duration of the transaction timeout for a response. | +| [`dispose`](#group__net_1ga4ebc25a93c33e047d2b6c23151a2c1a6) | Schedules the transaction for deferred deletion. | +| [`peerAddress`](#group__net_1ga4dbe158ad4bd2e7a844cfe8571623d71) | | +| [`~Transaction`](#group__net_1ga5ffa69ee1385312be868b345bc743193) | | +| [`onPacket`](#group__net_1gaa6c774d7f241760afe5e21cd55eb2970) | Overrides the [PacketSocketEmitter::onPacket](#group__net_1ga0de3859d43f868dbbdb88fda6e713092) callback for checking potential response candidates. | +| [`onResponse`](#group__net_1gae4f8a3d88a8fb944171ea7758e0e95bd) | Called when a successful response match is received. | +| [`checkResponse`](#group__net_1gad7f496deb9796c70a864033645e09121) | Sub classes should derive this method to implement response checking logic. The base implementation only performs address matching. | +| [`_peerAddress`](#group__net_1ga267322b198b169cb769dbc3b74432592) | | +--- +#### Transaction +```cpp +inline Transaction(const net::Socket::Ptr & socket, const Address & peerAddress, int timeout, int retries) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `socket` | `const net::Socket::Ptr &` | | +| `peerAddress` | `const Address &` | | +| `timeout` | `int` | | +| `retries` | `int` | | -#### `public inline virtual bool send()` +--- +#### send +```cpp +virtual inline bool send() +``` Starts the transaction timer and sends the request. Overriding classes should implement send logic here. -#### `public inline virtual void cancel()` +--- +#### cancel +```cpp +virtual inline void cancel() +``` Cancellation means that the agent will not retransmit the request, will not treat the lack of response to be a failure, but will wait the duration of the transaction timeout for a response. -#### `public inline virtual void dispose()` +--- +#### dispose +```cpp +virtual inline void dispose() +``` Schedules the transaction for deferred deletion. @@ -2018,484 +3386,774 @@ It is safe to call this function while the transaction is still active, providin Protected by the base implementation as this is called by the internal state machine. -#### `public inline `[`Address`](#classscy_1_1net_1_1Address)` peerAddress() const` - - - - - -#### `protected `[`Address`](./doc/api-net.md#classscy_1_1net_1_1Address)` _peerAddress` - +--- +#### peerAddress +```cpp +inline Address peerAddress() const +``` +--- -#### `protected inline virtual ~Transaction()` +#### ~Transaction +```cpp +virtual ~Transaction() = default +``` +--- +#### onPacket +```cpp +virtual inline void onPacket(IPacket & packet) +``` -#### `protected inline virtual void onPacket(`[`IPacket`](#classscy_1_1IPacket)` & packet)` +Overrides the [PacketSocketEmitter::onPacket](#group__net_1ga0de3859d43f868dbbdb88fda6e713092) callback for checking potential response candidates. +| Parameter | Type | Description | +|-----------|------|-------------| +| `packet` | `IPacket &` | | +--- -Overrides the PacketSocketEmitter::onPacket callback for checking potential response candidates. +#### onResponse -#### `protected inline virtual void onResponse()` +```cpp +virtual inline void onResponse() +``` Called when a successful response match is received. +--- +#### checkResponse -#### `protected inline virtual bool checkResponse(const PacketT & packet)` - - - -Sub classes should derive this method to implement response checking logic. The base implementation only performs address matching. - -# class `scy::net::UDPSocket` - +```cpp +virtual inline bool checkResponse(const PacketT & packet) ``` -class scy::net::UDPSocket - : public scy::uv::Handle< uv_udp_t > - : public scy::net::Socket -``` - -UDP socket implementation. - +Sub classes should derive this method to implement response checking logic. The base implementation only performs address matching. -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public UDPSocket(uv::Loop * loop)` | -`public virtual ~UDPSocket()` | -`public virtual void connect(const `[`net::Address`](#classscy_1_1net_1_1Address)` & address)` | -`public virtual void connect(const std::string & host,uint16_t port)` | -`public virtual void close()` | Closes the underlying socket. -`public virtual void bind(const `[`net::Address`](#classscy_1_1net_1_1Address)` & address,unsigned flags)` | -`public virtual ssize_t send(const char * data,size_t len,int flags)` | -`public virtual ssize_t send(const char * data,size_t len,const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddress,int flags)` | -`public bool setBroadcast(bool flag)` | -`public bool setMulticastLoop(bool flag)` | -`public bool setMulticastTTL(int ttl)` | -`public virtual `[`net::Address`](#classscy_1_1net_1_1Address)` address() const` | -`public virtual `[`net::Address`](#classscy_1_1net_1_1Address)` peerAddress() const` | -`public virtual net::TransportType transport() const` | Returns the UDP transport protocol. -`public virtual void setError(const `[`scy::Error`](#structscy_1_1Error)` & err)` | -`public virtual const `[`scy::Error`](#structscy_1_1Error)` & error() const` | Return the socket error if any. -`public virtual bool closed() const` | Returns true if the native socket handle is closed. -`public virtual uv::Loop * loop() const` | Returns the socket event loop. -`public virtual void * self()` | Return a pointer to the current or derived instance. -`public virtual void onRecv(const `[`MutableBuffer`](#classscy_1_1MutableBuffer)` & buf,const `[`net::Address`](#classscy_1_1net_1_1Address)` & address)` | -`protected `[`net::Address`](./doc/api-net.md#classscy_1_1net_1_1Address)` _peer` | -`protected `[`Buffer`](#group__base_1gab10b36b080deb583ed703fca6b63ffdd)` _buffer` | -`protected virtual void init()` | Initializes the underlying socket context. -`protected virtual void reset()` | Resets the socket context for reuse. -`protected virtual void onError(const `[`scy::Error`](#structscy_1_1Error)` & error)` | -`protected virtual void onClose()` | -`protected virtual bool recvStart()` | -`protected virtual bool recvStop()` | +| Parameter | Type | Description | +|-----------|------|-------------| +| `packet` | `const PacketT &` | | -## Members +--- -#### `public UDPSocket(uv::Loop * loop)` +#### _peerAddress +```cpp +Address _peerAddress +``` +## UDPSocket +> **Extends:** `scy::uv::Handle< uv_udp_t >`, `scy::net::Socket` +> **Defined in:** `udpsocket.h` +UDP socket implementation. -#### `public virtual ~UDPSocket()` +### Members + +| Name | Description | +|------|-------------| +| [`UDPSocket`](#group__net_1gac832137d0bc5d3397f48186f4265c800) | | +| [`~UDPSocket`](#group__net_1gac421df9fbeeb69142769802e9a80a178) | | +| [`connect`](#group__net_1ga89db9f772f64dd169d9363c0adf41932) | Connects to the given peer IP address. | +| [`connect`](#group__net_1ga63bd2be01433407bc8e58fd585432943) | Resolves and connects to the given host address. | +| [`close`](#group__net_1ga0f15d459c3559ed1307fe88c7107e6b0) | Close and destroy the handle. | +| [`bind`](#group__net_1ga914a8a799d51ed173950aade35e914f9) | Bind a local address to the socket. The address may be IPv4 or IPv6 (if supported). | +| [`send`](#group__net_1gaf4e0dc198384fc23e5f575458b92a269) | Sends the given data buffer to the connected peer. Returns the number of bytes sent or -1 on error. No exception will be thrown. For TCP sockets the given peer address must match the connected peer address. | +| [`send`](#group__net_1gaa082e3292be95cc50fb0db7fb327b4c3) | | +| [`setBroadcast`](#group__net_1ga0ee0352e997a45deff1805bfaa7dbe62) | | +| [`setMulticastLoop`](#group__net_1gad485a50948ead139d839ec2d53d83707) | | +| [`setMulticastTTL`](#group__net_1ga1b751c2f4af3dc831bde8ee1c08059d3) | | +| [`address`](#group__net_1gaf1c03aeaa87edc8b1666368c16eb84c8) | The locally bound address. | +| [`peerAddress`](#group__net_1ga40f222c85f1f1c0ef0da2f751e8aa15c) | The connected peer address. | +| [`transport`](#group__net_1ga1f7e25495d5fdae305009e341c567c5f) | Returns the UDP transport protocol. | +| [`setError`](#group__net_1ga5390d0fb28b4090359e008d541a9ca33) | Set the error and triggers callbacks. | +| [`error`](#group__net_1gad52712581b6bc1b18b72057ca007c025) | Return the socket error if any. | +| [`closed`](#group__net_1ga6358b5af775f5344616e029f95306fb2) | Returns true if the native socket handle is closed. | +| [`loop`](#group__net_1ga3076c8d49eef7dac47b706e096580a07) | Returns the socket event loop. | +| [`self`](#group__net_1gacd160add50e469282daa7c499bebadac) | Return a pointer to the current or derived instance. | +| [`onRecv`](#group__net_1ga1b142a3c18ca885e72d45aff466723a9) | | +| [`init`](#group__net_1gaa3b285eec570adc6aa71add9c23aff76) | Initializes the underlying socket context. | +| [`reset`](#group__net_1ga426001966462dda0611a52d27e09f295) | Resets the socket context for reuse. | +| [`onError`](#group__net_1ga31d96f40e2012f8069ef47ea3c8d4f4e) | [Error](./doc/api-base.md#structscy_1_1Error) callback. Override to handle errors. The error may be a UV error, or a custom error. | +| [`onClose`](#group__net_1ga45f862d7b7395e07da0a2d3c369dcb80) | Close callback. Override to handle closure. | +| [`recvStart`](#group__net_1ga33d1b77ebd07eade126a299151ef5258) | | +| [`recvStop`](#group__net_1gaf16dae934756ee7a561a7cc965cde0bd) | | +| [`onRecv`](#group__net_1gad9b6572bc6425425b294479b51cecfef) | | +| [`allocRecvBuffer`](#group__net_1ga11234c9a7d898b91b676d5f3944dfbda) | | +| [`_peer`](#group__net_1ga4b6e88e303adb6fc54a6d496e04d6d7e) | | +| [`_buffer`](#group__net_1gae4164f1c3392a3ef567cd255191afe78) | | + +--- + +#### UDPSocket + +```cpp +UDPSocket(uv::Loop * loop) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `loop` | `uv::Loop *` | | +--- +#### ~UDPSocket +```cpp +virtual ~UDPSocket() +``` -#### `public virtual void connect(const `[`net::Address`](#classscy_1_1net_1_1Address)` & address)` +--- +#### connect +```cpp +virtual void connect(const net::Address & address) +``` Connects to the given peer IP address. -Throws an exception if the address is malformed. Connection errors can be handled via the [Error](#structscy_1_1Error) signal. +Throws an exception if the address is malformed. Connection errors can be handled via the [Error](./doc/api-base.md#structscy_1_1Error) signal. + +| Parameter | Type | Description | +|-----------|------|-------------| +| `address` | `const net::Address &` | | -#### `public virtual void connect(const std::string & host,uint16_t port)` +--- +#### connect +```cpp +virtual void connect(const std::string & host, uint16_t port) +``` Resolves and connects to the given host address. -Throws an Exception if the host is malformed. Since the DNS callback is asynchronous implementations need to listen for the [Error](#structscy_1_1Error) signal for handling connection errors. +Throws an Exception if the host is malformed. Since the DNS callback is asynchronous implementations need to listen for the [Error](./doc/api-base.md#structscy_1_1Error) signal for handling connection errors. -#### `public virtual void close()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `host` | `const std::string &` | | +| `port` | `uint16_t` | | -Closes the underlying socket. +--- +#### close + +```cpp +virtual void close() +``` +Close and destroy the handle. -#### `public virtual void bind(const `[`net::Address`](#classscy_1_1net_1_1Address)` & address,unsigned flags)` +--- +#### bind +```cpp +virtual void bind(const net::Address & address, unsigned flags) +``` Bind a local address to the socket. The address may be IPv4 or IPv6 (if supported). Throws an Exception on error. -#### `public virtual ssize_t send(const char * data,size_t len,int flags)` - +| Parameter | Type | Description | +|-----------|------|-------------| +| `address` | `const net::Address &` | | +| `flags` | `unsigned` | | +--- -Sends the given data buffer to the connected peer. Returns the number of bytes sent or -1 on error. No exception will be thrown. For TCP sockets the given peer address must match the connected peer address. - -#### `public virtual ssize_t send(const char * data,size_t len,const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddress,int flags)` +#### send +```cpp +virtual ssize_t send(const char * data, size_t len, int flags) +``` +Sends the given data buffer to the connected peer. Returns the number of bytes sent or -1 on error. No exception will be thrown. For TCP sockets the given peer address must match the connected peer address. +| Parameter | Type | Description | +|-----------|------|-------------| +| `data` | `const char *` | | +| `len` | `size_t` | | +| `flags` | `int` | | +--- -#### `public bool setBroadcast(bool flag)` +#### send +```cpp +virtual ssize_t send(const char * data, size_t len, const net::Address & peerAddress, int flags) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `data` | `const char *` | | +| `len` | `size_t` | | +| `peerAddress` | `const net::Address &` | | +| `flags` | `int` | | +--- +#### setBroadcast -#### `public bool setMulticastLoop(bool flag)` +```cpp +bool setBroadcast(bool flag) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `flag` | `bool` | | +--- +#### setMulticastLoop +```cpp +bool setMulticastLoop(bool flag) +``` -#### `public bool setMulticastTTL(int ttl)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `flag` | `bool` | | +--- +#### setMulticastTTL +```cpp +bool setMulticastTTL(int ttl) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `ttl` | `int` | | -#### `public virtual `[`net::Address`](#classscy_1_1net_1_1Address)` address() const` +--- +#### address +```cpp +virtual net::Address address() const +``` The locally bound address. This function will not throw. A Wildcard 0.0.0.0:0 address is returned if the socket is closed or invalid. -#### `public virtual `[`net::Address`](#classscy_1_1net_1_1Address)` peerAddress() const` +--- +#### peerAddress +```cpp +virtual net::Address peerAddress() const +``` The connected peer address. This function will not throw. A Wildcard 0.0.0.0:0 address is returned if the socket is closed or invalid. -#### `public virtual net::TransportType transport() const` +--- + +#### transport + +```cpp +virtual net::TransportType transport() const +``` Returns the UDP transport protocol. +--- +#### setError -#### `public virtual void setError(const `[`scy::Error`](#structscy_1_1Error)` & err)` +```cpp +virtual void setError(const [scy::Error](./doc/api-base.md#structscy_1_1Error) & error) +``` +Set the error and triggers callbacks. +| Parameter | Type | Description | +|-----------|------|-------------| +| `error` | `const [scy::Error](./doc/api-base.md#structscy_1_1Error) &` | | -Sets the socket error. +--- -Setting the error will result in socket closure. +#### error -#### `public virtual const `[`scy::Error`](#structscy_1_1Error)` & error() const` +```cpp +virtual const [scy::Error](./doc/api-base.md#structscy_1_1Error) & error() const +``` Return the socket error if any. +--- +#### closed -#### `public virtual bool closed() const` +```cpp +virtual bool closed() const +``` Returns true if the native socket handle is closed. +--- +#### loop -#### `public virtual uv::Loop * loop() const` +```cpp +virtual uv::Loop * loop() const +``` Returns the socket event loop. +--- +#### self -#### `public virtual void * self()` +```cpp +virtual void * self() +``` Return a pointer to the current or derived instance. +--- +#### onRecv -#### `public virtual void onRecv(const `[`MutableBuffer`](#classscy_1_1MutableBuffer)` & buf,const `[`net::Address`](#classscy_1_1net_1_1Address)` & address)` - - - - - -#### `protected `[`net::Address`](./doc/api-net.md#classscy_1_1net_1_1Address)` _peer` - - - - - -#### `protected `[`Buffer`](#group__base_1gab10b36b080deb583ed703fca6b63ffdd)` _buffer` - +```cpp +virtual void onRecv(const MutableBuffer & buf, const net::Address & address) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `buf` | `const MutableBuffer &` | | +| `address` | `const net::Address &` | | +--- +#### init -#### `protected virtual void init()` +```cpp +virtual void init() +``` Initializes the underlying socket context. +--- +#### reset -#### `protected virtual void reset()` +```cpp +virtual void reset() +``` Resets the socket context for reuse. +--- +#### onError -#### `protected virtual void onError(const `[`scy::Error`](#structscy_1_1Error)` & error)` - +```cpp +virtual void onError(const [scy::Error](./doc/api-base.md#structscy_1_1Error) & error) +``` +[Error](./doc/api-base.md#structscy_1_1Error) callback. Override to handle errors. The error may be a UV error, or a custom error. -[Error](#structscy_1_1Error) callback. Override to handle errors. The error may be a UV error, or a custom error. +| Parameter | Type | Description | +|-----------|------|-------------| +| `error` | `const [scy::Error](./doc/api-base.md#structscy_1_1Error) &` | | -#### `protected virtual void onClose()` +--- +#### onClose +```cpp +virtual void onClose() +``` Close callback. Override to handle closure. -#### `protected virtual bool recvStart()` - - - - - -#### `protected virtual bool recvStop()` +--- +#### recvStart +```cpp +virtual bool recvStart() +``` +--- +#### recvStop -# class `scy::net::VerificationErrorDetails` - - -A utility class for certificate error handling. - - +```cpp +virtual bool recvStop() +``` -## Summary +--- - Members | Descriptions ---------------------------------|--------------------------------------------- -`public VerificationErrorDetails(const `[`crypto::X509Certificate`](#classscy_1_1crypto_1_1X509Certificate)` & cert,int errDepth,int errNum,const std::string & errMsg)` | -`public ~VerificationErrorDetails()` | Destroys the [VerificationErrorDetails](./doc/api-net.md#classscy_1_1net_1_1VerificationErrorDetails). -`public inline const `[`crypto::X509Certificate`](#classscy_1_1crypto_1_1X509Certificate)` & certificate() const` | Returns the certificate that caused the error. -`public inline int errorDepth() const` | Returns the position of the certificate in the certificate chain. -`public inline int errorNumber() const` | Returns the id of the error. -`public inline const std::string & errorMessage() const` | Returns the textual presentation of the errorNumber. -`public inline void setIgnoreError(bool ignoreError)` | -`public inline bool getIgnoreError() const` | returns the value of _ignoreError +#### onRecv -## Members +```cpp +static void onRecv(uv_udp_t * handle, ssize_t nread, const uv_buf_t * buf, const struct sockaddr * addr, unsigned flags) +``` -#### `public VerificationErrorDetails(const `[`crypto::X509Certificate`](#classscy_1_1crypto_1_1X509Certificate)` & cert,int errDepth,int errNum,const std::string & errMsg)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `handle` | `uv_udp_t *` | | +| `nread` | `ssize_t` | | +| `buf` | `const uv_buf_t *` | | +| `addr` | `const struct sockaddr *` | | +| `flags` | `unsigned` | | +--- +#### allocRecvBuffer -Creates the [VerificationErrorDetails](#classscy_1_1net_1_1VerificationErrorDetails). _ignoreError is per default set to false. +```cpp +static void allocRecvBuffer(uv_handle_t * handle, size_t suggested_size, uv_buf_t * buf) +``` -#### `public ~VerificationErrorDetails()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `handle` | `uv_handle_t *` | | +| `suggested_size` | `size_t` | | +| `buf` | `uv_buf_t *` | | -Destroys the [VerificationErrorDetails](#classscy_1_1net_1_1VerificationErrorDetails). +--- +#### _peer +```cpp +net::Address _peer +``` -#### `public inline const `[`crypto::X509Certificate`](#classscy_1_1crypto_1_1X509Certificate)` & certificate() const` +--- -Returns the certificate that caused the error. +#### _buffer +```cpp +Buffer _buffer +``` +## AddressBase -#### `public inline int errorDepth() const` +> **Subclasses:** `scy::net::IPv4AddressBase` -Returns the position of the certificate in the certificate chain. +### Members +| Name | Description | +|------|-------------| +| [`host`](#group__net_1ga867db5d11fa5c964830368ac1a4cbb7a) | | +| [`port`](#group__net_1ga44e7f8716b0b2f0a701d22e3edcf21b3) | | +| [`family`](#group__net_1ga018e56177bc5c8bf2b02bc88ec6efcfe) | | +| [`length`](#group__net_1ga9d32a44cd01e1e7e7e082f5c36aee5e1) | | +| [`addr`](#group__net_1ga532c3627f0f9a78bfa33a31a8951673b) | | +| [`af`](#group__net_1ga69583a3ceab6d1839acb20d972d7fa7f) | | +| [`AddressBase`](#group__net_1ga0c4217e82452f7e70750ba1662802a67) | | +| [`~AddressBase`](#group__net_1gaee163e8131fa554005928e0941c8bf93) | | +| [`AddressBase`](#group__net_1ga17555486795b6ea35256a3c3f564b4ba) | | +| [`operator=`](#group__net_1ga4f04abeacdbcd881b8491c5d79f80887) | | +--- -#### `public inline int errorNumber() const` +#### host -Returns the id of the error. +```cpp +std::string host() const +``` +--- +#### port -#### `public inline const std::string & errorMessage() const` +```cpp +uint16_t port() const +``` -Returns the textual presentation of the errorNumber. +--- +#### family +```cpp +Address::Family family() const +``` -#### `public inline void setIgnoreError(bool ignoreError)` +--- +#### length +```cpp +socklen_t length() const +``` -setIgnoreError to true, if a verification error is judged non-fatal by the user. +--- -#### `public inline bool getIgnoreError() const` +#### addr -returns the value of _ignoreError +```cpp +const struct sockaddr * addr() const +``` +--- +#### af -# struct `scy::net::GetAddrInfoEvent` +```cpp +int af() const +``` +--- -Get address info request callback event. +#### AddressBase +```cpp +inline AddressBase() +``` +--- -## Summary +#### ~AddressBase - Members | Descriptions ---------------------------------|--------------------------------------------- -`public int status` | -`public `[`net::Address`](./doc/api-net.md#classscy_1_1net_1_1Address)` addr` | +```cpp +virtual inline ~AddressBase() +``` -## Members +--- -#### `public int status` +#### AddressBase +```cpp +AddressBase(const AddressBase &) = delete +``` +--- +#### operator= +```cpp +AddressBase & operator=(const AddressBase &) = delete +``` -#### `public `[`net::Address`](./doc/api-net.md#classscy_1_1net_1_1Address)` addr` +## IPv4AddressBase +> **Extends:** `scy::net::AddressBase` +### Members +| Name | Description | +|------|-------------| +| [`IPv4AddressBase`](#group__net_1ga48fc92d2cb95f0b16b6c28b77c7d04d9) | | +| [`IPv4AddressBase`](#group__net_1ga9130e321cd339b3b9414929e1e6ff6d5) | | +| [`IPv4AddressBase`](#group__net_1ga88f691bffa5d02c3d34440fab859d2a1) | | +| [`host`](#group__net_1ga2d455659c2dd8150f39122a4b70c2459) | | +| [`port`](#group__net_1ga01593bde5ff3a252088beb95619ec343) | | +| [`family`](#group__net_1ga8200f0c126c892638c7f0818b786a0c6) | | +| [`length`](#group__net_1gae374547c5843e238cfdfaee8cdd82037) | | +| [`addr`](#group__net_1ga96ebb36649f22c95d05295b6a1afb699) | | +| [`af`](#group__net_1ga3468fd918b7a508ed76fb12baf0491e4) | | +| [`_addr`](#group__net_1ga5f0e8f71be2be18dde24822a37e523ff) | | +--- -# struct `scy::net::GetAddrInfoReq` +#### IPv4AddressBase +```cpp +inline IPv4AddressBase() ``` -struct scy::net::GetAddrInfoReq - : public scy::uv::Request< uv_getaddrinfo_t, GetAddrInfoEvent > -``` - -DNS resolver request to get the IP address of a hostname. - - -## Summary +--- - Members | Descriptions ---------------------------------|--------------------------------------------- -`public inline GetAddrInfoReq()` | -`public inline bool resolve(const std::string & host,int port,uv::Loop * loop)` | +#### IPv4AddressBase -## Members - -#### `public inline GetAddrInfoReq()` +```cpp +inline IPv4AddressBase(const struct sockaddr_in * addr) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `addr` | `const struct sockaddr_in *` | | +--- +#### IPv4AddressBase +```cpp +inline IPv4AddressBase(const void * addr, uint16_t port) +``` -#### `public inline bool resolve(const std::string & host,int port,uv::Loop * loop)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `addr` | `const void *` | | +| `port` | `uint16_t` | | +--- +#### host +```cpp +virtual inline std::string host() const +``` +--- -# struct `scy::net::PacketInfo` +#### port +```cpp +virtual inline uint16_t port() const ``` -struct scy::net::PacketInfo - : public scy::IPacketInfo -``` +--- +#### family -Provides information about packets emitted from a socket. See [SocketPacket](#classscy_1_1net_1_1SocketPacket). - -## Summary +```cpp +virtual inline Address::Family family() const +``` - Members | Descriptions ---------------------------------|--------------------------------------------- -`public Socket::Ptr socket` | The source socket. -`public `[`Address`](./doc/api-net.md#classscy_1_1net_1_1Address)` peerAddress` | -`public inline PacketInfo(const Socket::Ptr & socket,const `[`Address`](#classscy_1_1net_1_1Address)` & peerAddress)` | -`public inline PacketInfo(const `[`PacketInfo`](#structscy_1_1net_1_1PacketInfo)` & r)` | -`public inline virtual `[`IPacketInfo`](#structscy_1_1IPacketInfo)` * clone() const` | -`public inline virtual ~PacketInfo()` | +--- -## Members +#### length -#### `public Socket::Ptr socket` +```cpp +virtual inline socklen_t length() const +``` -The source socket. +--- +#### addr +```cpp +virtual inline const struct sockaddr * addr() const +``` -#### `public `[`Address`](./doc/api-net.md#classscy_1_1net_1_1Address)` peerAddress` +--- +#### af +```cpp +virtual inline int af() const +``` -The originating peer address. For TCP this will always be connected address. +--- -#### `public inline PacketInfo(const Socket::Ptr & socket,const `[`Address`](#classscy_1_1net_1_1Address)` & peerAddress)` +#### _addr +```cpp +struct sockaddr_in _addr +``` +## PacketInfo +> **Extends:** `scy::IPacketInfo` +> **Defined in:** `socket.h` +Provides information about packets emitted from a socket. See [SocketPacket](#classscy_1_1net_1_1SocketPacket). -#### `public inline PacketInfo(const `[`PacketInfo`](#structscy_1_1net_1_1PacketInfo)` & r)` +### Members +| Name | Description | +|------|-------------| +| [`PacketInfo`](#group__net_1gac4cee1c5178b1581eee877736e102755) | | +| [`PacketInfo`](#group__net_1gae0b9f9bcc10f550dfea602f962092247) | | +| [`clone`](#group__net_1ga92ec5afeaea19e87ea092a48a3a5d5d2) | | +| [`~PacketInfo`](#group__net_1ga0b05488ca9b52e594d47a21678150869) | | +| [`socket`](#group__net_1ga679e93ce36b1f3bd031bbc54ea7939db) | The source socket. | +| [`peerAddress`](#group__net_1ga41acad06a100d281506e6bf269b13799) | The originating peer address. For TCP this will always be connected address. | +--- +#### PacketInfo +```cpp +inline PacketInfo(const Socket::Ptr & socket, const Address & peerAddress) +``` -#### `public inline virtual `[`IPacketInfo`](#structscy_1_1IPacketInfo)` * clone() const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `socket` | `const Socket::Ptr &` | | +| `peerAddress` | `const Address &` | | +--- +#### PacketInfo +```cpp +inline PacketInfo(const PacketInfo & r) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `r` | `const PacketInfo &` | | -#### `public inline virtual ~PacketInfo()` +--- +#### clone +```cpp +virtual inline IPacketInfo * clone() const +``` +--- +#### ~PacketInfo -# struct `scy::net::SocketAdapter::Ref` +```cpp +virtual inline ~PacketInfo() +``` +--- +#### socket +```cpp +Socket::Ptr socket +``` +The source socket. +--- -## Summary +#### peerAddress - Members | Descriptions ---------------------------------|--------------------------------------------- -`public `[`SocketAdapter`](./doc/api-net.md#classscy_1_1net_1_1SocketAdapter)` * ptr` | -`public bool alive` | +```cpp +Address peerAddress +``` -## Members +The originating peer address. For TCP this will always be connected address. -#### `public `[`SocketAdapter`](./doc/api-net.md#classscy_1_1net_1_1SocketAdapter)` * ptr` +## Ref +> **Defined in:** `socketadapter.h` +### Members +| Name | Description | +|------|-------------| +| [`ptr`](#group__net_1ga7850ea3acb3330d7fb974c45f780f1c4) | | +| [`alive`](#group__net_1ga5e0d22008a914828d87ecd623872db05) | | +--- -#### `public bool alive` +#### ptr +```cpp +SocketAdapter * ptr +``` +--- +#### alive +```cpp +bool alive +``` diff --git a/doc/api-pacm.md b/doc/api-pacm.md index db164b479..f6b4641f8 100644 --- a/doc/api-pacm.md +++ b/doc/api-pacm.md @@ -1,1590 +1,2831 @@ -# Module `pacm` - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`namespace `[`scy::pacm`](#namespacescy_1_1pacm) | -`struct `[`scy::pacm::Package::Asset`](#structscy_1_1pacm_1_1Package_1_1Asset) | -`struct `[`scy::pacm::LocalPackage::Manifest`](#structscy_1_1pacm_1_1LocalPackage_1_1Manifest) | -`struct `[`scy::pacm::PackageManager::Options`](#structscy_1_1pacm_1_1PackageManager_1_1Options) | [Package](#structscy_1_1pacm_1_1Package) manager initialization options. -# namespace `scy::pacm` - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`class `[`scy::pacm::InstallMonitor`](#classscy_1_1pacm_1_1InstallMonitor) | -`class `[`scy::pacm::InstallTask`](#classscy_1_1pacm_1_1InstallTask) | This class implements the package installation procedure. -`class `[`scy::pacm::PackageManager`](#classscy_1_1pacm_1_1PackageManager) | -`struct `[`scy::pacm::InstallationState`](#structscy_1_1pacm_1_1InstallationState) | -`struct `[`scy::pacm::InstallOptions`](#structscy_1_1pacm_1_1InstallOptions) | [Package](#structscy_1_1pacm_1_1Package) installation options. -`struct `[`scy::pacm::LocalPackage`](#structscy_1_1pacm_1_1LocalPackage) | -`struct `[`scy::pacm::Package`](#structscy_1_1pacm_1_1Package) | -`struct `[`scy::pacm::PackagePair`](#structscy_1_1pacm_1_1PackagePair) | -`struct `[`scy::pacm::RemotePackage`](#structscy_1_1pacm_1_1RemotePackage) | -# class `scy::pacm::InstallMonitor` - - - - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public `[`Signal](#classscy_1_1Signal)< void([InstallTask](#classscy_1_1pacm_1_1InstallTask) &, const [InstallationState](#structscy_1_1pacm_1_1InstallationState) &, const [InstallationState`](#structscy_1_1pacm_1_1InstallationState) &)`> InstallStateChange` | Proxies state change events from managed packages. -`public `[`Signal](#classscy_1_1Signal)< void([LocalPackage`](#structscy_1_1pacm_1_1LocalPackage) &)`> InstallComplete` | Signals when a managed install task completes. -`public `[`Signal`](#classscy_1_1Signal)< void(int &)`> Progress` | Signals on overall progress update [0-100]. -`public `[`Signal`](#classscy_1_1Signal)< void(LocalPackageVec &)`> Complete` | Signals on all tasks complete. -`public InstallMonitor()` | -`public virtual ~InstallMonitor()` | -`public virtual void addTask(InstallTask::Ptr task)` | Adds a task to monitor. -`public virtual void startAll()` | Starts all monitored tasks. -`public virtual void cancelAll()` | Cancels all monitored tasks. -`public virtual bool isComplete() const` | -`public virtual InstallTaskPtrVec tasks() const` | Returns the list of monitored package tasks. -`public virtual LocalPackageVec packages() const` | Returns the list of monitored packages. -`protected mutable std::mutex _mutex` | -`protected InstallTaskPtrVec _tasks` | -`protected LocalPackageVec _packages` | -`protected int _progress` | -`protected virtual void onInstallStateChange(void * sender,`[`InstallationState`](#structscy_1_1pacm_1_1InstallationState)` & state,const `[`InstallationState`](#structscy_1_1pacm_1_1InstallationState)` & oldState)` | -`protected virtual void onInstallComplete(`[`InstallTask`](#classscy_1_1pacm_1_1InstallTask)` & task)` | -`protected virtual void setProgress(int value)` | - -## Members - -#### `public `[`Signal](#classscy_1_1Signal)< void([InstallTask](#classscy_1_1pacm_1_1InstallTask) &, const [InstallationState](#structscy_1_1pacm_1_1InstallationState) &, const [InstallationState`](#structscy_1_1pacm_1_1InstallationState) &)`> InstallStateChange` +# pacm + +### Classes + +| Name | Description | +|------|-------------| +| [`InstallMonitor`](#classscy_1_1pacm_1_1InstallMonitor) | | +| [`InstallTask`](#classscy_1_1pacm_1_1InstallTask) | This class implements the package installation procedure. | +| [`PackageManager`](#classscy_1_1pacm_1_1PackageManager) | The [Package](#structscy_1_1pacm_1_1Package) Manager provides an interface for managing, installing, updating and uninstalling Pacm packages. | +| [`InstallationState`](#structscy_1_1pacm_1_1InstallationState) | | +| [`InstallOptions`](#structscy_1_1pacm_1_1InstallOptions) | [Package](#structscy_1_1pacm_1_1Package) installation options. | +| [`Package`](#structscy_1_1pacm_1_1Package) | This class is a JSON representation of an package belonging to the [PackageManager](#classscy_1_1pacm_1_1PackageManager). | +| [`Asset`](#structscy_1_1pacm_1_1Package_1_1Asset) | This class represents a archived file asset containing files belonging to the parent package. | +| [`RemotePackage`](#structscy_1_1pacm_1_1RemotePackage) | This class is a JSON representation of an package existing on the remote server that may be downloaded and installed. | +| [`LocalPackage`](#structscy_1_1pacm_1_1LocalPackage) | This class is a JSON representation of an installed local package that exists on the file system. | +| [`Manifest`](#structscy_1_1pacm_1_1LocalPackage_1_1Manifest) | This class provides a list of all package files and their location on the file system. | +| [`PackagePair`](#structscy_1_1pacm_1_1PackagePair) | This class provides pairing of a local and a remote package. | +| [`Options`](#structscy_1_1pacm_1_1PackageManager_1_1Options) | [Package](#structscy_1_1pacm_1_1Package) manager initialization options. | + +### Members + +| Name | Description | +|------|-------------| +| [`DEFAULT_API_ENDPOINT`](#group__pacm_1ga522de8a765e3f326637b19946ea8084a) | | +| [`DEFAULT_API_INDEX_URI`](#group__pacm_1ga8a99b6b1f2c06d69f72b70a065e3abc3) | | +| [`DEFAULT_PACKAGE_INSTALL_DIR`](#group__pacm_1ga605f59cf1dcb1a0b86673ae28f3765e8) | | +| [`DEFAULT_PACKAGE_DATA_DIR`](#group__pacm_1ga3326a058ef7a92e406218251ed6548bd) | | +| [`DEFAULT_PACKAGE_TEMP_DIR`](#group__pacm_1ga5a8319c27335e60523a50a50f2816f67) | | +| [`DEFAULT_CHECKSUM_ALGORITHM`](#group__pacm_1ga1ea3bd19c5295bd7d1e6f6a862ef8b5d) | | +| [`Pacm_API`](#group__pacm_1ga4e79c10778b27ed9c9f018f88560af1c) | | + +--- + +#### DEFAULT_API_ENDPOINT + +```cpp +DEFAULT_API_ENDPOINT() +``` -Proxies state change events from managed packages. +--- +#### DEFAULT_API_INDEX_URI +```cpp +DEFAULT_API_INDEX_URI() +``` -#### `public `[`Signal](#classscy_1_1Signal)< void([LocalPackage`](#structscy_1_1pacm_1_1LocalPackage) &)`> InstallComplete` +--- -Signals when a managed install task completes. +#### DEFAULT_PACKAGE_INSTALL_DIR +```cpp +DEFAULT_PACKAGE_INSTALL_DIR() +``` +--- -#### `public `[`Signal`](#classscy_1_1Signal)< void(int &)`> Progress` - -Signals on overall progress update [0-100]. +#### DEFAULT_PACKAGE_DATA_DIR +```cpp +DEFAULT_PACKAGE_DATA_DIR() +``` +--- -#### `public `[`Signal`](#classscy_1_1Signal)< void(LocalPackageVec &)`> Complete` +#### DEFAULT_PACKAGE_TEMP_DIR -Signals on all tasks complete. +```cpp +DEFAULT_PACKAGE_TEMP_DIR() +``` +--- +#### DEFAULT_CHECKSUM_ALGORITHM -#### `public InstallMonitor()` +```cpp +DEFAULT_CHECKSUM_ALGORITHM() +``` +--- +#### Pacm_API +```cpp +Pacm_API() +``` +## InstallMonitor + +> **Defined in:** `installmonitor.h` + +### Members + +| Name | Description | +|------|-------------| +| [`InstallMonitor`](#group__pacm_1ga0120805da5155e36bf6be738d58f1550) | | +| [`~InstallMonitor`](#group__pacm_1ga9029008260c1d966e942f2b720d2237c) | | +| [`addTask`](#group__pacm_1gade82e15d697cebdcf4c27c79fba73d7b) | Adds a task to monitor. | +| [`startAll`](#group__pacm_1gaa77ef7964ec12fd63329648d615588f7) | Starts all monitored tasks. | +| [`cancelAll`](#group__pacm_1ga188395007e67e4562b350ebc945c347a) | Cancels all monitored tasks. | +| [`isComplete`](#group__pacm_1ga7eb6c0cd1bcb8ed8b38451a38b93a818) | Returns true if all install tasks have completed, either successfully or unsuccessfully. | +| [`tasks`](#group__pacm_1ga25a15551d09c6b50c27a628f9f548ed6) | Returns the list of monitored package tasks. | +| [`packages`](#group__pacm_1gae85037281be09f4c389ca0a1210d4793) | Returns the list of monitored packages. | +| [`onInstallStateChange`](#group__pacm_1gaa8d8ae7796e966977d7ccc052e7e392e) | | +| [`onInstallComplete`](#group__pacm_1ga3fee590aa5c73808d0f36de1c70f5b0d) | | +| [`setProgress`](#group__pacm_1ga747222082b89e98e0d6befc96c1bcc16) | | +| [`InstallStateChange`](#group__pacm_1ga5f7cb24385268ab5d2b50da72730d10a) | Proxies state change events from managed packages. | +| [`InstallComplete`](#group__pacm_1ga081f4bd707b531dfd4d38f2233588bf8) | Signals when a managed install task completes. | +| [`Progress`](#group__pacm_1ga293627c638d0d1f70e82546be766219a) | Signals on overall progress update [0-100]. | +| [`Complete`](#group__pacm_1ga9bdc4dad951bb031a861bb53efa411b4) | Signals on all tasks complete. | +| [`_mutex`](#group__pacm_1ga62930097be146c2422b7057622cd7ca4) | | +| [`_tasks`](#group__pacm_1ga9466e58faabe5386ae0e8cc4b053baf0) | | +| [`_packages`](#group__pacm_1ga5c5266c23cb36a98bbaf513f3c58beab) | | +| [`_progress`](#group__pacm_1ga3cfe9db2c67679216a9f84d31060c9c9) | | + +--- + +#### InstallMonitor + +```cpp +InstallMonitor() +``` -#### `public virtual ~InstallMonitor()` +--- +#### ~InstallMonitor +```cpp +virtual ~InstallMonitor() +``` +--- +#### addTask -#### `public virtual void addTask(InstallTask::Ptr task)` +```cpp +virtual void addTask(InstallTask::Ptr task) +``` Adds a task to monitor. +| Parameter | Type | Description | +|-----------|------|-------------| +| `task` | `InstallTask::Ptr` | | +--- -#### `public virtual void startAll()` +#### startAll + +```cpp +virtual void startAll() +``` Starts all monitored tasks. +--- +#### cancelAll -#### `public virtual void cancelAll()` +```cpp +virtual void cancelAll() +``` Cancels all monitored tasks. +--- +#### isComplete -#### `public virtual bool isComplete() const` +```cpp +virtual bool isComplete() const +``` +Returns true if all install tasks have completed, either successfully or unsuccessfully. +--- -Returns true if all install tasks have completed, either successfully or unsuccessfully. +#### tasks -#### `public virtual InstallTaskPtrVec tasks() const` +```cpp +virtual InstallTaskPtrVec tasks() const +``` Returns the list of monitored package tasks. +--- +#### packages -#### `public virtual LocalPackageVec packages() const` +```cpp +virtual LocalPackageVec packages() const +``` Returns the list of monitored packages. +--- +#### onInstallStateChange -#### `protected mutable std::mutex _mutex` - - - - - -#### `protected InstallTaskPtrVec _tasks` - - - - - -#### `protected LocalPackageVec _packages` - - +```cpp +virtual void onInstallStateChange(void * sender, InstallationState & state, const InstallationState & oldState) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `sender` | `void *` | | +| `state` | `InstallationState &` | | +| `oldState` | `const InstallationState &` | | +--- -#### `protected int _progress` +#### onInstallComplete +```cpp +virtual void onInstallComplete(InstallTask & task) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `task` | `InstallTask &` | | +--- +#### setProgress -#### `protected virtual void onInstallStateChange(void * sender,`[`InstallationState`](#structscy_1_1pacm_1_1InstallationState)` & state,const `[`InstallationState`](#structscy_1_1pacm_1_1InstallationState)` & oldState)` +```cpp +virtual void setProgress(int value) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `value` | `int` | | +--- +#### InstallStateChange +```cpp +Signal< void(InstallTask &, const InstallationState &, const InstallationState &)> InstallStateChange +``` -#### `protected virtual void onInstallComplete(`[`InstallTask`](#classscy_1_1pacm_1_1InstallTask)` & task)` +Proxies state change events from managed packages. +--- +#### InstallComplete +```cpp +Signal< void(LocalPackage &)> InstallComplete +``` +Signals when a managed install task completes. -#### `protected virtual void setProgress(int value)` +--- +#### Progress +```cpp +Signal< void(int &)> Progress +``` +Signals on overall progress update [0-100]. +--- -# class `scy::pacm::InstallTask` +#### Complete +```cpp +Signal< void(LocalPackageVec &)> Complete ``` -class scy::pacm::InstallTask - : public scy::basic::Runnable - : public scy::Stateful< InstallationState > -``` - -This class implements the package installation procedure. +Signals on all tasks complete. +--- -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public `[`Signal](#classscy_1_1Signal)< void([InstallTask`](#classscy_1_1pacm_1_1InstallTask) &, int &)`> Progress` | Signals on progress update [0-100]. -`public `[`Signal](#classscy_1_1Signal)< void([InstallTask`](#classscy_1_1pacm_1_1InstallTask) &)`> Complete` | -`public InstallTask(`[`PackageManager`](#classscy_1_1pacm_1_1PackageManager)` & manager,`[`LocalPackage`](#structscy_1_1pacm_1_1LocalPackage)` * local,`[`RemotePackage`](#structscy_1_1pacm_1_1RemotePackage)` * remote,const `[`InstallOptions`](#structscy_1_1pacm_1_1InstallOptions)` & options,uv::Loop * loop)` | -`public virtual ~InstallTask()` | -`public virtual void start()` | -`public virtual void cancel()` | -`public virtual void doDownload()` | Downloads the package archive from the server. -`public virtual void doExtract()` | -`public virtual void doFinalize()` | -`public virtual void setComplete()` | -`public virtual `[`Package::Asset`](#structscy_1_1pacm_1_1Package_1_1Asset)` getRemoteAsset() const` | -`public virtual `[`LocalPackage`](#structscy_1_1pacm_1_1LocalPackage)` * local() const` | -`public virtual `[`RemotePackage`](#structscy_1_1pacm_1_1RemotePackage)` * remote() const` | -`public virtual `[`InstallOptions`](#structscy_1_1pacm_1_1InstallOptions)` & options()` | -`public virtual uv::Loop * loop() const` | -`public virtual bool valid() const` | -`public virtual bool cancelled() const` | Returns true when the task has been cancelled. -`public virtual bool failed() const` | -`public virtual bool success() const` | -`public virtual bool complete() const` | -`public virtual int progress() const` | -`protected mutable std::mutex _mutex` | -`protected `[`Idler`](./doc/api-base.md#classscy_1_1Idler)` _runner` | -`protected `[`scy::Error`](./doc/api-base.md#structscy_1_1Error)` _error` | -`protected `[`PackageManager`](./doc/api-pacm.md#classscy_1_1pacm_1_1PackageManager)` & _manager` | -`protected `[`LocalPackage`](./doc/api-pacm.md#structscy_1_1pacm_1_1LocalPackage)` * _local` | -`protected `[`RemotePackage`](./doc/api-pacm.md#structscy_1_1pacm_1_1RemotePackage)` * _remote` | -`protected `[`InstallOptions`](./doc/api-pacm.md#structscy_1_1pacm_1_1InstallOptions)` _options` | -`protected int _progress` | -`protected bool _downloading` | -`protected http::ClientConnection::Ptr _dlconn` | -`protected uv::Loop * _loop` | -`protected virtual void run()` | Called asynchronously by the thread to do the work. -`protected virtual void onStateChange(`[`InstallationState`](#structscy_1_1pacm_1_1InstallationState)` & state,const `[`InstallationState`](#structscy_1_1pacm_1_1InstallationState)` & oldState)` | -`protected virtual void onDownloadProgress(const double & progress)` | -`protected virtual void onDownloadComplete(const `[`http::Response`](#classscy_1_1http_1_1Response)` & response)` | -`protected virtual void setProgress(int value)` | - -## Members - -#### `public `[`Signal](#classscy_1_1Signal)< void([InstallTask`](#classscy_1_1pacm_1_1InstallTask) &, int &)`> Progress` +#### _mutex -Signals on progress update [0-100]. +```cpp +std::mutex _mutex +``` +--- +#### _tasks -#### `public `[`Signal](#classscy_1_1Signal)< void([InstallTask`](#classscy_1_1pacm_1_1InstallTask) &)`> Complete` +```cpp +InstallTaskPtrVec _tasks +``` +--- +#### _packages -Signals on task completion for both success and failure cases. - -#### `public InstallTask(`[`PackageManager`](#classscy_1_1pacm_1_1PackageManager)` & manager,`[`LocalPackage`](#structscy_1_1pacm_1_1LocalPackage)` * local,`[`RemotePackage`](#structscy_1_1pacm_1_1RemotePackage)` * remote,const `[`InstallOptions`](#structscy_1_1pacm_1_1InstallOptions)` & options,uv::Loop * loop)` +```cpp +LocalPackageVec _packages +``` +--- +#### _progress +```cpp +int _progress +``` +## InstallTask -#### `public virtual ~InstallTask()` +> **Extends:** `scy::basic::Runnable`, `scy::Stateful< InstallationState >` +> **Defined in:** `installtask.h` +This class implements the package installation procedure. +### Members + +| Name | Description | +|------|-------------| +| [`InstallTask`](#group__pacm_1gac517d62628a6206362e8f8b8e8b6889e) | | +| [`~InstallTask`](#group__pacm_1ga136d640d67a5bab3c7a2c4a5607bd6db) | | +| [`start`](#group__pacm_1ga26a08fe537a7db788079445921650685) | | +| [`cancel`](#group__pacm_1ga8847a1e10771443fa49ea35939a22567) | | +| [`doDownload`](#group__pacm_1gaf815fbda71ebf69e76e015b68991e7b4) | Downloads the package archive from the server. | +| [`doExtract`](#group__pacm_1ga2f72241766459b160c804adc1478f5de) | Extracts the downloaded package files to the intermediate directory. | +| [`doFinalize`](#group__pacm_1ga6a1835d063d88174640ef5a28f883ac8) | Moves extracted files from the intermediate directory to the installation directory. | +| [`setComplete`](#group__pacm_1ga26d9a2a7502b8b85c7ee3a925567d882) | Called when the task completes either successfully or in error. This will trigger destruction. | +| [`getRemoteAsset`](#group__pacm_1gac019583f25b3acdb49d9341c1a7978c6) | | +| [`local`](#group__pacm_1gadbcbd1e53c273436d7115a41ed1873f7) | | +| [`remote`](#group__pacm_1gaf63f6840681ee74ee5664c82ffb889a2) | | +| [`options`](#group__pacm_1gadf2774d8799a8fd865fc4f6b73a00ed1) | | +| [`loop`](#group__pacm_1ga682298509ac94f66851b7760ce672c57) | | +| [`valid`](#group__pacm_1ga0a49aa89c7ace046190a1920c8db2704) | | +| [`cancelled`](#group__pacm_1gad4433a04ac1bb9dd5a6d2f222df77418) | Returns true when the task has been cancelled. | +| [`failed`](#group__pacm_1ga98d6a383a58aab12cf84e2591774571f) | | +| [`success`](#group__pacm_1ga10c6401c60f22f2845c9560e58496907) | | +| [`complete`](#group__pacm_1ga0dab536f7d0d8eddcb0cc5c9bddd1a87) | | +| [`progress`](#group__pacm_1ga3dbca4f9b48fa5266333f7428e45338b) | | +| [`run`](#group__pacm_1gab2791d8750f5bf0deece4e7fd708a0c9) | Called asynchronously by the thread to do the work. | +| [`onStateChange`](#group__pacm_1ga2f29805629456fceb726bd8c7f03c253) | | +| [`onDownloadProgress`](#group__pacm_1ga5a9f8befa6682fc5b725bab29d9cf60f) | | +| [`onDownloadComplete`](#group__pacm_1ga9c58cacb35a5d15d143c329b404e2b76) | | +| [`setProgress`](#group__pacm_1gaaa96e157962a5c8bfb70a84f5a49d634) | | +| [`Progress`](#group__pacm_1gaf703cf11a21b644acc7e59c1ebf26485) | Signals on progress update [0-100]. | +| [`Complete`](#group__pacm_1gaccf8591e8208940a4ad7c8133e3ec0ad) | Signals on task completion for both success and failure cases. | +| [`_mutex`](#group__pacm_1ga87292e561d64eca2a4b2d6677eb87d15) | | +| [`_runner`](#group__pacm_1gaf178666e39b153b95d05945e47602099) | | +| [`_error`](#group__pacm_1gacb7051d1db8a70b40f24cfee662aa18f) | | +| [`_manager`](#group__pacm_1ga75bf291aa5b026cc178ba1361d44ec92) | | +| [`_local`](#group__pacm_1gaed93e1d4951c6672b7f2ce7a91469cfd) | | +| [`_remote`](#group__pacm_1ga39c422153b97c6aa95a1b2fe74a4c0b5) | | +| [`_options`](#group__pacm_1ga3d6b1dbf5dc37e7aaf8d012f37d2c2cf) | | +| [`_progress`](#group__pacm_1ga969d6a197cb58d27f056a989d413057d) | | +| [`_downloading`](#group__pacm_1gac770bceb041aaa041c79f05a03a290b9) | | +| [`_dlconn`](#group__pacm_1gaa286e79832b53a9a13ff50c6db6166d3) | | +| [`_loop`](#group__pacm_1gab2e5dc630f6211673263d278d29be932) | | + +--- + +#### InstallTask + +```cpp +InstallTask(PackageManager & manager, LocalPackage * local, RemotePackage * remote, const InstallOptions & options, uv::Loop * loop) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `manager` | `PackageManager &` | | +| `local` | `LocalPackage *` | | +| `remote` | `RemotePackage *` | | +| `options` | `const InstallOptions &` | | +| `loop` | `uv::Loop *` | | +--- -#### `public virtual void start()` +#### ~InstallTask +```cpp +virtual ~InstallTask() +``` +--- +#### start +```cpp +virtual void start() +``` -#### `public virtual void cancel()` +--- +#### cancel +```cpp +virtual void cancel() +``` +--- +#### doDownload -#### `public virtual void doDownload()` +```cpp +virtual void doDownload() +``` Downloads the package archive from the server. +--- +#### doExtract -#### `public virtual void doExtract()` - - +```cpp +virtual void doExtract() +``` Extracts the downloaded package files to the intermediate directory. -#### `public virtual void doFinalize()` +--- +#### doFinalize +```cpp +virtual void doFinalize() +``` Moves extracted files from the intermediate directory to the installation directory. -#### `public virtual void setComplete()` +--- +#### setComplete +```cpp +virtual void setComplete() +``` Called when the task completes either successfully or in error. This will trigger destruction. -#### `public virtual `[`Package::Asset`](#structscy_1_1pacm_1_1Package_1_1Asset)` getRemoteAsset() const` - - - - - -#### `public virtual `[`LocalPackage`](#structscy_1_1pacm_1_1LocalPackage)` * local() const` - - - - - -#### `public virtual `[`RemotePackage`](#structscy_1_1pacm_1_1RemotePackage)` * remote() const` +--- +#### getRemoteAsset +```cpp +virtual Package::Asset getRemoteAsset() const +``` +--- +#### local -#### `public virtual `[`InstallOptions`](#structscy_1_1pacm_1_1InstallOptions)` & options()` +```cpp +virtual LocalPackage * local() const +``` +--- +#### remote +```cpp +virtual RemotePackage * remote() const +``` +--- -#### `public virtual uv::Loop * loop() const` +#### options +```cpp +virtual InstallOptions & options() +``` +--- +#### loop +```cpp +virtual uv::Loop * loop() const +``` -#### `public virtual bool valid() const` +--- +#### valid +```cpp +virtual bool valid() const +``` +--- +#### cancelled -#### `public virtual bool cancelled() const` +```cpp +virtual bool cancelled() const +``` Returns true when the task has been cancelled. +--- +#### failed -#### `public virtual bool failed() const` - - - - - -#### `public virtual bool success() const` - - - +```cpp +virtual bool failed() const +``` +--- -#### `public virtual bool complete() const` +#### success +```cpp +virtual bool success() const +``` +--- +#### complete +```cpp +virtual bool complete() const +``` -#### `public virtual int progress() const` +--- +#### progress +```cpp +virtual int progress() const +``` +--- +#### run -#### `protected mutable std::mutex _mutex` +```cpp +virtual void run() +``` +Called asynchronously by the thread to do the work. +--- +#### onStateChange +```cpp +virtual void onStateChange(InstallationState & state, const InstallationState & oldState) +``` -#### `protected `[`Idler`](./doc/api-base.md#classscy_1_1Idler)` _runner` +| Parameter | Type | Description | +|-----------|------|-------------| +| `state` | `InstallationState &` | | +| `oldState` | `const InstallationState &` | | +--- +#### onDownloadProgress +```cpp +virtual void onDownloadProgress(const double & progress) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `progress` | `const double &` | | -#### `protected `[`scy::Error`](./doc/api-base.md#structscy_1_1Error)` _error` +--- +#### onDownloadComplete +```cpp +virtual void onDownloadComplete(const http::Response & response) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `response` | `const http::Response &` | | +--- -#### `protected `[`PackageManager`](./doc/api-pacm.md#classscy_1_1pacm_1_1PackageManager)` & _manager` +#### setProgress +```cpp +virtual void setProgress(int value) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `value` | `int` | | +--- +#### Progress -#### `protected `[`LocalPackage`](./doc/api-pacm.md#structscy_1_1pacm_1_1LocalPackage)` * _local` +```cpp +Signal< void(InstallTask &, int &)> Progress +``` +Signals on progress update [0-100]. +--- +#### Complete +```cpp +Signal< void(InstallTask &)> Complete +``` -#### `protected `[`RemotePackage`](./doc/api-pacm.md#structscy_1_1pacm_1_1RemotePackage)` * _remote` +Signals on task completion for both success and failure cases. +--- +#### _mutex +```cpp +std::mutex _mutex +``` +--- -#### `protected `[`InstallOptions`](./doc/api-pacm.md#structscy_1_1pacm_1_1InstallOptions)` _options` +#### _runner +```cpp +Idler _runner +``` +--- +#### _error +```cpp +[scy::Error](./doc/api-base.md#structscy_1_1Error) _error +``` -#### `protected int _progress` +--- +#### _manager +```cpp +PackageManager & _manager +``` +--- +#### _local -#### `protected bool _downloading` +```cpp +LocalPackage * _local +``` +--- +#### _remote +```cpp +RemotePackage * _remote +``` +--- -#### `protected http::ClientConnection::Ptr _dlconn` +#### _options +```cpp +InstallOptions _options +``` +--- +#### _progress +```cpp +int _progress +``` -#### `protected uv::Loop * _loop` +--- +#### _downloading +```cpp +bool _downloading +``` +--- +#### _dlconn -#### `protected virtual void run()` +```cpp +http::ClientConnection::Ptr _dlconn +``` -Called asynchronously by the thread to do the work. +--- +#### _loop +```cpp +uv::Loop * _loop +``` -#### `protected virtual void onStateChange(`[`InstallationState`](#structscy_1_1pacm_1_1InstallationState)` & state,const `[`InstallationState`](#structscy_1_1pacm_1_1InstallationState)` & oldState)` +## PackageManager +> **Defined in:** `packagemanager.h` +The [Package](#structscy_1_1pacm_1_1Package) Manager provides an interface for managing, installing, updating and uninstalling Pacm packages. +### Members + +| Name | Description | +|------|-------------| +| [`PackageManager`](#group__pacm_1ga0294b3732c8c91eae3066bf22088dd8f) | | +| [`~PackageManager`](#group__pacm_1ga0cc70a4263385dff8736a9e93d1e8e91) | | +| [`initialize`](#group__pacm_1gad2aa7211618560cec5cadf2d2b935e3f) | Initialization Methods. | +| [`uninitialize`](#group__pacm_1ga3f0734d6e0baf127459b596be8f69041) | | +| [`initialized`](#group__pacm_1ga35d5d38a71defe859770d1f5ea45dc29) | | +| [`createDirectories`](#group__pacm_1ga7eac61590241621a6945610c642bbd20) | Creates the package manager directory structure if it does not already exist. | +| [`queryRemotePackages`](#group__pacm_1ga7a6a87813079f346cf8b1248ef6f954e) | Queries the server for a list of available packages. | +| [`loadLocalPackages`](#group__pacm_1ga274d4bdc0fb2824165912e29eaa4a83a) | Loads all local package manifests from file system. Clears all in memory package manifests. | +| [`loadLocalPackages`](#group__pacm_1gac57d2e0df47bd611aadd0018a8562bf5) | Loads all local package manifests residing the the given directory. This method may be called multiple times for different paths because it does not clear in memory package manifests. | +| [`saveLocalPackages`](#group__pacm_1ga0dd3c90a7e9f85b20e6c0e44484be0af) | | +| [`saveLocalPackage`](#group__pacm_1gaf7b9979bcb8cb9cb83f7ad1cb435879c) | Saves the local package manifest to the file system. | +| [`parseRemotePackages`](#group__pacm_1ga5a84f69090718da9af13247e64e28156) | Parse the remote packages from the given JSON data string. | +| [`installPackage`](#group__pacm_1gad295633f0783292623a120b227685090) | [Package](#structscy_1_1pacm_1_1Package) Installation Methods. | +| [`installPackages`](#group__pacm_1ga606a44cfed11394c05485adc351e9c04) | Installs multiple packages. The same options will be passed to each task. If a [InstallMonitor](#classscy_1_1pacm_1_1InstallMonitor) instance was passed in the tasks will need to be started, otherwise they will be auto-started. The [PackageManager](#classscy_1_1pacm_1_1PackageManager) does not take ownership of the [InstallMonitor](#classscy_1_1pacm_1_1InstallMonitor). | +| [`updatePackage`](#group__pacm_1ga027124b092208da323cfc62299d9d4bc) | Updates a single package. Throws an exception if the package does not exist. The returned [InstallTask](#classscy_1_1pacm_1_1InstallTask) must be started. | +| [`updatePackages`](#group__pacm_1gac48da691471662ce57f5815ac9c91ab0) | Updates multiple packages. Throws an exception if the package does not exist. If a [InstallMonitor](#classscy_1_1pacm_1_1InstallMonitor) instance was passed in the tasks will need to be started, otherwise they will be auto-started. The [PackageManager](#classscy_1_1pacm_1_1PackageManager) does not take ownership of the [InstallMonitor](#classscy_1_1pacm_1_1InstallMonitor). | +| [`updateAllPackages`](#group__pacm_1gaabc1315c35c2204028ef39ef77201d33) | Updates all installed packages. | +| [`uninstallPackages`](#group__pacm_1ga21634eceac90c02a342e413eb444a9d1) | Uninstalls multiple packages. | +| [`uninstallPackage`](#group__pacm_1ga06e4a2f271745f6ea4c50d4a85953bd5) | Uninstalls a single package. | +| [`hasUnfinalizedPackages`](#group__pacm_1ga736cd4d51f8c5e39dcfa2159fcfa0c8e) | Returns true if there are updates available that have not yet been finalized. Packages may be unfinalized if there were files in use at the time of installation. | +| [`finalizeInstallations`](#group__pacm_1ga65f16318834b79ddfa651fbbee66b301) | Finalizes active installations by moving all package files to their target destination. If files are to be overwritten they must not be in use or finalization will fail. | +| [`getInstallTask`](#group__pacm_1gad2d2c89ce41a9e620bdb0abfb005c369) | [Task](./doc/api-base.md#classscy_1_1Task) Helper Methods. | +| [`tasks`](#group__pacm_1ga06761269e2391f30c5e0564156af8374) | Returns a list of all tasks. | +| [`cancelAllTasks`](#group__pacm_1ga86a2bcebdc5c0bd217877ff180f1640b) | Aborts all package installation tasks. All tasks must be aborted before clearing local or remote manifests. | +| [`getPackagePairs`](#group__pacm_1ga11c411f6e676fb723561f8dc0c7bab4c) | [Package](#structscy_1_1pacm_1_1Package) Helper Methods. | +| [`getUpdatablePackagePairs`](#group__pacm_1ga8d2d399c321a02b82363387c25641aa0) | Returns a list of package pairs which may be updated. All pairs will have both local and remote package pointers, and the remote version will be newer than the local version. | +| [`getPackagePair`](#group__pacm_1ga2b2ef4158487fa1d82350994b5af38a9) | Returns a local and remote package pair. An exception will be thrown if either the local or remote packages aren't available or are invalid. | +| [`getOrCreatePackagePair`](#group__pacm_1gada7825aae6e2a54ee37332750686f67b) | Returns a local and remote package pair. If the local package doesn't exist it will be created from the remote package. If the remote package doesn't exist a NotFoundException will be thrown. | +| [`createInstallTask`](#group__pacm_1gafa07546ae7c88588169868deda5401ac) | Creates a package installation task for the given pair. | +| [`installedPackageVersion`](#group__pacm_1ga14871be8a910f944116f75c379352803) | Returns the version number of an installed package. Exceptions will be thrown if the package does not exist, or is not fully installed. | +| [`getLatestInstallableAsset`](#group__pacm_1ga5b0b61d38eb166ee35ae458d45bc3ea2) | Returns the best asset to install, or throws a descriptive exception if no updates are available, or if the package is already up-to-date. This method takes version and SDK locks into consideration. | +| [`hasAvailableUpdates`](#group__pacm_1ga994577213392b7452e0cc4f49893295a) | Returns true if there are updates available for this package, false otherwise. | +| [`clearCache`](#group__pacm_1gae83f81efc6fac83c6b1feff2ab5dcc9f) | File Helper Methods. | +| [`clearPackageCache`](#group__pacm_1gad57a7658f320091a47c9f592d34daf7f) | Clears a package archive from the local cache. | +| [`clearCacheFile`](#group__pacm_1ga547f44c7bb1c2307ac62b7a73aa9cb72) | Clears a file from the local cache. | +| [`hasCachedFile`](#group__pacm_1gabba22fcdb14b4ffe8c1bbaaed0845bf8) | Checks if a package archive exists in the local cache. | +| [`isSupportedFileType`](#group__pacm_1ga2b6d7aca72d07ffb066ed33126e33b00) | Checks if the file type is a supported package archive. | +| [`getCacheFilePath`](#group__pacm_1gaf98ef2e87f1508708c8d6387a4442fc2) | Returns the full path of the cached file if it exists, or an empty path if the file doesn't exist. | +| [`getPackageDataDir`](#group__pacm_1ga0e449180c70179434ff03226f8f612ca) | Returns the package data directory for the given package ID. | +| [`options`](#group__pacm_1ga2f058814ce88bd8f906fd1a0798ee3dd) | Accessors. | +| [`remotePackages`](#group__pacm_1ga666c75b4746425e5dd7c0dbbe52062ed) | | +| [`localPackages`](#group__pacm_1ga632003da9cc5e262bdbc679ee4dd2c9a) | | +| [`onPackageInstallComplete`](#group__pacm_1ga51dc83f2084498013b72c545d9ec5124) | Callbacks. | +| [`RemotePackageResponse`](#group__pacm_1gac9bfa675fc261bd38052ae17bae25356) | Events. | +| [`PackageUninstalled`](#group__pacm_1gab05d4bd29a2c2ecc7579e58f919d43c5) | Signals when a package is uninstalled. | +| [`InstallTaskCreated`](#group__pacm_1ga7fbc7057386ad4ec58af8223d56c7bef) | Signals when an installation task is created, before it is started. | +| [`InstallTaskComplete`](#group__pacm_1ga4e0d38796a84080bbf09756a553503c7) | Signals when a package installation tasks completes, either successfully or in error. | +| [`_mutex`](#group__pacm_1gae98d53378ea091de1bf8021d83163c49) | | +| [`_localPackages`](#group__pacm_1ga1f7e142696d6a5cace81ff92036d5079) | | +| [`_remotePackages`](#group__pacm_1ga8cc192fdcf6a3aafd15a9083504e37da) | | +| [`_tasks`](#group__pacm_1ga86909426338d228d0a01de9a98332617) | | +| [`_options`](#group__pacm_1ga6883f4d86ccd9d91baf44e737b4e3913) | | + +--- + +#### PackageManager + +```cpp +PackageManager(const Options & options) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `options` | `const Options &` | | -#### `protected virtual void onDownloadProgress(const double & progress)` +--- +#### ~PackageManager +```cpp +virtual ~PackageManager() +``` +--- +#### initialize -#### `protected virtual void onDownloadComplete(const `[`http::Response`](#classscy_1_1http_1_1Response)` & response)` +```cpp +virtual void initialize() +``` +Initialization Methods. +--- +#### uninitialize +```cpp +virtual void uninitialize() +``` -#### `protected virtual void setProgress(int value)` +--- +#### initialized +```cpp +virtual bool initialized() const +``` +--- +#### createDirectories -# class `scy::pacm::PackageManager` +```cpp +virtual void createDirectories() +``` +Creates the package manager directory structure if it does not already exist. +--- +#### queryRemotePackages -The [Package](#structscy_1_1pacm_1_1Package) Manager provides an interface for managing, installing, updating and uninstalling Pacm packages. +```cpp +virtual void queryRemotePackages() +``` -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public `[`Signal](#classscy_1_1Signal)< void(const [http::Response`](#classscy_1_1http_1_1Response) &)`> RemotePackageResponse` | Events. -`public `[`Signal](#classscy_1_1Signal)< void([LocalPackage`](#structscy_1_1pacm_1_1LocalPackage) &)`> PackageUninstalled` | Signals when a package is uninstalled. -`public `[`Signal](#classscy_1_1Signal)< void([InstallTask`](#classscy_1_1pacm_1_1InstallTask) &)`> InstallTaskCreated` | -`public `[`Signal](#classscy_1_1Signal)< void(const [InstallTask`](#classscy_1_1pacm_1_1InstallTask) &)`> InstallTaskComplete` | -`public PackageManager(const `[`Options`](#structscy_1_1pacm_1_1PackageManager_1_1Options)` & options)` | -`public virtual ~PackageManager()` | -`public virtual void initialize()` | Initialization Methods. -`public virtual void uninitialize()` | -`public virtual bool initialized() const` | -`public virtual void createDirectories()` | -`public virtual void queryRemotePackages()` | Queries the server for a list of available packages. -`public virtual void loadLocalPackages()` | -`public virtual void loadLocalPackages(const std::string & dir)` | -`public virtual bool saveLocalPackages(bool whiny)` | -`public virtual bool saveLocalPackage(`[`LocalPackage`](#structscy_1_1pacm_1_1LocalPackage)` & package,bool whiny)` | Saves the local package manifest to the file system. -`public virtual void parseRemotePackages(const std::string & data)` | Parse the remote packages from the given JSON data string. -`public virtual InstallTask::Ptr installPackage(const std::string & name,const `[`InstallOptions`](#structscy_1_1pacm_1_1InstallOptions)` & options)` | [Package](./doc/api-pacm.md#structscy_1_1pacm_1_1Package) Installation Methods. -`public virtual bool installPackages(const StringVec & ids,const `[`InstallOptions`](#structscy_1_1pacm_1_1InstallOptions)` & options,`[`InstallMonitor`](#classscy_1_1pacm_1_1InstallMonitor)` * monitor,bool whiny)` | -`public virtual InstallTask::Ptr updatePackage(const std::string & name,const `[`InstallOptions`](#structscy_1_1pacm_1_1InstallOptions)` & options)` | -`public virtual bool updatePackages(const StringVec & ids,const `[`InstallOptions`](#structscy_1_1pacm_1_1InstallOptions)` & options,`[`InstallMonitor`](#classscy_1_1pacm_1_1InstallMonitor)` * monitor,bool whiny)` | -`public virtual bool updateAllPackages(bool whiny)` | Updates all installed packages. -`public virtual bool uninstallPackages(const StringVec & ids,bool whiny)` | Uninstalls multiple packages. -`public virtual bool uninstallPackage(const std::string & id,bool whiny)` | Uninstalls a single package. -`public virtual bool hasUnfinalizedPackages()` | -`public virtual bool finalizeInstallations(bool whiny)` | -`public virtual InstallTask::Ptr getInstallTask(const std::string & id) const` | [Task](./doc/api-base.md#classscy_1_1Task) Helper Methods. -`public virtual InstallTaskPtrVec tasks() const` | Returns a list of all tasks. -`public virtual void cancelAllTasks()` | -`public virtual PackagePairVec getPackagePairs() const` | [Package](./doc/api-pacm.md#structscy_1_1pacm_1_1Package) Helper Methods. -`public virtual PackagePairVec getUpdatablePackagePairs() const` | -`public virtual `[`PackagePair`](#structscy_1_1pacm_1_1PackagePair)` getPackagePair(const std::string & id,bool whiny) const` | -`public virtual `[`PackagePair`](#structscy_1_1pacm_1_1PackagePair)` getOrCreatePackagePair(const std::string & id)` | -`public virtual InstallTask::Ptr createInstallTask(`[`PackagePair`](#structscy_1_1pacm_1_1PackagePair)` & pair,const `[`InstallOptions`](#structscy_1_1pacm_1_1InstallOptions)` & options)` | Creates a package installation task for the given pair. -`public virtual std::string installedPackageVersion(const std::string & id) const` | -`public virtual `[`Package::Asset`](#structscy_1_1pacm_1_1Package_1_1Asset)` getLatestInstallableAsset(const `[`PackagePair`](#structscy_1_1pacm_1_1PackagePair)` & pair,const `[`InstallOptions`](#structscy_1_1pacm_1_1InstallOptions)` & options) const` | -`public virtual bool hasAvailableUpdates(const `[`PackagePair`](#structscy_1_1pacm_1_1PackagePair)` & pair) const` | -`public void clearCache()` | File Helper Methods. -`public bool clearPackageCache(`[`LocalPackage`](#structscy_1_1pacm_1_1LocalPackage)` & package)` | Clears a package archive from the local cache. -`public bool clearCacheFile(const std::string & fileName,bool whiny)` | Clears a file from the local cache. -`public bool hasCachedFile(`[`Package::Asset`](#structscy_1_1pacm_1_1Package_1_1Asset)` & asset)` | Checks if a package archive exists in the local cache. -`public bool isSupportedFileType(const std::string & fileName)` | Checks if the file type is a supported package archive. -`public std::string getCacheFilePath(const std::string & fileName)` | -`public std::string getPackageDataDir(const std::string & id)` | -`public virtual `[`Options`](#structscy_1_1pacm_1_1PackageManager_1_1Options)` & options()` | Accessors. -`public virtual `[`RemotePackageStore`](#classscy_1_1LiveCollection)` & remotePackages()` | -`public virtual `[`LocalPackageStore`](#classscy_1_1LiveCollection)` & localPackages()` | -`protected mutable std::mutex _mutex` | -`protected `[`LocalPackageStore`](./doc/api-base.md#classscy_1_1LiveCollection)` _localPackages` | -`protected `[`RemotePackageStore`](./doc/api-base.md#classscy_1_1LiveCollection)` _remotePackages` | -`protected InstallTaskPtrVec _tasks` | -`protected `[`Options`](./doc/api-pacm.md#structscy_1_1pacm_1_1PackageManager_1_1Options)` _options` | -`protected void onPackageInstallComplete(`[`InstallTask`](#classscy_1_1pacm_1_1InstallTask)` & task)` | Callbacks. - -## Members - -#### `public `[`Signal](#classscy_1_1Signal)< void(const [http::Response`](#classscy_1_1http_1_1Response) &)`> RemotePackageResponse` +Queries the server for a list of available packages. -Events. +--- -Signals when the remote package list have been downloaded from the server. +#### loadLocalPackages -#### `public `[`Signal](#classscy_1_1Signal)< void([LocalPackage`](#structscy_1_1pacm_1_1LocalPackage) &)`> PackageUninstalled` +```cpp +virtual void loadLocalPackages() +``` -Signals when a package is uninstalled. +Loads all local package manifests from file system. Clears all in memory package manifests. +--- +#### loadLocalPackages -#### `public `[`Signal](#classscy_1_1Signal)< void([InstallTask`](#classscy_1_1pacm_1_1InstallTask) &)`> InstallTaskCreated` +```cpp +virtual void loadLocalPackages(const std::string & dir) +``` +Loads all local package manifests residing the the given directory. This method may be called multiple times for different paths because it does not clear in memory package manifests. +| Parameter | Type | Description | +|-----------|------|-------------| +| `dir` | `const std::string &` | | -Signals when an installation task is created, before it is started. +--- -#### `public `[`Signal](#classscy_1_1Signal)< void(const [InstallTask`](#classscy_1_1pacm_1_1InstallTask) &)`> InstallTaskComplete` +#### saveLocalPackages +```cpp +virtual bool saveLocalPackages(bool whiny) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `whiny` | `bool` | | -Signals when a package installation tasks completes, either successfully or in error. +--- -#### `public PackageManager(const `[`Options`](#structscy_1_1pacm_1_1PackageManager_1_1Options)` & options)` +#### saveLocalPackage +```cpp +virtual bool saveLocalPackage(LocalPackage & package, bool whiny) +``` +Saves the local package manifest to the file system. +| Parameter | Type | Description | +|-----------|------|-------------| +| `package` | `LocalPackage &` | | +| `whiny` | `bool` | | +--- -#### `public virtual ~PackageManager()` +#### parseRemotePackages +```cpp +virtual void parseRemotePackages(const std::string & data) +``` +Parse the remote packages from the given JSON data string. +| Parameter | Type | Description | +|-----------|------|-------------| +| `data` | `const std::string &` | | +--- -#### `public virtual void initialize()` +#### installPackage -Initialization Methods. +```cpp +virtual InstallTask::Ptr installPackage(const std::string & name, const InstallOptions & options) +``` +[Package](#structscy_1_1pacm_1_1Package) Installation Methods. +Installs a single package. The returned [InstallTask](#classscy_1_1pacm_1_1InstallTask) must be started. If the package is already up-to-date, a nullptr will be returned. Any other error will throw a std::runtime_error. -#### `public virtual void uninitialize()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | +| `options` | `const InstallOptions &` | | +--- +#### installPackages +```cpp +virtual bool installPackages(const StringVec & ids, const InstallOptions & options, InstallMonitor * monitor, bool whiny) +``` +Installs multiple packages. The same options will be passed to each task. If a [InstallMonitor](#classscy_1_1pacm_1_1InstallMonitor) instance was passed in the tasks will need to be started, otherwise they will be auto-started. The [PackageManager](#classscy_1_1pacm_1_1PackageManager) does not take ownership of the [InstallMonitor](#classscy_1_1pacm_1_1InstallMonitor). -#### `public virtual bool initialized() const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `ids` | `const StringVec &` | | +| `options` | `const InstallOptions &` | | +| `monitor` | `InstallMonitor *` | | +| `whiny` | `bool` | | +--- +#### updatePackage +```cpp +virtual InstallTask::Ptr updatePackage(const std::string & name, const InstallOptions & options) +``` +Updates a single package. Throws an exception if the package does not exist. The returned [InstallTask](#classscy_1_1pacm_1_1InstallTask) must be started. -#### `public virtual void createDirectories()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | +| `options` | `const InstallOptions &` | | +--- +#### updatePackages -Creates the package manager directory structure if it does not already exist. +```cpp +virtual bool updatePackages(const StringVec & ids, const InstallOptions & options, InstallMonitor * monitor, bool whiny) +``` -#### `public virtual void queryRemotePackages()` +Updates multiple packages. Throws an exception if the package does not exist. If a [InstallMonitor](#classscy_1_1pacm_1_1InstallMonitor) instance was passed in the tasks will need to be started, otherwise they will be auto-started. The [PackageManager](#classscy_1_1pacm_1_1PackageManager) does not take ownership of the [InstallMonitor](#classscy_1_1pacm_1_1InstallMonitor). -Queries the server for a list of available packages. +| Parameter | Type | Description | +|-----------|------|-------------| +| `ids` | `const StringVec &` | | +| `options` | `const InstallOptions &` | | +| `monitor` | `InstallMonitor *` | | +| `whiny` | `bool` | | +--- +#### updateAllPackages -#### `public virtual void loadLocalPackages()` +```cpp +virtual bool updateAllPackages(bool whiny) +``` +Updates all installed packages. +| Parameter | Type | Description | +|-----------|------|-------------| +| `whiny` | `bool` | | -Loads all local package manifests from file system. Clears all in memory package manifests. +--- -#### `public virtual void loadLocalPackages(const std::string & dir)` +#### uninstallPackages +```cpp +virtual bool uninstallPackages(const StringVec & ids, bool whiny) +``` +Uninstalls multiple packages. -Loads all local package manifests residing the the given directory. This method may be called multiple times for different paths because it does not clear in memory package manifests. +| Parameter | Type | Description | +|-----------|------|-------------| +| `ids` | `const StringVec &` | | +| `whiny` | `bool` | | -#### `public virtual bool saveLocalPackages(bool whiny)` +--- +#### uninstallPackage +```cpp +virtual bool uninstallPackage(const std::string & id, bool whiny) +``` +Uninstalls a single package. +| Parameter | Type | Description | +|-----------|------|-------------| +| `id` | `const std::string &` | | +| `whiny` | `bool` | | -#### `public virtual bool saveLocalPackage(`[`LocalPackage`](#structscy_1_1pacm_1_1LocalPackage)` & package,bool whiny)` +--- -Saves the local package manifest to the file system. +#### hasUnfinalizedPackages +```cpp +virtual bool hasUnfinalizedPackages() +``` +Returns true if there are updates available that have not yet been finalized. Packages may be unfinalized if there were files in use at the time of installation. -#### `public virtual void parseRemotePackages(const std::string & data)` +--- -Parse the remote packages from the given JSON data string. +#### finalizeInstallations +```cpp +virtual bool finalizeInstallations(bool whiny) +``` +Finalizes active installations by moving all package files to their target destination. If files are to be overwritten they must not be in use or finalization will fail. -#### `public virtual InstallTask::Ptr installPackage(const std::string & name,const `[`InstallOptions`](#structscy_1_1pacm_1_1InstallOptions)` & options)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `whiny` | `bool` | | -[Package](#structscy_1_1pacm_1_1Package) Installation Methods. +--- -Installs a single package. The returned [InstallTask](#classscy_1_1pacm_1_1InstallTask) must be started. If the package is already up-to-date, a nullptr will be returned. Any other error will throw a std::runtime_error. +#### getInstallTask -#### `public virtual bool installPackages(const StringVec & ids,const `[`InstallOptions`](#structscy_1_1pacm_1_1InstallOptions)` & options,`[`InstallMonitor`](#classscy_1_1pacm_1_1InstallMonitor)` * monitor,bool whiny)` +```cpp +virtual InstallTask::Ptr getInstallTask(const std::string & id) const +``` +[Task](./doc/api-base.md#classscy_1_1Task) Helper Methods. +Gets the install task for the given package ID. -Installs multiple packages. The same options will be passed to each task. If a [InstallMonitor](#classscy_1_1pacm_1_1InstallMonitor) instance was passed in the tasks will need to be started, otherwise they will be auto-started. The [PackageManager](#classscy_1_1pacm_1_1PackageManager) does not take ownership of the [InstallMonitor](#classscy_1_1pacm_1_1InstallMonitor). +| Parameter | Type | Description | +|-----------|------|-------------| +| `id` | `const std::string &` | | -#### `public virtual InstallTask::Ptr updatePackage(const std::string & name,const `[`InstallOptions`](#structscy_1_1pacm_1_1InstallOptions)` & options)` +--- +#### tasks +```cpp +virtual InstallTaskPtrVec tasks() const +``` -Updates a single package. Throws an exception if the package does not exist. The returned [InstallTask](#classscy_1_1pacm_1_1InstallTask) must be started. +Returns a list of all tasks. -#### `public virtual bool updatePackages(const StringVec & ids,const `[`InstallOptions`](#structscy_1_1pacm_1_1InstallOptions)` & options,`[`InstallMonitor`](#classscy_1_1pacm_1_1InstallMonitor)` * monitor,bool whiny)` +--- +#### cancelAllTasks +```cpp +virtual void cancelAllTasks() +``` -Updates multiple packages. Throws an exception if the package does not exist. If a [InstallMonitor](#classscy_1_1pacm_1_1InstallMonitor) instance was passed in the tasks will need to be started, otherwise they will be auto-started. The [PackageManager](#classscy_1_1pacm_1_1PackageManager) does not take ownership of the [InstallMonitor](#classscy_1_1pacm_1_1InstallMonitor). +Aborts all package installation tasks. All tasks must be aborted before clearing local or remote manifests. -#### `public virtual bool updateAllPackages(bool whiny)` +--- -Updates all installed packages. +#### getPackagePairs +```cpp +virtual PackagePairVec getPackagePairs() const +``` +[Package](#structscy_1_1pacm_1_1Package) Helper Methods. -#### `public virtual bool uninstallPackages(const StringVec & ids,bool whiny)` +Returns all package pairs, valid or invalid. Some pairs may not have both local and remote package pointers. -Uninstalls multiple packages. +--- +#### getUpdatablePackagePairs +```cpp +virtual PackagePairVec getUpdatablePackagePairs() const +``` -#### `public virtual bool uninstallPackage(const std::string & id,bool whiny)` +Returns a list of package pairs which may be updated. All pairs will have both local and remote package pointers, and the remote version will be newer than the local version. -Uninstalls a single package. +--- +#### getPackagePair +```cpp +virtual PackagePair getPackagePair(const std::string & id, bool whiny) const +``` -#### `public virtual bool hasUnfinalizedPackages()` +Returns a local and remote package pair. An exception will be thrown if either the local or remote packages aren't available or are invalid. +| Parameter | Type | Description | +|-----------|------|-------------| +| `id` | `const std::string &` | | +| `whiny` | `bool` | | +--- -Returns true if there are updates available that have not yet been finalized. Packages may be unfinalized if there were files in use at the time of installation. +#### getOrCreatePackagePair -#### `public virtual bool finalizeInstallations(bool whiny)` +```cpp +virtual PackagePair getOrCreatePackagePair(const std::string & id) +``` +Returns a local and remote package pair. If the local package doesn't exist it will be created from the remote package. If the remote package doesn't exist a NotFoundException will be thrown. +| Parameter | Type | Description | +|-----------|------|-------------| +| `id` | `const std::string &` | | -Finalizes active installations by moving all package files to their target destination. If files are to be overwritten they must not be in use or finalization will fail. +--- -#### `public virtual InstallTask::Ptr getInstallTask(const std::string & id) const` +#### createInstallTask -[Task](#classscy_1_1Task) Helper Methods. +```cpp +virtual InstallTask::Ptr createInstallTask(PackagePair & pair, const InstallOptions & options) +``` -Gets the install task for the given package ID. +Creates a package installation task for the given pair. -#### `public virtual InstallTaskPtrVec tasks() const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `pair` | `PackagePair &` | | +| `options` | `const InstallOptions &` | | -Returns a list of all tasks. +--- +#### installedPackageVersion +```cpp +virtual std::string installedPackageVersion(const std::string & id) const +``` -#### `public virtual void cancelAllTasks()` +Returns the version number of an installed package. Exceptions will be thrown if the package does not exist, or is not fully installed. +| Parameter | Type | Description | +|-----------|------|-------------| +| `id` | `const std::string &` | | +--- -Aborts all package installation tasks. All tasks must be aborted before clearing local or remote manifests. +#### getLatestInstallableAsset -#### `public virtual PackagePairVec getPackagePairs() const` +```cpp +virtual Package::Asset getLatestInstallableAsset(const PackagePair & pair, const InstallOptions & options) const +``` -[Package](#structscy_1_1pacm_1_1Package) Helper Methods. +Returns the best asset to install, or throws a descriptive exception if no updates are available, or if the package is already up-to-date. This method takes version and SDK locks into consideration. -Returns all package pairs, valid or invalid. Some pairs may not have both local and remote package pointers. +| Parameter | Type | Description | +|-----------|------|-------------| +| `pair` | `const PackagePair &` | | +| `options` | `const InstallOptions &` | | -#### `public virtual PackagePairVec getUpdatablePackagePairs() const` +--- +#### hasAvailableUpdates +```cpp +virtual bool hasAvailableUpdates(const PackagePair & pair) const +``` -Returns a list of package pairs which may be updated. All pairs will have both local and remote package pointers, and the remote version will be newer than the local version. +Returns true if there are updates available for this package, false otherwise. -#### `public virtual `[`PackagePair`](#structscy_1_1pacm_1_1PackagePair)` getPackagePair(const std::string & id,bool whiny) const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `pair` | `const PackagePair &` | | +--- +#### clearCache -Returns a local and remote package pair. An exception will be thrown if either the local or remote packages aren't available or are invalid. +```cpp +void clearCache() +``` -#### `public virtual `[`PackagePair`](#structscy_1_1pacm_1_1PackagePair)` getOrCreatePackagePair(const std::string & id)` +File Helper Methods. +Clears all files in the cache directory. +--- -Returns a local and remote package pair. If the local package doesn't exist it will be created from the remote package. If the remote package doesn't exist a NotFoundException will be thrown. +#### clearPackageCache -#### `public virtual InstallTask::Ptr createInstallTask(`[`PackagePair`](#structscy_1_1pacm_1_1PackagePair)` & pair,const `[`InstallOptions`](#structscy_1_1pacm_1_1InstallOptions)` & options)` +```cpp +bool clearPackageCache(LocalPackage & package) +``` -Creates a package installation task for the given pair. +Clears a package archive from the local cache. +| Parameter | Type | Description | +|-----------|------|-------------| +| `package` | `LocalPackage &` | | +--- -#### `public virtual std::string installedPackageVersion(const std::string & id) const` +#### clearCacheFile +```cpp +bool clearCacheFile(const std::string & fileName, bool whiny) +``` +Clears a file from the local cache. -Returns the version number of an installed package. Exceptions will be thrown if the package does not exist, or is not fully installed. +| Parameter | Type | Description | +|-----------|------|-------------| +| `fileName` | `const std::string &` | | +| `whiny` | `bool` | | -#### `public virtual `[`Package::Asset`](#structscy_1_1pacm_1_1Package_1_1Asset)` getLatestInstallableAsset(const `[`PackagePair`](#structscy_1_1pacm_1_1PackagePair)` & pair,const `[`InstallOptions`](#structscy_1_1pacm_1_1InstallOptions)` & options) const` +--- +#### hasCachedFile +```cpp +bool hasCachedFile(Package::Asset & asset) +``` -Returns the best asset to install, or throws a descriptive exception if no updates are available, or if the package is already up-to-date. This method takes version and SDK locks into consideration. +Checks if a package archive exists in the local cache. -#### `public virtual bool hasAvailableUpdates(const `[`PackagePair`](#structscy_1_1pacm_1_1PackagePair)` & pair) const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `asset` | `Package::Asset &` | | +--- +#### isSupportedFileType -Returns true if there are updates available for this package, false otherwise. +```cpp +bool isSupportedFileType(const std::string & fileName) +``` -#### `public void clearCache()` +Checks if the file type is a supported package archive. -File Helper Methods. +| Parameter | Type | Description | +|-----------|------|-------------| +| `fileName` | `const std::string &` | | -Clears all files in the cache directory. +--- -#### `public bool clearPackageCache(`[`LocalPackage`](#structscy_1_1pacm_1_1LocalPackage)` & package)` +#### getCacheFilePath -Clears a package archive from the local cache. +```cpp +std::string getCacheFilePath(const std::string & fileName) +``` +Returns the full path of the cached file if it exists, or an empty path if the file doesn't exist. +| Parameter | Type | Description | +|-----------|------|-------------| +| `fileName` | `const std::string &` | | -#### `public bool clearCacheFile(const std::string & fileName,bool whiny)` - -Clears a file from the local cache. +--- +#### getPackageDataDir +```cpp +std::string getPackageDataDir(const std::string & id) +``` -#### `public bool hasCachedFile(`[`Package::Asset`](#structscy_1_1pacm_1_1Package_1_1Asset)` & asset)` +Returns the package data directory for the given package ID. -Checks if a package archive exists in the local cache. +| Parameter | Type | Description | +|-----------|------|-------------| +| `id` | `const std::string &` | | +--- +#### options -#### `public bool isSupportedFileType(const std::string & fileName)` +```cpp +virtual Options & options() +``` -Checks if the file type is a supported package archive. +Accessors. +--- +#### remotePackages -#### `public std::string getCacheFilePath(const std::string & fileName)` +```cpp +virtual RemotePackageStore & remotePackages() +``` +--- +#### localPackages -Returns the full path of the cached file if it exists, or an empty path if the file doesn't exist. +```cpp +virtual LocalPackageStore & localPackages() +``` -#### `public std::string getPackageDataDir(const std::string & id)` +--- +#### onPackageInstallComplete +```cpp +void onPackageInstallComplete(InstallTask & task) +``` -Returns the package data directory for the given package ID. +Callbacks. -#### `public virtual `[`Options`](#structscy_1_1pacm_1_1PackageManager_1_1Options)` & options()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `task` | `InstallTask &` | | -Accessors. +--- +#### RemotePackageResponse +```cpp +Signal< void(const http::Response &)> RemotePackageResponse +``` -#### `public virtual `[`RemotePackageStore`](#classscy_1_1LiveCollection)` & remotePackages()` +Events. +Signals when the remote package list have been downloaded from the server. +--- +#### PackageUninstalled +```cpp +Signal< void(LocalPackage &)> PackageUninstalled +``` -#### `public virtual `[`LocalPackageStore`](#classscy_1_1LiveCollection)` & localPackages()` +Signals when a package is uninstalled. +--- +#### InstallTaskCreated +```cpp +Signal< void(InstallTask &)> InstallTaskCreated +``` +Signals when an installation task is created, before it is started. -#### `protected mutable std::mutex _mutex` +--- +#### InstallTaskComplete +```cpp +Signal< void(const InstallTask &)> InstallTaskComplete +``` +Signals when a package installation tasks completes, either successfully or in error. +--- -#### `protected `[`LocalPackageStore`](./doc/api-base.md#classscy_1_1LiveCollection)` _localPackages` +#### _mutex +```cpp +std::mutex _mutex +``` +--- +#### _localPackages +```cpp +LocalPackageStore _localPackages +``` -#### `protected `[`RemotePackageStore`](./doc/api-base.md#classscy_1_1LiveCollection)` _remotePackages` +--- +#### _remotePackages +```cpp +RemotePackageStore _remotePackages +``` +--- +#### _tasks -#### `protected InstallTaskPtrVec _tasks` +```cpp +InstallTaskPtrVec _tasks +``` +--- +#### _options +```cpp +Options _options +``` +## Options -#### `protected `[`Options`](./doc/api-pacm.md#structscy_1_1pacm_1_1PackageManager_1_1Options)` _options` +> **Defined in:** `packagemanager.h` +[Package](#structscy_1_1pacm_1_1Package) manager initialization options. +### Members + +| Name | Description | +|------|-------------| +| [`Options`](#group__pacm_1ga5bf57541a7fc15cae0283c80543060fb) | | +| [`endpoint`](#group__pacm_1ga17eaf31ffc1fc663c74715c0861feaa7) | The HTTP server endpoint. | +| [`indexURI`](#group__pacm_1gaeaf07e705ed06b76a6e6da069b06933a) | The HTTP server URI for querying packages JSON. | +| [`httpUsername`](#group__pacm_1ga2d4089adeb8ea1b332289aa912f9670d) | Username for HTTP basic auth. | +| [`httpPassword`](#group__pacm_1gad72b21a0fd0afc7d0afbe79a267977c9) | PAssword for HTTP basic auth. | +| [`httpOAuthToken`](#group__pacm_1ga3ae63176c907fe93eafb52451c55aa5d) | Will be used instead of HTTP basic if provided. | +| [`tempDir`](#group__pacm_1ga9baae9668ea2afb09d479bc4e1622059) | Directory where package files will be downloaded and extracted. | +| [`dataDir`](#group__pacm_1ga2983a9e79dab4c044b56a53c3bec3ba0) | Directory where package manifests will be kept. | +| [`installDir`](#group__pacm_1ga18001156609c5fe9845f4d0c259964ff) | Directory where packages will be installed. | +| [`platform`](#group__pacm_1gaa9e36a87975600551306e8551065414b) | Platform (win32, linux, mac) | +| [`checksumAlgorithm`](#group__pacm_1gaa458d98644fdde252a9562c01028ad47) | Checksum algorithm (MDS/SHA1) | +| [`clearFailedCache`](#group__pacm_1ga791221a28415eff06ee9a162e950e9dd) | This flag tells the package manager weather or not to clear the package cache if installation fails. | + +--- + +#### Options + +```cpp +inline Options(const std::string & root) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `root` | `const std::string &` | | +--- -#### `protected void onPackageInstallComplete(`[`InstallTask`](#classscy_1_1pacm_1_1InstallTask)` & task)` +#### endpoint -Callbacks. +```cpp +std::string endpoint +``` +The HTTP server endpoint. +--- -# struct `scy::pacm::InstallationState` +#### indexURI +```cpp +std::string indexURI ``` -struct scy::pacm::InstallationState - : public scy::State -``` - - - +The HTTP server URI for querying packages JSON. -## Summary +--- - Members | Descriptions ---------------------------------|--------------------------------------------- -`public inline std::string str(unsigned int id) const` | +#### httpUsername -## Members +```cpp +std::string httpUsername +``` -#### `public inline std::string str(unsigned int id) const` +Username for HTTP basic auth. +--- +#### httpPassword +```cpp +std::string httpPassword +``` +PAssword for HTTP basic auth. -# struct `scy::pacm::InstallOptions` +--- +#### httpOAuthToken -[Package](#structscy_1_1pacm_1_1Package) installation options. +```cpp +std::string httpOAuthToken +``` +Will be used instead of HTTP basic if provided. +--- -## Summary +#### tempDir - Members | Descriptions ---------------------------------|--------------------------------------------- -`public std::string version` | If set then the given package version will be installed. -`public std::string sdkVersion` | -`public std::string installDir` | -`public inline InstallOptions()` | +```cpp +std::string tempDir +``` -## Members +Directory where package files will be downloaded and extracted. -#### `public std::string version` +--- -If set then the given package version will be installed. +#### dataDir +```cpp +std::string dataDir +``` +Directory where package manifests will be kept. -#### `public std::string sdkVersion` +--- +#### installDir +```cpp +std::string installDir +``` -If set then the latest package version for given SDK version will be installed. +Directory where packages will be installed. -#### `public std::string installDir` +--- +#### platform +```cpp +std::string platform +``` -Install to the given location, otherwise the manager default `installDir` will be used. +Platform (win32, linux, mac) -#### `public inline InstallOptions()` +--- +#### checksumAlgorithm +```cpp +std::string checksumAlgorithm +``` +Checksum algorithm (MDS/SHA1) +--- -# struct `scy::pacm::LocalPackage` +#### clearFailedCache +```cpp +bool clearFailedCache ``` -struct scy::pacm::LocalPackage - : public scy::pacm::Package -``` +This flag tells the package manager weather or not to clear the package cache if installation fails. +## InstallationState -This class is a JSON representation of an installed local package that exists on the file system. +> **Extends:** `scy::State` +> **Defined in:** `installtask.h` -## Summary +### Members - Members | Descriptions ---------------------------------|--------------------------------------------- -`public LocalPackage()` | -`public LocalPackage(const json::value & src)` | -`public LocalPackage(const `[`RemotePackage`](#structscy_1_1pacm_1_1RemotePackage)` & src)` | -`public virtual ~LocalPackage()` | -`public virtual void setState(const std::string & state)` | -`public virtual void setInstallState(const std::string & state)` | -`public virtual void setInstallDir(const std::string & dir)` | Set's the installation directory for this package. -`public virtual void setInstalledAsset(const `[`Package::Asset`](#structscy_1_1pacm_1_1Package_1_1Asset)` & installedRemoteAsset)` | -`public virtual void setVersion(const std::string & version)` | -`public virtual void setVersionLock(const std::string & version)` | -`public virtual void setSDKVersionLock(const std::string & version)` | -`public virtual std::string version() const` | Returns the installed package version. -`public virtual std::string state() const` | Returns the current state of this package. -`public virtual std::string installState() const` | Returns the installation state of this package. -`public virtual std::string installDir() const` | Returns the installation directory for this package. -`public virtual std::string versionLock() const` | -`public virtual std::string sdkLockedVersion() const` | -`public virtual `[`Asset`](#structscy_1_1pacm_1_1Package_1_1Asset)` asset()` | -`public virtual bool isInstalled() const` | -`public virtual bool isFailed() const` | -`public virtual `[`Manifest`](#structscy_1_1pacm_1_1LocalPackage_1_1Manifest)` manifest()` | Returns the installation manifest. -`public virtual bool verifyInstallManifest(bool allowEmpty)` | -`public virtual std::string getInstalledFilePath(const std::string & fileName,bool whiny)` | -`public virtual json::value & errors()` | -`public virtual void addError(const std::string & message)` | -`public virtual std::string lastError() const` | -`public virtual void clearErrors()` | -`public virtual bool valid() const` | +| Name | Description | +|------|-------------| +| [`Type`](#group__pacm_1ga84f70fa8f6abb28bab6a1c4e15bea7fa) | | +| [`str`](#group__pacm_1gaa40b0c6a943b11ea07aa7464d60804d2) | | -## Members +--- -#### `public LocalPackage()` +#### Type +```cpp +enum Type +``` +| Value | Description | +|-------|-------------| +| `None` | | +| `Downloading` | | +| `Extracting` | | +| `Finalizing` | | +| `Installed` | | +| `Cancelled` | | +| `Failed` | | +--- +#### str -#### `public LocalPackage(const json::value & src)` +```cpp +inline std::string str(unsigned int id) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `id` | `unsigned int` | | +## InstallOptions +> **Defined in:** `installtask.h` +[Package](#structscy_1_1pacm_1_1Package) installation options. -#### `public LocalPackage(const `[`RemotePackage`](#structscy_1_1pacm_1_1RemotePackage)` & src)` +### Members +| Name | Description | +|------|-------------| +| [`InstallOptions`](#group__pacm_1ga948d1e6960c54926cf870ac7e6aef7ab) | | +| [`version`](#group__pacm_1ga9042e51b870e079ca083c96bedf53a49) | If set then the given package version will be installed. | +| [`sdkVersion`](#group__pacm_1ga179a2d6514580071b30f8b4f87b77b3a) | If set then the latest package version for given SDK version will be installed. | +| [`installDir`](#group__pacm_1gaa7c2627c783fa1ef3b919c40c8c51acb) | Install to the given location, otherwise the manager default `installDir` will be used. | +--- -Create the local package from the remote package reference with the following manipulations. 1) Add a local manifest element. 2) Remove asset mirror elements. +#### InstallOptions -#### `public virtual ~LocalPackage()` +```cpp +inline InstallOptions() +``` +--- +#### version +```cpp +std::string version +``` +If set then the given package version will be installed. -#### `public virtual void setState(const std::string & state)` +--- +#### sdkVersion +```cpp +std::string sdkVersion +``` -Set's the overall package state. Possible values are: Installing, Installed, Failed, Uninstalled. If the packages completes while still Installing, this means the package has yet to be finalized. +If set then the latest package version for given SDK version will be installed. -#### `public virtual void setInstallState(const std::string & state)` +--- +#### installDir +```cpp +std::string installDir +``` -Set's the package installation state. See [InstallationState](#structscy_1_1pacm_1_1InstallationState) for possible values. +Install to the given location, otherwise the manager default `installDir` will be used. -#### `public virtual void setInstallDir(const std::string & dir)` +## Package -Set's the installation directory for this package. +> **Extends:** `json::value` +> **Subclasses:** `scy::pacm::LocalPackage`, `scy::pacm::RemotePackage` +> **Defined in:** `package.h` +This class is a JSON representation of an package belonging to the [PackageManager](#classscy_1_1pacm_1_1PackageManager). +### Members -#### `public virtual void setInstalledAsset(const `[`Package::Asset`](#structscy_1_1pacm_1_1Package_1_1Asset)` & installedRemoteAsset)` +| Name | Description | +|------|-------------| +| [`Package`](#group__pacm_1ga2703eff38205e8c4fc502029c6666c31) | | +| [`Package`](#group__pacm_1ga0bb20d604c0310471e51c534350e234b) | | +| [`~Package`](#group__pacm_1ga33db4f8d2056f384b0c9797fa3ae35c0) | | +| [`id`](#group__pacm_1gadf03f04052d025ba84db73312dea23bb) | | +| [`name`](#group__pacm_1ga7fc35ed22e76fe0e4dc8e42ed82e5f3c) | | +| [`type`](#group__pacm_1gaf6e00584f5cc5ed044cd28e55f87ccea) | | +| [`author`](#group__pacm_1gad4b921e4c2f96f90b9762edfec3ad752) | | +| [`description`](#group__pacm_1ga6466be90a103884930f146af5acdc1a2) | | +| [`valid`](#group__pacm_1gab539f78ec4bc6fceb3944dc34936ec6c) | | +| [`print`](#group__pacm_1gaa2fc0fb484ee99c87f2997b3f8a3fe6b) | | +--- +#### Package -Sets the installed asset, once installed. This method also sets the version. +```cpp +Package() +``` -#### `public virtual void setVersion(const std::string & version)` +--- +#### Package +```cpp +Package(const json::value & src) +``` -Sets the current version of the local package. Installation must be complete. +| Parameter | Type | Description | +|-----------|------|-------------| +| `src` | `const json::value &` | | -#### `public virtual void setVersionLock(const std::string & version)` +--- +#### ~Package +```cpp +virtual ~Package() +``` -Locks the package at the given version. Once set this package will not be updated past the given version. Pass an empty string to remove the lock. +--- -#### `public virtual void setSDKVersionLock(const std::string & version)` +#### id +```cpp +virtual std::string id() const +``` +--- -Locks the package at the given SDK version. Once set this package will only update to the most recent version with given SDK version. Pass an empty string to remove the lock. +#### name -#### `public virtual std::string version() const` +```cpp +virtual std::string name() const +``` -Returns the installed package version. +--- +#### type +```cpp +virtual std::string type() const +``` -#### `public virtual std::string state() const` +--- -Returns the current state of this package. +#### author +```cpp +virtual std::string author() const +``` +--- -#### `public virtual std::string installState() const` +#### description -Returns the installation state of this package. +```cpp +virtual std::string description() const +``` +--- +#### valid -#### `public virtual std::string installDir() const` +```cpp +virtual bool valid() const +``` -Returns the installation directory for this package. +--- +#### print +```cpp +virtual void print(std::ostream & ost) const +``` -#### `public virtual std::string versionLock() const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `ost` | `std::ostream &` | | +## Asset +> **Defined in:** `package.h` +This class represents a archived file asset containing files belonging to the parent package. +### Members + +| Name | Description | +|------|-------------| +| [`Asset`](#group__pacm_1ga29d6d991aff1425c826b710f9136f4c8) | | +| [`~Asset`](#group__pacm_1ga9555259d3bcd6750e24f1c5cef5bd441) | | +| [`fileName`](#group__pacm_1ga9a79ee260434ba1b30489d1d6e9dd421) | | +| [`version`](#group__pacm_1ga6f83300447f0b5c1f7c4ec43cba3a5da) | | +| [`sdkVersion`](#group__pacm_1gabed743e99c221cc89bc4531db63b1e38) | | +| [`checksum`](#group__pacm_1gab4c084cccb50ec5c9597cf441cfe5a39) | | +| [`url`](#group__pacm_1gafbad31de39ae32ca71a513142d4b6ded) | | +| [`fileSize`](#group__pacm_1ga6a460e9ddb8c78f258a5ad16f6ef07e6) | | +| [`valid`](#group__pacm_1ga20d7328f063017efa5e8b5221361a51b) | | +| [`print`](#group__pacm_1ga3d847d7913a955228cf0a4600e8e9452) | | +| [`operator=`](#group__pacm_1gae5c60ffe2dd0ff7459182a5ba32ff8f8) | | +| [`operator==`](#group__pacm_1ga11abf75c67f982309036a02d79d3084b) | | +| [`root`](#group__pacm_1ga626d075e5da0403df011551bcbacda82) | | + +--- + +#### Asset + +```cpp +Asset(json::value & src) +``` -#### `public virtual std::string sdkLockedVersion() const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `src` | `json::value &` | | +--- +#### ~Asset +```cpp +virtual ~Asset() +``` +--- -#### `public virtual `[`Asset`](#structscy_1_1pacm_1_1Package_1_1Asset)` asset()` +#### fileName +```cpp +virtual std::string fileName() const +``` +--- -Returns the currently installed asset, if any. If none, the returned asset will be empty(). +#### version -#### `public virtual bool isInstalled() const` +```cpp +virtual std::string version() const +``` +--- +#### sdkVersion -Returns true or false depending on weather or not the package is installed successfully. False if package is in Failed state. +```cpp +virtual std::string sdkVersion() const +``` -#### `public virtual bool isFailed() const` +--- +#### checksum +```cpp +virtual std::string checksum() const +``` +--- +#### url -#### `public virtual `[`Manifest`](#structscy_1_1pacm_1_1LocalPackage_1_1Manifest)` manifest()` +```cpp +virtual std::string url(int index) const +``` -Returns the installation manifest. +| Parameter | Type | Description | +|-----------|------|-------------| +| `index` | `int` | | +--- +#### fileSize -#### `public virtual bool verifyInstallManifest(bool allowEmpty)` +```cpp +virtual int fileSize() const +``` +--- +#### valid +```cpp +virtual bool valid() const +``` +--- -#### `public virtual std::string getInstalledFilePath(const std::string & fileName,bool whiny)` +#### print +```cpp +virtual void print(std::ostream & ost) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `ost` | `std::ostream &` | | -Returns the full full path of the installed file. Thrown an exception if the install directory is unset. +--- -#### `public virtual json::value & errors()` +#### operator= +```cpp +virtual Asset & operator=(const Asset & r) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `r` | `const Asset &` | | +--- +#### operator== -#### `public virtual void addError(const std::string & message)` +```cpp +virtual bool operator==(const Asset & r) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `r` | `const Asset &` | | +--- +#### root +```cpp +json::value & root +``` -#### `public virtual std::string lastError() const` +## Asset +> **Defined in:** `package.h` +This class represents a archived file asset containing files belonging to the parent package. +### Members + +| Name | Description | +|------|-------------| +| [`Asset`](#group__pacm_1ga29d6d991aff1425c826b710f9136f4c8) | | +| [`~Asset`](#group__pacm_1ga9555259d3bcd6750e24f1c5cef5bd441) | | +| [`fileName`](#group__pacm_1ga9a79ee260434ba1b30489d1d6e9dd421) | | +| [`version`](#group__pacm_1ga6f83300447f0b5c1f7c4ec43cba3a5da) | | +| [`sdkVersion`](#group__pacm_1gabed743e99c221cc89bc4531db63b1e38) | | +| [`checksum`](#group__pacm_1gab4c084cccb50ec5c9597cf441cfe5a39) | | +| [`url`](#group__pacm_1gafbad31de39ae32ca71a513142d4b6ded) | | +| [`fileSize`](#group__pacm_1ga6a460e9ddb8c78f258a5ad16f6ef07e6) | | +| [`valid`](#group__pacm_1ga20d7328f063017efa5e8b5221361a51b) | | +| [`print`](#group__pacm_1ga3d847d7913a955228cf0a4600e8e9452) | | +| [`operator=`](#group__pacm_1gae5c60ffe2dd0ff7459182a5ba32ff8f8) | | +| [`operator==`](#group__pacm_1ga11abf75c67f982309036a02d79d3084b) | | +| [`root`](#group__pacm_1ga626d075e5da0403df011551bcbacda82) | | + +--- + +#### Asset + +```cpp +Asset(json::value & src) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `src` | `json::value &` | | -#### `public virtual void clearErrors()` +--- +#### ~Asset +```cpp +virtual ~Asset() +``` +--- +#### fileName -#### `public virtual bool valid() const` +```cpp +virtual std::string fileName() const +``` +--- +#### version +```cpp +virtual std::string version() const +``` +--- -# struct `scy::pacm::Package` +#### sdkVersion +```cpp +virtual std::string sdkVersion() const ``` -struct scy::pacm::Package - : public value -``` +--- +#### checksum -This class is a JSON representation of an package belonging to the [PackageManager](#classscy_1_1pacm_1_1PackageManager). - -## Summary +```cpp +virtual std::string checksum() const +``` - Members | Descriptions ---------------------------------|--------------------------------------------- -`public Package()` | -`public Package(const json::value & src)` | -`public virtual ~Package()` | -`public virtual std::string id() const` | -`public virtual std::string name() const` | -`public virtual std::string type() const` | -`public virtual std::string author() const` | -`public virtual std::string description() const` | -`public virtual bool valid() const` | -`public virtual void print(std::ostream & ost) const` | +--- -## Members +#### url -#### `public Package()` +```cpp +virtual std::string url(int index) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `index` | `int` | | +--- +#### fileSize +```cpp +virtual int fileSize() const +``` -#### `public Package(const json::value & src)` +--- +#### valid +```cpp +virtual bool valid() const +``` +--- +#### print -#### `public virtual ~Package()` +```cpp +virtual void print(std::ostream & ost) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `ost` | `std::ostream &` | | +--- +#### operator= +```cpp +virtual Asset & operator=(const Asset & r) +``` -#### `public virtual std::string id() const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `r` | `const Asset &` | | +--- +#### operator== +```cpp +virtual bool operator==(const Asset & r) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `r` | `const Asset &` | | -#### `public virtual std::string name() const` +--- +#### root +```cpp +json::value & root +``` +## RemotePackage +> **Extends:** `scy::pacm::Package` +> **Defined in:** `package.h` -#### `public virtual std::string type() const` +This class is a JSON representation of an package existing on the remote server that may be downloaded and installed. +### Members +| Name | Description | +|------|-------------| +| [`RemotePackage`](#group__pacm_1gaf64c095ee7ff79f3b3222c1e31e3f9b9) | | +| [`RemotePackage`](#group__pacm_1gaaa4c25d50d5f6c5207e2a66775149eca) | | +| [`~RemotePackage`](#group__pacm_1ga40701168173d0770c14a9ab7cd48c5c6) | | +| [`assets`](#group__pacm_1ga8bc111ca15a6078bae87e00336cb2145) | | +| [`latestAsset`](#group__pacm_1ga78a9d3c1e3023826f3c39f701cbf76cd) | Returns the latest asset for this package. For local packages this is the currently installed version. For remote packages this is the latest available version. Throws an exception if no asset exists. | +| [`assetVersion`](#group__pacm_1ga2aecae77982bef0703bd05e3381a4396) | Returns the latest asset for the given package version. Throws an exception if no asset exists. | +| [`latestSDKAsset`](#group__pacm_1ga43652748df730786052a32cfbc212971) | Returns the latest asset for the given SDK version. This method is for safely installing plug-ins which must be compiled against a specific SDK version. The package JSON must have a "sdk-version" member for this function to work as intended. Throws an exception if no asset exists. | +--- +#### RemotePackage -#### `public virtual std::string author() const` +```cpp +RemotePackage() +``` +--- +#### RemotePackage +```cpp +RemotePackage(const json::value & src) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `src` | `const json::value &` | | -#### `public virtual std::string description() const` +--- +#### ~RemotePackage +```cpp +virtual ~RemotePackage() +``` +--- +#### assets -#### `public virtual bool valid() const` +```cpp +virtual json::value & assets() +``` +--- +#### latestAsset +```cpp +virtual Asset latestAsset() +``` +Returns the latest asset for this package. For local packages this is the currently installed version. For remote packages this is the latest available version. Throws an exception if no asset exists. -#### `public virtual void print(std::ostream & ost) const` +--- +#### assetVersion +```cpp +virtual Asset assetVersion(const std::string & version) +``` +Returns the latest asset for the given package version. Throws an exception if no asset exists. +| Parameter | Type | Description | +|-----------|------|-------------| +| `version` | `const std::string &` | | -# struct `scy::pacm::PackagePair` +--- +#### latestSDKAsset +```cpp +virtual Asset latestSDKAsset(const std::string & version) +``` +Returns the latest asset for the given SDK version. This method is for safely installing plug-ins which must be compiled against a specific SDK version. The package JSON must have a "sdk-version" member for this function to work as intended. Throws an exception if no asset exists. -This class provides pairing of a local and a remote package. +| Parameter | Type | Description | +|-----------|------|-------------| +| `version` | `const std::string &` | | -## Summary +## LocalPackage - Members | Descriptions ---------------------------------|--------------------------------------------- -`public `[`LocalPackage`](./doc/api-pacm.md#structscy_1_1pacm_1_1LocalPackage)` * local` | -`public `[`RemotePackage`](./doc/api-pacm.md#structscy_1_1pacm_1_1RemotePackage)` * remote` | -`public PackagePair(`[`LocalPackage`](#structscy_1_1pacm_1_1LocalPackage)` * local,`[`RemotePackage`](#structscy_1_1pacm_1_1RemotePackage)` * remote)` | -`public virtual bool valid() const` | -`public std::string id() const` | -`public std::string name() const` | -`public std::string type() const` | -`public std::string author() const` | +> **Extends:** `scy::pacm::Package` +> **Defined in:** `package.h` -## Members +This class is a JSON representation of an installed local package that exists on the file system. -#### `public `[`LocalPackage`](./doc/api-pacm.md#structscy_1_1pacm_1_1LocalPackage)` * local` +### Members + +| Name | Description | +|------|-------------| +| [`LocalPackage`](#group__pacm_1ga146358d8ea6e0742af85e8dd1ed3cfbe) | | +| [`LocalPackage`](#group__pacm_1ga36942c874328ff874b5b558d2fc69adb) | | +| [`LocalPackage`](#group__pacm_1ga8d915798d4874783e5f1a93460c8a790) | Create the local package from the remote package reference with the following manipulations. 1) Add a local manifest element. 2) Remove asset mirror elements. | +| [`~LocalPackage`](#group__pacm_1gae753b7b0b571a560586e8f9f5f04c22b) | | +| [`setState`](#group__pacm_1gad38e4481bbac043f2bbcd7dd0cf23c15) | Set's the overall package state. Possible values are: Installing, Installed, Failed, Uninstalled. If the packages completes while still Installing, this means the package has yet to be finalized. | +| [`setInstallState`](#group__pacm_1ga43dfd9e6481e0d3f7e42767024db6051) | Set's the package installation state. See [InstallationState](#structscy_1_1pacm_1_1InstallationState) for possible values. | +| [`setInstallDir`](#group__pacm_1gad2f95cca3661df99a22d600cda6cf73d) | Set's the installation directory for this package. | +| [`setInstalledAsset`](#group__pacm_1ga2d16fefb83a30029394f13655f82999f) | Sets the installed asset, once installed. This method also sets the version. | +| [`setVersion`](#group__pacm_1ga1fe540ab674a6df4f1fe21beba27d0bb) | Sets the current version of the local package. Installation must be complete. | +| [`setVersionLock`](#group__pacm_1ga00f12d1314c1fe28733935ee118574f9) | Locks the package at the given version. Once set this package will not be updated past the given version. Pass an empty string to remove the lock. | +| [`setSDKVersionLock`](#group__pacm_1gadf546ce2b38e0afc4efddbf701fb573f) | Locks the package at the given SDK version. Once set this package will only update to the most recent version with given SDK version. Pass an empty string to remove the lock. | +| [`version`](#group__pacm_1gad30980d365279cfaee755cfe0561a170) | Returns the installed package version. | +| [`state`](#group__pacm_1ga4c5569e8655f1994146458e6f2cb13cf) | Returns the current state of this package. | +| [`installState`](#group__pacm_1ga5d9b98d55946300cd06145855241b13d) | Returns the installation state of this package. | +| [`installDir`](#group__pacm_1ga7f84ea33e777a251e2893a1f69fa31e3) | Returns the installation directory for this package. | +| [`versionLock`](#group__pacm_1ga750d04ba34e63bca0c4c5761f161cea9) | | +| [`sdkLockedVersion`](#group__pacm_1ga0e32d29a0d4c5ac84f85e81393ed003f) | | +| [`asset`](#group__pacm_1ga8bf8741c74d2cc37fa1e6731bebbf37f) | Returns the currently installed asset, if any. If none, the returned asset will be empty(). | +| [`isInstalled`](#group__pacm_1gac915b269b5ee73baf22c81a44a337e9d) | Returns true or false depending on weather or not the package is installed successfully. False if package is in Failed state. | +| [`isFailed`](#group__pacm_1ga7f0274050c627c6a040ff65cb75aa4ec) | | +| [`manifest`](#group__pacm_1ga9ce8a07f05febda5e87b1a2a706af857) | Returns the installation manifest. | +| [`verifyInstallManifest`](#group__pacm_1gaf1a9c2bdd76d940f200c53e6e175a587) | | +| [`getInstalledFilePath`](#group__pacm_1ga9f24a8d655179921947edd97ff2a4395) | Returns the full full path of the installed file. Thrown an exception if the install directory is unset. | +| [`errors`](#group__pacm_1ga068d92ded3a5a7997210227b7ed29e2a) | | +| [`addError`](#group__pacm_1ga359b1844b6d513f8e7daa83ce2eb1467) | | +| [`lastError`](#group__pacm_1gae1e11871cc82282a8ad592ba55fdf121) | | +| [`clearErrors`](#group__pacm_1gafb51214393066dc3a75690fa5fff966e) | | +| [`valid`](#group__pacm_1ga6778e88ac7cb3bdc1fba171e9cfe4e85) | | + +--- + +#### LocalPackage + +```cpp +LocalPackage() +``` +--- +#### LocalPackage -Returns true if there are no possible updates for this package, false otherwise. +```cpp +LocalPackage(const json::value & src) +``` -#### `public `[`RemotePackage`](./doc/api-pacm.md#structscy_1_1pacm_1_1RemotePackage)` * remote` +| Parameter | Type | Description | +|-----------|------|-------------| +| `src` | `const json::value &` | | +--- +#### LocalPackage +```cpp +LocalPackage(const RemotePackage & src) +``` +Create the local package from the remote package reference with the following manipulations. 1) Add a local manifest element. 2) Remove asset mirror elements. -#### `public PackagePair(`[`LocalPackage`](#structscy_1_1pacm_1_1LocalPackage)` * local,`[`RemotePackage`](#structscy_1_1pacm_1_1RemotePackage)` * remote)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `src` | `const RemotePackage &` | | +--- +#### ~LocalPackage +```cpp +virtual ~LocalPackage() +``` +--- -#### `public virtual bool valid() const` +#### setState +```cpp +virtual void setState(const std::string & state) +``` +Set's the overall package state. Possible values are: Installing, Installed, Failed, Uninstalled. If the packages completes while still Installing, this means the package has yet to be finalized. +| Parameter | Type | Description | +|-----------|------|-------------| +| `state` | `const std::string &` | | +--- -#### `public std::string id() const` +#### setInstallState +```cpp +virtual void setInstallState(const std::string & state) +``` +Set's the package installation state. See [InstallationState](#structscy_1_1pacm_1_1InstallationState) for possible values. +| Parameter | Type | Description | +|-----------|------|-------------| +| `state` | `const std::string &` | | +--- -#### `public std::string name() const` +#### setInstallDir +```cpp +virtual void setInstallDir(const std::string & dir) +``` +Set's the installation directory for this package. +| Parameter | Type | Description | +|-----------|------|-------------| +| `dir` | `const std::string &` | | +--- -#### `public std::string type() const` +#### setInstalledAsset +```cpp +virtual void setInstalledAsset(const Package::Asset & installedRemoteAsset) +``` +Sets the installed asset, once installed. This method also sets the version. +| Parameter | Type | Description | +|-----------|------|-------------| +| `installedRemoteAsset` | `const Package::Asset &` | | +--- -#### `public std::string author() const` +#### setVersion +```cpp +virtual void setVersion(const std::string & version) +``` +Sets the current version of the local package. Installation must be complete. +| Parameter | Type | Description | +|-----------|------|-------------| +| `version` | `const std::string &` | | +--- -# struct `scy::pacm::RemotePackage` +#### setVersionLock +```cpp +virtual void setVersionLock(const std::string & version) ``` -struct scy::pacm::RemotePackage - : public scy::pacm::Package -``` +Locks the package at the given version. Once set this package will not be updated past the given version. Pass an empty string to remove the lock. +| Parameter | Type | Description | +|-----------|------|-------------| +| `version` | `const std::string &` | | -This class is a JSON representation of an package existing on the remote server that may be downloaded and installed. +--- -## Summary +#### setSDKVersionLock - Members | Descriptions ---------------------------------|--------------------------------------------- -`public RemotePackage()` | -`public RemotePackage(const json::value & src)` | -`public virtual ~RemotePackage()` | -`public virtual json::value & assets()` | -`public virtual `[`Asset`](#structscy_1_1pacm_1_1Package_1_1Asset)` latestAsset()` | -`public virtual `[`Asset`](#structscy_1_1pacm_1_1Package_1_1Asset)` assetVersion(const std::string & version)` | -`public virtual `[`Asset`](#structscy_1_1pacm_1_1Package_1_1Asset)` latestSDKAsset(const std::string & version)` | +```cpp +virtual void setSDKVersionLock(const std::string & version) +``` -## Members +Locks the package at the given SDK version. Once set this package will only update to the most recent version with given SDK version. Pass an empty string to remove the lock. -#### `public RemotePackage()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `version` | `const std::string &` | | +--- +#### version +```cpp +virtual std::string version() const +``` +Returns the installed package version. -#### `public RemotePackage(const json::value & src)` +--- +#### state +```cpp +virtual std::string state() const +``` +Returns the current state of this package. +--- -#### `public virtual ~RemotePackage()` +#### installState +```cpp +virtual std::string installState() const +``` +Returns the installation state of this package. +--- +#### installDir -#### `public virtual json::value & assets()` +```cpp +virtual std::string installDir() const +``` +Returns the installation directory for this package. +--- +#### versionLock +```cpp +virtual std::string versionLock() const +``` -#### `public virtual `[`Asset`](#structscy_1_1pacm_1_1Package_1_1Asset)` latestAsset()` +--- +#### sdkLockedVersion +```cpp +virtual std::string sdkLockedVersion() const +``` -Returns the latest asset for this package. For local packages this is the currently installed version. For remote packages this is the latest available version. Throws an exception if no asset exists. +--- -#### `public virtual `[`Asset`](#structscy_1_1pacm_1_1Package_1_1Asset)` assetVersion(const std::string & version)` +#### asset +```cpp +virtual Asset asset() +``` +Returns the currently installed asset, if any. If none, the returned asset will be empty(). -Returns the latest asset for the given package version. Throws an exception if no asset exists. +--- -#### `public virtual `[`Asset`](#structscy_1_1pacm_1_1Package_1_1Asset)` latestSDKAsset(const std::string & version)` +#### isInstalled +```cpp +virtual bool isInstalled() const +``` +Returns true or false depending on weather or not the package is installed successfully. False if package is in Failed state. -Returns the latest asset for the given SDK version. This method is for safely installing plug-ins which must be compiled against a specific SDK version. The package JSON must have a "sdk-version" member for this function to work as intended. Throws an exception if no asset exists. +--- -# struct `scy::pacm::Package::Asset` +#### isFailed +```cpp +virtual bool isFailed() const +``` +--- +#### manifest -This class represents a archived file asset containing files belonging to the parent package. +```cpp +virtual Manifest manifest() +``` -## Summary +Returns the installation manifest. - Members | Descriptions ---------------------------------|--------------------------------------------- -`public json::value & root` | -`public Asset(json::value & src)` | -`public virtual ~Asset()` | -`public virtual std::string fileName() const` | -`public virtual std::string version() const` | -`public virtual std::string sdkVersion() const` | -`public virtual std::string checksum() const` | -`public virtual std::string url(int index) const` | -`public virtual int fileSize() const` | -`public virtual bool valid() const` | -`public virtual void print(std::ostream & ost) const` | -`public virtual `[`Asset`](#structscy_1_1pacm_1_1Package_1_1Asset)` & operator=(const `[`Asset`](#structscy_1_1pacm_1_1Package_1_1Asset)` & r)` | -`public virtual bool operator==(const `[`Asset`](#structscy_1_1pacm_1_1Package_1_1Asset)` & r) const` | +--- -## Members +#### verifyInstallManifest -#### `public json::value & root` +```cpp +virtual bool verifyInstallManifest(bool allowEmpty) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `allowEmpty` | `bool` | | +--- +#### getInstalledFilePath +```cpp +virtual std::string getInstalledFilePath(const std::string & fileName, bool whiny) +``` -#### `public Asset(json::value & src)` +Returns the full full path of the installed file. Thrown an exception if the install directory is unset. +| Parameter | Type | Description | +|-----------|------|-------------| +| `fileName` | `const std::string &` | | +| `whiny` | `bool` | | +--- +#### errors +```cpp +virtual json::value & errors() +``` -#### `public virtual ~Asset()` +--- +#### addError +```cpp +virtual void addError(const std::string & message) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `message` | `const std::string &` | | +--- -#### `public virtual std::string fileName() const` +#### lastError +```cpp +virtual std::string lastError() const +``` +--- +#### clearErrors +```cpp +virtual void clearErrors() +``` -#### `public virtual std::string version() const` +--- +#### valid +```cpp +virtual bool valid() const +``` +## Manifest +> **Defined in:** `package.h` -#### `public virtual std::string sdkVersion() const` +This class provides a list of all package files and their location on the file system. +### Members +| Name | Description | +|------|-------------| +| [`Manifest`](#group__pacm_1ga27938a9ecf0a7d28a49a33fbf1cf24b8) | | +| [`~Manifest`](#group__pacm_1ga9d7098ebc7d12fc1dbabd8c2d07aa05b) | | +| [`empty`](#group__pacm_1gaa767187173b460a6ed903ad7b5237b87) | | +| [`addFile`](#group__pacm_1ga46bf1459f6d73eb846287739d0b0c2f2) | | +| [`root`](#group__pacm_1gaac9eb9eb02a577f627687939e65a3af7) | | +--- +#### Manifest -#### `public virtual std::string checksum() const` +```cpp +Manifest(json::value & src) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `src` | `json::value &` | | +--- +#### ~Manifest +```cpp +virtual ~Manifest() +``` -#### `public virtual std::string url(int index) const` +--- +#### empty +```cpp +virtual bool empty() const +``` +--- +#### addFile -#### `public virtual int fileSize() const` +```cpp +virtual void addFile(const std::string & path) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `path` | `const std::string &` | | +--- +#### root +```cpp +json::value & root +``` -#### `public virtual bool valid() const` +## Manifest +> **Defined in:** `package.h` +This class provides a list of all package files and their location on the file system. +### Members +| Name | Description | +|------|-------------| +| [`Manifest`](#group__pacm_1ga27938a9ecf0a7d28a49a33fbf1cf24b8) | | +| [`~Manifest`](#group__pacm_1ga9d7098ebc7d12fc1dbabd8c2d07aa05b) | | +| [`empty`](#group__pacm_1gaa767187173b460a6ed903ad7b5237b87) | | +| [`addFile`](#group__pacm_1ga46bf1459f6d73eb846287739d0b0c2f2) | | +| [`root`](#group__pacm_1gaac9eb9eb02a577f627687939e65a3af7) | | -#### `public virtual void print(std::ostream & ost) const` +--- +#### Manifest +```cpp +Manifest(json::value & src) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `src` | `json::value &` | | +--- -#### `public virtual `[`Asset`](#structscy_1_1pacm_1_1Package_1_1Asset)` & operator=(const `[`Asset`](#structscy_1_1pacm_1_1Package_1_1Asset)` & r)` +#### ~Manifest +```cpp +virtual ~Manifest() +``` +--- +#### empty +```cpp +virtual bool empty() const +``` -#### `public virtual bool operator==(const `[`Asset`](#structscy_1_1pacm_1_1Package_1_1Asset)` & r) const` +--- +#### addFile +```cpp +virtual void addFile(const std::string & path) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `path` | `const std::string &` | | +--- -# struct `scy::pacm::LocalPackage::Manifest` +#### root +```cpp +json::value & root +``` +## PackagePair +> **Defined in:** `package.h` -This class provides a list of all package files and their location on the file system. +This class provides pairing of a local and a remote package. -## Summary +### Members - Members | Descriptions ---------------------------------|--------------------------------------------- -`public json::value & root` | -`public Manifest(json::value & src)` | -`public virtual ~Manifest()` | -`public virtual bool empty() const` | -`public virtual void addFile(const std::string & path)` | +| Name | Description | +|------|-------------| +| [`PackagePair`](#group__pacm_1ga0cfb58ccd49a5bff96f9c148ff7d39ef) | | +| [`valid`](#group__pacm_1gaff5ec132e15164c53c6874e690fb4c6c) | | +| [`id`](#group__pacm_1ga8bf565f8d76464a920733d01c68d9e78) | | +| [`name`](#group__pacm_1ga19214f72c4a06d16587f9ca8d4fc5f9b) | | +| [`type`](#group__pacm_1ga6ea1f67837c2ac9c11b46826b3eb79d6) | | +| [`author`](#group__pacm_1ga53e2b423f63a656def7af02faa7ef00b) | | +| [`local`](#group__pacm_1gadbaaae13eaaf203a08d8321bf0ca9bb0) | Returns true if there are no possible updates for this package, false otherwise. | +| [`remote`](#group__pacm_1ga64dacf8c8eafba27426e2f9a85cbd4b7) | | -## Members +--- -#### `public json::value & root` +#### PackagePair +```cpp +PackagePair(LocalPackage * local, RemotePackage * remote) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `local` | `LocalPackage *` | | +| `remote` | `RemotePackage *` | | +--- +#### valid -#### `public Manifest(json::value & src)` +```cpp +virtual bool valid() const +``` +--- +#### id +```cpp +std::string id() const +``` +--- -#### `public virtual ~Manifest()` +#### name +```cpp +std::string name() const +``` +--- +#### type +```cpp +std::string type() const +``` -#### `public virtual bool empty() const` +--- +#### author +```cpp +std::string author() const +``` +--- +#### local -#### `public virtual void addFile(const std::string & path)` +```cpp +LocalPackage * local +``` +Returns true if there are no possible updates for this package, false otherwise. +--- +#### remote +```cpp +RemotePackage * remote +``` -# struct `scy::pacm::PackageManager::Options` +## Options +> **Defined in:** `packagemanager.h` [Package](#structscy_1_1pacm_1_1Package) manager initialization options. +### Members + +| Name | Description | +|------|-------------| +| [`Options`](#group__pacm_1ga5bf57541a7fc15cae0283c80543060fb) | | +| [`endpoint`](#group__pacm_1ga17eaf31ffc1fc663c74715c0861feaa7) | The HTTP server endpoint. | +| [`indexURI`](#group__pacm_1gaeaf07e705ed06b76a6e6da069b06933a) | The HTTP server URI for querying packages JSON. | +| [`httpUsername`](#group__pacm_1ga2d4089adeb8ea1b332289aa912f9670d) | Username for HTTP basic auth. | +| [`httpPassword`](#group__pacm_1gad72b21a0fd0afc7d0afbe79a267977c9) | PAssword for HTTP basic auth. | +| [`httpOAuthToken`](#group__pacm_1ga3ae63176c907fe93eafb52451c55aa5d) | Will be used instead of HTTP basic if provided. | +| [`tempDir`](#group__pacm_1ga9baae9668ea2afb09d479bc4e1622059) | Directory where package files will be downloaded and extracted. | +| [`dataDir`](#group__pacm_1ga2983a9e79dab4c044b56a53c3bec3ba0) | Directory where package manifests will be kept. | +| [`installDir`](#group__pacm_1ga18001156609c5fe9845f4d0c259964ff) | Directory where packages will be installed. | +| [`platform`](#group__pacm_1gaa9e36a87975600551306e8551065414b) | Platform (win32, linux, mac) | +| [`checksumAlgorithm`](#group__pacm_1gaa458d98644fdde252a9562c01028ad47) | Checksum algorithm (MDS/SHA1) | +| [`clearFailedCache`](#group__pacm_1ga791221a28415eff06ee9a162e950e9dd) | This flag tells the package manager weather or not to clear the package cache if installation fails. | + +--- + +#### Options + +```cpp +inline Options(const std::string & root) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `root` | `const std::string &` | | -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public std::string endpoint` | The HTTP server endpoint. -`public std::string indexURI` | The HTTP server URI for querying packages JSON. -`public std::string httpUsername` | Username for HTTP basic auth. -`public std::string httpPassword` | PAssword for HTTP basic auth. -`public std::string httpOAuthToken` | Will be used instead of HTTP basic if provided. -`public std::string tempDir` | Directory where package files will be downloaded and extracted. -`public std::string dataDir` | Directory where package manifests will be kept. -`public std::string installDir` | Directory where packages will be installed. -`public std::string platform` | Platform (win32, linux, mac) -`public std::string checksumAlgorithm` | Checksum algorithm (MDS/SHA1) -`public bool clearFailedCache` | -`public inline Options(const std::string & root)` | +--- -## Members +#### endpoint -#### `public std::string endpoint` +```cpp +std::string endpoint +``` The HTTP server endpoint. +--- +#### indexURI -#### `public std::string indexURI` +```cpp +std::string indexURI +``` The HTTP server URI for querying packages JSON. +--- +#### httpUsername -#### `public std::string httpUsername` +```cpp +std::string httpUsername +``` Username for HTTP basic auth. +--- +#### httpPassword -#### `public std::string httpPassword` +```cpp +std::string httpPassword +``` PAssword for HTTP basic auth. +--- +#### httpOAuthToken -#### `public std::string httpOAuthToken` +```cpp +std::string httpOAuthToken +``` Will be used instead of HTTP basic if provided. +--- +#### tempDir -#### `public std::string tempDir` +```cpp +std::string tempDir +``` Directory where package files will be downloaded and extracted. +--- +#### dataDir -#### `public std::string dataDir` +```cpp +std::string dataDir +``` Directory where package manifests will be kept. +--- +#### installDir -#### `public std::string installDir` +```cpp +std::string installDir +``` Directory where packages will be installed. +--- +#### platform -#### `public std::string platform` +```cpp +std::string platform +``` Platform (win32, linux, mac) +--- +#### checksumAlgorithm -#### `public std::string checksumAlgorithm` +```cpp +std::string checksumAlgorithm +``` Checksum algorithm (MDS/SHA1) +--- +#### clearFailedCache -#### `public bool clearFailedCache` - - +```cpp +bool clearFailedCache +``` This flag tells the package manager weather or not to clear the package cache if installation fails. -#### `public inline Options(const std::string & root)` - - - - - diff --git a/doc/api-pluga.md b/doc/api-pluga.md index 8855ff2a8..fbf781f6a 100644 --- a/doc/api-pluga.md +++ b/doc/api-pluga.md @@ -1,74 +1,121 @@ -# Module `pluga` +# pluga +### Classes +| Name | Description | +|------|-------------| +| [`PluginDetails`](#structscy_1_1pluga_1_1PluginDetails) | | -## Summary +### Members - Members | Descriptions ---------------------------------|--------------------------------------------- -`namespace `[`scy::pluga`](#namespacescy_1_1pluga) | -# namespace `scy::pluga` +| Name | Description | +|------|-------------| +| [`Pluga_API`](#group__pluga_1ga390f34d988d3289ff511ac63cce92703) | | +| [`SCY_PLUGIN_API_VERSION`](#group__pluga_1gaa553946373327fb5298a3bf8486a448c) | | +| [`SCY_PLUGIN_EXPORT`](#group__pluga_1gaccf69db2d12fbad7474890842ef3c161) | | +| [`SCY_STANDARD_PLUGIN_STUFF`](#group__pluga_1gadbef14fcbc6a69b0cfe4406b65d8d32f) | | +| [`SCY_PLUGIN`](#group__pluga_1ga7074bc5a4704c34c0fd03c6ce5fb7dc2) | | +--- +#### Pluga_API -## Summary +```cpp +Pluga_API() +``` - Members | Descriptions ---------------------------------|--------------------------------------------- -`struct `[`scy::pluga::PluginDetails`](#structscy_1_1pluga_1_1PluginDetails) | -# struct `scy::pluga::PluginDetails` +--- +#### SCY_PLUGIN_API_VERSION +```cpp +SCY_PLUGIN_API_VERSION() +``` +--- +#### SCY_PLUGIN_EXPORT +```cpp +SCY_PLUGIN_EXPORT() +``` -## Summary +--- - Members | Descriptions ---------------------------------|--------------------------------------------- -`public int apiVersion` | -`public const char * fileName` | -`public const char * className` | -`public const char * pluginName` | -`public const char * pluginVersion` | -`public GetPluginFunc initializeFunc` | +#### SCY_STANDARD_PLUGIN_STUFF -## Members +```cpp +SCY_STANDARD_PLUGIN_STUFF() +``` -#### `public int apiVersion` +--- +#### SCY_PLUGIN +```cpp +SCY_PLUGIN() +``` +## PluginDetails +> **Defined in:** `pluga.h` -#### `public const char * fileName` +### Members +| Name | Description | +|------|-------------| +| [`apiVersion`](#group__pluga_1gaa152231bbe6f4dae3e74fcf944f2db5f) | | +| [`fileName`](#group__pluga_1ga7473a1532e31c59df31d2c9c313ba97d) | | +| [`className`](#group__pluga_1gaca5799f105a66aa2fddca468d453c474) | | +| [`pluginName`](#group__pluga_1ga23acb9cdbd0c3c48f97d674c102c3b49) | | +| [`pluginVersion`](#group__pluga_1gab2c00481c44ee4ad0bdaf9f4ed29ec0a) | | +| [`initializeFunc`](#group__pluga_1ga4b440d4ad60d7585fd3504601400c1ee) | | +--- +#### apiVersion +```cpp +int apiVersion +``` -#### `public const char * className` +--- +#### fileName +```cpp +const char * fileName +``` +--- +#### className -#### `public const char * pluginName` +```cpp +const char * className +``` +--- +#### pluginName +```cpp +const char * pluginName +``` +--- -#### `public const char * pluginVersion` - - - - - -#### `public GetPluginFunc initializeFunc` +#### pluginVersion +```cpp +const char * pluginVersion +``` +--- +#### initializeFunc +```cpp +GetPluginFunc initializeFunc +``` diff --git a/doc/api-sched.md b/doc/api-sched.md index a4f6dae6a..dbf869a3a 100644 --- a/doc/api-sched.md +++ b/doc/api-sched.md @@ -1,631 +1,920 @@ -# Module `sched` +# sched +### Classes +| Name | Description | +|------|-------------| +| [`Scheduler`](#classscy_1_1sched_1_1Scheduler) | The [Scheduler](#classscy_1_1sched_1_1Scheduler) manages and runs tasks that need to be executed at specific times. | +| [`Task`](#classscy_1_1sched_1_1Task) | This class extends the [Task](#classscy_1_1sched_1_1Task) class to implement scheduling capabilities. | +| [`TaskFactory`](#classscy_1_1sched_1_1TaskFactory) | The [TaskFactory](#classscy_1_1sched_1_1TaskFactory) can dynamically instantiate registered [sched::Task](#classscy_1_1sched_1_1Task) and [sched::Trigger](#structscy_1_1sched_1_1Trigger) classes from named strings. | +| [`Trigger`](#structscy_1_1sched_1_1Trigger) | | +| [`OnceOnlyTrigger`](#structscy_1_1sched_1_1OnceOnlyTrigger) | | +| [`IntervalTrigger`](#structscy_1_1sched_1_1IntervalTrigger) | | +| [`DailyTrigger`](#structscy_1_1sched_1_1DailyTrigger) | | -## Summary +### Members - Members | Descriptions ---------------------------------|--------------------------------------------- -`namespace `[`scy::sched`](#namespacescy_1_1sched) | -# namespace `scy::sched` +| Name | Description | +|------|-------------| +| [`Sched_API`](#group__sched_1ga4441e9df8956fd926aec04e6f1492ac9) | | +--- +#### Sched_API -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`class `[`scy::sched::Scheduler`](#classscy_1_1sched_1_1Scheduler) | -`class `[`scy::sched::Task`](#classscy_1_1sched_1_1Task) | -`class `[`scy::sched::TaskFactory`](#classscy_1_1sched_1_1TaskFactory) | -`struct `[`scy::sched::DailyTrigger`](#structscy_1_1sched_1_1DailyTrigger) | -`struct `[`scy::sched::IntervalTrigger`](#structscy_1_1sched_1_1IntervalTrigger) | -`struct `[`scy::sched::OnceOnlyTrigger`](#structscy_1_1sched_1_1OnceOnlyTrigger) | -`struct `[`scy::sched::Trigger`](#structscy_1_1sched_1_1Trigger) | -# class `scy::sched::Scheduler` - +```cpp +Sched_API() ``` -class scy::sched::Scheduler - : public scy::TaskRunner - : public scy::json::ISerializable -``` +## Scheduler +> **Extends:** `scy::TaskRunner`, `scy::json::ISerializable` +> **Defined in:** `scheduler.h` The [Scheduler](#classscy_1_1sched_1_1Scheduler) manages and runs tasks that need to be executed at specific times. -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public Scheduler()` | -`public virtual ~Scheduler()` | -`public virtual void schedule(`[`sched::Task`](#classscy_1_1sched_1_1Task)` * task)` | -`public virtual void cancel(`[`sched::Task`](#classscy_1_1sched_1_1Task)` * task)` | -`public virtual void clear()` | Destroys and clears all manages tasks. -`public virtual void serialize(json::value & root)` | -`public virtual void deserialize(json::value & root)` | -`public virtual void print(std::ostream & ost)` | -`protected virtual void run()` | Called by the async context to run the next task. -`protected virtual void update()` | - -## Members - -#### `public Scheduler()` - - - - - -#### `public virtual ~Scheduler()` - +### Members + +| Name | Description | +|------|-------------| +| [`Scheduler`](#group__sched_1ga2c5d8bd2230a1f7bf4f073f28110d936) | | +| [`~Scheduler`](#group__sched_1ga4a1c46d3daf229f48641fe62d73b3d8f) | | +| [`schedule`](#group__sched_1gab33387aa6f9c21d61dbd9ed75da33112) | | +| [`cancel`](#group__sched_1ga6dd66192cc1d853e8aea46206f9deeb0) | | +| [`clear`](#group__sched_1gad1100d94ca6a33a5cd7e12ec4b414ebb) | Destroys and clears all manages tasks. | +| [`serialize`](#group__sched_1ga4c35dfb97b425dfe52b7d0423b6e1c32) | | +| [`deserialize`](#group__sched_1ga7fbf9c5bdc302b447f5dfecb4d1e4f01) | | +| [`print`](#group__sched_1gace1e075e5d80427459eb6a9f431d82c7) | | +| [`getDefault`](#group__sched_1ga69f78c44f8ca4f6c98de61beb8f509d3) | Returns the default [Scheduler](#classscy_1_1sched_1_1Scheduler) singleton, although [Scheduler](#classscy_1_1sched_1_1Scheduler) instances may also be initialized individually. | +| [`factory`](#group__sched_1gaebe718c34d043b8995e5cde73d637f6b) | Returns the [TaskFactory](#classscy_1_1sched_1_1TaskFactory) singleton. | +| [`run`](#group__sched_1gae90f548144a297df629384b7c19753af) | Called by the async context to run the next task. | +| [`update`](#group__sched_1ga59ae89e12b6fc6cc7d4d3acf9aeb5138) | | + +--- + +#### Scheduler + +```cpp +Scheduler() +``` +--- +#### ~Scheduler +```cpp +virtual ~Scheduler() +``` -#### `public virtual void schedule(`[`sched::Task`](#classscy_1_1sched_1_1Task)` * task)` +--- +#### schedule +```cpp +virtual void schedule(sched::Task * task) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `task` | `sched::Task *` | | +--- -#### `public virtual void cancel(`[`sched::Task`](#classscy_1_1sched_1_1Task)` * task)` +#### cancel +```cpp +virtual void cancel(sched::Task * task) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `task` | `sched::Task *` | | +--- +#### clear -#### `public virtual void clear()` +```cpp +virtual void clear() +``` Destroys and clears all manages tasks. +--- +#### serialize -#### `public virtual void serialize(json::value & root)` - +```cpp +virtual void serialize(json::value & root) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `root` | `json::value &` | | +--- +#### deserialize -#### `public virtual void deserialize(json::value & root)` +```cpp +virtual void deserialize(json::value & root) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `root` | `json::value &` | | +--- +#### print +```cpp +virtual void print(std::ostream & ost) +``` -#### `public virtual void print(std::ostream & ost)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `ost` | `std::ostream &` | | +--- +#### getDefault +```cpp +static Scheduler & getDefault() +``` +Returns the default [Scheduler](#classscy_1_1sched_1_1Scheduler) singleton, although [Scheduler](#classscy_1_1sched_1_1Scheduler) instances may also be initialized individually. -#### `protected virtual void run()` +--- -Called by the async context to run the next task. +#### factory +```cpp +static sched::TaskFactory & factory() +``` +Returns the [TaskFactory](#classscy_1_1sched_1_1TaskFactory) singleton. -#### `protected virtual void update()` +--- +#### run +```cpp +virtual void run() +``` +Called by the async context to run the next task. +--- -# class `scy::sched::Task` +#### update +```cpp +virtual void update() ``` -class scy::sched::Task - : public scy::Task - : public scy::json::ISerializable -``` +## Task +> **Extends:** `scy::Task`, `scy::json::ISerializable` +> **Defined in:** `task.h` This class extends the [Task](#classscy_1_1sched_1_1Task) class to implement scheduling capabilities. -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public Task(const std::string & type,const std::string & name)` | -`public Task(`[`Scheduler`](#classscy_1_1sched_1_1Scheduler)` & scheduler,const std::string & type,const std::string & name)` | -`public virtual void serialize(json::value & root)` | Serializes the task to JSON. -`public virtual void deserialize(json::value & root)` | Deserializes the task from JSON. -`public template`
`inline T * createTrigger()` | -`public void setTrigger(`[`sched::Trigger`](#structscy_1_1sched_1_1Trigger)` * trigger)` | -`public `[`sched::Trigger`](#structscy_1_1sched_1_1Trigger)` & trigger()` | -`public `[`Scheduler`](#classscy_1_1sched_1_1Scheduler)` & scheduler()` | -`public std::int64_t remaining() const` | -`public std::string type() const` | -`public std::string name() const` | -`public void setName(const std::string & name)` | -`protected std::string _type` | -`protected std::string _name` | -`protected `[`sched::Scheduler`](./doc/api-sched.md#classscy_1_1sched_1_1Scheduler)` * _scheduler` | -`protected `[`sched::Trigger`](./doc/api-sched.md#structscy_1_1sched_1_1Trigger)` * _trigger` | -`protected mutable std::mutex _mutex` | -`protected virtual ~Task()` | -`protected virtual bool beforeRun()` | -`protected void run()` | -`protected virtual bool afterRun()` | - -## Members - -#### `public Task(const std::string & type,const std::string & name)` - - +### Members + +| Name | Description | +|------|-------------| +| [`Task`](#group__sched_1gada7aa3c08477dd31f77a15d9ab7ada69) | | +| [`Task`](#group__sched_1ga18514602a261599745e9d632a9298639) | | +| [`serialize`](#group__sched_1gad18e09c30fab7855d8c3c54f5e1430bb) | Serializes the task to JSON. | +| [`deserialize`](#group__sched_1gaf213bcf307f7831a73a53e20f2973ff0) | Deserializes the task from JSON. | +| [`createTrigger`](#group__sched_1ga5ccc658ea51817c922302024f1716d0c) | | +| [`setTrigger`](#group__sched_1ga750447b4c974d32fa66e6bf382968364) | | +| [`trigger`](#group__sched_1gaeca4e399907b97a311542cf3f6c02ac5) | Returns a reference to the associated [sched::Trigger](#structscy_1_1sched_1_1Trigger) or throws an exception. | +| [`scheduler`](#group__sched_1ga194bdc6aa8624503a044fe24e1b1ed34) | Returns a reference to the associated [Scheduler](#classscy_1_1sched_1_1Scheduler) or throws an exception. | +| [`remaining`](#group__sched_1ga5c18d3c47370a09baaff18b12ecb6779) | Returns the milliseconds remaining until the next scheduled timeout. An [sched::Trigger](#structscy_1_1sched_1_1Trigger) must be associated or an exception will be thrown. | +| [`type`](#group__sched_1gab2487a3713a57261b71454c05621dbcd) | | +| [`name`](#group__sched_1gadfe739e111da7d1d090c88de52da1767) | | +| [`setName`](#group__sched_1gaf82f66d275ae0a0b750c3ef3b8785093) | | +| [`~Task`](#group__sched_1ga92fdc84e904656f4e38cdc7acd8d6053) | Destroctor. Should remain protected. | +| [`beforeRun`](#group__sched_1gabcf93ea5a1c4c307524ce3711434ee39) | | +| [`run`](#group__sched_1ga3d2d7a26a59ef58967926367d6ba484a) | Called by the [TaskRunner](./doc/api-base.md#classscy_1_1TaskRunner) to run the task. Override this method to implement task action. Returning true means the true should be called again, and false will cause the task to be destroyed. The task will similarly be destroyed id [destroy()](./doc/api-base.md#group__base_1gaecd8a85018f8f75ae802dcbf3749bdef) was called during the current task iteration. | +| [`afterRun`](#group__sched_1gae7f7a8c0ead6727644d3aa045b0c25df) | | +| [`CompareTimeout`](#group__sched_1gaa91e1e6bcae34a4975f8ab33dd050373) | | +| [`_type`](#group__sched_1gac28fe32991a883c1b00a6b56bc555c35) | | +| [`_name`](#group__sched_1ga5c053d1a5d387b942e8cb55a9bfc2fac) | | +| [`_scheduler`](#group__sched_1ga1fe5675a303013606d55d54b79700557) | | +| [`_trigger`](#group__sched_1ga6627c1994358922d5dc892df16d7ab6e) | | +| [`_mutex`](#group__sched_1ga1233679a60cc60f163e2e63988701747) | | + +--- + +#### Task + +```cpp +Task(const std::string & type, const std::string & name) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `type` | `const std::string &` | | +| `name` | `const std::string &` | | +--- -#### `public Task(`[`Scheduler`](#classscy_1_1sched_1_1Scheduler)` & scheduler,const std::string & type,const std::string & name)` +#### Task +```cpp +Task(Scheduler & scheduler, const std::string & type, const std::string & name) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `scheduler` | `Scheduler &` | | +| `type` | `const std::string &` | | +| `name` | `const std::string &` | | +--- +#### serialize -#### `public virtual void serialize(json::value & root)` +```cpp +virtual void serialize(json::value & root) +``` Serializes the task to JSON. +| Parameter | Type | Description | +|-----------|------|-------------| +| `root` | `json::value &` | | +--- -#### `public virtual void deserialize(json::value & root)` - -Deserializes the task from JSON. - - +#### deserialize -#### `public template`
`inline T * createTrigger()` +```cpp +virtual void deserialize(json::value & root) +``` +Deserializes the task from JSON. +| Parameter | Type | Description | +|-----------|------|-------------| +| `root` | `json::value &` | | +--- +#### createTrigger -#### `public void setTrigger(`[`sched::Trigger`](#structscy_1_1sched_1_1Trigger)` * trigger)` +```cpp +template inline T * createTrigger() +``` +--- +#### setTrigger +```cpp +void setTrigger(sched::Trigger * trigger) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `trigger` | `sched::Trigger *` | | -#### `public `[`sched::Trigger`](#structscy_1_1sched_1_1Trigger)` & trigger()` +--- +#### trigger +```cpp +sched::Trigger & trigger() +``` Returns a reference to the associated [sched::Trigger](#structscy_1_1sched_1_1Trigger) or throws an exception. -#### `public `[`Scheduler`](#classscy_1_1sched_1_1Scheduler)` & scheduler()` +--- +#### scheduler +```cpp +Scheduler & scheduler() +``` Returns a reference to the associated [Scheduler](#classscy_1_1sched_1_1Scheduler) or throws an exception. -#### `public std::int64_t remaining() const` +--- +#### remaining +```cpp +std::int64_t remaining() const +``` Returns the milliseconds remaining until the next scheduled timeout. An [sched::Trigger](#structscy_1_1sched_1_1Trigger) must be associated or an exception will be thrown. -#### `public std::string type() const` - - - - - -#### `public std::string name() const` - - - - - -#### `public void setName(const std::string & name)` - - - - - -#### `protected std::string _type` - - +--- +#### type +```cpp +std::string type() const +``` -#### `protected std::string _name` +--- +#### name +```cpp +std::string name() const +``` +--- +#### setName -#### `protected `[`sched::Scheduler`](./doc/api-sched.md#classscy_1_1sched_1_1Scheduler)` * _scheduler` +```cpp +void setName(const std::string & name) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | +--- +#### ~Task +```cpp +virtual ~Task() +``` -#### `protected `[`sched::Trigger`](./doc/api-sched.md#structscy_1_1sched_1_1Trigger)` * _trigger` +Destroctor. Should remain protected. +--- +#### beforeRun +```cpp +virtual bool beforeRun() +``` +--- -#### `protected mutable std::mutex _mutex` +#### run +```cpp +void run() +``` +Called by the [TaskRunner](./doc/api-base.md#classscy_1_1TaskRunner) to run the task. Override this method to implement task action. Returning true means the true should be called again, and false will cause the task to be destroyed. The task will similarly be destroyed id [destroy()](./doc/api-base.md#group__base_1gaecd8a85018f8f75ae802dcbf3749bdef) was called during the current task iteration. +--- +#### afterRun -#### `protected virtual ~Task()` +```cpp +virtual bool afterRun() +``` +--- +#### CompareTimeout -Destroctor. Should remain protected. +```cpp +static inline bool CompareTimeout(const [scy::Task](./doc/api-base.md#classscy_1_1Task) * l, const [scy::Task](./doc/api-base.md#classscy_1_1Task) * r) +``` -#### `protected virtual bool beforeRun()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `l` | `const [scy::Task](./doc/api-base.md#classscy_1_1Task) *` | | +| `r` | `const [scy::Task](./doc/api-base.md#classscy_1_1Task) *` | | +--- +#### _type +```cpp +std::string _type +``` +--- -#### `protected void run()` +#### _name +```cpp +std::string _name +``` +--- -Called by the [TaskRunner](#classscy_1_1TaskRunner) to run the task. Override this method to implement task action. Returning true means the true should be called again, and false will cause the task to be destroyed. The task will similarly be destroyed id [destroy()](#group__base_1gaecd8a85018f8f75ae802dcbf3749bdef) was called during the current task iteration. +#### _scheduler -#### `protected virtual bool afterRun()` +```cpp +sched::Scheduler * _scheduler +``` +--- +#### _trigger +```cpp +sched::Trigger * _trigger +``` +--- -# class `scy::sched::TaskFactory` +#### _mutex +```cpp +std::mutex _mutex +``` +## TaskFactory +> **Defined in:** `taskfactory.h` The [TaskFactory](#classscy_1_1sched_1_1TaskFactory) can dynamically instantiate registered [sched::Task](#classscy_1_1sched_1_1Task) and [sched::Trigger](#structscy_1_1sched_1_1Trigger) classes from named strings. -## Summary +### Members + +| Name | Description | +|------|-------------| +| [`getDefault`](#group__sched_1ga09f76779885d97c4e99bf27c349909d1) | Returns the default [TaskFactory](#classscy_1_1sched_1_1TaskFactory) singleton. | +| [`createTask`](#group__sched_1gafa680c1c63b36eaa94986f3548ec301b) | | +| [`registerTask`](#group__sched_1ga3b265588e84942014d4d8ed689d71b2d) | | +| [`unregisterTask`](#group__sched_1ga16d6fa9512bcf4e4b3deb0f1f6807286) | | +| [`tasks`](#group__sched_1ga41531034b6b18d3a04b04279fe69f587) | | +| [`createTrigger`](#group__sched_1ga71080ec4924c904a67c07cb872654e99) | | +| [`registerTrigger`](#group__sched_1ga1cd0703715177bfc010ac24975120e9b) | | +| [`unregisterTrigger`](#group__sched_1gac05f05edd58089bd2fd37031dd3a2785) | | +| [`triggers`](#group__sched_1ga4c9f42c5dd1ae286d5d4c1e515740e50) | | +| [`_mutex`](#group__sched_1gad8e95336c38e4f191d7f27975a8543a4) | | +| [`_tasks`](#group__sched_1ga852d826a6712845f19aafa5d5588c4fc) | | +| [`_triggers`](#group__sched_1gaa63f76a92ad76b48cea935bda6ac7535) | | + +--- + +#### getDefault + +```cpp +static inline TaskFactory & getDefault() +``` - Members | Descriptions ---------------------------------|--------------------------------------------- -`public inline `[`sched::Task`](#classscy_1_1sched_1_1Task)` * createTask(const std::string & type)` | -`public template`
`inline void registerTask(const std::string & type)` | -`public inline void unregisterTask(const std::string & type)` | -`public inline `[`TaskMap`](#group__sched_1ga28cc2ed06a4154af8aa404b2ceee967e)` tasks() const` | -`public inline `[`sched::Trigger`](#structscy_1_1sched_1_1Trigger)` * createTrigger(const std::string & type)` | -`public template`
`inline void registerTrigger(const std::string & type)` | -`public inline void unregisterTrigger(const std::string & type)` | -`public inline TriggerMap triggers() const` | -`protected mutable std::mutex _mutex` | -`protected `[`TaskMap`](#group__sched_1ga28cc2ed06a4154af8aa404b2ceee967e)` _tasks` | -`protected TriggerMap _triggers` | +Returns the default [TaskFactory](#classscy_1_1sched_1_1TaskFactory) singleton. -## Members +--- -#### `public inline `[`sched::Task`](#classscy_1_1sched_1_1Task)` * createTask(const std::string & type)` +#### createTask +```cpp +inline sched::Task * createTask(const std::string & type) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `type` | `const std::string &` | | +--- +#### registerTask -#### `public template`
`inline void registerTask(const std::string & type)` +```cpp +template inline void registerTask(const std::string & type) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `type` | `const std::string &` | | +--- +#### unregisterTask +```cpp +inline void unregisterTask(const std::string & type) +``` -#### `public inline void unregisterTask(const std::string & type)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `type` | `const std::string &` | | +--- +#### tasks +```cpp +inline TaskMap tasks() const +``` +--- -#### `public inline `[`TaskMap`](#group__sched_1ga28cc2ed06a4154af8aa404b2ceee967e)` tasks() const` +#### createTrigger +```cpp +inline sched::Trigger * createTrigger(const std::string & type) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `type` | `const std::string &` | | +--- +#### registerTrigger -#### `public inline `[`sched::Trigger`](#structscy_1_1sched_1_1Trigger)` * createTrigger(const std::string & type)` +```cpp +template inline void registerTrigger(const std::string & type) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `type` | `const std::string &` | | +--- +#### unregisterTrigger +```cpp +inline void unregisterTrigger(const std::string & type) +``` -#### `public template`
`inline void registerTrigger(const std::string & type)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `type` | `const std::string &` | | +--- +#### triggers +```cpp +inline TriggerMap triggers() const +``` +--- -#### `public inline void unregisterTrigger(const std::string & type)` +#### _mutex +```cpp +std::mutex _mutex +``` +--- +#### _tasks +```cpp +TaskMap _tasks +``` -#### `public inline TriggerMap triggers() const` +--- +#### _triggers +```cpp +TriggerMap _triggers +``` +## Trigger +> **Extends:** `scy::json::ISerializable` +> **Subclasses:** `scy::sched::DailyTrigger`, `scy::sched::IntervalTrigger`, `scy::sched::OnceOnlyTrigger` +> **Defined in:** `trigger.h` -#### `protected mutable std::mutex _mutex` +### Members +| Name | Description | +|------|-------------| +| [`Trigger`](#group__sched_1ga1d108947ea17eb1787d2bbd9305dda59) | | +| [`update`](#group__sched_1ga5deb765be5af1396d7cdfb2904c426d8) | Updates the scheduleAt value to the next scheduled time. | +| [`remaining`](#group__sched_1gaaab35f447a018bbda0742b5bd9992f71) | Returns the milliseconds remaining until the next scheduled timeout. | +| [`timeout`](#group__sched_1gaa20be8a2498f10c86bdb7bf87b39cb70) | Returns true if the task is ready to be run, false otherwise. | +| [`expired`](#group__sched_1ga6085d6dc573d7034cbf55f70749f6e73) | Returns true if the task is expired and should be destroyed. Returns false by default. | +| [`serialize`](#group__sched_1ga78f847987a4e72cd79e5ec95d999725f) | | +| [`deserialize`](#group__sched_1ga756cab4a32e06179aa19a6eff84a473a) | | +| [`type`](#group__sched_1ga80dbc210eee2539299264057d881959a) | The type of this trigger class. | +| [`name`](#group__sched_1ga3e24e172d92dc417863569d8b95323d9) | The display name of this trigger class. | +| [`timesRun`](#group__sched_1ga16517ce07a40cd2e66fd8065fa998b7b) | The number of times the task has run since creation; | +| [`createdAt`](#group__sched_1ga36015f8af492436ca74de13d7a43ce79) | The time the task was created. | +| [`scheduleAt`](#group__sched_1ga6435f36f242fb144219d7b05600a4e1c) | The time the task is scheduled to run. | +| [`lastRunAt`](#group__sched_1ga9ed36dda7c8943d3644e295774a9a213) | The time the task was last run. | +--- +#### Trigger +```cpp +Trigger(const std::string & type, const std::string & name) +``` -#### `protected `[`TaskMap`](#group__sched_1ga28cc2ed06a4154af8aa404b2ceee967e)` _tasks` +| Parameter | Type | Description | +|-----------|------|-------------| +| `type` | `const std::string &` | | +| `name` | `const std::string &` | | +--- +#### update +```cpp +void update() +``` +Updates the scheduleAt value to the next scheduled time. -#### `protected TriggerMap _triggers` +--- +#### remaining +```cpp +virtual std::int64_t remaining() +``` +Returns the milliseconds remaining until the next scheduled timeout. +--- -# struct `scy::sched::DailyTrigger` +#### timeout +```cpp +virtual bool timeout() ``` -struct scy::sched::DailyTrigger - : public scy::sched::Trigger -``` - - +Returns true if the task is ready to be run, false otherwise. +--- -## Summary +#### expired - Members | Descriptions ---------------------------------|--------------------------------------------- -`public `[`DateTime`](./doc/api-base.md#classscy_1_1DateTime)` timeOfDay` | -`public std::vector< `[`DaysOfTheWeek`](#group__sched_1ga215a79a96d62b633ae6a1996fa93dcfe)` > daysExcluded` | -`public DailyTrigger()` | -`public virtual void update()` | +```cpp +virtual bool expired() +``` -## Members +Returns true if the task is expired and should be destroyed. Returns false by default. -#### `public `[`DateTime`](./doc/api-base.md#classscy_1_1DateTime)` timeOfDay` +--- +#### serialize +```cpp +virtual void serialize(json::value & root) +``` -This value represents the time of day the task will trigger. The date part of the timestamp is redundant. +| Parameter | Type | Description | +|-----------|------|-------------| +| `root` | `json::value &` | | -#### `public std::vector< `[`DaysOfTheWeek`](#group__sched_1ga215a79a96d62b633ae6a1996fa93dcfe)` > daysExcluded` +--- +#### deserialize +```cpp +virtual void deserialize(json::value & root) +``` -Days of the week can be excluded by adding the appropriate bit flag here. +| Parameter | Type | Description | +|-----------|------|-------------| +| `root` | `json::value &` | | -#### `public DailyTrigger()` +--- +#### type +```cpp +std::string type +``` +The type of this trigger class. +--- -#### `public virtual void update()` +#### name +```cpp +std::string name +``` +The display name of this trigger class. -Updates the scheduleAt value to the next scheduled time. +--- -# struct `scy::sched::IntervalTrigger` +#### timesRun +```cpp +int timesRun ``` -struct scy::sched::IntervalTrigger - : public scy::sched::Trigger -``` +The number of times the task has run since creation; +--- +#### createdAt +```cpp +DateTime createdAt +``` -## Summary +The time the task was created. - Members | Descriptions ---------------------------------|--------------------------------------------- -`public `[`Timespan`](./doc/api-base.md#classscy_1_1Timespan)` interval` | -`public int maxTimes` | -`public IntervalTrigger()` | -`public virtual void update()` | -`public virtual bool expired()` | -`public virtual void serialize(json::value & root)` | -`public virtual void deserialize(json::value & root)` | +--- -## Members +#### scheduleAt -#### `public `[`Timespan`](./doc/api-base.md#classscy_1_1Timespan)` interval` +```cpp +DateTime scheduleAt +``` +The time the task is scheduled to run. +--- -This value represents the interval to wait before running the task. +#### lastRunAt -#### `public int maxTimes` +```cpp +DateTime lastRunAt +``` +The time the task was last run. +## OnceOnlyTrigger -The maximum number of times the task will be run before it is destroyed. 0 for no effect. +> **Extends:** `scy::sched::Trigger` +> **Defined in:** `trigger.h` -#### `public IntervalTrigger()` +### Members +| Name | Description | +|------|-------------| +| [`OnceOnlyTrigger`](#group__sched_1ga134b95cccf5189e5e707b55437835436) | | +| [`update`](#group__sched_1ga0a1482f3273f7ac2ad93cd587d470d8a) | Updates the scheduleAt value to the next scheduled time. | +| [`expired`](#group__sched_1ga6c7f09ec6a53ba5603e1f8694fef7b1e) | Returns true if the task is expired and should be destroyed. Returns false by default. | +--- +#### OnceOnlyTrigger +```cpp +OnceOnlyTrigger() +``` -#### `public virtual void update()` +--- +#### update +```cpp +virtual inline void update() +``` Updates the scheduleAt value to the next scheduled time. -#### `public virtual bool expired()` +--- +#### expired +```cpp +virtual bool expired() +``` Returns true if the task is expired and should be destroyed. Returns false by default. -#### `public virtual void serialize(json::value & root)` +## IntervalTrigger +> **Extends:** `scy::sched::Trigger` +> **Defined in:** `trigger.h` +### Members +| Name | Description | +|------|-------------| +| [`IntervalTrigger`](#group__sched_1gad32ce801f384e0a4a4a4e19acfe3a34c) | | +| [`update`](#group__sched_1gaa0b8bbfe4eae4fe43dab985d5c248f76) | Updates the scheduleAt value to the next scheduled time. | +| [`expired`](#group__sched_1ga203c0a6cc5ccc67d29912187a8d5b6be) | Returns true if the task is expired and should be destroyed. Returns false by default. | +| [`serialize`](#group__sched_1ga902a0eb64586b66d47fa77d41a2a3925) | | +| [`deserialize`](#group__sched_1ga3ff1dce27e772257407c6dfbf834a6cf) | | +| [`interval`](#group__sched_1ga79c8a845365cd31f534b730e022e8d4d) | This value represents the interval to wait before running the task. | +| [`maxTimes`](#group__sched_1ga80f340cb8d0f23d4b1a89b2e200518b8) | The maximum number of times the task will be run before it is destroyed. 0 for no effect. | +--- -#### `public virtual void deserialize(json::value & root)` - - - - - -# struct `scy::sched::OnceOnlyTrigger` +#### IntervalTrigger +```cpp +IntervalTrigger() ``` -struct scy::sched::OnceOnlyTrigger - : public scy::sched::Trigger -``` - - - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public OnceOnlyTrigger()` | -`public inline virtual void update()` | -`public virtual bool expired()` | - -## Members -#### `public OnceOnlyTrigger()` - - - - - -#### `public inline virtual void update()` +--- +#### update +```cpp +virtual void update() +``` Updates the scheduleAt value to the next scheduled time. -#### `public virtual bool expired()` +--- +#### expired - -Returns true if the task is expired and should be destroyed. Returns false by default. - -# struct `scy::sched::Trigger` - +```cpp +virtual bool expired() ``` -struct scy::sched::Trigger - : public scy::json::ISerializable -``` - +Returns true if the task is expired and should be destroyed. Returns false by default. +--- +#### serialize -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public std::string type` | The type of this trigger class. -`public std::string name` | The display name of this trigger class. -`public int timesRun` | -`public `[`DateTime`](./doc/api-base.md#classscy_1_1DateTime)` createdAt` | The time the task was created. -`public `[`DateTime`](./doc/api-base.md#classscy_1_1DateTime)` scheduleAt` | The time the task is scheduled to run. -`public `[`DateTime`](./doc/api-base.md#classscy_1_1DateTime)` lastRunAt` | The time the task was last run. -`public Trigger(const std::string & type,const std::string & name)` | -`public void update()` | -`public virtual std::int64_t remaining()` | -`public virtual bool timeout()` | -`public virtual bool expired()` | -`public virtual void serialize(json::value & root)` | -`public virtual void deserialize(json::value & root)` | - -## Members - -#### `public std::string type` - -The type of this trigger class. - - - -#### `public std::string name` - -The display name of this trigger class. - - - -#### `public int timesRun` +```cpp +virtual void serialize(json::value & root) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `root` | `json::value &` | | +--- -The number of times the task has run since creation; +#### deserialize -#### `public `[`DateTime`](./doc/api-base.md#classscy_1_1DateTime)` createdAt` +```cpp +virtual void deserialize(json::value & root) +``` -The time the task was created. +| Parameter | Type | Description | +|-----------|------|-------------| +| `root` | `json::value &` | | +--- +#### interval -#### `public `[`DateTime`](./doc/api-base.md#classscy_1_1DateTime)` scheduleAt` +```cpp +Timespan interval +``` -The time the task is scheduled to run. +This value represents the interval to wait before running the task. +--- +#### maxTimes -#### `public `[`DateTime`](./doc/api-base.md#classscy_1_1DateTime)` lastRunAt` +```cpp +int maxTimes +``` -The time the task was last run. +The maximum number of times the task will be run before it is destroyed. 0 for no effect. +## DailyTrigger +> **Extends:** `scy::sched::Trigger` +> **Defined in:** `trigger.h` -#### `public Trigger(const std::string & type,const std::string & name)` +### Members +| Name | Description | +|------|-------------| +| [`DailyTrigger`](#group__sched_1ga5bbeff00daa5b34e548ec34276c599b0) | | +| [`update`](#group__sched_1ga3cf631dce5a9d307f9162e8d5b6ed4f8) | Updates the scheduleAt value to the next scheduled time. | +| [`timeOfDay`](#group__sched_1gac27c59a1258d294183119fd52ac5b4fc) | This value represents the time of day the task will trigger. The date part of the timestamp is redundant. | +| [`daysExcluded`](#group__sched_1ga336f20188705b1fa837686bb01898409) | Days of the week can be excluded by adding the appropriate bit flag here. | +--- +#### DailyTrigger +```cpp +DailyTrigger() +``` -#### `public void update()` +--- +#### update +```cpp +virtual void update() +``` Updates the scheduleAt value to the next scheduled time. -#### `public virtual std::int64_t remaining()` - - - -Returns the milliseconds remaining until the next scheduled timeout. - -#### `public virtual bool timeout()` - - - -Returns true if the task is ready to be run, false otherwise. - -#### `public virtual bool expired()` - - - -Returns true if the task is expired and should be destroyed. Returns false by default. - -#### `public virtual void serialize(json::value & root)` - - +--- +#### timeOfDay +```cpp +DateTime timeOfDay +``` -#### `public virtual void deserialize(json::value & root)` +This value represents the time of day the task will trigger. The date part of the timestamp is redundant. +--- +#### daysExcluded +```cpp +std::vector< DaysOfTheWeek > daysExcluded +``` +Days of the week can be excluded by adding the appropriate bit flag here. diff --git a/doc/api-sked.md b/doc/api-sked.md deleted file mode 100644 index 90e649364..000000000 --- a/doc/api-sked.md +++ /dev/null @@ -1,631 +0,0 @@ -# Module `sked` - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`namespace `[`scy::sked`](#namespacescy_1_1sked) | -# namespace `scy::sked` {#namespacescy_1_1sked} - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`class `[`scy::sked::Scheduler`](#classscy_1_1sked_1_1Scheduler) | -`class `[`scy::sked::Task`](#classscy_1_1sked_1_1Task) | -`class `[`scy::sked::TaskFactory`](#classscy_1_1sked_1_1TaskFactory) | -`struct `[`scy::sked::DailyTrigger`](#structscy_1_1sked_1_1DailyTrigger) | -`struct `[`scy::sked::IntervalTrigger`](#structscy_1_1sked_1_1IntervalTrigger) | -`struct `[`scy::sked::OnceOnlyTrigger`](#structscy_1_1sked_1_1OnceOnlyTrigger) | -`struct `[`scy::sked::Trigger`](#structscy_1_1sked_1_1Trigger) | -# class `scy::sked::Scheduler` {#classscy_1_1sked_1_1Scheduler} - -``` -class scy::sked::Scheduler - : public scy::TaskRunner - : public scy::json::ISerializable -``` - - - -The [Scheduler](#classscy_1_1sked_1_1Scheduler) manages and runs tasks that need to be executed at specific times. - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public Scheduler()` | -`public virtual ~Scheduler()` | -`public virtual void schedule(`[`sked::Task`](#classscy_1_1sked_1_1Task)` * task)` | -`public virtual void cancel(`[`sked::Task`](#classscy_1_1sked_1_1Task)` * task)` | -`public virtual void clear()` | Destroys and clears all manages tasks. -`public virtual void serialize(json::Value & root)` | -`public virtual void deserialize(json::Value & root)` | -`public virtual void print(std::ostream & ost)` | -`protected virtual void run()` | Called by the async context to run the next task. -`protected virtual void update()` | - -## Members - -#### `public Scheduler()` {#group__sked_1ga514a0aa9634b1951ae56a99564caeb33} - - - - - -#### `public virtual ~Scheduler()` {#group__sked_1ga48b23def7201e4a5037a35a673cb3f97} - - - - - -#### `public virtual void schedule(`[`sked::Task`](#classscy_1_1sked_1_1Task)` * task)` {#group__sked_1gacc21c6934f5af42c17f00f8eaeb779c8} - - - - - -#### `public virtual void cancel(`[`sked::Task`](#classscy_1_1sked_1_1Task)` * task)` {#group__sked_1ga0c63154c5dd7f3f7d78409102fa761f4} - - - - - -#### `public virtual void clear()` {#group__sked_1ga8df4c68754fab027eb3e30f44311df1e} - -Destroys and clears all manages tasks. - - - -#### `public virtual void serialize(json::Value & root)` {#group__sked_1gadd053ba59d1f38a08e041f3a42b8f9e2} - - - - - -#### `public virtual void deserialize(json::Value & root)` {#group__sked_1gaa6b3a781c8e69f6de99ad05b7b1d1d63} - - - - - -#### `public virtual void print(std::ostream & ost)` {#group__sked_1gaaab06d2eb415e90490cd565d749c5638} - - - - - -#### `protected virtual void run()` {#group__sked_1ga74363bb7cb688746b40d479d950f6975} - -Called by the async context to run the next task. - - - -#### `protected virtual void update()` {#group__sked_1ga67269cfef7d229e4a24f5bfc92bc339d} - - - - - -# class `scy::sked::Task` {#classscy_1_1sked_1_1Task} - -``` -class scy::sked::Task - : public scy::Task - : public scy::json::ISerializable -``` - - - -This class extends the [Task](#classscy_1_1sked_1_1Task) class to implement scheduling capabilities. - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public Task(const std::string & type,const std::string & name)` | -`public Task(`[`Scheduler`](#classscy_1_1sked_1_1Scheduler)` & scheduler,const std::string & type,const std::string & name)` | -`public virtual void serialize(json::Value & root)` | Serializes the task to JSON. -`public virtual void deserialize(json::Value & root)` | Deserializes the task from JSON. -`public template`
`inline T * createTrigger()` | -`public void setTrigger(`[`sked::Trigger`](#structscy_1_1sked_1_1Trigger)` * trigger)` | -`public `[`sked::Trigger`](#structscy_1_1sked_1_1Trigger)` & trigger()` | -`public `[`Scheduler`](#classscy_1_1sked_1_1Scheduler)` & scheduler()` | -`public std::int64_t remaining() const` | -`public std::string type() const` | -`public std::string name() const` | -`public void setName(const std::string & name)` | -`protected std::string _type` | -`protected std::string _name` | -`protected `[`sked::Scheduler`](./doc/api-sked.md#classscy_1_1sked_1_1Scheduler)` * _scheduler` | -`protected `[`sked::Trigger`](./doc/api-sked.md#structscy_1_1sked_1_1Trigger)` * _trigger` | -`protected mutable `[`Mutex`](./doc/api-base.md#classscy_1_1Mutex)` _mutex` | -`protected virtual ~Task()` | Should remain protected. -`protected virtual bool beforeRun()` | -`protected void run()` | -`protected virtual bool afterRun()` | - -## Members - -#### `public Task(const std::string & type,const std::string & name)` {#group__sked_1ga386a15d521531a67fdb090824da93890} - - - - - -#### `public Task(`[`Scheduler`](#classscy_1_1sked_1_1Scheduler)` & scheduler,const std::string & type,const std::string & name)` {#group__sked_1gab06c7ef2f60c5486229cd426919cc36c} - - - - - -#### `public virtual void serialize(json::Value & root)` {#group__sked_1ga2d10fe6de9492ad784039a4e257eced5} - -Serializes the task to JSON. - - - -#### `public virtual void deserialize(json::Value & root)` {#group__sked_1gac0c3e0cfa2b24a12d2f72488f62b4d09} - -Deserializes the task from JSON. - - - -#### `public template`
`inline T * createTrigger()` {#group__sked_1ga1a8b7a4f4fc7e1dcc06b5c4454c875ab} - - - - - -#### `public void setTrigger(`[`sked::Trigger`](#structscy_1_1sked_1_1Trigger)` * trigger)` {#group__sked_1ga3d72bcdb505450e88522b17dddd9b73b} - - - - - -#### `public `[`sked::Trigger`](#structscy_1_1sked_1_1Trigger)` & trigger()` {#group__sked_1ga79f463a50c3a8ee9cd482f7bce8d67ea} - - - -Returns a reference to the associated [sked::Trigger](#structscy_1_1sked_1_1Trigger) or throws an exception. - -#### `public `[`Scheduler`](#classscy_1_1sked_1_1Scheduler)` & scheduler()` {#group__sked_1ga8d439f1522684b89f81b3852348019bd} - - - -Returns a reference to the associated [Scheduler](#classscy_1_1sked_1_1Scheduler) or throws an exception. - -#### `public std::int64_t remaining() const` {#group__sked_1ga35f659f3ebe2737385595564402d0f54} - - - -Returns the milliseconds remaining until the next scheduled timeout. An [sked::Trigger](#structscy_1_1sked_1_1Trigger) must be associated or an exception will be thrown. - -#### `public std::string type() const` {#group__sked_1ga83e6c392d631a66fd5f803a806e9e502} - - - - - -#### `public std::string name() const` {#group__sked_1gac054517b6cd13fa107c629465e36c8bd} - - - - - -#### `public void setName(const std::string & name)` {#group__sked_1ga0d1f0b5a756774917f742f38acc7cefe} - - - - - -#### `protected std::string _type` {#group__sked_1ga593c8a61cdc6f5775aa26c83699f7acc} - - - - - -#### `protected std::string _name` {#group__sked_1ga0cff879b589e588e38589eef0f8329b2} - - - - - -#### `protected `[`sked::Scheduler`](./doc/api-sked.md#classscy_1_1sked_1_1Scheduler)` * _scheduler` {#group__sked_1ga7a67dcc93b0781f5e8579bb888951c6d} - - - - - -#### `protected `[`sked::Trigger`](./doc/api-sked.md#structscy_1_1sked_1_1Trigger)` * _trigger` {#group__sked_1ga29d12af7fc6b09ae0ea2120a21179f4a} - - - - - -#### `protected mutable `[`Mutex`](./doc/api-base.md#classscy_1_1Mutex)` _mutex` {#group__sked_1gacc6e9cb2c3332ce7e3856ad20053fd4f} - - - - - -#### `protected virtual ~Task()` {#group__sked_1ga27c4083f96354bccaa7b2b24b5404e7b} - -Should remain protected. - - - -#### `protected virtual bool beforeRun()` {#group__sked_1gaa4e46a5d56fe059de12ebec07538b343} - - - - - -#### `protected void run()` {#group__sked_1gaa9b1a4ffaa4e3e9d1ec795b1af35c0b9} - - - -Called by the [TaskRunner](#classscy_1_1TaskRunner) to run the task. Override this method to implement task action. Returning true means the true should be called again, and false will cause the task to be destroyed. The task will similarly be destroyed id [destroy()](#group__base_1gaecd8a85018f8f75ae802dcbf3749bdef) was called during the current task iteration. - -#### `protected virtual bool afterRun()` {#group__sked_1gaf1e8643d12b32391169a1fa66cd9532b} - - - - - -# class `scy::sked::TaskFactory` {#classscy_1_1sked_1_1TaskFactory} - - - - -The [TaskFactory](#classscy_1_1sked_1_1TaskFactory) can dynamically instantiate registered [sked::Task](#classscy_1_1sked_1_1Task) and [sked::Trigger](#structscy_1_1sked_1_1Trigger) classes from named strings. - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public inline `[`sked::Task`](#classscy_1_1sked_1_1Task)` * createTask(const std::string & type)` | -`public template`
`inline void registerTask(const std::string & type)` | -`public inline void unregisterTask(const std::string & type)` | -`public inline TaskMap tasks() const` | -`public inline `[`sked::Trigger`](#structscy_1_1sked_1_1Trigger)` * createTrigger(const std::string & type)` | -`public template`
`inline void registerTrigger(const std::string & type)` | -`public inline void unregisterTrigger(const std::string & type)` | -`public inline TriggerMap triggers() const` | -`protected mutable `[`Mutex`](./doc/api-base.md#classscy_1_1Mutex)` _mutex` | -`protected TaskMap _tasks` | -`protected TriggerMap _triggers` | - -## Members - -#### `public inline `[`sked::Task`](#classscy_1_1sked_1_1Task)` * createTask(const std::string & type)` {#group__sked_1gaf2c3154913174136d643907915637772} - - - - - -#### `public template`
`inline void registerTask(const std::string & type)` {#group__sked_1ga6abe68ae8192c8a724bfb8297dc2fb83} - - - - - -#### `public inline void unregisterTask(const std::string & type)` {#group__sked_1ga9279b37d8ed19efce7ed4a44fe14bcdb} - - - - - -#### `public inline TaskMap tasks() const` {#group__sked_1ga1810c49aadc9105cc18f4fd4eee54e8d} - - - - - -#### `public inline `[`sked::Trigger`](#structscy_1_1sked_1_1Trigger)` * createTrigger(const std::string & type)` {#group__sked_1ga6b74f8b76c41cfa76b2b966dc4f04728} - - - - - -#### `public template`
`inline void registerTrigger(const std::string & type)` {#group__sked_1gad7739778b7ea92b9164fabfd61f3162c} - - - - - -#### `public inline void unregisterTrigger(const std::string & type)` {#group__sked_1gaa82d4cb06fab8254b68fe95040dd0772} - - - - - -#### `public inline TriggerMap triggers() const` {#group__sked_1ga54a36cb63df452507f257c9bd02a31ea} - - - - - -#### `protected mutable `[`Mutex`](./doc/api-base.md#classscy_1_1Mutex)` _mutex` {#group__sked_1gaba4115abe13876bea87f674ce7354295} - - - - - -#### `protected TaskMap _tasks` {#group__sked_1ga83f4f9401b6f52622ca74c4d884d4e77} - - - - - -#### `protected TriggerMap _triggers` {#group__sked_1ga7f0a4e67c56a5f0a997cd2caa993b187} - - - - - -# struct `scy::sked::DailyTrigger` {#structscy_1_1sked_1_1DailyTrigger} - -``` -struct scy::sked::DailyTrigger - : public scy::sked::Trigger -``` - - - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public `[`DateTime`](./doc/api-base.md#classscy_1_1DateTime)` timeOfDay` | -`public std::vector< `[`DaysOfTheWeek`](#group__sked_1gafaf09924bf11ff91312d278879efc364)` > daysExcluded` | -`public DailyTrigger()` | -`public virtual void update()` | - -## Members - -#### `public `[`DateTime`](./doc/api-base.md#classscy_1_1DateTime)` timeOfDay` {#group__sked_1ga0f50994338086f658223bb591aaa855b} - - - -This value represents the time of day the task will trigger. The date part of the timestamp is redundant. - -#### `public std::vector< `[`DaysOfTheWeek`](#group__sked_1gafaf09924bf11ff91312d278879efc364)` > daysExcluded` {#group__sked_1gaeecee22b3f9a186f36b37c3967c84261} - - - -Days of the week can be excluded by adding the appropriate bit flag here. - -#### `public DailyTrigger()` {#group__sked_1gaefddcdf43f7dd40d2fd9c4973aa16f5c} - - - - - -#### `public virtual void update()` {#group__sked_1ga56d431a340ef90a63c3a9ef7c5fecdac} - - - -Updates the scheduleAt value to the next scheduled time. - -# struct `scy::sked::IntervalTrigger` {#structscy_1_1sked_1_1IntervalTrigger} - -``` -struct scy::sked::IntervalTrigger - : public scy::sked::Trigger -``` - - - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public `[`Timespan`](./doc/api-base.md#classscy_1_1Timespan)` interval` | -`public int maxTimes` | -`public IntervalTrigger()` | -`public virtual void update()` | -`public virtual bool expired()` | -`public virtual void serialize(json::Value & root)` | -`public virtual void deserialize(json::Value & root)` | - -## Members - -#### `public `[`Timespan`](./doc/api-base.md#classscy_1_1Timespan)` interval` {#group__sked_1ga8f86f84623d9cdd251cb596d1b9cd7ea} - - - -This value represents the interval to wait before running the task. - -#### `public int maxTimes` {#group__sked_1ga8e40cfaeaa7e36c6e8fecb557fa6fe4a} - - - -The maximum number of times the task will be run before it is destroyed. 0 for no effect. - -#### `public IntervalTrigger()` {#group__sked_1ga2a6fcdbba2933d6f1a0c2e60e75a1afa} - - - - - -#### `public virtual void update()` {#group__sked_1ga01c689ed43d5fb9981303ca9a57a2623} - - - -Updates the scheduleAt value to the next scheduled time. - -#### `public virtual bool expired()` {#group__sked_1gae9ebbb2da9675cf0f861105b406ec827} - - - -Returns true if the task is expired and should be destroyed. Returns false by default. - -#### `public virtual void serialize(json::Value & root)` {#group__sked_1gabae55c2745920c5b40daa2ff5fc23b66} - - - - - -#### `public virtual void deserialize(json::Value & root)` {#group__sked_1ga345231c106ed12e9a2ff6c30c91b3280} - - - - - -# struct `scy::sked::OnceOnlyTrigger` {#structscy_1_1sked_1_1OnceOnlyTrigger} - -``` -struct scy::sked::OnceOnlyTrigger - : public scy::sked::Trigger -``` - - - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public OnceOnlyTrigger()` | -`public inline virtual void update()` | -`public virtual bool expired()` | - -## Members - -#### `public OnceOnlyTrigger()` {#group__sked_1ga415a7be1c65cda0e938c2c71947650e5} - - - - - -#### `public inline virtual void update()` {#group__sked_1ga357a04a19f44aec0fff439398b574634} - - - -Updates the scheduleAt value to the next scheduled time. - -#### `public virtual bool expired()` {#group__sked_1ga578595dc276d57bce1a54e7ba3fd3da1} - - - -Returns true if the task is expired and should be destroyed. Returns false by default. - -# struct `scy::sked::Trigger` {#structscy_1_1sked_1_1Trigger} - -``` -struct scy::sked::Trigger - : public scy::json::ISerializable -``` - - - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public std::string type` | The type of this trigger class. -`public std::string name` | The display name of this trigger class. -`public int timesRun` | -`public `[`DateTime`](./doc/api-base.md#classscy_1_1DateTime)` createdAt` | The time the task was created. -`public `[`DateTime`](./doc/api-base.md#classscy_1_1DateTime)` scheduleAt` | The time the task is scheduled to run. -`public `[`DateTime`](./doc/api-base.md#classscy_1_1DateTime)` lastRunAt` | The time the task was last run. -`public Trigger(const std::string & type,const std::string & name)` | -`public void update()` | -`public virtual std::int64_t remaining()` | -`public virtual bool timeout()` | -`public virtual bool expired()` | -`public virtual void serialize(json::Value & root)` | -`public virtual void deserialize(json::Value & root)` | - -## Members - -#### `public std::string type` {#group__sked_1ga7cc1c5928a3bf2de63df3e6e7d4cd413} - -The type of this trigger class. - - - -#### `public std::string name` {#group__sked_1gaa49fe31e4a8bc141f9ded29e305ca322} - -The display name of this trigger class. - - - -#### `public int timesRun` {#group__sked_1ga9d336b4c320364d7a86762039418531c} - - - -The number of times the task has run since creation; - -#### `public `[`DateTime`](./doc/api-base.md#classscy_1_1DateTime)` createdAt` {#group__sked_1gaf0f5c1e386f877fd8f2d099d441093f3} - -The time the task was created. - - - -#### `public `[`DateTime`](./doc/api-base.md#classscy_1_1DateTime)` scheduleAt` {#group__sked_1ga1063f958b835c6d033c8ff389b2e94f0} - -The time the task is scheduled to run. - - - -#### `public `[`DateTime`](./doc/api-base.md#classscy_1_1DateTime)` lastRunAt` {#group__sked_1ga3fdacd4cae9a26840ff138aa48bbe4e1} - -The time the task was last run. - - - -#### `public Trigger(const std::string & type,const std::string & name)` {#group__sked_1ga6c5824c78e581a00b0d440466584bd22} - - - - - -#### `public void update()` {#group__sked_1gaf1f2ee5a783e1c9190430b07fc89f8da} - - - -Updates the scheduleAt value to the next scheduled time. - -#### `public virtual std::int64_t remaining()` {#group__sked_1ga01473ad840be6c629fc360a3d4750eca} - - - -Returns the milliseconds remaining until the next scheduled timeout. - -#### `public virtual bool timeout()` {#group__sked_1gadb3c28f4bb3af12a90422eff0c42dece} - - - -Returns true if the task is ready to be run, false otherwise. - -#### `public virtual bool expired()` {#group__sked_1ga2c6d97224c1bd3aaa8cb7fd70b6bc1c1} - - - -Returns true if the task is expired and should be destroyed. Returns false by default. - -#### `public virtual void serialize(json::Value & root)` {#group__sked_1ga263a8007f39041e235c835b967a61f93} - - - - - -#### `public virtual void deserialize(json::Value & root)` {#group__sked_1ga480d0f52b3319d765e5c6b809c946609} - - - - - diff --git a/doc/api-socketio.md b/doc/api-socketio.md index 2ade2e2c7..e69de29bb 100644 --- a/doc/api-socketio.md +++ b/doc/api-socketio.md @@ -1,880 +0,0 @@ -# Module `socketio` - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`namespace `[`scy::sockio`](#namespacescy_1_1sockio) | -`struct `[`scy::sockio::Client::Options`](#structscy_1_1sockio_1_1Client_1_1Options) | -# namespace `scy::sockio` - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`class `[`scy::sockio::Client`](#classscy_1_1sockio_1_1Client) | -`class `[`scy::sockio::Packet`](#classscy_1_1sockio_1_1Packet) | -`class `[`scy::sockio::SSLClient`](#classscy_1_1sockio_1_1SSLClient) | -`class `[`scy::sockio::TCPClient`](#classscy_1_1sockio_1_1TCPClient) | -`struct `[`scy::sockio::ClientState`](#structscy_1_1sockio_1_1ClientState) | -`struct `[`scy::sockio::Transaction`](#structscy_1_1sockio_1_1Transaction) | -# class `scy::sockio::Client` - -``` -class scy::sockio::Client - : public scy::Stateful< ClientState > - : public scy::net::SocketAdapter - : public scy::Signal< void(IPacket &)> -``` - - - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public Client(const net::Socket::Ptr & socket,const `[`Options`](#structscy_1_1sockio_1_1Client_1_1Options)` & options)` | Client(const net::Socket::Ptr& socket);. -`public virtual ~Client()` | -`public virtual void connect()` | -`public virtual void close()` | -`public virtual int send(const std::string & message,bool ack)` | Send a default message packet. -`public virtual int send(const json::value & message,bool ack)` | -`public virtual int send(const std::string & event,const char * message,bool ack)` | Send an event packet. -`public virtual int send(const std::string & event,const std::string & message,bool ack)` | -`public virtual int send(const std::string & event,const json::value & message,bool ack)` | -`public virtual int send(const `[`sockio::Packet`](#classscy_1_1sockio_1_1Packet)` & packet)` | Send the given packet. -`public `[`Transaction`](#structscy_1_1sockio_1_1Transaction)` * createTransaction(const `[`sockio::Packet`](#classscy_1_1sockio_1_1Packet)` & request,long timeout)` | Create a packet transaction. -`public `[`Client::Options`](#structscy_1_1sockio_1_1Client_1_1Options)` & options()` | Return a reference to the client options object. -`public `[`http::ws::WebSocket`](#classscy_1_1http_1_1ws_1_1WebSocket)` & ws()` | Return the underlying WebSocket instance. -`public std::string sessionID() const` | Return the current session ID assigned by the server. -`public `[`scy::Error`](#structscy_1_1Error)` error() const` | Return the error object (if any). -`public bool isOnline() const` | Return true if the client is is Online state. -`public bool reconnecting() const` | Return true if currently reconnecting. -`public bool wasOnline() const` | -`public inline virtual const char * className() const` | -`protected `[`Timer`](./doc/api-base.md#classscy_1_1Timer)` _pingTimer` | -`protected `[`Timer`](./doc/api-base.md#classscy_1_1Timer)` _pingTimeoutTimer` | -`protected `[`Timer`](./doc/api-base.md#classscy_1_1Timer)` _reconnectTimer` | -`protected `[`scy::Error`](./doc/api-base.md#structscy_1_1Error)` _error` | -`protected std::string _sessionID` | -`protected `[`Client::Options`](./doc/api-socketio.md#structscy_1_1sockio_1_1Client_1_1Options)` _options` | -`protected `[`http::ws::WebSocket`](./doc/api-http.md#classscy_1_1http_1_1ws_1_1WebSocket)` _ws` | -`protected int _pingTimeout` | -`protected int _pingInterval` | -`protected bool _reconnecting` | -`protected bool _wasOnline` | -`protected virtual void setError(const `[`scy::Error`](#structscy_1_1Error)` & error)` | -`protected virtual void reset()` | Reset variables and timers at the beginning and end of each session. -`protected virtual void onConnect()` | -`protected virtual void onOnline()` | -`protected virtual void onClose()` | -`protected virtual void onPacket(`[`sockio::Packet`](#classscy_1_1sockio_1_1Packet)` & packet)` | -`protected virtual void onHandshake(`[`sockio::Packet`](#classscy_1_1sockio_1_1Packet)` & packet)` | -`protected virtual void onMessage(`[`sockio::Packet`](#classscy_1_1sockio_1_1Packet)` & packet)` | -`protected virtual void onSocketConnect(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket)` | -`protected virtual void onSocketRecv(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket,const `[`MutableBuffer`](#classscy_1_1MutableBuffer)` & buffer,const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddress)` | -`protected virtual void onSocketError(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket,const `[`scy::Error`](#structscy_1_1Error)` & error)` | -`protected virtual void onSocketClose(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket)` | -`protected virtual void onPingTimer()` | -`protected virtual void onPingTimeoutTimer()` | -`protected virtual void startReconnectTimer()` | -`protected virtual void stopReconnectTimer()` | -`protected virtual void onReconnectTimer()` | -`protected virtual int sendPing()` | -`protected virtual void onPong()` | - -## Members - -#### `public Client(const net::Socket::Ptr & socket,const `[`Options`](#structscy_1_1sockio_1_1Client_1_1Options)` & options)` - -Client(const net::Socket::Ptr& socket);. - - - -#### `public virtual ~Client()` - - - - - -#### `public virtual void connect()` - - - - - -#### `public virtual void close()` - - - - - -#### `public virtual int send(const std::string & message,bool ack)` - -Send a default message packet. - - - -#### `public virtual int send(const json::value & message,bool ack)` - - - - - -#### `public virtual int send(const std::string & event,const char * message,bool ack)` - -Send an event packet. - - - -#### `public virtual int send(const std::string & event,const std::string & message,bool ack)` - - - - - -#### `public virtual int send(const std::string & event,const json::value & message,bool ack)` - - - - - -#### `public virtual int send(const `[`sockio::Packet`](#classscy_1_1sockio_1_1Packet)` & packet)` - -Send the given packet. - - - -#### `public `[`Transaction`](#structscy_1_1sockio_1_1Transaction)` * createTransaction(const `[`sockio::Packet`](#classscy_1_1sockio_1_1Packet)` & request,long timeout)` - -Create a packet transaction. - - - -#### `public `[`Client::Options`](#structscy_1_1sockio_1_1Client_1_1Options)` & options()` - -Return a reference to the client options object. - - - -#### `public `[`http::ws::WebSocket`](#classscy_1_1http_1_1ws_1_1WebSocket)` & ws()` - -Return the underlying WebSocket instance. - - - -#### `public std::string sessionID() const` - -Return the current session ID assigned by the server. - - - -#### `public `[`scy::Error`](#structscy_1_1Error)` error() const` - -Return the error object (if any). - - - -#### `public bool isOnline() const` - -Return true if the client is is Online state. - - - -#### `public bool reconnecting() const` - -Return true if currently reconnecting. - - - -#### `public bool wasOnline() const` - - - -Return true if the client was previously in the Online state. Useful for delegates handling the [Error](#structscy_1_1Error) state. - -#### `public inline virtual const char * className() const` - - - - - -#### `protected `[`Timer`](./doc/api-base.md#classscy_1_1Timer)` _pingTimer` - - - - - -#### `protected `[`Timer`](./doc/api-base.md#classscy_1_1Timer)` _pingTimeoutTimer` - - - - - -#### `protected `[`Timer`](./doc/api-base.md#classscy_1_1Timer)` _reconnectTimer` - - - - - -#### `protected `[`scy::Error`](./doc/api-base.md#structscy_1_1Error)` _error` - - - - - -#### `protected std::string _sessionID` - - - - - -#### `protected `[`Client::Options`](./doc/api-socketio.md#structscy_1_1sockio_1_1Client_1_1Options)` _options` - - - - - -#### `protected `[`http::ws::WebSocket`](./doc/api-http.md#classscy_1_1http_1_1ws_1_1WebSocket)` _ws` - - - - - -#### `protected int _pingTimeout` - - - - - -#### `protected int _pingInterval` - - - - - -#### `protected bool _reconnecting` - - - - - -#### `protected bool _wasOnline` - - - - - -#### `protected virtual void setError(const `[`scy::Error`](#structscy_1_1Error)` & error)` - - - - - -#### `protected virtual void reset()` - -Reset variables and timers at the beginning and end of each session. - - - -#### `protected virtual void onConnect()` - - - - - -#### `protected virtual void onOnline()` - - - - - -#### `protected virtual void onClose()` - - - - - -#### `protected virtual void onPacket(`[`sockio::Packet`](#classscy_1_1sockio_1_1Packet)` & packet)` - - - - - -#### `protected virtual void onHandshake(`[`sockio::Packet`](#classscy_1_1sockio_1_1Packet)` & packet)` - - - - - -#### `protected virtual void onMessage(`[`sockio::Packet`](#classscy_1_1sockio_1_1Packet)` & packet)` - - - - - -#### `protected virtual void onSocketConnect(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket)` - - - -These virtual methods can be overridden as necessary to intercept socket events before they hit the application. - -#### `protected virtual void onSocketRecv(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket,const `[`MutableBuffer`](#classscy_1_1MutableBuffer)` & buffer,const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddress)` - - - - - -#### `protected virtual void onSocketError(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket,const `[`scy::Error`](#structscy_1_1Error)` & error)` - - - - - -#### `protected virtual void onSocketClose(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket)` - - - - - -#### `protected virtual void onPingTimer()` - - - - - -#### `protected virtual void onPingTimeoutTimer()` - - - - - -#### `protected virtual void startReconnectTimer()` - - - - - -#### `protected virtual void stopReconnectTimer()` - - - - - -#### `protected virtual void onReconnectTimer()` - - - - - -#### `protected virtual int sendPing()` - - - - - -#### `protected virtual void onPong()` - - - - - -# class `scy::sockio::Packet` - -``` -class scy::sockio::Packet - : public scy::IPacket -``` - - - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public Packet(Frame frame,Type type,int id,const std::string & nsp,const std::string & event,const std::string & message,bool ack)` | Default contructor. -`public Packet(Type type,const std::string & message,bool ack)` | General contructor. -`public Packet(const std::string & message,bool ack)` | Message contructor. -`public Packet(const json::value & message,bool ack)` | JSON contructor. -`public Packet(const std::string & event,const std::string & message,bool ack)` | Event contructor. -`public Packet(const std::string & event,const json::value & message,bool ack)` | Event JSON contructor. -`public Packet(const `[`Packet`](#classscy_1_1sockio_1_1Packet)` & r)` | -`public `[`Packet`](#classscy_1_1sockio_1_1Packet)` & operator=(const `[`Packet`](#classscy_1_1sockio_1_1Packet)` & r)` | -`public virtual ~Packet()` | -`public virtual `[`IPacket`](#classscy_1_1IPacket)` * clone() const` | -`public Frame frame() const` | -`public Type type() const` | -`public int id() const` | -`public std::string nsp() const` | -`public std::string message() const` | -`public json::value json() const` | -`public void setID(int id)` | -`public void setNamespace(const std::string & nsp)` | -`public void setMessage(const std::string & message)` | -`public void setAck(bool flag)` | -`public virtual ssize_t read(const `[`ConstBuffer`](#classscy_1_1ConstBuffer)` &)` | -`public virtual void write(`[`Buffer`](#group__base_1gab10b36b080deb583ed703fca6b63ffdd)` &) const` | -`public virtual size_t size() const` | -`public bool valid() const` | -`public std::string frameString() const` | -`public std::string typeString() const` | -`public std::string toString() const` | -`public virtual void print(std::ostream & os) const` | -`public inline virtual const char * className() const` | -`protected Frame _frame` | -`protected Type _type` | -`protected int _id` | -`protected std::string _nsp` | -`protected std::string _event` | -`protected std::string _message` | -`protected bool _ack` | -`protected size_t _size` | - -## Members - -#### `public Packet(Frame frame,Type type,int id,const std::string & nsp,const std::string & event,const std::string & message,bool ack)` - -Default contructor. - - - -#### `public Packet(Type type,const std::string & message,bool ack)` - -General contructor. - - - -#### `public Packet(const std::string & message,bool ack)` - -Message contructor. - - - -#### `public Packet(const json::value & message,bool ack)` - -JSON contructor. - - - -#### `public Packet(const std::string & event,const std::string & message,bool ack)` - -Event contructor. - - - -#### `public Packet(const std::string & event,const json::value & message,bool ack)` - -Event JSON contructor. - - - -#### `public Packet(const `[`Packet`](#classscy_1_1sockio_1_1Packet)` & r)` - - - - - -#### `public `[`Packet`](#classscy_1_1sockio_1_1Packet)` & operator=(const `[`Packet`](#classscy_1_1sockio_1_1Packet)` & r)` - - - - - -#### `public virtual ~Packet()` - - - - - -#### `public virtual `[`IPacket`](#classscy_1_1IPacket)` * clone() const` - - - - - -#### `public Frame frame() const` - - - - - -#### `public Type type() const` - - - - - -#### `public int id() const` - - - - - -#### `public std::string nsp() const` - - - - - -#### `public std::string message() const` - - - - - -#### `public json::value json() const` - - - - - -#### `public void setID(int id)` - - - - - -#### `public void setNamespace(const std::string & nsp)` - - - - - -#### `public void setMessage(const std::string & message)` - - - - - -#### `public void setAck(bool flag)` - - - - - -#### `public virtual ssize_t read(const `[`ConstBuffer`](#classscy_1_1ConstBuffer)` &)` - - - -Read/parse to the packet from the given input buffer. The number of bytes read is returned. - -#### `public virtual void write(`[`Buffer`](#group__base_1gab10b36b080deb583ed703fca6b63ffdd)` &) const` - - - -Copy/generate to the packet given output buffer. The number of bytes written can be obtained from the buffer. - -Todo: It may be prefferable to use our pod types here instead of buffer input, but the current codebase requires that the buffer be dynamically resizable for some protocols... - -#### `public virtual size_t size() const` - - - -The size of the packet in bytes. - -This is the nember of bytes that will be written on a call to [write()](#group__socketio_1gad8bcc194e62922929788a39be680775c), but may not be the number of bytes that will be consumed by [read()](#group__socketio_1ga2b911c9a18008b42c74ab85015ddecb9). - -#### `public bool valid() const` - - - - - -#### `public std::string frameString() const` - - - - - -#### `public std::string typeString() const` - - - - - -#### `public std::string toString() const` - - - - - -#### `public virtual void print(std::ostream & os) const` - - - - - -#### `public inline virtual const char * className() const` - - - - - -#### `protected Frame _frame` - - - - - -#### `protected Type _type` - - - - - -#### `protected int _id` - - - - - -#### `protected std::string _nsp` - - - - - -#### `protected std::string _event` - - - - - -#### `protected std::string _message` - - - - - -#### `protected bool _ack` - - - - - -#### `protected size_t _size` - - - - - -# class `scy::sockio::SSLClient` - -``` -class scy::sockio::SSLClient - : public scy::sockio::Client -``` - - - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public SSLClient(const `[`Client::Options`](#structscy_1_1sockio_1_1Client_1_1Options)` & options,uv::Loop * loop)` | - -## Members - -#### `public SSLClient(const `[`Client::Options`](#structscy_1_1sockio_1_1Client_1_1Options)` & options,uv::Loop * loop)` - - - - - -# class `scy::sockio::TCPClient` - -``` -class scy::sockio::TCPClient - : public scy::sockio::Client -``` - - - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public TCPClient(const `[`Client::Options`](#structscy_1_1sockio_1_1Client_1_1Options)` & options,uv::Loop * loop)` | - -## Members - -#### `public TCPClient(const `[`Client::Options`](#structscy_1_1sockio_1_1Client_1_1Options)` & options,uv::Loop * loop)` - - - - - -# struct `scy::sockio::ClientState` - -``` -struct scy::sockio::ClientState - : public scy::State -``` - - - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public inline std::string str(unsigned int id) const` | - -## Members - -#### `public inline std::string str(unsigned int id) const` - - - - - -# struct `scy::sockio::Transaction` - -``` -struct scy::sockio::Transaction - : public scy::PacketTransaction< sockio::Packet > -``` - - - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public `[`sockio::Client`](./doc/api-socketio.md#classscy_1_1sockio_1_1Client)` & client` | -`public Transaction(`[`sockio::Client`](#classscy_1_1sockio_1_1Client)` & client,long timeout)` | -`public Transaction(`[`sockio::Client`](#classscy_1_1sockio_1_1Client)` & client,const `[`sockio::Packet`](#classscy_1_1sockio_1_1Packet)` & request,long timeout)` | -`public virtual bool send()` | -`public virtual bool checkResponse(const `[`sockio::Packet`](#classscy_1_1sockio_1_1Packet)` & packet)` | -`public virtual void onPotentialResponse(`[`sockio::Packet`](#classscy_1_1sockio_1_1Packet)` & packet)` | -`public virtual void onResponse()` | Called when a successful response is received. -`public inline virtual const char * className() const` | -`protected virtual ~Transaction()` | - -## Members - -#### `public `[`sockio::Client`](./doc/api-socketio.md#classscy_1_1sockio_1_1Client)` & client` - - - - - -#### `public Transaction(`[`sockio::Client`](#classscy_1_1sockio_1_1Client)` & client,long timeout)` - - - - - -#### `public Transaction(`[`sockio::Client`](#classscy_1_1sockio_1_1Client)` & client,const `[`sockio::Packet`](#classscy_1_1sockio_1_1Packet)` & request,long timeout)` - - - - - -#### `public virtual bool send()` - - - -Starts the transaction timer and sends the request. Overriding classes should implement send logic here. - -#### `public virtual bool checkResponse(const `[`sockio::Packet`](#classscy_1_1sockio_1_1Packet)` & packet)` - - - -Checks a potential response candidate and returns true on successful match. - -#### `public virtual void onPotentialResponse(`[`sockio::Packet`](#classscy_1_1sockio_1_1Packet)` & packet)` - - - - - -#### `public virtual void onResponse()` - -Called when a successful response is received. - - - -#### `public inline virtual const char * className() const` - - - - - -#### `protected virtual ~Transaction()` - - - - - -# struct `scy::sockio::Client::Options` - - - - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public std::string host` | -`public uint16_t port` | -`public bool reconnection` | Weather or not to reconnect if disconnected from the server. -`public int reconnectAttempts` | -`public int reconnectDelay` | -`public inline Options()` | - -## Members - -#### `public std::string host` - - - - - -#### `public uint16_t port` - - - - - -#### `public bool reconnection` - -Weather or not to reconnect if disconnected from the server. - - - -#### `public int reconnectAttempts` - - - -The number of times to attempt to reconnect if disconnected from the server. (0 = unlimited) - -#### `public int reconnectDelay` - - - - - -#### `public inline Options()` - - - - - diff --git a/doc/api-stun.md b/doc/api-stun.md index 3cd1ada5e..444549a1f 100644 --- a/doc/api-stun.md +++ b/doc/api-stun.md @@ -1,1181 +1,2145 @@ -# Module `stun` +# stun The `stun` module contains a STUN (rfc5389) implementation. -## Summary +### Classes - Members | Descriptions ---------------------------------|--------------------------------------------- -`namespace `[`scy::stun`](#namespacescy_1_1stun) | -# namespace `scy::stun` +| Name | Description | +|------|-------------| +| [`Attribute`](#classscy_1_1stun_1_1Attribute) | The virtual base class for all STUN/TURN attributes. | +| [`AddressAttribute`](#classscy_1_1stun_1_1AddressAttribute) | Implements a STUN/TURN attribute that contains a socket address. | +| [`UInt8Attribute`](#classscy_1_1stun_1_1UInt8Attribute) | Implements STUN/TURN attribute that reflects a 32-bit integer. | +| [`UInt32Attribute`](#classscy_1_1stun_1_1UInt32Attribute) | Implements STUN/TURN attribute that reflects a 32-bit integer. | +| [`UInt64Attribute`](#classscy_1_1stun_1_1UInt64Attribute) | Implements STUN/TURN attribute that reflects a 64-bit integer. | +| [`FlagAttribute`](#classscy_1_1stun_1_1FlagAttribute) | Implements STUN/TURN attribute representing a 0 size flag. | +| [`StringAttribute`](#classscy_1_1stun_1_1StringAttribute) | Implements STUN/TURN attribute that reflects an arbitrary byte string. | +| [`UInt16ListAttribute`](#classscy_1_1stun_1_1UInt16ListAttribute) | Implements STUN/TURN attribute that reflects a list of attribute names. | +| [`MessageIntegrity`](#classscy_1_1stun_1_1MessageIntegrity) | Implements STUN/TURN attributes that reflects an internet address. | +| [`ErrorCode`](#classscy_1_1stun_1_1ErrorCode) | Implements STUN/TURN attribute that reflects an error code. | +| [`Message`](#classscy_1_1stun_1_1Message) | | +| [`Transaction`](#classscy_1_1stun_1_1Transaction) | | +### Members +| Name | Description | +|------|-------------| +| [`STUN_API`](#group__stun_1gac8f9e71a23b67649cae4888b67270410) | | -## Summary +--- - Members | Descriptions ---------------------------------|--------------------------------------------- -`class `[`scy::stun::AddressAttribute`](#classscy_1_1stun_1_1AddressAttribute) | Implements a STUN/TURN attribute that contains a socket address. -`class `[`scy::stun::Attribute`](#classscy_1_1stun_1_1Attribute) | The virtual base class for all STUN/TURN attributes. -`class `[`scy::stun::ErrorCode`](#classscy_1_1stun_1_1ErrorCode) | Implements STUN/TURN attribute that reflects an error code. -`class `[`scy::stun::FlagAttribute`](#classscy_1_1stun_1_1FlagAttribute) | Implements STUN/TURN attribute representing a 0 size flag. -`class `[`scy::stun::Message`](#classscy_1_1stun_1_1Message) | -`class `[`scy::stun::MessageIntegrity`](#classscy_1_1stun_1_1MessageIntegrity) | Implements STUN/TURN attributes that reflects an internet address. -`class `[`scy::stun::StringAttribute`](#classscy_1_1stun_1_1StringAttribute) | Implements STUN/TURN attribute that reflects an arbitrary byte string. -`class `[`scy::stun::Transaction`](#classscy_1_1stun_1_1Transaction) | -`class `[`scy::stun::UInt16ListAttribute`](#classscy_1_1stun_1_1UInt16ListAttribute) | Implements STUN/TURN attribute that reflects a list of attribute names. -`class `[`scy::stun::UInt32Attribute`](#classscy_1_1stun_1_1UInt32Attribute) | Implements STUN/TURN attribute that reflects a 32-bit integer. -`class `[`scy::stun::UInt64Attribute`](#classscy_1_1stun_1_1UInt64Attribute) | Implements STUN/TURN attribute that reflects a 64-bit integer. -`class `[`scy::stun::UInt8Attribute`](#classscy_1_1stun_1_1UInt8Attribute) | Implements STUN/TURN attribute that reflects a 32-bit integer. -# class `scy::stun::AddressAttribute` +#### STUN_API +```cpp +STUN_API() ``` -class scy::stun::AddressAttribute - : public scy::stun::Attribute -``` - -Implements a STUN/TURN attribute that contains a socket address. - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public AddressAttribute(uint16_t type,bool ipv4)` | -`public AddressAttribute(const `[`AddressAttribute`](#classscy_1_1stun_1_1AddressAttribute)` & r)` | -`public virtual `[`stun::Attribute`](#classscy_1_1stun_1_1Attribute)` * clone()` | -`public inline `[`stun::AddressFamily`](#group__stun_1gaec260a57e19eb607c18301f58f80e7e1)` family() const` | -`public virtual `[`net::Address`](#classscy_1_1net_1_1Address)` address() const` | -`public virtual void read(`[`BitReader`](#classscy_1_1BitReader)` & reader)` | -`public virtual void write(`[`BitWriter`](#classscy_1_1BitWriter)` & writer) const` | -`public inline virtual void setAddress(const `[`net::Address`](#classscy_1_1net_1_1Address)` & addr)` | - -## Members - -#### `public AddressAttribute(uint16_t type,bool ipv4)` - - - - - -#### `public AddressAttribute(const `[`AddressAttribute`](#classscy_1_1stun_1_1AddressAttribute)` & r)` - - - - - -#### `public virtual `[`stun::Attribute`](#classscy_1_1stun_1_1Attribute)` * clone()` - - - - - -#### `public inline `[`stun::AddressFamily`](#group__stun_1gaec260a57e19eb607c18301f58f80e7e1)` family() const` - - - - - -#### `public virtual `[`net::Address`](#classscy_1_1net_1_1Address)` address() const` - - - - - -#### `public virtual void read(`[`BitReader`](#classscy_1_1BitReader)` & reader)` - - - -Reads the body (not the type or size) for this type of attribute from the given buffer. Return value is true if successful. - -#### `public virtual void write(`[`BitWriter`](#classscy_1_1BitWriter)` & writer) const` - - - -Writes the body (not the type or size) to the given buffer. Return value is true if successful. - -#### `public inline virtual void setAddress(const `[`net::Address`](#classscy_1_1net_1_1Address)` & addr)` - - +## Attribute - -# class `scy::stun::Attribute` - +> **Subclasses:** `scy::stun::AddressAttribute`, `scy::stun::ErrorCode`, `scy::stun::FlagAttribute`, `scy::stun::MessageIntegrity`, `scy::stun::StringAttribute`, `scy::stun::UInt16ListAttribute`, `scy::stun::UInt32Attribute`, `scy::stun::UInt64Attribute`, `scy::stun::UInt8Attribute` +> **Defined in:** `attributes.h` The virtual base class for all STUN/TURN attributes. +### Members + +| Name | Description | +|------|-------------| +| [`Type`](#group__stun_1ga58f9974b99873c21b541593d70751f76) | | +| [`~Attribute`](#group__stun_1ga3d20ce1b5f294cccb1ceecfd7dde685b) | | +| [`clone`](#group__stun_1gac70507d30dee5fc90020e5b4a13b5762) | | +| [`read`](#group__stun_1ga7a8eaf6fae7ce506dead82c972fee53d) | Reads the body (not the type or size) for this type of attribute from the given buffer. Return value is true if successful. | +| [`write`](#group__stun_1ga57e4567afce55ae046a19e20d5c96cb8) | Writes the body (not the type or size) to the given buffer. Return value is true if successful. | +| [`type`](#group__stun_1ga327f31a9e5e89e630fa29bf4d48476ea) | | +| [`size`](#group__stun_1gaafbe6576c2b87a33cf0faceec8da4e34) | | +| [`consumePadding`](#group__stun_1ga49af5c5548066acb3de3553218ba04e4) | | +| [`writePadding`](#group__stun_1ga9337ef7bb7032ea501938e7713f7bc99) | | +| [`typeString`](#group__stun_1ga11de2203671a16db2e059abaade0d148) | | +| [`create`](#group__stun_1ga24c455ae024130e437d90515a1ab07bb) | Creates an attribute object with the given type and size. | +| [`typeString`](#group__stun_1ga8f507e68f6b2d62ac7ea3e44cd620601) | | +| [`Attribute`](#group__stun_1ga9e161b5d779864cb7b8127b5bef9d7e0) | | +| [`setLength`](#group__stun_1ga5958b14f8dc45b50f2c3183fc1d120bc) | | +| [`TypeID`](#group__stun_1ga6abc429b06d52e8873d4cd1a20e0ab44) | | +| [`_type`](#group__stun_1gab338ca1d4ab28668a4c639ec33b31e7c) | | +| [`_size`](#group__stun_1ga33b3b945c5f3d949e63c24506da36a72) | | + +--- + +#### Type + +```cpp +enum Type +``` +| Value | Description | +|-------|-------------| +| `NotExist` | | +| `MappedAddress` | | +| `ResponseAddress` | | +| `ChangeRequest` | | +| `SourceAddress` | | +| `ChangedAddress` | | +| `Username` | | +| `Password` | | +| `MessageIntegrity` | | +| `ErrorCode` | | +| `Bandwidth` | | +| `DestinationAddress` | | +| `UnknownAttributes` | | +| `ReflectedFrom` | | +| `MagicCookie` | | +| `Realm` | | +| `Nonce` | | +| `XorMappedAddress` | | +| `Software` | | +| `Options` | | +| `AlternateServer` | | +| `Fingerprint` | | +| `ChannelNumber` | TURN. | +| `Lifetime` | | +| `XorPeerAddress` | | +| `Data` | | +| `XorRelayedAddress` | | +| `EventPort` | | +| `RequestedTransport` | | +| `DontFragment` | | +| `ReservationToken` | 0x0021: Reserved (was TIMER-VAL) | +| `ConnectionID` | TURN TCP. | +| `ICEControlled` | ICE. | +| `ICEControlling` | | +| `ICEPriority` | | +| `ICEUseCandidate` | | + +--- + +#### ~Attribute + +```cpp +virtual inline ~Attribute() +``` -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public inline virtual ~Attribute()` | -`public `[`Attribute`](#classscy_1_1stun_1_1Attribute)` * clone()` | -`public void read(`[`BitReader`](#classscy_1_1BitReader)` & reader)` | -`public void write(`[`BitWriter`](#classscy_1_1BitWriter)` & writer) const` | -`public uint16_t type() const` | -`public uint16_t size() const` | -`public void consumePadding(`[`BitReader`](#classscy_1_1BitReader)` & reader) const` | -`public void writePadding(`[`BitWriter`](#classscy_1_1BitWriter)` & writer) const` | -`public std::string typeString()` | -`protected uint16_t _type` | -`protected uint16_t _size` | -`protected Attribute(uint16_t type,uint16_t size)` | -`protected void setLength(uint16_t size)` | - -## Members - -#### `public inline virtual ~Attribute()` - - - - - -#### `public `[`Attribute`](#classscy_1_1stun_1_1Attribute)` * clone()` - - +--- +#### clone +```cpp +std::unique_ptr< Attribute > clone() +``` -#### `public void read(`[`BitReader`](#classscy_1_1BitReader)` & reader)` +--- +#### read +```cpp +void read(BitReader & reader) +``` Reads the body (not the type or size) for this type of attribute from the given buffer. Return value is true if successful. -#### `public void write(`[`BitWriter`](#classscy_1_1BitWriter)` & writer) const` - - - -Writes the body (not the type or size) to the given buffer. Return value is true if successful. - -#### `public uint16_t type() const` - +| Parameter | Type | Description | +|-----------|------|-------------| +| `reader` | `BitReader &` | | +--- +#### write +```cpp +void write(BitWriter & writer) const +``` -#### `public uint16_t size() const` +Writes the body (not the type or size) to the given buffer. Return value is true if successful. +| Parameter | Type | Description | +|-----------|------|-------------| +| `writer` | `BitWriter &` | | +--- +#### type +```cpp +uint16_t type() const +``` -#### `public void consumePadding(`[`BitReader`](#classscy_1_1BitReader)` & reader) const` +--- +#### size +```cpp +uint16_t size() const +``` +--- +#### consumePadding -#### `public void writePadding(`[`BitWriter`](#classscy_1_1BitWriter)` & writer) const` +```cpp +void consumePadding(BitReader & reader) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `reader` | `BitReader &` | | +--- +#### writePadding +```cpp +void writePadding(BitWriter & writer) const +``` -#### `public std::string typeString()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `writer` | `BitWriter &` | | +--- +#### typeString +```cpp +std::string typeString() +``` +--- -#### `protected uint16_t _type` +#### create +```cpp +static std::unique_ptr< Attribute > create(uint16_t type, uint16_t size) +``` +Creates an attribute object with the given type and size. +| Parameter | Type | Description | +|-----------|------|-------------| +| `type` | `uint16_t` | | +| `size` | `uint16_t` | | +--- -#### `protected uint16_t _size` +#### typeString +```cpp +static std::string typeString(uint16_t type) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `type` | `uint16_t` | | +--- +#### Attribute -#### `protected Attribute(uint16_t type,uint16_t size)` +```cpp +Attribute(uint16_t type, uint16_t size) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `type` | `uint16_t` | | +| `size` | `uint16_t` | | +--- +#### setLength +```cpp +void setLength(uint16_t size) +``` -#### `protected void setLength(uint16_t size)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `size` | `uint16_t` | | +--- +#### TypeID +```cpp +const uint16_t TypeID = 0 +``` +--- -# class `scy::stun::ErrorCode` +#### _type +```cpp +uint16_t _type ``` -class scy::stun::ErrorCode - : public scy::stun::Attribute -``` - -Implements STUN/TURN attribute that reflects an error code. - +--- -## Summary +#### _size - Members | Descriptions ---------------------------------|--------------------------------------------- -`public ErrorCode(uint16_t size)` | -`public ErrorCode(const `[`ErrorCode`](#classscy_1_1stun_1_1ErrorCode)` & r)` | -`public virtual ~ErrorCode()` | -`public virtual `[`Attribute`](#classscy_1_1stun_1_1Attribute)` * clone()` | -`public void setErrorCode(int code)` | -`public void setReason(const std::string & reason)` | -`public int errorCode() const` | -`public inline uint8_t errorClass() const` | -`public inline uint8_t errorNumber() const` | -`public inline const std::string & reason() const` | -`public virtual void read(`[`BitReader`](#classscy_1_1BitReader)` & reader)` | -`public virtual void write(`[`BitWriter`](#classscy_1_1BitWriter)` & writer) const` | +```cpp +uint16_t _size +``` -## Members +## AddressAttribute -#### `public ErrorCode(uint16_t size)` +> **Extends:** `scy::stun::Attribute` +> **Defined in:** `attributes.h` +Implements a STUN/TURN attribute that contains a socket address. +### Members +| Name | Description | +|------|-------------| +| [`AddressAttribute`](#group__stun_1ga26532e946f35dd12074567cb9aa83a89) | | +| [`AddressAttribute`](#group__stun_1gab1889e0952a12fef4df481639ff5dfd6) | | +| [`clone`](#group__stun_1ga08f80db0eca11594774aa981fe087951) | | +| [`family`](#group__stun_1gaa211f6fa23b641e1c922595b1884c287) | | +| [`address`](#group__stun_1gae694a695a83a7310bb2c2da8e504353c) | | +| [`read`](#group__stun_1ga4277615adc80ec240e36aa21d198136a) | Reads the body (not the type or size) for this type of attribute from the given buffer. Return value is true if successful. | +| [`write`](#group__stun_1gad48cd7a0d308a23c0c4c4549bf3d6fbf) | Writes the body (not the type or size) to the given buffer. Return value is true if successful. | +| [`setAddress`](#group__stun_1ga6c71d6b0ab7739e63ef2eb58241501c1) | | +| [`IPv4Size`](#group__stun_1gafb2012ed9f02a84dad86e64a623c3369) | | +| [`IPv6Size`](#group__stun_1ga4a8505f95e92cbca1efdf9baaaf5e5c5) | | +| [`_address`](#group__stun_1gad05adfb619be3a9d6977eece3ecf1daa) | | +--- -#### `public ErrorCode(const `[`ErrorCode`](#classscy_1_1stun_1_1ErrorCode)` & r)` +#### AddressAttribute +```cpp +AddressAttribute(uint16_t type, bool ipv4) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `type` | `uint16_t` | | +| `ipv4` | `bool` | | +--- +#### AddressAttribute -#### `public virtual ~ErrorCode()` +```cpp +AddressAttribute(const AddressAttribute & r) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `r` | `const AddressAttribute &` | | +--- +#### clone +```cpp +virtual std::unique_ptr< Attribute > clone() +``` -#### `public virtual `[`Attribute`](#classscy_1_1stun_1_1Attribute)` * clone()` +--- +#### family +```cpp +inline stun::AddressFamily family() const +``` +--- +#### address -#### `public void setErrorCode(int code)` +```cpp +virtual net::Address address() const +``` +--- +#### read +```cpp +virtual void read(BitReader & reader) +``` +Reads the body (not the type or size) for this type of attribute from the given buffer. Return value is true if successful. -#### `public void setReason(const std::string & reason)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `reader` | `BitReader &` | | +--- +#### write +```cpp +virtual void write(BitWriter & writer) const +``` +Writes the body (not the type or size) to the given buffer. Return value is true if successful. -#### `public int errorCode() const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `writer` | `BitWriter &` | | +--- +#### setAddress +```cpp +virtual inline void setAddress(const net::Address & addr) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `addr` | `const net::Address &` | | -#### `public inline uint8_t errorClass() const` +--- +#### IPv4Size +```cpp +const uint16_t IPv4Size = 8 +``` +--- +#### IPv6Size -#### `public inline uint8_t errorNumber() const` +```cpp +const uint16_t IPv6Size = 20 +``` +--- +#### _address +```cpp +net::Address _address +``` +## UInt8Attribute -#### `public inline const std::string & reason() const` +> **Extends:** `scy::stun::Attribute` +> **Defined in:** `attributes.h` +Implements STUN/TURN attribute that reflects a 32-bit integer. +### Members +| Name | Description | +|------|-------------| +| [`UInt8Attribute`](#group__stun_1ga31a7ecc9da1ab6bb9aef4f84f912644c) | | +| [`UInt8Attribute`](#group__stun_1gae1a4c7c1a53211e52739bd68955a26dd) | | +| [`clone`](#group__stun_1ga285944fdf39bff63efd31a10d587769b) | | +| [`value`](#group__stun_1gaa2111055d94bd81a601e00397e45cc92) | | +| [`setValue`](#group__stun_1ga222451185a8a5a7f5430d02b76428ee6) | | +| [`getBit`](#group__stun_1gae230c8a7751d5edfd007cd34b6f56cca) | | +| [`setBit`](#group__stun_1ga05fb3927bbbb041bd82e06473b686cb3) | | +| [`read`](#group__stun_1gaab5390f9fbef3b2e7d5b64d65cb13fc7) | Reads the body (not the type or size) for this type of attribute from the given buffer. Return value is true if successful. | +| [`write`](#group__stun_1ga632e2485387980cf23a0761705b68a5f) | Writes the body (not the type or size) to the given buffer. Return value is true if successful. | +| [`Size`](#group__stun_1gaeb8f25eb585791829d527b726e2c2e84) | | +| [`_bits`](#group__stun_1gaa1803741db41034c1462a17f99a17633) | | +--- -#### `public virtual void read(`[`BitReader`](#classscy_1_1BitReader)` & reader)` +#### UInt8Attribute +```cpp +UInt8Attribute(uint16_t type) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `type` | `uint16_t` | | -Reads the body (not the type or size) for this type of attribute from the given buffer. Return value is true if successful. +--- -#### `public virtual void write(`[`BitWriter`](#classscy_1_1BitWriter)` & writer) const` +#### UInt8Attribute +```cpp +UInt8Attribute(const UInt8Attribute & r) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `r` | `const UInt8Attribute &` | | -Writes the body (not the type or size) to the given buffer. Return value is true if successful. +--- -# class `scy::stun::FlagAttribute` +#### clone +```cpp +virtual std::unique_ptr< Attribute > clone() ``` -class scy::stun::FlagAttribute - : public scy::stun::Attribute -``` -Implements STUN/TURN attribute representing a 0 size flag. +--- +#### value +```cpp +inline uint8_t value() const +``` -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public FlagAttribute(uint16_t type)` | -`public virtual `[`Attribute`](#classscy_1_1stun_1_1Attribute)` * clone()` | -`public inline virtual void read(`[`BitReader`](#classscy_1_1BitReader)` & reader)` | -`public inline virtual void write(`[`BitWriter`](#classscy_1_1BitWriter)` & writer) const` | +--- -## Members +#### setValue -#### `public FlagAttribute(uint16_t type)` +```cpp +inline void setValue(uint8_t bits) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `bits` | `uint8_t` | | +--- +#### getBit +```cpp +bool getBit(int index) const +``` -#### `public virtual `[`Attribute`](#classscy_1_1stun_1_1Attribute)` * clone()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `index` | `int` | | +--- +#### setBit +```cpp +void setBit(int index, bool value) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `index` | `int` | | +| `value` | `bool` | | -#### `public inline virtual void read(`[`BitReader`](#classscy_1_1BitReader)` & reader)` +--- +#### read +```cpp +virtual void read(BitReader & reader) +``` Reads the body (not the type or size) for this type of attribute from the given buffer. Return value is true if successful. -#### `public inline virtual void write(`[`BitWriter`](#classscy_1_1BitWriter)` & writer) const` - +| Parameter | Type | Description | +|-----------|------|-------------| +| `reader` | `BitReader &` | | +--- -Writes the body (not the type or size) to the given buffer. Return value is true if successful. - -# class `scy::stun::Message` +#### write +```cpp +virtual void write(BitWriter & writer) const ``` -class scy::stun::Message - : public scy::IPacket -``` - - +Writes the body (not the type or size) to the given buffer. Return value is true if successful. +| Parameter | Type | Description | +|-----------|------|-------------| +| `writer` | `BitWriter &` | | -## Summary +--- - Members | Descriptions ---------------------------------|--------------------------------------------- -`public Message()` | -`public Message(ClassType clss,`[`MethodType`](#group__stun_1gac2630e3f14c223cdb85801feb8f848ee)` meth)` | -`public Message(const `[`Message`](#classscy_1_1stun_1_1Message)` & that)` | -`public `[`Message`](#classscy_1_1stun_1_1Message)` & operator=(const `[`Message`](#classscy_1_1stun_1_1Message)` & that)` | -`public virtual ~Message()` | -`public virtual `[`IPacket`](#classscy_1_1IPacket)` * clone() const` | -`public void setClass(ClassType type)` | -`public void setMethod(`[`MethodType`](#group__stun_1gac2630e3f14c223cdb85801feb8f848ee)` type)` | -`public void setTransactionID(const std::string & id)` | -`public ClassType classType() const` | -`public `[`MethodType`](#group__stun_1gac2630e3f14c223cdb85801feb8f848ee)` methodType() const` | -`public inline const TransactionID & transactionID() const` | -`public inline const std::vector< `[`Attribute`](#classscy_1_1stun_1_1Attribute)` * > attrs() const` | -`public inline virtual size_t size() const` | -`public std::string methodString() const` | -`public std::string classString() const` | -`public std::string errorString(uint16_t errorCode) const` | -`public void add(`[`Attribute`](#classscy_1_1stun_1_1Attribute)` * attr)` | -`public `[`Attribute`](#classscy_1_1stun_1_1Attribute)` * get(`[`Attribute::Type`](#group__stun_1ga58f9974b99873c21b541593d70751f76)` type,int index) const` | -`public template`
`inline T * get(int index) const` | -`public virtual ssize_t read(const `[`ConstBuffer`](#classscy_1_1ConstBuffer)` & buf)` | -`public virtual void write(`[`Buffer`](#group__base_1gab10b36b080deb583ed703fca6b63ffdd)` & buf) const` | Writes this object into a STUN/TURN packet. -`public std::string toString() const` | -`public virtual void print(std::ostream & os) const` | -`public inline virtual const char * className() const` | -`protected uint16_t _class` | -`protected uint16_t _method` | -`protected uint16_t _size` | -`protected TransactionID _transactionID` | -`protected std::vector< `[`Attribute`](./doc/api-stun.md#classscy_1_1stun_1_1Attribute)` * > _attrs` | +#### Size -## Members +```cpp +const uint16_t Size = 1 +``` -#### `public Message()` +--- +#### _bits +```cpp +uint8_t _bits +``` +## UInt32Attribute +> **Extends:** `scy::stun::Attribute` +> **Defined in:** `attributes.h` -#### `public Message(ClassType clss,`[`MethodType`](#group__stun_1gac2630e3f14c223cdb85801feb8f848ee)` meth)` +Implements STUN/TURN attribute that reflects a 32-bit integer. +### Members +| Name | Description | +|------|-------------| +| [`UInt32Attribute`](#group__stun_1ga3a756731e38a290ec92b77ac9b3dbc78) | | +| [`UInt32Attribute`](#group__stun_1ga0bf66ed373b22ff7629d82410fa4209a) | | +| [`clone`](#group__stun_1ga50ffdd5a4e24b8049bdd98fc0f9a578f) | | +| [`value`](#group__stun_1ga7a2fd11c9ca9b6c27f16efe46b0adfbd) | | +| [`setValue`](#group__stun_1gaf2e4cb4c7d16d53650c1a061c744472f) | | +| [`getBit`](#group__stun_1gabe7f310ea52d35848ff63ae5e02ef153) | | +| [`setBit`](#group__stun_1ga9745eaf379f6449f0a9aa3723cb342f2) | | +| [`read`](#group__stun_1ga336e05c124918d3e9046fb1b2f66cf09) | Reads the body (not the type or size) for this type of attribute from the given buffer. Return value is true if successful. | +| [`write`](#group__stun_1gaf41984e4e8cf61d64d88b1dfbe6e78c7) | Writes the body (not the type or size) to the given buffer. Return value is true if successful. | +| [`Size`](#group__stun_1ga3bd72ce4cd5089c44bdd15cbb651b656) | | +| [`_bits`](#group__stun_1gaa5deff7c7ea8a916ff518efb848834b3) | | +--- +#### UInt32Attribute -#### `public Message(const `[`Message`](#classscy_1_1stun_1_1Message)` & that)` +```cpp +UInt32Attribute(uint16_t type) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `type` | `uint16_t` | | +--- +#### UInt32Attribute +```cpp +UInt32Attribute(const UInt32Attribute & r) +``` -#### `public `[`Message`](#classscy_1_1stun_1_1Message)` & operator=(const `[`Message`](#classscy_1_1stun_1_1Message)` & that)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `r` | `const UInt32Attribute &` | | +--- +#### clone +```cpp +virtual std::unique_ptr< Attribute > clone() +``` +--- -#### `public virtual ~Message()` +#### value +```cpp +inline uint32_t value() const +``` +--- +#### setValue +```cpp +inline void setValue(uint32_t bits) +``` -#### `public virtual `[`IPacket`](#classscy_1_1IPacket)` * clone() const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `bits` | `uint32_t` | | +--- +#### getBit +```cpp +bool getBit(int index) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `index` | `int` | | -#### `public void setClass(ClassType type)` +--- +#### setBit +```cpp +void setBit(int index, bool value) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `index` | `int` | | +| `value` | `bool` | | +--- -#### `public void setMethod(`[`MethodType`](#group__stun_1gac2630e3f14c223cdb85801feb8f848ee)` type)` +#### read +```cpp +virtual void read(BitReader & reader) +``` +Reads the body (not the type or size) for this type of attribute from the given buffer. Return value is true if successful. +| Parameter | Type | Description | +|-----------|------|-------------| +| `reader` | `BitReader &` | | +--- -#### `public void setTransactionID(const std::string & id)` +#### write +```cpp +virtual void write(BitWriter & writer) const +``` +Writes the body (not the type or size) to the given buffer. Return value is true if successful. +| Parameter | Type | Description | +|-----------|------|-------------| +| `writer` | `BitWriter &` | | +--- -#### `public ClassType classType() const` +#### Size +```cpp +const uint16_t Size = 4 +``` +--- +#### _bits +```cpp +uint32_t _bits +``` -#### `public `[`MethodType`](#group__stun_1gac2630e3f14c223cdb85801feb8f848ee)` methodType() const` +## UInt64Attribute +> **Extends:** `scy::stun::Attribute` +> **Defined in:** `attributes.h` +Implements STUN/TURN attribute that reflects a 64-bit integer. +### Members +| Name | Description | +|------|-------------| +| [`UInt64Attribute`](#group__stun_1ga65fc4d0c4d7140af12a61457b0a89c9e) | | +| [`UInt64Attribute`](#group__stun_1gae47d568c25008f4d3a6f85c540b0d3bd) | | +| [`clone`](#group__stun_1ga9903c1b451344bba8e6dd41402e9217d) | | +| [`value`](#group__stun_1ga986e86dcf77f87c37e4b0ef5cd02ae48) | | +| [`setValue`](#group__stun_1gaac2af4e0ddd4d677e02c4cae2d3360f5) | | +| [`getBit`](#group__stun_1ga6de43e36aa136e9b6a14e9821b5038e7) | | +| [`setBit`](#group__stun_1ga48748faff06ececd74ef35a1410ca2f6) | | +| [`read`](#group__stun_1ga33044c201fbeac3902f69cb7a6ec05f5) | Reads the body (not the type or size) for this type of attribute from the given buffer. Return value is true if successful. | +| [`write`](#group__stun_1ga286f0a969b1a57a3587e04b630a783ce) | Writes the body (not the type or size) to the given buffer. Return value is true if successful. | +| [`Size`](#group__stun_1ga272ae90692c75840b76ec27cc84ce594) | | +| [`_bits`](#group__stun_1gae4178ca4345081da2f7f3c610458069e) | | -#### `public inline const TransactionID & transactionID() const` +--- +#### UInt64Attribute +```cpp +UInt64Attribute(uint16_t type) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `type` | `uint16_t` | | +--- -#### `public inline const std::vector< `[`Attribute`](#classscy_1_1stun_1_1Attribute)` * > attrs() const` +#### UInt64Attribute +```cpp +UInt64Attribute(const UInt64Attribute & r) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `r` | `const UInt64Attribute &` | | +--- +#### clone -#### `public inline virtual size_t size() const` +```cpp +virtual std::unique_ptr< Attribute > clone() +``` +--- +#### value -The size of the packet in bytes. +```cpp +inline uint64_t value() const +``` -This is the nember of bytes that will be written on a call to [write()](#group__stun_1ga3c6edd2eda4563ce398271ca1e398f2f), but may not be the number of bytes that will be consumed by [read()](#group__stun_1ga5277c8889063ec2d13b50de692a0f544). +--- -#### `public std::string methodString() const` +#### setValue +```cpp +inline void setValue(uint64_t bits) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `bits` | `uint64_t` | | +--- +#### getBit -#### `public std::string classString() const` +```cpp +bool getBit(int index) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `index` | `int` | | +--- +#### setBit +```cpp +void setBit(int index, bool value) +``` -#### `public std::string errorString(uint16_t errorCode) const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `index` | `int` | | +| `value` | `bool` | | +--- +#### read +```cpp +virtual void read(BitReader & reader) +``` +Reads the body (not the type or size) for this type of attribute from the given buffer. Return value is true if successful. -#### `public void add(`[`Attribute`](#classscy_1_1stun_1_1Attribute)` * attr)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `reader` | `BitReader &` | | +--- +#### write +```cpp +virtual void write(BitWriter & writer) const +``` +Writes the body (not the type or size) to the given buffer. Return value is true if successful. -#### `public `[`Attribute`](#classscy_1_1stun_1_1Attribute)` * get(`[`Attribute::Type`](#group__stun_1ga58f9974b99873c21b541593d70751f76)` type,int index) const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `writer` | `BitWriter &` | | +--- +#### Size +```cpp +const uint16_t Size = 8 +``` +--- -#### `public template`
`inline T * get(int index) const` +#### _bits +```cpp +uint64_t _bits +``` +## FlagAttribute +> **Extends:** `scy::stun::Attribute` +> **Defined in:** `attributes.h` +Implements STUN/TURN attribute representing a 0 size flag. -#### `public virtual ssize_t read(const `[`ConstBuffer`](#classscy_1_1ConstBuffer)` & buf)` +### Members +| Name | Description | +|------|-------------| +| [`FlagAttribute`](#group__stun_1ga3d77e3070134506d8f106ee70e09ac27) | | +| [`clone`](#group__stun_1ga46ddc45c2f45e6e3cf5df8beaadd66d0) | | +| [`read`](#group__stun_1ga797d67dc26d1b0eb52ff1b995b410200) | Reads the body (not the type or size) for this type of attribute from the given buffer. Return value is true if successful. | +| [`write`](#group__stun_1ga0397db5d05fc7fe0ae4a6877ccf1a37d) | Writes the body (not the type or size) to the given buffer. Return value is true if successful. | +| [`Size`](#group__stun_1gab159d8904434b86d4113e3a8ca6ef509) | | +--- -Parses the STUN/TURN packet from the given buffer. The return value indicates the number of bytes read. +#### FlagAttribute -#### `public virtual void write(`[`Buffer`](#group__base_1gab10b36b080deb583ed703fca6b63ffdd)` & buf) const` +```cpp +FlagAttribute(uint16_t type) +``` -Writes this object into a STUN/TURN packet. +| Parameter | Type | Description | +|-----------|------|-------------| +| `type` | `uint16_t` | | +--- +#### clone -#### `public std::string toString() const` +```cpp +virtual std::unique_ptr< Attribute > clone() +``` +--- +#### read +```cpp +virtual inline void read(BitReader & reader) +``` +Reads the body (not the type or size) for this type of attribute from the given buffer. Return value is true if successful. -#### `public virtual void print(std::ostream & os) const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `reader` | `BitReader &` | | +--- +#### write +```cpp +virtual inline void write(BitWriter & writer) const +``` +Writes the body (not the type or size) to the given buffer. Return value is true if successful. -#### `public inline virtual const char * className() const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `writer` | `BitWriter &` | | +--- +#### Size +```cpp +const uint16_t Size = 0 +``` +## StringAttribute -#### `protected uint16_t _class` +> **Extends:** `scy::stun::Attribute` +> **Defined in:** `attributes.h` +Implements STUN/TURN attribute that reflects an arbitrary byte string. +### Members + +| Name | Description | +|------|-------------| +| [`StringAttribute`](#group__stun_1gadc6a297cfcfa9c94fddef844138837ab) | | +| [`StringAttribute`](#group__stun_1ga6e51e83ff47fc75c46e8da2f87c338bf) | | +| [`~StringAttribute`](#group__stun_1ga44630835710accc66471ff5b43c19e87) | | +| [`clone`](#group__stun_1gab8166601b80abb25c2e4e6c5444680ea) | | +| [`bytes`](#group__stun_1ga3994fa1ebbe5dfd6e2814de47da07f3d) | | +| [`setBytes`](#group__stun_1ga4ed88f8e4e00fbd0ba5fd601d5ff55e5) | | +| [`asString`](#group__stun_1ga88fca368c8e188b41114f4cdea79e79b) | | +| [`copyBytes`](#group__stun_1gace004bc4eda7af876d91f1b7e5a01d02) | | +| [`copyBytes`](#group__stun_1ga3480d63f8b4d93697092fba0bdfd2e4d) | | +| [`getByte`](#group__stun_1ga8ad00fc7dfc7f4661ca2017271f4125b) | | +| [`setByte`](#group__stun_1gac45f8d1e10aeb2806f4fed85e6f8cd37) | | +| [`read`](#group__stun_1gabbb6dc3ce9fce25efb2225806a87cb80) | Reads the body (not the type or size) for this type of attribute from the given buffer. Return value is true if successful. | +| [`write`](#group__stun_1ga1e9de7ae89ad743833a88413b09921d2) | Writes the body (not the type or size) to the given buffer. Return value is true if successful. | +| [`_bytes`](#group__stun_1ga39143ccdeb16edc0f5b38f471a2c0c1d) | | + +--- + +#### StringAttribute + +```cpp +StringAttribute(uint16_t type, uint16_t size) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `type` | `uint16_t` | | +| `size` | `uint16_t` | | +--- -#### `protected uint16_t _method` +#### StringAttribute +```cpp +StringAttribute(const StringAttribute & r) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `r` | `const StringAttribute &` | | +--- +#### ~StringAttribute -#### `protected uint16_t _size` +```cpp +virtual ~StringAttribute() +``` +--- +#### clone +```cpp +virtual std::unique_ptr< Attribute > clone() +``` +--- -#### `protected TransactionID _transactionID` +#### bytes +```cpp +inline const char * bytes() const +``` +--- +#### setBytes +```cpp +void setBytes(const char * bytes, unsigned size) +``` -#### `protected std::vector< `[`Attribute`](./doc/api-stun.md#classscy_1_1stun_1_1Attribute)` * > _attrs` +| Parameter | Type | Description | +|-----------|------|-------------| +| `bytes` | `const char *` | | +| `size` | `unsigned` | | +--- +#### asString +```cpp +std::string asString() const +``` +--- -# class `scy::stun::MessageIntegrity` +#### copyBytes +```cpp +void copyBytes(const char * bytes) ``` -class scy::stun::MessageIntegrity - : public scy::stun::Attribute -``` - -Implements STUN/TURN attributes that reflects an internet address. +| Parameter | Type | Description | +|-----------|------|-------------| +| `bytes` | `const char *` | | +--- -## Summary +#### copyBytes - Members | Descriptions ---------------------------------|--------------------------------------------- -`public MessageIntegrity()` | -`public MessageIntegrity(const `[`MessageIntegrity`](#classscy_1_1stun_1_1MessageIntegrity)` & r)` | -`public virtual ~MessageIntegrity()` | -`public virtual `[`Attribute`](#classscy_1_1stun_1_1Attribute)` * clone()` | -`public bool verifyHmac(const std::string & key) const` | -`public inline std::string input() const` | -`public inline std::string hmac() const` | -`public inline std::string key() const` | -`public inline void setInput(const std::string & input)` | -`public inline void setHmac(const std::string & hmac)` | -`public inline void setKey(const std::string & key)` | -`public virtual void read(`[`BitReader`](#classscy_1_1BitReader)` & reader)` | -`public virtual void write(`[`BitWriter`](#classscy_1_1BitWriter)` & writer) const` | +```cpp +void copyBytes(const void * bytes, unsigned size) +``` -## Members +| Parameter | Type | Description | +|-----------|------|-------------| +| `bytes` | `const void *` | | +| `size` | `unsigned` | | -#### `public MessageIntegrity()` +--- +#### getByte +```cpp +uint8_t getByte(int index) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `index` | `int` | | +--- -#### `public MessageIntegrity(const `[`MessageIntegrity`](#classscy_1_1stun_1_1MessageIntegrity)` & r)` +#### setByte +```cpp +void setByte(int index, uint8_t value) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `index` | `int` | | +| `value` | `uint8_t` | | +--- +#### read -#### `public virtual ~MessageIntegrity()` +```cpp +virtual void read(BitReader & reader) +``` +Reads the body (not the type or size) for this type of attribute from the given buffer. Return value is true if successful. +| Parameter | Type | Description | +|-----------|------|-------------| +| `reader` | `BitReader &` | | +--- +#### write -#### `public virtual `[`Attribute`](#classscy_1_1stun_1_1Attribute)` * clone()` +```cpp +virtual void write(BitWriter & writer) const +``` +Writes the body (not the type or size) to the given buffer. Return value is true if successful. +| Parameter | Type | Description | +|-----------|------|-------------| +| `writer` | `BitWriter &` | | +--- +#### _bytes -#### `public bool verifyHmac(const std::string & key) const` +```cpp +std::vector< char > _bytes +``` +## UInt16ListAttribute +> **Extends:** `scy::stun::Attribute` +> **Defined in:** `attributes.h` +Implements STUN/TURN attribute that reflects a list of attribute names. +### Members -#### `public inline std::string input() const` +| Name | Description | +|------|-------------| +| [`UInt16ListAttribute`](#group__stun_1ga30618de614e5bcccd94b2eb3476f5150) | | +| [`UInt16ListAttribute`](#group__stun_1ga41111abd042a5eabd072a592e423a293) | | +| [`~UInt16ListAttribute`](#group__stun_1gacc94c85b8a1b73a30b6a764e40685940) | | +| [`clone`](#group__stun_1gade90ae784fb78df631002185d7d73f6a) | | +| [`size`](#group__stun_1ga804d0d2ac328075bd20e570ff9e7092b) | | +| [`getType`](#group__stun_1ga59b9881a1c5ed1c516134aa9d7961fac) | | +| [`setType`](#group__stun_1ga404efd93fa166215b2181097290cb6eb) | | +| [`addType`](#group__stun_1gacd1c6bcf94ad054a67910a38da04f803) | | +| [`read`](#group__stun_1gad0591118478c524485107997abfef834) | Reads the body (not the type or size) for this type of attribute from the given buffer. Return value is true if successful. | +| [`write`](#group__stun_1ga7807f8a64746aa49a1a81d9c494de1d6) | Writes the body (not the type or size) to the given buffer. Return value is true if successful. | +| [`_attrTypes`](#group__stun_1ga2b6dbf667c7b48e8bab3002037438f9c) | | +--- +#### UInt16ListAttribute +```cpp +UInt16ListAttribute(uint16_t type, uint16_t size) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `type` | `uint16_t` | | +| `size` | `uint16_t` | | -#### `public inline std::string hmac() const` +--- +#### UInt16ListAttribute +```cpp +UInt16ListAttribute(const UInt16ListAttribute & r) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `r` | `const UInt16ListAttribute &` | | +--- -#### `public inline std::string key() const` +#### ~UInt16ListAttribute +```cpp +virtual ~UInt16ListAttribute() +``` +--- +#### clone +```cpp +virtual std::unique_ptr< Attribute > clone() +``` -#### `public inline void setInput(const std::string & input)` +--- +#### size +```cpp +size_t size() const +``` +--- +#### getType -#### `public inline void setHmac(const std::string & hmac)` +```cpp +uint16_t getType(int index) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `index` | `int` | | +--- +#### setType +```cpp +void setType(int index, uint16_t value) +``` -#### `public inline void setKey(const std::string & key)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `index` | `int` | | +| `value` | `uint16_t` | | +--- +#### addType +```cpp +void addType(uint16_t value) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `value` | `uint16_t` | | -#### `public virtual void read(`[`BitReader`](#classscy_1_1BitReader)` & reader)` +--- +#### read +```cpp +virtual void read(BitReader & reader) +``` Reads the body (not the type or size) for this type of attribute from the given buffer. Return value is true if successful. -#### `public virtual void write(`[`BitWriter`](#classscy_1_1BitWriter)` & writer) const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `reader` | `BitReader &` | | +--- +#### write -Writes the body (not the type or size) to the given buffer. Return value is true if successful. - -# class `scy::stun::StringAttribute` - +```cpp +virtual void write(BitWriter & writer) const ``` -class scy::stun::StringAttribute - : public scy::stun::Attribute -``` - -Implements STUN/TURN attribute that reflects an arbitrary byte string. - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public StringAttribute(uint16_t type,uint16_t size)` | -`public StringAttribute(const `[`StringAttribute`](#classscy_1_1stun_1_1StringAttribute)` & r)` | -`public virtual ~StringAttribute()` | -`public virtual `[`Attribute`](#classscy_1_1stun_1_1Attribute)` * clone()` | -`public inline const char * bytes() const` | -`public void setBytes(char * bytes,unsigned size)` | -`public std::string asString() const` | -`public void copyBytes(const char * bytes)` | -`public void copyBytes(const void * bytes,unsigned size)` | -`public uint8_t getByte(int index) const` | -`public void setByte(int index,uint8_t value)` | -`public virtual void read(`[`BitReader`](#classscy_1_1BitReader)` & reader)` | -`public virtual void write(`[`BitWriter`](#classscy_1_1BitWriter)` & writer) const` | - -## Members - -#### `public StringAttribute(uint16_t type,uint16_t size)` - - - - - -#### `public StringAttribute(const `[`StringAttribute`](#classscy_1_1stun_1_1StringAttribute)` & r)` - - - - - -#### `public virtual ~StringAttribute()` +Writes the body (not the type or size) to the given buffer. Return value is true if successful. +| Parameter | Type | Description | +|-----------|------|-------------| +| `writer` | `BitWriter &` | | +--- +#### _attrTypes -#### `public virtual `[`Attribute`](#classscy_1_1stun_1_1Attribute)` * clone()` +```cpp +std::vector< uint16_t > _attrTypes +``` +## MessageIntegrity +> **Extends:** `scy::stun::Attribute` +> **Defined in:** `attributes.h` +Implements STUN/TURN attributes that reflects an internet address. +### Members + +| Name | Description | +|------|-------------| +| [`MessageIntegrity`](#group__stun_1ga6d3a6a3407b970154055dbe446670c8f) | | +| [`MessageIntegrity`](#group__stun_1ga0694d43ce6dc45ba4a11feffcf3c739b) | | +| [`~MessageIntegrity`](#group__stun_1gac74f0c9b519ad52390a6a4c231f9e60a) | | +| [`clone`](#group__stun_1ga0f9395fa807db78156ed21da4fd908ae) | | +| [`verifyHmac`](#group__stun_1gac299a78f8fa192ac0ae022ede8abaad1) | | +| [`input`](#group__stun_1ga403625dab98075c2b89fe8a65a9c0360) | | +| [`hmac`](#group__stun_1ga7d79aa318b53e4414af5669f911ec13b) | | +| [`key`](#group__stun_1ga0f30d8f2c2a6d93893ac5a520bfd9f4f) | | +| [`setInput`](#group__stun_1ga68372c04e7f849e206c8ceb5f0a19e3b) | | +| [`setHmac`](#group__stun_1gad71c737937a85fd4af54f6529d30d739) | | +| [`setKey`](#group__stun_1gaeafda2d185a37768cf3c1537bfa48447) | | +| [`read`](#group__stun_1gaf313ec3f5940d7dccaa8b9f9789dcedc) | Reads the body (not the type or size) for this type of attribute from the given buffer. Return value is true if successful. | +| [`write`](#group__stun_1ga25627d6670f7291f232c0ef65652c3ce) | Writes the body (not the type or size) to the given buffer. Return value is true if successful. | +| [`TypeID`](#group__stun_1ga4ed5e79ac9774b70be2b0833fbe193c4) | | +| [`Size`](#group__stun_1ga7f13e95256860a85ed679ea056a7fca1) | | +| [`_input`](#group__stun_1gac8a5a832e1b3107720359adfecce088a) | | +| [`_hmac`](#group__stun_1ga77f3a0fbb7cb13ddf7261775c885f5c2) | | +| [`_key`](#group__stun_1ga7441361a9d0be7ff9d3de74b5b09d81c) | | + +--- + +#### MessageIntegrity + +```cpp +MessageIntegrity() +``` -#### `public inline const char * bytes() const` +--- +#### MessageIntegrity +```cpp +MessageIntegrity(const MessageIntegrity & r) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `r` | `const MessageIntegrity &` | | +--- -#### `public void setBytes(char * bytes,unsigned size)` +#### ~MessageIntegrity +```cpp +virtual ~MessageIntegrity() +``` +--- +#### clone +```cpp +virtual std::unique_ptr< Attribute > clone() +``` -#### `public std::string asString() const` +--- +#### verifyHmac +```cpp +bool verifyHmac(const std::string & key) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `const std::string &` | | +--- -#### `public void copyBytes(const char * bytes)` +#### input +```cpp +inline std::string input() const +``` +--- +#### hmac +```cpp +inline std::string hmac() const +``` -#### `public void copyBytes(const void * bytes,unsigned size)` +--- +#### key +```cpp +inline std::string key() const +``` +--- +#### setInput -#### `public uint8_t getByte(int index) const` +```cpp +inline void setInput(const std::string & input) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `input` | `const std::string &` | | +--- +#### setHmac +```cpp +inline void setHmac(const std::string & hmac) +``` -#### `public void setByte(int index,uint8_t value)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `hmac` | `const std::string &` | | +--- +#### setKey +```cpp +inline void setKey(const std::string & key) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `const std::string &` | | -#### `public virtual void read(`[`BitReader`](#classscy_1_1BitReader)` & reader)` +--- +#### read +```cpp +virtual void read(BitReader & reader) +``` Reads the body (not the type or size) for this type of attribute from the given buffer. Return value is true if successful. -#### `public virtual void write(`[`BitWriter`](#classscy_1_1BitWriter)` & writer) const` - +| Parameter | Type | Description | +|-----------|------|-------------| +| `reader` | `BitReader &` | | +--- -Writes the body (not the type or size) to the given buffer. Return value is true if successful. - -# class `scy::stun::Transaction` +#### write +```cpp +virtual void write(BitWriter & writer) const ``` -class scy::stun::Transaction - : public scy::net::Transaction< Message > -``` - - - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public Transaction(const net::Socket::Ptr & socket,const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddress,long timeout,int retries)` | -`public virtual bool checkResponse(const `[`Message`](#classscy_1_1stun_1_1Message)` & message)` | -`public virtual void onResponse()` | Called when a successful response match is received. -`protected virtual ~Transaction()` | - -## Members - -#### `public Transaction(const net::Socket::Ptr & socket,const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddress,long timeout,int retries)` - - - +Writes the body (not the type or size) to the given buffer. Return value is true if successful. -#### `public virtual bool checkResponse(const `[`Message`](#classscy_1_1stun_1_1Message)` & message)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `writer` | `BitWriter &` | | +--- +#### TypeID +```cpp +const uint16_t TypeID = 0x0008 +``` +--- -#### `public virtual void onResponse()` +#### Size -Called when a successful response match is received. +```cpp +const uint16_t Size = 20 +``` +--- +#### _input -#### `protected virtual ~Transaction()` +```cpp +std::string _input +``` +--- +#### _hmac +```cpp +std::string _hmac +``` +--- -# class `scy::stun::UInt16ListAttribute` +#### _key +```cpp +std::string _key ``` -class scy::stun::UInt16ListAttribute - : public scy::stun::Attribute -``` - -Implements STUN/TURN attribute that reflects a list of attribute names. +## ErrorCode +> **Extends:** `scy::stun::Attribute` +> **Defined in:** `attributes.h` -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public UInt16ListAttribute(uint16_t type,uint16_t size)` | -`public UInt16ListAttribute(const `[`UInt16ListAttribute`](#classscy_1_1stun_1_1UInt16ListAttribute)` & r)` | -`public virtual ~UInt16ListAttribute()` | -`public virtual `[`Attribute`](#classscy_1_1stun_1_1Attribute)` * clone()` | -`public size_t size() const` | -`public uint16_t getType(int index) const` | -`public void setType(int index,uint16_t value)` | -`public void addType(uint16_t value)` | -`public virtual void read(`[`BitReader`](#classscy_1_1BitReader)` & reader)` | -`public virtual void write(`[`BitWriter`](#classscy_1_1BitWriter)` & writer) const` | +Implements STUN/TURN attribute that reflects an error code. -## Members +### Members + +| Name | Description | +|------|-------------| +| [`ErrorCode`](#group__stun_1gaa1566110dab6203ac5174c1a4a62a8b5) | | +| [`ErrorCode`](#group__stun_1ga90128dc8b841038c32835371b84afa93) | | +| [`~ErrorCode`](#group__stun_1gadcf975e8279a398a328a16b75dc29ca5) | | +| [`clone`](#group__stun_1ga11296179ca068fe44eaa534435b95f21) | | +| [`setErrorCode`](#group__stun_1gabffcf45778d52bcb75550ca73f7c8f9e) | | +| [`setReason`](#group__stun_1ga84d94ef041ed8a5e0ddc63547ac86114) | | +| [`errorCode`](#group__stun_1gaca2120c5893bbf603e0b199a285008ae) | | +| [`errorClass`](#group__stun_1gaad4ad600c8374950f9416a270b9be653) | | +| [`errorNumber`](#group__stun_1gab4a6abf000b4c8eb05a10a4ed2576298) | | +| [`reason`](#group__stun_1ga7fbdfcae77268b78efa51b3c88a06a19) | | +| [`read`](#group__stun_1ga2ccdf73aeed8dc2e0442f8e3d9078ea6) | Reads the body (not the type or size) for this type of attribute from the given buffer. Return value is true if successful. | +| [`write`](#group__stun_1gabf64fa5d609d641a426dedf91bb6b321) | Writes the body (not the type or size) to the given buffer. Return value is true if successful. | +| [`TypeID`](#group__stun_1ga2b266f933243cfc5d1b482c2d9d14418) | | +| [`MinSize`](#group__stun_1gaf2b0fdc230464a7dcf82ba4fd1a7edfb) | | +| [`_class`](#group__stun_1gaef16158bf5274f1f6be3cdee05657ff2) | | +| [`_number`](#group__stun_1gaf197ddb57d24858028593c668bfcf1d8) | | +| [`_reason`](#group__stun_1ga65fec4754ab028da7cf437a9658de75c) | | + +--- + +#### ErrorCode + +```cpp +ErrorCode(uint16_t size) +``` -#### `public UInt16ListAttribute(uint16_t type,uint16_t size)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `size` | `uint16_t` | | +--- +#### ErrorCode +```cpp +ErrorCode(const ErrorCode & r) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `r` | `const ErrorCode &` | | -#### `public UInt16ListAttribute(const `[`UInt16ListAttribute`](#classscy_1_1stun_1_1UInt16ListAttribute)` & r)` +--- +#### ~ErrorCode +```cpp +virtual ~ErrorCode() +``` +--- +#### clone -#### `public virtual ~UInt16ListAttribute()` +```cpp +virtual std::unique_ptr< Attribute > clone() +``` +--- +#### setErrorCode +```cpp +void setErrorCode(int code) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `code` | `int` | | -#### `public virtual `[`Attribute`](#classscy_1_1stun_1_1Attribute)` * clone()` +--- +#### setReason +```cpp +void setReason(const std::string & reason) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `reason` | `const std::string &` | | +--- -#### `public size_t size() const` +#### errorCode +```cpp +int errorCode() const +``` +--- +#### errorClass +```cpp +inline uint8_t errorClass() const +``` -#### `public uint16_t getType(int index) const` +--- +#### errorNumber +```cpp +inline uint8_t errorNumber() const +``` +--- +#### reason -#### `public void setType(int index,uint16_t value)` +```cpp +inline const std::string & reason() const +``` +--- +#### read +```cpp +virtual void read(BitReader & reader) +``` +Reads the body (not the type or size) for this type of attribute from the given buffer. Return value is true if successful. -#### `public void addType(uint16_t value)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `reader` | `BitReader &` | | +--- +#### write +```cpp +virtual void write(BitWriter & writer) const +``` +Writes the body (not the type or size) to the given buffer. Return value is true if successful. -#### `public virtual void read(`[`BitReader`](#classscy_1_1BitReader)` & reader)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `writer` | `BitWriter &` | | +--- +#### TypeID -Reads the body (not the type or size) for this type of attribute from the given buffer. Return value is true if successful. +```cpp +const uint16_t TypeID = 0x0009 +``` -#### `public virtual void write(`[`BitWriter`](#classscy_1_1BitWriter)` & writer) const` +--- +#### MinSize +```cpp +const uint16_t MinSize = 4 +``` -Writes the body (not the type or size) to the given buffer. Return value is true if successful. +--- -# class `scy::stun::UInt32Attribute` +#### _class +```cpp +uint8_t _class ``` -class scy::stun::UInt32Attribute - : public scy::stun::Attribute -``` - -Implements STUN/TURN attribute that reflects a 32-bit integer. +--- +#### _number -## Summary +```cpp +uint8_t _number +``` - Members | Descriptions ---------------------------------|--------------------------------------------- -`public UInt32Attribute(uint16_t type)` | -`public UInt32Attribute(const `[`UInt32Attribute`](#classscy_1_1stun_1_1UInt32Attribute)` & r)` | -`public virtual `[`Attribute`](#classscy_1_1stun_1_1Attribute)` * clone()` | -`public inline uint32_t value() const` | -`public inline void setValue(uint32_t bits)` | -`public bool getBit(int index) const` | -`public void setBit(int index,bool value)` | -`public virtual void read(`[`BitReader`](#classscy_1_1BitReader)` & reader)` | -`public virtual void write(`[`BitWriter`](#classscy_1_1BitWriter)` & writer) const` | +--- -## Members +#### _reason -#### `public UInt32Attribute(uint16_t type)` +```cpp +std::string _reason +``` +## Message + +> **Extends:** `scy::IPacket` +> **Subclasses:** `scy::turn::Request` +> **Defined in:** `message.h` + +### Members + +| Name | Description | +|------|-------------| +| [`MethodType`](#group__stun_1gac2630e3f14c223cdb85801feb8f848ee) | | +| [`ClassType`](#group__stun_1ga13db6d75080f8b7a57bdb7b7d14cdba6) | | +| [`ErrorCodes`](#group__stun_1ga4dbaf25761edabeffc85d63482b3aac9) | | +| [`Message`](#group__stun_1ga87d2d455f130210e6ebdcf10d0318f12) | | +| [`Message`](#group__stun_1ga19a2f2943326de6b24e4364c136482bf) | | +| [`Message`](#group__stun_1ga871f9b3b19510574bae25bd42509a1e7) | | +| [`Message`](#group__stun_1ga3ab2bf6930a6cbe8c847ae0a1c0c374d) | | +| [`operator=`](#group__stun_1gaa7b3f543c5d432bb2b052820b42d9dbd) | | +| [`operator=`](#group__stun_1ga3217c09e360934d369b01dbf95edf5b0) | | +| [`~Message`](#group__stun_1ga4a2d3d7faa8d1fae09689521c719f0e3) | | +| [`clone`](#group__stun_1gab3b901af3b3812c59a1e6e495f9ff9bd) | | +| [`setClass`](#group__stun_1gab1616a105946047c77332b9e5caadaac) | | +| [`setMethod`](#group__stun_1gac7c6555f867fef8dd90c388d13ba2afa) | | +| [`setTransactionID`](#group__stun_1ga7e1341a7429f6b7199354fda9b235a02) | | +| [`classType`](#group__stun_1ga7243fa9b4b257cd1ed0a00ae6ed131af) | | +| [`methodType`](#group__stun_1ga6453d6cb76a0ac955cf7c2d049b8ccce) | | +| [`transactionID`](#group__stun_1ga7fa4f16f053aa4cefde0941a7cee5696) | | +| [`size`](#group__stun_1ga6ea0876dd3d70145cdd1944cf257cc89) | The size of the packet in bytes. | +| [`methodString`](#group__stun_1ga6cb46477fe5b8deca78bcfe3be57630c) | | +| [`classString`](#group__stun_1gae0caeab266e261ca5e0f904fbac29a2a) | | +| [`errorString`](#group__stun_1ga375de70d1b2e483534b9e152cdaa7e7f) | | +| [`add`](#group__stun_1ga6d8a672d498981ae3aaf6ae56b64ad57) | Takes ownership of the raw pointer (wraps in unique_ptr). | +| [`add`](#group__stun_1gab062ea939971d108f24ef5a1e83179b4) | Takes ownership via unique_ptr. | +| [`get`](#group__stun_1ga42b45b4a75a1c9a1b7f4e3ee8117e953) | | +| [`get`](#group__stun_1gae18ed3a5c629f860d1959b2c9a17ac45) | | +| [`read`](#group__stun_1ga5277c8889063ec2d13b50de692a0f544) | Parses the STUN/TURN packet from the given buffer. The return value indicates the number of bytes read. | +| [`write`](#group__stun_1ga3c6edd2eda4563ce398271ca1e398f2f) | Writes this object into a STUN/TURN packet. | +| [`toString`](#group__stun_1ga50c1ef178929f59e10581ce89f38dbea) | | +| [`print`](#group__stun_1gab7840803d8273b4343225476ed0c8b2a) | | +| [`className`](#group__stun_1ga71e77048a4f6e090e42bc441f83ce4c0) | | +| [`_class`](#group__stun_1gaa6eafc6984888611aa79354a1970d3dd) | | +| [`_method`](#group__stun_1ga4ae5ed97d42f01ae3556c2b9b4bc242f) | | +| [`_size`](#group__stun_1ga0f08193c20c1ff33348838fae495f4d7) | | +| [`_transactionID`](#group__stun_1ga664565d5c2616896d5128d84ca2a7f5f) | | +| [`_attrs`](#group__stun_1ga00b4d60b33f4d2693640e076f1c0bff3) | | + +--- + +#### MethodType + +```cpp +enum MethodType +``` +| Value | Description | +|-------|-------------| +| `Undefined` | default error type | +| `Binding` | STUN. | +| `Allocate` | TURN. | +| `Refresh` | | +| `SendIndication` | (only indication semantics defined) | +| `DataIndication` | (only indication semantics defined) | +| `CreatePermission` | (only request/response semantics defined) | +| `ChannelBind` | (only request/response semantics defined) | +| `Connect` | TURN TCP RFC 6062. | +| `ConnectionBind` | | +| `ConnectionAttempt` | | + +--- + +#### ClassType + +```cpp +enum ClassType +``` +| Value | Description | +|-------|-------------| +| `Request` | | +| `Indication` | | +| `SuccessResponse` | | +| `ErrorResponse` | | +--- -#### `public UInt32Attribute(const `[`UInt32Attribute`](#classscy_1_1stun_1_1UInt32Attribute)` & r)` +#### ErrorCodes +```cpp +enum ErrorCodes +``` +| Value | Description | +|-------|-------------| +| `BadRequest` | | +| `NotAuthorized` | | +| `UnknownAttribute` | | +| `StaleCredentials` | | +| `IntegrityCheckFailure` | | +| `MissingUsername` | | +| `UseTLS` | | +| `RoleConflict` | | +| `ServerError` | | +| `GlobalFailure` | | +| `ConnectionAlreadyExists` | TURN TCP. | +| `ConnectionTimeoutOrFailure` | | + +--- + +#### Message + +```cpp +Message() +``` +--- +#### Message -#### `public virtual `[`Attribute`](#classscy_1_1stun_1_1Attribute)` * clone()` +```cpp +Message(ClassType clss, MethodType meth) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `clss` | `ClassType` | | +| `meth` | `MethodType` | | +--- +#### Message +```cpp +Message(const Message & that) +``` -#### `public inline uint32_t value() const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `that` | `const Message &` | | +--- +#### Message +```cpp +Message(Message && that) noexcept +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `that` | `Message &&` | | -#### `public inline void setValue(uint32_t bits)` +--- +#### operator= +```cpp +Message & operator=(const Message & that) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `that` | `const Message &` | | +--- -#### `public bool getBit(int index) const` +#### operator= +```cpp +Message & operator=(Message && that) noexcept +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `that` | `Message &&` | | +--- +#### ~Message -#### `public void setBit(int index,bool value)` +```cpp +virtual ~Message() +``` +--- +#### clone +```cpp +virtual IPacket * clone() const +``` +--- -#### `public virtual void read(`[`BitReader`](#classscy_1_1BitReader)` & reader)` +#### setClass +```cpp +void setClass(ClassType type) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `type` | `ClassType` | | -Reads the body (not the type or size) for this type of attribute from the given buffer. Return value is true if successful. +--- -#### `public virtual void write(`[`BitWriter`](#classscy_1_1BitWriter)` & writer) const` +#### setMethod +```cpp +void setMethod(MethodType type) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `type` | `MethodType` | | -Writes the body (not the type or size) to the given buffer. Return value is true if successful. +--- -# class `scy::stun::UInt64Attribute` +#### setTransactionID +```cpp +void setTransactionID(const std::string & id) ``` -class scy::stun::UInt64Attribute - : public scy::stun::Attribute -``` -Implements STUN/TURN attribute that reflects a 64-bit integer. +| Parameter | Type | Description | +|-----------|------|-------------| +| `id` | `const std::string &` | | +--- +#### classType -## Summary +```cpp +ClassType classType() const +``` - Members | Descriptions ---------------------------------|--------------------------------------------- -`public UInt64Attribute(uint16_t type)` | -`public UInt64Attribute(const `[`UInt64Attribute`](#classscy_1_1stun_1_1UInt64Attribute)` & r)` | -`public virtual `[`Attribute`](#classscy_1_1stun_1_1Attribute)` * clone()` | -`public inline uint64_t value() const` | -`public inline void setValue(uint64_t bits)` | -`public bool getBit(int index) const` | -`public void setBit(int index,bool value)` | -`public virtual void read(`[`BitReader`](#classscy_1_1BitReader)` & reader)` | -`public virtual void write(`[`BitWriter`](#classscy_1_1BitWriter)` & writer) const` | +--- -## Members +#### methodType -#### `public UInt64Attribute(uint16_t type)` +```cpp +MethodType methodType() const +``` +--- +#### transactionID +```cpp +inline const TransactionID & transactionID() const +``` +--- -#### `public UInt64Attribute(const `[`UInt64Attribute`](#classscy_1_1stun_1_1UInt64Attribute)` & r)` +#### size +```cpp +virtual inline size_t size() const +``` +The size of the packet in bytes. +This is the nember of bytes that will be written on a call to [write()](#group__stun_1ga3c6edd2eda4563ce398271ca1e398f2f), but may not be the number of bytes that will be consumed by [read()](#group__stun_1ga5277c8889063ec2d13b50de692a0f544). +--- -#### `public virtual `[`Attribute`](#classscy_1_1stun_1_1Attribute)` * clone()` +#### methodString +```cpp +std::string methodString() const +``` +--- +#### classString +```cpp +std::string classString() const +``` -#### `public inline uint64_t value() const` +--- +#### errorString +```cpp +std::string errorString(uint16_t errorCode) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `errorCode` | `uint16_t` | | +--- -#### `public inline void setValue(uint64_t bits)` +#### add +```cpp +void add(Attribute * attr) +``` +Takes ownership of the raw pointer (wraps in unique_ptr). +| Parameter | Type | Description | +|-----------|------|-------------| +| `attr` | `Attribute *` | | +--- -#### `public bool getBit(int index) const` +#### add +```cpp +void add(std::unique_ptr< Attribute > attr) +``` +Takes ownership via unique_ptr. +| Parameter | Type | Description | +|-----------|------|-------------| +| `attr` | `std::unique_ptr< Attribute >` | | +--- -#### `public void setBit(int index,bool value)` +#### get +```cpp +Attribute * get(Attribute::Type type, int index) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `type` | `Attribute::Type` | | +| `index` | `int` | | +--- +#### get -#### `public virtual void read(`[`BitReader`](#classscy_1_1BitReader)` & reader)` +```cpp +template inline T * get(int index) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `index` | `int` | | +--- -Reads the body (not the type or size) for this type of attribute from the given buffer. Return value is true if successful. +#### read -#### `public virtual void write(`[`BitWriter`](#classscy_1_1BitWriter)` & writer) const` +```cpp +virtual ssize_t read(const ConstBuffer & buf) +``` +Parses the STUN/TURN packet from the given buffer. The return value indicates the number of bytes read. +| Parameter | Type | Description | +|-----------|------|-------------| +| `buf` | `const ConstBuffer &` | | -Writes the body (not the type or size) to the given buffer. Return value is true if successful. +--- -# class `scy::stun::UInt8Attribute` +#### write +```cpp +virtual void write(Buffer & buf) const ``` -class scy::stun::UInt8Attribute - : public scy::stun::Attribute -``` -Implements STUN/TURN attribute that reflects a 32-bit integer. - - - -## Summary +Writes this object into a STUN/TURN packet. - Members | Descriptions ---------------------------------|--------------------------------------------- -`public UInt8Attribute(uint16_t type)` | -`public UInt8Attribute(const `[`UInt8Attribute`](#classscy_1_1stun_1_1UInt8Attribute)` & r)` | -`public virtual `[`Attribute`](#classscy_1_1stun_1_1Attribute)` * clone()` | -`public inline uint8_t value() const` | -`public inline void setValue(uint8_t bits)` | -`public bool getBit(int index) const` | -`public void setBit(int index,bool value)` | -`public virtual void read(`[`BitReader`](#classscy_1_1BitReader)` & reader)` | -`public virtual void write(`[`BitWriter`](#classscy_1_1BitWriter)` & writer) const` | +| Parameter | Type | Description | +|-----------|------|-------------| +| `buf` | `Buffer &` | | -## Members +--- -#### `public UInt8Attribute(uint16_t type)` +#### toString +```cpp +std::string toString() const +``` +--- +#### print +```cpp +virtual void print(std::ostream & os) const +``` -#### `public UInt8Attribute(const `[`UInt8Attribute`](#classscy_1_1stun_1_1UInt8Attribute)` & r)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `os` | `std::ostream &` | | +--- +#### className +```cpp +virtual inline const char * className() const +``` +--- -#### `public virtual `[`Attribute`](#classscy_1_1stun_1_1Attribute)` * clone()` +#### _class +```cpp +uint16_t _class +``` +--- +#### _method +```cpp +uint16_t _method +``` -#### `public inline uint8_t value() const` +--- +#### _size +```cpp +uint16_t _size +``` +--- +#### _transactionID -#### `public inline void setValue(uint8_t bits)` +```cpp +TransactionID _transactionID +``` +--- +#### _attrs +```cpp +std::vector< std::unique_ptr< Attribute > > _attrs +``` +## Transaction -#### `public bool getBit(int index) const` +> **Extends:** `scy::net::Transaction< Message >` +> **Defined in:** `transaction.h` +### Members +| Name | Description | +|------|-------------| +| [`Transaction`](#group__stun_1gaa3eed85a17dc6869a699e7e9c030cca3) | | +| [`checkResponse`](#group__stun_1ga82ab3d79a18d478172c6b39cc6d7428a) | | +| [`onResponse`](#group__stun_1gabeecdd054fceca609f3fd449a323159f) | Called when a successful response match is received. | +| [`~Transaction`](#group__stun_1ga8ab19322de3bf9d004ff2dacbcee5daf) | | +--- +#### Transaction -#### `public void setBit(int index,bool value)` +```cpp +Transaction(const net::Socket::Ptr & socket, const net::Address & peerAddress, long timeout, int retries) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `socket` | `const net::Socket::Ptr &` | | +| `peerAddress` | `const net::Address &` | | +| `timeout` | `long` | | +| `retries` | `int` | | +--- +#### checkResponse +```cpp +virtual bool checkResponse(const Message & message) +``` -#### `public virtual void read(`[`BitReader`](#classscy_1_1BitReader)` & reader)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `message` | `const Message &` | | +--- +#### onResponse -Reads the body (not the type or size) for this type of attribute from the given buffer. Return value is true if successful. +```cpp +virtual void onResponse() +``` -#### `public virtual void write(`[`BitWriter`](#classscy_1_1BitWriter)` & writer) const` +Called when a successful response match is received. +--- +#### ~Transaction -Writes the body (not the type or size) to the given buffer. Return value is true if successful. +```cpp +virtual ~Transaction() +``` diff --git a/doc/api-symple.md b/doc/api-symple.md index 2ae293cd3..257e46abf 100644 --- a/doc/api-symple.md +++ b/doc/api-symple.md @@ -1,1778 +1,2737 @@ -# Module `symple` - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`namespace `[`scy::smpl`](#namespacescy_1_1smpl) | -`struct `[`scy::smpl::Client::Options`](#structscy_1_1smpl_1_1Client_1_1Options) | -# namespace `scy::smpl` - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`class `[`scy::smpl::Client`](#classscy_1_1smpl_1_1Client) | -`class `[`scy::smpl::Command`](#classscy_1_1smpl_1_1Command) | -`class `[`scy::smpl::Event`](#classscy_1_1smpl_1_1Event) | -`class `[`scy::smpl::Form`](#classscy_1_1smpl_1_1Form) | -`class `[`scy::smpl::FormElement`](#classscy_1_1smpl_1_1FormElement) | -`class `[`scy::smpl::FormField`](#classscy_1_1smpl_1_1FormField) | -`class `[`scy::smpl::Message`](#classscy_1_1smpl_1_1Message) | -`class `[`scy::smpl::Peer`](#classscy_1_1smpl_1_1Peer) | -`class `[`scy::smpl::Presence`](#classscy_1_1smpl_1_1Presence) | -`class `[`scy::smpl::Roster`](#classscy_1_1smpl_1_1Roster) | -`class `[`scy::smpl::SSLClient`](#classscy_1_1smpl_1_1SSLClient) | -`class `[`scy::smpl::TCPClient`](#classscy_1_1smpl_1_1TCPClient) | -`struct `[`scy::smpl::Address`](#structscy_1_1smpl_1_1Address) | -`struct `[`scy::smpl::Filter`](#structscy_1_1smpl_1_1Filter) | -# class `scy::smpl::Client` - -``` -class scy::smpl::Client - : public scy::sockio::Client -``` - - - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public `[`Signal`](#classscy_1_1Signal)< void(const int &)`> Announce` | -`public `[`Signal](#classscy_1_1Signal)< void([Peer`](#classscy_1_1smpl_1_1Peer) &)`> PeerConnected` | Signals when a peer connects. -`public `[`Signal](#classscy_1_1Signal)< void([Peer`](#classscy_1_1smpl_1_1Peer) &)`> PeerDisconnected` | Signals when a peer disconnects. -`public `[`Signal](#classscy_1_1Signal)< void([Peer`](#classscy_1_1smpl_1_1Peer) &)`> CreatePresence` | -`public Client(const net::Socket::Ptr & socket,const `[`Options`](#structscy_1_1smpl_1_1Client_1_1Options)` & options)` | -`public virtual ~Client()` | -`public virtual void connect()` | -`public virtual void close()` | -`public virtual int send(`[`Message`](#classscy_1_1smpl_1_1Message)` & message,bool ack)` | -`public virtual int send(const std::string & message,bool ack)` | -`public `[`sockio::Transaction`](#structscy_1_1sockio_1_1Transaction)` * createTransaction(`[`Message`](#classscy_1_1smpl_1_1Message)` & message)` | -`public virtual int respond(`[`Message`](#classscy_1_1smpl_1_1Message)` & message,bool ack)` | Swap the 'to' and 'from' fields and send the given message. -`public virtual int sendPresence(bool probe)` | -`public virtual int sendPresence(const `[`Address`](#structscy_1_1smpl_1_1Address)` & to,bool probe)` | Send directed presence to the given peer. -`public virtual int joinRoom(const std::string & room)` | Join the given room. -`public virtual int leaveRoom(const std::string & room)` | Leave the given room. -`public virtual std::string ourID() const` | -`public StringVec rooms() const` | Return a list of rooms the client has joined. -`public virtual `[`Peer`](#classscy_1_1smpl_1_1Peer)` * ourPeer()` | -`public virtual `[`Roster`](#classscy_1_1smpl_1_1Roster)` & roster()` | Return the roster which stores all online peers. -`public virtual `[`PersistenceT`](#classscy_1_1TimedManager)` & persistence()` | -`public `[`Client::Options`](#structscy_1_1smpl_1_1Client_1_1Options)` & options()` | Return a reference to the client options object. -`public virtual `[`Client`](#classscy_1_1smpl_1_1Client)` & operator>>(`[`Message`](#classscy_1_1smpl_1_1Message)` & message)` | [Stream](#classscy_1_1Stream) operator alias for [send()](#group__symple_1ga4dffb71d16288852dbeb54e38ce9cc82). -`public virtual void onPresenceData(const json::value & data,bool whiny)` | Update the roster from the given client object. -`protected `[`Roster`](./doc/api-symple.md#classscy_1_1smpl_1_1Roster)` _roster` | -`protected std::string _ourID` | -`protected `[`PersistenceT`](./doc/api-util.md#classscy_1_1TimedManager)` _persistence` | -`protected `[`Client::Options`](./doc/api-symple.md#structscy_1_1smpl_1_1Client_1_1Options)` _options` | -`protected StringVec _rooms` | -`protected int _announceStatus` | -`protected virtual int announce()` | -`protected virtual void reset()` | -`protected virtual void createPresence(`[`Presence`](#classscy_1_1smpl_1_1Presence)` & p)` | Creates a [Presence](./doc/api-symple.md#classscy_1_1smpl_1_1Presence) object. -`protected virtual void emit(`[`IPacket`](#classscy_1_1IPacket)` & packet)` | Override PacketSignal::emit. -`protected virtual void onOnline()` | -`protected virtual void onAnnounceState(void * sender,`[`TransactionState`](#structscy_1_1TransactionState)` & state,const `[`TransactionState`](#structscy_1_1TransactionState)` &)` | - -## Members - -#### `public `[`Signal`](#classscy_1_1Signal)< void(const int &)`> Announce` - - - -SignalsNotifies the outside application about the response status code of our [announce()](#group__symple_1gadf0ac053e026a7c792d00ac165cb1298) call. Possible status codes are: // - 200: Authentication success - -* 401: Authentication failed - - -* 400: Bad request data - - -* 500: Server not found - -#### `public `[`Signal](#classscy_1_1Signal)< void([Peer`](#classscy_1_1smpl_1_1Peer) &)`> PeerConnected` - -Signals when a peer connects. - - - -#### `public `[`Signal](#classscy_1_1Signal)< void([Peer`](#classscy_1_1smpl_1_1Peer) &)`> PeerDisconnected` - -Signals when a peer disconnects. - - - -#### `public `[`Signal](#classscy_1_1Signal)< void([Peer`](#classscy_1_1smpl_1_1Peer) &)`> CreatePresence` - - - -Called by [createPresence()](#group__symple_1gace2ee9e3f211f1fb9979953c6d0dfa34) so outside classes can modify the outgoing [Peer](#classscy_1_1smpl_1_1Peer) JSON object. - -#### `public Client(const net::Socket::Ptr & socket,const `[`Options`](#structscy_1_1smpl_1_1Client_1_1Options)` & options)` - +# symple + +### Classes + +| Name | Description | +|------|-------------| +| [`Client`](#classscy_1_1smpl_1_1Client) | | +| [`TCPClient`](#classscy_1_1smpl_1_1TCPClient) | | +| [`SSLClient`](#classscy_1_1smpl_1_1SSLClient) | | +| [`Command`](#classscy_1_1smpl_1_1Command) | | +| [`Event`](#classscy_1_1smpl_1_1Event) | | +| [`FormElement`](#classscy_1_1smpl_1_1FormElement) | | +| [`Form`](#classscy_1_1smpl_1_1Form) | | +| [`FormField`](#classscy_1_1smpl_1_1FormField) | | +| [`Message`](#classscy_1_1smpl_1_1Message) | | +| [`Peer`](#classscy_1_1smpl_1_1Peer) | This class represents a peer on the network. A [Peer](#classscy_1_1smpl_1_1Peer) object may also contain arbitrary data set by the client to share with other peers on the network. **See also**: [Address](#structscy_1_1smpl_1_1Address) for further methods and [basic](./doc/api-undefined.md#namespacescy_1_1basic) accessors. | +| [`Presence`](#classscy_1_1smpl_1_1Presence) | | +| [`Roster`](#classscy_1_1smpl_1_1Roster) | The [Roster](#classscy_1_1smpl_1_1Roster) provides a registry for active network peers indexed by session ID. | +| [`Address`](#structscy_1_1smpl_1_1Address) | The [Address](#structscy_1_1smpl_1_1Address) structure is an endpoint identifier for a peer on the network. The format is like so: user|id | +| [`Options`](#structscy_1_1smpl_1_1Client_1_1Options) | | +| [`Filter`](#structscy_1_1smpl_1_1Filter) | | + +### Members + +| Name | Description | +|------|-------------| +| [`Symple_API`](#group__symple_1gabbd11164ccdcea231be5cb5fe26438ea) | | + +--- + +#### Symple_API + +```cpp +Symple_API() +``` +## Client + +> **Extends:** `scy::sockio::Client` +> **Subclasses:** `scy::smpl::SSLClient`, `scy::smpl::TCPClient` +> **Defined in:** `client.h` + +### Members + +| Name | Description | +|------|-------------| +| [`Client`](#group__symple_1ga5b46d09313a3360148246158e11dce4c) | | +| [`~Client`](#group__symple_1ga1eb6bbd30e54e4c0e918c7ce43fadeec) | | +| [`connect`](#group__symple_1gaa8c97bf06d3fc80ceea252a2a611c5c7) | | +| [`close`](#group__symple_1gae27e4556310a4b935ffe78b62bbe3a9c) | | +| [`send`](#group__symple_1ga4dffb71d16288852dbeb54e38ce9cc82) | Send a message. May be a polymorphic [Command](#classscy_1_1smpl_1_1Command), [Presence](#classscy_1_1smpl_1_1Presence), [Event](#classscy_1_1smpl_1_1Event) or other ... | +| [`send`](#group__symple_1ga6e121b7e49c36023f49190c9ab5bebef) | Send a string message. The message must be a valid Symple message otherwise it will not be delivered. | +| [`createTransaction`](#group__symple_1ga51add0f918bee39b510fad050c973db9) | Create a Transaction object with the given message which will notify on Ack response from the server. | +| [`respond`](#group__symple_1gaea0ec59bcf35da1f20a3cd46adf1e4f4) | Swap the 'to' and 'from' fields and send the given message. | +| [`sendPresence`](#group__symple_1gaa2b2c55f34473f05b397c88e6a1f1e19) | Broadcast presence to the user group scope. The outgoing [Presence](#classscy_1_1smpl_1_1Presence) object may be modified via the CreatePresence signal. | +| [`sendPresence`](#group__symple_1gaaf17806e06f596c196e007c5e98a0ea6) | Send directed presence to the given peer. | +| [`joinRoom`](#group__symple_1ga426afee6e4914560d5b82fb9098898d6) | Join the given room. | +| [`leaveRoom`](#group__symple_1ga7d696ae2396d9da0d87c7d0ed464b579) | Leave the given room. | +| [`ourID`](#group__symple_1gaeb1cebadd1f004d6b259c4831ff0901a) | Return the session ID of our current peer object. Return an empty string when offline. | +| [`rooms`](#group__symple_1ga468d33d5531670856a74208ecca2e8f6) | Return a list of rooms the client has joined. | +| [`ourPeer`](#group__symple_1ga680bfb6b0db4f75e9a863b61b61d734b) | Return the peer object for the current session, or throws an exception when offline. | +| [`roster`](#group__symple_1ga6998f1375a4767e630a98f60cb304300) | Return the roster which stores all online peers. | +| [`persistence`](#group__symple_1ga7ee28acdc40837302c167b543fc56a15) | Return the persistence manager which stores long lived messages. | +| [`options`](#group__symple_1ga6272271fea7d57a5719e2da9163b3224) | Return a reference to the client options object. | +| [`operator>>`](#group__symple_1ga991c5b0bbcca7d16536b0dccce4107d2) | [Stream](./doc/api-base.md#classscy_1_1Stream) operator alias for [send()](#group__symple_1ga4dffb71d16288852dbeb54e38ce9cc82). | +| [`onPresenceData`](#group__symple_1gaac8e9b77fda748176c2c99787b4d4355) | Update the roster from the given client object. | +| [`announce`](#group__symple_1gadf0ac053e026a7c792d00ac165cb1298) | Called when a new connection is established to announce and authenticate the peer on the server. | +| [`reset`](#group__symple_1gafe1d7b3e16488e4a61f6fc045601dc2a) | Resets variables and data at the beginning and end of each session. | +| [`createPresence`](#group__symple_1gace2ee9e3f211f1fb9979953c6d0dfa34) | Creates a [Presence](#classscy_1_1smpl_1_1Presence) object. | +| [`emit`](#group__symple_1ga805c44b00ddf3dfeba913dea6a03330d) | Override PacketSignal::emit. | +| [`onOnline`](#group__symple_1ga34e2a7ff6cc2292a40102a0d51917cd6) | | +| [`onAnnounceState`](#group__symple_1gae30976d64dc3e2b64b470eb0774fdf16) | | +| [`Announce`](#group__symple_1ga0228d93d0cedc21b61f12a580bb7c6b9) | Signals Notifies the outside application about the response status code of our [announce()](#group__symple_1gadf0ac053e026a7c792d00ac165cb1298) call. Possible status codes are: // - 200: Authentication success | +| [`PeerConnected`](#group__symple_1ga01d918d49dcf259d612543a353a7e98e) | Signals when a peer connects. | +| [`PeerDisconnected`](#group__symple_1ga317fcf03f379f086db4b77bbc58ba7f6) | Signals when a peer disconnects. | +| [`CreatePresence`](#group__symple_1ga026c3952b78bd1b4b4f18d9bd815e94e) | Called by [createPresence()](#group__symple_1gace2ee9e3f211f1fb9979953c6d0dfa34) so outside classes can modify the outgoing [Peer](#classscy_1_1smpl_1_1Peer) JSON object. | +| [`_roster`](#group__symple_1ga8a6dc184e85eb02e1180a6ff11af402f) | | +| [`_ourID`](#group__symple_1ga7aa335a7730f803fabab6a0ac7bf629f) | | +| [`_persistence`](#group__symple_1ga0ecdbbbdc4f57cac6e7b5fda9072f5fa) | | +| [`_options`](#group__symple_1gadfb98483f4d159dc718c788f787d6adf) | | +| [`_rooms`](#group__symple_1ga362e9d47266c26dcf32e1603e6d39a85) | | +| [`_announceStatus`](#group__symple_1gacece49388fbe130519f6b58232dd8067) | | + +--- + +#### Client + +```cpp +Client(const net::Socket::Ptr & socket, const Options & options) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `socket` | `const net::Socket::Ptr &` | | +| `options` | `const Options &` | | +--- -#### `public virtual ~Client()` +#### ~Client +```cpp +virtual ~Client() +``` +--- +#### connect +```cpp +virtual void connect() +``` -#### `public virtual void connect()` +--- +#### close +```cpp +virtual void close() +``` +--- +#### send -#### `public virtual void close()` +```cpp +virtual int send(Message & message, bool ack) +``` +Send a message. May be a polymorphic [Command](#classscy_1_1smpl_1_1Command), [Presence](#classscy_1_1smpl_1_1Presence), [Event](#classscy_1_1smpl_1_1Event) or other ... +| Parameter | Type | Description | +|-----------|------|-------------| +| `message` | `Message &` | | +| `ack` | `bool` | | +--- +#### send -#### `public virtual int send(`[`Message`](#classscy_1_1smpl_1_1Message)` & message,bool ack)` +```cpp +virtual int send(const std::string & message, bool ack) +``` +Send a string message. The message must be a valid Symple message otherwise it will not be delivered. +| Parameter | Type | Description | +|-----------|------|-------------| +| `message` | `const std::string &` | | +| `ack` | `bool` | | -Send a message. May be a polymorphic [Command](#classscy_1_1smpl_1_1Command), [Presence](#classscy_1_1smpl_1_1Presence), [Event](#classscy_1_1smpl_1_1Event) or other ... +--- -#### `public virtual int send(const std::string & message,bool ack)` +#### createTransaction +```cpp +sockio::Transaction * createTransaction(Message & message) +``` +Create a Transaction object with the given message which will notify on Ack response from the server. -Send a string message. The message must be a valid Symple message otherwise it will not be delivered. +| Parameter | Type | Description | +|-----------|------|-------------| +| `message` | `Message &` | | -#### `public `[`sockio::Transaction`](#structscy_1_1sockio_1_1Transaction)` * createTransaction(`[`Message`](#classscy_1_1smpl_1_1Message)` & message)` +--- +#### respond +```cpp +virtual int respond(Message & message, bool ack) +``` -Create a Transaction object with the given message which will notify on Ack response from the server. +Swap the 'to' and 'from' fields and send the given message. -#### `public virtual int respond(`[`Message`](#classscy_1_1smpl_1_1Message)` & message,bool ack)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `message` | `Message &` | | +| `ack` | `bool` | | -Swap the 'to' and 'from' fields and send the given message. +--- +#### sendPresence +```cpp +virtual int sendPresence(bool probe) +``` -#### `public virtual int sendPresence(bool probe)` +Broadcast presence to the user group scope. The outgoing [Presence](#classscy_1_1smpl_1_1Presence) object may be modified via the CreatePresence signal. +| Parameter | Type | Description | +|-----------|------|-------------| +| `probe` | `bool` | | +--- -Broadcast presence to the user group scope. The outgoing [Presence](#classscy_1_1smpl_1_1Presence) object may be modified via the CreatePresence signal. +#### sendPresence -#### `public virtual int sendPresence(const `[`Address`](#structscy_1_1smpl_1_1Address)` & to,bool probe)` +```cpp +virtual int sendPresence(const Address & to, bool probe) +``` Send directed presence to the given peer. +| Parameter | Type | Description | +|-----------|------|-------------| +| `to` | `const Address &` | | +| `probe` | `bool` | | +--- -#### `public virtual int joinRoom(const std::string & room)` +#### joinRoom + +```cpp +virtual int joinRoom(const std::string & room) +``` Join the given room. +| Parameter | Type | Description | +|-----------|------|-------------| +| `room` | `const std::string &` | | +--- -#### `public virtual int leaveRoom(const std::string & room)` +#### leaveRoom -Leave the given room. +```cpp +virtual int leaveRoom(const std::string & room) +``` +Leave the given room. +| Parameter | Type | Description | +|-----------|------|-------------| +| `room` | `const std::string &` | | -#### `public virtual std::string ourID() const` +--- +#### ourID +```cpp +virtual std::string ourID() const +``` Return the session ID of our current peer object. Return an empty string when offline. -#### `public StringVec rooms() const` +--- -Return a list of rooms the client has joined. +#### rooms +```cpp +StringVec rooms() const +``` +Return a list of rooms the client has joined. -#### `public virtual `[`Peer`](#classscy_1_1smpl_1_1Peer)` * ourPeer()` +--- +#### ourPeer +```cpp +virtual Peer * ourPeer() +``` Return the peer object for the current session, or throws an exception when offline. -#### `public virtual `[`Roster`](#classscy_1_1smpl_1_1Roster)` & roster()` +--- -Return the roster which stores all online peers. +#### roster +```cpp +virtual Roster & roster() +``` +Return the roster which stores all online peers. -#### `public virtual `[`PersistenceT`](#classscy_1_1TimedManager)` & persistence()` +--- +#### persistence +```cpp +virtual PersistenceT & persistence() +``` Return the persistence manager which stores long lived messages. -#### `public `[`Client::Options`](#structscy_1_1smpl_1_1Client_1_1Options)` & options()` - -Return a reference to the client options object. - - - -#### `public virtual `[`Client`](#classscy_1_1smpl_1_1Client)` & operator>>(`[`Message`](#classscy_1_1smpl_1_1Message)` & message)` - -[Stream](#classscy_1_1Stream) operator alias for [send()](#group__symple_1ga4dffb71d16288852dbeb54e38ce9cc82). - - - -#### `public virtual void onPresenceData(const json::value & data,bool whiny)` - -Update the roster from the given client object. - - - -#### `protected `[`Roster`](./doc/api-symple.md#classscy_1_1smpl_1_1Roster)` _roster` - - - - - -#### `protected std::string _ourID` - - - - - -#### `protected `[`PersistenceT`](./doc/api-util.md#classscy_1_1TimedManager)` _persistence` - - - - - -#### `protected `[`Client::Options`](./doc/api-symple.md#structscy_1_1smpl_1_1Client_1_1Options)` _options` - +--- +#### options +```cpp +Client::Options & options() +``` +Return a reference to the client options object. -#### `protected StringVec _rooms` +--- +#### operator>> +```cpp +virtual Client & operator>>(Message & message) +``` +[Stream](./doc/api-base.md#classscy_1_1Stream) operator alias for [send()](#group__symple_1ga4dffb71d16288852dbeb54e38ce9cc82). +| Parameter | Type | Description | +|-----------|------|-------------| +| `message` | `Message &` | | -#### `protected int _announceStatus` +--- +#### onPresenceData +```cpp +virtual void onPresenceData(const json::value & data, bool whiny) +``` +Update the roster from the given client object. +| Parameter | Type | Description | +|-----------|------|-------------| +| `data` | `const json::value &` | | +| `whiny` | `bool` | | -#### `protected virtual int announce()` +--- +#### announce +```cpp +virtual int announce() +``` Called when a new connection is established to announce and authenticate the peer on the server. -#### `protected virtual void reset()` +--- +#### reset +```cpp +virtual void reset() +``` Resets variables and data at the beginning and end of each session. -#### `protected virtual void createPresence(`[`Presence`](#classscy_1_1smpl_1_1Presence)` & p)` - -Creates a [Presence](#classscy_1_1smpl_1_1Presence) object. - - - -#### `protected virtual void emit(`[`IPacket`](#classscy_1_1IPacket)` & packet)` - -Override PacketSignal::emit. - - - -#### `protected virtual void onOnline()` +--- +#### createPresence - - - -#### `protected virtual void onAnnounceState(void * sender,`[`TransactionState`](#structscy_1_1TransactionState)` & state,const `[`TransactionState`](#structscy_1_1TransactionState)` &)` - - - - - -# class `scy::smpl::Command` - +```cpp +virtual void createPresence(Presence & p) ``` -class scy::smpl::Command - : public scy::smpl::Message -``` - - - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public Command()` | -`public Command(const json::value & root)` | -`public Command(const `[`Command`](#classscy_1_1smpl_1_1Command)` & root)` | -`public virtual ~Command()` | -`public std::string node() const` | -`public std::string action() const` | -`public void setNode(const std::string & node)` | -`public void setAction(const std::string & action)` | -`public virtual bool valid() const` | -`public std::string param(int n) const` | -`public std::vector< std::string > params()` | -`public bool matches(const std::string & xnode) const` | - -## Members - -#### `public Command()` - - - - - -#### `public Command(const json::value & root)` - - - - - -#### `public Command(const `[`Command`](#classscy_1_1smpl_1_1Command)` & root)` - - - - - -#### `public virtual ~Command()` - - - - - -#### `public std::string node() const` - - - - - -#### `public std::string action() const` - - - - - -#### `public void setNode(const std::string & node)` - - - - - -#### `public void setAction(const std::string & action)` - - - - - -#### `public virtual bool valid() const` - - - - - -#### `public std::string param(int n) const` - - - - - -#### `public std::vector< std::string > params()` - - - - - -#### `public bool matches(const std::string & xnode) const` - +Creates a [Presence](#classscy_1_1smpl_1_1Presence) object. +| Parameter | Type | Description | +|-----------|------|-------------| +| `p` | `Presence &` | | +--- -# class `scy::smpl::Event` +#### emit +```cpp +virtual void emit(IPacket & packet) ``` -class scy::smpl::Event - : public scy::smpl::Message -``` - - - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public Event()` | -`public Event(const json::value & root)` | -`public Event(const `[`Event`](#classscy_1_1smpl_1_1Event)` & root)` | -`public virtual ~Event()` | -`public virtual bool valid() const` | -`public std::string name() const` | -`public std::time_t time() const` | -`public void setName(const std::string & name)` | -`public void setTime(std::time_t time)` | - -## Members - -#### `public Event()` - - - - - -#### `public Event(const json::value & root)` - - - - - -#### `public Event(const `[`Event`](#classscy_1_1smpl_1_1Event)` & root)` - - - - - -#### `public virtual ~Event()` - - - - - -#### `public virtual bool valid() const` - - - - - -#### `public std::string name() const` - - - - - -#### `public std::time_t time() const` - - - - - -#### `public void setName(const std::string & name)` - - - - - -#### `public void setTime(std::time_t time)` - +Override PacketSignal::emit. +| Parameter | Type | Description | +|-----------|------|-------------| +| `packet` | `IPacket &` | | +--- -# class `scy::smpl::Form` +#### onOnline +```cpp +virtual void onOnline() ``` -class scy::smpl::Form - : public scy::smpl::FormElement -``` - - - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public Form()` | -`public Form(json::value & root)` | -`public Form(`[`Command`](#classscy_1_1smpl_1_1Command)` & root)` | -`public virtual ~Form()` | -`public bool valid()` | -`public std::string action() const` | -`public bool partial() const` | -`public void setAction(const std::string & action)` | -`public void setPartial(bool flag)` | - -## Members - -#### `public Form()` - - - - - -#### `public Form(json::value & root)` - - - - - -#### `public Form(`[`Command`](#classscy_1_1smpl_1_1Command)` & root)` - - - - - -#### `public virtual ~Form()` - +--- +#### onAnnounceState +```cpp +virtual void onAnnounceState(void * sender, TransactionState & state, const TransactionState &) +``` -#### `public bool valid()` - - - - - -#### `public std::string action() const` - - - - - -#### `public bool partial() const` - - - - - -#### `public void setAction(const std::string & action)` - - - -Possible "action" values `form` The form-processing entity is asking the form-submitting entity to complete a form. `submit` The form-submitting entity is submitting data to the form-processing entity. `cancel` The form-submitting entity has cancelled submission of data to the form-processing entity. `result` The form-processing entity is returning data to the form-submitting entity. - -#### `public void setPartial(bool flag)` - - - -Notifies the form is a partial section of the form. This is used for transmitting and updating live fields such as for auto-complete. - -# class `scy::smpl::FormElement` - - - - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public FormElement()` | -`public FormElement(json::value & root,const std::string & type,const std::string & id,const std::string & label)` | -`public FormElement(const `[`FormElement`](#classscy_1_1smpl_1_1FormElement)` & r)` | -`public `[`FormElement`](#classscy_1_1smpl_1_1FormElement)` & operator=(const `[`FormElement`](#classscy_1_1smpl_1_1FormElement)` & r)` | -`public virtual ~FormElement()` | -`public std::string type() const` | -`public std::string id() const` | -`public std::string label() const` | -`public void setType(const std::string & type)` | -`public void setId(const std::string & id)` | -`public void setLabel(const std::string & text)` | -`public void setHint(const std::string & text)` | -`public void setError(const std::string & error)` | Sets and optional validation error message. -`public `[`FormElement`](#classscy_1_1smpl_1_1FormElement)` addPage(const std::string & id,const std::string & label)` | -`public `[`FormElement`](#classscy_1_1smpl_1_1FormElement)` addSection(const std::string & id,const std::string & label)` | -`public `[`FormField`](#classscy_1_1smpl_1_1FormField)` addField(const std::string & type,const std::string & id,const std::string & label)` | -`public `[`FormField`](#classscy_1_1smpl_1_1FormField)` getField(const std::string & id,bool partial)` | -`public bool getField(const std::string & id,`[`FormField`](#classscy_1_1smpl_1_1FormField)` & field,bool partial)` | -`public bool hasField(const std::string & id,bool partial)` | -`public void setLive(bool flag)` | -`public bool live() const` | -`public bool clearElements(const std::string & id,bool partial)` | Clears child elements matching the given ID. -`public void clear()` | Clear the entire form. -`public bool valid() const` | Returns true if the form element is valid. -`public int numElements()` | Returns the number of child elements. -`public bool hasErrors()` | Returns true if any fields have errors. -`public bool hasPages()` | Returns true if the form has multiple pages. -`public json::value & root() const` | -`protected json::value * _root` | - -## Members - -#### `public FormElement()` - - - - - -#### `public FormElement(json::value & root,const std::string & type,const std::string & id,const std::string & label)` - - - - - -#### `public FormElement(const `[`FormElement`](#classscy_1_1smpl_1_1FormElement)` & r)` - - - - - -#### `public `[`FormElement`](#classscy_1_1smpl_1_1FormElement)` & operator=(const `[`FormElement`](#classscy_1_1smpl_1_1FormElement)` & r)` - - - - - -#### `public virtual ~FormElement()` - - - - - -#### `public std::string type() const` - - - - - -#### `public std::string id() const` - - - - - -#### `public std::string label() const` - - - - - -#### `public void setType(const std::string & type)` - +| Parameter | Type | Description | +|-----------|------|-------------| +| `sender` | `void *` | | +| `state` | `TransactionState &` | | +--- -Possible "type" values page, section, text, text-multi, list, list-multi, checkbox, media, custom +#### Announce -#### `public void setId(const std::string & id)` +```cpp +Signal< void(const int &)> Announce +``` +Signals Notifies the outside application about the response status code of our [announce()](#group__symple_1gadf0ac053e026a7c792d00ac165cb1298) call. Possible status codes are: // - 200: Authentication success +* 401: Authentication failed +* 400: Bad request data +* 500: Server not found -#### `public void setLabel(const std::string & text)` +--- +#### PeerConnected +```cpp +Signal< void(Peer &)> PeerConnected +``` +Signals when a peer connects. +--- -#### `public void setHint(const std::string & text)` +#### PeerDisconnected +```cpp +Signal< void(Peer &)> PeerDisconnected +``` +Signals when a peer disconnects. +--- +#### CreatePresence -#### `public void setError(const std::string & error)` +```cpp +Signal< void(Peer &)> CreatePresence +``` -Sets and optional validation error message. +Called by [createPresence()](#group__symple_1gace2ee9e3f211f1fb9979953c6d0dfa34) so outside classes can modify the outgoing [Peer](#classscy_1_1smpl_1_1Peer) JSON object. +--- +#### _roster -#### `public `[`FormElement`](#classscy_1_1smpl_1_1FormElement)` addPage(const std::string & id,const std::string & label)` +```cpp +Roster _roster +``` +--- +#### _ourID +```cpp +std::string _ourID +``` +--- -#### `public `[`FormElement`](#classscy_1_1smpl_1_1FormElement)` addSection(const std::string & id,const std::string & label)` +#### _persistence +```cpp +PersistenceT _persistence +``` +--- +#### _options +```cpp +Client::Options _options +``` -#### `public `[`FormField`](#classscy_1_1smpl_1_1FormField)` addField(const std::string & type,const std::string & id,const std::string & label)` +--- +#### _rooms +```cpp +StringVec _rooms +``` +--- +#### _announceStatus -#### `public `[`FormField`](#classscy_1_1smpl_1_1FormField)` getField(const std::string & id,bool partial)` +```cpp +int _announceStatus +``` +## Options +> **Defined in:** `client.h` +### Members +| Name | Description | +|------|-------------| +| [`Options`](#group__symple_1ga7dd4fee81e4318912e9d82a1e35c6550) | | +| [`host`](#group__symple_1ga05d0bdf5ab5eeefec7d0019bb110bb58) | | +| [`port`](#group__symple_1ga1b77c19ba3010b95adab9572de8812d4) | | +| [`reconnection`](#group__symple_1ga8388c0e51b717793da8e136f24ef4df6) | Weather or not to reconnect if disconnected from the server. | +| [`reconnectAttempts`](#group__symple_1gaad73b34182da94bd80d394d6c2cf8d59) | The number of times to attempt to reconnect if disconnected from the server. (0 = unlimited) | +| [`user`](#group__symple_1gace5d72442ca0ddd400242766dcbe0075) | | +| [`name`](#group__symple_1ga937a706d0ff802b29881200dd0f9b140) | | +| [`type`](#group__symple_1ga3a94f72a2f8e72b1bb84f11630f9cd9a) | | +| [`token`](#group__symple_1gae46b1ce6b2a9c5e8ae983cf36137d18d) | | -#### `public bool getField(const std::string & id,`[`FormField`](#classscy_1_1smpl_1_1FormField)` & field,bool partial)` +--- +#### Options +```cpp +inline Options() +``` +--- +#### host -#### `public bool hasField(const std::string & id,bool partial)` +```cpp +std::string host = "127.0.0.1" +``` +--- +#### port -Returns true if the given [Address](#structscy_1_1smpl_1_1Address) matches any of the internal form element IDs. If the partial flag is set then substring matches will be counted. +```cpp +uint16_t port = 4500 +``` -#### `public void setLive(bool flag)` +--- +#### reconnection +```cpp +bool reconnection = true +``` -Live fields or elements are used to submit partial sections a form, without sending the entire form. +Weather or not to reconnect if disconnected from the server. -#### `public bool live() const` +--- +#### reconnectAttempts +```cpp +int reconnectAttempts = 0 +``` -Returns true if this field is live, meaning the form-processing entity should auto-update this field's value whenever it changes. +The number of times to attempt to reconnect if disconnected from the server. (0 = unlimited) -#### `public bool clearElements(const std::string & id,bool partial)` +--- -Clears child elements matching the given ID. +#### user +```cpp +std::string user +``` +--- -#### `public void clear()` +#### name -Clear the entire form. +```cpp +std::string name +``` +--- +#### type -#### `public bool valid() const` +```cpp +std::string type +``` -Returns true if the form element is valid. +--- +#### token +```cpp +std::string token +``` -#### `public int numElements()` +## TCPClient -Returns the number of child elements. +> **Extends:** `scy::smpl::Client` +> **Defined in:** `client.h` +### Members +| Name | Description | +|------|-------------| +| [`TCPClient`](#group__symple_1gafc1541506c7fded90f495818835590b4) | | -#### `public bool hasErrors()` +--- -Returns true if any fields have errors. +#### TCPClient +```cpp +TCPClient(const Client::Options & options, uv::Loop * loop) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `options` | `const Client::Options &` | | +| `loop` | `uv::Loop *` | | -#### `public bool hasPages()` +## SSLClient -Returns true if the form has multiple pages. +> **Extends:** `scy::smpl::Client` +> **Defined in:** `client.h` +### Members +| Name | Description | +|------|-------------| +| [`SSLClient`](#group__symple_1ga03327af0bc01ae4e7a56affb83991aad) | | -#### `public json::value & root() const` +--- +#### SSLClient +```cpp +SSLClient(const Client::Options & options, uv::Loop * loop) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `options` | `const Client::Options &` | | +| `loop` | `uv::Loop *` | | +## Command -#### `protected json::value * _root` +> **Extends:** `scy::smpl::Message` +> **Defined in:** `command.h` +### Members +| Name | Description | +|------|-------------| +| [`Command`](#group__symple_1ga1d83f2b5a9be1780e3b77f5c96b34a9a) | | +| [`Command`](#group__symple_1ga91132752945caa9ada473cb1f820bd39) | | +| [`Command`](#group__symple_1ga2f980c97f7fdfee4882f8923cb2853c2) | | +| [`~Command`](#group__symple_1ga964d5a75ca62c76ff2c27e9236f90e00) | | +| [`node`](#group__symple_1gac5f9bb1710c74e1f8281c267ecf04c5f) | | +| [`action`](#group__symple_1ga81df2719cd693fbda9e76dff7027a654) | | +| [`setNode`](#group__symple_1ga904c2957be56206f513c33f92f89bcad) | | +| [`setAction`](#group__symple_1ga276a75d047efd959d77cfe473f8a1c58) | | +| [`valid`](#group__symple_1gad76ae409faa59e3300da80f7c745aec2) | | +| [`param`](#group__symple_1ga1611d5b3bdcc91574bae67dfbde437ae) | | +| [`params`](#group__symple_1ga43384ed4f7303ac921bcf65e6f18db26) | | +| [`matches`](#group__symple_1gae80a575c75e000c040d320ead0896323) | | -The root pointer is just a reference to the externally managed JSON value memory. +--- -# class `scy::smpl::FormField` +#### Command +```cpp +Command() ``` -class scy::smpl::FormField - : public scy::smpl::FormElement -``` - +--- +#### Command +```cpp +Command(const json::value & root) +``` -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public FormField()` | -`public FormField(json::value & root,const std::string & type,const std::string & id,const std::string & label)` | -`public virtual ~FormField()` | -`public void addOption(const std::string & key,const std::string & value)` | Adds an option for list based fields. -`public void addOption(const std::string & value)` | -`public void setValue(const std::string & value)` | Sets the value clearing all other values. -`public void setValue(int value)` | -`public void setValue(double value)` | -`public void setValue(bool value)` | -`public void addValue(const std::string & value)` | Appends a value to the value array. -`public void addValue(int value)` | -`public void addValue(double value)` | -`public void addValue(bool value)` | -`public json::value & values()` | Returns a JSON array of all values. -`public std::string value() const` | -`public int intValue() const` | -`public double doubleValue() const` | -`public bool boolValue() const` | +| Parameter | Type | Description | +|-----------|------|-------------| +| `root` | `const json::value &` | | -## Members +--- -#### `public FormField()` +#### Command +```cpp +Command(const Command & root) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `root` | `const Command &` | | +--- +#### ~Command -#### `public FormField(json::value & root,const std::string & type,const std::string & id,const std::string & label)` +```cpp +virtual ~Command() +``` +--- +#### node +```cpp +std::string node() const +``` +--- -#### `public virtual ~FormField()` +#### action +```cpp +std::string action() const +``` +--- +#### setNode +```cpp +void setNode(const std::string & node) +``` -#### `public void addOption(const std::string & key,const std::string & value)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `node` | `const std::string &` | | -Adds an option for list based fields. +--- +#### setAction +```cpp +void setAction(const std::string & action) +``` -#### `public void addOption(const std::string & value)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `action` | `const std::string &` | | +--- +#### valid +```cpp +virtual bool valid() const +``` +--- -#### `public void setValue(const std::string & value)` +#### param -Sets the value clearing all other values. +```cpp +std::string param(int n) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `n` | `int` | | +--- -#### `public void setValue(int value)` +#### params +```cpp +std::vector< std::string > params() +``` +--- +#### matches +```cpp +bool matches(const std::string & xnode) const +``` -#### `public void setValue(double value)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `xnode` | `const std::string &` | | +## Event +> **Extends:** `scy::smpl::Message` +> **Defined in:** `event.h` +### Members +| Name | Description | +|------|-------------| +| [`Event`](#group__symple_1gafe163cd025c2c0dafa7e779df5f5962d) | | +| [`Event`](#group__symple_1ga801abee141af76f34f96bd282fa9f1d3) | | +| [`Event`](#group__symple_1gae6aaee01e127e7de476f49d0ecb9f8c7) | | +| [`~Event`](#group__symple_1ga9b9bb5b13b492ec09f88e72249a83e3b) | | +| [`valid`](#group__symple_1ga365f48210b899bf487ac334a6b50bb6a) | | +| [`name`](#group__symple_1gaf4898557f256d37c2ec91dae453ba244) | | +| [`time`](#group__symple_1ga3f9805f507320d2a864fe81eaac155b5) | | +| [`setName`](#group__symple_1ga97e213f54bcc541345da6867f3f083ed) | | +| [`setTime`](#group__symple_1gab3e4b9fa8d12289de33477c9ac68330a) | | -#### `public void setValue(bool value)` +--- +#### Event +```cpp +Event() +``` +--- +#### Event -#### `public void addValue(const std::string & value)` +```cpp +Event(const json::value & root) +``` -Appends a value to the value array. +| Parameter | Type | Description | +|-----------|------|-------------| +| `root` | `const json::value &` | | +--- +#### Event -#### `public void addValue(int value)` +```cpp +Event(const Event & root) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `root` | `const Event &` | | +--- +#### ~Event +```cpp +virtual ~Event() +``` -#### `public void addValue(double value)` +--- +#### valid +```cpp +virtual bool valid() const +``` +--- +#### name -#### `public void addValue(bool value)` +```cpp +std::string name() const +``` +--- +#### time +```cpp +std::time_t time() const +``` +--- -#### `public json::value & values()` +#### setName -Returns a JSON array of all values. +```cpp +void setName(const std::string & name) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | +--- -#### `public std::string value() const` +#### setTime +```cpp +void setTime(std::time_t time) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `time` | `std::time_t` | | + +## FormElement + +> **Subclasses:** `scy::smpl::Form`, `scy::smpl::FormField` +> **Defined in:** `form.h` + +### Members + +| Name | Description | +|------|-------------| +| [`FormElement`](#group__symple_1ga7e047bc6b6e46abe01a946a82745ee11) | | +| [`FormElement`](#group__symple_1ga3ef7f1f4de265f10ddcc83061e21ab77) | | +| [`FormElement`](#group__symple_1ga94f85597aa5b95ef7dcc246ef41787b9) | | +| [`operator=`](#group__symple_1ga0d7c97e98878eb69ebd8830df6a01e58) | | +| [`~FormElement`](#group__symple_1ga2c7bf72c2e0e6650fe27a68cd5e1beec) | | +| [`type`](#group__symple_1ga3b53f1858ddcc524004726f4d6a463b4) | | +| [`id`](#group__symple_1ga0eacc59669c12ecf4faf45395cc08f17) | | +| [`label`](#group__symple_1ga0bf79407646db8313d409ccc9a2f4ba8) | | +| [`setType`](#group__symple_1gae723f824695861e34898005f225e12b7) | Possible "type" values page, section, text, text-multi, list, list-multi, checkbox, media, custom | +| [`setId`](#group__symple_1gaba4de61935c0d3795d537964f47c33d0) | | +| [`setLabel`](#group__symple_1ga52798e6759dd37b1116720a37a2c967d) | | +| [`setHint`](#group__symple_1ga1a9595540a1969bb17a3115be6e26df6) | | +| [`setError`](#group__symple_1gaf621f96173fcbe523d419fd4a3a87f3e) | Sets and optional validation error message. | +| [`addPage`](#group__symple_1ga432f56acec954ed84897f7fc01059813) | | +| [`addSection`](#group__symple_1gab0619bb63ac7241e61c36f69bbc4ed07) | | +| [`addField`](#group__symple_1ga474c9727e83a9ce0e0b206d246379d6c) | | +| [`getField`](#group__symple_1gac9715a4fffff97d29092698755242cab) | | +| [`getField`](#group__symple_1gad7d9fdada931140ef706d58036afb0fe) | | +| [`hasField`](#group__symple_1gae28386fbc730fd60fea605384563dc1c) | Returns true if the given [Address](#structscy_1_1smpl_1_1Address) matches any of the internal form element IDs. If the partial flag is set then substring matches will be counted. | +| [`setLive`](#group__symple_1ga88878fc79bdeed108b06703d29fab26b) | Live fields or elements are used to submit partial sections a form, without sending the entire form. | +| [`live`](#group__symple_1gace9f6fd60c701c643d660971c159ce43) | Returns true if this field is live, meaning the form-processing entity should auto-update this field's value whenever it changes. | +| [`clearElements`](#group__symple_1gac2ee4183b9d5465c0036ee4a4c38e562) | Clears child elements matching the given ID. | +| [`clear`](#group__symple_1ga4cf4750e263530a525b89755b20677c6) | Clear the entire form. | +| [`valid`](#group__symple_1ga47cf107cf15ea93bdb9f377253f76aa6) | Returns true if the form element is valid. | +| [`numElements`](#group__symple_1gaae3b7577b27fb174619fc68801607ea1) | Returns the number of child elements. | +| [`hasErrors`](#group__symple_1ga50aa0c3f85c44063771f28b75de0a428) | Returns true if any fields have errors. | +| [`hasPages`](#group__symple_1ga61e65544fa1f0357bc0721864cc54768) | Returns true if the form has multiple pages. | +| [`root`](#group__symple_1gaade1f7bef1e9dcc71718a22cbc7ffa2d) | | +| [`_root`](#group__symple_1ga16c6666fcbd0fa750e6e14b2464a3ad5) | The root pointer is just a reference to the externally managed JSON value memory. | + +--- + +#### FormElement + +```cpp +FormElement() +``` -Returns the first value. Most formats (except multi) only require single value. +--- -#### `public int intValue() const` +#### FormElement +```cpp +FormElement(json::value & root, const std::string & type, const std::string & id, const std::string & label) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `root` | `json::value &` | | +| `type` | `const std::string &` | | +| `id` | `const std::string &` | | +| `label` | `const std::string &` | | +--- +#### FormElement -#### `public double doubleValue() const` +```cpp +FormElement(const FormElement & r) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `r` | `const FormElement &` | | +--- +#### operator= +```cpp +FormElement & operator=(const FormElement & r) +``` -#### `public bool boolValue() const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `r` | `const FormElement &` | | +--- +#### ~FormElement +```cpp +virtual ~FormElement() +``` +--- -# class `scy::smpl::Message` +#### type +```cpp +std::string type() const ``` -class scy::smpl::Message - : public value - : public scy::IPacket -``` - +--- +#### id +```cpp +std::string id() const +``` -## Summary +--- - Members | Descriptions ---------------------------------|--------------------------------------------- -`public Message()` | -`public Message(const json::value & root)` | -`public Message(const `[`Message`](#classscy_1_1smpl_1_1Message)` & root)` | -`public virtual ~Message()` | -`public virtual `[`IPacket`](#classscy_1_1IPacket)` * clone() const` | -`public virtual bool valid() const` | -`public virtual void clear()` | -`public virtual void clearData()` | -`public virtual void clearNotes()` | -`public std::string type() const` | -`public std::string id() const` | -`public `[`Address`](#structscy_1_1smpl_1_1Address)` to() const` | -`public `[`Address`](#structscy_1_1smpl_1_1Address)` from() const` | -`public int status() const` | -`public void setType(const std::string & type)` | -`public void setTo(const `[`Peer`](#classscy_1_1smpl_1_1Peer)` & to)` | -`public void setTo(const `[`Address`](#structscy_1_1smpl_1_1Address)` & to)` | -`public void setTo(const std::string & to)` | -`public void setFrom(const `[`Peer`](#classscy_1_1smpl_1_1Peer)` & from)` | -`public void setFrom(const `[`Address`](#structscy_1_1smpl_1_1Address)` & from)` | -`public void setFrom(const std::string & from)` | -`public void setStatus(int code)` | -`public json::value & notes()` | -`public void setNote(const std::string & type,const std::string & text)` | -`public void addNote(const std::string & type,const std::string & text)` | -`public json::value data(const std::string & name) const` | -`public json::value & data(const std::string & name)` | -`public json::value & setData(const std::string & name)` | -`public void setData(const std::string & name,const char * data)` | -`public void setData(const std::string & name,const std::string & data)` | -`public void setData(const std::string & name,const json::value & data)` | -`public void setData(const std::string & name,int data)` | -`public void removeData(const std::string & name)` | -`public bool hasData(const std::string & name)` | -`public virtual ssize_t read(const `[`ConstBuffer`](#classscy_1_1ConstBuffer)` &)` | -`public virtual ssize_t read(const std::string & root)` | -`public virtual void write(`[`Buffer`](#group__base_1gab10b36b080deb583ed703fca6b63ffdd)` &) const` | -`public bool isRequest() const` | -`public virtual size_t size() const` | -`public virtual void print(std::ostream & os) const` | -`public inline virtual const char * className() const` | +#### label -## Members +```cpp +std::string label() const +``` -#### `public Message()` +--- +#### setType +```cpp +void setType(const std::string & type) +``` +Possible "type" values page, section, text, text-multi, list, list-multi, checkbox, media, custom +| Parameter | Type | Description | +|-----------|------|-------------| +| `type` | `const std::string &` | | -#### `public Message(const json::value & root)` +--- +#### setId +```cpp +void setId(const std::string & id) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `id` | `const std::string &` | | +--- -#### `public Message(const `[`Message`](#classscy_1_1smpl_1_1Message)` & root)` +#### setLabel +```cpp +void setLabel(const std::string & text) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `text` | `const std::string &` | | +--- +#### setHint -#### `public virtual ~Message()` +```cpp +void setHint(const std::string & text) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `text` | `const std::string &` | | +--- +#### setError +```cpp +void setError(const std::string & error) +``` -#### `public virtual `[`IPacket`](#classscy_1_1IPacket)` * clone() const` +Sets and optional validation error message. +| Parameter | Type | Description | +|-----------|------|-------------| +| `error` | `const std::string &` | | +--- +#### addPage +```cpp +FormElement addPage(const std::string & id, const std::string & label) +``` -#### `public virtual bool valid() const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `id` | `const std::string &` | | +| `label` | `const std::string &` | | +--- +#### addSection +```cpp +FormElement addSection(const std::string & id, const std::string & label) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `id` | `const std::string &` | | +| `label` | `const std::string &` | | -#### `public virtual void clear()` +--- +#### addField +```cpp +FormField addField(const std::string & type, const std::string & id, const std::string & label) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `type` | `const std::string &` | | +| `id` | `const std::string &` | | +| `label` | `const std::string &` | | +--- -#### `public virtual void clearData()` +#### getField +```cpp +FormField getField(const std::string & id, bool partial) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `id` | `const std::string &` | | +| `partial` | `bool` | | +--- +#### getField -#### `public virtual void clearNotes()` +```cpp +bool getField(const std::string & id, FormField & field, bool partial) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `id` | `const std::string &` | | +| `field` | `FormField &` | | +| `partial` | `bool` | | +--- +#### hasField +```cpp +bool hasField(const std::string & id, bool partial) +``` -#### `public std::string type() const` +Returns true if the given [Address](#structscy_1_1smpl_1_1Address) matches any of the internal form element IDs. If the partial flag is set then substring matches will be counted. +| Parameter | Type | Description | +|-----------|------|-------------| +| `id` | `const std::string &` | | +| `partial` | `bool` | | +--- +#### setLive +```cpp +void setLive(bool flag) +``` -#### `public std::string id() const` +Live fields or elements are used to submit partial sections a form, without sending the entire form. +| Parameter | Type | Description | +|-----------|------|-------------| +| `flag` | `bool` | | +--- +#### live +```cpp +bool live() const +``` -#### `public `[`Address`](#structscy_1_1smpl_1_1Address)` to() const` +Returns true if this field is live, meaning the form-processing entity should auto-update this field's value whenever it changes. +--- +#### clearElements +```cpp +bool clearElements(const std::string & id, bool partial) +``` +Clears child elements matching the given ID. -#### `public `[`Address`](#structscy_1_1smpl_1_1Address)` from() const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `id` | `const std::string &` | | +| `partial` | `bool` | | +--- +#### clear +```cpp +void clear() +``` +Clear the entire form. -#### `public int status() const` +--- +#### valid +```cpp +bool valid() const +``` +Returns true if the form element is valid. +--- -#### `public void setType(const std::string & type)` +#### numElements +```cpp +int numElements() +``` +Returns the number of child elements. +--- +#### hasErrors -#### `public void setTo(const `[`Peer`](#classscy_1_1smpl_1_1Peer)` & to)` +```cpp +bool hasErrors() +``` +Returns true if any fields have errors. +--- +#### hasPages +```cpp +bool hasPages() +``` -#### `public void setTo(const `[`Address`](#structscy_1_1smpl_1_1Address)` & to)` +Returns true if the form has multiple pages. +--- +#### root +```cpp +json::value & root() const +``` +--- -#### `public void setTo(const std::string & to)` +#### _root +```cpp +json::value * _root +``` +The root pointer is just a reference to the externally managed JSON value memory. +## Form +> **Extends:** `scy::smpl::FormElement` +> **Defined in:** `form.h` -#### `public void setFrom(const `[`Peer`](#classscy_1_1smpl_1_1Peer)` & from)` +### Members +| Name | Description | +|------|-------------| +| [`Form`](#group__symple_1ga68e4093955870a7823a1a0e2fb32781a) | | +| [`Form`](#group__symple_1gab2fed5a941e921052b77cf4e94120f22) | | +| [`Form`](#group__symple_1gaa8a3c6e4f9bca2257fdae351d7621a45) | | +| [`~Form`](#group__symple_1ga78e6a83ae030945f05c990ea856d7281) | | +| [`valid`](#group__symple_1ga0259ae314e90190494940841638b4a0e) | | +| [`action`](#group__symple_1ga2974536cdcca932554f986ed1dbd7e58) | | +| [`partial`](#group__symple_1ga25bd29f8f64828762cfeb0d44a2be46c) | | +| [`setAction`](#group__symple_1ga8bc4b676485d8e4e28da58b2f941acb9) | Possible "action" values `form` The form-processing entity is asking the form-submitting entity to complete a form. `submit` The form-submitting entity is submitting data to the form-processing entity. `cancel` The form-submitting entity has cancelled submission of data to the form-processing entity. `result` The form-processing entity is returning data to the form-submitting entity. | +| [`setPartial`](#group__symple_1ga828e2ab5535b743420349e7bb1ff59f9) | Notifies the form is a partial section of the form. This is used for transmitting and updating live fields such as for auto-complete. | +--- +#### Form +```cpp +Form() +``` -#### `public void setFrom(const `[`Address`](#structscy_1_1smpl_1_1Address)` & from)` +--- +#### Form +```cpp +Form(json::value & root) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `root` | `json::value &` | | +--- -#### `public void setFrom(const std::string & from)` +#### Form +```cpp +Form(Command & root) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `root` | `Command &` | | +--- +#### ~Form -#### `public void setStatus(int code)` +```cpp +virtual ~Form() +``` +--- +#### valid -HTTP status codes are used to describe the message response. -**See also**: [http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html](http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html) +```cpp +bool valid() +``` -#### `public json::value & notes()` +--- +#### action +```cpp +std::string action() const +``` +--- +#### partial -#### `public void setNote(const std::string & type,const std::string & text)` +```cpp +bool partial() const +``` +--- +#### setAction -Set a note for the application Possible "type" values: `info`, `warn`, `error` +```cpp +void setAction(const std::string & action) +``` -#### `public void addNote(const std::string & type,const std::string & text)` +Possible "action" values `form` The form-processing entity is asking the form-submitting entity to complete a form. `submit` The form-submitting entity is submitting data to the form-processing entity. `cancel` The form-submitting entity has cancelled submission of data to the form-processing entity. `result` The form-processing entity is returning data to the form-submitting entity. +| Parameter | Type | Description | +|-----------|------|-------------| +| `action` | `const std::string &` | | +--- +#### setPartial +```cpp +void setPartial(bool flag) +``` -#### `public json::value data(const std::string & name) const` +Notifies the form is a partial section of the form. This is used for transmitting and updating live fields such as for auto-complete. +| Parameter | Type | Description | +|-----------|------|-------------| +| `flag` | `bool` | | + +## FormField + +> **Extends:** `scy::smpl::FormElement` +> **Defined in:** `form.h` + +### Members + +| Name | Description | +|------|-------------| +| [`FormField`](#group__symple_1gaf9378e4d88099d33f5c73cd6e5301841) | | +| [`FormField`](#group__symple_1gabe61a857e005af10301b5ac987d0946d) | | +| [`~FormField`](#group__symple_1gac0c5aeeef91f25f93d981deff77382dd) | | +| [`addOption`](#group__symple_1ga26777a113bae5c3083906e77b62d13f6) | Adds an option for list based fields. | +| [`addOption`](#group__symple_1gaf3d1bf938ba0cbeade0da2a18543a35d) | | +| [`setValue`](#group__symple_1gaeee92fee4944e5013ebef43eee2b9183) | Sets the value clearing all other values. | +| [`setValue`](#group__symple_1ga170d9a5ddc51953f406331b6da779bcf) | | +| [`setValue`](#group__symple_1gaa29f083206c8cbf9005f730f61b55dad) | | +| [`setValue`](#group__symple_1gaee3ee4b29024eee4fc34e1dded5267b8) | | +| [`addValue`](#group__symple_1ga7cd9073b9e7c2a476f17104d6e9ce8fb) | Appends a value to the value array. | +| [`addValue`](#group__symple_1ga89b16c8639181a01f676ea4ec1d48cbc) | | +| [`addValue`](#group__symple_1ga686348a5aacfc900b9a4d3d3aea903ad) | | +| [`addValue`](#group__symple_1ga89eaf8cd95b3a7f081e30f154720e883) | | +| [`values`](#group__symple_1ga5f80c4930f8fb7127d42f7af3ceb93aa) | Returns a JSON array of all values. | +| [`value`](#group__symple_1gae0051a3119d85c46034f1167a35fc9e5) | Returns the first value. Most formats (except multi) only require single value. | +| [`intValue`](#group__symple_1ga6806b9902742ea0bfe06e2a4a3e18cb1) | | +| [`doubleValue`](#group__symple_1ga744a0a50084034c5179a92b6c5538956) | | +| [`boolValue`](#group__symple_1ga6d0f293a15bce06dc455fc7535619eef) | | + +--- + +#### FormField + +```cpp +FormField() +``` +--- +#### FormField +```cpp +FormField(json::value & root, const std::string & type, const std::string & id, const std::string & label) +``` -#### `public json::value & data(const std::string & name)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `root` | `json::value &` | | +| `type` | `const std::string &` | | +| `id` | `const std::string &` | | +| `label` | `const std::string &` | | +--- +#### ~FormField +```cpp +virtual ~FormField() +``` +--- -#### `public json::value & setData(const std::string & name)` +#### addOption +```cpp +void addOption(const std::string & key, const std::string & value) +``` +Adds an option for list based fields. +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `const std::string &` | | +| `value` | `const std::string &` | | +--- -#### `public void setData(const std::string & name,const char * data)` +#### addOption +```cpp +void addOption(const std::string & value) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `value` | `const std::string &` | | +--- +#### setValue -#### `public void setData(const std::string & name,const std::string & data)` +```cpp +void setValue(const std::string & value) +``` +Sets the value clearing all other values. +| Parameter | Type | Description | +|-----------|------|-------------| +| `value` | `const std::string &` | | +--- +#### setValue -#### `public void setData(const std::string & name,const json::value & data)` +```cpp +void setValue(int value) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `value` | `int` | | +--- +#### setValue +```cpp +void setValue(double value) +``` -#### `public void setData(const std::string & name,int data)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `value` | `double` | | +--- +#### setValue +```cpp +void setValue(bool value) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `value` | `bool` | | -#### `public void removeData(const std::string & name)` +--- +#### addValue +```cpp +void addValue(const std::string & value) +``` +Appends a value to the value array. +| Parameter | Type | Description | +|-----------|------|-------------| +| `value` | `const std::string &` | | -#### `public bool hasData(const std::string & name)` +--- +#### addValue +```cpp +void addValue(int value) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `value` | `int` | | +--- -#### `public virtual ssize_t read(const `[`ConstBuffer`](#classscy_1_1ConstBuffer)` &)` +#### addValue +```cpp +void addValue(double value) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `value` | `double` | | -Read/parse to the packet from the given input buffer. The number of bytes read is returned. +--- -#### `public virtual ssize_t read(const std::string & root)` +#### addValue +```cpp +void addValue(bool value) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `value` | `bool` | | +--- +#### values -#### `public virtual void write(`[`Buffer`](#group__base_1gab10b36b080deb583ed703fca6b63ffdd)` &) const` +```cpp +json::value & values() +``` +Returns a JSON array of all values. +--- -Copy/generate to the packet given output buffer. The number of bytes written can be obtained from the buffer. +#### value -Todo: It may be prefferable to use our pod types here instead of buffer input, but the current codebase requires that the buffer be dynamically resizable for some protocols... +```cpp +std::string value() const +``` -#### `public bool isRequest() const` +Returns the first value. Most formats (except multi) only require single value. +--- +#### intValue +```cpp +int intValue() const +``` +--- -#### `public virtual size_t size() const` +#### doubleValue +```cpp +double doubleValue() const +``` +--- -The size of the packet in bytes. +#### boolValue -This is the nember of bytes that will be written on a call to [write()](#group__symple_1gac31e3c36ff63b87942058867a282fa29), but may not be the number of bytes that will be consumed by [read()](#group__symple_1ga41bc3235b35ef5ade9c5bc5e639701b9). +```cpp +bool boolValue() const +``` -#### `public virtual void print(std::ostream & os) const` +## Message + +> **Extends:** `json::value`, `scy::IPacket` +> **Subclasses:** `scy::smpl::Command`, `scy::smpl::Event`, `scy::smpl::Presence` +> **Defined in:** `message.h` + +### Members + +| Name | Description | +|------|-------------| +| [`Message`](#group__symple_1ga993977c8fc55c8b8b8ec172b720df218) | | +| [`Message`](#group__symple_1gaf736d72cc20d17cc96035a9ca153f7f9) | | +| [`Message`](#group__symple_1gad7ccee50283b43fb6203d5d38655b5a8) | | +| [`~Message`](#group__symple_1ga6a2eb621f26dda23a4e00cf085e28733) | | +| [`clone`](#group__symple_1ga7772d48d3c40973f8ba273404efbc0f5) | | +| [`valid`](#group__symple_1ga6bc8ec508472b3a845517e37a7d9ecee) | | +| [`clear`](#group__symple_1gab6a00a852821506f2003ea5916e0937f) | | +| [`clearData`](#group__symple_1ga004941b724014d459a60784e9f638d62) | | +| [`clearNotes`](#group__symple_1ga2a2409a6b3bbff22b57394f3c64f232f) | | +| [`type`](#group__symple_1ga238a19ce026c212bbbb53242e22e0b35) | | +| [`id`](#group__symple_1ga36664179f4acfcacf616fdbae6f42cc3) | | +| [`to`](#group__symple_1ga91b5760d36713eb890827f069f82b6c5) | | +| [`from`](#group__symple_1ga97accfebe0c98bf39caa4f92159a52c9) | | +| [`status`](#group__symple_1gad93c255aca03896f8e91a360022521c8) | | +| [`setType`](#group__symple_1gad1ff57aeeaa0788b12714750c856aa97) | | +| [`setTo`](#group__symple_1ga59aff14b0a347efc0d7cd13790aee564) | | +| [`setTo`](#group__symple_1ga35ebeab4af091f299ea7813dec40b611) | | +| [`setTo`](#group__symple_1gaa95416e0a9ebdeae0311cfc2f5ec9a7a) | | +| [`setFrom`](#group__symple_1ga883e4a76d045695cbeb1d95fd6b09a06) | | +| [`setFrom`](#group__symple_1ga0121323c2d20f1ee7b6ec0b65949dd82) | | +| [`setFrom`](#group__symple_1gae951b7a32bf75402fc59b2eacd29e262) | | +| [`setStatus`](#group__symple_1gaaf9e802be207af079eb682439868720b) | HTTP status codes are used to describe the message response. **See also**: [http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html](http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html) | +| [`notes`](#group__symple_1ga423f8746648172da7e2fcaa7d5e61333) | | +| [`setNote`](#group__symple_1ga2a15db81f2ee696f70977047dc5c1388) | Set a note for the application Possible "type" values: `info`, `warn`, `error` | +| [`addNote`](#group__symple_1gabf23c5c1f2a42649d2c85ca0502bf7d5) | | +| [`data`](#group__symple_1gaee52f1f411f45da20cb48fea81b141f8) | | +| [`data`](#group__symple_1ga579e0d948fe9cca7ece181b0e851c72f) | | +| [`setData`](#group__symple_1ga737ffbb719a355701337880a4e27c754) | | +| [`setData`](#group__symple_1ga46b69d25c45569ff2c15f5c1982226c0) | | +| [`setData`](#group__symple_1ga27601dfabf9f11b474046c765f01d0f6) | | +| [`setData`](#group__symple_1ga24c090297182428c0391e4850439facc) | | +| [`setData`](#group__symple_1gab75585a9f4e4555c0a7da64926a3a5fd) | | +| [`removeData`](#group__symple_1gaad4ce633c0a2f4be14c2dc34114aea14) | | +| [`hasData`](#group__symple_1ga622a343fa5a0c26fe39d0a8822756d79) | | +| [`read`](#group__symple_1ga41bc3235b35ef5ade9c5bc5e639701b9) | Read/parse to the packet from the given input buffer. The number of bytes read is returned. | +| [`read`](#group__symple_1gacb4307d7c2134e6720b380553e56fa74) | | +| [`write`](#group__symple_1gac31e3c36ff63b87942058867a282fa29) | Copy/generate to the packet given output buffer. The number of bytes written can be obtained from the buffer. | +| [`isRequest`](#group__symple_1ga8893c0f725efc3aa1f42e0d8de208879) | | +| [`size`](#group__symple_1gae7dcb4133dd8d5a3492629aabf85b385) | The size of the packet in bytes. | +| [`print`](#group__symple_1gaefb77bc8f9a03adc57f931d0b1d1e05d) | | +| [`className`](#group__symple_1gaaae1eafc94ace22f9d961cc985ba9984) | | + +--- + +#### Message + +```cpp +Message() +``` +--- +#### Message +```cpp +Message(const json::value & root) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `root` | `const json::value &` | | -#### `public inline virtual const char * className() const` +--- +#### Message +```cpp +Message(const Message & root) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `root` | `const Message &` | | +--- -# class `scy::smpl::Peer` +#### ~Message +```cpp +virtual ~Message() ``` -class scy::smpl::Peer - : public value -``` +--- +#### clone -This class represents a peer on the network. A [Peer](#classscy_1_1smpl_1_1Peer) object may also contain arbitrary data set by the client to share with other peers on the network. -**See also**: [Address](#structscy_1_1smpl_1_1Address) for further methods and [basic](#namespacescy_1_1basic) accessors. - -## Summary +```cpp +virtual IPacket * clone() const +``` - Members | Descriptions ---------------------------------|--------------------------------------------- -`public Peer()` | -`public Peer(const `[`Peer`](#classscy_1_1smpl_1_1Peer)` & r)` | -`public Peer(const json::value & r)` | -`public virtual ~Peer()` | -`public `[`Address`](#structscy_1_1smpl_1_1Address)` address() const` | -`public std::string id() const` | -`public std::string user() const` | -`public std::string name() const` | -`public std::string type() const` | -`public std::string host() const` | -`public void setID(const std::string & id)` | -`public void setUser(const std::string & user)` | -`public void setName(const std::string & name)` | -`public void setType(const std::string & type)` | -`public void setHost(const std::string & host)` | -`public virtual bool valid()` | Updates the peer from the given data object. -`public void print(std::ostream & os) const` | -`public inline virtual const char * className() const` | +--- -## Members +#### valid -#### `public Peer()` +```cpp +virtual bool valid() const +``` +--- +#### clear +```cpp +virtual void clear() +``` +--- -#### `public Peer(const `[`Peer`](#classscy_1_1smpl_1_1Peer)` & r)` +#### clearData +```cpp +virtual void clearData() +``` +--- +#### clearNotes +```cpp +virtual void clearNotes() +``` -#### `public Peer(const json::value & r)` +--- +#### type +```cpp +std::string type() const +``` +--- +#### id -#### `public virtual ~Peer()` +```cpp +std::string id() const +``` +--- +#### to +```cpp +Address to() const +``` +--- -#### `public `[`Address`](#structscy_1_1smpl_1_1Address)` address() const` +#### from +```cpp +Address from() const +``` +--- +#### status +```cpp +int status() const +``` -#### `public std::string id() const` +--- +#### setType +```cpp +void setType(const std::string & type) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `type` | `const std::string &` | | +--- -#### `public std::string user() const` +#### setTo +```cpp +void setTo(const Peer & to) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `to` | `const Peer &` | | +--- +#### setTo -#### `public std::string name() const` +```cpp +void setTo(const Address & to) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `to` | `const Address &` | | +--- +#### setTo +```cpp +void setTo(const std::string & to) +``` -#### `public std::string type() const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `to` | `const std::string &` | | +--- +#### setFrom +```cpp +void setFrom(const Peer & from) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `from` | `const Peer &` | | -#### `public std::string host() const` +--- +#### setFrom +```cpp +void setFrom(const Address & from) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `from` | `const Address &` | | +--- -#### `public void setID(const std::string & id)` +#### setFrom +```cpp +void setFrom(const std::string & from) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `from` | `const std::string &` | | +--- +#### setStatus -#### `public void setUser(const std::string & user)` +```cpp +void setStatus(int code) +``` +HTTP status codes are used to describe the message response. **See also**: [http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html](http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html) +| Parameter | Type | Description | +|-----------|------|-------------| +| `code` | `int` | | +--- +#### notes -#### `public void setName(const std::string & name)` +```cpp +json::value & notes() +``` +--- +#### setNote +```cpp +void setNote(const std::string & type, const std::string & text) +``` +Set a note for the application Possible "type" values: `info`, `warn`, `error` -#### `public void setType(const std::string & type)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `type` | `const std::string &` | | +| `text` | `const std::string &` | | +--- +#### addNote +```cpp +void addNote(const std::string & type, const std::string & text) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `type` | `const std::string &` | | +| `text` | `const std::string &` | | -#### `public void setHost(const std::string & host)` +--- +#### data +```cpp +json::value data(const std::string & name) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | +--- -#### `public virtual bool valid()` +#### data -Updates the peer from the given data object. +```cpp +json::value & data(const std::string & name) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | +--- -#### `public void print(std::ostream & os) const` +#### setData +```cpp +json::value & setData(const std::string & name) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | +--- +#### setData -#### `public inline virtual const char * className() const` +```cpp +void setData(const std::string & name, const char * data) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | +| `data` | `const char *` | | +--- +#### setData +```cpp +void setData(const std::string & name, const std::string & data) +``` -# class `scy::smpl::Presence` +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | +| `data` | `const std::string &` | | -``` -class scy::smpl::Presence - : public scy::smpl::Message -``` +--- +#### setData +```cpp +void setData(const std::string & name, const json::value & data) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | +| `data` | `const json::value &` | | +--- -## Summary +#### setData - Members | Descriptions ---------------------------------|--------------------------------------------- -`public Presence()` | -`public Presence(const json::value & root)` | -`public Presence(const `[`Presence`](#classscy_1_1smpl_1_1Presence)` & root)` | -`public virtual ~Presence()` | -`public bool isProbe()` | -`public void setProbe(bool flag)` | +```cpp +void setData(const std::string & name, int data) +``` -## Members +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | +| `data` | `int` | | -#### `public Presence()` +--- +#### removeData +```cpp +void removeData(const std::string & name) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | +--- -#### `public Presence(const json::value & root)` +#### hasData +```cpp +bool hasData(const std::string & name) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | +--- +#### read -#### `public Presence(const `[`Presence`](#classscy_1_1smpl_1_1Presence)` & root)` +```cpp +virtual ssize_t read(const ConstBuffer &) +``` +Read/parse to the packet from the given input buffer. The number of bytes read is returned. +--- +#### read +```cpp +virtual ssize_t read(const std::string & root) +``` -#### `public virtual ~Presence()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `root` | `const std::string &` | | +--- +#### write +```cpp +virtual void write(Buffer &) const +``` +Copy/generate to the packet given output buffer. The number of bytes written can be obtained from the buffer. -#### `public bool isProbe()` +Todo: It may be prefferable to use our pod types here instead of buffer input, but the current codebase requires that the buffer be dynamically resizable for some protocols... +--- +#### isRequest +```cpp +bool isRequest() const +``` +--- -#### `public void setProbe(bool flag)` +#### size +```cpp +virtual size_t size() const +``` +The size of the packet in bytes. +This is the nember of bytes that will be written on a call to [write()](#group__symple_1gac31e3c36ff63b87942058867a282fa29), but may not be the number of bytes that will be consumed by [read()](#group__symple_1ga41bc3235b35ef5ade9c5bc5e639701b9). +--- -# class `scy::smpl::Roster` +#### print +```cpp +virtual void print(std::ostream & os) const ``` -class scy::smpl::Roster - : public scy::LiveCollection< std::string, Peer > -``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `os` | `std::ostream &` | | +--- -The [Roster](#classscy_1_1smpl_1_1Roster) provides a registry for active network peers indexed by session ID. +#### className -## Summary +```cpp +virtual inline const char * className() const +``` - Members | Descriptions ---------------------------------|--------------------------------------------- -`public Roster()` | -`public virtual ~Roster()` | -`public `[`Peer`](#classscy_1_1smpl_1_1Peer)` * getByHost(const std::string & host)` | Returns the first peer which matches the given host address. -`public virtual PeerMap peers() const` | -`public virtual void print(std::ostream & os) const` | -`public inline virtual const char * className() const` | +## Peer + +> **Extends:** `json::value` +> **Defined in:** `peer.h` + +This class represents a peer on the network. A [Peer](#classscy_1_1smpl_1_1Peer) object may also contain arbitrary data set by the client to share with other peers on the network. **See also**: [Address](#structscy_1_1smpl_1_1Address) for further methods and [basic](./doc/api-undefined.md#namespacescy_1_1basic) accessors. + +### Members + +| Name | Description | +|------|-------------| +| [`Peer`](#group__symple_1ga21699ec274f5b4a4609fa1232c7c2759) | | +| [`Peer`](#group__symple_1gaf1d1b51b210184552aa1e52ed9c1043f) | | +| [`Peer`](#group__symple_1ga2be2d8f4cc8f1f0a5ce2d7c4187645a1) | | +| [`~Peer`](#group__symple_1gab6b9fd40ad19b75f1476719938486687) | | +| [`address`](#group__symple_1gae18b7a663a71100f65a480a309928274) | | +| [`id`](#group__symple_1ga477d474d5af82b4d59a762efa970bb1a) | | +| [`user`](#group__symple_1ga9731497468e46249d9640bb38637ebdd) | | +| [`name`](#group__symple_1ga52cc114ca838238810e3d554425194b7) | | +| [`type`](#group__symple_1gab1ff841dfeb0d69ac798ad12c55bf43d) | | +| [`host`](#group__symple_1gae1ac4cb0de0b4845a2f73403b3caa83e) | | +| [`setID`](#group__symple_1ga0901ffbe8ce396fb01d83553815bad54) | | +| [`setUser`](#group__symple_1ga6da2b366cdda5ed7dfaa11b69d20ef37) | | +| [`setName`](#group__symple_1gaae1a1e30ed070876d5dc7d124a99434e) | | +| [`setType`](#group__symple_1ga6b4ce3657cc8995ad02e7c51939f1d53) | | +| [`setHost`](#group__symple_1ga1bab6aa0690fff8ca6cbf8749fc0efd8) | | +| [`valid`](#group__symple_1gad056870e5ed4649ca9d218c9cc6c8df3) | Updates the peer from the given data object. | +| [`print`](#group__symple_1gaba929db58e4c8245ed8e0c61d7f6bc57) | | +| [`className`](#group__symple_1ga9a99cfc94cb96aef6c338e514a254809) | | + +--- + +#### Peer + +```cpp +Peer() +``` -## Members +--- -#### `public Roster()` +#### Peer +```cpp +Peer(const Peer & r) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `r` | `const Peer &` | | +--- +#### Peer -#### `public virtual ~Roster()` +```cpp +Peer(const json::value & r) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `r` | `const json::value &` | | +--- +#### ~Peer +```cpp +virtual ~Peer() +``` -#### `public `[`Peer`](#classscy_1_1smpl_1_1Peer)` * getByHost(const std::string & host)` +--- -Returns the first peer which matches the given host address. +#### address +```cpp +Address address() const +``` +--- -#### `public virtual PeerMap peers() const` +#### id +```cpp +std::string id() const +``` +--- +#### user +```cpp +std::string user() const +``` -#### `public virtual void print(std::ostream & os) const` +--- +#### name +```cpp +std::string name() const +``` +--- +#### type -#### `public inline virtual const char * className() const` +```cpp +std::string type() const +``` +--- +#### host +```cpp +std::string host() const +``` +--- -# class `scy::smpl::SSLClient` +#### setID +```cpp +void setID(const std::string & id) ``` -class scy::smpl::SSLClient - : public scy::smpl::Client -``` - +| Parameter | Type | Description | +|-----------|------|-------------| +| `id` | `const std::string &` | | +--- +#### setUser -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public SSLClient(const `[`Client::Options`](#structscy_1_1smpl_1_1Client_1_1Options)` & options,uv::Loop * loop)` | +```cpp +void setUser(const std::string & user) +``` -## Members +| Parameter | Type | Description | +|-----------|------|-------------| +| `user` | `const std::string &` | | -#### `public SSLClient(const `[`Client::Options`](#structscy_1_1smpl_1_1Client_1_1Options)` & options,uv::Loop * loop)` +--- +#### setName +```cpp +void setName(const std::string & name) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | +--- -# class `scy::smpl::TCPClient` +#### setType +```cpp +void setType(const std::string & type) ``` -class scy::smpl::TCPClient - : public scy::smpl::Client -``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `type` | `const std::string &` | | + +--- +#### setHost +```cpp +void setHost(const std::string & host) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `host` | `const std::string &` | | -## Summary +--- - Members | Descriptions ---------------------------------|--------------------------------------------- -`public TCPClient(const `[`Client::Options`](#structscy_1_1smpl_1_1Client_1_1Options)` & options,uv::Loop * loop)` | +#### valid -## Members +```cpp +virtual bool valid() +``` -#### `public TCPClient(const `[`Client::Options`](#structscy_1_1smpl_1_1Client_1_1Options)` & options,uv::Loop * loop)` +Updates the peer from the given data object. +--- +#### print +```cpp +void print(std::ostream & os) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `os` | `std::ostream &` | | -# struct `scy::smpl::Address` +--- +#### className +```cpp +virtual inline const char * className() const +``` +## Presence -The [Address](#structscy_1_1smpl_1_1Address) structure is an endpoint identifier for a peer on the network. The format is like so: user|id +> **Extends:** `scy::smpl::Message` +> **Defined in:** `presence.h` -## Summary +### Members - Members | Descriptions ---------------------------------|--------------------------------------------- -`public std::string user` | -`public std::string id` | -`public Address()` | -`public Address(const std::string & addr)` | -`public Address(const std::string & user,const std::string & id)` | -`public virtual ~Address()` | -`public bool parse(const std::string & addr)` | -`public bool valid() const` | -`public void print(std::ostream & os) const` | -`public std::string toString() const` | -`public bool operator==(const `[`Address`](#structscy_1_1smpl_1_1Address)` & r)` | -`public bool operator==(std::string & r)` | +| Name | Description | +|------|-------------| +| [`Presence`](#group__symple_1ga8e1bf8928c147286c6992a68ba000b22) | | +| [`Presence`](#group__symple_1ga5b4433cbeca31ebc1d47be79a5e35e9f) | | +| [`Presence`](#group__symple_1gaa1b5a011069c478b0cc808efa0b8e3d2) | | +| [`~Presence`](#group__symple_1gae3237592f9d4e644c94eb9652b3ddd82) | | +| [`isProbe`](#group__symple_1ga2a03e7f09b7455a88ebc06bea78da377) | | +| [`setProbe`](#group__symple_1ga991b723ca51fbcc7d4b0a6e5ee9577ae) | | -## Members +--- -#### `public std::string user` +#### Presence +```cpp +Presence() +``` +--- +#### Presence +```cpp +Presence(const json::value & root) +``` -#### `public std::string id` +| Parameter | Type | Description | +|-----------|------|-------------| +| `root` | `const json::value &` | | +--- +#### Presence +```cpp +Presence(const Presence & root) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `root` | `const Presence &` | | -#### `public Address()` +--- +#### ~Presence +```cpp +virtual ~Presence() +``` +--- +#### isProbe -#### `public Address(const std::string & addr)` +```cpp +bool isProbe() +``` +--- +#### setProbe +```cpp +void setProbe(bool flag) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `flag` | `bool` | | -#### `public Address(const std::string & user,const std::string & id)` +## Roster +> **Extends:** `scy::LiveCollection< std::string, Peer >` +> **Defined in:** `roster.h` +The [Roster](#classscy_1_1smpl_1_1Roster) provides a registry for active network peers indexed by session ID. +### Members +| Name | Description | +|------|-------------| +| [`Roster`](#group__symple_1ga52cf6d7c73b07459e7231898cf3267c0) | | +| [`~Roster`](#group__symple_1ga548c497780612733999913ad9be891a6) | | +| [`getByHost`](#group__symple_1ga2762fe4481b419996e1f6f8ca51a222d) | Returns the first peer which matches the given host address. | +| [`peers`](#group__symple_1ga82d3344e72e6d3cea1acee9929613076) | Returns a copy of the peer map for thread-safe iteration. | +| [`print`](#group__symple_1ga1938a8f8c5784b7cafd64225133a1bae) | | +| [`className`](#group__symple_1ga626f160e6db0deb2de31b4d6f85a1689) | | -#### `public virtual ~Address()` +--- +#### Roster +```cpp +Roster() +``` +--- +#### ~Roster -#### `public bool parse(const std::string & addr)` +```cpp +virtual ~Roster() +``` +--- +#### getByHost +```cpp +Peer * getByHost(const std::string & host) +``` +Returns the first peer which matches the given host address. -#### `public bool valid() const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `host` | `const std::string &` | | +--- +#### peers +```cpp +virtual PeerMap peers() const +``` +Returns a copy of the peer map for thread-safe iteration. -#### `public void print(std::ostream & os) const` +--- +#### print +```cpp +virtual void print(std::ostream & os) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `os` | `std::ostream &` | | +--- -#### `public std::string toString() const` +#### className +```cpp +virtual inline const char * className() const +``` +## Address +> **Defined in:** `address.h` +The [Address](#structscy_1_1smpl_1_1Address) structure is an endpoint identifier for a peer on the network. The format is like so: user|id -#### `public bool operator==(const `[`Address`](#structscy_1_1smpl_1_1Address)` & r)` +### Members + +| Name | Description | +|------|-------------| +| [`Address`](#group__symple_1gac343658359ea35750fc8db0954b4859b) | | +| [`Address`](#group__symple_1ga7767484bbc9b2b9eef8ed405a1d6df4e) | | +| [`Address`](#group__symple_1ga124f7f256546189d7bb40403f15d1aee) | | +| [`~Address`](#group__symple_1gaec7089a1558336d72614e3ac3c6fe31b) | | +| [`parse`](#group__symple_1gadce752de542bbfc15cbbc6bd3399a609) | | +| [`valid`](#group__symple_1gad9683597832591065ff7527d9d0d1e7b) | | +| [`print`](#group__symple_1gae575d3b61d86073b6644fb77525e12b8) | | +| [`toString`](#group__symple_1ga3e7d857b2da0971cc034191a13ce4936) | | +| [`operator==`](#group__symple_1ga8404d6640ae900b3a41bd5bc9eb1ec0e) | | +| [`operator==`](#group__symple_1gad2e78b790fca7e0f7a234cdb3c39bd3c) | | +| [`user`](#group__symple_1gab04caf4352786515fca8fce459a56931) | | +| [`id`](#group__symple_1gae830f59b90e94397743b6f9540a7afe0) | | + +--- + +#### Address + +```cpp +Address() +``` +--- +#### Address +```cpp +Address(const std::string & addr) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `addr` | `const std::string &` | | -#### `public bool operator==(std::string & r)` +--- +#### Address +```cpp +Address(const std::string & user, const std::string & id) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `user` | `const std::string &` | | +| `id` | `const std::string &` | | +--- -# struct `scy::smpl::Filter` +#### ~Address +```cpp +virtual ~Address() +``` +--- +#### parse +```cpp +bool parse(const std::string & addr) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `addr` | `const std::string &` | | -## Summary +--- - Members | Descriptions ---------------------------------|--------------------------------------------- -`public `[`Bitwise`](./doc/api-base.md#structscy_1_1Bitwise)` flags` | -`public std::string path` | -`public inline Filter(const std::string & path,unsigned flags)` | -`public inline Filter(unsigned flags)` | +#### valid -## Members +```cpp +bool valid() const +``` -#### `public `[`Bitwise`](./doc/api-base.md#structscy_1_1Bitwise)` flags` +--- +#### print +```cpp +void print(std::ostream & os) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `os` | `std::ostream &` | | +--- -#### `public std::string path` +#### toString +```cpp +std::string toString() const +``` +--- +#### operator== +```cpp +bool operator==(const Address & r) +``` -#### `public inline Filter(const std::string & path,unsigned flags)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `r` | `const Address &` | | +--- +#### operator== +```cpp +bool operator==(std::string & r) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `r` | `std::string &` | | -#### `public inline Filter(unsigned flags)` +--- +#### user +```cpp +std::string user +``` +--- +#### id -# struct `scy::smpl::Client::Options` +```cpp +std::string id +``` +## Options +> **Defined in:** `client.h` +### Members +| Name | Description | +|------|-------------| +| [`Options`](#group__symple_1ga7dd4fee81e4318912e9d82a1e35c6550) | | +| [`host`](#group__symple_1ga05d0bdf5ab5eeefec7d0019bb110bb58) | | +| [`port`](#group__symple_1ga1b77c19ba3010b95adab9572de8812d4) | | +| [`reconnection`](#group__symple_1ga8388c0e51b717793da8e136f24ef4df6) | Weather or not to reconnect if disconnected from the server. | +| [`reconnectAttempts`](#group__symple_1gaad73b34182da94bd80d394d6c2cf8d59) | The number of times to attempt to reconnect if disconnected from the server. (0 = unlimited) | +| [`user`](#group__symple_1gace5d72442ca0ddd400242766dcbe0075) | | +| [`name`](#group__symple_1ga937a706d0ff802b29881200dd0f9b140) | | +| [`type`](#group__symple_1ga3a94f72a2f8e72b1bb84f11630f9cd9a) | | +| [`token`](#group__symple_1gae46b1ce6b2a9c5e8ae983cf36137d18d) | | +--- -## Summary +#### Options - Members | Descriptions ---------------------------------|--------------------------------------------- -`public std::string host` | -`public uint16_t port` | -`public bool reconnection` | Weather or not to reconnect if disconnected from the server. -`public int reconnectAttempts` | -`public std::string user` | -`public std::string name` | -`public std::string type` | -`public std::string token` | -`public inline Options()` | +```cpp +inline Options() +``` -## Members +--- -#### `public std::string host` +#### host +```cpp +std::string host = "127.0.0.1" +``` +--- +#### port +```cpp +uint16_t port = 4500 +``` -#### `public uint16_t port` +--- +#### reconnection +```cpp +bool reconnection = true +``` +Weather or not to reconnect if disconnected from the server. +--- -#### `public bool reconnection` +#### reconnectAttempts -Weather or not to reconnect if disconnected from the server. +```cpp +int reconnectAttempts = 0 +``` +The number of times to attempt to reconnect if disconnected from the server. (0 = unlimited) +--- -#### `public int reconnectAttempts` +#### user +```cpp +std::string user +``` +--- -The number of times to attempt to reconnect if disconnected from the server. (0 = unlimited) +#### name -#### `public std::string user` +```cpp +std::string name +``` +--- +#### type +```cpp +std::string type +``` +--- -#### `public std::string name` +#### token +```cpp +std::string token +``` +## Filter +> **Defined in:** `client.h` +### Members -#### `public std::string type` +| Name | Description | +|------|-------------| +| [`Filter`](#group__symple_1ga7e21efcc6d5fc951be79a19e246294dd) | | +| [`Filter`](#group__symple_1ga1f3cd2015d9c9dd0f710ec47c2d68e03) | | +| [`flags`](#group__symple_1ga84b2f5acb1cf965cae191acd953dfad4) | | +| [`path`](#group__symple_1ga54304a93d73847a0a53f8f1da50a62a1) | | +--- +#### Filter +```cpp +inline Filter(const std::string & path, unsigned flags) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `path` | `const std::string &` | | +| `flags` | `unsigned` | | -#### `public std::string token` +--- +#### Filter +```cpp +inline Filter(unsigned flags) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `flags` | `unsigned` | | +--- -#### `public inline Options()` +#### flags +```cpp +Bitwise flags +``` +--- +#### path +```cpp +std::string path +``` diff --git a/doc/api-turn.md b/doc/api-turn.md index ba8228842..5e860d7d8 100644 --- a/doc/api-turn.md +++ b/doc/api-turn.md @@ -1,2133 +1,3407 @@ -# Module `turn` +# turn The `turn` module contains TURN (rfc5766) client and server implementations. -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`namespace `[`scy::turn`](#namespacescy_1_1turn) | -`struct `[`scy::turn::Client::Options`](#structscy_1_1turn_1_1Client_1_1Options) | -# namespace `scy::turn` - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`class `[`scy::turn::Client`](#classscy_1_1turn_1_1Client) | -`class `[`scy::turn::FiveTuple`](#classscy_1_1turn_1_1FiveTuple) | -`class `[`scy::turn::IAllocation`](#classscy_1_1turn_1_1IAllocation) | -`class `[`scy::turn::Request`](#classscy_1_1turn_1_1Request) | -`class `[`scy::turn::Server`](#classscy_1_1turn_1_1Server) | TURN server rfc5766 implementation. -`class `[`scy::turn::ServerAllocation`](#classscy_1_1turn_1_1ServerAllocation) | -`class `[`scy::turn::TCPAllocation`](#classscy_1_1turn_1_1TCPAllocation) | -`class `[`scy::turn::TCPClient`](#classscy_1_1turn_1_1TCPClient) | -`class `[`scy::turn::TCPConnectionPair`](#classscy_1_1turn_1_1TCPConnectionPair) | -`class `[`scy::turn::UDPAllocation`](#classscy_1_1turn_1_1UDPAllocation) | -`class `[`scy::turn::UDPClient`](#classscy_1_1turn_1_1UDPClient) | -`struct `[`scy::turn::ClientObserver`](#structscy_1_1turn_1_1ClientObserver) | -`struct `[`scy::turn::ClientState`](#structscy_1_1turn_1_1ClientState) | -`struct `[`scy::turn::Permission`](#structscy_1_1turn_1_1Permission) | TURN permission for a user session. -`struct `[`scy::turn::RelayConnectionBinding`](#structscy_1_1turn_1_1RelayConnectionBinding) | -`struct `[`scy::turn::ServerObserver`](#structscy_1_1turn_1_1ServerObserver) | -`struct `[`scy::turn::ServerOptions`](#structscy_1_1turn_1_1ServerOptions) | [Configuration](#classscy_1_1Configuration) options for the TURN server. -`struct `[`scy::turn::TCPClientObserver`](#structscy_1_1turn_1_1TCPClientObserver) | -# class `scy::turn::Client` - -``` -class scy::turn::Client - : public scy::Stateful< ClientState > - : protected scy::turn::IAllocation -``` - - - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public Client(`[`ClientObserver`](#structscy_1_1turn_1_1ClientObserver)` & observer,const `[`Options`](#structscy_1_1turn_1_1Client_1_1Options)` & options,const net::Socket::Ptr & socket)` | -`public virtual ~Client()` | -`public virtual void initiate()` | Initiates the allocation sequence. -`public virtual void shutdown()` | Shutdown the client and destroy the active allocation. -`public virtual void sendAllocate()` | Sends the allocation request. -`public virtual void addPermission(const IPList & peerIPs)` | -`public virtual void addPermission(const std::string & ip)` | -`public virtual void sendCreatePermission()` | Sends a CreatePermission request including all hosts. -`public virtual void sendChannelBind(const std::string & peerIP)` | -`public virtual void sendRefresh()` | -`public virtual void sendData(const char * data,size_t size,const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddress)` | -`public virtual bool handleResponse(const `[`stun::Message`](#classscy_1_1stun_1_1Message)` & response)` | -`public virtual void handleAllocateResponse(const `[`stun::Message`](#classscy_1_1stun_1_1Message)` & response)` | -`public virtual void handleAllocateErrorResponse(const `[`stun::Message`](#classscy_1_1stun_1_1Message)` & response)` | -`public virtual void handleCreatePermissionResponse(const `[`stun::Message`](#classscy_1_1stun_1_1Message)` & response)` | -`public virtual void handleCreatePermissionErrorResponse(const `[`stun::Message`](#classscy_1_1stun_1_1Message)` & response)` | -`public virtual void handleRefreshResponse(const `[`stun::Message`](#classscy_1_1stun_1_1Message)` & response)` | -`public virtual void handleDataIndication(const `[`stun::Message`](#classscy_1_1stun_1_1Message)` & response)` | -`public virtual int transportProtocol()` | -`public virtual `[`stun::Transaction`](#classscy_1_1stun_1_1Transaction)` * createTransaction(const net::Socket::Ptr & socket)` | -`public virtual void authenticateRequest(`[`stun::Message`](#classscy_1_1stun_1_1Message)` & request)` | -`public virtual bool sendAuthenticatedTransaction(`[`stun::Transaction`](#classscy_1_1stun_1_1Transaction)` * transaction)` | -`public virtual bool removeTransaction(`[`stun::Transaction`](#classscy_1_1stun_1_1Transaction)` * transaction)` | -`public `[`net::Address`](#classscy_1_1net_1_1Address)` mappedAddress() const` | -`public virtual `[`net::Address`](#classscy_1_1net_1_1Address)` relayedAddress() const` | -`public bool closed() const` | -`public `[`ClientObserver`](#structscy_1_1turn_1_1ClientObserver)` & observer()` | -`public `[`Options`](#structscy_1_1turn_1_1Client_1_1Options)` & options()` | -`protected `[`ClientObserver`](./doc/api-turn.md#structscy_1_1turn_1_1ClientObserver)` & _observer` | -`protected `[`Options`](./doc/api-turn.md#structscy_1_1turn_1_1Client_1_1Options)` _options` | -`protected `[`net::SocketEmitter`](./doc/api-net.md#classscy_1_1net_1_1SocketEmitter)` _socket` | -`protected `[`Timer`](./doc/api-base.md#classscy_1_1Timer)` _timer` | -`protected `[`scy::Error`](./doc/api-base.md#structscy_1_1Error)` _error` | -`protected `[`net::Address`](./doc/api-net.md#classscy_1_1net_1_1Address)` _mappedAddress` | -`protected `[`net::Address`](./doc/api-net.md#classscy_1_1net_1_1Address)` _relayedAddress` | -`protected std::string _realm` | -`protected std::string _nonce` | -`protected std::deque< `[`stun::Message`](./doc/api-stun.md#classscy_1_1stun_1_1Message)` > _pendingIndications` | A list of queued Send indication packets awaiting server permissions. -`protected std::vector< `[`stun::Transaction`](./doc/api-stun.md#classscy_1_1stun_1_1Transaction)` * > _transactions` | A list containing currently active transactions. -`protected virtual void setError(const `[`scy::Error`](#structscy_1_1Error)` & error)` | -`protected virtual void onSocketConnect(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket)` | -`protected virtual void onSocketRecv(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket,const `[`MutableBuffer`](#classscy_1_1MutableBuffer)` & buffer,const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddress)` | -`protected virtual void onSocketClose(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket)` | -`protected virtual void onTransactionProgress(void * sender,`[`TransactionState`](#structscy_1_1TransactionState)` & state,const `[`TransactionState`](#structscy_1_1TransactionState)` &)` | -`protected virtual void onStateChange(`[`ClientState`](#structscy_1_1turn_1_1ClientState)` & state,const `[`ClientState`](#structscy_1_1turn_1_1ClientState)` & oldState)` | -`protected virtual void onTimer()` | - -## Members - -#### `public Client(`[`ClientObserver`](#structscy_1_1turn_1_1ClientObserver)` & observer,const `[`Options`](#structscy_1_1turn_1_1Client_1_1Options)` & options,const net::Socket::Ptr & socket)` - - - - - -#### `public virtual ~Client()` - - - - - -#### `public virtual void initiate()` - -Initiates the allocation sequence. - - - -#### `public virtual void shutdown()` - -Shutdown the client and destroy the active allocation. - - - -#### `public virtual void sendAllocate()` - -Sends the allocation request. +### Classes + +| Name | Description | +|------|-------------| +| [`Client`](#classscy_1_1turn_1_1Client) | | +| [`TCPClient`](#classscy_1_1turn_1_1TCPClient) | | +| [`UDPClient`](#classscy_1_1turn_1_1UDPClient) | | +| [`FiveTuple`](#classscy_1_1turn_1_1FiveTuple) | The 5-TUPLE consists of a local, a remote address, and the transport protocol used by the client to communicate with the server. +---------+ | +| [`IAllocation`](#classscy_1_1turn_1_1IAllocation) | All TURN operations revolve around allocations, and all TURN messages are associated with an allocation. An allocation conceptually consists of the following state data: | +| [`Server`](#classscy_1_1turn_1_1Server) | TURN server rfc5766 implementation. | +| [`ServerAllocation`](#classscy_1_1turn_1_1ServerAllocation) | | +| [`TCPAllocation`](#classscy_1_1turn_1_1TCPAllocation) | | +| [`TCPConnectionPair`](#classscy_1_1turn_1_1TCPConnectionPair) | | +| [`UDPAllocation`](#classscy_1_1turn_1_1UDPAllocation) | | +| [`Request`](#classscy_1_1turn_1_1Request) | | +| [`ClientState`](#structscy_1_1turn_1_1ClientState) | | +| [`ClientObserver`](#structscy_1_1turn_1_1ClientObserver) | | +| [`Options`](#structscy_1_1turn_1_1Client_1_1Options) | | +| [`TCPClientObserver`](#structscy_1_1turn_1_1TCPClientObserver) | | +| [`RelayConnectionBinding`](#structscy_1_1turn_1_1RelayConnectionBinding) | | +| [`Permission`](#structscy_1_1turn_1_1Permission) | TURN permission for a user session. | +| [`ServerOptions`](#structscy_1_1turn_1_1ServerOptions) | [Configuration](./doc/api-base.md#classscy_1_1Configuration) options for the TURN server. | +| [`ServerObserver`](#structscy_1_1turn_1_1ServerObserver) | The [ServerObserver](#structscy_1_1turn_1_1ServerObserver) receives callbacks for and is responsible for managing allocation and bandwidth quotas, authentication methods and authentication. | + +## Client + +> **Extends:** `scy::Stateful< ClientState >`, `scy::turn::IAllocation` +> **Subclasses:** `scy::turn::TCPClient`, `scy::turn::UDPClient` +> **Defined in:** `client.h` + +### Members + +| Name | Description | +|------|-------------| +| [`Client`](#group__turn_1ga65ce6f16a338792a1783d51edffd71dd) | | +| [`~Client`](#group__turn_1ga7fc90ccb1863fddf1a63fae16ae9c371) | | +| [`initiate`](#group__turn_1gadf723a357d7bb4ad4162850e1689d3e3) | Initiates the allocation sequence. | +| [`shutdown`](#group__turn_1ga1e0682ce8d32f7c62946ee7793c1181c) | Shutdown the client and destroy the active allocation. | +| [`sendAllocate`](#group__turn_1ga7d568f600867e83b78f42f61d24e13ef) | Sends the allocation request. | +| [`addPermission`](#group__turn_1ga63590b39064f8a8f96adb89eee134d63) | | +| [`addPermission`](#group__turn_1gaba5057ecad2da5a048e67a51efc74d0f) | Peer permissions should be added/created before we kick off the allocation sequence, but may be added later. | +| [`sendCreatePermission`](#group__turn_1ga8555bd85d39c6430f2f00f0f684d7628) | Sends a CreatePermission request including all hosts. | +| [`sendChannelBind`](#group__turn_1ga8901df806b203e670fe925fe13dca81e) | | +| [`sendRefresh`](#group__turn_1gacd3057049693dd485726f0a14b1e5ee0) | | +| [`sendData`](#group__turn_1ga20f4a32be7ab6b6ee5a787eb3c9320bc) | | +| [`handleResponse`](#group__turn_1ga0f6ebc4b5830aaa97b69ca66f0999261) | | +| [`handleAllocateResponse`](#group__turn_1ga68bbf8a80eedb0ba14918aec893448a5) | | +| [`handleAllocateErrorResponse`](#group__turn_1ga12709199bdbf16d3c7dc0cd82e3a93ab) | | +| [`handleCreatePermissionResponse`](#group__turn_1gaa22352721ef5518a253a6594877a21eb) | | +| [`handleCreatePermissionErrorResponse`](#group__turn_1gabbd2963a3eb1021634c55abb70d39d63) | | +| [`handleRefreshResponse`](#group__turn_1ga144c651f56df26ffc92879219930e848) | | +| [`handleDataIndication`](#group__turn_1gaadd3916417580152b965c64c32cf73bb) | | +| [`transportProtocol`](#group__turn_1ga32c28b5280210a450c0e008904a7b6b2) | | +| [`createTransaction`](#group__turn_1ga88dd79f35429039f830cd1fbfd7f3870) | | +| [`authenticateRequest`](#group__turn_1ga7a7dac39cdf0e23586d6607ac65b06cb) | | +| [`sendAuthenticatedTransaction`](#group__turn_1ga44237aae8a9ad5ad3cc4cecc19881e53) | | +| [`removeTransaction`](#group__turn_1ga9f51f7e1bcbe90260db6c8e862927482) | | +| [`mappedAddress`](#group__turn_1ga06d529cceb90e17ad9cdac3998cad80e) | | +| [`relayedAddress`](#group__turn_1ga5708eadcbe76c7c9bc3904d5942e07f5) | | +| [`closed`](#group__turn_1gafd23179bb00b8ce9dca4aaa666ba8f97) | | +| [`observer`](#group__turn_1gaba66ee1063e547550dcbb32432b42ec8) | | +| [`options`](#group__turn_1ga36514efc351b6cca0222702e137b27c9) | | +| [`setError`](#group__turn_1ga21670cb1ae05473fe43a5e82cb40b754) | | +| [`onSocketConnect`](#group__turn_1ga926f40e036ce12b00f365ae387b2102b) | | +| [`onSocketRecv`](#group__turn_1gaf226ce27add87f373131003383569b20) | | +| [`onSocketClose`](#group__turn_1gacfb499500c58c0392df68342e5aa59e7) | | +| [`onTransactionProgress`](#group__turn_1ga461a2a0c78dbde5294f0260cadf5410c) | | +| [`onStateChange`](#group__turn_1ga35a6d685c1ddb38d29e1467278b7bedc) | | +| [`onTimer`](#group__turn_1ga7fb62ec5f7d6748b7ba6549b86709344) | | +| [`_observer`](#group__turn_1gab2775eacd7fff57764950d54e7383306) | | +| [`_options`](#group__turn_1ga7baa7e34fb78a93ed627c6a3b36740ba) | | +| [`_socket`](#group__turn_1ga53562b6579f7832ad236ce922021852e) | | +| [`_timer`](#group__turn_1ga1704ecb1572601a2f2863ce70cc4fb97) | | +| [`_error`](#group__turn_1ga66ea7fae1ca4bed8445763221eb54020) | | +| [`_mappedAddress`](#group__turn_1ga21a746dd56680daa4e14d19630ba4ecf) | | +| [`_relayedAddress`](#group__turn_1ga1f3592858503ccb9efc59cad55ce3041) | | +| [`_realm`](#group__turn_1ga819fcd60d15c7c555792ad91e34df15f) | | +| [`_nonce`](#group__turn_1ga59aa3850af49ff0ea281fd6cb2168e14) | | +| [`_pendingIndications`](#group__turn_1ga269602d5f2c548df6a654ad9e7c17144) | A list of queued Send indication packets awaiting server permissions. | +| [`_transactions`](#group__turn_1ga9d80bebccf3f7cdf8d34d1246bf6fb02) | A list containing currently active transactions. | + +--- + +#### Client + +```cpp +Client(ClientObserver & observer, const Options & options, const net::Socket::Ptr & socket) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `observer` | `ClientObserver &` | | +| `options` | `const Options &` | | +| `socket` | `const net::Socket::Ptr &` | | +--- -#### `public virtual void addPermission(const IPList & peerIPs)` +#### ~Client +```cpp +virtual ~Client() +``` +--- +#### initiate +```cpp +virtual void initiate() +``` -#### `public virtual void addPermission(const std::string & ip)` +Initiates the allocation sequence. +--- +#### shutdown -Peer permissions should be added/created before we kick off the allocation sequence, but may be added later. +```cpp +virtual void shutdown() +``` -#### `public virtual void sendCreatePermission()` +Shutdown the client and destroy the active allocation. -Sends a CreatePermission request including all hosts. +--- -A CreatePermission request will be sent as soon as the Allocation is created, and at timer x intervals. +#### sendAllocate -#### `public virtual void sendChannelBind(const std::string & peerIP)` +```cpp +virtual void sendAllocate() +``` +Sends the allocation request. +--- +#### addPermission +```cpp +virtual void addPermission(const IPList & peerIPs) +``` -#### `public virtual void sendRefresh()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `peerIPs` | `const IPList &` | | +--- +#### addPermission +```cpp +virtual void addPermission(const std::string & ip) +``` +Peer permissions should be added/created before we kick off the allocation sequence, but may be added later. -#### `public virtual void sendData(const char * data,size_t size,const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddress)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `ip` | `const std::string &` | | +--- +#### sendCreatePermission +```cpp +virtual void sendCreatePermission() +``` +Sends a CreatePermission request including all hosts. -#### `public virtual bool handleResponse(const `[`stun::Message`](#classscy_1_1stun_1_1Message)` & response)` +A CreatePermission request will be sent as soon as the Allocation is created, and at timer x intervals. +--- +#### sendChannelBind +```cpp +virtual void sendChannelBind(const std::string & peerIP) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `peerIP` | `const std::string &` | | -#### `public virtual void handleAllocateResponse(const `[`stun::Message`](#classscy_1_1stun_1_1Message)` & response)` +--- +#### sendRefresh +```cpp +virtual void sendRefresh() +``` +--- +#### sendData -#### `public virtual void handleAllocateErrorResponse(const `[`stun::Message`](#classscy_1_1stun_1_1Message)` & response)` +```cpp +virtual void sendData(const char * data, size_t size, const net::Address & peerAddress) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `data` | `const char *` | | +| `size` | `size_t` | | +| `peerAddress` | `const net::Address &` | | +--- +#### handleResponse +```cpp +virtual bool handleResponse(const stun::Message & response) +``` -#### `public virtual void handleCreatePermissionResponse(const `[`stun::Message`](#classscy_1_1stun_1_1Message)` & response)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `response` | `const stun::Message &` | | +--- +#### handleAllocateResponse +```cpp +virtual void handleAllocateResponse(const stun::Message & response) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `response` | `const stun::Message &` | | -#### `public virtual void handleCreatePermissionErrorResponse(const `[`stun::Message`](#classscy_1_1stun_1_1Message)` & response)` +--- +#### handleAllocateErrorResponse +```cpp +virtual void handleAllocateErrorResponse(const stun::Message & response) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `response` | `const stun::Message &` | | +--- -#### `public virtual void handleRefreshResponse(const `[`stun::Message`](#classscy_1_1stun_1_1Message)` & response)` +#### handleCreatePermissionResponse +```cpp +virtual void handleCreatePermissionResponse(const stun::Message & response) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `response` | `const stun::Message &` | | +--- +#### handleCreatePermissionErrorResponse -#### `public virtual void handleDataIndication(const `[`stun::Message`](#classscy_1_1stun_1_1Message)` & response)` +```cpp +virtual void handleCreatePermissionErrorResponse(const stun::Message & response) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `response` | `const stun::Message &` | | +--- +#### handleRefreshResponse +```cpp +virtual void handleRefreshResponse(const stun::Message & response) +``` -#### `public virtual int transportProtocol()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `response` | `const stun::Message &` | | +--- +#### handleDataIndication +```cpp +virtual void handleDataIndication(const stun::Message & response) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `response` | `const stun::Message &` | | -#### `public virtual `[`stun::Transaction`](#classscy_1_1stun_1_1Transaction)` * createTransaction(const net::Socket::Ptr & socket)` +--- +#### transportProtocol +```cpp +virtual int transportProtocol() +``` +--- +#### createTransaction -#### `public virtual void authenticateRequest(`[`stun::Message`](#classscy_1_1stun_1_1Message)` & request)` +```cpp +virtual stun::Transaction * createTransaction(const net::Socket::Ptr & socket) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `socket` | `const net::Socket::Ptr &` | | +--- +#### authenticateRequest +```cpp +virtual void authenticateRequest(stun::Message & request) +``` -#### `public virtual bool sendAuthenticatedTransaction(`[`stun::Transaction`](#classscy_1_1stun_1_1Transaction)` * transaction)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `request` | `stun::Message &` | | +--- +#### sendAuthenticatedTransaction +```cpp +virtual bool sendAuthenticatedTransaction(stun::Transaction * transaction) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `transaction` | `stun::Transaction *` | | -#### `public virtual bool removeTransaction(`[`stun::Transaction`](#classscy_1_1stun_1_1Transaction)` * transaction)` +--- +#### removeTransaction +```cpp +virtual bool removeTransaction(stun::Transaction * transaction) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `transaction` | `stun::Transaction *` | | +--- -#### `public `[`net::Address`](#classscy_1_1net_1_1Address)` mappedAddress() const` +#### mappedAddress +```cpp +net::Address mappedAddress() const +``` +--- +#### relayedAddress +```cpp +virtual net::Address relayedAddress() const +``` -#### `public virtual `[`net::Address`](#classscy_1_1net_1_1Address)` relayedAddress() const` +--- +#### closed +```cpp +bool closed() const +``` +--- +#### observer -#### `public bool closed() const` +```cpp +ClientObserver & observer() +``` +--- +#### options +```cpp +Options & options() +``` +--- -#### `public `[`ClientObserver`](#structscy_1_1turn_1_1ClientObserver)` & observer()` +#### setError +```cpp +virtual void setError(const [scy::Error](./doc/api-base.md#structscy_1_1Error) & error) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `error` | `const [scy::Error](./doc/api-base.md#structscy_1_1Error) &` | | +--- +#### onSocketConnect -#### `public `[`Options`](#structscy_1_1turn_1_1Client_1_1Options)` & options()` +```cpp +virtual void onSocketConnect(net::Socket & socket) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `socket` | `net::Socket &` | | +--- +#### onSocketRecv +```cpp +virtual void onSocketRecv(net::Socket & socket, const MutableBuffer & buffer, const net::Address & peerAddress) +``` -#### `protected `[`ClientObserver`](./doc/api-turn.md#structscy_1_1turn_1_1ClientObserver)` & _observer` +| Parameter | Type | Description | +|-----------|------|-------------| +| `socket` | `net::Socket &` | | +| `buffer` | `const MutableBuffer &` | | +| `peerAddress` | `const net::Address &` | | +--- +#### onSocketClose +```cpp +virtual void onSocketClose(net::Socket & socket) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `socket` | `net::Socket &` | | -#### `protected `[`Options`](./doc/api-turn.md#structscy_1_1turn_1_1Client_1_1Options)` _options` +--- +#### onTransactionProgress +```cpp +virtual void onTransactionProgress(void * sender, TransactionState & state, const TransactionState &) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `sender` | `void *` | | +| `state` | `TransactionState &` | | +--- -#### `protected `[`net::SocketEmitter`](./doc/api-net.md#classscy_1_1net_1_1SocketEmitter)` _socket` +#### onStateChange +```cpp +virtual void onStateChange(ClientState & state, const ClientState & oldState) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `state` | `ClientState &` | | +| `oldState` | `const ClientState &` | | +--- +#### onTimer -#### `protected `[`Timer`](./doc/api-base.md#classscy_1_1Timer)` _timer` +```cpp +virtual void onTimer() +``` +--- +#### _observer +```cpp +ClientObserver & _observer +``` +--- -#### `protected `[`scy::Error`](./doc/api-base.md#structscy_1_1Error)` _error` +#### _options +```cpp +Options _options +``` +--- +#### _socket +```cpp +net::SocketEmitter _socket +``` -#### `protected `[`net::Address`](./doc/api-net.md#classscy_1_1net_1_1Address)` _mappedAddress` +--- +#### _timer +```cpp +Timer _timer +``` +--- +#### _error -#### `protected `[`net::Address`](./doc/api-net.md#classscy_1_1net_1_1Address)` _relayedAddress` +```cpp +[scy::Error](./doc/api-base.md#structscy_1_1Error) _error +``` +--- +#### _mappedAddress +```cpp +net::Address _mappedAddress +``` +--- -#### `protected std::string _realm` +#### _relayedAddress +```cpp +net::Address _relayedAddress +``` +--- +#### _realm +```cpp +std::string _realm +``` -#### `protected std::string _nonce` +--- +#### _nonce +```cpp +std::string _nonce +``` +--- +#### _pendingIndications -#### `protected std::deque< `[`stun::Message`](./doc/api-stun.md#classscy_1_1stun_1_1Message)` > _pendingIndications` +```cpp +std::deque< stun::Message > _pendingIndications +``` A list of queued Send indication packets awaiting server permissions. +--- +#### _transactions -#### `protected std::vector< `[`stun::Transaction`](./doc/api-stun.md#classscy_1_1stun_1_1Transaction)` * > _transactions` +```cpp +std::vector< stun::Transaction * > _transactions +``` A list containing currently active transactions. +## Options +> **Defined in:** `client.h` -#### `protected virtual void setError(const `[`scy::Error`](#structscy_1_1Error)` & error)` - - - - - -#### `protected virtual void onSocketConnect(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket)` - - - - - -#### `protected virtual void onSocketRecv(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket,const `[`MutableBuffer`](#classscy_1_1MutableBuffer)` & buffer,const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddress)` - - - - - -#### `protected virtual void onSocketClose(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket)` - - - - - -#### `protected virtual void onTransactionProgress(void * sender,`[`TransactionState`](#structscy_1_1TransactionState)` & state,const `[`TransactionState`](#structscy_1_1TransactionState)` &)` - - - - - -#### `protected virtual void onStateChange(`[`ClientState`](#structscy_1_1turn_1_1ClientState)` & state,const `[`ClientState`](#structscy_1_1turn_1_1ClientState)` & oldState)` - - - - - -#### `protected virtual void onTimer()` - - - - - -# class `scy::turn::FiveTuple` - - - - -The 5-TUPLE consists of a local, a remote address, and the transport protocol used by the client to communicate with the server. +---------+ - | | - | External| - / | Client | - // | | - / | | - // +---------+ - / - // - +-+ / - | | / - | | // - +---------+ | | +---------+ / +---------+ - | | |N| | | // | | - | TURN | | | | |/ | External| - | Client |----|A|----------| TURN |------------------| Client | - | | | |^ ^| Server |^ ^| | - | | |T|| || || || | - +---------+ | || |+---------+| |+---------+ - ^ | || | | | - | | || | | | - | +-+| | | | - | | | | | - | - Internal Internal External External -Client Remote Local Local Remote -Performing Transport Transport Transport Transport -Allocations Address Address Address Address - - | | | | - +-----+----+ +--------+-------+ - | | - | | - - Internal External - 5-Tuple 5-tuple - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public FiveTuple()` | -`public FiveTuple(const `[`net::Address`](#classscy_1_1net_1_1Address)` & remote,const `[`net::Address`](#classscy_1_1net_1_1Address)` & local,net::TransportType transport)` | -`public FiveTuple(const `[`FiveTuple`](#classscy_1_1turn_1_1FiveTuple)` & r)` | -`public inline const `[`net::Address`](#classscy_1_1net_1_1Address)` & remote() const` | -`public inline const `[`net::Address`](#classscy_1_1net_1_1Address)` & local() const` | -`public inline const net::TransportType & transport() const` | -`public inline void remote(const `[`net::Address`](#classscy_1_1net_1_1Address)` & remote)` | -`public inline void local(const `[`net::Address`](#classscy_1_1net_1_1Address)` & local)` | -`public inline void transport(const net::TransportType & transport)` | -`public bool operator==(const `[`FiveTuple`](#classscy_1_1turn_1_1FiveTuple)` & r) const` | -`public bool operator<(const `[`FiveTuple`](#classscy_1_1turn_1_1FiveTuple)` & r) const` | -`public std::string toString() const` | - -## Members - -#### `public FiveTuple()` - - - - - -#### `public FiveTuple(const `[`net::Address`](#classscy_1_1net_1_1Address)` & remote,const `[`net::Address`](#classscy_1_1net_1_1Address)` & local,net::TransportType transport)` - - - - - -#### `public FiveTuple(const `[`FiveTuple`](#classscy_1_1turn_1_1FiveTuple)` & r)` - - - - - -#### `public inline const `[`net::Address`](#classscy_1_1net_1_1Address)` & remote() const` - - - - - -#### `public inline const `[`net::Address`](#classscy_1_1net_1_1Address)` & local() const` - - - - - -#### `public inline const net::TransportType & transport() const` - - - - - -#### `public inline void remote(const `[`net::Address`](#classscy_1_1net_1_1Address)` & remote)` - - - - - -#### `public inline void local(const `[`net::Address`](#classscy_1_1net_1_1Address)` & local)` - - - - - -#### `public inline void transport(const net::TransportType & transport)` - - - - - -#### `public bool operator==(const `[`FiveTuple`](#classscy_1_1turn_1_1FiveTuple)` & r) const` - - - - - -#### `public bool operator<(const `[`FiveTuple`](#classscy_1_1turn_1_1FiveTuple)` & r) const` - - - - - -#### `public std::string toString() const` - - - - - -# class `scy::turn::IAllocation` - - - - -All TURN operations revolve around allocations, and all TURN messages are associated with an allocation. An allocation conceptually consists of the following state data: - - - -* the relayed transport address; - - -* the 5-tuple: (client's IP address, client's port, server IP address, server port, transport protocol); - - -* the authentication information; - - -* the time-to-expiry; - - - - - -a list of permissions; - -* a list of channel to peer bindings. - - - - - -The relayed transport address is the transport address allocated by the server for communicating with peers, while the 5-tuple describes the communication path between the client and the server. On the client, the 5-tuple uses the client's host transport address; on the server, the 5-tuple uses the client's server-reflexive transport address. - -Both the relayed transport address and the 5-tuple MUST be unique across all allocations, so either one can be used to uniquely identify the allocation. The authentication information (e.g., username, password, realm, and nonce) is used to both verify subsequent requests and to compute the message integrity of responses. The username, realm, and nonce values are initially those used in the authenticated Allocate request that creates the allocation, though the server can change the nonce value during the lifetime of the allocation using a 438 (Stale Nonce) reply. Note that, rather than storing the password explicitly, for security reasons, it may be desirable for the server to store the key value, which is an MD5 hash over the username, realm, and password (see [RFC5389]). - -The time-to-expiry is the time in seconds left until the allocation expires. Each Allocate or Refresh transaction sets this timer, which then ticks down towards 0. By default, each Allocate or Refresh transaction resets this timer to the default lifetime value of 600 seconds (10 minutes), but the client can request a different value in the Allocate and Refresh request. Allocations can only be refreshed using the Refresh request; sending data to a peer does not refresh an allocation. When an allocation expires, the state data associated with the allocation can be freed. - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public IAllocation(const `[`FiveTuple`](#classscy_1_1turn_1_1FiveTuple)` & tuple,const std::string & username,std::int64_t lifetime)` | -`public virtual ~IAllocation()` | -`public virtual void updateUsage(std::int64_t numBytes)` | -`public virtual void setLifetime(std::int64_t lifetime)` | Sets the lifetime of the allocation and resets the timeout. -`public virtual void setBandwidthLimit(std::int64_t numBytes)` | Sets the bandwidth limit in bytes for this allocation. -`public virtual bool expired() const` | -`public virtual bool deleted() const` | -`public virtual std::int64_t bandwidthLimit() const` | -`public virtual std::int64_t bandwidthUsed() const` | -`public virtual std::int64_t bandwidthRemaining() const` | -`public virtual std::int64_t timeRemaining() const` | -`public virtual `[`FiveTuple`](#classscy_1_1turn_1_1FiveTuple)` & tuple()` | -`public virtual std::string username() const` | -`public virtual std::int64_t lifetime() const` | -`public virtual PermissionList permissions() const` | -`public `[`net::Address`](#classscy_1_1net_1_1Address)` relayedAddress() const` | -`public virtual void addPermission(const std::string & ip)` | -`public virtual void addPermissions(const IPList & ips)` | -`public virtual void removePermission(const std::string & ip)` | -`public virtual void removeAllPermissions()` | -`public virtual void removeExpiredPermissions()` | -`public virtual bool hasPermission(const std::string & peerIP)` | -`public inline virtual void print(std::ostream & os) const` | -`protected `[`FiveTuple`](./doc/api-turn.md#classscy_1_1turn_1_1FiveTuple)` _tuple` | -`protected std::string _username` | -`protected PermissionList _permissions` | -`protected std::int64_t _lifetime` | -`protected std::int64_t _bandwidthLimit` | -`protected std::int64_t _bandwidthUsed` | -`protected time_t _createdAt` | -`protected time_t _updatedAt` | -`protected bool _deleted` | - -## Members - -#### `public IAllocation(const `[`FiveTuple`](#classscy_1_1turn_1_1FiveTuple)` & tuple,const std::string & username,std::int64_t lifetime)` - - - - - -#### `public virtual ~IAllocation()` - - +### Members +| Name | Description | +|------|-------------| +| [`Options`](#group__turn_1gae926546e19d8fd9a7fab86271b96a54f) | | +| [`software`](#group__turn_1ga5353220869e0f09239060488ecdb7fef) | | +| [`username`](#group__turn_1gac72217fb6b73d1d050c84379189354a5) | | +| [`password`](#group__turn_1ga90e75f93e08bd392b9def185c4f29ec1) | | +| [`timeout`](#group__turn_1ga3b36f9f68df1b465c1046b88529ccf69) | | +| [`lifetime`](#group__turn_1ga7dc6b1fc053f08ec22d0f2f97084d996) | | +| [`timerInterval`](#group__turn_1ga50b1abb4fea151715d0c93b5ac675f30) | | +| [`serverAddr`](#group__turn_1gaca69ae3e4cb351a623def3f8ca67a950) | | +--- -#### `public virtual void updateUsage(std::int64_t numBytes)` - - - -Updates the allocation's internal timeout and bandwidth usage each time the allocation is used. - -#### `public virtual void setLifetime(std::int64_t lifetime)` - -Sets the lifetime of the allocation and resets the timeout. - - - -#### `public virtual void setBandwidthLimit(std::int64_t numBytes)` - -Sets the bandwidth limit in bytes for this allocation. - - - -#### `public virtual bool expired() const` - - - -Returns true if the allocation is expired ie. is timed out or the bandwidth limit has been reached. - -#### `public virtual bool deleted() const` - - - -Returns true if the allocation's deleted flag is set and or if the allocation has expired. - -This signifies that the allocation is ready to be destroyed via async garbage collection. See Server::onTimer() and Client::onTimer() - -#### `public virtual std::int64_t bandwidthLimit() const` - - - - - -#### `public virtual std::int64_t bandwidthUsed() const` - - - - - -#### `public virtual std::int64_t bandwidthRemaining() const` - - - - - -#### `public virtual std::int64_t timeRemaining() const` - - - - - -#### `public virtual `[`FiveTuple`](#classscy_1_1turn_1_1FiveTuple)` & tuple()` - - - - - -#### `public virtual std::string username() const` - - - - - -#### `public virtual std::int64_t lifetime() const` - - - - - -#### `public virtual PermissionList permissions() const` - - - - - -#### `public `[`net::Address`](#classscy_1_1net_1_1Address)` relayedAddress() const` - - - - - -#### `public virtual void addPermission(const std::string & ip)` - - - - - -#### `public virtual void addPermissions(const IPList & ips)` - - - - - -#### `public virtual void removePermission(const std::string & ip)` - - - - - -#### `public virtual void removeAllPermissions()` - - - - - -#### `public virtual void removeExpiredPermissions()` - - - - - -#### `public virtual bool hasPermission(const std::string & peerIP)` - - - - - -#### `public inline virtual void print(std::ostream & os) const` - - - - - -#### `protected `[`FiveTuple`](./doc/api-turn.md#classscy_1_1turn_1_1FiveTuple)` _tuple` - - - - - -#### `protected std::string _username` - - - - - -#### `protected PermissionList _permissions` - - - - - -#### `protected std::int64_t _lifetime` - - - - - -#### `protected std::int64_t _bandwidthLimit` - - - - - -#### `protected std::int64_t _bandwidthUsed` - - - - - -#### `protected time_t _createdAt` - - - - - -#### `protected time_t _updatedAt` - - - - - -#### `protected bool _deleted` - - - - - -# class `scy::turn::Request` +#### Options +```cpp +inline Options() ``` -class scy::turn::Request - : public scy::stun::Message -``` - - - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public net::TransportType transport` | -`public `[`net::Address`](./doc/api-net.md#classscy_1_1net_1_1Address)` localAddress` | -`public `[`net::Address`](./doc/api-net.md#classscy_1_1net_1_1Address)` remoteAddress` | -`public std::string hash` | -`public inline Request(const `[`stun::Message`](#classscy_1_1stun_1_1Message)` & message,net::TransportType transport,const `[`net::Address`](#classscy_1_1net_1_1Address)` & localAddress,const `[`net::Address`](#classscy_1_1net_1_1Address)` & remoteAddress)` | - -## Members - -#### `public net::TransportType transport` - - - - - -#### `public `[`net::Address`](./doc/api-net.md#classscy_1_1net_1_1Address)` localAddress` - - - - - -#### `public `[`net::Address`](./doc/api-net.md#classscy_1_1net_1_1Address)` remoteAddress` - +--- +#### software +```cpp +std::string software +``` -#### `public std::string hash` +--- +#### username +```cpp +std::string username +``` +--- +#### password -#### `public inline Request(const `[`stun::Message`](#classscy_1_1stun_1_1Message)` & message,net::TransportType transport,const `[`net::Address`](#classscy_1_1net_1_1Address)` & localAddress,const `[`net::Address`](#classscy_1_1net_1_1Address)` & remoteAddress)` +```cpp +std::string password +``` +--- +#### timeout +```cpp +long timeout +``` +--- -# class `scy::turn::Server` +#### lifetime +```cpp +std::int64_t lifetime +``` -TURN server rfc5766 implementation. +--- +#### timerInterval +```cpp +std::int64_t timerInterval +``` -## Summary +--- - Members | Descriptions ---------------------------------|--------------------------------------------- -`public Server(`[`ServerObserver`](#structscy_1_1turn_1_1ServerObserver)` & observer,const `[`ServerOptions`](#structscy_1_1turn_1_1ServerOptions)` & options)` | -`public virtual ~Server()` | -`public virtual void start()` | -`public virtual void stop()` | -`public void handleRequest(`[`Request`](#classscy_1_1turn_1_1Request)` & request,AuthenticationState state)` | -`public void handleAuthorizedRequest(`[`Request`](#classscy_1_1turn_1_1Request)` & request)` | -`public void handleBindingRequest(`[`Request`](#classscy_1_1turn_1_1Request)` & request)` | -`public void handleAllocateRequest(`[`Request`](#classscy_1_1turn_1_1Request)` & request)` | -`public void handleConnectionBindRequest(`[`Request`](#classscy_1_1turn_1_1Request)` & request)` | -`public void respond(`[`Request`](#classscy_1_1turn_1_1Request)` & request,`[`stun::Message`](#classscy_1_1stun_1_1Message)` & response)` | -`public void respondError(`[`Request`](#classscy_1_1turn_1_1Request)` & request,int errorCode,const char * errorDesc)` | -`public ServerAllocationMap allocations() const` | -`public void addAllocation(`[`ServerAllocation`](#classscy_1_1turn_1_1ServerAllocation)` * alloc)` | -`public void removeAllocation(`[`ServerAllocation`](#classscy_1_1turn_1_1ServerAllocation)` * alloc)` | -`public `[`ServerAllocation`](#classscy_1_1turn_1_1ServerAllocation)` * getAllocation(const `[`FiveTuple`](#classscy_1_1turn_1_1FiveTuple)` & tuple)` | -`public `[`TCPAllocation`](#classscy_1_1turn_1_1TCPAllocation)` * getTCPAllocation(const uint32_t & connectionID)` | -`public net::TCPSocket::Ptr getTCPSocket(const `[`net::Address`](#classscy_1_1net_1_1Address)` & remoteAddr)` | -`public void releaseTCPSocket(const `[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket)` | -`public `[`ServerObserver`](#structscy_1_1turn_1_1ServerObserver)` & observer()` | -`public `[`ServerOptions`](#structscy_1_1turn_1_1ServerOptions)` & options()` | -`public `[`net::UDPSocket`](#classscy_1_1net_1_1UDPSocket)` & udpSocket()` | -`public `[`net::TCPSocket`](#classscy_1_1net_1_1TCPSocket)` & tcpSocket()` | -`public `[`Timer`](#classscy_1_1Timer)` & timer()` | -`public void onTCPAcceptConnection(const net::TCPSocket::Ptr & sock)` | -`public void onTCPSocketClosed(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket)` | -`public void onSocketRecv(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket,const `[`MutableBuffer`](#classscy_1_1MutableBuffer)` & buffer,const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddress)` | -`public void onTimer()` | +#### serverAddr -## Members +```cpp +net::Address serverAddr +``` -#### `public Server(`[`ServerObserver`](#structscy_1_1turn_1_1ServerObserver)` & observer,const `[`ServerOptions`](#structscy_1_1turn_1_1ServerOptions)` & options)` +## TCPClient + +> **Extends:** `scy::turn::Client` +> **Defined in:** `tcpclient.h` + +### Members + +| Name | Description | +|------|-------------| +| [`TCPClient`](#group__turn_1ga66a06f08c0fec14c755537b176dbe6fd) | | +| [`~TCPClient`](#group__turn_1gaa8bf16affc9175efa5ec96b7638cdd75) | | +| [`initiate`](#group__turn_1ga21a24b1e8e50a72306595dde1e62b8c8) | Initiates the allocation sequence. | +| [`shutdown`](#group__turn_1ga10311576b628961147df231abeea2e45) | Shutdown the client and destroy the active allocation. | +| [`sendConnectRequest`](#group__turn_1gabc681709fb413701323ae55d99ef86c2) | | +| [`sendData`](#group__turn_1gabd45ceb62c2d3cf0ccadc05d7ebe6867) | | +| [`handleResponse`](#group__turn_1ga2d300174a7c09873df9bc36af3a66fe7) | | +| [`handleConnectResponse`](#group__turn_1gaab0f1e53575195633d0e150b7532bbb9) | | +| [`handleConnectErrorResponse`](#group__turn_1gaf5be5aa0c7f2a0a346dcdb5b1af90cb0) | | +| [`handleConnectionBindResponse`](#group__turn_1ga577618f2ce93bc9e8089f84037a48381) | | +| [`handleConnectionBindErrorResponse`](#group__turn_1gab8e9eb2b935c3af5ad0823c7f6e3d693) | | +| [`handleConnectionAttemptIndication`](#group__turn_1ga5cee29ca9f9c7ffc3d6580f5ca504f2f) | | +| [`createAndBindConnection`](#group__turn_1ga3f7d5efb351d7f2b107d3a25d410ce89) | | +| [`onRelayConnectionConnect`](#group__turn_1ga9434e3aa4723ad58c16e197d12824031) | | +| [`onRelayDataReceived`](#group__turn_1ga3c4890ab6d10d4f3766a70ea4c6c12aa) | | +| [`onRelayConnectionError`](#group__turn_1ga12267279e5f527ecbe401f5bc3c96066) | | +| [`onRelayConnectionClosed`](#group__turn_1gad643fdeeeb3355f0df9bd946029a5791) | | +| [`freeConnection`](#group__turn_1ga1b8eac8a9103d924fcac1b6284c0c584) | | +| [`transportProtocol`](#group__turn_1ga1fa35721f9353c21bf1e7b470c836883) | | +| [`connections`](#group__turn_1ga8080d44f1441c6315d3cfcbae375b979) | | +| [`className`](#group__turn_1ga57bf3238ed15d6472a35559674673eda) | | +| [`_observer`](#group__turn_1ga07f4b77e0079d379c598ed2dd7fccb1c) | | +| [`_connections`](#group__turn_1ga35cdf1b381e1516ae904410722e6bbb1) | | + +--- + +#### TCPClient + +```cpp +TCPClient(TCPClientObserver & observer, const Client::Options & options) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `observer` | `TCPClientObserver &` | | +| `options` | `const Client::Options &` | | +--- +#### ~TCPClient +```cpp +virtual ~TCPClient() +``` -#### `public virtual ~Server()` +--- +#### initiate +```cpp +virtual void initiate() +``` +Initiates the allocation sequence. +--- -#### `public virtual void start()` +#### shutdown +```cpp +virtual void shutdown() +``` +Shutdown the client and destroy the active allocation. +--- +#### sendConnectRequest -#### `public virtual void stop()` +```cpp +virtual void sendConnectRequest(const net::Address & peerAddress) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `peerAddress` | `const net::Address &` | | +--- +#### sendData +```cpp +virtual void sendData(const char * data, size_t size, const net::Address & peerAddress) +``` -#### `public void handleRequest(`[`Request`](#classscy_1_1turn_1_1Request)` & request,AuthenticationState state)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `data` | `const char *` | | +| `size` | `size_t` | | +| `peerAddress` | `const net::Address &` | | +--- +#### handleResponse +```cpp +virtual bool handleResponse(const stun::Message & response) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `response` | `const stun::Message &` | | -#### `public void handleAuthorizedRequest(`[`Request`](#classscy_1_1turn_1_1Request)` & request)` +--- +#### handleConnectResponse +```cpp +virtual void handleConnectResponse(const stun::Message & response) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `response` | `const stun::Message &` | | +--- -#### `public void handleBindingRequest(`[`Request`](#classscy_1_1turn_1_1Request)` & request)` +#### handleConnectErrorResponse +```cpp +virtual void handleConnectErrorResponse(const stun::Message & response) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `response` | `const stun::Message &` | | +--- +#### handleConnectionBindResponse -#### `public void handleAllocateRequest(`[`Request`](#classscy_1_1turn_1_1Request)` & request)` +```cpp +virtual void handleConnectionBindResponse(const stun::Message & response) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `response` | `const stun::Message &` | | +--- +#### handleConnectionBindErrorResponse +```cpp +virtual void handleConnectionBindErrorResponse(const stun::Message & response) +``` -#### `public void handleConnectionBindRequest(`[`Request`](#classscy_1_1turn_1_1Request)` & request)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `response` | `const stun::Message &` | | +--- +#### handleConnectionAttemptIndication +```cpp +virtual void handleConnectionAttemptIndication(const stun::Message & response) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `response` | `const stun::Message &` | | -#### `public void respond(`[`Request`](#classscy_1_1turn_1_1Request)` & request,`[`stun::Message`](#classscy_1_1stun_1_1Message)` & response)` +--- +#### createAndBindConnection +```cpp +virtual bool createAndBindConnection(uint32_t connectionID, const net::Address & peerAddress) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `connectionID` | `uint32_t` | | +| `peerAddress` | `const net::Address &` | | +--- -#### `public void respondError(`[`Request`](#classscy_1_1turn_1_1Request)` & request,int errorCode,const char * errorDesc)` +#### onRelayConnectionConnect +```cpp +virtual void onRelayConnectionConnect(net::Socket & socket) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `socket` | `net::Socket &` | | +--- +#### onRelayDataReceived -#### `public ServerAllocationMap allocations() const` +```cpp +virtual void onRelayDataReceived(net::Socket & socket, const MutableBuffer & buffer, const net::Address & peerAddress) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `socket` | `net::Socket &` | | +| `buffer` | `const MutableBuffer &` | | +| `peerAddress` | `const net::Address &` | | +--- +#### onRelayConnectionError +```cpp +virtual void onRelayConnectionError(net::Socket & socket, const Error & error) +``` -#### `public void addAllocation(`[`ServerAllocation`](#classscy_1_1turn_1_1ServerAllocation)` * alloc)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `socket` | `net::Socket &` | | +| `error` | `const Error &` | | +--- +#### onRelayConnectionClosed +```cpp +virtual void onRelayConnectionClosed(net::Socket & socket) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `socket` | `net::Socket &` | | -#### `public void removeAllocation(`[`ServerAllocation`](#classscy_1_1turn_1_1ServerAllocation)` * alloc)` +--- +#### freeConnection +```cpp +void freeConnection(const net::Address & peerAddress) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `peerAddress` | `const net::Address &` | | +--- -#### `public `[`ServerAllocation`](#classscy_1_1turn_1_1ServerAllocation)` * getAllocation(const `[`FiveTuple`](#classscy_1_1turn_1_1FiveTuple)` & tuple)` +#### transportProtocol +```cpp +virtual int transportProtocol() +``` +--- +#### connections +```cpp +ConnectionManager & connections() +``` -#### `public `[`TCPAllocation`](#classscy_1_1turn_1_1TCPAllocation)` * getTCPAllocation(const uint32_t & connectionID)` +--- +#### className +```cpp +virtual inline const char * className() const +``` +--- +#### _observer -#### `public net::TCPSocket::Ptr getTCPSocket(const `[`net::Address`](#classscy_1_1net_1_1Address)` & remoteAddr)` +```cpp +TCPClientObserver & _observer +``` +--- +#### _connections +```cpp +ConnectionManager _connections +``` +## UDPClient -#### `public void releaseTCPSocket(const `[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket)` +> **Extends:** `scy::turn::Client` +> **Defined in:** `udpclient.h` +### Members +| Name | Description | +|------|-------------| +| [`UDPClient`](#group__turn_1gac81111283b7df471a1afe3409587ae20) | | +| [`~UDPClient`](#group__turn_1gac46009fd65b1194565e6f5b2a25ed3d5) | | +--- +#### UDPClient -#### `public `[`ServerObserver`](#structscy_1_1turn_1_1ServerObserver)` & observer()` +```cpp +UDPClient(ClientObserver & observer, const Options & options) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `observer` | `ClientObserver &` | | +| `options` | `const Options &` | | +--- +#### ~UDPClient +```cpp +virtual ~UDPClient() +``` -#### `public `[`ServerOptions`](#structscy_1_1turn_1_1ServerOptions)` & options()` +## FiveTuple +> **Defined in:** `fivetuple.h` +The 5-TUPLE consists of a local, a remote address, and the transport protocol used by the client to communicate with the server. +---------+ + | | + | External| + / | Client | + // | | + / | | + // +---------+ + / + // + +-+ / + | | / + | | // + +---------+ | | +---------+ / +---------+ + | | |N| | | // | | + | TURN | | | | |/ | External| + | Client |----|A|----------| TURN |------------------| Client | + | | | |^ ^| Server |^ ^| | + | | |T|| || || || | + +---------+ | || |+---------+| |+---------+ + ^ | || | | | + | | || | | | + | +-+| | | | + | | | | | + | + Internal Internal External External +Client Remote Local Local Remote +Performing Transport Transport Transport Transport +Allocations Address Address Address Address + | | | | + +-----+----+ +--------+-------+ + | | + | | + Internal External + 5-Tuple 5-tuple -#### `public `[`net::UDPSocket`](#classscy_1_1net_1_1UDPSocket)` & udpSocket()` +### Members + +| Name | Description | +|------|-------------| +| [`FiveTuple`](#group__turn_1ga7b1939ff40fd399a6e235149f46c240d) | | +| [`FiveTuple`](#group__turn_1ga2bf36ada2e32974976906cbef746713d) | | +| [`FiveTuple`](#group__turn_1ga9b05151cdd2cd10f1420c4a1bc60cd39) | | +| [`remote`](#group__turn_1gaeb5c122700c33f78f0dc1c3dd76a8ede) | | +| [`local`](#group__turn_1ga9cadde536d31752438fca9b62d69c463) | | +| [`transport`](#group__turn_1ga4bb51c63a1d47d47a5ce9bc262f6abeb) | | +| [`remote`](#group__turn_1ga4cfdde49f1c93769f29f20486a023de8) | | +| [`local`](#group__turn_1ga6a5743d49cf4a503f4e336a75e6ab1ec) | | +| [`transport`](#group__turn_1gaf92193a44ae9ae9eb7e490cc5d4ac889) | | +| [`operator==`](#group__turn_1ga68c363f7fec160aedbc1e43e842cf7ef) | | +| [`operator<`](#group__turn_1gaa8935b7a8df4ba5590d54571a244fb94) | | +| [`toString`](#group__turn_1gad03e05d274665545b82f9978f121f9a4) | | +| [`_remote`](#group__turn_1gacee27ca34748828d5a1e4b876b8a2eba) | | +| [`_local`](#group__turn_1ga7eec69720319bddd10a38120854d7698) | | +| [`_transport`](#group__turn_1gafe4ddb63e9ec25724be3301660d26f39) | | + +--- + +#### FiveTuple + +```cpp +FiveTuple() +``` +--- +#### FiveTuple +```cpp +FiveTuple(const net::Address & remote, const net::Address & local, net::TransportType transport) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `remote` | `const net::Address &` | | +| `local` | `const net::Address &` | | +| `transport` | `net::TransportType` | | -#### `public `[`net::TCPSocket`](#classscy_1_1net_1_1TCPSocket)` & tcpSocket()` +--- +#### FiveTuple +```cpp +FiveTuple(const FiveTuple & r) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `r` | `const FiveTuple &` | | +--- -#### `public `[`Timer`](#classscy_1_1Timer)` & timer()` +#### remote +```cpp +inline const net::Address & remote() const +``` +--- +#### local +```cpp +inline const net::Address & local() const +``` -#### `public void onTCPAcceptConnection(const net::TCPSocket::Ptr & sock)` +--- +#### transport +```cpp +inline const net::TransportType & transport() const +``` +--- +#### remote -#### `public void onTCPSocketClosed(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket)` +```cpp +inline void remote(const net::Address & remote) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `remote` | `const net::Address &` | | +--- +#### local +```cpp +inline void local(const net::Address & local) +``` -#### `public void onSocketRecv(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket,const `[`MutableBuffer`](#classscy_1_1MutableBuffer)` & buffer,const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddress)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `local` | `const net::Address &` | | +--- +#### transport +```cpp +inline void transport(const net::TransportType & transport) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `transport` | `const net::TransportType &` | | -#### `public void onTimer()` +--- +#### operator== +```cpp +bool operator==(const FiveTuple & r) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `r` | `const FiveTuple &` | | +--- -# class `scy::turn::ServerAllocation` +#### operator< +```cpp +bool operator<(const FiveTuple & r) const ``` -class scy::turn::ServerAllocation - : public scy::turn::IAllocation -``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `r` | `const FiveTuple &` | | +--- +#### toString +```cpp +std::string toString() const +``` -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public ServerAllocation(`[`Server`](#classscy_1_1turn_1_1Server)` & server,const `[`FiveTuple`](#classscy_1_1turn_1_1FiveTuple)` & tuple,const std::string & username,std::int64_t lifetime)` | -`public virtual bool handleRequest(`[`Request`](#classscy_1_1turn_1_1Request)` & request)` | -`public virtual void handleRefreshRequest(`[`Request`](#classscy_1_1turn_1_1Request)` & request)` | -`public virtual void handleCreatePermission(`[`Request`](#classscy_1_1turn_1_1Request)` & request)` | -`public virtual bool onTimer()` | -`public virtual std::int64_t timeRemaining() const` | -`public virtual std::int64_t maxTimeRemaining() const` | -`public virtual `[`Server`](#classscy_1_1turn_1_1Server)` & server()` | -`public virtual void print(std::ostream & os) const` | -`protected uint32_t _maxLifetime` | -`protected `[`Server`](./doc/api-turn.md#classscy_1_1turn_1_1Server)` & _server` | -`protected virtual ~ServerAllocation()` | +--- -## Members +#### _remote -#### `public ServerAllocation(`[`Server`](#classscy_1_1turn_1_1Server)` & server,const `[`FiveTuple`](#classscy_1_1turn_1_1FiveTuple)` & tuple,const std::string & username,std::int64_t lifetime)` +```cpp +net::Address _remote +``` +--- +#### _local +```cpp +net::Address _local +``` +--- -#### `public virtual bool handleRequest(`[`Request`](#classscy_1_1turn_1_1Request)` & request)` +#### _transport +```cpp +net::TransportType _transport +``` +## IAllocation +> **Subclasses:** `scy::turn::Client`, `scy::turn::ServerAllocation` +> **Defined in:** `iallocation.h` +All TURN operations revolve around allocations, and all TURN messages are associated with an allocation. An allocation conceptually consists of the following state data: -#### `public virtual void handleRefreshRequest(`[`Request`](#classscy_1_1turn_1_1Request)` & request)` +* the relayed transport address; +* the 5-tuple: (client's IP address, client's port, server IP address, server port, transport protocol); +* the authentication information; +* the time-to-expiry; +a list of permissions; -#### `public virtual void handleCreatePermission(`[`Request`](#classscy_1_1turn_1_1Request)` & request)` +* a list of channel to peer bindings. +The relayed transport address is the transport address allocated by the server for communicating with peers, while the 5-tuple describes the communication path between the client and the server. On the client, the 5-tuple uses the client's host transport address; on the server, the 5-tuple uses the client's server-reflexive transport address. +Both the relayed transport address and the 5-tuple MUST be unique across all allocations, so either one can be used to uniquely identify the allocation. The authentication information (e.g., username, password, realm, and nonce) is used to both verify subsequent requests and to compute the message integrity of responses. The username, realm, and nonce values are initially those used in the authenticated Allocate request that creates the allocation, though the server can change the nonce value during the lifetime of the allocation using a 438 (Stale Nonce) reply. Note that, rather than storing the password explicitly, for security reasons, it may be desirable for the server to store the key value, which is an MD5 hash over the username, realm, and password (see [RFC5389]). +The time-to-expiry is the time in seconds left until the allocation expires. Each Allocate or Refresh transaction sets this timer, which then ticks down towards 0. By default, each Allocate or Refresh transaction resets this timer to the default lifetime value of 600 seconds (10 minutes), but the client can request a different value in the Allocate and Refresh request. Allocations can only be refreshed using the Refresh request; sending data to a peer does not refresh an allocation. When an allocation expires, the state data associated with the allocation can be freed. +### Members + +| Name | Description | +|------|-------------| +| [`IAllocation`](#group__turn_1gab486a4e544ced3afa2e9af62cbba7300) | | +| [`~IAllocation`](#group__turn_1ga072f2bd3c27a11c556e95ca2f64a1b96) | | +| [`updateUsage`](#group__turn_1gabe3a1c0062b6a83c84afb534016a2518) | Updates the allocation's internal timeout and bandwidth usage each time the allocation is used. | +| [`setLifetime`](#group__turn_1gac08a8899932878a7f5a0fdcc0b48a071) | Sets the lifetime of the allocation and resets the timeout. | +| [`setBandwidthLimit`](#group__turn_1ga8e2c86e075882c326d4c9bde49901a07) | Sets the bandwidth limit in bytes for this allocation. | +| [`expired`](#group__turn_1ga853e61b93b00bf9298f2e6b63f09e175) | Returns true if the allocation is expired ie. is timed out or the bandwidth limit has been reached. | +| [`deleted`](#group__turn_1ga9a7c145937ae53982675cef2f30bfb94) | Returns true if the allocation's deleted flag is set and or if the allocation has expired. | +| [`bandwidthLimit`](#group__turn_1gaa53520d7f1d391551df07362f251e12d) | | +| [`bandwidthUsed`](#group__turn_1ga83e1e4abe2f5f66d276efde8912f07fe) | | +| [`bandwidthRemaining`](#group__turn_1ga6fae3daac8a208fe57d3415e17f9efb3) | | +| [`timeRemaining`](#group__turn_1gae4af5f598634519896c21d05b2ae3dff) | | +| [`tuple`](#group__turn_1ga1654e4d9fa04276e5f9e4bcf890bf744) | | +| [`username`](#group__turn_1ga9c6bf9973f8f4f0dda5aa9db792ab7cd) | | +| [`lifetime`](#group__turn_1ga849c4d7c1ee031980c799b30896ea3d0) | | +| [`permissions`](#group__turn_1gaa8d3ddee83af5feb781b95ef9453e4f1) | | +| [`relayedAddress`](#group__turn_1ga5541d6593c96ed16b5b82d7ed5e77d7d) | | +| [`addPermission`](#group__turn_1ga30fd3724a345cc202bc2c147f2fe0a0f) | | +| [`addPermissions`](#group__turn_1gaa48e79d80a25a5652d6ce7d1a8b20fed) | | +| [`removePermission`](#group__turn_1ga9204e82ce85c16b73ae5ba216f9d12f3) | | +| [`removeAllPermissions`](#group__turn_1gac156f8c87e140b20655b276d4fb2b99f) | | +| [`removeExpiredPermissions`](#group__turn_1ga3b88ba0d8ef79bccb52cf4bdba1b6be9) | | +| [`hasPermission`](#group__turn_1ga65e660c87fbe3a3ec5ff449a0b271c34) | | +| [`print`](#group__turn_1ga0bcf2cb6675c36864ac804c12bff53c4) | | +| [`_mutex`](#group__turn_1gafca7ccdb9a9e02a6cb14727308fa3d9b) | | +| [`_tuple`](#group__turn_1ga7c8695af0fa8d476fd2b3395c0e7acda) | | +| [`_username`](#group__turn_1gaf6bbdd7265acb0086e3946281bcab790) | | +| [`_permissions`](#group__turn_1ga8c38ed137db89cd1bee04ae3a94cf32a) | | +| [`_lifetime`](#group__turn_1ga4dcd6ce15037d29fd6d9b6a9a2ce470c) | | +| [`_bandwidthLimit`](#group__turn_1ga3a9549208c623572daf3e0fad84c17c1) | | +| [`_bandwidthUsed`](#group__turn_1ga3712c06d098b80de261f7476fa7cf445) | | +| [`_createdAt`](#group__turn_1ga70a95a5e99046c782c602708ab305573) | | +| [`_updatedAt`](#group__turn_1ga584485c991cbbc5a060b48b778d62b8e) | | +| [`_deleted`](#group__turn_1ga71472ac047f1522bf0bb6ac08f6e5c69) | | + +--- + +#### IAllocation + +```cpp +IAllocation(const FiveTuple & tuple, const std::string & username, std::int64_t lifetime) +``` -#### `public virtual bool onTimer()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `tuple` | `const FiveTuple &` | | +| `username` | `const std::string &` | | +| `lifetime` | `std::int64_t` | | +--- +#### ~IAllocation -Asynchronous timer callback for updating the allocation permissions and state etc. If this call returns false the allocation will be deleted. +```cpp +virtual ~IAllocation() +``` -#### `public virtual std::int64_t timeRemaining() const` +--- +#### updateUsage +```cpp +virtual void updateUsage(std::int64_t numBytes) +``` +Updates the allocation's internal timeout and bandwidth usage each time the allocation is used. +| Parameter | Type | Description | +|-----------|------|-------------| +| `numBytes` | `std::int64_t` | | -#### `public virtual std::int64_t maxTimeRemaining() const` +--- +#### setLifetime +```cpp +virtual void setLifetime(std::int64_t lifetime) +``` +Sets the lifetime of the allocation and resets the timeout. +| Parameter | Type | Description | +|-----------|------|-------------| +| `lifetime` | `std::int64_t` | | -#### `public virtual `[`Server`](#classscy_1_1turn_1_1Server)` & server()` +--- +#### setBandwidthLimit +```cpp +virtual void setBandwidthLimit(std::int64_t numBytes) +``` +Sets the bandwidth limit in bytes for this allocation. +| Parameter | Type | Description | +|-----------|------|-------------| +| `numBytes` | `std::int64_t` | | -#### `public virtual void print(std::ostream & os) const` +--- +#### expired +```cpp +virtual bool expired() const +``` +Returns true if the allocation is expired ie. is timed out or the bandwidth limit has been reached. +--- -#### `protected uint32_t _maxLifetime` +#### deleted +```cpp +virtual bool deleted() const +``` +Returns true if the allocation's deleted flag is set and or if the allocation has expired. +This signifies that the allocation is ready to be destroyed via async garbage collection. See [Server::onTimer()](#group__turn_1gad98e27c134b19c27bd2fc446aa927694) and [Client::onTimer()](#group__turn_1ga7fb62ec5f7d6748b7ba6549b86709344) +--- -#### `protected `[`Server`](./doc/api-turn.md#classscy_1_1turn_1_1Server)` & _server` +#### bandwidthLimit +```cpp +virtual std::int64_t bandwidthLimit() const +``` +--- +#### bandwidthUsed +```cpp +virtual std::int64_t bandwidthUsed() const +``` -#### `protected virtual ~ServerAllocation()` +--- +#### bandwidthRemaining +```cpp +virtual std::int64_t bandwidthRemaining() const +``` -IMPORTANT: The destructor should never be called directly as the allocation is deleted via the timer callback. See [onTimer()](#group__turn_1gae360050350229d817fda8d6317531862) +--- -# class `scy::turn::TCPAllocation` +#### timeRemaining +```cpp +virtual std::int64_t timeRemaining() const ``` -class scy::turn::TCPAllocation - : public scy::turn::ServerAllocation -``` +--- +#### tuple +```cpp +virtual FiveTuple & tuple() +``` +--- -## Summary +#### username - Members | Descriptions ---------------------------------|--------------------------------------------- -`public TCPAllocation(`[`Server`](#classscy_1_1turn_1_1Server)` & server,const net::Socket::Ptr & control,const `[`FiveTuple`](#classscy_1_1turn_1_1FiveTuple)` & tuple,const std::string & username,const uint32_t & lifetime)` | -`public virtual ~TCPAllocation()` | -`public virtual bool handleRequest(`[`Request`](#classscy_1_1turn_1_1Request)` & request)` | -`public void handleConnectRequest(`[`Request`](#classscy_1_1turn_1_1Request)` & request)` | -`public void handleConnectionBindRequest(`[`Request`](#classscy_1_1turn_1_1Request)` & request)` | -`public void sendPeerConnectResponse(`[`TCPConnectionPair`](#classscy_1_1turn_1_1TCPConnectionPair)` * pair,bool success)` | Sends a Connect request response to control. -`public int sendToControl(`[`stun::Message`](#classscy_1_1stun_1_1Message)` & message)` | -`public `[`net::TCPSocket`](#classscy_1_1net_1_1TCPSocket)` & control()` | -`public virtual `[`net::Address`](#classscy_1_1net_1_1Address)` relayedAddress() const` | -`public `[`TCPConnectionPairMap`](#classscy_1_1PointerCollection)` & pairs()` | -`public virtual bool onTimer()` | -`public void onPeerAccept(const net::TCPSocket::Ptr & sock)` | Accepts incoming peer sockets for ConnectionBind requests. -`public void onControlClosed(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket)` | -`protected `[`net::SocketEmitter`](./doc/api-net.md#classscy_1_1net_1_1SocketEmitter)` _control` | -`protected `[`net::SocketEmitter`](./doc/api-net.md#classscy_1_1net_1_1SocketEmitter)` _acceptor` | -`protected `[`TCPConnectionPairMap`](./doc/api-base.md#classscy_1_1PointerCollection)` _pairs` | +```cpp +virtual std::string username() const +``` -## Members +--- -#### `public TCPAllocation(`[`Server`](#classscy_1_1turn_1_1Server)` & server,const net::Socket::Ptr & control,const `[`FiveTuple`](#classscy_1_1turn_1_1FiveTuple)` & tuple,const std::string & username,const uint32_t & lifetime)` +#### lifetime +```cpp +virtual std::int64_t lifetime() const +``` +--- +#### permissions +```cpp +virtual PermissionList permissions() const +``` -#### `public virtual ~TCPAllocation()` +--- +#### relayedAddress +```cpp +net::Address relayedAddress() const +``` +--- +#### addPermission -#### `public virtual bool handleRequest(`[`Request`](#classscy_1_1turn_1_1Request)` & request)` +```cpp +virtual void addPermission(const std::string & ip) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `ip` | `const std::string &` | | +--- +#### addPermissions +```cpp +virtual void addPermissions(const IPList & ips) +``` -#### `public void handleConnectRequest(`[`Request`](#classscy_1_1turn_1_1Request)` & request)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `ips` | `const IPList &` | | +--- +#### removePermission +```cpp +virtual void removePermission(const std::string & ip) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `ip` | `const std::string &` | | -#### `public void handleConnectionBindRequest(`[`Request`](#classscy_1_1turn_1_1Request)` & request)` +--- +#### removeAllPermissions +```cpp +virtual void removeAllPermissions() +``` +--- +#### removeExpiredPermissions -#### `public void sendPeerConnectResponse(`[`TCPConnectionPair`](#classscy_1_1turn_1_1TCPConnectionPair)` * pair,bool success)` +```cpp +virtual void removeExpiredPermissions() +``` -Sends a Connect request response to control. +--- +#### hasPermission +```cpp +virtual bool hasPermission(const std::string & peerIP) +``` -#### `public int sendToControl(`[`stun::Message`](#classscy_1_1stun_1_1Message)` & message)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `peerIP` | `const std::string &` | | +--- +#### print +```cpp +virtual inline void print(std::ostream & os) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `os` | `std::ostream &` | | -#### `public `[`net::TCPSocket`](#classscy_1_1net_1_1TCPSocket)` & control()` +--- +#### _mutex +```cpp +std::mutex _mutex +``` +--- +#### _tuple -#### `public virtual `[`net::Address`](#classscy_1_1net_1_1Address)` relayedAddress() const` +```cpp +FiveTuple _tuple +``` +--- +#### _username +```cpp +std::string _username +``` +--- -#### `public `[`TCPConnectionPairMap`](#classscy_1_1PointerCollection)` & pairs()` +#### _permissions +```cpp +PermissionList _permissions +``` +--- +#### _lifetime +```cpp +std::int64_t _lifetime +``` -#### `public virtual bool onTimer()` +--- +#### _bandwidthLimit +```cpp +std::int64_t _bandwidthLimit +``` -Asynchronous timer callback for updating the allocation permissions and state etc. If this call returns false the allocation will be deleted. +--- -#### `public void onPeerAccept(const net::TCPSocket::Ptr & sock)` +#### _bandwidthUsed -Accepts incoming peer sockets for ConnectionBind requests. +```cpp +std::int64_t _bandwidthUsed +``` +--- +#### _createdAt -#### `public void onControlClosed(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket)` +```cpp +time_t _createdAt +``` +--- +#### _updatedAt -Callback for handling controll connection destruction. The allocation will be deleted. +```cpp +time_t _updatedAt +``` -#### `protected `[`net::SocketEmitter`](./doc/api-net.md#classscy_1_1net_1_1SocketEmitter)` _control` +--- +#### _deleted +```cpp +bool _deleted +``` +## Server +> **Defined in:** `server.h` -#### `protected `[`net::SocketEmitter`](./doc/api-net.md#classscy_1_1net_1_1SocketEmitter)` _acceptor` +TURN server rfc5766 implementation. +### Members + +| Name | Description | +|------|-------------| +| [`Server`](#group__turn_1ga2a8d83c2d9447d113d890b3850ea57fc) | | +| [`~Server`](#group__turn_1ga4abeb288eb73e7bed7699a4ed532564c) | | +| [`start`](#group__turn_1ga3f604371cc77d7849381505a586242c1) | | +| [`stop`](#group__turn_1gaf06ef5bbb67fe0d064273adf1bd47a64) | | +| [`handleRequest`](#group__turn_1gacb5bac1767407f17246c357bae94d8bc) | | +| [`handleAuthorizedRequest`](#group__turn_1gaab030a0ce83ea7ce592ee288c8ad3e45) | | +| [`handleBindingRequest`](#group__turn_1gaa5867d6f3c8126b0c1dd8daedf72455e) | | +| [`handleAllocateRequest`](#group__turn_1ga3b400ef28f963bbd282b747299762d53) | | +| [`handleConnectionBindRequest`](#group__turn_1ga9c45a88e010c2141510fdd7adbbaa331) | | +| [`respond`](#group__turn_1gafcae1c06fb5122cf021d731934c8725b) | | +| [`respondError`](#group__turn_1gadf23ef7b1ca2346b6b0ed57a865674aa) | | +| [`allocations`](#group__turn_1gac5a3297389a4f1b4f7f8a8297f38d7d4) | Returns a snapshot copy of the allocation map for safe iteration. Callers receive raw pointers that are valid only while the corresponding unique_ptr in _allocations is alive. | +| [`addAllocation`](#group__turn_1ga0f9507b513b5b0608085de25aa3b1862) | | +| [`removeAllocation`](#group__turn_1gaef7c8d35bd764c75388dce31f63d3eae) | | +| [`getAllocation`](#group__turn_1ga58132f7190c65ecad4f141eef0f3c971) | | +| [`getTCPAllocation`](#group__turn_1ga77c93ca11da8f7de8a0b95c048c8e8c2) | | +| [`getTCPSocket`](#group__turn_1ga67b8b43fd81875a89642793685adc25a) | | +| [`releaseTCPSocket`](#group__turn_1gac17bef322ec362bfb5b7bf6c2a8fa6a3) | | +| [`observer`](#group__turn_1gae00e2da8460fa504d5c184a30153c808) | | +| [`options`](#group__turn_1gac50bc8f6103c1f019a729e1fd8ab600d) | | +| [`udpSocket`](#group__turn_1gadc7036d9cd7736d8dddeb01a08344bfa) | | +| [`tcpSocket`](#group__turn_1ga87a51e97cb7537c4218e85d6c7f76eed) | | +| [`timer`](#group__turn_1ga52cc24e000f44454546ddfccdc85b197) | | +| [`onTCPAcceptConnection`](#group__turn_1gac7e0f1a43edbd4c6fb38536454e09825) | | +| [`onTCPSocketClosed`](#group__turn_1ga0795966f2c9e6d86f5d3ed508409958f) | | +| [`onSocketRecv`](#group__turn_1ga54e3e322a963a2a51287a650f76d7826) | | +| [`onTimer`](#group__turn_1gad98e27c134b19c27bd2fc446aa927694) | | +| [`_mutex`](#group__turn_1gae8b03ceb4deeae0c484c11832947a558) | | +| [`_observer`](#group__turn_1gae3092b782905e055347186b2a5b1743f) | | +| [`_options`](#group__turn_1ga8f6b7686421cf3346129c41b9033bf83) | | +| [`_udpSocket`](#group__turn_1ga90b2575c1704eebdf810d3651c346f5b) | | +| [`_tcpSocket`](#group__turn_1ga01eda07ea349c90434e83546fd43b84f) | | +| [`_tcpSockets`](#group__turn_1ga8176a75aa704535baedb19739c234dc2) | | +| [`_allocations`](#group__turn_1ga7752bede01f2191dc4f951638ab7463a) | | +| [`_timer`](#group__turn_1ga8cbb0a7dc682401cc9bff193537628a7) | | + +--- + +#### Server + +```cpp +Server(ServerObserver & observer, const ServerOptions & options) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `observer` | `ServerObserver &` | | +| `options` | `const ServerOptions &` | | +--- +#### ~Server -#### `protected `[`TCPConnectionPairMap`](./doc/api-base.md#classscy_1_1PointerCollection)` _pairs` +```cpp +virtual ~Server() +``` +--- +#### start +```cpp +virtual void start() +``` +--- -# class `scy::turn::TCPClient` +#### stop +```cpp +virtual void stop() ``` -class scy::turn::TCPClient - : public scy::turn::Client -``` - +--- +#### handleRequest +```cpp +void handleRequest(Request & request, AuthenticationState state) +``` -## Summary +| Parameter | Type | Description | +|-----------|------|-------------| +| `request` | `Request &` | | +| `state` | `AuthenticationState` | | - Members | Descriptions ---------------------------------|--------------------------------------------- -`public TCPClient(`[`TCPClientObserver`](#structscy_1_1turn_1_1TCPClientObserver)` & observer,const `[`Client::Options`](#structscy_1_1turn_1_1Client_1_1Options)` & options)` | -`public virtual ~TCPClient()` | -`public virtual void initiate()` | Initiates the allocation sequence. -`public virtual void shutdown()` | Shutdown the client and destroy the active allocation. -`public virtual void sendConnectRequest(const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddress)` | -`public virtual void sendData(const char * data,size_t size,const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddress)` | -`public virtual bool handleResponse(const `[`stun::Message`](#classscy_1_1stun_1_1Message)` & response)` | -`public virtual void handleConnectResponse(const `[`stun::Message`](#classscy_1_1stun_1_1Message)` & response)` | -`public virtual void handleConnectErrorResponse(const `[`stun::Message`](#classscy_1_1stun_1_1Message)` & response)` | -`public virtual void handleConnectionBindResponse(const `[`stun::Message`](#classscy_1_1stun_1_1Message)` & response)` | -`public virtual void handleConnectionBindErrorResponse(const `[`stun::Message`](#classscy_1_1stun_1_1Message)` & response)` | -`public virtual void handleConnectionAttemptIndication(const `[`stun::Message`](#classscy_1_1stun_1_1Message)` & response)` | -`public virtual bool createAndBindConnection(uint32_t connectionID,const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddress)` | -`public virtual void onRelayConnectionConnect(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket)` | -`public virtual void onRelayDataReceived(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket,const `[`MutableBuffer`](#classscy_1_1MutableBuffer)` & buffer,const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddress)` | -`public virtual void onRelayConnectionError(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket,const `[`Error`](#structscy_1_1Error)` & error)` | -`public virtual void onRelayConnectionClosed(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket)` | -`public void freeConnection(const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddress)` | -`public virtual int transportProtocol()` | -`public `[`ConnectionManager`](#classscy_1_1KVCollection)` & connections()` | -`public inline virtual const char * className() const` | -`protected `[`TCPClientObserver`](./doc/api-turn.md#structscy_1_1turn_1_1TCPClientObserver)` & _observer` | -`protected `[`ConnectionManager`](./doc/api-base.md#classscy_1_1KVCollection)` _connections` | +--- -## Members +#### handleAuthorizedRequest -#### `public TCPClient(`[`TCPClientObserver`](#structscy_1_1turn_1_1TCPClientObserver)` & observer,const `[`Client::Options`](#structscy_1_1turn_1_1Client_1_1Options)` & options)` +```cpp +void handleAuthorizedRequest(Request & request) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `request` | `Request &` | | +--- +#### handleBindingRequest +```cpp +void handleBindingRequest(Request & request) +``` -#### `public virtual ~TCPClient()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `request` | `Request &` | | +--- +#### handleAllocateRequest +```cpp +void handleAllocateRequest(Request & request) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `request` | `Request &` | | -#### `public virtual void initiate()` +--- -Initiates the allocation sequence. +#### handleConnectionBindRequest +```cpp +void handleConnectionBindRequest(Request & request) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `request` | `Request &` | | -#### `public virtual void shutdown()` +--- -Shutdown the client and destroy the active allocation. +#### respond +```cpp +void respond(Request & request, stun::Message & response) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `request` | `Request &` | | +| `response` | `stun::Message &` | | -#### `public virtual void sendConnectRequest(const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddress)` +--- +#### respondError +```cpp +void respondError(Request & request, int errorCode, const char * errorDesc) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `request` | `Request &` | | +| `errorCode` | `int` | | +| `errorDesc` | `const char *` | | +--- -#### `public virtual void sendData(const char * data,size_t size,const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddress)` +#### allocations +```cpp +std::map< FiveTuple, ServerAllocation * > allocations() const +``` +Returns a snapshot copy of the allocation map for safe iteration. Callers receive raw pointers that are valid only while the corresponding unique_ptr in _allocations is alive. +--- +#### addAllocation -#### `public virtual bool handleResponse(const `[`stun::Message`](#classscy_1_1stun_1_1Message)` & response)` +```cpp +void addAllocation(std::unique_ptr< ServerAllocation > alloc) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `alloc` | `std::unique_ptr< ServerAllocation >` | | +--- +#### removeAllocation +```cpp +void removeAllocation(ServerAllocation * alloc) +``` -#### `public virtual void handleConnectResponse(const `[`stun::Message`](#classscy_1_1stun_1_1Message)` & response)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `alloc` | `ServerAllocation *` | | +--- +#### getAllocation +```cpp +ServerAllocation * getAllocation(const FiveTuple & tuple) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `tuple` | `const FiveTuple &` | | -#### `public virtual void handleConnectErrorResponse(const `[`stun::Message`](#classscy_1_1stun_1_1Message)` & response)` +--- +#### getTCPAllocation +```cpp +TCPAllocation * getTCPAllocation(const uint32_t & connectionID) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `connectionID` | `const uint32_t &` | | +--- -#### `public virtual void handleConnectionBindResponse(const `[`stun::Message`](#classscy_1_1stun_1_1Message)` & response)` +#### getTCPSocket +```cpp +net::TCPSocket::Ptr getTCPSocket(const net::Address & remoteAddr) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `remoteAddr` | `const net::Address &` | | +--- +#### releaseTCPSocket -#### `public virtual void handleConnectionBindErrorResponse(const `[`stun::Message`](#classscy_1_1stun_1_1Message)` & response)` +```cpp +void releaseTCPSocket(const net::Socket & socket) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `socket` | `const net::Socket &` | | +--- +#### observer +```cpp +ServerObserver & observer() +``` -#### `public virtual void handleConnectionAttemptIndication(const `[`stun::Message`](#classscy_1_1stun_1_1Message)` & response)` +--- +#### options +```cpp +ServerOptions & options() +``` +--- +#### udpSocket -#### `public virtual bool createAndBindConnection(uint32_t connectionID,const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddress)` +```cpp +net::UDPSocket & udpSocket() +``` +--- +#### tcpSocket +```cpp +net::TCPSocket & tcpSocket() +``` +--- -#### `public virtual void onRelayConnectionConnect(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket)` +#### timer +```cpp +Timer & timer() +``` +--- +#### onTCPAcceptConnection +```cpp +void onTCPAcceptConnection(const net::TCPSocket::Ptr & sock) +``` -#### `public virtual void onRelayDataReceived(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket,const `[`MutableBuffer`](#classscy_1_1MutableBuffer)` & buffer,const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddress)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `sock` | `const net::TCPSocket::Ptr &` | | +--- +#### onTCPSocketClosed +```cpp +void onTCPSocketClosed(net::Socket & socket) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `socket` | `net::Socket &` | | -#### `public virtual void onRelayConnectionError(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket,const `[`Error`](#structscy_1_1Error)` & error)` +--- +#### onSocketRecv +```cpp +void onSocketRecv(net::Socket & socket, const MutableBuffer & buffer, const net::Address & peerAddress) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `socket` | `net::Socket &` | | +| `buffer` | `const MutableBuffer &` | | +| `peerAddress` | `const net::Address &` | | +--- -#### `public virtual void onRelayConnectionClosed(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket)` +#### onTimer +```cpp +void onTimer() +``` +--- +#### _mutex +```cpp +std::mutex _mutex +``` -#### `public void freeConnection(const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddress)` +--- +#### _observer +```cpp +ServerObserver & _observer +``` +--- +#### _options -#### `public virtual int transportProtocol()` +```cpp +ServerOptions _options +``` +--- +#### _udpSocket +```cpp +net::SocketEmitter _udpSocket +``` +--- -#### `public `[`ConnectionManager`](#classscy_1_1KVCollection)` & connections()` +#### _tcpSocket +```cpp +net::SocketEmitter _tcpSocket +``` +--- +#### _tcpSockets +```cpp +std::vector< net::SocketEmitter > _tcpSockets +``` -#### `public inline virtual const char * className() const` +--- +#### _allocations +```cpp +ServerAllocationMap _allocations +``` +--- +#### _timer -#### `protected `[`TCPClientObserver`](./doc/api-turn.md#structscy_1_1turn_1_1TCPClientObserver)` & _observer` +```cpp +Timer _timer +``` +## ServerAllocation + +> **Extends:** `scy::turn::IAllocation` +> **Subclasses:** `scy::turn::TCPAllocation`, `scy::turn::UDPAllocation` +> **Defined in:** `serverallocation.h` + +### Members + +| Name | Description | +|------|-------------| +| [`ServerAllocation`](#group__turn_1ga84047d7fa94573c8b4c9e90d7b2ca35e) | | +| [`~ServerAllocation`](#group__turn_1ga5a72f2a758d972ead206cd52fcc47132) | | +| [`handleRequest`](#group__turn_1ga196225684548a5af62dbaf4536a40a6c) | | +| [`handleRefreshRequest`](#group__turn_1ga067a994e4f4b78f1208d946b526b7782) | | +| [`handleCreatePermission`](#group__turn_1ga123f3fce597db5b9303583eb95c830dc) | | +| [`onTimer`](#group__turn_1gae360050350229d817fda8d6317531862) | Asynchronous timer callback for updating the allocation permissions and state etc. If this call returns false the allocation will be deleted. | +| [`timeRemaining`](#group__turn_1ga86f851d76c345f440db48a3b8cc373ea) | | +| [`maxTimeRemaining`](#group__turn_1gac32ad9173f59a4ee7fff11ae498a96f6) | | +| [`server`](#group__turn_1gac782e622e15da990801af994dbfa7bfa) | | +| [`print`](#group__turn_1ga7e83857083889f67c5f29a754a34aa24) | | +| [`refreshDeleteRequested`](#group__turn_1ga5872b7dd0f15d787034ef80180d54995) | Returns true if the refresh request set lifetime to 0, signaling the parent [Server](#classscy_1_1turn_1_1Server) to delete this allocation. | +| [`ServerAllocation`](#group__turn_1gae436d8a65e9a1a8a6f22cdeb46967690) | NonCopyable and NonMovable. | +| [`operator=`](#group__turn_1gafc5723b65e7b03176bd894f75717676c) | | +| [`_maxLifetime`](#group__turn_1gaffd29cbaf5c7b75d02f538b1f9535f97) | | +| [`_server`](#group__turn_1ga8c62f3c453e32f9c710ac172ad633aca) | | +| [`_refreshDeleteRequested`](#group__turn_1gaad617080bf2c8caf7d3843838aaeef87) | | + +--- + +#### ServerAllocation + +```cpp +ServerAllocation(Server & server, const FiveTuple & tuple, const std::string & username, std::int64_t lifetime) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `server` | `Server &` | | +| `tuple` | `const FiveTuple &` | | +| `username` | `const std::string &` | | +| `lifetime` | `std::int64_t` | | +--- +#### ~ServerAllocation -#### `protected `[`ConnectionManager`](./doc/api-base.md#classscy_1_1KVCollection)` _connections` +```cpp +virtual ~ServerAllocation() +``` +--- +#### handleRequest +```cpp +virtual bool handleRequest(Request & request) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `request` | `Request &` | | -# class `scy::turn::TCPConnectionPair` +--- +#### handleRefreshRequest +```cpp +virtual void handleRefreshRequest(Request & request) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `request` | `Request &` | | +--- +#### handleCreatePermission -## Summary +```cpp +virtual void handleCreatePermission(Request & request) +``` - Members | Descriptions ---------------------------------|--------------------------------------------- -`public `[`TCPAllocation`](./doc/api-turn.md#classscy_1_1turn_1_1TCPAllocation)` & allocation` | -`public `[`net::SocketEmitter`](./doc/api-net.md#classscy_1_1net_1_1SocketEmitter)` client` | The client socket, nullptr to start. -`public `[`net::SocketEmitter`](./doc/api-net.md#classscy_1_1net_1_1SocketEmitter)` peer` | The client socket, nullptr to start. -`public `[`Buffer`](#group__base_1gab10b36b080deb583ed703fca6b63ffdd)` earlyPeerData` | Stores early peer > client data. -`public uint32_t connectionID` | The unique connection ID. -`public bool isDataConnection` | True when p2p relay is flowing. -`public `[`Timeout`](./doc/api-base.md#classscy_1_1Timeout)` timeout` | The ConnectionBind request timeout counter. -`public stun::TransactionID transactionID` | -`public TCPConnectionPair(`[`TCPAllocation`](#classscy_1_1turn_1_1TCPAllocation)` & allocation)` | -`public virtual ~TCPConnectionPair()` | -`public bool doPeerConnect(const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddr)` | -`public bool makeDataConnection()` | -`public void setPeerSocket(const net::TCPSocket::Ptr & socket)` | -`public void setClientSocket(const net::TCPSocket::Ptr & socket)` | -`public void onPeerConnectSuccess(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket)` | Connection success callback for Connect request. -`public void onPeerConnectError(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket,const `[`Error`](#structscy_1_1Error)` & error)` | Connection error callback for Connect request. -`public void onClientDataReceived(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket,const `[`MutableBuffer`](#classscy_1_1MutableBuffer)` & buffer,const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddress)` | -`public void onPeerDataReceived(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket,const `[`MutableBuffer`](#classscy_1_1MutableBuffer)` & buffer,const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddress)` | -`public void onConnectionClosed(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket)` | -`public void startTimeout()` | -`public bool expired() const` | Return true if the peer `ConnectionBind` request timed out. +| Parameter | Type | Description | +|-----------|------|-------------| +| `request` | `Request &` | | -## Members +--- -#### `public `[`TCPAllocation`](./doc/api-turn.md#classscy_1_1turn_1_1TCPAllocation)` & allocation` +#### onTimer +```cpp +virtual bool onTimer() +``` +Asynchronous timer callback for updating the allocation permissions and state etc. If this call returns false the allocation will be deleted. +--- +#### timeRemaining -#### `public `[`net::SocketEmitter`](./doc/api-net.md#classscy_1_1net_1_1SocketEmitter)` client` +```cpp +virtual std::int64_t timeRemaining() const +``` -The client socket, nullptr to start. +--- +#### maxTimeRemaining +```cpp +virtual std::int64_t maxTimeRemaining() const +``` -#### `public `[`net::SocketEmitter`](./doc/api-net.md#classscy_1_1net_1_1SocketEmitter)` peer` +--- -The client socket, nullptr to start. +#### server +```cpp +virtual Server & server() +``` +--- -#### `public `[`Buffer`](#group__base_1gab10b36b080deb583ed703fca6b63ffdd)` earlyPeerData` +#### print -Stores early peer > client data. +```cpp +virtual void print(std::ostream & os) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `os` | `std::ostream &` | | +--- -#### `public uint32_t connectionID` +#### refreshDeleteRequested -The unique connection ID. +```cpp +inline bool refreshDeleteRequested() const +``` +Returns true if the refresh request set lifetime to 0, signaling the parent [Server](#classscy_1_1turn_1_1Server) to delete this allocation. +--- -#### `public bool isDataConnection` +#### ServerAllocation -True when p2p relay is flowing. +```cpp +ServerAllocation(const ServerAllocation &) = delete +``` +NonCopyable and NonMovable. +--- -#### `public `[`Timeout`](./doc/api-base.md#classscy_1_1Timeout)` timeout` +#### operator= -The ConnectionBind request timeout counter. +```cpp +ServerAllocation & operator=(const ServerAllocation &) = delete +``` +--- +#### _maxLifetime -#### `public stun::TransactionID transactionID` +```cpp +uint32_t _maxLifetime +``` +--- +#### _server +```cpp +Server & _server +``` +--- -#### `public TCPConnectionPair(`[`TCPAllocation`](#classscy_1_1turn_1_1TCPAllocation)` & allocation)` +#### _refreshDeleteRequested +```cpp +bool _refreshDeleteRequested = false +``` +## TCPAllocation + +> **Extends:** `scy::turn::ServerAllocation` +> **Defined in:** `tcpallocation.h` + +### Members + +| Name | Description | +|------|-------------| +| [`TCPAllocation`](#group__turn_1ga530362865a2ac00cec08e42dc73403a9) | | +| [`~TCPAllocation`](#group__turn_1ga312379a655b3f96bcdb99e79fb689710) | | +| [`handleRequest`](#group__turn_1ga6c454d8d13f6c5a006731cf8e5d9b517) | | +| [`handleConnectRequest`](#group__turn_1ga581cc086264aaebb23867da082b69d08) | | +| [`handleConnectionBindRequest`](#group__turn_1ga90d0b7dc91442cd9b165f0bbd597130e) | | +| [`sendPeerConnectResponse`](#group__turn_1gadfc50816e7433c9290781b9f906499ca) | Sends a Connect request response to control. | +| [`sendToControl`](#group__turn_1ga938af5d30b8c6f5d61812f8a241a0a0f) | | +| [`control`](#group__turn_1ga6b941622915a8607a4cedc7ee171437c) | | +| [`relayedAddress`](#group__turn_1ga7b3153537c0a9fd9453277443dcba25f) | | +| [`pairs`](#group__turn_1ga883345d6de7c95b47330a0b0daaeb19b) | | +| [`onTimer`](#group__turn_1ga263e247e447a7eaa989711bbd78a249a) | Asynchronous timer callback for updating the allocation permissions and state etc. If this call returns false the allocation will be deleted. | +| [`onPeerAccept`](#group__turn_1ga9c6c658f89aa5c1ebc89a80f12d0a570) | Accepts incoming peer sockets for ConnectionBind requests. | +| [`onControlClosed`](#group__turn_1gad7d9a3b524c3439fc19642ce621d306c) | Callback for handling controll connection destruction. The allocation will be deleted. | +| [`_control`](#group__turn_1ga76a78eca6ac1212ddfbf6512213e6901) | | +| [`_acceptor`](#group__turn_1ga6ae65a9eaa6379fa513984c4a30522e4) | | +| [`_pairs`](#group__turn_1ga865b233b3ce8e50c49c91c9fccc27920) | | + +--- + +#### TCPAllocation + +```cpp +TCPAllocation(Server & server, const net::Socket::Ptr & control, const FiveTuple & tuple, const std::string & username, const uint32_t & lifetime) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `server` | `Server &` | | +| `control` | `const net::Socket::Ptr &` | | +| `tuple` | `const FiveTuple &` | | +| `username` | `const std::string &` | | +| `lifetime` | `const uint32_t &` | | +--- -#### `public virtual ~TCPConnectionPair()` +#### ~TCPAllocation +```cpp +virtual ~TCPAllocation() +``` +--- +#### handleRequest +```cpp +virtual bool handleRequest(Request & request) +``` -#### `public bool doPeerConnect(const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddr)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `request` | `Request &` | | +--- +#### handleConnectRequest -Initiates an outgoing TCP connection to the peer for Connect requests. +```cpp +void handleConnectRequest(Request & request) +``` -#### `public bool makeDataConnection()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `request` | `Request &` | | +--- +#### handleConnectionBindRequest -Binds the client <> peer relay pipe once the ConnectionBind request is successfull. +```cpp +void handleConnectionBindRequest(Request & request) +``` -#### `public void setPeerSocket(const net::TCPSocket::Ptr & socket)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `request` | `Request &` | | +--- +#### sendPeerConnectResponse +```cpp +void sendPeerConnectResponse(TCPConnectionPair * pair, bool success) +``` +Sends a Connect request response to control. -#### `public void setClientSocket(const net::TCPSocket::Ptr & socket)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `pair` | `TCPConnectionPair *` | | +| `success` | `bool` | | +--- +#### sendToControl +```cpp +int sendToControl(stun::Message & message) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `message` | `stun::Message &` | | -#### `public void onPeerConnectSuccess(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket)` +--- -Connection success callback for Connect request. +#### control +```cpp +net::TCPSocket & control() +``` +--- -#### `public void onPeerConnectError(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket,const `[`Error`](#structscy_1_1Error)` & error)` +#### relayedAddress -Connection error callback for Connect request. +```cpp +virtual net::Address relayedAddress() const +``` +--- +#### pairs -#### `public void onClientDataReceived(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket,const `[`MutableBuffer`](#classscy_1_1MutableBuffer)` & buffer,const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddress)` +```cpp +TCPConnectionPairMap & pairs() +``` +--- +#### onTimer +```cpp +virtual bool onTimer() +``` +Asynchronous timer callback for updating the allocation permissions and state etc. If this call returns false the allocation will be deleted. -#### `public void onPeerDataReceived(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket,const `[`MutableBuffer`](#classscy_1_1MutableBuffer)` & buffer,const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddress)` +--- +#### onPeerAccept +```cpp +void onPeerAccept(const net::TCPSocket::Ptr & sock) +``` +Accepts incoming peer sockets for ConnectionBind requests. +| Parameter | Type | Description | +|-----------|------|-------------| +| `sock` | `const net::TCPSocket::Ptr &` | | -#### `public void onConnectionClosed(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket)` +--- +#### onControlClosed +```cpp +void onControlClosed(net::Socket & socket) +``` -Callback for handing either client or peer connections which result in the destruction of the [TCPConnectionPair](#classscy_1_1turn_1_1TCPConnectionPair). +Callback for handling controll connection destruction. The allocation will be deleted. -#### `public void startTimeout()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `socket` | `net::Socket &` | | +--- +#### _control -Starts the ConnectionBind request timeout. +```cpp +net::SocketEmitter _control +``` -If no ConnectionBind request associated with this peer data connection is received after 30 seconds, the peer data connection MUST be closed. +--- -#### `public bool expired() const` +#### _acceptor -Return true if the peer `ConnectionBind` request timed out. +```cpp +net::SocketEmitter _acceptor +``` +--- +#### _pairs -# class `scy::turn::UDPAllocation` +```cpp +TCPConnectionPairMap _pairs +``` +## TCPConnectionPair + +> **Defined in:** `tcpconnectionpair.h` + +### Members + +| Name | Description | +|------|-------------| +| [`TCPConnectionPair`](#group__turn_1gaef6a16730e04ad6935b74d7688d434ff) | | +| [`~TCPConnectionPair`](#group__turn_1ga624ca19946f081cf19f75b0b185f88bd) | | +| [`doPeerConnect`](#group__turn_1ga5fa2395970db2f91d0c39b2344293b4a) | Initiates an outgoing TCP connection to the peer for Connect requests. | +| [`makeDataConnection`](#group__turn_1ga9e9fa7894dcb1ba7aead4a9ce89ad2a8) | Binds the client <> peer relay pipe once the ConnectionBind request is successfull. | +| [`setPeerSocket`](#group__turn_1gabb87674d00d60b47ec5799578c4303e8) | | +| [`setClientSocket`](#group__turn_1gabe1aec80b35fe3f161fc38515f139b00) | | +| [`onPeerConnectSuccess`](#group__turn_1ga5a5912bc68b1a4c405a1347ea8fb82bb) | Connection success callback for Connect request. | +| [`onPeerConnectError`](#group__turn_1gabcbaa9d2da0811338030f6368c5eecea) | Connection error callback for Connect request. | +| [`onClientDataReceived`](#group__turn_1ga7850f0162f9bdd3d1d7b853a59324ddd) | | +| [`onPeerDataReceived`](#group__turn_1gae93b12998cb75c2784b8b4a83b8ed78e) | | +| [`onConnectionClosed`](#group__turn_1ga4f90949f22078df17775d5907451fa47) | Callback for handing either client or peer connections which result in the destruction of the [TCPConnectionPair](#classscy_1_1turn_1_1TCPConnectionPair). | +| [`startTimeout`](#group__turn_1ga36352c6ddc19d8bdfef9968df7dcc165) | Starts the ConnectionBind request timeout. | +| [`requestDeletion`](#group__turn_1ga2ac9623b2eccd557b9a56fae2cd0beca) | Signals the parent allocation to handle deletion instead of destroying ourselves directly. | +| [`expired`](#group__turn_1gae31259009aac3c03ea440ec0a4bb8ff7) | Return true if the peer `ConnectionBind` request timed out. | +| [`TCPConnectionPair`](#group__turn_1ga051968b4d67df635b32673ba0241177e) | NonCopyable and NonMovable. | +| [`operator=`](#group__turn_1gaac0eea313143b657b08277ed2aed266b) | | +| [`allocation`](#group__turn_1ga5f8ce0ee36a5bc87f55d76a95d4ffdc6) | | +| [`client`](#group__turn_1ga7299639b74d587a37787494d14674388) | The client socket, nullptr to start. | +| [`peer`](#group__turn_1ga519217dcc39475da5dc9e616266fbbaf) | The client socket, nullptr to start. | +| [`earlyPeerData`](#group__turn_1ga7d517bff868ad4aeb1a191abb6d440df) | Stores early peer > client data. | +| [`connectionID`](#group__turn_1gae745074629773597cef0ea7c2ed059c7) | The unique connection ID. | +| [`isDataConnection`](#group__turn_1gaa0975b408c5100d385ab97ab54492441) | True when p2p relay is flowing. | +| [`pendingDelete`](#group__turn_1ga234ee6b25a6996fc2c61e3d05d6deef9) | True when this pair has been flagged for deletion. | +| [`timeout`](#group__turn_1gad2382d7f6eabb79e3ddd8b5ae7fe17f1) | The ConnectionBind request timeout counter. | +| [`transactionID`](#group__turn_1gaa13970f4c75250ead1dccdfb573c3af5) | | + +--- + +#### TCPConnectionPair + +```cpp +TCPConnectionPair(TCPAllocation & allocation) ``` -class scy::turn::UDPAllocation - : public scy::turn::ServerAllocation -``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `allocation` | `TCPAllocation &` | | +--- +#### ~TCPConnectionPair +```cpp +virtual ~TCPConnectionPair() +``` -## Summary +--- - Members | Descriptions ---------------------------------|--------------------------------------------- -`public UDPAllocation(`[`Server`](#classscy_1_1turn_1_1Server)` & server,const `[`FiveTuple`](#classscy_1_1turn_1_1FiveTuple)` & tuple,const std::string & username,const uint32_t & lifetime)` | -`public virtual ~UDPAllocation()` | -`public void onPeerDataReceived(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket,const `[`MutableBuffer`](#classscy_1_1MutableBuffer)` & buffer,const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddress)` | -`public virtual bool handleRequest(`[`Request`](#classscy_1_1turn_1_1Request)` & request)` | -`public void handleSendIndication(`[`Request`](#classscy_1_1turn_1_1Request)` & request)` | -`public ssize_t send(const char * data,size_t size,const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddress)` | -`public virtual `[`net::Address`](#classscy_1_1net_1_1Address)` relayedAddress() const` | +#### doPeerConnect -## Members +```cpp +bool doPeerConnect(const net::Address & peerAddr) +``` -#### `public UDPAllocation(`[`Server`](#classscy_1_1turn_1_1Server)` & server,const `[`FiveTuple`](#classscy_1_1turn_1_1FiveTuple)` & tuple,const std::string & username,const uint32_t & lifetime)` +Initiates an outgoing TCP connection to the peer for Connect requests. +| Parameter | Type | Description | +|-----------|------|-------------| +| `peerAddr` | `const net::Address &` | | +--- +#### makeDataConnection +```cpp +bool makeDataConnection() +``` -#### `public virtual ~UDPAllocation()` +Binds the client <> peer relay pipe once the ConnectionBind request is successfull. +--- +#### setPeerSocket +```cpp +void setPeerSocket(const net::TCPSocket::Ptr & socket) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `socket` | `const net::TCPSocket::Ptr &` | | -#### `public void onPeerDataReceived(`[`net::Socket`](#classscy_1_1net_1_1Socket)` & socket,const `[`MutableBuffer`](#classscy_1_1MutableBuffer)` & buffer,const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddress)` +--- +#### setClientSocket +```cpp +void setClientSocket(const net::TCPSocket::Ptr & socket) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `socket` | `const net::TCPSocket::Ptr &` | | +--- -#### `public virtual bool handleRequest(`[`Request`](#classscy_1_1turn_1_1Request)` & request)` +#### onPeerConnectSuccess +```cpp +void onPeerConnectSuccess(net::Socket & socket) +``` +Connection success callback for Connect request. +| Parameter | Type | Description | +|-----------|------|-------------| +| `socket` | `net::Socket &` | | +--- -#### `public void handleSendIndication(`[`Request`](#classscy_1_1turn_1_1Request)` & request)` +#### onPeerConnectError +```cpp +void onPeerConnectError(net::Socket & socket, const Error & error) +``` +Connection error callback for Connect request. +| Parameter | Type | Description | +|-----------|------|-------------| +| `socket` | `net::Socket &` | | +| `error` | `const Error &` | | +--- -#### `public ssize_t send(const char * data,size_t size,const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddress)` +#### onClientDataReceived +```cpp +void onClientDataReceived(net::Socket & socket, const MutableBuffer & buffer, const net::Address & peerAddress) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `socket` | `net::Socket &` | | +| `buffer` | `const MutableBuffer &` | | +| `peerAddress` | `const net::Address &` | | +--- +#### onPeerDataReceived -#### `public virtual `[`net::Address`](#classscy_1_1net_1_1Address)` relayedAddress() const` +```cpp +void onPeerDataReceived(net::Socket & socket, const MutableBuffer & buffer, const net::Address & peerAddress) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `socket` | `net::Socket &` | | +| `buffer` | `const MutableBuffer &` | | +| `peerAddress` | `const net::Address &` | | +--- +#### onConnectionClosed +```cpp +void onConnectionClosed(net::Socket & socket) +``` -# class `scy::turn::UDPClient` +Callback for handing either client or peer connections which result in the destruction of the [TCPConnectionPair](#classscy_1_1turn_1_1TCPConnectionPair). -``` -class scy::turn::UDPClient - : public scy::turn::Client -``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `socket` | `net::Socket &` | | +--- +#### startTimeout +```cpp +void startTimeout() +``` +Starts the ConnectionBind request timeout. -## Summary +If no ConnectionBind request associated with this peer data connection is received after 30 seconds, the peer data connection MUST be closed. - Members | Descriptions ---------------------------------|--------------------------------------------- -`public UDPClient(`[`ClientObserver`](#structscy_1_1turn_1_1ClientObserver)` & observer,const `[`Options`](#structscy_1_1turn_1_1Client_1_1Options)` & options)` | -`public virtual ~UDPClient()` | +--- -## Members +#### requestDeletion -#### `public UDPClient(`[`ClientObserver`](#structscy_1_1turn_1_1ClientObserver)` & observer,const `[`Options`](#structscy_1_1turn_1_1Client_1_1Options)` & options)` +```cpp +void requestDeletion() +``` +Signals the parent allocation to handle deletion instead of destroying ourselves directly. +--- +#### expired +```cpp +bool expired() const +``` -#### `public virtual ~UDPClient()` +Return true if the peer `ConnectionBind` request timed out. +--- +#### TCPConnectionPair +```cpp +TCPConnectionPair(const TCPConnectionPair &) = delete +``` +NonCopyable and NonMovable. -# struct `scy::turn::ClientObserver` +--- +#### operator= +```cpp +TCPConnectionPair & operator=(const TCPConnectionPair &) = delete +``` +--- +#### allocation +```cpp +TCPAllocation & allocation +``` -## Summary +--- - Members | Descriptions ---------------------------------|--------------------------------------------- -`public void onClientStateChange(`[`Client`](#classscy_1_1turn_1_1Client)` & client,`[`ClientState`](#structscy_1_1turn_1_1ClientState)` & state,const `[`ClientState`](#structscy_1_1turn_1_1ClientState)` & oldState)` | -`public void onRelayDataReceived(`[`Client`](#classscy_1_1turn_1_1Client)` & client,const char * data,size_t size,const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddress)` | -`public inline virtual void onAllocationFailed(`[`Client`](#classscy_1_1turn_1_1Client)` & client,int errorCode,const std::string & reason)` | -`public inline virtual void onAllocationDeleted(`[`Client`](#classscy_1_1turn_1_1Client)` & client,const `[`stun::Transaction`](#classscy_1_1stun_1_1Transaction)` & transaction)` | -`public inline virtual void onAllocationPermissionsCreated(`[`Client`](#classscy_1_1turn_1_1Client)` & client,const PermissionList & permissions)` | -`public inline virtual void onTransactionResponse(`[`Client`](#classscy_1_1turn_1_1Client)` & client,const `[`stun::Transaction`](#classscy_1_1stun_1_1Transaction)` & transaction)` | -`public inline virtual void onTimer(`[`Client`](#classscy_1_1turn_1_1Client)` & client)` | +#### client -## Members +```cpp +net::SocketEmitter client +``` -#### `public void onClientStateChange(`[`Client`](#classscy_1_1turn_1_1Client)` & client,`[`ClientState`](#structscy_1_1turn_1_1ClientState)` & state,const `[`ClientState`](#structscy_1_1turn_1_1ClientState)` & oldState)` +The client socket, nullptr to start. +--- +#### peer +```cpp +net::SocketEmitter peer +``` +The client socket, nullptr to start. -#### `public void onRelayDataReceived(`[`Client`](#classscy_1_1turn_1_1Client)` & client,const char * data,size_t size,const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddress)` +--- +#### earlyPeerData +```cpp +Buffer earlyPeerData +``` +Stores early peer > client data. +--- -#### `public inline virtual void onAllocationFailed(`[`Client`](#classscy_1_1turn_1_1Client)` & client,int errorCode,const std::string & reason)` +#### connectionID +```cpp +uint32_t connectionID +``` +The unique connection ID. +--- +#### isDataConnection -#### `public inline virtual void onAllocationDeleted(`[`Client`](#classscy_1_1turn_1_1Client)` & client,const `[`stun::Transaction`](#classscy_1_1stun_1_1Transaction)` & transaction)` +```cpp +bool isDataConnection +``` +True when p2p relay is flowing. +--- +#### pendingDelete +```cpp +bool pendingDelete = false +``` -#### `public inline virtual void onAllocationPermissionsCreated(`[`Client`](#classscy_1_1turn_1_1Client)` & client,const PermissionList & permissions)` +True when this pair has been flagged for deletion. +--- +#### timeout +```cpp +Timeout timeout +``` +The ConnectionBind request timeout counter. -#### `public inline virtual void onTransactionResponse(`[`Client`](#classscy_1_1turn_1_1Client)` & client,const `[`stun::Transaction`](#classscy_1_1stun_1_1Transaction)` & transaction)` +--- +#### transactionID +```cpp +stun::TransactionID transactionID +``` -All received transaction responses will be routed here after local processing so the observer can easily implement extra functionality. +## UDPAllocation -#### `public inline virtual void onTimer(`[`Client`](#classscy_1_1turn_1_1Client)` & client)` +> **Extends:** `scy::turn::ServerAllocation` +> **Defined in:** `udpallocation.h` +### Members +| Name | Description | +|------|-------------| +| [`UDPAllocation`](#group__turn_1gad25035e1f05871ee31e609469e6f3e1c) | | +| [`~UDPAllocation`](#group__turn_1gacc331eb4c29175167d482de8fd682b2b) | | +| [`onPeerDataReceived`](#group__turn_1gaf3723305361367129ac0dbcaad73b8dd) | | +| [`handleRequest`](#group__turn_1gaadfa6b2dd671c0b9de943c687b4e507b) | | +| [`handleSendIndication`](#group__turn_1ga96ad3bfc1e1c63895c320c92f14462ee) | | +| [`send`](#group__turn_1ga1b4d823f104e4b9e324ade9497604b0f) | | +| [`relayedAddress`](#group__turn_1ga14647342910901c835819da6c0dfd7bc) | | +| [`_relaySocket`](#group__turn_1gabfed35bd8ab375ca916f357ddbf97595) | | -Fires after the client's internal timer callback. Handy for performing extra async cleanup tasks. +--- -# struct `scy::turn::ClientState` +#### UDPAllocation +```cpp +UDPAllocation(Server & server, const FiveTuple & tuple, const std::string & username, const uint32_t & lifetime) ``` -struct scy::turn::ClientState - : public scy::State -``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `server` | `Server &` | | +| `tuple` | `const FiveTuple &` | | +| `username` | `const std::string &` | | +| `lifetime` | `const uint32_t &` | | +--- +#### ~UDPAllocation +```cpp +virtual ~UDPAllocation() +``` -## Summary +--- - Members | Descriptions ---------------------------------|--------------------------------------------- -`public inline virtual std::string toString() const` | +#### onPeerDataReceived -## Members +```cpp +void onPeerDataReceived(net::Socket & socket, const MutableBuffer & buffer, const net::Address & peerAddress) +``` -#### `public inline virtual std::string toString() const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `socket` | `net::Socket &` | | +| `buffer` | `const MutableBuffer &` | | +| `peerAddress` | `const net::Address &` | | +--- +#### handleRequest +```cpp +virtual bool handleRequest(Request & request) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `request` | `Request &` | | -# struct `scy::turn::Permission` +--- +#### handleSendIndication -TURN permission for a user session. +```cpp +void handleSendIndication(Request & request) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `request` | `Request &` | | +--- +#### send -## Summary +```cpp +ssize_t send(const char * data, size_t size, const net::Address & peerAddress) +``` - Members | Descriptions ---------------------------------|--------------------------------------------- -`public std::string ip` | -`public `[`Timeout`](./doc/api-base.md#classscy_1_1Timeout)` timeout` | -`public inline Permission(const std::string & ip)` | -`public inline void refresh()` | -`public inline bool operator==(const std::string & r) const` | +| Parameter | Type | Description | +|-----------|------|-------------| +| `data` | `const char *` | | +| `size` | `size_t` | | +| `peerAddress` | `const net::Address &` | | -## Members +--- -#### `public std::string ip` +#### relayedAddress +```cpp +virtual net::Address relayedAddress() const +``` +--- +#### _relaySocket +```cpp +net::SocketEmitter _relaySocket +``` -#### `public `[`Timeout`](./doc/api-base.md#classscy_1_1Timeout)` timeout` +## Request +> **Extends:** `scy::stun::Message` +> **Defined in:** `types.h` +### Members +| Name | Description | +|------|-------------| +| [`Request`](#group__turn_1ga9449353e6e8218f409dc6cad8137bad1) | | +| [`transport`](#group__turn_1gad73229b9a0ed2c9766a35e6464921d83) | | +| [`localAddress`](#group__turn_1gaa5eaa3335646687346a79d16bf44d500) | | +| [`remoteAddress`](#group__turn_1ga063c2acad8fd94c729479e6ad8b3b9f7) | | +| [`hash`](#group__turn_1ga220ca9d82c58f5ade3bf21ab77250590) | | +--- -#### `public inline Permission(const std::string & ip)` +#### Request +```cpp +inline Request(const stun::Message & message, net::TransportType transport, const net::Address & localAddress, const net::Address & remoteAddress) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `message` | `const stun::Message &` | | +| `transport` | `net::TransportType` | | +| `localAddress` | `const net::Address &` | | +| `remoteAddress` | `const net::Address &` | | +--- +#### transport -#### `public inline void refresh()` +```cpp +net::TransportType transport +``` +--- +#### localAddress +```cpp +net::Address localAddress +``` +--- -#### `public inline bool operator==(const std::string & r) const` +#### remoteAddress +```cpp +net::Address remoteAddress +``` +--- +#### hash +```cpp +std::string hash +``` -# struct `scy::turn::RelayConnectionBinding` +## ClientState +> **Extends:** `scy::State` +> **Defined in:** `client.h` +### Members +| Name | Description | +|------|-------------| +| [`Type`](#group__turn_1ga969e50bad1780d036f55059904ac2a1e) | | +| [`toString`](#group__turn_1ga64488300060951e76776bd292ee76701) | | +--- +#### Type -## Summary +```cpp +enum Type +``` - Members | Descriptions ---------------------------------|--------------------------------------------- -`public uint32_t connectionID` | -`public `[`net::Address`](./doc/api-net.md#classscy_1_1net_1_1Address)` peerAddress` | +| Value | Description | +|-------|-------------| +| `None` | | +| `Allocating` | | +| `Authorizing` | | +| `Success` | | +| `Failed` | | -## Members +--- -#### `public uint32_t connectionID` +#### toString +```cpp +virtual inline std::string toString() const +``` +## ClientObserver +> **Subclasses:** `scy::turn::TCPClientObserver` +> **Defined in:** `client.h` +### Members -#### `public `[`net::Address`](./doc/api-net.md#classscy_1_1net_1_1Address)` peerAddress` +| Name | Description | +|------|-------------| +| [`onClientStateChange`](#group__turn_1ga2f8c99aadad178228ca800c56c66a53a) | | +| [`onRelayDataReceived`](#group__turn_1ga289952ed0e63f289511dcb4e89d8b993) | | +| [`onAllocationFailed`](#group__turn_1gaf843439ada68af5d0a8c44b9e6f84cef) | | +| [`onAllocationDeleted`](#group__turn_1ga2fa9e57662dbf68959503085fa781d02) | | +| [`onAllocationPermissionsCreated`](#group__turn_1ga26b4ea2e7a7f1a728218bda75b670c89) | | +| [`onTransactionResponse`](#group__turn_1ga0b96125a01852fdcd24ecdc7e9eba5af) | All received transaction responses will be routed here after local processing so the observer can easily implement extra functionality. | +| [`onTimer`](#group__turn_1gac3b5b3eae27058463dc291d16883bbb6) | Fires after the client's internal timer callback. Handy for performing extra async cleanup tasks. | +--- +#### onClientStateChange +```cpp +void onClientStateChange(Client & client, ClientState & state, const ClientState & oldState) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `client` | `Client &` | | +| `state` | `ClientState &` | | +| `oldState` | `const ClientState &` | | -# struct `scy::turn::ServerObserver` +--- +#### onRelayDataReceived +```cpp +void onRelayDataReceived(Client & client, const char * data, size_t size, const net::Address & peerAddress) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `client` | `Client &` | | +| `data` | `const char *` | | +| `size` | `size_t` | | +| `peerAddress` | `const net::Address &` | | -The [ServerObserver](#structscy_1_1turn_1_1ServerObserver) receives callbacks for and is responsible for managing allocation and bandwidth quotas, authentication methods and authentication. +--- -## Summary +#### onAllocationFailed - Members | Descriptions ---------------------------------|--------------------------------------------- -`public void onServerAllocationCreated(`[`Server`](#classscy_1_1turn_1_1Server)` * server,`[`IAllocation`](#classscy_1_1turn_1_1IAllocation)` * alloc)` | -`public void onServerAllocationRemoved(`[`Server`](#classscy_1_1turn_1_1Server)` * server,`[`IAllocation`](#classscy_1_1turn_1_1IAllocation)` * alloc)` | -`public AuthenticationState authenticateRequest(`[`Server`](#classscy_1_1turn_1_1Server)` * server,`[`Request`](#classscy_1_1turn_1_1Request)` & request)` | +```cpp +virtual inline void onAllocationFailed(Client & client, int errorCode, const std::string & reason) +``` -## Members +| Parameter | Type | Description | +|-----------|------|-------------| +| `client` | `Client &` | | +| `errorCode` | `int` | | +| `reason` | `const std::string &` | | -#### `public void onServerAllocationCreated(`[`Server`](#classscy_1_1turn_1_1Server)` * server,`[`IAllocation`](#classscy_1_1turn_1_1IAllocation)` * alloc)` +--- +#### onAllocationDeleted +```cpp +virtual inline void onAllocationDeleted(Client & client, const stun::Transaction & transaction) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `client` | `Client &` | | +| `transaction` | `const stun::Transaction &` | | +--- -#### `public void onServerAllocationRemoved(`[`Server`](#classscy_1_1turn_1_1Server)` * server,`[`IAllocation`](#classscy_1_1turn_1_1IAllocation)` * alloc)` +#### onAllocationPermissionsCreated +```cpp +virtual inline void onAllocationPermissionsCreated(Client & client, const PermissionList & permissions) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `client` | `Client &` | | +| `permissions` | `const PermissionList &` | | +--- +#### onTransactionResponse -#### `public AuthenticationState authenticateRequest(`[`Server`](#classscy_1_1turn_1_1Server)` * server,`[`Request`](#classscy_1_1turn_1_1Request)` & request)` +```cpp +virtual inline void onTransactionResponse(Client & client, const stun::Transaction & transaction) +``` +All received transaction responses will be routed here after local processing so the observer can easily implement extra functionality. +| Parameter | Type | Description | +|-----------|------|-------------| +| `client` | `Client &` | | +| `transaction` | `const stun::Transaction &` | | -The observer class can implement authentication using the long-term credential mechanism of [RFC5389]. The class design is such that authentication can be preformed asynchronously against a remote database, or locally. The default implementation returns true to all requests. +--- -To mitigate either intentional or unintentional denial-of-service attacks against the server by clients with valid usernames and passwords, it is RECOMMENDED that the server impose limits on both the number of allocations active at one time for a given username and on the amount of bandwidth those allocations can use. The server should reject new allocations that would exceed the limit on the allowed number of allocations active at one time with a 486 (Allocation Quota Exceeded) (see Section 6.2), and should discard application data traffic that exceeds the bandwidth quota. +#### onTimer -# struct `scy::turn::ServerOptions` +```cpp +virtual inline void onTimer(Client & client) +``` +Fires after the client's internal timer callback. Handy for performing extra async cleanup tasks. -[Configuration](#classscy_1_1Configuration) options for the TURN server. +| Parameter | Type | Description | +|-----------|------|-------------| +| `client` | `Client &` | | +## Options +> **Defined in:** `client.h` -## Summary +### Members - Members | Descriptions ---------------------------------|--------------------------------------------- -`public std::string software` | -`public std::string realm` | -`public uint32_t allocationDefaultLifetime` | -`public uint32_t allocationMaxLifetime` | -`public int allocationMaxPermissions` | -`public int timerInterval` | -`public int earlyMediaBufferSize` | -`public `[`net::Address`](./doc/api-net.md#classscy_1_1net_1_1Address)` listenAddr` | The TCP and UDP bind() address. -`public std::string externalIP` | The external public facing IP address of the server. -`public bool enableTCP` | -`public bool enableUDP` | -`public inline ServerOptions()` | +| Name | Description | +|------|-------------| +| [`Options`](#group__turn_1gae926546e19d8fd9a7fab86271b96a54f) | | +| [`software`](#group__turn_1ga5353220869e0f09239060488ecdb7fef) | | +| [`username`](#group__turn_1gac72217fb6b73d1d050c84379189354a5) | | +| [`password`](#group__turn_1ga90e75f93e08bd392b9def185c4f29ec1) | | +| [`timeout`](#group__turn_1ga3b36f9f68df1b465c1046b88529ccf69) | | +| [`lifetime`](#group__turn_1ga7dc6b1fc053f08ec22d0f2f97084d996) | | +| [`timerInterval`](#group__turn_1ga50b1abb4fea151715d0c93b5ac675f30) | | +| [`serverAddr`](#group__turn_1gaca69ae3e4cb351a623def3f8ca67a950) | | -## Members +--- -#### `public std::string software` +#### Options +```cpp +inline Options() +``` +--- +#### software +```cpp +std::string software +``` -#### `public std::string realm` +--- +#### username +```cpp +std::string username +``` +--- +#### password -#### `public uint32_t allocationDefaultLifetime` +```cpp +std::string password +``` +--- +#### timeout +```cpp +long timeout +``` +--- -#### `public uint32_t allocationMaxLifetime` +#### lifetime +```cpp +std::int64_t lifetime +``` +--- +#### timerInterval +```cpp +std::int64_t timerInterval +``` -#### `public int allocationMaxPermissions` +--- +#### serverAddr +```cpp +net::Address serverAddr +``` +## TCPClientObserver +> **Extends:** `scy::turn::ClientObserver` +> **Defined in:** `tcpclient.h` -#### `public int timerInterval` +### Members +| Name | Description | +|------|-------------| +| [`onRelayConnectionCreated`](#group__turn_1ga9cadceec9bf3a4687f3b32ea67404e8f) | | +| [`onRelayConnectionError`](#group__turn_1ga37d33d68190c4578c19b0bf376ad8f63) | | +| [`onRelayConnectionClosed`](#group__turn_1gaa0e978e987f8b59662356bf9d51b4616) | | +| [`onRelayConnectionBindingFailed`](#group__turn_1ga31a9a774ee2e1b13ca87e108bf6cf76e) | | +| [`onPeerConnectionAttempt`](#group__turn_1gad6938fba6074bc0e1ca499cf90bb84ca) | | +--- +#### onRelayConnectionCreated +```cpp +void onRelayConnectionCreated(TCPClient & client, const net::TCPSocket::Ptr & socket, const net::Address & peerAddress) +``` -#### `public int earlyMediaBufferSize` +| Parameter | Type | Description | +|-----------|------|-------------| +| `client` | `TCPClient &` | | +| `socket` | `const net::TCPSocket::Ptr &` | | +| `peerAddress` | `const net::Address &` | | +--- +#### onRelayConnectionError +```cpp +virtual inline void onRelayConnectionError(TCPClient & client, const net::TCPSocket::Ptr & socket, const net::Address & peerAddress) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `client` | `TCPClient &` | | +| `socket` | `const net::TCPSocket::Ptr &` | | +| `peerAddress` | `const net::Address &` | | -#### `public `[`net::Address`](./doc/api-net.md#classscy_1_1net_1_1Address)` listenAddr` +--- -The TCP and UDP bind() address. +#### onRelayConnectionClosed +```cpp +void onRelayConnectionClosed(TCPClient & client, const net::TCPSocket::Ptr & socket, const net::Address & peerAddress) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `client` | `TCPClient &` | | +| `socket` | `const net::TCPSocket::Ptr &` | | +| `peerAddress` | `const net::Address &` | | -#### `public std::string externalIP` +--- -The external public facing IP address of the server. +#### onRelayConnectionBindingFailed +```cpp +virtual inline void onRelayConnectionBindingFailed(TCPClient & client, const net::Address & peerAddress) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `client` | `TCPClient &` | | +| `peerAddress` | `const net::Address &` | | -#### `public bool enableTCP` +--- +#### onPeerConnectionAttempt +```cpp +virtual inline bool onPeerConnectionAttempt(TCPClient & client, const net::Address & peerAddress) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `client` | `TCPClient &` | | +| `peerAddress` | `const net::Address &` | | +## RelayConnectionBinding -#### `public bool enableUDP` +> **Defined in:** `tcpclient.h` +### Members +| Name | Description | +|------|-------------| +| [`connectionID`](#group__turn_1ga2c6b83886801342cdf489851451f02cb) | | +| [`peerAddress`](#group__turn_1gab40590fa9feb9154fbd96678304cf5ce) | | +--- +#### connectionID -#### `public inline ServerOptions()` +```cpp +uint32_t connectionID +``` +--- +#### peerAddress +```cpp +net::Address peerAddress +``` +## Permission -# struct `scy::turn::TCPClientObserver` +> **Defined in:** `permission.h` -``` -struct scy::turn::TCPClientObserver - : public scy::turn::ClientObserver -``` +TURN permission for a user session. +### Members +| Name | Description | +|------|-------------| +| [`Permission`](#group__turn_1ga1d84a2f95323c85990c9464c4a9d3256) | | +| [`refresh`](#group__turn_1ga0b8b830b544ab68a84f3214563347080) | | +| [`operator==`](#group__turn_1gabf7857f22a589a833b5aa79391b57830) | | +| [`ip`](#group__turn_1gac3d4b7db7da99f5df332df065c3bbeba) | | +| [`timeout`](#group__turn_1ga7f9706e123e06bacdfc229e9f2d4b503) | | +--- +#### Permission -## Summary +```cpp +inline Permission(const std::string & ip) +``` - Members | Descriptions ---------------------------------|--------------------------------------------- -`public void onRelayConnectionCreated(`[`TCPClient`](#classscy_1_1turn_1_1TCPClient)` & client,const net::TCPSocket::Ptr & socket,const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddress)` | -`public inline virtual void onRelayConnectionError(`[`TCPClient`](#classscy_1_1turn_1_1TCPClient)` & client,const net::TCPSocket::Ptr & socket,const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddress)` | -`public void onRelayConnectionClosed(`[`TCPClient`](#classscy_1_1turn_1_1TCPClient)` & client,const net::TCPSocket::Ptr & socket,const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddress)` | -`public inline virtual void onRelayConnectionBindingFailed(`[`TCPClient`](#classscy_1_1turn_1_1TCPClient)` & client,const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddress)` | -`public inline virtual bool onPeerConnectionAttempt(`[`TCPClient`](#classscy_1_1turn_1_1TCPClient)` & client,const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddress)` | +| Parameter | Type | Description | +|-----------|------|-------------| +| `ip` | `const std::string &` | | -## Members +--- -#### `public void onRelayConnectionCreated(`[`TCPClient`](#classscy_1_1turn_1_1TCPClient)` & client,const net::TCPSocket::Ptr & socket,const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddress)` +#### refresh +```cpp +inline void refresh() +``` +--- +#### operator== +```cpp +inline bool operator==(const std::string & r) const +``` -#### `public inline virtual void onRelayConnectionError(`[`TCPClient`](#classscy_1_1turn_1_1TCPClient)` & client,const net::TCPSocket::Ptr & socket,const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddress)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `r` | `const std::string &` | | +--- +#### ip +```cpp +std::string ip +``` +--- -#### `public void onRelayConnectionClosed(`[`TCPClient`](#classscy_1_1turn_1_1TCPClient)` & client,const net::TCPSocket::Ptr & socket,const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddress)` +#### timeout +```cpp +Timeout timeout +``` +## ServerOptions +> **Defined in:** `server.h` +[Configuration](./doc/api-base.md#classscy_1_1Configuration) options for the TURN server. -#### `public inline virtual void onRelayConnectionBindingFailed(`[`TCPClient`](#classscy_1_1turn_1_1TCPClient)` & client,const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddress)` +### Members +| Name | Description | +|------|-------------| +| [`ServerOptions`](#group__turn_1ga23b935569a27d3f3dcf0f78e8a5ca280) | | +| [`software`](#group__turn_1gac2291c280fe0980304bca18ab44f8731) | | +| [`realm`](#group__turn_1gaabb449fc0c3e896938868e9eba870ba4) | | +| [`allocationDefaultLifetime`](#group__turn_1ga8d82709c768778e902772af859826ee6) | | +| [`allocationMaxLifetime`](#group__turn_1ga7230b59c2f23a9a850a9a74c28a9114f) | | +| [`allocationMaxPermissions`](#group__turn_1gab877b8fafddc71ed3de320159ff614e5) | | +| [`timerInterval`](#group__turn_1ga30c595ee93bb3dfee3cd52faff6a4222) | | +| [`earlyMediaBufferSize`](#group__turn_1ga9122325d7162eb5b1f23888d63cd282d) | | +| [`listenAddr`](#group__turn_1gabd4aa0f66ce2fc218e80810f3c762d76) | The TCP and UDP bind() address. | +| [`externalIP`](#group__turn_1ga88891ec27dede5dc6be7219ed26c9b2a) | The external public facing IP address of the server. | +| [`enableTCP`](#group__turn_1ga1d0c462bf8701333710f2f1d4eb0f18a) | | +| [`enableUDP`](#group__turn_1gaf34f6a53ee1dd805c81af5556deecdb9) | | +--- +#### ServerOptions +```cpp +inline ServerOptions() +``` -#### `public inline virtual bool onPeerConnectionAttempt(`[`TCPClient`](#classscy_1_1turn_1_1TCPClient)` & client,const `[`net::Address`](#classscy_1_1net_1_1Address)` & peerAddress)` +--- +#### software +```cpp +std::string software +``` +--- +#### realm -# struct `scy::turn::Client::Options` +```cpp +std::string realm +``` +--- +#### allocationDefaultLifetime +```cpp +uint32_t allocationDefaultLifetime +``` +--- +#### allocationMaxLifetime -## Summary +```cpp +uint32_t allocationMaxLifetime +``` - Members | Descriptions ---------------------------------|--------------------------------------------- -`public std::string software` | -`public std::string username` | -`public std::string password` | -`public long timeout` | -`public std::int64_t lifetime` | -`public std::int64_t timerInterval` | -`public `[`net::Address`](./doc/api-net.md#classscy_1_1net_1_1Address)` serverAddr` | -`public inline Options()` | +--- -## Members +#### allocationMaxPermissions -#### `public std::string software` +```cpp +int allocationMaxPermissions +``` +--- +#### timerInterval +```cpp +int timerInterval +``` +--- -#### `public std::string username` +#### earlyMediaBufferSize +```cpp +int earlyMediaBufferSize +``` +--- +#### listenAddr +```cpp +net::Address listenAddr +``` -#### `public std::string password` +The TCP and UDP bind() address. +--- +#### externalIP +```cpp +std::string externalIP +``` +The external public facing IP address of the server. -#### `public long timeout` +--- +#### enableTCP +```cpp +bool enableTCP +``` +--- +#### enableUDP -#### `public std::int64_t lifetime` +```cpp +bool enableUDP +``` +## ServerObserver +> **Defined in:** `server.h` +The [ServerObserver](#structscy_1_1turn_1_1ServerObserver) receives callbacks for and is responsible for managing allocation and bandwidth quotas, authentication methods and authentication. +### Members -#### `public std::int64_t timerInterval` +| Name | Description | +|------|-------------| +| [`onServerAllocationCreated`](#group__turn_1gae40bc9446a48541dcbd436ed8fb6e1ff) | | +| [`onServerAllocationRemoved`](#group__turn_1ga080fc643212385979ab6b66210bc15c1) | | +| [`authenticateRequest`](#group__turn_1ga36ad126902d380f3b569e6a7c70837a1) | The observer class can implement authentication using the long-term credential mechanism of [RFC5389]. The class design is such that authentication can be preformed asynchronously against a remote database, or locally. The default implementation returns true to all requests. | +--- +#### onServerAllocationCreated +```cpp +void onServerAllocationCreated(Server * server, IAllocation * alloc) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `server` | `Server *` | | +| `alloc` | `IAllocation *` | | -#### `public `[`net::Address`](./doc/api-net.md#classscy_1_1net_1_1Address)` serverAddr` +--- +#### onServerAllocationRemoved +```cpp +void onServerAllocationRemoved(Server * server, IAllocation * alloc) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `server` | `Server *` | | +| `alloc` | `IAllocation *` | | +--- -#### `public inline Options()` +#### authenticateRequest +```cpp +AuthenticationState authenticateRequest(Server * server, Request & request) +``` +The observer class can implement authentication using the long-term credential mechanism of [RFC5389]. The class design is such that authentication can be preformed asynchronously against a remote database, or locally. The default implementation returns true to all requests. +To mitigate either intentional or unintentional denial-of-service attacks against the server by clients with valid usernames and passwords, it is RECOMMENDED that the server impose limits on both the number of allocations active at one time for a given username and on the amount of bandwidth those allocations can use. The server should reject new allocations that would exceed the limit on the allowed number of allocations active at one time with a 486 (Allocation Quota Exceeded) (see Section 6.2), and should discard application data traffic that exceeds the bandwidth quota. +| Parameter | Type | Description | +|-----------|------|-------------| +| `server` | `Server *` | | +| `request` | `Request &` | | diff --git a/doc/api-util.md b/doc/api-util.md index 246e3329f..e20520853 100644 --- a/doc/api-util.md +++ b/doc/api-util.md @@ -1,828 +1,1093 @@ -# Module `util` +# util A simple message rate limiter based on the token bucket algorithm. -/// +### Classes -## Summary +| Name | Description | +|------|-------------| +| [`Base64PacketEncoder`](#classscy_1_1Base64PacketEncoder) | | +| [`IDiagnostic`](#classscy_1_1IDiagnostic) | | +| [`AsyncDiagnostic`](#classscy_1_1AsyncDiagnostic) | | +| [`DiagnosticManager`](#classscy_1_1DiagnosticManager) | | +| [`IRegistry`](#classscy_1_1IRegistry) | | +| [`RateLimiter`](#classscy_1_1RateLimiter) | | +| [`StreamManager`](#classscy_1_1StreamManager) | | +| [`TimedManager`](#classscy_1_1TimedManager) | Timed pointer manager | +| [`BasicUser`](#classscy_1_1BasicUser) | | +| [`UserManager`](#classscy_1_1UserManager) | > Deprecated: This class manages a list of users. | +| [`DiagnosticState`](#structscy_1_1DiagnosticState) | | +| [`IUser`](#structscy_1_1IUser) | | - Members | Descriptions ---------------------------------|--------------------------------------------- -`namespace `[`scy`](#namespacescy) | -# namespace `scy` +## Base64PacketEncoder +> **Extends:** `scy::PacketProcessor` +> **Defined in:** `base64packetencoder.h` +### Members -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`class `[`scy::AsyncDiagnostic`](#classscy_1_1AsyncDiagnostic) | -`class `[`scy::Base64PacketEncoder`](#classscy_1_1Base64PacketEncoder) | -`class `[`scy::BasicUser`](#classscy_1_1BasicUser) | -`class `[`scy::DiagnosticManager`](#classscy_1_1DiagnosticManager) | -`class `[`scy::IDiagnostic`](#classscy_1_1IDiagnostic) | -`class `[`scy::IRegistry`](#classscy_1_1IRegistry) | -`class `[`scy::RateLimiter`](#classscy_1_1RateLimiter) | -`class `[`scy::StreamManager`](#classscy_1_1StreamManager) | -`class `[`scy::TimedManager`](#classscy_1_1TimedManager) | -`class `[`scy::UserManager`](#classscy_1_1UserManager) | -`struct `[`scy::DiagnosticState`](#structscy_1_1DiagnosticState) | -`struct `[`scy::IUser`](#structscy_1_1IUser) | -# class `scy::AsyncDiagnostic` - -``` -class scy::AsyncDiagnostic - : public scy::IDiagnostic - : public scy::basic::Runnable -``` - - - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public inline virtual ~AsyncDiagnostic()` | -`public void run()` | The run method will be called by the asynchronous context. -`public inline virtual void check()` | -`protected `[`Thread`](./doc/api-base.md#classscy_1_1Thread)` _thread` | - -## Members - -#### `public inline virtual ~AsyncDiagnostic()` - - - - - -#### `public void run()` - -The run method will be called by the asynchronous context. +| Name | Description | +|------|-------------| +| [`Base64PacketEncoder`](#group__util_1ga7a4a4a092ea8e67ba50a511a57acaa0b) | | +| [`process`](#group__util_1ga2180bb1a7753b37c2d12754eeb9d6e99) | This method performs processing on the given packet and emits the result. | +| [`emitter`](#group__util_1ga2d3eededaa9fe67484a81fb7a346dc03) | | +--- +#### Base64PacketEncoder -#### `public inline virtual void check()` - - - - - -#### `protected `[`Thread`](./doc/api-base.md#classscy_1_1Thread)` _thread` - - - - - -# class `scy::Base64PacketEncoder` - +```cpp +inline Base64PacketEncoder() ``` -class scy::Base64PacketEncoder - : public scy::PacketProcessor -``` - - - - - -## Summary - Members | Descriptions ---------------------------------|--------------------------------------------- -`public `[`PacketSignal`](#group__base_1ga3ffb5bda6133fac97f3bed2b567b9b6a)` emitter` | -`public inline Base64PacketEncoder()` | -`public inline virtual void process(`[`IPacket`](#classscy_1_1IPacket)` & packet)` | +--- -## Members - -#### `public `[`PacketSignal`](#group__base_1ga3ffb5bda6133fac97f3bed2b567b9b6a)` emitter` - - - - - -#### `public inline Base64PacketEncoder()` - - - - - -#### `public inline virtual void process(`[`IPacket`](#classscy_1_1IPacket)` & packet)` - - - -This method performs processing on the given packet and emits the result. - -Note: If packet processing is async (the packet is not in the current thread scope) then packet data must be copied. Copied data can be freed directly aFter the async call to emit() the outgoing packet. - -# class `scy::BasicUser` +#### process +```cpp +virtual inline void process(IPacket & packet) ``` -class scy::BasicUser - : public scy::IUser -``` - - - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public inline BasicUser(const std::string & username,const std::string & password)` | -`public inline virtual std::string username() const` | -`public inline virtual std::string password() const` | -`protected std::string _username` | -`protected std::string _password` | - -## Members - -#### `public inline BasicUser(const std::string & username,const std::string & password)` - - - - - -#### `public inline virtual std::string username() const` - - - - - -#### `public inline virtual std::string password() const` - - - - - -#### `protected std::string _username` - - - - - -#### `protected std::string _password` +This method performs processing on the given packet and emits the result. +Note: If packet processing is async (the packet is not in the current thread scope) then packet data must be copied. Copied data can be freed directly aFter the async call to [emit()](./doc/api-base.md#group__base_1ga995248310998c29df87051389f52b58c) the outgoing packet. +| Parameter | Type | Description | +|-----------|------|-------------| +| `packet` | `IPacket &` | | +--- -# class `scy::DiagnosticManager` +#### emitter +```cpp +PacketSignal emitter ``` -class scy::DiagnosticManager - : public scy::PointerCollection< TKey, TValue, TDeleter > -``` - - - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public `[`NullSignal`](./doc/api-base.md#classscy_1_1Signal)` DiagnosticsComplete` | -`public DiagnosticManager()` | -`public virtual ~DiagnosticManager()` | -`public bool freeDiagnostic(const std::string & name)` | -`public bool addDiagnostic(`[`IDiagnostic`](#classscy_1_1IDiagnostic)` * test)` | Adds a [IDiagnostic](./doc/api-util.md#classscy_1_1IDiagnostic) test instance. -`public virtual `[`IDiagnostic`](#classscy_1_1IDiagnostic)` * getDiagnostic(const std::string & name)` | -`public virtual void resetAll()` | -`public virtual void checkAll()` | -`public virtual bool allComplete()` | -`public virtual void onDiagnosticStateChange(void *,`[`DiagnosticState`](#structscy_1_1DiagnosticState)` & state,const `[`DiagnosticState`](#structscy_1_1DiagnosticState)` &)` | - -## Members - -#### `public `[`NullSignal`](./doc/api-base.md#classscy_1_1Signal)` DiagnosticsComplete` - - - - - -#### `public DiagnosticManager()` - - - - - -#### `public virtual ~DiagnosticManager()` - - - - - -#### `public bool freeDiagnostic(const std::string & name)` - - - +## IDiagnostic + +> **Extends:** `scy::Stateful< DiagnosticState >` +> **Subclasses:** `scy::AsyncDiagnostic` +> **Defined in:** `diagnosticmanager.h` + +### Members + +| Name | Description | +|------|-------------| +| [`IDiagnostic`](#group__util_1gac8aca5149fda66a927334e1132c48890) | | +| [`~IDiagnostic`](#group__util_1ga4ef2121b9fd45a42fda1b2aee0a9ea2c) | | +| [`check`](#group__util_1gabd4bf909e78503107e0604f11d0437f6) | | +| [`reset`](#group__util_1ga4824c0cc08d8b244a5b7a8916e50a136) | | +| [`complete`](#group__util_1ga23369ac4b799996b3b2911e05076e557) | | +| [`passed`](#group__util_1ga5ed635d12653d66026810386a4bfb7a1) | | +| [`failed`](#group__util_1ga31ceeef28f1b085ec2162002deb00d60) | | +| [`run`](#group__util_1ga36bfaa138a649addc6f0d89d4df5ea28) | Override to implement diagnostic logic. | +| [`pass`](#group__util_1ga673e4cb65e024a8ec9e123061689b112) | | +| [`fail`](#group__util_1ga05af62ad19e7683f04b2a0637ae0baed) | | +| [`addSummary`](#group__util_1ga64ac18ee28d24cec3f898123db0a62c8) | | +| [`name`](#group__util_1gaa69e4ded0fb7d0db9113ab8c318a043f) | The name of the diagnostic. | +| [`description`](#group__util_1ga5a7dca63479b6fb69f62ed3c33919a11) | The diagnostic description. | +| [`summary`](#group__util_1gac24ce2f6e0d721dc04d292d6b99e2beb) | The diagnostic summary, maybe including troubleshooting information on failure. | +| [`SummaryUpdated`](#group__util_1ga0383aed91dd872f4f1d6326a882e8922) | Signals when a new text item is added to the summary. | + +--- + +#### IDiagnostic + +```cpp +IDiagnostic() +``` -#### `public bool addDiagnostic(`[`IDiagnostic`](#classscy_1_1IDiagnostic)` * test)` +--- -Adds a [IDiagnostic](#classscy_1_1IDiagnostic) test instance. +#### ~IDiagnostic +```cpp +virtual ~IDiagnostic() +``` +--- -#### `public virtual `[`IDiagnostic`](#classscy_1_1IDiagnostic)` * getDiagnostic(const std::string & name)` +#### check +```cpp +virtual void check() +``` +--- -Returns the [IDiagnostic](#classscy_1_1IDiagnostic) instance or throws a NotFoundException exception. +#### reset -#### `public virtual void resetAll()` +```cpp +virtual void reset() +``` +--- +#### complete +```cpp +virtual bool complete() const +``` +--- -#### `public virtual void checkAll()` +#### passed +```cpp +virtual bool passed() const +``` +--- -Runs all managed [IDiagnostic](#classscy_1_1IDiagnostic) tests. DiagnosticsComplete will be dispatched on completion. +#### failed -#### `public virtual bool allComplete()` +```cpp +virtual bool failed() const +``` +--- +#### run +```cpp +void run() +``` +Override to implement diagnostic logic. -#### `public virtual void onDiagnosticStateChange(void *,`[`DiagnosticState`](#structscy_1_1DiagnosticState)` & state,const `[`DiagnosticState`](#structscy_1_1DiagnosticState)` &)` +The StateChange signal will dispatch diagnostic test results to delegates. +--- +#### pass +```cpp +virtual bool pass() +``` +--- -# class `scy::IDiagnostic` +#### fail +```cpp +virtual bool fail() ``` -class scy::IDiagnostic - : public scy::Stateful< DiagnosticState > -``` - +--- +#### addSummary +```cpp +virtual void addSummary(const std::string & text) +``` -## Summary +| Parameter | Type | Description | +|-----------|------|-------------| +| `text` | `const std::string &` | | - Members | Descriptions ---------------------------------|--------------------------------------------- -`public std::string name` | The name of the diagnostic. -`public std::string description` | The diagnostic description. -`public std::vector< std::string > summary` | -`public `[`Signal`](#classscy_1_1Signal)< void(const std::string &)`> SummaryUpdated` | -`public IDiagnostic()` | -`public virtual ~IDiagnostic()` | -`public virtual void check()` | -`public virtual void reset()` | -`public virtual bool complete() const` | -`public virtual bool passed() const` | -`public virtual bool failed() const` | -`protected void run()` | Override to implement diagnostic logic. -`protected virtual bool pass()` | -`protected virtual bool fail()` | -`protected virtual void addSummary(const std::string & text)` | +--- -## Members +#### name -#### `public std::string name` +```cpp +std::string name +``` The name of the diagnostic. +--- +#### description -#### `public std::string description` +```cpp +std::string description +``` The diagnostic description. +--- +#### summary -#### `public std::vector< std::string > summary` - - +```cpp +std::vector< std::string > summary +``` The diagnostic summary, maybe including troubleshooting information on failure. -#### `public `[`Signal`](#classscy_1_1Signal)< void(const std::string &)`> SummaryUpdated` +--- +#### SummaryUpdated +```cpp +Signal< void(const std::string &)> SummaryUpdated +``` Signals when a new text item is added to the summary. -#### `public IDiagnostic()` - - +## AsyncDiagnostic +> **Extends:** `scy::IDiagnostic`, `scy::basic::Runnable` +> **Defined in:** `diagnosticmanager.h` +### Members -#### `public virtual ~IDiagnostic()` +| Name | Description | +|------|-------------| +| [`~AsyncDiagnostic`](#group__util_1ga505c905b8a86b311f10b1bc81f3dd3e9) | | +| [`run`](#group__util_1ga620c69a7b25a89564232ab870c57c956) | Override to implement diagnostic logic. | +| [`check`](#group__util_1gab2c4393ef71dc2d6d090ed5eabe01224) | | +| [`_thread`](#group__util_1ga86a906cd8701f49e2f2065c9e8e3c1f3) | | +--- +#### ~AsyncDiagnostic +```cpp +virtual inline ~AsyncDiagnostic() +``` +--- -#### `public virtual void check()` +#### run +```cpp +void run() +``` +Override to implement diagnostic logic. +The StateChange signal will dispatch diagnostic test results to delegates. +--- -#### `public virtual void reset()` +#### check +```cpp +virtual inline void check() +``` +--- +#### _thread +```cpp +Thread _thread +``` -#### `public virtual bool complete() const` +## DiagnosticManager +> **Extends:** `scy::PointerCollection< TKey, TValue >` +> **Defined in:** `diagnosticmanager.h` +### Members +| Name | Description | +|------|-------------| +| [`DiagnosticManager`](#group__util_1ga1f7e1a71860acf1acf2ad00e658168b4) | | +| [`~DiagnosticManager`](#group__util_1ga33969db867a5da02ba66af577888cce1) | | +| [`freeDiagnostic`](#group__util_1gafcfa5828dcb06aa0da5d926026fba952) | | +| [`addDiagnostic`](#group__util_1ga965c646fe610d64eee38396d477e1527) | Adds a [IDiagnostic](#classscy_1_1IDiagnostic) test instance. | +| [`getDiagnostic`](#group__util_1gac6ba64b207ffd86739f287a1efda9e73) | Returns the [IDiagnostic](#classscy_1_1IDiagnostic) instance or throws a NotFoundException exception. | +| [`resetAll`](#group__util_1gaf46ebc8e54d7508f44dc5ad49c0e269f) | | +| [`checkAll`](#group__util_1ga32981bf8dbec2deef3f70427d48c2e54) | Runs all managed [IDiagnostic](#classscy_1_1IDiagnostic) tests. DiagnosticsComplete will be dispatched on completion. | +| [`allComplete`](#group__util_1gad077e09ee488e3639b0188c8667f2477) | | +| [`onDiagnosticStateChange`](#group__util_1gae5adc21f9a476721730d164a13c8dcb3) | | +| [`DiagnosticsComplete`](#group__util_1gae4bffe1d36c1087a6456bdc124740968) | | +--- -#### `public virtual bool passed() const` +#### DiagnosticManager +```cpp +DiagnosticManager() +``` +--- +#### ~DiagnosticManager +```cpp +virtual ~DiagnosticManager() +``` -#### `public virtual bool failed() const` +--- +#### freeDiagnostic +```cpp +bool freeDiagnostic(const std::string & name) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | +--- -#### `protected void run()` +#### addDiagnostic -Override to implement diagnostic logic. +```cpp +bool addDiagnostic(IDiagnostic * test) +``` -The StateChange signal will dispatch diagnostic test results to delegates. +Adds a [IDiagnostic](#classscy_1_1IDiagnostic) test instance. -#### `protected virtual bool pass()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `test` | `IDiagnostic *` | | +--- +#### getDiagnostic +```cpp +virtual IDiagnostic * getDiagnostic(const std::string & name) +``` +Returns the [IDiagnostic](#classscy_1_1IDiagnostic) instance or throws a NotFoundException exception. -#### `protected virtual bool fail()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | +--- +#### resetAll +```cpp +virtual void resetAll() +``` +--- -#### `protected virtual void addSummary(const std::string & text)` +#### checkAll +```cpp +virtual void checkAll() +``` +Runs all managed [IDiagnostic](#classscy_1_1IDiagnostic) tests. DiagnosticsComplete will be dispatched on completion. +--- +#### allComplete -# class `scy::IRegistry` +```cpp +virtual bool allComplete() +``` +--- +#### onDiagnosticStateChange +```cpp +virtual void onDiagnosticStateChange(void *, DiagnosticState & state, const DiagnosticState &) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `state` | `DiagnosticState &` | | +--- -## Summary +#### DiagnosticsComplete - Members | Descriptions ---------------------------------|--------------------------------------------- -`public `[`Signal`](#classscy_1_1Signal)< void(const std::string &)`> TypeRegistered` | -`public `[`Signal`](#classscy_1_1Signal)< void(const std::string &)`> TypeUnregistered` | -`public inline IRegistry()` | -`public inline virtual ~IRegistry()` | -`public inline virtual ItemT * createInstance(const std::string & s)` | -`public template`
`inline void registerType(const std::string & s)` | -`public inline virtual void unregisterType(const std::string & s)` | -`public inline TypeMap types() const` | +```cpp +NullSignal DiagnosticsComplete +``` -## Members +## IRegistry -#### `public `[`Signal`](#classscy_1_1Signal)< void(const std::string &)`> TypeRegistered` +> **Defined in:** `iregistry.h` +### Members +| Name | Description | +|------|-------------| +| [`createT`](#group__util_1gaea23db6c38a420f33f2a0f7811bb02f1) | | +| [`IRegistry`](#group__util_1ga1c7634f07f5a50280145164b4948ec71) | | +| [`~IRegistry`](#group__util_1gae6ab7fa3040b6ccb7539a4e4a989cc6d) | | +| [`createInstance`](#group__util_1gaea046c8664de5a458c5d8eb30f03c976) | | +| [`registerType`](#group__util_1gae25f5528b11ce12d628e246eeb7e0e78) | | +| [`unregisterType`](#group__util_1ga6501164e448376e278823594a9af0d93) | | +| [`types`](#group__util_1ga2b6c7be0bba65bcbe8131921459f0d3f) | | +| [`TypeRegistered`](#group__util_1gafea9585c6ff2924b3217fa26cb1a6c83) | | +| [`TypeUnregistered`](#group__util_1gab4b972dc17709d48a418073e33e264b8) | | +| [`_types`](#group__util_1ga6caeb590a40377bee11802fcd7153962) | | +--- +#### createT -#### `public `[`Signal`](#classscy_1_1Signal)< void(const std::string &)`> TypeUnregistered` +```cpp +template inline ItemT * createT() +``` +--- +#### IRegistry +```cpp +IRegistry() = default +``` +--- -#### `public inline IRegistry()` +#### ~IRegistry +```cpp +virtual ~IRegistry() = default +``` +--- +#### createInstance +```cpp +virtual inline ItemT * createInstance(const std::string & s) +``` -#### `public inline virtual ~IRegistry()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `s` | `const std::string &` | | +--- +#### registerType +```cpp +template inline void registerType(const std::string & s) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `s` | `const std::string &` | | -#### `public inline virtual ItemT * createInstance(const std::string & s)` +--- +#### unregisterType +```cpp +virtual inline void unregisterType(const std::string & s) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `s` | `const std::string &` | | +--- -#### `public template`
`inline void registerType(const std::string & s)` +#### types +```cpp +inline TypeMap types() const +``` +--- +#### TypeRegistered +```cpp +Signal< void(const std::string &)> TypeRegistered +``` -#### `public inline virtual void unregisterType(const std::string & s)` +--- +#### TypeUnregistered +```cpp +Signal< void(const std::string &)> TypeUnregistered +``` +--- +#### _types -#### `public inline TypeMap types() const` +```cpp +TypeMap _types +``` +## RateLimiter +> **Defined in:** `ratelimiter.h` +### Members +| Name | Description | +|------|-------------| +| [`RateLimiter`](#group__util_1gaba3e054e11999e0faf0d8be12e31855e) | | +| [`canSend`](#group__util_1gaa714f604007b21bc6435d3e518d68de4) | | +| [`rate`](#group__util_1ga91c35e10dfcf207f17e62d2242708f26) | How many messages. | +| [`seconds`](#group__util_1gac47e0bd0461efd33ba6d7e480eeb9059) | Over how many seconds. | +| [`allowance`](#group__util_1ga40eb12dada557ee2fff2ad2e419ec92c) | Remaining send allowance. | +| [`lastCheck`](#group__util_1ga247fefbc3361b60286b4e431410ff98a) | Last time [canSend()](#group__util_1gaa714f604007b21bc6435d3e518d68de4) was called. | -# class `scy::RateLimiter` +--- +#### RateLimiter +```cpp +inline RateLimiter(double rate, double seconds) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `rate` | `double` | | +| `seconds` | `double` | | +--- +#### canSend -## Summary +```cpp +inline bool canSend() +``` - Members | Descriptions ---------------------------------|--------------------------------------------- -`public double rate` | How many messages. -`public double seconds` | Over how many seconds. -`public double allowance` | Remaining send allowance. -`public clock_t lastCheck` | Last time canSend() was called. -`public inline RateLimiter(double rate,double seconds)` | -`public inline bool canSend()` | +--- -## Members +#### rate -#### `public double rate` +```cpp +double rate +``` How many messages. +--- +#### seconds -#### `public double seconds` +```cpp +double seconds +``` Over how many seconds. +--- +#### allowance -#### `public double allowance` +```cpp +double allowance +``` Remaining send allowance. +--- +#### lastCheck -#### `public clock_t lastCheck` - -Last time canSend() was called. - - - -#### `public inline RateLimiter(double rate,double seconds)` - - - - - -#### `public inline bool canSend()` - - - - - -# class `scy::StreamManager` - +```cpp +clock_t lastCheck ``` -class scy::StreamManager - : public scy::LiveCollection< PacketStream > > -``` - - - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public StreamManager(bool freeClosedStreams)` | -`public virtual ~StreamManager()` | -`public virtual bool addStream(`[`PacketStream`](#classscy_1_1PacketStream)` * stream,bool whiny)` | -`public virtual bool closeStream(const std::string & name,bool whiny)` | -`public virtual void closeAll()` | -`public virtual `[`PacketStream`](#classscy_1_1PacketStream)` * getStream(const std::string & name,bool whiny)` | -`public virtual `[`PacketStream`](#classscy_1_1PacketStream)` * getDafaultStream()` | Returns the first stream in the list, or NULL. -`public virtual Map streams() const` | -`public virtual void print(std::ostream & os) const` | -`protected bool _freeClosedStreams` | -`protected virtual void onAdd(`[`PacketStream`](#classscy_1_1PacketStream)` * task)` | Called after a stream is added. -`protected virtual void onRemove(`[`PacketStream`](#classscy_1_1PacketStream)` * task)` | Called after a stream is removed. -`protected virtual void onStreamStateChange(void * sender,`[`PacketStreamState`](#structscy_1_1PacketStreamState)` & state,const `[`PacketStreamState`](#structscy_1_1PacketStreamState)` &)` | -`protected inline virtual const char * className() const` | -## Members +Last time [canSend()](#group__util_1gaa714f604007b21bc6435d3e518d68de4) was called. -#### `public StreamManager(bool freeClosedStreams)` +## StreamManager +> **Extends:** `scy::LiveCollection< TKey, TValue >` +> **Defined in:** `streammanager.h` +### Members +| Name | Description | +|------|-------------| +| [`StreamManager`](#group__util_1ga1f895ea996be0a12e49f0e44e4427ce2) | | +| [`~StreamManager`](#group__util_1ga0204c0879b0c83ce9cd770ff14327669) | | +| [`addStream`](#group__util_1gaf630cdcb67fa136f37e4b8ae9f07cf05) | | +| [`closeStream`](#group__util_1ga4d9fe6b1424912270ee3669c093d6ac3) | | +| [`closeAll`](#group__util_1ga6a82d6d92fa742e14402400791ef12a0) | | +| [`getStream`](#group__util_1ga07cf385a3eb2fa5e1e4a4d236dbc6b3c) | | +| [`getDafaultStream`](#group__util_1ga7cc76a987b8398d5c12cb01575bad6f0) | Returns the first stream in the list, or NULL. | +| [`streams`](#group__util_1ga65bc8e98624a30595536f5feca2024ad) | | +| [`print`](#group__util_1gaf885fbf7d31d61dd1545862913c34e94) | | +| [`onAdd`](#group__util_1ga1353a4e0b6b655a9e433b2dcf727d5b6) | Called after a stream is added. | +| [`onRemove`](#group__util_1gaef450cb0b58f02c844a8d31657f67822) | Called after a stream is removed. | +| [`onStreamStateChange`](#group__util_1ga7388ae78948b7e42d5ef65470d97022c) | | +| [`className`](#group__util_1ga0d838f9621cbf8455f08d6cdc259fc23) | | +--- -#### `public virtual ~StreamManager()` - - - +#### StreamManager +```cpp +StreamManager() +``` -#### `public virtual bool addStream(`[`PacketStream`](#classscy_1_1PacketStream)` * stream,bool whiny)` +--- +#### ~StreamManager +```cpp +virtual ~StreamManager() +``` +--- +#### addStream -#### `public virtual bool closeStream(const std::string & name,bool whiny)` +```cpp +virtual bool addStream(PacketStream * stream, bool whiny) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `stream` | `PacketStream *` | | +| `whiny` | `bool` | | +--- +#### closeStream +```cpp +virtual bool closeStream(const std::string & name, bool whiny) +``` -#### `public virtual void closeAll()` +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | +| `whiny` | `bool` | | +--- +#### closeAll +```cpp +virtual void closeAll() +``` +--- -#### `public virtual `[`PacketStream`](#classscy_1_1PacketStream)` * getStream(const std::string & name,bool whiny)` +#### getStream +```cpp +virtual PacketStream * getStream(const std::string & name, bool whiny) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `name` | `const std::string &` | | +| `whiny` | `bool` | | +--- +#### getDafaultStream -#### `public virtual `[`PacketStream`](#classscy_1_1PacketStream)` * getDafaultStream()` +```cpp +virtual PacketStream * getDafaultStream() +``` Returns the first stream in the list, or NULL. +--- +#### streams -#### `public virtual Map streams() const` - - - - - -#### `public virtual void print(std::ostream & os) const` - - - +```cpp +virtual const Map & streams() const +``` +--- -#### `protected bool _freeClosedStreams` +#### print +```cpp +virtual void print(std::ostream & os) const +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `os` | `std::ostream &` | | +--- +#### onAdd -#### `protected virtual void onAdd(`[`PacketStream`](#classscy_1_1PacketStream)` * task)` +```cpp +virtual void onAdd(const std::string &, PacketStream * task) +``` Called after a stream is added. +| Parameter | Type | Description | +|-----------|------|-------------| +| `task` | `PacketStream *` | | +--- -#### `protected virtual void onRemove(`[`PacketStream`](#classscy_1_1PacketStream)` * task)` - -Called after a stream is removed. - - - -#### `protected virtual void onStreamStateChange(void * sender,`[`PacketStreamState`](#structscy_1_1PacketStreamState)` & state,const `[`PacketStreamState`](#structscy_1_1PacketStreamState)` &)` - +#### onRemove +```cpp +virtual void onRemove(const std::string &, PacketStream * task) +``` +Called after a stream is removed. +| Parameter | Type | Description | +|-----------|------|-------------| +| `task` | `PacketStream *` | | -#### `protected inline virtual const char * className() const` +--- +#### onStreamStateChange +```cpp +virtual void onStreamStateChange(void * sender, PacketStreamState & state, const PacketStreamState &) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `sender` | `void *` | | +| `state` | `PacketStreamState &` | | +--- -# class `scy::TimedManager` +#### className +```cpp +virtual inline const char * className() const ``` -class scy::TimedManager - : public scy::PointerCollection< TKey, TValue, TDeleter > -``` +## TimedManager +> **Extends:** `scy::PointerCollection< TKey, TValue >` +> **Defined in:** `timedmanager.h` Timed pointer manager Provides timed persistent data storage for class instances. TValue must implement the clone() method. -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public inline TimedManager(uv::Loop * loop)` | -`public inline virtual ~TimedManager()` | -`public inline virtual void add(const TKey & key,TValue * item,long timeout)` | -`public inline virtual bool expires(const TKey & key,long timeout)` | Update the item expiry timeout. -`public inline virtual bool expires(TValue * item,long timeout)` | Update the item expiry timeout. -`public inline virtual void clear()` | -`protected mutable std::mutex _tmutex` | -`protected TimeoutMap _timeouts` | -`protected `[`Timer`](./doc/api-base.md#classscy_1_1Timer)` _timer` | -`protected inline virtual bool setTimeout(TValue * item,long timeout)` | -`protected inline virtual void onRemove(const TKey & key,TValue * item)` | -`protected inline virtual void onTimeout(TValue * item)` | -`protected inline void onTimerUpdate()` | - -## Members - -#### `public inline TimedManager(uv::Loop * loop)` - - - - - -#### `public inline virtual ~TimedManager()` +### Members + +| Name | Description | +|------|-------------| +| [`TimedManager`](#group__util_1gabe8bdf4cce5c58328201adb38ac8189d) | | +| [`~TimedManager`](#group__util_1ga26d523897eb3a1df55e1d08e145adc8b) | | +| [`add`](#group__util_1gaf24ec59ddd41c6995cbbc4c36694d8d5) | Add an item which will expire (and be deleted) after the specified timeout value. If the timeout is 0 the item will be stored indefinitely. The [TimedManager](#classscy_1_1TimedManager) assumes ownership of the given pointer. | +| [`expires`](#group__util_1gaab30aca59aa37b7d54435095eadfebbf) | Update the item expiry timeout. | +| [`expires`](#group__util_1ga82593ffb8f8a37f8803b1472cffa0460) | Update the item expiry timeout. | +| [`clear`](#group__util_1ga182cfabe68dcb766dca8a3dc1934f128) | | +| [`setTimeout`](#group__util_1gac948ff0dba56d8682862800b5e9cc90b) | | +| [`onRemove`](#group__util_1ga16b8d3dd608e5034e2f90e776fd096ae) | | +| [`onTimeout`](#group__util_1ga6344f6f8576af612ce4a4d73c8e35cc4) | | +| [`onTimerUpdate`](#group__util_1ga234ef400c37fa8b8df13454853f124c3) | | +| [`_tmutex`](#group__util_1ga02e84f8577dfe8953dd646f6ba13eb63) | | +| [`_timeouts`](#group__util_1ga92175954595f2f17eda515d21ce23283) | | +| [`_timer`](#group__util_1gadf29428f84cad7b8fe48af01c9899fb7) | | + +--- + +#### TimedManager + +```cpp +inline TimedManager(uv::Loop * loop) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `loop` | `uv::Loop *` | | +--- +#### ~TimedManager +```cpp +virtual inline ~TimedManager() +``` -#### `public inline virtual void add(const TKey & key,TValue * item,long timeout)` +--- +#### add +```cpp +virtual inline void add(const TKey & key, TValue * item, long timeout) +``` Add an item which will expire (and be deleted) after the specified timeout value. If the timeout is 0 the item will be stored indefinitely. The [TimedManager](#classscy_1_1TimedManager) assumes ownership of the given pointer. -#### `public inline virtual bool expires(const TKey & key,long timeout)` - -Update the item expiry timeout. +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `const TKey &` | | +| `item` | `TValue *` | | +| `timeout` | `long` | | +--- +#### expires -#### `public inline virtual bool expires(TValue * item,long timeout)` +```cpp +virtual inline bool expires(const TKey & key, long timeout) +``` Update the item expiry timeout. +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `const TKey &` | | +| `timeout` | `long` | | +--- -#### `public inline virtual void clear()` - - - - +#### expires -#### `protected mutable std::mutex _tmutex` +```cpp +virtual inline bool expires(TValue * item, long timeout) +``` +Update the item expiry timeout. +| Parameter | Type | Description | +|-----------|------|-------------| +| `item` | `TValue *` | | +| `timeout` | `long` | | +--- +#### clear -#### `protected TimeoutMap _timeouts` +```cpp +virtual inline void clear() +``` +--- +#### setTimeout +```cpp +virtual inline bool setTimeout(TValue * item, long timeout) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `item` | `TValue *` | | +| `timeout` | `long` | | -#### `protected `[`Timer`](./doc/api-base.md#classscy_1_1Timer)` _timer` +--- +#### onRemove +```cpp +virtual inline void onRemove(const TKey & key, TValue * item) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `const TKey &` | | +| `item` | `TValue *` | | +--- -#### `protected inline virtual bool setTimeout(TValue * item,long timeout)` +#### onTimeout +```cpp +virtual inline void onTimeout(TValue * item) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `item` | `TValue *` | | +--- +#### onTimerUpdate -#### `protected inline virtual void onRemove(const TKey & key,TValue * item)` +```cpp +inline void onTimerUpdate() +``` +--- +#### _tmutex +```cpp +std::mutex _tmutex +``` +--- -#### `protected inline virtual void onTimeout(TValue * item)` +#### _timeouts +```cpp +TimeoutMap _timeouts +``` +--- +#### _timer +```cpp +Timer _timer +``` -#### `protected inline void onTimerUpdate()` +## BasicUser +> **Extends:** `scy::IUser` +> **Defined in:** `usermanager.h` +### Members +| Name | Description | +|------|-------------| +| [`BasicUser`](#group__util_1ga99d6a8ec8d148263b858607fc12e6915) | | +| [`username`](#group__util_1gaa4d74cffed88430c95be50f4178a407c) | | +| [`password`](#group__util_1gaf85d948cee382cb7a8fd63bce2230906) | | +| [`_username`](#group__util_1ga984dc62d5f29dad4f46adb0a18709614) | | +| [`_password`](#group__util_1ga6049b540334bbb0faa236a6a78646fb0) | | +--- -# class `scy::UserManager` +#### BasicUser +```cpp +inline BasicUser(const std::string & username, const std::string & password) ``` -class scy::UserManager - : public scy::LiveCollection< std::string, IUser > -``` - - -> Deprecated: This class contains a list of users that have access on the system. +| Parameter | Type | Description | +|-----------|------|-------------| +| `username` | `const std::string &` | | +| `password` | `const std::string &` | | -## Summary +--- - Members | Descriptions ---------------------------------|--------------------------------------------- -`public inline UserManager()` | -`public inline virtual ~UserManager()` | -`public inline virtual bool add(`[`IUser`](#structscy_1_1IUser)` * user)` | +#### username -## Members +```cpp +virtual inline std::string username() const +``` -#### `public inline UserManager()` +--- +#### password +```cpp +virtual inline std::string password() const +``` +--- +#### _username -#### `public inline virtual ~UserManager()` +```cpp +std::string _username +``` +--- +#### _password +```cpp +std::string _password +``` +## UserManager -#### `public inline virtual bool add(`[`IUser`](#structscy_1_1IUser)` * user)` +> **Extends:** `scy::LiveCollection< std::string, IUser >` +> **Defined in:** `usermanager.h` +> Deprecated: This class manages a list of users. +### Members +| Name | Description | +|------|-------------| +| [`UserManager`](#group__util_1gacc943bf23bcb3a3d2ce174dc52da725b) | | +| [`~UserManager`](#group__util_1ga8551f4207a9d4898cf43366d10d5e2d0) | | +| [`add`](#group__util_1ga7885b358f8dad3a9c1bfa26351919eb3) | | +--- -# struct `scy::DiagnosticState` +#### UserManager +```cpp +UserManager() = default ``` -struct scy::DiagnosticState - : public scy::State -``` +--- +#### ~UserManager +```cpp +virtual ~UserManager() = default +``` +--- -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public inline std::string str(unsigned int id) const` | - -## Members +#### add -#### `public inline std::string str(unsigned int id) const` +```cpp +virtual inline bool add(IUser * user) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `user` | `IUser *` | | +## DiagnosticState +> **Extends:** `scy::State` +> **Defined in:** `diagnosticmanager.h` +### Members -# struct `scy::IUser` +| Name | Description | +|------|-------------| +| [`Type`](#group__util_1ga3d95bbbd220fafe8e34708b6edebe92a) | | +| [`str`](#group__util_1ga0ff5f446bcd0e549324821cbd482ff04) | | +--- +#### Type +```cpp +enum Type +``` +| Value | Description | +|-------|-------------| +| `None` | | +| `Checking` | | +| `Passed` | | +| `Failed` | | +--- -## Summary +#### str - Members | Descriptions ---------------------------------|--------------------------------------------- -`public std::string username() const` | -`public std::string password() const` | +```cpp +inline std::string str(unsigned int id) const +``` -## Members +| Parameter | Type | Description | +|-----------|------|-------------| +| `id` | `unsigned int` | | -#### `public std::string username() const` +## IUser +> **Subclasses:** `scy::BasicUser` +> **Defined in:** `usermanager.h` +### Members +| Name | Description | +|------|-------------| +| [`username`](#group__util_1gab1897a1d6cd4507762cb93b1a8144c3c) | | +| [`password`](#group__util_1gad90f6bab88fd34f0a1644c2ec43b5e5f) | | +--- -#### `public std::string password() const` +#### username +```cpp +std::string username() const +``` +--- +#### password +```cpp +std::string password() const +``` diff --git a/doc/api-uv.md b/doc/api-uv.md index d9b5b0ef9..5eb6cdff1 100644 --- a/doc/api-uv.md +++ b/doc/api-uv.md @@ -1,384 +1,712 @@ -# Module `uv` +# uv The `uv` module contains C++ wrappers for `libuv`. -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`namespace `[`scy::uv`](#namespacescy_1_1uv) | -# namespace `scy::uv` - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`class `[`scy::uv::Handle`](#classscy_1_1uv_1_1Handle) | -`struct `[`scy::uv::BasicEvent`](#structscy_1_1uv_1_1BasicEvent) | Default request callback event. -`struct `[`scy::uv::Context`](#structscy_1_1uv_1_1Context) | Shared `libuv` handle context. -`struct `[`scy::uv::Request`](#structscy_1_1uv_1_1Request) | -# class `scy::uv::Handle` +### Classes +| Name | Description | +|------|-------------| +| [`Handle`](#classscy_1_1uv_1_1Handle) | Wrapper class for managing `uv_handle_t` variants. | +| [`Context`](#structscy_1_1uv_1_1Context) | Shared `libuv` handle context. | +| [`BasicEvent`](#structscy_1_1uv_1_1BasicEvent) | Default request callback event. | +| [`Request`](#structscy_1_1uv_1_1Request) | Wrapper class for managing `uv_req_t` variants. | +| [`ConnectReq`](#structscy_1_1uv_1_1ConnectReq) | [Stream](./doc/api-base.md#classscy_1_1Stream) connection request for sockets and pipes. | +| [`GetAddrInfoEvent`](#structscy_1_1uv_1_1GetAddrInfoEvent) | Get address info request callback event. | +| [`GetAddrInfoReq`](#structscy_1_1uv_1_1GetAddrInfoReq) | DNS resolver request to get the IP address of a hostname. | +## Handle +> **Subclasses:** `scy::Stream< uv_pipe_t >`, `scy::Stream< uv_tcp_t >`, `scy::Stream< T >` +> **Defined in:** `handle.h` Wrapper class for managing `uv_handle_t` variants. This class manages the handle during it's lifecycle and safely handles the asynchronous destruction mechanism. -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public inline Handle(uv::Loop * loop)` | -`public inline virtual ~Handle()` | -`public template`
`inline bool init(F && f,Args &&... args)` | Initialize the handle. -`public template`
`inline bool invoke(F && f,Args &&... args)` | Invoke a method on the handle. -`public template`
`inline void invokeOrThrow(const std::string & message,F && f,Args &&... args)` | -`public inline virtual void close()` | Close and destroy the handle. -`public inline void ref()` | Reference main loop again, once unref'd. -`public inline void unref()` | Unreference the main loop after initialized. -`public inline bool initialized() const` | Return true if the handle has been initialized. -`public inline virtual bool active() const` | Return true when the handle is active. -`public inline virtual bool closing() const` | Return true if the handle is closing. -`public inline virtual bool closed() const` | Return true is the handle has been closed. -`public inline const `[`Error`](#structscy_1_1Error)` & error() const` | Return the error context if any. -`public inline virtual void setError(const `[`Error`](#structscy_1_1Error)` & err)` | Set the error and triggers callbacks. -`public inline void setUVError(int errorno,const std::string & prefix)` | -`public inline void setAndThrowError(int errorno,const std::string & prefix)` | -`public inline void throwLastError(const std::string & prefix)` | -`public inline uv::Loop * loop() const` | Return a cast pointer to the managed `libuv` handle. -`public inline virtual void * self()` | Return a pointer to the current or derived instance. -`public inline void reset()` | Reset the internal handle pointer and container state. -`public template`
`inline `[`Handle`](#classscy_1_1uv_1_1Handle)` * get() const` | Return a typecasted pointer to the managed handle. -`public inline std::thread::id tid() const` | Return the parent thread ID. -`public inline std::shared_ptr< `[`Context`](#structscy_1_1uv_1_1Context)`< T > > context() const` | Return the shared handle pointer context. -`public inline void assertThread() const` | Assert the call is from the parent event loop thread. -`protected uv::Loop * _loop` | -`protected std::shared_ptr< `[`Context`](./doc/api-uv.md#structscy_1_1uv_1_1Context)`< T > > _context` | -`protected std::thread::id _tid` | -`protected `[`Error`](./doc/api-base.md#structscy_1_1Error)` _error` | -`protected inline virtual void onError(const `[`Error`](#structscy_1_1Error)` & error)` | -`protected inline virtual void onClose()` | -`protected Handle(const `[`Handle`](#classscy_1_1uv_1_1Handle)` &) = delete` | NonCopyable and NonMovable. -`protected `[`Handle`](#classscy_1_1uv_1_1Handle)` & operator=(const `[`Handle`](#classscy_1_1uv_1_1Handle)` &) = delete` | - -## Members +### Members + +| Name | Description | +|------|-------------| +| [`Handle`](#group__uv_1gaf854eceb8518bda916774bc3a7564f2e) | | +| [`~Handle`](#group__uv_1ga6e83df44c5a7312440ef4c553249d1e3) | | +| [`init`](#group__uv_1gad883331655d4ca532a9364525f92ffec) | Initialize the handle. | +| [`invoke`](#group__uv_1gad6d9e20a3b932067608a21d513ee1dc2) | Invoke a method on the handle. | +| [`invokeOrThrow`](#group__uv_1gab361483fb3d274d6cd9b57def3201a6a) | Invoke a method on the handle. | +| [`close`](#group__uv_1ga30f5777b4b06de06c7867d5aa0c5fba2) | Close and destroy the handle. | +| [`ref`](#group__uv_1ga66960719f77ad6e4337135ba57aaacc6) | Reference main loop again, once unref'd. | +| [`unref`](#group__uv_1gad08501641ba20a3b51590fdabf708b53) | Unreference the main loop after initialized. | +| [`initialized`](#group__uv_1ga9f00c0db0e29656e77591f93cb78abf8) | Return true if the handle has been initialized. | +| [`active`](#group__uv_1gab0f0149cf3366468c1a4a8939670d70e) | Return true when the handle is active. | +| [`closing`](#group__uv_1ga1702f25d65a416ee7c63b03c594c3efd) | Return true if the handle is closing. | +| [`closed`](#group__uv_1gaaf63956b52958374cf9605351de1613c) | Return true is the handle has been closed. | +| [`error`](#group__uv_1ga7a417c609609e95f6640616c2feca656) | Return the error context if any. | +| [`setError`](#group__uv_1ga28954ab3e3c9cab2d406ee382fd8c9db) | Set the error and triggers callbacks. | +| [`setUVError`](#group__uv_1ga0b13beb047d3b4f1fa1095014305c065) | Set the error and trigger relevant callbacks. This method can be called inside `libuv` callbacks. | +| [`setAndThrowError`](#group__uv_1gae8ed57be72aa225686f67214ca21222c) | Set the error and throw an exception. Should never be called inside `libuv` callbacks. | +| [`throwLastError`](#group__uv_1gaf017bab932c1738f9c0bdf3364f9c5d3) | Throw an exception if the handle is in error state. The error message prefix will be updated if provided. | +| [`loop`](#group__uv_1gaa39643311153b62440c46d9f98d06093) | Return a cast pointer to the managed `libuv` handle. | +| [`self`](#group__uv_1gade08aa52cd372aea4ad24d2f54458886) | Return a pointer to the current or derived instance. | +| [`reset`](#group__uv_1ga2299bfef477dd7edd7e9f4595b39efb5) | Reset the internal handle pointer and container state. | +| [`get`](#group__uv_1gacbb9d1703eabdd2962ae99470a992d67) | Return a typecasted pointer to the managed handle. | +| [`tid`](#group__uv_1ga2528dc53f1af808d3fa0dc05563deb4c) | Return the parent thread ID. | +| [`context`](#group__uv_1gac4b3ca8752769915f33c76924d3bbbd3) | Return the shared handle pointer context. | +| [`assertThread`](#group__uv_1gaa46a6be75e3a975a003a938631eb6ae2) | Assert the call is from the parent event loop thread. | +| [`onError`](#group__uv_1gaffc115aedb14ff27a16613570738753c) | [Error](./doc/api-base.md#structscy_1_1Error) callback. Override to handle errors. The error may be a UV error, or a custom error. | +| [`onClose`](#group__uv_1gad6564419640315d2933cb9d08f948c53) | Close callback. Override to handle closure. | +| [`Handle`](#group__uv_1ga0b418ca2765a4f2b6295ab4226fe0e0e) | NonCopyable and NonMovable. | +| [`operator=`](#group__uv_1gad883c6796c902047357383f64ee0f164) | | +| [`_loop`](#group__uv_1ga158c033f5c162bfd2d3c7e7c4d1d63ba) | | +| [`_context`](#group__uv_1ga052d3d8c37fba9cbb926c019ae0d5c8a) | | +| [`_tid`](#group__uv_1ga4f9cb8a011b402320694bc2cf20970b6) | | +| [`_error`](#group__uv_1ga6c3b4a8509c1e7434ad63f7840faa085) | | + +--- + +#### Handle + +```cpp +inline Handle(uv::Loop * loop) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `loop` | `uv::Loop *` | | + +--- + +#### ~Handle + +```cpp +virtual inline ~Handle() +``` + +--- + +#### init + +```cpp +template inline bool init(F && f, Args &&... args) +``` -#### `public inline Handle(uv::Loop * loop)` - - - - - -#### `public inline virtual ~Handle()` +Initialize the handle. +| Parameter | Type | Description | +|-----------|------|-------------| +| `f` | `F &&` | | +| `args` | `Args &&...` | | +--- +#### invoke +```cpp +template inline bool invoke(F && f, Args &&... args) +``` -#### `public template`
`inline bool init(F && f,Args &&... args)` +Invoke a method on the handle. -Initialize the handle. +| Parameter | Type | Description | +|-----------|------|-------------| +| `f` | `F &&` | | +| `args` | `Args &&...` | | +--- +#### invokeOrThrow -#### `public template`
`inline bool invoke(F && f,Args &&... args)` +```cpp +template inline void invokeOrThrow(const std::string & message, F && f, Args &&... args) +``` Invoke a method on the handle. +An exception will be thrown if the invoked method returns an error. +| Parameter | Type | Description | +|-----------|------|-------------| +| `message` | `const std::string &` | | +| `f` | `F &&` | | +| `args` | `Args &&...` | | -#### `public template`
`inline void invokeOrThrow(const std::string & message,F && f,Args &&... args)` - - - -Invoke a method on the handle. +--- -An exception will be thrown if the invoked method returns an error. +#### close -#### `public inline virtual void close()` +```cpp +virtual inline void close() +``` Close and destroy the handle. +--- +#### ref -#### `public inline void ref()` +```cpp +inline void ref() +``` Reference main loop again, once unref'd. +--- +#### unref -#### `public inline void unref()` +```cpp +inline void unref() +``` Unreference the main loop after initialized. +--- +#### initialized -#### `public inline bool initialized() const` +```cpp +inline bool initialized() const +``` Return true if the handle has been initialized. +--- +#### active -#### `public inline virtual bool active() const` +```cpp +virtual inline bool active() const +``` Return true when the handle is active. +--- +#### closing -#### `public inline virtual bool closing() const` +```cpp +virtual inline bool closing() const +``` Return true if the handle is closing. +--- +#### closed -#### `public inline virtual bool closed() const` +```cpp +virtual inline bool closed() const +``` Return true is the handle has been closed. +--- +#### error -#### `public inline const `[`Error`](#structscy_1_1Error)` & error() const` +```cpp +inline const [scy::Error](./doc/api-base.md#structscy_1_1Error) & error() const +``` Return the error context if any. +--- +#### setError -#### `public inline virtual void setError(const `[`Error`](#structscy_1_1Error)` & err)` +```cpp +virtual inline void setError(const Error & error) +``` Set the error and triggers callbacks. +| Parameter | Type | Description | +|-----------|------|-------------| +| `error` | `const Error &` | | +--- -#### `public inline void setUVError(int errorno,const std::string & prefix)` - +#### setUVError +```cpp +inline void setUVError(int err, std::string prefix) +``` Set the error and trigger relevant callbacks. This method can be called inside `libuv` callbacks. -#### `public inline void setAndThrowError(int errorno,const std::string & prefix)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `err` | `int` | | +| `prefix` | `std::string` | | +--- +#### setAndThrowError + +```cpp +inline void setAndThrowError(int err, std::string prefix) +``` Set the error and throw an exception. Should never be called inside `libuv` callbacks. -#### `public inline void throwLastError(const std::string & prefix)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `err` | `int` | | +| `prefix` | `std::string` | | + +--- +#### throwLastError +```cpp +inline void throwLastError(std::string prefix) +``` Throw an exception if the handle is in error state. The error message prefix will be updated if provided. -#### `public inline uv::Loop * loop() const` +| Parameter | Type | Description | +|-----------|------|-------------| +| `prefix` | `std::string` | | + +--- + +#### loop + +```cpp +inline uv::Loop * loop() const +``` Return a cast pointer to the managed `libuv` handle. +--- +#### self -#### `public inline virtual void * self()` +```cpp +virtual inline void * self() +``` Return a pointer to the current or derived instance. +--- +#### reset -#### `public inline void reset()` +```cpp +inline void reset() +``` Reset the internal handle pointer and container state. +--- +#### get -#### `public template`
`inline `[`Handle`](#classscy_1_1uv_1_1Handle)` * get() const` +```cpp +template inline Handle * get() const +``` Return a typecasted pointer to the managed handle. +--- +#### tid -#### `public inline std::thread::id tid() const` +```cpp +inline std::thread::id tid() const +``` Return the parent thread ID. +--- +#### context -#### `public inline std::shared_ptr< `[`Context`](#structscy_1_1uv_1_1Context)`< T > > context() const` +```cpp +inline std::shared_ptr< Context< T > > context() const +``` Return the shared handle pointer context. +--- +#### assertThread -#### `public inline void assertThread() const` +```cpp +inline void assertThread() const +``` Assert the call is from the parent event loop thread. +--- +#### onError -#### `protected uv::Loop * _loop` +```cpp +virtual inline void onError(const Error & error) +``` +[Error](./doc/api-base.md#structscy_1_1Error) callback. Override to handle errors. The error may be a UV error, or a custom error. +| Parameter | Type | Description | +|-----------|------|-------------| +| `error` | `const Error &` | | +--- +#### onClose -#### `protected std::shared_ptr< `[`Context`](./doc/api-uv.md#structscy_1_1uv_1_1Context)`< T > > _context` +```cpp +virtual inline void onClose() +``` +Close callback. Override to handle closure. +--- +#### Handle +```cpp +Handle(const Handle &) = delete +``` -#### `protected std::thread::id _tid` +NonCopyable and NonMovable. +--- +#### operator= +```cpp +Handle & operator=(const Handle &) = delete +``` +--- -#### `protected `[`Error`](./doc/api-base.md#structscy_1_1Error)` _error` +#### _loop +```cpp +uv::Loop * _loop +``` +--- +#### _context +```cpp +std::shared_ptr< Context< T > > _context +``` -#### `protected inline virtual void onError(const `[`Error`](#structscy_1_1Error)` & error)` +--- +#### _tid +```cpp +std::thread::id _tid = std::this_thread::get_id() +``` -[Error](#structscy_1_1Error) callback. Override to handle errors. The error may be a UV error, or a custom error. +--- -#### `protected inline virtual void onClose()` +#### _error +```cpp +Error _error +``` +## Context -Close callback. Override to handle closure. +> **Defined in:** `handle.h` -#### `protected Handle(const `[`Handle`](#classscy_1_1uv_1_1Handle)` &) = delete` +Shared `libuv` handle context. -NonCopyable and NonMovable. +### Members +| Name | Description | +|------|-------------| +| [`Context`](#group__uv_1ga4e2cc68f5af9da3664ed1d678c7ed152) | | +| [`~Context`](#group__uv_1ga8c43209d5ec23f42726c090d8d3875f6) | | +| [`handle`](#group__uv_1gadb09e2ca5aa8003d12d602ee9e92e5e2) | | +| [`ptr`](#group__uv_1ga5b56a1767069f00d52535b5a12253011) | | +| [`initialized`](#group__uv_1ga7bd98d15327713a202724137f0429196) | | +| [`deleted`](#group__uv_1ga33997488e52b3073a4a0ffbcf97d7900) | | +--- -#### `protected `[`Handle`](#classscy_1_1uv_1_1Handle)` & operator=(const `[`Handle`](#classscy_1_1uv_1_1Handle)` &) = delete` +#### Context +```cpp +inline Context(Handle< T > * h) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `h` | `Handle< T > *` | | +--- +#### ~Context -# struct `scy::uv::BasicEvent` +```cpp +inline ~Context() +``` +--- -Default request callback event. +#### handle +```cpp +Handle< T > * handle = nullptr +``` +--- -## Summary +#### ptr - Members | Descriptions ---------------------------------|--------------------------------------------- -`public int status` | +```cpp +T * ptr = new T +``` -## Members +--- -#### `public int status` +#### initialized +```cpp +bool initialized = false +``` +--- +#### deleted +```cpp +bool deleted = false +``` -# struct `scy::uv::Context` +## BasicEvent +> **Defined in:** `request.h` -Shared `libuv` handle context. +Default request callback event. +### Members +| Name | Description | +|------|-------------| +| [`status`](#group__uv_1gaaf2af795b60beb6649fe7f26f15d374a) | | -## Summary +--- - Members | Descriptions ---------------------------------|--------------------------------------------- -`public `[`Handle`](./doc/api-uv.md#classscy_1_1uv_1_1Handle)`< T > * handle` | -`public T * ptr` | -`public bool initialized` | -`public bool deleted` | -`public inline Context(`[`Handle`](#classscy_1_1uv_1_1Handle)`< T > * h)` | -`public inline ~Context()` | +#### status -## Members +```cpp +int status +``` -#### `public `[`Handle`](./doc/api-uv.md#classscy_1_1uv_1_1Handle)`< T > * handle` +## Request +> **Defined in:** `request.h` +Wrapper class for managing `uv_req_t` variants. +This class povides safe access to the parent handle incase the handle gets destroyed before the request callback returns, and should be used whenever the handle pointer is accessed via the callback. +### Members -#### `public T * ptr` +| Name | Description | +|------|-------------| +| [`Request`](#group__uv_1gad027fbdf614b379deadaf4681c8f3da2) | | +| [`invoke`](#group__uv_1ga182893e356c9cbfd3702b52afef6850b) | | +| [`defaultCallback`](#group__uv_1ga9b5acaa79eb6c49487c376ef6dd897e4) | | +| [`req`](#group__uv_1ga1c2d4993bdd5fa576901b59c677811b3) | | +| [`callback`](#group__uv_1ga93497dface68fec7c3073c4ae1fbb621) | | +| [`invoke`](#structscy_1_1uv_1_1Request_1ga182893e356c9cbfd3702b52afef6850b) | | +--- +#### Request +```cpp +inline Request() +``` +--- -#### `public bool initialized` +#### invoke +```cpp +template inline auto invoke(F && f, Args &&... args) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `f` | `F &&` | | +| `args` | `Args &&...` | | +--- +#### defaultCallback -#### `public bool deleted` +```cpp +static inline void defaultCallback(T * req, int status) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `req` | `T *` | | +| `status` | `int` | | +--- +#### req +```cpp +T req +``` -#### `public inline Context(`[`Handle`](#classscy_1_1uv_1_1Handle)`< T > * h)` +--- +#### callback +```cpp +std::function< void(const E &)> callback +``` +--- +#### invoke -#### `public inline ~Context()` +```cpp +template inline auto invoke(F && f, Args &&... args) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `f` | `F &&` | | +| `args` | `Args &&...` | | +## ConnectReq +> **Extends:** `scy::uv::Request< uv_connect_t >` +> **Defined in:** `request.h` +[Stream](./doc/api-base.md#classscy_1_1Stream) connection request for sockets and pipes. -# struct `scy::uv::Request` +### Members +| Name | Description | +|------|-------------| +| [`ConnectReq`](#group__uv_1gaf3c68ef1149aaf2fbc902776afcaa563) | | +| [`connect`](#group__uv_1ga02fc3c248e3346f95b201bb39455aa21) | | +| [`connect`](#group__uv_1gad07534f80d5b321995ad74f3b5a5abbf) | | +--- +#### ConnectReq -Wrapper class for managing `uv_req_t` variants. +```cpp +inline ConnectReq() +``` -This class povides safe access to the parent handle incase the handle gets destroyed before the request callback returns, and should be used whenever the handle pointer is accessed via the callback. +--- + +#### connect + +```cpp +inline auto connect(uv_tcp_t * handle, const struct sockaddr * addr) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `handle` | `uv_tcp_t *` | | +| `addr` | `const struct sockaddr *` | | + +--- + +#### connect + +```cpp +inline auto connect(uv_pipe_t * handle, const char * name) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `handle` | `uv_pipe_t *` | | +| `name` | `const char *` | | + +## GetAddrInfoEvent + +> **Defined in:** `request.h` + +Get address info request callback event. + +### Members -## Summary +| Name | Description | +|------|-------------| +| [`status`](#group__uv_1gaa3c385f2d6fad57b50d74db35770ea99) | | +| [`addr`](#group__uv_1ga4f414acbeba1d1b61d3c829b5ca1fac5) | | - Members | Descriptions ---------------------------------|--------------------------------------------- -`public T req` | -`public std::function< void(const E &)> callback` | -`public inline Request()` | -`public template`
`inline auto invoke(F && f,Args &&... args)` | +--- -## Members +#### status -#### `public T req` +```cpp +int status +``` +--- +#### addr +```cpp +struct addrinfo * addr +``` +## GetAddrInfoReq -#### `public std::function< void(const E &)> callback` +> **Extends:** `scy::uv::Request< uv_getaddrinfo_t, GetAddrInfoEvent >` +> **Defined in:** `request.h` +DNS resolver request to get the IP address of a hostname. +### Members +| Name | Description | +|------|-------------| +| [`GetAddrInfoReq`](#group__uv_1ga317acd338a40f9d913ce58f10c9ad8d7) | | +| [`resolve`](#group__uv_1ga28197714fd84c1bfbb96cb0ae2377b0a) | | +| [`getAddrInfoCallback`](#group__uv_1gaf879113f50493b9cb303b72e1cdc7c3f) | | +--- -#### `public inline Request()` +#### GetAddrInfoReq +```cpp +inline GetAddrInfoReq() +``` +--- +#### resolve +```cpp +inline auto resolve(const std::string & host, int port, uv::Loop * loop) +``` -#### `public template`
`inline auto invoke(F && f,Args &&... args)` +| Parameter | Type | Description | +|-----------|------|-------------| +| `host` | `const std::string &` | | +| `port` | `int` | | +| `loop` | `uv::Loop *` | | +--- +#### getAddrInfoCallback +```cpp +static inline void getAddrInfoCallback(Request::Type * req, int status, struct addrinfo * res) +``` +| Parameter | Type | Description | +|-----------|------|-------------| +| `req` | `Request::Type *` | | +| `status` | `int` | | +| `res` | `struct addrinfo *` | | diff --git a/doc/api-webrtc.md b/doc/api-webrtc.md deleted file mode 100644 index 707793f0b..000000000 --- a/doc/api-webrtc.md +++ /dev/null @@ -1,1651 +0,0 @@ -# Module `webrtc` - -The `webrtc` module contains WebRTC integrations. - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`namespace `[`scy::wrtc`](#namespacescy_1_1wrtc) | -# namespace `scy::wrtc` - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`class `[`scy::wrtc::DummySetSessionDescriptionObserver`](#classscy_1_1wrtc_1_1DummySetSessionDescriptionObserver) | -`class `[`scy::wrtc::FakeAudioDeviceModule`](#classscy_1_1wrtc_1_1FakeAudioDeviceModule) | This class implements a fake `AudioDeviceModule` that does absolutely nothing. -`class `[`scy::wrtc::FFmpeg420Buffer`](#classscy_1_1wrtc_1_1FFmpeg420Buffer) | -`class `[`scy::wrtc::ImageSequenceRecorder`](#classscy_1_1wrtc_1_1ImageSequenceRecorder) | -`class `[`scy::wrtc::Peer`](#classscy_1_1wrtc_1_1Peer) | -`class `[`scy::wrtc::PeerFactoryContext`](#classscy_1_1wrtc_1_1PeerFactoryContext) | -`class `[`scy::wrtc::PeerManager`](#classscy_1_1wrtc_1_1PeerManager) | -`class `[`scy::wrtc::StreamingPeerConnection`](#classscy_1_1wrtc_1_1StreamingPeerConnection) | -`class `[`scy::wrtc::YuvFrameGenerator`](#classscy_1_1wrtc_1_1YuvFrameGenerator) | -`class `[`scy::wrtc::YuvVideoCapturer`](#classscy_1_1wrtc_1_1YuvVideoCapturer) | -# class `scy::wrtc::DummySetSessionDescriptionObserver` - -``` -class scy::wrtc::DummySetSessionDescriptionObserver - : public SetSessionDescriptionObserver -``` - - - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public virtual void OnSuccess()` | -`public virtual void OnFailure(const std::string & error)` | -`protected inline DummySetSessionDescriptionObserver()` | -`protected inline ~DummySetSessionDescriptionObserver()` | - -## Members - -#### `public virtual void OnSuccess()` - - - - - -#### `public virtual void OnFailure(const std::string & error)` - - - - - -#### `protected inline DummySetSessionDescriptionObserver()` - - - - - -#### `protected inline ~DummySetSessionDescriptionObserver()` - - - - - -# class `scy::wrtc::FakeAudioDeviceModule` - -``` -class scy::wrtc::FakeAudioDeviceModule - : public AudioDeviceModule - : public MessageHandler -``` - -This class implements a fake `AudioDeviceModule` that does absolutely nothing. - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public int64_t TimeUntilNextProcess()` | -`public void Process()` | -`public int32_t ActiveAudioLayer(AudioLayer * audio_layer) const` | -`public ErrorCode LastError() const` | -`public int32_t RegisterEventObserver(webrtc::AudioDeviceObserver * event_callback)` | -`public int32_t RegisterAudioCallback(webrtc::AudioTransport * audio_callback)` | Note: Calling this method from a callback may result in deadlock. -`public int32_t Init()` | -`public int32_t Terminate()` | -`public bool Initialized() const` | -`public int16_t PlayoutDevices()` | -`public int16_t RecordingDevices()` | -`public int32_t PlayoutDeviceName(uint16_t index,char name,char guid)` | -`public int32_t RecordingDeviceName(uint16_t index,char name,char guid)` | -`public int32_t SetPlayoutDevice(uint16_t index)` | -`public int32_t SetPlayoutDevice(WindowsDeviceType device)` | -`public int32_t SetRecordingDevice(uint16_t index)` | -`public int32_t SetRecordingDevice(WindowsDeviceType device)` | -`public int32_t PlayoutIsAvailable(bool * available)` | -`public int32_t InitPlayout()` | -`public bool PlayoutIsInitialized() const` | -`public int32_t RecordingIsAvailable(bool * available)` | -`public int32_t InitRecording()` | -`public bool RecordingIsInitialized() const` | -`public int32_t StartPlayout()` | -`public int32_t StopPlayout()` | -`public bool Playing() const` | -`public int32_t StartRecording()` | -`public int32_t StopRecording()` | -`public bool Recording() const` | -`public int32_t SetAGC(bool enable)` | -`public bool AGC() const` | -`public int32_t SetWaveOutVolume(uint16_t volume_left,uint16_t volume_right)` | -`public int32_t WaveOutVolume(uint16_t * volume_left,uint16_t * volume_right) const` | -`public int32_t InitSpeaker()` | -`public bool SpeakerIsInitialized() const` | -`public int32_t InitMicrophone()` | -`public bool MicrophoneIsInitialized() const` | -`public int32_t SpeakerVolumeIsAvailable(bool * available)` | -`public int32_t SetSpeakerVolume(uint32_t volume)` | -`public int32_t SpeakerVolume(uint32_t * volume) const` | -`public int32_t MaxSpeakerVolume(uint32_t * max_volume) const` | -`public int32_t MinSpeakerVolume(uint32_t * min_volume) const` | -`public int32_t SpeakerVolumeStepSize(uint16_t * step_size) const` | -`public int32_t MicrophoneVolumeIsAvailable(bool * available)` | -`public int32_t SetMicrophoneVolume(uint32_t volume)` | -`public int32_t MicrophoneVolume(uint32_t * volume) const` | -`public int32_t MaxMicrophoneVolume(uint32_t * max_volume) const` | -`public int32_t MinMicrophoneVolume(uint32_t * min_volume) const` | -`public int32_t MicrophoneVolumeStepSize(uint16_t * step_size) const` | -`public int32_t SpeakerMuteIsAvailable(bool * available)` | -`public int32_t SetSpeakerMute(bool enable)` | -`public int32_t SpeakerMute(bool * enabled) const` | -`public int32_t MicrophoneMuteIsAvailable(bool * available)` | -`public int32_t SetMicrophoneMute(bool enable)` | -`public int32_t MicrophoneMute(bool * enabled) const` | -`public int32_t MicrophoneBoostIsAvailable(bool * available)` | -`public int32_t SetMicrophoneBoost(bool enable)` | -`public int32_t MicrophoneBoost(bool * enabled) const` | -`public int32_t StereoPlayoutIsAvailable(bool * available) const` | -`public int32_t SetStereoPlayout(bool enable)` | -`public int32_t StereoPlayout(bool * enabled) const` | -`public int32_t StereoRecordingIsAvailable(bool * available) const` | -`public int32_t SetStereoRecording(bool enable)` | -`public int32_t StereoRecording(bool * enabled) const` | -`public int32_t SetRecordingChannel(const ChannelType channel)` | -`public int32_t RecordingChannel(ChannelType * channel) const` | -`public int32_t SetPlayoutBuffer(const BufferType type,uint16_t size_ms)` | -`public int32_t PlayoutBuffer(BufferType * type,uint16_t * size_ms) const` | -`public int32_t PlayoutDelay(uint16_t * delay_ms) const` | -`public int32_t RecordingDelay(uint16_t * delay_ms) const` | -`public int32_t CPULoad(uint16_t * load) const` | -`public int32_t StartRawOutputFileRecording(const char pcm_file_name_utf8)` | -`public int32_t StopRawOutputFileRecording()` | -`public int32_t StartRawInputFileRecording(const char pcm_file_name_utf8)` | -`public int32_t StopRawInputFileRecording()` | -`public int32_t SetRecordingSampleRate(const uint32_t samples_per_sec)` | -`public int32_t RecordingSampleRate(uint32_t * samples_per_sec) const` | -`public int32_t SetPlayoutSampleRate(const uint32_t samples_per_sec)` | -`public int32_t PlayoutSampleRate(uint32_t * samples_per_sec) const` | -`public int32_t ResetAudioDevice()` | -`public int32_t SetLoudspeakerStatus(bool enable)` | -`public int32_t GetLoudspeakerStatus(bool * enabled) const` | -`public inline bool BuiltInAECIsAvailable() const` | -`public inline int32_t EnableBuiltInAEC(bool enable)` | -`public inline bool BuiltInAGCIsAvailable() const` | -`public inline int32_t EnableBuiltInAGC(bool enable)` | -`public inline bool BuiltInNSIsAvailable() const` | -`public inline int32_t EnableBuiltInNS(bool enable)` | -`public void OnMessage(rtc::Message * msg)` | End of functions inherited from `webrtc::AudioDeviceModule`. -`protected explicit FakeAudioDeviceModule()` | -`protected virtual ~FakeAudioDeviceModule()` | - -## Members - -#### `public int64_t TimeUntilNextProcess()` - - - -Following functions are inherited from `webrtc::AudioDeviceModule`. Only functions called by `[Peer](#classscy_1_1wrtc_1_1Peer)` are implemented, the rest do nothing and return success. If a function is not expected to be called by `[Peer](#classscy_1_1wrtc_1_1Peer)` an assertion is triggered if it is in fact called. - -#### `public void Process()` - - - - - -#### `public int32_t ActiveAudioLayer(AudioLayer * audio_layer) const` - - - - - -#### `public ErrorCode LastError() const` - - - - - -#### `public int32_t RegisterEventObserver(webrtc::AudioDeviceObserver * event_callback)` - - - - - -#### `public int32_t RegisterAudioCallback(webrtc::AudioTransport * audio_callback)` - -Note: Calling this method from a callback may result in deadlock. - - - -#### `public int32_t Init()` - - - - - -#### `public int32_t Terminate()` - - - - - -#### `public bool Initialized() const` - - - - - -#### `public int16_t PlayoutDevices()` - - - - - -#### `public int16_t RecordingDevices()` - - - - - -#### `public int32_t PlayoutDeviceName(uint16_t index,char name,char guid)` - - - - - -#### `public int32_t RecordingDeviceName(uint16_t index,char name,char guid)` - - - - - -#### `public int32_t SetPlayoutDevice(uint16_t index)` - - - - - -#### `public int32_t SetPlayoutDevice(WindowsDeviceType device)` - - - - - -#### `public int32_t SetRecordingDevice(uint16_t index)` - - - - - -#### `public int32_t SetRecordingDevice(WindowsDeviceType device)` - - - - - -#### `public int32_t PlayoutIsAvailable(bool * available)` - - - - - -#### `public int32_t InitPlayout()` - - - - - -#### `public bool PlayoutIsInitialized() const` - - - - - -#### `public int32_t RecordingIsAvailable(bool * available)` - - - - - -#### `public int32_t InitRecording()` - - - - - -#### `public bool RecordingIsInitialized() const` - - - - - -#### `public int32_t StartPlayout()` - - - - - -#### `public int32_t StopPlayout()` - - - - - -#### `public bool Playing() const` - - - - - -#### `public int32_t StartRecording()` - - - - - -#### `public int32_t StopRecording()` - - - - - -#### `public bool Recording() const` - - - - - -#### `public int32_t SetAGC(bool enable)` - - - - - -#### `public bool AGC() const` - - - - - -#### `public int32_t SetWaveOutVolume(uint16_t volume_left,uint16_t volume_right)` - - - - - -#### `public int32_t WaveOutVolume(uint16_t * volume_left,uint16_t * volume_right) const` - - - - - -#### `public int32_t InitSpeaker()` - - - - - -#### `public bool SpeakerIsInitialized() const` - - - - - -#### `public int32_t InitMicrophone()` - - - - - -#### `public bool MicrophoneIsInitialized() const` - - - - - -#### `public int32_t SpeakerVolumeIsAvailable(bool * available)` - - - - - -#### `public int32_t SetSpeakerVolume(uint32_t volume)` - - - - - -#### `public int32_t SpeakerVolume(uint32_t * volume) const` - - - - - -#### `public int32_t MaxSpeakerVolume(uint32_t * max_volume) const` - - - - - -#### `public int32_t MinSpeakerVolume(uint32_t * min_volume) const` - - - - - -#### `public int32_t SpeakerVolumeStepSize(uint16_t * step_size) const` - - - - - -#### `public int32_t MicrophoneVolumeIsAvailable(bool * available)` - - - - - -#### `public int32_t SetMicrophoneVolume(uint32_t volume)` - - - - - -#### `public int32_t MicrophoneVolume(uint32_t * volume) const` - - - - - -#### `public int32_t MaxMicrophoneVolume(uint32_t * max_volume) const` - - - - - -#### `public int32_t MinMicrophoneVolume(uint32_t * min_volume) const` - - - - - -#### `public int32_t MicrophoneVolumeStepSize(uint16_t * step_size) const` - - - - - -#### `public int32_t SpeakerMuteIsAvailable(bool * available)` - - - - - -#### `public int32_t SetSpeakerMute(bool enable)` - - - - - -#### `public int32_t SpeakerMute(bool * enabled) const` - - - - - -#### `public int32_t MicrophoneMuteIsAvailable(bool * available)` - - - - - -#### `public int32_t SetMicrophoneMute(bool enable)` - - - - - -#### `public int32_t MicrophoneMute(bool * enabled) const` - - - - - -#### `public int32_t MicrophoneBoostIsAvailable(bool * available)` - - - - - -#### `public int32_t SetMicrophoneBoost(bool enable)` - - - - - -#### `public int32_t MicrophoneBoost(bool * enabled) const` - - - - - -#### `public int32_t StereoPlayoutIsAvailable(bool * available) const` - - - - - -#### `public int32_t SetStereoPlayout(bool enable)` - - - - - -#### `public int32_t StereoPlayout(bool * enabled) const` - - - - - -#### `public int32_t StereoRecordingIsAvailable(bool * available) const` - - - - - -#### `public int32_t SetStereoRecording(bool enable)` - - - - - -#### `public int32_t StereoRecording(bool * enabled) const` - - - - - -#### `public int32_t SetRecordingChannel(const ChannelType channel)` - - - - - -#### `public int32_t RecordingChannel(ChannelType * channel) const` - - - - - -#### `public int32_t SetPlayoutBuffer(const BufferType type,uint16_t size_ms)` - - - - - -#### `public int32_t PlayoutBuffer(BufferType * type,uint16_t * size_ms) const` - - - - - -#### `public int32_t PlayoutDelay(uint16_t * delay_ms) const` - - - - - -#### `public int32_t RecordingDelay(uint16_t * delay_ms) const` - - - - - -#### `public int32_t CPULoad(uint16_t * load) const` - - - - - -#### `public int32_t StartRawOutputFileRecording(const char pcm_file_name_utf8)` - - - - - -#### `public int32_t StopRawOutputFileRecording()` - - - - - -#### `public int32_t StartRawInputFileRecording(const char pcm_file_name_utf8)` - - - - - -#### `public int32_t StopRawInputFileRecording()` - - - - - -#### `public int32_t SetRecordingSampleRate(const uint32_t samples_per_sec)` - - - - - -#### `public int32_t RecordingSampleRate(uint32_t * samples_per_sec) const` - - - - - -#### `public int32_t SetPlayoutSampleRate(const uint32_t samples_per_sec)` - - - - - -#### `public int32_t PlayoutSampleRate(uint32_t * samples_per_sec) const` - - - - - -#### `public int32_t ResetAudioDevice()` - - - - - -#### `public int32_t SetLoudspeakerStatus(bool enable)` - - - - - -#### `public int32_t GetLoudspeakerStatus(bool * enabled) const` - - - - - -#### `public inline bool BuiltInAECIsAvailable() const` - - - - - -#### `public inline int32_t EnableBuiltInAEC(bool enable)` - - - - - -#### `public inline bool BuiltInAGCIsAvailable() const` - - - - - -#### `public inline int32_t EnableBuiltInAGC(bool enable)` - - - - - -#### `public inline bool BuiltInNSIsAvailable() const` - - - - - -#### `public inline int32_t EnableBuiltInNS(bool enable)` - - - - - -#### `public void OnMessage(rtc::Message * msg)` - -End of functions inherited from `webrtc::AudioDeviceModule`. - -The following function is inherited from `rtc::MessageHandler`. - -#### `protected explicit FakeAudioDeviceModule()` - - - -The constructor is protected because the class needs to be created as a reference counted object (for memory managment reasons). It could be exposed in which case the burden of proper instantiation would be put on the creator of a [FakeAudioDeviceModule](#classscy_1_1wrtc_1_1FakeAudioDeviceModule) instance. To create an instance of this class use the `[Create()](#group__webrtc_1gabca7cbc7b427f7e5dd8c55584f0848da)` API. - -#### `protected virtual ~FakeAudioDeviceModule()` - - - -The destructor is protected because it is reference counted and should not be deleted directly. - -# class `scy::wrtc::FFmpeg420Buffer` - -``` -class scy::wrtc::FFmpeg420Buffer - : public VideoFrameBuffer -``` - - - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public std::vector< uint8_t > ydata` | -`public std::vector< uint8_t > udata` | -`public std::vector< uint8_t > vdata` | -`public FFmpeg420Buffer(int width,int height,const uint8_t * y_plane,int y_stride,const uint8_t * u_plane,int u_stride,const uint8_t * v_plane,int v_stride)` | -`public FFmpeg420Buffer(const `[`av::PlanarVideoPacket`](#structscy_1_1av_1_1PlanarVideoPacket)` & packet)` | -`public int width() const` | -`public int height() const` | -`public const uint8_t * DataY() const` | -`public const uint8_t * DataU() const` | -`public const uint8_t * DataV() const` | -`public int StrideY() const` | -`public int StrideU() const` | -`public int StrideV() const` | -`public void * native_handle() const` | -`public rtc::scoped_refptr< webrtc::VideoFrameBuffer > NativeToI420Buffer()` | - -## Members - -#### `public std::vector< uint8_t > ydata` - - - - - -#### `public std::vector< uint8_t > udata` - - - - - -#### `public std::vector< uint8_t > vdata` - - - - - -#### `public FFmpeg420Buffer(int width,int height,const uint8_t * y_plane,int y_stride,const uint8_t * u_plane,int u_stride,const uint8_t * v_plane,int v_stride)` - - - - - -#### `public FFmpeg420Buffer(const `[`av::PlanarVideoPacket`](#structscy_1_1av_1_1PlanarVideoPacket)` & packet)` - - - - - -#### `public int width() const` - - - - - -#### `public int height() const` - - - - - -#### `public const uint8_t * DataY() const` - - - - - -#### `public const uint8_t * DataU() const` - - - - - -#### `public const uint8_t * DataV() const` - - - - - -#### `public int StrideY() const` - - - - - -#### `public int StrideU() const` - - - - - -#### `public int StrideV() const` - - - - - -#### `public void * native_handle() const` - - - - - -#### `public rtc::scoped_refptr< webrtc::VideoFrameBuffer > NativeToI420Buffer()` - - - - - -# class `scy::wrtc::ImageSequenceRecorder` - -``` -class scy::wrtc::ImageSequenceRecorder - : public rtc::VideoSinkInterface< cricket::VideoFrame > -``` - - - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public ImageSequenceRecorder(webrtc::VideoTrackInterface * track_to_render,const std::string & basename)` | -`public virtual ~ImageSequenceRecorder()` | -`public std::string getNextFilename()` | -`public void OnFrame(const cricket::VideoFrame & frame)` | VideoSinkInterface implementation. -`protected rtc::scoped_refptr< webrtc::VideoTrackInterface > _renderedTrack` | -`protected const std::string _basename` | -`protected size_t _count` | -`protected int _width` | -`protected int _height` | -`protected av::VideoEncoder _encoder` | -`protected AVFrame * _avframe` | - -## Members - -#### `public ImageSequenceRecorder(webrtc::VideoTrackInterface * track_to_render,const std::string & basename)` - - - - - -#### `public virtual ~ImageSequenceRecorder()` - - - - - -#### `public std::string getNextFilename()` - - - - - -#### `public void OnFrame(const cricket::VideoFrame & frame)` - -VideoSinkInterface implementation. - - - -#### `protected rtc::scoped_refptr< webrtc::VideoTrackInterface > _renderedTrack` - - - - - -#### `protected const std::string _basename` - - - - - -#### `protected size_t _count` - - - - - -#### `protected int _width` - - - - - -#### `protected int _height` - - - - - -#### `protected av::VideoEncoder _encoder` - - - - - -#### `protected AVFrame * _avframe` - - - - - -# class `scy::wrtc::Peer` - -``` -class scy::wrtc::Peer - : public PeerConnectionObserver - : public CreateSessionDescriptionObserver -``` - - - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public Peer(`[`PeerManager`](#classscy_1_1wrtc_1_1PeerManager)` * manager,`[`PeerFactoryContext`](#classscy_1_1wrtc_1_1PeerFactoryContext)` * context,const std::string & peerid,const std::string & token,`[`Mode`](#group__webrtc_1ga0a5220c6e568323fb5dfb9769e016a20)` mode)` | -`public virtual ~Peer()` | -`public virtual rtc::scoped_refptr< webrtc::MediaStreamInterface > createMediaStream()` | -`public virtual void createConnection()` | -`public virtual void closeConnection()` | Close the peer connection. -`public virtual void createOffer()` | -`public virtual void recvSDP(const std::string & type,const std::string & sdp)` | Receive a remote offer or answer. -`public virtual void recvCandidate(const std::string & mid,int mlineindex,const std::string & sdp)` | Receive a remote candidate. -`public void setPeerFactory(rtc::scoped_refptr< webrtc::PeerConnectionFactoryInterface > factory)` | -`public void setPortRange(int minPort,int maxPort)` | -`public std::string peerid() const` | -`public std::string token() const` | -`public webrtc::FakeConstraints & constraints()` | -`public webrtc::PeerConnectionFactoryInterface * factory() const` | -`public rtc::scoped_refptr< webrtc::PeerConnectionInterface > peerConnection() const` | -`public rtc::scoped_refptr< webrtc::MediaStreamInterface > stream() const` | -`protected `[`PeerManager`](./doc/api-webrtc.md#classscy_1_1wrtc_1_1PeerManager)` * _manager` | -`protected `[`PeerFactoryContext`](./doc/api-webrtc.md#classscy_1_1wrtc_1_1PeerFactoryContext)` * _context` | -`protected std::string _peerid` | -`protected std::string _token` | -`protected `[`Mode`](#group__webrtc_1ga0a5220c6e568323fb5dfb9769e016a20)` _mode` | -`protected webrtc::PeerConnectionInterface::RTCConfiguration _config` | -`protected webrtc::FakeConstraints _constraints` | -`protected rtc::scoped_refptr< webrtc::PeerConnectionInterface > _peerConnection` | -`protected rtc::scoped_refptr< webrtc::MediaStreamInterface > _stream` | -`protected std::unique_ptr< cricket::BasicPortAllocator > _portAllocator` | -`protected virtual void OnAddStream(webrtc::MediaStreamInterface * stream)` | inherited from PeerConnectionObserver -`protected virtual void OnRemoveStream(webrtc::MediaStreamInterface * stream)` | -`protected virtual void OnAddStream(rtc::scoped_refptr< webrtc::MediaStreamInterface > stream)` | since 7f0676 -`protected virtual void OnRemoveStream(rtc::scoped_refptr< webrtc::MediaStreamInterface > stream)` | since 7f0676 -`protected virtual void OnDataChannel(rtc::scoped_refptr< webrtc::DataChannelInterface > stream)` | since 7f0676 -`protected virtual void OnIceCandidate(const webrtc::IceCandidateInterface * candidate)` | -`protected virtual void OnSignalingChange(webrtc::PeerConnectionInterface::SignalingState new_state)` | -`protected virtual void OnIceConnectionChange(webrtc::PeerConnectionInterface::IceConnectionState new_state)` | -`protected virtual void OnIceGatheringChange(webrtc::PeerConnectionInterface::IceGatheringState new_state)` | -`protected virtual void OnRenegotiationNeeded()` | -`protected virtual void OnSuccess(webrtc::SessionDescriptionInterface * desc)` | inherited from CreateSessionDescriptionObserver -`protected virtual void OnFailure(const std::string & error)` | -`protected inline virtual int AddRef() const` | -`protected inline virtual int Release() const` | - -## Members - -#### `public Peer(`[`PeerManager`](#classscy_1_1wrtc_1_1PeerManager)` * manager,`[`PeerFactoryContext`](#classscy_1_1wrtc_1_1PeerFactoryContext)` * context,const std::string & peerid,const std::string & token,`[`Mode`](#group__webrtc_1ga0a5220c6e568323fb5dfb9769e016a20)` mode)` - - - - - -#### `public virtual ~Peer()` - - - - - -#### `public virtual rtc::scoped_refptr< webrtc::MediaStreamInterface > createMediaStream()` - - - -Create the local media stream. Only necessary when we are creating the offer. - -#### `public virtual void createConnection()` - - - -Create the peer connection once configuration, constraints and streams have been created. - -#### `public virtual void closeConnection()` - -Close the peer connection. - - - -#### `public virtual void createOffer()` - - - -Create the offer SDP tos end to the peer. No offer should be received after creating the offer. A call to `recvSDP` with answer is expected in order to initiate the session. - -#### `public virtual void recvSDP(const std::string & type,const std::string & sdp)` - -Receive a remote offer or answer. - - - -#### `public virtual void recvCandidate(const std::string & mid,int mlineindex,const std::string & sdp)` - -Receive a remote candidate. - - - -#### `public void setPeerFactory(rtc::scoped_refptr< webrtc::PeerConnectionFactoryInterface > factory)` - - - -Set a custom PeerFactory object. Must be set before any streams are initiated. - -#### `public void setPortRange(int minPort,int maxPort)` - - - -Set the port range for WebRTC connections. Must be done before the connection is initiated. - -#### `public std::string peerid() const` - - - - - -#### `public std::string token() const` - - - - - -#### `public webrtc::FakeConstraints & constraints()` - - - - - -#### `public webrtc::PeerConnectionFactoryInterface * factory() const` - - - - - -#### `public rtc::scoped_refptr< webrtc::PeerConnectionInterface > peerConnection() const` - - - - - -#### `public rtc::scoped_refptr< webrtc::MediaStreamInterface > stream() const` - - - - - -#### `protected `[`PeerManager`](./doc/api-webrtc.md#classscy_1_1wrtc_1_1PeerManager)` * _manager` - - - - - -#### `protected `[`PeerFactoryContext`](./doc/api-webrtc.md#classscy_1_1wrtc_1_1PeerFactoryContext)` * _context` - - - - - -#### `protected std::string _peerid` - - - - - -#### `protected std::string _token` - - - - - -#### `protected `[`Mode`](#group__webrtc_1ga0a5220c6e568323fb5dfb9769e016a20)` _mode` - - - - - -#### `protected webrtc::PeerConnectionInterface::RTCConfiguration _config` - - - - - -#### `protected webrtc::FakeConstraints _constraints` - - - - - -#### `protected rtc::scoped_refptr< webrtc::PeerConnectionInterface > _peerConnection` - - - - - -#### `protected rtc::scoped_refptr< webrtc::MediaStreamInterface > _stream` - - - - - -#### `protected std::unique_ptr< cricket::BasicPortAllocator > _portAllocator` - - - - - -#### `protected virtual void OnAddStream(webrtc::MediaStreamInterface * stream)` - -inherited from PeerConnectionObserver - -> Deprecated: - -#### `protected virtual void OnRemoveStream(webrtc::MediaStreamInterface * stream)` - - - -> Deprecated: - -#### `protected virtual void OnAddStream(rtc::scoped_refptr< webrtc::MediaStreamInterface > stream)` - -since 7f0676 - - - -#### `protected virtual void OnRemoveStream(rtc::scoped_refptr< webrtc::MediaStreamInterface > stream)` - -since 7f0676 - - - -#### `protected virtual void OnDataChannel(rtc::scoped_refptr< webrtc::DataChannelInterface > stream)` - -since 7f0676 - - - -#### `protected virtual void OnIceCandidate(const webrtc::IceCandidateInterface * candidate)` - - - - - -#### `protected virtual void OnSignalingChange(webrtc::PeerConnectionInterface::SignalingState new_state)` - - - - - -#### `protected virtual void OnIceConnectionChange(webrtc::PeerConnectionInterface::IceConnectionState new_state)` - - - - - -#### `protected virtual void OnIceGatheringChange(webrtc::PeerConnectionInterface::IceGatheringState new_state)` - - - - - -#### `protected virtual void OnRenegotiationNeeded()` - - - - - -#### `protected virtual void OnSuccess(webrtc::SessionDescriptionInterface * desc)` - -inherited from CreateSessionDescriptionObserver - - - -#### `protected virtual void OnFailure(const std::string & error)` - - - - - -#### `protected inline virtual int AddRef() const` - - - - - -#### `protected inline virtual int Release() const` - - - - - -# class `scy::wrtc::PeerFactoryContext` - - - - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public std::unique_ptr< rtc::Thread > networkThread` | -`public std::unique_ptr< rtc::Thread > workerThread` | -`public std::unique_ptr< rtc::NetworkManager > networkManager` | -`public std::unique_ptr< rtc::PacketSocketFactory > socketFactory` | -`public rtc::scoped_refptr< webrtc::PeerConnectionFactoryInterface > factory` | -`public PeerFactoryContext(webrtc::AudioDeviceModule * default_adm,cricket::WebRtcVideoEncoderFactory * video_encoder_factory,cricket::WebRtcVideoDecoderFactory * video_decoder_factory,rtc::scoped_refptr< webrtc::AudioEncoderFactory > audio_encoder_factory,rtc::scoped_refptr< webrtc::AudioDecoderFactory > audio_decoder_factory)` | -`public void initCustomNetworkManager()` | - -## Members - -#### `public std::unique_ptr< rtc::Thread > networkThread` - - - - - -#### `public std::unique_ptr< rtc::Thread > workerThread` - - - - - -#### `public std::unique_ptr< rtc::NetworkManager > networkManager` - - - - - -#### `public std::unique_ptr< rtc::PacketSocketFactory > socketFactory` - - - - - -#### `public rtc::scoped_refptr< webrtc::PeerConnectionFactoryInterface > factory` - - - - - -#### `public PeerFactoryContext(webrtc::AudioDeviceModule * default_adm,cricket::WebRtcVideoEncoderFactory * video_encoder_factory,cricket::WebRtcVideoDecoderFactory * video_decoder_factory,rtc::scoped_refptr< webrtc::AudioEncoderFactory > audio_encoder_factory,rtc::scoped_refptr< webrtc::AudioDecoderFactory > audio_decoder_factory)` - - - - - -#### `public void initCustomNetworkManager()` - - - - - -# class `scy::wrtc::PeerManager` - -``` -class scy::wrtc::PeerManager - : public scy::PointerCollection< std::string, Peer > -``` - - - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public PeerManager()` | -`public virtual ~PeerManager()` | -`public virtual void sendSDP(`[`Peer`](#classscy_1_1wrtc_1_1Peer)` * conn,const std::string & type,const std::string & sdp)` | -`public virtual void sendCandidate(`[`Peer`](#classscy_1_1wrtc_1_1Peer)` * conn,const std::string & mid,int mlineindex,const std::string & sdp)` | -`public virtual void recvSDP(const std::string & token,const json::value & data)` | -`public virtual void recvCandidate(const std::string & token,const json::value & data)` | -`public virtual void onAddRemoteStream(`[`Peer`](#classscy_1_1wrtc_1_1Peer)` * conn,webrtc::MediaStreamInterface * stream)` | -`public virtual void onRemoveRemoteStream(`[`Peer`](#classscy_1_1wrtc_1_1Peer)` * conn,webrtc::MediaStreamInterface * stream)` | -`public virtual void onStable(`[`Peer`](#classscy_1_1wrtc_1_1Peer)` * conn)` | -`public virtual void onClosed(`[`Peer`](#classscy_1_1wrtc_1_1Peer)` * conn)` | -`public virtual void onFailure(`[`Peer`](#classscy_1_1wrtc_1_1Peer)` * conn,const std::string & error)` | - -## Members - -#### `public PeerManager()` - - - - - -#### `public virtual ~PeerManager()` - - - - - -#### `public virtual void sendSDP(`[`Peer`](#classscy_1_1wrtc_1_1Peer)` * conn,const std::string & type,const std::string & sdp)` - - - - - -#### `public virtual void sendCandidate(`[`Peer`](#classscy_1_1wrtc_1_1Peer)` * conn,const std::string & mid,int mlineindex,const std::string & sdp)` - - - - - -#### `public virtual void recvSDP(const std::string & token,const json::value & data)` - - - - - -#### `public virtual void recvCandidate(const std::string & token,const json::value & data)` - - - - - -#### `public virtual void onAddRemoteStream(`[`Peer`](#classscy_1_1wrtc_1_1Peer)` * conn,webrtc::MediaStreamInterface * stream)` - - - - - -#### `public virtual void onRemoveRemoteStream(`[`Peer`](#classscy_1_1wrtc_1_1Peer)` * conn,webrtc::MediaStreamInterface * stream)` - - - - - -#### `public virtual void onStable(`[`Peer`](#classscy_1_1wrtc_1_1Peer)` * conn)` - - - - - -#### `public virtual void onClosed(`[`Peer`](#classscy_1_1wrtc_1_1Peer)` * conn)` - - - - - -#### `public virtual void onFailure(`[`Peer`](#classscy_1_1wrtc_1_1Peer)` * conn,const std::string & error)` - - - - - -# class `scy::wrtc::StreamingPeerConnection` - -``` -class scy::wrtc::StreamingPeerConnection - : public PeerConnection -``` - - - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public StreamingPeerConnection(PeerConnectionManager * manager,const std::string & peerid,const std::string & token,const std::string & file)` | Create the streaming peer connection. -`public virtual ~StreamingPeerConnection()` | -`public virtual rtc::scoped_refptr< webrtc::MediaStreamInterface > createMediaStream()` | -`public virtual void OnIcePeerChange(webrtc::PeerConnectionInterface::IcePeerState new_state)` | -`protected std::string _file` | -`protected MultiplexMediaCapturer _capturer` | -`protected std::unique_ptr< rtc::Thread > _networkThread` | -`protected std::unique_ptr< rtc::Thread > _workerThread` | - -## Members - -#### `public StreamingPeerConnection(PeerConnectionManager * manager,const std::string & peerid,const std::string & token,const std::string & file)` - -Create the streaming peer connection. - - - -#### `public virtual ~StreamingPeerConnection()` - - - - - -#### `public virtual rtc::scoped_refptr< webrtc::MediaStreamInterface > createMediaStream()` - - - - - -#### `public virtual void OnIcePeerChange(webrtc::PeerConnectionInterface::IcePeerState new_state)` - - - - - -#### `protected std::string _file` - - - - - -#### `protected MultiplexMediaCapturer _capturer` - - - - - -#### `protected std::unique_ptr< rtc::Thread > _networkThread` - - - - - -#### `protected std::unique_ptr< rtc::Thread > _workerThread` - - - - - -# class `scy::wrtc::YuvFrameGenerator` - - - - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public YuvFrameGenerator(int width,int height,bool enable_barcode)` | -`public ~YuvFrameGenerator()` | -`public void GenerateNextFrame(int32_t barcode_value)` | -`public void CopyInterleavedData(uint8_t * frame_buffer)` | -`public const uint8_t * DataY() const` | -`public const uint8_t * DataU() const` | -`public const uint8_t * DataV() const` | -`public inline int GetFrameSize()` | -`public inline int GetHeight()` | -`public inline int GetWidth()` | -`public void GetBarcodeBounds(int * top,int * left,int * width,int * height)` | - -## Members - -#### `public YuvFrameGenerator(int width,int height,bool enable_barcode)` - - - - - -#### `public ~YuvFrameGenerator()` - - - - - -#### `public void GenerateNextFrame(int32_t barcode_value)` - - - - - -#### `public void CopyInterleavedData(uint8_t * frame_buffer)` - - - - - -#### `public const uint8_t * DataY() const` - - - - - -#### `public const uint8_t * DataU() const` - - - - - -#### `public const uint8_t * DataV() const` - - - - - -#### `public inline int GetFrameSize()` - - - - - -#### `public inline int GetHeight()` - - - - - -#### `public inline int GetWidth()` - - - - - -#### `public void GetBarcodeBounds(int * top,int * left,int * width,int * height)` - - - - - -# class `scy::wrtc::YuvVideoCapturer` - -``` -class scy::wrtc::YuvVideoCapturer - : public VideoCapturer - : public Thread -``` - - - - - -## Summary - - Members | Descriptions ---------------------------------|--------------------------------------------- -`public inline YuvVideoCapturer()` | -`public inline virtual ~YuvVideoCapturer()` | -`public inline void SignalFrameCapturedOnStartThread()` | -`public inline void Run()` | -`public inline virtual cricket::CaptureState Start(const cricket::VideoFormat & format)` | -`public inline virtual void Stop()` | -`public inline virtual bool GetPreferredFourccs(std::vector< uint32_t > * fourccs)` | -`public inline virtual bool IsScreencast() const` | -`public inline virtual bool IsRunning()` | - -## Members - -#### `public inline YuvVideoCapturer()` - - - - - -#### `public inline virtual ~YuvVideoCapturer()` - - - - - -#### `public inline void SignalFrameCapturedOnStartThread()` - - - - - -#### `public inline void Run()` - - - - - -#### `public inline virtual cricket::CaptureState Start(const cricket::VideoFormat & format)` - - - - - -#### `public inline virtual void Stop()` - - - - - -#### `public inline virtual bool GetPreferredFourccs(std::vector< uint32_t > * fourccs)` - - - - - -#### `public inline virtual bool IsScreencast() const` - - - - - -#### `public inline virtual bool IsRunning()` - - - - - diff --git a/doc/assets/doxygen.svg b/doc/assets/doxygen.svg deleted file mode 100644 index d9d8541c6..000000000 --- a/doc/assets/doxygen.svg +++ /dev/null @@ -1 +0,0 @@ -codecodedocumenteddocumented \ No newline at end of file diff --git a/doc/book.json b/doc/book.json deleted file mode 100644 index d28bac6cc..000000000 --- a/doc/book.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "gitbook": "3.2.x", - "title": "LibSourcey", - "styles": { - "website": "styles/website.css" - } -} diff --git a/doc/examples.md b/doc/examples.md index 5dbbcd40c..1e626e1b5 100644 --- a/doc/examples.md +++ b/doc/examples.md @@ -2,29 +2,32 @@ There are plenty of examples available in the `samples` and `tests` folder of each module for you to cut your teeth on. -* [WebRTC Recorder](https://github.com/sourcey/libsourcey/tree/master/src/webrtc/samples/webrtcrecorder) - The WebRTC native multiplex recorder lets you record live WebRTC streams from the browser on the server side. - -* [WebRTC Streamer](https://github.com/sourcey/libsourcey/tree/master/src/webrtc/samples/webrtcstreamer) - The WebRTC Streamer lets you stream any video source ie. webcam and microphone or video file from the server to the browser. - * [Media Server](https://github.com/sourcey/libsourcey/tree/master/src/av/samples/mediaserver) - Check out the `mediaserver` sample in the `av` module for how to stream media over HTTP, WebSocket and TURN protocols. You will need to compile LibSourcey with FFmpeg enabled to use it. + Stream media over HTTP, WebSocket and TURN protocols. Requires FFmpeg. * [Device Recorder](https://github.com/sourcey/libsourcey/tree/master/src/av/samples/devicerecorder) - The `devicerecorder` sample lets you multiplex record live webcam and microphone capture streams in any video format supported by FFmpeg. Remember, you will need to compile LibSourcey with FFmpeg enabled to use it. + Multiplex record live webcam and microphone capture streams in any video format supported by FFmpeg. * [Device Enumerator](https://github.com/sourcey/libsourcey/tree/master/src/av/samples/deviceenumerator) - The `deviceenumerator` sample outputs all the available input and output devices on the system. + Outputs all the available input and output devices on the system. + +* [Video Socket](https://github.com/sourcey/libsourcey/tree/master/src/av/samples/videosocket) + Stream video over a socket connection. + +* [Waveform Output](https://github.com/sourcey/libsourcey/tree/master/src/av/samples/waveformoutput) + Audio waveform output sample. * [HTTP Echo Server](https://github.com/sourcey/libsourcey/tree/master/src/http/samples/httpechoserver) - Where would we be without the good ol' HTTP echo server? Works for HTTP, HTTPS and WebSocket connections. + HTTP echo server that works with HTTP, HTTPS and WebSocket connections. -* [Socket Echo Server](https://github.com/sourcey/libsourcey/tree/master/src/http/samples/httpechoserver) - The socket echo server echoes raw data packets over TCP and UPD socket connections. +* [Socket Echo Server](https://github.com/sourcey/libsourcey/tree/master/src/net/samples/echoserver) + Echoes raw data packets over TCP and UDP socket connections. -* [Package Manager](https://github.com/sourcey/pacm/tree/master/apps/pacmconsole) - Take a look at `pacm` for a redistributable C++ package manager built on LibSourcey, and specifically the `pacmconsole` application. http://sourcey.com/pacm/ +* [Symple Console](https://github.com/sourcey/libsourcey/tree/master/src/symple/samples/sympleconsole) + Console client for the Symple realtime messaging protocol. * [TURN Server](https://github.com/sourcey/libsourcey/tree/master/src/turn/samples/turnserver) - The TURN server provides a functional RFC 5766 server implementation. + A functional RFC 5766 TURN server implementation. + +* [TURN Media Provider](https://github.com/sourcey/libsourcey/tree/master/src/turn/samples/turnmediaprovider) + Media provider for the TURN relay server. diff --git a/doc/getting-started.md b/doc/getting-started.md index 3ebfc3a26..76519b787 100644 --- a/doc/getting-started.md +++ b/doc/getting-started.md @@ -1,71 +1,63 @@ # Getting Started -First and foremost, welcome to LibSourcey — it's great to have you along for the ride! We've done our best to make the docs as clear as possible to save you time, so if something's missing or changed, or newer versions are available then please let us know or submit a [Push Request](/README.md#contributing) with your updates. +Welcome to LibSourcey! If something's missing or outdated, please submit a [pull request](../README.md#contributing) with your updates. -Before going any further please follow the [installation guide](/installation.md) to compiled and install LibSourcey on your system. +Before going any further please follow the [installation guide](installation.md) to compile and install LibSourcey on your system. -Once LibSourcey is installed you a number of choices how you include the libraries in your own project: +Once LibSourcey is installed you have a number of choices for how to include the libraries in your own project: ### 1) Using `pkg-config` (Linux only) -Using `pkg-config` is the simplest and easiest method to include LibSourcey libraries and headers in your project. After running `make install` the `pkg-config` script is located in `/usr/local/lib/pkgconfig/libsourcey.pc` by default. +After running `make install` the `pkg-config` script is located in `/usr/local/lib/pkgconfig/libsourcey.pc` by default. -Using the default structure you can include Libsourcey in your project like so (using `gcc`): - -~~~ bash -gcc -o test test.cpp $(pkg-config --libs --cflags libsourcey) -~~~ +```bash +g++ -o test test.cpp $(pkg-config --libs --cflags libsourcey) +``` ### 2) Using CMake -If you're already using CMake in your own project then including LibSourcey with CMake is highly recommended. Once you have built and installed LibSourcey you can include all the libraries and headers by adding the following lines to your `CMakeLists.txt`: +If you're already using CMake then including LibSourcey with CMake is recommended. Once you have built and installed LibSourcey you can include all the libraries and headers by adding the following lines to your `CMakeLists.txt`: -~~~ +```cmake # The LibSourcey root directory must be set set(LibSourcey_ROOT_DIR "" CACHE STRING "Where is the LibSourcey root directory located?") -find_package_handle_standard_args(${module} DEFAULT_MSG LibSourcey_ROOT_DIR) # Tell CMake where to locate the LibSourcey .cmake files set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${LibSourcey_ROOT_DIR}/cmake) set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} ${LibSourcey_ROOT_DIR}/cmake) -# Include LibSourcey with specified modules (example: uv base net crypto http) -find_package(LibSourcey COMPONENTS uv base net crypto http REQUIRED) -~~~ +# Include LibSourcey with specified modules (example: base net crypto http) +find_package(LibSourcey COMPONENTS base net crypto http REQUIRED) +``` ### 3) Extending the build system -The third option is to include the LibSourcey CMake build system in your own project. When you choose this option you will be building LibSourcey modules along side your own project as dependencies, and will also inherit the LibSorucey build system (which is pretty awesome). [See here](/installation.md#cmake-build-options) for a complete list of build options. +The third option is to include the LibSourcey CMake build system in your own project. This method builds LibSourcey modules alongside your own project as dependencies. [See here](installation.md#cmake-build-options) for a complete list of build options. -This method is only recommended for advanced users and if you want your project to be tightly coupled with LibSourcey. +This method is only recommended for advanced users who want their project tightly coupled with LibSourcey. -Below is an example of a full `CMakeLists.txt` file that you can use to include LibSourcey in your build tree: +Below is an example `CMakeLists.txt`: -~~~ -cmake_minimum_required(VERSION 2.8.10) +```cmake +cmake_minimum_required(VERSION 3.14) project(exampleapp) -# Set the source directory and search locations as required for your project +# Set the source directory set(sourcedir src) -set(sourcefiles ${sourcedir}/*.cpp) -set(headerfiles ${sourcedir}/*.h) # Include LibSourcey include("../libsourcey/LibSourcey.cmake") -include_directories(${Libourcey_INCLUDE_DIRS}) -link_libraries(${LibSourcey_LIBRARIES}) include_directories(${sourcedir} ${LibSourcey_INCLUDE_DIRS}) +link_libraries(${LibSourcey_LIBRARIES}) -# Glob your sources and headers -# Be sure to modify the search paths according to your project structure -file(GLOB_RECURSE sources ${sourcefiles}) -file(GLOB_RECURSE headers ${headerfiles}) +file(GLOB_RECURSE sources ${sourcedir}/*.cpp) +file(GLOB_RECURSE headers ${sourcedir}/*.h) add_executable(exampleapp ${sources} ${headers}) install(TARGETS exampleapp) -~~~ +``` ## Next Steps -Once LibSourcey is included in your project you're ready to start using the API. Check out the [code examples](/examples.md), and [API reference](/api-base.md) to start cutting code. +Once LibSourcey is included in your project you're ready to start using the API. Check out the [code examples](examples.md) and [API reference](api-base.md) to start cutting code. diff --git a/doc/installation-linux.md b/doc/installation-linux.md index ba19b4dff..815f6706c 100644 --- a/doc/installation-linux.md +++ b/doc/installation-linux.md @@ -1,110 +1,76 @@ # Installing on Linux -This guide is written for Ubuntu 14.04, although installation should be fairly portable across most flavors of Linux. - ## Install Dependencies -Before doing anything make sure you have the core dependencies installed: +Install the core dependencies: -~~~ bash +```bash sudo apt-get update sudo apt-get install -y build-essential pkg-config git cmake openssl libssl-dev -~~~ - - - - +``` ### Install FFmpeg (optional) FFmpeg is an optional but recommended dependency that's required to make use of LibSourcey's media encoding capabilities. -Most versions on Linux have FFmpeg development libraries that you can install directly from the package manager. If you're on a newer version of Ubuntu (>= 15.04) then you can install the required libraries as follows: +On most Linux distributions you can install FFmpeg development libraries from the package manager: + +```bash +# Ubuntu/Debian +sudo apt-get install -y libavcodec-dev libavdevice-dev libavfilter-dev libavformat-dev libswresample-dev libswscale-dev libpostproc-dev -~~~ bash -sudo apt-get install --yes libavcodec-ffmpeg-dev libavdevice-ffmpeg-dev libavfilter-ffmpeg-dev libavformat-ffmpeg-dev libswresample-ffmpeg-dev libpostproc-ffmpeg-dev -~~~ +# Fedora/RHEL +sudo dnf install ffmpeg-devel +``` -Otherwise if you want to compile FFmpeg yourself you can follow the [official guide for installing FFmpeg](http://trac.ffmpeg.org/wiki/CompilationGuide) that works out of the box with LibSourcey without configuration. +Alternatively you can compile FFmpeg from source following the [official guide](https://trac.ffmpeg.org/wiki/CompilationGuide). -If FFmpeg is installed in a non-standard location you can enable expose it to the CMake build system like so: +If FFmpeg is installed in a non-standard location you can expose it to the CMake build system like so: -~~~ bash +```bash cmake .. -DWITH_FFMPEG=ON -DFFMPEG_ROOT_DIR= -~~~ +``` - - -### Install WebRTC (optional) - - +Note: if you're compiling FFmpeg yourself (as above), build OpenCV with `WITH_FFMPEG=OFF` to avoid conflicting FFmpeg libraries on your system. -The easiest way to get started with WebRTC is to download the precompiled static libraries and headers available here: https://sourcey.com/precompiled-webrtc-libraries/ +Enable OpenCV in the LibSourcey build: -Alternatively if you want to compile WebRTC yourself you can use our automated build scripts, which can be found here: https://github.com/sourcey/webrtc-builds - -~~~ bash -cd ~/tmp -git clone git@github.com:sourcey/webrtc-builds.git -cd webrtc-builds -./build.sh -~~~ - -Once installed enable and add the WebRTC root directory to your build command like so: - -~~~ bash -cmake .. -DWITH_WEBRTC=ON -DWEBRTC_ROOT_DIR= -~~~ +```bash +cmake .. -DWITH_OPENCV=ON +``` ### Install LibSourcey -~~~ bash -cd ~/tmp +```bash git clone https://github.com/sourcey/libsourcey.git cd libsourcey mkdir build cd build -cmake .. -DCMAKE_BUILD_TYPE=RELEASE # extra cmake commands here, see below for a full list... +cmake .. -DCMAKE_BUILD_TYPE=RELEASE # extra cmake commands here... make sudo make install -~~~ - -All done! +``` -[See here](/installation.md#cmake-build-options) for a complete list of build options. +[See here](installation.md#cmake-build-options) for a complete list of build options. diff --git a/doc/installation-osx.md b/doc/installation-osx.md index be7ae4b1f..5ebe7955f 100644 --- a/doc/installation-osx.md +++ b/doc/installation-osx.md @@ -1,58 +1,35 @@ -# Installing on Apple (OS X) +# Installing on macOS -This guide is for written for Mac users using [Homebrew](http://brew.sh). +This guide uses [Homebrew](https://brew.sh). Works on both Intel and Apple Silicon Macs. ## Install Dependencies - +```bash +brew install cmake openssl +``` -~~~ bash -# OpenSSL: -brew install openssl -brew link --force openssl +CMake should find OpenSSL automatically. If not, set the path: -# CMake: -brew install cmake -~~~ +```bash +cmake .. -DOPENSSL_ROOT_DIR=$(brew --prefix openssl) +``` -Please see the [Linux instructions](/installation-linux.md) for other optional dependencies, such as FFmpeg and WebRTC. +For optional dependencies like FFmpeg, see the [Linux instructions](installation-linux.md#install-ffmpeg-optional) - the same `cmake` flags apply. ## Install LibSourcey -~~~ bash -cd ~/tmp +```bash git clone https://github.com/sourcey/libsourcey.git cd libsourcey mkdir build cd build -cmake .. -D CMAKE_BUILD_TYPE=RELEASE # extra cmake commands here, see below for a full list... +cmake .. -DCMAKE_BUILD_TYPE=RELEASE # extra cmake commands here... make sudo make install -~~~ - - - - - - - - +``` ## Compile with Xcode -* Generate Xcode project using CMake, as described above. -* Launch Xcode, locate and open `libsourcey.xcodeproj`. Select "Debug", build the BUILD_ALL target (Cmd-B), select "Release" and build it too. +* Generate an Xcode project: `cmake .. -G Xcode` +* Launch Xcode, open `libsourcey.xcodeproj` +* Select "Debug", build (Cmd-B), then select "Release" and build again diff --git a/doc/installation-windows.md b/doc/installation-windows.md index 85938f06f..41630d69f 100644 --- a/doc/installation-windows.md +++ b/doc/installation-windows.md @@ -5,73 +5,41 @@ ### Install Git [Download git-scm](https://git-scm.com/) -You can also use either the git command line or GUI client. ### Install CMake [Download CMake](https://cmake.org/download/) -CMake generates the LibSourcey project files so you can build on most platforms and compilers. -Here we use CMake to generate project for Visual Studio. - - ### Install OpenSSL -Download and install the 1.0.x branch [Windows OpenSSL binaries](http://slproweb.com/products/Win32OpenSSL.html). -Don't forget to set system path if you download `zip` file version, or if the OpenSSL Installer failed to set the properly: - -* `\bin` - -You can set the `OPENSSL_ROOT_DIR` CMake variable to point to your OpenSSL installation directory and the build system will do the rest. +Install OpenSSL using [vcpkg](https://vcpkg.io/) or download prebuilt binaries from [slproweb.com](https://slproweb.com/products/Win32OpenSSL.html). +Set the `OPENSSL_ROOT_DIR` CMake variable to point to your OpenSSL installation directory and the build system will do the rest. ### Install FFmpeg (optional) -Download and install [FFmpeg for Windows](https://ffmpeg.zeranoe.com/builds/). -Notice that you need to download both `Shared` and `Dev` version. -Extract zip files and set them to head of your system's `PATH` (you can just add new item in Windows 10): - -* `\bin` - -Now you can set the `FFMPEG_ROOT_DIR` CMake variable to point to your FFmpeg dev installation directory and the build system will do the rest. - -For example, if you want to build LibSourcey with FFmpeg enabled your CMake command might look something like this: - -~~~ bash -cmake .. -DOPENSSL_ROOT_DIR=E:\dev\vendor\OpenSSL-Win64 -DWITH_FFMPEG=ON -DFFMPEG_ROOT_DIR=E:\dev\vendor\ffmpeg-3.2.2-win64-dev -~~~ +Download FFmpeg development libraries from [gyan.dev](https://www.gyan.dev/ffmpeg/builds/) (both shared and dev packages). +Add the FFmpeg `bin` directory to your system `PATH`, then set the `FFMPEG_ROOT_DIR` CMake variable: -### Install WebRTC (optional) - -The easiest way to get started with WebRTC is to download the precompiled static libraries and headers available here: https://sourcey.com/precompiled-webrtc-libraries/ - -Alternatively if you want to compile WebRTC yourself you can use our automated build scripts, which can be found here: https://github.com/sourcey/webrtc-builds - -There is also a step-by-step build Windows guide here: https://sourcey.com/building-and-installing-webrtc-on-windows/ - -Once installed enable and add the WebRTC root directory to your build command like so: - -~~~ bash -cmake .. -DWITH_WEBRTC=ON -DWEBRTC_ROOT_DIR=E:\dev\vendor\webrtcbuilds\out\webrtc-17657-02ba69d-win-x64 -~~~ - -Note that you will need Visual Studio 2017 Update 3 or newer to build with WebRTC on Windows. +```bash +cmake .. -DOPENSSL_ROOT_DIR=C:\vendor\OpenSSL-Win64 -DWITH_FFMPEG=ON -DFFMPEG_ROOT_DIR=C:\vendor\ffmpeg-dev +``` ### Download LibSourcey -Clone the repository: `git clone https://github.com/sourcey/libsourcey.git`. If you haven't got Git for some reason you can download and extract the [package archive](https://github.com/sourcey/libsourcey) from GitHub. - +```bash +git clone https://github.com/sourcey/libsourcey.git +``` ## Generate Project Files Open the CMake GUI and set the project directory to point to the LibSourcey root directory. Execute "Configure" to do the initial configuration, then adjust any options, then press "Configure" again and then press "Generate". -[See here](/installation.md#cmake-build-options) for a complete list of build options. - +[See here](installation.md#cmake-build-options) for a complete list of build options. ## Compile with Visual Studio -1. Generate solutions using CMake, as described above. Make sure, you chose the proper generator (32-bit or 64-bit) -2. Launch Visual Studio, locate and open the `libsourcey.sln` solution file in your generated build folder (eg: `C:\LibSourcey\build\libsourcey.sln`). Select "Debug" configuration, build the solution (Ctrl-Shift-B), and/or select "Release" and build it. -3. Add `{CMAKE_BINARY_DIR}\bin\Release`, `{CMAKE_BINARY_DIR}\bin\Debug` (containing `libscy*.dll` and `libscy*d.dll`, respectively) to the system path (My Computer--[Right button click]->Properties->Advanced->Environment Variables->Path) +1. Generate solutions using CMake, as described above. Make sure you choose the proper generator (32-bit or 64-bit) +2. Launch Visual Studio, locate and open `libsourcey.sln` in your generated build folder. Select "Debug" configuration, build the solution (Ctrl-Shift-B), and/or select "Release" and build it. +3. Add `{CMAKE_BINARY_DIR}\bin\Release` and `{CMAKE_BINARY_DIR}\bin\Debug` to your system PATH. diff --git a/doc/installation.md b/doc/installation.md index 1134c8c87..7bed8affc 100644 --- a/doc/installation.md +++ b/doc/installation.md @@ -1,56 +1,42 @@ ## Installation -LibSourcey uses `CMake` to generate the project files for your compiler, and the codebase is cross platform so it should compile on any system with a modern C++14 compiler. LibSourcey has been successfully compiled and used on the following platforms: +LibSourcey uses `CMake` to generate the project files for your compiler, and the codebase is cross platform so it should compile on any system with a C++20 compiler. LibSourcey has been successfully compiled and used on the following platforms: -* Linux (`gcc` >= 5.0) -* OS X (`Xcode`, `gcc`) -* Windows (`msys`, `vs`) -* Android -* iOS - -**Note**: If using `gcc` then version >= 5.0 is required because older versions have a bug and that doesn't accept parameters pack in lambdas. See here: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55914 +* Linux (`gcc` >= 10, `clang` >= 10) +* macOS (`Xcode`, `clang`) +* Windows (`msvc`, `msys2`) Please refer to the platform specific installation guides: -* [Linux](/installation-linux.md) -* [OS X](/installation-osx.md) -* [Windows](/installation-windows.md) +* [Linux](installation-linux.md) +* [macOS](installation-osx.md) +* [Windows](installation-windows.md) ## Dependencies - -* **OpenSSL** (>= 1.0.1g, required, external) +* **OpenSSL** (required, external) Required by the `net` and `crypto` modules for SSL networking, encryption and cryptography -* **FFmpeg** (>= 2.8.3, optional, external) +* **FFmpeg** (optional, external) Required to compile media related encoding, decoding, device and capture classes in the `av` module -* **WebRTC** (optional, external) - Peer-to-peer video conferencing -* **OpenCV** (>= 3.0, optional, external) +* **OpenCV** (>= 3.0, optional, external) Video capture and computer vision algorithms - ## CMake Build Options The main build options you will want to configure are as follows: -* `BUILD_SHARED_LIBS`: Build shared libraries (.dll/.so) instead of static ones (.lib/.a). _default: NOT (WIN32 OR ANDROID OR IOS)_ -* `BUILD_DEPENDENCIES`: Build LibSourcey in source third-party dependencies. _default: ON_ -* `BUILD_MODULES`: Build LibSourcey modules. _default: ON_ -* `BUILD_MODULE_xxx`: Enable or disable a specific module replacing `xxx` with the module name. -* `BUILD_APPLICATIONS`: Build LibSourcey modules _default: ON_ -* `BUILD_APPLICATION_xxx`: Enable or disable a specific applications replacing `xxx` with the module name. -* `BUILD_TESTS`: Build module test applications _default: ON_ -* `BUILD_TEST_xxx`: Enable or disable a specific test replacing `xxx` with the module name. -* `BUILD_SAMPLES`: Build module test applications _default: ON_ -* `BUILD_SAMPLE_xxx`: Enable or disable a specific test replacing `xxx` with the module name. -* `BUILD_MODULE_SAMPLES`: Build module sample applications _default: ON_ -* `ENABLE_LOGGING`: Enable internal debug logging _default: OFF_ - -If you are using third-party libraries is custom locations then make sure you update the CMake include paths: `CMAKE_SYSTEM_PREFIX_PATH` and `CMAKE_LIBRARY_PATH`. +* `BUILD_SHARED_LIBS`: Build shared libraries (.dll/.so) instead of static ones (.lib/.a). _default: OFF_ +* `BUILD_MODULES`: Build LibSourcey modules. _default: ON_ +* `BUILD_MODULE_xxx`: Enable or disable a specific module replacing `xxx` with the module name. +* `BUILD_APPLICATIONS`: Build LibSourcey applications. _default: ON_ +* `BUILD_TESTS`: Build module test applications. _default: OFF_ +* `BUILD_SAMPLES`: Build module sample applications. _default: OFF_ +* `WITH_OPENSSL`: Enable OpenSSL support. _default: ON_ +* `WITH_FFMPEG`: Enable FFmpeg support. _default: OFF_ +* `WITH_OPENCV`: Enable OpenCV support. _default: OFF_ +* `ENABLE_LOGGING`: Enable internal debug logging. _default: OFF_ -The only third-party libraries that may need configuring if you're using them are FFmpeg, OpenCV and WebRTC. +If you are using third-party libraries in custom locations then make sure you update the CMake include paths: `CMAKE_SYSTEM_PREFIX_PATH` and `CMAKE_LIBRARY_PATH`. For an exhaustive list of options check the `CMakeLists.txt` in the main directory. @@ -58,43 +44,28 @@ For an exhaustive list of options check the `CMakeLists.txt` in the main directo LibSourcey can be packaged into `deb`, `rpm`, `tar.gz`, `zip` and many other formats using CPack: -~~~ bash +```bash cd libsourcey/build cmake .. -DCPACK_GENERATOR=DEB # other build commands here sudo cpack .. -~~~ +``` The output package will be in the `build` folder. -Check the [CPack documentation](https://cmake.org/Wiki/CMake:CPackPackageGenerators) for a full list of supported package generators. +Check the [CPack documentation](https://cmake.org/cmake/resources/software.html) for a full list of supported package generators. ## CMake Build Shortcuts Below are a number of build shortcuts that can be used to build LibSourcey with different features enabled: -~~~ bash +```bash # Default debug build cmake .. -DCMAKE_BUILD_TYPE=DEBUG -DBUILD_SHARED_LIBS=OFF \ -DBUILD_MODULES=ON -DBUILD_APPLICATIONS=ON \ -DBUILD_SAMPLES=ON -DBUILD_TESTS=ON \ - -DWITH_FFMPEG=ON -DWITH_WEBRTC=OFF + -DWITH_FFMPEG=ON -# All modules (selective) -cmake .. -DCMAKE_BUILD_TYPE=DEBUG -DBUILD_SHARED_LIBS=OFF \ - -DBUILD_APPLICATIONS=OFF -DBUILD_MODULES=OFF \ - -DBUILD_SAMPLES=ON -DBUILD_TESTS=ON \ - -DWITH_FFMPEG=ON -DWITH_OPENCV=OFF \ - -DWITH_WEBRTC=OFF -DBUILD_MODULE_archo=ON \ - -DBUILD_MODULE_base=ON -DBUILD_MODULE_crypto=ON \ - -DBUILD_MODULE_http=ON -DBUILD_MODULE_json=ON \ - -DBUILD_MODULE_av=ON -DBUILD_MODULE_net=ON \ - -DBUILD_MODULE_pacm=ON -DBUILD_MODULE_pluga=ON \ - -DBUILD_MODULE_sked=ON -DBUILD_MODULE_socketio=ON \ - -DBUILD_MODULE_stun=ON -DBUILD_MODULE_symple=ON \ - -DBUILD_MODULE_turn=ON -DBUILD_MODULE_util=ON \ - -DBUILD_MODULE_webrtc=ON - -# Minimum build (uv, base) +# Minimum build (base only) cmake .. -DCMAKE_BUILD_TYPE=DEBUG -DBUILD_MODULES=OFF \ -DBUILD_MODULE_base=ON @@ -105,18 +76,6 @@ cmake .. -DCMAKE_BUILD_TYPE=DEBUG -DBUILD_SHARED_LIBS=OFF \ -DWITH_FFMPEG=ON -DWITH_OPENCV=OFF \ -DBUILD_MODULE_av=ON -DBUILD_MODULE_base=ON - -# WebRTC build (with Symple) -cmake .. -DCMAKE_BUILD_TYPE=DEBUG -DBUILD_SHARED_LIBS=OFF \ - -DBUILD_MODULES=OFF -DBUILD_APPLICATIONS=OFF \ - -DBUILD_SAMPLES=OFF -DBUILD_TESTS=OFF \ - -DWITH_WEBRTC=ON -DWITH_FFMPEG=ON \ - -DBUILD_MODULE_base=ON -DBUILD_MODULE_crypto=ON \ - -DBUILD_MODULE_http=ON -DBUILD_MODULE_json=ON \ - -DBUILD_MODULE_av=ON -DBUILD_MODULE_net=ON \ - -DBUILD_MODULE_socketio=ON -DBUILD_MODULE_symple=ON \ - -DBUILD_MODULE_util=ON -DBUILD_MODULE_webrtc=ON - # Symple build (no media) cmake .. -DCMAKE_BUILD_TYPE=DEBUG -DBUILD_SHARED_LIBS=OFF \ -DBUILD_APPLICATIONS=ON -DBUILD_MODULES=OFF \ @@ -139,7 +98,6 @@ cmake .. -DCMAKE_BUILD_TYPE=DEBUG -DBUILD_SHARED_LIBS=OFF \ -DBUILD_MODULE_net=ON -DBUILD_MODULE_socketio=ON \ -DBUILD_MODULE_symple=ON -DBUILD_MODULE_util=ON - # HTTP build cmake .. -DCMAKE_BUILD_TYPE=RELEASE -DBUILD_SHARED_LIBS=OFF \ -DBUILD_APPLICATIONS=ON -DBUILD_MODULES=OFF \ @@ -154,6 +112,5 @@ cmake .. -DCMAKE_BUILD_TYPE=DEBUG -DBUILD_SHARED_LIBS=OFF \ -DBUILD_APPLICATIONS=ON -DBUILD_MODULES=OFF \ -DBUILD_MODULE_base=ON -DBUILD_MODULE_crypto=ON \ -DBUILD_MODULE_net=ON -DBUILD_MODULE_stun=ON \ - -DBUILD_MODULE_turn=ON -DBUILD_MODULE_util=OFF - -~~~ + -DBUILD_MODULE_turn=ON +``` diff --git a/doc/modules.md b/doc/modules.md new file mode 100644 index 000000000..1ece60c4d --- /dev/null +++ b/doc/modules.md @@ -0,0 +1,65 @@ +# Modules + +LibSourcey is organised into 14 modules. Each module builds as a separate library and declares its dependencies via CMake. + +## Dependency Diagram + +``` + symple + / | \ + socketio | \ + / | \ \ | \ + / | \ json \ + / | \ | \ + / | http sched + / | / | \ + / | / | \ + / net | \ + \ / \ | / + \ / \ | / + crypto \ | / + \ \ | / + \ base + \ | + \ libuv (vendored) + \ + openssl (system) + + archo pluga av + | | | + base base base (+FFmpeg) + + stun ---- turn + | / | + net / | + | / | + crypto net + | + base + + pacm + / | \ \ + net json http archo + | | | | + ... | ... base + base +``` + +## Module Overview + +| Module | Description | Dependencies | +|--------|-------------|--------------| +| **base** | Core platform abstractions, event loop (libuv), signals, streams, logging, filesystem, process, timers, rate limiter, stream manager, timed manager | libuv (vendored) | +| **crypto** | Cryptographic operations - hashing, HMAC, RSA, X509 certificates | base, OpenSSL | +| **net** | TCP/SSL/UDP networking, socket adapters, DNS resolution | base, crypto | +| **http** | HTTP client/server, WebSocket support, form handling, cookies, URL parsing | base, net, crypto | +| **json** | JSON serialization using nlohmann/json | base | +| **av** | Audio/video encoding, decoding, device capture, media formats | base, FFmpeg (optional) | +| **socketio** | Socket.IO protocol implementation | base, crypto, net, http, json | +| **symple** | Realtime messaging protocol for presence and messaging | base, crypto, net, http, socketio, json | +| **stun** | STUN protocol (RFC 5389) for NAT traversal | base, net, crypto | +| **turn** | TURN relay server (RFC 5766) for media relaying | base, net, stun, crypto | +| **pacm** | Package manager for distributing and installing plugins | base, net, json, http, archo, crypto | +| **archo** | Archive and ZIP handling | base | +| **pluga** | Plugin system for shared library loading | base | +| **sched** | Task scheduler for deferred and periodic jobs | base, json | diff --git a/doc/styles/website.css b/doc/styles/website.css deleted file mode 100644 index 7af761987..000000000 --- a/doc/styles/website.css +++ /dev/null @@ -1,18 +0,0 @@ -.book .book-summary ul.summary li b { - display: none; -} -.book .book-summary ul.summary li.done > a i { - display: none; -} - -.markdown-section h1, -.markdown-section h2 { - border-bottom: 1px solid #eee; -} - -.markdown-section ol ol, -.markdown-section ol ul, -.markdown-section ul ol, -.markdown-section ul ul { - margin-bottom: .85em; -} diff --git a/src/.gitignore b/src/.gitignore index 55e63b626..1718ba742 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -6,11 +6,11 @@ !http !json !net +!pacm +!pluga !sched !socketio !stun !symple !turn -!util !uv -!webrtc diff --git a/src/archo/CMakeLists.txt b/src/archo/CMakeLists.txt index 157cdb0e3..824f6d5e4 100644 --- a/src/archo/CMakeLists.txt +++ b/src/archo/CMakeLists.txt @@ -1,17 +1,4 @@ -ask_build_sourcey_module(archo) -if(BUILD_MODULES OR (NOT BUILD_MODULES AND BUILD_MODULE_archo)) - set(INSTALL_BIN_DIR "${LibSourcey_VENDOR_INSTALL_DIR}/bin") - set(INSTALL_LIB_DIR "${LibSourcey_VENDOR_INSTALL_DIR}/lib") - set(INSTALL_INC_DIR "${LibSourcey_VENDOR_INSTALL_DIR}/include") - set(INSTALL_MAN_DIR "${LibSourcey_VENDOR_INSTALL_DIR}/share/man") - set(INSTALL_PKGCONFIG_DIR "${LibSourcey_VENDOR_INSTALL_DIR}/share/pkgconfig") - - #add_subdirectory(vendor/zlib) - #add_subdirectory(vendor/minizip) - - #include_dependency(LibUV) # REQUIRED) - #include_dependency(ZLIB) - #include_dependency(Minizip) - - define_sourcey_module(archo base) -endif () +scy_add_module(archo + DEPENDS base + PACKAGES minizip +) diff --git a/src/archo/include/scy/archo/archo.h b/src/archo/include/scy/archo/archo.h index dba67dba9..eb4e96684 100644 --- a/src/archo/include/scy/archo/archo.h +++ b/src/archo/include/scy/archo/archo.h @@ -9,8 +9,7 @@ /// @{ -#ifndef SCY_Archo_H -#define SCY_Archo_H +#pragma once #include "scy/base.h" @@ -18,17 +17,14 @@ /// Shared library exports #if defined(SCY_WIN) && defined(SCY_SHARED_LIBRARY) - #if defined(Archo_EXPORTS) - #define Archo_API __declspec(dllexport) - #else - #define Archo_API __declspec(dllimport) - #endif +#if defined(Archo_EXPORTS) +#define Archo_API __declspec(dllexport) #else - #define Archo_API // nothing +#define Archo_API __declspec(dllimport) +#endif +#else +#define Archo_API // nothing #endif - - -#endif // SCY_Archo_H /// @\} diff --git a/src/archo/include/scy/archo/zipfile.h b/src/archo/include/scy/archo/zipfile.h index 13fe2cb93..d41f98bfb 100644 --- a/src/archo/include/scy/archo/zipfile.h +++ b/src/archo/include/scy/archo/zipfile.h @@ -9,12 +9,12 @@ /// @{ -#ifndef SCY_Archo_ZipFile_H -#define SCY_Archo_ZipFile_H +#pragma once #include "scy/archo/archo.h" -#include "scy/base64.h" +#include +#include #include // zlib #include @@ -26,24 +26,29 @@ namespace archo { struct Archo_API ZipFile { ZipFile(); - ZipFile(const std::string& file); + explicit ZipFile(const std::filesystem::path& file); ~ZipFile(); - void open(const std::string& file); - bool opened() const; + ZipFile(const ZipFile&) = delete; + ZipFile& operator=(const ZipFile&) = delete; + ZipFile(ZipFile&&) = delete; + ZipFile& operator=(ZipFile&&) = delete; + + void open(const std::filesystem::path& file); + [[nodiscard]] bool opened() const; void close(); /// Extracts the archive contents to the given directory path. - void extract(const std::string& path); - bool extractCurrentFile(const std::string& path, bool whiny = true); + void extract(const std::filesystem::path& path); + [[nodiscard]] bool extractCurrentFile(const std::filesystem::path& path, bool whiny = true); - bool goToFirstFile(); - bool goToNextFile(); + [[nodiscard]] bool goToFirstFile(); + [[nodiscard]] bool goToNextFile(); void openCurrentFile(); void closeCurrentFile(); - std::string currentFileName(); + [[nodiscard]] std::string currentFileName(); struct FileInfo { @@ -57,11 +62,8 @@ struct Archo_API ZipFile }; -} // namespace arc +} // namespace archo } // namespace scy -#endif // SCY_Archo_ZipFile_H - - /// @\} diff --git a/src/archo/src/zipfile.cpp b/src/archo/src/zipfile.cpp index da4d2f4d9..39df4c246 100644 --- a/src/archo/src/zipfile.cpp +++ b/src/archo/src/zipfile.cpp @@ -10,7 +10,11 @@ #include "scy/archo/zipfile.h" -#include "scy/filesystem.h" +#include "scy/logger.h" + +#include +#include +#include using std::endl; @@ -72,7 +76,7 @@ ZipFile::ZipFile() } -ZipFile::ZipFile(const std::string& file) +ZipFile::ZipFile(const std::filesystem::path& file) : fp(nullptr) { this->open(file); @@ -91,12 +95,12 @@ bool ZipFile::opened() const } -void ZipFile::open(const std::string& file) +void ZipFile::open(const std::filesystem::path& file) { this->close(); - this->fp = unzOpen(fs::transcode(file).c_str()); + this->fp = unzOpen(file.string().c_str()); if (this->fp == nullptr) - internal::throwError("Cannot open archive file: " + file); + internal::throwError("Cannot open archive file: " + file.string()); for (int ret = unzGoToFirstFile(this->fp); ret == UNZ_OK; ret = unzGoToNextFile(this->fp)) { @@ -108,11 +112,11 @@ void ZipFile::open(const std::string& file) FileInfo finfo; finfo.path = fileName; - finfo.compressedSize = static_cast(fileInfo.uncompressed_size); - finfo.uncompressedSize = static_cast(fileInfo.compressed_size); + finfo.compressedSize = static_cast(fileInfo.compressed_size); + finfo.uncompressedSize = static_cast(fileInfo.uncompressed_size); this->info.push_back(finfo); - LTrace("Zip file contains: ", fileName) + LTrace("Zip file contains: ", fileName); } unzGoToFirstFile(this->fp); // rewind @@ -128,9 +132,9 @@ void ZipFile::close() } -void ZipFile::extract(const std::string& path) +void ZipFile::extract(const std::filesystem::path& path) { - LTrace("Extracting zip to: ", path) + LTrace("Extracting zip to: ", path.string()); if (!opened()) throw std::runtime_error("The archive must be opened for extraction."); @@ -146,7 +150,7 @@ void ZipFile::extract(const std::string& path) } -bool ZipFile::extractCurrentFile(const std::string& path, bool whiny) +bool ZipFile::extractCurrentFile(const std::filesystem::path& path, bool whiny) { int ret; unz_file_info finfo; @@ -157,24 +161,30 @@ bool ZipFile::extractCurrentFile(const std::string& path, bool whiny) unzGetCurrentFileInfo(this->fp, &finfo, fname, 1024, nullptr, 0, nullptr, 0)); - std::string outPath(path); - fs::addnode(outPath, fname); + auto outPath = path / fname; + + // Validate against path traversal attacks (e.g. "../../../etc/passwd") + auto canonical = std::filesystem::weakly_canonical(outPath); + auto canonicalBase = std::filesystem::weakly_canonical(path); + auto [rootEnd, nothing] = std::mismatch(canonicalBase.begin(), canonicalBase.end(), canonical.begin()); + if (rootEnd != canonicalBase.end()) + throw std::runtime_error("Zip entry attempts path traversal: " + std::string(fname)); - LTrace("Extracting asset: ", outPath) + LTrace("Extracting asset: ", outPath.string()); // Create directory #if !WIN32 const int FILE_ATTRIBUTE_DIRECTORY = 0x10; #endif if (finfo.external_fa & FILE_ATTRIBUTE_DIRECTORY || - fname[strlen(fname) - 1] == fs::delimiter) { - LTrace("Create directory: ", outPath) - fs::mkdirr(outPath); + fname[strlen(fname) - 1] == '/') { + LTrace("Create directory: ", outPath.string()); + std::filesystem::create_directories(outPath); } // Create file else { - LTrace("Create file: ", outPath) + LTrace("Create file: ", outPath.string()); // Note: If this fails the file we are trying // to write may be in use on the filesystem. @@ -186,12 +196,12 @@ bool ZipFile::extractCurrentFile(const std::string& path, bool whiny) // need to be ready to create directories if the output file // fails to open. if (!ofs.is_open()) { - fs::mkdirr(fs::dirname(outPath)); + std::filesystem::create_directories(outPath.parent_path()); ofs.open(outPath); } if (!ofs.is_open()) - throw std::runtime_error("Cannot open zip output file: " + outPath); + throw std::runtime_error("Cannot open zip output file: " + outPath.string()); char buffer[16384]; while ((ret = unzReadCurrentFile(this->fp, buffer, 16384)) > 0) @@ -203,7 +213,7 @@ bool ZipFile::extractCurrentFile(const std::string& path, bool whiny) closeCurrentFile(); } } catch (std::exception& exc) { - LError("Cannot unzip file: ", exc.what()) + LError("Cannot unzip file: ", exc.what()); if (whiny) throw exc; return false; @@ -232,7 +242,7 @@ void ZipFile::openCurrentFile() void ZipFile::closeCurrentFile() { - internal::api("unzCloseCurrentFile", unzOpenCurrentFile(this->fp)); + internal::api("unzCloseCurrentFile", unzCloseCurrentFile(this->fp)); } diff --git a/src/archo/tests/CMakeLists.txt b/src/archo/tests/CMakeLists.txt index e48612cfa..1b542f845 100644 --- a/src/archo/tests/CMakeLists.txt +++ b/src/archo/tests/CMakeLists.txt @@ -1 +1 @@ -define_libsourcey_test(archotests base archo) +scy_add_test(archotests DEPENDS base archo) diff --git a/src/archo/tests/archotests.cpp b/src/archo/tests/archotests.cpp index 2a2e5fefc..41dd3c484 100644 --- a/src/archo/tests/archotests.cpp +++ b/src/archo/tests/archotests.cpp @@ -115,6 +115,58 @@ int main(int argc, char** argv) fs::unlink(output); }); + + describe("zip file open/close lifecycle", []() { + archo::ZipFile zip; + expect(!zip.opened()); + + std::string path(testDataDir("test.zip")); + zip.open(path); + expect(zip.opened()); + + zip.close(); + expect(!zip.opened()); + }); + + + describe("zip file enumerate entries", []() { + std::string path(testDataDir("test.zip")); + archo::ZipFile zip(path); + expect(zip.opened()); + + // Iterate through all files in the archive + int count = 0; + if (zip.goToFirstFile()) { + do { + std::string name = zip.currentFileName(); + expect(!name.empty()); + count++; + } while (zip.goToNextFile()); + } + expect(count > 0); + }); + + + describe("zip file info populated on open", []() { + std::string path(testDataDir("test.zip")); + archo::ZipFile zip(path); + + // The info vector should be populated after open + expect(!zip.info.empty()); + for (const auto& fi : zip.info) { + expect(!fi.path.empty()); + } + }); + + + describe("zip file invalid path throws", []() { + try { + archo::ZipFile zip("/nonexistent/path/fake.zip"); + expect(0 && "opening nonexistent zip - must throw"); + } catch (std::exception&) { + } + }); + test::runAll(); return test::finalize(); } diff --git a/src/av/CMakeLists.txt b/src/av/CMakeLists.txt index c9efeed46..29c6e92f5 100644 --- a/src/av/CMakeLists.txt +++ b/src/av/CMakeLists.txt @@ -1,20 +1,10 @@ -ask_build_sourcey_module(av) -if(BUILD_MODULES OR (NOT BUILD_MODULES AND BUILD_MODULE_av)) - - # RtAudio is now deprecated - # if(WITH_RTAUDIO) - # set(BUILD_TESTING OFF) # don't build rtaudio tests - # add_vendor_dependency(RTAUDIO rtaudio) - # endif() - - # if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - # find_library(AVFOUNDATION AVFoundation) - # list(APPEND LibSourcey_BUILD_DEPENDENCIES ${AVFOUNDATION}) - # endif() - - include_dependency(FFmpeg) - # include_dependency(OpenCV) - - set(av_PRETTY_NAME AV) - define_sourcey_module(av base) +scy_add_module(av + DEPENDS base + PRETTY_NAME AV +) + +# FFmpeg is optional for this module +if(HAVE_FFMPEG AND TARGET av) + target_link_libraries(av PUBLIC ${FFMPEG_LIBRARIES}) + target_include_directories(av PUBLIC ${FFMPEG_INCLUDE_DIRS}) endif() diff --git a/src/av/deprecated/include/scy/av/audiocapture.h b/src/av/deprecated/include/scy/av/audiocapture.h deleted file mode 100644 index b2ad8247b..000000000 --- a/src/av/deprecated/include/scy/av/audiocapture.h +++ /dev/null @@ -1,111 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// @addtogroup av -/// @{ - - -#ifndef SCY_AV_AudioCapture_H -#define SCY_AV_AudioCapture_H - - -#include "scy/base.h" - -#ifdef HAVE_RTAUDIO - -#include "scy/av/format.h" -#include "scy/av/icapture.h" -#include "scy/av/types.h" -#include "scy/signal.h" - -#include "RtAudio.h" - -#include -#include -#include - - -namespace scy { -namespace av { - - -DefinePolymorphicDelegateWithArg(audioDelegate, IPacket, PacketDelegateBase, - void*, nullptr) - - /// Implements a cross platfrom audio device capture class. - /// - /// NOTE: Audio buffer samples are always in interleaved, not planar channel - /// format for ease of use ie. `c1 c1 c2 c2 c1 c1 c2 c2...` - class AudioCapture : public ICapture -{ -public: - typedef std::shared_ptr Ptr; - - AudioCapture(int deviceId, int channels, int sampleRate, - RtAudioFormat format = RTAUDIO_SINT16); - virtual ~AudioCapture(); - - virtual void open(); - virtual void close(); - - virtual void start(); - virtual void stop(); - - int deviceId() const; - int sampleRate() const; - int channels() const; - bool running() const; - bool isOpen() const; - RtAudioFormat format() const; - std::string formatString() const; - - void getEncoderFormat(Format& iformat); - void getAudioCodec(AudioCodec& icodec); - -protected: - /// Sets the error message and throws an exception. - virtual void setError(const std::string& message, bool throwExec = true); - - - static int audioCallback( - void* outputBuffer, void* inputBuffer, - unsigned int nBufferFrames, // The system audio capture callback. - /// Samples will be dispatched from the audio capture thread, // so - /// proper synchronization is required. - double streamTime, RtAudioStreamStatus status, void* data); - - /// The system audio error callback. - /// Since this static method provides no client data argument we just log - /// the error. - /// Errors *may* be dispatched from the audio capture thread, // so - /// proper synchronization is required. - static void errorCallback(RtAudioError::Type type, - const std::string& errorText); - - -private: - mutable std::mutex _mutex; - int _deviceId; - int _channels; - int _sampleRate; - RtAudio _audio; - RtAudioFormat _format; - RtAudio::StreamParameters _iParams; - std::string _error; - bool _opened; -}; - - -typedef std::map AudioCaptureMap; - - -} // namespace av -} // namespace scy - - -#endif -#endif diff --git a/src/av/deprecated/include/scy/av/devicemanager.h b/src/av/deprecated/include/scy/av/devicemanager.h deleted file mode 100644 index 85881ecac..000000000 --- a/src/av/deprecated/include/scy/av/devicemanager.h +++ /dev/null @@ -1,240 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// @addtogroup av -/// @{ -// Implemented from libjingle r116 Feb 16, 2012 - - -#ifndef SCY_AV_DeviceManager_H -#define SCY_AV_DeviceManager_H - -#include -#include - -#include "scy/base.h" -#include "scy/signal.h" - - -namespace scy { -namespace av { - -/// Represents a system audio, video or render device. -struct Device -{ - Device(); - Device(const std::string& type, int id, const std::string& name, - const std::string& guid = "", bool isDefault = false, - bool isAvailable = true); - - void print(std::ostream& os); - - std::string type; // audioin, audioout, video - int id; - std::string name; - std::string guid; - bool isDefault; - bool isAvailable; - - bool operator==(const Device& that) const - { - return id == that.id && type == that.type && name == that.name && - guid == that.guid; - } -}; - - -enum MediaCapabilities -{ - AUDIO_RECV = 1 << 0, - AUDIO_SEND = 1 << 1, - VIDEO_RECV = 1 << 2, - VIDEO_SEND = 1 << 3, -}; - -/// A platform independent interface to enumerate audio -/// and video devices on the system. -class IDeviceManager -{ -public: - virtual ~IDeviceManager() {} - /// Initialization - virtual bool initialize() = 0; - virtual void uninitialize() = 0; - - /// Device enumeration - virtual bool getAudioInputDevices(std::vector& devices) = 0; - virtual bool getAudioOutputDevices(std::vector& devices) = 0; - - virtual bool getAudioInputDevice(Device& out, const std::string& name, - int id = -1) = 0; - virtual bool getAudioInputDevice(Device& out, int id) = 0; - - virtual bool getAudioOutputDevice(Device& out, const std::string& name, - int id = -1) = 0; - virtual bool getAudioOutputDevice(Device& out, int id) = 0; - - // virtual bool getAudioInputDevice(const std::string& name, Device& out) = - // 0; - // virtual bool getAudioOutputDevice(const std::string& name, Device& out) = - // 0; - - virtual bool getVideoCaptureDevices(std::vector& devs) = 0; - virtual bool getVideoCaptureDevice(Device& out, int id) = 0; - virtual bool getVideoCaptureDevice(Device& out, const std::string& name, - int id = -1) = 0; - - virtual bool getDefaultAudioInputDevice(Device& device) = 0; - virtual bool getDefaultAudioOutputDevice(Device& device) = 0; - virtual bool getDefaultVideoCaptureDevice(Device& device) = 0; - - /// Capabilities - virtual int getCapabilities() = 0; - - virtual void print(std::ostream& ost) = 0; /// Signals on DevicesChanged. - /// Arg 1 is true when device is video, false for audio - /// Arg 2 is true when device connects, flase on disconnection - Signal DevicesChanged; - - - static const char kDefaultDeviceName[]; -}; - - -class DeviceWatcher -{ -public: - explicit DeviceWatcher(IDeviceManager*) {} - virtual ~DeviceWatcher() {} - virtual bool start() { return true; } - virtual void stop() {} -}; - - -class DeviceManagerFactory -{ -public: - static IDeviceManager* create(); - -private: - DeviceManagerFactory(); -}; - - -class DeviceManager : public IDeviceManager -{ -public: - DeviceManager(); - virtual ~DeviceManager(); - - /// Initialization - virtual bool initialize(); - virtual void uninitialize(); - - /// Capabilities - virtual int getCapabilities(); - - /// Device enumeration - virtual bool getAudioInputDevices(std::vector& devices); - virtual bool getAudioOutputDevices(std::vector& devices); - - // virtual bool getAudioInputDevice(const std::string& name, Device& out); - // virtual bool getAudioOutputDevice(const std::string& name, Device& out); - - virtual bool getAudioInputDevice(Device& out, const std::string& name, - int id = -1); - virtual bool getAudioInputDevice(Device& out, int id); - - virtual bool getAudioOutputDevice(Device& out, const std::string& name, - int id = -1); - virtual bool getAudioOutputDevice(Device& out, int id); - - virtual bool getVideoCaptureDevices(std::vector& devs); - virtual bool getVideoCaptureDevice( - Device& out, const std::string& name, - int id = - -1); /// Returns the video capture device at the given system index. - virtual bool getVideoCaptureDevice(Device& out, int id); - - - virtual bool getDefaultAudioInputDevice(Device& device); - virtual bool getDefaultAudioOutputDevice(Device& device); - virtual bool getDefaultVideoCaptureDevice( - Device& - device); /// The exclusionList MUST be a nullptr terminated list. - static bool filterDevices(std::vector& devices, - const char* const exclusionList[]); - - /// Returns a device matching the given ID. - static bool matchID(std::vector& devices, Device& out, int id); - - /// Returns a device matching the given name and ID. - /// If the device name is not available at the given ID then first - /// device of that name will be returned. - /// If the ID should not be matched the given ID should be -1. - static bool matchNameAndID(std::vector& devices, Device& out, - const std::string& name, int id = -1); - - - bool initialized() const { return _initialized; } - - void print(std::ostream& ost); - -protected: - virtual bool getDefaultAudioDevice(bool input, Device& device); - virtual bool getAudioDevices(bool input, std::vector& devs); - virtual bool getAudioDevice(bool input, Device& out, - const std::string& name, int id = -1); - virtual bool getAudioDevice(bool input, Device& out, int id); - - void setInitialized(bool initialized); - - void setWatcher(DeviceWatcher* watcher); - DeviceWatcher* watcher(); - -private: /// The exclusionList MUST be a nullptr terminated list. - static bool shouldDeviceBeIgnored(const std::string& deviceName, - const char* const exclusionList[]); - - DeviceWatcher* _watcher; - bool _initialized; -}; - - -} // namespace av -} // namespace scy - - -#endif // SCY_AV_DeviceManager_H - - -/* - * libjingle - * Copyright 2004 Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/src/av/deprecated/include/scy/av/devicemanager_fake.h b/src/av/deprecated/include/scy/av/devicemanager_fake.h deleted file mode 100644 index aa067fe9b..000000000 --- a/src/av/deprecated/include/scy/av/devicemanager_fake.h +++ /dev/null @@ -1,212 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// @addtogroup av -/// @{ -// Implemented from libjingle r116 Feb 16, 2012 - - -#ifndef SCY_AV_DeviceManager_FAKE_H -#define SCY_AV_DeviceManager_FAKE_H - - -#include -#include - -#include "scy/av/devicemanager.h" -//#include "talk/session/phone/devicemanager.h" -//#include "talk/session/phone/mediacommon.h" - - -namespace scy { -namespace av { - - -class FakeDeviceManager : public IDeviceManager -{ -public: - FakeDeviceManager() {} - - virtual bool initialize() { return true; } - - virtual void uninitialize() {} - - virtual int getCapabilities() - { - std::vector devices; - int caps = VIDEO_RECV; - if (!input_devices_.empty()) { - caps |= AUDIO_SEND; - } - if (!output_devices_.empty()) { - caps |= AUDIO_RECV; - } - if (!vidcap_devices_.empty()) { - caps |= VIDEO_SEND; - } - return caps; - } - - virtual bool getMicrophones(std::vector& devs) - { - devs = input_devices_; - return true; - } - - virtual bool getSpeakers(std::vector& devs) - { - devs = output_devices_; - return true; - } - - virtual bool getMicrophone(const std::string& name, Device& out) - { - return getAudioDevice(true, name, out); - } - - virtual bool getSpeaker(const std::string& name, Device& out) - { - return getAudioDevice(false, name, out); - } - - virtual bool getCameras(std::vector& devs) - { - devs = vidcap_devices_; - return true; - } - - virtual bool getDefaultCamera(Device& device) - { - if (vidcap_devices_.empty()) { - return false; - } - device = vidcap_devices_[0]; - return true; - } - -#ifdef OSX - bool QtKitToSgDevice(const std::string& qtkit_name, Device& out) - { - out->name = qtkit_name; - out->id = "sg:" + qtkit_name; - return true; - } -#endif - - void setMicrophones(const std::vector& devices) - { - // for (std::size_t i = 0; i < devices.size(); ++i) { - /// input_devices_.push_back(Device(devices[i], i)); - //} - // input_devices_.clear(); - - // DevicesChanged(); - input_devices_ = devices; - } - - void setSpeakers(const std::vector& devices) - { - // for (std::size_t i = 0; i < devices.size(); ++i) { - /// output_devices_.push_back(Device(devices[i], i)); - //} - // output_devices_.clear(); - - // DevicesChanged(); - output_devices_ = devices; - } - - void setCameras(const std::vector& devices) - { - // for (std::size_t i = 0; i < devices.size(); ++i) { - /// vidcap_devices_.push_back(Device(devices[i], i)); - //} - // vidcap_devices_.clear(); - - // DevicesChanged(); - vidcap_devices_ = devices; - } - - - virtual bool getCamera(const std::string& name, Device& out) - { - if (vidcap_devices_.empty()) - return false; - - // If the name is empty, return the default device. - if (name.empty() || name == kDefaultDeviceName) { - out = vidcap_devices_[0]; - return true; - } - - return findDeviceByName(vidcap_devices_, name, out); - } - - bool getAudioDevice(bool input, const std::string& name, Device& out) - { - // If the name is empty, return the default device. - // if (name.empty() || name == kDefaultDeviceName) { - // out = Device(name, -1); - // return true; - //} - - return findDeviceByName((input ? input_devices_ : output_devices_), - name, out); - } - - static bool findDeviceByName(const std::vector& devices, - const std::string& name, Device& out) - { - for (std::vector::const_iterator it = devices.begin(); - it != devices.end(); ++it) { - if (name == it->name) { - out = *it; - return true; - } - } - return false; - } - -private: - std::vector input_devices_; - std::vector output_devices_; - std::vector vidcap_devices_; -}; - - -} // namespace av -} // namespace scy - - -#endif // SCY_AV_DeviceManager_FAKE_H - - -/* - * libjingle - * Copyright 2008--2011, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ \ No newline at end of file diff --git a/src/av/deprecated/include/scy/av/devicemanager_linux.h b/src/av/deprecated/include/scy/av/devicemanager_linux.h deleted file mode 100644 index ac6b1f927..000000000 --- a/src/av/deprecated/include/scy/av/devicemanager_linux.h +++ /dev/null @@ -1,73 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// @addtogroup av -/// @{ -// Implemented from libjingle r116 Feb 16, 2012 - - -#ifndef SCY_AV_DeviceManager_LINUX_H -#define SCY_AV_DeviceManager_LINUX_H - - -#include -#include - -#include "scy/av/devicemanager.h" - -//#include "talk/base/sigslot.h" -//#include "talk/base/stringencode.h" -//#include "talk/sound/soundsystemfactory.h" - - -namespace scy { -namespace av { - - -class LinuxDeviceManager : public DeviceManager -{ -public: - LinuxDeviceManager(); - virtual ~LinuxDeviceManager(); - - virtual bool getCameras(std::vector& devs); -}; - - -} // namespace av -} // namespace scy - - -#endif // SCY_AV_DeviceManager_LINUX_H - - -/* - * libjingle - * Copyright 2004 Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/src/av/deprecated/include/scy/av/devicemanager_mac.h b/src/av/deprecated/include/scy/av/devicemanager_mac.h deleted file mode 100644 index 50cd78ab2..000000000 --- a/src/av/deprecated/include/scy/av/devicemanager_mac.h +++ /dev/null @@ -1,78 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// @addtogroup av -/// @{ -// Implemented from libjingle r116 Feb 16, 2012 - - -#ifndef SCY_AV_DeviceManager_MAC_H -#define SCY_AV_DeviceManager_MAC_H - - -#include -#include - -#include "scy/av/devicemanager.h" - -// #include "talk/base/sigslot.h" -// #include "talk/base/stringencode.h" - - -namespace scy { -namespace av { - - -class DeviceWatcher; - -class MacDeviceManager : public DeviceManager -{ -public: - MacDeviceManager(); - virtual ~MacDeviceManager(); - - virtual bool getCameras(std::vector& devs); - -private - : /// virtual bool getAudioDevices(bool input, std::vector& devs); - bool FilterDevice(const Device& d); -}; - - -} // namespace av -} // namespace scy - - -#endif // SCY_AV_DeviceManager_MAC_H - - -/* - * libjingle - * Copyright 2004 Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/src/av/deprecated/include/scy/av/devicemanager_win32.h b/src/av/deprecated/include/scy/av/devicemanager_win32.h deleted file mode 100644 index 5fbe42ca2..000000000 --- a/src/av/deprecated/include/scy/av/devicemanager_win32.h +++ /dev/null @@ -1,154 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// @addtogroup av -/// @{ -// Implemented from libjingle r116 Feb 16, 2012 - - -#ifndef SCY_AV_DeviceManager_WIN32_H -#define SCY_AV_DeviceManager_WIN32_H - -//#ifndef __WINDOWS_DS__ -//#define __WINDOWS_DS__ -//#endif - -#include "scy/av/devicemanager.h" -#include "scy/base.h" - -#include -#include - -#ifdef HAVE_RTAUDIO - - -namespace scy { -namespace av { - - -// -// Win32 Device Manager -// - - -class Win32DeviceManager : public DeviceManager -{ -public: - Win32DeviceManager(); - virtual ~Win32DeviceManager(); - - virtual bool initialize(); - virtual void uninitialize(); - - virtual bool getCameras(std::vector& devs); - virtual bool getDefaultCamera(Device& device); - -private: - bool _needCoUninitialize; - static Mutex _mutex; -}; - - -// -// Win32 Window -// - - -class Win32Window -{ -public: - Win32Window(); - virtual ~Win32Window(); - - bool Create(HWND parent, const wchar_t* title, DWORD style, DWORD exstyle, - int x, int y, int cx, int cy); - void Destroy(); - - HWND handle() const { return wnd_; } - /// Call this when your DLL unloads. - static void Shutdown(); - -protected: - virtual bool OnMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, - LRESULT& result); - - virtual bool OnClose() { return true; } - virtual void OnNcDestroy() {} - -private: - static LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, - LPARAM lParam); - - HWND wnd_; - static HINSTANCE instance_; - static ATOM window_class_; -}; - - -// -// Win32 Device Watcher -// - - -/// Plugs into windows event notifications to detect the adding -/// and removing of attached audio and video devices. -/// -/// Note: The application must be compiled with SUBSYSTEM:WINDOWS. -/// Console applications receive no device notification. -class Win32DeviceWatcher : public DeviceWatcher, public Win32Window -{ -public: - explicit Win32DeviceWatcher(Win32DeviceManager* dm); - virtual ~Win32DeviceWatcher(); - virtual bool start(); - virtual void stop(); - -private: - HDEVNOTIFY Register(REFGUID guid); - void Unregister(HDEVNOTIFY notify); - virtual bool OnMessage(UINT msg, WPARAM wp, LPARAM lp, LRESULT& result); - - Win32DeviceManager* manager_; - HDEVNOTIFY audio_notify_; - HDEVNOTIFY video_notify_; -}; - - -} // namespace av -} // namespace scy - - -#endif -#endif // SCY_AV_DeviceManager_WIN32_H - - -/* -* libjingle -* Copyright 2004 Google Inc. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, -* this list of conditions and the following disclaimer. -* 2. Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* 3. The name of the author may not be used to endorse or promote products -* derived from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED -* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO -* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; -* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ diff --git a/src/av/deprecated/include/scy/av/flvmetadatainjector.h b/src/av/deprecated/include/scy/av/flvmetadatainjector.h deleted file mode 100644 index 7ee2dfa7f..000000000 --- a/src/av/deprecated/include/scy/av/flvmetadatainjector.h +++ /dev/null @@ -1,484 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// @addtogroup av -/// @{ - - -#ifndef SCY_AV_FLVMetadataInjector_H -#define SCY_AV_FLVMetadataInjector_H - - -#include "scy/av/format.h" -#include "scy/av/fpscounter.h" -#include "scy/av/types.h" -#include "scy/byteorder.h" -#include "scy/packetstream.h" -#include "scy/signal.h" -#include - - -namespace scy { -namespace av { - -/// This class implements a packetizer which appends correct -/// stream headers and modifies the timestamp of FLV packets -/// so Adobe's Flash Player will play our videos mid-stream. -/// -/// This adapter is useful for multicast situations where we -/// don't have the option of restarting the encoder stream. -class FLVMetadataInjector : public IPacketizer -{ -public: - enum AMFDataType - { - AMF_DATA_TYPE_NUMBER = 0x00, - AMF_DATA_TYPE_BOOL = 0x01, - AMF_DATA_TYPE_STRING = 0x02, - AMF_DATA_TYPE_OBJECT = 0x03, - AMF_DATA_TYPE_NULL = 0x05, - AMF_DATA_TYPE_UNDEFINED = 0x06, - AMF_DATA_TYPE_REFERENCE = 0x07, - AMF_DATA_TYPE_MIXEDARRAY = 0x08, - AMF_DATA_TYPE_OBJECT_END = 0x09, - AMF_DATA_TYPE_ARRAY = 0x0a, - AMF_DATA_TYPE_DATE = 0x0b, - AMF_DATA_TYPE_LONG_STRING = 0x0c, - AMF_DATA_TYPE_UNSUPPORTED = 0x0d, - }; - - enum - { - FLV_TAG_TYPE_AUDIO = 0x08, - FLV_TAG_TYPE_VIDEO = 0x09, - FLV_TAG_TYPE_SCRIPT = 0x12, - }; - - enum - { - FLV_FRAME_KEY = 1 << 4, - FLV_FRAME_INTER = 2 << 4, - FLV_FRAME_DISP_INTER = 3 << 4, - }; - - IPacketizer(this->emitter), _format(format), _initial(true), - _modifyingStream(false), _waitingForKeyframe(false), - _timestampOffset(0) FLVMetadataInjector(const Format& format) - : - { - traceL("FLVMetadataInjector", this) << "Create" << std::endl; - } /// This method is called by the Packet Stream - /// whenever the stream is restarted. - virtual void onStreamStateChange(const PacketStreamState& state) - { - traceL("FLVMetadataInjector", this) << "Stream state change: " << state - << std::endl; - - switch (state.id()) { - case PacketStreamState::Active: - _initial = true; - _modifyingStream = false; - _waitingForKeyframe = false; - _timestampOffset = 0; - break; - } - - IPacketizer::onStreamStateChange(state); - } - - virtual void process(IPacket& packet) - { - av::MediaPacket* mpacket = dynamic_cast(&packet); - if (mpacket && mpacket->size() > 15) { - - // Read the first packet to determine weather or not - // we need to generate and inject custom metadata. - if (_initial && !_modifyingStream) { - // Buffer buf; - // packet.write(buf); - _modifyingStream = true; //! isFLVHeader(buf); - _waitingForKeyframe = _modifyingStream; - _timestampOffset = 0; - _initial = false; - } - - // Modify the stream only if required. This involves - // dropping all packets until we receive the first - // keyframe, and prepending custom FLV headers. - if (_modifyingStream) { - - // Wait for the first keyframe... - if (_waitingForKeyframe) { - - // Drop all frames until we receive the first keyframe. - // fastIsFLVHeader(reinterpret_cast(mpacket->data()) - if (!fastIsFLVKeyFrame(mpacket->data())) { - traceL("FLVMetadataInjector", this) - << "Waiting for keyframe, dropping packet" - << std::endl; - return; - } - - // Create and dispatch our custom header. - _waitingForKeyframe = false; - traceL("FLVMetadataInjector", this) - << "Got keyframe, prepending headers" << std::endl; - // Buffer flvHeader(512); - std::vector flvHeader(512); - BitWriter writer(flvHeader); - writeFLVHeader(writer); - - MediaPacket opacket((std::uint8_t*)flvHeader.data(), - writer.position()); - emit(opacket); - } - - // A correct timetsamp value must be sent to the flash - // player otherwise payback will be jerky or delayed. - _fpsCounter.tick(); - -// Generate a timestamp based on frame rate and number. -// std::uint32_t timestamp = static_cast((1000.0 / -// _fpsCounter.fps) * _fpsCounter.frames); - -// Update the output packet timestamp. -// fastUpdateTimestamp(mpacket->data(), timestamp); - -#if 0 - BitReader reader1(mpacket->data(), mpacket->size()); - dumpFLVTags(reader1); -#endif - - // Dispatch the modified packet... - traceL("FLVMetadataInjector", this) << "Emit modified packet" - << std::endl; - emit(*mpacket); - return; - } - } /// Just proxy the packet if no modification is required. - traceL("FLVMetadataInjector", this) << "Proxy packet" << std::endl; - emit(packet); - } /// Updates the timestamp in the given FLV tag buffer. - /// No more need to copy data with this method. - /// Caution: this method does not check buffer size. - virtual void fastUpdateTimestamp(char* buf, std::uint32_t timestamp) - { - std::uint32_t val = hostToNetwork32(timestamp); - - // traceL("FLVMetadataInjector", this) << "Updating timestamp: " // - // << "\n\tTimestamp: " << timestamp - /// << "\n\tTimestamp Val: " << val - /// << "\n\tFrame Number: " << _fpsCounter.frames - /// << "\n\tFrame Rate: " << _fpsCounter.fps - /// << std::endl; - - std::memcpy(buf + 4, reinterpret_cast(&val) + 1, 3); - } /// Caution: this method does not check buffer size. - virtual bool fastIsFLVHeader(char* buf) - { - return strncmp(buf, "FLV", 3) == 0; - } /// Caution: this method does not check buffer size. - virtual bool fastIsFLVKeyFrame(char* buf) - { - std::uint8_t flags = buf[11]; - return (flags & FLV_FRAME_KEY) == FLV_FRAME_KEY; - } - - virtual void writeFLVHeader(BitWriter& writer) - { - /// - /// FLV Header - writer.put("FLV", 3); - writer.putU8(0x01); - writer.putU8(((_format.video.enabled) ? 1 : 0) | - ((_format.audio.enabled) ? 4 : 0)); - writer.putU32(0x09); - - writer.putU32(0); // previous tag size - - /// - /// FLV Metadata Object - writer.putU8(FLV_TAG_TYPE_SCRIPT); - int dataSizePos = writer.position(); // - offset; - writer.putU24(0); // size of data part (sum of all parts below) - writer.putU24(0); // time stamp - writer.putU32(0); // reserved - - int dataStartPos = writer.position(); // - offset; - - writer.putU8(AMF_DATA_TYPE_STRING); // AMF_DATA_TYPE_STRING - writeAMFSring(writer, "onMetaData"); - - writer.putU8(AMF_DATA_TYPE_MIXEDARRAY); - writer.putU32(2 + // number of elements in array - (_format.video.enabled ? 5 : 0) + - (_format.audio.enabled ? 5 : 0)); - - writeAMFSring(writer, "duration"); - writeAMFDouble(writer, 0); - - if (_format.video.enabled) { - writeAMFSring(writer, "width"); - writeAMFDouble(writer, _format.video.width); - - writeAMFSring(writer, "height"); - writeAMFDouble(writer, _format.video.height); - - // writeAMFSring(writer, "videodatarate"); - // writeAMFDouble(writer, _format.video.bitRate / 1024.0); - - // writeAMFSring(writer, "framerate"); - // writeAMFDouble(writer, _format.video.fps); - - // Not necessary for playback.. - // writeAMFSring(writer, "videocodecid"); - // writeAMFDouble(writer, 2); // FIXME: get FLV Codec ID from FFMpeg - // ID - } - - if (_format.audio.enabled) { - writeAMFSring(writer, "audiodatarate"); - writeAMFDouble(writer, _format.audio.bitRate / 1024.0); - - writeAMFSring(writer, "audiosamplerate"); - writeAMFDouble(writer, _format.audio.sampleRate); - - writeAMFSring(writer, "audiosamplesize"); - writeAMFDouble(writer, 16); // FIXME: audio_enc->codec_id == - // AV_CODEC_ID_PCM_U8 ? 8 : 16 - - writeAMFSring(writer, "stereo"); - writeAMFBool(writer, _format.audio.channels == 2); - - // Not necessary for playback.. - // writeAMFSring(buf, "audiocodecid"); - // writeAMFDouble(buf, 0/* audio_enc->codec_tag*/); // FIXME: get - // FLV Codec ID from FFMpeg ID - } - - writeAMFSring(writer, "filesize"); - writeAMFDouble(writer, 0); // delayed write - - writer.put("", 1); - writer.putU8(AMF_DATA_TYPE_OBJECT_END); /// Write data size - int dataSize = writer.position() - dataStartPos; - writer.updateU24(dataSize, dataSizePos); /// Write tag size - writer.putU32(dataSize + 11); - - traceL("FLVMetadataInjector", this) << "FLV Header:" - //<< "\n\tType: " << (int)tagType - << "\n\tData Size: " << dataSize - //<< "\n\tTimestamp: " << timestamp - //<< "\n\tStream ID: " << streamId - << std::endl; - } - - static bool dumpFLVTags(BitReader& reader) - { - bool result = false; - - std::uint8_t tagType; - std::uint32_t dataSize; - std::uint32_t timestamp; - std::uint8_t timestampExtended; - std::uint32_t streamId; - std::uint8_t flags; - std::uint32_t previousTagSize; - - do { - if (reader.available() < 12) - break; - - reader.getU8(tagType); - if (tagType != FLV_TAG_TYPE_AUDIO && // audio - tagType != FLV_TAG_TYPE_VIDEO && // video - tagType != FLV_TAG_TYPE_SCRIPT) // script - break; - - reader.getU24(dataSize); - if (dataSize < 100) - break; - - reader.getU24(timestamp); - if (timestamp < 0) - break; - - reader.getU8(timestampExtended); - - reader.getU24(streamId); - if (streamId != 0) - break; - - // Start of data size bytes - int dataStartPos = reader.position(); - - reader.getU8(flags); - - bool isKeyFrame = false; - bool isInterFrame = false; - // bool isDispInterFrame = false; - switch (tagType) { - case FLV_TAG_TYPE_AUDIO: - break; - - case FLV_TAG_TYPE_VIDEO: - isKeyFrame = (flags & FLV_FRAME_KEY) == FLV_FRAME_KEY; - isInterFrame = (flags & FLV_FRAME_INTER) == FLV_FRAME_INTER; - // isDispInterFrame = (flags & FLV_FRAME_DISP_INTER) == - // FLV_FRAME_DISP_INTER; - break; - - case FLV_TAG_TYPE_SCRIPT: - break; - - default: - break; - } - - // Read to the end of the current tag. - reader.seek(dataStartPos + dataSize); - reader.getU32(previousTagSize); - if (previousTagSize == 0) { - assert(false); - break; - } - - traceL("FLVMetadataInjector") - << "FLV Tag:" - << "\n\tType: " << (int)tagType - << "\n\tTag Size: " << previousTagSize - << "\n\tData Size: " << dataSize - << "\n\tTimestamp: " << timestamp - //<< "\n\tTimestamp Extended: " << (int)timestampExtended - << "\n\tKey Frame: " << isKeyFrame - << "\n\tInter Frame: " << isInterFrame - //<< "\n\tDisp Inter Frame: " << isDispInterFrame - //<< "\n\tFlags: " << (int)flags - //<< "\n\tStream ID: " << streamId - << std::endl; - - result = true; - - } while (0); - - return result; - } - - std::int64_t doubleToInt(double d) - { - int e; - if (!d) - return 0; - else if (d - d) - return 0x7FF0000000000000LL + ((std::int64_t)(d < 0) << 63) + - (d != d); - d = frexp(d, &e); - return (std::int64_t)(d < 0) << 63 | (e + 1022LL) << 52 | - (std::int64_t)((fabs(d) - 0.5) * (1LL << 53)); - } - - - /// - /// AMF Helpers - // - - virtual void writeAMFSring(BitWriter& writer, const char* val) - { - std::uint16_t len = strlen(val); - writer.putU16(len); - writer.put(val, len); - } - - virtual void writeAMFDouble(BitWriter& writer, double val) - { -#if WIN32 // The implementation is not perfect, but it's sufficient for our - // needs. - if ((val > double(_I64_MAX)) || (val < double(_I64_MIN))) { - traceL("FLVMetadataInjector") << "Double to int truncated" - << std::endl; - assert(0); - } -#endif - - writer.putU8(AMF_DATA_TYPE_NUMBER); // AMF_DATA_TYPE_NUMBER - // writer.putU64(std::int64_t(val)); - writer.putU64(doubleToInt(val)); - } - - virtual void writeAMFBool(BitWriter& writer, bool val) - { - writer.putU8(AMF_DATA_TYPE_BOOL); // AMF_DATA_TYPE_NUMBER - writer.putU8(val ? 1 : 0); - } - - PacketSignal emitter; - -protected: - Format _format; - bool _initial; - bool _modifyingStream; - bool _waitingForKeyframe; - std::uint32_t _timestampOffset; - legacy::FPSCounter _fpsCounter; // Need legacy counter for smooth playback -}; - - -} // namespace av -} // namespace scy - - -#endif - - -/* -virtual void updateTimestamp(Buffer& buf, std::uint32_t timestamp) -{ -/// Note: The buffer must be positioned at -/// the start of the tag. - int offset = buf.position(); - if (buf.available() < offset + 4) { - errorL("FLVMetadataInjector", this) << "The FLV tag buffer is too -small." << std::endl; - return; - } - - traceL("FLVMetadataInjector", this) << "Updating timestamp: " - << "\n\tTimestamp: " << timestamp - << "\n\tFrame Number: " << _fpsCounter.frames - << "\n\tFrame Rate: " << _fpsCounter.fps - << std::endl; - - buf.updateU24(timestamp, offset + 4); -} - -virtual bool isFLVHeader(BitWriter& writer) -{ - std::string signature; - buf.get(signature, 3); - return signature == "FLV"; -} - -virtual bool isFLVKeyFrame(BitWriter& writer) -{ - if (buf.available() < 100) - return false; - - int offset = buf.position(); - - //buf.getU8(tagType); - //if (tagType != FLV_TAG_TYPE_VIDEO) // return false; - //std::uint8_t tagType; - - - std::uint8_t flags; - buf.position(11); - buf.getU8(flags); - - buf.position(offset); - return (flags & FLV_FRAME_KEY) == FLV_FRAME_KEY; -} -*/ diff --git a/src/av/deprecated/include/scy/av/imageencoder.h b/src/av/deprecated/include/scy/av/imageencoder.h deleted file mode 100644 index df095c67e..000000000 --- a/src/av/deprecated/include/scy/av/imageencoder.h +++ /dev/null @@ -1,71 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// @addtogroup av -/// @{ - - -#ifndef SCY_AV_ImageEncoder_H -#define SCY_AV_ImageEncoder_H - - -#include "scy/av/iencoder.h" -#include "scy/av/types.h" - -#ifdef HAVE_OPENCV - -#include -#include - - -namespace scy { -namespace av { - - -/// This class is a PacketStreamAdapter which uses OpenCV /// to encode -/// images from raw data packets. -/// -/// See OpenCV documentation for cvParams information. -/// JPEG: /// 0 = CV_IMWRITE_JPEG_QUALITY -/// 1 = (quality) default 95 [0-100] -/// -/// PNG: /// 0 = CV_IMWRITE_PNG_COMPRESSION -/// 1 = (compression) default 3 [0-9] -// -class ImageEncoder : public PacketProcessor // IPacketEncoder -{ -public: - ImageEncoder(EncoderOptions& options, - std::vector cvParams = std::vector()); - virtual ~ImageEncoder(); - - virtual void initialize(); - virtual void uninitialize(); - - virtual bool accepts(IPacket* packet); - virtual void process(IPacket& packet); - - virtual EncoderOptions& options(); - - PacketSignal emitter; - -private: - std::string _extension; - EncoderOptions _options; - std::vector _params; -}; - - -} // namespace av -} // namespace scy - - -#endif -#endif // SCY_AV_ImageEncoder_H - - -/// @\} diff --git a/src/av/deprecated/include/scy/av/matrixconverter.h b/src/av/deprecated/include/scy/av/matrixconverter.h deleted file mode 100644 index caf834d55..000000000 --- a/src/av/deprecated/include/scy/av/matrixconverter.h +++ /dev/null @@ -1,123 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// @addtogroup av -/// @{ - - -#ifndef SCY_AV_MatrixConverter_H -#define SCY_AV_MatrixConverter_H - -#include "scy/packetstream.h" -#include "scy/signal.h" - -#if defined(HAVE_OPENCV) && defined(HAVE_FFMPEG) - -extern "C" { -#include -#include -} - -#include - - -namespace scy { -namespace av { - -/// This class provides the ability to convert decoded -/// video stream frames to OpenCV matrix images. -/// Input packets must pass a VideoDecoder pointer -/// as client data. -class MatrixConverter : public IPacketizer -{ -public: - _convCtx(nullptr), _oframe(nullptr) MatrixConverter() - : - { - } - - ~MatrixConverter() - { - if (_convCtx) - sws_freeContext(_convCtx); - - if (_oframe) { - if (_oframe->data) - av_free(_oframe->data[0]); - av_free(_oframe); - } - } - - virtual bool accepts(IPacket* packet) - { - return dynamic_cast(&packet) != 0; - } - - virtual void process(IPacket& packet) - { - VideoPacket& vpacket = reinterpret_cast(packet); - VideoDecoder* video = reinterpret_cast(packet.opaque); - if (video == nullptr) - throw std::runtime_error("Matrix Converter: Video packets must " - "contain a VideoDecoder pointer."); - // Create and allocate the conversion frame. - if (_oframe == nullptr) { - _oframe = av_frame_alloc(); - if (_oframe == nullptr) - throw std::runtime_error( - "Matrix Converter: Could not allocate the output frame."); - - avpicture_alloc(reinterpret_cast(_oframe), - AV_PIX_FMT_BGR24, video->ctx->width, - video->ctx->height); - } - // Convert the image from its native format to BGR. - if (_convCtx == nullptr) { - _convCtx = sws_getContext(video->ctx->width, video->ctx->height, - video->ctx->pix_fmt, video->ctx->width, - video->ctx->height, AV_PIX_FMT_BGR24, - SWS_BICUBIC, nullptr, nullptr, nullptr); - _mat.create(video->ctx->height, video->ctx->width, CV_8UC(3)); - } - if (_convCtx == nullptr) - throw std::runtime_error("Matrix Converter: Unable to initialize " - "the conversion context."); - // Scales the source data according to our SwsContext settings. - if (sws_scale(_convCtx, video->frame->data, video->frame->linesize, 0, - video->ctx->height, _oframe->data, _oframe->linesize) < 0) - throw std::runtime_error("Matrix Converter: Pixel format " - "conversion not supported."); /// Populate - /// the - /// OpenCV - /// Matrix. - for (int y = 0; y < video->ctx->height; y++) { - for (int x = 0; x < video->ctx->width; x++) { - _mat.at(y, x)[0] = - _oframe->data[0][y * _oframe->linesize[0] + x * 3 + 0]; - _mat.at(y, x)[1] = - _oframe->data[0][y * _oframe->linesize[0] + x * 3 + 1]; - _mat.at(y, x)[2] = - _oframe->data[0][y * _oframe->linesize[0] + x * 3 + 2]; - } - } - - vpacket.mat = &_mat; - emit(this, vpacket); - } - - cv::Mat _mat; - AVFrame* _oframe; - struct SwsContext* _convCtx; -}; - - -} // namespace av -} // namespace scy - - -#endif -#endif diff --git a/src/av/deprecated/include/scy/av/mediafactory.h b/src/av/deprecated/include/scy/av/mediafactory.h deleted file mode 100644 index bf21b35c1..000000000 --- a/src/av/deprecated/include/scy/av/mediafactory.h +++ /dev/null @@ -1,136 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// @addtogroup av -/// @{ - - -#ifndef SCY_AV_MediaFactory_H -#define SCY_AV_MediaFactory_H - - -#include "scy/av/formatregistry.h" -#include "scy/av/mediacapture.h" -#include "scy/av/mediacapture.h" -#include "scy/av/types.h" -#include - -#if defined(HAVE_OPENCV) && defined(HAVE_RTAUDIO) - -#include -#include - -#include -#include - -#include "scy/av/devicemanager.h" -#if !defined(USING_FAKE_DeviceManager) && defined(WIN32) -#include "scy/av/devicemanager_win32.h" -#elif !defined(USING_FAKE_DeviceManager) && defined(MACOS) -#include "scy/av/devicemanager_mac.h" -#elif !defined(USING_FAKE_DeviceManager) && defined(LINUX) -#include "scy/av/devicemanager_linux.h" -#else -#include "scy/av/devicemanager_fake.h" -#endif - - -namespace scy { -namespace av { - -/// The MediaFactory class is a singleton manager for audio/video -/// captures, device enumeration and encoder media formats. -class MediaFactory -{ -public: - /// Creates a VideoCapture instance for given device ID. - /// - /// If the VideoCapture already exists for this camera then this method - /// can be used to create VideoCaptures in any thread. - /// - /// If the VideoCapture has not been created for this camera yet it will - /// be created now, but take case since VideoCapture instances should - /// only be initialized from the main thread (OpenCV limitation). - /// You can also lazy load video cameras using loadVideoCaptures() - VideoCapture::Ptr createVideoCapture(int deviceId); - - /// Creates a VideoCapture from given source file. - /// File captures can be created in any thread. - VideoCapture::Ptr createFileCapture(const std::string& file); - - - AudioCapture::Ptr createAudioCapture( - int deviceId, int channels = DEFAULT_AUDIO_CHANNELS, - int sampleRate = DEFAULT_AUDIO_SAMPLE_RATE, // Creates an AudioCapture - // from given options. - RtAudioFormat format = RTAUDIO_SINT16); - - /// Preloads a VideoCapture instance for each available camera. - /// This method MUST be called from the main thread. - /// This method can be called from the main thread to lazy load - /// video device captures. Alternatively you can call createVideoCapture() - /// // This will ensure captures are always available to the - /// application using createVideoCapture(), from any thread. - void loadVideoCaptures(); - - /// Destroys all managed VideoCapture instances. - void unloadVideoCaptures(); - - /// Reloads video captures that may have failed or been unplugged. - /// The original VideoCapture instance is not deleted, just reused. - /// This method MUST be called from the main thread. - void reloadFailedVideoCaptures(); - - /// Siganls when a video capture is loaded. - Signal VideoCaptureLoaded; - - /// Siganls when a video capture fails, or is unplugged. - Signal VideoCaptureError; - - - std::map - videoCaptures() const; /// Returns the device manager instance. - IDeviceManager& devices(); - - /// Returns all registered media formats. - FormatRegistry& formats(); - - /// Returns the default MediaFactory singleton. - static MediaFactory& instance(); - - /// Shuts down the MediaFactory and deletes the singleton instance. - static void shutdown(); - - -protected: - MediaFactory(); - MediaFactory(MediaFactory const&){}; - // MediaFactory& operator=(MediaFactory const&){}; - ~MediaFactory(); - - void onVideoCaptureError(void*, const scy::Error& err); - - // VideoCapture::Ptr getVideoCapture(int deviceId); - - friend class Singleton; - friend class VideoCapture; - - mutable std::mutex _mutex; - - IDeviceManager* _devices; - FormatRegistry _formats; - // bool _hasFailedVideoCaptures; - std::map _videoCaptures; -}; - - -} // namespace av -} // namespace scy - - -#endif -#endif diff --git a/src/av/deprecated/include/scy/av/thumbnailer.h b/src/av/deprecated/include/scy/av/thumbnailer.h deleted file mode 100644 index f66718d8c..000000000 --- a/src/av/deprecated/include/scy/av/thumbnailer.h +++ /dev/null @@ -1,83 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// @addtogroup av -/// @{ - - -#ifndef SCY_AV_Thumbnailer_H -#define SCY_AV_Thumbnailer_H - - -#if 0 // needs updating to latest API - -#include "scy/av/config.h" -#include "scy/av/mediacapture.h" -#include "scy/av/videoencoder.h" -#include "scy/base.h" - -#include -#include -#include - - -namespace scy { -namespace av { - - -struct ThumbnailerOptions -{ - std::string ifile; - std::string ofile; - int width; - int height; - double seek; - - ThumbnailerOptions(const std::string& ifile = "", const std::string& ofile = "", - int width = 0, int height = 0, double seek = 0.0) - : ifile(ifile), ofile(ofile), width(width), height(height), seek(seek) {}; -}; - - -#ifdef HAVE_FFMPEG - - - /// Creates video thumbnail using FFmpeg. - /// Note that even if FFmpeg is unavailable we still expose - /// ThumbnailerOptions for the Spot API. -struct Thumbnailer -{ - ThumbnailerOptions options; - av::MediaCapture reader; - av::VideoEncoder encoder; - - Thumbnailer(const ThumbnailerOptions& options = ThumbnailerOptions()); - ~Thumbnailer() ; /// Open the input file - /// The encoder context may still be configured after this call - /// If the ofile path is empty a default one will be selected - /// using defaultThumbPath() - void open(); - - /// Initialize the image encoder and grab a thumbnail at the - /// specified seek position - void grab(); - - - void onVideoPacket(void*, av::VideoPacket& packet); - - static std::string defaultThumbPath(const std::string& ifile, const std::string& ext = ".jpg", const std::string& suffix = "_thumb"); -}; - -#endif - - -} // namespace av -} // namespace scy - - -#endif -#endif diff --git a/src/av/deprecated/include/scy/av/videoanalyzer.h b/src/av/deprecated/include/scy/av/videoanalyzer.h deleted file mode 100644 index b8ad8d352..000000000 --- a/src/av/deprecated/include/scy/av/videoanalyzer.h +++ /dev/null @@ -1,169 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// @addtogroup av -/// @{ - - -#ifndef SCY_AV_VideoAnalyzer_H -#define SCY_AV_VideoAnalyzer_H - - -#include "scy/base.h" - -#ifdef HAVE_FFMPEG - -#include "scy/av/format.h" -#include "scy/av/fpscounter.h" -#include "scy/av/mediacapture.h" -#include "scy/av/videoconverter.h" -#include "scy/interface.h" -#include "scy/packetstream.h" -#include "scy/packetstream.h" -#include "scy/signal.h" -#include "scy/stateful.h" - -extern "C" { -#include -} - - -namespace scy { -namespace av { - -/// This class provides basic AV spectrum analysis on a -/// video using the Fourier Transform algorithm. -/// Data is outputted in CSV format. -/// -/// TODO:/// - Pluggable algorithms and processors -/// - Normalization (scaling) for output values -/// - Process multiple audio channels properly -/// - Inherit from PacketProcessor -class VideoAnalyzer //: public PacketProcessor -{ -public: - struct Options - { - std::string ifile; // The input video file. - int rdftSize; // Size of the FFT input array - // bool blocking; // Blocking mode (disable async) - - Options() - { - rdftSize = 1024; - // blocking = false; - } - }; - - struct Stream - { - std::string name; - RDFTContext* rdft; - FFTSample* rdftData; - int rdftSize; - int rdftBits; - std::int64_t frames; - int filled; - - Stream(const std::string& name, int rdftSize); - ~Stream(); - - void initialize(); - void uninitialize(); - - void fft(); - // Preforms FFT on internal rdftData - }; - - struct Packet - { - double time; - // double min; - // double max; - double value; - - Packet( - double time = 0.0, - double value = 0.0); //, double min = 99999.9, double max = -99999.9 - }; - -public: - VideoAnalyzer( - const VideoAnalyzer::Options& options = VideoAnalyzer::Options()); - virtual ~VideoAnalyzer(); /// Set everything up, and open the input file. - virtual void initialize(); - - /// Stop processing and free everything. - virtual void uninitialize(); - - /// Begin processing. - virtual void start(); - - /// Stop processing. - virtual void stop(); - - /// Signals on VideoAnalyzer::Packet output - /// Raw FFT data is available via VideoAnalyzer::Stream->rdftData - Signal - PacketOut; - - /// Signals on analysis complete - NullSignal Complete; - - - virtual MediaCapture& reader(); - virtual Options& options(); - virtual std::string error() const; - -protected: - AVFrame* getGrayVideoFrame(); - - virtual void onReadComplete(void* sender); - virtual void onVideo(void* sender, VideoPacket& packet); - virtual void onAudio(void* sender, AudioPacket& packet); - - const char* className() const { return "VideoAnalyzer"; } - -protected: - mutable std::mutex _mutex; - - Options _options; - std::string _error; - MediaCapture _reader; - VideoAnalyzer::Stream* _video; - VideoAnalyzer::Stream* _audio; - VideoConverter* _videoConv; -}; - - -// --------------------------------------------------------------------- -// FFT Helpers -// Based on http://www.codeproject.com/Articles/6855/FFT-of-waveIn-audio-signals -// -inline double CalculateFrequencyIntensity(VideoAnalyzer::Stream& stream); -inline double CalculateCentroidFrequency(VideoAnalyzer::Stream& stream); - -inline double GetFrequencyIntensity(double re, double im); -inline double GetDecibels(double re, double im); -inline double GetAmplitude(double re, double im, int len); -inline double GetAmplitudeScaled(double re, double im, int len, int scale); - -#ifdef SCY_WIN -inline double log2(double n); -#endif - - -} // namespace av -} // namespace scy - - -#endif -#endif - - -// virtual void writeCSV(const VideoAnalyzer::Packet& packet);, double time -// std::ofstream _ofile; diff --git a/src/av/deprecated/include/scy/av/videocapture.h b/src/av/deprecated/include/scy/av/videocapture.h deleted file mode 100644 index 31c10e892..000000000 --- a/src/av/deprecated/include/scy/av/videocapture.h +++ /dev/null @@ -1,170 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// @addtogroup av -/// @{ - - -#ifndef SCY_AV_VideoCapture_H -#define SCY_AV_VideoCapture_H - - -#include "scy/av/format.h" -#include "scy/av/fpscounter.h" -#include "scy/av/icapture.h" -#include "scy/av/types.h" -#include "scy/bitwise.h" -#include "scy/interface.h" -#include -#include - -#ifdef HAVE_OPENCV -#include "opencv2/opencv.hpp" - -#include -#include - -#define HAVE_OPENCV_VIDEOCAPTURE - - -namespace scy { -namespace av { - - -// -// Video Capture -// - -/// Class for capturing video from cameras and files using OpenCV. -/// Do not use this class directly, use VideoCapture instead. -/// -/// To handle output packets listen in on the ICapture::emitter signal. -/// -/// Limitations:/// OpenCV doesn't support multi-thread capturing so -/// VideoCapture -/// instances should be created in the main thread. -/// File captures do not have this limitation. -/// Also avoid creating multiple instances using the same device. -/// Instead reuse the same instance, preferably using the -/// MediaFactory interface. -/// -/// Windows:/// OpenCV HighGUI DirectShow must be compiled with -/// VI_COM_MULTI_THREADED -/// defined otherwise capture there will be CoInitialize conflicts -/// with the DeviceManager. -class VideoCapture : public ICapture, public basic::Runnable -{ -public: - typedef std::shared_ptr - Ptr; /// Creates and opens the given device. - /// Should be created in the main thread. - VideoCapture(int deviceId); - - /// Creates and opens the given video file. - /// Can be created in any thread. - VideoCapture(const std::string& filename); - - /// Destroys the VideoCapture. - virtual ~VideoCapture(); - - /// Opens the VideoCapture. - bool open(bool whiny = true); - - - virtual void start(); - virtual void stop(); /// True when the system device is open. - bool opened() const; - - /// True when the internal thread is running. - bool running() const; - - - void getFrame(cv::Mat& frame, int width = 0, int height = 0); - - virtual void getEncoderFormat(Format& iformat); - - int deviceId() const; - std::string filename() const; - std::string name() const; - const scy::Error& error() const; - double fps() const; - int width(); - int height(); - cv::Mat lastFrame() const; - cv::VideoCapture& - capture(); /// Signals that the capture is closed in error. - Signal Error; - - -protected: - cv::Mat grab(); - virtual void run(); - - void setError(const std::string& error); - - friend class MediaFactory; - -private: - mutable std::mutex _mutex; - - std::string _filename; // Source file to capture from if any - int _deviceId; // Source device to capture from - bool _opened; - bool _started; - bool _stopping; - bool _capturing; - cv::Mat _frame; // Current video image - scy::Error _error; // Error message if any - FPSCounter _counter; - cv::VideoCapture _capture; - Thread _thread; -}; - - -typedef std::map VideoCaptureMap; - - -// -// Matrix Packet -// - - -class MatrixPacket : public VideoPacket -{ -public: - cv::Mat* mat; // For OpenCV generated packets. - // TODO: Use stream offset time instead of process time - // for consistency with AudioCapture for realtime pts calculation - - MatrixPacket(cv::Mat* mat, double time = time::clockSecs()) - : VideoPacket(reinterpret_cast(mat->data), - mat->rows * mat->step, mat->cols, mat->rows, time) - , mat(mat) - { - } - - MatrixPacket(char* data = nullptr, int size = 0, int width = 0, - int height = 0, double time = time::clockSecs()) - : VideoPacket(reinterpret_cast(data), size, width, - height, time) - , mat(nullptr){}; - - virtual IPacket* clone() const { return new MatrixPacket(*this); } - - virtual const char* className() const { return "MatrixPacket"; } -}; - - -} // namespace av -} // namespace scy - - -#endif -#endif // SCY_AV_VideoCapture_H - - -/// @\} diff --git a/src/av/deprecated/src/audiocapture.cpp b/src/av/deprecated/src/audiocapture.cpp deleted file mode 100644 index 5b3c39cb1..000000000 --- a/src/av/deprecated/src/audiocapture.cpp +++ /dev/null @@ -1,341 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// @addtogroup av -/// @{ - - -#include "scy/av/mediacapture.h" -#include "scy/logger.h" - -#ifdef HAVE_RTAUDIO - - -using std::endl; - - -namespace scy { -namespace av { - - -AudioCapture::AudioCapture(int deviceId, int channels, int sampleRate, - RtAudioFormat format) - : _deviceId(deviceId) - , _channels(channels) - , _sampleRate(sampleRate) - , _format(format) - , _opened(false) -{ - LTrace("Create") - - _iParams.deviceId = _deviceId; - _iParams.nChannels = _channels; - _iParams.firstChannel = 0; - - if (_audio.getDeviceCount() < 1) { - LWarn("No audio devices found!") - return; - } - - // Let RtAudio print messages to stderr. - _audio.showWarnings(true); - - // Open the audio stream or throw an exception. - open(); // channels, sampleRate - LTrace("Create: OK") -} - - -AudioCapture::~AudioCapture() -{ - LTrace("Destroy") -} - - -void AudioCapture::open() // int channels, int sampleRate, RtAudioFormat format -{ - if (isOpen()) - close(); - - std::lock_guard guard(_mutex); - LTrace("Opening: ", _channels, ": ", _sampleRate) - - // 1024 is a common frame size for many codecs. - unsigned int nBufferFrames = 1024; // 256, 512 - - RtAudio::StreamOptions options; - options.flags = RTAUDIO_SCHEDULE_REALTIME; - - // TODO: Implement planar audio format to pass the `RTAUDIO_NONINTERLEAVED` - // flag to RtAudio::StreamOptions. Some work will be required for the packet - // interface to support planar buffer formats. - - try { - _audio.openStream(nullptr, &_iParams, _format, _sampleRate, - &nBufferFrames, &AudioCapture::audioCallback, - (void*)this, &options, AudioCapture::errorCallback); - - _error = ""; - _opened = true; - LTrace("Opening: OK") - } catch (RtAudioError& e) { - setError("Cannot open audio capture: " + e.getMessage()); - } catch (...) { - setError("Cannot open audio capture."); - } -} - - -void AudioCapture::close() -{ - LTrace("Closing") - try { - std::lock_guard guard(_mutex); - _opened = false; - if (_audio.isStreamOpen()) - _audio.closeStream(); - LTrace("Closing: OK") - } catch (RtAudioError& e) { - setError("Cannot close audio capture: " + e.getMessage()); - } catch (...) { - setError("Cannot close audio capture."); - } -} - - -void AudioCapture::start() -{ - LTrace("Starting") - - if (!running()) { - try { - std::lock_guard guard(_mutex); - _audio.startStream(); - _error = ""; - LTrace("Starting: OK") - } catch (RtAudioError& e) { - setError("Cannot start audio capture: " + e.getMessage()); - } catch (...) { - setError("Cannot start audio capture."); - } - } -} - - -void AudioCapture::stop() -{ - LTrace("Stopping") - - if (running()) { - try { - std::lock_guard guard(_mutex); - LTrace("Stopping: Before") - _audio.stopStream(); - LTrace("Stopping: OK") - } catch (RtAudioError& e) { - setError("Cannot stop audio capture: " + e.getMessage()); - } catch (...) { - setError("Cannot stop audio capture."); - } - } -} - - -#if 0 -void AudioCapture::attach(const PacketDelegateBase& delegate) -{ - PacketSignal::attach(delegate); - LTrace("Added Delegate: ", refCount()) - if (refCount() == 1) - start(); -} - - -bool AudioCapture::detach(const PacketDelegateBase& delegate) -{ - if (PacketSignal::detach(delegate)) { - LTrace("Removed Delegate: ", refCount()) - if (refCount() == 0) - stop(); - LTrace("Removed Delegate: OK") - return true; - } - return false; -} -#endif - - -int AudioCapture::audioCallback(void* /* outputBuffer */, void* inputBuffer, - unsigned int nBufferFrames, double streamTime, - RtAudioStreamStatus status, void* data) -{ - auto self = reinterpret_cast(data); - AudioPacket packet; - - if (status) - LError("Stream over/underflow detected") - - assert(inputBuffer); - if (inputBuffer == nullptr) { - LError("Input buffer is NULL") - return 2; - } - - { - std::lock_guard guard(_mutex); - packet.setData((char*)inputBuffer, - nBufferFrames * self->_channels * sizeof(RtAudioFormat)); - packet.numSamples = nBufferFrames; - packet.time = streamTime; - } - - // STrace << "Captured audio packet: " - // << "\n\tPacket Ptr: " << inputBuffer - // << "\n\tPacket Size: " << packet.size() - // << "\n\tStream Time: " << packet.time - // << endl; - - LTrace("Emitting: ", packet.time) - self->emit(packet); - return 0; -} - - -void AudioCapture::errorCallback(RtAudioError::Type type, - const std::string& errorText) -{ - LError("Audio system error: ", errorText) -} - - -void AudioCapture::setError(const std::string& message, bool throwExec) -{ - LError("Error: ", message) - _error = message; - if (throwExec) - throw std::runtime_error(message); -} - - -RtAudioFormat AudioCapture::format() const -{ - std::lock_guard guard(_mutex); - return _format; -} - - -bool AudioCapture::isOpen() const -{ - std::lock_guard guard(_mutex); - return _opened; -} - - -bool AudioCapture::running() const -{ - std::lock_guard guard(_mutex); - return _audio.isStreamRunning(); -} - - -int AudioCapture::deviceId() const -{ - std::lock_guard guard(_mutex); - return _deviceId; -} - - -int AudioCapture::sampleRate() const -{ - std::lock_guard guard(_mutex); - return _sampleRate; -} - - -int AudioCapture::channels() const -{ - std::lock_guard guard(_mutex); - return _channels; -} - - -std::string AudioCapture::formatString() const -{ - // FFmpeg sample formats: `ffmpeg -sample_fmts` - // name depth - // u8 8 - // s16 16 - // s32 32 - // flt 32 - // dbl 64 - // u8p 8 - // s16p 16 - // s32p 32 - // fltp 32 - // dblp 64 - - bool planar = false; // planar audio not implemented - switch (format()) { - case RTAUDIO_SINT8: - return planar ? "u8p" : "u8"; - case RTAUDIO_SINT16: - return planar ? "s16p" : "s16"; - case RTAUDIO_SINT24: - return planar ? "s32p" : "s32"; - case RTAUDIO_SINT32: - return planar ? "s32p" : "s32"; - case RTAUDIO_FLOAT32: - return planar ? "fltp" : "flt"; - case RTAUDIO_FLOAT64: - return planar ? "dblp" : "dbl"; - } - assert(0 && "unsupported pixel format"); - return ""; -} - - -void AudioCapture::getAudioCodec(AudioCodec& icodec) -{ - icodec.channels = channels(); - icodec.sampleRate = sampleRate(); - icodec.sampleFmt = formatString(); -} - -void AudioCapture::getEncoderFormat(Format& iformat) -{ - iformat.name = "PCM"; - iformat.audio.enabled = true; - getAudioCodec(iformat.audio); - // bool planar = true; - // switch(_format) { - // case RTAUDIO_SINT8: - // iformat.audio.sampleFmt = planar ? "u8p" : "u8"; - // break; - // case RTAUDIO_SINT16: - // iformat.audio.sampleFmt = planar ? "s16p" : "s16"; - // break; - // case RTAUDIO_SINT24: - // iformat.audio.sampleFmt = planar ? "s32p" : "s32"; - // break; - // case RTAUDIO_SINT32: - // iformat.audio.sampleFmt = planar ? "s32p" : "s32"; - // break; - // case RTAUDIO_FLOAT32: - // iformat.audio.sampleFmt = planar ? "fltp" : "flt"; - // break; - // case RTAUDIO_FLOAT64: - // iformat.audio.sampleFmt = planar ? "dblp" : "dbl"; - // break; - // } -} - - -} // namespace av -} // namespace scy - - -#endif diff --git a/src/av/deprecated/src/devicemanager.cpp b/src/av/deprecated/src/devicemanager.cpp deleted file mode 100644 index a7a9420bb..000000000 --- a/src/av/deprecated/src/devicemanager.cpp +++ /dev/null @@ -1,569 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// @addtogroup av -/// @{ -// Implemented from libjingle r116 Feb 16, 2012 - - -#include "scy/av/devicemanager.h" - -#ifdef HAVE_RTAUDIO -#include "RtAudio.h" -#endif - - -using std::endl; - - -namespace scy { -namespace av { - -static const char* kFilteredAudioDevicesName[] = { - NULL, -}; - -// Initialize to empty string -const char IDeviceManager::kDefaultDeviceName[] = ""; - - -// -// Device -// - - -Device::Device() - : id(-1) -{ -} - - -Device::Device(const std::string& type, int id, const std::string& name, - const std::string& guid, bool isDefault, bool isAvailable) - : type(type) - , id(id) - , name(name) - , guid(guid) - , isDefault(isDefault) - , isAvailable(isAvailable) -{ -} - - -void Device::print(std::ostream& os) -{ - os << "Device[" << type << ": " << id << ": " << name << ": " << isDefault - << ": " << isAvailable << "]"; -} - - -// -// Device Manager -// - - -DeviceManager::DeviceManager() - : _watcher(nullptr) - , _initialized(false) -{ -} - - -DeviceManager::~DeviceManager() -{ - if (initialized()) - uninitialize(); - if (_watcher) - delete _watcher; -} - - -bool DeviceManager::initialize() -{ - if (!initialized()) { - if (watcher() && !watcher()->start()) - return false; - setInitialized(true); - } - return true; -} - - -void DeviceManager::uninitialize() -{ - if (initialized()) { - if (watcher()) - watcher()->stop(); - setInitialized(false); - } -} - - -int DeviceManager::getCapabilities() -{ - std::vector devices; - int caps = VIDEO_RECV; - if (getAudioInputDevices(devices) && !devices.empty()) { - caps |= AUDIO_SEND; - } - if (getAudioOutputDevices(devices) && !devices.empty()) { - caps |= AUDIO_RECV; - } - if (getVideoCaptureDevices(devices) && !devices.empty()) { - caps |= VIDEO_SEND; - } - return caps; -} - - -bool DeviceManager::getAudioInputDevices(std::vector& devices) -{ - return getAudioDevices(true, devices); -} - - -bool DeviceManager::getAudioOutputDevices(std::vector& devices) -{ - return getAudioDevices(false, devices); -} - - -bool DeviceManager::getAudioInputDevice(Device& out, const std::string& name, - int id) -{ - return getAudioDevice(true, out, name, id); -} - - -bool DeviceManager::getAudioInputDevice(Device& out, int id) -{ - return getAudioDevice(true, out, id); -} - - -bool DeviceManager::getAudioOutputDevice(Device& out, const std::string& name, - int id) -{ - return getAudioDevice(false, out, name, id); -} - - -bool DeviceManager::getAudioOutputDevice(Device& out, int id) -{ - return getAudioDevice(false, out, id); -} - - -bool DeviceManager::getVideoCaptureDevices(std::vector& devices) -{ - devices.clear(); -#if defined(ANDROID) || defined(IOS) - // TODO: Incomplete. Use ANDROID implementation for IOS to quiet compiler. - // On Android, we treat the camera(s) as a single device. Even if there are - // multiple cameras, that's abstracted away at a higher level. - Device dev("camera", "1"); // name and ID - devices.push_back(dev); -#else - return false; -#endif -} - - -#if 0 -bool DeviceManager::getAudioInputDevice(Device& out, const std::string& name, int id) -{ - // If the name is empty, return the default device. - if (name.empty()) - return getDefaultAudioInputDevice(out); - - std::vector devices; - getAudioInputDevices(devices); - return matchNameAndID(devices, out, name, id); -} - - -bool DeviceManager::getAudioOutputDevice(Device& out, const std::string& name, int id) -{ - // If the name is empty, return the default device. - if (name.empty()) - return getDefaultAudioOutputDevice(out); - - std::vector devices; - return getAudioOutputDevices(devices) && - matchNameAndID(devices, name, id); -} -#endif - - -bool DeviceManager::getVideoCaptureDevice(Device& out, int id) -{ - std::vector devices; - return getVideoCaptureDevices(devices) && matchID(devices, out, id); -} - - -bool DeviceManager::getVideoCaptureDevice(Device& out, const std::string& name, - int id) -{ - // If the name is empty, return the default device. - if (name.empty() || name == kDefaultDeviceName) { - return getDefaultVideoCaptureDevice(out); - } - - std::vector devices; - return getVideoCaptureDevices(devices) && - matchNameAndID(devices, out, name, id); - -#if 0 - for (std::vector::const_iterator it = devices.begin(); it != devices.end(); ++it) { - if (name == it->name) { - LInfo("Create VideoCapturer for ", name) - out = *it; - return true; - } - } - - // If the name is a valid path to a file, then we'll create a simulated device - // with the filename. The LmiMediaEngine will know to use a FileVideoCapturer - // for these devices. - if (talk_base::FileSystem::IsFile(name)) { - LInfo("Create FileVideoCapturer") - *out = FileVideoCapturer::CreateFileVideoCapturerDevice(name); - return true; - } -#endif -} - - -bool DeviceManager::getAudioDevices(bool input, std::vector& devs) -{ - devs.clear(); - -#if defined(ANDROID) - // Under Android, we don't access the device file directly. - // Arbitrary use 0 for the mic and 1 for the output. - // These ids are used in MediaEngine::SetSoundDevices(in, out); - // The strings are for human consumption. - if (input) { - devs.push_back(Device("audioin", "audiorecord", 0)); - } else { - devs.push_back(Device("audioout", "audiotrack", 1)); - } - return true; -#elif defined(HAVE_RTAUDIO) - - // Since we are using RtAudio for audio capture it's best to - // use RtAudio to enumerate devices to ensure indexes match. - RtAudio audio; - - // Determine the number of devices available - auto ndevices = audio.getDeviceCount(); - LTrace("Get audio devices: ", ndevices) - - // Scan through devices for various capabilities - RtAudio::DeviceInfo info; - for (unsigned i = 0; i <= ndevices; i++) { - try { - info = audio.getDeviceInfo(i); // may throw RtAudioError - - STrace << "Device:" - << "\n\tName: " << info.name - << "\n\tOutput Channels: " << info.outputChannels - << "\n\tInput Channels: " << info.inputChannels - << "\n\tDuplex Channels: " << info.duplexChannels - << "\n\tDefault Output: " << info.isDefaultOutput - << "\n\tDefault Input: " << info.isDefaultInput - << "\n\tProbed: " << info.probed << endl; - - if (info.probed == true && ((input && info.inputChannels > 0) || - (!input && info.outputChannels > 0))) { - - LTrace("Adding device: ", info.name) - Device dev( - (input ? "audioin" : "audioout"), i, info.name, "", - (input ? info.isDefaultInput : info.isDefaultOutput)); - devs.push_back(dev); - } - } catch (RtAudioError& e) { - SError << "Cannot probe audio device: " << e.getMessage() - << endl; - } - } - - return filterDevices(devs, kFilteredAudioDevicesName); -#endif -} - - -bool DeviceManager::getDefaultVideoCaptureDevice(Device& device) -{ - bool ret = false; - // We just return the first device. - std::vector devices; - ret = (getVideoCaptureDevices(devices) && !devices.empty()); - if (ret) { - device = devices[0]; - } - return ret; -} - - -bool DeviceManager::getAudioDevice(bool input, Device& out, - const std::string& name, int id) -{ - LTrace("Get audio device: ", id, ": ", name) - - // If the name is empty, return the default device id. - if (name.empty() || name == kDefaultDeviceName) { - // out = Device(input ? "audioin" : "audioout", -1, name); - // return true; - // input ? getDefaultAudioInputDevice(out) : - // getDefaultAudioOutputDevice(out); - return getAudioDevice(input, out, id); - } - - std::vector devices; - input ? getAudioInputDevices(devices) : getAudioOutputDevices(devices); - LTrace("Get audio devices: ", devices.size()) - return matchNameAndID(devices, out, name, id); -} - - -bool DeviceManager::getAudioDevice(bool input, Device& out, int id) -{ - std::vector devices; - input ? getAudioInputDevices(devices) : getAudioOutputDevices(devices); - LTrace("Get audio devices: ", devices.size()) - return matchID(devices, out, id); -} - - -#if 0 -bool DeviceManager::getDefaultAudioInputDevice(Device& device) -{ - bool ret = false; - // We just return the first device. - std::vector devices; - ret = (getAudioInputDevices(devices) && !devices.empty()); - if (ret) { - device = devices[0]; - } - return ret; -} - - -bool DeviceManager::getDefaultAudioOutputDevice(Device& device) -{ - bool ret = false; - // We just return the first device. - std::vector devices; - ret = (getAudioOutputDevices(devices) && !devices.empty()); - if (ret) { - device = devices[0]; - } - return ret; -} -#endif - - -bool DeviceManager::getDefaultAudioDevice(bool input, Device& device) -{ - bool ret = false; - std::vector devices; - ret = (getAudioDevices(input, devices) && !devices.empty()); - if (ret) { - // Use the first device by default - device = devices[0]; - - // Loop through devices to check if any are explicitly - // set as default - for (std::size_t i = 0; i < devices.size(); ++i) { - if (devices[i].isDefault) { - device = devices[i]; - } - } - } - return ret; -} - - -bool DeviceManager::getDefaultAudioInputDevice(Device& device) -{ - return getDefaultAudioDevice(true, device); -} - - -bool DeviceManager::getDefaultAudioOutputDevice(Device& device) -{ - return getDefaultAudioDevice(false, device); -} - -// bool DeviceManager::getDefaultAudioInputDevice(Device& device) -// { -// //device = Device("audioin", -1, "None"); -// //return true; -// return getDefaultAudioDevice(true, device); -// } -// -// -// bool DeviceManager::getDefaultAudioOutputDevice(Device& device) -// { -// //device = Device("audioout", -1, "None"); -// //return true; -// return getDefaultAudioDevice(false, device); -// } - - -bool DeviceManager::shouldDeviceBeIgnored(const std::string& deviceName, - const char* const exclusionList[]) -{ - // If exclusionList is empty return directly. - if (!exclusionList) - return false; - - int i = 0; - while (exclusionList[i]) { - if (util::icompare(deviceName, exclusionList[i]) == 0) { - LDebug("Ignoring device ", deviceName) - return true; - } - ++i; - } - return false; -} - - -bool DeviceManager::filterDevices(std::vector& devices, - const char* const exclusionList[]) -{ - for (auto it = devices.begin(); it != devices.end();) { - if (shouldDeviceBeIgnored(it->name, exclusionList)) { - it = devices.erase(it); - } else { - ++it; - } - } - return !devices.empty(); -} - - -bool DeviceManager::matchID(std::vector& devices, Device& out, int id) -{ - for (unsigned i = 0; i < devices.size(); ++i) { - if (devices[i].id == id) { - out = devices[i]; - return true; - } - } - - // if (id >= 0 && !devices.empty() && devices.size() >= (id + 1)) { - // out = devices[id]; - // return true; - //} - return false; -} - - -bool DeviceManager::matchNameAndID(std::vector& devices, Device& out, - const std::string& name, int id) -{ - LTrace("Match name and ID: ", name, ": ", id) - - bool ret = false; - for (int i = 0; i < static_cast(devices.size()); ++i) { - LTrace("Match name and ID: Checking: ", devices[i].name) - if (devices[i].name == name) { - // The first device matching the given name will be returned, - // but we will try and match the given ID as well. - // if (out.id == -1) - out = devices[i]; - LTrace("Match name and ID: Match: ", out.name) - - ret = true; - if (id == -1 || id == i) { - - LTrace("Match name and ID: Match ID: ", out.name) - break; - } - } - } - - return ret; -} - - -void DeviceManager::setWatcher(DeviceWatcher* watcher) -{ - if (_watcher) - delete _watcher; - _watcher = watcher; - //_watcher.reset(watcher); -} - - -DeviceWatcher* DeviceManager::watcher() -{ - return _watcher; //_watcher.get(); -} - - -void DeviceManager::setInitialized(bool initialized) -{ - _initialized = initialized; -} - - -void DeviceManager::print(std::ostream& ost) -{ - std::vector devs; - getAudioInputDevices(devs); - ost << "Audio input devices: " << endl; - for (std::size_t i = 0; i < devs.size(); ++i) - devs[i].print(ost); - - getAudioOutputDevices(devs); - ost << "Audio output devices: " << endl; - for (std::size_t i = 0; i < devs.size(); ++i) - devs[i].print(ost); - - getVideoCaptureDevices(devs); - ost << "Video capture devices: " << endl; - for (std::size_t i = 0; i < devs.size(); ++i) - devs[i].print(ost); -} - - -} // namespace av -} // namespace scy - - -/* - * libjingle - * Copyright 2004 Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ diff --git a/src/av/deprecated/src/devicemanager_linux.cpp b/src/av/deprecated/src/devicemanager_linux.cpp deleted file mode 100644 index 6db085d2b..000000000 --- a/src/av/deprecated/src/devicemanager_linux.cpp +++ /dev/null @@ -1,570 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// @addtogroup av -/// @{ -// Implemented from libjingle r116 Feb 16, 2012 - - -#include "scy/av/devicemanager_linux.h" -#include "scy/filesystem.h" - -#include - -#include -#include -#include -#include -#include -#include -#include - -// #include -// #include "talk/base/linux.h" -// #include "talk/base/logging.h" -// #include "talk/base/fileutils.h" -// #include "talk/base/pathutils.h" -// #include "talk/base/physicalsocketserver.h" -// #include "talk/base/stream.h" -// #include "talk/base/stringutils.h" -// #include "talk/base/thread.h" -// #include "talk/session/phone/libudevsymboltable.h" -// #include "talk/session/phone/mediacommon.h" -// #include "talk/session/phone/v4llookup.h" -// #include "talk/sound/platformsoundsystem.h" -// #include "talk/sound/platformsoundsystemfactory.h" -// #include "talk/sound/sounddevicelocator.h" -// #include "talk/sound/soundsysteminterface.h" -using std::endl; - - -namespace scy { -namespace av { - - -IDeviceManager* DeviceManagerFactory::create() -{ - return new LinuxDeviceManager(); -} - - -// class LinuxDeviceWatcher -// : public DeviceWatcher, -// private talk_base::Dispatcher { -// public: -// explicit LinuxDeviceWatcher(IDeviceManager* dm); -// virtual ~LinuxDeviceWatcher(); -// virtual bool start(); -// virtual void stop(); -// -// private: -// virtual uint32 GetRequestedEvents(); -// virtual void OnPreEvent(uint32 ff); -// virtual void OnEvent(uint32 ff, int err); -// virtual int GetDescriptor(); -// virtual bool IsDescriptorClosed(); -// -// IDeviceManager* manager_; -// LibUDevSymbolTable libudev_; -// struct udev* udev_; -// struct udev_monitor* udev_monitor_; -// bool registered_; -// }; -// -// #define LATE(sym) LATESYM_GET(LibUDevSymbolTable, &libudev_, sym) - - -static const char* const kFilteredAudioDevicesName[] = { -#if defined(CHROMEOS) - "surround40:", "surround41:", "surround50:", "surround51:", "surround71:", - "iec958:", // S/PDIF -#endif - NULL, -}; -static const char* kFilteredVideoDevicesName[] = { - NULL, -}; - - -LinuxDeviceManager::LinuxDeviceManager() -//: sound_system_(new PlatformSoundSystemFactory()) -{ - // setWatcher(new LinuxDeviceWatcher(this)); -} - - -LinuxDeviceManager::~LinuxDeviceManager() -{ -} - - -// bool LinuxDeviceManager::getAudioDevices(bool input, std::vector& -// devs) -// { -// devs.clear(); -// -// NEW METHOD: -// -// if (!sound_system_.get()) { -// return false; -// } -// SoundSystemInterface::SoundDeviceLocatorList list; -// bool success; -// if (input) { -// success = sound_system_->EnumerateCaptureDevices(&list); -// } else { -// success = sound_system_->EnumeratePlaybackDevices(&list); -// } -// if (!success) { -// LError("Can't enumerate devices") -// sound_system_.release(); -// return false; -// } -// // We have to start the index at 1 because GIPS VoiceEngine puts the -// default -// // device at index 0, but Enumerate(Capture|Playback)Devices does not -// include -// // a locator for the default device. -// int index = 1; -// for (SoundSystemInterface::SoundDeviceLocatorList::iterator i = -// list.begin(); -// i != list.end(); -// ++i, ++index) { -// devs.push_back(Device((*i)->name(), index)); -// } -// SoundSystemInterface::ClearSoundDeviceLocatorList(&list); -// sound_system_.release(); -// -// OLD METHOD: -// -// int card = -1, dev = -1; -// snd_ctl_t *handle = NULL; -// snd_pcm_info_t *pcminfo = NULL; -// -// snd_pcm_info_malloc(&pcminfo); -// -// while (true) { -// if (snd_card_next(&card) != 0 || card < 0) -// break; -// -// char *card_name; -// if (snd_card_get_name(card, &card_name) != 0) -// continue; -// -// char card_string[7]; -// snprintf(card_string, sizeof(card_string), "hw:%d", card); -// if (snd_ctl_open(&handle, card_string, 0) != 0) -// continue; -// -// while (true) { -// if (snd_ctl_pcm_next_device(handle, &dev) < 0 || dev < 0) -// break; -// snd_pcm_info_set_device(pcminfo, dev); -// snd_pcm_info_set_subdevice(pcminfo, 0); -// snd_pcm_info_set_stream(pcminfo, input ? SND_PCM_STREAM_CAPTURE : -// SND_PCM_STREAM_PLAYBACK); -// if (snd_ctl_pcm_info(handle, pcminfo) != 0) -// continue; -// -// char name[128]; -// sprintfn(name, sizeof(name), "%s (%s)", card_name, -// snd_pcm_info_get_name(pcminfo)); -// // TODO(tschmelcher): We might want to identify devices with -// something -// // more specific than just their card number (e.g., the PCM names -// that -// // aplay -L prints out). -// devs.push_back(Device(input ? "audioin" : "audioout", name, -// card)); -// -// Log("debug") << "Found device: id = " << card << ", name = " << -// name << endl; -// } -// snd_ctl_close(handle); -// } -// snd_pcm_info_free(pcminfo); -// -// return filterDevices(devs, kFilteredAudioDevicesName); -// } - - -static const std::string kVideoMetaPathK2_4("/proc/video/dev/"); -static const std::string kVideoMetaPathK2_6("/sys/class/video4linux/"); - - -enum MetaType -{ - M2_4, - M2_6, - NONE -}; - - -bool isV4L2Device(const std::string& devicePath) -{ - // Check device major/minor numbers are in the range for video devices - struct stat s; - if (lstat(devicePath.c_str(), &s) != 0 || !S_ISCHR(s.st_mode)) - return false; - int video_fd = -1; - bool is_v4l2 = false; - - // Check major/minur device numbers are in range for video device - if (major(s.st_rdev) == 81) { - dev_t num = minor(s.st_rdev); - if (num <= 63 && num >= 0) { - video_fd = ::open(devicePath.c_str(), O_RDONLY | O_NONBLOCK); - if ((video_fd >= 0) || (errno == EBUSY)) { - ::v4l2_capability video_caps; - memset(&video_caps, 0, sizeof(video_caps)); - if ((errno == EBUSY) || - (::ioctl(video_fd, VIDIOC_QUERYCAP, &video_caps) >= 0 && - (video_caps.capabilities & V4L2_CAP_VIDEO_CAPTURE))) { - SInfo << "Found V4L2 capture device " << devicePath; - is_v4l2 = true; - } else { - SError << "VIDIOC_QUERYCAP failed for " << devicePath; - } - } else { - SError << "Failed to open " << devicePath; - } - } - } - if (video_fd >= 0) - ::close(video_fd); - return is_v4l2; -} - -static std::string trim(const std::string& s, const std::string& drop = " \t") -{ - std::string::size_type first = s.find_first_not_of(drop); - std::string::size_type last = s.find_last_not_of(drop); - - if (first == std::string::npos || last == std::string::npos) - return std::string(""); - - return s.substr(first, last - first + 1); -} - - -static void scanDeviceDirectory(const std::string& devdir, - std::vector& devices) -{ - std::vector nodes; - fs::readdir(devdir, nodes); - for (auto& filename : nodes) { - std::string deviceName = devdir + filename; - if (filename.find("video") == 0 && isV4L2Device(deviceName)) { - devices.push_back(Device("video", devices.size(), deviceName)); - } - } -} - - -static std::string getVideoDeviceNameK2_6(const std::string& deviceMetaPath) -{ - std::ifstream metaFile(deviceMetaPath); - if (metaFile.is_open()) { - std::string deviceName; - if (std::getline(metaFile, deviceName)) { - return deviceName; - } - metaFile.close(); - } - - LError("Failed to read V4L2 device meta ", deviceMetaPath) - return ""; -} - -static std::string getVideoDeviceNameK2_4(const std::string& deviceMetaPath) -{ - // FIXME: Port to our API - - // talk_base::ConfigParser::MapVector all_values; - // - // talk_base::ConfigParser config_parser; - // talk_base::FileStream* file_stream = - // talk_base::Filesystem::OpenFile(deviceMetaPath, "r"); - // - // if (file_stream == NULL) return ""; - // - // config_parser.Attach(file_stream); - // config_parser.Parse(&all_values); - // - // for (talk_base::ConfigParser::MapVector::iterator i = all_values.begin(); - // i != all_values.end(); ++i) { - // talk_base::ConfigParser::SimpleMap::iterator deviceName_i = - // i->find("name"); - // - // if (deviceName_i != i->end()) { - // return deviceName_i->second; - // } - // } - - return ""; -} - - -static std::string getVideoDeviceName(MetaType meta, - const std::string& deviceFileName) -{ - std::string deviceMetaPath; - std::string deviceName; - std::string metaFilePath; - - if (meta == M2_6) { - metaFilePath = kVideoMetaPathK2_6 + deviceFileName + "/name"; - - LInfo("Trying " + metaFilePath) - deviceName = getVideoDeviceNameK2_6(metaFilePath); - if (deviceName.empty()) { - metaFilePath = kVideoMetaPathK2_6 + deviceFileName + "/model"; - - LInfo("Trying ", metaFilePath) - deviceName = getVideoDeviceNameK2_6(metaFilePath); - } - } else { - metaFilePath = kVideoMetaPathK2_4 + deviceFileName; - LInfo("Trying ", metaFilePath) - deviceName = getVideoDeviceNameK2_4(metaFilePath); - } - - if (deviceName.empty()) { - deviceName = "/dev/" + deviceFileName; - SError << "Device name not found, defaulting to device path: " - << deviceName << endl; - } - - LInfo("Name for " << deviceFileName << " is ", deviceName) - - return trim(deviceName); -} - - -static void scanV4L2Devices(std::vector& devices) -{ - LInfo("Enumerating V4L2 devices") - - MetaType meta; - std::string metadataDir; - - if (fs::exists(kVideoMetaPathK2_6)) { - meta = M2_6; - metadataDir = kVideoMetaPathK2_6; - } else if (fs::exists(kVideoMetaPathK2_4)) { - meta = M2_4; - metadataDir = kVideoMetaPathK2_4; - } else { - meta = NONE; - } - - if (meta != NONE) { - LInfo("V4L2 device metadata found at ", metadataDir) - - std::vector nodes; - fs::readdir(metadataDir, nodes); - for (auto& filename : nodes) { - LDebug("Checking video device ", filename) - if (filename.find("video") == 0) { - std::string devicePath = "/dev/" + filename; - if (isV4L2Device(devicePath)) { - devices.push_back(Device("video", devices.size(), - getVideoDeviceName(meta, filename), - devicePath)); - } - } - } - } else { - LError("Unable to detect v4l2 metadata directory") - } - - if (devices.size() == 0) { - LInfo("Plan B. Scanning all video devices in /dev directory") - scanDeviceDirectory("/dev/", devices); - } - - LInfo("Total V4L2 devices found : ", devices.size()) -} - - -bool LinuxDeviceManager::getCameras(std::vector& devices) -{ - devices.clear(); - scanV4L2Devices(devices); - return filterDevices(devices, kFilteredVideoDevicesName); -} - - -// LinuxDeviceWatcher::LinuxDeviceWatcher(IDeviceManager* dm) -// : DeviceWatcher(dm), -// manager_(dm), -// udev_(NULL), -// udev_monitor_(NULL), -// registered_(false) { -// } -// -// -// LinuxDeviceWatcher::~LinuxDeviceWatcher() { -// } -// -// -// bool LinuxDeviceWatcher::start() { -// // We deliberately return true in the failure paths here because libudev -// is -// // not a critical component of a Linux system so it may not be -// present/usable, -// // and we don't want to halt LinuxDeviceManager initialization in such a -// case. -// if (!libudev_.Load()) { -// Log("warn") << "libudev not present/usable; LinuxDeviceWatcher -// disabled" << endl; -// return true; -// } -// udev_ = LATE(udev_new)(); -// if (!udev_) { -// LError("udev_new()") -// return true; -// } -// // The second argument here is the event source. It can be either -// "kernel" or -// // "udev", but "udev" is the only correct choice. Apps listen on udev and -// the -// // udev daemon in turn listens on the kernel. -// udev_monitor_ = LATE(udev_monitor_new_from_netlink)(udev_, "udev"); -// if (!udev_monitor_) { -// LError("udev_monitor_new_from_netlink()") -// return true; -// } -// // We only listen for changes in the video devices. Audio devices are -// more or -// // less unimportant because receiving device change notifications really -// only -// // matters for broadcasting updated send/recv capabilities based on -// whether -// // there is at least one device available, and almost all computers have -// at -// // least one audio device. Also, PulseAudio device notifications don't -// come -// // from the udev daemon, they come from the PulseAudio daemon, so we'd -// only -// // want to listen for audio device changes from udev if using ALSA. For -// // simplicity, we don't bother with any audio stuff at all. -// if (LATE(udev_monitor_filter_add_match_subsystem_devtype)(udev_monitor_, -// "video4linux", -// NULL) < 0) { -// SError << "udev_monitor_filter_add_match_subsystem_devtype()" << -// endl; -// return true; -// } -// if (LATE(udev_monitor_enable_receiving)(udev_monitor_) < 0) { -// LError("udev_monitor_enable_receiving()") -// return true; -// } -// static_cast( -// talk_base::Thread::Current()->socketserver())->Add(this); -// registered_ = true; -// return true; -// } -// -// -// void LinuxDeviceWatcher::stop() { -// if (registered_) { -// static_cast( -// talk_base::Thread::Current()->socketserver())->Remove(this); -// registered_ = false; -// } -// if (udev_monitor_) { -// LATE(udev_monitor_unref)(udev_monitor_); -// udev_monitor_ = NULL; -// } -// if (udev_) { -// LATE(udev_unref)(udev_); -// udev_ = NULL; -// } -// libudev_.Unload(); -// } -// -// -// uint32 LinuxDeviceWatcher::GetRequestedEvents() { -// return talk_base::DE_READ; -// } -// -// -// void LinuxDeviceWatcher::OnPreEvent(uint32 ff) { -// // Nothing to do. -// } -// -// -// void LinuxDeviceWatcher::OnEvent(uint32 ff, int err) { -// udev_device* device = LATE(udev_monitor_receive_device)(udev_monitor_); -// if (!device) { -// // Probably the socket connection to the udev daemon was terminated -// (perhaps -// // the daemon crashed or is being restarted?). -// LOG_ERR(LS_WARNING) << "udev_monitor_receive_device()"; -// // Stop listening to avoid potential livelock (an fd with EOF in it -// is -// // always considered readable). -// static_cast( -// talk_base::Thread::Current()->socketserver())->Remove(this); -// registered_ = false; -// return; -// } -// // Else we read the device successfully. -// -// // Since we already have our own filesystem-based device enumeration -// code, we -// // simply re-enumerate rather than inspecting the device event. -// LATE(udev_device_unref)(device); -// manager_->SignalDevicesChange(); -// } -// -// -// int LinuxDeviceWatcher::GetDescriptor() { -// return LATE(udev_monitor_get_fd)(udev_monitor_); -// } -// -// -// bool LinuxDeviceWatcher::IsDescriptorClosed() { -// // If it is closed then we will just get an error in -// // udev_monitor_receive_device and unregister, so we don't need to check -// for -// // it separately. -// return false; -// } - - -} // namespace av -} // namespace scy - - -/* - * libjingle - * Copyright 2004 Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/src/av/deprecated/src/devicemanager_mac.cpp b/src/av/deprecated/src/devicemanager_mac.cpp deleted file mode 100644 index 06f6983a6..000000000 --- a/src/av/deprecated/src/devicemanager_mac.cpp +++ /dev/null @@ -1,240 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// @addtogroup av -/// @{ -// Implemented from libjingle r116 Feb 16, 2012 - - -#include "scy/av/devicemanager_mac.h" - -#include -#include - -// #include "talk/base/logging.h" -// #include "talk/base/stringutils.h" -// #include "talk/base/thread.h" -// #include "talk/base/mediacommon.h" -using std::endl; - -class DeviceWatcherImpl; - -namespace scy { -namespace av { - - -IDeviceManager* DeviceManagerFactory::create() -{ - return new MacDeviceManager(); -} - - -class MacDeviceWatcher : public DeviceWatcher -{ -public: - explicit MacDeviceWatcher(IDeviceManager* dm); - virtual ~MacDeviceWatcher(); - virtual bool start(); - virtual void stop(); - -private: - IDeviceManager* manager_; - DeviceWatcherImpl* impl_; -}; - - -static const char* kFilteredAudioDevicesName[] = { - NULL, -}; -// TODO: Try to get hold of a copy of Final Cut to understand -// why we crash while scanning their components on OS X. -static const char* const kFilteredVideoDevicesName[] = { - "Google Camera Adapter", // Our own magiccams - "DVCPRO HD", // Final cut - "Sonix SN9C201p", // Crashes in OpenAComponent and CloseComponent - NULL, -}; -static const int kVideoDeviceOpenAttempts = 3; -static const std::uint32_t kAudioDeviceNameLength = 64; -// Obj-C functions defined in DeviceManager_MAC.mm -// TODO: have a shared header for these function defines. -extern DeviceWatcherImpl* CreateDeviceWatcherCallback(IDeviceManager* dm); -extern void ReleaseDeviceWatcherCallback(DeviceWatcherImpl* impl); -extern bool GetAVFoundationVideoDevices(std::vector* out); -// static bool getAudioDeviceIDs(bool inputs, std::vector* out); -// static bool getAudioDeviceName(AudioDeviceID id, bool input, std::string* -// out); - - -MacDeviceManager::MacDeviceManager() -{ - setWatcher(new MacDeviceWatcher(this)); -} - - -MacDeviceManager::~MacDeviceManager() -{ -} - - -bool MacDeviceManager::getCameras(std::vector& devices) -{ - devices.clear(); - if (!GetAVFoundationVideoDevices(&devices)) { - return false; - } - return filterDevices(devices, kFilteredVideoDevicesName); -} - - -// bool MacDeviceManager::getAudioDevices(bool input, -// std::vector& devs) { -// devs.clear(); -// std::vector dev_ids; -// bool ret = getAudioDeviceIDs(input, &dev_ids); -// if (!ret) { -// return false; -// } -// for (std::size_t i = 0; i < dev_ids.size(); ++i) { -// std::string name; -// if (getAudioDeviceName(dev_ids[i], input, &name)) { -// devs.push_back(Device(name, dev_ids[i])); -// } -// } -// return filterDevices(devs, kFilteredAudioDevicesName); -// } -// -// -// static bool getAudioDeviceIDs(bool input, -// std::vector* out_dev_ids) { -// std::uint32_t propsize; -// OSErr err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, -// &propsize, NULL); -// if (0 != err) { -// SError << "Couldn't get information about property, " -// << "so no device list acquired." << endl; -// return false; -// } -// -// std::size_t num_devices = propsize / sizeof(AudioDeviceID); -// auto device_ids = new AudioDeviceID[num_devices]; -// // talk_base::scoped_array device_ids( -// // new AudioDeviceID[num_devices]); -// -// err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, -// &propsize, device_ids); //.get() -// if (0 != err) { -// SError << "Failed to get device ids, " -// << "so no device listing acquired." << endl; -// delete device_ids; -// return false; -// } -// -// for (std::size_t i = 0; i < num_devices; ++i) { -// AudioDeviceID an_id = device_ids[i]; -// // find out the number of channels for this direction -// // (input/output) on this device - -// // we'll ignore anything with no channels. -// err = AudioDeviceGetPropertyInfo(an_id, 0, input, -// kAudioDevicePropertyStreams, -// &propsize, NULL); -// if (0 == err) { -// unsigned num_channels = propsize / sizeof(AudioStreamID); -// if (0 < num_channels) { -// out_dev_ids->push_back(an_id); -// } -// } else { -// SError << "No property info for stream property for device id " -// << an_id << "(input == " << input -// << "), so not including it in the list." << endl; -// } -// } -// -// delete device_ids; -// return true; -// } -// -// -// static bool getAudioDeviceName(AudioDeviceID id, -// bool input, -// std::string* out_name) { -// std::uint32_t nameLength = kAudioDeviceNameLength; -// char name[kAudioDeviceNameLength + 1]; -// OSErr err = AudioDeviceGetProperty(id, 0, input, -// kAudioDevicePropertyDeviceName, -// &nameLength, name); -// if (0 != err) { -// LError("No name acquired for device id ", id) -// return false; -// } -// -// *out_name = name; -// return true; -// } - - -MacDeviceWatcher::MacDeviceWatcher(IDeviceManager* manager) - : DeviceWatcher(manager) - , manager_(manager) - , impl_(NULL) -{ -} - - -MacDeviceWatcher::~MacDeviceWatcher() -{ -} - - -bool MacDeviceWatcher::start() -{ - if (!impl_) { - impl_ = CreateDeviceWatcherCallback(manager_); - } - return impl_ != NULL; -} - - -void MacDeviceWatcher::stop() -{ - if (impl_) { - ReleaseDeviceWatcherCallback(impl_); - impl_ = NULL; - } -} - - -} // namespace av -} // namespace scy - - -/* - * libjingle - * Copyright 2004 Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/src/av/deprecated/src/devicemanager_mac.mm b/src/av/deprecated/src/devicemanager_mac.mm deleted file mode 100644 index 96c791f5e..000000000 --- a/src/av/deprecated/src/devicemanager_mac.mm +++ /dev/null @@ -1,198 +0,0 @@ -/* - * libjingle - * Copyright 2010, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -// support GCC compiler -#ifndef __has_feature -#define __has_feature(x) 0 -#endif - -// #include "talk/media/devices/devicemanager.h" -#include "scy/av/devicemanager.h" - -#import -#ifdef __MAC_OS_X_VERSION_MAX_ALLOWED -#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 - #import -#endif -#endif -#import - -// #include "webrtc/base/logging.h" -#include "scy/logger.h" - -@interface DeviceWatcherImpl : NSObject { - @private - scy::av::IDeviceManager* manager_; -} -- (id)init:(scy::av::IDeviceManager*)manager; -- (void)onDevicesChanged:(NSNotification*)notification; -@end - -@implementation DeviceWatcherImpl -- (id)init:(scy::av::IDeviceManager*)manager { - if ((self = [super init])) { - assert(manager != NULL); - manager_ = manager; - [[NSNotificationCenter defaultCenter] - addObserver:self - selector:@selector(onDevicesChanged:) - name:QTCaptureDeviceWasConnectedNotification - object:nil]; - [[NSNotificationCenter defaultCenter] - addObserver:self - selector:@selector(onDevicesChanged:) - name:QTCaptureDeviceWasDisconnectedNotification - object:nil]; - } - return self; -} - -- (void)dealloc { - [[NSNotificationCenter defaultCenter] removeObserver:self]; -#if !__has_feature(objc_arc) - [super dealloc]; -#endif -} -- (void)onDevicesChanged:(NSNotification*)notification { - bool isVideo = true; - bool isConnect = true; - manager_->DevicesChanged.emit(manager_, isVideo, isConnect); //SignalDevicesChange(); -} -@end - -namespace scy { -namespace av { - -DeviceWatcherImpl* CreateDeviceWatcherCallback( - IDeviceManager* manager) { - DeviceWatcherImpl* impl; -#if !__has_feature(objc_arc) - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; -#else - @autoreleasepool -#endif - { impl = [[DeviceWatcherImpl alloc] init:manager]; } -#if !__has_feature(objc_arc) - [pool drain]; -#endif - return impl; -} - -void ReleaseDeviceWatcherCallback(DeviceWatcherImpl* watcher) { -#if !__has_feature(objc_arc) - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - [watcher release]; - [pool drain]; -#endif -} - -bool GetQTKitVideoDevices(std::vector* devices) { -#if !__has_feature(objc_arc) - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; -#else - @autoreleasepool -#endif - { - NSArray* qt_capture_devices = - [QTCaptureDevice inputDevicesWithMediaType:QTMediaTypeVideo]; - NSUInteger count = [qt_capture_devices count]; - SInfo << count << " capture device(s) found:"; - for (QTCaptureDevice* qt_capture_device in qt_capture_devices) { - static NSString* const kFormat = @"localizedDisplayName: \"%@\", " - @"modelUniqueID: \"%@\", uniqueID \"%@\", isConnected: %d, " - @"isOpen: %d, isInUseByAnotherApplication: %d"; - NSString* info = [NSString - stringWithFormat:kFormat, - [qt_capture_device localizedDisplayName], - [qt_capture_device modelUniqueID], - [qt_capture_device uniqueID], - [qt_capture_device isConnected], - [qt_capture_device isOpen], - [qt_capture_device isInUseByAnotherApplication]]; - SInfo << [info UTF8String]; - - std::string name([[qt_capture_device localizedDisplayName] UTF8String]); - devices->push_back( - Device("video", devices->size() - 1, name)); //[[capture_device uniqueID] UTF8String] - } - } -#if !__has_feature(objc_arc) - [pool drain]; -#endif - return true; -} - -bool GetAVFoundationVideoDevices(std::vector* devices) { -#ifdef __MAC_OS_X_VERSION_MAX_ALLOWED -#if __MAC_OS_X_VERSION_MAX_ALLOWED >=1070 - if (![MediaCaptureDevice class]) { - // Fallback to using QTKit if AVFoundation is not available - return GetQTKitVideoDevices(devices); - } -#if !__has_feature(objc_arc) - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; -#else - @autoreleasepool -#endif - { - NSArray* capture_devices = [MediaCaptureDevice devices]; - SInfo << [capture_devices count] << " capture device(s) found:"; - for (MediaCaptureDevice* capture_device in capture_devices) { - if ([capture_device hasMediaType:AVMediaTypeVideo] || - [capture_device hasMediaType:AVMediaTypeMuxed]) { - static NSString* const kFormat = @"localizedName: \"%@\", " - @"modelID: \"%@\", uniqueID \"%@\", isConnected: %d, " - @"isInUseByAnotherApplication: %d"; - NSString* info = [NSString - stringWithFormat:kFormat, - [capture_device localizedName], - [capture_device modelID], - [capture_device uniqueID], - [capture_device isConnected], - [capture_device isInUseByAnotherApplication]]; - SInfo << [info UTF8String]; - - std::string name([[capture_device localizedName] UTF8String]); - devices->push_back( - Device("video", devices->size() - 1, name)); //[[capture_device uniqueID] UTF8String] - } - } - } -#if !__has_feature(objc_arc) - [pool drain]; -#endif - return true; -#else // __MAC_OS_X_VERSION_MAX_ALLOWED >=1070 - return GetQTKitVideoDevices(devices); -#endif // __MAC_OS_X_VERSION_MAX_ALLOWED >=1070 -#else // __MAC_OS_X_VERSION_MAX_ALLOWED - return GetQTKitVideoDevices(devices); -#endif // __MAC_OS_X_VERSION_MAX_ALLOWED -} - -} // namespace av -} // namespace scy diff --git a/src/av/deprecated/src/devicemanager_win32.cpp b/src/av/deprecated/src/devicemanager_win32.cpp deleted file mode 100644 index 55a2e6198..000000000 --- a/src/av/deprecated/src/devicemanager_win32.cpp +++ /dev/null @@ -1,780 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// @addtogroup av -/// @{ - - -#include "scy/av/devicemanager_win32.h" -#include "scy/platform.h" - -//#ifdef HAVE_RTAUDIO - -#include // DBT_* & DEV_* -#include -#include -#include // KSCATEGORY_* -#include - - -using std::endl; - - -namespace scy { -namespace av { - - -static const char* const kFilteredVideoDevicesName[] = { - "Google Camera Adapter", // Google magiccams - "Asus virtual Camera", // Bad Asus desktop virtual cam - "Bluetooth Video", // Bad Sony viao bluetooth sharing driver - NULL, -}; -static const char kUsbDevicePathPrefix[] = "\\\\?\\usb"; -static bool getDevicesWin32(const CLSID& catid, std::vector& out); - - -IDeviceManager* DeviceManagerFactory::create() -{ - return new Win32DeviceManager(); -} - - -// -// Win32 Device Manager -// - - -Win32DeviceManager::Win32DeviceManager() - : _needCoUninitialize(false) -{ - LTrace("Create") - - // FIXME: Not receiving WM_DEVICECHANGE in our console applications - setWatcher(new Win32DeviceWatcher(this)); -} - - -Win32DeviceManager::~Win32DeviceManager() -{ - LTrace("Destroy") -} - - -bool Win32DeviceManager::initialize() -{ - LTrace("Initializing") - if (!initialized()) { - HRESULT hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED); - // HRESULT hr = CoInitialize(nullptr); - _needCoUninitialize = SUCCEEDED(hr); - if (FAILED(hr)) { - if (hr != RPC_E_CHANGED_MODE) { - LError("CoInitialize failed, hr=", hr) - return false; - } else - LWarn("CoInitialize Changed Mode") - } - if (watcher() && !watcher()->start()) { - LError("Cannot start watcher") - return false; - } - setInitialized(true); - } - LTrace("Initializing: OK") - return true; -} - - -void Win32DeviceManager::uninitialize() -{ - LTrace("Uninitializing") - - if (initialized()) { - if (watcher()) - watcher()->stop(); - if (_needCoUninitialize) { - CoUninitialize(); - _needCoUninitialize = false; - } - setInitialized(false); - } - LTrace("Uninitializing: OK") -} - - -bool Win32DeviceManager::getCameras(std::vector& devices) -{ - devices.clear(); - if (!getDevicesWin32(CLSID_VideoInputDeviceCategory, devices)) - return false; - return filterDevices(devices, kFilteredVideoDevicesName); -} - -#define ARRAY_SIZE(x) (static_cast((sizeof(x) / sizeof(x[0])))) - - -bool Win32DeviceManager::getDefaultCamera(Device& device) -{ - bool ret = false; - // If there are multiple capture devices, we want the first USB device. - // This avoids issues with defaulting to virtual cameras or grabber cards. - std::vector devices; - ret = (getCameras(devices) && !devices.empty()); - if (ret) { - device = devices[0]; - for (std::size_t i = 0; i < devices.size(); ++i) { - if (strnicmp( - devices[i].guid.c_str(), kUsbDevicePathPrefix, - // if (strnicmp(devices[i].id.c_str(), kUsbDevicePathPrefix, - ARRAY_SIZE(kUsbDevicePathPrefix) - 1) == 0) { - device = devices[i]; - break; - } - } - } - return ret; -} - - -namespace internal { // Windows API stuff - -#pragma comment(lib, "strmiids") - -HRESULT enumerateDevices(REFGUID category, IEnumMoniker** ppEnum) -{ - // Create the System Device Enumerator. - ICreateDevEnum* pDevEnum; - HRESULT hr = - CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, - IID_PPV_ARGS(&pDevEnum)); - - if (SUCCEEDED(hr)) { - // Create an enumerator for the category. - hr = pDevEnum->CreateClassEnumerator(category, ppEnum, 0); - if (hr == S_FALSE) { - hr = VFW_E_NOT_FOUND; // The category is empty. Treat as an error. - } - pDevEnum->Release(); - } - return hr; -} - - -void getDeviceInformation(IEnumMoniker* pEnum, REFGUID catid, - std::vector& devices) -{ - IMoniker* pMoniker = NULL; - - while (pEnum->Next(1, &pMoniker, NULL) == S_OK) { - IPropertyBag* pPropBag; - HRESULT hr = pMoniker->BindToStorage(0, 0, IID_PPV_ARGS(&pPropBag)); - if (FAILED(hr)) { - pMoniker->Release(); - continue; - } - - VARIANT var; - VariantInit(&var); - std::string name_str, path_str; - - // Get description or friendly name. - hr = pPropBag->Read(L"FriendlyName", &var, 0); - if (FAILED(hr)) { - hr = pPropBag->Read(L"Description", &var, 0); - } - if (SUCCEEDED(hr)) { - // printf("%S\n", var.bstrVal); - name_str = scy::toUtf8(var.bstrVal); - VariantClear(&var); - } - - hr = pPropBag->Read(L"DevicePath", &var, 0); - if (SUCCEEDED(hr)) { - // The device path is not intended for display. - // printf("Device path: %S\n", var.bstrVal); - path_str = scy::toUtf8(var.bstrVal); - VariantClear(&var); - } - - devices.push_back( - Device(catid == CLSID_VideoInputDeviceCategory ? "video" : "audio", - (int)devices.size(), name_str, path_str)); - - pPropBag->Release(); - pMoniker->Release(); - } -} - -} // namespace internal - - -bool getDevicesWin32(REFGUID catid, std::vector& devices) -{ - // Selecting a Capture Device - // http://msdn.microsoft.com/en-us/library/windows/desktop/dd377566(v=vs.85).aspx - - IEnumMoniker* pEnum; - HRESULT hr = internal::enumerateDevices(catid, &pEnum); - if (SUCCEEDED(hr)) { - internal::getDeviceInformation(pEnum, catid, devices); - pEnum->Release(); - return true; - } - return false; -} - - -// -// Win32 Device Watcher -// - - -Win32DeviceWatcher::Win32DeviceWatcher(Win32DeviceManager* manager) - : DeviceWatcher(manager) - , manager_(manager) - , audio_notify_(NULL) - , video_notify_(NULL) -{ -} - - -Win32DeviceWatcher::~Win32DeviceWatcher() -{ -} - - -bool Win32DeviceWatcher::start() -{ - if (!Create(NULL, L"LibSourcey Device Watcher Window", 0, 0, 0, 0, 0, 0)) { - return false; - } - - audio_notify_ = Register(KSCATEGORY_AUDIO); - if (!audio_notify_) { - stop(); - return false; - } - - video_notify_ = Register(KSCATEGORY_VIDEO); - if (!video_notify_) { - stop(); - return false; - } - - return true; -} - - -void Win32DeviceWatcher::stop() -{ - UnregisterDeviceNotification(video_notify_); - video_notify_ = NULL; - UnregisterDeviceNotification(audio_notify_); - audio_notify_ = NULL; - Destroy(); -} - - -HDEVNOTIFY Win32DeviceWatcher::Register(REFGUID guid) -{ - // DEV_BROADCAST_DEVICEINTERFACE dbdi; - // dbdi.dbcc_size = sizeof(dbdi); - // dbdi.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; - // dbdi.dbcc_classguid = guid; - - DEV_BROADCAST_DEVICEINTERFACE dbdi; - - ZeroMemory(&dbdi, sizeof(dbdi)); - dbdi.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE); - dbdi.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; - dbdi.dbcc_classguid = guid; - - // Add DEVICE_NOTIFY_ALL_INTERFACE_CLASSES to ignore - // dbcc_classguid and listen for all GUID types. - return RegisterDeviceNotification(handle(), &dbdi, - DEVICE_NOTIFY_WINDOW_HANDLE); - // DEVICE_NOTIFY_WINDOW_HANDLE); -} - - -void Win32DeviceWatcher::Unregister(HDEVNOTIFY handle) -{ - UnregisterDeviceNotification(handle); -} - - -bool Win32DeviceWatcher::OnMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, - LRESULT& result) -{ - LDebug("OnMessage: ", uMsg) - - if (uMsg == WM_DEVICECHANGE) { - // bool arriving = wParam == DBT_DEVICEARRIVAL; - // bool removing = wParam == DBT_DEVICEREMOVECOMPLETE; - if (wParam == DBT_DEVICEARRIVAL || wParam == DBT_DEVICEREMOVECOMPLETE) { - DEV_BROADCAST_DEVICEINTERFACE* dbdi = - reinterpret_cast(lParam); - if (dbdi->dbcc_classguid == KSCATEGORY_AUDIO || - dbdi->dbcc_classguid == KSCATEGORY_VIDEO) { - bool isVideo = dbdi->dbcc_classguid == KSCATEGORY_VIDEO; - bool isConnect = wParam == DBT_DEVICEARRIVAL; - LDebug("Signal Devices changed: ", isVideo, ": ", isConnect); - manager_->DevicesChanged.emit(manager_, isVideo, isConnect); - } - } - result = 0; - return true; - } - - return false; -} - - -// -// Win32 Window -// - -static const wchar_t kWindowBaseClassName[] = L"WindowBaseClass"; -HINSTANCE Win32Window::instance_ = NULL; -ATOM Win32Window::window_class_ = 0; - -Win32Window::Win32Window() - : wnd_(NULL) -{ -} - - -Win32Window::~Win32Window() -{ - assert(NULL == wnd_); -} - - -bool Win32Window::Create(HWND parent, const wchar_t* title, DWORD style, - DWORD exstyle, int x, int y, int cx, int cy) -{ - if (wnd_) { - // Window already exists. - return false; - } - - if (!window_class_) { - if (!GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | - GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, - reinterpret_cast(&Win32Window::WndProc), - &instance_)) { - LError("GetModuleHandleEx failed") - return false; - } - - // Class not registered, register it. - WNDCLASSEX wcex; - memset(&wcex, 0, sizeof(wcex)); - wcex.cbSize = sizeof(wcex); - wcex.hInstance = instance_; - wcex.lpfnWndProc = &Win32Window::WndProc; - wcex.lpszClassName = kWindowBaseClassName; - window_class_ = ::RegisterClassEx(&wcex); - if (!window_class_) { - LError("RegisterClassEx failed") - return false; - } - } - wnd_ = ::CreateWindowEx(exstyle, kWindowBaseClassName, title, style, x, y, - cx, cy, parent, NULL, instance_, this); - return (NULL != wnd_); -} - - -void Win32Window::Destroy() -{ - BOOL res = ::DestroyWindow(wnd_); - assert(res != FALSE); -} - - -void Win32Window::Shutdown() -{ - if (window_class_) { - ::UnregisterClass(MAKEINTATOM(window_class_), instance_); - window_class_ = 0; - } -} - - -bool Win32Window::OnMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, - LRESULT& result) -{ - switch (uMsg) { - case WM_CLOSE: - if (!OnClose()) { - result = 0; - return true; - } - break; - } - return false; -} - - -LRESULT Win32Window::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - Win32Window* that = - reinterpret_cast(::GetWindowLongPtr(hwnd, GWLP_USERDATA)); - if (!that && (WM_CREATE == uMsg)) { - CREATESTRUCT* cs = reinterpret_cast(lParam); - that = static_cast(cs->lpCreateParams); - that->wnd_ = hwnd; - ::SetWindowLongPtr(hwnd, GWLP_USERDATA, - reinterpret_cast(that)); - } - if (that) { - LRESULT result; - bool handled = that->OnMessage(uMsg, wParam, lParam, result); - if (WM_DESTROY == uMsg) { - for (HWND child = ::GetWindow(hwnd, GW_CHILD); child; - child = ::GetWindow(child, GW_HWNDNEXT)) { - LDebug("Child window: ", static_cast(child)) - } - } - if (WM_NCDESTROY == uMsg) { - ::SetWindowLongPtr(hwnd, GWLP_USERDATA, NULL); - that->wnd_ = NULL; - that->OnNcDestroy(); - } - if (handled) { - return result; - } - } - return ::DefWindowProc(hwnd, uMsg, wParam, lParam); -} - - -#if 0 -bool getDevices(const CLSID& catid, std::vector& devices) -{ - HRESULT hr; - - // CComPtr is a scoped pointer that will be auto released when going - // out of scope. CoUninitialize must not be called before the - // release. - CComPtr sys_dev_enum; - CComPtr cam_enum; - if (FAILED(hr = sys_dev_enum.CoCreateInstance(CLSID_SystemDeviceEnum)) || - FAILED(hr = sys_dev_enum->CreateClassEnumerator(catid, &cam_enum, 0))) { - LError("Cannot create device enumerator, hr=" , hr) - return false; - } - - // Only enum devices if CreateClassEnumerator returns S_OK. If there are no - // devices available, S_FALSE will be returned, but enumMk will be nullptr. - if (hr == S_OK) { - CComPtr mk; - while (cam_enum->Next(1, &mk, nullptr) == S_OK) { - CComPtr bag; - if (SUCCEEDED(mk->BindToStorage(nullptr, nullptr, - __uuidof(bag), reinterpret_cast(&bag)))) { - CComVariant name, path; - std::string type_str, name_str, path_str; - if (SUCCEEDED(bag->Read(L"FriendlyName", &name, 0)) && - name.vt == VT_BSTR) { - name = scy::toUtf8(name.bstrVal); - // Get the device id if one exists. - if (SUCCEEDED(bag->Read(L"DevicePath", &path, 0)) && - path.vt == VT_BSTR) { - path = scy::toUtf8(path.bstrVal); - } - if (catid == CLSID_VideoInputDeviceCategory) - type_str = "video"; - else - assert(0 && "unknown type"); - devices.push_back(Device(type_str, (int)devices.size(), name_str, path_str)); - } - } - mk = nullptr; - } - } - - return true; -} - - -static const wchar_t kFriendlyName[] = L"FriendlyName"; -static const wchar_t kDevicePath[] = L"DevicePath"; -static bool getCoreAudioDevices(bool input, std::vector& devs); -static bool getWaveDevices(bool input, std::vector& devs); - -bool Win32DeviceManager::getAudioDevices(bool input, std::vector& devs) -{ - devs.clear(); - - //if (scy::IsWindowsVistaOrLater()) { - if (util::isWindowsVistaOrLater()) { - if (!getCoreAudioDevices(input, devs)) - return false; - } else { - if (!getWaveDevices(input, devs)) - return false; - } - return filterDevices(devs, kFilteredAudioDevicesName); -} - - -HRESULT getStringProp(IPropertyStore* bag, PROPERTYKEY key, string* out) { - out->clear(); - PROPVARIANT var; - PropVariantInit(&var); - - HRESULT hr = bag->GetValue(key, &var); - if (SUCCEEDED(hr)) { - if (var.pwszVal) - Poco::toUtf::toUTF8(var.pwszVal, *out); - //*out = scy::toUtf8(var.pwszVal); - else - hr = E_FAIL; - } - - PropVariantClear(&var); - return hr; -} - - -// Adapted from http://msdn.microsoft.com/en-us/library/dd370812(v=VS.85).aspx -HRESULT getDeviceFromImmDevice(IMMDevice* device, Device& out) { - CComPtr props; - - HRESULT hr = device->OpenPropertyStore(STGM_READ, &props); - if (FAILED(hr)) { - return hr; - } - - // Get the endpoint's name and guid. - std::string name, guid; - hr = getStringProp(props, PKEY_Device_FriendlyName, &name); - if (SUCCEEDED(hr)) { - hr = getStringProp(props, PKEY_AudioEndpoint_GUID, &guid); - - if (SUCCEEDED(hr)) { - out.name = name; - out.guid = guid; - } - } - return hr; -} - - -bool getCoreAudioDevices(bool input, std::vector& devs) -{ - HRESULT hr = S_OK; - CComPtr enumerator; - - hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_ALL, - __uuidof(IMMDeviceEnumerator), reinterpret_cast(&enumerator)); - if (SUCCEEDED(hr)) { - CComPtr devices; - - // Enumerate ALL devices, so we can get the correct system index - hr = enumerator->EnumAudioEndpoints(eAll, //(input ? eCapture : eRender), - DEVICE_STATE_ACTIVE, &devices); - if (SUCCEEDED(hr)) { - unsigned int count; - hr = devices->GetCount(&count); - - if (SUCCEEDED(hr)) { - for (unsigned int i = 0; i < count; i++) { - CComPtr device; - - // Get pointer to endpoint - hr = devices->Item(i, &device); - if (FAILED(hr)) - break; - - // Get an endpoint interface for the current device - IMMEndpoint* endpoint = nullptr; - hr = device->QueryInterface(__uuidof(IMMEndpoint), (void**)&endpoint); - if (FAILED(hr)) - break; - - // Get the data flow for the current device - EDataFlow dataFlow; - hr = endpoint->GetDataFlow(&dataFlow); - if (FAILED(hr)) - break; - - // Get next device if data flow is not as specified - if (dataFlow != (input ? eCapture : eRender)) - continue; - - //device->QueryInterface(__uuidof(IMMEndpoint)) - // You can get the flow (render or capture) by calling IMMDevice::QueryInterface(__uuidof(IMMEndpoint)) and then IMMEndpoint::GetDataFlow. - // http://social.msdn.microsoft.com/Forums/en-US/windowspro-audiodevelopment/thread/50889257-7200-4137-851d-6cc690234863/ - //device - - Device dev(input ? "audioin" : "audioout", "", i); - - LTrace("Enumerating Device: ", i) - hr = getDeviceFromImmDevice(device, dev); - if (SUCCEEDED(hr)) { - devs.push_back(dev); - } else { - LWarn("Cannot query IMM Device, skipping. HR=", hr) - hr = S_FALSE; - } - } - } - } - } - - if (FAILED(hr)) { - LWarn("getCoreAudioDevices failed with hr ", hr) - return false; - } - return true; -} - - -bool getWaveDevices(bool input, std::vector& devs) -{ - // Note, we don't use the System Device Enumerator interface here since it - // adds lots of pseudo-devices to the list, such as DirectSound and Wave - // variants of the same device. - if (input) { - int numDevs = waveInGetNumDevs(); - for (int i = 0; i < numDevs; ++i) { - WAVEINCAPS caps; - if (waveInGetDevCaps(i, &caps, sizeof(caps)) == MMSYSERR_NOERROR && - caps.wChannels > 0) { - std::string name; - Poco::toUtf::toUTF8(caps.szPname, name); - devs.push_back(Device("audioin", name, i)); - } - } - } - else { - int numDevs = waveOutGetNumDevs(); - for (int i = 0; i < numDevs; ++i) { - WAVEOUTCAPS caps; - if (waveOutGetDevCaps(i, &caps, sizeof(caps)) == MMSYSERR_NOERROR && - caps.wChannels > 0) { - std::string name; - devs.push_back(Device("audioout", name, i)); - //devs.push_back(Device(scy::toUtf8(caps.szPname), i)); - } - } - } - return true; -} - - -Win32DeviceWatcher::Win32DeviceWatcher(Win32DeviceManager* manager) - : DeviceWatcher(manager), - manager_(manager), - audio_notify_(nullptr), - video_notify_(nullptr) { -} - -Win32DeviceWatcher::~Win32DeviceWatcher() { -} - -bool Win32DeviceWatcher::start() { - if (!Create(nullptr, _T("libjingle Win32DeviceWatcher Window"), - 0, 0, 0, 0, 0, 0)) { - return false; - } - - audio_notify_ = Register(KSCATEGORY_AUDIO); - if (!audio_notify_) { - stop(); - return false; - } - - video_notify_ = Register(KSCATEGORY_VIDEO); - if (!video_notify_) { - stop(); - return false; - } - - return true; -} - -void Win32DeviceWatcher::stop() { - UnregisterDeviceNotification(video_notify_); - video_notify_ = nullptr; - UnregisterDeviceNotification(audio_notify_); - audio_notify_ = nullptr; - Destroy(); -} - -HDEVNOTIFY Win32DeviceWatcher::Register(REFGUID guid) { - DEV_BROADCAST_DEVICEINTERFACE dbdi; - dbdi.dbcc_size = sizeof(dbdi); - dbdi.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; - dbdi.dbcc_classguid = guid; - dbdi.dbcc_name[0] = '\0'; - return RegisterDeviceNotification(handle(), &dbdi, - DEVICE_NOTIFY_WINDOW_HANDLE); -} - -void Win32DeviceWatcher::Unregister(HDEVNOTIFY handle) { - UnregisterDeviceNotification(handle); -} - -bool Win32DeviceWatcher::OnMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, - LRESULT& result) { - if (uMsg == WM_DEVICECHANGE) { - if (wParam == DBT_DEVICEARRIVAL || - wParam == DBT_DEVICEREMOVECOMPLETE) { - DEV_BROADCAST_DEVICEINTERFACE* dbdi = - reinterpret_cast(lParam); - if (dbdi->dbcc_classguid == KSCATEGORY_AUDIO || - dbdi->dbcc_classguid == KSCATEGORY_VIDEO) { - manager_->DevicesChanged(); - } - } - result = 0; - return true; - } - - return false; -} -//#endif - - -} // namespace av -} // namespace scy - - -#endif - - -/* - * libjingle - * Copyright 2004 Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/src/av/deprecated/src/imageencoder.cpp b/src/av/deprecated/src/imageencoder.cpp deleted file mode 100644 index 57e881ed7..000000000 --- a/src/av/deprecated/src/imageencoder.cpp +++ /dev/null @@ -1,111 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// @addtogroup av -/// @{ - - -#include "scy/av/imageencoder.h" -#include "scy/av/mediacapture.h" -#include "scy/logger.h" - -#include "assert.h" - -#ifdef HAVE_OPENCV - - -using std::endl; - - -namespace scy { -namespace av { - - -ImageEncoder::ImageEncoder(EncoderOptions& options, std::vector cvParams) - : PacketProcessor(this->emitter) - , _options(options) - , _params(cvParams) -{ - LTrace("Create") - - if (_options.oformat.id == "jpeg" || _options.oformat.id == "mjpeg") - _extension = ".jpg"; - else if (_options.oformat.id == "png" || _options.oformat.id == "mpng") - _extension = ".png"; - else - // TODO: support more! - assert(false); -} - - -ImageEncoder::~ImageEncoder() -{ - LTrace("Destroy") -} - - -void ImageEncoder::initialize() -{ -} - - -void ImageEncoder::uninitialize() -{ -} - - -bool ImageEncoder::accepts(IPacket* packet) -{ - return dynamic_cast(&packet) != 0; -} - - -void ImageEncoder::process(IPacket& packet) -{ - // LTrace("Processing") - - MatrixPacket* mpacket = dynamic_cast(&packet); - if (!mpacket) - throw std::runtime_error("Unknown video packet type."); - if (!mpacket->mat) - throw std::runtime_error("Video packets must contain an OpenCV image."); - - std::vector buffer; - - // FIXME: If the video capture is stopped before - // this callback completes our Mat is corrupted. - cv::Mat& source = *mpacket->mat; - if (source.cols != _options.oformat.video.width && - source.rows != _options.oformat.video.height) { - cv::Mat resized; - cv::resize(source, resized, cv::Size(_options.oformat.video.width, - _options.oformat.video.height)); - cv::imencode(_extension, resized, buffer, _params); - } else - cv::imencode(_extension, source, buffer, _params); - - // Temp reference on the stack only - mpacket->_data = (char*)&buffer[0]; - mpacket->_size = buffer.size(); - - // LTrace("Broadcasting: ", mpacket) - emit(*mpacket); // this, - // LTrace("Broadcasting: OK: ", mpacket) -} - - -EncoderOptions& ImageEncoder::options() -{ - return _options; -} - - -} // namespace av -} // namespace scy - - -#endif \ No newline at end of file diff --git a/src/av/deprecated/src/mediafactory.cpp b/src/av/deprecated/src/mediafactory.cpp deleted file mode 100644 index d1223ea44..000000000 --- a/src/av/deprecated/src/mediafactory.cpp +++ /dev/null @@ -1,204 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// @addtogroup av -/// @{ - - -#include "scy/av/mediafactory.h" -#include "scy/logger.h" - - -#if defined(HAVE_OPENCV) && defined(HAVE_RTAUDIO) - - -using std::endl; - - -namespace scy { -namespace av { - - -static Singleton singleton; - - -MediaFactory& MediaFactory::instance() -{ - return *singleton.get(); -} - - -void MediaFactory::shutdown() -{ - singleton.destroy(); -} - - -MediaFactory::MediaFactory() -{ - _devices = DeviceManagerFactory::create(); - _devices->initialize(); - //_devices->DevicesChanged += sdelegate(this, - //&MediaFactory::onDevicesChanged); -} - - -MediaFactory::~MediaFactory() -{ - if (_devices) { - //_devices->DevicesChanged -= sdelegate(this, - //&MediaFactory::onDevicesChanged); - _devices->uninitialize(); - delete _devices; - } -} - - -IDeviceManager& MediaFactory::devices() -{ - std::lock_guard guard(_mutex); - return *_devices; -} - - -FormatRegistry& MediaFactory::formats() -{ - std::lock_guard guard(_mutex); - return _formats; -} - - -void MediaFactory::loadVideoCaptures() -{ - LDebug("Loading video captures") - assert(Thread::mainID == Thread::currentID()); - - // Initialize a VideoCapture object for each available device. - // The video capture object will begin capturing frames when it's - // reference count becomes positive. - std::vector devs; - devices().getCameras(devs); - for (std::size_t i = 0; i < devs.size(); ++i) { - try { - createVideoCapture(devs[0].id); - } catch (std::exception& exc) { - SError << "Cannot load video capture: " << devs[0].id << ": " - << exc.what() << endl; - } - } -} - - -void MediaFactory::reloadFailedVideoCaptures() -{ - LDebug("Reloading failed video captures") - assert(Thread::mainID == Thread::currentID()); - - // Loop through captures and attempt to reopen any - // that may have been unplugged - auto videoCaptures = this->videoCaptures(); - for (auto& kv : videoCaptures) { - if (kv.second->error().any()) { - STrace << "Reloading capture " << kv.second->deviceId() << ": " - << kv.second->error() << endl; - try { - kv.second->open(); - kv.second->start(); - - // Manually emit the capture loaded signal if the - // capture was successfully reloaded - if (!kv.second->error().any()) { - VideoCaptureLoaded.emit(kv.second); - } - } catch (std::exception& exc) { - SError << "Capture initialization error: " << exc.what() - << endl; - } - } - } -} - - -std::map MediaFactory::videoCaptures() const -{ - std::lock_guard guard(_mutex); - return _videoCaptures; -} - - -void MediaFactory::unloadVideoCaptures() -{ - std::lock_guard guard(_mutex); - _videoCaptures.clear(); -} - - -VideoCapture::Ptr -MediaFactory::createVideoCapture(int deviceId) //, unsigned flags -{ - LTrace("Creating video capture: ", deviceId) - - if (deviceId < 0) - throw std::runtime_error("Invalid video device ID"); - - std::lock_guard guard(_mutex); - - auto it = _videoCaptures.find(deviceId); - if (it != _videoCaptures.end()) - return it->second; - - auto capture = std::make_shared(deviceId); - _videoCaptures[deviceId] = capture; - VideoCaptureLoaded.emit(capture); - - // Listen for errors. - // NOTE: The capture is opened and started in the constructor, - // so exceptions thrown during startup will not be handled - // via this callback. - capture->Error += sdelegate(this, &MediaFactory::onVideoCaptureError); - return capture; -} - - -void MediaFactory::onVideoCaptureError(void* sender, const scy::Error& err) -{ - auto capture = reinterpret_cast(sender); - auto videoCaptures = this->videoCaptures(); - auto it = videoCaptures.find(capture->deviceId()); - if (it != videoCaptures.end()) { - VideoCaptureError.emit(it->second); - } else - assert(0); -} - - -VideoCapture::Ptr MediaFactory::createFileCapture(const std::string& file) -{ - LTrace("Create video file capture: ", file) - - return std::make_shared(file); -} - - -AudioCapture::Ptr MediaFactory::createAudioCapture(int deviceId, int channels, - int sampleRate, - RtAudioFormat format) -{ - LTrace("Create audio capture: ", deviceId) - if (deviceId < 0) - throw std::runtime_error("Invalid audio device ID"); - - return std::make_shared(deviceId, channels, sampleRate, - format); -} - - -} // namespace av -} // namespace scy - - -#endif diff --git a/src/av/deprecated/src/thumbnailer.cpp b/src/av/deprecated/src/thumbnailer.cpp deleted file mode 100644 index 53e6d83b3..000000000 --- a/src/av/deprecated/src/thumbnailer.cpp +++ /dev/null @@ -1,139 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// @addtogroup av -/// @{ - - -#include "scy/av/thumbnailer.h" - -#if 0 // needs updating to latest API -#ifdef HAVE_FFMPEG - -#include "scy/filesystem.h" - -using std::endl; - - -namespace scy { -namespace av { - - -Thumbnailer::Thumbnailer(const ThumbnailerOptions& options) : - options(options) -{ - initializeFFmpeg(); -} - - -Thumbnailer::~Thumbnailer() -{ - uninitializeFFmpeg(); -} - - -void Thumbnailer::open() //, int owidth, int oheight, double seek -{ - if (!fs::exists(options.ifile)) { - throw std::runtime_error("Cannot create thumbnail: The input file doesn't exist."); - } - - if (options.ofile.empty()) { - options.ofile = defaultThumbPath(options.ifile); - } - - reader.emitter += packetSlot(this, &Thumbnailer::onVideoPacket); - reader.openFile(options.ifile); - - if (options.seek > reader.video()->stream->duration) - throw std::runtime_error("Seek position exceeds stream duration"); - - if (options.ofile.find(".png") != std::string::npos) { - encoder.oparams.encoder = "png"; - } - else if (options.ofile.find(".jpg") != std::string::npos) { - encoder.oparams.encoder = "mjpeg"; - encoder.oparams.pixelFmt = "yuvj420p"; - } - else { - throw std::runtime_error("Unsupportted image format: " + options.ofile); - } - - // reader.getEncoderFormat(encoder.iparams); - auto ctx = reader.video()->ctx; - encoder.iparams.width = ctx->width; - encoder.iparams.height = ctx->height; - encoder.iparams.pixelFmt = av_get_pix_fmt_name(ctx->pix_fmt); - encoder.oparams.width = options.width ? options.width : ctx->width; - encoder.oparams.height = options.height ? options.height : ctx->height; - encoder.oparams.fps = 1; - encoder.oparams.enabled = true; - encoder.create(); - - //encoder.oparams.print(cout); -} - - -void Thumbnailer::grab() -{ - // Open here so settings may be modified - encoder.open(); - - // Run the decoder loop - reader.run(); - assert(fs::exists(options.ofile)); -} - - -void Thumbnailer::onVideoPacket(void*, av::VideoPacket& packet) -{ - LDebug("Thumbnail packet out: ", packet.size()) - - // Skip frames before seek position - if (reader.video()->pts < options.seek) { - LTrace("Skipping thumbnail frame: ", reader.video()->pts, " < ", options.seek) - return; - } - - if (!packet.iframe) { - LTrace("Skipping non-iframe") - return; - } - - // Feed the decoded frame into the encoder - AVPacket opacket; - if (encoder.encode(reader.video()->frame, opacket)) { - - // Save the thumbnail - fs::savefile(options.ofile, (const char*)opacket.data, (std::streamsize)opacket.size); - - // Break out of the reader scope - reader.stop(); - } -} - - -std::string Thumbnailer::defaultThumbPath(const std::string& ifile, const std::string& ext, const std::string& suffix) -{ - if (ifile.find(suffix + ext) != std::string::npos) - return ifile; - std::string thumbpath(ifile); - thumbpath = thumbpath.substr(0, thumbpath.length() - ext.length()); - thumbpath += suffix; - thumbpath += ext; - return thumbpath; -} - - -} // namespace av -} // namespace scy - -#endif -#endif - - -/// @\} diff --git a/src/av/deprecated/src/videoanalyzer.cpp b/src/av/deprecated/src/videoanalyzer.cpp deleted file mode 100644 index 3c6c50d3d..000000000 --- a/src/av/deprecated/src/videoanalyzer.cpp +++ /dev/null @@ -1,417 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// @addtogroup av -/// @{ - - -#include "scy/av/videoanalyzer.h" - - -#ifdef HAVE_FFMPEG - - -using std::endl; - - -namespace scy { -namespace av { - - -VideoAnalyzer::VideoAnalyzer(const Options& options) - : _options(options) - , _video(nullptr) - , _audio(nullptr) - , _videoConv(nullptr) -{ - LTrace("Create") -} - - -VideoAnalyzer::~VideoAnalyzer() -{ - LTrace("Destroy") - uninitialize(); -} - - -void VideoAnalyzer::initialize() -{ - if (_options.ifile.empty()) - throw std::runtime_error("Please specify an input file."); - - LTrace("Loading: ", _options.ifile) - - _error = ""; - - // Open the input file decoder. - _reader.openFile(_options.ifile); - - if (_reader.video()) { - _videoConv = nullptr; - _video = new VideoAnalyzer::Stream("Video", _options.rdftSize); - _video->initialize(); - } - - if (_reader.audio()) { - _audio = new VideoAnalyzer::Stream("Audio", _options.rdftSize); - _audio->initialize(); - } - - _reader.emitter += packetSlot(this, &VideoAnalyzer::onVideo); - _reader.emitter += packetSlot(this, &VideoAnalyzer::onAudio); - _reader.Closing += sdelegate(this, &VideoAnalyzer::onReadComplete); -} - - -void VideoAnalyzer::uninitialize() -{ - // STrace << "[VideoAnalyzerStream: " << this << ": " << name << "] - // Uninitializing" << endl; - stop(); - - - - if (_video) - delete _video; - if (_videoConv) - delete _videoConv; - if (_audio) - delete _audio; -} - - -void VideoAnalyzer::start() -{ - std::lock_guard guard(_mutex); - - try { - if (!_reader.audio() && !_reader.video()) - throw std::runtime_error("Video reader not initialized"); - - // if (_options.blocking) - // _reader.run(); - // else - _reader.start(); - } catch (std::exception& exc) { - _error = exc.what(); - LError("Error: ", _error) - throw exc; //.rethrow() - } -} - - -void VideoAnalyzer::stop() -{ - // Can't lock here in case we are inside a callback. - - - _reader.Closing -= sdelegate(this, &VideoAnalyzer::onReadComplete); - _reader.emitter.detach(this); - _reader.stop(); -} - - -void VideoAnalyzer::onVideo(void*, VideoPacket& packet) -{ - // STrace << "On video: " - // << packet.size() << ": " << packet.time << endl; - - VideoAnalyzer::Packet pkt(packet.time); - AVFrame* greyFrame = getGrayVideoFrame(); - int width = greyFrame->width; - int height = greyFrame->height; - int step = greyFrame->linesize[0]; - int frames = 0; - // VideoDecoder* video = _reader.video(); - - std::lock_guard guard(_mutex); - - // Prepeare FFT input data array - // http://stackoverflow.com/questions/7790877/forward-fft-an-image-and-backward-fft-an-image-to-get-the-same-result - // https://code.google.com/p/video-processing-application/source/browse/trunk/+video-processing-application/untitled6/Fourier/highpassrgb.cpp?r=2 - // http://codepaste.ru/9226/ - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - _video->rdftData[_video->filled++] = - (float)greyFrame->data[0][y * step + x] * pow(-1.0, y + x); - if (_video->filled == _video->rdftSize) { - _video->fft(); - pkt.value += CalculateFrequencyIntensity(*_video); - frames++; - _video->frames++; - _video->filled = 0; - } - } - } - - if (frames) { - - // Calculate and scale the average value for this video frame - pkt.value /= frames; - pkt.value = sqrt(pkt.value); ///= _video->rdftSize; - - STrace << "Video Output: " << pkt.time << ", " << pkt.value - << endl; - PacketOut.emit(*_video, pkt); - } -} - -void VideoAnalyzer::onAudio(void*, AudioPacket& packet) -{ - // STrace << "On Audio: " - // << packet.size() << ": " << packet.time << endl; - - std::lock_guard guard(_mutex); - - VideoAnalyzer::Packet pkt(packet.time); - short const* data = reinterpret_cast(packet.data()); - int channels = _reader.audio()->stream->codec->channels; - int size = packet.size(); - int frames = 0; - - // Packet size / 2 = 2 bytes per sample (short) - // Example at http://blackhole.ubitux.fr/bench-fftw-ffmpeg-fft/fft.c - for (int i = 0; i < size / 2; i += channels) { - int k, v = 0; - for (k = 0; k < channels; k++) // mix channels - v += data[i + k]; - - _audio->rdftData[_audio->filled++] = (float)v / channels / SHRT_MAX; - if (_audio->filled == _audio->rdftSize) { - _audio->fft(); - pkt.value += CalculateFrequencyIntensity(*_audio); - frames++; - _audio->frames++; - _audio->filled = 0; - } - } - - if (frames) { - - // Calculate the average value for this video frame - pkt.value /= frames; - - STrace << "Audio Output: " << pkt.time << ", " << pkt.value - << endl; - PacketOut.emit(*_audio, pkt); - } -} - - -AVFrame* VideoAnalyzer::getGrayVideoFrame() -{ - std::lock_guard guard(_mutex); - VideoDecoder* video = _reader.video(); - - // TODO: Conversion via decoder? - if (_videoConv == nullptr) { - _videoConv = new VideoConverter(); - - auto& iparams = _videoConv->iparams; - iparams.width = video->ctx->width; - iparams.height = video->ctx->height; - iparams.pixelFmt = av_get_pix_fmt_name(video->ctx->pix_fmt); - - auto& oparams = _videoConv->oparams; - oparams.width = video->ctx->width; - oparams.height = video->ctx->height; - oparams.pixelFmt = "gray"; - - _videoConv->create(); - } - if (_videoConv == nullptr) - throw std::runtime_error("Video Analyzer: Unable to initialize the " - "video conversion context."); - - // Convert the source image to grayscale - return _videoConv->convert(video->frame); -} - - -void VideoAnalyzer::onReadComplete(void* sender) -{ - LTrace("On Read Complete") - - MediaCapture* reader = reinterpret_cast(sender); - { - std::lock_guard guard(_mutex); - if (_error.empty()) - _error = reader->error(); - } - - Complete.emit(/*this*/); -} - - -MediaCapture& VideoAnalyzer::reader() -{ - std::lock_guard guard(_mutex); - return _reader; -} - - -VideoAnalyzer::Options& VideoAnalyzer::options() -{ - std::lock_guard guard(_mutex); - return _options; -} - - -std::string VideoAnalyzer::error() const -{ - std::lock_guard guard(_mutex); - return _error; -} - - -// --------------------------------------------------------------------- -// -VideoAnalyzer::Packet::Packet(double time, double value) - : //, double min, double max - time(time) - , value(value) -{ - // this->min = min; - // this->max = max; -} - - -// --------------------------------------------------------------------- -// -const int kMaxFFTPow2Size = 24; - - -VideoAnalyzer::Stream::Stream(const std::string& name, int rdftSize) - : name(name) - , rdft(nullptr) - , rdftData(nullptr) - , rdftSize(rdftSize) - , rdftBits(static_cast(log2(rdftSize))) - , frames(0) - , filled(0) -{ - STrace << "[VideoAnalyzerStream: " << this << ": " << name - << "] Creating: " << rdftLize(": ", rdftBits) - - assert(rdftSize); - assert(rdftBits < kMaxFFTPow2Size); - - // We only allow power of two. - assert(int(1UL << rdftBits) == rdftSize); -} - - -VideoAnalyzer::Stream::~Stream() -{ - uninitialize(); -} - - -void VideoAnalyzer::Stream::initialize() -{ - frames = 0; - filled = 0; - - assert(rdft == nullptr); - rdft = av_rdft_init(rdftBits, DFT_R2C); - if (rdft == nullptr) - throw std::runtime_error("Cannot allocate FFT context"); - - assert(rdftData == nullptr); - rdftData = (FFTSample*)av_malloc(rdftSize * sizeof(*rdftData)); - if (rdftData == nullptr) - throw std::runtime_error("Cannot allocate FFT buffer"); -} - - -void VideoAnalyzer::Stream::uninitialize() -{ - // STrace << "[VideoAnalyzerStream: " << this << ": " << name << "] - // Uninitializing" << endl; - - if (rdft) - av_rdft_end(rdft); - if (rdftData) - av_free(rdftData); -} - - -void VideoAnalyzer::Stream::fft() -{ - assert(filled == rdftSize); - av_rdft_calc(rdft, rdftData); -} - - -// --------------------------------------------------------------------- -// -double CalculateCentroidFrequency(VideoAnalyzer::Stream& stream) -{ - // These two values are used for getting the Spectral Centroid - // http://en.wikipedia.org/wiki/Spectral_centroid - double centroidFnXn = 0; - double centroidXn = 0; - - for (int i = 0; i < stream.filled / 2; i += 2) { - centroidFnXn += i * abs(stream.rdftData[i]); - centroidXn += abs(stream.rdftData[i]); - } - - return centroidFnXn / centroidXn; -} - - -double CalculateFrequencyIntensity(VideoAnalyzer::Stream& stream) -{ - double intensity = 0.0; - for (int i = 0; i < stream.filled / 2; i += 2) { - intensity += - GetFrequencyIntensity(stream.rdftData[i], stream.rdftData[i + 1]); - } - return intensity; -} - - -double GetFrequencyIntensity(double re, double im) -{ - return sqrt((re * re) + (im * im)); -} - - -double GetDecibels(double re, double im) -{ - return (re == 0 && im == 0) ? 0 : 10.0 * log10(re * re + im * im); -} - -double GetAmplitude(double re, double im, int len) -{ - return GetFrequencyIntensity(re, im) / (len); -} - -double GetAmplitudeScaled(double re, double im, int len, int scale) -{ - return static_cast(GetAmplitude(re, im, len)) % scale; -} - - -#ifdef SCY_WIN -double log2(double n) -{ - return log(n) / log(double(2)); -} -#endif - - -} // namespace av -} // namespace scy - - -#endif - - -/// @\} diff --git a/src/av/deprecated/src/videocapture.cpp b/src/av/deprecated/src/videocapture.cpp deleted file mode 100644 index 077488024..000000000 --- a/src/av/deprecated/src/videocapture.cpp +++ /dev/null @@ -1,429 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// @addtogroup av -/// @{ - -#include "scy/av/mediacapture.h" -#include "scy/logger.h" -#include "scy/platform.h" -#include "scy/util.h" - - -#ifdef HAVE_OPENCV - -namespace scy { -namespace av { - - -inline std::string exceptionMessage(const std::string& reason) -{ - std::stringstream ss; - ss << reason; - if (reason.at(reason.length() - 1) != '.') - ss << "."; - ss << " Please ensure the device is properly connected and not in use by " - "another application."; - return ss.str(); -} - - -// -// Video Capture -// - - -VideoCapture::VideoCapture(int deviceId) - : _deviceId(deviceId) - , _opened(false) - , _started(false) - , _stopping(false) - , _capturing(false) -{ - LTrace("Create: ", deviceId) - open(); - start(); -} - - -VideoCapture::VideoCapture(const std::string& filename) - : _filename(filename) - , _deviceId(-1) - , _opened(false) - , _started(false) - , _stopping(false) - , _capturing(false) -{ - LTrace("Create: ", filename) - open(); - start(); -} - - -VideoCapture::~VideoCapture() -{ - LTrace("Destroy") - // stop(); - - // Ensure we are not inside the thread context - assert(Thread::currentID() != _thread.tid()); - - // Terminate the internal thread - if (_thread.started()) { - LTrace("Destroy: Terminating thread") - _stopping = true; - _thread.join(); - } - - // Try to release the capture (automatic once unrefed) - // try { release(); } catch (...) {} - - LTrace("Destroy: OK") -} - - -void VideoCapture::start() -{ - LTrace("Starting") - { - std::lock_guard guard(_mutex); - - if (!_started) { // - LTrace("Initializing thread") - - // The capture must be opened first. - // open() must be called from the main thread, - // where as start() may be called from any thread. - if (!_opened) - throw std::runtime_error( - "The capture must be opened before starting the thread."); - - _started = true; - _stopping = false; - _capturing = false; - _counter.reset(); - _error = ""; - - assert(!_thread.started()); - assert(!_thread.running()); - _thread.start(*this); - } - } - while (!_capturing && error().any()) { - LTrace("Starting: Waiting") - scy::sleep(10); - } - - LTrace("Starting: OK") -} - - -void VideoCapture::stop() -{ - LTrace("Stopping") - -// NOTE: This function no longer does anything. -// Once the capture is running, it will continue to do -// so until it is either closed or destroyed. - -#if 0 - // The capture can only be stopped when the delegate - // count reaches zero, therefore in order to ensure - // stoppage one must first disconnect all signals. - - assert(Thread::currentID() != _thread.tid()); - if (_started && emitter.nslots() == 0) { //_thread.started() - LTrace("Terminating thread") - _stopping = true; - _thread.join(); - } -#endif -} - - -bool VideoCapture::open(bool whiny) -{ - LTrace("Open") - std::lock_guard guard(_mutex); - assert(Thread::currentID() != _thread.tid()); - - if (_opened && _capture.isOpened()) - return true; - - _opened = _capture.isOpened() ? true : _filename.empty() - ? _capture.open(_deviceId) - : _capture.open(_filename); - - if (!_opened && whiny) - throw std::runtime_error(exceptionMessage( - "Cannot open the video capture device: " + name())); - - LTrace("Open: ", _opened) - return _opened; -} - - -void VideoCapture::run() -{ - try { - // Grab an initial frame - cv::Mat frame(grab()); - _capturing = true; - bool empty = true; - PacketSignal* next = nullptr; - - STrace << "Running:" - << "\n\tDevice ID: " << _deviceId - << "\n\tFilename: " << _filename - << "\n\tWidth: " << width() << "\n\tHeight: " << height() - << std::endl; - - while (!_stopping) { - frame = grab(); - // STrace << "Frame: " << frame.rows << "x" << frame.cols << - // std::endl; - - empty = emitter.nslots() == 0; - if (!empty) { - LTrace("Emitting: ", _counter.fps) - MatrixPacket out(&frame); - emitter.emit(next, out); - } - - // Update last frame less often while in limbo - scy::sleep(empty ? 50 : 3); - - // Always call waitKey otherwise all hell breaks loose - cv::waitKey(3); - } - } catch (cv::Exception& exc) { - _error.exception = - std::current_exception(); // cv::Exception extends std::exception - setError("OpenCV Error: " + exc.err); - } - - // TODO: We probably should have a MediaException type in order to - // differentiate between internal exceptions and exceptions thrown inside - // the callback signal. The latter represents a serious application error. - // Currently they both set the capture to error state. - catch (std::exception& exc) { - _error.exception = std::current_exception(); - setError(exc.what()); - } - - _started = false; - _capturing = false; - - // Note: Need to release the capture, otherwise this class instance - // cannot be reused ie. the next call to open() will fail. - LTrace("Releasing") - _capture.release(); - - LTrace("Exiting") -} - - -cv::Mat VideoCapture::grab() -{ - assert(Thread::currentID() == _thread.tid()); - - std::lock_guard guard(_mutex); - - // Grab a frame from the capture source - // If the capture source is invalid, it will set an invalid frame here - _capture >> _frame; - - // Keep looping the input video if using file input and we reach eof - if (!_filename.empty() && (!_frame.cols || !_frame.rows)) { - _capture.release(); - _capture.open(_filename); - if (!_capture.isOpened()) { - assert(0 && "invalid frame"); - throw std::runtime_error(exceptionMessage( - "Cannot grab video frame: Cannot loop video source: " + - name())); - } - _capture >> _frame; - } - - if (!_capture.isOpened()) - throw std::runtime_error(exceptionMessage( - "Cannot grab video frame: Device is closed: " + name())); - - if (!_frame.cols || !_frame.rows) - throw std::runtime_error(exceptionMessage( - "Cannot grab video frame: Got an invalid frame from device: " + - name())); - - _counter.tick(); - - return _frame; -} - - -cv::Mat VideoCapture::lastFrame() const -{ - std::lock_guard guard(_mutex); - - if (!_opened) - throw std::runtime_error( - error().any() - ? error().message - : exceptionMessage( - "Cannot grab video frame: Please check device: " + - name())); - - if (!_frame.cols && !_frame.rows) - throw std::runtime_error(exceptionMessage( - "Cannot grab video frame: Device is closed: " + name())); - - if (_frame.size().area() <= 0) - throw std::runtime_error(exceptionMessage( - "Cannot grab video frame: Invalid source frame: " + name())); - - return _frame; // no data is copied -} - - -void VideoCapture::getFrame(cv::Mat& frame, int width, int height) -{ - LTrace << "Get frame: ", width("x", height) - - // Don't actually grab a frame here, just copy the current frame - // If no valid frame is available an exception will be thrown - cv::Mat lastFrame = this->lastFrame(); - if ((width && lastFrame.cols != width) || - (height && lastFrame.rows != height)) { - cv::resize(lastFrame, frame, cv::Size(width, height)); - } else { - lastFrame.copyTo(frame); - } -} - - -void VideoCapture::getEncoderFormat(Format& iformat) -{ - iformat.name = "OpenCV"; - // iformat.id = "rawvideo"; - iformat.video.encoder = "rawvideo"; - iformat.video.pixelFmt = "bgr24"; - iformat.video.width = width(); - iformat.video.height = height(); - iformat.video.enabled = true; -} - - -#if 0 -void VideoCapture::addEmitter(PacketSignal* emitter) -{ - std::lock_guard guard(_mutex); - _emitters.push_back(emitter); -} - - -void VideoCapture::removeEmitter(PacketSignal* emitter) -{ - std::lock_guard guard(_mutex); - for (PacketSignalVec::iterator it = _emitters.begin(); it != _emitters.end(); ++it) { - if (*it == emitter) { - _emitters.erase(it); - return; - } - } - assert(0 && "unknown emitter"); -} -#endif - - -void VideoCapture::setError(const std::string& error) -{ - LError("Set error: ", error) - { - std::lock_guard guard(_mutex); - _error.message = error; - } - Error.emit(_error); -} - - -int VideoCapture::width() -{ - std::lock_guard guard(_mutex); - return int(_capture.get(CV_CAP_PROP_FRAME_WIDTH)); // not const -} - - -int VideoCapture::height() -{ - std::lock_guard guard(_mutex); - return int(_capture.get(CV_CAP_PROP_FRAME_HEIGHT)); // not const -} - - -bool VideoCapture::opened() const -{ - std::lock_guard guard(_mutex); - return _opened; -} - - -bool VideoCapture::running() const -{ - std::lock_guard guard(_mutex); - return _thread.running(); -} - - -int VideoCapture::deviceId() const -{ - std::lock_guard guard(_mutex); - return _deviceId; -} - - -std::string VideoCapture::filename() const -{ - std::lock_guard guard(_mutex); - return _filename; -} - - -std::string VideoCapture::name() const -{ - std::lock_guard guard(_mutex); - std::stringstream ss; - _filename.empty() ? (ss << _deviceId) : (ss << _filename); - return ss.str(); -} - - -const scy::Error& VideoCapture::error() const -{ - std::lock_guard guard(_mutex); - return _error; -} - - -double VideoCapture::fps() const -{ - std::lock_guard guard(_mutex); - return _counter.fps; -} - - -cv::VideoCapture& VideoCapture::capture() -{ - std::lock_guard guard(_mutex); - return _capture; -} - - -} // namespace av -} // namespace scy - - -#endif diff --git a/src/av/include/scy/av/apple/avfoundation.h b/src/av/include/scy/av/apple/avfoundation.h index 04d986ab0..51e1a3657 100644 --- a/src/av/include/scy/av/apple/avfoundation.h +++ b/src/av/include/scy/av/apple/avfoundation.h @@ -9,8 +9,7 @@ /// @{ -#ifndef SCY_AV_AVFoundation_H -#define SCY_AV_AVFoundation_H +#pragma once #include "scy/av/devicemanager.h" @@ -33,6 +32,3 @@ bool getDeviceList(Device::Type type, std::vector& devices); } // namespace avfoundation } // namespace av } // namespace scy - - -#endif // SCY_AV_AVFoundation_H diff --git a/src/av/include/scy/av/audiobuffer.h b/src/av/include/scy/av/audiobuffer.h index 4cfa32962..fd232ad68 100644 --- a/src/av/include/scy/av/audiobuffer.h +++ b/src/av/include/scy/av/audiobuffer.h @@ -1,57 +1,75 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// @addtogroup av -/// @{ - - -#ifndef SCY_AV_AudioBuffer_H -#define SCY_AV_AudioBuffer_H - - -#include - -#include "scy/av/av.h" - -#ifdef HAVE_FFMPEG - -extern "C" { -#include -} - - -namespace scy { -namespace av { - - -struct AV_API AudioBuffer -{ - AudioBuffer(); - ~AudioBuffer(); - - void alloc(const std::string& sampleFmt, int channels, int numSamples = 1024); - void reset(); - void close(); - - void write(void** samples, int numSamples); - bool read(void** samples, int numSamples); - - int available() const; - - AVAudioFifo* fifo; -}; - - -} // namespace av -} // namespace scy - - -#endif -#endif // SCY_AV_AudioBuffer_H - - -/// @\} +/// +// +// LibSourcey +// Copyright (c) 2005, Sourcey +// +// SPDX-License-Identifier: LGPL-2.1+ +// +/// @addtogroup av +/// @{ + + +#pragma once + + +#include + +#include "scy/av/av.h" + +#ifdef HAVE_FFMPEG + +extern "C" { +#include +} + + +namespace scy { +namespace av { + + +struct AV_API AudioBuffer +{ + AudioBuffer(); + ~AudioBuffer() noexcept; + + AudioBuffer(const AudioBuffer&) = delete; + AudioBuffer& operator=(const AudioBuffer&) = delete; + AudioBuffer(AudioBuffer&&) = delete; + AudioBuffer& operator=(AudioBuffer&&) = delete; + + /// Allocate the audio FIFO buffer. + /// + /// @param sampleFmt The sample format name (e.g. "s16", "fltp"). + /// @param channels The number of audio channels. + /// @param numSamples The initial buffer capacity in samples per channel. + void alloc(const std::string& sampleFmt, int channels, int numSamples = 1024); + void reset(); + void close(); + + /// Write samples into the FIFO buffer. + /// + /// @param samples Array of per-channel sample buffers. + /// @param numSamples The number of samples per channel to write. + void write(void** samples, int numSamples); + + /// Read samples from the FIFO buffer. + /// + /// @param samples Array of per-channel sample buffers to fill. + /// @param numSamples The number of samples per channel to read. + /// @return True if enough samples were available. + bool read(void** samples, int numSamples); + + int available() const; + + AVAudioFifo* fifo; +}; + + +} // namespace av +} // namespace scy + + +#endif + + +/// @\} diff --git a/src/av/include/scy/av/audiocapture.h b/src/av/include/scy/av/audiocapture.h index 9177cc6fe..4ca6a9398 100644 --- a/src/av/include/scy/av/audiocapture.h +++ b/src/av/include/scy/av/audiocapture.h @@ -9,8 +9,7 @@ /// @{ -#ifndef SCY_AV_AudioCapture_H -#define SCY_AV_AudioCapture_H +#pragma once #include "scy/base.h" @@ -27,16 +26,16 @@ namespace av { class AV_API AudioCapture : public MediaCapture { public: - typedef std::shared_ptr Ptr; + using Ptr = std::shared_ptr; AudioCapture(); AudioCapture(const std::string& device, const av::AudioCodec& params); - AudioCapture(const std::string& device, int channels = -1, int sampleRate = -1, + AudioCapture(const std::string& device, int channels = -1, int sampleRate = -1, const std::string& sampleFmt = ""); - virtual ~AudioCapture(); + virtual ~AudioCapture() noexcept; virtual void openAudio(const std::string& device, const av::AudioCodec& params); - virtual void openAudio(const std::string& device, int channels = -1, int sampleRate = -1, + virtual void openAudio(const std::string& device, int channels = -1, int sampleRate = -1, const std::string& sampleFmt = ""); }; @@ -46,7 +45,6 @@ class AV_API AudioCapture : public MediaCapture #endif -#endif // SCY_AV_AudioCapture_H /// @\} diff --git a/src/av/include/scy/av/audiocontext.h b/src/av/include/scy/av/audiocontext.h index 98c655545..3baef4f8c 100644 --- a/src/av/include/scy/av/audiocontext.h +++ b/src/av/include/scy/av/audiocontext.h @@ -9,8 +9,7 @@ /// @{ -#ifndef SCY_AV_AudioContext_H -#define SCY_AV_AudioContext_H +#pragma once #include "scy/base.h" @@ -39,7 +38,12 @@ struct AudioResampler; struct AudioContext { AudioContext(); - virtual ~AudioContext(); + virtual ~AudioContext() noexcept; + + AudioContext(const AudioContext&) = delete; + AudioContext& operator=(const AudioContext&) = delete; + AudioContext(AudioContext&&) = delete; + AudioContext& operator=(AudioContext&&) = delete; /// Initialize the `AVCodecContext` with default values virtual void create() = 0; @@ -55,28 +59,26 @@ struct AudioContext PacketSignal emitter; - AudioCodec iparams; ///< input parameters - AudioCodec oparams; ///< output parameters - AVStream* stream; ///< encoder or decoder stream - AVCodecContext* ctx; ///< encoder or decoder context - AVCodec* codec; ///< encoder or decoder codec - AVFrame* frame; ///< last encoded or decoded frame - AudioResampler* resampler; ///< audio resampler - int outputFrameSize; ///< encoder or decoder output frame size - int64_t time; ///< stream time in codec time base - int64_t pts; ///< last packet pts value - double seconds; ///< video time in seconds - std::string error; ///< error message + AudioCodec iparams; ///< input parameters + AudioCodec oparams; ///< output parameters + AVStream* stream; ///< encoder or decoder stream + AVCodecContext* ctx; ///< encoder or decoder context + const AVCodec* codec; ///< encoder or decoder codec + AVFrame* frame; ///< last encoded or decoded frame + std::unique_ptr resampler; ///< audio resampler + int outputFrameSize; ///< encoder or decoder output frame size + int64_t time; ///< stream time in codec time base + int64_t pts; ///< last packet pts value + double seconds; ///< audio time in seconds + std::string error; ///< error message }; void initAudioCodecFromContext(const AVCodecContext* ctx, AudioCodec& params); -AVSampleFormat selectSampleFormat(AVCodec* codec, av::AudioCodec& params); -bool isSampleFormatSupported(AVCodec* codec, enum AVSampleFormat sampleFormat); -void initDecodedAudioPacket(const AVStream* stream, const AVCodecContext* ctx, - const AVFrame* frame, AVPacket* opacket); -bool frameIsPlanar(const std::string& pixfmt); -bool frameIsPlanar(AVSampleFormat format); +AVSampleFormat selectSampleFormat(const AVCodec* codec, av::AudioCodec& params); +bool isSampleFormatSupported(const AVCodec* codec, enum AVSampleFormat sampleFormat); +bool formatIsPlanar(const std::string& pixfmt); +bool formatIsPlanar(AVSampleFormat format); } // namespace av @@ -84,7 +86,6 @@ bool frameIsPlanar(AVSampleFormat format); #endif -#endif // SCY_AV_AudioContext_H /// @\} diff --git a/src/av/include/scy/av/audiodecoder.h b/src/av/include/scy/av/audiodecoder.h index da1ab2e07..2634791d0 100644 --- a/src/av/include/scy/av/audiodecoder.h +++ b/src/av/include/scy/av/audiodecoder.h @@ -9,16 +9,15 @@ /// @{ -#ifndef SCY_AV_AudioDecoder_H -#define SCY_AV_AudioDecoder_H +#pragma once #include "scy/base.h" #ifdef HAVE_FFMPEG -#include "scy/av/packet.h" #include "scy/av/audiocontext.h" +#include "scy/av/packet.h" namespace scy { @@ -28,15 +27,14 @@ namespace av { struct AudioDecoder : public AudioContext { AudioDecoder(AVStream* stream); - virtual ~AudioDecoder(); + ~AudioDecoder() noexcept override; virtual void create() override; virtual void close() override; /// Decodes a the given input packet. /// Returns true an output packet was created, false otherwise. - //virtual bool decode(uint8_t* data, int size); - virtual bool decode(AVPacket& ipacket); + [[nodiscard]] virtual bool decode(AVPacket& ipacket); /// Flushes buffered frames. /// This method should be called once after decoding. @@ -49,7 +47,6 @@ struct AudioDecoder : public AudioContext #endif -#endif // SCY_AV_AudioDecoder_H /// @\} diff --git a/src/av/include/scy/av/audioencoder.h b/src/av/include/scy/av/audioencoder.h index 07236face..edf95c31f 100644 --- a/src/av/include/scy/av/audioencoder.h +++ b/src/av/include/scy/av/audioencoder.h @@ -9,8 +9,7 @@ /// @{ -#ifndef SCY_AV_AudioEncoder_H -#define SCY_AV_AudioEncoder_H +#pragma once #include "scy/base.h" @@ -37,7 +36,7 @@ namespace av { struct AudioEncoder : public AudioContext { AudioEncoder(AVFormatContext* format = nullptr); - virtual ~AudioEncoder(); + ~AudioEncoder() noexcept override; virtual void create() override; virtual void close() override; @@ -48,7 +47,7 @@ struct AudioEncoder : public AudioContext /// @param numSamples The number of input samples per channel. /// @param pts The input samples presentation timestamp. /// @param opacket The output packet data will be encoded to. - virtual bool encode(uint8_t* samples, const int numSamples, const int64_t pts); + [[nodiscard]] virtual bool encode(uint8_t* samples, const int numSamples, const int64_t pts); /// Encode planar audio samples. /// @@ -56,10 +55,10 @@ struct AudioEncoder : public AudioContext /// @param numSamples The number of input samples per channel. /// @param pts The input samples presentation timestamp. /// @param opacket The output packet data will be encoded to. - virtual bool encode(uint8_t* samples[4], const int numSamples, const int64_t pts); + [[nodiscard]] virtual bool encode(uint8_t* samples[4], const int numSamples, const int64_t pts); /// Encode a single AVFrame from the decoder. - virtual bool encode(AVFrame* iframe); + [[nodiscard]] virtual bool encode(AVFrame* iframe); /// Flush remaining packets to be encoded. /// This method should be called once before stream closure. @@ -75,7 +74,6 @@ struct AudioEncoder : public AudioContext #endif -#endif // SCY_AV_AudioEncoder_H /// @\} diff --git a/src/av/include/scy/av/audioresampler.h b/src/av/include/scy/av/audioresampler.h index 63b1b168d..32d4f34fa 100644 --- a/src/av/include/scy/av/audioresampler.h +++ b/src/av/include/scy/av/audioresampler.h @@ -9,8 +9,7 @@ /// @{ -#ifndef SCY_AV_AudioResampler_H -#define SCY_AV_AudioResampler_H +#pragma once #include "scy/base.h" @@ -23,13 +22,10 @@ extern "C" { #include +#include #include -#include -#ifdef HAVE_FFMPEG_SWRESAMPLE #include -#else -#include -#endif +#include } @@ -43,7 +39,12 @@ struct AudioResampler { AudioResampler(const AudioCodec& iparams = AudioCodec(), const AudioCodec& oparams = AudioCodec()); - ~AudioResampler(); + ~AudioResampler() noexcept; + + AudioResampler(const AudioResampler&) = delete; + AudioResampler& operator=(const AudioResampler&) = delete; + AudioResampler(AudioResampler&&) = delete; + AudioResampler& operator=(AudioResampler&&) = delete; void open(); void close(); @@ -52,24 +53,21 @@ struct AudioResampler /// NOTE: Input buffers must be contiguous, therefore only interleaved /// input formats are accepted at this point. /// - /// Return the number of converted samples or zero if samples - /// were internally buffered. An exception will be thrown on error. + /// Converted samples are accessible via the `outSamples` class member. /// - /// Converted samples are accessable via the `outSamples` class member. + /// @param inSamples Pointer to the input sample buffer array. + /// @param inNumSamples The number of input samples per channel. + /// @return The number of converted samples, or zero if samples were internally buffered. int resample(uint8_t** inSamples, int inNumSamples); -#ifdef HAVE_FFMPEG_SWRESAMPLE SwrContext* ctx; ///< the conversion context -#else - AVAudioResampleContext* ctx; -#endif - AudioCodec iparams; ///< input audio parameters - AudioCodec oparams; ///< output audio parameters - uint8_t** outSamples; ///< the output samples buffer - int outNumSamples; ///< the number of samples currently in the output buffer - int outBufferSize; ///< the number of bytes currently in the buffer - int maxNumSamples; ///< the maximum number of samples that can be stored in + AudioCodec iparams; ///< input audio parameters + AudioCodec oparams; ///< output audio parameters + uint8_t** outSamples; ///< the output samples buffer + int outNumSamples; ///< the number of samples currently in the output buffer + int outBufferSize; ///< the number of bytes currently in the buffer + int maxNumSamples; ///< the maximum number of samples that can be stored in enum AVSampleFormat inSampleFmt; ///< input sample format enum AVSampleFormat outSampleFmt; ///< output sample format }; @@ -80,7 +78,6 @@ struct AudioResampler #endif -#endif // SCY_AV_AudioResampler_H /// @\} diff --git a/src/av/include/scy/av/av.h b/src/av/include/scy/av/av.h index 8de9b4cb5..8b38f8e5b 100644 --- a/src/av/include/scy/av/av.h +++ b/src/av/include/scy/av/av.h @@ -9,15 +9,14 @@ /// @{ -#ifndef SCY_AV_H -#define SCY_AV_H +#pragma once #include "scy/base.h" #define MAX_VIDEO_PACKET_SIZE (3 * 1024 * 1024) -#define MAX_AUDIO_PACKET_SIZE (128 * 1500) ///< 1 second of 48khz 32bit audio +#define MAX_AUDIO_PACKET_SIZE (128 * 1500) ///< 1 second of 48khz 32bit audio #define MAX_ENCODE_DURATION (3 * 60 * 60 * 1000) ///< 3 hours @@ -37,17 +36,14 @@ // Shared library exports #if defined(SCY_WIN) && defined(SCY_SHARED_LIBRARY) - #if defined(AV_EXPORTS) - #define AV_API __declspec(dllexport) - #else - #define AV_API __declspec(dllimport) - #endif +#if defined(AV_EXPORTS) +#define AV_API __declspec(dllexport) #else - #define AV_API // nothing +#define AV_API __declspec(dllimport) +#endif +#else +#define AV_API // nothing #endif - - -#endif // SCY_AV_H /// @\} diff --git a/src/av/include/scy/av/codec.h b/src/av/include/scy/av/codec.h index 14e3e3799..27f02b132 100644 --- a/src/av/include/scy/av/codec.h +++ b/src/av/include/scy/av/codec.h @@ -9,8 +9,7 @@ /// @{ -#ifndef SCY_AV_Codec_H -#define SCY_AV_Codec_H +#pragma once #include "scy/av/av.h" @@ -36,6 +35,7 @@ struct AV_API Codec int sampleRate; ///< The sampling rate or RTP clock rate. int bitRate; ///< The bit rate to encode at. int quality; ///< Optional quality value, variable range depending on codec. + int compliance; ///< FFmpeg strict_std_compliance level (default: FF_COMPLIANCE_EXPERIMENTAL). bool enabled; ///< Weather or not the codec is available for use. // @@ -47,7 +47,7 @@ struct AV_API Codec Codec(const std::string& name, const std::string& encoder, int sampleRate = 0, int bitRate = 0, bool enabled = true); /// Codec(const Codec& r); - virtual ~Codec(); + virtual ~Codec() noexcept; // // Methods @@ -75,10 +75,10 @@ struct AV_API AudioCodec : public Codec std::string sampleFmt; ///< One of: u8, s16, s32, flt, dbl, u8p, s16p, s32p, fltp, dblp AudioCodec(); - AudioCodec(int channels, // = DEFAULT_AUDIO_CHANNELS - int sampleRate, // = DEFAULT_AUDIO_SAMPLE_RATE - const std::string& sampleFmt = "", // = DEFAULT_AUDIO_SAMPLE_FMT - int bitRate = 0); // = DEFAULT_AUDIO_BIT_RATE + AudioCodec(int channels, // = DEFAULT_AUDIO_CHANNELS + int sampleRate, // = DEFAULT_AUDIO_SAMPLE_RATE + const std::string& sampleFmt = "", // = DEFAULT_AUDIO_SAMPLE_FMT + int bitRate = 0); // = DEFAULT_AUDIO_BIT_RATE AudioCodec(const std::string& name, int channels = 0, int sampleRate = 0, @@ -91,7 +91,7 @@ struct AV_API AudioCodec : public Codec int bitRate = 0, const std::string& sampleFmt = ""); // AudioCodec(const AudioCodec& r); - virtual ~AudioCodec(); + virtual ~AudioCodec() noexcept; virtual std::string toString() const override; virtual void print(std::ostream& ost) override; @@ -118,35 +118,35 @@ struct AV_API VideoCodec : public Codec VideoCodec(); VideoCodec(int width, int height, double fps = 0.0, - const std::string& pixelFmt = "", // = DEFAULT_VIDEO_PIXEL_FMT - int bitRate = 0, // = DEFAULT_VIDEO_BIT_RATE - int sampleRate = 0); // = DEFAULT_VIDEO_SAMPLE_RATE + const std::string& pixelFmt = DEFAULT_VIDEO_PIXEL_FMT, + int bitRate = 0, // = DEFAULT_VIDEO_BIT_RATE + int sampleRate = 0); // = DEFAULT_VIDEO_SAMPLE_RATE VideoCodec(const std::string& name, int width = 0, int height = 0, double fps = 0.0, int bitRate = 0, int sampleRate = 0, - const std::string& pixelFmt = ""); + const std::string& pixelFmt = DEFAULT_VIDEO_PIXEL_FMT); VideoCodec(const std::string& name, const std::string& encoder, int width = 0, int height = 0, double fps = 0.0, int bitRate = 0, int sampleRatee = 0, - const std::string& pixelFmt = ""); + const std::string& pixelFmt = DEFAULT_VIDEO_PIXEL_FMT); VideoCodec(const VideoCodec& r); - virtual ~VideoCodec(); + virtual ~VideoCodec() noexcept; virtual std::string toString() const override; virtual void print(std::ostream& ost) override; }; -typedef std::list CodecList; -typedef std::list CodecPList; +using CodecList = std::list; +using CodecPList = std::list; // --------------------------------------------------------------------- // inline int64_t fpsToInterval(int fps) { - static const int64_t kMinimumInterval = time::kNumNanosecsPerSec / 10000; // 10k fps. + static const int64_t kMinimumInterval = time::kNumNanosecsPerSec / 10000; // 10k fps. return fps ? time::kNumNanosecsPerSec / fps : kMinimumInterval; } @@ -171,6 +171,3 @@ inline float intervalToFpsFloat(int64_t interval) } // namespace av } // namespace scy - - -#endif diff --git a/src/av/include/scy/av/devicemanager.h b/src/av/include/scy/av/devicemanager.h index 97dd8372b..305f5e298 100644 --- a/src/av/include/scy/av/devicemanager.h +++ b/src/av/include/scy/av/devicemanager.h @@ -1,163 +1,160 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// @addtogroup av -/// @{ - - -#ifndef SCY_AV_DeviceManager_H -#define SCY_AV_DeviceManager_H - -#include -#include - -#include "scy/av/av.h" -#include "scy/signal.h" - -#ifdef HAVE_FFMPEG - -#include "scy/av/ffmpeg.h" - -extern "C" { -#include -#include -#ifdef HAVE_FFMPEG_AVDEVICE -#include -#endif -} - -#endif - - -namespace scy { -namespace av { - - -class AV_API DeviceManager; - - -// -// Device -// - -/// Represents a system audio, video or render device. -struct AV_API Device -{ - enum Type - { - Unknown, - VideoInput, - VideoOutput, - AudioInput, - AudioOutput - }; - - Type type; - std::string id; - std::string name; - bool isDefault; - - Device(); - Device(Type type, const std::string& id, const std::string& name, bool isDefault = false); - - void print(std::ostream& os); - - bool operator==(const Device& that) const - { - return type == that.type && id == that.id && name == that.name; - } -}; - - -enum MediaCapabilities -{ - AUDIO_RECV = 1 << 0, - AUDIO_SEND = 1 << 1, - VIDEO_RECV = 1 << 2, - VIDEO_SEND = 1 << 3, -}; - - -// -// Device Watcher -// - - -class AV_API DeviceWatcher -{ -public: - explicit DeviceWatcher(DeviceManager*) {} - virtual ~DeviceWatcher() {} - virtual bool start() { return true; } - virtual void stop() {} -}; - - -// -// Device Manager -// - - -class AV_API DeviceManager -{ -public: - DeviceManager(); - ~DeviceManager(); - - /// Device enumeration - bool getCameras(std::vector& devices); - bool getMicrophones(std::vector& devices); - bool getSpeakers(std::vector& devices); - - /// Default devices - bool getDefaultMicrophone(Device& device); - bool getDefaultSpeaker(Device& device); - bool getDefaultCamera(Device& device); - - /// Find device by name or id - bool findCamera(const std::string& name, Device& device); - bool findMicrophone(const std::string& name, Device& device); - bool findSpeaker(const std::string& name, Device& device); - - /// Base device list - bool getDeviceList(Device::Type type, std::vector& devices); - - /// Capabilities - int getCapabilities(); - - void setWatcher(DeviceWatcher* watcher); - DeviceWatcher* watcher(); - - /// Print all devices to the output stream. - void print(std::ostream& ost); - - /// Returns the default `DeviceManager` singleton. - static DeviceManager& instance(); - - /// Shuts down the `MediaFactory` and deletes the singleton instance. - static void shutdown(); - - /// Signals when a system device is connecetd or removed. - /// This signal is emitted by the platform specific `DeviceWatcher`. - NullSignal DevicesChanged; - -#ifdef HAVE_FFMPEG - /// Find base FFmpeg formats - AVInputFormat* findVideoInputFormat(); - AVInputFormat* findAudioInputFormat(); -#endif - -protected: - std::unique_ptr _watcher; -}; - - -} // namespace av -} // namespace scy - - -#endif // SCY_AV_DeviceManager_H +/// +// +// LibSourcey +// Copyright (c) 2005, Sourcey +// +// SPDX-License-Identifier: LGPL-2.1+ +// +/// @addtogroup av +/// @{ + + +#pragma once + + +#include +#include + +#include "scy/av/av.h" +#include "scy/signal.h" + +#ifdef HAVE_FFMPEG + +#include "scy/av/ffmpeg.h" + +extern "C" { +#include +#include +#ifdef HAVE_FFMPEG_AVDEVICE +#include +#endif +} + +#endif + + +namespace scy { +namespace av { + + +class AV_API DeviceManager; + + +// +// Device +// + +/// Represents a system audio, video or render device. +struct AV_API Device +{ + enum Type + { + Unknown, + VideoInput, + VideoOutput, + AudioInput, + AudioOutput + }; + + Type type; + std::string id; + std::string name; + bool isDefault; + + Device(); + Device(Type type, const std::string& id, const std::string& name, bool isDefault = false); + + void print(std::ostream& os); + + bool operator==(const Device& that) const + { + return type == that.type && id == that.id && name == that.name; + } +}; + + +enum MediaCapabilities +{ + AUDIO_RECV = 1 << 0, + AUDIO_SEND = 1 << 1, + VIDEO_RECV = 1 << 2, + VIDEO_SEND = 1 << 3, +}; + + +// +// Device Watcher +// + + +class AV_API DeviceWatcher +{ +public: + explicit DeviceWatcher(DeviceManager*) {} + virtual ~DeviceWatcher() noexcept {} + virtual bool start() { return true; } + virtual void stop() {} +}; + + +// +// Device Manager +// + + +class AV_API DeviceManager +{ +public: + DeviceManager(); + ~DeviceManager() noexcept; + + /// Device enumeration + bool getCameras(std::vector& devices); + bool getMicrophones(std::vector& devices); + bool getSpeakers(std::vector& devices); + + /// Default devices + bool getDefaultMicrophone(Device& device); + bool getDefaultSpeaker(Device& device); + bool getDefaultCamera(Device& device); + + /// Find device by name or id + bool findCamera(const std::string& name, Device& device); + bool findMicrophone(const std::string& name, Device& device); + bool findSpeaker(const std::string& name, Device& device); + + /// Base device list + bool getDeviceList(Device::Type type, std::vector& devices); + + /// Capabilities + int getCapabilities(); + + void setWatcher(DeviceWatcher* watcher); + DeviceWatcher* watcher(); + + /// Print all devices to the output stream. + void print(std::ostream& ost); + + /// Returns the default `DeviceManager` singleton. + static DeviceManager& instance(); + + /// Shuts down the `MediaFactory` and deletes the singleton instance. + static void shutdown(); + + /// Signals when a system device is connecetd or removed. + /// This signal is emitted by the platform specific `DeviceWatcher`. + NullSignal DevicesChanged; + +#ifdef HAVE_FFMPEG + /// Find base FFmpeg formats + const AVInputFormat* findVideoInputFormat(); + const AVInputFormat* findAudioInputFormat(); +#endif + +protected: + std::unique_ptr _watcher; +}; + + +} // namespace av +} // namespace scy diff --git a/src/av/include/scy/av/ffmpeg.h b/src/av/include/scy/av/ffmpeg.h index 550202a13..17d5e1fad 100644 --- a/src/av/include/scy/av/ffmpeg.h +++ b/src/av/include/scy/av/ffmpeg.h @@ -9,18 +9,18 @@ /// @{ -#ifndef SCY_AV_FFmpeg_H -#define SCY_AV_FFmpeg_H +#pragma once #include "scy/base.h" -#include #include +#include #ifdef HAVE_FFMPEG extern "C" { +#include #include #ifdef HAVE_FFMPEG_AVDEVICE #include @@ -54,48 +54,41 @@ void printEncoders(std::ostream& ost, const char* delim = " "); /// Utilites for RAII: /// Deleter adaptor for functions like av_free that take a pointer. -template struct Deleter { - inline void operator() (T* p) const { +template +struct Deleter +{ + inline void operator()(T* p) const + { if (p) Fn(p); } }; /// Deleter adaptor for functions like av_freep that take a pointer to a pointer. -template struct Deleterp { - inline void operator() (T* p) const { +template +struct Deleterp +{ + inline void operator()(T* p) const + { if (p) Fn(&p); } }; using AVFrameHolder = std::unique_ptr< - AVFrame, Deleterp ->; - -// using AVFifoBufferHolder = std::unique_ptr< -// AVFifoBuffer, Deleter -// >; + AVFrame, Deleterp>; using AVFormatContextHolder = std::unique_ptr< - AVFormatContext, Deleter ->; + AVFormatContext, Deleter>; using AVCodecContextHolder = std::unique_ptr< - AVCodecContext, Deleter ->; + AVCodecContext, Deleterp>; using AVDictionaryCleanup = std::unique_ptr< - AVDictionary*, Deleter ->; + AVDictionary*, Deleter>; -// using UFileHolder = std::unique_ptr< -// AVIOContext, Deleter -// >; - -// template using AVMallocHolder = std::unique_ptr< -// T, Deleter -// >; +using AVPacketHolder = std::unique_ptr< + AVPacket, Deleterp>; #endif @@ -104,7 +97,4 @@ using AVDictionaryCleanup = std::unique_ptr< } // namespace scy -#endif // SCY_Media_FFmpeg_H - - /// @\} diff --git a/src/av/include/scy/av/format.h b/src/av/include/scy/av/format.h index b646daf89..bcce7fc97 100644 --- a/src/av/include/scy/av/format.h +++ b/src/av/include/scy/av/format.h @@ -9,8 +9,7 @@ /// @{ -#ifndef SCY_AV_Format_H -#define SCY_AV_Format_H +#pragma once #include "scy/av/codec.h" @@ -82,12 +81,9 @@ struct AV_API Format }; -typedef std::vector FormatList; -typedef std::vector FormatPList; +using FormatList = std::vector; +using FormatPList = std::vector; } // namespace av } // namespace scy - - -#endif diff --git a/src/av/include/scy/av/formatregistry.h b/src/av/include/scy/av/formatregistry.h index dc3c6c662..008adf845 100644 --- a/src/av/include/scy/av/formatregistry.h +++ b/src/av/include/scy/av/formatregistry.h @@ -9,8 +9,7 @@ /// @{ -#ifndef SCY_AV_FormatRegistry_H -#define SCY_AV_FormatRegistry_H +#pragma once #include "scy/av/format.h" @@ -28,14 +27,14 @@ class AV_API FormatRegistry static FormatRegistry& instance(); FormatRegistry(); - virtual ~FormatRegistry(); + virtual ~FormatRegistry() noexcept; virtual Format& get(const std::string& name); virtual Format& getByID(const std::string& id); /// Returns the default media format. virtual Format& getOrDefault(const std::string& name); - + /// If a default has been specified it will be /// returned, other the format with the highest /// priority will take precedence. @@ -58,8 +57,13 @@ class AV_API FormatRegistry virtual FormatList formats() const; private: - FormatRegistry(FormatRegistry const&) = delete; - FormatRegistry& operator=(FormatRegistry const&) = delete; + FormatRegistry(const FormatRegistry&) = delete; + FormatRegistry& operator=(const FormatRegistry&) = delete; + FormatRegistry(FormatRegistry&&) = delete; + FormatRegistry& operator=(FormatRegistry&&) = delete; + + Format& findByName(const std::string& name); // requires _mutex held + Format& defaultLocked(); // requires _mutex held FormatList _formats; std::string _default; @@ -71,7 +75,4 @@ class AV_API FormatRegistry } // namespace scy -#endif // SCY_AV_FormatRegistry_H - - /// @\} diff --git a/src/av/include/scy/av/fpscounter.h b/src/av/include/scy/av/fpscounter.h index 5bbf45ac7..a44cf6ba9 100644 --- a/src/av/include/scy/av/fpscounter.h +++ b/src/av/include/scy/av/fpscounter.h @@ -9,12 +9,11 @@ /// @{ -#ifndef SCY_AV_FPSCounter_H -#define SCY_AV_FPSCounter_H +#pragma once -#include "scy/packetstream.h" #include "scy/av/packet.h" +#include "scy/packetstream.h" #include @@ -85,9 +84,9 @@ struct FPSCounter double total; double fps; - FPSCounter() - { - reset(); + FPSCounter() + { + reset(); } void tick() @@ -106,14 +105,14 @@ struct FPSCounter frames = 0; } - bool started() - { - return start != 0; + bool started() + { + return start != 0; } - void startFrame() - { - start = clock(); + void startFrame() + { + start = clock(); } double endFrame() @@ -126,7 +125,7 @@ struct FPSCounter } }; -} // legacy +} // namespace legacy /// This class limits the throughput rate of IPackets @@ -157,7 +156,7 @@ class AV_API FPSLimiter : public PacketProcessor if (_counter.started()) _counter.endFrame(); if (static_cast(_counter.fps) > _max) { - STrace << "Dropping packet: " + STrace << "Dropping packet: " << _counter.fps << " > " << _max << std::endl; return; } @@ -183,7 +182,4 @@ class AV_API FPSLimiter : public PacketProcessor } // namespace scy -#endif // SCY_AV_FPSCounter_H - - /// @\} diff --git a/src/av/include/scy/av/icapture.h b/src/av/include/scy/av/icapture.h index aa19e1718..323b40f36 100644 --- a/src/av/include/scy/av/icapture.h +++ b/src/av/include/scy/av/icapture.h @@ -9,8 +9,7 @@ /// @{ -#ifndef SCY_AV_ICapture_H -#define SCY_AV_ICapture_H +#pragma once #include "scy/packetstream.h" @@ -23,7 +22,8 @@ namespace av { struct Format; -class AV_API ICapture : public PacketSource, public basic::Startable +class AV_API ICapture : public PacketSource + , public basic::Startable { public: ICapture() @@ -58,7 +58,4 @@ class AV_API ICapture : public PacketSource, public basic::Startable } // namespace scy -#endif // SCY_AV_ICapture_H - - /// @\} diff --git a/src/av/include/scy/av/iencoder.h b/src/av/include/scy/av/iencoder.h index b5237c982..0e6fce192 100644 --- a/src/av/include/scy/av/iencoder.h +++ b/src/av/include/scy/av/iencoder.h @@ -9,8 +9,7 @@ /// @{ -#ifndef SCY_AV_IEncoder_H -#define SCY_AV_IEncoder_H +#pragma once #include "scy/av/format.h" @@ -102,14 +101,11 @@ class AV_API IEncoder : public Stateful }; -typedef IEncoder IPacketEncoder; ///< 0.8.x compatibility +using IPacketEncoder = IEncoder; ///< 0.8.x compatibility } // namespace av } // namespace scy -#endif // SCY_AV_IEncoder_H - - /// @\} diff --git a/src/av/include/scy/av/mediacapture.h b/src/av/include/scy/av/mediacapture.h index c3bbf142b..40745d1f6 100644 --- a/src/av/include/scy/av/mediacapture.h +++ b/src/av/include/scy/av/mediacapture.h @@ -9,8 +9,7 @@ /// @{ -#ifndef SCY_AV_MediaCapture_H -#define SCY_AV_MediaCapture_H +#pragma once #include "scy/base.h" @@ -25,6 +24,8 @@ #include "scy/interface.h" #include "scy/packetsignal.h" +#include + namespace scy { namespace av { @@ -32,13 +33,19 @@ namespace av { /// This class implements a cross platform audio, video, screen and /// video file capturer. -class AV_API MediaCapture : public ICapture, public basic::Runnable +class AV_API MediaCapture : public ICapture + , public basic::Runnable { public: - typedef std::shared_ptr Ptr; + using Ptr = std::shared_ptr; MediaCapture(); - virtual ~MediaCapture(); + ~MediaCapture() noexcept override; + + MediaCapture(const MediaCapture&) = delete; + MediaCapture& operator=(const MediaCapture&) = delete; + MediaCapture(MediaCapture&&) = delete; + MediaCapture& operator=(MediaCapture&&) = delete; virtual void openFile(const std::string& file); // #ifdef HAVE_FFMPEG_AVDEVICE @@ -56,11 +63,16 @@ class AV_API MediaCapture : public ICapture, public basic::Runnable virtual void getEncoderAudioCodec(AudioCodec& params); virtual void getEncoderVideoCodec(VideoCodec& params); - /// Continuously loop the input file when set + /// Continuously loop the input file when set. void setLoopInput(bool flag); - /// Playback video in real time when set - void setRealtimePlayback(bool flag); + /// Limit playback to video FPS. + void setLimitFramerate(bool flag); + + /// Set to use realtime PTS calculation. + /// This is preferred when sing live captures as FFmpeg provided values are + /// not always reliable. + void setRealtimePTS(bool flag); AVFormatContext* formatCtx() const; VideoDecoder* video() const; @@ -73,7 +85,12 @@ class AV_API MediaCapture : public ICapture, public basic::Runnable NullSignal Closing; protected: - virtual void openStream(const std::string& filename, AVInputFormat* inputFormat, AVDictionary** formatParams); + /// Open the underlying media stream. + /// + /// @param filename The file path or device name to open. + /// @param inputFormat The forced input format, or nullptr for auto-detect. + /// @param formatParams Optional format parameters; may be updated by FFmpeg on return. + virtual void openStream(const std::string& filename, const AVInputFormat* inputFormat, AVDictionary** formatParams); void emit(IPacket& packet); @@ -81,12 +98,13 @@ class AV_API MediaCapture : public ICapture, public basic::Runnable mutable std::mutex _mutex; Thread _thread; AVFormatContext* _formatCtx; - VideoDecoder* _video; - AudioDecoder* _audio; + std::unique_ptr _video; + std::unique_ptr _audio; std::string _error; - bool _stopping; - bool _looping; - bool _realtime; + std::atomic _stopping; + std::atomic _looping; + std::atomic _realtime; + std::atomic _ratelimit; }; @@ -95,7 +113,6 @@ class AV_API MediaCapture : public ICapture, public basic::Runnable #endif -#endif // SCY_AV_MediaCapture_H /// @\} diff --git a/src/av/include/scy/av/multiplexencoder.h b/src/av/include/scy/av/multiplexencoder.h index 21e7d17f2..7d93ee163 100644 --- a/src/av/include/scy/av/multiplexencoder.h +++ b/src/av/include/scy/av/multiplexencoder.h @@ -9,8 +9,7 @@ /// @{ -#ifndef SCY_AV_MultiplexEncoder_H -#define SCY_AV_MultiplexEncoder_H +#pragma once #include "scy/base.h" @@ -23,8 +22,8 @@ #include "scy/av/packet.h" #include "scy/av/videoencoder.h" #include "scy/packetstream.h" -#include #include +#include extern "C" { #include @@ -43,7 +42,12 @@ class AV_API MultiplexEncoder : public IEncoder { public: MultiplexEncoder(const EncoderOptions& options = EncoderOptions()); - virtual ~MultiplexEncoder(); + ~MultiplexEncoder() noexcept override; + + MultiplexEncoder(const MultiplexEncoder&) = delete; + MultiplexEncoder& operator=(const MultiplexEncoder&) = delete; + MultiplexEncoder(MultiplexEncoder&&) = delete; + MultiplexEncoder& operator=(MultiplexEncoder&&) = delete; virtual void init() override; virtual void uninit() override; @@ -54,26 +58,49 @@ class AV_API MultiplexEncoder : public IEncoder /// Encode a single video frame. /// All frame values must be set, such as size, pizel format and PTS. - virtual bool encodeVideo(AVFrame* frame); + [[nodiscard]] virtual bool encodeVideo(AVFrame* frame); - /// Encode a single video frame. + /// Encode a single interleaved video frame. /// If the frame time is specified it should be the microseconds /// offset since the start of the input stream. If no time is specified /// a realtime time value will be assigned to the frame. - virtual bool encodeVideo(uint8_t* buffer, int bufferSize, int width, int height, - int64_t time = AV_NOPTS_VALUE); - virtual bool encodeVideo(uint8_t* data[4], int linesize[4], int width, int height, - int64_t time = AV_NOPTS_VALUE); + /// + /// @param buffer The raw video frame buffer. + /// @param bufferSize The buffer size in bytes. + /// @param width The frame width in pixels. + /// @param height The frame height in pixels. + /// @param time The timestamp in microseconds, or AV_NOPTS_VALUE for realtime. + [[nodiscard]] virtual bool encodeVideo(uint8_t* buffer, int bufferSize, int width, int height, + int64_t time = AV_NOPTS_VALUE); + + /// Encode a single planar video frame. + /// + /// @param data Array of per-plane data pointers (up to 4 planes). + /// @param linesize Array of per-plane byte strides. + /// @param width The frame width in pixels. + /// @param height The frame height in pixels. + /// @param time The timestamp in microseconds, or AV_NOPTS_VALUE for realtime. + [[nodiscard]] virtual bool encodeVideo(uint8_t* data[4], int linesize[4], int width, int height, + int64_t time = AV_NOPTS_VALUE); virtual void createAudio(); virtual void freeAudio(); - /// Encode a single audio frame. - // virtual bool encodeAudio(AVFrame* frame); - virtual bool encodeAudio(uint8_t* buffer, int numSamples, - int64_t time = AV_NOPTS_VALUE); - virtual bool encodeAudio(uint8_t* data[4], int numSamples, - int64_t time = AV_NOPTS_VALUE); + /// Encode a single interleaved audio frame. + /// + /// @param buffer The interleaved audio sample buffer. + /// @param numSamples The number of samples per channel. + /// @param time The timestamp in microseconds, or AV_NOPTS_VALUE for realtime. + [[nodiscard]] virtual bool encodeAudio(uint8_t* buffer, int numSamples, + int64_t time = AV_NOPTS_VALUE); + + /// Encode a single planar audio frame. + /// + /// @param data Array of per-plane sample buffers (one per channel). + /// @param numSamples The number of samples per channel. + /// @param time The timestamp in microseconds, or AV_NOPTS_VALUE for realtime. + [[nodiscard]] virtual bool encodeAudio(uint8_t* data[4], int numSamples, + int64_t time = AV_NOPTS_VALUE); /// Flush and beffered or queued packets. virtual void flush(); @@ -88,6 +115,9 @@ class AV_API MultiplexEncoder : public IEncoder bool writeOutputPacket(AVPacket& packet); /// Convert input microseconds to the stream time base. + /// + /// @param stream The target stream for time base conversion. + /// @param pts Pointer to the timestamp; converted in place. bool updateStreamPts(AVStream* stream, int64_t* pts); void onVideoEncoded(av::VideoPacket& packet); @@ -95,10 +125,10 @@ class AV_API MultiplexEncoder : public IEncoder EncoderOptions _options; AVFormatContext* _formatCtx; - VideoEncoder* _video; - AudioEncoder* _audio; + std::unique_ptr _video; + std::unique_ptr _audio; AVIOContext* _ioCtx; - uint8_t* _ioBuffer; + std::unique_ptr _ioBuffer; int64_t _pts; mutable std::mutex _mutex; }; @@ -109,7 +139,6 @@ class AV_API MultiplexEncoder : public IEncoder #endif -#endif // SCY_AV_MultiplexEncoder_H /// @\} diff --git a/src/av/include/scy/av/multiplexpacketencoder.h b/src/av/include/scy/av/multiplexpacketencoder.h index 60a245e07..c06c90432 100644 --- a/src/av/include/scy/av/multiplexpacketencoder.h +++ b/src/av/include/scy/av/multiplexpacketencoder.h @@ -9,8 +9,7 @@ /// @{ -#ifndef SCY_AV_MultiplexPacketEncoder_H -#define SCY_AV_MultiplexPacketEncoder_H +#pragma once #include "scy/base.h" @@ -26,11 +25,17 @@ namespace av { /// Encodes and multiplexes a realtime video stream form /// audio / video capture sources. /// FFmpeg is used for encoding. -class AV_API MultiplexPacketEncoder : public MultiplexEncoder, public PacketProcessor +class AV_API MultiplexPacketEncoder : public MultiplexEncoder + , public PacketProcessor { public: MultiplexPacketEncoder(const EncoderOptions& options = EncoderOptions()); - virtual ~MultiplexPacketEncoder(); + virtual ~MultiplexPacketEncoder() noexcept; + + MultiplexPacketEncoder(const MultiplexPacketEncoder&) = delete; + MultiplexPacketEncoder& operator=(const MultiplexPacketEncoder&) = delete; + MultiplexPacketEncoder(MultiplexPacketEncoder&&) = delete; + MultiplexPacketEncoder& operator=(MultiplexPacketEncoder&&) = delete; virtual void encode(VideoPacket& packet); virtual void encode(AudioPacket& packet); @@ -47,73 +52,8 @@ class AV_API MultiplexPacketEncoder : public MultiplexEncoder, public PacketProc }; -#if 0 -// -// PTS Calculator -// - -/// Helper class which calculates PTS values for a live source -struct PTSCalculator -{ - AVRational timeBase; - clock_t frameTime; - double frameDuration; - double frameDiff; - - int64_t currentPTS; - int64_t lastPTS; - - PTSCalculator() { - reset(); - } - - void reset() { - lastPTS = 0; - currentPTS = 0; - frameTime = 0; - frameDuration = 0; - frameDiff = 0; - } - - void log() { - Timestamp ts; - debugL("PTSCalculator", this) << "Values:" - << "\n\tCurrent PTS: " << currentPTS - << "\n\tLast PTS: " << lastPTS - << "\n\tFrame Duration: " << frameDuration - << "\n\tFrame Diff: " << frameDiff - << "\n\tFrame Time: " << frameTime - << "\n\tTime Base: " << timeBase.den << ": " << timeBase.num - << std::endl; - } - - int64_t tick() { - /// Initializing - if (frameTime == 0) { - assert(!frameDuration); - frameTime = clock(); - currentPTS = 1; - } /// Updating - else { - frameDuration = (double)(clock() - frameTime) / CLOCKS_PER_SEC; - frameTime = clock(); - frameDiff = timeBase.den/(timeBase.num/(frameDuration)); - currentPTS = lastPTS + frameDiff; - } - - log(); - - assert(currentPTS > lastPTS); - lastPTS = currentPTS; - return currentPTS; - } -}; -#endif - - } // namespace av } // namespace scy #endif -#endif diff --git a/src/av/include/scy/av/packet.h b/src/av/include/scy/av/packet.h index 3a28347d9..f299a78a0 100644 --- a/src/av/include/scy/av/packet.h +++ b/src/av/include/scy/av/packet.h @@ -9,14 +9,16 @@ /// @{ -#ifndef SCY_AV_Packet_H -#define SCY_AV_Packet_H +#pragma once #include "scy/av/av.h" #include "scy/packet.h" #include "scy/time.h" +struct AVPacket; +struct AVFrame; + namespace scy { namespace av { @@ -32,6 +34,13 @@ struct MediaPacket : public RawPacket { } + /// Construct with const data (copied, owning). + MediaPacket(const uint8_t* data, size_t size, int64_t time = 0) + : RawPacket(reinterpret_cast(data), size) + , time(time) + { + } + MediaPacket(const MediaPacket& r) : RawPacket(r) , time(r.time) @@ -40,7 +49,7 @@ struct MediaPacket : public RawPacket virtual ~MediaPacket() = default; - virtual IPacket* clone() const override { return new MediaPacket(*this); } + virtual std::unique_ptr clone() const override { return std::make_unique(*this); } virtual const char* className() const override { return "MediaPacket"; } }; @@ -53,6 +62,10 @@ struct VideoPacket : public MediaPacket int height; bool iframe; + /// Non-owning pointer to the encoded AVPacket from FFmpeg. + /// Set by VideoEncoder, read by MultiplexEncoder. + AVPacket* avpacket = nullptr; + VideoPacket(uint8_t* data = nullptr, size_t size = 0, int width = 0, int height = 0, int64_t time = 0) : MediaPacket(data, size, time) @@ -67,30 +80,43 @@ struct VideoPacket : public MediaPacket , width(r.width) , height(r.height) , iframe(r.iframe) + , avpacket(r.avpacket) { } virtual ~VideoPacket() = default; - virtual IPacket* clone() const override { return new VideoPacket(*this); } + virtual std::unique_ptr clone() const override { return std::make_unique(*this); } virtual const char* className() const override { return "VideoPacket"; } }; -/// Video packet for planar formats +/// Video packet for planar formats. +/// +/// @param data Array of per-plane data pointers (up to 4 planes). +/// @param linesize Array of per-plane byte strides. +/// @param pixelFmt The pixel format name (e.g. "yuv420p"). +/// @param width The frame width in pixels. +/// @param height The frame height in pixels. +/// @param time The timestamp in microseconds. struct PlanarVideoPacket : public VideoPacket { - uint8_t* buffer[4] = { nullptr }; - int linesize[4]; + uint8_t* buffer[4] = {nullptr}; + int linesize[4] = {0}; std::string pixelFmt; + bool owns_buffer = false; + + /// Non-owning pointer to the decoded AVFrame from FFmpeg. + /// Set by VideoDecoder. + AVFrame* avframe = nullptr; PlanarVideoPacket(uint8_t* data[4], const int linesize[4], const std::string& pixelFmt = "", int width = 0, int height = 0, int64_t time = 0); PlanarVideoPacket(const PlanarVideoPacket& r); - virtual ~PlanarVideoPacket(); + virtual ~PlanarVideoPacket() noexcept; - virtual IPacket* clone() const { return new PlanarVideoPacket(*this); } + virtual std::unique_ptr clone() const override { return std::make_unique(*this); } virtual const char* className() const { return "PlanarVideoPacket"; } }; @@ -101,6 +127,10 @@ struct AudioPacket : public MediaPacket { size_t numSamples; // number of samples per channel + /// Non-owning pointer to the encoded AVPacket from FFmpeg. + /// Set by AudioEncoder, read by MultiplexEncoder. + AVPacket* avpacket = nullptr; + AudioPacket(uint8_t* data = nullptr, size_t size = 0, size_t numSamples = 0, int64_t time = 0) @@ -111,31 +141,38 @@ struct AudioPacket : public MediaPacket virtual ~AudioPacket() = default; - virtual IPacket* clone() const override { return new AudioPacket(*this); } + virtual std::unique_ptr clone() const override { return std::make_unique(*this); } virtual uint8_t* samples() const { return reinterpret_cast(_data); } - virtual const char* className() const override{ return "AudioPacket"; } + virtual const char* className() const override { return "AudioPacket"; } }; -/// Audio packet for planar formats +/// Audio packet for planar formats. +/// +/// @param data Array of per-plane sample buffers (one per channel). +/// @param channels The number of audio channels. +/// @param numSamples The number of samples per channel. +/// @param sampleFmt The sample format name (e.g. "fltp"). +/// @param time The timestamp in microseconds. struct PlanarAudioPacket : public AudioPacket { - uint8_t* buffer[4] = { nullptr }; - int linesize; - int channels; + uint8_t* buffer[4] = {nullptr}; + int linesize = 0; + int channels = 0; std::string sampleFmt; + bool owns_buffer = false; PlanarAudioPacket(uint8_t* data[4], int channels = 0, size_t numSamples = 0, //, size_t size = 0 const std::string& sampleFmt = "", int64_t time = 0); PlanarAudioPacket(const PlanarAudioPacket& r); - virtual ~PlanarAudioPacket(); + virtual ~PlanarAudioPacket() noexcept; - virtual IPacket* clone() const override { return new PlanarAudioPacket(*this); } + virtual std::unique_ptr clone() const override { return std::make_unique(*this); } virtual const char* className() const override { return "PlanarAudioPacket"; } }; @@ -145,7 +182,4 @@ struct PlanarAudioPacket : public AudioPacket } // namespace scy -#endif // SCY_AV_Packet_H - - /// @\} diff --git a/src/av/include/scy/av/realtimepacketqueue.h b/src/av/include/scy/av/realtimepacketqueue.h index 00bb884da..fc62570f1 100644 --- a/src/av/include/scy/av/realtimepacketqueue.h +++ b/src/av/include/scy/av/realtimepacketqueue.h @@ -9,8 +9,7 @@ /// @{ -#ifndef SCY_RealtimePacketQueue_H -#define SCY_RealtimePacketQueue_H +#pragma once #include "scy/av/packet.h" @@ -27,14 +26,14 @@ template class RealtimePacketQueue : public AsyncPacketQueue { public: - typedef AsyncPacketQueue BaseQueue; + using BaseQueue = AsyncPacketQueue; RealtimePacketQueue(int maxSize = 1024) : BaseQueue(maxSize) { } - virtual ~RealtimePacketQueue() + virtual ~RealtimePacketQueue() noexcept { } @@ -63,13 +62,13 @@ class RealtimePacketQueue : public AsyncPacketQueue BaseQueue::pop(); STrace << "Pop next: " << BaseQueue::size() << ": " - << realTime() << " > " << next->time << std::endl; + << realTime() << " > " << next->time << std::endl; return next; } virtual void onStreamStateChange(const PacketStreamState& state) override { - LTrace("Stream state changed: ", state) + LTrace("Stream state changed: ", state); if (state.equals(PacketStreamState::Active)) { _startTime = time::hrtime(); @@ -80,7 +79,8 @@ class RealtimePacketQueue : public AsyncPacketQueue struct MediaPacketTimeCompare { - bool operator()(const MediaPacket* a, const MediaPacket* b) { + bool operator()(const MediaPacket* a, const MediaPacket* b) + { return a->time < b->time; } }; @@ -93,7 +93,4 @@ class RealtimePacketQueue : public AsyncPacketQueue } // namespace scy -#endif // SCY_RealtimePacketQueue_H - - /// @\} diff --git a/src/av/include/scy/av/videocapture.h b/src/av/include/scy/av/videocapture.h index efc3481da..083ac963c 100644 --- a/src/av/include/scy/av/videocapture.h +++ b/src/av/include/scy/av/videocapture.h @@ -8,8 +8,7 @@ /// @addtogroup av /// @{ -#ifndef SCY_AV_VideoCapture_H -#define SCY_AV_VideoCapture_H +#pragma once #include "scy/base.h" @@ -27,13 +26,13 @@ namespace av { class AV_API VideoCapture : public MediaCapture { public: - typedef std::shared_ptr Ptr; + using Ptr = std::shared_ptr; VideoCapture(); VideoCapture(const std::string& device, const av::VideoCodec& params); VideoCapture(const std::string& device, int width = 0, int height = 0, double framerate = 0, const std::string& pixelFmt = ""); - virtual ~VideoCapture(); + virtual ~VideoCapture() noexcept; virtual void openVideo(const std::string& device, const av::VideoCodec& params); virtual void openVideo(const std::string& device, int width = 0, @@ -47,7 +46,6 @@ class AV_API VideoCapture : public MediaCapture #endif -#endif // SCY_AV_VideoCapture_H /// @\} diff --git a/src/av/include/scy/av/videocontext.h b/src/av/include/scy/av/videocontext.h index 59d07d5a9..1ceb43baf 100644 --- a/src/av/include/scy/av/videocontext.h +++ b/src/av/include/scy/av/videocontext.h @@ -9,8 +9,7 @@ /// @{ -#ifndef SCY_AV_VideoContext_H -#define SCY_AV_VideoContext_H +#pragma once #include "scy/base.h" @@ -27,7 +26,6 @@ extern "C" { #include #include -// #include #include #include #include @@ -44,7 +42,12 @@ namespace av { struct VideoContext { VideoContext(); - virtual ~VideoContext(); + virtual ~VideoContext() noexcept; + + VideoContext(const VideoContext&) = delete; + VideoContext& operator=(const VideoContext&) = delete; + VideoContext(VideoContext&&) = delete; + VideoContext& operator=(VideoContext&&) = delete; /// Create the `AVCodecContext` using default values virtual void create(); @@ -67,19 +70,17 @@ struct VideoContext PacketSignal emitter; - VideoCodec iparams; ///< input parameters - VideoCodec oparams; ///< output parameters - AVStream* stream; ///< encoder or decoder stream - AVCodecContext* ctx; ///< encoder or decoder context - AVCodec* codec; ///< encoder or decoder codec - AVFrame* frame; ///< encoder or decoder frame - VideoConverter* conv; ///< video conversion context - // FPSCounter fps; ///< encoder or decoder fps rate - // double pts; ///< pts in decimal seconds - int64_t time; ///< stream time in codec time base - int64_t pts; ///< last packet pts value - double seconds; ///< video time in seconds - std::string error; ///< error message + VideoCodec iparams; ///< input parameters + VideoCodec oparams; ///< output parameters + AVStream* stream; ///< encoder or decoder stream + AVCodecContext* ctx; ///< encoder or decoder context + const AVCodec* codec; ///< encoder or decoder codec + AVFrame* frame; ///< encoder or decoder frame + std::unique_ptr conv; ///< video conversion context + int64_t time; ///< stream time in codec time base + int64_t pts; ///< last packet pts value + double seconds; ///< video time in seconds + std::string error; ///< error message }; @@ -91,8 +92,7 @@ struct VideoContext AVFrame* createVideoFrame(AVPixelFormat pixelFmt, int width, int height); AVFrame* cloneVideoFrame(AVFrame* source); void initVideoCodecFromContext(const AVStream* stream, const AVCodecContext* ctx, VideoCodec& params); -AVPixelFormat selectPixelFormat(AVCodec* codec, VideoCodec& params); - +AVPixelFormat selectPixelFormat(const AVCodec* codec, VideoCodec& params); } // namespace av @@ -100,7 +100,6 @@ AVPixelFormat selectPixelFormat(AVCodec* codec, VideoCodec& params); #endif -#endif // SCY_AV_VideoContext_H /// @\} diff --git a/src/av/include/scy/av/videoconverter.h b/src/av/include/scy/av/videoconverter.h index 1033ff228..108dcd25c 100644 --- a/src/av/include/scy/av/videoconverter.h +++ b/src/av/include/scy/av/videoconverter.h @@ -9,8 +9,7 @@ /// @{ -#ifndef SCY_AV_VideoConverter_H -#define SCY_AV_VideoConverter_H +#pragma once #include "scy/base.h" @@ -32,7 +31,12 @@ namespace av { struct VideoConverter { VideoConverter(); - virtual ~VideoConverter(); + virtual ~VideoConverter() noexcept; + + VideoConverter(const VideoConverter&) = delete; + VideoConverter& operator=(const VideoConverter&) = delete; + VideoConverter(VideoConverter&&) = delete; + VideoConverter& operator=(VideoConverter&&) = delete; virtual void create(); virtual void close(); @@ -51,7 +55,6 @@ struct VideoConverter #endif -#endif // SCY_AV_VideoConverter_H /// @\} diff --git a/src/av/include/scy/av/videodecoder.h b/src/av/include/scy/av/videodecoder.h index 345c0ec87..3edf8e378 100644 --- a/src/av/include/scy/av/videodecoder.h +++ b/src/av/include/scy/av/videodecoder.h @@ -9,8 +9,7 @@ /// @{ -#ifndef SCY_AV_VideoDecoder_H -#define SCY_AV_VideoDecoder_H +#pragma once #include "scy/base.h" @@ -28,7 +27,7 @@ namespace av { struct VideoDecoder : public VideoContext { VideoDecoder(AVStream* stream); - virtual ~VideoDecoder(); + ~VideoDecoder() noexcept override; virtual void create() override; virtual void open() override; @@ -38,7 +37,7 @@ struct VideoDecoder : public VideoContext /// Input packets should use the raw `AVStream` time base. Time base /// conversion will happen internally. /// Returns true an output packet was was decoded, false otherwise. - virtual bool decode(AVPacket& ipacket); + [[nodiscard]] virtual bool decode(AVPacket& ipacket); /// Flushes buffered frames. /// This method should be called after decoding @@ -52,7 +51,6 @@ struct VideoDecoder : public VideoContext #endif -#endif // SCY_AV_VideoDecoder_H /// @\} diff --git a/src/av/include/scy/av/videoencoder.h b/src/av/include/scy/av/videoencoder.h index 0a0ba16a8..e5842a16d 100644 --- a/src/av/include/scy/av/videoencoder.h +++ b/src/av/include/scy/av/videoencoder.h @@ -9,8 +9,7 @@ /// @{ -#ifndef SCY_AV_VideoEncoder_H -#define SCY_AV_VideoEncoder_H +#pragma once #include "scy/base.h" @@ -30,23 +29,29 @@ namespace av { struct VideoEncoder : public VideoContext { VideoEncoder(AVFormatContext* format = nullptr); - virtual ~VideoEncoder(); + ~VideoEncoder() noexcept override; virtual void create() override; virtual void close() override; /// Encode a single video frame. - /// The pts argument should be in stream base time format. /// This method is for interleaved video formats. - virtual bool encode(uint8_t* data, int size, int64_t pts); + /// + /// @param data The raw video frame buffer. + /// @param size The buffer size in bytes. + /// @param pts The presentation timestamp in stream time base units. + [[nodiscard]] virtual bool encode(uint8_t* data, int size, int64_t pts); /// Encode a single video frame. - /// The pts argument should be in stream base time format. /// This method is for planar video formats. - virtual bool encode(uint8_t* data[4], int linesize[4], int64_t pts); + /// + /// @param data Array of per-plane data pointers (up to 4 planes). + /// @param linesize Array of per-plane byte strides. + /// @param pts The presentation timestamp in stream time base units. + [[nodiscard]] virtual bool encode(uint8_t* data[4], int linesize[4], int64_t pts); /// Encode a single AVFrame. - virtual bool encode(AVFrame* iframe); + [[nodiscard]] virtual bool encode(AVFrame* iframe); /// Flush remaining packets to be encoded. /// This method should be called once before stream closure. @@ -61,7 +66,6 @@ struct VideoEncoder : public VideoContext #endif -#endif // SCY_AV_VideoEncoder_H /// @\} diff --git a/src/av/include/scy/av/win32/directshow.h b/src/av/include/scy/av/win32/directshow.h index b4ed0eb5d..91b93c42b 100644 --- a/src/av/include/scy/av/win32/directshow.h +++ b/src/av/include/scy/av/win32/directshow.h @@ -8,8 +8,7 @@ /// @addtogroup av /// @{ -#ifndef SCY_AV_DirectShow_H -#define SCY_AV_DirectShow_H +#pragma once #include "scy/av/devicemanager.h" @@ -36,6 +35,3 @@ bool getDeviceList(Device::Type type, std::vector& devices); } // namespace dshow } // namespace av } // namespace scy - - -#endif // SCY_AV_DirectShow_H diff --git a/src/av/samples/deviceenumerator/CMakeLists.txt b/src/av/samples/deviceenumerator/CMakeLists.txt index 83a5a2c26..59251b357 100644 --- a/src/av/samples/deviceenumerator/CMakeLists.txt +++ b/src/av/samples/deviceenumerator/CMakeLists.txt @@ -1,5 +1 @@ -include_dependency(FFmpeg REQUIRED) -# print_module_variables(${name}) -# message(FATAL_ERROR "LibSourcey_INCLUDE_LIBRARIES ${LibSourcey_INCLUDE_LIBRARIES}") - -define_sourcey_module_sample(deviceenumerator base av) +scy_add_sample(deviceenumerator DEPENDS base av) diff --git a/src/av/samples/deviceenumerator/deviceenumerator.cpp b/src/av/samples/deviceenumerator/deviceenumerator.cpp index 0a852b2cc..bbc7bb0e4 100644 --- a/src/av/samples/deviceenumerator/deviceenumerator.cpp +++ b/src/av/samples/deviceenumerator/deviceenumerator.cpp @@ -7,7 +7,7 @@ using namespace scy; int main(int argc, char** argv) { - Logger::instance().add(new ConsoleChannel("debug", Level::Trace)); + Logger::instance().add(std::make_unique("debug", Level::Trace)); { av::DeviceManager devman; devman.print(std::cout); diff --git a/src/av/samples/devicerecorder/CMakeLists.txt b/src/av/samples/devicerecorder/CMakeLists.txt index a5462c4f9..8b5d66264 100644 --- a/src/av/samples/devicerecorder/CMakeLists.txt +++ b/src/av/samples/devicerecorder/CMakeLists.txt @@ -1,3 +1 @@ -include_dependency(FFmpeg REQUIRED) - -define_sourcey_module_sample(devicerecorder base av) +scy_add_sample(devicerecorder DEPENDS base av) diff --git a/src/av/samples/devicerecorder/devicerecorder.cpp b/src/av/samples/devicerecorder/devicerecorder.cpp index c5b414fee..fe832a946 100644 --- a/src/av/samples/devicerecorder/devicerecorder.cpp +++ b/src/av/samples/devicerecorder/devicerecorder.cpp @@ -21,9 +21,9 @@ // device captures using LibSourcey. #define OUTPUT_FILENAME "deviceoutput.mp4" -#define OUTPUT_FORMAT av::Format("MP4 Realtime", "mp4", \ - { "libx264", 400, 300, 25, 48000, 128000, "yuv420p" }, \ - { "aac", 2, 44100, 64000, "fltp" }); +#define OUTPUT_FORMAT av::Format("MP4 Realtime", "mp4", \ + {"libx264", 400, 300, 25, 48000, 128000, "yuv420p"}, \ + {"aac", 2, 44100, 64000, "fltp"}); using namespace scy; using std::endl; @@ -31,7 +31,7 @@ using std::endl; int main(int argc, char** argv) { - Logger::instance().add(new ConsoleChannel("debug", Level::Trace)); // Debug + Logger::instance().add(std::make_unique("debug", Level::Trace)); // Debug { // Create a PacketStream to pass packets // from device captures to the encoder @@ -50,8 +50,8 @@ int main(int argc, char** argv) // Create and attach the default video capture av::VideoCapture video; if (devman.getDefaultCamera(device)) { - LInfo("Using video device: ", device.name) - video.openVideo(device.id, { 640, 480 }); + LInfo("Using video device: ", device.name); + video.openVideo(device.id, {640, 480}); video.getEncoderFormat(options.iformat); stream.attachSource(&video, false, true); } @@ -59,8 +59,8 @@ int main(int argc, char** argv) // Create and attach the default audio capture av::AudioCapture audio; if (devman.getDefaultMicrophone(device)) { - LInfo("Using audio device: ", device.name) - audio.openAudio(device.id, { 2, 44100 }); + LInfo("Using audio device: ", device.name); + audio.openAudio(device.id, {2, 44100}); audio.getEncoderFormat(options.iformat); stream.attachSource(&audio, false, true); } @@ -74,10 +74,11 @@ int main(int argc, char** argv) stream.start(); // Keep recording until Ctrl-C is pressed - LInfo("Recording video: ", OUTPUT_FILENAME) + LInfo("Recording video: ", OUTPUT_FILENAME); waitForShutdown([](void* opaque) { reinterpret_cast(opaque)->stop(); - }, &stream); + }, + &stream); } // Logger::destroy(); diff --git a/src/av/samples/mediaserver/CMakeLists.txt b/src/av/samples/mediaserver/CMakeLists.txt index ccf7f38ef..ddbbeea14 100644 --- a/src/av/samples/mediaserver/CMakeLists.txt +++ b/src/av/samples/mediaserver/CMakeLists.txt @@ -1,9 +1 @@ -# include_dependency(LibUV) -# include_dependency(HttpParser) -include_dependency(SSL REQUIRED) -include_dependency(FFmpeg REQUIRED) -# include_dependency(RtAudio) -# include_dependency(OpenCV REQUIRED) - - -define_sourcey_module_sample(mediaserver base av net http turn stun util) +scy_add_sample(mediaserver DEPENDS base av net http turn stun) diff --git a/src/av/samples/mediaserver/client/index.html b/src/av/samples/mediaserver/client/index.html index d8efaeecf..e41d94d08 100644 --- a/src/av/samples/mediaserver/client/index.html +++ b/src/av/samples/mediaserver/client/index.html @@ -4,27 +4,28 @@ Symple Player Tests - + + - - - - + + + + - - + - +

Test Notes

-

A quick test to instantiate a Symple player for each streaming engine using a range of media formats, and also to test the Symple C++ MediaServer. The MediaServer sample is part of the Symple C++ module distribured with LibSourcey.

+

+ A quick test to instantiate a Symple player for each streaming engine using a range of media formats, and also to test the Symple C++ MediaServer. + The MediaServer sample is part of the Symple C++ module distribured with LibSourcey. + This page is not very dynamic yet, so you will need to rerfesh this page once the MediaServer is running. +

- +

All Available Engines

- - + +
+

MJPEG WebSocket

+
+
+
+ + +
- + - \ No newline at end of file + diff --git a/src/av/samples/mediaserver/client/package-lock.json b/src/av/samples/mediaserver/client/package-lock.json new file mode 100644 index 000000000..4b392f594 --- /dev/null +++ b/src/av/samples/mediaserver/client/package-lock.json @@ -0,0 +1,926 @@ +{ + "name": "libsourcey-media-server", + "version": "0.1.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "accepts": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.2.13.tgz", + "integrity": "sha1-5fHzkoxtlf2WVYw27D2dDeSm7Oo=", + "requires": { + "mime-types": "2.1.18", + "negotiator": "0.5.3" + } + }, + "after": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", + "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=" + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, + "arraybuffer.slice": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.6.tgz", + "integrity": "sha1-8zshWfBTKj8xB6JywMz70a0peco=" + }, + "async": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.0.tgz", + "integrity": "sha1-rDYTsdqb7RtHUQu0ZRuJMeRxRsc=" + }, + "async-limiter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", + "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==" + }, + "backo2": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", + "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=" + }, + "base64-arraybuffer": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", + "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=" + }, + "base64id": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz", + "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=" + }, + "benchmark": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/benchmark/-/benchmark-1.0.0.tgz", + "integrity": "sha1-Lx4vpMNZ8REiqhgwgiGOlX45DHM=" + }, + "better-assert": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", + "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", + "requires": { + "callsite": "1.0.0" + } + }, + "blob": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.4.tgz", + "integrity": "sha1-vPEwUspURj8w+fx+lbmkdjCpSSE=" + }, + "callsite": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", + "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=" + }, + "component-bind": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", + "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=" + }, + "component-emitter": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.1.2.tgz", + "integrity": "sha1-KWWU8nU9qmOZbSrwjRWpURbJrsM=" + }, + "component-inherit": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", + "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=" + }, + "content-disposition": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.1.tgz", + "integrity": "sha1-h0dsamfI2qh+Muh2Ft+IO6f7Bxs=" + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + }, + "cookie": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.1.5.tgz", + "integrity": "sha1-armUiksa4hlSzSWIUwpHItQETXw=" + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "requires": { + "ms": "0.7.1" + } + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "double-ended-queue": { + "version": "2.1.0-0", + "resolved": "https://registry.npmjs.org/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz", + "integrity": "sha1-ED01J/0xUo9AGIEwyEHv3XgmTlw=" + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "ejs": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.3.4.tgz", + "integrity": "sha1-PHbKoJZks1g7ADevncE2557Gi5g=" + }, + "engine.io": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-1.8.5.tgz", + "integrity": "sha512-j1DWIcktw4hRwrv6nWx++5nFH2X64x16MAG2P0Lmi5Dvdfi3I+Jhc7JKJIdAmDJa+5aZ/imHV7dWRPy2Cqjh3A==", + "requires": { + "accepts": "1.3.3", + "base64id": "1.0.0", + "cookie": "0.3.1", + "debug": "2.3.3", + "engine.io-parser": "1.3.2", + "ws": "1.1.5" + }, + "dependencies": { + "accepts": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.3.tgz", + "integrity": "sha1-w8p0NJOGSMPg2cHjKN1otiLChMo=", + "requires": { + "mime-types": "2.1.18", + "negotiator": "0.6.1" + } + }, + "cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" + }, + "debug": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.3.3.tgz", + "integrity": "sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w=", + "requires": { + "ms": "0.7.2" + } + }, + "ms": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", + "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=" + }, + "negotiator": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" + } + } + }, + "engine.io-client": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-1.8.5.tgz", + "integrity": "sha512-AYTgHyeVUPitsseqjoedjhYJapNVoSPShbZ+tEUX9/73jgZ/Z3sUlJf9oYgdEBBdVhupUpUqSxH0kBCXlQnmZg==", + "requires": { + "component-emitter": "1.2.1", + "component-inherit": "0.0.3", + "debug": "2.3.3", + "engine.io-parser": "1.3.2", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "parsejson": "0.0.3", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "ws": "1.1.5", + "xmlhttprequest-ssl": "1.5.3", + "yeast": "0.1.2" + }, + "dependencies": { + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" + }, + "debug": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.3.3.tgz", + "integrity": "sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w=", + "requires": { + "ms": "0.7.2" + } + }, + "ms": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", + "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=" + } + } + }, + "engine.io-parser": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-1.3.2.tgz", + "integrity": "sha1-k3sHnwAH0Ik+xW1GyyILjLQ1Igo=", + "requires": { + "after": "0.8.2", + "arraybuffer.slice": "0.0.6", + "base64-arraybuffer": "0.1.5", + "blob": "0.0.4", + "has-binary": "0.1.7", + "wtf-8": "1.0.0" + } + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "etag": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.7.0.tgz", + "integrity": "sha1-A9MLX2fdbmMtKUXTDWZScxo01dg=" + }, + "express": { + "version": "4.13.4", + "resolved": "https://registry.npmjs.org/express/-/express-4.13.4.tgz", + "integrity": "sha1-PAt288d1kMg0VzkGHsC9O6Bn7CQ=", + "requires": { + "accepts": "1.2.13", + "array-flatten": "1.1.1", + "content-disposition": "0.5.1", + "content-type": "1.0.4", + "cookie": "0.1.5", + "cookie-signature": "1.0.6", + "debug": "2.2.0", + "depd": "1.1.2", + "escape-html": "1.0.3", + "etag": "1.7.0", + "finalhandler": "0.4.1", + "fresh": "0.3.0", + "merge-descriptors": "1.0.1", + "methods": "1.1.2", + "on-finished": "2.3.0", + "parseurl": "1.3.2", + "path-to-regexp": "0.1.7", + "proxy-addr": "1.0.10", + "qs": "4.0.0", + "range-parser": "1.0.3", + "send": "0.13.1", + "serve-static": "1.10.3", + "type-is": "1.6.16", + "utils-merge": "1.0.0", + "vary": "1.0.1" + } + }, + "finalhandler": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.4.1.tgz", + "integrity": "sha1-haF8bFmpRxfSYtYSMNSw6+PUoU0=", + "requires": { + "debug": "2.2.0", + "escape-html": "1.0.3", + "on-finished": "2.3.0", + "unpipe": "1.0.0" + } + }, + "forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" + }, + "fresh": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.3.0.tgz", + "integrity": "sha1-ZR+DjiJCTnVm3hYdg1jKoZn4PU8=" + }, + "has-binary": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/has-binary/-/has-binary-0.1.7.tgz", + "integrity": "sha1-aOYesWIQyVRaClzOBqhzkS/h5ow=", + "requires": { + "isarray": "0.0.1" + } + }, + "has-binary2": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.2.tgz", + "integrity": "sha1-6D26SfC5vk0CbSc2U1DZ8D9Uvpg=", + "requires": { + "isarray": "2.0.1" + }, + "dependencies": { + "isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=" + } + } + }, + "has-cors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", + "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=" + }, + "http-errors": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz", + "integrity": "sha1-GX4izevUGYWF6GlO9nhhl7ke2UI=", + "requires": { + "inherits": "2.0.3", + "statuses": "1.2.1" + } + }, + "indexof": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=" + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ipaddr.js": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.0.5.tgz", + "integrity": "sha1-X6eM8wG4JceKvDBC2BJyMEnqI8c=" + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "jquery": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.3.1.tgz", + "integrity": "sha512-Ubldcmxp5np52/ENotGxlLe6aGMvmF4R8S6tZjsP6Knsaxd/xp3Zrh50cG93lR6nPXyUFwzN3ZSOQI0wRJNdGg==" + }, + "json3": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", + "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=" + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + }, + "mime": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz", + "integrity": "sha1-EV+eO2s9rylZmDyzjxSaLUDrXVM=" + }, + "mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==" + }, + "mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "requires": { + "mime-db": "1.33.0" + } + }, + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=" + }, + "msgpack": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/msgpack/-/msgpack-1.0.2.tgz", + "integrity": "sha1-kj4sXP+mXIQY6bIo0RJHk5acQpw=", + "requires": { + "nan": "2.10.0" + } + }, + "nan": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", + "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==" + }, + "negotiator": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.5.3.tgz", + "integrity": "sha1-Jp1cR2gQ7JLtvntsLygxY4T5p+g=" + }, + "object-assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz", + "integrity": "sha1-ejs9DpgGPUP0wD8uiubNUahog6A=" + }, + "object-component": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", + "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=" + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "requires": { + "ee-first": "1.1.1" + } + }, + "options": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/options/-/options-0.0.6.tgz", + "integrity": "sha1-7CLTEoBrtT5zF3Pnza788cZDEo8=" + }, + "parsejson": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/parsejson/-/parsejson-0.0.3.tgz", + "integrity": "sha1-q343WfIJ7OmUN5c/fQ8fZK4OZKs=", + "requires": { + "better-assert": "1.0.2" + } + }, + "parseqs": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", + "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", + "requires": { + "better-assert": "1.0.2" + } + }, + "parseuri": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", + "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", + "requires": { + "better-assert": "1.0.2" + } + }, + "parseurl": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + }, + "proxy-addr": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.0.10.tgz", + "integrity": "sha1-DUCoL4Afw1VWfS7LZe/j8HfxIcU=", + "requires": { + "forwarded": "0.1.2", + "ipaddr.js": "1.0.5" + } + }, + "qs": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-4.0.0.tgz", + "integrity": "sha1-wx2bdOwn33XlQ6hseHKO2NRiNgc=" + }, + "range-parser": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.0.3.tgz", + "integrity": "sha1-aHKCNTXGkuLCoBA4Jq/YLC4P8XU=" + }, + "redis": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/redis/-/redis-2.4.2.tgz", + "integrity": "sha1-L5FgJVompsrSt5vwhH4GcoChRuo=", + "requires": { + "double-ended-queue": "2.1.0-0", + "redis-commands": "1.3.5" + } + }, + "redis-commands": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.3.5.tgz", + "integrity": "sha512-foGF8u6MXGFF++1TZVC6icGXuMYPftKXt1FBT2vrfU9ZATNtZJ8duRC5d1lEfE8hyVe3jhelHGB91oB7I6qLsA==" + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" + }, + "send": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.13.1.tgz", + "integrity": "sha1-ow1fTILIqbrprQCh2bG9vm8Zntc=", + "requires": { + "debug": "2.2.0", + "depd": "1.1.2", + "destroy": "1.0.4", + "escape-html": "1.0.3", + "etag": "1.7.0", + "fresh": "0.3.0", + "http-errors": "1.3.1", + "mime": "1.3.4", + "ms": "0.7.1", + "on-finished": "2.3.0", + "range-parser": "1.0.3", + "statuses": "1.2.1" + } + }, + "serve-static": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.10.3.tgz", + "integrity": "sha1-zlpuzTEB/tXsCYJ9rCKpwpv7BTU=", + "requires": { + "escape-html": "1.0.3", + "parseurl": "1.3.2", + "send": "0.13.2" + }, + "dependencies": { + "send": { + "version": "0.13.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.13.2.tgz", + "integrity": "sha1-dl52B8gFVFK7pvCwUllTUJhgNt4=", + "requires": { + "debug": "2.2.0", + "depd": "1.1.2", + "destroy": "1.0.4", + "escape-html": "1.0.3", + "etag": "1.7.0", + "fresh": "0.3.0", + "http-errors": "1.3.1", + "mime": "1.3.4", + "ms": "0.7.1", + "on-finished": "2.3.0", + "range-parser": "1.0.3", + "statuses": "1.2.1" + } + } + } + }, + "socket.io": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-1.7.4.tgz", + "integrity": "sha1-L37O3DORvy1cc+KR/iM+bjTU3QA=", + "requires": { + "debug": "2.3.3", + "engine.io": "1.8.5", + "has-binary": "0.1.7", + "object-assign": "4.1.0", + "socket.io-adapter": "0.5.0", + "socket.io-client": "1.7.4", + "socket.io-parser": "2.3.1" + }, + "dependencies": { + "debug": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.3.3.tgz", + "integrity": "sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w=", + "requires": { + "ms": "0.7.2" + } + }, + "ms": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", + "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=" + }, + "socket.io-adapter": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-0.5.0.tgz", + "integrity": "sha1-y21LuL7IHhB4uZZ3+c7QBGBmu4s=", + "requires": { + "debug": "2.3.3", + "socket.io-parser": "2.3.1" + } + } + } + }, + "socket.io-adapter": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-0.4.0.tgz", + "integrity": "sha1-+5+CqxqmUpC/csNleVW5MKmRok8=", + "requires": { + "debug": "2.2.0", + "socket.io-parser": "2.2.2" + }, + "dependencies": { + "json3": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/json3/-/json3-3.2.6.tgz", + "integrity": "sha1-9u/JPAagTemuxTBT3yVZuxniA4s=" + }, + "socket.io-parser": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-2.2.2.tgz", + "integrity": "sha1-PXr2tkSX6Va32f53X5mXFgJ/lBc=", + "requires": { + "benchmark": "1.0.0", + "component-emitter": "1.1.2", + "debug": "0.7.4", + "isarray": "0.0.1", + "json3": "3.2.6" + }, + "dependencies": { + "debug": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-0.7.4.tgz", + "integrity": "sha1-BuHqgILCyxTjmAbiLi9vdX+Srzk=" + } + } + } + } + }, + "socket.io-client": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-1.7.4.tgz", + "integrity": "sha1-7J+CA1btme9tNX8HVtZIcXvdQoE=", + "requires": { + "backo2": "1.0.2", + "component-bind": "1.0.0", + "component-emitter": "1.2.1", + "debug": "2.3.3", + "engine.io-client": "1.8.5", + "has-binary": "0.1.7", + "indexof": "0.0.1", + "object-component": "0.0.3", + "parseuri": "0.0.5", + "socket.io-parser": "2.3.1", + "to-array": "0.1.4" + }, + "dependencies": { + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" + }, + "debug": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.3.3.tgz", + "integrity": "sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w=", + "requires": { + "ms": "0.7.2" + } + }, + "ms": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", + "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=" + } + } + }, + "socket.io-parser": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-2.3.1.tgz", + "integrity": "sha1-3VMgJRA85Clpcya+/WQAX8/ltKA=", + "requires": { + "component-emitter": "1.1.2", + "debug": "2.2.0", + "isarray": "0.0.1", + "json3": "3.3.2" + } + }, + "statuses": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.2.1.tgz", + "integrity": "sha1-3e1FzBglbVHtQK7BQkidXGECbSg=" + }, + "symple": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/symple/-/symple-1.0.7.tgz", + "integrity": "sha1-/mRo/beWsV9WcaYMId8ATB06eIk=", + "requires": { + "async": "0.9.0", + "debug": "2.2.0", + "msgpack": "1.0.2", + "redis": "2.4.2", + "socket.io": "1.7.4", + "socket.io-adapter": "0.4.0", + "uid2": "0.0.3" + } + }, + "symple-client": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/symple-client/-/symple-client-1.0.2.tgz", + "integrity": "sha1-cBZXdQfGpaDJPW+XtCTxALUHk1k=", + "requires": { + "socket.io-client": "2.0.4" + }, + "dependencies": { + "arraybuffer.slice": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", + "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==" + }, + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "engine.io-client": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.1.6.tgz", + "integrity": "sha512-hnuHsFluXnsKOndS4Hv6SvUrgdYx1pk2NqfaDMW+GWdgfU3+/V25Cj7I8a0x92idSpa5PIhJRKxPvp9mnoLsfg==", + "requires": { + "component-emitter": "1.2.1", + "component-inherit": "0.0.3", + "debug": "3.1.0", + "engine.io-parser": "2.1.2", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "ws": "3.3.3", + "xmlhttprequest-ssl": "1.5.5", + "yeast": "0.1.2" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + } + } + }, + "engine.io-parser": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.2.tgz", + "integrity": "sha512-dInLFzr80RijZ1rGpx1+56/uFoH7/7InhH3kZt+Ms6hT8tNx3NGW/WNSA/f8As1WkOfkuyb3tnRyuXGxusclMw==", + "requires": { + "after": "0.8.2", + "arraybuffer.slice": "0.0.7", + "base64-arraybuffer": "0.1.5", + "blob": "0.0.4", + "has-binary2": "1.0.2" + } + }, + "isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=" + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "socket.io-client": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.0.4.tgz", + "integrity": "sha1-CRilUkBtxeVAs4Dc2Xr8SmQzL44=", + "requires": { + "backo2": "1.0.2", + "base64-arraybuffer": "0.1.5", + "component-bind": "1.0.0", + "component-emitter": "1.2.1", + "debug": "2.6.9", + "engine.io-client": "3.1.6", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "object-component": "0.0.3", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "socket.io-parser": "3.1.3", + "to-array": "0.1.4" + } + }, + "socket.io-parser": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.1.3.tgz", + "integrity": "sha512-g0a2HPqLguqAczs3dMECuA1RgoGFPyvDqcbaDEdCWY9g59kdUAz3YRmaJBNKXflrHNwB7Q12Gkf/0CZXfdHR7g==", + "requires": { + "component-emitter": "1.2.1", + "debug": "3.1.0", + "has-binary2": "1.0.2", + "isarray": "2.0.1" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + } + } + }, + "ultron": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", + "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==" + }, + "ws": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", + "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", + "requires": { + "async-limiter": "1.0.0", + "safe-buffer": "5.1.1", + "ultron": "1.1.1" + } + }, + "xmlhttprequest-ssl": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", + "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=" + } + } + }, + "symple-client-player": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/symple-client-player/-/symple-client-player-1.0.5.tgz", + "integrity": "sha512-Czc8enryYuDBH5cAZ8kwLQ/1y6thLml/IXtDYZdDrzwflixY/8wX9R7t82PNuprtc4sNJLPx4iR/AK2tnChhDQ==" + }, + "to-array": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", + "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=" + }, + "type-is": { + "version": "1.6.16", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", + "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "2.1.18" + } + }, + "uid2": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.3.tgz", + "integrity": "sha1-SDEm4Rd03y9xuLY53NeZw3YWK4I=" + }, + "ultron": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz", + "integrity": "sha1-rOEWq1V80Zc4ak6I9GhTeMiy5Po=" + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "utils-merge": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", + "integrity": "sha1-ApT7kiu5N1FTVBxPcJYjHyh8ivg=" + }, + "vary": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.0.1.tgz", + "integrity": "sha1-meSYFWaihhGN+yuBc1ffeZM3bRA=" + }, + "ws": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ws/-/ws-1.1.5.tgz", + "integrity": "sha512-o3KqipXNUdS7wpQzBHSe180lBGO60SoK0yVo3CYJgb2MkobuWuBX6dhkYP5ORCLd55y+SaflMOV5fqAB53ux4w==", + "requires": { + "options": "0.0.6", + "ultron": "1.0.2" + } + }, + "wtf-8": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wtf-8/-/wtf-8-1.0.0.tgz", + "integrity": "sha1-OS2LotDxw00e4tYw8V0O+2jhBIo=" + }, + "xmlhttprequest-ssl": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.3.tgz", + "integrity": "sha1-GFqIjATspGw+QHDZn3tJ3jUomS0=" + }, + "yeast": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", + "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=" + } + } +} diff --git a/src/av/samples/mediaserver/client/package.json b/src/av/samples/mediaserver/client/package.json new file mode 100644 index 000000000..c6b6ef67b --- /dev/null +++ b/src/av/samples/mediaserver/client/package.json @@ -0,0 +1,16 @@ +{ + "name": "libsourcey-media-server", + "title": "LibSourcey Media Server", + "version": "0.1.0", + "scripts": { + "start": "node app.js" + }, + "dependencies": { + "ejs": "*", + "express": "*", + "jquery": "^3.3.1", + "symple": "*", + "symple-client": "*", + "symple-client-player": "*" + } +} diff --git a/src/av/samples/mediaserver/client/swfobject.js b/src/av/samples/mediaserver/client/swfobject.js deleted file mode 100644 index bf35c07c8..000000000 --- a/src/av/samples/mediaserver/client/swfobject.js +++ /dev/null @@ -1,777 +0,0 @@ -/*! SWFObject v2.2 - is released under the MIT License -*/ - -var swfobject = function() { - - var UNDEF = "undefined", - OBJECT = "object", - SHOCKWAVE_FLASH = "Shockwave Flash", - SHOCKWAVE_FLASH_AX = "ShockwaveFlash.ShockwaveFlash", - FLASH_MIME_TYPE = "application/x-shockwave-flash", - EXPRESS_INSTALL_ID = "SWFObjectExprInst", - ON_READY_STATE_CHANGE = "onreadystatechange", - - win = window, - doc = document, - nav = navigator, - - plugin = false, - domLoadFnArr = [main], - regObjArr = [], - objIdArr = [], - listenersArr = [], - storedAltContent, - storedAltContentId, - storedCallbackFn, - storedCallbackObj, - isDomLoaded = false, - isExpressInstallActive = false, - dynamicStylesheet, - dynamicStylesheetMedia, - autoHideShow = true, - - /* Centralized function for browser feature detection - - User agent string detection is only used when no good alternative is possible - - Is executed directly for optimal performance - */ - ua = function() { - var w3cdom = typeof doc.getElementById != UNDEF && typeof doc.getElementsByTagName != UNDEF && typeof doc.createElement != UNDEF, - u = nav.userAgent.toLowerCase(), - p = nav.platform.toLowerCase(), - windows = p ? /win/.test(p) : /win/.test(u), - mac = p ? /mac/.test(p) : /mac/.test(u), - webkit = /webkit/.test(u) ? parseFloat(u.replace(/^.*webkit\/(\d+(\.\d+)?).*$/, "$1")) : false, // returns either the webkit version or false if not webkit - ie = !+"\v1", // feature detection based on Andrea Giammarchi's solution: http://webreflection.blogspot.com/2009/01/32-bytes-to-know-if-your-browser-is-ie.html - playerVersion = [0,0,0], - d = null; - if (typeof nav.plugins != UNDEF && typeof nav.plugins[SHOCKWAVE_FLASH] == OBJECT) { - d = nav.plugins[SHOCKWAVE_FLASH].description; - if (d && !(typeof nav.mimeTypes != UNDEF && nav.mimeTypes[FLASH_MIME_TYPE] && !nav.mimeTypes[FLASH_MIME_TYPE].enabledPlugin)) { // navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin indicates whether plug-ins are enabled or disabled in Safari 3+ - plugin = true; - ie = false; // cascaded feature detection for Internet Explorer - d = d.replace(/^.*\s+(\S+\s+\S+$)/, "$1"); - playerVersion[0] = parseInt(d.replace(/^(.*)\..*$/, "$1"), 10); - playerVersion[1] = parseInt(d.replace(/^.*\.(.*)\s.*$/, "$1"), 10); - playerVersion[2] = /[a-zA-Z]/.test(d) ? parseInt(d.replace(/^.*[a-zA-Z]+(.*)$/, "$1"), 10) : 0; - } - } - else if (typeof win.ActiveXObject != UNDEF) { - try { - var a = new ActiveXObject(SHOCKWAVE_FLASH_AX); - if (a) { // a will return null when ActiveX is disabled - d = a.GetVariable("$version"); - if (d) { - ie = true; // cascaded feature detection for Internet Explorer - d = d.split(" ")[1].split(","); - playerVersion = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)]; - } - } - } - catch(e) {} - } - return { w3:w3cdom, pv:playerVersion, wk:webkit, ie:ie, win:windows, mac:mac }; - }(), - - /* Cross-browser onDomLoad - - Will fire an event as soon as the DOM of a web page is loaded - - Internet Explorer workaround based on Diego Perini's solution: http://javascript.nwbox.com/IEContentLoaded/ - - Regular onload serves as fallback - */ - onDomLoad = function() { - if (!ua.w3) { return; } - if ((typeof doc.readyState != UNDEF && doc.readyState == "complete") || (typeof doc.readyState == UNDEF && (doc.getElementsByTagName("body")[0] || doc.body))) { // function is fired after onload, e.g. when script is inserted dynamically - callDomLoadFunctions(); - } - if (!isDomLoaded) { - if (typeof doc.addEventListener != UNDEF) { - doc.addEventListener("DOMContentLoaded", callDomLoadFunctions, false); - } - if (ua.ie && ua.win) { - doc.attachEvent(ON_READY_STATE_CHANGE, function() { - if (doc.readyState == "complete") { - doc.detachEvent(ON_READY_STATE_CHANGE, arguments.callee); - callDomLoadFunctions(); - } - }); - if (win == top) { // if not inside an iframe - (function(){ - if (isDomLoaded) { return; } - try { - doc.documentElement.doScroll("left"); - } - catch(e) { - setTimeout(arguments.callee, 0); - return; - } - callDomLoadFunctions(); - })(); - } - } - if (ua.wk) { - (function(){ - if (isDomLoaded) { return; } - if (!/loaded|complete/.test(doc.readyState)) { - setTimeout(arguments.callee, 0); - return; - } - callDomLoadFunctions(); - })(); - } - addLoadEvent(callDomLoadFunctions); - } - }(); - - function callDomLoadFunctions() { - if (isDomLoaded) { return; } - try { // test if we can really add/remove elements to/from the DOM; we don't want to fire it too early - var t = doc.getElementsByTagName("body")[0].appendChild(createElement("span")); - t.parentNode.removeChild(t); - } - catch (e) { return; } - isDomLoaded = true; - var dl = domLoadFnArr.length; - for (var i = 0; i < dl; i++) { - domLoadFnArr[i](); - } - } - - function addDomLoadEvent(fn) { - if (isDomLoaded) { - fn(); - } - else { - domLoadFnArr[domLoadFnArr.length] = fn; // Array.push() is only available in IE5.5+ - } - } - - /* Cross-browser onload - - Based on James Edwards' solution: http://brothercake.com/site/resources/scripts/onload/ - - Will fire an event as soon as a web page including all of its assets are loaded - */ - function addLoadEvent(fn) { - if (typeof win.addEventListener != UNDEF) { - win.addEventListener("load", fn, false); - } - else if (typeof doc.addEventListener != UNDEF) { - doc.addEventListener("load", fn, false); - } - else if (typeof win.attachEvent != UNDEF) { - addListener(win, "onload", fn); - } - else if (typeof win.onload == "function") { - var fnOld = win.onload; - win.onload = function() { - fnOld(); - fn(); - }; - } - else { - win.onload = fn; - } - } - - /* Main function - - Will preferably execute onDomLoad, otherwise onload (as a fallback) - */ - function main() { - if (plugin) { - testPlayerVersion(); - } - else { - matchVersions(); - } - } - - /* Detect the Flash Player version for non-Internet Explorer browsers - - Detecting the plug-in version via the object element is more precise than using the plugins collection item's description: - a. Both release and build numbers can be detected - b. Avoid wrong descriptions by corrupt installers provided by Adobe - c. Avoid wrong descriptions by multiple Flash Player entries in the plugin Array, caused by incorrect browser imports - - Disadvantage of this method is that it depends on the availability of the DOM, while the plugins collection is immediately available - */ - function testPlayerVersion() { - var b = doc.getElementsByTagName("body")[0]; - var o = createElement(OBJECT); - o.setAttribute("type", FLASH_MIME_TYPE); - var t = b.appendChild(o); - if (t) { - var counter = 0; - (function(){ - if (typeof t.GetVariable != UNDEF) { - var d = t.GetVariable("$version"); - if (d) { - d = d.split(" ")[1].split(","); - ua.pv = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)]; - } - } - else if (counter < 10) { - counter++; - setTimeout(arguments.callee, 10); - return; - } - b.removeChild(o); - t = null; - matchVersions(); - })(); - } - else { - matchVersions(); - } - } - - /* Perform Flash Player and SWF version matching; static publishing only - */ - function matchVersions() { - var rl = regObjArr.length; - if (rl > 0) { - for (var i = 0; i < rl; i++) { // for each registered object element - var id = regObjArr[i].id; - var cb = regObjArr[i].callbackFn; - var cbObj = {success:false, id:id}; - if (ua.pv[0] > 0) { - var obj = getElementById(id); - if (obj) { - if (hasPlayerVersion(regObjArr[i].swfVersion) && !(ua.wk && ua.wk < 312)) { // Flash Player version >= published SWF version: Houston, we have a match! - setVisibility(id, true); - if (cb) { - cbObj.success = true; - cbObj.ref = getObjectById(id); - cb(cbObj); - } - } - else if (regObjArr[i].expressInstall && canExpressInstall()) { // show the Adobe Express Install dialog if set by the web page author and if supported - var att = {}; - att.data = regObjArr[i].expressInstall; - att.width = obj.getAttribute("width") || "0"; - att.height = obj.getAttribute("height") || "0"; - if (obj.getAttribute("class")) { att.styleclass = obj.getAttribute("class"); } - if (obj.getAttribute("align")) { att.align = obj.getAttribute("align"); } - // parse HTML object param element's name-value pairs - var par = {}; - var p = obj.getElementsByTagName("param"); - var pl = p.length; - for (var j = 0; j < pl; j++) { - if (p[j].getAttribute("name").toLowerCase() != "movie") { - par[p[j].getAttribute("name")] = p[j].getAttribute("value"); - } - } - showExpressInstall(att, par, id, cb); - } - else { // Flash Player and SWF version mismatch or an older Webkit engine that ignores the HTML object element's nested param elements: display alternative content instead of SWF - displayAltContent(obj); - if (cb) { cb(cbObj); } - } - } - } - else { // if no Flash Player is installed or the fp version cannot be detected we let the HTML object element do its job (either show a SWF or alternative content) - setVisibility(id, true); - if (cb) { - var o = getObjectById(id); // test whether there is an HTML object element or not - if (o && typeof o.SetVariable != UNDEF) { - cbObj.success = true; - cbObj.ref = o; - } - cb(cbObj); - } - } - } - } - } - - function getObjectById(objectIdStr) { - var r = null; - var o = getElementById(objectIdStr); - if (o && o.nodeName == "OBJECT") { - if (typeof o.SetVariable != UNDEF) { - r = o; - } - else { - var n = o.getElementsByTagName(OBJECT)[0]; - if (n) { - r = n; - } - } - } - return r; - } - - /* Requirements for Adobe Express Install - - only one instance can be active at a time - - fp 6.0.65 or higher - - Win/Mac OS only - - no Webkit engines older than version 312 - */ - function canExpressInstall() { - return !isExpressInstallActive && hasPlayerVersion("6.0.65") && (ua.win || ua.mac) && !(ua.wk && ua.wk < 312); - } - - /* Show the Adobe Express Install dialog - - Reference: http://www.adobe.com/cfusion/knowledgebase/index.cfm?id=6a253b75 - */ - function showExpressInstall(att, par, replaceElemIdStr, callbackFn) { - isExpressInstallActive = true; - storedCallbackFn = callbackFn || null; - storedCallbackObj = {success:false, id:replaceElemIdStr}; - var obj = getElementById(replaceElemIdStr); - if (obj) { - if (obj.nodeName == "OBJECT") { // static publishing - storedAltContent = abstractAltContent(obj); - storedAltContentId = null; - } - else { // dynamic publishing - storedAltContent = obj; - storedAltContentId = replaceElemIdStr; - } - att.id = EXPRESS_INSTALL_ID; - if (typeof att.width == UNDEF || (!/%$/.test(att.width) && parseInt(att.width, 10) < 310)) { att.width = "310"; } - if (typeof att.height == UNDEF || (!/%$/.test(att.height) && parseInt(att.height, 10) < 137)) { att.height = "137"; } - doc.title = doc.title.slice(0, 47) + " - Flash Player Installation"; - var pt = ua.ie && ua.win ? "ActiveX" : "PlugIn", - fv = "MMredirectURL=" + encodeURI(window.location).toString().replace(/&/g,"%26") + "&MMplayerType=" + pt + "&MMdoctitle=" + doc.title; - if (typeof par.flashvars != UNDEF) { - par.flashvars += "&" + fv; - } - else { - par.flashvars = fv; - } - // IE only: when a SWF is loading (AND: not available in cache) wait for the readyState of the object element to become 4 before removing it, - // because you cannot properly cancel a loading SWF file without breaking browser load references, also obj.onreadystatechange doesn't work - if (ua.ie && ua.win && obj.readyState != 4) { - var newObj = createElement("div"); - replaceElemIdStr += "SWFObjectNew"; - newObj.setAttribute("id", replaceElemIdStr); - obj.parentNode.insertBefore(newObj, obj); // insert placeholder div that will be replaced by the object element that loads expressinstall.swf - obj.style.display = "none"; - (function(){ - if (obj.readyState == 4) { - obj.parentNode.removeChild(obj); - } - else { - setTimeout(arguments.callee, 10); - } - })(); - } - createSWF(att, par, replaceElemIdStr); - } - } - - /* Functions to abstract and display alternative content - */ - function displayAltContent(obj) { - if (ua.ie && ua.win && obj.readyState != 4) { - // IE only: when a SWF is loading (AND: not available in cache) wait for the readyState of the object element to become 4 before removing it, - // because you cannot properly cancel a loading SWF file without breaking browser load references, also obj.onreadystatechange doesn't work - var el = createElement("div"); - obj.parentNode.insertBefore(el, obj); // insert placeholder div that will be replaced by the alternative content - el.parentNode.replaceChild(abstractAltContent(obj), el); - obj.style.display = "none"; - (function(){ - if (obj.readyState == 4) { - obj.parentNode.removeChild(obj); - } - else { - setTimeout(arguments.callee, 10); - } - })(); - } - else { - obj.parentNode.replaceChild(abstractAltContent(obj), obj); - } - } - - function abstractAltContent(obj) { - var ac = createElement("div"); - if (ua.win && ua.ie) { - ac.innerHTML = obj.innerHTML; - } - else { - var nestedObj = obj.getElementsByTagName(OBJECT)[0]; - if (nestedObj) { - var c = nestedObj.childNodes; - if (c) { - var cl = c.length; - for (var i = 0; i < cl; i++) { - if (!(c[i].nodeType == 1 && c[i].nodeName == "PARAM") && !(c[i].nodeType == 8)) { - ac.appendChild(c[i].cloneNode(true)); - } - } - } - } - } - return ac; - } - - /* Cross-browser dynamic SWF creation - */ - function createSWF(attObj, parObj, id) { - var r, el = getElementById(id); - if (ua.wk && ua.wk < 312) { return r; } - if (el) { - if (typeof attObj.id == UNDEF) { // if no 'id' is defined for the object element, it will inherit the 'id' from the alternative content - attObj.id = id; - } - if (ua.ie && ua.win) { // Internet Explorer + the HTML object element + W3C DOM methods do not combine: fall back to outerHTML - var att = ""; - for (var i in attObj) { - if (attObj[i] != Object.prototype[i]) { // filter out prototype additions from other potential libraries - if (i.toLowerCase() == "data") { - parObj.movie = attObj[i]; - } - else if (i.toLowerCase() == "styleclass") { // 'class' is an ECMA4 reserved keyword - att += ' class="' + attObj[i] + '"'; - } - else if (i.toLowerCase() != "classid") { - att += ' ' + i + '="' + attObj[i] + '"'; - } - } - } - var par = ""; - for (var j in parObj) { - if (parObj[j] != Object.prototype[j]) { // filter out prototype additions from other potential libraries - par += ''; - } - } - el.outerHTML = '' + par + ''; - objIdArr[objIdArr.length] = attObj.id; // stored to fix object 'leaks' on unload (dynamic publishing only) - r = getElementById(attObj.id); - } - else { // well-behaving browsers - var o = createElement(OBJECT); - o.setAttribute("type", FLASH_MIME_TYPE); - for (var m in attObj) { - if (attObj[m] != Object.prototype[m]) { // filter out prototype additions from other potential libraries - if (m.toLowerCase() == "styleclass") { // 'class' is an ECMA4 reserved keyword - o.setAttribute("class", attObj[m]); - } - else if (m.toLowerCase() != "classid") { // filter out IE specific attribute - o.setAttribute(m, attObj[m]); - } - } - } - for (var n in parObj) { - if (parObj[n] != Object.prototype[n] && n.toLowerCase() != "movie") { // filter out prototype additions from other potential libraries and IE specific param element - createObjParam(o, n, parObj[n]); - } - } - el.parentNode.replaceChild(o, el); - r = o; - } - } - return r; - } - - function createObjParam(el, pName, pValue) { - var p = createElement("param"); - p.setAttribute("name", pName); - p.setAttribute("value", pValue); - el.appendChild(p); - } - - /* Cross-browser SWF removal - - Especially needed to safely and completely remove a SWF in Internet Explorer - */ - function removeSWF(id) { - var obj = getElementById(id); - if (obj && obj.nodeName == "OBJECT") { - if (ua.ie && ua.win) { - obj.style.display = "none"; - (function(){ - if (obj.readyState == 4) { - removeObjectInIE(id); - } - else { - setTimeout(arguments.callee, 10); - } - })(); - } - else { - obj.parentNode.removeChild(obj); - } - } - } - - function removeObjectInIE(id) { - var obj = getElementById(id); - if (obj) { - for (var i in obj) { - if (typeof obj[i] == "function") { - obj[i] = null; - } - } - obj.parentNode.removeChild(obj); - } - } - - /* Functions to optimize JavaScript compression - */ - function getElementById(id) { - var el = null; - try { - el = doc.getElementById(id); - } - catch (e) {} - return el; - } - - function createElement(el) { - return doc.createElement(el); - } - - /* Updated attachEvent function for Internet Explorer - - Stores attachEvent information in an Array, so on unload the detachEvent functions can be called to avoid memory leaks - */ - function addListener(target, eventType, fn) { - target.attachEvent(eventType, fn); - listenersArr[listenersArr.length] = [target, eventType, fn]; - } - - /* Flash Player and SWF content version matching - */ - function hasPlayerVersion(rv) { - var pv = ua.pv, v = rv.split("."); - v[0] = parseInt(v[0], 10); - v[1] = parseInt(v[1], 10) || 0; // supports short notation, e.g. "9" instead of "9.0.0" - v[2] = parseInt(v[2], 10) || 0; - return (pv[0] > v[0] || (pv[0] == v[0] && pv[1] > v[1]) || (pv[0] == v[0] && pv[1] == v[1] && pv[2] >= v[2])) ? true : false; - } - - /* Cross-browser dynamic CSS creation - - Based on Bobby van der Sluis' solution: http://www.bobbyvandersluis.com/articles/dynamicCSS.php - */ - function createCSS(sel, decl, media, newStyle) { - if (ua.ie && ua.mac) { return; } - var h = doc.getElementsByTagName("head")[0]; - if (!h) { return; } // to also support badly authored HTML pages that lack a head element - var m = (media && typeof media == "string") ? media : "screen"; - if (newStyle) { - dynamicStylesheet = null; - dynamicStylesheetMedia = null; - } - if (!dynamicStylesheet || dynamicStylesheetMedia != m) { - // create dynamic stylesheet + get a global reference to it - var s = createElement("style"); - s.setAttribute("type", "text/css"); - s.setAttribute("media", m); - dynamicStylesheet = h.appendChild(s); - if (ua.ie && ua.win && typeof doc.styleSheets != UNDEF && doc.styleSheets.length > 0) { - dynamicStylesheet = doc.styleSheets[doc.styleSheets.length - 1]; - } - dynamicStylesheetMedia = m; - } - // add style rule - if (ua.ie && ua.win) { - if (dynamicStylesheet && typeof dynamicStylesheet.addRule == OBJECT) { - dynamicStylesheet.addRule(sel, decl); - } - } - else { - if (dynamicStylesheet && typeof doc.createTextNode != UNDEF) { - dynamicStylesheet.appendChild(doc.createTextNode(sel + " {" + decl + "}")); - } - } - } - - function setVisibility(id, isVisible) { - if (!autoHideShow) { return; } - var v = isVisible ? "visible" : "hidden"; - if (isDomLoaded && getElementById(id)) { - getElementById(id).style.visibility = v; - } - else { - createCSS("#" + id, "visibility:" + v); - } - } - - /* Filter to avoid XSS attacks - */ - function urlEncodeIfNecessary(s) { - var regex = /[\\\"<>\.;]/; - var hasBadChars = regex.exec(s) != null; - return hasBadChars && typeof encodeURIComponent != UNDEF ? encodeURIComponent(s) : s; - } - - /* Release memory to avoid memory leaks caused by closures, fix hanging audio/video threads and force open sockets/NetConnections to disconnect (Internet Explorer only) - */ - var cleanup = function() { - if (ua.ie && ua.win) { - window.attachEvent("onunload", function() { - // remove listeners to avoid memory leaks - var ll = listenersArr.length; - for (var i = 0; i < ll; i++) { - listenersArr[i][0].detachEvent(listenersArr[i][1], listenersArr[i][2]); - } - // cleanup dynamically embedded objects to fix audio/video threads and force open sockets and NetConnections to disconnect - var il = objIdArr.length; - for (var j = 0; j < il; j++) { - removeSWF(objIdArr[j]); - } - // cleanup library's main closures to avoid memory leaks - for (var k in ua) { - ua[k] = null; - } - ua = null; - for (var l in swfobject) { - swfobject[l] = null; - } - swfobject = null; - }); - } - }(); - - return { - /* Public API - - Reference: http://code.google.com/p/swfobject/wiki/documentation - */ - registerObject: function(objectIdStr, swfVersionStr, xiSwfUrlStr, callbackFn) { - if (ua.w3 && objectIdStr && swfVersionStr) { - var regObj = {}; - regObj.id = objectIdStr; - regObj.swfVersion = swfVersionStr; - regObj.expressInstall = xiSwfUrlStr; - regObj.callbackFn = callbackFn; - regObjArr[regObjArr.length] = regObj; - setVisibility(objectIdStr, false); - } - else if (callbackFn) { - callbackFn({success:false, id:objectIdStr}); - } - }, - - getObjectById: function(objectIdStr) { - if (ua.w3) { - return getObjectById(objectIdStr); - } - }, - - embedSWF: function(swfUrlStr, replaceElemIdStr, widthStr, heightStr, swfVersionStr, xiSwfUrlStr, flashvarsObj, parObj, attObj, callbackFn) { - var callbackObj = {success:false, id:replaceElemIdStr}; - if (ua.w3 && !(ua.wk && ua.wk < 312) && swfUrlStr && replaceElemIdStr && widthStr && heightStr && swfVersionStr) { - setVisibility(replaceElemIdStr, false); - addDomLoadEvent(function() { - widthStr += ""; // auto-convert to string - heightStr += ""; - var att = {}; - if (attObj && typeof attObj === OBJECT) { - for (var i in attObj) { // copy object to avoid the use of references, because web authors often reuse attObj for multiple SWFs - att[i] = attObj[i]; - } - } - att.data = swfUrlStr; - att.width = widthStr; - att.height = heightStr; - var par = {}; - if (parObj && typeof parObj === OBJECT) { - for (var j in parObj) { // copy object to avoid the use of references, because web authors often reuse parObj for multiple SWFs - par[j] = parObj[j]; - } - } - if (flashvarsObj && typeof flashvarsObj === OBJECT) { - for (var k in flashvarsObj) { // copy object to avoid the use of references, because web authors often reuse flashvarsObj for multiple SWFs - if (typeof par.flashvars != UNDEF) { - par.flashvars += "&" + k + "=" + flashvarsObj[k]; - } - else { - par.flashvars = k + "=" + flashvarsObj[k]; - } - } - } - if (hasPlayerVersion(swfVersionStr)) { // create SWF - var obj = createSWF(att, par, replaceElemIdStr); - if (att.id == replaceElemIdStr) { - setVisibility(replaceElemIdStr, true); - } - callbackObj.success = true; - callbackObj.ref = obj; - } - else if (xiSwfUrlStr && canExpressInstall()) { // show Adobe Express Install - att.data = xiSwfUrlStr; - showExpressInstall(att, par, replaceElemIdStr, callbackFn); - return; - } - else { // show alternative content - setVisibility(replaceElemIdStr, true); - } - if (callbackFn) { callbackFn(callbackObj); } - }); - } - else if (callbackFn) { callbackFn(callbackObj); } - }, - - switchOffAutoHideShow: function() { - autoHideShow = false; - }, - - ua: ua, - - getFlashPlayerVersion: function() { - return { major:ua.pv[0], minor:ua.pv[1], release:ua.pv[2] }; - }, - - hasFlashPlayerVersion: hasPlayerVersion, - - createSWF: function(attObj, parObj, replaceElemIdStr) { - if (ua.w3) { - return createSWF(attObj, parObj, replaceElemIdStr); - } - else { - return undefined; - } - }, - - showExpressInstall: function(att, par, replaceElemIdStr, callbackFn) { - if (ua.w3 && canExpressInstall()) { - showExpressInstall(att, par, replaceElemIdStr, callbackFn); - } - }, - - removeSWF: function(objElemIdStr) { - if (ua.w3) { - removeSWF(objElemIdStr); - } - }, - - createCSS: function(selStr, declStr, mediaStr, newStyleBoolean) { - if (ua.w3) { - createCSS(selStr, declStr, mediaStr, newStyleBoolean); - } - }, - - addDomLoadEvent: addDomLoadEvent, - - addLoadEvent: addLoadEvent, - - getQueryParamValue: function(param) { - var q = doc.location.search || doc.location.hash; - if (q) { - if (/\?/.test(q)) { q = q.split("?")[1]; } // strip question mark - if (param == null) { - return urlEncodeIfNecessary(q); - } - var pairs = q.split("&"); - for (var i = 0; i < pairs.length; i++) { - if (pairs[i].substring(0, pairs[i].indexOf("=")) == param) { - return urlEncodeIfNecessary(pairs[i].substring((pairs[i].indexOf("=") + 1))); - } - } - } - return ""; - }, - - // For internal usage only - expressInstallCallback: function() { - if (isExpressInstallActive) { - var obj = getElementById(EXPRESS_INSTALL_ID); - if (obj && storedAltContent) { - obj.parentNode.replaceChild(storedAltContent, obj); - if (storedAltContentId) { - setVisibility(storedAltContentId, true); - if (ua.ie && ua.win) { storedAltContent.style.display = "block"; } - } - if (storedCallbackFn) { storedCallbackFn(storedCallbackObj); } - } - isExpressInstallActive = false; - } - } - }; -}(); diff --git a/src/av/samples/mediaserver/client/symple.webrtc.test.html b/src/av/samples/mediaserver/client/symple.webrtc.test.html deleted file mode 100644 index 9cee53b36..000000000 --- a/src/av/samples/mediaserver/client/symple.webrtc.test.html +++ /dev/null @@ -1,184 +0,0 @@ - - - - Symple Player Tests - - - - - - - - - - - - - - -
- - -
-

WebRTC Video Player

-
-
-
- - - - -
-
-
-
- -
- - - \ No newline at end of file diff --git a/src/av/samples/mediaserver/config.h b/src/av/samples/mediaserver/config.h index f23208f62..179015291 100644 --- a/src/av/samples/mediaserver/config.h +++ b/src/av/samples/mediaserver/config.h @@ -2,7 +2,6 @@ #define SCY_MediaServer_Config_H #include "scy/application.h" -//#include "scy/av/mediafactory.h" #include "scy/av/multiplexencoder.h" #include "scy/http/server.h" #include "scy/logger.h" @@ -13,8 +12,7 @@ namespace scy { -// const std::string kPublicIP = "124.171.220.107"; // Current external IP for TURN permissions -const std::string kRelayServerIP = "127.0.0.1"; // TURN server IP +const std::string kRelayServerIP = "127.0.0.1"; // TURN server IP #define SERVER_PORT 1328 @@ -22,7 +20,4 @@ const std::string kRelayServerIP = "127.0.0.1"; // TURN server IP } // namespace scy -#endif // SCY_MediaServer_Config_H - - -/// @\} \ No newline at end of file +#endif // SCY_MediaServer_Config_H \ No newline at end of file diff --git a/src/av/samples/mediaserver/main.cpp b/src/av/samples/mediaserver/main.cpp index 364aff333..5c3bf797b 100644 --- a/src/av/samples/mediaserver/main.cpp +++ b/src/av/samples/mediaserver/main.cpp @@ -7,11 +7,10 @@ using namespace scy; #define SERVER_PORT 1328 - int main(int argc, char** argv) { - Logger::instance().add(new ConsoleChannel("debug", Level::Trace)); - //Logger::instance().setWriter(new AsyncLogWriter); + Logger::instance().add(std::make_unique("debug", Level::Trace)); + //Logger::instance().setWriter(std::make_unique()); { // Pre-initialize video captures in the main thread // MediaFactory::instance().loadVideoCaptures(); diff --git a/src/av/samples/mediaserver/mediaserver.cpp b/src/av/samples/mediaserver/mediaserver.cpp index bff164468..d64f94996 100644 --- a/src/av/samples/mediaserver/mediaserver.cpp +++ b/src/av/samples/mediaserver/mediaserver.cpp @@ -1,285 +1,284 @@ -#include "mediaserver.h" -#include "relayresponder.h" -#include "snapshotresponder.h" -#include "streamingresponder.h" -#include "websocketresponder.h" -#include "scy/av/formatregistry.h" -#include "scy/av/devicemanager.h" -#include "scy/av/multiplexpacketencoder.h" -#include "scy/collection.h" - -#include "scy/http/packetizers.h" -#include "scy/http/util.h" -#include "scy/util/base64packetencoder.h" - - -using namespace std; -using namespace scy; - - -namespace scy { - - -// -// HTTP Media Server -// - - -MediaServer::MediaServer(uint16_t port) - : http::Server(net::Address("0.0.0.0", port), - net::makeSocket(), - new HTTPStreamingConnectionFactory(this)) -{ - LDebug("Create") - - // Register the media formats we will be using - // FormatRegistry& formats = MediaFactory::instance().formats(); - - // Adobe Flash Player requires that audio files be 16bit and have a sample - // rate of 44.1khz. - // Flash Player can handle MP3 files encoded at 32kbps, 48kbps, 56kbps, - // 64kbps, 128kbps, 160kbps or 256kbps. - // NOTE: 128000 works fine for 44100, but 64000 is borked! - formats.registerFormat(av::Format("MP3", "mp3", - av::AudioCodec("MP3", "libmp3lame", 2, 44100, 128000, "s16p"))); - - formats.registerFormat(av::Format("FLV", "flv", - av::VideoCodec("FLV", "flv", 320, 240))); - - formats.registerFormat(av::Format("FLV-Speex", "flv", - av::VideoCodec("FLV", "flv", 320, 240), - av::AudioCodec("Speex", "libspeex", 1, 16000))); - - formats.registerFormat(av::Format("Speex", "flv", - av::AudioCodec("Speex", "libspeex", 1, 16000))); - - formats.registerFormat(av::Format("MJPEG", "mjpeg", - av::VideoCodec("MJPEG", "mjpeg", 480, 320, 20))); - - // TODO: Add h264 and newer audio formats -} - - -MediaServer::~MediaServer() -{ - LDebug("Destroy") -} - - -void MediaServer::setupPacketStream(PacketStream& stream, const StreamingOptions& options, - bool freeCaptures, bool attachPacketizers) -{ - LDebug("Setup Packet Stream") - - // Attach capture sources - - assert(options.oformat.video.enabled || options.oformat.audio.enabled); - if (options.oformat.video.enabled) { - assert(options.videoCapture); - - // assert(dynamic_cast(options.videoCapture.get())); - // assert(dynamic_cast(options.videoCapture.get())); - - // auto source = dynamic_cast(options.videoCapture.get()); - // assert(source); - // if (!source) throw std::runtime_error("Cannot attach incompatible packet source."); - - stream.attachSource(options.videoCapture, true); // freeCaptures, - } - if (options.oformat.audio.enabled) { - assert(options.audioCapture); - stream.attachSource(options.audioCapture, true); // freeCaptures, - } - - // Attach an FPS limiter to the stream - // stream.attach(new FPSLimiter(5), 1, true); - - // Attach an async queue so we don't choke - // the video capture while encoding. - // auto async = new AsyncPacketQueue<>(2048); - // stream.attach(async, 3, true); - - // Attach the video encoder - auto encoder = new av::MultiplexPacketEncoder(options); - // encoder->init(); - stream.attach(encoder, 5, true); - - // Add format specific framings - if (options.oformat.name == "MJPEG") { - - // Base64 encode the MJPEG stream for old browsers - if (options.encoding.empty() || options.encoding == "none" || options.encoding == "None") { - // no default encoding - } else if (options.encoding == "Base64") { - auto base64 = new Base64PacketEncoder(); - stream.attach(base64, 10, true); - } else - throw std::runtime_error("Unsupported encoding method: " + options.encoding); - } - else if (options.oformat.name == "FLV") { - - // Allow mid-stream flash client connection - // FIXME: Broken in latest flash - // auto injector = new FLVMetadataInjector(options.oformat); - // stream.attach(injector, 10); - } - - // Attach the HTTP output framing - IPacketizer* framing = nullptr; - if (options.framing.empty() || options.framing == "none" || options.framing == "None") - ; - // framing = new http::StreamingAdapter("image/jpeg"); - - else if (options.framing == "chunked") - framing = new http::ChunkedAdapter("image/jpeg"); - - else if (options.framing == "multipart") - framing = new http::MultipartAdapter("image/jpeg", options.encoding == "Base64"); // false, - - else - throw std::runtime_error("Unsupported framing method: " + options.framing); - - if (framing) - stream.attach(framing, 15, true); - - // Attach a sync queue to synchronize output with the event loop - auto sync = new SyncPacketQueue<>; - stream.attach(sync, 20, true); -} - - -// -// HTTP Streaming Connection Factory -// - - -HTTPStreamingConnectionFactory::HTTPStreamingConnectionFactory(MediaServer* server) - : _server(server) -{ -} - - -HTTPStreamingConnectionFactory:: ~HTTPStreamingConnectionFactory() -{ -} - - -StreamingOptions HTTPStreamingConnectionFactory::createStreamingOptions(http::ServerConnection& conn) -{ - auto& request = conn.request(); - - // Parse streaming options from query - StreamingOptions options(_server); - NVCollection params; - request.getURIParameters(params); - - // An exception will be thrown if no format was provided, - // or if the request format is not registered. - options.oformat = _server->formats.get(params.get("format", "MJPEG")); - if (params.has("width")) - options.oformat.video.width = util::strtoi(params.get("width")); - if (params.has("height")) - options.oformat.video.height = util::strtoi(params.get("height")); - if (params.has("fps")) - options.oformat.video.fps = util::strtoi(params.get("fps")); - if (params.has("quality")) - options.oformat.video.quality = util::strtoi(params.get("quality")); - - // Response encoding and framing options - options.encoding = params.get("encoding", ""); - options.framing = params.get("framing", ""); - - // Open video and audio captures. - av::Device dev; - av::DeviceManager devman; - if (options.oformat.video.enabled) { - devman.getDefaultCamera(dev); - LInfo("Default video capture ", dev.id) - options.videoCapture = std::make_shared(dev.id, options.oformat.video); - //options.videoCapture->openVideo(dev.id, options.oformat.video.width, - // options.oformat.video.height, - // options.oformat.video.fps); - options.videoCapture->getEncoderFormat(options.iformat); - } - if (options.oformat.audio.enabled) { - devman.getDefaultMicrophone(dev); - LInfo("Default audio capture ", dev.id) - options.audioCapture = std::make_shared(dev.id, options.oformat.audio); - //options.audioCapture->open(dev.id, options.oformat.audio.channels, - // options.oformat.audio.sampleRate); - options.audioCapture->getEncoderFormat(options.iformat); - } - - if (!options.videoCapture && !options.audioCapture) { - throw std::runtime_error("No audio or video devices are available for capture"); - } - - return options; -} - - -http::ServerResponder* HTTPStreamingConnectionFactory::createResponder(http::ServerConnection& conn) -{ - try { - auto& request = conn.request(); - - // Log incoming requests - SInfo << "Incoming connection from " << conn.socket()->peerAddress() - << ": URI:\n" << request.getURI() - << ": Request:\n" << request << endl; - - // Handle websocket connections - if (request.getURI().find("/websocket") == 0 || request.has("Sec-WebSocket-Key")) { - return new WebSocketRequestHandler(conn, createStreamingOptions(conn)); - } - - // Handle HTTP streaming - if (request.getURI().find("/streaming") == 0) { - return new StreamingRequestHandler(conn, createStreamingOptions(conn)); - } - - // Handle relayed media requests - if (request.getURI().find("/relay") == 0) { - return new RelayedStreamingResponder(conn, createStreamingOptions(conn)); - } - -#ifdef HAVE_OPENCV - // Handle HTTP snapshot requests - if (request.getURI().find("/snapshot") == 0) { - return new SnapshotRequestHandler(conn, createStreamingOptions(conn)); - } -#endif - } - catch (std::exception& exc) { - LError("Request error: ", exc.what()) - } - - LWarn("Bad Request") - conn.response().setStatus(http::StatusCode::BadRequest); - conn.sendHeader(); - conn.close(); - return nullptr; -} - - -// -// HTTP Streaming Options -// - - -StreamingOptions::StreamingOptions(MediaServer* server, - av::VideoCapture::Ptr videoCapture, - av::AudioCapture::Ptr audioCapture) - : server(server) - , videoCapture(videoCapture) - , audioCapture(audioCapture) -{ -} - - -StreamingOptions::~StreamingOptions() -{ -} - - -} // namespace scy \ No newline at end of file +#include "mediaserver.h" +#include "relayresponder.h" +#include "scy/av/devicemanager.h" +#include "scy/av/formatregistry.h" +#include "scy/av/multiplexpacketencoder.h" +#include "scy/collection.h" +#include "snapshotresponder.h" +#include "streamingresponder.h" +#include "websocketresponder.h" + +#include "scy/base64packetencoder.h" +#include "scy/http/packetizers.h" +#include "scy/http/util.h" + + +using namespace std; +using namespace scy; + + +namespace scy { + + +// +// HTTP Media Server +// + + +MediaServer::MediaServer(uint16_t port) + : http::Server(net::Address("0.0.0.0", port), + net::makeSocket(), + new HTTPStreamingConnectionFactory(this)) +{ + LDebug("Create"); + + // Register the media formats we will be using + // FormatRegistry& formats = MediaFactory::instance().formats(); + + // Adobe Flash Player requires that audio files be 16bit and have a sample + // rate of 44.1khz. + // Flash Player can handle MP3 files encoded at 32kbps, 48kbps, 56kbps, + // 64kbps, 128kbps, 160kbps or 256kbps. + // NOTE: 128000 works fine for 44100, but 64000 is borked! + formats.registerFormat(av::Format("MP3", "mp3", + av::AudioCodec("MP3", "libmp3lame", 2, 44100, 128000, "s16p"))); + + formats.registerFormat(av::Format("FLV", "flv", + av::VideoCodec("FLV", "flv", 320, 240))); + + formats.registerFormat(av::Format("FLV-Speex", "flv", + av::VideoCodec("FLV", "flv", 320, 240), + av::AudioCodec("Speex", "libspeex", 1, 16000))); + + formats.registerFormat(av::Format("Speex", "flv", + av::AudioCodec("Speex", "libspeex", 1, 16000))); + + formats.registerFormat(av::Format("MJPEG", "mjpeg", + av::VideoCodec("MJPEG", "mjpeg", 480, 320, 20))); + + // TODO: Add h264 and newer audio formats +} + + +MediaServer::~MediaServer() +{ + LDebug("Destroy"); +} + + +void MediaServer::setupPacketStream(PacketStream& stream, const StreamingOptions& options, + bool freeCaptures, bool attachPacketizers) +{ + LDebug("Setup Packet Stream"); + + // Attach capture sources + + assert(options.oformat.video.enabled || options.oformat.audio.enabled); + if (options.oformat.video.enabled) { + assert(options.videoCapture); + + // assert(dynamic_cast(options.videoCapture.get())); + // assert(dynamic_cast(options.videoCapture.get())); + + // auto source = dynamic_cast(options.videoCapture.get()); + // assert(source); + // if (!source) throw std::runtime_error("Cannot attach incompatible packet source."); + + stream.attachSource(options.videoCapture, true); // freeCaptures, + } + if (options.oformat.audio.enabled) { + assert(options.audioCapture); + stream.attachSource(options.audioCapture, true); // freeCaptures, + } + + // Attach an FPS limiter to the stream + // stream.attach(new FPSLimiter(5), 1, true); + + // Attach an async queue so we don't choke + // the video capture while encoding. + // auto async = new AsyncPacketQueue<>(2048); + // stream.attach(async, 3, true); + + // Attach the video encoder + auto encoder = new av::MultiplexPacketEncoder(options); + // encoder->init(); + stream.attach(encoder, 5, true); + + // Add format specific framings + if (options.oformat.name == "MJPEG") { + + // Base64 encode the MJPEG stream for old browsers + if (options.encoding.empty() || options.encoding == "none") { + // no default encoding + } else if (options.encoding == "Base64") { + auto base64 = new Base64PacketEncoder(); + stream.attach(base64, 10, true); + } else + throw std::runtime_error("Unsupported encoding method: " + options.encoding); + } else if (options.oformat.name == "FLV") { + // Allow mid-stream flash client connection + // FIXME: Broken in latest flash + // auto injector = new FLVMetadataInjector(options.oformat); + // stream.attach(injector, 10); + } + // Attach the HTTP output framing + IPacketizer* framing = nullptr; + if (options.framing.empty() || options.framing == "none") + ; + // framing = new http::StreamingAdapter("image/jpeg"); + + else if (options.framing == "chunked") + framing = new http::ChunkedAdapter("image/jpeg"); + + else if (options.framing == "multipart") + framing = new http::MultipartAdapter("image/jpeg", options.encoding == "Base64"); // false, + + else + throw std::runtime_error("Unsupported framing method: " + options.framing); + + if (framing) + stream.attach(framing, 15, true); + + // Attach a sync queue to synchronize output with the event loop + auto sync = new SyncPacketQueue<>; + stream.attach(sync, 20, true); +} + + +// +// HTTP Streaming Connection Factory +// + + +HTTPStreamingConnectionFactory::HTTPStreamingConnectionFactory(MediaServer* server) + : _server(server) +{ +} + + +HTTPStreamingConnectionFactory::~HTTPStreamingConnectionFactory() +{ +} + + +StreamingOptions HTTPStreamingConnectionFactory::createStreamingOptions(http::ServerConnection& conn) +{ + auto& request = conn.request(); + + // Parse streaming options from query + StreamingOptions options(_server); + NVCollection params; + request.getURIParameters(params); + + // An exception will be thrown if no format was provided, + // or if the request format is not registered. + options.oformat = _server->formats.get(params.get("format", "MJPEG")); + if (params.has("width")) + options.oformat.video.width = util::strtoi(params.get("width")); + if (params.has("height")) + options.oformat.video.height = util::strtoi(params.get("height")); + if (params.has("fps")) + options.oformat.video.fps = util::strtoi(params.get("fps")); + if (params.has("quality")) + options.oformat.video.quality = util::strtoi(params.get("quality")); + + // Response encoding and framing options + options.encoding = params.get("encoding", ""); + options.framing = params.get("framing", ""); + + // Open video and audio captures. + av::Device dev; + av::DeviceManager devman; + if (options.oformat.video.enabled) { + devman.getDefaultCamera(dev); + LInfo("Default video capture ", dev.id); + options.videoCapture = std::make_shared(dev.id, options.oformat.video); + // options.videoCapture->openVideo(dev.id, options.oformat.video.width, + // options.oformat.video.height, + // options.oformat.video.fps); + options.videoCapture->getEncoderFormat(options.iformat); + } + if (options.oformat.audio.enabled) { + devman.getDefaultMicrophone(dev); + LInfo("Default audio capture ", dev.id); + options.audioCapture = std::make_shared(dev.id, options.oformat.audio); + // options.audioCapture->open(dev.id, options.oformat.audio.channels, + // options.oformat.audio.sampleRate); + options.audioCapture->getEncoderFormat(options.iformat); + } + + if (!options.videoCapture && !options.audioCapture) { + throw std::runtime_error("No audio or video devices are available for capture"); + } + + return options; +} + + +http::ServerResponder* HTTPStreamingConnectionFactory::createResponder(http::ServerConnection& conn) +{ + try { + auto& request = conn.request(); + + // Log incoming requests + SInfo << "Incoming connection from " << conn.socket()->peerAddress() + << ": URI:\n" + << request.getURI() + << ": Request:\n" + << request << endl; + + // Handle websocket connections + if (request.getURI().find("/websocket") == 0 || request.has("Sec-WebSocket-Key")) { + return new WebSocketRequestHandler(conn, createStreamingOptions(conn)); + } + + // Handle HTTP streaming + if (request.getURI().find("/streaming") == 0) { + return new StreamingRequestHandler(conn, createStreamingOptions(conn)); + } + + // Handle relayed media requests + if (request.getURI().find("/relay") == 0) { + return new RelayedStreamingResponder(conn, createStreamingOptions(conn)); + } + +#ifdef HAVE_OPENCV + // Handle HTTP snapshot requests + if (request.getURI().find("/snapshot") == 0) { + return new SnapshotRequestHandler(conn, createStreamingOptions(conn)); + } +#endif + } catch (std::exception& exc) { + LError("Request error: ", exc.what()); + } + + LWarn("Bad Request"); + conn.response() + .setStatus(http::StatusCode::BadRequest); + conn.sendHeader(); + conn.close(); + return nullptr; +} + + +// +// HTTP Streaming Options +// + + +StreamingOptions::StreamingOptions(MediaServer* server, + av::VideoCapture::Ptr videoCapture, + av::AudioCapture::Ptr audioCapture) + : server(server) + , videoCapture(videoCapture) + , audioCapture(audioCapture) +{ +} + + +StreamingOptions::~StreamingOptions() +{ +} + + +} // namespace scy diff --git a/src/av/samples/mediaserver/mediaserver.h b/src/av/samples/mediaserver/mediaserver.h index 8a3b8810b..d43c0fcd8 100644 --- a/src/av/samples/mediaserver/mediaserver.h +++ b/src/av/samples/mediaserver/mediaserver.h @@ -4,11 +4,11 @@ #include "config.h" #include "scy/application.h" -#include "scy/av/videocapture.h" #include "scy/av/audiocapture.h" -#include "scy/av/multiplexencoder.h" #include "scy/av/devicemanager.h" #include "scy/av/formatregistry.h" +#include "scy/av/multiplexencoder.h" +#include "scy/av/videocapture.h" #include "scy/http/server.h" #include "scy/logger.h" #include "scy/packetstream.h" diff --git a/src/av/samples/mediaserver/relayresponder.h b/src/av/samples/mediaserver/relayresponder.h index b7c2688b6..ae700c57b 100644 --- a/src/av/samples/mediaserver/relayresponder.h +++ b/src/av/samples/mediaserver/relayresponder.h @@ -1,7 +1,7 @@ #include "mediaserver.h" +#include "scy/streammanager.h" #include "scy/turn/client/tcpclient.h" -#include "scy/util/streammanager.h" namespace scy { @@ -52,24 +52,25 @@ class RelayedStreamingAllocation : public turn::TCPClientObserver void initiate() { - LDebug("Initiating") + LDebug("Initiating"); try { // Initiate the TRUN client allocation client.addPermission(peerIP); client.addPermission("127.0.0.1"); // for proxy client.addPermission("192.168.1.1"); // for proxy client.initiate(); - } - catch (std::exception& exc) { - LError("Error: ", exc.what()) + } catch (std::exception& exc) { + LError("Error: ", exc.what()); assert(0); } } void dispose() { - LDebug("Terminating") - if (deleted) { + LDebug("Terminating"); + if (deleted) + ; + { // assert(0); return; } @@ -80,14 +81,14 @@ class RelayedStreamingAllocation : public turn::TCPClientObserver streams.closeAll(); // Destroy the client when the allocation is lost - scy::deleteLater(this); + delete this; deleted = true; } protected: void onClientStateChange(turn::Client&, turn::ClientState& state, const turn::ClientState&) { - LDebug("Relay state changed: ", state.toString()) + LDebug("Relay state changed: ", state.toString()); switch (state.id()) { case turn::ClientState::None: @@ -101,22 +102,22 @@ class RelayedStreamingAllocation : public turn::TCPClientObserver break; case turn::ClientState::Failed: // assert(0 && "Allocation failed"); - LWarn("Relay connection lost") + LWarn("Relay connection lost"); // AllocationFailed.emit(this->client); // dispose(); break; - // case turn::ClientState::Terminated: - // break; + // case turn::ClientState::Terminated: + // break; } } void onRelayConnectionCreated(turn::TCPClient&, const net::TCPSocket::Ptr& socket, const net::Address& peerAddr) // uint32_t connectionID, { - LDebug("Connection created: ", peerAddr) + LDebug("Connection created: ", peerAddr); // Just allow one stream for now if (this->streams.size() == 1) { - LDebug("Rejecting connection") + LDebug("Rejecting connection"); return; } @@ -145,14 +146,14 @@ class RelayedStreamingAllocation : public turn::TCPClientObserver this->streams.addStream(stream); } catch (std::exception& exc) { - LError("Stream error: ", exc.what()) + LError("Stream error: ", exc.what()); assert(0); } } void onRelayConnectionClosed(turn::TCPClient&, const net::TCPSocket::Ptr& socket, const net::Address& peerAddress) { - LDebug("Connection closed: ", peerAddress) + LDebug("Connection closed: ", peerAddress); try { // Destroy the media stream for the closed connection (if any). @@ -168,7 +169,7 @@ class RelayedStreamingAllocation : public turn::TCPClientObserver // stream->destroy(); } } catch (std::exception& exc) { - LError("Stream error: ", exc.what()) + LError("Stream error: ", exc.what()); assert(0); } @@ -179,14 +180,14 @@ class RelayedStreamingAllocation : public turn::TCPClientObserver void onRelayDataReceived(turn::Client&, const char* data, std::size_t size, const net::Address& peerAddr) { SDebug << "Received data from peer: " << std::string(data, size) - << ": " << peerAddr << std::endl; + << ": " << peerAddr << std::endl; // If the remove peer is a web browser then the HTTP request sent // to the relayed address will be the first thing we see here... } void onAllocationPermissionsCreated(turn::Client&, const turn::PermissionList& permissions) { - LDebug("Permissions created") + LDebug("Permissions created"); } }; @@ -240,9 +241,11 @@ class RelayedStreamingResponder : public http::ServerResponder allocation->AllocationCreated -= slot(this, &RelayedStreamingResponder::onAllocationCreated); std::string address(allocation->client.relayedAddress().toString()); - LDebug("Allocation Created: ", address) + LDebug("Allocation Created: ", address); // Send the relay address response to the initiator - connection().response().set("Access-Control-Allow-Origin", "*"); + connection() + .response() + .set("Access-Control-Allow-Origin", "*"); connection().send(address.c_str(), address.length()); connection().close(); } @@ -251,7 +254,7 @@ class RelayedStreamingResponder : public http::ServerResponder // { // allocation->AllocationFailed -= sdelegate(this, &RelayedStreamingResponder::onAllocationFailed); // - // LDebug("Allocation Failed") + // LDebug("Allocation Failed"); // // // Send the relay address response to the initiator // //connection().socket()->send(address.c_str(), address.length()); diff --git a/src/av/samples/mediaserver/snapshotresponder.h b/src/av/samples/mediaserver/snapshotresponder.h index 207a763ee..0a9b9e2fa 100644 --- a/src/av/samples/mediaserver/snapshotresponder.h +++ b/src/av/samples/mediaserver/snapshotresponder.h @@ -10,7 +10,7 @@ class SnapshotRequestHandler : public http::ServerResponder { public: SnapshotRequestHandler(http::ServerConnection& connection, - const StreamingOptions& options) + const StreamingOptions& options) : http::ServerResponder(connection) , options(options) { @@ -20,7 +20,7 @@ class SnapshotRequestHandler : public http::ServerResponder void onRequest(http::Request& request, http::Response& response) { - LDebug("Running") + LDebug("Running"); cv::Mat frame; options.videoCapture->getFrame(frame, options.oformat.video.width, @@ -39,7 +39,7 @@ class SnapshotRequestHandler : public http::ServerResponder << "\n\tCapture Height: " << options.videoCapture->height() << "\n\tType: " << frame.type() << "\n\tInput Size: " << frame.total() - << "\n\tOutput Lize: " << buffer.size() << std::endl; + << "\n\tOutput Size: " << buffer.size() << std::endl; // std::copy(buffer.begin(), buffer.end(), data); // connection().sendData((const char*)data, buffer.size()); diff --git a/src/av/samples/mediaserver/streamingresponder.h b/src/av/samples/mediaserver/streamingresponder.h index f70d6b18b..881f24800 100644 --- a/src/av/samples/mediaserver/streamingresponder.h +++ b/src/av/samples/mediaserver/streamingresponder.h @@ -11,28 +11,28 @@ class StreamingRequestHandler : public http::ServerResponder : http::ServerResponder(connection) , options(options) { - LDebug("Create") + LDebug("Create"); } virtual ~StreamingRequestHandler() { - LDebug("Destroy") + LDebug("Destroy"); } virtual void onRequest(http::Request& request, http::Response& response) { SDebug << "Handle request: " - //<< "\n\tOutput Format: " << options.oformat.name - << "\n\tOutput Encoding: " << options.encoding - << "\n\tOutput Packetizer: " << options.framing - << std::endl; - + //<< "\n\tOutput Format: " << options.oformat.name + << "\n\tOutput Encoding: " << options.encoding + << "\n\tOutput Packetizer: " << options.framing + << std::endl; + // We will be sending our own headers - connection().shouldSendHeader(false); - + connection().shouldSendHeader(false); + // Create the packet stream - MediaServer::setupPacketStream(stream, options, true, true); - + MediaServer::setupPacketStream(stream, options, true, true); + // Start the stream stream.emitter += packetSlot(this, &StreamingRequestHandler::onVideoEncoded); stream.start(); @@ -40,7 +40,7 @@ class StreamingRequestHandler : public http::ServerResponder virtual void onClose() { - LDebug("On close") + LDebug("On close"); stream.emitter -= packetSlot(this, &StreamingRequestHandler::onVideoEncoded); stream.stop(); } @@ -48,15 +48,16 @@ class StreamingRequestHandler : public http::ServerResponder void onVideoEncoded(RawPacket& packet) { SDebug << "Send packet: " - // assert(!connection().socket()->closed()); - << packet.size() << ": " << fpsCounter.fps << std::endl; + // assert(!connection().socket()->closed()); + << packet.size() << ": " << fpsCounter.fps << std::endl; try { connection().socket()->send((const char*)packet.data(), packet.size()); fpsCounter.tick(); } catch (std::exception& exc) { - LError(exc.what()) - connection().close(); + LError(exc.what()); + connection() + .close(); } } @@ -66,4 +67,4 @@ class StreamingRequestHandler : public http::ServerResponder }; -} // namespace scy \ No newline at end of file +} // namespace scy diff --git a/src/av/samples/mediaserver/websocketresponder.h b/src/av/samples/mediaserver/websocketresponder.h index fd3cb7eda..d7a91fb75 100644 --- a/src/av/samples/mediaserver/websocketresponder.h +++ b/src/av/samples/mediaserver/websocketresponder.h @@ -14,11 +14,11 @@ class WebSocketRequestHandler : public http::ServerResponder : http::ServerResponder(connection) , options(options) { - LDebug("Create") + LDebug("Create"); // Create the packet stream - MediaServer::setupPacketStream(stream, options); - + MediaServer::setupPacketStream(stream, options); + // Start the stream stream.emitter += packetSlot(this, &WebSocketRequestHandler::onVideoEncoded); stream.start(); @@ -26,12 +26,12 @@ class WebSocketRequestHandler : public http::ServerResponder virtual ~WebSocketRequestHandler() { - LDebug("Destroy") + LDebug("Destroy"); } void onClose() { - LDebug("On close") + LDebug("On close"); stream.emitter -= packetSlot(this, &WebSocketRequestHandler::onVideoEncoded); stream.stop(); @@ -40,17 +40,16 @@ class WebSocketRequestHandler : public http::ServerResponder void onVideoEncoded(RawPacket& packet) { SDebug << "Sending Packet: " - // assert(!connection().socket()->closed()); - << &connection() << ": " << packet.size() << ": " - << fpsCounter.fps << std::endl; + << &connection() << ": " << packet.size() << ": " + << fpsCounter.fps << std::endl; try { - connection().socket()->send(packet.data(), packet.size(), http::ws::Binary); - // connection().sendData(packet.data(), packet.size(), http::WebSocket::Binary); + connection().send(packet.data(), packet.size(), http::ws::Binary); fpsCounter.tick(); } catch (std::exception& exc) { - LError("Error: ", exc.what()) - connection().close(); + LError("Error: ", exc.what()); + connection() + .close(); } } diff --git a/src/av/samples/videosocket/CMakeLists.txt b/src/av/samples/videosocket/CMakeLists.txt index 2dec6938f..859f4b190 100644 --- a/src/av/samples/videosocket/CMakeLists.txt +++ b/src/av/samples/videosocket/CMakeLists.txt @@ -1,8 +1 @@ -#include_dependency(LibUV) -#include_dependency(HttpParser) -#include_dependency(JsonCpp) -#include_dependency(SSL REQUIRED) -include_dependency(FFmpeg REQUIRED) -include_dependency(OpenCV REQUIRED) - -define_sourcey_module_sample(videosocket base crypto net http av util) +scy_add_sample(videosocket DEPENDS base crypto net http av) diff --git a/src/av/samples/videosocket/videosocket.cpp b/src/av/samples/videosocket/videosocket.cpp index 5feea0c1d..aad25f9ef 100644 --- a/src/av/samples/videosocket/videosocket.cpp +++ b/src/av/samples/videosocket/videosocket.cpp @@ -35,7 +35,7 @@ class MPEGResponder : public http::ServerResponder MPEGResponder(http::ServerConnection& conn) : http::ServerResponder(conn) { - LDebug("Creating") + LDebug("Creating"); auto stream = new PacketStream; @@ -48,8 +48,7 @@ class MPEGResponder : public http::ServerResponder // Setup the encoder options av::EncoderOptions options; options.oformat = av::Format( - "MJPEG", "mjpeg", av::VideoCodec("MJPEG", "mjpeg", 400, 300, 25, - 48000, 128000, "yuvj420p")); + "MJPEG", "mjpeg", av::VideoCodec("MJPEG", "mjpeg", 400, 300, 25, 48000, 128000, "yuvj420p")); gVideoCapture->getEncoderFormat(options.iformat); // Create and attach the encoder @@ -70,26 +69,26 @@ class MPEGResponder : public http::ServerResponder ~MPEGResponder() { - LDebug("Destroying") + LDebug("Destroying"); // stream->destroy(); delete stream; } void onPayload(const Buffer& body) { - LDebug("On recv payload: ", body.size()) + LDebug("On recv payload: ", body.size()); // do something with data from peer } void onClose() { - LDebug("On close") + LDebug("On close"); stream->emitter -= packetSlot(this, &MPEGResponder::onVideoEncoded); - LDebug("On close 1") + LDebug("On close 1"); stream->stop(); - LDebug("On close 2") + LDebug("On close 2"); } void onVideoEncoded(void* sender, RawPacket& packet) @@ -132,7 +131,7 @@ static void onShutdownSignal(void* opaque) int main(int argc, char** argv) { - Logger::instance().add(new ConsoleChannel("debug", Level::Trace)); + Logger::instance().add(std::make_unique("debug", Level::Trace)); #if USE_AVDEVICE_CAPTURE gVideoCapture = new av::MediaCapture(); diff --git a/src/av/samples/waveformoutput/CMakeLists.txt b/src/av/samples/waveformoutput/CMakeLists.txt index b5ea12d9d..358293d3a 100644 --- a/src/av/samples/waveformoutput/CMakeLists.txt +++ b/src/av/samples/waveformoutput/CMakeLists.txt @@ -1 +1,2 @@ -define_sourcey_module_sample(waveformoutput anionu base media) +# Legacy sample - depends on modules that no longer exist (anionu, media) +# scy_add_sample(waveformoutput DEPENDS base av) diff --git a/src/av/samples/waveformoutput/waveformoutput.cpp b/src/av/samples/waveformoutput/waveformoutput.cpp index 3220c88ac..d249e0316 100644 --- a/src/av/samples/waveformoutput/waveformoutput.cpp +++ b/src/av/samples/waveformoutput/waveformoutput.cpp @@ -21,7 +21,7 @@ CMemLeakDetect memLeakDetect; int main(int argc, char** argv) { try { - Logger::instance().add(new ConsoleChannel("debug", STraceevel)); + Logger::instance().add(std::make_unique("debug", STraceevel)); VideoAnalyzer analyzer; diff --git a/src/av/src/apple/avfoundation.cpp b/src/av/src/apple/avfoundation.cpp index da52d4ebc..e734b94ed 100644 --- a/src/av/src/apple/avfoundation.cpp +++ b/src/av/src/apple/avfoundation.cpp @@ -9,9 +9,9 @@ /// @{ +#include "scy/av/apple/avfoundation.h" #include "scy/logger.h" #include -#include "scy/av/apple/avfoundation.h" using std::endl; @@ -32,7 +32,7 @@ bool getDeviceList(Device::Type type, std::vector& devices) case Device::AudioInput: return GetAVFoundationVideoDevices(type, &devices); default: - LWarn("AVFoundation cannot enumerate output devices: Not implemented") + LWarn("AVFoundation cannot enumerate output devices: Not implemented"); break; } diff --git a/src/av/src/apple/avfoundation.mm b/src/av/src/apple/avfoundation_mm similarity index 100% rename from src/av/src/apple/avfoundation.mm rename to src/av/src/apple/avfoundation_mm diff --git a/src/av/src/audiobuffer.cpp b/src/av/src/audiobuffer.cpp index dc878acde..e329f2dd9 100644 --- a/src/av/src/audiobuffer.cpp +++ b/src/av/src/audiobuffer.cpp @@ -27,13 +27,13 @@ namespace av { AudioBuffer::AudioBuffer() : fifo(nullptr) { - LTrace("Create") + LTrace("Create"); } -AudioBuffer::~AudioBuffer() +AudioBuffer::~AudioBuffer() noexcept { - LTrace("Destroy") + LTrace("Destroy"); close(); } @@ -47,9 +47,12 @@ void AudioBuffer::alloc(const std::string& sampleFmt, int channels, int numSampl << endl; enum AVSampleFormat format = av_get_sample_fmt(sampleFmt.c_str()); - assert(!fifo); - assert(channels); - assert(format != AV_SAMPLE_FMT_NONE); + if (fifo) + throw std::runtime_error("AudioBuffer: already allocated"); + if (!channels) + throw std::runtime_error("AudioBuffer: channels must be non-zero"); + if (format == AV_SAMPLE_FMT_NONE) + throw std::runtime_error("AudioBuffer: invalid sample format"); // Create the FIFO buffer based on the specified sample format. fifo = av_audio_fifo_alloc(format, channels, numSamples); @@ -61,7 +64,7 @@ void AudioBuffer::alloc(const std::string& sampleFmt, int channels, int numSampl void AudioBuffer::reset() { - LTrace("Reset") + LTrace("Reset"); if (fifo) { av_audio_fifo_reset(fifo); @@ -71,7 +74,7 @@ void AudioBuffer::reset() void AudioBuffer::close() { - LTrace("Close") + LTrace("Close"); if (fifo) { av_audio_fifo_free(fifo); @@ -83,9 +86,8 @@ void AudioBuffer::close() void AudioBuffer::write(void** samples, int numSamples) { int error; - assert(fifo); - assert(samples); - assert(samples[0]); + if (!fifo || !samples || !samples[0]) + throw std::runtime_error("AudioBuffer: write called with invalid state"); // Make the FIFO as large as it needs to be to hold both // the old and the new samples. @@ -102,7 +104,7 @@ void AudioBuffer::write(void** samples, int numSamples) bool AudioBuffer::read(void** samples, int numSamples) { - LTrace("Read samples: ", numSamples) + LTrace("Read samples: ", numSamples); // Make sure that there is one frame worth of samples in the FIFO // buffer so that the encoder can do its work. @@ -110,7 +112,7 @@ bool AudioBuffer::read(void** samples, int numSamples) // need to FIFO buffer to store as many frames worth of input samples // that they make up at least one frame worth of output samples. if (available() < numSamples) { - LTrace("No packets in buffer") + LTrace("No packets in buffer"); return false; } diff --git a/src/av/src/audiocapture.cpp b/src/av/src/audiocapture.cpp index 1261c47e9..00db27f08 100644 --- a/src/av/src/audiocapture.cpp +++ b/src/av/src/audiocapture.cpp @@ -45,7 +45,7 @@ AudioCapture::AudioCapture(const std::string& device, const av::AudioCodec& para } -AudioCapture::~AudioCapture() +AudioCapture::~AudioCapture() noexcept { } @@ -59,10 +59,10 @@ void AudioCapture::openAudio(const std::string& device, const av::AudioCodec& pa void AudioCapture::openAudio(const std::string& device, int channels, int sampleRate, const std::string& sampleFmt) { STrace << "Opening microphone: " - << "device=" << device << ", " - << "channels=" << channels << ", " - << "sampleRate=" << sampleRate << ", " - << "sampleFmt=" << sampleFmt << endl; + << "device=" << device << ", " + << "channels=" << channels << ", " + << "sampleRate=" << sampleRate << ", " + << "sampleFmt=" << sampleFmt << endl; DeviceManager devman; auto iformat = devman.findAudioInputFormat(); @@ -70,7 +70,7 @@ void AudioCapture::openAudio(const std::string& device, int channels, int sample throw std::runtime_error("Couldn't find microphone input format."); AVDictionary* iparams = nullptr; - AVDictionaryCleanup cleanup{ &iparams }; + AVDictionaryCleanup cleanup{&iparams}; // Set custom parameters for devices. // NOTE: This doesn't work for DirectShow diff --git a/src/av/src/audiocontext.cpp b/src/av/src/audiocontext.cpp index 0af8d24f7..853a34a13 100644 --- a/src/av/src/audiocontext.cpp +++ b/src/av/src/audiocontext.cpp @@ -30,7 +30,6 @@ AudioContext::AudioContext() : stream(nullptr) , codec(nullptr) , frame(nullptr) - , resampler(nullptr) , outputFrameSize(0) , time(0) , pts(AV_NOPTS_VALUE) @@ -40,7 +39,7 @@ AudioContext::AudioContext() } -AudioContext::~AudioContext() +AudioContext::~AudioContext() noexcept { close(); uninitializeFFmpeg(); @@ -53,13 +52,8 @@ void AudioContext::open() << "\n\tInput: " << iparams.toString() << "\n\tOutput: " << oparams.toString() << endl; - assert(ctx); - assert(avcodec_is_open(ctx) && "avcodec_open2 must be called"); - assert(codec); - - // // Open the audio codec - // if (avcodec_open2(ctx, codec, nullptr) < 0) - // throw std::runtime_error("Cannot open the audio codec."); + if (!ctx || !avcodec_is_open(ctx) || !codec) + throw std::runtime_error("Audio codec not open"); // Create the resampler if resampling is required if (iparams.channels != oparams.channels || @@ -77,81 +71,26 @@ void AudioContext::close() frame = nullptr; } if (ctx) { - avcodec_close(ctx); + avcodec_free_context(&ctx); ctx = nullptr; } if (stream) { // The stream pointer is managed by the AVFormatContext stream = nullptr; } - if (resampler) { - delete resampler; - resampler = nullptr; - } + resampler.reset(); time = 0; pts = AV_NOPTS_VALUE; seconds = 0; - // error = ""; } -// double AudioContext::ptsSeconds() -// { -// double val = 0.0; -// -// // Local PTS value represented as decimal seconds -// // if (opacket->dts != AV_NOPTS_VALUE) { -// // *pts = (double)opacket->pts; -// // *pts *= av_q2d(stream->time_base); -// // } -// -// // Local PTS value represented as decimal seconds -// if (stream && pts > 0 && pts != AV_NOPTS_VALUE) { -// val = (double)pts; -// val *= av_q2d(stream->time_base); -// } -// -// return val; -// } - - bool AudioContext::recreateResampler() { - // if (resampler) - // throw std::runtime_error("Conversion context already exists."); - - // NOTE: the input output `channels`, `sampleRate`, and `sampleFmt` - // parameters work - // slightly differently for encoders and decoders. - // For encoders `iparams` is the picture format from the application and - // `oparams` is the picture format passed into the encoder. - // For decoders `iparams` is the picture format from the decoder and - // `oparams` is the picture format passed into the application. - - // // Check if resampler is required - // if (iparams.channels == oparams.channels && - // iparams.sampleRate == oparams.sampleRate && - // iparams.sampleFmt == oparams.sampleFmt) { - // return false; - // } - // - // // Check if the resampler context needs to be recreated - // if (resampler && ( - // resampler->iparams.channels == iparams.channels && - // resampler->iparams.sampleRate == iparams.sampleRate && - // resampler->iparams.sampleFmt == iparams.sampleFmt) && ( - // resampler->oparams.channels == oparams.channels && - // resampler->oparams.sampleRate == oparams.sampleRate && - // resampler->oparams.sampleFmt == oparams.sampleFmt)) { - // return false; - // } - // Recreate the resampler context - LDebug("Recreating audio resampler context") - if (resampler) - delete resampler; - resampler = new AudioResampler(); + LDebug("Recreating audio resampler context"); + resampler = std::make_unique(); resampler->iparams = iparams; resampler->oparams = oparams; resampler->open(); @@ -169,13 +108,17 @@ void initAudioCodecFromContext(const AVCodecContext* ctx, AudioCodec& params) params.enabled = true; params.encoder = avcodec_get_name(ctx->codec_id); params.sampleFmt = av_get_sample_fmt_name(ctx->sample_fmt); +#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100) + params.channels = ctx->ch_layout.nb_channels; +#else params.channels = ctx->channels; +#endif params.sampleRate = ctx->sample_rate; params.bitRate = ctx->bit_rate; } -bool isSampleFormatSupported(AVCodec* codec, enum AVSampleFormat sampleFormat) +bool isSampleFormatSupported(const AVCodec* codec, enum AVSampleFormat sampleFormat) { const enum AVSampleFormat* p = codec->sample_fmts; while (*p != AV_SAMPLE_FMT_NONE) { @@ -200,7 +143,7 @@ bool formatIsPlanar(const std::string& pixfmt) } -AVSampleFormat selectSampleFormat(AVCodec* codec, av::AudioCodec& params) +AVSampleFormat selectSampleFormat(const AVCodec* codec, av::AudioCodec& params) { enum AVSampleFormat compatible = AV_SAMPLE_FMT_NONE; enum AVSampleFormat requested = av_get_sample_fmt(params.sampleFmt.c_str()); diff --git a/src/av/src/audiodecoder.cpp b/src/av/src/audiodecoder.cpp index b468722f2..20e1679fa 100644 --- a/src/av/src/audiodecoder.cpp +++ b/src/av/src/audiodecoder.cpp @@ -14,7 +14,6 @@ #ifdef HAVE_FFMPEG -#include "scy/av/audioresampler.h" #include "scy/av/ffmpeg.h" #include "scy/logger.h" @@ -32,7 +31,7 @@ AudioDecoder::AudioDecoder(AVStream* stream) } -AudioDecoder::~AudioDecoder() +AudioDecoder::~AudioDecoder() noexcept { close(); } @@ -40,20 +39,27 @@ AudioDecoder::~AudioDecoder() void AudioDecoder::create() { - assert(stream); - LTrace("Create: ", stream->index) - - ctx = stream->codec; + if (!stream) + throw std::runtime_error("AudioDecoder: stream is null"); + LTrace("Create: ", stream->index); - codec = avcodec_find_decoder(ctx->codec_id); + codec = avcodec_find_decoder(stream->codecpar->codec_id); if (!codec) throw std::runtime_error("Cannot find audio decoder."); + ctx = avcodec_alloc_context3(codec); + if (!ctx) + throw std::runtime_error("Cannot allocate audio decoder context."); + + int ret = avcodec_parameters_to_context(ctx, stream->codecpar); + if (ret < 0) + throw std::runtime_error("Cannot copy audio codec parameters: " + averror(ret)); + frame = av_frame_alloc(); if (!frame) throw std::runtime_error("Cannot allocate input frame."); - int ret = avcodec_open2(ctx, codec, nullptr); + ret = avcodec_open2(ctx, codec, nullptr); if (ret < 0) throw std::runtime_error("Cannot open the audio codec: " + averror(ret)); @@ -63,9 +69,6 @@ void AudioDecoder::create() // created on the next call to open() to output the desired format. initAudioCodecFromContext(ctx, iparams); initAudioCodecFromContext(ctx, oparams); - - // Default to s16 interleaved output. - // oparams.sampleFmt = "s16"; } @@ -77,177 +80,96 @@ void AudioDecoder::close() bool emitPacket(AudioDecoder* dec) { - //auto sampleFmt = av_get_sample_fmt(dec->oparams.sampleFmt.c_str()); - //assert(av_sample_fmt_is_planar(sampleFmt) == 0 && "planar formats not supported"); - // Set the decoder time in microseconds - // This value represents the number of microseconds - // that have elapsed since the brginning of the stream. - dec->time = dec->frame->pkt_pts > 0 ? static_cast(dec->frame->pkt_pts * - av_q2d(dec->stream->time_base) * AV_TIME_BASE) : 0; + int64_t pts = dec->frame->pts; + dec->time = pts > 0 ? static_cast(pts * + av_q2d(dec->stream->time_base) * AV_TIME_BASE) + : 0; // Set the decoder pts in stream time base - dec->pts = dec->frame->pkt_pts; + dec->pts = pts; // Set the decoder seconds since stream start - // http://stackoverflow.com/questions/6731706/syncing-decoded-video-using-ffmpeg - dec->seconds = (dec->frame->pkt_dts - dec->stream->start_time) * av_q2d(dec->stream->time_base); + dec->seconds = (pts - dec->stream->start_time) * av_q2d(dec->stream->time_base); if (dec->resampler) { if (!dec->resampler->resample((uint8_t**)dec->frame->extended_data, dec->frame->nb_samples)) { - LDebug("Samples buffered by resampler") + LDebug("Samples buffered by resampler"); return false; } - // AudioPacket audio(dec->resampler->outSamples[0], - // dec->resampler->outBufferSize, - // dec->resampler->outNumSamples, dec->time); - // dec->outputFrameSize = dec->resampler->outNumSamples; - // dec->emitter.emit(audio); - // opacket.data = dec->resampler->outSamples[0]; - // opacket.size = dec->resampler->outBufferSize; - PlanarAudioPacket audio(dec->resampler->outSamples, - dec->oparams.channels, dec->resampler->outNumSamples, - dec->oparams.sampleFmt, dec->time); + dec->oparams.channels, dec->resampler->outNumSamples, + dec->oparams.sampleFmt, dec->time); dec->outputFrameSize = dec->resampler->outNumSamples; dec->emitter.emit(audio); - assert(audio.size() == dec->resampler->outBufferSize); - } - else { - // int size = av_samples_get_buffer_size(nullptr, dec->ctx->channels, - // dec->frame->nb_samples, - // dec->ctx->sample_fmt, 0); - // AudioPacket audio(dec->frame->data[0], size, dec->outputFrameSize, dec->time); - // dec->outputFrameSize = dec->frame->nb_samples; - // dec->emitter.emit(audio); - + } else { PlanarAudioPacket audio(dec->frame->data, - dec->oparams.channels, dec->frame->nb_samples, - dec->oparams.sampleFmt, dec->time); + dec->oparams.channels, dec->frame->nb_samples, + dec->oparams.sampleFmt, dec->time); dec->outputFrameSize = dec->frame->nb_samples; dec->emitter.emit(audio); } - // opacket.pts = dec->frame->pkt_pts; // Decoder PTS values may be out of sequence - // opacket.dts = dec->frame->pkt_dts; - - // assert(opacket.data); - // assert(opacket.size); - // assert(opacket.pts >= 0); - // assert(opacket.dts >= 0); - return true; } -// bool AudioDecoder::decode(uint8_t* data, int size) -// { -// AVPacket ipacket; -// av_init_packet(&ipacket); -// ipacket.data = data; -// ipacket.size = size; -// if (stream) -// ipacket.stream_index = stream->index; -// return decode(ipacket); -// } - - bool AudioDecoder::decode(AVPacket& ipacket) { - assert(ctx); - assert(codec); - assert(frame); - assert(!stream || ipacket.stream_index == stream->index); - - // Convert input packet to codec time base - // ipacket.dts = av_rescale_q_rnd(ipacket.dts, - // stream->time_base, - // stream->codec->time_base, - // AVRounding(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX)); - // ipacket.pts = av_rescale_q_rnd(ipacket.pts, - // stream->time_base, - // stream->codec->time_base, - // AVRounding(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX)); - - // av_init_packet(&opacket); - // opacket.data = nullptr; - // opacket.size = 0; - - // av_frame_unref(frame); - // int frameDecoded = 0; - // int bytesDecoded = 0; - // int bytesRemaining = ipacket.size; - - int ret, frameDecoded = 0; - while (ipacket.size > 0) { - ret = avcodec_decode_audio4(ctx, frame, &frameDecoded, &ipacket); + if (!ctx || !codec || !frame) + throw std::runtime_error("AudioDecoder not initialized"); + if (stream && ipacket.stream_index != stream->index) + return false; + + // Send packet to the decoder + int ret = avcodec_send_packet(ctx, &ipacket); + if (ret < 0) { + error = "Audio decoder error: " + averror(ret); + LError(error); + throw std::runtime_error(error); + } + + bool decoded = false; + while (ret >= 0) { + ret = avcodec_receive_frame(ctx, frame); + if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { + break; + } if (ret < 0) { error = "Audio decoder error: " + averror(ret); - LError(error) + LError(error); throw std::runtime_error(error); } - if (frameDecoded) { - // assert(bytesDecoded == ipacket.size); - - // STrace << "Decoded frame:" - // << "\n\tFrame Size: " << opacket.size - // << "\n\tFrame PTS: " << opacket.pts - // << "\n\tInput Frame PTS: " << ipacket.pts - // << "\n\tInput Bytes: " << ipacket.size - // << "\n\tBytes Decoded: " << bytesDecoded - // << "\n\tFrame PTS: " << frame->pts - // << "\n\tDecoder PTS: " << pts - // << endl; - - // fps.tick(); - emitPacket(this); - } - - ipacket.size -= ret; - ipacket.data += ret; + // fps.tick(); + emitPacket(this); + decoded = true; } - assert(ipacket.size == 0); - return !!frameDecoded; + + return decoded; } void AudioDecoder::flush() { - AVPacket ipacket; - av_init_packet(&ipacket); - ipacket.data = nullptr; - ipacket.size = 0; - - // av_init_packet(&opacket); - // opacket.data = nullptr; - // opacket.size = 0; - - int frameDecoded = 0; - av_frame_unref(frame); - avcodec_decode_audio4(ctx, frame, &frameDecoded, &ipacket); - - if (frameDecoded) { - LTrace("Flushed audio frame: ", frame->pts) - assert(0); - emitPacket(this); + // Send nullptr packet to flush the decoder + avcodec_send_packet(ctx, nullptr); + + int ret = 0; + while (ret >= 0) { + ret = avcodec_receive_frame(ctx, frame); + if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { + break; + } + if (ret >= 0) { + LTrace("Flushed audio frame: ", frame->pts); + emitPacket(this); + } } } -// void AudioContext::process(IPacket& packet) -// { -// LTrace("Process") -// -// auto apacket = dynamic_cast(&packet); -// if (!apacket) -// throw std::runtime_error("Unknown audio packet type."); -// -// decode(apacket->data(), apacket->size()); -// } - - } // namespace av } // namespace scy diff --git a/src/av/src/audioencoder.cpp b/src/av/src/audioencoder.cpp index 2df400220..e3d177b7e 100644 --- a/src/av/src/audioencoder.cpp +++ b/src/av/src/audioencoder.cpp @@ -28,13 +28,13 @@ namespace av { AudioEncoder::AudioEncoder(AVFormatContext* format) : format(format) { - LTrace("Create") + LTrace("Create"); } -AudioEncoder::~AudioEncoder() +AudioEncoder::~AudioEncoder() noexcept { - LTrace("Destroy") + LTrace("Destroy"); close(); } @@ -44,7 +44,6 @@ AudioEncoder::~AudioEncoder() static AVFrame* initOutputFrame(AVCodecContext* ctx) { AVFrame* frame; - int error; // Create a new frame to store the audio samples. if (!(frame = av_frame_alloc())) { @@ -52,17 +51,17 @@ static AVFrame* initOutputFrame(AVCodecContext* ctx) } // Set the frame's parameters, especially its size and format. - // av_frame_get_buffer needs this to allocate memory for the - // audio samples of the frame. - // Default channel layouts based on the number of channels - // are assumed for simplicity. frame->nb_samples = ctx->frame_size; - frame->channel_layout = ctx->channel_layout; frame->format = ctx->sample_fmt; frame->sample_rate = ctx->sample_rate; +#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100) + av_channel_layout_copy(&frame->ch_layout, &ctx->ch_layout); +#else + frame->channel_layout = ctx->channel_layout; +#endif - // Allocate the samples of the created frame. This call will make - // sure that the audio frame can hold as many samples as specified. + // Allocate the samples of the created frame. + int error; if ((error = av_frame_get_buffer(frame, 0)) < 0) { av_frame_free(&frame); throw std::runtime_error("Could allocate output frame samples: " + averror(error)); @@ -74,7 +73,7 @@ static AVFrame* initOutputFrame(AVCodecContext* ctx) void AudioEncoder::create() { - LTrace("Create") + LTrace("Create"); int err; // Find the audio encoder @@ -83,31 +82,19 @@ void AudioEncoder::create() throw std::runtime_error("Cannot find an audio encoder for: " + oparams.encoder); } - // Allocate stream and AVCodecContext from the AVFormatContext if available + // Allocate stream from the AVFormatContext if available if (format) { - format->oformat->audio_codec = codec->id; - // Create a new audio stream in the output file container. if (!(stream = avformat_new_stream(format, codec))) { throw std::runtime_error("Cannot create the audio stream: Out of memory"); } - - ctx = stream->codec; - } - - // Otherwise allocate the standalone AVCodecContext - else { - ctx = avcodec_alloc_context3(codec); - if (!ctx) - throw std::runtime_error("Cannot allocate encoder context."); } - // assert(oparams.bitRate); - // assert(oparams.sampleRate); - // assert(oparams.channels); - // assert(!oparams.sampleFmt.empty()); + // Allocate the AVCodecContext + ctx = avcodec_alloc_context3(codec); + if (!ctx) + throw std::runtime_error("Cannot allocate encoder context."); - // int bitRate = oparams.bitRate ? oparams.bitRate : DEFAULT_AUDIO_BIT_RATE if (!oparams.bitRate) oparams.bitRate = DEFAULT_AUDIO_BIT_RATE; if (!oparams.sampleRate) @@ -118,109 +105,84 @@ void AudioEncoder::create() oparams.sampleFmt = DEFAULT_AUDIO_SAMPLE_FMT; // Now we'll setup the parameters of AVCodecContext - avcodec_get_context_defaults3(ctx, codec); ctx->bit_rate = oparams.bitRate; ctx->sample_fmt = selectSampleFormat(codec, oparams); ctx->sample_rate = oparams.sampleRate; +#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100) + av_channel_layout_default(&ctx->ch_layout, oparams.channels); +#else ctx->channels = oparams.channels; ctx->channel_layout = av_get_default_channel_layout(oparams.channels); +#endif - // // Set the sample rate for the container. - // ctx->time_base.den = oparams.sampleRate; - // ctx->time_base.num = 1; - - ctx->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL; + ctx->strict_std_compliance = oparams.compliance; // Some container formats (like MP4) require global headers to be present - // Mark the encoder so that it behaves accordingly. - if (format && format->oformat->flags & AVFMT_GLOBALHEADER) - ctx->flags |= CODEC_FLAG_GLOBAL_HEADER; + if (format && format->oformat->flags & AVFMT_GLOBALHEADER) { + ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; + } // Open the encoder for the audio stream to use it later. if ((err = avcodec_open2(ctx, codec, nullptr)) < 0) { throw std::runtime_error("Cannot open the audio codec: " + averror(err)); } + // Copy codec parameters to the stream + if (stream) { + int ret = avcodec_parameters_from_context(stream->codecpar, ctx); + if (ret < 0) + throw std::runtime_error("Cannot copy audio codec parameters to stream: " + averror(ret)); + stream->time_base = ctx->time_base; + } + // Use the encoder's desired frame size for processing. outputFrameSize = ctx->frame_size; - assert(outputFrameSize); + if (!outputFrameSize) + throw std::runtime_error("Audio codec returned zero frame size"); // Create the encode frame frame = initOutputFrame(ctx); // Create the FIFO buffer based on the specified output sample format. - // NOTE: We read from a FIFO buffer as many codecs require a FULL - // `ctx->frame_size` samples for encoding. fifo.alloc(oparams.sampleFmt, oparams.channels, outputFrameSize); // Update parameters that may have changed initAudioCodecFromContext(ctx, oparams); - - // // Create the resampler if resampling if required - // if (iparams.channels != oparams.channels || - // iparams.sampleRate != oparams.sampleRate || - // iparams.sampleFmt != oparams.sampleFmt) { - // recreateResampler(); - // } } -// void AudioEncoder::open() -// { -// LTrace("Create") -// } - - void AudioEncoder::close() { - LTrace("Closing") + LTrace("Closing"); AudioContext::close(); - - if (resampler) { - delete resampler; - resampler = nullptr; - } } -void emitPacket(AudioEncoder* enc, AVPacket& opacket) +void emitPacket(AudioEncoder* enc, AVPacket* opacket) { - // auto sampleFmt = av_get_sample_fmt(enc->oparams.sampleFmt.c_str()); - // assert(av_sample_fmt_is_planar(sampleFmt) == 0 && "planar formats not supported"); - if (enc->stream) { // Set the encoder time in microseconds - // This value represents the number of microseconds - // that have elapsed since the brginning of the stream. - enc->time = opacket.pts > 0 ? static_cast( - opacket.pts * av_q2d(enc->stream->time_base) * AV_TIME_BASE) : 0; - - // Set the encoder seconds since stream start - // enc->seconds = enc->time / time::kNumMicrosecsPerSec; - // enc->seconds = (opacket.pts - enc->stream->start_time) * av_q2d(enc->stream->time_base); - enc->seconds = opacket.pts * av_q2d(enc->stream->time_base); + enc->time = opacket->pts > 0 ? static_cast( + opacket->pts * av_q2d(enc->stream->time_base) * AV_TIME_BASE) + : 0; + + enc->seconds = opacket->pts * av_q2d(enc->stream->time_base); } // Set the encoder pts in stream time base - enc->pts = opacket.pts; - - assert(opacket.data); - assert(opacket.size); - // assert(opacket.pts >= 0); - // assert(opacket.dts >= 0); + enc->pts = opacket->pts; - AudioPacket audio(opacket.data, opacket.size, enc->outputFrameSize, enc->time); - audio.source = &opacket; - audio.opaque = enc; + if (!opacket->data || !opacket->size) + return; + AudioPacket audio(opacket->data, opacket->size, enc->outputFrameSize, enc->time); + audio.avpacket = opacket; enc->emitter.emit(audio); } int flushBuffer(AudioEncoder* enc) { - // LTrace("Flush") - // Read frames from the FIFO while available int num = 0; while (enc->fifo.read((void**)enc->frame->data, enc->frame->nb_samples) && @@ -239,19 +201,13 @@ int flushBuffer(AudioEncoder* enc) bool AudioEncoder::encode(uint8_t* samples, const int numSamples, const int64_t pts) { - // LTrace("Encoding audio packet: ", numSamples) - // Resample input data or add it to the buffer directly if (resampler) { if (!resampler->resample((uint8_t**)&samples, numSamples)) { - LTrace("Samples buffered by resampler") + LTrace("Samples buffered by resampler"); return false; } - // STrace << "Resampled audio packet: " - // << numSamples << " <=> " - // << resampler->outNumSamples << endl; - // Add the converted input samples to the FIFO buffer. fifo.write((void**)resampler->outSamples, resampler->outNumSamples); } else { @@ -270,22 +226,21 @@ bool AudioEncoder::encode(uint8_t* samples, const int numSamples, const int64_t bool AudioEncoder::encode(uint8_t* samples[4], const int numSamples, const int64_t pts) { - LTrace("Encoding audio packet: ", numSamples) + LTrace("Encoding audio packet: ", numSamples); // Resample input data or add it to the buffer directly if (resampler) { if (!resampler->resample((uint8_t**)samples, numSamples)) { - LTrace("Samples buffered by resampler") + LTrace("Samples buffered by resampler"); return false; } STrace << "Resampled audio packet: " << numSamples << " <=> " - << resampler->outNumSamples << endl; + << resampler->outNumSamples << endl; // Add the converted input samples to the FIFO buffer. fifo.write((void**)resampler->outSamples, resampler->outNumSamples); - } - else { + } else { // Add the input samples to the FIFO buffer. fifo.write((void**)samples, numSamples); } @@ -301,65 +256,69 @@ bool AudioEncoder::encode(uint8_t* samples[4], const int numSamples, const int64 bool AudioEncoder::encode(AVFrame* iframe) { - LTrace("Encoding audio frame") - - int frameEncoded, ret; - - // This method only receives input format sample frames - assert(!iframe || iframe->format == ctx->sample_fmt); - assert(!iframe || iframe->nb_samples == ctx->frame_size); + LTrace("Encoding audio frame"); - // Set the packet data and size so that it is recognized as being empty. - AVPacket opacket; - av_init_packet(&opacket); - opacket.data = nullptr; - opacket.size = 0; + // Validate input frame format matches encoder expectations + if (iframe && iframe->format != ctx->sample_fmt) + throw std::runtime_error("Audio frame sample format mismatch"); + if (iframe && iframe->nb_samples != ctx->frame_size) + throw std::runtime_error("Audio frame size mismatch"); - // Encode the audio frame and store it in the temporary packet. - // The output audio stream encoder is used to do this. - if ((ret = avcodec_encode_audio2(ctx, &opacket, iframe, &frameEncoded)) < 0) { + // Send the frame to the encoder + int ret = avcodec_send_frame(ctx, iframe); + if (ret < 0) { throw std::runtime_error("Cannot encode audio frame: " + averror(ret)); } - if (frameEncoded) { + bool frameEncoded = false; + AVPacket* opacket = av_packet_alloc(); + if (!opacket) + throw std::runtime_error("Cannot allocate output packet"); + + // Receive all available encoded packets + while (ret >= 0) { + ret = avcodec_receive_packet(ctx, opacket); + if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { + break; + } + if (ret < 0) { + av_packet_free(&opacket); + throw std::runtime_error("Cannot encode audio frame: " + averror(ret)); + } + // fps.tick(); - opacket.flags |= AV_PKT_FLAG_KEY; + opacket->flags |= AV_PKT_FLAG_KEY; if (stream) { - opacket.stream_index = stream->index; - // if (opacket.pts != AV_NOPTS_VALUE) - // opacket.pts = av_rescale_q(opacket.pts, ctx->time_base, stream->time_base); - // if (opacket.dts != AV_NOPTS_VALUE) - // opacket.dts = av_rescale_q(opacket.dts, ctx->time_base, stream->time_base); - // if (opacket.duration > 0) - // opacket.duration = (int)av_rescale_q(opacket.duration, ctx->time_base, stream->time_base); + opacket->stream_index = stream->index; } STrace << "Audio frame encoded:\n" << "\n\tFrame PTS: " << (iframe ? iframe->pts : 0) - << "\n\tPTS: " << opacket.pts << "\n\tDTS: " << opacket.dts - << "\n\tDuration: " << opacket.duration << endl; + << "\n\tPTS: " << opacket->pts << "\n\tDTS: " << opacket->dts + << "\n\tDuration: " << opacket->duration << endl; emitPacket(this, opacket); - } - else { - LTrace("No frame encoded") + frameEncoded = true; + av_packet_unref(opacket); } - av_packet_unref(&opacket); + if (!frameEncoded) { + LTrace("No frame encoded"); + } - return frameEncoded > 0; + av_packet_free(&opacket); + return frameEncoded; } void AudioEncoder::flush() { - LTrace("Flush") + LTrace("Flush"); // Flush any remaining frames in the FIFO flushBuffer(this); - do { - // :) - } while (encode(nullptr)); + // Send nullptr frame to signal end of stream + encode(nullptr); } diff --git a/src/av/src/audioresampler.cpp b/src/av/src/audioresampler.cpp index 178fb5008..6b11ba756 100644 --- a/src/av/src/audioresampler.cpp +++ b/src/av/src/audioresampler.cpp @@ -39,7 +39,7 @@ AudioResampler::AudioResampler(const AudioCodec& iparams, } -AudioResampler::~AudioResampler() +AudioResampler::~AudioResampler() noexcept { close(); } @@ -50,42 +50,50 @@ void AudioResampler::open() if (ctx) throw std::runtime_error("Resample context already initialized"); +#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100) + AVChannelLayout inChLayout = {}; + AVChannelLayout outChLayout = {}; + av_channel_layout_default(&inChLayout, iparams.channels); + av_channel_layout_default(&outChLayout, oparams.channels); +#else int64_t inChLayout = av_get_default_channel_layout(iparams.channels); int64_t outChLayout = av_get_default_channel_layout(oparams.channels); - - char inChBuf[128], outChBuf[128]; - av_get_channel_layout_string(inChBuf, sizeof(inChBuf), -1, inChLayout); - av_get_channel_layout_string(outChBuf, sizeof(outChBuf), -1, outChLayout); +#endif inSampleFmt = av_get_sample_fmt(iparams.sampleFmt.c_str()); outSampleFmt = av_get_sample_fmt(oparams.sampleFmt.c_str()); STrace << "Create audio resampler:\n" - << "\n\tIn Nb Channels: " << iparams.channels - << "\n\tIn Channel Layout: " << inChBuf - << "\n\tIn Sample Rate: " << iparams.sampleRate - << "\n\tIn Sample Fmt: " << iparams.sampleFmt - << "\n\tOut Nb Channels: " << oparams.channels - << "\n\tOut Channel Layout: " << outChBuf - << "\n\tOut Sample Rate: " << oparams.sampleRate - << "\n\tOut Lample Fmt: " << oparams.sampleFmt << std::endl; - - assert(iparams.channels); - assert(oparams.channels); - assert(iparams.sampleRate); - assert(oparams.sampleRate); - assert(!iparams.sampleFmt.empty()); - assert(!oparams.sampleFmt.empty()); - assert(inChLayout); - assert(outChLayout); - assert(inSampleFmt != AV_SAMPLE_FMT_NONE); - assert(outSampleFmt != AV_SAMPLE_FMT_NONE); - -#ifdef HAVE_FFMPEG_SWRESAMPLE - ctx = swr_alloc(); + << "\n\tIn Nb Channels: " << iparams.channels + << "\n\tIn Sample Rate: " << iparams.sampleRate + << "\n\tIn Sample Fmt: " << iparams.sampleFmt + << "\n\tOut Nb Channels: " << oparams.channels + << "\n\tOut Sample Rate: " << oparams.sampleRate + << "\n\tOut Sample Fmt: " << oparams.sampleFmt << std::endl; + + if (!iparams.channels || !oparams.channels) + throw std::runtime_error("Input and output channel count must be set"); + if (!iparams.sampleRate || !oparams.sampleRate) + throw std::runtime_error("Input and output sample rate must be set"); + if (iparams.sampleFmt.empty() || oparams.sampleFmt.empty()) + throw std::runtime_error("Input and output sample format must be set"); + if (inSampleFmt == AV_SAMPLE_FMT_NONE || outSampleFmt == AV_SAMPLE_FMT_NONE) + throw std::runtime_error("Invalid sample format"); + + int ret; + +#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100) + // Use the new channel layout API (FFmpeg 5.1+) + ret = swr_alloc_set_opts2(&ctx, + &outChLayout, outSampleFmt, oparams.sampleRate, + &inChLayout, inSampleFmt, iparams.sampleRate, + 0, nullptr); + if (ret < 0 || !ctx) { + throw std::runtime_error("Cannot allocate resample context: " + averror(ret)); + } + ret = swr_init(ctx); #else - ctx = avresample_alloc_context(); -#endif + ctx = swr_alloc(); if (!ctx) { throw std::runtime_error("Cannot allocate resample context"); } @@ -97,31 +105,23 @@ void AudioResampler::open() av_opt_set_sample_fmt(ctx, "in_sample_fmt", inSampleFmt, 0); av_opt_set_sample_fmt(ctx, "out_sample_fmt", outSampleFmt, 0); -// Open the resampler context. -#ifdef HAVE_FFMPEG_SWRESAMPLE - int ret = swr_init(ctx); -#else - int ret = avresample_open(ctx); + ret = swr_init(ctx); #endif if (ret < 0) { close(); throw std::runtime_error("Cannot initialize resample context: " + averror(ret)); } - LTrace("Create: OK") + LTrace("Create: OK"); } void AudioResampler::close() { - LTrace("Closing") + LTrace("Closing"); if (ctx) { -#ifdef HAVE_FFMPEG_SWRESAMPLE swr_free(&ctx); -#else - avresample_free(&ctx); -#endif ctx = nullptr; } @@ -147,13 +147,10 @@ int AudioResampler::resample(uint8_t** inSamples, int inNumSamples) // Compute the output number of samples // https://github.com/FFmpeg/FFmpeg/blob/master/doc/examples/resampling_audio.c requiredNumSamples = av_rescale_rnd( -#ifdef HAVE_FFMPEG_SWRESAMPLE swr_get_delay(ctx, (int64_t)iparams.sampleRate) + -#else - avresample_get_delay(ctx) + -#endif - (int64_t)inNumSamples, (int64_t)oparams.sampleRate, - (int64_t)iparams.sampleRate, AV_ROUND_UP); + (int64_t)inNumSamples, + (int64_t)oparams.sampleRate, + (int64_t)iparams.sampleRate, AV_ROUND_UP); // Resize the output buffer if required if (requiredNumSamples > maxNumSamples) { @@ -164,21 +161,16 @@ int AudioResampler::resample(uint8_t** inSamples, int inNumSamples) throw std::runtime_error("Cannot allocate buffer for converted output samples: " + averror(ret)); } - LTrace("Resizing resampler buffer: ", outBufferSize) + LTrace("Resizing resampler buffer: ", outBufferSize); maxNumSamples = requiredNumSamples; } - assert(requiredNumSamples); - assert(maxNumSamples); + if (!requiredNumSamples || !maxNumSamples) + throw std::runtime_error("Invalid resampler buffer state"); // Convert the samples using the resampler. -#ifdef HAVE_FFMPEG_SWRESAMPLE ret = swr_convert(ctx, outSamples, maxNumSamples, - (const uint8_t**)/*&*/inSamples, inNumSamples); -#else - ret = avresample_convert(ctx, outSamples, 0, maxNumSamples, - (uint8_t**)/*&*/inSamples, 0, inNumSamples); -#endif + const_cast(inSamples), inNumSamples); if (ret < 0) { close(); throw std::runtime_error("Cannot convert input samples: " + averror(ret)); @@ -212,82 +204,6 @@ int AudioResampler::resample(uint8_t** inSamples, int inNumSamples) } -#if 0 -int AudioResampler::resample(const uint8_t* inSamples, int inNumSamples) -{ - if (!ctx) - throw std::runtime_error("Conversion context must be initialized."); - - int error, outLinesize, requiredNumSamples; - - // Compute output number of samples - // https://github.com/FFmpeg/FFmpeg/blob/master/doc/examples/resampling_audio.c - requiredNumSamples = av_rescale_rnd( -#ifdef HAVE_FFMPEG_SWRESAMPLE - swr_get_delay(ctx, (int64_t)iparams.sampleRate) + -#else - avresample_get_delay(ctx) + -#endif - (int64_t)inNumSamples, - (int64_t)oparams.sampleRate, (int64_t)iparams.sampleRate, AV_ROUND_UP); - - requiredNumSamples = 440; - - // Resize the output buffer if required - if (requiredNumSamples > maxNumSamples) { - error = av_samples_alloc_array_and_samples(&outSamples, &outLinesize, - oparams.channels, - requiredNumSamples, - av_get_sample_fmt(oparams.sampleFmt.c_str()), 0); - if (error < 0) { - throw std::runtime_error("Cannot allocate buffer for converted output samples: " + averror(error)); - } - - maxNumSamples = requiredNumSamples; - } - - assert(requiredNumSamples); - assert(maxNumSamples); - - // Convert the samples using the resampler. -#ifdef HAVE_FFMPEG_SWRESAMPLE - outNumSamples = swr_convert(ctx, outSamples, maxNumSamples, (const uint8_t**)&inSamples, inNumSamples); -#else - outNumSamples = avresample_convert(ctx, outSamples, 0, maxNumSamples, (uint8_t**)&inSamples, 0, inNumSamples); -#endif - if (outNumSamples < 0) { - close(); - throw std::runtime_error("Cannot convert input samples: " + averror(outNumSamples)); - } - - // Set the output buffer size in bytes. - // This may be useful for implementations that need to know the size of - // converted output samples in bytes, such as for writing to files. - outBufferSize = av_samples_get_buffer_size(&outLinesize, - oparams.channels, - outNumSamples, - av_get_sample_fmt(oparams.sampleFmt.c_str()), 1); - assert(outBufferSize > 0); - - STrace << "Resampled audio frame:" - << "\n\tIn Nb Samples: " << inNumSamples - << "\n\tIn Channels: " << iparams.channels - << "\n\tIn Sample Rate: " << iparams.sampleRate - << "\n\tIn Sample Fmt: " << iparams.sampleFmt - << "\n\tOut Nb Samples: " << outNumSamples - << "\n\tOut Max Nb Samples: " << maxNumSamples - << "\n\tOut Line Size: " << outLinesize - << "\n\tOut Buffer Size: " << outBufferSize - << "\n\tOut Channels: " << oparams.channels - << "\n\tOut Sample Rate: " << oparams.sampleRate - << "\n\tOut Sample Fmt: " << oparams.sampleFmt - << endl; - - return outNumSamples; -} -#endif - - } // namespace av } // namespace scy diff --git a/src/av/src/codec.cpp b/src/av/src/codec.cpp index 59ace531e..b0ea59272 100644 --- a/src/av/src/codec.cpp +++ b/src/av/src/codec.cpp @@ -31,6 +31,7 @@ Codec::Codec() , sampleRate(0) , bitRate(0) , quality(0) + , compliance(-2) // FF_COMPLIANCE_EXPERIMENTAL , enabled(false) { } @@ -40,6 +41,7 @@ Codec::Codec(const std::string& name, int sampleRate, int bitRate, bool enabled) , sampleRate(sampleRate) , bitRate(bitRate) , quality(0) + , compliance(-2) // FF_COMPLIANCE_EXPERIMENTAL , enabled(enabled) { } @@ -51,6 +53,7 @@ Codec::Codec(const std::string& name, const std::string& encoder, , encoder(encoder) , sampleRate(sampleRate) , bitRate(bitRate) + , compliance(-2) // FF_COMPLIANCE_EXPERIMENTAL , enabled(enabled) { } @@ -82,7 +85,7 @@ Codec::Codec(const std::string& name, const std::string& encoder, // } -Codec::~Codec() +Codec::~Codec() noexcept { } @@ -118,7 +121,7 @@ AudioCodec::AudioCodec() } -AudioCodec::AudioCodec(int channels, int sampleRate, +AudioCodec::AudioCodec(int channels, int sampleRate, const std::string& sampleFmt, int bitRate) : Codec("Unknown", sampleRate, bitRate, true) , channels(channels) @@ -161,7 +164,7 @@ AudioCodec::AudioCodec(const std::string& name, const std::string& encoder, // } -AudioCodec::~AudioCodec() +AudioCodec::~AudioCodec() noexcept { } @@ -200,7 +203,7 @@ VideoCodec::VideoCodec() } -VideoCodec::VideoCodec(int width, int height, double fps, +VideoCodec::VideoCodec(int width, int height, double fps, const std::string& pixelFmt, int sampleRate, int bitRate) : Codec("Unknown", sampleRate, bitRate, true) , width(width) @@ -245,7 +248,7 @@ VideoCodec::VideoCodec(const VideoCodec& r) } -VideoCodec::~VideoCodec() +VideoCodec::~VideoCodec() noexcept { } diff --git a/src/av/src/devicemanager.cpp b/src/av/src/devicemanager.cpp index 521833931..2c434b75e 100644 --- a/src/av/src/devicemanager.cpp +++ b/src/av/src/devicemanager.cpp @@ -1,749 +1,475 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// @addtogroup av -/// @{ - - -#include "scy/av/devicemanager.h" -#include "scy/logger.h" - - -// TODO: implement all possible platform formats: -// -// input/output: alsa, decklink, fbdev, oss, pulse, sndio, v4l2 -// input: avfoundation, bktr, dshow, dv1394, gdigrab, iec61883, jack, lavfi, -// openal, vfwcap, x11grab, x11grab_xcb -// output: caca, opengl, qtkit, sdl, xv - -#if defined(SCY_WIN) -#include "scy/av/win32/directshow.h" -#define SCY_VIDEO_INPUTS \ - { \ - "dshow", "vfwcap" \ - } -#define SCY_VIDEO_OUTPUTS \ - { \ - } -#define SCY_SCREEN_INPUTS \ - { \ - "gdigrab" \ - } -#define SCY_AUDIO_INPUTS \ - { \ - "dsound" \ - } -#define SCY_AUDIO_OUTPUTS \ - { \ - "dsound" \ - } -#elif defined(SCY_APPLE) -#include "scy/av/apple/avfoundation.h" -#define SCY_VIDEO_INPUTS \ - { \ - "avfoundation", "qtkit" \ - } -#define SCY_VIDEO_OUTPUTS \ - { \ - } -#define SCY_SCREEN_INPUTS \ - { \ - "avfoundation" \ - } -#define SCY_AUDIO_INPUTS \ - { \ - "avfoundation" \ - } -#define SCY_AUDIO_OUTPUTS \ - { \ - "avfoundation" \ - } -#elif defined(SCY_LINUX) -#define SCY_VIDEO_INPUTS \ - { \ - "v4l2", "dv1394" \ - } -#define SCY_VIDEO_OUTPUTS \ - { \ - } -#define SCY_SCREEN_INPUTS \ - { \ - "x11grab" \ - } -#define SCY_AUDIO_INPUTS \ - { \ - "alsa", "jack", "pulse" \ - } -#define SCY_AUDIO_OUTPUTS \ - { \ - "alsa" \ - } -#endif - - -using std::endl; - - -namespace scy { -namespace av { - - -// -// Device -// - - -Device::Device() - : type(Unknown) - , isDefault(false) -{ -} - - -Device::Device(Type type, const std::string& id, const std::string& name, bool isDefault) - : type(type) - , id(id) - , name(name) - , isDefault(isDefault) -{ -} - - -void Device::print(std::ostream& os) -{ - os << "Device[" << type << ":" << name << ":" << id << ":" << isDefault << "]"; -} - - -// -// Helpers -// - - -namespace internal { - - -#ifdef HAVE_FFMPEG - -// Substitute for missing `av_find_output_format()` function -AVOutputFormat* findOutputFormat(const std::string& name) -{ - AVOutputFormat* oformat = av_oformat_next(nullptr); - while (oformat) { - if (name == oformat->name) { - break; - } - oformat = av_oformat_next(oformat); - } - return oformat; -} - - -AVOutputFormat* findDefaultOutputFormat(const std::vector& outputs) -{ - AVOutputFormat* oformat = nullptr; - for (auto& output : outputs) { - oformat = findOutputFormat(output.c_str()); - if (oformat) - break; - } - - assert(oformat && "no output format found"); - return oformat; -} - - -AVInputFormat* findDefaultInputFormat(const std::vector& inputs) -{ - AVInputFormat* iformat = nullptr; - for (auto& input : inputs) { - iformat = av_find_input_format(input.c_str()); - if (iformat) - break; - } - - assert(iformat && "no input format found"); - return iformat; -} - - -bool enumerateDeviceList(AVFormatContext* s, Device::Type type, - std::vector& devices) -{ -#ifndef HAVE_FFMPEG_AVDEVICE - devices.clear(); - return false; -#else - int error; - // AVDictionary *tmp = nullptr; - AVDeviceInfoList* devlist = nullptr; - - // av_dict_copy(&tmp, nullptr, 0); - // if (av_opt_set_dict2(ctx, &tmp, AV_OPT_SEARCH_CHILDREN) < 0) { - // assert(0 && "cannot set device options"); - // goto fail; - // } - - // TODO: replace with `list_devices_for_context` - error = avdevice_list_devices(s, &devlist); - if (error || !devlist) { - LWarn("Cannot list system devices: ", averror(error)) - goto fail; - } - - devices.clear(); - for (int i = 0; i < devlist->nb_devices; i++) { - auto dev = devlist->devices[i]; - devices.push_back( - av::Device(type, dev->device_name, dev->device_description)); - } - -fail: - if (devlist) - avdevice_free_list_devices(&devlist); - - return !devices.empty(); -#endif -} - - -bool getInputDeviceList(const std::vector& inputs, - Device::Type type, std::vector& devices) -{ -#ifndef HAVE_FFMPEG_AVDEVICE - SWarn << "HAVE_FFMPEG_AVDEVICE not defined, cannot list input devices" - << endl; - return false; -#else - AVFormatContextHolder ctx(avformat_alloc_context()); - // AVFormatContext* ctx = nullptr; - AVInputFormat* iformat = nullptr; - - iformat = findDefaultInputFormat(inputs); - if (!iformat) { - assert(0 && "no input formats"); - return false; - } - - // Alloc an input device context - if (!ctx) { - assert(0); - goto fail; - } - - if (!iformat->priv_class || - !AV_IS_INPUT_DEVICE(iformat->priv_class->category)) { - assert(0 && "not an input device"); - goto fail; - } - - ctx->iformat = iformat; - if (ctx->iformat->priv_data_size > 0) { - ctx->priv_data = av_mallocz(ctx->iformat->priv_data_size); - if (!ctx->priv_data) { - assert(0); - goto fail; - } - if (ctx->iformat->priv_class) { - *(const AVClass**)ctx->priv_data = ctx->iformat->priv_class; - av_opt_set_defaults(ctx->priv_data); - } - } else { - ctx->priv_data = nullptr; - } - - // // s->iformat->get_device_list - // - // assert(ctx->oformat || ctx->iformat); - // assert((ctx->oformat && ctx->oformat->get_device_list) || - // (ctx->iformat && ctx->iformat->get_device_list)); - - enumerateDeviceList(ctx.get(), type, devices); - -fail: - // avformat_free_context(ctx); - - return !devices.empty(); -#endif -} - - -bool getOutputDeviceList(const std::vector& outputs, - Device::Type type, std::vector& devices) -{ -#ifndef HAVE_FFMPEG_AVDEVICE - SWarn << "HAVE_FFMPEG_AVDEVICE not defined, cannot list output devices" - << endl; - return false; -#else - - AVFormatContextHolder ctx(avformat_alloc_context()); - //AVFormatContext* ctx = nullptr; - AVOutputFormat* oformat = nullptr; - - oformat = findDefaultOutputFormat(outputs); - if (!oformat) { - assert(0 && "no output formats"); - return false; - } - - if (!ctx) { - assert(0); - goto fail; - } - - if (!oformat->priv_class || - !AV_IS_OUTPUT_DEVICE(oformat->priv_class->category)) { - assert(0 && "not an output device"); - goto fail; - } - - ctx->oformat = oformat; - if (ctx->oformat->priv_data_size > 0) { - ctx->priv_data = av_mallocz(ctx->oformat->priv_data_size); - if (!ctx->priv_data) { - assert(0); - goto fail; - } - if (ctx->oformat->priv_class) { - *(const AVClass**)ctx->priv_data = ctx->oformat->priv_class; - av_opt_set_defaults(ctx->priv_data); - } - } else { - ctx->priv_data = nullptr; - } - - enumerateDeviceList(ctx.get(), type, devices); - -fail: - //if (ctx) - // avformat_free_context(ctx); - - return !devices.empty(); -#endif -} - -#endif // HAVE_FFMPEG - - -void printDevices(std::ostream& ost, std::vector& devs) -{ - for (size_t i = 0; i < devs.size(); ++i) { - ost << '\t'; - devs[i].print(ost); - ost << endl; - } -} - - -} // namespace internal - - -// -// Device Manager -// - - -DeviceManager::DeviceManager() - : _watcher(nullptr) -{ -#ifdef HAVE_FFMPEG - initializeFFmpeg(); -#endif // HAVE_FFMPEG -} - - -DeviceManager::~DeviceManager() -{ -#ifdef HAVE_FFMPEG - uninitializeFFmpeg(); -#endif // HAVE_FFMPEG -} - - -bool DeviceManager::getCameras(std::vector& devices) -{ - return getDeviceList(Device::VideoInput, devices); -} - - -bool DeviceManager::getMicrophones(std::vector& devices) -{ - return getDeviceList(Device::AudioInput, devices); -} - - -bool DeviceManager::getSpeakers(std::vector& devices) -{ - return getDeviceList(Device::AudioOutput, devices); -} - - -bool DeviceManager::findCamera(const std::string& name, Device& device) -{ - std::vector devices; - if (getCameras(devices)) { - for (auto& dev : devices) { - if (dev.id == name || dev.name == name) { - device = dev; - return true; - } - } - } - - return false; -} - - -bool DeviceManager::findMicrophone(const std::string& name, Device& device) -{ - std::vector devices; - if (getMicrophones(devices)) { - for (auto& dev : devices) { - if (dev.id == name || dev.name == name) { - device = dev; - return true; - } - } - } - - return false; -} - - -bool DeviceManager::findSpeaker(const std::string& name, Device& device) -{ - std::vector devices; - if (getSpeakers(devices)) { - for (auto& dev : devices) { - if (dev.id == name || dev.name == name) { - device = dev; - return true; - } - } - } - - return false; -} - - -bool DeviceManager::getDefaultCamera(Device& device) -{ - std::vector devices; - if (getCameras(devices)) { - device = devices[0]; - return true; - } - - return false; -} - - -bool DeviceManager::getDefaultMicrophone(Device& device) -{ - std::vector devices; - if (getMicrophones(devices)) { - device = devices[0]; - return true; - } - - return false; -} - - -bool DeviceManager::getDefaultSpeaker(Device& device) -{ - std::vector devices; - if (getSpeakers(devices)) { - device = devices[0]; - return true; - } - - return false; -} - - -#ifdef HAVE_FFMPEG - -AVInputFormat* DeviceManager::findVideoInputFormat() -{ - return internal::findDefaultInputFormat(SCY_VIDEO_INPUTS); -} - - -AVInputFormat* DeviceManager::findAudioInputFormat() -{ - return internal::findDefaultInputFormat(SCY_AUDIO_INPUTS); -} - -#endif // HAVE_FFMPEG - - -bool DeviceManager::getDeviceList(Device::Type type, std::vector& devices) -{ - devices.clear(); - -// NOTE: Unfortunately FFmpeg's dshow and avfoundation implementations don't -// list devices properly yet so we need to call native libraries outselves: -// https://trac.ffmpeg.org/ticket/4486 -#if defined(SCY_WIN) - return dshow::getDeviceList(type, devices); -#elif defined(SCY_APPLE) - return avfoundation::getDeviceList(type, devices); -#elif defined(HAVE_FFMPEG) - // Use FFmpeg by default - switch (type) { - case Device::VideoInput: - return internal::getInputDeviceList(SCY_VIDEO_INPUTS, type, devices); - case Device::AudioInput: - return internal::getInputDeviceList(SCY_AUDIO_INPUTS, type, devices); - case Device::VideoOutput: - return internal::getOutputDeviceList(SCY_VIDEO_OUTPUTS, type, devices); - case Device::AudioOutput: - return internal::getOutputDeviceList(SCY_AUDIO_OUTPUTS, type, devices); - default: - assert(0 && "unknown device type"); - break; - } -#endif - - return false; -} - - -int DeviceManager::getCapabilities() -{ - std::vector devices; - int caps = VIDEO_RECV; - if (getMicrophones(devices)) { - caps |= AUDIO_SEND; - } - if (getSpeakers(devices)) { - caps |= AUDIO_RECV; - } - if (getCameras(devices)) { - caps |= VIDEO_SEND; - } - return caps; -} - - -void DeviceManager::setWatcher(DeviceWatcher* watcher) -{ - _watcher.reset(watcher); -} - - -DeviceWatcher* DeviceManager::watcher() -{ - return _watcher.get(); -} - - -void DeviceManager::print(std::ostream& ost) -{ - std::vector devs; - - ost << "Video capture devices: " << endl; - if (getCameras(devs)) { - internal::printDevices(ost, devs); - } else { - ost << "\tNone" << endl; - } - - ost << "Audio input devices: " << endl; - if (getMicrophones(devs)) { - internal::printDevices(ost, devs); - } else { - ost << "\tNone" << endl; - } - - ost << "Audio output devices: " << endl; - if (getSpeakers(devs)) { - internal::printDevices(ost, devs); - } else { - ost << "\tNone" << endl; - } -} - - -#if 0 - -// New API's below can be implemented once they have better support across more -// linux distros - -bool enumerateInputDeviceList(AVInputFormat *fmt, Device::Type type, std::vector& devices) //AVFormatContext* s -{ - int ret, i; - AVDeviceInfoList* devlist = nullptr; - // AVDictionary* opts = nullptr; - - LDebug("Enumerating input devices for: ", fmt->name) - if (!fmt || !fmt->priv_class || !AV_IS_INPUT_DEVICE(fmt->priv_class->category)) { - assert(0 && "not an input device"); - } - - if (!fmt->get_device_list) { - LWarn("Cannot list input devices: Not implemented") - goto fail; - } - - if ((ret = avdevice_list_input_sources(fmt, nullptr, nullptr/*opts*/, &devlist)) < 0) { - LWarn("Cannot list input device: ", averror(ret)) - goto fail; - } - - for (int i = 0; i < devlist->nb_devices; i++) { - auto dev = devlist->devices[i]; - // printf("%s %s [%s]\n", devlist->default_device == i ? "*" : " ", - // devlist->devices[i]->device_name, devlist->devices[i]->device_description); - devices.push_back(av::Device(type, - dev->device_name, - dev->device_description, - devlist->default_device == i)); - } - - fail: - avdevice_free_list_devices(&devlist); - - return !devices.empty(); -} - - -bool enumerateOutputDeviceList(AVOutputFormat *fmt, Device::Type type, std::vector& devices) -{ - int ret, i; - AVDeviceInfoList* devlist = nullptr; - // AVDictionary* opts = nullptr; - - LDebug("Enumerating output devices for: ", fmt->name) - if (!fmt || !fmt->priv_class || !AV_IS_OUTPUT_DEVICE(fmt->priv_class->category)) { - assert(0 && "not an output device"); - } - - if (!fmt->get_device_list) { - LWarn("Cannot list output devices: Not implemented") - goto fail; - } - - if ((ret = avdevice_list_output_sinks(fmt, nullptr, nullptr/*opts*/, &devlist)) < 0) { - LWarn("Cannot list output device: ", averror(ret)) - goto fail; - } - - for (i = 0; i < devlist->nb_devices; i++) { - auto dev = devlist->devices[i]; - // printf("%s %s [%s]\n", devlist->default_device == i ? "*" : " ", - // devlist->devices[i]->device_name, devlist->devices[i]->device_description); - devices.push_back(av::Device(type, - dev->device_name, - dev->device_description, - devlist->default_device == i)); - } - - fail: - avdevice_free_list_devices(&devlist); - - return !devices.empty(); -} - - -AVClassCategory getAVClassCategoryFromDeviceType(Device::Type type) -{ - switch (type) { - case Device::VideoInput: return AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT; - case Device::AudioInput: return AV_CLASS_CATEGORY_DEVICE_AUDIO_INPUT; - case Device::VideoOutput: return AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT; - case Device::AudioOutput: return AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT; - default: - assert(0 && "unknown device type"); - break; - } - return AV_CLASS_CATEGORY_NA; -} - - -AVInputFormat* nextInputDevice(Device::Type type, AVInputFormat* prev = nullptr) //AVClassCategory c1, AVClassCategory c2 -{ - const AVClass* pc; - AVClassCategory category = AV_CLASS_CATEGORY_NA; - AVClassCategory c1 = getAVClassCategoryFromDeviceType(type); - AVClassCategory c2 = AV_CLASS_CATEGORY_DEVICE_INPUT; - do { - if (!(prev = av_iformat_next(prev))) - break; - pc = ((AVInputFormat *)prev)->priv_class; - if (!pc) - continue; - category = pc->category; - } while (category != c1 && category != c2); - return prev; -} - - -AVOutputFormat* nextOutputDevice(Device::Type type, AVOutputFormat* prev = nullptr) //, AVClassCategory c1, AVClassCategory c2 -{ - const AVClass* pc; - AVClassCategory category = AV_CLASS_CATEGORY_NA; - AVClassCategory c1 = getAVClassCategoryFromDeviceType(type); - AVClassCategory c2 = AV_CLASS_CATEGORY_DEVICE_OUTPUT; - do { - if (!(prev = av_oformat_next(prev))) - break; - pc = prev->priv_class; - if (!pc) - continue; - category = pc->category; - } while (category != c1 && category != c2); - return prev; -} - - -// do { -// fmt = av_input_audio_device_next(fmt); -// if (fmt) { -// if (!strcmp(fmt->name, "lavfi")) -// continue; //it's pointless to probe lavfi -// if (dev && !av_match_name(dev, fmt->name)) -// continue; -// print_device_sources(fmt, opts); -// } -// } while (fmt); -// do { -// fmt = av_input_video_device_next(fmt); -// if (fmt) { -// if (dev && !av_match_name(dev, fmt->name)) -// continue; -// print_device_sources(fmt, opts); -// } -// } while (fmt); - -// do { -// fmt = av_output_audio_device_next(fmt); -// if (fmt) { -// if (dev && !av_match_name(dev, fmt->name)) -// continue; -// print_device_sinks(fmt, opts); -// } -// } while (fmt); -// do { -// fmt = av_output_video_device_next(fmt); -// if (fmt) { -// if (dev && !av_match_name(dev, fmt->name)) -// continue; -// print_device_sinks(fmt, opts); -// } -// } while (fmt); - -#endif - - -} // namespace av -} // namespace scy - - -/// @\} +/// +// +// LibSourcey +// Copyright (c) 2005, Sourcey +// +// SPDX-License-Identifier: LGPL-2.1+ +// +/// @addtogroup av +/// @{ + + +#include "scy/av/devicemanager.h" +#include "scy/logger.h" + + +#if defined(SCY_WIN) +#include "scy/av/win32/directshow.h" +#define SCY_VIDEO_INPUTS \ + { \ + "dshow", "vfwcap"} +#define SCY_VIDEO_OUTPUTS \ + { \ + } +#define SCY_SCREEN_INPUTS \ + { \ + "gdigrab"} +#define SCY_AUDIO_INPUTS \ + { \ + "dsound"} +#define SCY_AUDIO_OUTPUTS \ + { \ + "dsound"} +#elif defined(SCY_APPLE) +#include "scy/av/apple/avfoundation.h" +#define SCY_VIDEO_INPUTS \ + { \ + "avfoundation", "qtkit"} +#define SCY_VIDEO_OUTPUTS \ + { \ + } +#define SCY_SCREEN_INPUTS \ + { \ + "avfoundation"} +#define SCY_AUDIO_INPUTS \ + { \ + "avfoundation"} +#define SCY_AUDIO_OUTPUTS \ + { \ + "avfoundation"} +#elif defined(SCY_LINUX) +#define SCY_VIDEO_INPUTS \ + { \ + "v4l2", "dv1394"} +#define SCY_VIDEO_OUTPUTS \ + { \ + } +#define SCY_SCREEN_INPUTS \ + { \ + "x11grab"} +#define SCY_AUDIO_INPUTS \ + { \ + "alsa", "jack", "pulse"} +#define SCY_AUDIO_OUTPUTS \ + { \ + "alsa"} +#endif + + +using std::endl; + + +namespace scy { +namespace av { + + +// +// Device +// + + +Device::Device() + : type(Unknown) + , isDefault(false) +{ +} + + +Device::Device(Type type, const std::string& id, const std::string& name, bool isDefault) + : type(type) + , id(id) + , name(name) + , isDefault(isDefault) +{ +} + + +void Device::print(std::ostream& os) +{ + os << "Device[" << type << ":" << name << ":" << id << ":" << isDefault << "]"; +} + + +// +// Helpers +// + + +namespace internal { + + +#ifdef HAVE_FFMPEG + +// Find an output format by name using the iterate API +const AVOutputFormat* findOutputFormat(const std::string& name) +{ + const AVOutputFormat* oformat = nullptr; + void* opaque = nullptr; + while ((oformat = av_muxer_iterate(&opaque))) { + if (name == oformat->name) { + return oformat; + } + } + return nullptr; +} + + +const AVOutputFormat* findDefaultOutputFormat(const std::vector& outputs) +{ + const AVOutputFormat* oformat = nullptr; + for (auto& output : outputs) { + oformat = findOutputFormat(output.c_str()); + if (oformat) + break; + } + + if (!oformat) + throw std::runtime_error("No output format found"); + return oformat; +} + + +const AVInputFormat* findDefaultInputFormat(const std::vector& inputs) +{ + const AVInputFormat* iformat = nullptr; + for (auto& input : inputs) { + iformat = av_find_input_format(input.c_str()); + if (iformat) + break; + } + + if (!iformat) + throw std::runtime_error("No input format found"); + return iformat; +} + + +bool getInputDeviceList(const std::vector& inputs, + Device::Type type, std::vector& devices) +{ +#ifndef HAVE_FFMPEG_AVDEVICE + SWarn << "HAVE_FFMPEG_AVDEVICE not defined, cannot list input devices" + << endl; + return false; +#else + const AVInputFormat* iformat = findDefaultInputFormat(inputs); + if (!iformat) + return false; + + AVDeviceInfoList* devlist = nullptr; + int error = avdevice_list_input_sources(iformat, nullptr, nullptr, &devlist); + if (error < 0 || !devlist) { + LWarn("Cannot list input devices for '", iformat->name, "': ", averror(error)); + if (devlist) + ; + avdevice_free_list_devices(&devlist); + return false; + } + + devices.clear(); + for (int i = 0; i < devlist->nb_devices; i++) { + auto dev = devlist->devices[i]; + devices.push_back( + av::Device(type, dev->device_name, dev->device_description, + i == devlist->default_device)); + } + + avdevice_free_list_devices(&devlist); + return !devices.empty(); +#endif +} + + +bool getOutputDeviceList(const std::vector& outputs, + Device::Type type, std::vector& devices) +{ +#ifndef HAVE_FFMPEG_AVDEVICE + SWarn << "HAVE_FFMPEG_AVDEVICE not defined, cannot list output devices" + << endl; + return false; +#else + const AVOutputFormat* oformat = findDefaultOutputFormat(outputs); + if (!oformat) + return false; + + AVDeviceInfoList* devlist = nullptr; + int error = avdevice_list_output_sinks(oformat, nullptr, nullptr, &devlist); + if (error < 0 || !devlist) { + LWarn("Cannot list output devices for '", oformat->name, "': ", averror(error)); + if (devlist) + ; + avdevice_free_list_devices(&devlist); + return false; + } + + devices.clear(); + for (int i = 0; i < devlist->nb_devices; i++) { + auto dev = devlist->devices[i]; + devices.push_back( + av::Device(type, dev->device_name, dev->device_description, + i == devlist->default_device)); + } + + avdevice_free_list_devices(&devlist); + return !devices.empty(); +#endif +} + +#endif // HAVE_FFMPEG + + +void printDevices(std::ostream& ost, std::vector& devs) +{ + for (size_t i = 0; i < devs.size(); ++i) { + ost << '\t'; + devs[i].print(ost); + ost << endl; + } +} + + +} // namespace internal + + +// +// Device Manager +// + + +DeviceManager::DeviceManager() + : _watcher(nullptr) +{ +#ifdef HAVE_FFMPEG + initializeFFmpeg(); +#endif // HAVE_FFMPEG +} + + +DeviceManager::~DeviceManager() noexcept +{ +#ifdef HAVE_FFMPEG + uninitializeFFmpeg(); +#endif // HAVE_FFMPEG +} + + +bool DeviceManager::getCameras(std::vector& devices) +{ + return getDeviceList(Device::VideoInput, devices); +} + + +bool DeviceManager::getMicrophones(std::vector& devices) +{ + return getDeviceList(Device::AudioInput, devices); +} + + +bool DeviceManager::getSpeakers(std::vector& devices) +{ + return getDeviceList(Device::AudioOutput, devices); +} + + +bool DeviceManager::findCamera(const std::string& name, Device& device) +{ + std::vector devices; + if (getCameras(devices)) { + for (auto& dev : devices) { + if (dev.id == name || dev.name == name) { + device = dev; + return true; + } + } + } + + return false; +} + + +bool DeviceManager::findMicrophone(const std::string& name, Device& device) +{ + std::vector devices; + if (getMicrophones(devices)) { + for (auto& dev : devices) { + if (dev.id == name || dev.name == name) { + device = dev; + return true; + } + } + } + + return false; +} + + +bool DeviceManager::findSpeaker(const std::string& name, Device& device) +{ + std::vector devices; + if (getSpeakers(devices)) { + for (auto& dev : devices) { + if (dev.id == name || dev.name == name) { + device = dev; + return true; + } + } + } + + return false; +} + + +bool DeviceManager::getDefaultCamera(Device& device) +{ + std::vector devices; + if (getCameras(devices)) { + device = devices[0]; + return true; + } + + return false; +} + + +bool DeviceManager::getDefaultMicrophone(Device& device) +{ + std::vector devices; + if (getMicrophones(devices)) { + device = devices[0]; + return true; + } + + return false; +} + + +bool DeviceManager::getDefaultSpeaker(Device& device) +{ + std::vector devices; + if (getSpeakers(devices)) { + device = devices[0]; + return true; + } + + return false; +} + + +#ifdef HAVE_FFMPEG + +const AVInputFormat* DeviceManager::findVideoInputFormat() +{ + return internal::findDefaultInputFormat(SCY_VIDEO_INPUTS); +} + + +const AVInputFormat* DeviceManager::findAudioInputFormat() +{ + return internal::findDefaultInputFormat(SCY_AUDIO_INPUTS); +} + +#endif // HAVE_FFMPEG + + +bool DeviceManager::getDeviceList(Device::Type type, std::vector& devices) +{ + devices.clear(); + +// NOTE: Unfortunately FFmpeg's dshow and avfoundation implementations don't +// list devices properly yet so we need to call native libraries outselves: +// https://trac.ffmpeg.org/ticket/4486 +#if defined(SCY_WIN) + return dshow::getDeviceList(type, devices); +#elif defined(SCY_APPLE) + return avfoundation::getDeviceList(type, devices); +#elif defined(HAVE_FFMPEG) + // Use FFmpeg by default + switch (type) { + case Device::VideoInput: + return internal::getInputDeviceList(SCY_VIDEO_INPUTS, type, devices); + case Device::AudioInput: + return internal::getInputDeviceList(SCY_AUDIO_INPUTS, type, devices); + case Device::VideoOutput: + return internal::getOutputDeviceList(SCY_VIDEO_OUTPUTS, type, devices); + case Device::AudioOutput: + return internal::getOutputDeviceList(SCY_AUDIO_OUTPUTS, type, devices); + default: + throw std::runtime_error("Unknown device type"); + } +#endif + + return false; +} + + +int DeviceManager::getCapabilities() +{ + std::vector devices; + int caps = VIDEO_RECV; + if (getMicrophones(devices)) { + caps |= AUDIO_SEND; + } + if (getSpeakers(devices)) { + caps |= AUDIO_RECV; + } + if (getCameras(devices)) { + caps |= VIDEO_SEND; + } + return caps; +} + + +void DeviceManager::setWatcher(DeviceWatcher* watcher) +{ + _watcher.reset(watcher); +} + + +DeviceWatcher* DeviceManager::watcher() +{ + return _watcher.get(); +} + + +void DeviceManager::print(std::ostream& ost) +{ + std::vector devs; + + ost << "Video capture devices: " << endl; + if (getCameras(devs)) { + internal::printDevices(ost, devs); + } else { + ost << "\tNone" << endl; + } + + ost << "Audio input devices: " << endl; + if (getMicrophones(devs)) { + internal::printDevices(ost, devs); + } else { + ost << "\tNone" << endl; + } + + ost << "Audio output devices: " << endl; + if (getSpeakers(devs)) { + internal::printDevices(ost, devs); + } else { + ost << "\tNone" << endl; + } +} + + +} // namespace av +} // namespace scy + + +/// @\} diff --git a/src/av/src/ffmpeg.cpp b/src/av/src/ffmpeg.cpp index 32b1115f4..299d4d0a2 100644 --- a/src/av/src/ffmpeg.cpp +++ b/src/av/src/ffmpeg.cpp @@ -15,8 +15,8 @@ #ifdef HAVE_FFMPEG -#include #include +#include #include @@ -25,59 +25,33 @@ namespace av { namespace internal { -static int LockManagerOperation(void** lock, enum AVLockOp op) -{ - switch (op) { - case AV_LOCK_CREATE: - *lock = new std::mutex(); - if (!*lock) - return 1; - return 0; - - case AV_LOCK_OBTAIN: - static_cast(*lock)->lock(); - return 0; - - case AV_LOCK_RELEASE: - static_cast(*lock)->unlock(); - return 0; - - case AV_LOCK_DESTROY: - delete static_cast(*lock); - *lock = NULL; - return 0; - } - return 1; -} - - static std::mutex _mutex; static int _refCount(0); -static void logCallback(void *ptr, int level, const char *fmt, va_list vl) +static void logCallback(void* ptr, int level, const char* fmt, va_list vl) { char logbuf[256]; vsnprintf(logbuf, sizeof(logbuf), fmt, vl); logbuf[sizeof(logbuf) - 1] = '\0'; switch (level) { - case AV_LOG_PANIC: - case AV_LOG_FATAL: - case AV_LOG_ERROR: - LError("FFmpeg: ", util::trimRight(logbuf)) - break; - case AV_LOG_WARNING: - LWarn("FFmpeg: ", util::trimRight(logbuf)) - break; - case AV_LOG_INFO: - LDebug("FFmpeg: ", util::trimRight(logbuf)) - break; - default: - case AV_LOG_VERBOSE: - case AV_LOG_DEBUG: - // LTrace("FFmpeg: ", util::trimRight(logbuf)) - break; + case AV_LOG_PANIC: + case AV_LOG_FATAL: + case AV_LOG_ERROR: + LError("FFmpeg: ", util::trimRight(logbuf)); + break; + case AV_LOG_WARNING: + LWarn("FFmpeg: ", util::trimRight(logbuf)); + break; + case AV_LOG_INFO: + LDebug("FFmpeg: ", util::trimRight(logbuf)); + break; + default: + case AV_LOG_VERBOSE: + case AV_LOG_DEBUG: + // LTrace("FFmpeg: ", util::trimRight(logbuf)); + break; } } @@ -94,16 +68,9 @@ void init() // Optionally disable logging. // av_log_set_level(AV_LOG_QUIET); - // Register our protocol glue code with FFmpeg. - av_lockmgr_register(&LockManagerOperation); - - // Now register the rest of FFmpeg. - av_register_all(); - - // And devices if available. -#ifdef HAVE_FFMPEG_AVDEVICE - avdevice_register_all(); -#endif + // Note: av_register_all(), av_lockmgr_register(), and + // avdevice_register_all() were removed in FFmpeg 4.0+/5.0+. + // Codec, format, and device registration is now automatic. } } @@ -111,10 +78,7 @@ void init() void uninit() { std::lock_guard guard(_mutex); - - if (--_refCount == 0) { - av_lockmgr_register(NULL); - } + --_refCount; } @@ -135,7 +99,7 @@ void uninitializeFFmpeg() std::string averror(const int error) { - static char error_buffer[255]; + char error_buffer[255]; av_strerror(error, error_buffer, sizeof(error_buffer)); return error_buffer; } @@ -143,38 +107,32 @@ std::string averror(const int error) void printInputFormats(std::ostream& ost, const char* delim) { - initializeFFmpeg(); // init here so reference is not held - AVInputFormat* p = av_iformat_next(nullptr); - while (p) { + const AVInputFormat* p = nullptr; + void* opaque = nullptr; + while ((p = av_demuxer_iterate(&opaque))) { ost << p->name << delim; - p = av_iformat_next(p); } - uninitializeFFmpeg(); } void printOutputFormats(std::ostream& ost, const char* delim) { - initializeFFmpeg(); // init here so reference is not held - AVOutputFormat* p = av_oformat_next(nullptr); - while (p) { + const AVOutputFormat* p = nullptr; + void* opaque = nullptr; + while ((p = av_muxer_iterate(&opaque))) { ost << p->name << delim; - p = av_oformat_next(p); } - uninitializeFFmpeg(); } void printEncoders(std::ostream& ost, const char* delim) { - initializeFFmpeg(); // init here so reference is not held - AVCodec* p = av_codec_next(nullptr); - while (p) { + const AVCodec* p = nullptr; + void* opaque = nullptr; + while ((p = av_codec_iterate(&opaque))) { if (av_codec_is_encoder(p)) ost << p->name << delim; - p = p->next; } - uninitializeFFmpeg(); } diff --git a/src/av/src/format.cpp b/src/av/src/format.cpp index d50b386a6..837990534 100644 --- a/src/av/src/format.cpp +++ b/src/av/src/format.cpp @@ -22,8 +22,7 @@ namespace av { Format::Format() - : name("Unknown") - , priority(0) + : priority(0) { } diff --git a/src/av/src/formatregistry.cpp b/src/av/src/formatregistry.cpp index 633a3653b..e6191eced 100644 --- a/src/av/src/formatregistry.cpp +++ b/src/av/src/formatregistry.cpp @@ -10,7 +10,6 @@ #include "scy/av/formatregistry.h" -#include "scy/singleton.h" using std::endl; @@ -25,81 +24,61 @@ FormatRegistry::FormatRegistry() } -FormatRegistry::~FormatRegistry() +FormatRegistry::~FormatRegistry() noexcept { } FormatRegistry& FormatRegistry::instance() { - static Singleton sh; - return *sh.get(); + static FormatRegistry instance; + return instance; } Format& FormatRegistry::get(const std::string& name) { std::lock_guard guard(_mutex); - for (unsigned int i = 0; i < _formats.size(); i++) { - if (_formats[i].name == name) { - return _formats[i]; - } - } - - throw std::runtime_error("Not found: No media format for: " + name); + return findByName(name); } Format& FormatRegistry::getByID(const std::string& id) { std::lock_guard guard(_mutex); - for (unsigned int i = 0; i < _formats.size(); i++) { - if (_formats[i].id == id) { - return _formats[i]; - } + for (auto& fmt : _formats) { + if (fmt.id == id) + return fmt; } - throw std::runtime_error("Not found: No media format type: " + id); } Format& FormatRegistry::getOrDefault(const std::string& name) { - { - std::lock_guard guard(_mutex); - for (unsigned int i = 0; i < _formats.size(); i++) { - if (_formats[i].name == name) { - return _formats[i]; - } - } + std::lock_guard guard(_mutex); + for (auto& fmt : _formats) { + if (fmt.name == name) + return fmt; } - - return getDefault(); + return defaultLocked(); } Format& FormatRegistry::getDefault() { std::lock_guard guard(_mutex); - if (!_default.empty()) { - return get(_default); - } else if (!_formats.empty()) { - return *_formats.begin(); - } - - throw std::runtime_error("Not found: No default media format."); + return defaultLocked(); } bool FormatRegistry::exists(const std::string& name) { std::lock_guard guard(_mutex); - for (unsigned int i = 0; i < _formats.size(); i++) { - if (_formats[i].name == name) { + for (const auto& fmt : _formats) { + if (fmt.name == name) return true; - } } - return false; } @@ -120,8 +99,16 @@ FormatList FormatRegistry::formats() const void FormatRegistry::registerFormat(const Format& format) { - unregisterFormat(format.name); std::lock_guard guard(_mutex); + // Remove existing format with the same name (unlocked) + for (auto it = _formats.begin(); it != _formats.end(); ++it) { + if (it->name == format.name) { + if (_default == format.name) + _default = ""; + _formats.erase(it); + break; + } + } _formats.push_back(format); } @@ -129,9 +116,8 @@ void FormatRegistry::registerFormat(const Format& format) bool FormatRegistry::unregisterFormat(const std::string& name) { std::lock_guard guard(_mutex); - for (FormatList::iterator it = _formats.begin(); it != _formats.end(); - ++it) { - if ((*it).name == name) { + for (auto it = _formats.begin(); it != _formats.end(); ++it) { + if (it->name == name) { _formats.erase(it); if (_default == name) _default = ""; @@ -149,6 +135,28 @@ void FormatRegistry::setDefault(const std::string& name) } +// Private: must be called with _mutex held +Format& FormatRegistry::findByName(const std::string& name) +{ + for (auto& fmt : _formats) { + if (fmt.name == name) + return fmt; + } + throw std::runtime_error("Not found: No media format for: " + name); +} + + +// Private: must be called with _mutex held +Format& FormatRegistry::defaultLocked() +{ + if (!_default.empty()) + return findByName(_default); + if (!_formats.empty()) + return *_formats.begin(); + throw std::runtime_error("Not found: No default media format."); +} + + } // namespace av } // namespace scy diff --git a/src/av/src/mediacapture.cpp b/src/av/src/mediacapture.cpp index 24a572180..edc8900aa 100644 --- a/src/av/src/mediacapture.cpp +++ b/src/av/src/mediacapture.cpp @@ -32,17 +32,16 @@ namespace av { MediaCapture::MediaCapture() : _formatCtx(nullptr) - , _video(nullptr) - , _audio(nullptr) , _stopping(false) , _looping(false) , _realtime(false) + , _ratelimit(false) { initializeFFmpeg(); } -MediaCapture::~MediaCapture() +MediaCapture::~MediaCapture() noexcept { close(); uninitializeFFmpeg(); @@ -51,39 +50,35 @@ MediaCapture::~MediaCapture() void MediaCapture::close() { - LTrace("Closing") + LTrace("Closing"); stop(); - if (_video) { - delete _video; - _video = nullptr; - } - - if (_audio) { - delete _audio; - _audio = nullptr; - } + { + std::lock_guard guard(_mutex); + _video.reset(); + _audio.reset(); - if (_formatCtx) { - avformat_close_input(&_formatCtx); - _formatCtx = nullptr; + if (_formatCtx) { + avformat_close_input(&_formatCtx); + _formatCtx = nullptr; + } } - LTrace("Closing: OK") + LTrace("Closing: OK"); } void MediaCapture::openFile(const std::string& file) { - LTrace("Opening file: ", file) + LTrace("Opening file: ", file); openStream(file, nullptr, nullptr); } -void MediaCapture::openStream(const std::string& filename, AVInputFormat* inputFormat, AVDictionary** formatParams) +void MediaCapture::openStream(const std::string& filename, const AVInputFormat* inputFormat, AVDictionary** formatParams) { - LTrace("Opening stream: ", filename) + LTrace("Opening stream: ", filename); if (_formatCtx) throw std::runtime_error("Capture has already been initialized"); @@ -91,7 +86,6 @@ void MediaCapture::openStream(const std::string& filename, AVInputFormat* inputF if (avformat_open_input(&_formatCtx, filename.c_str(), inputFormat, formatParams) < 0) throw std::runtime_error("Cannot open the media source: " + filename); - // _formatCtx->max_analyze_duration = 0; if (avformat_find_stream_info(_formatCtx, nullptr) < 0) throw std::runtime_error("Cannot find stream information: " + filename); @@ -99,15 +93,13 @@ void MediaCapture::openStream(const std::string& filename, AVInputFormat* inputF for (unsigned i = 0; i < _formatCtx->nb_streams; i++) { auto stream = _formatCtx->streams[i]; - auto codec = stream->codec; - if (!_video && codec->codec_type == AVMEDIA_TYPE_VIDEO) { - _video = new VideoDecoder(stream); + if (!_video && stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { + _video = std::make_unique(stream); _video->emitter.attach(packetSlot(this, &MediaCapture::emit)); _video->create(); _video->open(); - } - else if (!_audio && codec->codec_type == AVMEDIA_TYPE_AUDIO) { - _audio = new AudioDecoder(stream); + } else if (!_audio && stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { + _audio = std::make_unique(stream); _audio->emitter.attach(packetSlot(this, &MediaCapture::emit)); _audio->create(); _audio->open(); @@ -121,13 +113,16 @@ void MediaCapture::openStream(const std::string& filename, AVInputFormat* inputF void MediaCapture::start() { - LTrace("Starting") + LTrace("Starting"); - std::lock_guard guard(_mutex); - assert(_video || _audio); + std::lock_guard + guard(_mutex); + + if (!_video && !_audio) + throw std::runtime_error("No media streams available"); if ((_video || _audio) && !_thread.running()) { - LTrace("Initializing thread") + LTrace("Initializing thread"); _stopping = false; _thread.start(std::bind(&MediaCapture::run, this)); } @@ -136,13 +131,14 @@ void MediaCapture::start() void MediaCapture::stop() { - LTrace("Stopping") + LTrace("Stopping"); - std::lock_guard guard(_mutex); + std::lock_guard + guard(_mutex); _stopping = true; if (_thread.running()) { - LTrace("Terminating thread") + LTrace("Terminating thread"); _thread.cancel(); _thread.join(); } @@ -151,7 +147,7 @@ void MediaCapture::stop() void MediaCapture::emit(IPacket& packet) { - LTrace("Emit: ", packet.size()) + LTrace("Emit: ", packet.size()); emitter.emit(packet); } @@ -159,24 +155,28 @@ void MediaCapture::emit(IPacket& packet) void MediaCapture::run() { - LTrace("Running") + LTrace("Running"); try { int res; - AVPacket ipacket; - av_init_packet(&ipacket); + AVPacket* ipacket = av_packet_alloc(); + if (!ipacket) + throw std::runtime_error("Cannot allocate packet"); // Looping variables int64_t videoPtsOffset = 0; int64_t audioPtsOffset = 0; // Realtime variables + int64_t startTime = time::hrtime(); + + // Rate limiting variables int64_t lastTimestamp = time::hrtime(); int64_t frameInterval = _video ? fpsToInterval(int(_video->iparams.fps)) : 0; // Reset the stream back to the beginning when looping is enabled if (_looping) { - LTrace("Looping") + LTrace("Looping"); for (unsigned i = 0; i < _formatCtx->nb_streams; i++) { if (avformat_seek_file(_formatCtx, i, 0, 0, 0, AVSEEK_FLAG_FRAME) < 0) { throw std::runtime_error("Cannot reset media stream"); @@ -185,57 +185,58 @@ void MediaCapture::run() } // Read input packets until complete - while ((res = av_read_frame(_formatCtx, &ipacket)) >= 0) { + while ((res = av_read_frame(_formatCtx, ipacket)) >= 0) { STrace << "Read frame: " - << "pts=" << ipacket.pts << ", " - << "dts=" << ipacket.dts << endl; + << "pts=" << ipacket->pts << ", " + << "dts=" << ipacket->dts << endl; if (_stopping) break; - if (_video && ipacket.stream_index == _video->stream->index) { + if (_video && ipacket->stream_index == _video->stream->index) { - // Set the PTS offset when looping - if (_looping) { - if (ipacket.pts == 0 && _video->pts > 0) + // Realtime PTS calculation in microseconds + if (_realtime) { + ipacket->pts = time::hrtime() - startTime; + } else if (_looping) { + // Set the PTS offset when looping + if (ipacket->pts == 0 && _video->pts > 0) videoPtsOffset = _video->pts; - ipacket.pts += videoPtsOffset; + ipacket->pts += videoPtsOffset; } // Decode and emit - if (_video->decode(ipacket)) { + if (_video->decode(*ipacket)) { STrace << "Decoded video: " << "time=" << _video->time << ", " << "pts=" << _video->pts << endl; } - // Pause the input stream in realtime mode if the + // Pause the input stream in rate limited mode if the // decoder is working too fast - if (_realtime) { + if (_ratelimit) { auto nsdelay = frameInterval - (time::hrtime() - lastTimestamp); - // LDebug("Sleep delay: ", nsdelay, ", ", (time::hrtime() - lastTimestamp), ", ", frameInterval) std::this_thread::sleep_for(std::chrono::nanoseconds(nsdelay)); lastTimestamp = time::hrtime(); } - } - else if (_audio && ipacket.stream_index == _audio->stream->index) { + } else if (_audio && ipacket->stream_index == _audio->stream->index) { // Set the PTS offset when looping if (_looping) { - if (ipacket.pts == 0 && _audio->pts > 0) + if (ipacket->pts == 0 && _audio->pts > 0) videoPtsOffset = _audio->pts; - ipacket.pts += audioPtsOffset; + ipacket->pts += audioPtsOffset; } // Decode and emit - if (_audio->decode(ipacket)) { + if (_audio->decode(*ipacket)) { STrace << "Decoded Audio: " << "time=" << _audio->time << ", " << "pts=" << _audio->pts << endl; } } - av_packet_unref(&ipacket); + av_packet_unref(ipacket); } // Flush remaining packets @@ -246,18 +247,20 @@ void MediaCapture::run() _audio->flush(); } + av_packet_free(&ipacket); + // End of file or error - LTrace("Decoder EOF: ", res) + LTrace("Decoder EOF: ", res); } catch (std::exception& exc) { _error = exc.what(); - LError("Decoder Error: ", _error) + LError("Decoder Error: ", _error); } catch (...) { _error = "Unknown Error"; - LError("Unknown Error") + LError("Unknown Error"); } if (_stopping || !_looping) { - LTrace("Exiting") + LTrace("Exiting"); _stopping = true; Closing.emit(); } @@ -276,9 +279,8 @@ void MediaCapture::getEncoderAudioCodec(AudioCodec& params) { std::lock_guard guard(_mutex); if (_audio) { - assert(_audio->oparams.channels); - assert(_audio->oparams.sampleRate); - assert(!_audio->oparams.sampleFmt.empty()); + if (!_audio->oparams.channels || !_audio->oparams.sampleRate || _audio->oparams.sampleFmt.empty()) + throw std::runtime_error("Audio codec parameters not initialized"); params = _audio->oparams; } } @@ -288,9 +290,8 @@ void MediaCapture::getEncoderVideoCodec(VideoCodec& params) { std::lock_guard guard(_mutex); if (_video) { - assert(_video->oparams.width); - assert(_video->oparams.height); - assert(!_video->oparams.pixelFmt.empty()); + if (!_video->oparams.width || !_video->oparams.height || _video->oparams.pixelFmt.empty()) + throw std::runtime_error("Video codec parameters not initialized"); params = _video->oparams; } } @@ -306,14 +307,14 @@ AVFormatContext* MediaCapture::formatCtx() const VideoDecoder* MediaCapture::video() const { std::lock_guard guard(_mutex); - return _video; + return _video.get(); } AudioDecoder* MediaCapture::audio() const { std::lock_guard guard(_mutex); - return _audio; + return _audio.get(); } @@ -324,7 +325,13 @@ void MediaCapture::setLoopInput(bool flag) } -void MediaCapture::setRealtimePlayback(bool flag) +void MediaCapture::setLimitFramerate(bool flag) +{ + _ratelimit = flag; +} + + +void MediaCapture::setRealtimePTS(bool flag) { _realtime = flag; } diff --git a/src/av/src/multiplexencoder.cpp b/src/av/src/multiplexencoder.cpp index 8d6b9b5c1..744676a09 100644 --- a/src/av/src/multiplexencoder.cpp +++ b/src/av/src/multiplexencoder.cpp @@ -13,17 +13,10 @@ #ifdef HAVE_FFMPEG -#include "assert.h" - extern "C" { -#include "libavutil/time.h" // av_gettime (deprecated) +#include "libavutil/time.h" } -#ifdef SCY_WIN -#define snprintf _snprintf -#endif - - using std::endl; @@ -34,20 +27,17 @@ namespace av { MultiplexEncoder::MultiplexEncoder(const EncoderOptions& options) : _options(options) , _formatCtx(nullptr) - , _video(nullptr) - , _audio(nullptr) , _ioCtx(nullptr) - , _ioBuffer(nullptr) , _pts(0) { - LTrace("Create") + LTrace("Create"); initializeFFmpeg(); } -MultiplexEncoder::~MultiplexEncoder() +MultiplexEncoder::~MultiplexEncoder() noexcept { - LTrace("Destroy") + LTrace("Destroy"); uninit(); uninitializeFFmpeg(); } @@ -55,18 +45,18 @@ MultiplexEncoder::~MultiplexEncoder() static int dispatchOutputPacket(void* opaque, uint8_t* buffer, int bufferSize) { - // Callback example at: - // http://lists.mplayerhq.hu/pipermail/libav-client/2009-May/003034.html auto klass = reinterpret_cast(opaque); if (klass) { - LTrace("Dispatching packet: ", bufferSize) - if (!klass->isActive()) { - LWarn("Dropping packet: " , bufferSize, ": ", klass->state()) + LTrace("Dispatching packet: ", bufferSize); + if (!klass->isActive()) + ; + { + LWarn("Dropping packet: ", bufferSize, ": ", klass->state()); return bufferSize; } MediaPacket packet(buffer, bufferSize); klass->emitter.emit(packet); - LTrace("Dispatching packet: OK: ", bufferSize) + LTrace("Dispatching packet: OK: ", bufferSize); } return bufferSize; @@ -75,12 +65,13 @@ static int dispatchOutputPacket(void* opaque, uint8_t* buffer, int bufferSize) void MultiplexEncoder::init() { - assert(!isActive()); + if (isActive()) + throw std::runtime_error("Encoder already active"); STrace << "Initialize:" - << "\n\tInput Format: " << _options.iformat.toString() - << "\n\tOutput Format: " << _options.oformat.toString() - << "\n\tDuration: " << _options.duration << endl; + << "\n\tInput Format: " << _options.iformat.toString() + << "\n\tOutput Format: " << _options.oformat.toString() + << "\n\tDuration: " << _options.duration << endl; try { _options.oformat.video.enabled = _options.iformat.video.enabled; @@ -92,13 +83,14 @@ void MultiplexEncoder::init() throw std::runtime_error("The output container format must be specified."); // Allocate the output media context - assert(!_formatCtx); + if (_formatCtx) + throw std::runtime_error("Format context already allocated"); _formatCtx = avformat_alloc_context(); if (!_formatCtx) throw std::runtime_error("Cannot allocate format context."); if (!_options.ofile.empty()) - snprintf(_formatCtx->filename, sizeof(_formatCtx->filename), "%s", _options.ofile.c_str()); + _formatCtx->url = av_strdup(_options.ofile.c_str()); // Set the container codec _formatCtx->oformat = av_guess_format(_options.oformat.id.c_str(), @@ -117,9 +109,9 @@ void MultiplexEncoder::init() // Operating in streaming mode. Generated packets can be // obtained by connecting to the outgoing PacketSignal. // Setup the output IO context for our output stream. - int ioBufferSize(MAX_VIDEO_PACKET_SIZE); // * 10 - _ioBuffer = new unsigned char[ioBufferSize]; - _ioCtx = avio_alloc_context(_ioBuffer, ioBufferSize, + int ioBufferSize(MAX_VIDEO_PACKET_SIZE); + _ioBuffer = std::make_unique(ioBufferSize); + _ioCtx = avio_alloc_context(_ioBuffer.get(), ioBufferSize, AVIO_FLAG_WRITE, this, nullptr, dispatchOutputPacket, nullptr); if (!_ioCtx) @@ -131,7 +123,6 @@ void MultiplexEncoder::init() // Operating in file mode. // Open the output file... if (!(_formatCtx->oformat->flags & AVFMT_NOFILE)) { - // if (url_fopen(&_formatCtx->pb, _options.ofile.c_str(), URL_WRONLY) < 0) { if (avio_open(&_formatCtx->pb, _options.ofile.c_str(), AVIO_FLAG_WRITE) < 0) { throw std::runtime_error("AVWriter: Unable to open the output file"); } @@ -139,48 +130,52 @@ void MultiplexEncoder::init() } // Write the stream header (if any) - // TODO: After Ready state - avformat_write_header(_formatCtx, nullptr); + int ret = avformat_write_header(_formatCtx, nullptr); + if (ret < 0) + throw std::runtime_error("Cannot write format header: " + averror(ret)); // Send the format information to sdout av_dump_format(_formatCtx, 0, _options.ofile.c_str(), 1); // Get realtime presentation timestamp - _formatCtx->start_time_realtime = av_gettime(); + _formatCtx->start_time_realtime = av_gettime_relative(); setState(this, EncoderState::Ready); } catch (std::exception& exc) { - LError("Error: ", exc.what()) - setState(this, EncoderState::Error); //, exc.what() + LError("Error: ", exc.what()); + setState(this, EncoderState::Error); cleanup(); throw exc; } - LTrace("Initialize: OK") + LTrace("Initialize: OK"); } void MultiplexEncoder::uninit() { - LTrace("Uninitialize") + LTrace("Uninitialize"); // Write the trailer and dispatch the tail packet if any - if (_formatCtx && _formatCtx->pb) - av_write_trailer(_formatCtx); + if (_formatCtx && _formatCtx->pb) { + int ret = av_write_trailer(_formatCtx); + if (ret < 0) + LWarn("Cannot write format trailer: ", averror(ret)); + } - LTrace("Uninitializing: Wrote trailer") + LTrace("Uninitializing: Wrote trailer"); // Free memory cleanup(); setState(this, EncoderState::Stopped); - LTrace("Uninitialize: OK") + LTrace("Uninitialize: OK"); } void MultiplexEncoder::cleanup() { - LTrace("Cleanup") + LTrace("Cleanup"); // Delete stream encoders freeVideo(); @@ -189,35 +184,28 @@ void MultiplexEncoder::cleanup() // Close the format if (_formatCtx) { - // Free all remaining streams - for (unsigned int i = 0; i < _formatCtx->nb_streams; i++) { - av_freep(&_formatCtx->streams[i]->codec); - av_freep(&_formatCtx->streams[i]); - } - // Close the output file (if any) if (!_options.ofile.empty() && _formatCtx->pb && _formatCtx->oformat && - !(_formatCtx->oformat->flags & AVFMT_NOFILE)) - avio_close(_formatCtx->pb); - // avio_url_fclose(_formatCtx->pb); + !(_formatCtx->oformat->flags & AVFMT_NOFILE)) { + int ret = avio_close(_formatCtx->pb); + if (ret < 0) + LWarn("Cannot close output file: ", averror(ret)); + } - // Free the format context - av_free(_formatCtx); + // Free the format context (also frees streams) + avformat_free_context(_formatCtx); _formatCtx = nullptr; } - if (_ioBuffer) { - delete _ioBuffer; - _ioBuffer = nullptr; - } + _ioBuffer.reset(); - LTrace("Cleanup: OK") + LTrace("Cleanup: OK"); } void MultiplexEncoder::flush() { - LTrace("Flushing") + LTrace("Flushing"); if (_video) { _video->flush(); @@ -236,13 +224,13 @@ EncoderOptions& MultiplexEncoder::options() VideoEncoder* MultiplexEncoder::video() { - return _video; + return _video.get(); } AudioEncoder* MultiplexEncoder::audio() { - return _audio; + return _audio.get(); } @@ -254,21 +242,23 @@ AudioEncoder* MultiplexEncoder::audio() // Write a packet to the output stream. bool MultiplexEncoder::writeOutputPacket(AVPacket& packet) { - assert(packet.data); - assert(packet.size); - assert(packet.pts != AV_NOPTS_VALUE); - assert(isActive()); + if (!packet.data || !packet.size) + return false; + if (packet.pts == AV_NOPTS_VALUE) + return false; + if (!isActive()) + return false; STrace << "Writing packet:" - << "\n\tPacket Size: " << packet.size + << "\n\tPacket Size: " << packet.size << "\n\tPTS: " << packet.pts - << "\n\tDTS: " << packet.dts + << "\n\tDTS: " << packet.dts << "\n\tDuration: " << packet.duration << endl; // Write the encoded frame to the output file if (av_interleaved_write_frame(_formatCtx, &packet) != 0) { - LWarn("Cannot write packet") + LWarn("Cannot write packet"); return false; } return true; @@ -277,24 +267,25 @@ bool MultiplexEncoder::writeOutputPacket(AVPacket& packet) bool MultiplexEncoder::updateStreamPts(AVStream* stream, int64_t* pts) { - LTrace("Update PTS: last=", _pts, ", input=", *pts) + std::lock_guard guard(_mutex); + + LTrace("Update PTS: last=", _pts, ", input=", *pts); - // https://docs.thefoundry.co.uk/products/nuke/developers/63/ndkdevguide/examples/ffmpegReader.cpp - // https://ffmpeg.org/doxygen/trunk/doc_2examples_2muxing_8c-example.html - // https://ffmpeg.org/doxygen/trunk/doc_2examples_2transcoding_8c-example.html int64_t next; if (*pts == AV_NOPTS_VALUE) { // Set a realtime pts value if not specified - int64_t delta(av_gettime() - _formatCtx->start_time_realtime); + int64_t delta(av_gettime_relative() - _formatCtx->start_time_realtime); next = delta * (double)stream->time_base.den / (double)stream->time_base.num / AV_TIME_BASE; - } - else { + } else { // Convert from input microseconds to encoder stream time base next = *pts * (double)stream->time_base.den / (double)stream->time_base.num / AV_TIME_BASE; } - if (next == _pts) { - LWarn("Dropping frame at dusplicate PTS: ", next) + if (next < _pts) { + LWarn("Invalid pts (", next, ") <= last (", _pts, ")"); + return false; + } else if (next == _pts) { + LWarn("Dropping frame at duplicate PTS: ", next); return false; } @@ -310,10 +301,14 @@ bool MultiplexEncoder::updateStreamPts(AVStream* stream, int64_t* pts) void MultiplexEncoder::createVideo() { - assert(!_video); - assert(_options.oformat.video.enabled); - assert(_formatCtx->oformat->video_codec != AV_CODEC_ID_NONE); - _video = new VideoEncoder(_formatCtx); + std::lock_guard guard(_mutex); + if (_video) + throw std::runtime_error("Video encoder already created"); + if (!_options.oformat.video.enabled) + throw std::runtime_error("Video output is not enabled"); + if (_formatCtx->oformat->video_codec == AV_CODEC_ID_NONE) + throw std::runtime_error("No video codec available for this format"); + _video = std::make_unique(_formatCtx); _video->emitter.attach(packetSlot(this, &MultiplexEncoder::onVideoEncoded)); _video->iparams = _options.iformat.video; _video->oparams = _options.oformat.video; @@ -324,19 +319,13 @@ void MultiplexEncoder::createVideo() void MultiplexEncoder::freeVideo() { - if (_video) { - delete _video; - _video = nullptr; - } + _video.reset(); } bool MultiplexEncoder::encodeVideo(AVFrame* frame) { - LTrace("Encoding video: ", frame->pts) - - assert(isActive()); - assert(_video && _video->frame); + LTrace("Encoding video: ", frame->pts); if (!isActive()) throw std::runtime_error("The encoder is not initialized"); @@ -358,12 +347,7 @@ bool MultiplexEncoder::encodeVideo(AVFrame* frame) bool MultiplexEncoder::encodeVideo(uint8_t* data[4], int linesize[4], int width, int height, int64_t time) { - LTrace("Encoding video: ", time) - - assert(isActive()); - assert(_video && _video->frame); - assert(data[0]); - assert(linesize[0]); + LTrace("Encoding video: ", time); if (!isActive()) throw std::runtime_error("The encoder is not initialized"); @@ -385,12 +369,7 @@ bool MultiplexEncoder::encodeVideo(uint8_t* data[4], int linesize[4], bool MultiplexEncoder::encodeVideo(uint8_t* buffer, int bufferSize, int width, int height, int64_t time) { - LTrace("Encoding video: ", time) - - assert(isActive()); - assert(_video && _video->frame); - assert(buffer); - assert(bufferSize); + LTrace("Encoding video: ", time); if (!isActive()) throw std::runtime_error("The encoder is not initialized"); @@ -412,7 +391,7 @@ bool MultiplexEncoder::encodeVideo(uint8_t* buffer, int bufferSize, void MultiplexEncoder::onVideoEncoded(av::VideoPacket& packet) { std::lock_guard guard(_mutex); - writeOutputPacket(*reinterpret_cast(packet.source)); + writeOutputPacket(*packet.avpacket); } @@ -423,13 +402,17 @@ void MultiplexEncoder::onVideoEncoded(av::VideoPacket& packet) void MultiplexEncoder::createAudio() { - LTrace("Create Audio") + std::lock_guard guard(_mutex); + LTrace("Create Audio"); - assert(!_audio); - assert(_options.oformat.audio.enabled); - assert(_formatCtx->oformat->audio_codec != AV_CODEC_ID_NONE); + if (_audio) + throw std::runtime_error("Audio encoder already created"); + if (!_options.oformat.audio.enabled) + throw std::runtime_error("Audio output is not enabled"); + if (_formatCtx->oformat->audio_codec == AV_CODEC_ID_NONE) + throw std::runtime_error("No audio codec available for this format"); - _audio = new AudioEncoder(_formatCtx); + _audio = std::make_unique(_formatCtx); _audio->emitter.attach(packetSlot(this, &MultiplexEncoder::onAudioEncoded)); _audio->iparams = _options.iformat.audio; _audio->oparams = _options.oformat.audio; @@ -440,28 +423,13 @@ void MultiplexEncoder::createAudio() void MultiplexEncoder::freeAudio() { - if (_audio) { - delete _audio; - _audio = nullptr; - } - - // if (_audioFifo) { - // av_fifo_free(_audioFifo); - // _audioFifo = nullptr; - // } - - // if (_audioBuffer) { - // av_free(_audioBuffer); - // _audioBuffer = nullptr; - // } + _audio.reset(); } bool MultiplexEncoder::encodeAudio(uint8_t* buffer, int numSamples, int64_t time) { - LTrace("Encoding audio packet: samples=", numSamples, ", time=", time) - assert(buffer); - assert(numSamples); + LTrace("Encoding audio packet: samples=", numSamples, ", time=", time); if (!buffer || !numSamples) throw std::runtime_error("Invalid audio input"); @@ -480,9 +448,7 @@ bool MultiplexEncoder::encodeAudio(uint8_t* buffer, int numSamples, int64_t time bool MultiplexEncoder::encodeAudio(uint8_t* buffer[4], int numSamples, int64_t time) { - LTrace("Encoding audio packet: samples=", numSamples, ", time=", time) - assert(buffer[0]); - assert(numSamples); + LTrace("Encoding audio packet: samples=", numSamples, ", time=", time); if (!buffer[0] || !numSamples) throw std::runtime_error("Invalid audio input"); @@ -502,7 +468,7 @@ bool MultiplexEncoder::encodeAudio(uint8_t* buffer[4], int numSamples, int64_t t void MultiplexEncoder::onAudioEncoded(av::AudioPacket& packet) { std::lock_guard guard(_mutex); - writeOutputPacket(*reinterpret_cast(packet.source)); + writeOutputPacket(*packet.avpacket); } diff --git a/src/av/src/multiplexpacketencoder.cpp b/src/av/src/multiplexpacketencoder.cpp index 641477606..3851e2f7f 100644 --- a/src/av/src/multiplexpacketencoder.cpp +++ b/src/av/src/multiplexpacketencoder.cpp @@ -27,84 +27,16 @@ MultiplexPacketEncoder::MultiplexPacketEncoder(const EncoderOptions& options) } -MultiplexPacketEncoder::~MultiplexPacketEncoder() +MultiplexPacketEncoder::~MultiplexPacketEncoder() noexcept { } -#if 0 void MultiplexPacketEncoder::process(IPacket& packet) { std::lock_guard guard(_mutex); - LTrace("processing") - - // We may be receiving either audio or video packets - auto vPacket = dynamic_cast(&packet); - auto aPacket = vPacket ? nullptr : dynamic_cast(&packet); - if (!vPacket && !aPacket) - throw std::invalid_argument("Unknown media packet type."); - - // Do some special synchronizing for muxing live variable framerate streams - if (_muxLiveStreams) { - auto video = MultiplexEncoder::video(); - auto audio = MultiplexEncoder::audio(); - assert(audio && video); - double audioPts, videoPts; - int times = 0; - for (;;) { - times++; - assert(times < 10); - audioPts = audio ? (double)audio->stream->pts.val * audio->stream->time_base.num / audio->stream->time_base.den : 0.0; - videoPts = video ? (double)video->stream->pts.val * video->stream->time_base.num / video->stream->time_base.den : 0.0; - if (aPacket) { - // Write the audio packet when the encoder is ready - if (!video || audioPts < videoPts) { - encode(*aPacket); - break; - } - - // Write dummy video frames until we can encode the audio - else { - // May be null if the first packet was audio, skip... - if (!_lastVideoPacket) - break; - - encode(*_lastVideoPacket); - } - } - else if (vPacket) { - // Write the video packet if the encoder is ready - if (!audio || audioPts > videoPts) - encode(*vPacket); - - if (audio) { - // Clone and buffer the last video packet it can be used - // as soon as we need an available frame. - // used as a filler if the source framerate is inconstant. - if (_lastVideoPacket) - delete _lastVideoPacket; - _lastVideoPacket = reinterpret_cast(vPacket->clone()); - } - break; - } - } - } - else if (vPacket) { - encode(*vPacket); - } - else if (aPacket) { - encode(*aPacket); - } -} -#endif - - -void MultiplexPacketEncoder::process(IPacket& packet) -{ - std::lock_guard guard(_mutex); - - LTrace("Processing") + LTrace("Processing"); // We may be receiving either audio or video packets auto vPacket = dynamic_cast(&packet); @@ -124,11 +56,10 @@ void MultiplexPacketEncoder::encode(VideoPacket& packet) auto planar = dynamic_cast(&packet); if (planar) { encodeVideo(planar->buffer, planar->linesize, planar->width, - planar->height, planar->time); - } - else { - encodeVideo((uint8_t*)packet.data(), int(packet.size()), packet.width, - packet.height, packet.time); + planar->height, planar->time); + } else { + encodeVideo(reinterpret_cast(packet.data()), static_cast(packet.size()), packet.width, + packet.height, packet.time); } } @@ -138,9 +69,8 @@ void MultiplexPacketEncoder::encode(AudioPacket& packet) auto planar = dynamic_cast(&packet); if (planar) { encodeAudio(planar->buffer, int(planar->numSamples), planar->time); - } - else { - encodeAudio((uint8_t*)packet.data(), int(packet.numSamples), packet.time); + } else { + encodeAudio(reinterpret_cast(packet.data()), static_cast(packet.numSamples), packet.time); } } @@ -153,14 +83,15 @@ bool MultiplexPacketEncoder::accepts(IPacket* packet) void MultiplexPacketEncoder::onStreamStateChange(const PacketStreamState& state) { - LTrace("On stream state change: ", state) + LTrace("On stream state change: ", state); - std::lock_guard guard(_mutex); + std::lock_guard + guard(_mutex); switch (state.id()) { case PacketStreamState::Active: if (!isActive()) { - LTrace("Initializing") + LTrace("Initializing"); // if (MultiplexEncoder::options().oformat.video.enabled && // MultiplexEncoder::options().oformat.audio.enabled) // _muxLiveStreams = true; @@ -171,7 +102,7 @@ void MultiplexPacketEncoder::onStreamStateChange(const PacketStreamState& state) // case PacketStreamState::Resetting: case PacketStreamState::Stopping: if (isActive()) { - LTrace("Uninitializing") + LTrace("Uninitializing"); MultiplexEncoder::flush(); MultiplexEncoder::uninit(); } @@ -182,7 +113,7 @@ void MultiplexPacketEncoder::onStreamStateChange(const PacketStreamState& state) // case PacketStreamState::Closed: } - LTrace("Stream state change: OK: ", state) + LTrace("Stream state change: OK: ", state); } diff --git a/src/av/src/packet.cpp b/src/av/src/packet.cpp index c07d5e72d..e353b0b11 100644 --- a/src/av/src/packet.cpp +++ b/src/av/src/packet.cpp @@ -14,8 +14,8 @@ #ifdef HAVE_FFMPEG extern "C" { -#include #include +#include } @@ -51,30 +51,30 @@ PlanarVideoPacket::PlanarVideoPacket(uint8_t* data[4], const int linesize[4], co PlanarVideoPacket::PlanarVideoPacket(const PlanarVideoPacket& r) : VideoPacket(r) , pixelFmt(r.pixelFmt) + , owns_buffer(true) { - assert(!pixelFmt.empty() && "pixel format required to copy"); + if (pixelFmt.empty()) + throw std::runtime_error("PlanarVideoPacket: pixel format required to copy"); auto pixfmt = av_get_pix_fmt(pixelFmt.c_str()); - // Allocate image where the data image will copied - _size = av_image_alloc((uint8_t**)r.buffer, (int*)r.linesize, - width, height, pixfmt, 1); + // Allocate into this packet's buffer arrays + _size = av_image_alloc(buffer, linesize, width, height, pixfmt, 1); if (_size < 0) { - LError("Could not allocate raw video buffer"); - assert(0); + throw std::runtime_error("PlanarVideoPacket: av_image_alloc failed"); } - // Copy image data from other frame + // Deep copy image data from source frame av_image_copy(buffer, linesize, - (const uint8_t* *)r.buffer, (int*)r.linesize, - pixfmt, width, height); + const_cast(r.buffer), + const_cast(r.linesize), + pixfmt, width, height); } -PlanarVideoPacket::~PlanarVideoPacket() +PlanarVideoPacket::~PlanarVideoPacket() noexcept { - if (_free) { + if (owns_buffer) { av_freep(&buffer[0]); - av_freep(buffer); } } @@ -105,29 +105,28 @@ PlanarAudioPacket::PlanarAudioPacket(const PlanarAudioPacket& r) : AudioPacket(r) , channels(r.channels) , sampleFmt(r.sampleFmt) + , owns_buffer(true) { - assert(!sampleFmt.empty() && "sample format required to copy"); + if (sampleFmt.empty()) + throw std::runtime_error("PlanarAudioPacket: sample format required to copy"); auto fmt = av_get_sample_fmt(sampleFmt.c_str()); - // Allocate image where the data image will copied - int ret = av_samples_alloc_array_and_samples((uint8_t***)&buffer, - nullptr, channels, (int)numSamples, fmt, 0); + // Allocate audio buffers into this packet's buffer array + int ret = av_samples_alloc(buffer, &linesize, channels, (int)numSamples, fmt, 0); if (ret < 0) { - LError("Could not allocate raw audio buffer"); - assert(0); + throw std::runtime_error("PlanarAudioPacket: av_samples_alloc failed"); } - // Copy image data from other frame - av_samples_copy(buffer, (uint8_t* const*)r.buffer, 0, 0, - channels, (int)numSamples, fmt); + // Deep copy audio data from source frame + av_samples_copy(buffer, const_cast(r.buffer), 0, 0, + channels, (int)numSamples, fmt); } -PlanarAudioPacket::~PlanarAudioPacket() +PlanarAudioPacket::~PlanarAudioPacket() noexcept { - if (_free) { + if (owns_buffer) { av_freep(&buffer[0]); - av_freep(buffer); } } diff --git a/src/av/src/videocapture.cpp b/src/av/src/videocapture.cpp index a9733c07f..1111b773f 100644 --- a/src/av/src/videocapture.cpp +++ b/src/av/src/videocapture.cpp @@ -34,7 +34,7 @@ VideoCapture::VideoCapture() } -VideoCapture::VideoCapture(const std::string& device, int width, int height, +VideoCapture::VideoCapture(const std::string& device, int width, int height, double framerate, const std::string& pixelFmt) { openVideo(device, width, height, framerate); @@ -47,8 +47,7 @@ VideoCapture::VideoCapture(const std::string& device, const av::VideoCodec& para } - -VideoCapture::~VideoCapture() +VideoCapture::~VideoCapture() noexcept { } @@ -59,13 +58,14 @@ void VideoCapture::openVideo(const std::string& device, const av::VideoCodec& pa } -void VideoCapture::openVideo(const std::string& device, int width, int height, +void VideoCapture::openVideo(const std::string& device, int width, int height, double framerate, const std::string& pixelFmt) { - STrace << "Opening camera: " << device << ", " - << "width=" << width << ", " - << "height=" << height << ", " - << "framerate=" << framerate << endl; + SDebug << "Opening camera: " << device << ", " + << "width=" << width << ", " + << "height=" << height << ", " + << "framerate=" << framerate << ", " + << "pixelFmt=" << pixelFmt << endl; DeviceManager devman; auto iformat = devman.findVideoInputFormat(); @@ -73,7 +73,11 @@ void VideoCapture::openVideo(const std::string& device, int width, int height, throw std::runtime_error("Couldn't find camera input format."); AVDictionary* iparams = nullptr; - AVDictionaryCleanup cleanup{ &iparams }; + AVDictionaryCleanup cleanup{&iparams}; + + // NOTE: A pixel format must be passed or the capture may error out with: + // [mjpeg @ 0x7fb5f40016c0] Specified pixel format -1 is invalid or not supported + std::string pixfmt = pixelFmt.empty() ? "yuv420p" : pixelFmt; // Set custom parameters for devices. // NOTE: This doesn't work for DirectShow. @@ -84,10 +88,13 @@ void VideoCapture::openVideo(const std::string& device, int width, int height, av_dict_set(&iparams, "framerate", util::format("%f", framerate).c_str(), 0); // Set the desired pixel format - // TODO: Use yuv420p once encoders support PlanarVideoPacket input - av_dict_set(&iparams, "pixel_format", pixelFmt.data(), 0); //bgr24, yuv420p + av_dict_set(&iparams, "pixel_format", pixfmt.data(), 0); //bgr24, yuv420p #endif + // Use realtime PTS calculation for live sources + setRealtimePTS(true); + + // Open the stream openStream(device.c_str(), iformat, &iparams); // Set the decoder video output parameters for conversion context. @@ -95,8 +102,8 @@ void VideoCapture::openVideo(const std::string& device, int width, int height, // If the input device wouldn't accept our parameters then we will // perform pixel conversions and resizing ourself (on the decoder). if (_video) { - if (!pixelFmt.empty()) - _video->oparams.pixelFmt = pixelFmt; // bgr24, yuv420p + if (!pixfmt.empty()) + _video->oparams.pixelFmt = pixfmt; // bgr24, yuv420p if (width > 0) _video->oparams.width = width; if (height > 0) diff --git a/src/av/src/videocontext.cpp b/src/av/src/videocontext.cpp index 44839a54a..1999e4db4 100644 --- a/src/av/src/videocontext.cpp +++ b/src/av/src/videocontext.cpp @@ -28,19 +28,18 @@ VideoContext::VideoContext() , ctx(nullptr) , codec(nullptr) , frame(nullptr) - , conv(nullptr) , time(0) , pts(AV_NOPTS_VALUE) , seconds(0) { - LTrace("Create") + LTrace("Create"); initializeFFmpeg(); } -VideoContext::~VideoContext() +VideoContext::~VideoContext() noexcept { - LTrace("Destroy") + LTrace("Destroy"); close(); uninitializeFFmpeg(); @@ -55,17 +54,11 @@ void VideoContext::create() void VideoContext::open() { SDebug << "Open: " - << "\n\tInput: " << iparams.toString() - << "\n\tOutput: " << oparams.toString() << endl; + << "\n\tInput: " << iparams.toString() + << "\n\tOutput: " << oparams.toString() << endl; - assert(ctx); - assert(avcodec_is_open(ctx) && "avcodec_open2 must be called"); - assert(codec); - - // NOTE: The codec must be opened prior to calling open() - // // Open the video codec - // if (avcodec_open2(ctx, codec, nullptr) < 0) - // throw std::runtime_error("Cannot open the video codec."); + if (!ctx || !avcodec_is_open(ctx) || !codec) + throw std::runtime_error("Video codec not open"); // Create the video conversion context if required recreateConverter(); @@ -74,74 +67,52 @@ void VideoContext::open() void VideoContext::close() { - LTrace("Closing") + LTrace("Closing"); if (frame) { - av_free(frame); + av_frame_free(&frame); frame = nullptr; } if (ctx) { - avcodec_close(ctx); + avcodec_free_context(&ctx); ctx = nullptr; } - if (conv) { - delete conv; - conv = nullptr; - } + conv.reset(); - // Streams are managed differently by the external impl - // if (stream) { - // stream = nullptr; - // Note: The stream is managed by the AVFormatContext - // av_freep(stream); - //} + // Streams are managed by the AVFormatContext + stream = nullptr; time = 0; pts = AV_NOPTS_VALUE; seconds = 0; error = ""; - LTrace("Closing: OK") + LTrace("Closing: OK"); } -AVFrame* VideoContext::convert(AVFrame* iframe) //, VideoCodec& cparams +AVFrame* VideoContext::convert(AVFrame* iframe) { // While flushing the input frame may be null if (!iframe) return nullptr; - assert(iframe->width == iparams.width); - assert(iframe->height == iparams.height); + if (iframe->width != iparams.width || iframe->height != iparams.height) + throw std::runtime_error("Input frame dimensions mismatch"); // Recreate the video conversion context on the fly // if the input resolution changes. - - //if (iframe->width != /*conv->*/ oparams.width || - // iframe->height != /*conv->*/ oparams.height || - // iframe->format != /*conv->*/ av_get_pix_fmt(oparams.pixelFmt.c_str())) { - //if (iframe->width != conv->iparams.width || - // iframe->height != conv->iparams.height || - // iframe->format != av_get_pix_fmt(conv->iparams.pixelFmt.c_str()) || - // oparams.width != conv->oparams.width || - // oparams.height != conv->oparams.height || - // av_get_pix_fmt(oparams.pixelFmt.c_str()) != av_get_pix_fmt(conv->oparams.pixelFmt.c_str())) { - iparams.width = iframe->width; - iparams.height = iframe->height; - iparams.pixelFmt = av_get_pix_fmt_name((AVPixelFormat)iframe->format); - recreateConverter(); - //} + iparams.width = iframe->width; + iparams.height = iframe->height; + iparams.pixelFmt = av_get_pix_fmt_name((AVPixelFormat)iframe->format); + recreateConverter(); // Return the input frame if no conversion is required if (!conv) return iframe; - // // Set the input PTS or a monotonic value to keep the encoder happy. - // // The actual setting of the PTS is outside the scope of this encoder. - // cframe->pts = iframe->pts != AV_NOPTS_VALUE ? iframe->pts : ctx->frame_number; - // Convert the input frame and return the result return conv->convert(iframe); } @@ -149,20 +120,8 @@ AVFrame* VideoContext::convert(AVFrame* iframe) //, VideoCodec& cparams bool VideoContext::recreateConverter() { - // if (conv) - // throw std::runtime_error("Conversion context already exists."); - - // NOTE: the input output `width`, `height`, and `pixelFmt` parameters work - // slightly differently for encoders and decoders. - // For encoders `iparams` is the picture format from the application and - // `oparams` is the picture format passed into the encoder. - // For decoders `iparams` is the picture format from the decoder and - // `oparams` is the picture format passed into the application. - // Check if conversion is required - // This check if only for when unitialized - // If iparams or oparams is changed after initialization a conversion - // context must be created + // This check is only for when uninitialized if (!conv && iparams.width == oparams.width && iparams.height == oparams.height && @@ -171,9 +130,7 @@ bool VideoContext::recreateConverter() } // Check if the conversion context needs to be recreated - if (conv && (conv->iparams.width == iparams.width && - conv->iparams.height == iparams.height && - conv->iparams.pixelFmt == iparams.pixelFmt) && + if (conv && (conv->iparams.width == iparams.width && conv->iparams.height == iparams.height && conv->iparams.pixelFmt == iparams.pixelFmt) && (conv->oparams.width == oparams.width && conv->oparams.height == oparams.height && conv->oparams.pixelFmt == oparams.pixelFmt)) { @@ -181,10 +138,8 @@ bool VideoContext::recreateConverter() } // Recreate the conversion context - LDebug("Recreating video conversion context") - if (conv) - delete conv; - conv = new VideoConverter(); + LDebug("Recreating video conversion context"); + conv = std::make_unique(); conv->iparams = iparams; conv->oparams = oparams; conv->create(); @@ -203,21 +158,16 @@ AVFrame* createVideoFrame(AVPixelFormat pixelFmt, int width, int height) if (!picture) return nullptr; - // TODO: Replace with AVFrameHolder - int size = av_image_get_buffer_size(pixelFmt, width, height, 16); - auto buffer = reinterpret_cast(av_malloc(size)); - if (!buffer) { - av_free(picture); - return nullptr; - } - - av_image_fill_arrays(picture->data, picture->linesize, buffer, pixelFmt, width, height, 1); - - // FFmpeg v3.1.4 does not set width and height values for us anymore picture->width = width; picture->height = height; picture->format = pixelFmt; + // Allocate frame buffer via av_frame_get_buffer for proper refcounting + if (av_frame_get_buffer(picture, 16) < 0) { + av_frame_free(&picture); + return nullptr; + } + return picture; } @@ -228,8 +178,12 @@ AVFrame* cloneVideoFrame(AVFrame* source) copy->format = source->format; copy->width = source->width; copy->height = source->height; +#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100) + av_channel_layout_copy(©->ch_layout, &source->ch_layout); +#else copy->channels = source->channels; copy->channel_layout = source->channel_layout; +#endif copy->nb_samples = source->nb_samples; av_frame_get_buffer(copy, 32); av_frame_copy(copy, source); @@ -252,7 +206,7 @@ void initVideoCodecFromContext(const AVStream* stream, const AVCodecContext* ctx } } -AVPixelFormat selectPixelFormat(AVCodec* codec, VideoCodec& params) +AVPixelFormat selectPixelFormat(const AVCodec* codec, VideoCodec& params) { enum AVPixelFormat compatible = AV_PIX_FMT_NONE; enum AVPixelFormat requested = av_get_pix_fmt(params.pixelFmt.c_str()); diff --git a/src/av/src/videoconverter.cpp b/src/av/src/videoconverter.cpp index 2c6cbfbb4..c45dd33b1 100644 --- a/src/av/src/videoconverter.cpp +++ b/src/av/src/videoconverter.cpp @@ -30,7 +30,7 @@ VideoConverter::VideoConverter() } -VideoConverter::~VideoConverter() +VideoConverter::~VideoConverter() noexcept { close(); } @@ -38,15 +38,15 @@ VideoConverter::~VideoConverter() void VideoConverter::create() { -//#if 0 + //#if 0 STrace << "Create:" - << "\n\tInput Width: " << iparams.width - << "\n\tInput Height: " << iparams.height - << "\n\tInput Pixel Format: " << iparams.pixelFmt - << "\n\tOutput Width: " << oparams.width - << "\n\tOutput Height: " << oparams.height - << "\n\tOutput Pixel Format: " << oparams.pixelFmt << endl; -//#endif + << "\n\tInput Width: " << iparams.width + << "\n\tInput Height: " << iparams.height + << "\n\tInput Pixel Format: " << iparams.pixelFmt + << "\n\tOutput Width: " << oparams.width + << "\n\tOutput Height: " << oparams.height + << "\n\tOutput Pixel Format: " << oparams.pixelFmt << endl; + //#endif if (ctx) throw std::runtime_error("Conversion context already initialized."); @@ -65,10 +65,10 @@ void VideoConverter::create() void VideoConverter::close() { - LTrace("Closing") + LTrace("Closing"); if (oframe) { - av_free(oframe); + av_frame_free(&oframe); oframe = nullptr; } @@ -82,20 +82,19 @@ void VideoConverter::close() AVFrame* VideoConverter::convert(AVFrame* iframe) { STrace << "Convert:" - << "\n\tIn Format: " << iparams.pixelFmt - << "\n\tIn Size: " << iframe->width << "x" << iframe->height - << "\n\tOut Format: " << oparams.pixelFmt - << "\n\tOut Size: " << oparams.width << "x" << oparams.height - << "\n\tPTS: " << iframe->pts - << "\n\tPacket PTS: " << iframe->pkt_pts - << endl; - - assert(iframe); - assert(iframe->data[0]); - assert(iframe->width == iparams.width); - assert(iframe->height == iparams.height); - assert(iframe); - assert(oframe->format == av_get_pix_fmt(oparams.pixelFmt.c_str())); + << "\n\tIn Format: " << iparams.pixelFmt + << "\n\tIn Size: " << iframe->width << "x" << iframe->height + << "\n\tOut Format: " << oparams.pixelFmt + << "\n\tOut Size: " << oparams.width << "x" << oparams.height + << "\n\tPTS: " << iframe->pts + << endl; + + if (!iframe || !iframe->data[0]) + throw std::runtime_error("Invalid input frame for conversion"); + if (iframe->width != iparams.width || iframe->height != iparams.height) + throw std::runtime_error("Input frame dimensions do not match converter input parameters"); + if (oframe->format != av_get_pix_fmt(oparams.pixelFmt.c_str())) + throw std::runtime_error("Output frame pixel format mismatch"); if (!ctx) throw std::runtime_error("Conversion context must be initialized."); diff --git a/src/av/src/videodecoder.cpp b/src/av/src/videodecoder.cpp index e7a9579a7..45dbe556e 100644 --- a/src/av/src/videodecoder.cpp +++ b/src/av/src/videodecoder.cpp @@ -30,7 +30,7 @@ VideoDecoder::VideoDecoder(AVStream* stream) } -VideoDecoder::~VideoDecoder() +VideoDecoder::~VideoDecoder() noexcept { close(); } @@ -38,22 +38,29 @@ VideoDecoder::~VideoDecoder() void VideoDecoder::create() { - assert(stream); - LTrace("Create: ", stream->index) + if (!stream) + throw std::runtime_error("VideoDecoder: stream is null"); + LTrace("Create: ", stream->index); - ctx = stream->codec; - - codec = avcodec_find_decoder(ctx->codec_id); + codec = avcodec_find_decoder(stream->codecpar->codec_id); if (!codec) throw std::runtime_error("Video codec missing or unsupported."); + ctx = avcodec_alloc_context3(codec); + if (!ctx) + throw std::runtime_error("Cannot allocate video decoder context."); + + int ret = avcodec_parameters_to_context(ctx, stream->codecpar); + if (ret < 0) + throw std::runtime_error("Cannot copy video codec parameters: " + averror(ret)); + frame = av_frame_alloc(); if (frame == nullptr) throw std::runtime_error("Cannot allocate video input frame."); - int ret = avcodec_open2(ctx, codec, nullptr); + ret = avcodec_open2(ctx, codec, nullptr); if (ret < 0) - throw std::runtime_error("Cannot open the audio codec: " + averror(ret)); + throw std::runtime_error("Cannot open the video codec: " + averror(ret)); // Set the default input and output parameters are set here once the codec // context has been opened. The output pixel format, width or height can be @@ -61,9 +68,6 @@ void VideoDecoder::create() // next call to open() to output the desired format. initVideoCodecFromContext(stream, ctx, iparams); initVideoCodecFromContext(stream, ctx, oparams); - - // Default to bgr24 interleaved output. - // oparams.pixelFmt = "bgr24"; } @@ -81,108 +85,88 @@ void VideoDecoder::close() inline void emitPacket(VideoDecoder* dec, AVFrame* frame) { - frame->pts = av_frame_get_best_effort_timestamp(frame); + // Use best_effort_timestamp which is set by the decoder + frame->pts = frame->best_effort_timestamp; // Set the decoder time in microseconds - // This value represents the number of microseconds - // that have elapsed since the brginning of the stream. - dec->time = dec->frame->pts > 0 ? static_cast(dec->frame->pkt_pts * - av_q2d(dec->stream->time_base) * AV_TIME_BASE) : 0; + int64_t pts = frame->pts; + dec->time = pts > 0 ? static_cast(pts * + av_q2d(dec->stream->time_base) * AV_TIME_BASE) + : 0; // Set the decoder pts in stream time base - dec->pts = frame->pts; + dec->pts = pts; // Set the decoder seconds since stream start - dec->seconds = (frame->pkt_dts - dec->stream->start_time) * av_q2d(dec->stream->time_base); + dec->seconds = (pts - dec->stream->start_time) * av_q2d(dec->stream->time_base); STrace << "Decoded video frame:" - << "\n\tFrame DTS: " << frame->pkt_dts - << "\n\tFrame PTS: " << frame->pts - << "\n\tTimestamp: " << dec->time - << "\n\tSeconds: " << dec->seconds - << endl; + << "\n\tFrame PTS: " << frame->pts + << "\n\tTimestamp: " << dec->time + << "\n\tPTS: " << pts + << "\n\tSeconds: " << dec->seconds + << endl; PlanarVideoPacket video(frame->data, frame->linesize, dec->oparams.pixelFmt, frame->width, frame->height, dec->time); - video.source = frame; - video.opaque = dec; + video.avframe = frame; dec->emitter.emit(video); } -//bool VideoDecoder::decode(uint8_t* data, int size) -//{ -// AVPacket ipacket; -// av_init_packet(&ipacket); -// ipacket.stream_index = stream->index; -// ipacket.data = data; -// ipacket.size = size; -// return decode(ipacket); -//} - - bool VideoDecoder::decode(AVPacket& ipacket) { - assert(ctx); - assert(codec); - assert(frame); - assert(!stream || ipacket.stream_index == stream->index); - - int ret, frameDecoded = 0; - while (ipacket.size > 0) { - ret = avcodec_decode_video2(ctx, frame, &frameDecoded, &ipacket); + if (!ctx || !codec || !frame) + throw std::runtime_error("VideoDecoder not initialized"); + if (stream && ipacket.stream_index != stream->index) + return false; + + // Send packet to the decoder + int ret = avcodec_send_packet(ctx, &ipacket); + if (ret < 0) { + error = "Video decoder error: " + averror(ret); + LError(error); + throw std::runtime_error(error); + } + + bool decoded = false; + while (ret >= 0) { + ret = avcodec_receive_frame(ctx, frame); + if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { + break; + } if (ret < 0) { - error = "Audio decoder error: " + averror(ret); - LError(error) + error = "Video decoder error: " + averror(ret); + LError(error); throw std::runtime_error(error); } - if (frameDecoded) { - // assert(bytesDecoded == ipacket.size); - - // STrace << "Decoded frame:" - // << "\n\tFrame Size: " << opacket.size - // << "\n\tFrame PTS: " << opacket.pts - // << "\n\tInput Frame PTS: " << ipacket.pts - // << "\n\tInput Bytes: " << ipacket.size - // << "\n\tBytes Decoded: " << bytesDecoded - // << "\n\tFrame PTS: " << frame->pts - // << "\n\tDecoder PTS: " << pts - // << endl; - - // fps.tick(); - emitPacket(this, convert(frame)); //, frame, opacket, &ptsSeconds - } - - ipacket.size -= ret; - ipacket.data += ret; + // fps.tick(); + emitPacket(this, convert(frame)); + decoded = true; } - assert(ipacket.size == 0); - return !!frameDecoded; + + return decoded; } -void VideoDecoder::flush() // AVPacket& opacket +void VideoDecoder::flush() { - AVPacket ipacket; - av_init_packet(&ipacket); - ipacket.data = nullptr; - ipacket.size = 0; - - // av_init_packet(&opacket); - // opacket.data = nullptr; - // opacket.size = 0; - - int frameDecoded = 0; - do { - avcodec_decode_video2(ctx, frame, &frameDecoded, &ipacket); - if (frameDecoded) { - LTrace("Flushed video frame") - emitPacket(this, convert(frame)); //, opacket stream, ctx, &pts, oparams - // return true; + // Send nullptr packet to flush the decoder + avcodec_send_packet(ctx, nullptr); + + int ret = 0; + while (ret >= 0) { + ret = avcodec_receive_frame(ctx, frame); + if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { + break; + } + if (ret >= 0) { + LTrace("Flushed video frame"); + emitPacket(this, convert(frame)); } - } while (frameDecoded); + } } diff --git a/src/av/src/videoencoder.cpp b/src/av/src/videoencoder.cpp index 47b9ab930..bb32f1b5c 100644 --- a/src/av/src/videoencoder.cpp +++ b/src/av/src/videoencoder.cpp @@ -29,7 +29,7 @@ VideoEncoder::VideoEncoder(AVFormatContext* format) } -VideoEncoder::~VideoEncoder() +VideoEncoder::~VideoEncoder() noexcept { close(); } @@ -48,43 +48,25 @@ void VideoEncoder::create() // Allocate stream and AVCodecContext from the AVFormatContext if available if (format) { - format->oformat->video_codec = codec->id; - // Add a video stream that uses the format's default video // codec to the format context's streams[] array. stream = avformat_new_stream(format, codec); if (!stream) throw std::runtime_error("Cannot create video stream."); - - // Testing realtime streams - // - // http://stackoverflow.com/questions/16768794/muxing-from-video-and-video-files-with-ffmpeg - // stream->time_base.den = 1000; //realtime_ ? 1000 : fps_.num; - // stream->time_base.num = 1; //realtime_ ? 1: fps_.den; - // - // stream->r_frame_rate.num = oparams.fps; - // stream->r_frame_rate.den = 1; - // stream->avg_frame_rate.den = 1; - // stream->avg_frame_rate.num = oparams.fps; - - ctx = stream->codec; } - // Otherwise allocate the standalone AVCodecContext - else { - ctx = avcodec_alloc_context3(codec); - if (!ctx) - throw std::runtime_error("Cannot allocate encoder context."); - } + // Allocate the AVCodecContext + ctx = avcodec_alloc_context3(codec); + if (!ctx) + throw std::runtime_error("Cannot allocate encoder context."); - assert(oparams.enabled); + if (!oparams.enabled) + throw std::runtime_error("Video output parameters are not enabled"); - avcodec_get_context_defaults3(ctx, codec); ctx->codec_id = codec->id; ctx->codec_type = AVMEDIA_TYPE_VIDEO; ctx->pix_fmt = selectPixelFormat(codec, oparams); ctx->frame_number = 0; - // ctx->max_b_frames = 1; // Resolution must be a multiple of two ctx->width = oparams.width; @@ -101,24 +83,14 @@ void VideoEncoder::create() ctx->bit_rate_tolerance = oparams.bitRate * 1000; // needed when time_base.num > 1 } - // Emit one intra frame every ten - // ctx->gop_size = 10; - // Set some defaults for codecs of note. - // Also set optimal output pixel formats if the - // default AV_PIX_FMT_YUV420P was given. switch (ctx->codec_id) { case AV_CODEC_ID_H264: - // TODO: Use oparams.quality to determine profile? - av_opt_set(ctx->priv_data, "preset", "slow", 0); // veryfast, slow, baseline + av_opt_set(ctx->priv_data, "preset", "slow", 0); break; case AV_CODEC_ID_MJPEG: case AV_CODEC_ID_LJPEG: - // Use high quality JPEG - // TODO: Use oparams.quality to determine values - // ctx->mb_lmin = ctx->lmin = ctx->qmin * FF_QP2LAMBDA; - // ctx->mb_lmax = ctx->lmax = ctx->qmax * FF_QP2LAMBDA; - ctx->flags = CODEC_FLAG_QSCALE; + ctx->flags |= AV_CODEC_FLAG_QSCALE; ctx->global_quality = ctx->qmin * FF_QP2LAMBDA; break; case AV_CODEC_ID_MPEG2VIDEO: @@ -129,8 +101,9 @@ void VideoEncoder::create() } // Some formats want stream headers to be separate - if (format && format->oformat->flags & AVFMT_GLOBALHEADER) - ctx->flags |= CODEC_FLAG_GLOBAL_HEADER; + if (format && format->oformat->flags & AVFMT_GLOBALHEADER) { + ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; + } // Allocate the input frame frame = createVideoFrame(av_get_pix_fmt(iparams.pixelFmt.c_str()), @@ -142,6 +115,14 @@ void VideoEncoder::create() if (ret < 0) throw std::runtime_error("Cannot open the video codec: " + averror(ret)); + // Copy codec parameters to the stream + if (stream) { + int ret = avcodec_parameters_from_context(stream->codecpar, ctx); + if (ret < 0) + throw std::runtime_error("Cannot copy video codec parameters to stream: " + averror(ret)); + stream->time_base = ctx->time_base; + } + // Update any output parameters that might have changed initVideoCodecFromContext(stream, ctx, oparams); } @@ -149,39 +130,18 @@ void VideoEncoder::create() void VideoEncoder::close() { - LTrace("Closing") + LTrace("Closing"); VideoContext::close(); - -#if 0 - if (buffer) { - av_free(buffer); - buffer = nullptr; - } - - // Free the stream - if (stream && format && format->nb_streams) { - for (unsigned int i = 0; i < format->nb_streams; i++) { - if (format->streams[i] == stream) { - LTrace("Closing: Removing stream: ", stream) - av_freep(&format->streams[i]->codec); - av_freep(&format->streams[i]); - stream = nullptr; - format->nb_streams--; - } - } - } -#endif } bool VideoEncoder::encode(uint8_t* data[4], int linesize[4], int64_t pts) { - assert(data); - assert(data[0]); - assert(linesize[0]); - assert(frame); - assert(codec); + if (!data || !data[0] || !linesize[0]) + throw std::runtime_error("Invalid video input data"); + if (!frame || !codec) + throw std::runtime_error("Video encoder not initialized"); // Populate the input frame with data from the given buffer. for (int i = 0; i < 4; ++i) { @@ -196,10 +156,10 @@ bool VideoEncoder::encode(uint8_t* data[4], int linesize[4], int64_t pts) bool VideoEncoder::encode(uint8_t* data, int size, int64_t pts) { - assert(data); - assert(size); - assert(frame); - assert(codec); + if (!data || !size) + throw std::runtime_error("Invalid video input data"); + if (!frame || !codec) + throw std::runtime_error("Video encoder not initialized"); // Populate the input frame with data from the given buffer. frame->data[0] = reinterpret_cast(data); @@ -209,95 +169,86 @@ bool VideoEncoder::encode(uint8_t* data, int size, int64_t pts) } -void emitPacket(VideoEncoder* enc, AVPacket& opacket) +void emitPacket(VideoEncoder* enc, AVPacket* opacket) { - // auto pixelFmt = av_get_pix_fmt(enc->oparams.pixelFmt.c_str()); - // assert(av_pix_fmt_count_planes(pixelFmt) == 1 && "planar formats not supported"); - if (enc->stream) { // Set the encoder time in microseconds - // This value represents the number of microseconds - // that have elapsed since the brginning of the stream. - enc->time = opacket.pts > 0 ? static_cast( - opacket.pts * av_q2d(enc->stream->time_base) * AV_TIME_BASE) : 0; - - // Set the encoder seconds since stream start - // enc->seconds = enc->time / time::kNumMicrosecsPerSec; - // enc->seconds = (opacket.pts - enc->stream->start_time) * av_q2d(enc->stream->time_base); - enc->seconds = opacket.pts * av_q2d(enc->stream->time_base); + enc->time = opacket->pts > 0 ? static_cast( + opacket->pts * av_q2d(enc->stream->time_base) * AV_TIME_BASE) + : 0; + + enc->seconds = opacket->pts * av_q2d(enc->stream->time_base); } // Set the encoder pts in stream time base - enc->pts = opacket.pts; + enc->pts = opacket->pts; - assert(opacket.data); - assert(opacket.size); - // assert(opacket.pts >= 0); - // assert(opacket.dts >= 0); + if (!opacket->data || !opacket->size) + return; - VideoPacket video(opacket.data, opacket.size, enc->ctx->coded_frame->width, - enc->ctx->coded_frame->height, enc->time); - video.source = &opacket; - video.opaque = enc; + VideoPacket video(opacket->data, opacket->size, enc->ctx->width, + enc->ctx->height, enc->time); + video.avpacket = opacket; enc->emitter.emit(video); } bool VideoEncoder::encode(AVFrame* iframe) { - // assert(iframe); - // assert(iframe->data[0]); - assert(ctx); - assert(codec); - - AVPacket opacket; - av_init_packet(&opacket); - opacket.data = nullptr; // using encoder assigned buffer - opacket.size = 0; - - int frameEncoded = 0; - int ret = avcodec_encode_video2(ctx, &opacket, convert(iframe), &frameEncoded); + if (!ctx || !codec) + throw std::runtime_error("Video encoder not initialized"); + + // Send the frame to the encoder (convert first if needed) + int ret = avcodec_send_frame(ctx, convert(iframe)); if (ret < 0) { error = "Video encoder error: " + averror(ret); - LError(error) + LError(error); throw std::runtime_error(error); } - if (frameEncoded) { + bool encoded = false; + AVPacket* opacket = av_packet_alloc(); + if (!opacket) + throw std::runtime_error("Cannot allocate output packet"); + + // Receive all available encoded packets + while (ret >= 0) { + ret = avcodec_receive_packet(ctx, opacket); + if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { + break; + } + if (ret < 0) { + av_packet_free(&opacket); + error = "Video encoder error: " + averror(ret); + LError(error); + throw std::runtime_error(error); + } + // fps.tick(); - if (ctx->coded_frame->key_frame) - opacket.flags |= AV_PKT_FLAG_KEY; if (stream) { - opacket.stream_index = stream->index; - // if (opacket.pts != AV_NOPTS_VALUE) - // opacket.pts = av_rescale_q(opacket.pts, ctx->time_base, stream->time_base); - // if (opacket.dts != AV_NOPTS_VALUE) - // opacket.dts = av_rescale_q(opacket.dts, ctx->time_base, stream->time_base); - // if (opacket.duration > 0) - // opacket.duration = (int)av_rescale_q(opacket.duration, ctx->time_base, stream->time_base); + opacket->stream_index = stream->index; STrace << "Encoded frame:" - << "\n\tScaled PTS: " << opacket.pts - << "\n\tScaled DTS: " << opacket.dts - << "\n\tLcaled Duration: " << opacket.duration << std::endl; - - emitPacket(this, opacket); + << "\n\tScaled PTS: " << opacket->pts + << "\n\tScaled DTS: " << opacket->dts + << "\n\tDuration: " << opacket->duration << std::endl; } - return true; - } + emitPacket(this, opacket); - av_packet_unref(&opacket); + encoded = true; + av_packet_unref(opacket); + } - return false; + av_packet_free(&opacket); + return encoded; } void VideoEncoder::flush() { - do { - // :) - } while (encode(nullptr)); + // Send nullptr frame to signal end of stream + encode(nullptr); } diff --git a/src/av/src/win32/directshow.cpp b/src/av/src/win32/directshow.cpp index 15d644ea8..93ed107d6 100644 --- a/src/av/src/win32/directshow.cpp +++ b/src/av/src/win32/directshow.cpp @@ -10,10 +10,9 @@ #include "scy/av/win32/directshow.h" -#include "scy/platform.h" #include "scy/logger.h" +#include "scy/platform.h" -#include #include // DBT_* & DEV_* #include #include @@ -37,10 +36,10 @@ bool getDeviceCategoryList(Device::Type type, REFGUID category, std::vector& devices) return getDeviceCategoryList(type, CLSID_AudioInputDeviceCategory, devices); default: // assert(0 && "unknown dshow device type"); - LDebug("DirectShow cannot enumerate output devices: Not implemented") + LDebug("DirectShow cannot enumerate output devices: Not implemented"); break; } diff --git a/src/av/tests/CMakeLists.txt b/src/av/tests/CMakeLists.txt index a7d670199..f43897a60 100644 --- a/src/av/tests/CMakeLists.txt +++ b/src/av/tests/CMakeLists.txt @@ -1,4 +1 @@ -#if(HAVE_FFMPEGV) - # set(avtests_EXCLUDE_CTEST TRUE) - define_libsourcey_test(avtests base av) -#endif() +scy_add_test(avtests DEPENDS base av) diff --git a/src/av/tests/avtests.cpp b/src/av/tests/avtests.cpp index 8aaff476d..fd24ffaa1 100644 --- a/src/av/tests/avtests.cpp +++ b/src/av/tests/avtests.cpp @@ -1,122 +1,252 @@ -#include "avtests.h" - - -using namespace std; -using namespace scy; -using namespace scy::av; -using namespace scy::test; - - -int main(int argc, char** argv) -{ - Logger::instance().add(new ConsoleChannel("debug", Level::Debug)); // Level::Trace, Level::Debug - // Logger::instance().setWriter(new AsyncLogWriter); - test::init(); - - // Define class based tests -#ifdef HAVE_FFMPEG - describe("audio encoder", new AudioEncoderTest); - describe("audio resampler", new AudioResamplerTest); - describe("audio fifo buffer", new AudioBufferTest); - describe("h264 video file transcoder", new VideoFileTranscoderTest); - describe("h264 multiplex capture encoder", new MultiplexCaptureEncoderTest); - // describe("realtime encoder media queue", new RealtimeMediaQueueEncoderTest); - // describe("audio capture", new AudioCaptureTest); - // describe("audio capture encoder", new AudioCaptureEncoderTest); - // describe("audio capture resampler", new AudioCaptureResamplerTest); - // describe("device capture multiplex encoder", new DeviceCaptureMultiplexEncoderTest); -#endif - - describe("realtime media queue", new RealtimeMediaQueueTest); - - test::runAll(); - - return test::finalize(); -} - - -// // -// /// Device Manager Tests -// // -// -// describe("device manager", []() { -// LDebug("Starting") -// auto& deviceManager = av::MediaFactory::instance().devices(); -// -// av::Device device; -// if (deviceManager.getDefaultCamera(device)) { -// LDebug("Default video device: ", device.id, ": ", device.name) -// } -// if (deviceManager.getDefaultMicrophone(device)) { -// LDebug("Default audio device: ", device.id, ": ", device.name) -// } -// -// std::vector devices; -// if (deviceManager.getCameras(devices)) { -// LDebug("Num video devices: ", devices.size()) -// for (auto& device : devices) { -// SDebug << "Printing video device: " << device.id << ": " << -// device.name << endl; -// } -// } -// else { -// LDebug("No video devices detected!") -// } -// if (deviceManager.getMicrophones(devices)) { -// LDebug("Num audio devices: ", devices.size()) -// for (auto& device : devices) { -// SDebug << "Printing audio device: " << device.id << ": " << -// device.name << endl; -// } -// } -// else { -// LDebug("No video devices detected!") -// } -// -// // TODO: verify data integrity? -// }); -// -// -// // -// /// Video Capture Tests -// // -// -// describe("video capture", []() { -// LDebug("Starting") -// -// av::VideoCapture::Ptr capture = -// MediaFactory::instance().createVideoCapture(0); -// capture->emitter += packetSlot(&context, -// &CallbackContext::onVideoCaptureFrame); -// -// // std::puts("Press any key to continue..."); -// // std::getchar(); -// -// // FIXME: Run loop until x number of frames received -// -// capture->emitter -= packetSlot(this, -// &CallbackContext::onVideoCaptureFrame); -// -// LDebug("Complete") -// } -// -// describe("video capture stream", []() { -// LDebug("Starting") -// -// av::VideoCapture::Ptr capture = -// MediaFactory::instance().createVideoCapture(0); -// { -// PacketStream stream; -// stream.emitter += packetSlot(&context, -// &CallbackContext::onVideoCaptureStreamFrame); -// stream.attachSource(capture, true); -// stream.start(); -// -// // std::puts("Press any key to continue..."); -// // std::getchar(); -// } -// -// assert(capture->emitter.nslots() == 0); -// -// LDebug("Complete") -// }); +#include "avtests.h" + + +using namespace std; +using namespace scy; +using namespace scy::av; +using namespace scy::test; + + +int main(int argc, char** argv) +{ + Logger::instance().add(std::make_unique("debug", Level::Debug)); // Level::Trace, Level::Debug + // Logger::instance().setWriter(std::make_unique()); + test::init(); + + // Define class based tests +#ifdef HAVE_FFMPEG + describe("audio encoder", new AudioEncoderTest); + describe("audio resampler", new AudioResamplerTest); + describe("audio fifo buffer", new AudioBufferTest); + describe("video encoder", new VideoEncoderTest); + describe("video decoder", new VideoDecoderTest); + describe("audio decoder", new AudioDecoderTest); + describe("h264 video file transcoder", new VideoFileTranscoderTest); + describe("h264 multiplex capture encoder", new MultiplexCaptureEncoderTest); + // describe("realtime encoder media queue", new RealtimeMediaQueueEncoderTest); + // describe("audio capture", new AudioCaptureTest); + // describe("audio capture encoder", new AudioCaptureEncoderTest); + // describe("audio capture resampler", new AudioCaptureResamplerTest); + // describe("device capture multiplex encoder", new DeviceCaptureMultiplexEncoderTest); +#endif + + describe("realtime media queue", new RealtimeMediaQueueTest); + + + // ========================================================================= + // Format Construction + // + describe("format construction", []() { + av::Format fmt; + expect(fmt.name.empty()); + expect(fmt.id.empty()); + expect(fmt.type() == av::Format::None); + }); + + describe("format video only", []() { + av::Format fmt("MJPEG", "mjpeg", + av::VideoCodec("MJPEG", "mjpeg", 640, 480, 25)); + expect(fmt.name == "MJPEG"); + expect(fmt.id == "mjpeg"); + expect(fmt.video.enabled); + expect(!fmt.audio.enabled); + expect(fmt.video.width == 640); + expect(fmt.video.height == 480); + expect(fmt.type() == av::Format::Video); + }); + + describe("format audio only", []() { + av::Format fmt("MP3", "mp3", + av::AudioCodec("MP3", "libmp3lame", 2, 44100, 128000)); + expect(fmt.name == "MP3"); + expect(!fmt.video.enabled); + expect(fmt.audio.enabled); + expect(fmt.audio.channels == 2); + expect(fmt.audio.sampleRate == 44100); + expect(fmt.type() == av::Format::Audio); + }); + + describe("format multiplex", []() { + av::Format fmt("FLV", "flv", + av::VideoCodec("FLV", "flv", 320, 240), + av::AudioCodec("Speex", "libspeex", 1, 16000)); + expect(fmt.video.enabled); + expect(fmt.audio.enabled); + expect(fmt.type() == av::Format::Multiplex); + }); + + describe("format priority", []() { + av::Format f1("A", "a", av::VideoCodec("V", "v", 100, 100)); + av::Format f2("B", "b", av::VideoCodec("V", "v", 100, 100)); + f1.priority = 1; + f2.priority = 2; + expect(f1.priority < f2.priority); + }); + + + // ========================================================================= + // FormatRegistry + // + describe("format registry register and get", []() { + av::FormatRegistry registry; + av::Format fmt("TestFmt", "testfmt", + av::VideoCodec("V", "v", 100, 100)); + registry.registerFormat(fmt); + + expect(registry.exists("TestFmt")); + auto got = registry.get("TestFmt"); + expect(got.name == "TestFmt"); + expect(got.id == "testfmt"); + }); + + describe("format registry getByID", []() { + av::FormatRegistry registry; + registry.registerFormat(av::Format("Foo", "foo_id", + av::VideoCodec("V", "v", 100, 100))); + + auto got = registry.getByID("foo_id"); + expect(got.name == "Foo"); + }); + + describe("format registry default", []() { + av::FormatRegistry registry; + av::Format f1("First", "first", av::VideoCodec("V", "v", 100, 100)); + av::Format f2("Second", "second", av::VideoCodec("V", "v", 100, 100)); + registry.registerFormat(f1); + registry.registerFormat(f2); + + registry.setDefault("Second"); + auto def = registry.getDefault(); + expect(def.name == "Second"); + }); + + describe("format registry unregister", []() { + av::FormatRegistry registry; + registry.registerFormat(av::Format("Del", "del", + av::VideoCodec("V", "v", 100, 100))); + expect(registry.exists("Del")); + + registry.unregisterFormat("Del"); + expect(!registry.exists("Del")); + }); + + describe("format registry clear", []() { + av::FormatRegistry registry; + registry.registerFormat(av::Format("A", "a", av::VideoCodec("V", "v", 100, 100))); + registry.registerFormat(av::Format("B", "b", av::VideoCodec("V", "v", 100, 100))); + registry.clear(); + expect(!registry.exists("A")); + expect(!registry.exists("B")); + }); + + + // ========================================================================= + // FPSCounter + // + describe("fps counter", []() { + av::FPSCounter counter; + expect(counter.fps == 0.0); + expect(counter.frames == 0); + + // Tick a few times + for (int i = 0; i < 10; i++) { + counter.tick(); + } + expect(counter.frames == 10); + + counter.reset(); + expect(counter.frames == 0); + }); + + + test::runAll(); + + return test::finalize(); +} + + +// // +// /// Device Manager Tests +// // +// +// describe("device manager", []() { +// LDebug("Starting"); +// auto& deviceManager = av::MediaFactory::instance().devices(); +// +// av::Device device; +// if (deviceManager.getDefaultCamera(device)) { +// LDebug("Default video device: ", device.id, ": ", device.name); +// } +// if (deviceManager.getDefaultMicrophone(device)) { +// LDebug("Default audio device: ", device.id, ": ", device.name); +// } +// +// std::vector devices; +// if (deviceManager.getCameras(devices)) { +// LDebug("Num video devices: ", devices.size()); +// for (auto& device : devices) { +// SDebug << "Printing video device: " << device.id << ": " << +// device.name << endl; +// } +// } +// else { +// LDebug("No video devices detected!"); +// } +// if (deviceManager.getMicrophones(devices)) { +// LDebug("Num audio devices: ", devices.size()); +// for (auto& device : devices) { +// SDebug << "Printing audio device: " << device.id << ": " << +// device.name << endl; +// } +// } +// else { +// LDebug("No video devices detected!"); +// } +// +// // TODO: verify data integrity? +// }); +// +// +// // +// /// Video Capture Tests +// // +// +// describe("video capture", []() { +// LDebug("Starting"); +// +// av::VideoCapture::Ptr capture = +// MediaFactory::instance().createVideoCapture(0); +// capture->emitter += packetSlot(&context, +// &CallbackContext::onVideoCaptureFrame); +// +// // std::puts("Press any key to continue..."); +// // std::getchar(); +// +// // FIXME: Run loop until x number of frames received +// +// capture->emitter -= packetSlot(this, +// &CallbackContext::onVideoCaptureFrame); +// +// LDebug("Complete"); +// } +// +// describe("video capture stream", []() { +// LDebug("Starting"); +// +// av::VideoCapture::Ptr capture = +// MediaFactory::instance().createVideoCapture(0); +// { +// PacketStream stream; +// stream.emitter += packetSlot(&context, +// &CallbackContext::onVideoCaptureStreamFrame); +// stream.attachSource(capture, true); +// stream.start(); +// +// // std::puts("Press any key to continue..."); +// // std::getchar(); +// } +// +// assert(capture->emitter.nslots() == 0); +// +// LDebug("Complete"); +// }); diff --git a/src/av/tests/avtests.h b/src/av/tests/avtests.h index ef17044d6..387b774a0 100644 --- a/src/av/tests/avtests.h +++ b/src/av/tests/avtests.h @@ -17,10 +17,15 @@ #include "scy/av/audioencoder.h" #include "scy/av/audioresampler.h" #include "scy/av/devicemanager.h" +#include "scy/av/format.h" +#include "scy/av/formatregistry.h" +#include "scy/av/fpscounter.h" #include "scy/av/mediacapture.h" #include "scy/av/multiplexpacketencoder.h" #include "scy/av/realtimepacketqueue.h" #include "scy/av/videocapture.h" +#include "scy/av/videodecoder.h" +#include "scy/av/videoencoder.h" #include "scy/base.h" #include "scy/filesystem.h" #include "scy/logger.h" @@ -28,11 +33,18 @@ #include "scy/util.h" #include +#ifdef HAVE_FFMPEG +extern "C" { +#include +#include +} +#endif -using std::cout; + +using scy::test::Test; using std::cerr; +using std::cout; using std::endl; -using scy::test::Test; namespace scy { @@ -42,26 +54,20 @@ static const int kNumberFramesWanted = 200; static const int kInNumSamples = 1024; #ifdef SCY_WIN - // Use native aac encoder on Windows since newer FFmpeg - // version should always be available. +// Use native aac encoder on Windows since newer FFmpeg +// version should always be available. #define ACC_ENCODER "aac" #else - // Use libfdk_aac on Linux since native FFmpeg aac - // encoder is shaky on older versions. +// Use libfdk_aac on Linux since native FFmpeg aac +// encoder is shaky on older versions. #define ACC_ENCODER "libfdk_aac" #endif -#define MP4_H264_AAC_TRANSCODER_FORMAT av::Format{"MP4 Default", "mp4", \ - { "libx264", 400, 300 }, \ - { ACC_ENCODER }}; +#define MP4_H264_AAC_TRANSCODER_FORMAT av::Format{"MP4 Default", "mp4", {"libx264", 400, 300}, {ACC_ENCODER}}; -#define MP4_H264_AAC_REALTIME_FORMAT av::Format{"MP4 Realtime", "mp4", \ - { "libx264", 400, 300, 25, 48000, 128000, "yuv420p" }, \ - { ACC_ENCODER, 2, 44100, 64000, "fltp" }}; +#define MP4_H264_AAC_REALTIME_FORMAT av::Format{"MP4 Realtime", "mp4", {"libx264", 400, 300, 25, 48000, 128000, "yuv420p"}, {ACC_ENCODER, 2, 44100, 64000, "fltp"}}; -#define VP8_H264_AAC_REALTIME_FORMAT av::Format{"MP4 VP8 Realtime", "mp4", \ - { "vp8", 400, 300, 25, 48000, 128000, "yuv420p" }, \ - { ACC_ENCODER, 2, 44100, 64000, "fltp" }}; +#define VP8_H264_AAC_REALTIME_FORMAT av::Format{"MP4 VP8 Realtime", "mp4", {"vp8", 400, 300, 25, 48000, 128000, "yuv420p"}, {ACC_ENCODER, 2, 44100, 64000, "fltp"}}; // ============================================================================= @@ -200,7 +206,7 @@ class VideoFileTranscoderTest : public Test stream.start(); while (!capture->stopping()) { - LDebug("Waiting for completion") + LDebug("Waiting for completion"); scy::sleep(10); } @@ -267,7 +273,7 @@ class MultiplexCaptureEncoderTest : public Test // Create and attach the default video capture av::VideoCapture video; if (devman.getDefaultCamera(device)) { - LInfo("Using video device: ", device.name) + LInfo("Using video device: ", device.name); video.openVideo(device.id, 640, 480); video.getEncoderFormat(options.iformat); stream.attachSource(&video, false, true); @@ -276,7 +282,7 @@ class MultiplexCaptureEncoderTest : public Test // Create and attach the default audio capture av::AudioCapture audio; if (devman.getDefaultMicrophone(device)) { - LInfo("Using audio device: ", device.name) + LInfo("Using audio device: ", device.name); audio.openAudio(device.id, 2, 44100); audio.getEncoderFormat(options.iformat); stream.attachSource(&audio, false, true); @@ -295,7 +301,7 @@ class MultiplexCaptureEncoderTest : public Test // Encode 100 frames and break while (video.video()->seconds < 10 && !video.stopping() && !audio.stopping()) { - // LDebug("Waiting for completion: ", numFramesRemaining) + // LDebug("Waiting for completion: ", numFramesRemaining); scy::sleep(10); } @@ -467,7 +473,7 @@ class AudioCaptureTest : public Test expect(oparams.sampleRate == inSampleRate); while (numFramesRemaining > 0 && !capture.stopping()) { - LDebug("Waiting for completion: ", numFramesRemaining) + LDebug("Waiting for completion: ", numFramesRemaining); scy::sleep(10); } @@ -534,11 +540,11 @@ class AudioCaptureEncoderTest : public Test expect(iparams.sampleRate == inSampleRate); while (numFramesRemaining > 0 && !capture.stopping()) { - LDebug("Waiting for completion: ", numFramesRemaining) + LDebug("Waiting for completion: ", numFramesRemaining); scy::sleep(10); } - LDebug("Number samples remaining: ", encoder.fifo.available()) + LDebug("Number samples remaining: ", encoder.fifo.available()); // assert(encoder.fifo.available() == 0); expect(encoder.fifo.available() < 1024); @@ -610,14 +616,14 @@ class AudioCaptureResamplerTest : public Test capture.emitter.attach(packetSlot(this, &AudioCaptureResamplerTest::onAudioCaptured)); while (numFramesRemaining > 0) { - LDebug("Waiting for completion: ", numFramesRemaining) + LDebug("Waiting for completion: ", numFramesRemaining); scy::sleep(10); } capture.stop(); resampler.close(); output.close(); - LDebug("numFramesRemaining: ", numFramesRemaining) + LDebug("numFramesRemaining: ", numFramesRemaining); // TODO: verify data integrity expect(numFramesRemaining == 0); @@ -627,7 +633,7 @@ class AudioCaptureResamplerTest : public Test { if (numFramesRemaining) { numFramesRemaining--; - LDebug("On audio packet: ", packet.size()) + LDebug("On audio packet: ", packet.size()); auto data = reinterpret_cast(packet.data()); if (resampler.resample(&data, packet.numSamples)) { output.write( @@ -654,7 +660,7 @@ class AudioCaptureResamplerTest : public Test // stream.emitter += packetSlot(this, &RealtimeMediaQueueEncoderTest::onPacketPlayout); // // while (numFramesRemaining > 0) { -// LDebug("Waiting for completion: ", numFramesRemaining) +// LDebug("Waiting for completion: ", numFramesRemaining); // scy::sleep(10); // } // @@ -666,8 +672,8 @@ class AudioCaptureResamplerTest : public Test // { // if (numFramesRemaining) { // numFramesRemaining--; -// LDebug("On packet: ", numFramesRemaining, ": ", packet.time) -// // LDebug("On packet: ", numFramesRemaining, ": ", packet.time) +// LDebug("On packet: ", numFramesRemaining, ": ", packet.time); +// // LDebug("On packet: ", numFramesRemaining, ": ", packet.time); // } // else { // stream.stop(); @@ -682,7 +688,8 @@ class AudioCaptureResamplerTest : public Test // ============================================================================= // Realtime Media Queue Test // -struct MockMediaPacketSource : public PacketSource, public basic::Startable +struct MockMediaPacketSource : public PacketSource + , public basic::Startable { Thread runner; PacketSignal emitter; @@ -696,7 +703,7 @@ struct MockMediaPacketSource : public PacketSource, public basic::Startable void start() { - LDebug("Start") + LDebug("Start"); runner.start([](void* arg) { auto self = reinterpret_cast(arg); if (self->numFramesRemaining) { @@ -707,23 +714,24 @@ struct MockMediaPacketSource : public PacketSource, public basic::Startable std::mt19937 rng(rd()); std::uniform_int_distribution uni(1000, 1000000 * 5); auto time = uni(rng); - // LDebug("Emitting: ", self->numFramesRemaining, ": ", time) - av::MediaPacket p(new uint8_t[10], 10, time); - p.assignDataOwnership(); + // LDebug("Emitting: ", self->numFramesRemaining, ": ", time); + uint8_t buf[10] = {}; + av::MediaPacket p(static_cast(buf), 10, time); self->emitter.emit(p); } - }, this); + }, + this); } void stop() { - LDebug("Stop") + LDebug("Stop"); runner.cancel(); } void onStreamStateChange(const PacketStreamState& state) { - LDebug("Stream state: ", state) + LDebug("Stream state: ", state); if (state.equals(PacketStreamState::Closed) || state.equals(PacketStreamState::Error)) { @@ -750,7 +758,7 @@ class RealtimeMediaQueueTest : public Test stream.emitter += packetSlot(this, &RealtimeMediaQueueTest::onPacketPlayout); while (numFramesRemaining > 0) { - // LDebug("Waiting for completion: ", numFramesRemaining) + // LDebug("Waiting for completion: ", numFramesRemaining); scy::sleep(10); } @@ -763,7 +771,7 @@ class RealtimeMediaQueueTest : public Test // auto pkt = reinterpret_cast(packet); if (numFramesRemaining) { numFramesRemaining--; - LDebug("On packet: ", numFramesRemaining, ": ", packet.time) + LDebug("On packet: ", numFramesRemaining, ": ", packet.time); } else { stream.stop(); } @@ -778,7 +786,7 @@ class RealtimeMediaQueueTest : public Test // // Tests(Application& app) : app(app) // { -// LDebug("Running tests...") +// LDebug("Running tests..."); // // try { // @@ -819,7 +827,7 @@ class RealtimeMediaQueueTest : public Test // #endif // } // catch (std::exception& exc) { -// LError("Error: ", exc.what()) +// LError("Error: ", exc.what()); // } // }; // @@ -831,7 +839,7 @@ class RealtimeMediaQueueTest : public Test // // // void onVideoCaptureStreamFrame(void* sender, av::MatrixPacket& packet) // { -// LDebug("On stream packet: ", packet.size()) +// LDebug("On stream packet: ", packet.size()); // } // // @@ -897,12 +905,12 @@ class RealtimeMediaQueueTest : public Test // &VideoCaptureThread::onVideo); // capture.stop(); // -// LDebug(" Ended..................") +// LDebug(" Ended.................."); // } // // void onVideo(void* sender, MatrixPacket& packet) // { -// LDebug("On thread frame: ", packet.size()) +// LDebug("On thread frame: ", packet.size()); // cv::imshow(_name, *packet.mat); // frames++; // } @@ -918,7 +926,7 @@ class RealtimeMediaQueueTest : public Test // // void runVideoCaptureThreadTest() // { -// LDebug("Running video capture test...") +// LDebug("Running video capture test..."); // // // // start and destroy multiple receivers @@ -929,10 +937,10 @@ class RealtimeMediaQueueTest : public Test // threads.push_back(new VideoCaptureThread(0)); // } // -// LDebug(" Ending..................") +// LDebug(" Ending.................."); // } // catch (std::exception& exc) { -// LError("[VideoCaptureThread] Error: ", exc.what()) +// LError("[VideoCaptureThread] Error: ", exc.what()); // } // // std::puts("Press any key to continue..."); @@ -948,7 +956,7 @@ class RealtimeMediaQueueTest : public Test // // // void testVideoThumbnailer() // { -// LDebug("Starting") +// LDebug("Starting"); // // try { // assert(0 && "fixme"); @@ -957,13 +965,13 @@ class RealtimeMediaQueueTest : public Test // //thumb.grab(); // } // catch (std::exception& exc) { -// LError("VideoThumbnailer: ", exc.what()) +// LError("VideoThumbnailer: ", exc.what()); // } // catch (...) { -// LError("VideoThumbnailer: Unknown error") +// LError("VideoThumbnailer: Unknown error"); // } // -// LDebug("Complete") +// LDebug("Complete"); // } // // @@ -1100,7 +1108,7 @@ class RealtimeMediaQueueTest : public Test // // // Init captures // if (options.oformat.video.enabled) { -// LDebug("Video device: ", 0) +// LDebug("Video device: ", 0); // videoCapture = // MediaFactory::instance().createVideoCapture(0); //0 // //videoCapture = @@ -1118,7 +1126,7 @@ class RealtimeMediaQueueTest : public Test // if // (MediaFactory::instance().devices().getDefaultMicrophone(device)) // { -// LDebug("Audio device: ", device.id) +// LDebug("Audio device: ", device.id); // audioCapture = // MediaFactory::instance().createAudioCapture(device.id, // options.oformat.audio.channels, @@ -1150,14 +1158,14 @@ class RealtimeMediaQueueTest : public Test // // virtual ~StreamEncoderTest() // { -// LDebug("Destroying") +// LDebug("Destroying"); // close(); -// LDebug("Destroying: OK") +// LDebug("Destroying: OK"); // } // // void close() // { -// LDebug("########### Closing: ", frames) +// LDebug("########### Closing: ", frames); // closed = true; // // // Close the stream @@ -1199,7 +1207,7 @@ class RealtimeMediaQueueTest : public Test // // void onVideoCapture(void* sender, av::MatrixPacket& packet) // { -// LDebug("On packet: ", packet.size()) +// LDebug("On packet: ", packet.size()); // // //cv::imshow("StreamEncoderTest", *packet.mat); // } @@ -1231,7 +1239,7 @@ class RealtimeMediaQueueTest : public Test // // void runStreamEncoderTest() // { -// LDebug("Running") +// LDebug("Running"); // try // { // // Setup encoding format @@ -1274,13 +1282,13 @@ class RealtimeMediaQueueTest : public Test // // // Shutdown the garbage collector so we can free memory. // //GarbageCollector::instance().shutdown(); -// //LDebug("#################### Finalizing") +// //LDebug("#################### Finalizing"); // //GarbageCollector::instance().shutdown(); -// //LDebug("#################### Exiting") +// //LDebug("#################### Exiting"); // -// //LDebug("#################### Finalizing") +// //LDebug("#################### Finalizing"); // //app.cleanup(); -// //LDebug("#################### Exiting") +// //LDebug("#################### Exiting"); // // // Wait for enter keypress // //scy::pause(); @@ -1291,17 +1299,17 @@ class RealtimeMediaQueueTest : public Test // } // catch (std::exception& exc) // { -// LError("Error: ", exc.what()) +// LError("Error: ", exc.what()); // assert(0); // } // -// LDebug("Ended") +// LDebug("Ended"); // } // // // void runCaptureRecorderTest() // { -// LDebug("Starting") +// LDebug("Starting"); // // /* // av::VideoCapture::Ptr capture(0); @@ -1329,7 +1337,7 @@ class RealtimeMediaQueueTest : public Test // encoder.stop(); // */ // -// LDebug("Complete") +// LDebug("Complete"); // } // // @@ -1338,7 +1346,7 @@ class RealtimeMediaQueueTest : public Test // // // void runOpenCVCaptureTest() // { -// LDebug("Starting") +// LDebug("Starting"); // // cv::VideoCapture cap(0); // if (!cap.isOpened()) @@ -1356,7 +1364,7 @@ class RealtimeMediaQueueTest : public Test // if (cv::waitKey(30) >= 0) break; // } // -// LDebug("Complete") +// LDebug("Complete"); // } // // @@ -1404,7 +1412,7 @@ class RealtimeMediaQueueTest : public Test // endl; // } // -// LDebug("[AudioCaptureThread] Ended..................") +// LDebug("[AudioCaptureThread] Ended.................."); // //delete this; // } // @@ -1423,7 +1431,7 @@ class RealtimeMediaQueueTest : public Test // // void runAudioCaptureThreadTest() // { -// LDebug("Running Audio Capture Thread test...") +// LDebug("Running Audio Capture Thread test..."); // // // start and destroy multiple receivers // list threads; @@ -1443,13 +1451,13 @@ class RealtimeMediaQueueTest : public Test // // // void onCaptureTestAudioCapture(void*, AudioPacket& packet) // { -// LDebug("onCaptureTestAudioCapture: ", packet.size()) +// LDebug("onCaptureTestAudioCapture: ", packet.size()); // //cv::imshow("Target", *packet.mat); // } // // void runAudioCaptureTest() // { -// LDebug("Running Audio Capture test...") +// LDebug("Running Audio Capture test..."); // // AudioCapture* capture = new AudioCapture(0, 1, 16000); // capture.attach(packetSlot(this, &Tests::onCaptureTestAudioCapture)); @@ -1558,7 +1566,7 @@ class RealtimeMediaQueueTest : public Test // StreamSocket& ss = socket(); // // fpsCounter.tick(); -// LDebug("On Video Packet Encoded: ", fpsCounter.fps) +// LDebug("On Video Packet Encoded: ", fpsCounter.fps); // // //if (fpsCounter.frames < 10) // // return; @@ -1585,7 +1593,7 @@ class RealtimeMediaQueueTest : public Test // // void runMediaSocketTest() // { -// LDebug("Running Media Socket Test") +// LDebug("Running Media Socket Test"); // // ServerSocket svs(666); // TCPServer srv(new TCPServerConnectionFactoryImpl(), @@ -1602,7 +1610,7 @@ class RealtimeMediaQueueTest : public Test // // void runCaptureRecorderTest() // { -// LDebug("Running Capture Encoder Test") +// LDebug("Running Capture Encoder Test"); // // av::EncoderOptions options; // options.ofile = "enctest.mp4"; @@ -1626,14 +1634,14 @@ class RealtimeMediaQueueTest : public Test // //scy::pause(); // enc.stop(); // -// LDebug("Running Capture Encoder Test: END") +// LDebug("Running Capture Encoder Test: END"); // } // // FPSCounter fpsCounter; // void onCaptureRecorderTestVideoEncoded(void* sender, MediaPacket& packet) // { // fpsCounter.tick(); -// LDebug("On Video Packet Encoded: ", fpsCounter.fps) +// LDebug("On Video Packet Encoded: ", fpsCounter.fps); // } // // // --------------------------------------------------------------------- @@ -1713,7 +1721,7 @@ class RealtimeMediaQueueTest : public Test // // void onFrame(void* sender, RawPacket& packet) // { -// LDebug("On packet: ", packet.size()) +// LDebug("On packet: ", packet.size()); // assert(!closed); // try // { @@ -1721,7 +1729,7 @@ class RealtimeMediaQueueTest : public Test // } // catch (std::exception& exc) // { -// LError("Capture Recorder Error: ", exc.what()) +// LError("Capture Recorder Error: ", exc.what()); // stop(); // } // } @@ -1745,7 +1753,7 @@ class RealtimeMediaQueueTest : public Test // av::Device dev; // auto& media = av::MediaFactory::instance(); // media.devices().getDefaultMicrophone(dev); -// LInfo("Default audio capture ", dev.id) +// LInfo("Default audio capture ", dev.id); // av::MediaCapture::Ptr audioCapture = media.createAudioCapture(0, // //dev.id // options.oformat.audio.channels, @@ -1813,7 +1821,7 @@ class RealtimeMediaQueueTest : public Test // av::Device dev; // auto& media = av::MediaFactory::instance(); // media.devices().getDefaultMicrophone(dev); -// LInfo("Default audio capture ", dev.id) +// LInfo("Default audio capture ", dev.id); // av::MediaCapture::Ptr audioCapture = media.createAudioCapture(0, // //dev.id // options.oformat.audio.channels, @@ -1837,6 +1845,230 @@ class RealtimeMediaQueueTest : public Test // }; +#ifdef HAVE_FFMPEG + +// ============================================================================= +// Standalone Video Encoder Test +// +// Generates synthetic YUV420P frames, encodes them with libx264, +// and verifies output packets are produced. +// +class VideoEncoderTest : public Test +{ + int numPacketsEncoded = 0; + + void run() + { + av::VideoEncoder encoder; + + encoder.iparams.width = 320; + encoder.iparams.height = 240; + encoder.iparams.pixelFmt = "yuv420p"; + + encoder.oparams.encoder = "libx264"; + encoder.oparams.pixelFmt = "yuv420p"; + encoder.oparams.width = 320; + encoder.oparams.height = 240; + encoder.oparams.fps = 25; + encoder.oparams.bitRate = 400000; + encoder.oparams.enabled = true; + + encoder.emitter += packetSlot(this, &VideoEncoderTest::onVideoEncoded); + encoder.create(); + encoder.open(); + + // Generate and encode synthetic frames + const int numFrames = 50; + for (int i = 0; i < numFrames; i++) { + AVFrame* frame = encoder.frame; + + // Fill Y plane with gradient pattern + for (int y = 0; y < encoder.iparams.height; y++) { + for (int x = 0; x < encoder.iparams.width; x++) { + frame->data[0][y * frame->linesize[0] + x] = + static_cast((x + y + i * 3) % 256); + } + } + // Fill U and V planes + for (int y = 0; y < encoder.iparams.height / 2; y++) { + for (int x = 0; x < encoder.iparams.width / 2; x++) { + frame->data[1][y * frame->linesize[1] + x] = + static_cast((128 + y + i * 2) % 256); + frame->data[2][y * frame->linesize[2] + x] = + static_cast((64 + x + i * 5) % 256); + } + } + + frame->pts = i; + encoder.encode(frame); + } + + encoder.flush(); + encoder.close(); + + LDebug("Video encoder test: encoded ", numPacketsEncoded, " packets from ", numFrames, " frames"); + expect(numPacketsEncoded > 0); + } + + void onVideoEncoded(av::VideoPacket& packet) + { + numPacketsEncoded++; + expect(packet.size() > 0); + expect(packet.width > 0); + expect(packet.height > 0); + } +}; + + +// ============================================================================= +// Standalone Video Decoder Test +// +// Decodes video frames from test.mp4, verifies frame dimensions and count. +// +class VideoDecoderTest : public Test +{ + int numFramesDecoded = 0; + + void run() + { + std::string inputFile = sampleDataDir("test.mp4"); + + // Open the file and find the video stream + AVFormatContext* formatCtx = nullptr; + if (avformat_open_input(&formatCtx, inputFile.c_str(), nullptr, nullptr) < 0) { + std::cout << "Cannot open " << inputFile << ", skipping..." << endl; + return; + } + if (avformat_find_stream_info(formatCtx, nullptr) < 0) { + avformat_close_input(&formatCtx); + std::cout << "Cannot find stream info, skipping..." << endl; + return; + } + + // Find video stream + AVStream* videoStream = nullptr; + for (unsigned i = 0; i < formatCtx->nb_streams; i++) { + if (formatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { + videoStream = formatCtx->streams[i]; + break; + } + } + expect(videoStream != nullptr); + + // Create decoder + av::VideoDecoder decoder(videoStream); + decoder.emitter += packetSlot(this, &VideoDecoderTest::onVideoDecoded); + decoder.create(); + decoder.open(); + + int width = decoder.oparams.width; + int height = decoder.oparams.height; + expect(width > 0); + expect(height > 0); + + // Decode all video packets + AVPacket* pkt = av_packet_alloc(); + while (av_read_frame(formatCtx, pkt) >= 0) { + if (pkt->stream_index == videoStream->index) { + decoder.decode(*pkt); + } + av_packet_unref(pkt); + } + decoder.flush(); + av_packet_free(&pkt); + + avformat_close_input(&formatCtx); + + LDebug("Video decoder test: decoded ", numFramesDecoded, " frames (", width, "x", height, ")"); + expect(numFramesDecoded > 0); + } + + void onVideoDecoded(av::VideoPacket& packet) + { + numFramesDecoded++; + expect(packet.width > 0); + expect(packet.height > 0); + expect(packet.size() > 0); + } +}; + + +// ============================================================================= +// Standalone Audio Decoder Test +// +// Decodes audio from test.mp4, verifies sample output. +// +class AudioDecoderTest : public Test +{ + int numFramesDecoded = 0; + + void run() + { + std::string inputFile = sampleDataDir("test.mp4"); + + // Open the file and find the audio stream + AVFormatContext* formatCtx = nullptr; + if (avformat_open_input(&formatCtx, inputFile.c_str(), nullptr, nullptr) < 0) { + std::cout << "Cannot open " << inputFile << ", skipping..." << endl; + return; + } + if (avformat_find_stream_info(formatCtx, nullptr) < 0) { + avformat_close_input(&formatCtx); + std::cout << "Cannot find stream info, skipping..." << endl; + return; + } + + // Find audio stream + AVStream* audioStream = nullptr; + for (unsigned i = 0; i < formatCtx->nb_streams; i++) { + if (formatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { + audioStream = formatCtx->streams[i]; + break; + } + } + + if (!audioStream) { + avformat_close_input(&formatCtx); + std::cout << "No audio stream in test file, skipping..." << endl; + return; + } + + // Create decoder + av::AudioDecoder decoder(audioStream); + decoder.emitter += packetSlot(this, &AudioDecoderTest::onAudioDecoded); + decoder.create(); + decoder.open(); + + expect(decoder.oparams.channels > 0); + expect(decoder.oparams.sampleRate > 0); + + // Decode all audio packets + AVPacket* pkt = av_packet_alloc(); + while (av_read_frame(formatCtx, pkt) >= 0) { + if (pkt->stream_index == audioStream->index) { + decoder.decode(*pkt); + } + av_packet_unref(pkt); + } + decoder.flush(); + av_packet_free(&pkt); + + avformat_close_input(&formatCtx); + + LDebug("Audio decoder test: decoded ", numFramesDecoded, " frames"); + expect(numFramesDecoded > 0); + } + + void onAudioDecoded(av::AudioPacket& packet) + { + numFramesDecoded++; + expect(packet.size() > 0); + } +}; + +#endif // HAVE_FFMPEG + + } // namespace scy diff --git a/src/base/CMakeLists.txt b/src/base/CMakeLists.txt index c6e7621c8..64d29751b 100644 --- a/src/base/CMakeLists.txt +++ b/src/base/CMakeLists.txt @@ -1,7 +1,3 @@ -ask_build_sourcey_module(base) -if(BUILD_MODULES OR (NOT BUILD_MODULES AND BUILD_MODULE_base)) - #include_dependency(SSL REQUIRED) - #include_dependency(LibUV REQUIRED) - - define_sourcey_module(base) -endif() +scy_add_module(base + PACKAGES uv_a Threads::Threads +) diff --git a/src/base/deprecated/src/thread.cpp b/src/base/deprecated/src/thread.cpp index a549e6d52..c6a953bcf 100644 --- a/src/base/deprecated/src/thread.cpp +++ b/src/base/deprecated/src/thread.cpp @@ -10,9 +10,9 @@ #include "scy/thread.h" +#include "assert.h" #include "scy/logger.h" #include "scy/platform.h" -#include "assert.h" #include diff --git a/src/base/include/scy/application.h b/src/base/include/scy/application.h index 6a3a5dc9c..a16589b2e 100644 --- a/src/base/include/scy/application.h +++ b/src/base/include/scy/application.h @@ -9,13 +9,12 @@ /// @{ -#ifndef SCY_Application_H -#define SCY_Application_H +#pragma once #include "scy/base.h" -#include "scy/util.h" #include "scy/loop.h" +#include "scy/util.h" #include #include @@ -82,6 +81,8 @@ class Base_API Application protected: Application(const Application&) = delete; Application& operator=(const Application&) = delete; + Application(Application&&) = delete; + Application& operator=(Application&&) = delete; static void onShutdownSignal(uv_signal_t* req, int signum); static void onPrintHandle(uv_handle_t* handle, void* arg); @@ -93,11 +94,11 @@ class Base_API Application // -typedef std::map OptionMap; +using OptionMap = std::map; struct Base_API OptionParser { - std::string exepath; // TODO: UTF8 + std::string exepath; OptionMap args; OptionParser(int argc, char* argv[], const char* delim); // "--" @@ -112,7 +113,8 @@ struct Base_API OptionParser return std::string(); } - template NumericType get(const char* key) + template + NumericType get(const char* key) { OptionMap::const_iterator it = args.find(key); if (it != args.end()) @@ -145,11 +147,10 @@ inline void onShutdownSignal(std::function callback = nullptr, uv_signal_init(loop, sig); uv_signal_start(sig, [](uv_signal_t* req, int /* signum */) { auto cmd = reinterpret_cast(req->data); - uv_close((uv_handle_t*)req, [](uv_handle_t* handle) { delete handle; }); + uv_close(reinterpret_cast(req), [](uv_handle_t* handle) { delete handle; }); if (cmd->callback) cmd->callback(cmd->opaque); - delete cmd; - }, SIGINT); + delete cmd; }, SIGINT); } @@ -164,7 +165,4 @@ inline void waitForShutdown(std::function callback = nullptr, } // namespace scy -#endif // SCY_Application_H - - /// @\} diff --git a/src/base/include/scy/base.h b/src/base/include/scy/base.h index b8c9b5d80..ccf555649 100644 --- a/src/base/include/scy/base.h +++ b/src/base/include/scy/base.h @@ -10,8 +10,7 @@ /// The `base` module contains reusable cross platform tools and utilities. -#ifndef SCY_H -#define SCY_H +#pragma once // Include build config @@ -19,14 +18,11 @@ // Shared library exports #if defined(SCY_WIN) && defined(SCY_SHARED_LIBRARY) - #if defined(Base_EXPORTS) - #define Base_API __declspec(dllexport) - #else - #define Base_API __declspec(dllimport) - #endif +#if defined(Base_EXPORTS) +#define Base_API __declspec(dllexport) #else - #define Base_API // nothing +#define Base_API __declspec(dllimport) +#endif +#else +#define Base_API // nothing #endif - - -#endif // SCY_H diff --git a/src/base/include/scy/base64.h b/src/base/include/scy/base64.h index a58128f83..21935999a 100644 --- a/src/base/include/scy/base64.h +++ b/src/base/include/scy/base64.h @@ -12,8 +12,7 @@ /// @{ -#ifndef SCY_Base64_H -#define SCY_Base64_H +#pragma once #include "scy/interface.h" @@ -28,8 +27,8 @@ namespace scy { namespace base64 { -const int BUFFER_SIZE = 16384; -const int LINE_LENGTH = 72; +constexpr int BUFFER_SIZE = 16384; +constexpr int LINE_LENGTH = 72; // @@ -40,16 +39,21 @@ const int LINE_LENGTH = 72; namespace internal { -typedef enum { step_A, step_B, step_C } encodestep; +enum encodestep +{ + step_A, + step_B, + step_C +}; -typedef struct +struct encodestate { encodestep step; char result; int stepcount; int linelength; // added int nullptrlterminate; // added -} encodestate; +}; Base_API void init_encodestate(internal::encodestate* state_in); @@ -76,39 +80,34 @@ struct Encoder : public basic::Encoder void encode(std::istream& istrm, std::ostream& ostrm) { const int N = _buffersize; - char* readbuf = new char[N]; - char* encbuf = new char[2 * N]; + auto readbuf = std::make_unique(N); + auto encbuf = std::make_unique(2 * N); ssize_t nread; ssize_t enclen; do { - istrm.read(readbuf, N); + istrm.read(readbuf.get(), N); nread = static_cast(istrm.gcount()); - enclen = encode(readbuf, nread, encbuf); - ostrm.write(encbuf, enclen); + enclen = encode(readbuf.get(), nread, encbuf.get()); + ostrm.write(encbuf.get(), enclen); } while (istrm.good() && nread > 0); - enclen = finalize(encbuf); - ostrm.write(encbuf, enclen); + enclen = finalize(encbuf.get()); + ostrm.write(encbuf.get(), enclen); internal::init_encodestate(&_state); - - delete[] encbuf; - delete[] readbuf; } void encode(const std::string& in, std::string& out) { - char* encbuf = new char[in.length() * 2]; - ssize_t enclen = encode(in.c_str(), in.length(), encbuf); - out.append(encbuf, enclen); + auto encbuf = std::make_unique(in.length() * 2); + ssize_t enclen = encode(in.c_str(), in.length(), encbuf.get()); + out.append(encbuf.get(), enclen); - enclen = finalize(encbuf); - out.append(encbuf, enclen); + enclen = finalize(encbuf.get()); + out.append(encbuf.get(), enclen); internal::init_encodestate(&_state); - - delete[] encbuf; } ssize_t encode(const char* inbuf, size_t nread, char* outbuf) override @@ -134,7 +133,7 @@ inline std::string encode(const T& bytes, int lineLength = LINE_LENGTH) { std::string res; res.reserve(bytes.size() * 2); - std::unique_ptr encbuf(new char[bytes.size() * 2]); + auto encbuf = std::make_unique(bytes.size() * 2); internal::encodestate state; internal::init_encodestate(&state); @@ -158,13 +157,19 @@ inline std::string encode(const T& bytes, int lineLength = LINE_LENGTH) namespace internal { -typedef enum { step_a, step_b, step_c, step_d } decodestep; +enum decodestep +{ + step_a, + step_b, + step_c, + step_d +}; -typedef struct +struct decodestate { decodestep step; char plainchar; -} decodestate; +}; Base_API void init_decodestate(internal::decodestate* state_in); @@ -196,22 +201,19 @@ struct Decoder : public basic::Decoder void decode(std::istream& istrm, std::ostream& ostrm) { const int N = _buffersize; - char* decbuf = new char[N]; - char* readbuf = new char[N]; + auto decbuf = std::make_unique(N); + auto readbuf = std::make_unique(N); size_t declen; size_t nread; do { - istrm.read((char*)decbuf, N); + istrm.read(decbuf.get(), N); declen = static_cast(istrm.gcount()); - nread = decode(decbuf, declen, readbuf); - ostrm.write((const char*)readbuf, nread); + nread = decode(decbuf.get(), declen, readbuf.get()); + ostrm.write(readbuf.get(), nread); } while (istrm.good() && declen > 0); internal::init_decodestate(&_state); - - delete[] decbuf; - delete[] readbuf; } internal::decodestate _state; @@ -225,7 +227,7 @@ inline std::string decode(const T& bytes) { std::string res; res.reserve(bytes.size() * 2); - std::unique_ptr encbuf(new char[bytes.size() * 2]); + auto encbuf = std::make_unique(bytes.size() * 2); internal::decodestate state; internal::init_decodestate(&state); @@ -242,7 +244,4 @@ inline std::string decode(const T& bytes) } // namespace scy -#endif // SCY_Base64_H - - /// @\} diff --git a/src/util/include/scy/util/base64packetencoder.h b/src/base/include/scy/base64packetencoder.h similarity index 61% rename from src/util/include/scy/util/base64packetencoder.h rename to src/base/include/scy/base64packetencoder.h index 9f700d726..d760d648b 100644 --- a/src/util/include/scy/util/base64packetencoder.h +++ b/src/base/include/scy/base64packetencoder.h @@ -5,12 +5,11 @@ // // SPDX-License-Identifier: LGPL-2.1+ // -/// @addtogroup util +/// @addtogroup base /// @{ -#ifndef SCY_HTTP_Base64PacketEncoder_H -#define SCY_HTTP_Base64PacketEncoder_H +#pragma once #include "scy/base64.h" @@ -22,7 +21,7 @@ namespace scy { -/// @addtogroup util +/// @addtogroup base class /* SCY_EXTERN */ Base64PacketEncoder : public PacketProcessor { public: @@ -33,15 +32,14 @@ class /* SCY_EXTERN */ Base64PacketEncoder : public PacketProcessor virtual void process(IPacket& packet) override { - RawPacket& p = dynamic_cast(packet); // cast or throw + auto& p = dynamic_cast(packet); // cast or throw base64::Encoder enc; std::vector result(packet.size() * 2); - size_t size = - enc.encode((const char*)p.data(), p.size(), &result[0]); - size += enc.finalize(&result[size]); + size_t size = enc.encode(p.data(), p.size(), result.data()); + size += enc.finalize(result.data() + size); - emit(&result[0], size); + emit(result.data(), size); } PacketSignal emitter; @@ -49,6 +47,3 @@ class /* SCY_EXTERN */ Base64PacketEncoder : public PacketProcessor } // namespace scy - - -#endif diff --git a/src/base/include/scy/bitwise.h b/src/base/include/scy/bitwise.h index 0840cf83f..117e69e4c 100644 --- a/src/base/include/scy/bitwise.h +++ b/src/base/include/scy/bitwise.h @@ -9,8 +9,7 @@ /// @{ -#ifndef SCY_Flaggable_H -#define SCY_Flaggable_H +#pragma once #include "scy/base.h" @@ -43,44 +42,7 @@ struct Bitwise }; -#if 0 -class Flaggable -{ -public: - Flaggable(unsigned flags = 0) : _flags(flags) {} - Flaggable(const Flaggable& r) : _flags(r._flags) {} - Flaggable(const Flags& r) : _flags(r) {} - - virtual void setFlag(unsigned flag) { - _flags.set(flag); - }; - virtual void addFlag(unsigned flag) { - _flags.add(flag); - }; - virtual void removeFlag(unsigned flag) { - _flags.remove(flag); - }; - virtual void toggleFlag(unsigned flag) { - _flags.toggle(flag); - }; - virtual bool hasFlag(unsigned flag) const { - return _flags.has(flag); - }; - virtual void setFlags(Flags flags) { - _flags = flags; - }; - virtual Flags flags() const { return _flags; }; - -protected: - Flags _flags; -}; -#endif - - } // namespace scy -#endif // SCY_Flaggable_H - - /// @\} diff --git a/src/base/include/scy/buffer.h b/src/base/include/scy/buffer.h index b89642ed6..e16193fe2 100644 --- a/src/base/include/scy/buffer.h +++ b/src/base/include/scy/buffer.h @@ -9,16 +9,15 @@ /// @{ -#ifndef SCY_Buffer_H -#define SCY_Buffer_H +#pragma once #include "scy/base.h" #include "scy/byteorder.h" #include -#include #include +#include #include #include @@ -27,7 +26,7 @@ namespace scy { /// Core buffer type. -typedef std::vector Buffer; +using Buffer = std::vector; // @@ -42,24 +41,24 @@ class Base_API MutableBuffer { public: /// Construct an empty buffer. - MutableBuffer() - : _data(0) + constexpr MutableBuffer() + : _data(nullptr) , _size(0) { } /// Construct a buffer to represent the given memory range. - MutableBuffer(void* data, size_t size) + constexpr MutableBuffer(void* data, size_t size) : _data(data) , _size(size) { } - void* data() const { return _data; } - size_t size() const { return _size; } + [[nodiscard]] constexpr void* data() const { return _data; } + [[nodiscard]] constexpr size_t size() const { return _size; } /// Cast the buffer as a char pointer. - char* cstr() const { return reinterpret_cast(_data); } + [[nodiscard]] char* cstr() const { return reinterpret_cast(_data); } /// Returns the buffer as a string. std::string str() const { return std::string(cstr(), size()); } @@ -124,31 +123,31 @@ class Base_API ConstBuffer { public: /// Construct an empty buffer. - ConstBuffer() - : _data(0) + constexpr ConstBuffer() + : _data(nullptr) , _size(0) { } /// Construct a buffer to represent the given memory range. - ConstBuffer(const void* data, size_t size) + constexpr ConstBuffer(const void* data, size_t size) : _data(data) , _size(size) { } /// Construct a non-modifiable buffer from a modifiable one. - ConstBuffer(const MutableBuffer& b) + constexpr ConstBuffer(const MutableBuffer& b) : _data(b.data()) , _size(b.size()) { } - const void* data() const { return _data; } - size_t size() const { return _size; } + [[nodiscard]] constexpr const void* data() const { return _data; } + [[nodiscard]] constexpr size_t size() const { return _size; } /// Cast the buffer as a const char pointer. - const char* cstr() const { return reinterpret_cast(_data); } + [[nodiscard]] const char* cstr() const { return reinterpret_cast(_data); } /// Returns the buffer as a string. std::string str() const { return std::string(cstr(), size()); } @@ -176,7 +175,7 @@ inline ConstBuffer constBuffer(const std::vector& vec) return ConstBuffer(reinterpret_cast(&vec[0]), vec.size()); // careful! } -inline ConstBuffer constBuffer(const MutableBuffer& buf) +inline constexpr ConstBuffer constBuffer(const MutableBuffer& buf) { return ConstBuffer(buf.data(), buf.size()); } @@ -201,7 +200,7 @@ inline ConstBuffer constBuffer(const Buffer& buf) /// Cast a non-modifiable buffer to a specified pointer to POD type. template -inline PointerToPodType bufferCast(const MutableBuffer& b) +inline constexpr PointerToPodType bufferCast(const MutableBuffer& b) { return static_cast(b.data()); } @@ -209,7 +208,7 @@ inline PointerToPodType bufferCast(const MutableBuffer& b) /// Cast a non-modifiable buffer to a specified pointer to POD type. template -inline PointerToPodType bufferCast(const ConstBuffer& b) +inline constexpr PointerToPodType bufferCast(const ConstBuffer& b) { return static_cast(b.data()); } @@ -273,17 +272,17 @@ class Base_API BitReader void skip(size_t size); /// Returns the read limit. - size_t limit() const; + [[nodiscard]] size_t limit() const; /// Returns the current read position. - size_t position() const { return _position; } + [[nodiscard]] size_t position() const { return _position; } /// Returns the number of elements between the current position and the /// limit. - size_t available() const; + [[nodiscard]] size_t available() const; - const char* begin() const { return _bytes; } - const char* current() const { return _bytes + _position; } + [[nodiscard]] const char* begin() const { return _bytes; } + [[nodiscard]] const char* current() const { return _bytes + _position; } ByteOrder order() const { return _order; } @@ -353,20 +352,20 @@ class Base_API BitWriter void skip(size_t size); /// Returns the write limit. - size_t limit() const; + [[nodiscard]] size_t limit() const; /// Returns the current write position. - size_t position() const { return _position; } + [[nodiscard]] size_t position() const { return _position; } /// Returns the number of elements between the current write position and /// the limit. - size_t available() const; + [[nodiscard]] size_t available() const; - char* begin() { return _bytes; } - char* current() { return _bytes + _position; } + [[nodiscard]] char* begin() { return _bytes; } + [[nodiscard]] char* current() { return _bytes + _position; } - const char* begin() const { return _bytes; } - const char* current() const { return _bytes + _position; } + [[nodiscard]] const char* begin() const { return _bytes; } + [[nodiscard]] const char* current() const { return _bytes + _position; } ByteOrder order() const { return _order; } @@ -417,9 +416,3 @@ class Base_API DynamicBitWriter : public BitWriter } // namespace scy - - -#endif // SCY_Buffer_H - - -/// @\} diff --git a/src/base/include/scy/byteorder.h b/src/base/include/scy/byteorder.h index 9ef765062..cf72c6508 100644 --- a/src/base/include/scy/byteorder.h +++ b/src/base/include/scy/byteorder.h @@ -9,8 +9,7 @@ /// @{ -#ifndef SCY_ByteOrder_H -#define SCY_ByteOrder_H +#pragma once #include @@ -21,7 +20,7 @@ #endif #ifdef SCY_WIN -#include +#include #endif @@ -74,7 +73,7 @@ inline void setBE64(void* memory, uint64_t v) inline uint16_t getBE16(const void* memory) { return static_cast((get8(memory, 0) << 8) | - (get8(memory, 1) << 0)); + (get8(memory, 1) << 0)); } inline uint32_t getBE32(const void* memory) @@ -126,7 +125,7 @@ inline void setLE64(void* memory, uint64_t v) inline uint16_t getLE16(const void* memory) { return static_cast((get8(memory, 0) << 0) | - (get8(memory, 1) << 8)); + (get8(memory, 1) << 8)); } inline uint32_t getLE32(const void* memory) @@ -196,7 +195,4 @@ inline uint64_t networkToHost64(uint64_t n) } // namespace scy -#endif // SCY_ByteOrder_H - - /// @\} diff --git a/src/base/include/scy/collection.h b/src/base/include/scy/collection.h index dc0a44730..490bc773c 100644 --- a/src/base/include/scy/collection.h +++ b/src/base/include/scy/collection.h @@ -9,8 +9,7 @@ /// @{ -#ifndef SCY_Containers_H -#define SCY_Containers_H +#pragma once #include "scy/base.h" @@ -18,9 +17,11 @@ #include "scy/signal.h" #include "scy/util.h" -#include +#include #include -#include +#include +#include +#include #include #include @@ -30,10 +31,11 @@ namespace scy { /// AbstractCollection is an abstract interface for managing a /// key-value store of indexed pointers. -template class AbstractCollection +template +class AbstractCollection { public: - AbstractCollection(){}; + AbstractCollection() {}; virtual ~AbstractCollection() {} virtual bool add(const TKey& key, TValue* item, bool whiny = true) = 0; @@ -54,18 +56,13 @@ template class AbstractCollection // -/// This collection is used to maintain an map of any pointer -/// type indexed by key value in a thread-safe way. -/// -/// This class allows for custom memory handling of managed -/// pointers via the TDeleter argument. -template > +/// This collection is used to maintain a map of unique_ptr +/// values indexed by key in a thread-safe way. +template class /* Base_API */ PointerCollection : public AbstractCollection { public: - typedef std::map Map; - typedef TDeleter Deleter; + using Map = std::map>; public: PointerCollection() {} @@ -73,42 +70,43 @@ class /* Base_API */ PointerCollection : public AbstractCollection virtual ~PointerCollection() { clear(); } virtual bool add(const TKey& key, TValue* item, bool whiny = true) override + { + return add(key, std::unique_ptr(item), whiny); + } + + virtual bool add(const TKey& key, std::unique_ptr item, bool whiny = true) { if (exists(key)) { - if (whiny) { - // std::ostringstream ss; - // ss << "An item already exists: " << key << std::endl; + if (whiny) throw std::runtime_error("Item already exists"); - } return false; } + auto* raw = item.get(); { - std::lock_guard guard(_mutex); - _map[key] = item; + std::unique_lock guard(_mutex); + _map[key] = std::move(item); } - onAdd(key, item); + onAdd(key, raw); return true; } - virtual void update(const TKey& key, TValue* item) + virtual void update(const TKey& key, std::unique_ptr item) { - // Note: This method will not delete existing values. + auto* raw = item.get(); { - std::lock_guard guard(_mutex); - _map[key] = item; + std::unique_lock guard(_mutex); + _map[key] = std::move(item); } - onAdd(key, item); + onAdd(key, raw); } virtual TValue* get(const TKey& key, bool whiny = true) const override { - std::lock_guard guard(_mutex); - typename Map::const_iterator it = _map.find(key); + std::shared_lock guard(_mutex); + auto it = _map.find(key); if (it != _map.end()) { - return it->second; + return it->second.get(); } else if (whiny) { - // std::ostringstream ss; - // ss << "Invalid item requested: " << key << std::endl; throw std::runtime_error("Item not found"); } @@ -117,65 +115,75 @@ class /* Base_API */ PointerCollection : public AbstractCollection virtual bool free(const TKey& key) override { - TValue* item = remove(key); - if (item) { - TDeleter func; - func(item); - return true; + std::unique_ptr item; + TValue* raw = nullptr; + { + std::unique_lock guard(_mutex); + auto it = _map.find(key); + if (it != _map.end()) { + raw = it->second.get(); + item = std::move(it->second); + _map.erase(it); + } } - return false; + if (raw) + onRemove(key, raw); + // item is destroyed here via unique_ptr + return raw != nullptr; } virtual TValue* remove(const TKey& key) override { - TValue* item = nullptr; + TValue* raw = nullptr; + std::unique_ptr owned; { - std::lock_guard guard(_mutex); - typename Map::iterator it = _map.find(key); + std::unique_lock guard(_mutex); + auto it = _map.find(key); if (it != _map.end()) { - item = it->second; + owned = std::move(it->second); + raw = owned.release(); // caller takes ownership _map.erase(it); } } - if (item) - onRemove(key, item); - return item; + if (raw) + onRemove(key, raw); + return raw; } virtual bool remove(const TValue* item) override { TKey key; - TValue* ptr = nullptr; + TValue* raw = nullptr; + std::unique_ptr owned; { - std::lock_guard guard(_mutex); - for (typename Map::iterator it = _map.begin(); it != _map.end(); - ++it) { - if (item == it->second) { + std::unique_lock guard(_mutex); + for (auto it = _map.begin(); it != _map.end(); ++it) { + if (item == it->second.get()) { key = it->first; - ptr = it->second; + raw = it->second.get(); + owned = std::move(it->second); _map.erase(it); break; } } } - if (ptr) - onRemove(key, ptr); - return ptr != nullptr; + if (raw) + onRemove(key, raw); + // owned is destroyed here via unique_ptr + return raw != nullptr; } virtual bool exists(const TKey& key) const override { - std::lock_guard guard(_mutex); - typename Map::const_iterator it = _map.find(key); - return it != _map.end(); + std::shared_lock guard(_mutex); + return _map.find(key) != _map.end(); } virtual bool exists(const TValue* item) const override { - std::lock_guard guard(_mutex); - for (typename Map::const_iterator it = _map.begin(); it != _map.end(); - ++it) { - if (item == it->second) + std::shared_lock guard(_mutex); + for (const auto& [key, val] : _map) { + if (item == val.get()) return true; } return false; @@ -183,31 +191,31 @@ class /* Base_API */ PointerCollection : public AbstractCollection virtual bool empty() const override { - std::lock_guard guard(_mutex); + std::shared_lock guard(_mutex); return _map.empty(); } virtual size_t size() const override { - std::lock_guard guard(_mutex); + std::shared_lock guard(_mutex); return _map.size(); } virtual void clear() override { - std::lock_guard guard(_mutex); - util::clearMap(_map); + std::unique_lock guard(_mutex); + _map.clear(); } - virtual Map map() const + virtual Map& map() { - std::lock_guard guard(_mutex); + std::unique_lock guard(_mutex); return _map; } - virtual Map& map() + virtual const Map& map() const { - std::lock_guard guard(_mutex); + std::shared_lock guard(_mutex); return _map; } @@ -222,7 +230,7 @@ class /* Base_API */ PointerCollection : public AbstractCollection } protected: - mutable std::mutex _mutex; + mutable std::shared_mutex _mutex; Map _map; }; @@ -232,12 +240,11 @@ class /* Base_API */ PointerCollection : public AbstractCollection // -template > -class /* Base_API */ LiveCollection : public PointerCollection +template +class /* Base_API */ LiveCollection : public PointerCollection { public: - typedef PointerCollection Base; + using Base = PointerCollection; public: virtual void onAdd(const TKey&, TValue* item) override @@ -265,7 +272,7 @@ template class /* Base_API */ KVCollection { public: - typedef std::map Map; + using Map = std::map; public: KVCollection() @@ -366,9 +373,9 @@ class Base_API NVCollection } }; - typedef std::multimap Map; - typedef Map::iterator Iterator; - typedef Map::const_iterator ConstIterator; + using Map = std::multimap; + using Iterator = Map::iterator; + using ConstIterator = Map::const_iterator; NVCollection() { @@ -379,12 +386,18 @@ class Base_API NVCollection { } + NVCollection(NVCollection&& nvc) noexcept + : _map(std::move(nvc._map)) + { + } + virtual ~NVCollection() { } /// Assigns the name-value pairs of another NVCollection to this one. NVCollection& operator=(const NVCollection& nvc); + NVCollection& operator=(NVCollection&& nvc) noexcept; /// Returns the value of the (first) name-value pair with the given name. /// @@ -441,14 +454,11 @@ class Base_API NVCollection }; -typedef std::map StringMap; -typedef std::vector StringVec; +using StringMap = std::map; +using StringVec = std::vector; } // namespace scy -#endif // SCY_Containers_H - - /// @\} diff --git a/src/base/include/scy/configuration.h b/src/base/include/scy/configuration.h index 1861131af..d94da720f 100644 --- a/src/base/include/scy/configuration.h +++ b/src/base/include/scy/configuration.h @@ -9,14 +9,13 @@ /// @{ -#ifndef SCY_Configuration_H -#define SCY_Configuration_H +#pragma once #include "scy/base.h" #include "scy/signal.h" -#include #include +#include namespace scy { @@ -157,6 +156,8 @@ class Base_API Configuration protected: Configuration(const Configuration&) = delete; Configuration& operator=(const Configuration&) = delete; + Configuration(Configuration&&) = delete; + Configuration& operator=(Configuration&&) = delete; private: mutable std::mutex _mutex; @@ -219,9 +220,6 @@ class Base_API ScopedConfiguration } // namespace scy -#endif // SCY_Configuration_H - - /// @\} diff --git a/src/base/include/scy/datetime.h b/src/base/include/scy/datetime.h index aa43c32d2..adf8f7484 100644 --- a/src/base/include/scy/datetime.h +++ b/src/base/include/scy/datetime.h @@ -12,8 +12,7 @@ // -#ifndef SCY_DateTime_H -#define SCY_DateTime_H +#pragma once #include "scy/base.h" @@ -39,9 +38,9 @@ namespace scy { class Base_API Timestamp { public: - typedef std::int64_t TimeVal; ///< monotonic UTC time value in microsecond resolution - typedef std::int64_t UtcTimeVal; ///< monotonic UTC time value in 100 nanosecond resolution - typedef std::int64_t TimeDiff; ///< difference between two timestamps in microseconds + using TimeVal = std::int64_t; ///< monotonic UTC time value in microsecond resolution + using UtcTimeVal = std::int64_t; ///< monotonic UTC time value in 100 nanosecond resolution + using TimeDiff = std::int64_t; ///< difference between two timestamps in microseconds /// Creates a timestamp with the current time. Timestamp(); @@ -122,7 +121,7 @@ class Base_API Timestamp class Base_API Timespan { public: - typedef Timestamp::TimeDiff TimeDiff; + using TimeDiff = Timestamp::TimeDiff; /// Creates a zero Timespan. Timespan(); @@ -1779,9 +1778,6 @@ class Base_API Stopwatch } // namespace scy -#endif // SCY_DateTime_H - - /// @\} diff --git a/src/base/include/scy/delegate.h b/src/base/include/scy/delegate.h index 295660233..41eb3aa88 100644 --- a/src/base/include/scy/delegate.h +++ b/src/base/include/scy/delegate.h @@ -9,8 +9,7 @@ /// @{ -#ifndef SCY_Delegate_H -#define SCY_Delegate_H +#pragma once #include @@ -156,7 +155,4 @@ struct PolymorphicDelegate : AbstractDelegate } // namespace scy -#endif // SCY_Delegate_H - - /// @\} diff --git a/src/util/include/scy/util/diagnosticmanager.h b/src/base/include/scy/diagnosticmanager.h similarity index 86% rename from src/util/include/scy/util/diagnosticmanager.h rename to src/base/include/scy/diagnosticmanager.h index 81c81eddd..8d5c4ad49 100644 --- a/src/util/include/scy/util/diagnosticmanager.h +++ b/src/base/include/scy/diagnosticmanager.h @@ -5,12 +5,11 @@ // // SPDX-License-Identifier: LGPL-2.1+ // -/// @addtogroup util +/// @addtogroup base /// @{ -#ifndef SCY_DiagnosticManager_H -#define SCY_DiagnosticManager_H +#pragma once #include "scy/collection.h" @@ -61,8 +60,8 @@ class /* SCY_EXTERN */ IDiagnostic : public Stateful IDiagnostic(); virtual ~IDiagnostic(); - std::string name; ///< The name of the diagnostic. - std::string description; ///< The diagnostic description. + std::string name; ///< The name of the diagnostic. + std::string description; ///< The diagnostic description. std::vector summary; ///< The diagnostic summary, maybe including ///< troubleshooting information on failure. @@ -90,7 +89,7 @@ class /* SCY_EXTERN */ IDiagnostic : public Stateful }; -typedef PointerCollection DiagnosticStore; +using DiagnosticStore = PointerCollection; // @@ -98,10 +97,11 @@ typedef PointerCollection DiagnosticStore; // -class /* SCY_EXTERN */ AsyncDiagnostic : public IDiagnostic, public basic::Runnable +class /* SCY_EXTERN */ AsyncDiagnostic : public IDiagnostic + , public basic::Runnable { public: - virtual ~AsyncDiagnostic(){}; + virtual ~AsyncDiagnostic() {}; virtual void run() = 0; @@ -154,7 +154,4 @@ class /* SCY_EXTERN */ DiagnosticManager : public DiagnosticStore } // namespace scy -#endif // SCY_DiagnosticManager_H - - /// @\} diff --git a/src/base/include/scy/error.h b/src/base/include/scy/error.h index e26d03961..3ca5ba646 100644 --- a/src/base/include/scy/error.h +++ b/src/base/include/scy/error.h @@ -9,8 +9,7 @@ /// @{ -#ifndef SCY_Error_H -#define SCY_Error_H +#pragma once #include "scy/base.h" @@ -103,7 +102,4 @@ inline void throwError(std::string message, int err = UV_UNKNOWN) } // namespace scy -#endif // SCY_Error_H - - /// @\} diff --git a/src/base/include/scy/filesystem.h b/src/base/include/scy/filesystem.h index 137fb7a32..96a7ffacd 100644 --- a/src/base/include/scy/filesystem.h +++ b/src/base/include/scy/filesystem.h @@ -9,25 +9,24 @@ /// @{ -#ifndef SCY_FileSystem_H -#define SCY_FileSystem_H +#pragma once #include "scy/base.h" +#include #include #include -#include namespace scy { namespace fs { -/// The platform specific path split separator: -/// "/" on unix and '\\' on windows. +/// The platform specific path separator string: +/// "/" on unix and "\\" on windows. Base_API extern const char* separator; -/// The platform specific path split delimiter: +/// The platform specific path separator character: /// '/' on unix and '\\' on windows. Base_API extern const char delimiter; @@ -40,13 +39,14 @@ Base_API std::string basename(const std::string& path); /// Returns the directory part of the path. Base_API std::string dirname(const std::string& path); -/// Returns the file extension part of the path. -Base_API std::string extname(const std::string& path, bool includeDot = false); +/// Returns the file extension part of the path (including dot). +/// If `includeDot` is false, the leading dot is stripped. +Base_API std::string extname(const std::string& path, bool includeDot = true); /// Returns true if the file or directory exists. Base_API bool exists(const std::string& path); -/// Returns true if the directory exists on the system. +/// Returns true if the path is a directory. Base_API bool isdir(const std::string& path); /// Returns the size in bytes of the given file, or -1 if file doesn't exist. @@ -61,7 +61,7 @@ Base_API void mkdir(const std::string& path, int mode = 0755); /// Creates a directory recursively. Base_API void mkdirr(const std::string& path, int mode = 0755); -/// Creates a directory. +/// Removes a directory. Base_API void rmdir(const std::string& path); /// Deletes a file. @@ -78,11 +78,14 @@ Base_API void addsep(std::string& path); /// If the given path has no trailing separator one will be appended. Base_API void addnode(std::string& path, const std::string& node); -/// Normalizes a path for the current opearting system. -/// Currently this function only converts directory separators to native style. +/// Builds a path from a base and one or more nodes. +Base_API std::string makePath(const std::string& base, const std::string& node); + +/// Normalizes a path, resolving `.` and `..` segments and +/// converting separators to the native style. Base_API std::string normalize(const std::string& path); -/// Transcodes the path to into windows native format if using windows +/// Transcodes the path to windows native format if using windows /// and if LibSourcey was compiled with Unicode support (SCY_UNICODE), /// otherwise the path string is returned unchanged. Base_API std::string transcode(const std::string& path); @@ -90,17 +93,12 @@ Base_API std::string transcode(const std::string& path); /// Saves the given data buffer to the output file path. /// Returns true on success, or if whiny is set then an /// exception will be thrown on error. -Base_API bool savefile(const std::string& path, const char* data, - size_t size, bool whiny = false); - -// TODO: Implement more libuv fs_* types +Base_API bool savefile(const std::string& path, const char* data, + size_t size, bool whiny = false); } // namespace fs } // namespace scy -#endif - - /// @\} diff --git a/src/base/include/scy/handle.h b/src/base/include/scy/handle.h index 9ceb635c3..e917895e1 100644 --- a/src/base/include/scy/handle.h +++ b/src/base/include/scy/handle.h @@ -9,8 +9,7 @@ /// @{ -#ifndef SCY_UV_Handle_H -#define SCY_UV_Handle_H +#pragma once #include "scy/base.h" @@ -19,9 +18,9 @@ #include "uv.h" -#include #include -#include +#include +#include namespace scy { @@ -33,7 +32,7 @@ class Base_API Handle; /// Shared `libuv` handle context. -template +template struct Context { Handle* handle = nullptr; @@ -52,8 +51,7 @@ struct Context uv_close(reinterpret_cast(ptr), [](uv_handle_t* handle) { delete handle; }); - } - else { + } else { delete ptr; } } @@ -64,7 +62,7 @@ struct Context /// /// This class manages the handle during it's lifecycle and safely handles the /// asynchronous destruction mechanism. -template +template class Base_API Handle { public: @@ -79,12 +77,12 @@ class Base_API Handle } /// Initialize the handle. - template + template bool init(F&& f, Args&&... args) { assertThread(); - assert(_context); - assert(!initialized()); + if (!_context || initialized()) + throw std::logic_error("Handle not in valid state for initialization"); int err = std::forward(f)(loop(), get(), std::forward(args)...); if (err) setUVError(err, "Initialization failed"); @@ -94,11 +92,12 @@ class Base_API Handle } /// Invoke a method on the handle. - template + template bool invoke(F&& f, Args&&... args) //, const std::string& prefix = "UV Error") { assertThread(); - assert(initialized()); + if (!initialized()) + throw std::logic_error("Handle not initialized"); int err = std::forward(f)(std::forward(args)...); if (err) setUVError(err, "UV Error"); @@ -108,11 +107,12 @@ class Base_API Handle /// Invoke a method on the handle. /// /// An exception will be thrown if the invoked method returns an error. - template + template void invokeOrThrow(const std::string& message, F&& f, Args&&... args) { assertThread(); - assert(initialized()); + if (!initialized()) + throw std::logic_error("Handle not initialized"); int err = std::forward(f)(std::forward(args)...); if (err) setAndThrowError(message, err); @@ -217,12 +217,6 @@ class Base_API Handle return _loop; } - /// Return a pointer to the current or derived instance. - virtual void* self() - { - return this; - } - /// Reset the internal handle pointer and container state. void reset() { @@ -254,12 +248,13 @@ class Base_API Handle /// Assert the call is from the parent event loop thread. void assertThread() const { - // assert(uv_thread_equal(&_tid, &uv_thread_self())); - assert(std::this_thread::get_id() == _tid); + if (std::this_thread::get_id() != _tid) { + throw std::logic_error("Handle accessed from wrong thread"); + } } /// Define the native handle type. - typedef T Type; + using Type = T; protected: /// Error callback. @@ -279,6 +274,8 @@ class Base_API Handle /// NonCopyable and NonMovable Handle(const Handle&) = delete; Handle& operator=(const Handle&) = delete; + Handle(Handle&&) = delete; + Handle& operator=(Handle&&) = delete; uv::Loop* _loop; std::shared_ptr> _context; @@ -291,7 +288,4 @@ class Base_API Handle } // namespace scy -#endif // SCY_UV_Handle - - /// @\} diff --git a/src/base/include/scy/hex.h b/src/base/include/scy/hex.h index 4fdedfab4..28a0ac36d 100644 --- a/src/base/include/scy/hex.h +++ b/src/base/include/scy/hex.h @@ -9,14 +9,13 @@ /// @{ -#ifndef SCY_Hex_H -#define SCY_Hex_H +#pragma once #include "scy/error.h" #include "scy/interface.h" #include "scy/logger.h" -#include +#include #include #include @@ -61,7 +60,7 @@ struct Encoder : public basic::Encoder return nwrite; } - virtual ssize_t finalize(char* /* outbuf */) override { return 0; } + virtual ssize_t finalize(char* /* outbuf */) override { return 0; } void setUppercase(bool flag) { _uppercase = flag ? 16 : 0; } @@ -171,7 +170,4 @@ struct Decoder : public basic::Decoder } // namespace scy -#endif // SCY_Hex_H - - /// @\} diff --git a/src/base/include/scy/idler.h b/src/base/include/scy/idler.h index 0e0f54a28..c62324557 100644 --- a/src/base/include/scy/idler.h +++ b/src/base/include/scy/idler.h @@ -9,14 +9,14 @@ /// @{ -#ifndef SCY_Idler_H -#define SCY_Idler_H +#pragma once #include "scy/base.h" -#include "scy/runner.h" #include "scy/handle.h" +#include "scy/runner.h" +#include #include @@ -35,7 +35,7 @@ class Base_API Idler : public Runner Idler(uv::Loop* loop = uv::defaultLoop()); /// Create and start the idler with the given callback. - template + template explicit Idler(Function&& func, Args&&... args) : _handle(uv::defaultLoop()) { @@ -44,7 +44,7 @@ class Base_API Idler : public Runner } /// Create and start the idler with the given callback and event loop. - template + template explicit Idler(uv::Loop* loop, Function&& func, Args&&... args) : _handle(loop) { @@ -53,10 +53,10 @@ class Base_API Idler : public Runner } /// Start the idler with the given callback function. - template + template void start(Function&& func, Args&&... args) { - typedef internal::DeferredCallable Callback; + using Callback = internal::DeferredCallable; assert(!_handle.active()); assert(!_handle.active()); @@ -72,17 +72,16 @@ class Base_API Idler : public Runner std::forward(func), std::forward(args)...); _handle.invoke(&uv_idle_start, _handle.get(), - [](uv_idle_t* req) { - auto wrap = reinterpret_cast(req->data); - if (!wrap->ctx->cancelled) { - wrap->invoke(); - } - else { - wrap->ctx->running = false; - uv_idle_stop(req); - delete wrap; - } - }); + [](uv_idle_t* req) { + auto wrap = reinterpret_cast(req->data); + if (!wrap->ctx->cancelled) { + wrap->invoke(); + } else { + wrap->ctx->running = false; + uv_idle_stop(req); + delete wrap; + } + }); _handle.throwLastError("Cannot start idler"); } @@ -105,7 +104,4 @@ class Base_API Idler : public Runner } // namespace scy -#endif // SCY_Idler_H - - /// @\} diff --git a/src/base/include/scy/interface.h b/src/base/include/scy/interface.h index 56d9f29dc..b64489c3f 100644 --- a/src/base/include/scy/interface.h +++ b/src/base/include/scy/interface.h @@ -9,8 +9,7 @@ /// @{ -#ifndef SCY_Interfaces_H -#define SCY_Interfaces_H +#pragma once #include "scy/base.h" @@ -105,7 +104,4 @@ class Base_API Sendable } // namespace scy -#endif // SCY_Interfaces_H - - /// @\} diff --git a/src/base/include/scy/ipc.h b/src/base/include/scy/ipc.h index 8afeb0f82..8a0eed363 100644 --- a/src/base/include/scy/ipc.h +++ b/src/base/include/scy/ipc.h @@ -9,16 +9,17 @@ /// @{ -#ifndef SCY_IPC_H -#define SCY_IPC_H +#pragma once #include "scy/base.h" #include "scy/synchronizer.h" -#include +#include #include +#include #include +#include namespace scy { @@ -31,7 +32,7 @@ namespace ipc { /// Default action type for executing synchronized callbacks. struct Action { - typedef std::function Callback; + using Callback = std::function; Callback target; void* arg; @@ -88,18 +89,19 @@ class Queue virtual void post() {} - void waitForSync() + void waitForSync(std::chrono::milliseconds timeout = std::chrono::milliseconds(5000)) { - // TODO: impose a time limit - while (true) { + auto deadline = std::chrono::steady_clock::now() + timeout; + while (std::chrono::steady_clock::now() < deadline) { { std::lock_guard guard(_mutex); if (_actions.empty()) return; } - LDebug("Wait for sync") - scy::sleep(10); + LDebug("Wait for sync"); + std::this_thread::sleep_for(std::chrono::milliseconds(10)); } + LWarn("waitForSync timed out after ", timeout.count(), "ms"); } protected: @@ -134,15 +136,12 @@ class SyncQueue : public Queue }; -typedef ipc::Queue ActionQueue; -typedef ipc::SyncQueue ActionSyncQueue; +using ActionQueue = ipc::Queue; +using ActionSyncQueue = ipc::SyncQueue; } // namespace ipc } // namespace scy -#endif - - /// @\} diff --git a/src/util/include/scy/util/iregistry.h b/src/base/include/scy/iregistry.h similarity index 70% rename from src/util/include/scy/util/iregistry.h rename to src/base/include/scy/iregistry.h index abf6ab45f..84a50030e 100644 --- a/src/util/include/scy/util/iregistry.h +++ b/src/base/include/scy/iregistry.h @@ -5,12 +5,11 @@ // // SPDX-License-Identifier: LGPL-2.1+ // -/// @addtogroup util +/// @addtogroup base /// @{ -#ifndef SCY_IRegistry_H -#define SCY_IRegistry_H +#pragma once #include "scy/signal.h" @@ -21,25 +20,31 @@ namespace scy { -template class IRegistry +template +class IRegistry { - template ItemT* createT() { return new T(); } + template + static ItemT* createT() + { + return new T(); + } public: - typedef std::map TypeMap; + using TypeMap = std::map; IRegistry() = default; virtual ~IRegistry() = default; virtual ItemT* createInstance(const std::string& s) { - TypeMap::iterator it = _types.find(s); + typename TypeMap::iterator it = _types.find(s); if (it == _types.end()) - return NULL; + return nullptr; return it->second(); } - template void registerType(const std::string& s) + template + void registerType(const std::string& s) { _types.insert(std::make_pair(s, &createT)); TypeRegistered.emit(s); @@ -67,7 +72,4 @@ template class IRegistry } // namespace scy -#endif // SCY_IRegistry_H - - /// @\} diff --git a/src/base/include/scy/logger.h b/src/base/include/scy/logger.h index 1d8795981..c9fe8ad5b 100644 --- a/src/base/include/scy/logger.h +++ b/src/base/include/scy/logger.h @@ -9,8 +9,7 @@ /// @{ -#ifndef SCY_Logger_H -#define SCY_Logger_H +#pragma once #include "scy/base.h" @@ -19,14 +18,15 @@ #include "scy/singleton.h" #include "scy/thread.h" +#include #include #include #include #include #include -#include +#include #include -#include +#include namespace scy { @@ -98,7 +98,7 @@ class Base_API LogWriter virtual ~LogWriter(); /// Writes the given log message stream. - virtual void write(LogStream* stream); + virtual void write(std::unique_ptr stream); }; @@ -108,14 +108,15 @@ class Base_API LogWriter /// Thread based log output stream writer. -class Base_API AsyncLogWriter : public LogWriter, public basic::Runnable +class Base_API AsyncLogWriter : public LogWriter + , public basic::Runnable { public: AsyncLogWriter(); virtual ~AsyncLogWriter(); /// Queues the given log message stream. - virtual void write(LogStream* stream) override; + virtual void write(std::unique_ptr stream) override; /// Flushes queued messages. void flush(); @@ -130,7 +131,7 @@ class Base_API AsyncLogWriter : public LogWriter, public basic::Runnable bool writeNext(); Thread _thread; - std::deque _pending; + std::deque> _pending; mutable std::mutex _mutex; }; @@ -157,12 +158,11 @@ class Base_API Logger /// Destroys the default logger singleton instance. static void destroy(); - /// Adds the given log channel. - void add(LogChannel* channel); + /// Adds the given log channel. Takes ownership. + void add(std::unique_ptr channel); - /// Removes the given log channel by name, - /// and optionally frees the pointer. - void remove(const std::string& name, bool freePointer = true); + /// Removes the given log channel by name. + void remove(const std::string& name); /// Returns the specified log channel. /// Throws an exception if the channel doesn't exist. @@ -171,8 +171,8 @@ class Base_API Logger /// Sets the default log to the specified log channel. void setDefault(const std::string& name); - /// Sets the log writer instance. - void setWriter(LogWriter* writer); + /// Sets the log writer instance. Takes ownership. + void setWriter(std::unique_ptr writer); /// Returns the default log channel, or the nullptr channel /// if no default channel has been set. @@ -183,29 +183,24 @@ class Base_API Logger void write(const LogStream& stream); /// Writes the given message to the default log channel. - /// The stream pointer will be deleted when appropriate. - void write(LogStream* stream); - - /// Sends to the default log using the given class instance. - /// Recommend using write(LogStream&) to avoid copying data. - // LogStream& send(const char* level = "debug", const char* realm = "", - // const void* ptr = nullptr, - // const char* channel = nullptr) const; + void write(std::unique_ptr stream); protected: /// NonCopyable and NonMovable Logger(const Logger&) = delete; Logger& operator=(const Logger&) = delete; + Logger(Logger&&) = delete; + Logger& operator=(Logger&&) = delete; - typedef std::map LogChannelMap; + using LogChannelMap = std::map>; friend class Singleton; friend class Thread; mutable std::mutex _mutex; LogChannelMap _channels; - LogChannel* _defaultChannel; - LogWriter* _writer; + LogChannel* _defaultChannel; // non-owning view into _channels + std::unique_ptr _writer; }; @@ -220,7 +215,7 @@ void logArgs(std::ostream& o, T&& t) o << t; // << ' '; // << std::endl; } -template +template void logArgs(std::ostream& o, T&& t, Args&&... args) // recursive variadic function { logArgs(o, std::forward(t)); @@ -250,7 +245,7 @@ struct LogStream ~LogStream(); /// Recursively log veradic arguments. - template + template void write(Args... args) { logArgs(message, args...); @@ -258,7 +253,8 @@ struct LogStream } /// Write data to the log message. - template LogStream& operator<<(const T& data) + template + LogStream& operator<<(const T& data) { message << data; return *this; @@ -289,7 +285,7 @@ struct LogStream if (!flushed) { flushed = true; message << std::endl; - Logger::instance().write(new LogStream(*this)); + Logger::instance().write(std::make_unique(*this)); } } }; @@ -301,12 +297,13 @@ struct LogStream LogStream(Level level, std::string realm, int line, const char* channel = nullptr) {}; LogStream(const LogStream& that) {}; - template + template void write(Args... args) { } - template LogStream& operator<<(const T&) + template + LogStream& operator<<(const T&) { return *this; } @@ -357,7 +354,7 @@ class Base_API LogChannel /// /// Redifine the base `LogChannel` as `NullChannel` so it can be logically used /// as a disabled log channel. -typedef LogChannel NullChannel; +using NullChannel = LogChannel; // @@ -432,7 +429,7 @@ class Base_API RotatingFileChannel : public LogChannel void setRotationInterval(int interval) { _rotationInterval = interval; }; protected: - std::ofstream* _fstream; + std::unique_ptr _fstream; std::string _dir; std::string _filename; std::string _extension; @@ -441,39 +438,17 @@ class Base_API RotatingFileChannel : public LogChannel }; -#if 0 -class Base_API EventedFileChannel: public FileChannel -{ -public: - EventedFileChannel( - std::string name, - const std::string& dir, - Level level = Level::Debug, - const std::string& extension = "log", - int rotationInterval = 12 * 3600, - const char* timeFormat = "%H:%M:%S"); - virtual ~EventedFileChannel(); - - virtual void write(const std::string& message, Level level = Level::Debug, - const char* realm = "", const void* ptr = nullptr); - virtual void write(const LogStream& stream); - - Signal OnLogStream; -}; -#endif - - // // Compile time helpers for replacing file paths with filenames // -constexpr const char* str_end(const char *str) +constexpr const char* str_end(const char* str) { return *str ? str_end(str + 1) : str; } -constexpr bool str_slant(const char *str) +constexpr bool str_slant(const char* str) { return *str == '/' || *str == '\\' ? true : (*str ? str_slant(str + 1) : false); } @@ -513,15 +488,30 @@ inline std::string _methodName(const std::string& fsig) #define STrace LogStream(Level::Trace, _fileName(__FILE__), __LINE__) #define SDebug LogStream(Level::Debug, _fileName(__FILE__), __LINE__) -#define SInfo LogStream(Level::Info, _fileName(__FILE__), __LINE__) -#define SWarn LogStream(Level::Warn, _fileName(__FILE__), __LINE__) +#define SInfo LogStream(Level::Info, _fileName(__FILE__), __LINE__) +#define SWarn LogStream(Level::Warn, _fileName(__FILE__), __LINE__) #define SError LogStream(Level::Error, _fileName(__FILE__), __LINE__) -#define LTrace(...) { LogStream(Level::Trace, _fileName(__FILE__), __LINE__).write(__VA_ARGS__); } -#define LDebug(...) { LogStream(Level::Debug, _fileName(__FILE__), __LINE__).write(__VA_ARGS__); } -#define LInfo(...) { LogStream(Level::Info, _fileName(__FILE__), __LINE__).write(__VA_ARGS__); } -#define LWarn(...) { LogStream(Level::Warn, _fileName(__FILE__), __LINE__).write(__VA_ARGS__); } -#define LError(...) { LogStream(Level::Error, _fileName(__FILE__), __LINE__).write(__VA_ARGS__); } +#define LTrace(...) \ + do { \ + LogStream(Level::Trace, _fileName(__FILE__), __LINE__).write(__VA_ARGS__); \ + } while (0) +#define LDebug(...) \ + do { \ + LogStream(Level::Debug, _fileName(__FILE__), __LINE__).write(__VA_ARGS__); \ + } while (0) +#define LInfo(...) \ + do { \ + LogStream(Level::Info, _fileName(__FILE__), __LINE__).write(__VA_ARGS__); \ + } while (0) +#define LWarn(...) \ + do { \ + LogStream(Level::Warn, _fileName(__FILE__), __LINE__).write(__VA_ARGS__); \ + } while (0) +#define LError(...) \ + do { \ + LogStream(Level::Error, _fileName(__FILE__), __LINE__).write(__VA_ARGS__); \ + } while (0) // #define TraceS(self) LogStream(Level::Trace, _fileName(__FILE__), __LINE__, self) // #define DebugS(self) LogStream(Level::Debug, _fileName(__FILE__), __LINE__, self) @@ -539,7 +529,4 @@ inline std::string _methodName(const std::string& fsig) } // namespace scy -#endif - - /// @\} diff --git a/src/base/include/scy/loop.h b/src/base/include/scy/loop.h index 2bbae89e3..4381d8e25 100644 --- a/src/base/include/scy/loop.h +++ b/src/base/include/scy/loop.h @@ -13,8 +13,7 @@ /// @{ -#ifndef SCY_UV_LOOP_H -#define SCY_UV_LOOP_H +#pragma once #include "scy/base.h" @@ -26,7 +25,7 @@ namespace scy { namespace uv { -typedef uv_loop_t Loop; +using Loop = uv_loop_t; inline Loop* defaultLoop() @@ -57,11 +56,37 @@ inline bool closeLoop(Loop* loop) } -} // namespace uv -} // namespace scy +/// RAII wrapper for a libuv event loop. +/// Automatically closes and deletes the loop on destruction. +struct ScopedLoop +{ + Loop* loop; + + ScopedLoop() + : loop(createLoop()) + { + } + + ~ScopedLoop() + { + if (loop) { + closeLoop(loop); + delete loop; + } + } + operator Loop*() const { return loop; } + Loop* get() const { return loop; } -#endif // SCY_UV_LOOP_H + ScopedLoop(const ScopedLoop&) = delete; + ScopedLoop& operator=(const ScopedLoop&) = delete; + ScopedLoop(ScopedLoop&&) = delete; + ScopedLoop& operator=(ScopedLoop&&) = delete; +}; + + +} // namespace uv +} // namespace scy /// @\} diff --git a/src/base/include/scy/memory.h b/src/base/include/scy/memory.h index 1918fac79..2cf5ef71f 100644 --- a/src/base/include/scy/memory.h +++ b/src/base/include/scy/memory.h @@ -9,125 +9,46 @@ /// @{ -#ifndef SCY_Memory_H -#define SCY_Memory_H +#pragma once #include "scy/base.h" -#include "scy/logger.h" -#include "scy/timer.h" -#include "scy/singleton.h" -//#include "scy/handle.h" -#include -#include -#include -#include +#include "scy/loop.h" + +#include #include -#include namespace scy { -class Base_API ScopedPointer; - - -/// Garbage collector for safe memory management and deferred pointer deletion. -class Base_API GarbageCollector +/// Schedule deferred deletion on the next event loop iteration. +/// This is essential for deleting objects that may still be referenced +/// by pending libuv callbacks (e.g. socket adapters with in-flight I/O). +template +inline void deleteLater(T* ptr, uv::Loop* loop) { -public: - GarbageCollector(); - ~GarbageCollector(); - - /// Returns the GarbageCollector singleton. - static GarbageCollector& instance(); - - /// Shuts down the garbage collector and deletes - /// the singleton instance. - /// This method must be called from the main thread - /// while the event loop is inactive. - static void destroy(); - - /// Schedules a pointer for deferred deletion. - template - void deleteLater(C* ptr, uv::Loop* loop = uv::defaultLoop()); - - /// Schedules a shared pointer for deferred deletion. - template - void deleteLater(std::shared_ptr ptr, uv::Loop* loop = uv::defaultLoop()); - - /// Frees all scheduled pointers now. - /// This method must be called from the main thread - /// while the event loop is inactive. - void finalize(); - - /// Returns the TID of the main garbage collector thread. - std::thread::id tid(); - -protected: - /// Garbage collector cleaner context. - /// - /// The grabage collector maintains a single cleaner - /// context per event loop. - class Base_API Cleaner - { - public: - Cleaner(uv::Loop* loop = uv::defaultLoop()); - ~Cleaner(); - - void work(); - void finalize(); - - mutable std::mutex _mutex; - std::vector _pending; - std::vector _ready; - Timer _timer; - uv::Loop* _loop; - bool _finalize; - }; - - /// Get the cleaner context for the given loop. - Cleaner* getCleaner(uv::Loop* loop = uv::defaultLoop()); - -protected: - mutable std::mutex _mutex; - std::vector _cleaners; - std::thread::id _tid; -}; + if (!ptr) + return; + auto* idle = new uv_idle_t; + uv_idle_init(loop, idle); + idle->data = ptr; + uv_idle_start(idle, [](uv_idle_t* handle) { + uv_idle_stop(handle); + delete static_cast(handle->data); + uv_close(reinterpret_cast(handle), [](uv_handle_t* h) { + delete reinterpret_cast(h); + }); + }); +} -// -/// Deleter Functors -// - namespace deleter { -#if 0 // use std::default_delete instead -template struct Default -{ - void operator()(T *ptr) - { - assert(ptr); - static_assert(0 < sizeof(T), "can't delete an incomplete type"); - delete ptr; - } -}; -#endif - - -template struct Deferred -{ - void operator()(T* ptr) - { - assert(ptr); - static_assert(0 < sizeof(T), "can't delete an incomplete type"); - GarbageCollector::instance().deleteLater(ptr); - } -}; - - -template struct Dispose +/// Deleter functor that calls dispose() on the pointer. +template +struct Dispose { void operator()(T* ptr) { @@ -138,187 +59,18 @@ template struct Dispose }; -template struct Array +/// Deleter functor for array pointers. +template +struct Array { void operator()(T* ptr) { assert(ptr); static_assert(0 < sizeof(T), "can't delete an incomplete type"); delete[] ptr; - ptr->dispose(); } }; } // namespace deleter - - -// -/// Scoped Pointer Classes -// - - -/// ScopedPointer provides an interface for holding -/// and ansynchronously deleting a pointer in various ways. -class ScopedPointer -{ -public: - ScopedPointer() {} - virtual ~ScopedPointer() {} -}; - - -/// ScopedRawPointer implements the ScopedPointer interface -/// to provide a method for deleting a raw pointer. -template > -class ScopedRawPointer : public ScopedPointer -{ -public: - void* ptr; - - ScopedRawPointer(void* p) - : ptr(p) - { - } - - virtual ~ScopedRawPointer() - { - D func; - func((T*)ptr); - ptr = nullptr; - } -}; - - -/// ScopedSharedPointer implements the ScopedPointer interface to -/// provide deferred deletion for shared_ptr managed pointers. -/// Note that this class does not guarantee deletion of the managed -/// pointer; all it does is copy the shared_ptr and release it when -/// the ScopedSharedPointer instance is deleted, which makes it useful -/// for certain asyncronous scenarios. -template -class ScopedSharedPointer : public ScopedPointer -{ -public: - std::shared_ptr ptr; - - ScopedSharedPointer(std::shared_ptr p) - : ptr(p) - { - assert(ptr); - } - - virtual ~ScopedSharedPointer() {} -}; - - -// -// Garbage Collector inlines -// - - -/// Schedules a pointer for deferred deletion. -template -inline void GarbageCollector::deleteLater(C* ptr, uv::Loop* loop) -{ - auto cleaner = getCleaner(loop); - std::lock_guard guard(cleaner->_mutex); - cleaner->_pending.push_back(new ScopedRawPointer(ptr)); -} - - -/// Schedules a shared pointer for deferred deletion. -template -inline void GarbageCollector::deleteLater(std::shared_ptr ptr, uv::Loop* loop) -{ - auto cleaner = getCleaner(loop); - std::lock_guard guard(cleaner->_mutex); - cleaner->_pending.push_back(new ScopedSharedPointer(ptr)); -} - - -/// Convenience function for accessing GarbageCollector::deleteLater -template -inline void deleteLater(C* ptr, uv::Loop* loop = uv::defaultLoop()) -{ - GarbageCollector::instance().deleteLater(ptr, loop); -} - - -/// Convenience function for accessing GarbageCollector::deleteLater -template -inline void deleteLater(std::shared_ptr ptr, uv::Loop* loop = uv::defaultLoop()) -{ - GarbageCollector::instance().deleteLater(ptr, loop); -} - - -#if 0 // deprecated in favour of std::shared_ptr with custom deleters -/// SharedObject is the base class for objects that -/// employ reference counting based garbage collection. -/// -/// Reference-counted objects inhibit construction by -/// copying and assignment. -class SharedObject -{ -public: - /// Creates the SharedObject with an - /// initial reference count of one. - SharedObject(bool deferred = false) - : count(1) - , deferred(deferred) - { - } - - /// Increment the object's reference count. - void duplicate() - { - std::atomic_fetch_add_explicit(&count, 1u, std::memory_order_relaxed); - } - - /// Decrement the object's reference count and - /// calls delete if the count reaches zero. - void release() - { - if (std::atomic_fetch_sub_explicit(&count, 1u, std::memory_order_release) == 1) { - std::atomic_thread_fence(std::memory_order_acquire); - freeMemory(); - } - } - - unsigned refCount() const { return count; } - -protected: - /// Deletes the instance when the reference count reaches zero. - /// This method can be overridden for different deletion strategies. - virtual void freeMemory() - { - if (deferred) - deleteLater(this); - else - delete this; - } - - /// Destroys the SharedObject. - /// The destructor should never be called directly. - virtual ~SharedObject() {} - - SharedObject(const SharedObject&) = delete; - SharedObject& operator=(const SharedObject&) = delete; - - friend struct std::default_delete; - // friend struct deleter::Deferred; - - std::atomic count; - bool deferred; -}; -#endif - - } // namespace scy - - -#endif // SCY_Memory_H - - -/// @\} diff --git a/src/base/include/scy/numeric.h b/src/base/include/scy/numeric.h index d1b3c94f9..dc874b483 100644 --- a/src/base/include/scy/numeric.h +++ b/src/base/include/scy/numeric.h @@ -12,12 +12,11 @@ // -#ifndef SCY_Numeric_H -#define SCY_Numeric_H +#pragma once -#include #include +#include namespace scy { @@ -160,38 +159,10 @@ void formatHex(std::string& str, uint64_t value); void formatHex(std::string& str, uint64_t value, int width); -#if 0 -/// Formats a float value in decimal floating-point notation, -/// according to std::printf's %g format with a precision of 8 fractional digits. -void format(std::string& str, float value); - -/// Formats a double value in decimal floating-point notation, -/// according to std::printf's %g format with a precision of 16 fractional digits. -void format(std::string& str, double value); - -/// Formats a double value in decimal floating-point notation, -/// according to std::printf's %f format with the given precision. -void format(std::string& str, double value, int precision); - -/// Formats a double value in decimal floating-point notation, -/// right justified in a field of the specified width, -/// with the number of fractional digits given in precision. -void format(std::string& str, double value, int width, int precision); - -/// Formats a pointer in an eight (32-bit architectures) or -/// sixteen (64-bit architectures) characters wide -/// field in hexadecimal notation. -void format(std::string& str, const void* ptr); -#endif - - } // namespace numeric } // namespace scy -#endif // SCY_Numeric_H - - /// @\} diff --git a/src/base/include/scy/once.h b/src/base/include/scy/once.h index b91620b01..efcf95139 100644 --- a/src/base/include/scy/once.h +++ b/src/base/include/scy/once.h @@ -9,23 +9,22 @@ /// @{ -#ifndef SCY_Once_H -#define SCY_Once_H +#pragma once #include "scy/base.h" -#include "scy/runner.h" #include "scy/loop.h" +#include "scy/runner.h" namespace scy { /// Run the given function at the beginning of the next event loop iteration. -template +template void runOnce(uv::Loop* loop, Function&& func, Args&&... args) { - typedef internal::DeferredCallable Callback; + using Callback = internal::DeferredCallable; auto prepare = new uv_prepare_t; prepare->data = new Callback(nullptr, @@ -33,12 +32,14 @@ void runOnce(uv::Loop* loop, Function&& func, Args&&... args) std::forward(args)...); uv_prepare_init(loop, prepare); - uv_prepare_start(prepare, [](uv_prepare_t *req) { + uv_prepare_start(prepare, [](uv_prepare_t* req) { auto wrap = reinterpret_cast(req->data); wrap->invoke(); delete wrap; uv_prepare_stop(req); - delete req; + uv_close(reinterpret_cast(req), [](uv_handle_t* h) { + delete reinterpret_cast(h); + }); }); } @@ -46,7 +47,4 @@ void runOnce(uv::Loop* loop, Function&& func, Args&&... args) } // namespace scy -#endif // SCY_Once_H - - /// @\} diff --git a/src/base/include/scy/packet.h b/src/base/include/scy/packet.h index 0d2612c92..085d740e1 100644 --- a/src/base/include/scy/packet.h +++ b/src/base/include/scy/packet.h @@ -9,8 +9,7 @@ /// @{ -#ifndef SCY_Packet_H -#define SCY_Packet_H +#pragma once #include "scy/base.h" @@ -21,6 +20,7 @@ #include #include // memcpy +#include namespace scy { @@ -33,7 +33,7 @@ struct IPacketInfo IPacketInfo() = default; virtual ~IPacketInfo() = default; - virtual IPacketInfo* clone() const = 0; + virtual std::unique_ptr clone() const = 0; }; @@ -43,18 +43,16 @@ struct IPacketInfo class Base_API IPacket { public: - IPacket(void* source = nullptr, void* opaque = nullptr, - IPacketInfo* info = nullptr, unsigned flags = 0) - : source(source) - , opaque(opaque) - , info(info) + IPacket(void* opaque = nullptr, + std::unique_ptr info = nullptr, unsigned flags = 0) + : opaque(opaque) + , info(std::move(info)) , flags(flags) { } IPacket(const IPacket& r) - : source(r.source) - , opaque(r.opaque) + : opaque(r.opaque) , info(r.info ? r.info->clone() : nullptr) , flags(r.flags) { @@ -62,33 +60,22 @@ class Base_API IPacket IPacket& operator=(const IPacket& r) { - source = r.source; opaque = r.opaque; - info = (r.info ? r.info->clone() : nullptr); + info = r.info ? r.info->clone() : nullptr; flags = r.flags; return *this; } - virtual IPacket* clone() const = 0; + virtual std::unique_ptr clone() const = 0; - virtual ~IPacket() - { - if (info) - delete info; - } - - /// Packet source pointer reference which enables processors - /// along the signal chain can determine the packet origin. - /// Often a subclass of PacketStreamSource. - void* source; + virtual ~IPacket() = default; /// Optional client data pointer. /// This pointer is not managed by the packet. void* opaque; /// Optional extra information about the packet. - /// This pointer is managed by the packet. - IPacketInfo* info; + std::unique_ptr info; /// Provides basic information about the packet. Bitwise flags; @@ -139,13 +126,13 @@ class Base_API FlagPacket : public IPacket { public: FlagPacket(unsigned flags = 0) - : IPacket(nullptr, nullptr, nullptr, flags) + : IPacket(nullptr, nullptr, flags) { } - virtual IPacket* clone() const override + virtual std::unique_ptr clone() const override { - return new FlagPacket(*this); + return std::make_unique(*this); } FlagPacket(const FlagPacket& that) @@ -168,71 +155,49 @@ class Base_API FlagPacket : public IPacket class Base_API RawPacket : public IPacket { public: + /// Construct with borrowed (non-owning) buffer. RawPacket(char* data = nullptr, size_t size = 0, unsigned flags = 0, - void* source = nullptr, void* opaque = nullptr, - IPacketInfo* info = nullptr) - : IPacket(source, opaque, info, flags) + void* opaque = nullptr, + std::unique_ptr info = nullptr) + : IPacket(opaque, std::move(info), flags) , _data(data) , _size(size) - , _free(false) { } + /// Construct with const data (copied, owning). RawPacket(const char* data, size_t size = 0, unsigned flags = 0, - void* source = nullptr, void* opaque = nullptr, - IPacketInfo* info = nullptr) - : IPacket(source, opaque, info, flags) + void* opaque = nullptr, + std::unique_ptr info = nullptr) + : IPacket(opaque, std::move(info), flags) , _data(nullptr) - , _size(size) - , _free(true) + , _size(0) { - copyData(data, size); // copy const data + copyData(data, size); } + /// Copy constructor (always copies data). RawPacket(const RawPacket& that) : IPacket(that) , _data(nullptr) , _size(0) - , _free(true) { - // Copy assigned data and set the free flag - // Todo: Use a simple reference counted buffer wrapper - // so we don't need to force memcpy here. copyData(that._data, that._size); } - virtual ~RawPacket() - { - if (_data && _free) - delete[] _data; - } + virtual ~RawPacket() = default; - virtual IPacket* clone() const override + virtual std::unique_ptr clone() const override { - return new RawPacket(*this); + return std::make_unique(*this); } - // virtual void setData(char* data, size_t size) - // { - // assert(size > 0); - // if (_free) // copy data if reuqested - // copyData(data, size); - // else { // otherwise just assign the pointer - // _data = data; - // _size = size; - // } - // } - virtual void copyData(const void* data, size_t size) { - // traceL("RawPacket", this) << "Cloning: " << size << std::endl; - // assert(_free); if (data && size > 0) { - if (_data && _free) - delete[] _data; + _owned = std::make_unique(size); + _data = _owned.get(); _size = size; - _data = new char[size]; - _free = true; std::memcpy(_data, data, size); } } @@ -245,63 +210,51 @@ class Base_API RawPacket : public IPacket virtual void write(Buffer& buf) const override { - // buf.insert(a.end(), b.begin(), b.end()); - // buf.append(_data, _size); buf.insert(buf.end(), _data, _data + _size); } virtual char* data() const override { return _data; } - // virtual char* cdata() const { return static_cast(_data); } - virtual size_t size() const override { return _size; } virtual const char* className() const override { return "RawPacket"; } - bool ownsBuffer() const { return _free; } - - void assignDataOwnership() { _free = true; } + bool ownsBuffer() const { return _owned != nullptr; } protected: char* _data; size_t _size; - bool _free; + std::unique_ptr _owned; }; inline RawPacket rawPacket(const MutableBuffer& buf, unsigned flags = 0, - void* source = nullptr, void* opaque = nullptr, - IPacketInfo* info = nullptr) + void* opaque = nullptr, + std::unique_ptr info = nullptr) { - return RawPacket(bufferCast(buf), buf.size(), flags, source, opaque, info); + return RawPacket(bufferCast(buf), buf.size(), flags, opaque, std::move(info)); } inline RawPacket rawPacket(const ConstBuffer& buf, unsigned flags = 0, - void* source = nullptr, void* opaque = nullptr, - IPacketInfo* info = nullptr) + void* opaque = nullptr, + std::unique_ptr info = nullptr) { - return RawPacket(bufferCast(buf), buf.size(), flags, source, opaque, info); // copy const data + return RawPacket(bufferCast(buf), buf.size(), flags, opaque, std::move(info)); } inline RawPacket rawPacket(char* data = nullptr, size_t size = 0, - unsigned flags = 0, void* source = nullptr, - void* opaque = nullptr, IPacketInfo* info = nullptr) + unsigned flags = 0, void* opaque = nullptr, + std::unique_ptr info = nullptr) { - return RawPacket(data, size, flags, source, opaque, info); + return RawPacket(data, size, flags, opaque, std::move(info)); } inline RawPacket rawPacket(const char* data = nullptr, size_t size = 0, - unsigned flags = 0, void* source = nullptr, - void* opaque = nullptr, IPacketInfo* info = nullptr) + unsigned flags = 0, void* opaque = nullptr, + std::unique_ptr info = nullptr) { - return RawPacket(data, size, flags, source, opaque, info); // copy const data + return RawPacket(data, size, flags, opaque, std::move(info)); } } // namespace scy - - -#endif // SCY_Packet_H - - -/// @\} diff --git a/src/base/include/scy/packetfactory.h b/src/base/include/scy/packetfactory.h index 4352b2474..8dbb70d38 100644 --- a/src/base/include/scy/packetfactory.h +++ b/src/base/include/scy/packetfactory.h @@ -9,8 +9,7 @@ /// @{ -#ifndef SCY_PacketFactory_H -#define SCY_PacketFactory_H +#pragma once #include "scy/base.h" @@ -39,7 +38,7 @@ class /* Base_API */ IPacketCreationStrategy }; -typedef std::vector PacketCreationStrategyList; +using PacketCreationStrategyList = std::vector; /// This template class implements an adapter that sits between @@ -108,7 +107,7 @@ class /* Base_API */ PacketFactory { for (auto it = _types.begin(); it != _types.end(); ++it) { - if (dynamic_cast*>(*it) != 0) { + if (dynamic_cast*>(*it) != nullptr) { delete *it; _types.erase(it); return; @@ -131,7 +130,7 @@ class /* Base_API */ PacketFactory { for (auto it = _types.begin(); it != _types.end(); ++it) { - if (dynamic_cast(*it) != 0) { + if (dynamic_cast(*it) != nullptr) { delete *it; _types.erase(it); return; @@ -182,7 +181,4 @@ class /* Base_API */ PacketFactory } // namespace scy -#endif // SCY_PacketFactory_H - - /// @\} diff --git a/src/base/include/scy/packetio.h b/src/base/include/scy/packetio.h index 5559632ec..9160761a2 100644 --- a/src/base/include/scy/packetio.h +++ b/src/base/include/scy/packetio.h @@ -9,8 +9,7 @@ /// @{ -#ifndef SCY_PACKET_IO_H -#define SCY_PACKET_IO_H +#pragma once #include "scy/base.h" @@ -29,7 +28,8 @@ namespace scy { /// class that derives from `std::istream`. It's most regularly used for reading /// input files. /// -class ThreadedStreamReader : public PacketSource, public basic::Startable +class ThreadedStreamReader : public PacketSource + , public basic::Startable { public: ThreadedStreamReader(std::istream* is) @@ -57,9 +57,10 @@ class ThreadedStreamReader : public PacketSource, public basic::Startable self->emit(line); } if (self->stream().eof()) { - self->emit(PacketFlags::Final); + self->emit(static_cast(PacketFlags::Final)); } - }, this); + }, + this); } void stop() override @@ -67,7 +68,8 @@ class ThreadedStreamReader : public PacketSource, public basic::Startable _runner.cancel(); } - template StreamT& stream() + template + StreamT& stream() { auto stream = dynamic_cast(_istream); if (!stream) @@ -123,7 +125,8 @@ class StreamWriter : public PacketProcessor emit(packet); } - template StreamT& stream() + template + StreamT& stream() { auto stream = dynamic_cast(_ostream); if (!stream) @@ -134,21 +137,21 @@ class StreamWriter : public PacketProcessor void onStreamStateChange(const PacketStreamState& state) override { - //LTrace("Stream state: ", state) + //LTrace("Stream state: ", state); switch (state.id()) { - // case PacketStreamState::None: - // case PacketStreamState::Active: - // case PacketStreamState::Resetting: - // case PacketStreamState::Stopping: - // case PacketStreamState::Stopped: - case PacketStreamState::Closed: - case PacketStreamState::Error: - // Close file handles - auto fstream = dynamic_cast(_ostream); - if (fstream) - fstream->close(); - break; + // case PacketStreamState::None: + // case PacketStreamState::Active: + // case PacketStreamState::Resetting: + // case PacketStreamState::Stopping: + // case PacketStreamState::Stopped: + case PacketStreamState::Closed: + case PacketStreamState::Error: + // Close file handles + auto fstream = dynamic_cast(_ostream); + if (fstream) + fstream->close(); + break; } } @@ -169,7 +172,4 @@ class StreamWriter : public PacketProcessor } // namespace scy -#endif // SCY_PACKET_IO_H - - /// @\} diff --git a/src/base/include/scy/packetqueue.h b/src/base/include/scy/packetqueue.h index de88dbf4a..e861b520f 100644 --- a/src/base/include/scy/packetqueue.h +++ b/src/base/include/scy/packetqueue.h @@ -9,8 +9,7 @@ /// @{ -#ifndef SCY_PacketQueue_H -#define SCY_PacketQueue_H +#pragma once #include "scy/base.h" @@ -28,11 +27,12 @@ namespace scy { template -class SyncPacketQueue : public SyncQueue, public PacketProcessor +class SyncPacketQueue : public SyncQueue + , public PacketProcessor { public: - typedef SyncQueue Queue; - typedef PacketProcessor Processor; + using Queue = SyncQueue; + using Processor = PacketProcessor; SyncPacketQueue(uv::Loop* loop, int maxSize = 1024) : Queue(loop, maxSize) @@ -64,12 +64,11 @@ template inline void SyncPacketQueue::process(IPacket& packet) { if (Queue::cancelled()) { - LWarn("Process late packet") - assert(0); + LWarn("Process late packet"); return; } - Queue::push(reinterpret_cast(packet.clone())); + Queue::push(static_cast(packet.clone().release())); } @@ -77,8 +76,7 @@ template inline void SyncPacketQueue::dispatch(T& packet) { if (Queue::cancelled()) { - LWarn("Dispatch late packet") - assert(0); + LWarn("Dispatch late packet"); return; } @@ -92,14 +90,14 @@ inline void SyncPacketQueue::dispatch(T& packet) template inline bool SyncPacketQueue::accepts(IPacket* packet) { - return dynamic_cast(packet) != 0; + return dynamic_cast(packet) != nullptr; } template inline void SyncPacketQueue::onStreamStateChange(const PacketStreamState& state) { - LTrace("Stream state: ", state) + LTrace("Stream state: ", state); switch (state.id()) { // case PacketStreamState::None: @@ -121,11 +119,12 @@ inline void SyncPacketQueue::onStreamStateChange(const PacketStreamState& sta template -class AsyncPacketQueue : public AsyncQueue, public PacketProcessor +class AsyncPacketQueue : public AsyncQueue + , public PacketProcessor { public: - typedef AsyncQueue Queue; - typedef PacketProcessor Processor; + using Queue = AsyncQueue; + using Processor = PacketProcessor; AsyncPacketQueue(int maxSize = 1024) : Queue(maxSize) @@ -154,18 +153,19 @@ inline void AsyncPacketQueue::close() { // Flush queued items, some protocols can't afford dropped packets Queue::flush(); - assert(Queue::empty()); + if (!Queue::empty()) + LWarn("Queue not empty after flush during close"); Queue::cancel(); Queue::_thread.join(); } -template inline void +template +inline void AsyncPacketQueue::dispatch(T& packet) { if (Queue::cancelled()) { - LWarn("Dispatch late packet") - assert(0); + LWarn("Dispatch late packet"); return; } @@ -177,26 +177,26 @@ template inline void AsyncPacketQueue::process(IPacket& packet) { if (Queue::cancelled()) { - LWarn("Process late packet") - assert(0); + LWarn("Process late packet"); return; } - this->push(reinterpret_cast(packet.clone())); + this->push(static_cast(packet.clone().release())); } template inline bool AsyncPacketQueue::accepts(IPacket* packet) { - return dynamic_cast(packet) != 0; + return dynamic_cast(packet) != nullptr; } -template inline void +template +inline void AsyncPacketQueue::onStreamStateChange(const PacketStreamState& state) { - LTrace("Stream state: ", state) + LTrace("Stream state: ", state); switch (state.id()) { case PacketStreamState::Active: @@ -219,7 +219,4 @@ AsyncPacketQueue::onStreamStateChange(const PacketStreamState& state) } // namespace scy -#endif // SCY_PacketQueue_H - - /// @\} diff --git a/src/base/include/scy/packetsignal.h b/src/base/include/scy/packetsignal.h index f3872ba9d..080c7cb12 100644 --- a/src/base/include/scy/packetsignal.h +++ b/src/base/include/scy/packetsignal.h @@ -9,8 +9,7 @@ /// @{ -#ifndef SCY_PacketSignal_H -#define SCY_PacketSignal_H +#pragma once #include "scy/packet.h" @@ -22,7 +21,7 @@ namespace scy { /// Signal that broadcasts `IPacket` types. -typedef Signal PacketSignal; +using PacketSignal = Signal; /// Signal slot that allows listeners to filter polymorphic `IPacket` types. @@ -38,7 +37,4 @@ packetSlot(Class* instance, RT (Class::*method)(PT&), int id = -1, int priority } // namespace scy -#endif // SCY_PacketSignal_H - - /// @\} diff --git a/src/base/include/scy/packetstream.h b/src/base/include/scy/packetstream.h index 2ed82e4f4..20b550f8e 100644 --- a/src/base/include/scy/packetstream.h +++ b/src/base/include/scy/packetstream.h @@ -9,18 +9,19 @@ /// @{ -#ifndef SCY_PacketStream_H -#define SCY_PacketStream_H +#pragma once #include "scy/base.h" #include "scy/error.h" #include "scy/interface.h" -#include "scy/memory.h" #include "scy/logger.h" +#include "scy/loop.h" #include "scy/packetsignal.h" #include "scy/stateful.h" +#include #include +#include namespace scy { @@ -41,7 +42,7 @@ class Base_API PacketStreamAdapter { public: PacketStreamAdapter(PacketSignal& emitter); - virtual ~PacketStreamAdapter(){}; + virtual ~PacketStreamAdapter() {}; virtual void emit(char* data, size_t len, unsigned flags = 0); virtual void emit(const char* data, size_t len, unsigned flags = 0); @@ -57,18 +58,20 @@ class Base_API PacketStreamAdapter /// On receiving the Stopped state, it is the responsibility /// of the adapter to have ceased all outgoing packet transmission, /// especially in multi-thread scenarios. - virtual void onStreamStateChange(const PacketStreamState&){}; + virtual void onStreamStateChange(const PacketStreamState&) {}; protected: /// NonCopyable and NonMovable PacketStreamAdapter(const PacketStreamAdapter&) = delete; PacketStreamAdapter& operator=(const PacketStreamAdapter&) = delete; + PacketStreamAdapter(PacketStreamAdapter&&) = delete; + PacketStreamAdapter& operator=(PacketStreamAdapter&&) = delete; PacketSignal& _emitter; }; -typedef PacketStreamAdapter PacketSource; ///< For 0.8.x compatibility +using PacketSource = PacketStreamAdapter; ///< For 0.8.x compatibility // @@ -104,38 +107,42 @@ class Base_API PacketProcessor : public PacketStreamAdapter }; -typedef PacketProcessor IPacketizer; -typedef PacketProcessor IDepacketizer; /// For 0.8.x compatibility +using IPacketizer = PacketProcessor; +using IDepacketizer = PacketProcessor; ///< For 0.8.x compatibility // // Packet Adapter Reference // -/// Provides a reference to a PacketSignal instance. +/// Provides a reference to a PacketStreamAdapter with optional ownership. struct PacketAdapterReference { - typedef std::shared_ptr Ptr; + using Ptr = std::shared_ptr; - PacketStreamAdapter* ptr; - ScopedPointer* deleter; + PacketStreamAdapter* ptr; // non-owning view + std::shared_ptr _prevent_deletion; // prevent premature deletion via type erasure int order; bool syncState; + /// Construct with raw pointer (non-owning). PacketAdapterReference(PacketStreamAdapter* ptr = nullptr, - ScopedPointer* deleter = nullptr, int order = 0, - bool syncState = false) + int order = 0, bool syncState = false) : ptr(ptr) - , deleter(deleter) , order(order) , syncState(syncState) { } - ~PacketAdapterReference() + /// Construct with shared_ptr ownership. + template + PacketAdapterReference(std::shared_ptr owned, int order = 0, + bool syncState = false) + : ptr(static_cast(owned.get())) + , _prevent_deletion(std::move(owned)) + , order(order) + , syncState(syncState) { - if (deleter) - delete deleter; } static bool compareOrder(const PacketAdapterReference::Ptr& l, @@ -146,16 +153,21 @@ struct PacketAdapterReference }; -typedef std::vector PacketAdapterVec; +using PacketAdapterVec = std::vector; /// Flags which determine how the packet is handled by the PacketStream -enum PacketFlags +enum class PacketFlags : unsigned { NoModify = 0x01, ///< The packet should not be modified by processors. - Final ///< The final packet in the stream. + Final = 0x02 ///< The final packet in the stream. }; +constexpr unsigned operator|(PacketFlags lhs, PacketFlags rhs) +{ + return static_cast(lhs) | static_cast(rhs); +} + // // Packet Stream State @@ -164,7 +176,7 @@ enum PacketFlags struct PacketStreamState : public State { - enum Type + enum class Type : unsigned int { None = 0, Locked, @@ -177,29 +189,38 @@ struct PacketStreamState : public State Error, }; + // Re-export enum values into the struct scope for backward compatibility. + // These are unsigned int constants so they work with State::ID (uint32_t). + static constexpr unsigned int None = static_cast(Type::None); + static constexpr unsigned int Locked = static_cast(Type::Locked); + static constexpr unsigned int Active = static_cast(Type::Active); + static constexpr unsigned int Paused = static_cast(Type::Paused); + static constexpr unsigned int Stopping = static_cast(Type::Stopping); + static constexpr unsigned int Stopped = static_cast(Type::Stopped); + static constexpr unsigned int Closed = static_cast(Type::Closed); + static constexpr unsigned int Error = static_cast(Type::Error); + std::string str(unsigned int id) const { - switch (id) { - case None: + switch (static_cast(id)) { + case Type::None: return "None"; - case Locked: + case Type::Locked: return "Locked"; - case Active: + case Type::Active: return "Active"; - // case Resetting: + // case Type::Resetting: // return "Resetting"; - case Paused: + case Type::Paused: return "Paused"; - case Stopping: + case Type::Stopping: return "Stopping"; - case Stopped: + case Type::Stopped: return "Stopped"; - case Closed: + case Type::Closed: return "Closed"; - case Error: + case Type::Error: return "Error"; - default: - assert(false); } return "undefined"; } @@ -234,11 +255,16 @@ struct PacketStreamState : public State class Base_API PacketStream : public Stateful { public: - typedef std::shared_ptr Ptr; + using Ptr = std::shared_ptr; PacketStream(const std::string& name = ""); virtual ~PacketStream(); + PacketStream(const PacketStream&) = delete; + PacketStream& operator=(const PacketStream&) = delete; + PacketStream(PacketStream&&) = delete; + PacketStream& operator=(PacketStream&&) = delete; + /// Start the stream and synchronized sources. virtual void start(); @@ -288,12 +314,11 @@ class Base_API PacketStream : public Stateful virtual void attachSource(PacketSignal& source); /// Attaches a source packet emitter to the stream. - /// If freePointer is true, the pointer will be deleted when the stream is - /// closed. - /// If syncState is true and the source is a basic::Stratable, then + /// If owned is true, the stream takes ownership and will delete the pointer. + /// If syncState is true and the source is a basic::Startable, then /// the source's start()/stop() methods will be synchronized when /// calling startSources()/stopSources(). - virtual void attachSource(PacketStreamAdapter* source, bool freePointer = true, bool syncState = false); + virtual void attachSource(PacketStreamAdapter* source, bool owned = true, bool syncState = false); /// Attaches a source packet emitter to the stream. /// This method enables compatibility with shared_ptr managed adapter @@ -303,48 +328,41 @@ class Base_API PacketStream : public Stateful { auto source = dynamic_cast(ptr.get()); if (!source) { - assert(0 && "invalid adapter"); throw std::runtime_error("Cannot attach incompatible packet source."); } attachSource(std::make_shared( - source, new ScopedSharedPointer(ptr), false, syncState)); + std::move(ptr), 0, syncState)); } /// Detaches the given source packet signal from the stream. virtual bool detachSource(PacketSignal& source); /// Detaches the given source packet adapter from the stream. - /// Note: The pointer will be forgotten about, so if the freePointer - /// flag set when calling attachSource() will have no effect. virtual bool detachSource(PacketStreamAdapter* source); /// Attaches a packet processor to the stream. /// Order determines the position of the processor in the stream queue. - /// If freePointer is true, the pointer will be deleted when the stream - /// closes. - virtual void attach(PacketProcessor* proc, int order = 0, bool freePointer = true); + /// If owned is true, the stream takes ownership and will delete the pointer. + virtual void attach(PacketProcessor* proc, int order = 0, bool owned = true); /// Attaches a packet processor to the stream. /// This method enables compatibility with shared_ptr managed adapter /// instances. template - void attach(std::shared_ptr ptr, bool syncState = false) + void attach(std::shared_ptr ptr, int order = 0, bool syncState = false) { auto proc = dynamic_cast(ptr.get()); if (!proc) { - assert(0 && "invalid adapter"); throw std::runtime_error( "Cannot attach incompatible packet processor."); } attach(std::make_shared( - proc, new ScopedSharedPointer(ptr), 0, syncState)); + std::move(ptr), order, syncState)); } /// Detaches a packet processor from the stream. - /// Note: The pointer will be forgotten about, so if the freePointer - /// flag set when calling attach() will have no effect. virtual bool detach(PacketProcessor* proc); /// Synchronize stream output packets with the given event loop. @@ -399,7 +417,8 @@ class Base_API PacketStream : public Stateful int numProcessors() const; int numAdapters() const; - template AdapterT* getSource(int index = 0) + template + AdapterT* getSource(int index = 0) { int x = 0; std::lock_guard guard(_mutex); @@ -415,7 +434,8 @@ class Base_API PacketStream : public Stateful return nullptr; } - template AdapterT* getProcessor(int index = 0) + template + AdapterT* getProcessor(int index = 0) { int x = 0; std::lock_guard guard(_mutex); @@ -445,9 +465,6 @@ class Base_API PacketStream : public Stateful return nullptr; } - // Client data pointer - void* opaque; - protected: /// Attach the source and processor delegate chain. void setup(); @@ -501,14 +518,8 @@ class Base_API PacketStream : public Stateful }; -typedef std::vector PacketStreamVec; -typedef std::vector PacketStreamPtrVec; +using PacketStreamVec = std::vector; +using PacketStreamPtrVec = std::vector; } // namespace scy - - -#endif // SCY_PacketStream_H - - -/// @\} diff --git a/src/base/include/scy/packettransaction.h b/src/base/include/scy/packettransaction.h index 217c40339..604b9513f 100644 --- a/src/base/include/scy/packettransaction.h +++ b/src/base/include/scy/packettransaction.h @@ -9,14 +9,12 @@ /// @{ -#ifndef SCY_PacketTransaction_H -#define SCY_PacketTransaction_H +#pragma once #include "scy/base.h" #include "scy/interface.h" #include "scy/packet.h" -#include "scy/memory.h" #include "scy/stateful.h" #include "scy/timer.h" @@ -59,8 +57,8 @@ struct TransactionState : public State /// PacketTransactions are fire and forget. The object will be deleted /// after a successful response or a timeout. template -class PacketTransaction : public basic::Sendable, - public Stateful +class PacketTransaction : public basic::Sendable + , public Stateful { public: PacketTransaction(long timeout = 10000, int retries = 0, @@ -122,7 +120,7 @@ class PacketTransaction : public basic::Sendable, _timer.Timeout -= slot(this, &PacketTransaction::onTimeout); _timer.stop(); - deleteLater(this); + delete this; } } @@ -200,47 +198,56 @@ class PacketTransaction : public basic::Sendable, }; -template inline void PacketTransaction::cancel() +template +inline void PacketTransaction::cancel() { setState(this, TransactionState::Cancelled); } -template inline bool PacketTransaction::cancelled() const +template +inline bool PacketTransaction::cancelled() const { return stateEquals(TransactionState::Cancelled); } -template inline bool PacketTransaction::canResend() +template +inline bool PacketTransaction::canResend() { return !cancelled() && attempts() <= retries(); } -template inline int PacketTransaction::attempts() const +template +inline int PacketTransaction::attempts() const { return _attempts; } -template inline int PacketTransaction::retries() const +template +inline int PacketTransaction::retries() const { return _retries; } -template inline T& PacketTransaction::request() +template +inline T& PacketTransaction::request() { return _request; } -template inline T PacketTransaction::request() const +template +inline T PacketTransaction::request() const { return _request; } -template inline T& PacketTransaction::response() +template +inline T& PacketTransaction::response() { return _response; } -template inline T PacketTransaction::response() const +template +inline T PacketTransaction::response() const { return _response; } @@ -249,7 +256,4 @@ template inline T PacketTransaction::response() const } // namespace scy -#endif // SCY_PacketTransaction_H - - /// @\} diff --git a/src/base/include/scy/pipe.h b/src/base/include/scy/pipe.h index 936c7bae0..b031dfdd9 100644 --- a/src/base/include/scy/pipe.h +++ b/src/base/include/scy/pipe.h @@ -9,8 +9,7 @@ /// @{ -#ifndef SCY_Pipe_H -#define SCY_Pipe_H +#pragma once #include "scy/base.h" @@ -37,7 +36,4 @@ class Base_API Pipe : public Stream } // namespace scy -#endif // SCY_Stream_H - - /// @\} diff --git a/src/base/include/scy/platform.h b/src/base/include/scy/platform.h index 4d707358e..365431541 100644 --- a/src/base/include/scy/platform.h +++ b/src/base/include/scy/platform.h @@ -9,14 +9,13 @@ /// @{ -#ifndef SCY_Platform_H -#define SCY_Platform_H +#pragma once #include "scy/base.h" -#include #include +#include namespace scy { @@ -64,7 +63,6 @@ Base_API bool getEnvBool(const std::string& name); #ifdef SCY_WIN -Base_API bool getOsVersion(int* major, int* minor, int* build); Base_API bool isWindowsVistaOrLater(); Base_API bool isWindowsXpOrLater(); @@ -77,9 +75,3 @@ Base_API std::string toUtf8(const std::wstring& wstr); } // namespace scy - - -#endif // SCY_Platform_H - - -/// @\} diff --git a/src/base/include/scy/process.h b/src/base/include/scy/process.h index 1e80c95fd..3f201906c 100644 --- a/src/base/include/scy/process.h +++ b/src/base/include/scy/process.h @@ -9,22 +9,21 @@ /// @{ -#ifndef SCY_Process_H -#define SCY_Process_H +#pragma once #include "scy/base.h" -#include "scy/pipe.h" #include "scy/handle.h" +#include "scy/pipe.h" #include -#include #include +#include namespace scy { -typedef uv_process_options_t ProcessOptions; +using ProcessOptions = uv_process_options_t; class Base_API Process @@ -39,30 +38,41 @@ class Base_API Process /// Destructor. ~Process(); + Process(const Process&) = delete; + Process& operator=(const Process&) = delete; + Process(Process&&) = delete; + Process& operator=(Process&&) = delete; + /// Path to the program to execute. - /// Cenvenience proxy for options.file. + /// Convenience proxy for options.file. /// Must be set before `spawn()` std::string file; /// Set the current working directory. - /// Cenvenience proxy for options.cwd. + /// Convenience proxy for options.cwd. /// Must be set before `spawn()` std::string cwd; - /// Command line agruments to pass to the process. - /// Cenvenience proxy for options.args. + /// Command line arguments to pass to the process. + /// Convenience proxy for options.args. /// Must be set before `spawn()` std::vector args; + /// Environment variables for the process. + /// Each entry should be in "KEY=VALUE" format. + /// If empty, the child inherits the parent environment. + /// Must be set before `spawn()` + std::vector env; + /// Spawns the process. /// Options must be properly set. - /// Throws and exception on error. + /// Throws an exception on error. void spawn(); - /// Kills the process + /// Kills the process. bool kill(int signum = SIGKILL); - /// Returns the process PID + /// Returns the process PID, or 0 if not spawned. int pid() const; /// Returns the stdin pipe. @@ -71,12 +81,19 @@ class Base_API Process /// Returns the stdout pipe. Pipe& out(); - /// Stdout signal. - /// Signals when a line has been output from the process. + /// Returns the stderr pipe. + Pipe& err(); + + /// Stdout callback. + /// Called when a line has been output from the process. std::function onstdout; - /// Exit stgnals. - /// Signals process exit status code. + /// Stderr callback. + /// Called when a line has been output on stderr. + std::function onstderr; + + /// Exit callback. + /// Called with process exit status code. std::function onexit; /// LibUV C options. @@ -89,15 +106,14 @@ class Base_API Process uv::Handle _handle; Pipe _stdin; Pipe _stdout; - uv_stdio_container_t _stdio[2]; + Pipe _stderr; + uv_stdio_container_t _stdio[3]; std::vector _cargs; + std::vector _cenv; }; } // namespace scy -#endif // SCY_Process_H - - /// @\} diff --git a/src/base/include/scy/queue.h b/src/base/include/scy/queue.h index 1c73f7000..3a5c3dc7c 100644 --- a/src/base/include/scy/queue.h +++ b/src/base/include/scy/queue.h @@ -9,8 +9,7 @@ /// @{ -#ifndef SCY_Queue_H -#define SCY_Queue_H +#pragma once #include "scy/base.h" @@ -20,13 +19,15 @@ #include "scy/synchronizer.h" #include "scy/thread.h" #include +#include namespace scy { /// Thread-safe queue container. -template class Queue +template +class Queue { public: void push(const T& data) @@ -101,7 +102,8 @@ template class Queue template -class RunnableQueue : public Queue, public basic::Runnable +class RunnableQueue : public Queue + , public basic::Runnable { public: /// The default dispatch function. @@ -126,7 +128,7 @@ class RunnableQueue : public Queue, public basic::Runnable std::lock_guard guard(_mutex); while (_limit > 0 && static_cast(Queue::size()) >= _limit) { - LWarn("Purging: ", Queue::size()) + LWarn("Purging: ", Queue::size()); delete Queue::front(); Queue::pop(); } @@ -165,9 +167,8 @@ class RunnableQueue : public Queue, public basic::Runnable runTimeout(); } else { while (!cancelled()) { - dispatchNext(); - scy::sleep(1); - // scy::sleep(dispatchNext() ? 1 : 50); + if (!dispatchNext()) + std::this_thread::yield(); } } } @@ -200,13 +201,16 @@ class RunnableQueue : public Queue, public basic::Runnable void setTimeout(int milliseconds) { std::lock_guard guard(_mutex); - assert(Queue::empty() && "queue must not be active"); + if (!Queue::empty()) + throw std::logic_error("Cannot change timeout while queue is active"); _timeout = milliseconds; } protected: RunnableQueue(const RunnableQueue&) = delete; RunnableQueue& operator=(const RunnableQueue&) = delete; + RunnableQueue(RunnableQueue&&) = delete; + RunnableQueue& operator=(RunnableQueue&&) = delete; /// Pops the next waiting item. virtual T* popNext() @@ -253,7 +257,7 @@ template class SyncQueue : public RunnableQueue { public: - typedef RunnableQueue Queue; + using Queue = RunnableQueue; SyncQueue(uv::Loop* loop, int limit = 2048, int timeout = 20) : Queue(limit, timeout) @@ -308,7 +312,7 @@ template class AsyncQueue : public RunnableQueue { public: - typedef RunnableQueue Queue; + using Queue = RunnableQueue; AsyncQueue(int limit = 2048) : Queue(limit) @@ -334,7 +338,4 @@ class AsyncQueue : public RunnableQueue } // namespace scy -#endif // SCY_Queue_H - - /// @\} diff --git a/src/base/include/scy/random.h b/src/base/include/scy/random.h index a267b809e..f684dadc7 100644 --- a/src/base/include/scy/random.h +++ b/src/base/include/scy/random.h @@ -11,12 +11,12 @@ // -#ifndef SCY_Random_H -#define SCY_Random_H +#pragma once #include "scy/base.h" #include +#include namespace scy { @@ -92,16 +92,13 @@ class Base_API Random int _randDeg; int _randSep; uint32_t* _endPtr; - char* _buffer; + std::unique_ptr _buffer; }; } // namespace scy -#endif // SCY_Random_H - - /// @\} diff --git a/src/base/include/scy/ratelimiter.h b/src/base/include/scy/ratelimiter.h new file mode 100644 index 000000000..c14b85572 --- /dev/null +++ b/src/base/include/scy/ratelimiter.h @@ -0,0 +1,78 @@ +/// +// +// LibSourcey +// Copyright (c) 2005, Sourcey +// +// SPDX-License-Identifier: LGPL-2.1+ +// +/// @addtogroup base +/// @{ + + +#pragma once + + +#include "scy/logger.h" +#include + + +namespace scy { + + +/// @addtogroup base +/// A simple message rate limiter based on the token bucket algorithm. +class /* SCY_EXTERN */ RateLimiter +{ +public: + double rate; ///< How many messages + double seconds; ///< Over how many seconds + double allowance; ///< Remaining send allowance + + RateLimiter(double rate = 5.0, double seconds = 6.0) + : rate(rate) + , seconds(seconds) + , allowance(rate) + , _lastCheck() + , _started(false) + { + } + + bool canSend() + { + auto current = std::chrono::steady_clock::now(); + if (!_started) { + _lastCheck = current; + _started = true; + } + double elapsed = std::chrono::duration(current - _lastCheck).count(); + _lastCheck = current; + allowance += elapsed * (rate / seconds); + + LTrace("Can send: allowance=", allowance, " elapsed=", elapsed, + " rate=", rate, " seconds=", seconds); + + if (allowance > rate) + { + allowance = rate; // throttle + LTrace("Throttling: ", allowance); + } + else if (allowance < 1.0) + { + LTrace("Message rate exceeded: ", allowance); + return false; + } + allowance -= 1.0; + LTrace("Can send message: ", allowance); + return true; + } + +private: + std::chrono::steady_clock::time_point _lastCheck; + bool _started; +}; + + +} // namespace scy + + +/// @\} diff --git a/src/base/include/scy/request.h b/src/base/include/scy/request.h index 735be4309..6b5a5a40f 100644 --- a/src/base/include/scy/request.h +++ b/src/base/include/scy/request.h @@ -9,8 +9,7 @@ /// @{ -#ifndef SCY_UV_Request_H -#define SCY_UV_Request_H +#pragma once #include "scy/base.h" @@ -42,11 +41,11 @@ struct BasicEvent /// This class povides safe access to the parent handle incase the handle gets /// destroyed before the request callback returns, and should be used whenever /// the handle pointer is accessed via the callback. -template +template struct Request { - typedef T Type; - typedef E Event; + using Type = T; + using Event = E; T req; std::function callback; @@ -64,18 +63,19 @@ struct Request delete wrap; } - template + template auto invoke(F&& f, Args&&... args) - -> std::enable_if_t>::value, int> + -> std::enable_if_t>::value, int> { auto err = std::forward(f)(std::forward(args)...); - if (err && callback) callback(E{err}); + if (err && callback) + callback(E{err}); return !err; } - template + template auto invoke(F&& f, Args&&... args) - -> std::enable_if_t>::value> + -> std::enable_if_t>::value> { std::forward(f)(std::forward(args)...); } @@ -83,7 +83,7 @@ struct Request /// Generic helper for instantiating requests. -template +template inline T& createRequest(std::function callback) { auto req = new T(); @@ -123,7 +123,7 @@ struct GetAddrInfoEvent /// DNS resolver request to get the IP address of a hostname. struct GetAddrInfoReq : public uv::Request { - typedef uv::Request Request; + using Request = uv::Request; GetAddrInfoReq() { @@ -147,13 +147,8 @@ struct GetAddrInfoReq : public uv::Request }; - - } // namespace uv } // namespace scy -#endif // SCY_UV_Request - - /// @\} diff --git a/src/base/include/scy/runner.h b/src/base/include/scy/runner.h index 2e93a94c5..01b75002d 100644 --- a/src/base/include/scy/runner.h +++ b/src/base/include/scy/runner.h @@ -9,22 +9,21 @@ /// @{ -#ifndef SCY_Runner_H -#define SCY_Runner_H +#pragma once #include "scy/base.h" #include "scy/interface.h" -#include "scy/platform.h" -#include "scy/util.h" -#include -#include #include +#include +#include #include +#include #include #include -#include +#include +#include namespace scy { @@ -106,6 +105,8 @@ class Base_API Runner /// NonCopyable and NonMovable Runner(const Runner&) = delete; Runner& operator=(const Runner&) = delete; + Runner(Runner&&) = delete; + Runner& operator=(Runner&&) = delete; /// Shared pointer to the internal Context. std::shared_ptr _context; @@ -121,10 +122,9 @@ namespace internal { /// Helper function for running an async context. -template +template inline void runAsync(std::shared_ptr c, Function func, Args... args) { - // std::cout << "Runner::runAsync" << std::endl; c->tid = std::this_thread::get_id(); c->running = true; do { @@ -137,39 +137,16 @@ inline void runAsync(std::shared_ptr c, Function func, Args... std::cerr << "Runner exception: " << exc.what() << std::endl; } #endif - scy::sleep(1); + if (c->repeating && !c->cancelled) + std::this_thread::yield(); } while (c->repeating && !c->cancelled); c->running = false; } -/// Call a function with the given argument tuple. -/// -/// Note: This will become redundant once C++17 `std::apply` is fully supported. -template -auto invoke(Function f, Tuple t, std::index_sequence) -{ - return f(std::get(t)...); -} - - -/// Call a function with the given argument tuple. -/// -/// Create an index sequence for the array, and pass it to the -/// implementation `invoke` function. -/// -/// Note: This will become redundant once C++17 `std::apply` is fully supported. -template -auto invoke(Function f, Tuple t) -{ - static constexpr auto size = std::tuple_size::value; - return invoke(f, t, std::make_index_sequence{}); -} - - -/// Helper class that stores a function pointer and veradic arguments as a tuple +/// Helper class that stores a function pointer and variadic arguments as a tuple /// for deferred invocation. -template +template struct DeferredCallable { std::shared_ptr ctx; @@ -185,7 +162,7 @@ struct DeferredCallable void invoke() { - internal::invoke(func, args); + std::apply(func, args); } }; @@ -194,7 +171,4 @@ struct DeferredCallable } // namespace scy -#endif // SCY_Runner_H - - /// @\} diff --git a/src/base/include/scy/sharedlibrary.h b/src/base/include/scy/sharedlibrary.h index 3c736badb..91a768654 100644 --- a/src/base/include/scy/sharedlibrary.h +++ b/src/base/include/scy/sharedlibrary.h @@ -9,8 +9,7 @@ /// @{ -#ifndef SCY_SharedLibrary_H -#define SCY_SharedLibrary_H +#pragma once #include "scy/util.h" @@ -72,7 +71,4 @@ struct SharedLibrary } // namespace scy -#endif // SCY_SharedLibrary_H - - /// @\} diff --git a/src/base/include/scy/signal.h b/src/base/include/scy/signal.h index 05f4dbc1b..28616bcf7 100644 --- a/src/base/include/scy/signal.h +++ b/src/base/include/scy/signal.h @@ -9,16 +9,17 @@ /// @{ -#ifndef SCY_Signal_H -#define SCY_Signal_H +#pragma once #include "scy/delegate.h" -#include +#include #include #include +#include +#include +#include #include -#include namespace scy { @@ -28,19 +29,12 @@ namespace scy { namespace internal { /// Signal slot storage class. -template struct Slot; +template +struct Slot; } // namespace internal -/// Exception to break out of the current Signal callback scope. -class StopPropagation : public std::exception -{ -public: - virtual ~StopPropagation() throw() = default; -}; - - /// Signal and slots implementation. /// /// To create a signal, declare member variables of type @@ -123,16 +117,18 @@ class StopPropagation : public std::exception /// will cause any callbacks connected to the signal to be called, /// passing the integer `42` as the only argument. /// -template class Signal; -template class Signal +template +class Signal; +template +class Signal { public: - typedef std::function Function; - typedef std::shared_ptr> SlotPtr; + using Function = std::function; + using SlotPtr = std::shared_ptr>; /// Connects a `lambda` or `std::function` to the `Signal`. /// The returned value can be used to detach the slot. - int attach(Function const& func, void* instance = nullptr, int id = -1, int priority = -1) const + [[nodiscard]] int attach(Function const& func, void* instance = nullptr, int id = -1, int priority = -1) const { return attach(std::make_shared>( new FunctionDelegate(func), instance, id, priority)); @@ -140,24 +136,32 @@ template class Signal /// Connects a `SlotPtr` instance to the `Signal`. /// The returned value can be used to detach the slot. - int attach(SlotPtr slot) const + [[nodiscard]] int attach(SlotPtr slot) const { detach(slot); // clear duplicates - std::lock_guard guard(_mutex); - if (slot->id == -1) - slot->id = ++_lastId; // TODO: assert unique? + std::unique_lock guard(_mutex); + if (slot->id == -1) { + slot->id = ++_lastId; + } else { + // Ensure explicit IDs don't collide with existing slots + for (auto const& s : _slots) { + if (s->alive() && s->id == slot->id) + throw std::logic_error("Signal slot ID already in use"); + } + if (slot->id > _lastId) + _lastId = slot->id; + } _slots.push_back(slot); //_slots.sort(Slot::ComparePrioroty); std::sort(_slots.begin(), _slots.end(), - [](SlotPtr const& l, SlotPtr const& r) { - return l->priority > r->priority; }); + [](SlotPtr const& l, SlotPtr const& r) { return l->priority > r->priority; }); return slot->id; } /// Detaches a previously attached slot. bool detach(int id) const { - std::lock_guard guard(_mutex); + std::unique_lock guard(_mutex); for (auto it = _slots.begin(); it != _slots.end();) { auto& slot = *it; if (slot->alive() && slot->id == id) { @@ -173,8 +177,8 @@ template class Signal /// Detaches all slots for the given instance. bool detach(const void* instance) const { - std::lock_guard guard(_mutex); - bool removed = true; + std::unique_lock guard(_mutex); + bool removed = false; for (auto it = _slots.begin(); it != _slots.end();) { auto& slot = *it; if (slot->alive() && slot->instance == instance) { @@ -190,7 +194,7 @@ template class Signal /// Detaches all attached functions for the given instance. bool detach(SlotPtr other) const { - std::lock_guard guard(_mutex); + std::unique_lock guard(_mutex); for (auto it = _slots.begin(); it != _slots.end();) { auto& slot = *it; if (slot->alive() && (*slot->delegate == *other->delegate)) { @@ -206,7 +210,7 @@ template class Signal /// Detaches all previously attached functions. void detachAll() const { - std::lock_guard guard(_mutex); + std::unique_lock guard(_mutex); while (!_slots.empty()) { _slots.back()->kill(); _slots.pop_back(); @@ -214,30 +218,39 @@ template class Signal } /// Emits the signal to all attached functions. - virtual void emit(Args... args) //const + /// For Signal, returns true if any slot returned true + /// (stops propagation to remaining slots). + /// For Signal, calls all slots unconditionally. + virtual RT emit(Args... args) { - try { + if constexpr (std::is_same_v) { + for (auto const& slot : slots()) { + if (slot->alive()) { + if ((*slot->delegate)(std::forward(args)...)) + return true; + } + } + return false; + } else { for (auto const& slot : slots()) { if (slot->alive()) { (*slot->delegate)(std::forward(args)...); } } } - catch (StopPropagation&) { - } } /// Returns the managed slot list. std::vector slots() const { - std::lock_guard guard(_mutex); + std::shared_lock guard(_mutex); return _slots; } /// Returns the number of active slots. - size_t nslots() const + [[nodiscard]] size_t nslots() const { - std::lock_guard guard(_mutex); + std::shared_lock guard(_mutex); return _slots.size(); } @@ -266,7 +279,7 @@ template class Signal } /// Assignment operator - Signal& operator = (const Signal& r) + Signal& operator=(const Signal& r) { if (&r != this) { _slots = r._slots; @@ -276,13 +289,13 @@ template class Signal } private: - mutable std::mutex _mutex; + mutable std::shared_mutex _mutex; mutable std::vector _slots; mutable int _lastId = 0; }; -typedef Signal NullSignal; +using NullSignal = Signal; // @@ -316,7 +329,8 @@ slot(RT (*method)(Args...), int id = -1, int priority = -1) return std::make_shared>( new FunctionDelegate([method](Args... args) { return (*method)(std::forward(args)...); - }), nullptr, id, priority); + }), + nullptr, id, priority); } @@ -324,9 +338,10 @@ slot(RT (*method)(Args...), int id = -1, int priority = -1) namespace internal { /// Signal slot storage class. -template struct Slot +template +struct Slot { - AbstractDelegate* delegate; + std::unique_ptr> delegate; void* instance; int id; int priority; @@ -341,11 +356,7 @@ template struct Slot flag.test_and_set(); } - ~Slot() - { - if (delegate) - delete delegate; - } + ~Slot() = default; void kill() { @@ -368,7 +379,4 @@ template struct Slot } // namespace scy -#endif // SCY_Signal_H - - /// @\} diff --git a/src/base/include/scy/singleton.h b/src/base/include/scy/singleton.h index 1fc349801..d590dc377 100644 --- a/src/base/include/scy/singleton.h +++ b/src/base/include/scy/singleton.h @@ -9,54 +9,41 @@ /// @{ -#ifndef SCY_Singleton_H -#define SCY_Singleton_H +#pragma once -#include +#include #include namespace scy { -/// This is a helper template class for managing -/// singleton objects allocated on the heap. +/// Helper template class for managing singleton objects allocated on the heap. template class Singleton { public: - /// Creates the Singleton wrapper. - Singleton() - : _ptr(0) - { - } + Singleton() = default; - /// Destroys the Singleton wrapper and the managed - /// singleton instance it holds. - ~Singleton() - { - if (_ptr) - delete _ptr; - } + ~Singleton() = default; - /// Returns a pointer to the singleton object hold by the Singleton. - /// The first call to get on a nullptr singleton will instantiate - /// the singleton. + /// Returns a pointer to the singleton object held by the Singleton. + /// The first call to get will instantiate the singleton. S* get() { std::lock_guard guard(_m); if (!_ptr) - _ptr = new S; - return _ptr; + _ptr.reset(new S()); + return _ptr.get(); } /// Swaps the old pointer with the new one and returns the old instance. S* swap(S* newPtr) { std::lock_guard guard(_m); - S* oldPtr = _ptr; - _ptr = newPtr; + S* oldPtr = _ptr.release(); + _ptr.reset(newPtr); return oldPtr; } @@ -64,21 +51,19 @@ class Singleton void destroy() { std::lock_guard guard(_m); - if (_ptr) - delete _ptr; - _ptr = nullptr; + _ptr.reset(); } private: - S* _ptr; + /// Custom deleter that can access private destructors via friendship. + struct Deleter + { + void operator()(S* p) const { delete p; } + }; + + std::unique_ptr _ptr; std::mutex _m; }; } // namespace scy - - -#endif // SCY_Singleton_H - - -/// @\} diff --git a/src/base/include/scy/stateful.h b/src/base/include/scy/stateful.h index f832e2e71..8d8d4e32c 100644 --- a/src/base/include/scy/stateful.h +++ b/src/base/include/scy/stateful.h @@ -9,8 +9,7 @@ /// @{ -#ifndef SCY_Stateful_H -#define SCY_Stateful_H +#pragma once #include "scy/base.h" @@ -32,7 +31,7 @@ namespace scy { class Base_API State { public: - typedef uint32_t ID; + using ID = uint32_t; State(ID id = 0); State(const State& that); @@ -136,7 +135,4 @@ class Stateful } // namespace scy -#endif // SCY_Stateful_H - - /// @\} diff --git a/src/base/include/scy/stream.h b/src/base/include/scy/stream.h index 16793b2c3..1bdfc83c6 100644 --- a/src/base/include/scy/stream.h +++ b/src/base/include/scy/stream.h @@ -9,16 +9,15 @@ /// @{ -#ifndef SCY_Stream_H -#define SCY_Stream_H +#pragma once #include "scy/base.h" +#include "scy/buffer.h" #include "scy/handle.h" +#include "scy/logger.h" #include "scy/request.h" -#include "scy/buffer.h" #include "scy/signal.h" -#include "scy/logger.h" #include @@ -27,11 +26,11 @@ namespace scy { /// Basic stream type for sockets and pipes. -template +template class Base_API Stream : public uv::Handle { public: - typedef uv::Handle Handle; + using Handle = uv::Handle; Stream(uv::Loop* loop = uv::defaultLoop()) : uv::Handle(loop) @@ -50,7 +49,7 @@ class Base_API Stream : public uv::Handle /// If the stream is already closed this call will have no side-effects. virtual void close() override { - // LTrace("Close: ", ptr()) + // LTrace("Close: ", ptr()); if (_started) readStop(); Handle::close(); @@ -64,44 +63,52 @@ class Base_API Stream : public uv::Handle if (!Handle::active()) return false; - // XXX: Sending shutdown causes an eof error to be returned via - // handleRead() which sets the stream to error state. This is not - // really an error, perhaps it should be handled differently? return uv_shutdown(new uv_shutdown_t, stream(), - [](uv_shutdown_t* req, int) { - delete req; - }) == 0; + [](uv_shutdown_t* req, int) { + delete req; + }) == 0; } /// Writes data to the stream. /// - /// Return false if the underlying socket is closed. + /// Return false if the underlying socket is closed or if the write + /// queue has exceeded the high water mark (backpressure). /// This method does not throw an exception. bool write(const char* data, size_t len) { - if (!Handle::active()) + if (!Handle::active() || !_started) return false; - assert(_started); + // Backpressure: reject writes if libuv's write queue is too large. + // This prevents unbounded memory growth on slow connections. + size_t queueSize = stream()->write_queue_size; + if (queueSize > _highWaterMark) { + LWarn("Write queue full (", queueSize, " bytes), dropping write of ", len, " bytes"); + return false; + } - auto buf = uv_buf_init((char*)data, (int)len); + auto buf = uv_buf_init(const_cast(data), static_cast(len)); return Handle::invoke(&uv_write, new uv_write_t, stream(), &buf, 1, [](uv_write_t* req, int) { delete req; }); } + /// Set the high water mark for the write queue (default 16MB). + /// When the write queue exceeds this size, write() returns false. + void setHighWaterMark(size_t bytes) { _highWaterMark = bytes; } + /// Write data to the target stream. /// /// This method is only valid for IPC streams. bool write(const char* data, size_t len, uv_stream_t* send) { - if (!Handle::active()) + if (!Handle::active() || !_started) return false; - assert(_started); - assert(stream()->type == UV_NAMED_PIPE && this->template get()->ipc); + if (stream()->type != UV_NAMED_PIPE || !this->template get()->ipc) + throw std::logic_error("write2 is only valid for IPC pipes"); - auto buf = uv_buf_init((char*)data, (int)len); + auto buf = uv_buf_init(const_cast(data), static_cast(len)); return Handle::invoke(&uv_write2, new uv_write_t, stream(), &buf, 1, send, [](uv_write_t* req, int) { delete req; }); @@ -119,8 +126,9 @@ class Base_API Stream : public uv::Handle protected: virtual bool readStart() { - // LTrace("Read start: ", ptr()) - assert(!_started); + // LTrace("Read start: ", ptr()); + if (_started) + return false; _started = true; stream()->data = this; @@ -129,8 +137,9 @@ class Base_API Stream : public uv::Handle virtual bool readStop() { - // LTrace("Read stop: ", ptr()) - assert(_started); + // LTrace("Read stop: ", ptr()); + if (!_started) + return false; _started = false; return Handle::invoke(&uv_read_stop, stream()); @@ -138,12 +147,11 @@ class Base_API Stream : public uv::Handle virtual void onRead(const char* data, size_t len) { - // LTrace("On read: ", len) - assert(Handle::initialized()); - assert(!Handle::closed()); - assert(_started); + // LTrace("On read: ", len); + if (!Handle::initialized() || Handle::closed() || !_started) + return; - Read.emit(data, (const int)len); + Read.emit(data, static_cast(len)); } // @@ -151,20 +159,23 @@ class Base_API Stream : public uv::Handle static void handleRead(uv_stream_t* handle, ssize_t nread, const uv_buf_t* buf) { - // LTrace("Handle read: ", nread) + // LTrace("Handle read: ", nread); auto self = reinterpret_cast(handle->data); #ifdef SCY_EXCEPTION_RECOVERY try { #endif if (nread >= 0) { self->onRead(buf->base, nread); - } - else { - self->setUVError((int)nread, "Stream read error"); + } else if (nread == UV_EOF) { + // EOF is not an error - it's the normal result of the peer + // closing their end of the connection (e.g. after shutdown). + // Close the stream gracefully instead of setting error state. + self->close(); + } else { + self->setUVError(static_cast(nread), "Stream read error"); } #ifdef SCY_EXCEPTION_RECOVERY - } - catch (std::exception& exc) { + } catch (std::exception& exc) { // Exceptions thrown inside the read callback scope will set the // stream error in order to keep errors in the event loop LError("Stream exception: ", exc.what()); @@ -176,9 +187,8 @@ class Base_API Stream : public uv::Handle static void allocReadBuffer(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) { auto& buffer = reinterpret_cast(handle->data)->_buffer; - assert(buffer.size() >= suggested_size); - // if (suggested_size > buffer.capacity()) - // buffer.capacity(suggested_size); + if (buffer.size() < suggested_size) + buffer.resize(suggested_size); buf->base = buffer.data(); buf->len = buffer.size(); @@ -187,13 +197,11 @@ class Base_API Stream : public uv::Handle protected: Buffer _buffer; bool _started{false}; + size_t _highWaterMark{16 * 1024 * 1024}; ///< 16MB default write queue limit }; } // namespace scy -#endif // SCY_Stream_H - - /// @\} diff --git a/src/util/include/scy/util/streammanager.h b/src/base/include/scy/streammanager.h similarity index 67% rename from src/util/include/scy/util/streammanager.h rename to src/base/include/scy/streammanager.h index 85573aa69..93a0694f8 100644 --- a/src/util/include/scy/util/streammanager.h +++ b/src/base/include/scy/streammanager.h @@ -5,12 +5,11 @@ // // SPDX-License-Identifier: LGPL-2.1+ // -/// @addtogroup util +/// @addtogroup base /// @{ -#ifndef SCY_StreamManager_H -#define SCY_StreamManager_H +#pragma once #include "scy/collection.h" @@ -20,18 +19,17 @@ namespace scy { -typedef LiveCollection> StreamManagerBase; +using StreamManagerBase = LiveCollection; class /* SCY_EXTERN */ StreamManager : public StreamManagerBase { public: - typedef StreamManagerBase Manager; - typedef Manager::Map Map; + using Manager = StreamManagerBase; + using Map = Manager::Map; public: - StreamManager(bool freeClosedStreams = true); + StreamManager(); virtual ~StreamManager(); virtual bool addStream(PacketStream* stream, bool whiny = true); @@ -39,10 +37,10 @@ class /* SCY_EXTERN */ StreamManager : public StreamManagerBase virtual void closeAll(); virtual PacketStream* getStream(const std::string& name, bool whiny = true); - /// Returns the first stream in the list, or NULL. - virtual PacketStream* getDafaultStream(); + /// Returns the first stream in the list, or nullptr. + virtual PacketStream* getDefaultStream(); - virtual Map streams() const; + virtual const Map& streams() const; virtual void print(std::ostream& os) const; @@ -58,14 +56,10 @@ class /* SCY_EXTERN */ StreamManager : public StreamManagerBase virtual const char* className() const { return "Stream Manager"; }; protected: - bool _freeClosedStreams; }; } // namespace scy -#endif // SCY_StreamManager_H - - /// @\} diff --git a/src/base/include/scy/synchronizer.h b/src/base/include/scy/synchronizer.h index 0ca08e29e..ccaef3aff 100644 --- a/src/base/include/scy/synchronizer.h +++ b/src/base/include/scy/synchronizer.h @@ -9,16 +9,16 @@ /// @{ -#ifndef SCY_Synchronizer_H -#define SCY_Synchronizer_H +#pragma once #include "scy/base.h" +#include "scy/handle.h" #include "scy/interface.h" #include "scy/logger.h" #include "scy/platform.h" -#include "scy/handle.h" +#include #include @@ -48,7 +48,7 @@ class Base_API Synchronizer : public Runner Synchronizer(std::function target, uv::Loop* loop = uv::defaultLoop()); /// Create the synchronization context the given event loop and method. - template + template explicit Synchronizer(Function&& func, Args&&... args, uv::Loop* loop = uv::defaultLoop()) : _handle(loop) { @@ -66,10 +66,10 @@ class Base_API Synchronizer : public Runner void post(); /// Start the synchronizer with the given callback. - template + template void start(Function&& func, Args&&... args) { - typedef internal::DeferredCallable Callback; + using Callback = internal::DeferredCallable; // assert(!_handle.active()); assert(!_context->running); @@ -88,8 +88,7 @@ class Base_API Synchronizer : public Runner auto wrap = reinterpret_cast(req->data); if (!wrap->ctx->cancelled) { wrap->invoke(); - } - else { + } else { req->data = nullptr; wrap->ctx->running = false; delete wrap; @@ -116,123 +115,7 @@ class Base_API Synchronizer : public Runner }; -#if 0 - -// -// Synchronization Delegate -// - -/// This template class implements an adapter that sits between -/// an DelegateBase and an object receiving notifications from it. -template -class Base_API SyncDelegate: public Delegate -{ -public: - //typedef DelegateBase DerivedT; - typedef typename CallbackT::Method Method; - typedef typename BaseT::DataT DataT; - - struct Context - { - void* sender; - P arg; - P2 arg2; - P3 arg3; - P4 arg4; - Context(void* sender, P arg, P2 arg2, P3 arg3, P4 arg4) : - sender(sender), arg(arg), arg2(arg2), arg3(arg3), arg4(arg4) {} - }; - - SyncDelegate(C* object, Method method, uv::Loop* loop = uv::defaultLoop(), int priority = 0) : - Delegate(object, method, priority), - _loop(loop), - _sync(nullptr) - { - } - - SyncDelegate(C* object, Method method, DataT filter, uv::Loop* loop = uv::defaultLoop(), int priority = 0) : - Delegate(object, method, filter, priority), - _loop(loop), - _sync(nullptr) - { - } - - virtual ~SyncDelegate() - { - if (_sync) - _sync->dispose(); - } - - SyncDelegate(const SyncDelegate& r) : - Delegate(r), - _loop(r._loop), - _sync(nullptr) - { - } - - BaseT* clone() const - { - return new SyncDelegate(*this); - } - - virtual void emit(void* sender, P arg, P2 arg2, P3 arg3, P4 arg4) - { - // Create the context on first emit - if (!_sync) { - _sync = new SyncQueue(_loop); - _sync->ondispatch = std::bind(&SyncDelegate::emitSync, this, std::placeholders::_1); - } - _sync->push(new Context(sender, arg, arg2, arg3, arg4)); - } - - void emitSync(Context& ctx) - { - if (!_cancelled) - CallbackT::emit(ctx.sender, ctx.arg, ctx.arg2, ctx.arg3, ctx.arg4); - } - -protected: - SyncDelegate() - { - } - - uv::Loop& _loop; - SyncQueue* _sync; -}; - - -template -static SyncDelegate, - DelegateCallback -> syncDelegate(C* pObj, void (C::*Method)(void*), uv::Loop* loop = uv::defaultLoop(), int priority = 0) -{ - return SyncDelegate, - DelegateCallback - >(pObj, Method, loop, priority); -} - - -template -static SyncDelegate, - DelegateCallback, P -> syncDelegate(C* pObj, void (C::*Method)(void*,P), uv::Loop* loop = uv::defaultLoop(), int priority = 0) -{ - return SyncDelegate, - DelegateCallback, P - >(pObj, Method, loop, priority); -} - -#endif - - } // namespace scy -#endif // SCY_Synchronizer_H - - /// @\} diff --git a/src/base/include/scy/task.h b/src/base/include/scy/task.h index bef12b72e..d82f6666e 100644 --- a/src/base/include/scy/task.h +++ b/src/base/include/scy/task.h @@ -9,14 +9,15 @@ /// @{ -#ifndef SCY_Task_H -#define SCY_Task_H +#pragma once #include "scy/base.h" #include "scy/runner.h" #include "scy/signal.h" -#include "scy/task.h" + +#include +#include namespace scy { @@ -48,19 +49,20 @@ class Base_API Task : public basic::Runnable /// Unique task ID. virtual uint32_t id() const; + virtual ~Task(); + // Inherits basic::Runnable: // // virtual void run(); // virtual void cancel(); // virtual bool cancelled() const; -protected: Task(const Task& task) = delete; Task& operator=(Task const&) = delete; + Task(Task&&) = delete; + Task& operator=(Task&&) = delete; - /// Destroctor. - /// Should remain protected. - virtual ~Task(); +protected: /// Called by the TaskRunner to run the task. /// Override this method to implement task action. @@ -93,6 +95,11 @@ class Base_API TaskRunner : public basic::Runnable TaskRunner(std::shared_ptr runner = nullptr); virtual ~TaskRunner(); + TaskRunner(const TaskRunner&) = delete; + TaskRunner& operator=(const TaskRunner&) = delete; + TaskRunner(TaskRunner&&) = delete; + TaskRunner& operator=(TaskRunner&&) = delete; + /// Starts a task, adding it if it doesn't exist. virtual bool start(Task* task); @@ -163,7 +170,7 @@ class Base_API TaskRunner : public basic::Runnable virtual void onRun(Task* task); protected: - typedef std::deque TaskList; + using TaskList = std::deque>; mutable std::mutex _mutex; std::shared_ptr _runner; @@ -174,7 +181,4 @@ class Base_API TaskRunner : public basic::Runnable } // namespace scy -#endif // SCY_Task_H - - /// @\} diff --git a/src/base/include/scy/test.h b/src/base/include/scy/test.h index b15fd5a95..be464192c 100644 --- a/src/base/include/scy/test.h +++ b/src/base/include/scy/test.h @@ -9,16 +9,15 @@ /// @{ -#ifndef SCY_Test_H -#define SCY_Test_H +#pragma once #include "scy/base.h" #include "scy/interface.h" -#include #include #include #include +#include namespace scy { @@ -31,9 +30,9 @@ namespace test { class Base_API Test; class Base_API TestRunner; -typedef std::list TestList; -typedef std::list SErrorist; -typedef std::map ErrorMap; +using TestList = std::list; +using SErrorist = std::list; +using ErrorMap = std::map; /// Initialize the test environment. Base_API void init(); @@ -57,9 +56,9 @@ Base_API void expectImpl(bool passed, const char* assert, const char* file, long // Shamelessly define macros to aesthetic name :) #ifdef NDEBUG -#define expect(x) test::expectImpl(true, "", "", 0) +#define expect(x) scy::test::expectImpl(true, "", "", 0) #else -#define expect(x) test::expectImpl(x, #x, __FILE__, __LINE__) +#define expect(x) scy::test::expectImpl(x, #x, __FILE__, __LINE__) #endif @@ -183,7 +182,4 @@ class Base_API TestRunner } // namespace scy -#endif // SCY_Test_H - - /// @\} diff --git a/src/base/include/scy/thread.h b/src/base/include/scy/thread.h index 1a8950bc6..5569ccfd9 100644 --- a/src/base/include/scy/thread.h +++ b/src/base/include/scy/thread.h @@ -9,18 +9,16 @@ /// @{ -#ifndef SCY_Thread_H -#define SCY_Thread_H +#pragma once #include "scy/base.h" #include "scy/runner.h" -#include "scy/util.h" +#include #include #include #include -#include namespace scy { @@ -34,7 +32,7 @@ namespace scy { class Base_API Thread : public Runner { public: - typedef std::shared_ptr Ptr; + using Ptr = std::shared_ptr; /// Default constructor. Thread(); @@ -42,11 +40,11 @@ class Base_API Thread : public Runner /// Templated constructor. /// /// This constructor starts the thread with the given function. - template - explicit Thread(Function&& func, Args&&... args) : - _thread(internal::runAsync, _context, - std::forward(func), - std::forward(args)...) + template + explicit Thread(Function&& func, Args&&... args) + : _thread(internal::runAsync, _context, + std::forward(func), + std::forward(args)...) { } @@ -56,7 +54,7 @@ class Base_API Thread : public Runner /// Start a function with veradic arguments. /// /// This method starts the thread with the given function. - template + template void start(Function&& func, Args&&... args) { _thread = std::thread(internal::runAsync, _context, @@ -83,6 +81,8 @@ class Base_API Thread : public Runner /// NonCopyable and NonMovable Thread(const Thread&) = delete; Thread& operator=(const Thread&) = delete; + Thread(Thread&&) = delete; + Thread& operator=(Thread&&) = delete; bool async() const override; @@ -90,55 +90,7 @@ class Base_API Thread : public Runner }; -#if 0 -/// This class is an invisible wrapper around a Startable instance, -/// which provides asynchronous access to the Startable start() and -/// stop() methods. -/// -/// TStartable is an instance of basic::Startable. -/// @deprecated -template -class Base_API AsyncStartable: public TStartable -{ -public: - AsyncStartable() = default; - virtual ~AsyncStartable() = default; - - static void runAsync(void* arg) { - try { - // Call the blocking start() function once only - static_cast(arg)->start(); - } - catch (std::exception& exc) { - // errorL("AsyncLtartable")(exc.what(), ) -#ifdef _DEBUG - throw exc; -#endif - } - } - - virtual bool start() - { - _thread.start(*this); - return true; - } - - virtual void stop() - { - TStartable::stop(); - _thread.join(); - } - -protected: - Thread _thread; -}; -#endif - - } // namespace scy -#endif - - /// @\} diff --git a/src/base/include/scy/time.h b/src/base/include/scy/time.h index 1fab7ed9f..a3db46bc5 100644 --- a/src/base/include/scy/time.h +++ b/src/base/include/scy/time.h @@ -9,14 +9,14 @@ /// @{ -#ifndef SCY_Time_H -#define SCY_Time_H +#pragma once #include "scy/base.h" -#include -#include +#include #include +#include +#include namespace scy { @@ -75,20 +75,9 @@ Base_API std::string getUTC(); /// Return the current high-resolution real time in nanoseconds. Base_API uint64_t hrtime(); -#if 0 -/// Retrieves the number of milliseconds that have elapsed since the system was started, up to 49.7 days. -uint64_t ticks(); - -/// Return the current real time in milliseconds. -uint64_t getTimeMS(); -#endif - } // namespace time } // namespace scy -#endif // SCY_Time_H - - /// @\} diff --git a/src/util/include/scy/util/timedmanager.h b/src/base/include/scy/timedmanager.h similarity index 69% rename from src/util/include/scy/util/timedmanager.h rename to src/base/include/scy/timedmanager.h index fea2e0273..e4a8a1033 100644 --- a/src/util/include/scy/util/timedmanager.h +++ b/src/base/include/scy/timedmanager.h @@ -5,17 +5,16 @@ // // SPDX-License-Identifier: LGPL-2.1+ // -/// @addtogroup util +/// @addtogroup base /// @{ -#ifndef SCY_TimedManager_H -#define SCY_TimedManager_H +#pragma once #include "scy/base.h" #include "scy/collection.h" -#include "scy/util/timeout.h" +#include "scy/timeout.h" namespace scy { @@ -24,12 +23,12 @@ namespace scy { /// /// Provides timed persistent data storage for class instances. /// TValue must implement the clone() method. -template > -class /* SCY_EXTERN */ TimedManager : public PointerCollection +template +class /* SCY_EXTERN */ TimedManager : public PointerCollection { public: - typedef PointerCollection Base; - typedef std::map TimeoutMap; + using Base = PointerCollection; + using TimeoutMap = std::map; TimedManager(uv::Loop* loop = uv::defaultLoop()) : _timer(100, 100, loop) // check every 100ms @@ -56,14 +55,14 @@ class /* SCY_EXTERN */ TimedManager : public PointerCollection guard(_tmutex); if (timeout > 0) { - LTrace("Set timeout: ", item, ": ", timeout) + LTrace("Set timeout: ", item, ": ", timeout); auto& t = _timeouts[item]; t.setDelay(timeout); t.start(); @@ -109,10 +108,7 @@ class /* SCY_EXTERN */ TimedManager : public PointerCollectionfirst << ": " - // << it->second.delay() << ": " - // << it->second.remaining() << std::endl; - if (it->second.expired()) { - // auto item = it->first; - LTrace("Item expired: ", it->first) - onTimeout(it->first); - // it = _timeouts.erase(it); + for (const auto& [item, timeout] : timeouts) { + if (timeout.expired()) { + LTrace("Item expired: ", item); + onTimeout(item); } - // else ++it; } } @@ -143,10 +131,7 @@ class /* SCY_EXTERN */ TimedManager : public PointerCollection #include -#include namespace scy { @@ -28,11 +27,13 @@ namespace scy { /// Timeout counter which expires after a given delay. +/// Delay is specified in milliseconds. class Timeout { public: Timeout(long delay = 0, bool autoStart = false); Timeout(const Timeout& src); + Timeout(Timeout&& src) noexcept = default; ~Timeout(); bool running() const; @@ -44,14 +45,15 @@ class Timeout void setDelay(long delay) { _delay = delay; }; - clock_t startAt() const { return _startAt; }; long delay() const { return _delay; }; Timeout& operator=(const Timeout& src); + Timeout& operator=(Timeout&& src) noexcept = default; protected: - clock_t _startAt; + std::chrono::steady_clock::time_point _startAt; long _delay; + bool _running; }; @@ -78,6 +80,3 @@ class Base_API TimedToken : public Timeout } // namespace scy - - -#endif // SCY_Timeout_H diff --git a/src/base/include/scy/timer.h b/src/base/include/scy/timer.h index 567c5b72a..94194c65f 100644 --- a/src/base/include/scy/timer.h +++ b/src/base/include/scy/timer.h @@ -9,14 +9,13 @@ /// @{ -#ifndef SCY_Timer_H -#define SCY_Timer_H +#pragma once #include "scy/base.h" +#include "scy/handle.h" #include "scy/runner.h" #include "scy/signal.h" -#include "scy/handle.h" #include #include @@ -96,6 +95,8 @@ class Base_API Timer : public Runner protected: Timer(const Timer&) = delete; Timer& operator=(const Timer&) = delete; + Timer(Timer&&) = delete; + Timer& operator=(Timer&&) = delete; void init(); @@ -109,7 +110,4 @@ class Base_API Timer : public Runner } // namespace scy -#endif // SCY_Timer_H - - /// @\} diff --git a/src/util/include/scy/util/usermanager.h b/src/base/include/scy/usermanager.h similarity index 98% rename from src/util/include/scy/util/usermanager.h rename to src/base/include/scy/usermanager.h index 823334e9e..1e4dd7389 100644 --- a/src/util/include/scy/util/usermanager.h +++ b/src/base/include/scy/usermanager.h @@ -5,7 +5,7 @@ // // SPDX-License-Identifier: LGPL-2.1+ // -/// @addtogroup util +/// @addtogroup base /// @{ diff --git a/src/base/include/scy/util.h b/src/base/include/scy/util.h index b7d0cb885..7753791df 100644 --- a/src/base/include/scy/util.h +++ b/src/base/include/scy/util.h @@ -11,13 +11,13 @@ /// @{ -#ifndef SCY_Util_H -#define SCY_Util_H +#pragma once #include "scy/base.h" #include "scy/error.h" +#include #include #include #include @@ -25,8 +25,8 @@ #include #include #include +#include #include -#include namespace scy { @@ -41,10 +41,10 @@ Base_API std::string format(const char* fmt, ...); Base_API void toUnderscore(std::string& str); /// Checks if the string is a number -Base_API bool isNumber(const std::string& str); +Base_API bool isNumber(std::string_view str); /// Returns true if the string ends with the given substring. -Base_API bool endsWith(const std::string& str, const std::string& suffix); +Base_API bool endsWith(std::string_view str, std::string_view suffix); /// Replaces non-alphanumeric characters. Base_API void removeSpecialCharacters(std::string& str, bool allowSpaces = false); @@ -79,7 +79,8 @@ std::string memAddress(const void* ptr); // /// Converts integer T to string. -template std::string itostr(const T& t) +template +std::string itostr(const T& t) { std::ostringstream oss; oss << t; @@ -89,7 +90,8 @@ template std::string itostr(const T& t) /// Converts string to integer T. /// Ensure the integer type has /// sufficient storage capacity. -template T strtoi(const std::string& s) +template +T strtoi(const std::string& s) { std::istringstream iss(s); T x; @@ -98,18 +100,6 @@ template T strtoi(const std::string& s) return x; } -#if 0 -/// Interger to double -double intToDouble(std::int64_t v); - -/// Interger to float -float intToFloat(std::int32_t v); - -/// Double to interger -std::int64_t doubleToInt(double d); -#endif - - // // Random generators // @@ -141,6 +131,8 @@ Base_API std::vector split(const std::string& str, char delim, int // String replace methods (Poco) // +/// Replace all occurrences of `from` in `str` with `to`, starting at position `start`. +/// Modifies and returns `str` in place. `from` must not be empty. template S& replaceInPlace(S& str, const S& from, const S& to, typename S::size_type start = 0) @@ -163,6 +155,8 @@ S& replaceInPlace(S& str, const S& from, const S& to, return str; } +/// Replace all occurrences of `from` in `str` with `to`, starting at position `start`. +/// C-string overload. Modifies and returns `str` in place. template S& replaceInPlace(S& str, const typename S::value_type* from, const typename S::value_type* to, @@ -214,7 +208,8 @@ S replace(const S& str, const typename S::value_type* from, /// Returns a copy of str with all leading /// whitespace removed. -template S trimLeft(const S& str) +template +S trimLeft(const S& str) { typename S::const_iterator it = str.begin(); typename S::const_iterator end = str.end(); @@ -225,7 +220,8 @@ template S trimLeft(const S& str) } /// Removes all leading whitespace in str. -template S& trimLeftInPlace(S& str) +template +S& trimLeftInPlace(S& str) { typename S::iterator it = str.begin(); typename S::iterator end = str.end(); @@ -238,7 +234,8 @@ template S& trimLeftInPlace(S& str) /// Returns a copy of str with all trailing /// whitespace removed. -template S trimRight(const S& str) +template +S trimRight(const S& str) { int pos = int(str.size()) - 1; @@ -248,7 +245,8 @@ template S trimRight(const S& str) } /// Removes all trailing whitespace in str. -template S& trimRightInPlace(S& str) +template +S& trimRightInPlace(S& str) { int pos = int(str.size()) - 1; @@ -261,7 +259,8 @@ template S& trimRightInPlace(S& str) /// Returns a copy of str with all leading and /// trailing whitespace removed. -template S trim(const S& str) +template +S trim(const S& str) { int first = 0; int last = int(str.size()) - 1; @@ -275,7 +274,8 @@ template S trim(const S& str) } /// Removes all leading and trailing whitespace in str. -template S& trimInPlace(S& str) +template +S& trimInPlace(S& str) { int first = 0; int last = int(str.size()) - 1; @@ -297,7 +297,8 @@ template S& trimInPlace(S& str) // /// Returns a copy of str containing all upper-case characters. -template S toUpper(const S& str) +template +S toUpper(const S& str) { typename S::const_iterator it = str.begin(); typename S::const_iterator end = str.end(); @@ -310,7 +311,8 @@ template S toUpper(const S& str) } /// Replaces all characters in str with their upper-case counterparts. -template S& toUpperInPlace(S& str) +template +S& toUpperInPlace(S& str) { typename S::iterator it = str.begin(); typename S::iterator end = str.end(); @@ -323,7 +325,8 @@ template S& toUpperInPlace(S& str) } /// Returns a copy of str containing all lower-case characters. -template S toLower(const S& str) +template +S toLower(const S& str) { typename S::const_iterator it = str.begin(); typename S::const_iterator end = str.end(); @@ -336,7 +339,8 @@ template S toLower(const S& str) } /// Replaces all characters in str with their lower-case counterparts. -template S& toLowerInPlace(S& str) +template +S& toLowerInPlace(S& str) { typename S::iterator it = str.begin(); typename S::iterator end = str.end(); @@ -353,7 +357,8 @@ template S& toLowerInPlace(S& str) // String case-insensative comparators (POCO) // -/// Case-insensitive string comparison +/// Case-insensitive string comparison. +/// Returns negative if str < str2, zero if equal, positive if str > str2. template int icompare(const S& str, typename S::size_type pos, typename S::size_type n, It it2, It end2) { @@ -381,7 +386,7 @@ int icompare(const S& str, typename S::size_type pos, typename S::size_type n, I return 1; } -template +template int icompare(const S& str1, const S& str2) { typename S::const_iterator it1(str1.begin()); @@ -490,7 +495,7 @@ int icompare(const S& str, typename S::size_type pos, return icompare(str, pos, str.size() - pos, ptr); } -template +template int icompare(const S& str, const typename S::value_type* ptr) { return icompare(str, 0, str.size(), ptr); @@ -501,9 +506,14 @@ int icompare(const S& str, const typename S::value_type* ptr) // Stream copiers // +/// Copy all data from istr to ostr one byte at a time. Base_API std::streamsize copyStreamUnbuffered(std::istream& istr, std::ostream& ostr); + +/// Copy all data from istr to ostr using a buffer of the given size. Base_API std::streamsize copyStream(std::istream& istr, std::ostream& ostr, size_t bufferSize = 8192); + +/// Read all data from istr into str using a buffer of the given size. Base_API std::streamsize copyToString(std::istream& istr, std::string& str, size_t bufferSize = 8192); @@ -569,7 +579,7 @@ struct Version /// Delete all elements from a list of pointers. /// @param L List of pointers to delete. -template +template inline void clearList(std::list& L) { typename std::list::iterator it = L.begin(); @@ -581,7 +591,7 @@ inline void clearList(std::list& L) /// Delete all elements from a list of pointers. /// @param D List of pointers to delete. -template +template inline void clearDeque(std::deque& D) { typename std::deque::iterator it = D.begin(); @@ -604,7 +614,7 @@ inline void clearDeque(std::deque& D) /// Delete all elements from a vector of pointers. /// @param V Vector of pointers to delete. -template +template inline void clearVector(std::vector& V) { typename std::vector::iterator it = V.begin(); @@ -666,7 +676,4 @@ inline void clearMap(std::map& M) } // namespace scy -#endif // SCY_Util_H - - /// @\} \ No newline at end of file diff --git a/src/base/src/application.cpp b/src/base/src/application.cpp index 5add6c22c..f7ab8375b 100644 --- a/src/base/src/application.cpp +++ b/src/base/src/application.cpp @@ -1,168 +1,164 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// @addtogroup base -/// @{ - - -#include "scy/application.h" -#include "scy/memory.h" -#include "scy/logger.h" -#include "scy/error.h" -#include "scy/singleton.h" - - -namespace scy { - - -namespace internal { - - static Singleton singleton; - - struct ShutdownCmd - { - Application* self; - void* opaque; - std::function callback; - }; - -} - - -Application& Application::getDefault() -{ - return *internal::singleton.get(); -} - - -Application::Application(uv::Loop* loop) : - loop(loop) -{ - LDebug("Create") -} - - -Application::~Application() -{ - LDebug("Destroy") -} - - -void Application::run() -{ - uv_run(loop, UV_RUN_DEFAULT); -} - - -void Application::stop() -{ - uv_stop(loop); -} - - -void Application::finalize() -{ - LDebug("Finalizing") - -#ifdef _DEBUG - // Print active handles - uv_walk(loop, Application::onPrintHandle, nullptr); -#endif - - // Shutdown the garbage collector to safely free memory before the app exists - GarbageCollector::instance().finalize(); - - // Run until handles are closed - run(); - assert(loop->active_handles == 0); - //assert(loop->active_reqs == 0); - - LDebug("Finalization complete") -} - - -void Application::bindShutdownSignal(std::function callback, void* opaque) -{ - auto cmd = new internal::ShutdownCmd; - cmd->self = this; - cmd->opaque = opaque; - cmd->callback = callback; - - auto sig = new uv_signal_t; - sig->data = cmd; - uv_signal_init(loop, sig); - uv_signal_start(sig, Application::onShutdownSignal, SIGINT); -} - - -void Application::waitForShutdown(std::function callback, void* opaque) -{ - LDebug("Wait for shutdown") - bindShutdownSignal(callback, opaque); - run(); -} - - -void Application::onShutdownSignal(uv_signal_t* req, int /* signum */) -{ - auto cmd = reinterpret_cast(req->data); - LDebug("Got shutdown signal") - - uv_close((uv_handle_t*)req, [](uv_handle_t* handle) { - delete handle; - }); - if (cmd->callback) - cmd->callback(cmd->opaque); - delete cmd; -} - - -void Application::onPrintHandle(uv_handle_t* handle, void* /* arg */) -{ - LDebug("Active handle: ", handle, ": ", handle->type) -} - - -// -// Command-line option parser -// - -OptionParser::OptionParser(int argc, char* argv[], const char* delim) -{ - char* lastkey = 0; - auto dlen = strlen(delim); - for (int i = 0; i < argc; i++) { - - // Get the application exe path - if (i == 0) { - exepath.assign(argv[i]); - continue; - } - - // Get option keys - if (strncmp(argv[i], delim, dlen) == 0) { - lastkey = (&argv[i][dlen]); - args[lastkey] = ""; - } - - // Get value for current key - else if (lastkey) { - args[lastkey] = argv[i]; - lastkey = 0; - } - - else { - LDebug("Unrecognized option:", argv[i]); - } - } -} - - -} // namespace scy - - -/// @\} +/// +// +// LibSourcey +// Copyright (c) 2005, Sourcey +// +// SPDX-License-Identifier: LGPL-2.1+ +// +/// @addtogroup base +/// @{ + + +#include "scy/application.h" +#include "scy/error.h" +#include "scy/logger.h" +#include "scy/platform.h" + + +namespace scy { + + +namespace internal { + +struct ShutdownCmd +{ + Application* self; + void* opaque; + std::function callback; +}; + +} // namespace internal + + +Application& Application::getDefault() +{ + static Application instance; + return instance; +} + + +Application::Application(uv::Loop* loop) + : loop(loop) +{ + LDebug("Create"); +} + + +Application::~Application() +{ + LDebug("Destroy"); +} + + +void Application::run() +{ + uv_run(loop, UV_RUN_DEFAULT); +} + + +void Application::stop() +{ + uv_stop(loop); +} + + +void Application::finalize() +{ + LDebug("Finalizing"); + +#ifdef _DEBUG + // Print active handles + uv_walk(loop, Application::onPrintHandle, nullptr); +#endif + + // Run until handles are closed + run(); + if (uv_loop_alive(loop)) + LWarn("Event loop still alive after run"); + //assert(loop->active_reqs == 0); + + LDebug("Finalization complete"); +} + + +void Application::bindShutdownSignal(std::function callback, void* opaque) +{ + auto cmd = new internal::ShutdownCmd; + cmd->self = this; + cmd->opaque = opaque; + cmd->callback = callback; + + auto sig = new uv_signal_t; + sig->data = cmd; + uv_signal_init(loop, sig); + uv_signal_start(sig, Application::onShutdownSignal, SIGINT); +} + + +void Application::waitForShutdown(std::function callback, void* opaque) +{ + LDebug("Wait for shutdown"); + bindShutdownSignal(callback, opaque); + run(); +} + + +void Application::onShutdownSignal(uv_signal_t* req, int /* signum */) +{ + auto cmd = reinterpret_cast(req->data); + LDebug("Got shutdown signal"); + + uv_close(reinterpret_cast(req), [](uv_handle_t* handle) { + delete handle; + }); + if (cmd->callback) + cmd->callback(cmd->opaque); + delete cmd; +} + + +void Application::onPrintHandle(uv_handle_t* handle, void* /* arg */) +{ + LDebug("Active handle: ", handle, ": ", handle->type); +} + + +// +// Command-line option parser +// + +OptionParser::OptionParser(int argc, char* argv[], const char* delim) +{ + char* lastkey = nullptr; + auto dlen = strlen(delim); + for (int i = 0; i < argc; i++) { + + // Get the application exe path (use platform API for UTF-8 support) + if (i == 0) { + exepath = getExePath(); + continue; + } + + // Get option keys + if (strncmp(argv[i], delim, dlen) == 0) { + lastkey = (&argv[i][dlen]); + args[lastkey] = ""; + } + + // Get value for current key + else if (lastkey) { + args[lastkey] = argv[i]; + lastkey = nullptr; + } + + else { + LDebug("Unrecognized option:", argv[i]); + } + } +} + + +} // namespace scy + + +/// @\} diff --git a/src/base/src/base64.cpp b/src/base/src/base64.cpp index dd57009a1..97397ae75 100644 --- a/src/base/src/base64.cpp +++ b/src/base/src/base64.cpp @@ -31,7 +31,7 @@ void init_encodestate(encodestate* state_in) state_in->result = 0; state_in->stepcount = 0; state_in->linelength = LINE_LENGTH; // added: set 0 for no line feeds - state_in->nullptrlterminate = 0; // added: set 1 for nullptrl terminated output string + state_in->nullptrlterminate = 0; // added: set 1 for nullptrl terminated output string } @@ -40,7 +40,7 @@ char encode_value(char value_in) static const char* encoding = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; if (value_in > 63) return '='; - return encoding[(int)value_in]; + return encoding[static_cast(value_in)]; } @@ -134,9 +134,9 @@ ssize_t encode_blockend(char* code_out, encodestate* state_in) ssize_t decode_value(char value_in) { - static const char decoding[] = { + static const signed char decoding[] = { 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, - -1, -1, -2, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + -1, -1, -2, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51}; @@ -144,7 +144,7 @@ ssize_t decode_value(char value_in) value_in -= 43; if (value_in < 0 || value_in >= decoding_size) return -1; - return decoding[(int)value_in]; + return decoding[static_cast(value_in)]; } @@ -172,7 +172,7 @@ ssize_t decode_block(const char* code_in, const size_t length_in, char* plaintex state_in->plainchar = *plainchar; return plainchar - plaintext_out; } - fragment = (char)decode_value(*codechar++); + fragment = static_cast(decode_value(*codechar++)); } while (fragment < 0); *plainchar = (fragment & 0x03f) << 2; case step_b: @@ -182,7 +182,7 @@ ssize_t decode_block(const char* code_in, const size_t length_in, char* plaintex state_in->plainchar = *plainchar; return plainchar - plaintext_out; } - fragment = (char)decode_value(*codechar++); + fragment = static_cast(decode_value(*codechar++)); } while (fragment < 0); *plainchar++ |= (fragment & 0x030) >> 4; *plainchar = (fragment & 0x00f) << 4; @@ -193,7 +193,7 @@ ssize_t decode_block(const char* code_in, const size_t length_in, char* plaintex state_in->plainchar = *plainchar; return plainchar - plaintext_out; } - fragment = (char)decode_value(*codechar++); + fragment = static_cast(decode_value(*codechar++)); } while (fragment < 0); *plainchar++ |= (fragment & 0x03c) >> 2; *plainchar = (fragment & 0x003) << 6; @@ -204,7 +204,7 @@ ssize_t decode_block(const char* code_in, const size_t length_in, char* plaintex state_in->plainchar = *plainchar; return plainchar - plaintext_out; } - fragment = (char)decode_value(*codechar++); + fragment = static_cast(decode_value(*codechar++)); } while (fragment < 0); *plainchar++ |= (fragment & 0x03f); } diff --git a/src/base/src/buffer.cpp b/src/base/src/buffer.cpp index e6a0a7f14..03758062b 100644 --- a/src/base/src/buffer.cpp +++ b/src/base/src/buffer.cpp @@ -16,8 +16,8 @@ #include #include -#include #include +#include namespace scy { @@ -151,10 +151,10 @@ void BitReader::get(std::string& val, size_t len) { if (len > available()) { SError << "index out of range: " - << "len=" << len << ", " - << "available=" << available() << ", " - << "position=" << position() << ", " - << "limit=" << limit() << std::endl; + << "len=" << len << ", " + << "available=" << available() << ", " + << "position=" << position() << ", " + << "limit=" << limit() << std::endl; throw std::out_of_range("index out of range"); } @@ -167,10 +167,10 @@ void BitReader::get(char* val, size_t len) { if (len > available()) { SError << "index out of range: " - << "len=" << len << ", " - << "available=" << available() << ", " - << "position=" << position() << ", " - << "limit=" << limit() << std::endl; + << "len=" << len << ", " + << "available=" << available() << ", " + << "position=" << position() << ", " + << "limit=" << limit() << std::endl; throw std::out_of_range("index out of range"); } @@ -183,7 +183,7 @@ const char BitReader::peek() { if (_limit > _position) return (const char)_bytes[_position]; - // LDebug("Peeking next character is NULL") + // LDebug("Peeking next character is NULL"); return 0; } @@ -196,7 +196,7 @@ const uint8_t BitReader::peekU8() _position -= 1; return v; } catch (std::out_of_range&) { - LDebug("Peeking uint8_t: NULL") + LDebug("Peeking uint8_t: NULL"); } return 0; } @@ -210,7 +210,7 @@ const uint16_t BitReader::peekU16() _position -= 2; return v; } catch (std::out_of_range&) { - LDebug("Peeking uint16_t: NULL") + LDebug("Peeking uint16_t: NULL"); } return 0; @@ -225,7 +225,7 @@ const uint32_t BitReader::peekU24() _position -= 3; return v; } catch (std::out_of_range&) { - LDebug("Peeking UInt24: NULL") + LDebug("Peeking UInt24: NULL"); } return 0; @@ -240,7 +240,7 @@ const uint32_t BitReader::peekU32() _position -= 4; return v; } catch (std::out_of_range&) { - LDebug("Peeking uint32_t: NULL") + LDebug("Peeking uint32_t: NULL"); } return 0; @@ -255,7 +255,7 @@ const uint64_t BitReader::peekU64() _position -= 8; return v; } catch (std::out_of_range&) { - LDebug("Peeking uint64_t: NULL") + LDebug("Peeking uint64_t: NULL"); } return 0; @@ -426,10 +426,10 @@ void BitWriter::skip(size_t val) { if (_position + val > _limit) { SError << "index out of range: " - << "val=" << val << ", " - << "available=" << available() << ", " - << "position=" << position() << ", " - << "limit=" << limit() << std::endl; + << "val=" << val << ", " + << "available=" << available() << ", " + << "position=" << position() << ", " + << "limit=" << limit() << std::endl; throw std::out_of_range("index out of range"); } @@ -441,10 +441,10 @@ void BitWriter::seek(size_t val) { if (val > _limit) { SError << "index out of range: " - << "val=" << val << ", " - << "available=" << available() << ", " - << "position=" << position() << ", " - << "limit=" << limit() << std::endl; + << "val=" << val << ", " + << "available=" << available() << ", " + << "position=" << position() << ", " + << "limit=" << limit() << std::endl; throw std::out_of_range("index out of range"); } @@ -522,10 +522,10 @@ void BitWriter::put(const char* val, size_t len) { if ((_position + len) > _limit) { SError << "insufficient buffer capacity: " - << "len=" << len << ", " - << "available=" << available() << ", " - << "position=" << position() << ", " - << "limit=" << limit() << std::endl; + << "len=" << len << ", " + << "available=" << available() << ", " + << "position=" << position() << ", " + << "limit=" << limit() << std::endl; throw std::out_of_range("insufficient buffer capacity"); } diff --git a/src/base/src/collection.cpp b/src/base/src/collection.cpp index 4be49af74..1a7eb3c67 100644 --- a/src/base/src/collection.cpp +++ b/src/base/src/collection.cpp @@ -24,6 +24,15 @@ NVCollection& NVCollection::operator=(const NVCollection& nvc) } +NVCollection& NVCollection::operator=(NVCollection&& nvc) noexcept +{ + if (&nvc != this) { + _map = std::move(nvc._map); + } + return *this; +} + + const std::string& NVCollection::operator[](const std::string& name) const { ConstIterator it = _map.find(name); @@ -61,7 +70,7 @@ const std::string& NVCollection::get(const std::string& name) const const std::string& NVCollection::get(const std::string& name, - const std::string& defaultValue) const + const std::string& defaultValue) const { ConstIterator it = _map.find(name); if (it != _map.end()) @@ -103,7 +112,7 @@ bool NVCollection::empty() const int NVCollection::size() const { - return (int)_map.size(); + return static_cast(_map.size()); } diff --git a/src/base/src/datetime.cpp b/src/base/src/datetime.cpp index fd2d6dbdf..d4ab960fa 100644 --- a/src/base/src/datetime.cpp +++ b/src/base/src/datetime.cpp @@ -18,14 +18,9 @@ #include "scy/util.h" #include +#include #include #include -#if defined(_WIN32_WCE) -#include "wce_time.h" -#endif -#if !defined(WIN32) -#include -#endif using std::endl; @@ -80,14 +75,12 @@ DateTime::DateTime(int year, int month, int day, int hour, int minute, , _millisecond(millisecond) , _microsecond(microsecond) { - assert(year >= 0 && year <= 9999); - assert(month >= 1 && month <= 12); - assert(day >= 1 && day <= daysOfMonth(year, month)); - assert(hour >= 0 && hour <= 23); - assert(minute >= 0 && minute <= 59); - assert(second >= 0 && second <= 59); - assert(millisecond >= 0 && millisecond <= 999); - assert(microsecond >= 0 && microsecond <= 999); + if (year < 0 || year > 9999 || month < 1 || month > 12 || + day < 1 || day > daysOfMonth(year, month) || + hour < 0 || hour > 23 || minute < 0 || minute > 59 || + second < 0 || second > 59 || millisecond < 0 || millisecond > 999 || + microsecond < 0 || microsecond > 999) + throw std::invalid_argument("DateTime: invalid date/time component"); _utcTime = toUtcTime(toJulianDay(year, month, day)) + 10 * (hour * Timespan::HOURS + minute * Timespan::MINUTES + @@ -167,14 +160,12 @@ DateTime& DateTime::operator=(double julianDay) DateTime& DateTime::assign(int year, int month, int day, int hour, int minute, int second, int millisecond, int microsecond) { - assert(year >= 0 && year <= 9999); - assert(month >= 1 && month <= 12); - assert(day >= 1 && day <= daysOfMonth(year, month)); - assert(hour >= 0 && hour <= 23); - assert(minute >= 0 && minute <= 59); - assert(second >= 0 && second <= 59); - assert(millisecond >= 0 && millisecond <= 999); - assert(microsecond >= 0 && microsecond <= 999); + if (year < 0 || year > 9999 || month < 1 || month > 12 || + day < 1 || day > daysOfMonth(year, month) || + hour < 0 || hour > 23 || minute < 0 || minute > 59 || + second < 0 || second > 59 || millisecond < 0 || millisecond > 999 || + microsecond < 0 || microsecond > 999) + throw std::invalid_argument("DateTime::assign: invalid date/time component"); _utcTime = toUtcTime(toJulianDay(year, month, day)) + 10 * (hour * Timespan::HOURS + minute * Timespan::MINUTES + @@ -225,9 +216,10 @@ int DateTime::dayOfYear() const int DateTime::daysOfMonth(int year, int month) { - assert(month >= 1 && month <= 12); + if (month < 1 || month > 12) + throw std::invalid_argument("DateTime::daysOfMonth: month out of range"); - static int daysOfMonthTable[] = {0, 31, 28, 31, 30, 31, 30, + static int daysOfMonthTable[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; if (month == 2 && isLeapYear(year)) @@ -251,7 +243,8 @@ bool DateTime::isValid(int year, int month, int day, int hour, int minute, int DateTime::week(int firstDayOfWeek) const { - assert(firstDayOfWeek >= 0 && firstDayOfWeek <= 6); + if (firstDayOfWeek < 0 || firstDayOfWeek > 6) + throw std::invalid_argument("DateTime::week: firstDayOfWeek out of range"); // find the first firstDayOfWeek. int baseDay = 1; @@ -325,13 +318,15 @@ double DateTime::toJulianDay(int year, int month, int day, int hour, int minute, int second, int millisecond, int microsecond) { // lookup table for (153*month - 457)/5 - note that 3 <= month <= 14. - static int lookup[] = {-91, -60, -30, 0, 31, 61, 92, 122, + static int lookup[] = {-91, -60, -30, 0, 31, 61, 92, 122, 153, 184, 214, 245, 275, 306, 337}; // day to double double dday = double(day) + - ((double((hour * 60 + minute) * 60 + second) * 1000 + millisecond) * - 1000 + microsecond) / 86400000000.0; + ((double((hour * 60 + minute) * 60 + second) * 1000 + millisecond) * + 1000 + + microsecond) / + 86400000000.0; if (month < 3) { month += 12; --year; @@ -402,13 +397,11 @@ void DateTime::computeGregorian(double julianDay) normalize(); - assert(_month >= 1 && _month <= 12); - assert(_day >= 1 && _day <= daysOfMonth(_year, _month)); - assert(_hour >= 0 && _hour <= 23); - assert(_minute >= 0 && _minute <= 59); - assert(_second >= 0 && _second <= 59); - assert(_millisecond >= 0 && _millisecond <= 999); - assert(_microsecond >= 0 && _microsecond <= 999); + if (_month < 1 || _month > 12 || _day < 1 || _day > daysOfMonth(_year, _month) || + _hour < 0 || _hour > 23 || _minute < 0 || _minute > 59 || + _second < 0 || _second > 59 || _millisecond < 0 || _millisecond > 999 || + _microsecond < 0 || _microsecond > 999) + throw std::logic_error("DateTime: internal computation produced invalid values"); } @@ -430,8 +423,7 @@ void DateTime::computeDaytime() } _day = daysOfMonth(_year, _month); } - } - else if (hour == 0 && _hour == 23) { + } else if (hour == 0 && _hour == 23) { _day++; if (_day > daysOfMonth(_year, _month)) { _month++; @@ -856,28 +848,32 @@ std::string Timezone::dstName() // Timezone: Unix // -class Base_API TZInfo -{ -public: - TZInfo() { tzset(); } +class Base_API TZInfo{ + public: + TZInfo(){tzset(); +} - int timeZone() - { +int timeZone() +{ #if defined(__APPLE__) || defined(__FreeBSD__) || defined(POCO_ANDROID) // no timezone global var - std::time_t now = std::time(nullptr); - struct std::tm t; - gmtime_r(&now, &t); - std::time_t utc = std::mktime(&t); - return now - utc; + std::time_t now = std::time(nullptr); + struct std::tm t; + gmtime_r(&now, &t); + std::time_t utc = std::mktime(&t); + return now - utc; #elif defined(__CYGWIN__) - return -_timezone; + return -_timezone; #else - return -timezone; + return -timezone; #endif - } +} - const char* name(bool dst) { return tzname[dst ? 1 : 0]; } -}; +const char* name(bool dst) +{ + return tzname[dst ? 1 : 0]; +} +} +; static TZInfo tzInfo; @@ -947,13 +943,13 @@ const std::string DateTimeFormat::SORTABLE_FORMAT("%Y-%m-%d %H:%M:%S"); const std::string DateTimeFormat::WEEKDAY_NAMES[] = { - "Sunday", "Monday", "Tuesday", "Wednesday", + "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; const std::string DateTimeFormat::MONTH_NAMES[] = { - "January", "February", "March", "April", "May", "June", - "July", "August", "September", "October", "November", "December"}; + "January", "February", "March", "April", "May", "June", + "July", "August", "September", "October", "November", "December"}; // @@ -1038,8 +1034,7 @@ void DateTimeFormatter::append(std::string& str, const DateTime& dateTime, case 's': scy::numeric::format0(str, dateTime.second(), 2); str += '.'; - scy::numeric::format0(str, dateTime.millisecond() * 1000 + - dateTime.microsecond(), 6); + scy::numeric::format0(str, dateTime.millisecond() * 1000 + dateTime.microsecond(), 6); break; case 'i': scy::numeric::format0(str, dateTime.millisecond(), 3); @@ -1048,8 +1043,7 @@ void DateTimeFormatter::append(std::string& str, const DateTime& dateTime, scy::numeric::format(str, dateTime.millisecond() / 100); break; case 'F': - scy::numeric::format0(str, dateTime.millisecond() * 1000 + - dateTime.microsecond(), 6); + scy::numeric::format0(str, dateTime.millisecond() * 1000 + dateTime.microsecond(), 6); break; case 'z': tzdISO(str, timeZoneDifferential); @@ -1105,8 +1099,7 @@ void DateTimeFormatter::append(std::string& str, const Timespan& timespan, scy::numeric::format(str, timespan.milliseconds() / 100); break; case 'F': - scy::numeric::format0(str, timespan.milliseconds() * 1000 + - timespan.microseconds(), 6); + scy::numeric::format0(str, timespan.milliseconds() * 1000 + timespan.microseconds(), 6); break; default: str += *it; @@ -1160,38 +1153,38 @@ void DateTimeFormatter::tzdRFC(std::string& str, int timeZoneDifferential) // -#define SKIP_JUNK() \ - while (it != end && !::isdigit(*it)) \ +#define SKIP_JUNK() \ + while (it != end && !::isdigit(*it)) \ ++it -#define SKIP_DIGITS() \ - while (it != end && ::isdigit(*it)) \ +#define SKIP_DIGITS() \ + while (it != end && ::isdigit(*it)) \ ++it -#define PARSE_NUMBER(var) \ - while (it != end && ::isdigit(*it)) \ +#define PARSE_NUMBER(var) \ + while (it != end && ::isdigit(*it)) \ var = var * 10 + ((*it++) - '0') -#define PARSE_NUMBER_N(var, n) \ - { \ - int i = 0; \ - while (i++ < n && it != end && ::isdigit(*it)) \ - var = var * 10 + ((*it++) - '0'); \ +#define PARSE_NUMBER_N(var, n) \ + { \ + int i = 0; \ + while (i++ < n && it != end && ::isdigit(*it)) \ + var = var * 10 + ((*it++) - '0'); \ } -#define PARSE_FRACTIONAL_N(var, n) \ - { \ - int i = 0; \ - while (i < n && it != end && ::isdigit(*it)) { \ - var = var * 10 + ((*it++) - '0'); \ - i++; \ - } \ - while (i++ < n) \ - var *= 10; \ +#define PARSE_FRACTIONAL_N(var, n) \ + { \ + int i = 0; \ + while (i < n && it != end && ::isdigit(*it)) { \ + var = var * 10 + ((*it++) - '0'); \ + i++; \ + } \ + while (i++ < n) \ + var *= 10; \ } @@ -1494,7 +1487,8 @@ int DateTimeParser::parseMonth(std::string::const_iterator& it, } if (month.length() < 3) throw std::runtime_error("Syntax error: Month name must be at least " - "three characters long: " + month); + "three characters long: " + + month); for (int i = 0; i < 12; ++i) { if (DateTimeFormat::MONTH_NAMES[i].find(month) == 0) return i + 1; @@ -1620,34 +1614,9 @@ Timestamp Timestamp::fromUtcTime(UtcTimeVal val) void Timestamp::update() { -#if defined(WIN32) - - FILETIME ft; -#if defined(_WIN32_WCE) - GetSystemTimeAsFileTimeWithMillisecondResolution(&ft); -#else - GetSystemTimeAsFileTime(&ft); -#endif - - ULARGE_INTEGER epoch; // UNIX epoch (1970-01-01 00:00:00) expressed in - // Windows NT FILETIME - epoch.LowPart = 0xD53E8000; - epoch.HighPart = 0x019DB1DE; - - ULARGE_INTEGER ts; - ts.LowPart = ft.dwLowDateTime; - ts.HighPart = ft.dwHighDateTime; - ts.QuadPart -= epoch.QuadPart; - _ts = ts.QuadPart / 10; - -#else - - struct timeval tv; - if (gettimeofday(&tv, nullptr)) - throw std::runtime_error("System error: Cannot get time of day"); - _ts = TimeVal(tv.tv_sec) * resolution() + tv.tv_usec; - -#endif + auto now = std::chrono::system_clock::now(); + auto epoch = now.time_since_epoch(); + _ts = std::chrono::duration_cast(epoch).count(); } @@ -1682,9 +1651,9 @@ Timespan::Timespan(long seconds, long microseconds) Timespan::Timespan(int days, int hours, int minutes, int seconds, int microseconds) - : _span(TimeDiff(microseconds) + + : _span(TimeDiff(microseconds) + TimeDiff(seconds) * SECONDS + - TimeDiff(minutes) * MINUTES + + TimeDiff(minutes) * MINUTES + TimeDiff(hours) * HOURS + TimeDiff(days) * DAYS) { diff --git a/src/util/src/diagnosticmanager.cpp b/src/base/src/diagnosticmanager.cpp similarity index 68% rename from src/util/src/diagnosticmanager.cpp rename to src/base/src/diagnosticmanager.cpp index 878a4edaf..6b6ab974a 100644 --- a/src/util/src/diagnosticmanager.cpp +++ b/src/base/src/diagnosticmanager.cpp @@ -5,12 +5,13 @@ // // SPDX-License-Identifier: LGPL-2.1+ // -/// @addtogroup util +/// @addtogroup base /// @{ -#include "scy/util/diagnosticmanager.h" +#include "scy/diagnosticmanager.h" +#include using std::endl; @@ -70,8 +71,7 @@ bool IDiagnostic::complete() const bool IDiagnostic::passed() const { - return stateEquals(DiagnosticState::Passed) || - stateEquals(DiagnosticState::Failed); + return stateEquals(DiagnosticState::Passed); } @@ -85,38 +85,38 @@ bool IDiagnostic::failed() const // DiagnosticManager::DiagnosticManager() { - LTrace("Create") + LTrace("Create"); } DiagnosticManager::~DiagnosticManager() { - LTrace("Destroy") + LTrace("Destroy"); } void DiagnosticManager::resetAll() { - Map tests = map(); - for (auto& test : tests) { - test.second->reset(); + std::unique_lock guard(_mutex); + for (auto& [name, test] : _map) { + test->reset(); } } void DiagnosticManager::checkAll() { - Map tests = map(); - for (auto& test : tests) { - test.second->check(); + std::unique_lock guard(_mutex); + for (auto& [name, test] : _map) { + test->check(); } } bool DiagnosticManager::allComplete() { - Map tests = map(); - for (auto& test : tests) { - if (!test.second->complete()) + std::shared_lock guard(_mutex); + for (auto& [name, test] : _map) { + if (!test->complete()) return false; } return true; @@ -125,10 +125,12 @@ bool DiagnosticManager::allComplete() bool DiagnosticManager::addDiagnostic(IDiagnostic* test) { - assert(test); - assert(!test->name.empty()); + if (!test) + throw std::invalid_argument("DiagnosticManager: test cannot be null"); + if (test->name.empty()) + throw std::invalid_argument("DiagnosticManager: test name cannot be empty"); - LTrace("Adding Diagnostic: ", test->name) + LTrace("Adding Diagnostic: ", test->name); // test->StateChange += sdelegate(this, // &DiagnosticManager::onDiagnosticStateChange); return DiagnosticStore::add(test->name, test); @@ -137,15 +139,13 @@ bool DiagnosticManager::addDiagnostic(IDiagnostic* test) bool DiagnosticManager::freeDiagnostic(const std::string& name) { - assert(!name.empty()); + if (name.empty()) + throw std::invalid_argument("DiagnosticManager: name cannot be empty"); - LTrace("Removing Diagnostic: ", name) - IDiagnostic* test = DiagnosticStore::remove(name); + LTrace("Removing Diagnostic: ", name); + std::unique_ptr + test(DiagnosticStore::remove(name)); if (test) { - // TODO: - // test->StateChange -= sdelegate(this, - // &DiagnosticManager::onDiagnosticStateChange); - delete test; return true; } return false; diff --git a/src/base/src/filesystem.cpp b/src/base/src/filesystem.cpp index e6370fa4b..942b622ee 100644 --- a/src/base/src/filesystem.cpp +++ b/src/base/src/filesystem.cpp @@ -10,258 +10,180 @@ #include "scy/filesystem.h" -#include "scy/logger.h" -#include "scy/util.h" -#include "scy/util.h" -#include +#include #include -#include -#include +#include #if defined(_MSC_VER) && defined(SCY_UNICODE) #include #include +#include #endif +namespace stdfs = std::filesystem; + + namespace scy { namespace fs { -static const char* separatorWin = "\\"; -static const char* separatorUnix = "/"; #ifdef SCY_WIN const char delimiter = '\\'; -const char* separator = separatorWin; -static const char* sepPattern = "/\\"; +const char* separator = "\\"; #else const char delimiter = '/'; -const char* separator = separatorUnix; -static const char* sepPattern = "/"; +const char* separator = "/"; #endif std::string filename(const std::string& path) { - size_t dirp = path.find_last_of(fs::sepPattern); - if (dirp == std::string::npos) - return path; - return path.substr(dirp + 1); + return stdfs::path(path).filename().string(); } std::string dirname(const std::string& path) { - size_t dirp = path.find_last_of(sepPattern); - if (dirp == std::string::npos) + auto parent = stdfs::path(path).parent_path(); + if (parent.empty()) return "."; - return path.substr(0, dirp); + return parent.string(); } std::string basename(const std::string& path) { - size_t dotp = path.find_last_of("."); - if (dotp == std::string::npos) - return path; - - size_t dirp = path.find_last_of(fs::sepPattern); - if (dirp != std::string::npos && dotp < dirp) - return path; - - return path.substr(0, dotp); + return stdfs::path(path).stem().string(); } std::string extname(const std::string& path, bool includeDot) { - size_t dotp = path.find_last_of("."); - if (dotp == std::string::npos) - return ""; - - // Ensure the dot was not part of the pathname - size_t dirp = path.find_last_of(fs::sepPattern); - if (dirp != std::string::npos && dotp < dirp) + auto ext = stdfs::path(path).extension().string(); + if (ext.empty()) return ""; - - return path.substr((dotp + includeDot) ? 0 : 1); + if (!includeDot && !ext.empty() && ext[0] == '.') + return ext.substr(1); + return ext; } bool exists(const std::string& path) { -// Normalize is needed to ensure no -// trailing slash for directories or -// stat fails to recognize validity. -// TODO: Do we need transcode here? -#ifdef SCY_WIN - struct _stat s; - return _stat(fs::normalize(path).c_str(), &s) != -1; -#else - struct stat s; - return stat(fs::normalize(path).c_str(), &s) != -1; -#endif + std::error_code ec; + return stdfs::exists(path, ec); } bool isdir(const std::string& path) { -// TODO: Do we need transcode here? -#ifdef SCY_WIN - struct _stat s; - _stat(fs::normalize(path).c_str(), &s); -#else - struct stat s; - stat(fs::normalize(path).c_str(), &s); -#endif - // S_IFDIR: directory file. - // S_IFCHR: character-oriented device file - // S_IFBLK: block-oriented device file - // S_IFREG: regular file - // S_IFLNK: symbolic link - // S_IFSOCK: socket - // S_IFIFO: FIFO or pipe - return (s.st_mode & S_IFDIR) != 0; + std::error_code ec; + return stdfs::is_directory(path, ec); } std::int64_t filesize(const std::string& path) { -#ifdef SCY_WIN - struct _stat s; - if (_stat(path.c_str(), &s) == 0) -#else - struct stat s; - if (stat(path.c_str(), &s) == 0) -#endif - return s.st_size; - return -1; + std::error_code ec; + auto size = stdfs::file_size(path, ec); + if (ec) + return -1; + return static_cast(size); } -namespace internal { - -struct FSReq -{ - FSReq() {} - ~FSReq() { uv_fs_req_cleanup(&req); } - FSReq(const FSReq& req) = delete; - FSReq& operator=(const FSReq& req) = delete; - uv_fs_t req; -}; - -#define FSapi(func, ...) \ - FSReq wrap; \ - int err = \ - uv_fs_##func(uv_default_loop(), &wrap.req, __VA_ARGS__, nullptr); \ - if (err < 0) \ - uv::throwError(std::string("Filesystem error: ") + #func + \ - std::string(" failed"), err); - -} // namespace internal - - void readdir(const std::string& path, std::vector& res) { - internal::FSapi(scandir, path.c_str(), 0) - - uv_dirent_t dent; - while (UV_EOF != uv_fs_scandir_next(&wrap.req, &dent)) { - res.push_back(dent.name); + std::error_code ec; + for (const auto& entry : stdfs::directory_iterator(path, ec)) { + res.push_back(entry.path().filename().string()); } + if (ec) + throw std::runtime_error("Filesystem error: scandir failed: " + path); } -void mkdir(const std::string& path, int mode) +void mkdir(const std::string& path, int /*mode*/) { - internal::FSapi(mkdir, path.c_str(), mode) + std::error_code ec; + stdfs::create_directory(path, ec); + if (ec) + throw std::runtime_error("Filesystem error: mkdir failed: " + path + ": " + ec.message()); } -void mkdirr(const std::string& path, int mode) +void mkdirr(const std::string& path, int /*mode*/) { - std::string current; - std::string level; - std::istringstream istr(fs::normalize(path)); - - while (std::getline(istr, level, fs::delimiter)) { - if (level.empty()) - continue; - -#ifdef SCY_WIN - current += level; - if (level.at(level.length() - 1) == ':') { - current += fs::separator; - continue; // skip drive letter - } -#else - if (current.empty()) - current += fs::separator; - current += level; -#endif - // create current level - if (!fs::exists(current)) - fs::mkdir(current.c_str(), mode); // create or throw - - current += fs::separator; - } + std::error_code ec; + stdfs::create_directories(path, ec); + if (ec) + throw std::runtime_error("Filesystem error: mkdir failed: " + path + ": " + ec.message()); } void rmdir(const std::string& path) { - internal::FSapi(rmdir, path.c_str()) + std::error_code ec; + stdfs::remove(path, ec); + if (ec) + throw std::runtime_error("Filesystem error: rmdir failed: " + path + ": " + ec.message()); } void unlink(const std::string& path) { - internal::FSapi(unlink, path.c_str()) + std::error_code ec; + stdfs::remove(path, ec); + if (ec) + throw std::runtime_error("Filesystem error: unlink failed: " + path + ": " + ec.message()); } void rename(const std::string& path, const std::string& target) { - internal::FSapi(rename, path.c_str(), target.c_str()) + std::error_code ec; + stdfs::rename(path, target, ec); + if (ec) + throw std::runtime_error("Filesystem error: rename failed: " + path + ": " + ec.message()); } -void trimslash(std::string& path) +void addsep(std::string& path) { - if (path.empty()) return; - size_t dirp = path.find_last_of(sepPattern); - if (dirp == path.length() - 1) - path.resize(dirp); + if (!path.empty() && path.back() != '/' && path.back() != '\\') + path.append(fs::separator, 1); } -std::string normalize(const std::string& path) +void addnode(std::string& path, const std::string& node) { - std::string s(util::replace(path, -#ifdef SCY_WIN - separatorUnix, separatorWin -#else - separatorWin, separatorUnix -#endif - )); + fs::addsep(path); + path += node; +} + - // Trim the trailing slash for stat compatability - trimslash(s); - return s; +std::string makePath(const std::string& base, const std::string& node) +{ + return (stdfs::path(base) / node).string(); +} + + +std::string normalize(const std::string& path) +{ + return stdfs::path(path).lexically_normal().string(); } std::string transcode(const std::string& path) { #if defined(_MSC_VER) && defined(SCY_UNICODE) - std::wstring_convert> - convert; // conversion between UTF-16 and UTF-8 - std::wstring uniPath = convert.from_bytes( - path); // convert UTF-8 std::string to UTF-16 std::wstring + std::wstring_convert> convert; + std::wstring uniPath = convert.from_bytes(path); DWORD len = WideCharToMultiByte( CP_ACP, WC_NO_BEST_FIT_CHARS, uniPath.c_str(), static_cast(uniPath.length()), nullptr, 0, nullptr, nullptr); if (len > 0) { - std::unique_ptr buffer(new char[len]); + auto buffer = std::make_unique(len); DWORD rc = WideCharToMultiByte( CP_ACP, WC_NO_BEST_FIT_CHARS, uniPath.c_str(), static_cast(uniPath.length()), buffer.get(), @@ -275,20 +197,6 @@ std::string transcode(const std::string& path) } -void addsep(std::string& path) -{ - if (!path.empty() && path.at(path.length() - 1) != fs::separator[0]) - path.append(fs::separator, 1); -} - - -void addnode(std::string& path, const std::string& node) -{ - fs::addsep(path); - path += node; -} - - bool savefile(const std::string& path, const char* data, size_t size, bool whiny) { diff --git a/src/base/src/logger.cpp b/src/base/src/logger.cpp index 6fc0803b4..3766c8501 100644 --- a/src/base/src/logger.cpp +++ b/src/base/src/logger.cpp @@ -1,605 +1,554 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// @addtogroup base -/// @{ - - -#include "scy/logger.h" -#include "scy/datetime.h" -#include "scy/filesystem.h" -#include "scy/platform.h" -#include "scy/time.h" -#include "scy/util.h" - -#include -#include - - -using std::endl; - - -namespace scy { - - -static Singleton singleton; - - -Logger::Logger() - : _defaultChannel(nullptr) - , _writer(new LogWriter) -{ - // Decouple C and C++ streams for performance increase. - // std::cout.sync_with_stdio(false); -} - - -Logger::~Logger() - { - if (_writer) - delete _writer; - util::clearMap(_channels); - _defaultChannel = nullptr; -} - - -Logger& Logger::instance() -{ - return *singleton.get(); -} - - -void Logger::setInstance(Logger* logger, bool freeExisting) -{ - auto current = singleton.swap(logger); - if (current && freeExisting) - delete current; -} - - -void Logger::destroy() -{ - singleton.destroy(); -} - - -void Logger::add(LogChannel* channel) -{ - std::lock_guard guard(_mutex); - // The first channel added will be the default channel. - if (_defaultChannel == nullptr) - _defaultChannel = channel; - _channels[channel->name()] = channel; -} - - -void Logger::remove(const std::string& name, bool freePointer) -{ - std::lock_guard guard(_mutex); - LogChannelMap::iterator it = _channels.find(name); - assert(it != _channels.end()); - if (it != _channels.end()) { - if (_defaultChannel == it->second) - _defaultChannel = nullptr; - if (freePointer) - delete it->second; - _channels.erase(it); - } -} - - -LogChannel* Logger::get(const std::string& name, bool whiny) const -{ - std::lock_guard guard(_mutex); - LogChannelMap::const_iterator it = _channels.find(name); - if (it != _channels.end()) - return it->second; - if (whiny) - throw std::runtime_error("Not found: No log channel named: " + name); - return nullptr; -} - - -void Logger::setDefault(const std::string& name) -{ - std::lock_guard guard(_mutex); - _defaultChannel = get(name, true); -} - - -LogChannel* Logger::getDefault() const -{ - std::lock_guard guard(_mutex); - return _defaultChannel; -} - - -void Logger::setWriter(LogWriter* writer) -{ - // NOTE: Cannot lock here as writer may - // attempt to flush pending on destruction. - // std::lock_guard guard(_mutex); - if (_writer) { - delete _writer; - } - _writer = writer; -} - - -void Logger::write(const LogStream& stream) -{ - // avoid if possible, requires extra copy - write(new LogStream(stream)); -} - - -void Logger::write(LogStream* stream) -{ -#ifdef SCY_ENABLE_LOGGING - std::lock_guard guard(_mutex); - if (stream->channel == nullptr) - stream->channel = _defaultChannel; - - // Drop messages if there is no output channel - if (stream->channel == nullptr) { - delete stream; - return; - } - _writer->write(stream); -#endif -} - - -// LogStream& Logger::send(const char* level, const char* realm, const void* ptr, -// const char* channel) const -// { -// return *new LogStream(getLevelFromString(level), realm, 0, ptr, channel); -// } - - -// -// Log Writer -// - - -LogWriter::LogWriter() -{ -} - - -LogWriter::~LogWriter() -{ -} - - -void LogWriter::write(LogStream* stream) -{ -#ifdef SCY_ENABLE_LOGGING - // TODO: Make safer; if the app exists and async stuff - // is still logging we can end up with a crash here. - stream->channel->write(*stream); - delete stream; -#endif -} - - -// -// Asynchronous Log Writer -// - - -AsyncLogWriter::AsyncLogWriter() -{ - _thread.start(std::bind(&AsyncLogWriter::run, this)); -} - - -AsyncLogWriter::~AsyncLogWriter() -{ - // Cancel and wait for the thread - cancel(); - - // Note: Not using join here as it is causing a deadlock - // when unloading shared libraries when the logger is not - // explicitly shutdown(). - // while (_thread.running()) - // scy::sleep(10); - _thread.join(); - - // Flush remaining items synchronously - flush(); - assert(_pending.empty()); -} - - -void AsyncLogWriter::write(LogStream* stream) -{ - std::lock_guard guard(_mutex); - _pending.push_back(stream); -} - - -void AsyncLogWriter::clear() -{ - std::lock_guard guard(_mutex); - LogStream* next = nullptr; - while (!_pending.empty()) { - next = _pending.front(); - delete next; - _pending.pop_front(); - } -} - - -void AsyncLogWriter::flush() -{ - while (writeNext()) - scy::sleep(1); -} - - -void AsyncLogWriter::run() -{ - while (!cancelled()) { - scy::sleep(writeNext() ? 1 : 50); - } -} - - -bool AsyncLogWriter::writeNext() -{ -#ifdef SCY_ENABLE_LOGGING - LogStream* next; - { - std::lock_guard guard(_mutex); - if (_pending.empty()) - return false; - - next = _pending.front(); - _pending.pop_front(); - } - next->channel->write(*next); - delete next; - return true; -#else - return false; -#endif -} - - -// -// Log Stream -// - - -#ifdef SCY_ENABLE_LOGGING - -LogStream::LogStream(Level level, std::string realm, int line, const char* channel) - : level(level) - , line(line) - , realm(std::move(realm)) - , ts(time::now()) - , channel(channel ? Logger::instance().get(channel, false) : nullptr) - , flushed(false) -{ -} - - -LogStream::LogStream(const LogStream& that) - : level(that.level) - , line(that.line) - , realm(that.realm) - , ts(that.ts) - , channel(that.channel) - , flushed(that.flushed) -{ - // NOTE: std::stringstream::swap is not implemented on gcc < 5 -#if __GNUC__ < 5 - message.str(that.message.str()); -#else - // message.rdbuf()->swap(*that.message.rdbuf()); - message.swap(const_cast(that.message)); -#endif -} - - -LogStream::~LogStream() -{ - flush(); -} - -#endif - - -// -// Log Channel -// - - -LogChannel::LogChannel(std::string name, Level level, - std::string timeFormat) - : _name(std::move(name)) - , _level(level) - , _timeFormat(std::move(timeFormat)) -{ -} - - -void LogChannel::write(std::string message, Level level, - std::string realm) -{ -#ifdef SCY_ENABLE_LOGGING - LogStream stream(level, std::move(realm), 0); - stream << std::move(message); - write(stream); -#endif -} - - -void LogChannel::write(const LogStream& stream) -{ - (void)stream; -} - - -void LogChannel::format(const LogStream& stream, std::ostream& ost) -{ -#ifdef SCY_ENABLE_LOGGING - if (!_timeFormat.empty()) - ost << time::print(time::toLocal(stream.ts), _timeFormat.c_str()); - ost << " [" << getStringFromLevel(stream.level) << "] "; - if (!stream.realm.empty()) { // || !stream.address.empty() - ost << "["; - if (!stream.realm.empty()) - ost << stream.realm; - if (stream.line > 0) - ost << "(" << stream.line << ")"; - // if (!stream.address.empty()) - // ost << ":" << stream.address; - ost << "] "; - } - ost << stream.message.str(); - ost.flush(); -#endif -} - - -// -// Console Channel -// - - -ConsoleChannel::ConsoleChannel(std::string name, Level level, - std::string timeFormat) - : LogChannel(std::move(name), level, std::move(timeFormat)) -{ -} - - -void ConsoleChannel::write(const LogStream& stream) -{ -#ifdef SCY_ENABLE_LOGGING - if (_level > stream.level) - return; - - if (!_filter.empty() && !util::matchNodes(stream.realm, _filter, "::")) - return; - - std::ostringstream ss; - format(stream, ss); -#if !defined(WIN32) || defined(_CONSOLE) || defined(_DEBUG) - std::cout << ss.str() << std::flush; -#endif -//#if defined(_MSC_VER) && defined(_DEBUG) -// std::string s(ss.str()); -// std::wstring temp(s.length(), L' '); -// std::copy(s.begin(), s.end(), temp.begin()); -// OutputSDebugtring(temp.c_str()); -//#endif -#endif -} - - -// -// File Channel -// - - -FileChannel::FileChannel(std::string name, std::string path, - Level level, std::string timeFormat) - : LogChannel(std::move(name), level, std::move(timeFormat)) - , _path(std::move(path)) -{ -} - - -FileChannel::~FileChannel() -{ - close(); -} - - -void FileChannel::open() -{ - // Ensure a path was set - if (_path.empty()) - throw std::runtime_error("Log file path must be set."); - - // Create directories if needed - fs::mkdirr(fs::dirname(_path)); - - // Open the file stream - _fstream.close(); - _fstream.open(_path.c_str(), std::ios::out | std::ios::app); - - // Throw on failure - if (!_fstream.is_open()) - throw std::runtime_error("Failed to open log file: " + _path); -} - - -void FileChannel::close() -{ - _fstream.close(); -} - - -void FileChannel::write(const LogStream& stream) -{ -#ifdef SCY_ENABLE_LOGGING - if (this->level() > stream.level) - return; - - if (!_fstream.is_open()) - open(); - - std::ostringstream ss; - format(stream, ss); - _fstream << ss.str() << std::endl; - _fstream.flush(); - -#if defined(_CONSOLE) || defined(_DEBUG) - std::cout << ss.str() << std::flush; -#endif -//#if defined(_MSC_VER) && defined(_DEBUG) -// std::string s(ss.str()); -// std::wstring temp(s.length(), L' '); -// std::copy(s.begin(), s.end(), temp.begin()); -// OutputSDebugtring(temp.c_str()); -//#endif -#endif -} - - -void FileChannel::setPath(const std::string& path) -{ - _path = path; - open(); -} - - -std::string FileChannel::path() const -{ - return _path; -} - - -// -// Rotating File Channel -// - - -RotatingFileChannel::RotatingFileChannel(std::string name, - std::string dir, - Level level, - std::string extension, - int rotationInterval, - std::string timeFormat) - : LogChannel(std::move(name), level, std::move(timeFormat)) - , _fstream(nullptr) - , _dir(std::move(dir)) - , _extension(std::move(extension)) - , _rotationInterval(rotationInterval) - , _rotatedAt(0) -{ - // The initial log file will be opened on the first call to rotate() -} - - -RotatingFileChannel::~RotatingFileChannel() -{ - if (_fstream) { - _fstream->close(); - delete _fstream; - } -} - - -void RotatingFileChannel::write(const LogStream& stream) -{ -#ifdef SCY_ENABLE_LOGGING - if (this->level() > stream.level) - return; - - if (_fstream == nullptr || stream.ts - _rotatedAt > _rotationInterval) - rotate(); - - std::ostringstream ss; - format(stream, ss); - *_fstream << ss.str(); - _fstream->flush(); - -#if defined(_CONSOLE) && defined(_DEBUG) - std::cout << ss.str() << std::flush; -#endif -//#if defined(_MSC_VER) && defined(_DEBUG) -// std::string s(ss.str()); -// std::wstring temp(s.length(), L' '); -// std::copy(s.begin(), s.end(), temp.begin()); -// OutputSDebugtring(temp.c_str()); -//#endif -#endif -} - - -void RotatingFileChannel::rotate() -{ - if (_fstream) { - _fstream->close(); - delete _fstream; - } - - // Always try to create the directory - fs::mkdirr(_dir); - - // Open the next log file - _filename = util::format("%s_%ld.%s", _name.c_str(), - static_cast(Timestamp().epochTime()), - _extension.c_str()); - - std::string path(_dir); - fs::addnode(path, _filename); - _fstream = new std::ofstream(path); - _rotatedAt = time::now(); -} - - -#if 0 -// --------------------------------------------------------------------- -// Evented File Channel -// -EventedFileChannel::EventedFileChannel(std::string name, - const std::string& dir, - Level level, - const std::string& extension, - int rotationInterval, - const char* timeFormat) : - FileChannel(name, dir, level, extension, rotationInterval, timeFormat) -{ -} - - -EventedFileChannel::~EventedFileChannel() -{ -} - - -void EventedFileChannel::write(const LogStream& stream, Level level, const char* realm, const void* ptr) -{ - if (this->level() > level) - return; - - FileChannel::write(message, level, ptr); - OnLogStream.emit(message, level, ptr); -} -#endif - - -} // namespace scy - - -/// @\} +/// +// +// LibSourcey +// Copyright (c) 2005, Sourcey +// +// SPDX-License-Identifier: LGPL-2.1+ +// +/// @addtogroup base +/// @{ + + +#include "scy/logger.h" +#include "scy/datetime.h" +#include "scy/platform.h" + +#include "scy/filesystem.h" +#include "scy/time.h" +#include "scy/util.h" + +#include +#include +#include + + +using std::endl; + + +namespace scy { + + +static Singleton singleton; + + +Logger::Logger() + : _defaultChannel(nullptr) + , _writer(std::make_unique()) +{ +} + + +Logger::~Logger() +{ + _defaultChannel = nullptr; + _channels.clear(); +} + + +Logger& Logger::instance() +{ + return *singleton.get(); +} + + +void Logger::setInstance(Logger* logger, bool freeExisting) +{ + auto current = singleton.swap(logger); + if (current && freeExisting) + delete current; +} + + +void Logger::destroy() +{ + singleton.destroy(); +} + + +void Logger::add(std::unique_ptr channel) +{ + std::lock_guard guard(_mutex); + auto* raw = channel.get(); + // The first channel added will be the default channel. + if (_defaultChannel == nullptr) + _defaultChannel = raw; + _channels[raw->name()] = std::move(channel); +} + + +void Logger::remove(const std::string& name) +{ + std::lock_guard guard(_mutex); + auto it = _channels.find(name); + if (it == _channels.end()) + throw std::runtime_error("Logger: channel not found: " + name); + { + if (_defaultChannel == it->second.get()) + _defaultChannel = nullptr; + _channels.erase(it); + } +} + + +LogChannel* Logger::get(const std::string& name, bool whiny) const +{ + std::lock_guard guard(_mutex); + auto it = _channels.find(name); + if (it != _channels.end()) + return it->second.get(); + if (whiny) + throw std::runtime_error("Not found: No log channel named: " + name); + return nullptr; +} + + +void Logger::setDefault(const std::string& name) +{ + std::lock_guard guard(_mutex); + _defaultChannel = get(name, true); +} + + +LogChannel* Logger::getDefault() const +{ + std::lock_guard guard(_mutex); + return _defaultChannel; +} + + +void Logger::setWriter(std::unique_ptr writer) +{ + // NOTE: Cannot lock here as writer may + // attempt to flush pending on destruction. + _writer = std::move(writer); +} + + +void Logger::write(const LogStream& stream) +{ + // avoid if possible, requires extra copy + write(std::make_unique(stream)); +} + + +void Logger::write(std::unique_ptr stream) +{ +#ifdef SCY_ENABLE_LOGGING + std::lock_guard guard(_mutex); + if (stream->channel == nullptr) + stream->channel = _defaultChannel; + + // Drop messages if there is no output channel + if (stream->channel == nullptr) + return; + _writer->write(std::move(stream)); +#endif +} + + +// LogStream& Logger::send(const char* level, const char* realm, const void* ptr, +// const char* channel) const +// { +// return *new LogStream(getLevelFromString(level), realm, 0, ptr, channel); +// } + + +// +// Log Writer +// + + +LogWriter::LogWriter() +{ +} + + +LogWriter::~LogWriter() +{ +} + + +void LogWriter::write(std::unique_ptr stream) +{ +#ifdef SCY_ENABLE_LOGGING + stream->channel->write(*stream); +#endif +} + + +// +// Asynchronous Log Writer +// + + +AsyncLogWriter::AsyncLogWriter() +{ + _thread.start(std::bind(&AsyncLogWriter::run, this)); +} + + +AsyncLogWriter::~AsyncLogWriter() +{ + // Cancel and wait for the thread + cancel(); + + // Note: Not using join here as it is causing a deadlock + // when unloading shared libraries when the logger is not + // explicitly shutdown(). + // while (_thread.running()) + // scy::sleep(10); + _thread.join(); + + // Flush remaining items synchronously + flush(); + if (!_pending.empty()) + LWarn("AsyncLogWriter: pending messages on close"); +} + + +void AsyncLogWriter::write(std::unique_ptr stream) +{ + std::lock_guard guard(_mutex); + _pending.push_back(std::move(stream)); +} + + +void AsyncLogWriter::clear() +{ + std::lock_guard guard(_mutex); + _pending.clear(); +} + + +void AsyncLogWriter::flush() +{ + while (writeNext()) + std::this_thread::yield(); +} + + +void AsyncLogWriter::run() +{ + using namespace std::chrono_literals; + while (!cancelled()) { + if (!writeNext()) + std::this_thread::sleep_for(50ms); + } +} + + +bool AsyncLogWriter::writeNext() +{ +#ifdef SCY_ENABLE_LOGGING + std::unique_ptr next; + { + std::lock_guard guard(_mutex); + if (_pending.empty()) + return false; + + next = std::move(_pending.front()); + _pending.pop_front(); + } + next->channel->write(*next); + return true; +#else + return false; +#endif +} + + +// +// Log Stream +// + + +#ifdef SCY_ENABLE_LOGGING + +LogStream::LogStream(Level level, std::string realm, int line, const char* channel) + : level(level) + , line(line) + , realm(std::move(realm)) + , ts(time::now()) + , channel(channel ? Logger::instance().get(channel, false) : nullptr) + , flushed(false) +{ +} + + +LogStream::LogStream(const LogStream& that) + : level(that.level) + , line(that.line) + , realm(that.realm) + , ts(that.ts) + , channel(that.channel) + , flushed(that.flushed) +{ + // NOTE: std::stringstream::swap is not implemented on gcc < 5 +#if __GNUC__ < 5 + message.str(that.message.str()); +#else + // message.rdbuf()->swap(*that.message.rdbuf()); + message.swap(const_cast(that.message)); +#endif +} + + +LogStream::~LogStream() +{ + flush(); +} + +#endif + + +// +// Log Channel +// + + +LogChannel::LogChannel(std::string name, Level level, + std::string timeFormat) + : _name(std::move(name)) + , _level(level) + , _timeFormat(std::move(timeFormat)) +{ +} + + +void LogChannel::write(std::string message, Level level, + std::string realm) +{ +#ifdef SCY_ENABLE_LOGGING + LogStream stream(level, std::move(realm), 0); + stream << std::move(message); + write(stream); +#endif +} + + +void LogChannel::write(const LogStream& stream) +{ + (void)stream; +} + + +void LogChannel::format(const LogStream& stream, std::ostream& ost) +{ +#ifdef SCY_ENABLE_LOGGING + if (!_timeFormat.empty()) + ost << time::print(time::toLocal(stream.ts), _timeFormat.c_str()); + ost << " [" << getStringFromLevel(stream.level) << "] "; + if (!stream.realm.empty()) { // || !stream.address.empty() + ost << "["; + if (!stream.realm.empty()) + ost << stream.realm; + if (stream.line > 0) + ost << "(" << stream.line << ")"; + // if (!stream.address.empty()) + // ost << ":" << stream.address; + ost << "] "; + } + ost << stream.message.str(); + ost.flush(); +#endif +} + + +// +// Console Channel +// + + +ConsoleChannel::ConsoleChannel(std::string name, Level level, + std::string timeFormat) + : LogChannel(std::move(name), level, std::move(timeFormat)) +{ +} + + +void ConsoleChannel::write(const LogStream& stream) +{ +#ifdef SCY_ENABLE_LOGGING + if (_level > stream.level) + return; + + if (!_filter.empty() && !util::matchNodes(stream.realm, _filter, "::")) + return; + + std::ostringstream ss; + format(stream, ss); +#if !defined(WIN32) || defined(_CONSOLE) || defined(_DEBUG) + std::cout << ss.str() << std::flush; +#endif +//#if defined(_MSC_VER) && defined(_DEBUG) +// std::string s(ss.str()); +// std::wstring temp(s.length(), L' '); +// std::copy(s.begin(), s.end(), temp.begin()); +// OutputSDebugtring(temp.c_str()); +//#endif +#endif +} + + +// +// File Channel +// + + +FileChannel::FileChannel(std::string name, std::string path, + Level level, std::string timeFormat) + : LogChannel(std::move(name), level, std::move(timeFormat)) + , _path(std::move(path)) +{ +} + + +FileChannel::~FileChannel() +{ + close(); +} + + +void FileChannel::open() +{ + // Ensure a path was set + if (_path.empty()) + throw std::runtime_error("Log file path must be set."); + + // Create directories if needed + fs::mkdirr(fs::dirname(_path)); + + // Open the file stream + _fstream.close(); + _fstream.open(_path.c_str(), std::ios::out | std::ios::app); + + // Throw on failure + if (!_fstream.is_open()) + throw std::runtime_error("Failed to open log file: " + _path); +} + + +void FileChannel::close() +{ + _fstream.close(); +} + + +void FileChannel::write(const LogStream& stream) +{ +#ifdef SCY_ENABLE_LOGGING + if (this->level() > stream.level) + return; + + if (!_fstream.is_open()) + open(); + + std::ostringstream ss; + format(stream, ss); + _fstream << ss.str() << std::endl; + _fstream.flush(); + +#if defined(_CONSOLE) || defined(_DEBUG) + std::cout << ss.str() << std::flush; +#endif +//#if defined(_MSC_VER) && defined(_DEBUG) +// std::string s(ss.str()); +// std::wstring temp(s.length(), L' '); +// std::copy(s.begin(), s.end(), temp.begin()); +// OutputSDebugtring(temp.c_str()); +//#endif +#endif +} + + +void FileChannel::setPath(const std::string& path) +{ + _path = path; + open(); +} + + +std::string FileChannel::path() const +{ + return _path; +} + + +// +// Rotating File Channel +// + + +RotatingFileChannel::RotatingFileChannel(std::string name, + std::string dir, + Level level, + std::string extension, + int rotationInterval, + std::string timeFormat) + : LogChannel(std::move(name), level, std::move(timeFormat)) + , _dir(std::move(dir)) + , _extension(std::move(extension)) + , _rotationInterval(rotationInterval) + , _rotatedAt(0) +{ + // The initial log file will be opened on the first call to rotate() +} + + +RotatingFileChannel::~RotatingFileChannel() +{ + if (_fstream) + _fstream->close(); +} + + +void RotatingFileChannel::write(const LogStream& stream) +{ +#ifdef SCY_ENABLE_LOGGING + if (this->level() > stream.level) + return; + + if (!_fstream || stream.ts - _rotatedAt > _rotationInterval) + rotate(); + + std::ostringstream ss; + format(stream, ss); + *_fstream << ss.str(); + _fstream->flush(); + +#if defined(_CONSOLE) && defined(_DEBUG) + std::cout << ss.str() << std::flush; +#endif +//#if defined(_MSC_VER) && defined(_DEBUG) +// std::string s(ss.str()); +// std::wstring temp(s.length(), L' '); +// std::copy(s.begin(), s.end(), temp.begin()); +// OutputSDebugtring(temp.c_str()); +//#endif +#endif +} + + +void RotatingFileChannel::rotate() +{ + if (_fstream) + _fstream->close(); + + // Always try to create the directory + fs::mkdirr(_dir); + + // Open the next log file + _filename = util::format("%s_%ld.%s", _name.c_str(), + static_cast(Timestamp().epochTime()), + _extension.c_str()); + + std::string path = fs::makePath(_dir, _filename); + _fstream = std::make_unique(path); + _rotatedAt = time::now(); +} + + +} // namespace scy + + +/// @\} diff --git a/src/base/src/memory.cpp b/src/base/src/memory.cpp deleted file mode 100644 index 45baaa4f8..000000000 --- a/src/base/src/memory.cpp +++ /dev/null @@ -1,199 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// @addtogroup base -/// @{ - - -#include "scy/memory.h" -#include "scy/util.h" - - -using std::endl; - - -namespace scy { - - -static Singleton singleton; -static const int GCTimerDelay = 100; - - -GarbageCollector::GarbageCollector() - : _tid(std::this_thread::get_id()) -{ - LTrace("Create") -} - - -GarbageCollector::~GarbageCollector() -{ - //if (!_finalize) - // finalize(); - finalize(); - - util::clearVector(_cleaners); -} - - - -GarbageCollector::Cleaner* GarbageCollector::getCleaner(uv::Loop* loop) -{ - std::lock_guard guard(_mutex); - - for (auto cleaner : _cleaners) { - if (loop == cleaner->_loop) - return cleaner; - } - - auto clnr = new Cleaner(loop); - _cleaners.push_back(clnr); - return clnr; -} - - -void GarbageCollector::finalize() -{ - // LTrace("Finalize") - - std::lock_guard guard(_mutex); - - assert(_tid == std::this_thread::get_id()); - for (auto cleaner : _cleaners) { - if (!cleaner->_finalize) - cleaner->finalize(); - } - - //// Ensure the loop is not running and that the - //// calling thread is the main thread. - //_handle.assertThread(); - //// assert(_handle.loop()->active_handles <= 1); - //assert(!_handle.closed()); - //assert(!_finalize); - //_finalize = true; - - //// Run the loop until managed pointers have been deleted, - //// and the internal timer has also been deleted. - //uv_timer_set_repeat(_handle.ptr(), 1); - //uv_ref(_handle.ptr()); - //uv_run(_handle.loop(), UV_RUN_DEFAULT); - - //LTrace("Finalize: OK") -} - - -std::thread::id GarbageCollector::tid() -{ - return _tid; -} - - -void GarbageCollector::destroy() -{ - singleton.destroy(); -} - - -GarbageCollector& GarbageCollector::instance() -{ - return *singleton.get(); -} - - -// -// Garbage Collector Cleaner -// - - -GarbageCollector::Cleaner::Cleaner(uv::Loop* loop) - : _timer(GCTimerDelay, GCTimerDelay, loop, - std::bind(&GarbageCollector::Cleaner::work, this)) - , _loop(loop) - , _finalize(false) -{ - LTrace("Create: ", loop) -} - - -GarbageCollector::Cleaner::~Cleaner() -{ - if (!_finalize) - finalize(); - - // The queue should be empty on shutdown if finalized correctly. - assert(_pending.empty()); - assert(_ready.empty()); - - //util::clearVector(_ready); - //util::clearVector(_pending); -} - - -void GarbageCollector::Cleaner::finalize() -{ - assert(!_finalize && "finalizing twice"); - _finalize = true; - - // Ensure previous calls to uv_stop don't prevent cleanup. - //_loop->stop_flag = 0; - - assert(_timer.handle().initialized()); - _timer.setInterval(1); - _timer.handle().ref(); // ref until complete - uv_run(_loop, UV_RUN_DEFAULT); - - assert(_pending.empty()); - assert(_ready.empty()); -} - - -void GarbageCollector::Cleaner::work() -{ - std::vector deletable; - { - std::lock_guard guard(_mutex); - if (!_ready.empty() || !_pending.empty()) { - // STrace << "Deleting: " - // << "ready=" << _ready.size() << ", " - // << "pending=" << _pending.size() << std::endl; - - // Delete waiting pointers - deletable = _ready; - _ready.clear(); - - // Swap pending pointers to the ready queue - _ready.swap(_pending); - } - } - - // Delete pointers - util::clearVector(deletable); - - // Handle finalization - if (_finalize) { - std::lock_guard guard(_mutex); - if (_ready.empty() && _pending.empty()) { - // Stop the timer handle allowing the finalize() method to return. - _timer.stop(); - - // LTrace("Finalization complete: ", _loop->active_handles) -#ifdef _DEBUG - // Print active handles, there should only be 1 left (our timer) - uv_walk(_loop, [](uv_handle_t* handle, void* /* arg */) { - // LDebug("Active handle: ", handle, ": ", handle->type) - }, nullptr); - // assert(_handle.loop()->active_handles <= 1); -#endif - } - } -} - - -} // namespace scy - - -/// @\} diff --git a/src/base/src/numeric.cpp b/src/base/src/numeric.cpp index 20f77777a..e5ea6b045 100644 --- a/src/base/src/numeric.cpp +++ b/src/base/src/numeric.cpp @@ -14,7 +14,7 @@ #include "scy/numeric.h" -#include +#include #if defined(_MSC_VER) || defined(__MINGW32__) @@ -40,7 +40,8 @@ void format(std::string& str, int value) void format(std::string& str, int value, int width) { - assert(width > 0 && width < 64); + if (width <= 0 || width >= 64) + throw std::invalid_argument("Numeric: width out of range"); char buffer[64]; std::sprintf(buffer, "%*d", width, value); @@ -50,7 +51,8 @@ void format(std::string& str, int value, int width) void format0(std::string& str, int value, int width) { - assert(width > 0 && width < 64); + if (width <= 0 || width >= 64) + throw std::invalid_argument("Numeric: width out of range"); char buffer[64]; std::sprintf(buffer, "%0*d", width, value); @@ -68,7 +70,8 @@ void formatHex(std::string& str, int value) void formatHex(std::string& str, int value, int width) { - assert(width > 0 && width < 64); + if (width <= 0 || width >= 64) + throw std::invalid_argument("Numeric: width out of range"); char buffer[64]; std::sprintf(buffer, "%0*X", width, value); @@ -86,7 +89,8 @@ void format(std::string& str, unsigned value) void format(std::string& str, unsigned value, int width) { - assert(width > 0 && width < 64); + if (width <= 0 || width >= 64) + throw std::invalid_argument("Numeric: width out of range"); char buffer[64]; std::sprintf(buffer, "%*u", width, value); @@ -96,7 +100,8 @@ void format(std::string& str, unsigned value, int width) void format0(std::string& str, unsigned int value, int width) { - assert(width > 0 && width < 64); + if (width <= 0 || width >= 64) + throw std::invalid_argument("Numeric: width out of range"); char buffer[64]; std::sprintf(buffer, "%0*u", width, value); @@ -114,7 +119,8 @@ void formatHex(std::string& str, unsigned value) void formatHex(std::string& str, unsigned value, int width) { - assert(width > 0 && width < 64); + if (width <= 0 || width >= 64) + throw std::invalid_argument("Numeric: width out of range"); char buffer[64]; std::sprintf(buffer, "%0*X", width, value); @@ -132,7 +138,8 @@ void format(std::string& str, long value) void format(std::string& str, long value, int width) { - assert(width > 0 && width < 64); + if (width <= 0 || width >= 64) + throw std::invalid_argument("Numeric: width out of range"); char buffer[64]; std::sprintf(buffer, "%*ld", width, value); @@ -142,7 +149,8 @@ void format(std::string& str, long value, int width) void format0(std::string& str, long value, int width) { - assert(width > 0 && width < 64); + if (width <= 0 || width >= 64) + throw std::invalid_argument("Numeric: width out of range"); char buffer[64]; std::sprintf(buffer, "%0*ld", width, value); @@ -160,7 +168,8 @@ void formatHex(std::string& str, long value) void formatHex(std::string& str, long value, int width) { - assert(width > 0 && width < 64); + if (width <= 0 || width >= 64) + throw std::invalid_argument("Numeric: width out of range"); char buffer[64]; std::sprintf(buffer, "%0*lX", width, value); @@ -178,7 +187,8 @@ void format(std::string& str, unsigned long value) void format(std::string& str, unsigned long value, int width) { - assert(width > 0 && width < 64); + if (width <= 0 || width >= 64) + throw std::invalid_argument("Numeric: width out of range"); char buffer[64]; std::sprintf(buffer, "%*lu", width, value); @@ -188,7 +198,8 @@ void format(std::string& str, unsigned long value, int width) void format0(std::string& str, unsigned long value, int width) { - assert(width > 0 && width < 64); + if (width <= 0 || width >= 64) + throw std::invalid_argument("Numeric: width out of range"); char buffer[64]; std::sprintf(buffer, "%0*lu", width, value); @@ -206,7 +217,8 @@ void formatHex(std::string& str, unsigned long value) void formatHex(std::string& str, unsigned long value, int width) { - assert(width > 0 && width < 64); + if (width <= 0 || width >= 64) + throw std::invalid_argument("Numeric: width out of range"); char buffer[64]; std::sprintf(buffer, "%0*lX", width, value); @@ -227,7 +239,8 @@ void format(std::string& str, std::int64_t value) void format(std::string& str, std::int64_t value, int width) { - assert(width > 0 && width < 64); + if (width <= 0 || width >= 64) + throw std::invalid_argument("Numeric: width out of range"); char buffer[64]; std::sprintf(buffer, "%*" I64_FMT "d", width, value); @@ -237,7 +250,8 @@ void format(std::string& str, std::int64_t value, int width) void format0(std::string& str, std::int64_t value, int width) { - assert(width > 0 && width < 64); + if (width <= 0 || width >= 64) + throw std::invalid_argument("Numeric: width out of range"); char buffer[64]; std::sprintf(buffer, "%0*" I64_FMT "d", width, value); @@ -255,7 +269,8 @@ void formatHex(std::string& str, std::int64_t value) void formatHex(std::string& str, std::int64_t value, int width) { - assert(width > 0 && width < 64); + if (width <= 0 || width >= 64) + throw std::invalid_argument("Numeric: width out of range"); char buffer[64]; std::sprintf(buffer, "%0*" I64_FMT "X", width, value); @@ -273,7 +288,8 @@ void format(std::string& str, uint64_t value) void format(std::string& str, uint64_t value, int width) { - assert(width > 0 && width < 64); + if (width <= 0 || width >= 64) + throw std::invalid_argument("Numeric: width out of range"); char buffer[64]; std::sprintf(buffer, "%*" I64_FMT "u", width, value); @@ -283,7 +299,8 @@ void format(std::string& str, uint64_t value, int width) void format0(std::string& str, uint64_t value, int width) { - assert(width > 0 && width < 64); + if (width <= 0 || width >= 64) + throw std::invalid_argument("Numeric: width out of range"); char buffer[64]; std::sprintf(buffer, "%0*" I64_FMT "u", width, value); @@ -301,7 +318,8 @@ void formatHex(std::string& str, uint64_t value) void formatHex(std::string& str, uint64_t value, int width) { - assert(width > 0 && width < 64); + if (width <= 0 || width >= 64) + throw std::invalid_argument("Numeric: width out of range"); char buffer[64]; std::sprintf(buffer, "%0*" I64_FMT "X", width, value); @@ -315,17 +333,6 @@ void formatHex(std::string& str, uint64_t value, int width) void format(std::string& str, const void* ptr) { char buffer[24]; -#if 0 // deprecated -#if defined(SCY_PTR_IS_64_BIT) -#if defined(SCY_LONG_IS_64_BIT) - std::sprintf(buffer, "%016lX", (std::uintptr_t)ptr); -#else - std::sprintf(buffer, "%016" I64_FMT "X", (std::uintptr_t)ptr); -#endif -#else - std::sprintf(buffer, "%08lX", (std::uintptr_t)ptr); -#endif -#endif std::sprintf(buffer, "%p", ptr); str.append(buffer); } diff --git a/src/base/src/packetstream.cpp b/src/base/src/packetstream.cpp index 7c1e06407..a168b63f7 100644 --- a/src/base/src/packetstream.cpp +++ b/src/base/src/packetstream.cpp @@ -10,7 +10,6 @@ #include "scy/packetstream.h" -#include "scy/memory.h" #include "scy/packetqueue.h" @@ -21,8 +20,7 @@ namespace scy { PacketStream::PacketStream(const std::string& name) - : opaque(nullptr) - , _name(name) + : _name(name) , _autoStart(false) , _closeOnError(true) { @@ -36,23 +34,24 @@ PacketStream::~PacketStream() // Delete managed adapters reset(); - // The event machine should always be complete - assert(stateEquals(PacketStreamState::None) || - stateEquals(PacketStreamState::Closed) || - stateEquals(PacketStreamState::Error)); + // Verify the stream reached a terminal state + if (!stateEquals(PacketStreamState::None) && + !stateEquals(PacketStreamState::Closed) && + !stateEquals(PacketStreamState::Error)) + LWarn("PacketStream destroyed in non-terminal state: ", state()); - // Make sure all adapters have been cleaned up - assert(_sources.empty()); - assert(_processors.empty()); + // Verify all adapters have been cleaned up + if (!_sources.empty() || !_processors.empty()) + LWarn("PacketStream destroyed with remaining adapters"); } void PacketStream::start() { - LTrace("Start") + LTrace("Start"); if (stateEquals(PacketStreamState::Active)) { - LTrace("Start: Already active") + LTrace("Start: Already active"); // assert(0); return; } @@ -73,12 +72,12 @@ void PacketStream::start() void PacketStream::stop() { - LTrace("Stop") + LTrace("Stop"); if (stateEquals(PacketStreamState::Stopped) || stateEquals(PacketStreamState::Stopping) || stateEquals(PacketStreamState::Closed)) { - LTrace("Stop: Already stopped") + LTrace("Stop: Already stopped"); // assert(0); return; } @@ -96,16 +95,16 @@ void PacketStream::stop() void PacketStream::pause() { - LTrace("Pause") + LTrace("Pause"); setState(this, PacketStreamState::Paused); } void PacketStream::resume() { - LTrace("Resume") + LTrace("Resume"); if (!stateEquals(PacketStreamState::Paused)) { - LTrace("Resume: Not paused") + LTrace("Resume: Not paused"); return; } @@ -115,12 +114,13 @@ void PacketStream::resume() void PacketStream::reset() { - LTrace("Reset") - assert(stateEquals(PacketStreamState::None) || - stateEquals(PacketStreamState::Closed)); + LTrace("Reset"); + if (!stateEquals(PacketStreamState::None) && + !stateEquals(PacketStreamState::Closed)) + throw std::logic_error("PacketStream: cannot reset in current state"); std::lock_guard guard(_mutex); - _sources.clear(); // not detaching here + _sources.clear(); // not detaching here _processors.clear(); // not detaching here } @@ -129,7 +129,7 @@ void PacketStream::close() { if (stateEquals(PacketStreamState::None) || stateEquals(PacketStreamState::Closed)) { - // LTrace("Already closed") + // LTrace("Already closed"); // assert(0); return; } @@ -139,7 +139,7 @@ void PacketStream::close() !stateEquals(PacketStreamState::Stopping)) stop(); - LTrace("Closing") + LTrace("Closing"); // Queue the Closed state setState(this, PacketStreamState::Closed); @@ -263,7 +263,7 @@ void PacketStream::synchronizeStates() _states.pop_front(); } - LTrace("Set queued state: ", state) + LTrace("Set queued state: ", state); // Send the stream state to packet adapters. // This is done inside the processor thread context so @@ -279,7 +279,7 @@ void PacketStream::synchronizeStates() void PacketStream::process(IPacket& packet) { STrace << "Processing packet: " << state() << ": " - << packet.className() << endl; + << packet.className() << endl; // assert(Thread::currentID() == _runner->tid()); try { @@ -291,11 +291,10 @@ void PacketStream::process(IPacket& packet) // Process the packet if the stream is active PacketProcessor* firstProc = nullptr; if (stateEquals(PacketStreamState::Active) && - !packet.flags.has(PacketFlags::NoModify)) { + !packet.flags.has(static_cast(PacketFlags::NoModify))) { { std::lock_guard guard(_mutex); - firstProc = !_processors.empty() ? - reinterpret_cast(_processors[0]->ptr) : nullptr; + firstProc = !_processors.empty() ? reinterpret_cast(_processors[0]->ptr) : nullptr; } if (firstProc) { @@ -323,24 +322,23 @@ void PacketStream::process(IPacket& packet) // Proxy packets which are rejected by the first processor else { SWarn << "Source packet rejected: " << firstProc - << ": " << packet.className() << endl; + << ": " << packet.className() << endl; firstProc = nullptr; } } } - // Otherwise just proxy and emit the packet - // TODO: Should we pass the packet to the PacketSyncQueue if - // synchronizeOutput was used? + // Otherwise just proxy and emit the packet. + // Note: synchronizeOutput is not applied here (packets bypass sync queue). if (!firstProc) { STrace << "Proxying packet: " << state() << ": " - << packet.className() << endl; + << packet.className() << endl; emit(packet); } // Stop the packet stream on the final packet if (stateEquals(PacketStreamState::Active) && - packet.flags.has(PacketFlags::Final)) { + packet.flags.has(static_cast(PacketFlags::Final))) { this->stop(); } } @@ -357,11 +355,11 @@ void PacketStream::process(IPacket& packet) void PacketStream::emit(IPacket& packet) { - LTrace("Emit: ", packet.size()) + LTrace("Emit: ", packet.size()); // Ensure the stream is still running if (!stateEquals(PacketStreamState::Active)) { - LTrace("Dropping packet on inactive stream: ", state()) + LTrace("Dropping packet on inactive stream: ", state()); return; } @@ -398,7 +396,7 @@ void PacketStream::setup() source->ptr->getEmitter() += slot(this, &PacketStream::process); } } catch (std::exception& exc) { - LError("Cannot start stream: ", exc.what()) + LError("Cannot start stream: ", exc.what()); setState(this, PacketStreamState::Error); //, exc.what() throw exc; } @@ -407,8 +405,9 @@ void PacketStream::setup() void PacketStream::teardown() { - LTrace("Teardown") - std::lock_guard guard(_mutex); + LTrace("Teardown"); + std::lock_guard + guard(_mutex); // Detach the processor chain first PacketProcessor* lastProc = nullptr; @@ -429,11 +428,15 @@ void PacketStream::teardown() } -void PacketStream::attachSource(PacketStreamAdapter* source, bool freePointer, bool syncState) +void PacketStream::attachSource(PacketStreamAdapter* source, bool owned, bool syncState) { - // LTrace("Attach source: ", source) - attachSource(std::make_shared( - source, freePointer ? new ScopedRawPointer(source) : nullptr, 0, syncState)); + if (owned) { + // Wrap in shared_ptr that will delete when the reference is dropped + std::shared_ptr sp(source); + attachSource(std::make_shared(std::move(sp), 0, syncState)); + } else { + attachSource(std::make_shared(source, 0, syncState)); + } } @@ -449,19 +452,15 @@ void PacketStream::attachSource(PacketAdapterReference::Ptr ref) void PacketStream::attachSource(PacketSignal& source) { - // LTrace("Attach source signal: ", &source) assertCanModify(); - - // TODO: unique_ptr for exception safe pointer creation so we - // don't need to do state checks here as well as - // `attachSource(PacketStreamAdapter*)` - attachSource(new PacketStreamAdapter(source), true, false); + auto adapter = std::make_shared(source); + attachSource(std::make_shared(std::move(adapter), 0, false)); } bool PacketStream::detachSource(PacketStreamAdapter* source) { - // LTrace("Detach source adapter: ", source) + // LTrace("Detach source adapter: ", source); assertCanModify(); std::lock_guard guard(_mutex); @@ -478,7 +477,7 @@ bool PacketStream::detachSource(PacketStreamAdapter* source) bool PacketStream::detachSource(PacketSignal& source) { - // LTrace("Detach source signal: ", &source) + // LTrace("Detach source signal: ", &source); assertCanModify(); std::lock_guard guard(_mutex); @@ -492,30 +491,34 @@ bool PacketStream::detachSource(PacketSignal& source) } -void PacketStream::attach(PacketProcessor* proc, int order, bool freePointer) +void PacketStream::attach(PacketProcessor* proc, int order, bool owned) { - // LTrace("Attach processor: ", proc) - assert(order >= -1 && order <= 101); + if (order < -1 || order > 101) + throw std::invalid_argument("PacketStream: processor order must be between -1 and 101"); assertCanModify(); - std::lock_guard guard(_mutex); - _processors.push_back(std::make_shared(proc, - freePointer ? new ScopedRawPointer(proc) : nullptr, - order == -1 ? int(_processors.size()) : order)); + int effectiveOrder = order == -1 ? int(_processors.size()) : order; + std::lock_guard guard(_mutex); + if (owned) { + std::shared_ptr sp(static_cast(proc)); + _processors.push_back(std::make_shared(std::move(sp), effectiveOrder)); + } else { + _processors.push_back(std::make_shared(proc, effectiveOrder)); + } sort(_processors.begin(), _processors.end(), PacketAdapterReference::compareOrder); } bool PacketStream::detach(PacketProcessor* proc) { - // LTrace("Detach processor: ", proc) + // LTrace("Detach processor: ", proc); assertCanModify(); std::lock_guard guard(_mutex); for (auto it = _processors.begin(); it != _processors.end(); ++it) { if ((*it)->ptr == proc) { - LTrace("Detached processor: ", proc) + LTrace("Detached processor: ", proc); _processors.erase(it); return true; } @@ -542,14 +545,14 @@ void PacketStream::startSources() if (source->syncState) { auto startable = dynamic_cast(source->ptr); if (startable) { - LTrace("Start source: ", startable) + LTrace("Start source: ", startable); startable->start(); } else - assert(0 && "unknown synchronizable"); + throw std::runtime_error("PacketStream: unknown synchronizable source"); #if 0 auto runnable = dynamic_cast(source); if (runnable) { - LTrace("Starting runnable: ", source) + LTrace("Starting runnable: ", source); runnable->run(); } #endif @@ -565,14 +568,14 @@ void PacketStream::stopSources() if (source->syncState) { auto startable = dynamic_cast(source->ptr); if (startable) { - LTrace("Stop source: ", startable) + LTrace("Stop source: ", startable); startable->stop(); } else - assert(0 && "unknown synchronizable"); + throw std::runtime_error("PacketStream: unknown synchronizable source"); #if 0 auto runnable = dynamic_cast(source); if (runnable) { - LTrace("Stop runnable: ", source) + LTrace("Stop runnable: ", source); runnable->cancel(); } #endif @@ -583,7 +586,7 @@ void PacketStream::stopSources() void PacketStream::handleException(std::exception& exc) { - LError("Error: ", exc.what()) + LError("Error: ", exc.what()); // Set the stream Error state. No need for queueState // as we are currently inside the processor context. @@ -596,7 +599,7 @@ void PacketStream::handleException(std::exception& exc) //_syncError = true; if (_closeOnError) { - LTrace("Close on error") + LTrace("Close on error"); this->close(); } } @@ -607,8 +610,7 @@ void PacketStream::assertCanModify() if (stateEquals(PacketStreamState::Locked) || stateEquals(PacketStreamState::Stopping) || stateEquals(PacketStreamState::Active)) { - LError("Cannot modify an ", state(), " packet stream") - assert(0 && "cannot modify active packet stream"); + LError("Cannot modify an ", state(), " packet stream"); throw std::runtime_error("Cannot modify an active packet stream."); } } @@ -620,16 +622,17 @@ void PacketStream::synchronizeOutput(uv::Loop* loop) // Add a SyncPacketQueue as the final processor so output // packets will be synchronized when they hit the emit() method - attach(new SyncPacketQueue<>(loop), 101, true); + attach(std::make_shared>(loop), 101); } void PacketStream::onStateChange(PacketStreamState& state, const PacketStreamState& oldState) { - LTrace("On state change: ", oldState, " => ", state) + LTrace("On state change: ", oldState, " => ", state); // Queue state for passing to adapters - std::lock_guard guard(_mutex); + std::lock_guard + guard(_mutex); _states.push_back(state); } @@ -756,7 +759,7 @@ PacketSignal& PacketStreamAdapter::getEmitter() // bool waitForStateSync(PacketStream* stream, PacketStreamState::ID state) // { // int times = 0; -// LTrace(stream)("Wait for sync state: ", state) +// LTrace(stream)("Wait for sync state: ", state); // while (!stream->stateEquals(state) || stream->hasQueuedState(state)) { // STrace(stream) << "Wait for sync state: " << state << ": " << times // << endl; @@ -765,7 +768,7 @@ PacketSignal& PacketStreamAdapter::getEmitter() // assert(0 && "deadlock; calling inside stream scope?"); // 5 secs // } // } -// LTrace(stream), "Wait for sync state: "(state, ": OK") +// LTrace(stream), "Wait for sync state: "(state, ": OK"); // return true; // } diff --git a/src/base/src/platform.cpp b/src/base/src/platform.cpp index 05c3c7d2a..93d2a4d42 100644 --- a/src/base/src/platform.cpp +++ b/src/base/src/platform.cpp @@ -14,14 +14,17 @@ #include "uv.h" -#include -#include +#include +#include +#include +#include + +#include #ifdef SCY_WIN +#include #include #include -#else -#include #endif @@ -67,7 +70,7 @@ uint64_t getTotalMemory() int numCpuCores() { - uv_cpu_info_t *info; + uv_cpu_info_t* info; int cpu_count; uv_cpu_info(&info, &cpu_count); uv_free_cpu_info(info, cpu_count); @@ -77,11 +80,7 @@ int numCpuCores() void sleep(int ms) { -#ifdef SCY_WIN - Sleep(ms); -#else - usleep(ms * 1000); -#endif + std::this_thread::sleep_for(std::chrono::milliseconds(ms)); } @@ -112,9 +111,8 @@ std::string getEnv(const std::string& name, const std::string& defaultValue) bool getEnvBool(const std::string& name) { const char* value = getenv(name.c_str()); - return value && ( - strcmp(value, "1") == 0 || - strcmp(value, "true") == 0); + return value && (strcmp(value, "1") == 0 || + strcmp(value, "true") == 0); } @@ -124,52 +122,23 @@ bool getEnvBool(const std::string& name) #ifdef SCY_WIN -enum WindowsMajorVersions -{ - kWindows2000 = 5, - kWindowsVista = 6, -}; - - -bool getOsVersion(int* major, int* minor, int* build) -{ - OSVERSIONINFO info = {0}; - info.dwOSVersionInfoSize = sizeof(info); - if (GetVersionEx(&info)) { - if (major) - *major = info.dwMajorVersion; - if (minor) - *minor = info.dwMinorVersion; - if (build) - *build = info.dwBuildNumber; - return true; - } - return false; -} - bool isWindowsVistaOrLater() { - int major; - return (getOsVersion(&major, nullptr, nullptr) && major >= kWindowsVista); + return ::IsWindowsVistaOrGreater(); } bool isWindowsXpOrLater() { - int major, minor; - return (getOsVersion(&major, &minor, nullptr) && - (major >= kWindowsVista || (major == kWindows2000 && minor >= 1))); + return ::IsWindowsXPOrGreater(); } -#define STACK_ARRAY(TYPE, LEN) static_cast(::alloca((LEN) * sizeof(TYPE))) - - std::wstring toUtf16(const char* utf8, size_t len) { - auto len16 = ::MultiByteToWideChar(CP_UTF8, 0, utf8, int(len), NULL, 0); - wchar_t* ws = STACK_ARRAY(wchar_t, len16); - ::MultiByteToWideChar(CP_UTF8, 0, utf8, int(len), ws, len16); - return std::wstring(ws, len16); + auto len16 = ::MultiByteToWideChar(CP_UTF8, 0, utf8, static_cast(len), nullptr, 0); + std::vector ws(len16); + ::MultiByteToWideChar(CP_UTF8, 0, utf8, static_cast(len), ws.data(), len16); + return std::wstring(ws.data(), len16); } std::wstring toUtf16(const std::string& str) @@ -179,10 +148,10 @@ std::wstring toUtf16(const std::string& str) std::string toUtf8(const wchar_t* wide, size_t len) { - auto len8 = ::WideCharToMultiByte(CP_UTF8, 0, wide, int(len), NULL, 0, NULL, NULL); - char* ns = STACK_ARRAY(char, len8); - ::WideCharToMultiByte(CP_UTF8, 0, wide, int(len), ns, len8, NULL, NULL); - return std::string(ns, len8); + auto len8 = ::WideCharToMultiByte(CP_UTF8, 0, wide, static_cast(len), nullptr, 0, nullptr, nullptr); + std::vector ns(len8); + ::WideCharToMultiByte(CP_UTF8, 0, wide, static_cast(len), ns.data(), len8, nullptr, nullptr); + return std::string(ns.data(), len8); } std::string toUtf8(const std::wstring& wstr) diff --git a/src/base/src/process.cpp b/src/base/src/process.cpp index 0ed898a21..07e1afc05 100644 --- a/src/base/src/process.cpp +++ b/src/base/src/process.cpp @@ -10,7 +10,6 @@ #include "scy/process.h" -#include "scy/filesystem.h" #include @@ -21,6 +20,7 @@ Process::Process(uv::Loop* loop) : _handle(loop) , _stdin(loop) , _stdout(loop) + , _stderr(loop) { init(); } @@ -31,6 +31,7 @@ Process::Process(std::initializer_list args, uv::Loop* loop) , _handle(loop) , _stdin(loop) , _stdout(loop) + , _stderr(loop) { init(); } @@ -55,71 +56,87 @@ void Process::init() auto self = reinterpret_cast(req->data); if (self->onexit) self->onexit(exitStatus); - // We could call close() here to free the uv_process_t content + + // Close the process handle to free resources. + // After exit the handle is no longer active but must + // still be closed to release the uv_process_t. + self->_handle.close(); }; _stdin.init(); _stdout.init(); - _stdout.Read += [this](/*Stream&, */const char* data, const int& len) { + _stderr.init(); + + _stdout.Read += [this](const char* data, const int& len) { if (onstdout) onstdout(std::string(data, len)); }; + _stderr.Read += [this](const char* data, const int& len) { + if (onstderr) + onstderr(std::string(data, len)); + }; + options.stdio = _stdio; options.stdio[0].flags = uv_stdio_flags(UV_CREATE_PIPE | UV_READABLE_PIPE); options.stdio[0].data.stream = _stdin.get(); - //options.stdio[0].flags = uv_stdio_flags(UV_IGNORE); options.stdio[1].flags = uv_stdio_flags(UV_CREATE_PIPE | UV_WRITABLE_PIPE); options.stdio[1].data.stream = _stdout.get(); - options.stdio_count = 2; + options.stdio[2].flags = uv_stdio_flags(UV_CREATE_PIPE | UV_WRITABLE_PIPE); + options.stdio[2].data.stream = _stderr.get(); + options.stdio_count = 3; - // _handle.init(); _handle.get()->data = this; } void Process::spawn() { - // Sanity checks - //if (options.file == nullptr) - // throw std::runtime_error("Cannot spawn process: File path must be set."); - if (args.size() > 10) - throw std::runtime_error("Cannot spawn process: Maximum of 10 command line arguments are supported."); - - // Override c style args if STL containers have items. + // Build c style args from STL containers. _cargs.clear(); if (!args.empty()) { - //assert(!!options.args && "setting both args and options.args"); for (auto& arg : args) _cargs.push_back(&arg[0]); _cargs.push_back(nullptr); } if (!cwd.empty()) { - options.cwd = &cwd[0]; + options.cwd = cwd.c_str(); } if (!file.empty()) { - options.file = &file[0]; + options.file = file.c_str(); if (_cargs.empty()) { _cargs.push_back(&file[0]); _cargs.push_back(nullptr); } - } - else if (!_cargs.empty()) { + } else if (!_cargs.empty()) { options.file = _cargs[0]; } - assert(!_cargs.empty() && "args must not be empty"); + if (_cargs.empty()) + throw std::runtime_error("Cannot spawn process: No file or args specified."); + options.args = &_cargs[0]; + // Build c style env if specified. + _cenv.clear(); + if (!env.empty()) { + for (auto& e : env) + _cenv.push_back(&e[0]); + _cenv.push_back(nullptr); + options.env = &_cenv[0]; + } + // Spawn the process _handle.init(&uv_spawn, &options); _handle.throwLastError("Cannot spawn process"); - // Start reading on the stdout pipe + // Start reading on the stdout and stderr pipes if (!_stdout.readStart()) _handle.setAndThrowError(_stdout.error().err, "Cannot read stdout pipe"); + if (!_stderr.readStart()) + _handle.setAndThrowError(_stderr.error().err, "Cannot read stderr pipe"); } @@ -135,19 +152,28 @@ Pipe& Process::out() } +Pipe& Process::err() +{ + return _stderr; +} + + bool Process::kill(int signum) { - if (!_handle.initialized()) + if (!_handle.initialized() || _handle.closing() || _handle.closed()) return false; - assert(pid() > 0); - return uv_kill(pid(), signum) == 0; + int p = uv_process_get_pid(_handle.get()); + if (p <= 0) + return false; + return uv_process_kill(_handle.get(), signum) == 0; } int Process::pid() const { - assert(_handle.initialized()); - return _handle.get()->pid; + if (!_handle.initialized()) + return 0; + return uv_process_get_pid(_handle.get()); } diff --git a/src/base/src/random.cpp b/src/base/src/random.cpp index 10c8baf71..5c9c57f18 100644 --- a/src/base/src/random.cpp +++ b/src/base/src/random.cpp @@ -15,14 +15,13 @@ #include "scy/random.h" #include "scy/error.h" -#include #include #include #if defined(WIN32) -#include #include +#include #if defined(_WIN32_WCE) #include #endif @@ -130,21 +129,19 @@ namespace scy { Random::Random(int stateSize) { - assert(BREAK_0 <= stateSize && stateSize <= BREAK_4); + if (stateSize < BREAK_0 || stateSize > BREAK_4) + throw std::invalid_argument("Random: state size out of range"); - _buffer = new char[stateSize]; + _buffer = std::make_unique(stateSize); #if defined(_WIN32_WCE) - initState((uint32_t)wceex_time(nullptr), _buffer, stateSize); + initState(static_cast(wceex_time(nullptr)), _buffer.get(), stateSize); #else - initState((uint32_t)std::time(nullptr), _buffer, stateSize); + initState(static_cast(std::time(nullptr)), _buffer.get(), stateSize); #endif } -Random::~Random() -{ - delete[] _buffer; -} +Random::~Random() = default; /* @@ -218,7 +215,7 @@ void Random::seed() else len = _randDeg * sizeof _state[0]; - getSeed((char*)_state, len); + getSeed(reinterpret_cast(_state), len); } @@ -229,7 +226,7 @@ void Random::getSeed(char* seed, unsigned length) #ifdef SCY_WIN HCRYPTPROV hProvider = 0; CryptAcquireContext(&hProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); - CryptGenRandom(hProvider, (DWORD)length, (BYTE*)seed); + CryptGenRandom(hProvider, static_cast(length), reinterpret_cast(seed)); CryptReleaseContext(hProvider, 0); n = static_cast(length); #else @@ -271,10 +268,10 @@ void Random::getSeed(char* seed, unsigned length) */ void Random::initState(uint32_t s, char* argState, std::int32_t n) { - uint32_t* intArgState = (uint32_t*)argState; + auto intArgState = reinterpret_cast(argState); if (n < BREAK_0) { - assert(0 && "not enough state"); + throw std::logic_error("Random: not enough state"); return; } if (n < BREAK_1) { @@ -304,7 +301,7 @@ void Random::initState(uint32_t s, char* argState, std::int32_t n) if (_randType == TYPE_0) intArgState[0] = _randType; else - intArgState[0] = MAX_TYPES * (int)(_rptr - _state) + _randType; + intArgState[0] = MAX_TYPES * static_cast(_rptr - _state) + _randType; } diff --git a/src/base/src/runner.cpp b/src/base/src/runner.cpp index e3000a760..236f3fa7e 100644 --- a/src/base/src/runner.cpp +++ b/src/base/src/runner.cpp @@ -11,14 +11,16 @@ #include "scy/interface.h" #include "scy/logger.h" +#include #include +#include namespace scy { -Runner::Runner() : - _context(std::make_shared()) +Runner::Runner() + : _context(std::make_shared()) { } @@ -32,7 +34,8 @@ Runner::~Runner() void Runner::setRepeating(bool flag) { - assert(!_context->running); + if (_context->running) + throw std::logic_error("Runner already running"); _context->repeating = flag; } @@ -69,15 +72,18 @@ std::thread::id Runner::tid() const bool Runner::waitForExit(int timeout) { - assert(Thread::currentID() != tid()); - int times = 0; - int interval = 10; + if (Thread::currentID() == tid()) + throw std::logic_error("Runner: cannot join from own thread"); + using namespace std::chrono; + auto start = steady_clock::now(); while (!cancelled() || running()) { - scy::sleep(interval); - times++; - if (timeout && ((times * interval) > timeout)) { - assert(0 && "deadlock; calling inside thread scope?"); - return false; + std::this_thread::sleep_for(milliseconds(10)); + if (timeout > 0) { + auto elapsed = duration_cast(steady_clock::now() - start).count(); + if (elapsed > timeout) { + throw std::logic_error("Runner: join timed out, possible deadlock"); + return false; + } } } return true; diff --git a/src/base/src/stateful.cpp b/src/base/src/stateful.cpp index 3b6647b09..2d8ebcaec 100644 --- a/src/base/src/stateful.cpp +++ b/src/base/src/stateful.cpp @@ -20,7 +20,7 @@ namespace scy { State::State(State::ID id) //, const std::string& message : _id(id) - // , _message(message) +// , _message(message) { } diff --git a/src/base/src/stream.cpp b/src/base/src/stream.cpp deleted file mode 100644 index f27b95474..000000000 --- a/src/base/src/stream.cpp +++ /dev/null @@ -1,221 +0,0 @@ -// /// -// // -// // LibSourcey -// // Copyright (c) 2005, Sourcey -// // -// // SPDX-License-Identifier: LGPL-2.1+ -// // -// /// @addtogroup base -// /// @{ -// -// -// #include "scy/stream.h" -// #include "scy/logger.h" -// -// -// using std::endl; -// -// -// namespace scy { -// -// -// Stream::Stream(uv::Loop* loop, void* stream) -// : uv::Handle(loop, stream) -// , _buffer(65536) -// , _started(false) -// { -// } -// -// -// Stream::~Stream() -// { -// close(); // must close underlying stream -// } -// -// -// void Stream::close() -// { -// // LTrace("Close: ", ptr()) -// -// if (_started) -// readStop(); -// uv::Handle::close(); -// } -// -// -// bool Stream::shutdown() -// { -// assertThread(); -// -// // LTrace("Send shutdown") -// if (!active()) { -// LWarn("Cannot shutdown a closed stream") -// return false; -// } -// -// // XXX: Sending shutdown causes an eof error to be -// // returned via handleRead() which sets the stream -// // to error state. This is not really an error, -// // perhaps it should be handled differently? -// int r = uv_shutdown(new uv_shutdown_t, ptr(), [](uv_shutdown_t* req, int) { -// delete req; -// }); -// -// return r == 0; -// } -// -// -// bool Stream::write(const char* data, size_t len) -// { -// assertThread(); -// assert(_started); -// assert(initialized()); -// assert(active()); -// assert(!closed()); -// -// // if (closed()) -// // throw std::runtime_error("IO error: Cannot write to closed stream"); -// if (!active()) -// return false; -// -// int r; -// uv_write_t* req = new uv_write_t; -// uv_buf_t buf = uv_buf_init((char*)data, (int)len); -// uv_stream_t* stream = this->ptr(); -// bool isIPC = stream->type == UV_NAMED_PIPE && -// reinterpret_cast(stream)->ipc; -// -// if (!isIPC) { -// r = uv_write(req, stream, &buf, 1, [](uv_write_t* req, int) { -// delete req; -// }); -// } else { -// r = uv_write2(req, stream, &buf, 1, nullptr, [](uv_write_t* req, int) { -// delete req; -// }); -// } -// -// if (r) { -// delete req; -// assert(0); -// // setAndThrowError(r, "Stream write error"); -// } -// return r == 0; -// } -// -// -// Buffer& Stream::buffer() -// { -// assertThread(); -// return _buffer; -// } -// -// -// bool Stream::closed() const -// { -// return uv::Handle::closed(); -// } -// -// -// bool Stream::readStart() -// { -// // LTrace("Read start: ", ptr()) -// assert(initialized()); -// assert(!_started); -// _started = true; -// -// int r = uv_read_start(this->ptr(), Stream::allocReadBuffer, handleRead); -// if (r) -// setUVError("Stream read error", r); -// return r == 0; -// } -// -// -// bool Stream::readStop() -// { -// // LTrace("Read stop: ", ptr()) -// assert(initialized()); -// assert(!closed()); -// assert(_started); -// _started = false; -// -// int r = uv_read_stop(ptr()); -// if (r) -// setUVError("Stream read error", r); -// return r == 0; -// } -// -// -// void Stream::onRead(const char* data, size_t len) -// { -// // LTrace("On read: ", len) -// Read.emit(*this, data, (const int)len); -// } -// -// -// void Stream::handleReadCommon(uv_stream_t* handle, ssize_t nread, const uv_buf_t* buf, uv_handle_type pending) -// { -// // LTrace("Handle read: ", nread) -// auto self = reinterpret_cast(handle->data); -// assert(self->_started); -// assert(self->initialized()); -// assert(!self->closed()); -// -// // try { -// if (nread >= 0) { -// self->onRead(buf->base, nread); -// } -// else { -// // The stream was closed in error -// // The value of nread is the error number -// // ie. UV_ECONNRESET or UV_EOF etc ... -// self->setUVError("Stream error", (int)nread); -// } -// // } -// // catch (std::exception& exc) { -// // -// // // Swallow exceptions and set the stream error -// // // This keep errors in the event loop -// // LError("Exception: ", exc.what()) -// // self->setUVError(exc.what()); -// // return; -// // } -// } -// -// -// // -// /// UV callbacks -// // -// -// -// void Stream::handleRead(uv_stream_t* handle, ssize_t nread, const uv_buf_t* buf) -// { -// handleReadCommon(handle, nread, buf, UV_UNKNOWN_HANDLE); -// } -// -// -// void Stream::handleRead2(uv_pipe_t* handle, ssize_t nread, const uv_buf_t* buf, uv_handle_type pending) -// { -// handleReadCommon((uv_stream_t*)handle, nread, buf, pending); -// } -// -// -// void Stream::allocReadBuffer(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) -// { -// auto self = reinterpret_cast(handle->data); -// -// // Reserve the recommended buffer size -// // if (suggested_size > self->_buffer.capacity()) -// // self->_buffer.capacity(suggested_size); -// assert(self->_buffer.size() >= suggested_size); -// -// // Reset the buffer position on each read -// buf->base = self->_buffer.data(); -// buf->len = self->_buffer.size(); -// } -// -// -// } // namespace scy -// -// -// /// @\} diff --git a/src/base/src/streammanager.cpp b/src/base/src/streammanager.cpp new file mode 100644 index 000000000..8ce95a5e7 --- /dev/null +++ b/src/base/src/streammanager.cpp @@ -0,0 +1,146 @@ +/// +// +// LibSourcey +// Copyright (c) 2005, Sourcey +// +// SPDX-License-Identifier: LGPL-2.1+ +// +/// @addtogroup base +/// @{ + + +#include "scy/streammanager.h" +#include "scy/logger.h" + + +using namespace std; + + +namespace scy { + + +StreamManager::StreamManager() +{ +} + + +StreamManager::~StreamManager() +{ + closeAll(); +} + + +void StreamManager::closeAll() +{ + std::unique_lock guard(_mutex); + + LDebug("Close all streams: ", _map.size()); + for (auto it = _map.begin(); it != _map.end();) { + it->second->StateChange -= slot(this, &StreamManager::onStreamStateChange); + it->second->close(); + it = _map.erase(it); // unique_ptr deletes the stream + } +} + + +bool StreamManager::addStream(PacketStream* stream, bool whiny) +{ + if (!stream) + throw std::invalid_argument("StreamManager: stream cannot be null"); + if (stream->name().empty()) + throw std::invalid_argument("StreamManager: stream name cannot be empty"); + return Manager::add(stream->name(), stream, whiny); +} + + +PacketStream* StreamManager::getStream(const std::string& name, bool whiny) +{ + return Manager::get(name, whiny); +} + + +bool StreamManager::closeStream(const std::string& name, bool whiny) +{ + if (name.empty()) + throw std::invalid_argument("StreamManager: stream name cannot be empty"); + + LDebug("Close stream: ", name); + PacketStream* stream = get(name, whiny); + if (stream) { + stream->close(); + return true; + } + return false; +} + + +PacketStream* StreamManager::getDefaultStream() +{ + std::shared_lock guard(_mutex); + + // Returns the first stream or nullptr. + if (!_map.empty()) { + return _map.begin()->second.get(); + } + + return nullptr; +} + + +void StreamManager::onAdd(const std::string&, PacketStream* stream) +{ + // Stream name can't be empty + if (stream->name().empty()) + throw std::invalid_argument("StreamManager: stream name cannot be empty"); + + // Receive callbacks after all other listeners + // so we can delete the stream when it closes. + LDebug("stream added: ", stream->name()); + stream->StateChange += slot(this, &StreamManager::onStreamStateChange, -1); +} + + +void StreamManager::onRemove(const std::string&, PacketStream* stream) +{ + LDebug("stream removed: ", stream->name()); + stream->StateChange -= slot(this, &StreamManager::onStreamStateChange); +} + + +void StreamManager::onStreamStateChange(void* sender, PacketStreamState& state, + const PacketStreamState&) +{ + LDebug("Stream state change: ", state); + + // Cantch stream closed state and free it if necessary + if (state.equals(PacketStreamState::Closed)) { + auto stream = reinterpret_cast(sender); + stream->StateChange -= slot(this, &StreamManager::onStreamStateChange); + LDebug("On stream close: freeing: ", stream->name()); + bool success = Manager::free(stream->name()); + if (!success) { + LWarn("Cannot remove stream: ", stream->name()); + } + } +} + + +const StreamManager::Map& StreamManager::streams() const +{ + std::shared_lock guard(_mutex); + return _map; +} + + +void StreamManager::print(std::ostream& os) const +{ + std::shared_lock guard(_mutex); + os << "StreamManager["; + for (const auto& [name, stream] : _map) { + os << "\n\t" << stream.get() << ": " << name; + } + os << "\n]"; +} + + +} // namespace scy diff --git a/src/base/src/synchronizer.cpp b/src/base/src/synchronizer.cpp index cdaa789a0..e41ef7ca9 100644 --- a/src/base/src/synchronizer.cpp +++ b/src/base/src/synchronizer.cpp @@ -42,8 +42,9 @@ void Synchronizer::start(std::function target) void Synchronizer::post() { - assert(_handle.initialized()); - uv_async_send(_handle.get()); + if (!_handle.initialized()) return; + // NOTE: Cannot call `_handle.get()` as we're on different thread + uv_async_send(_handle.context()->ptr); } diff --git a/src/base/src/task.cpp b/src/base/src/task.cpp index 19473fa30..1a14af890 100644 --- a/src/base/src/task.cpp +++ b/src/base/src/task.cpp @@ -11,13 +11,11 @@ #include "scy/task.h" #include "scy/logger.h" -#include "scy/memory.h" #include "scy/platform.h" -#include "scy/singleton.h" #include "scy/util.h" -#include #include +#include using std::endl; @@ -41,7 +39,6 @@ Task::Task(bool repeat) Task::~Task() { - // assert(destroyed()); } @@ -85,8 +82,7 @@ TaskRunner::TaskRunner(std::shared_ptr runner) TaskRunner::~TaskRunner() { - Shutdown.emit(/*this*/); - // Idler::stop(); + Shutdown.emit(); if (_runner) _runner->cancel(); clear(); @@ -96,68 +92,51 @@ TaskRunner::~TaskRunner() bool TaskRunner::start(Task* task) { add(task); - - // if (task->_cancelled) { - // task->_cancelled = false; - // task->start(); - LTrace("Start task: ", task) + LTrace("Start task: ", task); onStart(task); - //_wakeUp.set(); return true; - //} - // return false; } bool TaskRunner::cancel(Task* task) { - // if (!task->_cancelled) { - // task->_cancelled = true; - // task->cancel(); - // LTrace("Cancelled task: ", task) - // onCancel(task); - //_wakeUp.set(); - // return true; - //} - if (!task->cancelled()) { task->cancel(); - LTrace("Cancel task: ", task) + LTrace("Cancel task: ", task); onCancel(task); - //_wakeUp.set(); return true; } - return false; } bool TaskRunner::destroy(Task* task) { - LTrace("Abort task: ", task) + LTrace("Abort task: ", task); // If the task exists then set the destroyed flag. + // It will be cleaned up during the next run() iteration. if (exists(task)) { - LTrace("Abort managed task: ", task) + LTrace("Abort managed task: ", task); task->_destroyed = true; } - // Otherwise destroy the pointer. + // Otherwise destroy the pointer directly (unmanaged task). else { - LTrace("Delete unmanaged task: ", task) + LTrace("Delete unmanaged task: ", task); delete task; } - return true; // hmmm + return true; } bool TaskRunner::add(Task* task) { - LTrace("Add task: ", task) + LTrace("Add task: ", task); if (!exists(task)) { std::lock_guard guard(_mutex); - _tasks.push_back(task); + _tasks.push_back(std::unique_ptr(task)); onAdd(task); return true; } @@ -167,12 +146,12 @@ bool TaskRunner::add(Task* task) bool TaskRunner::remove(Task* task) { - LTrace("Remove task: ", task) + LTrace("Remove task: ", task); std::lock_guard guard(_mutex); for (auto it = _tasks.begin(); it != _tasks.end(); ++it) { - if (*it == task) { - _tasks.erase(it); + if (it->get() == task) { + _tasks.erase(it); // unique_ptr destructs the task onRemove(task); return true; } @@ -184,8 +163,8 @@ bool TaskRunner::remove(Task* task) bool TaskRunner::exists(Task* task) const { std::lock_guard guard(_mutex); - for (auto it = _tasks.begin(); it != _tasks.end(); ++it) { - if (*it == task) + for (const auto& t : _tasks) { + if (t.get() == task) return true; } return false; @@ -195,9 +174,9 @@ bool TaskRunner::exists(Task* task) const Task* TaskRunner::get(uint32_t id) const { std::lock_guard guard(_mutex); - for (auto it = _tasks.begin(); it != _tasks.end(); ++it) { - if ((*it)->id() == id) - return *it; + for (const auto& t : _tasks) { + if (t->id() == id) + return t.get(); } return nullptr; } @@ -206,9 +185,9 @@ Task* TaskRunner::get(uint32_t id) const Task* TaskRunner::next() const { std::lock_guard guard(_mutex); - for (auto it = _tasks.begin(); it != _tasks.end(); ++it) { - if (!(*it)->cancelled()) - return *it; + for (const auto& t : _tasks) { + if (!t->cancelled()) + return t.get(); } return nullptr; } @@ -217,20 +196,17 @@ Task* TaskRunner::next() const void TaskRunner::clear() { std::lock_guard guard(_mutex); - for (auto it = _tasks.begin(); it != _tasks.end(); ++it) { - LTrace("Clear: Destroying task: ", *it) - delete *it; - } - _tasks.clear(); + _tasks.clear(); // unique_ptrs auto-delete all tasks } void TaskRunner::setRunner(std::shared_ptr runner) { - LTrace("Set async: ", runner.get()) + LTrace("Set async: ", runner.get()); std::lock_guard guard(_mutex); - assert(!_runner); + if (_runner) + throw std::logic_error("TaskRunner already has a runner"); _runner = runner; _runner->setRepeating(true); _runner->start(std::bind(&TaskRunner::run, this)); @@ -240,13 +216,12 @@ void TaskRunner::setRunner(std::shared_ptr runner) void TaskRunner::run() { Task* task = next(); - // LTrace("Next task: ", task) // Run the task if (task) { // Check once more that the task has not been cancelled if (!task->cancelled()) { - LTrace("Run task: ", task) + LTrace("Run task: ", task); task->run(); onRun(task); @@ -254,33 +229,29 @@ void TaskRunner::run() // Cancel the task if not repeating if (!task->repeating()) task->cancel(); - - // if (task->cancelled()) - // task->_destroyed = true; } - // Advance the task queue + // Advance the task queue (rotate front to back) { std::lock_guard guard(_mutex); - Task* t = _tasks.front(); + auto t = std::move(_tasks.front()); _tasks.pop_front(); - _tasks.push_back(t); + _tasks.push_back(std::move(t)); } - // Destroy the task if required + // Destroy the task if required. + // remove() will erase the unique_ptr, which deletes the task. if (task->destroyed()) { - LTrace("Destroy task: ", task) + LTrace("Destroy task: ", task); remove(task); - delete task; } } // Dispatch the Idle signal - // LTrace("idle: "<< Idle.nslots(), ) - Idle.emit(/*this*/); + Idle.emit(); // Prevent 100% CPU - scy::sleep(1); + std::this_thread::yield(); } @@ -311,8 +282,8 @@ void TaskRunner::onRun(Task*) TaskRunner& TaskRunner::getDefault() { - static Singleton sh; - return *sh.get(); + static TaskRunner instance; + return instance; } diff --git a/src/base/src/test.cpp b/src/base/src/test.cpp index 76dd19aa6..5d08e2078 100644 --- a/src/base/src/test.cpp +++ b/src/base/src/test.cpp @@ -11,17 +11,16 @@ #include "scy/test.h" #include "scy/logger.h" -#include "scy/memory.h" #include "scy/singleton.h" #include "scy/time.h" #include "scy/util.h" -#include +#include #include -using std::cout; using std::cerr; +using std::cout; using std::endl; @@ -37,7 +36,7 @@ void init() // Set the logger to only log warning level and above if no debug // channel has been set yet. if (!Logger::instance().get("debug", false)) - Logger::instance().add(new ConsoleChannel("debug", Level::Warn)); + Logger::instance().add(std::make_unique("debug", Level::Warn)); // Initialize the default test runner. TestRunner::getDefault(); @@ -51,9 +50,6 @@ int finalize() bool passed = TestRunner::getDefault().passed(); singleton.destroy(); - // Finalize the garbage collector to ensure memory if freed before exiting. - GarbageCollector::instance().finalize(); - return passed ? 0 : 1; } diff --git a/src/base/src/thread.cpp b/src/base/src/thread.cpp index cf174c422..c438cd3cd 100644 --- a/src/base/src/thread.cpp +++ b/src/base/src/thread.cpp @@ -11,8 +11,6 @@ #include "scy/thread.h" #include "scy/logger.h" -#include "scy/platform.h" -#include #include @@ -25,8 +23,8 @@ namespace scy { const std::thread::id Thread::mainID = std::this_thread::get_id(); -Thread::Thread() : - // Call the default constructor explicitly to +Thread::Thread() + : // Call the default constructor explicitly to // underline the fact that it does get called _thread() { @@ -49,10 +47,12 @@ void Thread::start(std::function target) void Thread::join() { - assert(this->tid() != Thread::currentID()); + if (this->tid() == Thread::currentID()) + throw std::logic_error("Thread: cannot join from own thread"); // assert(this->cancelled()); // should probably be cancelled _thread.join(); - assert(!this->running()); + if (this->running()) + LWarn("Thread still running after join"); } diff --git a/src/base/src/time.cpp b/src/base/src/time.cpp index 7967af0d8..60be6c71c 100644 --- a/src/base/src/time.cpp +++ b/src/base/src/time.cpp @@ -10,13 +10,11 @@ #include "scy/time.h" -#include "scy/util.h" #include "uv.h" +#include #include -#include -//#include #include #include #include @@ -28,17 +26,15 @@ namespace time { std::time_t now() { -#if 0 // no need for chrono here yet - std::chrono::time_point system_now = std::chrono::system_clock::now(); - return std::chrono::system_clock::to_time_t(system_now); -#endif - return std::time(0); + return std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); } double clockSecs() { - return clock() / CLOCKS_PER_SEC; + using namespace std::chrono; + auto t = steady_clock::now().time_since_epoch(); + return duration_cast>(t).count(); } @@ -56,12 +52,11 @@ std::tm toLocal(const std::time_t& time) std::tm toUTC(const std::time_t& time) { - // TODO: double check thread safety of native methods std::tm tm_snapshot; #if defined(WIN32) gmtime_s(&tm_snapshot, &time); // thread-safe? #else - gmtime_r(&time, &tm_snapshot); // POSIX + gmtime_r(&time, &tm_snapshot); // POSIX #endif return tm_snapshot; } @@ -69,24 +64,9 @@ std::tm toUTC(const std::time_t& time) std::string print(const std::tm& dt, const char* fmt) { -#if defined(WIN32) - // BOGUS hack done for VS2012: C++11 non-conformant since - // it SHOULD take a `const struct tm*` - // ref. C++11 standard: ISO/IEC 14882:2011, � 27.7.1 std::ostringstream oss; - oss << std::put_time(const_cast(&dt), fmt); + oss << std::put_time(&dt, fmt); return oss.str(); - -#else // LINUX - const size_t size = 1024; - char buffer[size]; - auto success = std::strftime(buffer, size, fmt, &dt); - - if (0 == success) - return fmt; - - return buffer; -#endif } @@ -120,32 +100,6 @@ uint64_t hrtime() } -#if 0 -std::time_t nowUTC() -{ - std::time_t local = std::time(NULL); - return std::mktime(std::gmtime(&local)); // UTC time -} - -uint64_t ticks() -{ -#ifdef SCY_WIN - return ::GetTickCount(); -#else - struct timespec tval; - clock_gettime(CLOCK_MONOTONIC, &tval); - return tval.tv_sec * 1000 + tval.tv_nsec / 1000000; -#endif -} - - -uint64_t getTimeMS() -{ - return uv_hrtime() / 1000000; -} -#endif - - } // namespace time } // namespace scy diff --git a/src/util/src/timeout.cpp b/src/base/src/timeout.cpp similarity index 60% rename from src/util/src/timeout.cpp rename to src/base/src/timeout.cpp index 907395028..f6f6ce2c6 100644 --- a/src/util/src/timeout.cpp +++ b/src/base/src/timeout.cpp @@ -10,7 +10,7 @@ // -#include "scy/util/timeout.h" +#include "scy/timeout.h" #include "scy/util.h" @@ -23,8 +23,9 @@ namespace scy { Timeout::Timeout(long delay, bool autoStart) - : _startAt(0) + : _startAt() , _delay(delay) + , _running(false) { if (autoStart) start(); @@ -34,6 +35,7 @@ Timeout::Timeout(long delay, bool autoStart) Timeout::Timeout(const Timeout& src) : _startAt(src._startAt) , _delay(src._delay) + , _running(src._running) { } @@ -42,6 +44,7 @@ Timeout& Timeout::operator=(const Timeout& src) { _startAt = src._startAt; _delay = src._delay; + _running = src._running; return *this; } @@ -53,42 +56,45 @@ Timeout::~Timeout() bool Timeout::running() const { - return _startAt != 0; + return _running; } void Timeout::start() { - //_startAt = time::ticks(); - _startAt = clock(); + _startAt = std::chrono::steady_clock::now(); + _running = true; } void Timeout::stop() { - _startAt = 0; + _running = false; } void Timeout::reset() { - //_startAt = time::ticks(); - _startAt = clock(); + _startAt = std::chrono::steady_clock::now(); + _running = true; } long Timeout::remaining() const { - // time_t current = time::ticks(); - clock_t current = clock(); - long remaining = static_cast(_delay - (current - _startAt)); - return remaining > 0 ? remaining : 0; + if (!_running) + return _delay; + + auto now = std::chrono::steady_clock::now(); + auto elapsed = std::chrono::duration_cast(now - _startAt).count(); + long rem = _delay - static_cast(elapsed); + return rem > 0 ? rem : 0; } bool Timeout::expired() const { - if (_delay == 0) // _startAt == 0 || + if (!_running) return false; return remaining() == 0; @@ -101,14 +107,14 @@ bool Timeout::expired() const TimedToken::TimedToken(long duration) - : Timeout(duration) + : Timeout(duration, true) , _id(util::randomString(32)) { } TimedToken::TimedToken(const std::string& id, long duration) - : Timeout(duration) + : Timeout(duration, true) , _id(id) { } @@ -117,4 +123,4 @@ TimedToken::TimedToken(const std::string& id, long duration) } // namespace scy -/// @\} \ No newline at end of file +/// @\} diff --git a/src/base/src/timer.cpp b/src/base/src/timer.cpp index fb16eaee1..90e5063e2 100644 --- a/src/base/src/timer.cpp +++ b/src/base/src/timer.cpp @@ -10,7 +10,6 @@ #include "scy/timer.h" -#include "assert.h" #include "scy/logger.h" #include "scy/platform.h" @@ -27,7 +26,7 @@ Timer::Timer(uv::Loop* loop) , _interval(0) , _count(0) { - // LTrace("Create") + // LTrace("Create"); init(); } @@ -38,7 +37,7 @@ Timer::Timer(std::int64_t timeout, uv::Loop* loop, std::function func) , _interval(0) , _count(0) { - // LTrace("Create") + // LTrace("Create"); init(); if (func) start(func); @@ -51,7 +50,7 @@ Timer::Timer(std::int64_t timeout, std::int64_t interval, uv::Loop* loop, std::f , _interval(interval) , _count(0) { - // LTrace("Create") + // LTrace("Create"); init(); if (func) start(func); @@ -60,20 +59,20 @@ Timer::Timer(std::int64_t timeout, std::int64_t interval, uv::Loop* loop, std::f Timer::~Timer() { - // LTrace("Destroy") + // LTrace("Destroy"); } void Timer::init() { - // LTrace("Init") + // LTrace("Init"); // _count = 0; // _timeout = 0; // _interval = 0; - assert(!_handle.initialized()); - assert(_handle.get()); + if (!_handle.get()) + throw std::logic_error("Timer handle not allocated"); _handle.get()->data = this; _handle.init(&uv_timer_init); _handle.throwLastError("Cannot initialize timer"); @@ -96,28 +95,28 @@ void Timer::start(std::function func) void Timer::start() { - // LTrace("Starting: ",, timeout, ": ", interval) - assert(!active()); - assert(_handle.get()); - assert(_timeout > 0 || _interval > 0); + // LTrace("Starting: ",, timeout, ": ", interval); + if (active()) return; + if (!_handle.get()) + throw std::logic_error("Timer handle not allocated"); + if (_timeout <= 0 && _interval <= 0) + throw std::logic_error("Timer: no timeout or interval set"); // _timeout = timeout; // _interval = interval; _count = 0; - _handle.invoke(&uv_timer_start, _handle.get(), - [](uv_timer_t* req) { + _handle.invoke(&uv_timer_start, _handle.get(), [](uv_timer_t* req) { auto self = reinterpret_cast(req->data); self->_count++; - self->Timeout.emit(); - }, _timeout, _interval); + self->Timeout.emit(); }, _timeout, _interval); _handle.throwLastError("Cannot start timer"); } void Timer::stop() { - // LTrace("Stopping") + // LTrace("Stopping"); if (!active()) return; // do nothing @@ -125,7 +124,6 @@ void Timer::stop() _count = 0; _handle.invoke(&uv_timer_stop, _handle.get()); _handle.throwLastError("Cannot stop timer"); - assert(!active()); } @@ -140,9 +138,10 @@ void Timer::restart() void Timer::again() { - // LTrace("Again") + // LTrace("Again"); - assert(_handle.get()); + if (!_handle.get()) + throw std::logic_error("Timer handle not allocated"); _handle.invoke(&uv_timer_again, _handle.get()); _handle.throwLastError("Cannot run timer again"); @@ -153,14 +152,15 @@ void Timer::again() void Timer::setTimeout(std::int64_t timeout) { - assert(!active()); + if (active()) return; _timeout = timeout; } void Timer::setInterval(std::int64_t interval) { - assert(_handle.get()); + if (!_handle.get()) + throw std::logic_error("Timer handle not allocated"); _interval = interval; uv_timer_set_repeat(_handle.get(), interval); } @@ -180,7 +180,8 @@ std::int64_t Timer::timeout() const std::int64_t Timer::interval() const { - assert(_handle.get()); + if (!_handle.get()) + throw std::logic_error("Timer handle not allocated"); return std::min( uv_timer_get_repeat(_handle.get()), 0); } diff --git a/src/base/src/util.cpp b/src/base/src/util.cpp index 63631a522..833ff4cd3 100644 --- a/src/base/src/util.cpp +++ b/src/base/src/util.cpp @@ -16,11 +16,11 @@ #include #include -#include #include #include #include #include +#include using std::endl; @@ -33,7 +33,7 @@ namespace util { std::string string_vprintf(const char* fmt, va_list args) { size_t size = 500; - char* buf = (char*)malloc(size); + char* buf = static_cast(malloc(size)); // Grow the buffer size until the output is no longer truncated while (true) { va_list args_copy; @@ -53,7 +53,7 @@ std::string string_vprintf(const char* fmt, va_list args) return ret; } size *= 2; - buf = (char*)realloc(buf, size); + buf = static_cast(realloc(buf, size)); } } @@ -68,10 +68,12 @@ std::string format(const char* fmt, ...) } -bool isNumber(const std::string& str) +bool isNumber(std::string_view str) { + if (str.empty()) + return false; for (size_t i = 0; i < str.length(); i++) { - if (!::isdigit(str[i])) + if (!::isdigit(static_cast(str[i]))) return false; } return true; @@ -137,18 +139,18 @@ uint32_t randomNumber() void split(const std::string& s, const std::string& delim, std::vector& elems, int limit) { - bool final = false; std::string::size_type prev = 0, pos = 0; - while ((pos = s.find(delim, pos)) != std::string::npos) { - final = limit && static_cast(elems.size() + 1) == limit; - elems.push_back( - s.substr(prev, final ? (s.size() - prev) : (pos - prev))); - prev = ++pos; - if (final) + while ((pos = s.find(delim, prev)) != std::string::npos) { + if (limit > 0 && static_cast(elems.size()) == limit - 1) { + // Last allowed element: take everything from prev to end break; - } - if (prev != std::string::npos) + } elems.push_back(s.substr(prev, pos - prev)); + prev = pos + delim.size(); + } + // Remaining portion (or entire string if no delimiter found) + if (prev <= s.size()) + elems.push_back(s.substr(prev)); } @@ -181,43 +183,17 @@ void split(const std::string& s, char delim, std::vector& elems, std::vector split(const std::string& s, char delim, int limit) { std::vector elems; - split(s, (char)delim, elems, limit); + split(s, delim, elems, limit); return elems; } -bool endsWith(const std::string& str, const std::string& suffix) -{ - return std::equal(suffix.rbegin(), suffix.rend(), str.rbegin()); -} - - -#if 0 -double intToDouble(std::int64_t v) +bool endsWith(std::string_view str, std::string_view suffix) { - if (v+v > 0xFFEULL<<52) - return 0; - return ldexp((double)((v&((1LL<<52)-1)) + (1LL<<52)) * (v>>63|1), (int)(v>>52&0x7FF)-1075); -} - - -float intToFloat(std::int32_t v) -{ - if (v+v > 0xFF000000U) - return 0; - return ldexp((float)((v&0x7FFFFF) + (1<<23)) * (v>>31|1), (int)(v>>23&0xFF)-150); -} - - -std::int64_t doubleToInt(double d) -{ - int e; - if ( !d) return 0; - else if(d-d) return 0x7FF0000000000000LL + ((std::int64_t)(d<0)<<63) + (d!=d); - d = frexp(d, &e); - return (std::int64_t)(d<0)<<63 | (e+1022LL)<<52 | (std::int64_t)((fabs(d)-0.5)*(1LL<<53)); + if (suffix.size() > str.size()) + return false; + return str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0; } -#endif std::string dumpbin(const char* data, size_t len) @@ -329,9 +305,10 @@ bool matchNodes(const std::vector& params, std::streamsize copyStream(std::istream& istr, std::ostream& ostr, size_t bufferSize) { - assert(bufferSize > 0); + if (bufferSize <= 0) + throw std::invalid_argument("Buffer size must be positive"); - std::unique_ptr buffer(new char[bufferSize]); + auto buffer = std::make_unique(bufferSize); std::streamsize len = 0; istr.read(buffer.get(), bufferSize); std::streamsize n = istr.gcount(); @@ -365,9 +342,10 @@ std::streamsize copyStreamUnbuffered(std::istream& istr, std::ostream& ostr) std::streamsize copyToString(std::istream& istr, std::string& str, size_t bufferSize) { - assert(bufferSize > 0); + if (bufferSize <= 0) + throw std::invalid_argument("Buffer size must be positive"); - std::unique_ptr buffer(new char[bufferSize]); + auto buffer = std::make_unique(bufferSize); std::streamsize len = 0; istr.read(buffer.get(), bufferSize); std::streamsize n = istr.gcount(); diff --git a/src/base/tests/CMakeLists.txt b/src/base/tests/CMakeLists.txt index fce2653ff..2ec9b4f59 100644 --- a/src/base/tests/CMakeLists.txt +++ b/src/base/tests/CMakeLists.txt @@ -1 +1,2 @@ -define_libsourcey_test(basetests base) +scy_add_test(basetests DEPENDS base) +scy_add_test(utiltests DEPENDS base) diff --git a/src/base/tests/basetests.cpp b/src/base/tests/basetests.cpp index b0e83800a..04017ec67 100644 --- a/src/base/tests/basetests.cpp +++ b/src/base/tests/basetests.cpp @@ -1,7 +1,7 @@ #include "basetests.h" -using std::cout; using std::cerr; +using std::cout; using std::endl; using namespace scy; using namespace scy::test; @@ -9,42 +9,9 @@ using namespace scy::test; int main(int argc, char** argv) { - // Logger::instance().add(new ConsoleChannel("debug", Level::Trace)); + // Logger::instance().add(std::make_unique("debug", Level::Trace)); test::init(); - // ========================================================================= - // Garbage Collector - // - describe("garbage collector", []() { - GarbageCollector gc; - auto loop = uv::defaultLoop(); - auto loop1 = uv::createLoop(); - - // delete running idler on default loop - auto idler = new Idler(loop, []() {}); - idler->handle().ref(); - gc.deleteLater(idler, loop); - - // delete running idler on loop1 - auto idler1 = new Idler(loop1, []() {}); - idler1->handle().ref(); - gc.deleteLater(idler1, loop1); - - // run the default loop which will return - // once the idler is deleted - uv::runLoop(); - - // finalize deletion of all pointers - gc.finalize(); - - expect(loop->active_handles == 0); - expect(loop1->active_handles == 0); - - // free the created loop1 - uv::closeLoop(loop1); - }); - - // ========================================================================= // Signal Benchmarks // @@ -61,9 +28,9 @@ int main(int argc, char** argv) expect(value == i); std::cout << "signal class member benchmark: " - << ((benchdone - benchstart) * 1.0 / i) << "ns " - << "per emission (sz=" << sizeof(signal) << ")" - << std::endl; + << ((benchdone - benchstart) * 1.0 / i) << "ns " + << "per emission (sz=" << sizeof(signal) << ")" + << std::endl; }); describe("signal const class member benchmark", []() { @@ -79,8 +46,8 @@ int main(int argc, char** argv) expect(value == i); std::cout << "signal const class member benchmark: " - << ((benchdone - benchstart) * 1.0 / i) << "ns " - << "per emission (sz=" << sizeof(signal) << ")" << std::endl; + << ((benchdone - benchstart) * 1.0 / i) << "ns " + << "per emission (sz=" << sizeof(signal) << ")" << std::endl; }); describe("signal static member benchmark", []() { @@ -95,9 +62,9 @@ int main(int argc, char** argv) expect(value == i); std::cout << "signal static member benchmark: " - << ((benchdone - benchstart) * 1.0 / i) << "ns " - << "per emission (sz=" << sizeof(signal) << ")" - << std::endl; + << ((benchdone - benchstart) * 1.0 / i) << "ns " + << "per emission (sz=" << sizeof(signal) << ")" + << std::endl; }); describe("signal free function benchmark", []() { @@ -112,9 +79,9 @@ int main(int argc, char** argv) expect(value == i); std::cout << "signal free function benchmark: " - << ((benchdone - benchstart) * 1.0 / i) << "ns " - << "per emission (sz=" << sizeof(signal) << ")" - << std::endl; + << ((benchdone - benchstart) * 1.0 / i) << "ns " + << "per emission (sz=" << sizeof(signal) << ")" + << std::endl; }); @@ -122,7 +89,7 @@ int main(int argc, char** argv) // Buffer // describe("buffer", []() { - ByteOrder orders[2] = { ByteOrder::Host, ByteOrder::Network }; + ByteOrder orders[2] = {ByteOrder::Host, ByteOrder::Network}; for (size_t i = 0; i < 2; i++) { Buffer buffer(1024); BitReader reader(buffer, orders[i]); @@ -226,8 +193,7 @@ int main(int argc, char** argv) try { writer.seek(1200); expect(0 && "must throw"); - } - catch (std::out_of_range& exc) { + } catch (std::out_of_range& exc) { } }); @@ -249,7 +215,7 @@ int main(int argc, char** argv) std::string write_string("hello"); std::string write_string1("world"); - ByteOrder orders[2] = { ByteOrder::Host, ByteOrder::Network }; + ByteOrder orders[2] = {ByteOrder::Host, ByteOrder::Network}; for (size_t i = 0; i < 2; i++) { Buffer buffer; DynamicBitWriter writer(buffer, orders[i]); @@ -289,15 +255,13 @@ int main(int argc, char** argv) try { std::string value = nvc.get("name3"); expect(0 && "not found - must throw"); - } - catch (std::exception&) { + } catch (std::exception&) { } try { std::string value = nvc["name3"]; expect(0 && "not found - must throw"); - } - catch (std::exception&) { + } catch (std::exception&) { } expect(nvc.get("name", "default") == "value"); @@ -357,7 +321,6 @@ int main(int argc, char** argv) // cout << "dir name: " << dir << endl; expect(fs::exists(dir)); expect(fs::exists(dir + "/")); - expect(fs::exists(dir + "\\")); expect(fs::dirname("file.a") == "."); expect(fs::dirname("/some/file.a") == "/some"); expect(fs::dirname("/some/dir") == "/some"); @@ -375,45 +338,48 @@ int main(int argc, char** argv) Logger& logger = Logger::instance(); // Test default synchronous writer - logger.setWriter(new LogWriter); + logger.setWriter(std::make_unique()); clock_t start = clock(); for (unsigned i = 0; i < 1000; i++) - LTrace("sync log ", i) - cout << "logger: synchronous test completed after: " << (clock() - start) << "ms" << endl; + LTrace("sync log ", i); + cout + << "logger: synchronous test completed after: " << (clock() - start) << "ms" << endl; // Test default synchronous var args writer start = clock(); for (unsigned i = 0; i < 1000; i++) - LTrace("sync log", i) - cout << "logger: synchronous var args test completed after: " << (clock() - start) << "ms" << endl; + LTrace("sync log", i); + cout + << "logger: synchronous var args test completed after: " << (clock() - start) << "ms" << endl; // Test asynchronous writer (approx 10x faster with console output) - logger.setWriter(new AsyncLogWriter); + logger.setWriter(std::make_unique()); start = clock(); for (unsigned i = 0; i < 1000; i++) - LTrace("async log ", i) - cout << "logger: asynchronous test completed after: " << (clock() - start) << "ms" << endl; - - //// Test function logging - //start = clock(); - //for (unsigned i = 0; i < 1000; i++) - // LTrace("test: ", i) - //cout << "logger: asynchronous function logging completed after: " - // << (clock() - start) << endl; - - //// Test function and mem address logging - //start = clock(); - //for (unsigned i = 0; i < 1000; i++) - // LTrace("test: ", i) - //cout << "logger: asynchronous function and mem address logging completed after: " - // << (clock() - start) << endl; - - logger.setWriter(nullptr); - - // TODO: Test log filtering - // logger.getDefault()->setFilter("scy::*"); - // Destory the current Logger instance to ensure no crash - Logger::destroy(); + LTrace("async log ", i); + cout + << "logger: asynchronous test completed after: " << (clock() - start) << "ms" << endl; + + //// Test function logging + //start = clock(); + //for (unsigned i = 0; i < 1000; i++) + // LTrace("test: ", i); + //cout << "logger: asynchronous function logging completed after: " + // << (clock() - start) << endl; + + //// Test function and mem address logging + //start = clock(); + //for (unsigned i = 0; i < 1000; i++) + // LTrace("test: ", i); + //cout << "logger: asynchronous function and mem address logging completed after: " + // << (clock() - start) << endl; + + logger.setWriter(nullptr); + + // TODO: Test log filtering + // logger.getDefault()->setFilter("scy::*"); + // Destory the current Logger instance to ensure no crash + Logger::destroy(); }); @@ -482,7 +448,8 @@ int main(int argc, char** argv) *ran = true; expect(idler->running() == true); idler->cancel(); - }, &idler, &ran); + }, + &idler, &ran); // Run the loop again uv::runLoop(); @@ -527,31 +494,446 @@ int main(int argc, char** argv) // describe("process", []() { bool gotStdout = false, gotExit = false; - Process proc{ "ping", "-c 4", "sourcey.com" }; + Process proc{"echo", "hello world"}; proc.onstdout = [&](std::string line) { - std::cout << "process stdout: " << line << std::endl; gotStdout = true; proc.kill(); }; proc.onexit = [&](int64_t status) { - std::cout << "process exit: " << status << std::endl; gotExit = true; }; proc.spawn(); uv::runLoop(); expect(gotStdout); expect(gotExit); + }); + + describe("process with env", []() { + std::string output; + bool gotExit = false; + Process proc{"sh", "-c", "echo $TEST_VAR"}; + proc.env = {"TEST_VAR=hello_from_env"}; + proc.onstdout = [&](std::string line) { + output += line; + }; + proc.onexit = [&](int64_t status) { + gotExit = true; + }; + proc.spawn(); + uv::runLoop(); + expect(gotExit); + expect(output.find("hello_from_env") != std::string::npos); + }); + + describe("process stderr", []() { + std::string errOutput; + bool gotExit = false; + Process proc{"sh", "-c", "echo error >&2"}; + proc.onstderr = [&](std::string line) { + errOutput += line; + }; + proc.onexit = [&](int64_t status) { + gotExit = true; + }; + proc.spawn(); + uv::runLoop(); + expect(gotExit); + expect(errOutput.find("error") != std::string::npos); + }); + + + // ========================================================================= + // Buffer overflow + // + describe("buffer overflow", []() { + Buffer buffer(8); + BitReader reader(buffer, ByteOrder::Host); + BitWriter writer(buffer, ByteOrder::Host); + + // Fill the buffer + writer.putU64(0x0102030405060708ULL); + + // Attempting to read past the end should throw + uint64_t val; + reader.getU64(val); + expect(val == 0x0102030405060708ULL); + + try { + uint8_t extra; + reader.getU8(extra); + expect(0 && "reading past end - must throw"); + } catch (std::out_of_range&) { + } + + // Attempting to write past the end should throw + try { + writer.putU8(0xFF); + expect(0 && "writing past end - must throw"); + } catch (std::out_of_range&) { + } + }); + + + // ========================================================================= + // Random + // + describe("random", []() { + Random rng; + + // next() should produce different values + uint32_t a = rng.next(); + uint32_t b = rng.next(); + uint32_t c = rng.next(); + // Extremely unlikely all three are the same + expect(!(a == b && b == c)); + + // next(n) should produce values in range [0, n) + for (int i = 0; i < 100; ++i) { + uint32_t val = rng.next(10); + expect(val < 10); + } + + // nextBool() should return true and false (statistical) + int trueCount = 0; + for (int i = 0; i < 100; ++i) { + if (rng.nextBool()) + trueCount++; + } + expect(trueCount > 0 && trueCount < 100); + + // nextFloat() should be in [0, 1) + for (int i = 0; i < 100; ++i) { + float f = rng.nextFloat(); + expect(f >= 0.0f && f < 1.0f); + } + + // nextDouble() should be in [0, 1) + for (int i = 0; i < 100; ++i) { + double d = rng.nextDouble(); + expect(d >= 0.0 && d < 1.0); + } + + // Seeding with same value should produce same sequence + Random rng1, rng2; + rng1.seed(42); + rng2.seed(42); + for (int i = 0; i < 10; ++i) { + expect(rng1.next() == rng2.next()); + } + }); + + + // ========================================================================= + // Base64 encode/decode + // + describe("base64 encode/decode", []() { + // RFC 4648 test vectors + base64::Encoder enc; + base64::Decoder dec; + + // Empty string + { + std::string in; + std::string encoded; + enc.encode(in, encoded); + expect(encoded.empty()); + } - // TODO: test stdin pipes and verify file contents + // Standard test vectors via stream interface + { + std::istringstream in("f"); + std::ostringstream out; + base64::Encoder enc2; + enc2.setLineLength(0); + enc2.encode(in, out); + std::string result = out.str(); + // Remove trailing newline/padding whitespace + while (!result.empty() && (result.back() == '\n' || result.back() == '\r')) + result.pop_back(); + expect(result == "Zg=="); + } + + // Round-trip with longer data + { + std::string original = "The quick brown fox jumps over the lazy dog"; + base64::Encoder enc3; + enc3.setLineLength(0); + std::string encoded; + enc3.encode(original, encoded); + expect(!encoded.empty()); + + std::string decoded = base64::decode(encoded); + expect(decoded == original); + } + + // Round-trip with binary data (all byte values) + { + std::string binary; + for (int i = 0; i < 256; ++i) + binary += static_cast(i); + + base64::Encoder enc4; + enc4.setLineLength(0); + std::string encoded; + enc4.encode(binary, encoded); + + std::string decoded = base64::decode(encoded); + expect(decoded == binary); + } + }); + + + // ========================================================================= + // DateTime / Timestamp + // + describe("datetime", []() { + // Timestamp should be non-zero and increasing + Timestamp ts1; + Timestamp ts2; + expect(ts1.epochMicroseconds() > 0); + expect(ts2 >= ts1); + + // DateTime construction + DateTime dt(2024, 1, 15, 10, 30, 45); + expect(dt.year() == 2024); + expect(dt.month() == 1); + expect(dt.day() == 15); + expect(dt.hour() == 10); + expect(dt.minute() == 30); + expect(dt.second() == 45); + + // Timespan + Timespan ts(0, 1, 30, 0, 0); // 1 hour 30 minutes + expect(ts.totalSeconds() == 5400); + expect(ts.totalMinutes() == 90); + expect(ts.hours() == 1); + expect(ts.minutes() == 30); + }); + + + // ========================================================================= + // Error + // + describe("error", []() { + Error err; + expect(!err.any()); + expect(err.err == 0); + expect(err.message.empty()); + + err.err = 42; + err.message = "test error"; + expect(err.any()); + + err.reset(); + expect(!err.any()); + expect(err.err == 0); + expect(err.message.empty()); + }); + + + // ========================================================================= + // Stateful + // + describe("stateful", []() { + State s1(0); + expect(s1.id() == 0); + + s1.set(5); + expect(s1.id() == 5); + expect(s1.equals(5)); + expect(s1.between(3, 7)); + expect(!s1.between(6, 10)); + + State s2(5); + expect(s1 == s2); + }); + + + // ========================================================================= + // Util: string operations + // + describe("util string operations", []() { + // split + auto parts = util::split("a,b,c", ","); + expect(parts.size() == 3); + expect(parts[0] == "a"); + expect(parts[1] == "b"); + expect(parts[2] == "c"); + + // split with limit + parts = util::split("a,b,c,d", ",", 2); + expect(parts.size() == 2); + + // trim + expect(util::trim(std::string(" hello ")) == "hello"); + expect(util::trimLeft(std::string(" hello")) == "hello"); + expect(util::trimRight(std::string("hello ")) == "hello"); + + // case conversion + expect(util::toUpper(std::string("hello")) == "HELLO"); + expect(util::toLower(std::string("HELLO")) == "hello"); + + // replace + std::string s = "foo bar foo"; + expect(util::replace(s, std::string("foo"), std::string("baz")) == "baz bar baz"); + + // isNumber + expect(util::isNumber("12345")); + expect(!util::isNumber("123abc")); + expect(!util::isNumber("")); + + // endsWith + expect(util::endsWith("hello.txt", ".txt")); + expect(!util::endsWith("hello.txt", ".png")); + + // icompare + expect(util::icompare(std::string("Hello"), std::string("hello")) == 0); + expect(util::icompare(std::string("abc"), std::string("def")) < 0); + + // randomString + std::string r1 = util::randomString(16); + std::string r2 = util::randomString(16); + expect(r1.size() == 16); + expect(r2.size() == 16); + expect(r1 != r2); // extremely unlikely to be equal + }); + + + // ========================================================================= + // Util: stream copiers + // + describe("util stream copiers", []() { + std::string data = "hello stream copier world"; + std::istringstream in(data); + std::string result; + util::copyToString(in, result); + expect(result == data); + + // Stream to stream + std::istringstream in2(data); + std::ostringstream out; + util::copyStream(in2, out); + expect(out.str() == data); + }); + + + // ========================================================================= + // Platform (expanded) + // + describe("platform expanded", []() { + expect(!scy::getExePath().empty()); + expect(!scy::getCwd().empty()); + + // Hostname should be non-empty + expect(!scy::getHostname().empty()); + + // CPU count should be >= 1 + expect(scy::numCpuCores() >= 1); + + // Memory should be > 0 + expect(scy::getTotalMemory() > 0); + expect(scy::getFreeMemory() > 0); + expect(scy::getFreeMemory() <= scy::getTotalMemory()); + }); + + + // ========================================================================= + // Filesystem (expanded) + // + describe("filesystem expanded", []() { + // filename / basename / extname + expect(fs::filename("/some/path/file.txt") == "file.txt"); + expect(fs::basename("/some/path/file.txt") == "file"); + expect(fs::extname("/some/path/file.txt") == ".txt"); + expect(fs::extname("/some/path/noext") == ""); + + // mkdir / exists / rmdir + std::string tmpdir = "basetests_tmpdir"; + if (fs::exists(tmpdir)) + fs::rmdir(tmpdir); + expect(!fs::exists(tmpdir)); + fs::mkdir(tmpdir); + expect(fs::exists(tmpdir)); + expect(fs::isdir(tmpdir)); + fs::rmdir(tmpdir); + expect(!fs::exists(tmpdir)); + + // savefile / filesize / unlink + std::string tmpfile = "basetests_tmp.txt"; + std::string content = "test file content"; + fs::savefile(tmpfile, content.c_str(), content.size(), true); + expect(fs::exists(tmpfile)); + expect(!fs::isdir(tmpfile)); + expect(fs::filesize(tmpfile) == static_cast(content.size())); + fs::unlink(tmpfile); + expect(!fs::exists(tmpfile)); + + // normalize + expect(fs::normalize("/some/../other/path") == "/other/path"); + }); + + + // ========================================================================= + // Thread multiple concurrent + // + describe("thread concurrent", []() { + const int numThreads = 4; + std::atomic counter{0}; + Thread threads[numThreads]; + + for (int i = 0; i < numThreads; ++i) { + threads[i].start([&counter]() { + for (int j = 0; j < 1000; ++j) + counter++; + }); + } + + for (int i = 0; i < numThreads; ++i) + threads[i].join(); + + expect(counter == numThreads * 1000); + }); + + + // ========================================================================= + // Signal: clear and re-attach + // + describe("signal clear and re-attach", []() { + Signal sig; + int value = 0; + + sig += [](int& v) { + v += 10; + }; + sig += [](int& v) { + v += 20; + }; + sig.emit(value); + expect(value == 30); + + sig.detachAll(); + expect(sig.nslots() == 0); + + value = 0; + sig += [](int& v) { + v += 5; + }; + sig.emit(value); + expect(value == 5); }); // Define class based tests describe("signal", new SignalTest); describe("ipc", new IpcTest); + describe("ipc round-trip", new IpcRoundTripTest); describe("timer", new TimerTest); + describe("timer pause/resume", new TimerPauseResumeTest); + describe("timer one-shot", new TimerOneShotTest); + describe("logger filtering", new LoggerFilterTest); describe("packet stream", new PacketStreamTest); describe("packet stream file io", new PacketStreamIOTest); + describe("packet stream overflow", new PacketStreamOverflowTest); // describe("multi packet stream", new MultiPacketStreamTest); test::runAll(); diff --git a/src/base/tests/basetests.h b/src/base/tests/basetests.h index 4305966e4..f8b1aec9d 100644 --- a/src/base/tests/basetests.h +++ b/src/base/tests/basetests.h @@ -11,12 +11,13 @@ #define SCY_Base_Tests_H -#include "scy/base.h" -#include "scy/test.h" #include "scy/application.h" +#include "scy/base.h" +#include "scy/base64.h" #include "scy/buffer.h" -#include "scy/datetime.h" #include "scy/collection.h" +#include "scy/datetime.h" +#include "scy/error.h" #include "scy/filesystem.h" #include "scy/idler.h" #include "scy/ipc.h" @@ -26,18 +27,23 @@ #include "scy/packetstream.h" #include "scy/platform.h" #include "scy/process.h" +#include "scy/random.h" #include "scy/sharedlibrary.h" #include "scy/signal.h" +#include "scy/stateful.h" +#include "scy/test.h" +#include "scy/thread.h" #include "scy/time.h" #include "scy/timer.h" -#include "scy/thread.h" #include "scy/util.h" +#include -using std::cout; + +using scy::test::Test; using std::cerr; +using std::cout; using std::endl; -using scy::test::Test; namespace scy { @@ -68,7 +74,7 @@ class IpcTest : public Test ipc.push(new ipc::Action( std::bind(&IpcTest::ipcCallback, this, std::placeholders::_1), &ipc, "test4")); ipc.push(new ipc::Action( - std::bind(&IpcTest::ipcCallback, this, std::placeholders::_1), &ipc, "test5")); + std::bind(&IpcTest::ipcCallback, this, std::placeholders::_1), &ipc, "test5")); // std::cout << "Test IPC: OK" << std::endl; uv::runLoop(); @@ -244,7 +250,7 @@ bool signalHandlerC(const char* sl, size_t ln) } -class SignalTest: public Test +class SignalTest : public Test { struct Foo { @@ -304,8 +310,9 @@ class SignalTest: public Test expect(refid4 == 100); // Attach a static function via += operator + // Auto-ID follows _lastId which was bumped to 100 by explicit slot above refid5 = signal += signalHandlerC; - expect(refid5 == 4); + expect(refid5 == 101); signal.emit("the answer to life the universe and everything is", 42); } @@ -352,7 +359,8 @@ class ProcessTest : public Test // ============================================================================= // Packet Stream // -struct MockThreadedPacketSource : public PacketSource, public basic::Startable +struct MockThreadedPacketSource : public PacketSource + , public basic::Startable { Thread runner; PacketSignal emitter; @@ -372,7 +380,8 @@ struct MockThreadedPacketSource : public PacketSource, public basic::Startable RawPacket p("hello", 5); self->emitter.emit(/*self, */ p); // std::cout << "Emitting 2" << std::endl; - }, this); + }, + this); } void stop() @@ -547,6 +556,259 @@ class MultiPacketStreamTest : public Test }; +// ============================================================================= +// Timer Pause/Resume Test +// +class TimerPauseResumeTest : public Test +{ + void run() + { + // Test: timer fires, we stop it, restart it, verify total ticks + int ticksBeforeStop = 0; + int ticksAfterRestart = 0; + bool stopped = false; + bool restarted = false; + + Timer timer(5, 5); + Timer restartTimer(20); + + timer.start([&]() { + if (!stopped) { + ticksBeforeStop++; + if (ticksBeforeStop == 3) { + stopped = true; + timer.stop(); + // Restart after a brief delay + restartTimer.start([&]() { + restarted = true; + restartTimer.handle().unref(); + timer.start(); + }); + restartTimer.handle().ref(); + } + } else { + ticksAfterRestart++; + if (ticksAfterRestart == 3) { + timer.handle().unref(); + timer.stop(); + } + } + }); + timer.handle().ref(); + uv::runLoop(); + + expect(ticksBeforeStop == 3); + expect(ticksAfterRestart == 3); + expect(restarted == true); + } +}; + + +// ============================================================================= +// Timer One-shot Test +// +class TimerOneShotTest : public Test +{ + void run() + { + int ticks = 0; + + // One-shot timer: timeout set, no interval (0) + Timer timer(std::int64_t(10), std::int64_t(0)); + timer.start([&]() { + ticks++; + timer.handle().unref(); + }); + timer.handle().ref(); + uv::runLoop(); + + expect(ticks == 1); + } +}; + + +// ============================================================================= +// IPC Round-trip Test +// +class IpcRoundTripTest : public Test +{ + void run() + { + // Test: push actions from a worker thread, verify they execute + // on the event loop thread + std::atomic callbackCount{0}; + std::vector receivedData; + std::thread::id loopThreadId = std::this_thread::get_id(); + bool allOnLoopThread = true; + + ipc::SyncQueue<> ipc; + + // Push from a background thread + Thread worker; + worker.start([&]() { + for (int i = 0; i < 3; i++) { + ipc.push(new ipc::Action( + [&](const ipc::Action& action) { + if (std::this_thread::get_id() != loopThreadId) + allOnLoopThread = false; + receivedData.push_back(action.data); + if (++callbackCount == 3) { + // Stop the event loop from the callback + uv::stopLoop(); + } + }, + &ipc, "msg" + std::to_string(i))); + scy::sleep(5); + } + }); + + uv::runLoop(); + ipc.close(); + // Run once more to process the close + uv::runLoop(uv::defaultLoop(), UV_RUN_NOWAIT); + worker.join(); + + expect(callbackCount == 3); + expect(receivedData.size() == 3); + expect(receivedData[0] == "msg0"); + expect(receivedData[1] == "msg1"); + expect(receivedData[2] == "msg2"); + expect(allOnLoopThread == true); + } +}; + + +// ============================================================================= +// Logger Level Filtering Test +// +class LoggerFilterTest : public Test +{ + void run() + { + // Custom channel that captures messages + struct CaptureChannel : public LogChannel + { + std::vector messages; + std::vector levels; + + CaptureChannel(const std::string& name, Level level) + : LogChannel(name, level) + { + } + + void write(const LogStream& stream) override + { + if (this->level() > stream.level) + return; + messages.push_back(stream.message.str()); + levels.push_back(stream.level); + } + }; + + // Test 1: channel at Warn level should filter out Trace/Debug/Info + { + auto channel = std::make_unique("filter_test", Level::Warn); + auto* channelPtr = channel.get(); + Logger::instance().add(std::move(channel)); + + // These should be filtered out (below Warn threshold) + LogStream(Level::Trace, "test.cpp", 1, "filter_test").write("trace msg"); + LogStream(Level::Debug, "test.cpp", 2, "filter_test").write("debug msg"); + LogStream(Level::Info, "test.cpp", 3, "filter_test").write("info msg"); + + // These should pass through + LogStream(Level::Warn, "test.cpp", 4, "filter_test").write("warn msg"); + LogStream(Level::Error, "test.cpp", 5, "filter_test").write("error msg"); + + expect(channelPtr->messages.size() == 2); + expect(channelPtr->levels[0] == Level::Warn); + expect(channelPtr->levels[1] == Level::Error); + + Logger::instance().remove("filter_test"); + } + + // Test 2: channel at Trace level should pass everything + { + auto channel = std::make_unique("pass_all", Level::Trace); + auto* channelPtr = channel.get(); + Logger::instance().add(std::move(channel)); + + LogStream(Level::Trace, "test.cpp", 1, "pass_all").write("a"); + LogStream(Level::Debug, "test.cpp", 2, "pass_all").write("b"); + LogStream(Level::Info, "test.cpp", 3, "pass_all").write("c"); + LogStream(Level::Warn, "test.cpp", 4, "pass_all").write("d"); + LogStream(Level::Error, "test.cpp", 5, "pass_all").write("e"); + + expect(channelPtr->messages.size() == 5); + + Logger::instance().remove("pass_all"); + } + } +}; + + +// ============================================================================= +// Packet Stream Overflow Test +// +// Verifies that a PacketStream with a bounded SyncPacketQueue handles a fast +// producer gracefully: no crash, packets are purged when the queue limit is +// exceeded, and the consumer receives some subset of sent packets. +// +class PacketStreamOverflowTest : public Test +{ + std::atomic numReceived{0}; + + void onPacket(IPacket& packet) + { + numReceived++; + } + + void run() + { + const int totalToSend = 500; + const int queueLimit = 10; // small queue to force overflow/purging + + PacketStream stream; + + // Attach a SyncPacketQueue with a small capacity so the queue's + // push() will purge old packets when the limit is reached. + stream.attach(new SyncPacketQueue<>(uv::defaultLoop(), queueLimit), 0, true); + stream.attach(new MockPacketProcessor, 1, true); + stream.emitter += slot(this, &PacketStreamOverflowTest::onPacket); + + stream.start(); + + // Blast packets from a background thread as fast as possible + Thread producer; + producer.start([&]() { + for (int i = 0; i < totalToSend; i++) { + stream.write(RawPacket("overflow", 8)); + } + }); + + // Give the event loop time to drain some packets + scy::sleep(200); + + // Run the event loop briefly to dispatch queued items + uv::runLoop(uv::defaultLoop(), UV_RUN_NOWAIT); + scy::sleep(50); + uv::runLoop(uv::defaultLoop(), UV_RUN_NOWAIT); + + producer.join(); + stream.close(); + + // The key assertions: + // 1. We didn't crash (reaching here proves it) + // 2. We received some packets but fewer than sent (due to purging) + expect(numReceived > 0); + expect(numReceived <= totalToSend); + + std::cout << "PacketStreamOverflow: sent=" << totalToSend + << " received=" << numReceived << std::endl; + } +}; + + } // namespace scy diff --git a/src/base/tests/utiltests.cpp b/src/base/tests/utiltests.cpp new file mode 100644 index 000000000..440b4434b --- /dev/null +++ b/src/base/tests/utiltests.cpp @@ -0,0 +1,301 @@ +#include "scy/base.h" +#include "scy/iregistry.h" +#include "scy/platform.h" +#include "scy/ratelimiter.h" +#include "scy/test.h" +#include "scy/timeout.h" + +#include + + +using namespace std; +using namespace scy; +using namespace scy::test; + + +// ============================================================================= +// Test types for IRegistry +// +struct Animal +{ + virtual ~Animal() = default; + virtual std::string speak() const = 0; +}; + +struct Dog : public Animal +{ + std::string speak() const override { return "woof"; } +}; + +struct Cat : public Animal +{ + std::string speak() const override { return "meow"; } +}; + + +int main(int argc, char** argv) +{ + test::init(); + + // ========================================================================= + // Timeout - basic lifecycle + // + describe("timeout basic", []() { + Timeout t(100); + expect(!t.running()); + expect(!t.expired()); + + t.start(); + expect(t.running()); + expect(!t.expired()); + expect(t.remaining() > 0); + expect(t.remaining() <= 100); + }); + + + // ========================================================================= + // Timeout - expiry + // + describe("timeout expiry", []() { + Timeout t(50, true); // 50ms, autoStart + expect(t.running()); + + // Wait for expiry + std::this_thread::sleep_for(std::chrono::milliseconds(80)); + expect(t.expired()); + expect(t.remaining() == 0); + }); + + + // ========================================================================= + // Timeout - reset + // + describe("timeout reset", []() { + Timeout t(50, true); + std::this_thread::sleep_for(std::chrono::milliseconds(80)); + expect(t.expired()); + + t.reset(); + expect(t.running()); + expect(!t.expired()); + expect(t.remaining() > 0); + }); + + + // ========================================================================= + // Timeout - stop + // + describe("timeout stop", []() { + Timeout t(1000, true); + expect(t.running()); + + t.stop(); + expect(!t.running()); + }); + + + // ========================================================================= + // Timeout - copy + // + describe("timeout copy", []() { + Timeout t1(200); + t1.start(); + + Timeout t2(t1); + expect(t2.running()); + expect(t2.delay() == 200); + }); + + + // ========================================================================= + // Timeout - assignment + // + describe("timeout assignment", []() { + Timeout t1(300, true); + Timeout t2; + + t2 = t1; + expect(t2.delay() == 300); + expect(t2.running()); + }); + + + // ========================================================================= + // Timeout - zero delay expires immediately + // + describe("timeout zero delay", []() { + Timeout t(0, true); + expect(t.expired()); + }); + + + // ========================================================================= + // TimedToken + // + describe("timed token", []() { + TimedToken token("abc123", 100); + expect(token.id() == "abc123"); + expect(token.delay() == 100); + expect(token.running()); // constructor starts it + + expect(token == std::string("abc123")); + expect(token == TimedToken("abc123")); + + TimedToken other("xyz", 100); + expect(!(token == other)); + }); + + + // ========================================================================= + // TimedToken - expiry + // + describe("timed token expiry", []() { + TimedToken token("sess", 50); + expect(!token.expired()); + + std::this_thread::sleep_for(std::chrono::milliseconds(80)); + expect(token.expired()); + }); + + + // ========================================================================= + // RateLimiter - allows initial burst + // + describe("rate limiter initial burst", []() { + RateLimiter limiter(5.0, 6.0); + + // Should allow at least 5 messages initially + for (int i = 0; i < 5; i++) { + expect(limiter.canSend()); + } + }); + + + // ========================================================================= + // RateLimiter - throttles excess + // + describe("rate limiter throttle", []() { + RateLimiter limiter(3.0, 6.0); + + // Exhaust allowance + for (int i = 0; i < 3; i++) { + limiter.canSend(); + } + + // Next should be rejected (no time has passed) + expect(!limiter.canSend()); + }); + + + // ========================================================================= + // RateLimiter - recovers over time + // + describe("rate limiter recovery", []() { + RateLimiter limiter(2.0, 1.0); // 2 per second + + // Exhaust + limiter.canSend(); + limiter.canSend(); + expect(!limiter.canSend()); + + // Wait for recovery + std::this_thread::sleep_for(std::chrono::milliseconds(600)); + expect(limiter.canSend()); + }); + + + // ========================================================================= + // IRegistry - register and create + // + describe("iregistry register and create", []() { + IRegistry registry; + + registry.registerType("Dog"); + registry.registerType("Cat"); + + auto dog = registry.createInstance("Dog"); + expect(dog != nullptr); + expect(dog->speak() == "woof"); + delete dog; + + auto cat = registry.createInstance("Cat"); + expect(cat != nullptr); + expect(cat->speak() == "meow"); + delete cat; + }); + + + // ========================================================================= + // IRegistry - unknown type returns null + // + describe("iregistry unknown type", []() { + IRegistry registry; + auto result = registry.createInstance("Fish"); + expect(result == nullptr); + }); + + + // ========================================================================= + // IRegistry - unregister + // + describe("iregistry unregister", []() { + IRegistry registry; + registry.registerType("Dog"); + + expect(registry.createInstance("Dog") != nullptr); + + registry.unregisterType("Dog"); + expect(registry.createInstance("Dog") == nullptr); + }); + + + // ========================================================================= + // IRegistry - types map + // + describe("iregistry types", []() { + IRegistry registry; + registry.registerType("Dog"); + registry.registerType("Cat"); + + auto types = registry.types(); + expect(types.size() == 2); + expect(types.find("Dog") != types.end()); + expect(types.find("Cat") != types.end()); + }); + + + // ========================================================================= + // IRegistry - signals + // + describe("iregistry signals", []() { + IRegistry registry; + std::string registered; + std::string unregistered; + + registry.TypeRegistered += [&](const std::string& name) { + registered = name; + }; + registry.TypeUnregistered += [&](const std::string& name) { + unregistered = name; + }; + + registry.registerType("Dog"); + expect(registered == "Dog"); + + registry.unregisterType("Dog"); + expect(unregistered == "Dog"); + }); + + + // ========================================================================= + // IRegistry - unregister nonexistent is safe + // + describe("iregistry unregister nonexistent", []() { + IRegistry registry; + registry.unregisterType("DoesNotExist"); // should not crash + }); + + + test::runAll(); + return test::finalize(); +} diff --git a/src/crypto/CMakeLists.txt b/src/crypto/CMakeLists.txt index 8f1bf5f5c..ab62549d8 100644 --- a/src/crypto/CMakeLists.txt +++ b/src/crypto/CMakeLists.txt @@ -1,8 +1,6 @@ -ask_build_sourcey_module(crypto) -if(BUILD_MODULES OR (NOT BUILD_MODULES AND BUILD_MODULE_crypto)) - #include_dependency(OpenSSL REQUIRED) - include_dependency(SSL REQUIRED) - #include_dependency(LibUV REQUIRED) - - define_sourcey_module(crypto base) +if(HAVE_OPENSSL) + scy_add_module(crypto + DEPENDS base + PACKAGES OpenSSL::SSL OpenSSL::Crypto + ) endif() diff --git a/src/crypto/include/scy/crypto/cipher.h b/src/crypto/include/scy/crypto/cipher.h index c3cceb1bc..283680787 100644 --- a/src/crypto/include/scy/crypto/cipher.h +++ b/src/crypto/include/scy/crypto/cipher.h @@ -9,8 +9,7 @@ /// @{ -#ifndef SCY_Crypto_Cipher_H -#define SCY_Crypto_Cipher_H +#pragma once #include "scy/crypto/crypto.h" @@ -20,14 +19,18 @@ #include -#include #include +#include +#include namespace scy { namespace crypto { +using EvpCipherCtxPtr = std::unique_ptr; + + /// Provides symmetric algorithms for encryption and decryption. /// The algorithms that are available depend on the particular /// version of OpenSSL that is installed. @@ -113,10 +116,10 @@ class Crypto_API Cipher } /// Encrypts a string and encodes it using the given encoding. - virtual std::string encryptString(const std::string& str, Encoding encoding = Binary); + [[nodiscard]] virtual std::string encryptString(const std::string& str, Encoding encoding = Binary); /// Decrypts a string that is encoded with the given encoding. - virtual std::string decryptString(const std::string& str, Encoding encoding = Binary); + [[nodiscard]] virtual std::string decryptString(const std::string& str, Encoding encoding = Binary); /// Encrypts an input stream and encodes it using the given encoding. virtual void encryptStream(std::istream& source, std::ostream& sink, Encoding encoding = Binary); @@ -179,6 +182,8 @@ class Crypto_API Cipher Cipher() = default; Cipher(const Cipher&) = delete; Cipher& operator=(const Cipher&) = delete; + Cipher(Cipher&&) = delete; + Cipher& operator=(Cipher&&) = delete; /// Generates and sets the key and IV from a password and optional salt string. void generateKey(const std::string& passphrase, const std::string& salt, int iterationCount); @@ -195,7 +200,7 @@ class Crypto_API Cipher bool _initialized; bool _encrypt; const EVP_CIPHER* _cipher; - EVP_CIPHER_CTX* _ctx; + EvpCipherCtxPtr _ctx; std::string _name; ByteVec _key; ByteVec _iv; @@ -238,7 +243,4 @@ std::string decryptString(const std::string& algorithm, const std::string& data, } // namespace scy -#endif // SCY_Crypto_Cipher_H - - /// @\} diff --git a/src/crypto/include/scy/crypto/crypto.h b/src/crypto/include/scy/crypto/crypto.h index 21a8e61a8..57980006a 100644 --- a/src/crypto/include/scy/crypto/crypto.h +++ b/src/crypto/include/scy/crypto/crypto.h @@ -9,34 +9,33 @@ /// @{ -#ifndef SCY_Crypto_Crypto_H -#define SCY_Crypto_Crypto_H +#pragma once #include "scy/base.h" #include #include -#ifdef SCY_WIN -#include +#ifdef SCY_WIN #include +#include // Undefine the following definitions defined in wincrypt.h -// as they conflict with BoringSSL -#undef X509_NAME -#undef X509_CERT_PAIR -#undef X509_EXTENSIONS -#endif +// as they conflict with OpenSSL +#undef X509_NAME +#undef X509_CERT_PAIR +#undef X509_EXTENSIONS +#endif // Shared library exports #if defined(SCY_WIN) && defined(SCY_SHARED_LIBRARY) - #if defined(Crypto_EXPORTS) - #define Crypto_API __declspec(dllexport) - #else - #define Crypto_API __declspec(dllimport) - #endif +#if defined(Crypto_EXPORTS) +#define Crypto_API __declspec(dllexport) #else - #define Crypto_API // nothing +#define Crypto_API __declspec(dllimport) +#endif +#else +#define Crypto_API // nothing #endif @@ -62,7 +61,7 @@ Crypto_API void initializeEngine(); Crypto_API void uninitializeEngine(); /// Generic storage container for storing cryptographic binary data. -typedef std::vector ByteVec; +using ByteVec = std::vector; namespace internal { @@ -77,7 +76,8 @@ void throwError(); /// The class uses const_cast for maximum flexibility, so use with care. /// Also ensure that std::string is contiguous on your platform /// before using the std::string constructors (C++11 guarantees it). -template struct Raw +template +struct Raw { T ptr; size_t len; @@ -126,7 +126,4 @@ template struct Raw } // namespace scy -#endif // SCY_Crypto_Crypto_H - - /// @\} diff --git a/src/crypto/include/scy/crypto/hash.h b/src/crypto/include/scy/crypto/hash.h index a93fdde9c..b56bf67b2 100644 --- a/src/crypto/include/scy/crypto/hash.h +++ b/src/crypto/include/scy/crypto/hash.h @@ -9,13 +9,13 @@ /// @{ -#ifndef SCY_Crypto_Hash_H -#define SCY_Crypto_Hash_H +#pragma once #include "scy/crypto/crypto.h" #include "scy/hex.h" #include +#include #include @@ -24,6 +24,9 @@ namespace scy { namespace crypto { +using EvpMdCtxPtr = std::unique_ptr; + + class Crypto_API Hash { public: @@ -39,10 +42,10 @@ class Crypto_API Hash void update(const void* data, size_t length); /// Finish up the digest operation and return the result. - const ByteVec& digest(); + [[nodiscard]] const ByteVec& digest(); /// Finish up the digest operation and return the result as a string. - std::string digestStr(); + [[nodiscard]] std::string digestStr(); /// Resets the engine and digest state ready for the next computation. void reset(); @@ -53,7 +56,7 @@ class Crypto_API Hash protected: Hash& operator=(Hash const&); - EVP_MD_CTX _ctx; + EvpMdCtxPtr _ctx; const EVP_MD* _md; crypto::ByteVec _digest; std::string _algorithm; @@ -99,7 +102,4 @@ inline std::string checksum(const std::string& algorithm, } // namespace scy -#endif // SCY_Crypto_Hash_H - - /// @\} diff --git a/src/crypto/include/scy/crypto/hmac.h b/src/crypto/include/scy/crypto/hmac.h index 4a38b838b..675c683d8 100644 --- a/src/crypto/include/scy/crypto/hmac.h +++ b/src/crypto/include/scy/crypto/hmac.h @@ -9,8 +9,7 @@ /// @{ -#ifndef SCY_Crypto_HMAC_H -#define SCY_Crypto_HMAC_H +#pragma once #include "scy/crypto/crypto.h" @@ -25,14 +24,11 @@ namespace crypto { /// used for message authentication, which is based on a hash function (SHA1). /// /// Input is the data to be signed, and key is the private password. -std::string computeHMAC(const std::string& input, const std::string& key); +[[nodiscard]] std::string computeHMAC(const std::string& input, const std::string& key); } // namespace crypto } // namespace scy -#endif // SCY_Crypto_HMAC_H - - /// @\} diff --git a/src/crypto/include/scy/crypto/rsa.h b/src/crypto/include/scy/crypto/rsa.h index d3107dbf5..027264d88 100644 --- a/src/crypto/include/scy/crypto/rsa.h +++ b/src/crypto/include/scy/crypto/rsa.h @@ -9,8 +9,7 @@ /// @{ -#ifndef SCY_Crypto_RSA_H -#define SCY_Crypto_RSA_H +#pragma once #include "scy/crypto/crypto.h" @@ -23,14 +22,11 @@ namespace crypto { /// Forward the OpenSSL type to our namespace. /// This may become a class/wrapper in the future. -typedef ::RSA RSAKey; +using RSAKey = ::RSA; } // namespace crypto } // namespace scy -#endif // SCY_Crypto_RSA_H - - /// @\} diff --git a/src/crypto/include/scy/crypto/x509certificate.h b/src/crypto/include/scy/crypto/x509certificate.h index c4cffea34..6cfddbff7 100644 --- a/src/crypto/include/scy/crypto/x509certificate.h +++ b/src/crypto/include/scy/crypto/x509certificate.h @@ -9,15 +9,14 @@ /// @{ -#ifndef SCY_Crypto_X509Certificate_H -#define SCY_Crypto_X509Certificate_H +#pragma once #include "scy/crypto/crypto.h" #include "scy/datetime.h" -#include "scy/memory.h" #include +#include #include #include @@ -28,6 +27,9 @@ namespace crypto { /// This class represents a X509 Certificate. +/// RAII wrapper for OpenSSL X509 pointers. +using X509Ptr = std::unique_ptr; + class Crypto_API X509Certificate { public: @@ -65,9 +67,15 @@ class Crypto_API X509Certificate /// Creates the certificate by copying another one. X509Certificate(const X509Certificate& cert); + /// Move constructor. + X509Certificate(X509Certificate&& cert) noexcept; + /// Assigns a certificate. X509Certificate& operator=(const X509Certificate& cert); + /// Move assignment. + X509Certificate& operator=(X509Certificate&& cert) noexcept; + /// Exchanges the certificate with another one. void swap(X509Certificate& cert); @@ -127,6 +135,7 @@ class Crypto_API X509Certificate /// Returns the underlying OpenSSL certificate. const X509* certificate() const; + X509* certificate(); protected: /// Loads the certificate from the given buffer. @@ -148,7 +157,7 @@ class Crypto_API X509Certificate std::string _issuerName; std::string _subjectName; - X509* _certificate; + X509Ptr _certificate; }; @@ -156,7 +165,4 @@ class Crypto_API X509Certificate } // namespace scy -#endif // SCY_Crypto_X509Certificate_H - - /// @\} \ No newline at end of file diff --git a/src/crypto/src/cipher.cpp b/src/crypto/src/cipher.cpp index 9b728ba31..467e6ec76 100644 --- a/src/crypto/src/cipher.cpp +++ b/src/crypto/src/cipher.cpp @@ -32,7 +32,7 @@ Cipher::Cipher(const std::string& name, const std::string& passphrase, : _initialized(false) , _encrypt(false) , _cipher(nullptr) - , _ctx(EVP_CIPHER_CTX_new()) + , _ctx(EVP_CIPHER_CTX_new(), EVP_CIPHER_CTX_free) , _name(name) , _key() , _iv() @@ -54,7 +54,7 @@ Cipher::Cipher(const std::string& name, const ByteVec& key, const ByteVec& iv) : _initialized(false) , _encrypt(false) , _cipher(nullptr) - , _ctx(EVP_CIPHER_CTX_new()) + , _ctx(EVP_CIPHER_CTX_new(), EVP_CIPHER_CTX_free) , _name(name) , _key(key) , _iv(iv) @@ -72,7 +72,7 @@ Cipher::Cipher(const std::string& name) : _initialized(false) , _encrypt(false) , _cipher(nullptr) - , _ctx(EVP_CIPHER_CTX_new()) + , _ctx(EVP_CIPHER_CTX_new(), EVP_CIPHER_CTX_free) , _name(name) , _key() , _iv() @@ -96,8 +96,7 @@ Cipher::~Cipher() crypto::uninitializeEngine(); if (_initialized) - EVP_CIPHER_CTX_cleanup(_ctx); - EVP_CIPHER_CTX_free(_ctx); + EVP_CIPHER_CTX_reset(_ctx.get()); } @@ -116,10 +115,10 @@ void Cipher::initDecryptor() void Cipher::init(bool encrypt) { if (_initialized) - EVP_CIPHER_CTX_cleanup(_ctx); + EVP_CIPHER_CTX_reset(_ctx.get()); - EVP_CipherInit(_ctx, _cipher, &_key[0], _iv.empty() ? 0 : &_iv[0], - encrypt ? 1 : 0); + EVP_CipherInit_ex(_ctx.get(), _cipher, nullptr, &_key[0], + _iv.empty() ? nullptr : &_iv[0], encrypt ? 1 : 0); _encrypt = encrypt; _initialized = true; @@ -129,18 +128,20 @@ void Cipher::init(bool encrypt) ssize_t Cipher::update(const unsigned char* input, size_t inputLength, unsigned char* output, size_t outputLength) { - assert(outputLength >= (inputLength + blockSize() - 1)); + if (outputLength < (inputLength + blockSize() - 1)) + throw std::runtime_error("Cipher: output buffer too small"); int len; - internal::api(EVP_CipherUpdate(_ctx, output, &len, input, (int)inputLength)); + internal::api(EVP_CipherUpdate(_ctx.get(), output, &len, input, (int)inputLength)); return (ssize_t)len; } ssize_t Cipher::final(unsigned char* output, size_t length) { - assert(length >= (size_t)blockSize()); + if (length < (size_t)blockSize()) + throw std::runtime_error("Cipher: input length less than block size"); int len; - internal::api(EVP_CipherFinal_ex(_ctx, output, &len)); + internal::api(EVP_CipherFinal_ex(_ctx.get(), output, &len)); return (ssize_t)len; } @@ -355,7 +356,7 @@ void Cipher::decryptStream(std::istream& source, std::ostream& sink, Encoding en int Cipher::setPadding(int padding) { - return EVP_CIPHER_CTX_set_padding(_ctx, padding); + return EVP_CIPHER_CTX_set_padding(_ctx.get(), padding); } @@ -432,9 +433,9 @@ void Cipher::generateKey(const std::string& password, const std::string& salt, saltBytes[i % 8] ^= salt.at(i); } - // Now create the key and IV, using the MD5 digest algorithm. + // Now create the key and IV, using the SHA-256 digest algorithm. int keySize = EVP_BytesToKey( - _cipher, EVP_md5(), (salt.empty() ? 0 : saltBytes), + _cipher, EVP_sha256(), (salt.empty() ? 0 : saltBytes), reinterpret_cast(password.data()), static_cast(password.size()), iterationCount, keyBytes, ivBytes); diff --git a/src/crypto/src/crypto.cpp b/src/crypto/src/crypto.cpp index 729fa615c..7e27fbd2d 100644 --- a/src/crypto/src/crypto.cpp +++ b/src/crypto/src/crypto.cpp @@ -11,7 +11,6 @@ #include "scy/crypto/crypto.h" #include "scy/random.h" -#include "scy/thread.h" #include #include @@ -20,15 +19,6 @@ #include #include #include -#include - - -extern "C" { -struct CRYPTO_dynlock_value -{ - std::mutex _mutex; -}; -} namespace scy { @@ -44,7 +34,7 @@ void throwError() while ((err = ERR_get_error())) { if (!msg.empty()) msg.append("; "); - msg.append(ERR_error_string(err, 0)); + msg.append(ERR_error_string(err, nullptr)); } throw std::runtime_error(msg); @@ -63,102 +53,38 @@ void api(int ret, const char* error) // -// Private internal methods +// OpenSSL 1.1.0+ / 3.x initialization +// +// Since OpenSSL 1.1.0, library initialization is automatic and thread-safe. +// The old CRYPTO_set_locking_callback, SSL_library_init, SSL_load_error_strings, +// OpenSSL_add_all_algorithms, OPENSSL_config, EVP_cleanup, ERR_free_strings, +// and the dynlock callbacks are all unnecessary and removed in OpenSSL 3.0. +// +// We keep the ref-counted init/uninit pattern for RAND seeding, but the +// locking infrastructure is gone. // - const int SEEDSIZE = 256; -static std::mutex* _mutexes(0); static std::mutex _mutex; static int _refCount(0); -void lock(int mode, int n, const char* /* file */, int /* line */) -{ - if (mode & CRYPTO_LOCK) - _mutexes[n].lock(); - else - _mutexes[n].unlock(); -} - - -// unsigned long id() -// { -// return Thread::currentID(); -// } - - -struct CRYPTO_dynlock_value* dynlockCreate(const char* /* file */, - int /* line */) -{ - return new CRYPTO_dynlock_value; -} - - -void dynlock(int mode, struct CRYPTO_dynlock_value* lock, - const char* /* file */, int /* line */) -{ - assert(lock); - - if (mode & CRYPTO_LOCK) - lock->_mutex.lock(); - else - lock->_mutex.unlock(); -} - - -void dynlockDestroy(struct CRYPTO_dynlock_value* lock, - const char* /* file */, int /* line */) -{ - delete lock; -} - - void init() { std::lock_guard guard(_mutex); if (++_refCount == 1) { -#if OPENSSL_VERSION_NUMBER >= 0x0907000L - OPENSSL_config(NULL); -#endif - SSL_library_init(); - SSL_load_error_strings(); - - OpenSSL_add_all_algorithms(); -#ifdef OPENSSL_IS_BORINGSSL - CRYPTO_library_init(); -#endif - char seed[SEEDSIZE]; Random::getSeed(seed, sizeof(seed)); RAND_seed(seed, SEEDSIZE); - - int nMutexes = CRYPTO_num_locks(); - _mutexes = new std::mutex[nMutexes]; - CRYPTO_set_locking_callback(&internal::lock); -// #ifndef WIN32 // SF# 1828231: random unhandled exceptions when linking with ssl -// CRYPTO_set_id_callback(&internal::id); -// #endif - CRYPTO_set_dynlock_create_callback(&internal::dynlockCreate); - CRYPTO_set_dynlock_lock_callback(&internal::dynlock); - CRYPTO_set_dynlock_destroy_callback(&internal::dynlockDestroy); } } void uninit() { - // NOTE: crypto::uninit() should be called before the app exists - // to endure the mutex is still in memory. std::lock_guard guard(_mutex); - - if (--_refCount == 0) { - EVP_cleanup(); - ERR_free_strings(); - CRYPTO_set_locking_callback(0); - delete[] _mutexes; - } + --_refCount; } diff --git a/src/crypto/src/hash.cpp b/src/crypto/src/hash.cpp index 1a0fad345..ec321e6a9 100644 --- a/src/crypto/src/hash.cpp +++ b/src/crypto/src/hash.cpp @@ -21,10 +21,11 @@ using std::endl; namespace scy { namespace crypto { - Hash::Hash(const std::string& algorithm) - : _algorithm(algorithm) - //, _ctx(EVP_MD_CTX_new()) + : _ctx(EVP_MD_CTX_new(), EVP_MD_CTX_free) + , _md(nullptr) + , _digest() + , _algorithm(algorithm) { crypto::initializeEngine(); @@ -32,32 +33,27 @@ Hash::Hash(const std::string& algorithm) if (!_md) throw std::runtime_error("Algorithm not supported: " + algorithm); - EVP_DigestInit(&_ctx, _md); + EVP_DigestInit_ex(_ctx.get(), _md, nullptr); } Hash::~Hash() { crypto::uninitializeEngine(); - - EVP_MD_CTX_cleanup(&_ctx); - //EVP_MD_CTX_free(_ctx); } void Hash::reset() { - //EVP_MD_CTX_free(_ctx); - //_ctx = EVP_MD_CTX_new(); - internal::api(EVP_MD_CTX_cleanup(&_ctx)); - internal::api(EVP_DigestInit(&_ctx, _md)); + internal::api(EVP_MD_CTX_reset(_ctx.get())); + internal::api(EVP_DigestInit_ex(_ctx.get(), _md, nullptr)); _digest.clear(); } void Hash::update(const void* data, size_t length) { - internal::api(EVP_DigestUpdate(&_ctx, data, length)); + internal::api(EVP_DigestUpdate(_ctx.get(), data, length)); } @@ -77,9 +73,9 @@ const ByteVec& Hash::digest() { // Compute the first time if (_digest.size() == 0) { - _digest.resize(EVP_MAX_MD_SIZE); // TODO: Get actual algorithm size + _digest.resize(EVP_MAX_MD_SIZE); unsigned int len = 0; - internal::api(EVP_DigestFinal(&_ctx, &_digest[0], &len)); + internal::api(EVP_DigestFinal_ex(_ctx.get(), &_digest[0], &len)); _digest.resize(len); } return _digest; diff --git a/src/crypto/src/hmac.cpp b/src/crypto/src/hmac.cpp index 3561dd31d..494862576 100644 --- a/src/crypto/src/hmac.cpp +++ b/src/crypto/src/hmac.cpp @@ -11,7 +11,7 @@ #include "scy/crypto/hmac.h" #include "scy/util.h" -#include +#include #ifdef SCY_WIN // hack for name collision of OCSP_RESPONSE and wincrypto.h in openssl release @@ -37,7 +37,8 @@ std::string computeHMAC(const std::string& input, const std::string& key) HMAC(EVP_sha1(), key.c_str(), key.length(), reinterpret_cast(input.c_str()), input.length(), reinterpret_cast(&buf), &len); - assert(len == 20); + if (len != 20) + throw std::runtime_error("HMAC: unexpected digest length"); return std::string(buf, len); } diff --git a/src/crypto/src/x509certificate.cpp b/src/crypto/src/x509certificate.cpp index 76f5e799b..a088675f8 100644 --- a/src/crypto/src/x509certificate.cpp +++ b/src/crypto/src/x509certificate.cpp @@ -10,11 +10,12 @@ #include "scy/crypto/x509certificate.h" -#include #include #include +#include #include #include +#include namespace scy { @@ -22,46 +23,38 @@ namespace crypto { X509Certificate::X509Certificate(const char* data, size_t length) - : _certificate(0) + : _certificate(nullptr, X509_free) { - std::string res; - Timestamp ts; - DateTimeFormatter::append(res, ts, DateTimeFormat::HTTP_FORMAT); - - std::string dateTime; - int tzd; - DateTime t = DateTimeParser::parse("%y%m%d%H%M%S", dateTime, tzd); - Timespan t1; - load(data, length); } X509Certificate::X509Certificate(const std::string& path) - : _certificate(0) + : _certificate(nullptr, X509_free) { load(path); } X509Certificate::X509Certificate(X509* pCert) - : _certificate(pCert) + : _certificate(pCert, X509_free) { - assert(_certificate); + if (!_certificate) + throw std::runtime_error("X509Certificate: certificate is null"); init(); } X509Certificate::X509Certificate(X509* pCert, bool shared) - : _certificate(pCert) + : _certificate(pCert, X509_free) { - assert(_certificate); - - if (shared) - _certificate->references++; - // X509_up_ref(_certificate); // OpenSSL >= 1.1.0 + if (!_certificate) + throw std::runtime_error("X509Certificate: certificate is null"); + if (shared) { + X509_up_ref(_certificate.get()); + } init(); } @@ -69,9 +62,16 @@ X509Certificate::X509Certificate(X509* pCert, bool shared) X509Certificate::X509Certificate(const X509Certificate& cert) : _issuerName(cert._issuerName) , _subjectName(cert._subjectName) - , _certificate(cert._certificate) + , _certificate(X509_dup(cert._certificate.get()), X509_free) +{ +} + + +X509Certificate::X509Certificate(X509Certificate&& cert) noexcept + : _issuerName(std::move(cert._issuerName)) + , _subjectName(std::move(cert._subjectName)) + , _certificate(std::move(cert._certificate)) { - _certificate = X509_dup(_certificate); } @@ -83,6 +83,17 @@ X509Certificate& X509Certificate::operator=(const X509Certificate& cert) } +X509Certificate& X509Certificate::operator=(X509Certificate&& cert) noexcept +{ + if (&cert != this) { + _issuerName = std::move(cert._issuerName); + _subjectName = std::move(cert._subjectName); + _certificate = std::move(cert._certificate); + } + return *this; +} + + void X509Certificate::swap(X509Certificate& cert) { std::swap(cert._issuerName, _issuerName); @@ -91,15 +102,13 @@ void X509Certificate::swap(X509Certificate& cert) } -X509Certificate::~X509Certificate() -{ - X509_free(_certificate); -} +X509Certificate::~X509Certificate() = default; void X509Certificate::load(const char* data, size_t length) { - assert(!_certificate); + if (_certificate) + throw std::logic_error("X509Certificate: already loaded"); std::string cert(data, length); BIO* pBIO = BIO_new_mem_buf(const_cast(cert.data()), @@ -107,12 +116,12 @@ void X509Certificate::load(const char* data, size_t length) if (!pBIO) throw std::runtime_error( "SSL IO error: Cannot create BIO for reading certificate"); - _certificate = PEM_read_bio_X509(pBIO, 0, 0, 0); + _certificate.reset(PEM_read_bio_X509(pBIO, nullptr, nullptr, nullptr)); BIO_free(pBIO); if (!_certificate) throw std::runtime_error( - "SSL IO error: Faild to load X509 certificate from stream"); + "SSL IO error: Failed to load X509 certificate from stream"); init(); } @@ -120,7 +129,8 @@ void X509Certificate::load(const char* data, size_t length) void X509Certificate::load(const std::string& path) { - assert(!_certificate); + if (_certificate) + throw std::logic_error("X509Certificate: already loaded"); BIO* pBIO = BIO_new(BIO_s_file()); if (!pBIO) @@ -134,12 +144,12 @@ void X509Certificate::load(const std::string& path) path); } - _certificate = PEM_read_bio_X509(pBIO, 0, 0, 0); + _certificate.reset(PEM_read_bio_X509(pBIO, nullptr, nullptr, nullptr)); BIO_free(pBIO); if (!_certificate) throw std::runtime_error( - "SSL file error: Faild to load certificate from: " + path); + "SSL file error: Failed to load certificate from: " + path); init(); } @@ -152,7 +162,7 @@ void X509Certificate::save(std::ostream& stream) const throw std::runtime_error( "SSL IO error: Cannot create BIO for writing certificate"); try { - if (!PEM_write_bio_X509(pBIO, _certificate)) + if (!PEM_write_bio_X509(pBIO, _certificate.get())) throw std::runtime_error( "SSL IO error: Failed to write certificate to stream"); @@ -172,7 +182,7 @@ void X509Certificate::save(const std::string& path) const { BIO* pBIO = BIO_new(BIO_s_file()); if (!pBIO) - std::runtime_error( + throw std::runtime_error( "SSL IO error: Cannot create BIO for reading certificate file: " + path); if (!BIO_write_filename(pBIO, const_cast(path.c_str()))) { @@ -182,7 +192,7 @@ void X509Certificate::save(const std::string& path) const } try { - if (!PEM_write_bio_X509(pBIO, _certificate)) + if (!PEM_write_bio_X509(pBIO, _certificate.get())) throw std::runtime_error( "SSL file error: Failed to write certificate to file: " + path); } catch (...) { @@ -197,9 +207,9 @@ void X509Certificate::save(const std::string& path) const void X509Certificate::init() { char buffer[NAME_BUFFER_SIZE]; - X509_NAME_oneline(X509_get_issuer_name(_certificate), buffer, sizeof(buffer)); + X509_NAME_oneline(X509_get_issuer_name(_certificate.get()), buffer, sizeof(buffer)); _issuerName = buffer; - X509_NAME_oneline(X509_get_subject_name(_certificate), buffer, sizeof(buffer)); + X509_NAME_oneline(X509_get_subject_name(_certificate.get()), buffer, sizeof(buffer)); _subjectName = buffer; } @@ -212,7 +222,7 @@ std::string X509Certificate::commonName() const std::string X509Certificate::issuerName(NID nid) const { - if (X509_NAME* issuer = X509_get_issuer_name(_certificate)) { + if (X509_NAME* issuer = X509_get_issuer_name(_certificate.get())) { char buffer[NAME_BUFFER_SIZE]; X509_NAME_get_text_by_NID(issuer, nid, buffer, sizeof(buffer)); return std::string(buffer); @@ -223,7 +233,7 @@ std::string X509Certificate::issuerName(NID nid) const std::string X509Certificate::subjectName(NID nid) const { - if (X509_NAME* subj = X509_get_subject_name(_certificate)) { + if (X509_NAME* subj = X509_get_subject_name(_certificate.get())) { char buffer[NAME_BUFFER_SIZE]; X509_NAME_get_text_by_NID(subj, nid, buffer, sizeof(buffer)); return std::string(buffer); @@ -237,12 +247,12 @@ void X509Certificate::extractNames(std::string& cmnName, { domainNames.clear(); if (STACK_OF(GENERAL_NAME)* names = static_cast( - X509_get_ext_d2i(_certificate, NID_subject_alt_name, 0, 0))) { + X509_get_ext_d2i(_certificate.get(), NID_subject_alt_name, nullptr, nullptr))) { for (int i = 0; i < sk_GENERAL_NAME_num(names); ++i) { const GENERAL_NAME* name = sk_GENERAL_NAME_value(names, i); if (name->type == GEN_DNS) { const char* data = - reinterpret_cast(ASN1_STRING_data(name->d.ia5)); + reinterpret_cast(ASN1_STRING_get0_data(name->d.ia5)); size_t len = ASN1_STRING_length(name->d.ia5); domainNames.insert(std::string(data, len)); } @@ -259,7 +269,7 @@ void X509Certificate::extractNames(std::string& cmnName, DateTime X509Certificate::validFrom() const { - ASN1_TIME* certTime = X509_get_notBefore(_certificate); + const ASN1_TIME* certTime = X509_get0_notBefore(_certificate.get()); std::string dateTime(reinterpret_cast(certTime->data)); int tzd; return DateTimeParser::parse("%y%m%d%H%M%S", dateTime, tzd); @@ -268,7 +278,7 @@ DateTime X509Certificate::validFrom() const DateTime X509Certificate::expiresOn() const { - ASN1_TIME* certTime = X509_get_notAfter(_certificate); + const ASN1_TIME* certTime = X509_get0_notAfter(_certificate.get()); std::string dateTime(reinterpret_cast(certTime->data)); int tzd; return DateTimeParser::parse("%y%m%d%H%M%S", dateTime, tzd); @@ -277,7 +287,7 @@ DateTime X509Certificate::expiresOn() const bool X509Certificate::issuedBy(const X509Certificate& issuerCertificate) const { - X509* pCert = const_cast(_certificate); + X509* pCert = const_cast(_certificate.get()); X509* pIssuerCert = const_cast(issuerCertificate.certificate()); EVP_PKEY* pIssuerPublicKey = X509_get_pubkey(pIssuerCert); if (!pIssuerPublicKey) @@ -302,7 +312,13 @@ const std::string& X509Certificate::subjectName() const const X509* X509Certificate::certificate() const { - return _certificate; + return _certificate.get(); +} + + +X509* X509Certificate::certificate() +{ + return _certificate.get(); } @@ -310,4 +326,4 @@ const X509* X509Certificate::certificate() const } // namespace scy -/// @\} \ No newline at end of file +/// @\} diff --git a/src/crypto/tests/CMakeLists.txt b/src/crypto/tests/CMakeLists.txt index ac25bc330..53fae9e6b 100644 --- a/src/crypto/tests/CMakeLists.txt +++ b/src/crypto/tests/CMakeLists.txt @@ -1,3 +1 @@ -# include_dependency(SSL REQUIRED) - -define_libsourcey_test(cryptotests base crypto) +scy_add_test(cryptotests DEPENDS base crypto) diff --git a/src/crypto/tests/cryptotests.cpp b/src/crypto/tests/cryptotests.cpp index 5ce344c49..a23aad0be 100644 --- a/src/crypto/tests/cryptotests.cpp +++ b/src/crypto/tests/cryptotests.cpp @@ -1,15 +1,22 @@ -#include "scy/crypto/crypto.h" #include "scy/crypto/cipher.h" +#include "scy/crypto/crypto.h" #include "scy/crypto/hash.h" #include "scy/crypto/rsa.h" -#include "scy/test.h" +#include "scy/crypto/x509certificate.h" +#include "scy/filesystem.h" +#include "scy/hex.h" #include "scy/logger.h" +#include "scy/test.h" #include "scy/util.h" -#include "scy/hex.h" #include +#include +#include #include +#include +#include + using std::endl; using namespace scy; @@ -30,7 +37,7 @@ void testCipher(const std::string algorithm, int iterations) std::string result = ciph.decryptString(out, crypto::Cipher::Binary); expect(in == result); } - LDebug("Binary: ", (clock() - start)) + LDebug("Binary: ", (clock() - start)); } { @@ -42,7 +49,7 @@ void testCipher(const std::string algorithm, int iterations) std::string result = ciph.decryptString(out, crypto::Cipher::Base64); expect(in == result); } - LDebug("Base64: ", (clock() - start)) + LDebug("Base64: ", (clock() - start)); } { @@ -54,7 +61,7 @@ void testCipher(const std::string algorithm, int iterations) std::string result = ciph.decryptString(out, crypto::Cipher::BinHex); expect(in == result); } - LDebug("BinHex: ", (clock() - start)) + LDebug("BinHex: ", (clock() - start)); } { @@ -86,20 +93,100 @@ void testCipher(const std::string algorithm, int iterations) } +/// Compute HMAC using OpenSSL EVP API directly +std::string computeHMAC(const std::string& algorithm, const std::string& key, + const std::string& data) +{ + const EVP_MD* md = EVP_get_digestbyname(algorithm.c_str()); + if (!md) + throw std::runtime_error("HMAC algorithm not supported: " + algorithm); + + unsigned char result[EVP_MAX_MD_SIZE]; + unsigned int len = 0; + HMAC(md, key.data(), static_cast(key.size()), + reinterpret_cast(data.data()), + data.size(), result, &len); + + return hex::encode(std::vector(result, result + len)); +} + + } // namespace scy int main(int argc, char** argv) { - // Logger::instance().add(new ConsoleChannel("debug", Level::Trace)); + // Logger::instance().add(std::make_unique("debug", Level::Trace)); test::init(); crypto::initializeEngine(); // ========================================================================= - // Cypher + // Cipher: AES-256-CBC + // + describe("aes256 cipher", []() { + testCipher("aes-256-cbc", 100); + }); + + // ========================================================================= + // Cipher: empty input + // + describe("cipher empty input", []() { + crypto::Cipher ciph("aes-256-cbc"); + std::string in; + std::string out = ciph.encryptString(in, crypto::Cipher::Binary); + std::string result = ciph.decryptString(out, crypto::Cipher::Binary); + expect(result.empty()); + }); + + // ========================================================================= + // Cipher: large input (64KB) + // + describe("cipher large input", []() { + crypto::Cipher ciph("aes-256-cbc"); + std::string in(65536, 'A'); + std::string out = ciph.encryptString(in, crypto::Cipher::Binary); + std::string result = ciph.decryptString(out, crypto::Cipher::Binary); + expect(in == result); + }); + + // ========================================================================= + // Cipher: passphrase-based key derivation + // + describe("cipher with passphrase", []() { + crypto::Cipher ciph("aes-256-cbc", "my secret passphrase", "saltsalt", 2000); + std::string in = "encrypt me with a passphrase"; + std::string out = ciph.encryptString(in, crypto::Cipher::Base64); + std::string result = ciph.decryptString(out, crypto::Cipher::Base64); + expect(in == result); + }); + + // ========================================================================= + // Cipher: stream encryption // - describe("aes256 cypher", []() { - testCipher("aes-256-cbc", 10000); + describe("cipher stream encrypt/decrypt", []() { + crypto::Cipher ciph("aes-256-cbc"); + std::string in = "stream encryption test data that is longer than one block"; + + std::istringstream source(in); + std::ostringstream encrypted; + ciph.encryptStream(source, encrypted, crypto::Cipher::Base64); + + std::istringstream encSource(encrypted.str()); + std::ostringstream decrypted; + ciph.decryptStream(encSource, decrypted, crypto::Cipher::Base64); + + expect(decrypted.str() == in); + }); + + // ========================================================================= + // Cipher: invalid algorithm throws + // + describe("cipher invalid algorithm", []() { + try { + crypto::Cipher ciph("nonexistent-cipher-xyz"); + expect(0 && "invalid algorithm - must throw"); + } catch (std::exception&) { + } }); // ========================================================================= @@ -160,7 +247,339 @@ int main(int argc, char** argv) }); // ========================================================================= - // Hex + // SHA-256 Hash + // + describe("sha256 hash", []() { + // test vectors from FIPS 180-2 + + crypto::Hash engine("SHA256"); + engine.update("abc", 3); + expect(hex::encode(engine.digest()) == "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"); + + engine.reset(); + engine.update("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"); + expect(hex::encode(engine.digest()) == "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1"); + + // empty string + engine.reset(); + engine.update("", 0); + expect(hex::encode(engine.digest()) == "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"); + }); + + // ========================================================================= + // SHA-512 Hash + // + describe("sha512 hash", []() { + crypto::Hash engine("SHA512"); + engine.update("abc", 3); + expect(hex::encode(engine.digest()) == + "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a" + "2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"); + + // empty string + engine.reset(); + engine.update("", 0); + expect(hex::encode(engine.digest()) == + "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce" + "47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"); + }); + + // ========================================================================= + // Hash: empty input + // + describe("hash empty input", []() { + // MD5 of empty string + crypto::Hash engine("MD5"); + engine.update("", 0); + expect(hex::encode(engine.digest()) == "d41d8cd98f00b204e9800998ecf8427e"); + }); + + // ========================================================================= + // Hash: large input (1MB) + // + describe("hash large input", []() { + crypto::Hash engine("SHA256"); + std::string chunk(4096, 'z'); + for (int i = 0; i < 256; ++i) + engine.update(chunk); + + // Just verify it completes and produces a 64-char hex digest + std::string result = hex::encode(engine.digest()); + expect(result.size() == 64); + }); + + // ========================================================================= + // Hash: invalid algorithm throws + // + describe("hash invalid algorithm", []() { + try { + crypto::Hash engine("NONEXISTENT_HASH"); + expect(0 && "invalid algorithm - must throw"); + } catch (std::exception&) { + } + }); + + // ========================================================================= + // Hash: convenience function + // + describe("hash convenience function", []() { + std::string result = crypto::hash("SHA1", "abc"); + expect(result == "a9993e364706816aba3e25717850c26c9cd0d89d"); + + result = crypto::hash("MD5", std::string("")); + expect(result == "d41d8cd98f00b204e9800998ecf8427e"); + }); + + // ========================================================================= + // Hash: digestStr + // + describe("hash digestStr", []() { + crypto::Hash engine("MD5"); + engine.update("abc"); + std::string raw = engine.digestStr(); + // MD5 produces 16 bytes + expect(raw.size() == 16); + }); + + // ========================================================================= + // Hash: incremental update + // + describe("hash incremental update", []() { + // Hashing in chunks should produce same result as hashing all at once + crypto::Hash engine1("SHA256"); + engine1.update("hello world"); + + crypto::Hash engine2("SHA256"); + engine2.update("hello "); + engine2.update("world"); + + expect(hex::encode(engine1.digest()) == hex::encode(engine2.digest())); + }); + + // ========================================================================= + // HMAC: SHA-256 + // + describe("hmac sha256", []() { + // RFC 4231 test vectors + + // Test case 1 + std::string key1(20, '\x0b'); + std::string data1 = "Hi There"; + expect(computeHMAC("SHA256", key1, data1) == + "b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7"); + + // Test case 2: "Jefe" / "what do ya want for nothing?" + expect(computeHMAC("SHA256", "Jefe", "what do ya want for nothing?") == + "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843"); + }); + + // ========================================================================= + // HMAC: SHA-1 + // + describe("hmac sha1", []() { + // RFC 2202 test case 1 + std::string key(20, '\x0b'); + std::string data = "Hi There"; + expect(computeHMAC("SHA1", key, data) == + "b617318655057264e28bc0b6fb378c8ef146be00"); + }); + + // ========================================================================= + // HMAC: MD5 + // + describe("hmac md5", []() { + // RFC 2104 test case 1 + std::string key(16, '\x0b'); + std::string data = "Hi There"; + expect(computeHMAC("MD5", key, data) == + "9294727a3638bb1c13f48ef8158bfc9d"); + }); + + // ========================================================================= + // HMAC: empty data + // + describe("hmac empty data", []() { + std::string result = computeHMAC("SHA256", "key", ""); + // Just verify it produces a valid 64-char hex string + expect(result.size() == 64); + }); + + // ========================================================================= + // X509Certificate: load from file + // + describe("x509 load from file", []() { + std::string certPath(SCY_SOURCE_DIR); + fs::addnode(certPath, "net"); + fs::addnode(certPath, "tests"); + fs::addnode(certPath, "cert.pem"); + + if (!fs::exists(certPath)) { + std::cout << "Skipping X509 file test - cert.pem not found at: " << certPath << std::endl; + return; + } + + crypto::X509Certificate cert(certPath); + + // Verify basic accessors return non-empty strings + expect(!cert.issuerName().empty()); + expect(!cert.subjectName().empty()); + }); + + // ========================================================================= + // X509Certificate: load from buffer + // + describe("x509 load from buffer", []() { + std::string certPath(SCY_SOURCE_DIR); + fs::addnode(certPath, "net"); + fs::addnode(certPath, "tests"); + fs::addnode(certPath, "cert.pem"); + + if (!fs::exists(certPath)) { + std::cout << "Skipping X509 buffer test - cert.pem not found" << std::endl; + return; + } + + // Read cert data into a string + std::ifstream file(certPath); + std::string certData((std::istreambuf_iterator(file)), + std::istreambuf_iterator()); + expect(!certData.empty()); + + crypto::X509Certificate cert(certData.data(), certData.size()); + + expect(!cert.issuerName().empty()); + expect(!cert.subjectName().empty()); + }); + + // ========================================================================= + // X509Certificate: copy and assignment + // + describe("x509 copy and assignment", []() { + std::string certPath(SCY_SOURCE_DIR); + fs::addnode(certPath, "net"); + fs::addnode(certPath, "tests"); + fs::addnode(certPath, "cert.pem"); + + if (!fs::exists(certPath)) { + std::cout << "Skipping X509 copy test" << std::endl; + return; + } + + crypto::X509Certificate cert1(certPath); + + // Copy constructor + crypto::X509Certificate cert2(cert1); + expect(cert1.issuerName() == cert2.issuerName()); + expect(cert1.subjectName() == cert2.subjectName()); + + // Assignment operator + crypto::X509Certificate cert3(certPath); + cert3 = cert1; + expect(cert1.issuerName() == cert3.issuerName()); + expect(cert1.subjectName() == cert3.subjectName()); + }); + + // ========================================================================= + // X509Certificate: save and reload (round-trip) + // + describe("x509 save and reload", []() { + std::string certPath(SCY_SOURCE_DIR); + fs::addnode(certPath, "net"); + fs::addnode(certPath, "tests"); + fs::addnode(certPath, "cert.pem"); + + if (!fs::exists(certPath)) { + std::cout << "Skipping X509 save test" << std::endl; + return; + } + + crypto::X509Certificate cert1(certPath); + + // Save to stream + std::ostringstream oss; + cert1.save(oss); + std::string pemData = oss.str(); + expect(!pemData.empty()); + expect(pemData.find("-----BEGIN CERTIFICATE-----") != std::string::npos); + + // Reload from buffer + crypto::X509Certificate cert2(pemData.data(), pemData.size()); + expect(cert1.issuerName() == cert2.issuerName()); + expect(cert1.subjectName() == cert2.subjectName()); + }); + + // ========================================================================= + // X509Certificate: extractNames + // + describe("x509 extract names", []() { + std::string certPath(SCY_SOURCE_DIR); + fs::addnode(certPath, "net"); + fs::addnode(certPath, "tests"); + fs::addnode(certPath, "cert.pem"); + + if (!fs::exists(certPath)) { + std::cout << "Skipping X509 extractNames test" << std::endl; + return; + } + + crypto::X509Certificate cert(certPath); + std::string commonName; + std::set domainNames; + cert.extractNames(commonName, domainNames); + + // commonName should be populated for any valid cert + // (domainNames may or may not have SANs depending on cert) + expect(!commonName.empty() || !domainNames.empty()); + }); + + // ========================================================================= + // X509Certificate: validity dates + // + describe("x509 validity dates", []() { + std::string certPath(SCY_SOURCE_DIR); + fs::addnode(certPath, "net"); + fs::addnode(certPath, "tests"); + fs::addnode(certPath, "cert.pem"); + + if (!fs::exists(certPath)) { + std::cout << "Skipping X509 validity test" << std::endl; + return; + } + + crypto::X509Certificate cert(certPath); + + // Just verify the date accessors don't throw + DateTime validFrom = cert.validFrom(); + DateTime expiresOn = cert.expiresOn(); + + // expiresOn should be after validFrom + expect(expiresOn > validFrom); + }); + + // ========================================================================= + // X509Certificate: invalid PEM data throws + // + describe("x509 invalid data throws", []() { + try { + crypto::X509Certificate cert("not a valid certificate", 23); + expect(0 && "invalid PEM data - must throw"); + } catch (std::exception&) { + } + }); + + // ========================================================================= + // X509Certificate: invalid file path throws + // + describe("x509 invalid path throws", []() { + try { + crypto::X509Certificate cert("/nonexistent/path/cert.pem"); + expect(0 && "nonexistent file - must throw"); + } catch (std::exception&) { + } + }); + + // ========================================================================= + // Hex encoder/decoder // describe("hex encoder/decoder", []() { hex::Encoder enc; @@ -171,24 +590,86 @@ int main(int argc, char** argv) char encBuf[2048]; size_t len = enc.encode(in.c_str(), in.length(), encBuf); std::string encRes(encBuf, len); - LDebug("Encoded: ", encRes) + LDebug("Encoded: ", encRes); char decBuf[2048]; len = dec.decode(encBuf, len, decBuf); std::string decRes(decBuf, len); - LDebug("Decoded: ", decRes) + LDebug("Decoded: ", decRes); expect(in == decRes); }); // ========================================================================= - // Checksum + // Hex: empty input + // + describe("hex empty input", []() { + std::vector empty; + std::string result = hex::encode(empty); + expect(result.empty()); + }); + + // ========================================================================= + // Hex: round-trip various data + // + describe("hex round-trip", []() { + hex::Encoder enc; + hex::Decoder dec; + + // Test with all byte values 0x00-0xFF + std::string in; + for (int i = 0; i < 256; ++i) + in += static_cast(i); + + char encBuf[1024]; + size_t encLen = enc.encode(in.c_str(), in.length(), encBuf); + + char decBuf[512]; + size_t decLen = dec.decode(encBuf, encLen, decBuf); + + expect(decLen == 256); + for (int i = 0; i < 256; ++i) + expect(static_cast(decBuf[i]) == static_cast(i)); + }); + + // ========================================================================= + // File checksum // describe("file checksum", []() { - // NOTE: checksum tests currently located in HTTP tests + // Create a temporary file and verify its checksum + std::string path = "checksum_test.tmp"; + std::string content = "hello checksum world"; + fs::savefile(path, content.c_str(), content.size(), true); + + std::string md5 = crypto::checksum("MD5", path); + expect(!md5.empty()); + expect(md5.size() == 32); // MD5 hex digest is 32 chars + + std::string sha1 = crypto::checksum("SHA1", path); + expect(!sha1.empty()); + expect(sha1.size() == 40); // SHA1 hex digest is 40 chars + + std::string sha256 = crypto::checksum("SHA256", path); + expect(!sha256.empty()); + expect(sha256.size() == 64); // SHA256 hex digest is 64 chars + + // Verify MD5 matches manual computation + crypto::Hash manual("MD5"); + manual.update(content); + expect(md5 == hex::encode(manual.digest())); - // std::string path("test.mp4"); - // expect(crypto::checksum("MD5", path) == "57e14d2f24ab34a6eb1de3eb82f02f33"); + fs::unlink(path); + }); + + // ========================================================================= + // File checksum: nonexistent file throws + // + describe("file checksum nonexistent", []() { + try { + crypto::checksum("MD5", "/nonexistent/file.bin"); + expect(0 && "nonexistent file - must throw"); + } catch (std::exception&) { + } }); test::runAll(); diff --git a/src/http/CMakeLists.txt b/src/http/CMakeLists.txt index 2e046ae49..2c8e5ebff 100644 --- a/src/http/CMakeLists.txt +++ b/src/http/CMakeLists.txt @@ -1,18 +1,7 @@ -ask_build_sourcey_module(http) -if(BUILD_MODULES OR (NOT BUILD_MODULES AND BUILD_MODULE_http)) - - #list(APPEND LibSourcey_BUILD_DEPENDENCIES http_parser) - #list(APPEND LibSourcey_BUILD_DEPENDENCIES http_parser PARENT_SCOPE) - #set(LibSourcey_BUILD_DEPENDENCIES ${LibSourcey_BUILD_DEPENDENCIES} http_parser PARENT_SCOPE) - #add_subdirectory(vendor/http_parser) - #set(HAVE_HTTPPARSER 1) - - include_dependency(SSL REQUIRED) - #include_dependency(LibUV) - #include_dependency(HttpParser) - - #include_directories(${CMAKE_CURRENT_SOURCE_DIR}/vendor/http_parser) - - set(http_PRETTY_NAME HTTP) - define_sourcey_module(http base net crypto) # util +if(HAVE_OPENSSL) + scy_add_module(http + DEPENDS base net crypto + PACKAGES OpenSSL::SSL OpenSSL::Crypto llhttp_static + PRETTY_NAME HTTP + ) endif() diff --git a/src/http/include/scy/http/authenticator.h b/src/http/include/scy/http/authenticator.h index 5646bc613..636bbb4f4 100644 --- a/src/http/include/scy/http/authenticator.h +++ b/src/http/include/scy/http/authenticator.h @@ -8,10 +8,7 @@ /// @addtogroup http /// @{ - -#ifndef SCY_HTTP_Authenticator_H -#define SCY_HTTP_Authenticator_H - +#pragma once #include "scy/http/http.h" #include "scy/http/url.h" @@ -26,6 +23,7 @@ class HTTP_API Request; class HTTP_API Response; +/// @ingroup http /// This is a utility class for working with HTTP /// authentication (basic or digest) in http::Request objects. /// @@ -58,20 +56,17 @@ class HTTP_API Authenticator void setUsername(const std::string& username); /// Returns the username. - const std::string& username() const; + [[nodiscard]] const std::string& username() const; /// Sets the password. void setPassword(const std::string& password); /// Returns the password. - const std::string& password() const; + [[nodiscard]] const std::string& password() const; /// Inspects WWW-Authenticate header of the response, initializes /// the internal state (in case of digest authentication) and /// adds required information to the given http::Request. - /// - /// Does nothing if there is no WWW-Authenticate header in the - /// http::Response. void authenticate(http::Request& request, const http::Response& response); /// Updates internal state (in case of digest authentication) and @@ -81,9 +76,6 @@ class HTTP_API Authenticator /// Inspects Proxy-Authenticate header of the response, initializes /// the internal state (in case of digest authentication) and /// adds required information to the given http::Request. - /// - /// Does nothing if there is no Proxy-Authenticate header in the - /// http::Response. void proxyAuthenticate(http::Request& request, const http::Response& response); @@ -92,8 +84,8 @@ class HTTP_API Authenticator void updateProxyAuthInfo(http::Request& request); private: - Authenticator(const Authenticator&); - Authenticator& operator=(const Authenticator&); + Authenticator(const Authenticator&) = delete; + Authenticator& operator=(const Authenticator&) = delete; std::string _username; std::string _password; @@ -104,6 +96,7 @@ class HTTP_API Authenticator // Basic Authenticator (rfc2617) // +/// @ingroup http /// This is a utility class for working with HTTP Basic /// Authentication in http::Request objects. class HTTP_API BasicAuthenticator @@ -137,13 +130,13 @@ class HTTP_API BasicAuthenticator void setUsername(const std::string& username); /// Returns the username. - const std::string& username() const; + [[nodiscard]] const std::string& username() const; /// Sets the password. void setPassword(const std::string& password); /// Returns the password. - const std::string& password() const; + [[nodiscard]] const std::string& password() const; /// Adds authentication information to the given http::Request. void authenticate(http::Request& request) const; @@ -158,8 +151,8 @@ class HTTP_API BasicAuthenticator void parseAuthInfo(const std::string& authInfo); private: - BasicAuthenticator(const BasicAuthenticator&); - BasicAuthenticator& operator=(const BasicAuthenticator&); + BasicAuthenticator(const BasicAuthenticator&) = delete; + BasicAuthenticator& operator=(const BasicAuthenticator&) = delete; std::string _username; std::string _password; @@ -171,65 +164,25 @@ class HTTP_API BasicAuthenticator // -bool isBasicCredentials(const std::string& header); /// Returns true if - /// authentication header is - /// for Basic - /// authentication. - -bool isDigestCredentials(const std::string& header); /// Returns true if - /// authentication header - /// is for Digest - /// authentication. - -bool hasBasicCredentials(const http::Request& request); /// Returns true if - /// Authorization with - /// Basic credentials - /// header is present in - /// the request. - -bool hasDigestCredentials(const http::Request& request); /// Returns true if - /// Authorization with - /// Digest credentials - /// header is present - /// in the request. - -bool hasProxyBasicCredentials(const http::Request& request); /// Returns true if - /// Authorization - /// with Basic - /// credentials - /// header is - /// present in the - /// request. - -bool hasProxyDigestCredentials(const http::Request& request); /// Returns true - /// if - /// Authorization - /// with Digest - /// credentials - /// header is - /// present in the - /// request. +[[nodiscard]] bool isBasicCredentials(const std::string& header); +[[nodiscard]] bool isDigestCredentials(const std::string& header); +[[nodiscard]] bool hasBasicCredentials(const http::Request& request); +[[nodiscard]] bool hasDigestCredentials(const http::Request& request); +[[nodiscard]] bool hasProxyBasicCredentials(const http::Request& request); +[[nodiscard]] bool hasProxyDigestCredentials(const http::Request& request); void extractCredentials(const std::string& userInfo, std::string& username, - std::string& password); /// Extracts username and - /// password from user:password - /// information std::string. + std::string& password); -void extractCredentials( - const http::URL& uri, std::string& username, - std::string& password); /// Extracts username and password from the given - /// URI (e.g.: - /// "http://user:pass@sample.com/secret"). +void extractCredentials(const http::URL& uri, std::string& username, + std::string& password); } // namespace http } // namespace scy -#endif // SCY_HTTP_Authenticator_H - - -/// @\} +/// @} // diff --git a/src/http/include/scy/http/client.h b/src/http/include/scy/http/client.h index 0f7f101da..78327ecf6 100644 --- a/src/http/include/scy/http/client.h +++ b/src/http/include/scy/http/client.h @@ -9,9 +9,7 @@ /// @{ -#ifndef SCY_HTTP_Client_H -#define SCY_HTTP_Client_H - +#pragma once #include "scy/http/connection.h" #include "scy/http/websocket.h" @@ -22,16 +20,20 @@ #include "scy/packetio.h" #include "scy/timer.h" +#include + namespace scy { namespace http { class HTTP_API Client; + +/// HTTP client connection for managing request/response lifecycle. class HTTP_API ClientConnection : public Connection { public: - typedef std::shared_ptr Ptr; + using Ptr = std::shared_ptr; /// Create a standalone connection with the given host. ClientConnection(const URL& url, const net::TCPSocket::Ptr& socket = std::make_shared()); @@ -59,12 +61,6 @@ class HTTP_API ClientConnection : public Connection /// /// Throws an exception if the socket is not already or connected. virtual ssize_t send(const char* data, size_t len, int flags = 0) override; - // virtual ssize_t send(const std::string& buf, int flags = 0); - // virtual void sendData(const char* buf, size_t len); //, int flags = 0 - // virtual void sendData(const std::string& buf); //, int flags = 0 - - /// Forcefully closes the HTTP connection. - //virtual void close(); /// Set the output stream for writing response data to. /// The stream pointer is managed internally, @@ -72,7 +68,8 @@ class HTTP_API ClientConnection : public Connection virtual void setReadStream(std::ostream* os); /// Return the cast read stream pointer or nullptr. - template StreamT& readStream() + template + StreamT& readStream() { if (!_readStream) throw std::runtime_error("No stream reader associated with HTTP client."); @@ -99,6 +96,7 @@ class HTTP_API ClientConnection : public Connection Signal Payload; ///< Signals when raw data is received Signal Complete; ///< Signals when the HTTP transaction is complete Signal Close; ///< Signals when the connection is closed + ProgressSignal IncomingProgress; ///< Signals download progress (0-100%) protected: /// Connects to the server endpoint. @@ -108,7 +106,7 @@ class HTTP_API ClientConnection : public Connection http::Message* incomingHeader(); http::Message* outgoingHeader(); - void onSocketConnect(net::Socket& socket); + bool onSocketConnect(net::Socket& socket); protected: URL _url; @@ -120,7 +118,7 @@ class HTTP_API ClientConnection : public Connection }; -typedef std::vector ClientConnectionPtrVec; +using ClientConnectionPtrVec = std::vector; // @@ -135,28 +133,14 @@ inline ClientConnection::Ptr createConnectionT(const URL& url, uv::Loop* loop = if (url.scheme() == "http") { conn = std::make_shared(url, std::make_shared(loop)); - // conn->replaceAdapter(new ConnectionAdapter(conn, HTTP_RESPONSE)); - // conn = std::shared_ptr( - // new ConnectionT(url, std::make_shared(loop)), - // deleter::Deferred()); } else if (url.scheme() == "https") { conn = std::make_shared(url, std::make_shared(loop)); - // conn->replaceAdapter(new ConnectionAdapter(conn, HTTP_RESPONSE)); - // conn = std::shared_ptr( - // new ConnectionT(url, std::make_shared(loop)), - // deleter::Deferred()); } else if (url.scheme() == "ws") { conn = std::make_shared(url, std::make_shared(loop)); - conn->replaceAdapter(new ws::ConnectionAdapter(conn.get(), ws::ClientSide)); - // conn = std::shared_ptr( - // new ConnectionT(url, std::make_shared(loop)), - // deleter::Deferred()); + conn->replaceAdapter(std::make_unique(conn.get(), ws::ClientSide)); } else if (url.scheme() == "wss") { conn = std::make_shared(url, std::make_shared(loop)); - conn->replaceAdapter(new ws::ConnectionAdapter(conn.get(), ws::ClientSide)); - // conn = std::shared_ptr( - // new ConnectionT(url, std::make_shared(loop)), - // deleter::Deferred()); + conn->replaceAdapter(std::make_unique(conn.get(), ws::ClientSide)); } else throw std::runtime_error("Unknown connection type for URL: " + url.str()); @@ -169,6 +153,7 @@ inline ClientConnection::Ptr createConnectionT(const URL& url, uv::Loop* loop = // +/// HTTP client for creating and managing outgoing connections. class HTTP_API Client { public: @@ -228,57 +213,8 @@ inline ClientConnection::Ptr createConnection(const URL& url, http::Client* clie } -#if 0 -class HTTP_API SecureClientConnection: public ClientConnection -{ -public: - SecureClientConnection(Client* client, const URL& url) : //, const net::Address& address - ClientConnection(client, url, net::SSLSocket()) //, address - { - } - - virtual ~SecureClientConnection() - { - } -}; - - -class HTTP_API WebSocketClientConnection: public ClientConnection -{ -public: - WebSocketClientConnection(Client* client, const URL& url) : //, const net::Address& address - ClientConnection(client, url) //, address - { - socket().replaceAdapter(new ws::ConnectionAdapter(*this, ws::ClientSide)); //&socket(), &request(), request(), request() - } - - virtual ~WebSocketClientConnection() - { - } -}; - - -class HTTP_API WebSocketSecureClientConnection: public ClientConnection -{ -public: - WebSocketSecureClientConnection(Client* client, const URL& url) : //, const net::Address& address - ClientConnection(client, url, net::SSLSocket()) //, address - { - socket().replaceAdapter(new ws::ConnectionAdapter(*this, ws::ClientSide)); //(&socket(), &request() - } - - virtual ~WebSocketSecureClientConnection() - { - } -}; -#endif - - } // namespace http } // namespace scy -#endif - - -/// @\} +/// @} diff --git a/src/http/include/scy/http/connection.h b/src/http/include/scy/http/connection.h index 0734b1111..99ed08884 100644 --- a/src/http/include/scy/http/connection.h +++ b/src/http/include/scy/http/connection.h @@ -8,10 +8,7 @@ /// @addtogroup http /// @{ - -#ifndef SCY_HTTP_ServerConnection_H -#define SCY_HTTP_ServerConnection_H - +#pragma once #include "scy/http/parser.h" #include "scy/http/request.h" @@ -22,6 +19,9 @@ #include "scy/packetqueue.h" #include "scy/timer.h" +#include +#include + namespace scy { namespace http { @@ -29,13 +29,14 @@ namespace http { class HTTP_API ConnectionStream; class HTTP_API ConnectionAdapter; +/// @ingroup http class HTTP_API Connection : public net::SocketAdapter { public: - typedef std::shared_ptr Ptr; + using Ptr = std::shared_ptr; Connection(const net::TCPSocket::Ptr& socket = std::make_shared()); - virtual ~Connection(); + virtual ~Connection() noexcept; virtual void onHeaders() = 0; virtual void onPayload(const MutableBuffer&) = 0; @@ -53,36 +54,39 @@ class HTTP_API Connection : public net::SocketAdapter virtual void close(); /// Return true if the connection is closed. - bool closed() const; + [[nodiscard]] bool closed() const; /// Return the error object if any. - scy::Error error() const; - - /// Return true if the server did not give us - /// a proper response within the allotted time. - // bool expired() const; + [[nodiscard]] scy::Error error() const; /// Return true if headers should be automatically sent. - bool shouldSendHeader() const; + [[nodiscard]] bool shouldSendHeader() const; /// Set true to prevent auto-sending HTTP headers. void shouldSendHeader(bool flag); - /// Assign the new ConnectionAdapter and setup the chain - /// The flow is: Connection <-> ConnectionAdapter <-> Socket - virtual void replaceAdapter(net::SocketAdapter* adapter); + /// Assign the new ConnectionAdapter and setup the chain. + /// The flow is: Connection <-> ConnectionAdapter <-> Socket. + /// Takes ownership of the adapter (deferred deletion via uv loop). + virtual void replaceAdapter(std::unique_ptr adapter); + + /// Overload for nullptr (used in destructor to clear adapter). + virtual void replaceAdapter(std::nullptr_t); + + /// Return true if the connection uses TLS/SSL. + [[nodiscard]] bool secure() const; /// Return the underlying socket pointer. - net::TCPSocket::Ptr& socket(); + [[nodiscard]] net::TCPSocket::Ptr& socket(); /// Return the underlying adapter pointer. - net::SocketAdapter* adapter() const; + [[nodiscard]] net::SocketAdapter* adapter() const; /// The HTTP request headers. - Request& request(); + [[nodiscard]] Request& request(); /// The HTTP response headers. - Response& response(); + [[nodiscard]] Response& response(); virtual http::Message* incomingHeader() = 0; virtual http::Message* outgoingHeader() = 0; @@ -93,10 +97,10 @@ class HTTP_API Connection : public net::SocketAdapter virtual void setError(const scy::Error& err); /// net::SocketAdapter interface - virtual void onSocketConnect(net::Socket& socket) override; - virtual void onSocketRecv(net::Socket& socket, const MutableBuffer& buffer, const net::Address& peerAddress) override; - virtual void onSocketError(net::Socket& socket, const scy::Error& error) override; - virtual void onSocketClose(net::Socket& socket) override; + virtual bool onSocketConnect(net::Socket& socket) override; + virtual bool onSocketRecv(net::Socket& socket, const MutableBuffer& buffer, const net::Address& peerAddress) override; + virtual bool onSocketError(net::Socket& socket, const scy::Error& error) override; + virtual bool onSocketClose(net::Socket& socket) override; protected: net::TCPSocket::Ptr _socket; @@ -117,11 +121,13 @@ class HTTP_API Connection : public net::SocketAdapter // +/// @ingroup http /// Default HTTP socket adapter for reading and writing HTTP messages -class HTTP_API ConnectionAdapter : public ParserObserver, public net::SocketAdapter +class HTTP_API ConnectionAdapter : public ParserObserver + , public net::SocketAdapter { public: - ConnectionAdapter(Connection* connection, http_parser_type type); + ConnectionAdapter(Connection* connection, llhttp_type_t type); virtual ~ConnectionAdapter(); virtual ssize_t send(const char* data, size_t len, int flags = 0); @@ -132,14 +138,12 @@ class HTTP_API ConnectionAdapter : public ParserObserver, public net::SocketAdap /// matches the current receiver. virtual void removeReceiver(SocketAdapter* adapter); - Parser& parser(); - Connection* connection(); + [[nodiscard]] Parser& parser(); + [[nodiscard]] Connection* connection(); protected: /// SocketAdapter interface - virtual void onSocketRecv(net::Socket& socket, const MutableBuffer& buffer, const net::Address& peerAddress); - // virtual void onSocketError(const Error& error); - // virtual void onSocketClose(); + virtual bool onSocketRecv(net::Socket& socket, const MutableBuffer& buffer, const net::Address& peerAddress); /// HTTP Parser interface virtual void onParserHeader(const std::string& name, const std::string& value); @@ -158,7 +162,8 @@ class HTTP_API ConnectionAdapter : public ParserObserver, public net::SocketAdap // -// HTTP progress signal for upload and download progress notifications. +/// @ingroup http +/// HTTP progress signal for upload and download progress notifications. class HTTP_API ProgressSignal : public Signal { public: @@ -173,11 +178,13 @@ class HTTP_API ProgressSignal : public Signal { } - double progress() const { return (current / (total * 1.0)) * 100; } + [[nodiscard]] double progress() const { return (current / (total * 1.0)) * 100; } void update(int nread) { - assert(current <= total); + if (current > total) { + throw std::runtime_error("ProgressSignal: current exceeds total"); + } current += nread; emit(progress()); } @@ -189,6 +196,7 @@ class HTTP_API ProgressSignal : public Signal // +/// @ingroup http /// Packet stream wrapper for a HTTP connection. class HTTP_API ConnectionStream : public net::SocketAdapter { @@ -200,7 +208,7 @@ class HTTP_API ConnectionStream : public net::SocketAdapter virtual ssize_t send(const char* data, size_t len, int flags = 0); /// Return a reference to the underlying connection. - Connection::Ptr connection(); + [[nodiscard]] Connection::Ptr connection(); /// The Outgoing stream is responsible for packetizing /// raw application data into the agreed upon HTTP @@ -217,8 +225,7 @@ class HTTP_API ConnectionStream : public net::SocketAdapter ProgressSignal OutgoingProgress; ///< Fired on upload progress protected: - //void onRecv(net::Socket& socket, const MutableBuffer& buffer, const net::Address& peerAddress); - virtual void onSocketRecv(net::Socket& socket, const MutableBuffer& buffer, const net::Address& peerAddress); + virtual bool onSocketRecv(net::Socket& socket, const MutableBuffer& buffer, const net::Address& peerAddress); Connection::Ptr _connection; }; @@ -228,7 +235,4 @@ class HTTP_API ConnectionStream : public net::SocketAdapter } // namespace scy -#endif - - -/// @\} +/// @} diff --git a/src/http/include/scy/http/cookie.h b/src/http/include/scy/http/cookie.h index b57587c7f..0ca42b2b7 100644 --- a/src/http/include/scy/http/cookie.h +++ b/src/http/include/scy/http/cookie.h @@ -8,20 +8,18 @@ /// @addtogroup http /// @{ +#pragma once -#ifndef SCY_HTTP_Cookie_H -#define SCY_HTTP_Cookie_H - - +#include "scy/collection.h" #include "scy/http/http.h" #include "scy/net/net.h" -#include "scy/collection.h" namespace scy { namespace http { +/// @ingroup http /// This class represents a HTTP Cookie. /// /// A cookie is a small amount of information sent by a Web @@ -74,13 +72,13 @@ class HTTP_API Cookie /// Returns the version of the cookie, which is /// either 0 or 1. - int getVersion() const; + [[nodiscard]] int getVersion() const; /// Sets the name of the cookie. void setName(const std::string& name); /// Returns the name of the cookie. - const std::string& getName() const; + [[nodiscard]] const std::string& getName() const; /// Sets the value of the cookie. /// @@ -93,7 +91,7 @@ class HTTP_API Cookie void setValue(const std::string& value); /// Returns the value of the cookie. - const std::string& getValue() const; + [[nodiscard]] const std::string& getValue() const; /// Sets the comment for the cookie. /// @@ -101,19 +99,19 @@ class HTTP_API Cookie void setComment(const std::string& comment); /// Returns the comment for the cookie. - const std::string& getComment() const; + [[nodiscard]] const std::string& getComment() const; /// Sets the domain for the cookie. void setDomain(const std::string& domain); /// Returns the domain for the cookie. - const std::string& getDomain() const; + [[nodiscard]] const std::string& getDomain() const; /// Sets the path for the cookie. void setPath(const std::string& path); /// Returns the path for the cookie. - const std::string& getPath() const; + [[nodiscard]] const std::string& getPath() const; /// Sets the value of the secure flag for /// the cookie. @@ -121,7 +119,7 @@ class HTTP_API Cookie /// Returns the value of the secure flag /// for the cookie. - bool getSecure() const; + [[nodiscard]] bool getSecure() const; /// Sets the maximum age in seconds for /// the cookie. @@ -135,40 +133,22 @@ class HTTP_API Cookie /// Returns the maximum age in seconds for /// the cookie. - int getMaxAge() const; + [[nodiscard]] int getMaxAge() const; /// Sets the HttpOnly flag for the cookie. void setHttpOnly(bool flag = true); /// Returns true if the cookie's HttpOnly flag is set. - bool getHttpOnly() const; + [[nodiscard]] bool getHttpOnly() const; /// Returns a std::string representation of the cookie, /// suitable for use in a Set-Cookie header. - std::string toString() const; + [[nodiscard]] std::string toString() const; /// Escapes the given std::string by replacing all /// non-alphanumeric characters with escape /// sequences in the form %xx, where xx is the /// hexadecimal character code. - /// - /// The following characters will be replaced - /// with escape sequences: - /// - percent sign % - /// - less-than and greater-than < and > - /// - curly brackets { and } - /// - square brackets [ and ] - /// - parenthesis ( and ) - /// - solidus / - /// - vertical line | - /// - reverse solidus (backslash /) - /// - quotation mark " - /// - apostrophe ' - /// - circumflex accent ^ - /// - grave accent ` - /// - comma and semicolon , and ; - - /// - whitespace and control characters static std::string escape(const std::string& str); /// Unescapes the given std::string by replacing all @@ -247,10 +227,7 @@ inline bool Cookie::getHttpOnly() const } // namespace scy -#endif // SCY_HTTP_Cookie_H - - -/// @\} +/// @} // diff --git a/src/http/include/scy/http/form.h b/src/http/include/scy/http/form.h index be31b0dd5..b40706624 100644 --- a/src/http/include/scy/http/form.h +++ b/src/http/include/scy/http/form.h @@ -8,16 +8,16 @@ /// @addtogroup http /// @{ +#pragma once -#ifndef SCY_HTTP_Form_H -#define SCY_HTTP_Form_H - - -#include "scy/http/http.h" #include "scy/collection.h" +#include "scy/http/http.h" #include "scy/packetstream.h" #include "scy/thread.h" +#include +#include + namespace scy { namespace http { @@ -32,16 +32,16 @@ class HTTP_API FormPart; // HTML Form Writer // +/// @ingroup http /// FormWriter is a HTTP client connection adapter for writing HTML forms. /// /// This class runs in its own thread so as not to block the event loop /// while uploading big files. Class members are not synchronized hence /// they should not be accessed while the form is sending, not that there /// would be any reason to do so. -class HTTP_API FormWriter : - public NVCollection, - public PacketSource, - public basic::Startable +class HTTP_API FormWriter : public NVCollection + , public PacketSource + , public basic::Startable { public: /// Creates the FormWriter that uses the given connection and @@ -68,24 +68,12 @@ class HTTP_API FormWriter : void stop(); /// Returns true if the request is complete. - bool complete() const; + [[nodiscard]] bool complete() const; /// Returns true if the request is cancelled. - bool cancelled() const; + [[nodiscard]] bool cancelled() const; /// Prepares the outgoing HTTP request object for submitting the form. - /// - /// If the request method is GET, the encoded form is appended to the - /// request URI as query std::string. Otherwise (the method is - /// POST), the form's content type is set to the form's encoding. - /// The form's parameters must be written to the - /// request body separately, with a call to write. - /// If the request's HTTP version is HTTP/1.0: - /// - persistent connections are disabled - /// - the content transfer encoding is set to identity encoding - /// Otherwise, if the request's HTTP version is HTTP/1.1: - /// - the request's persistent connection state is left unchanged - /// - the content transfer encoding is set to chunked void prepareSubmit(); /// Processes the entire stream and calculates the content length. @@ -96,43 +84,29 @@ class HTTP_API FormWriter : /// the client connection. void writeUrl(std::ostream& ostr); -#if 0 - /// Writes the complete "multipart/form-data" request to the - /// client connection. This method is blocking, and should be - /// called from a thread, especially when sending large files. - void writeMultipart(); -#endif - /// Writes the next multipart "multipart/form-data" encoded - /// to the client connection. This method is non-blocking, // and is - /// suitable for use with the event loop. + /// to the client connection. This method is non-blocking, + /// and is suitable for use with the event loop. void writeMultipartChunk(); /// Called asynchronously by the Runner to write the next message chunk. - /// If "multipart/form-data" the next multipart chunk will be written. - /// If "application/x-www-form-urlencoded" the entire message will be - /// written. - /// The complete flag will be set when the entire request has been written. void writeAsync(); /// Sets the encoding used for posting the form. - /// - /// Encoding must be either "application/x-www-form-urlencoded" - /// (which is the default) or "multipart/form-data". void setEncoding(const std::string& encoding); /// Returns the encoding used for posting the form. - const std::string& encoding() const; + [[nodiscard]] const std::string& encoding() const; /// Sets the boundary to use for separating form parts. /// Must be set before prepareSubmit() is called. void setBoundary(const std::string& boundary); /// Returns the MIME boundary used for writing multipart form data. - const std::string& boundary() const; + [[nodiscard]] const std::string& boundary() const; /// The associated HTTP client connection. - ConnectionStream& connection(); + [[nodiscard]] ConnectionStream& connection(); /// The outgoing packet emitter. PacketSignal emitter; @@ -143,14 +117,13 @@ class HTTP_API FormWriter : protected: /// Creates the FormWriter that uses the given encoding. - /// - /// Encoding must be either "application/x-www-form-urlencoded" - /// (which is the default) or "multipart/form-data". FormWriter(ConnectionStream& conn, std::shared_ptr runner, const std::string& encoding = FormWriter::ENCODING_URL); FormWriter(const FormWriter&) = delete; FormWriter& operator=(const FormWriter&) = delete; + FormWriter(FormWriter&&) = delete; + FormWriter& operator=(FormWriter&&) = delete; /// Writes the message boundary std::string, followed /// by the message header to the output stream. @@ -160,9 +133,6 @@ class HTTP_API FormWriter : void writeEnd(std::ostream& ostr); /// Creates a random boundary std::string. - /// - /// The std::string always has the form boundary-XXXXXXXXXXXX, - /// where XXXXXXXXXXXX is a randomly generate number. static std::string createBoundary(); /// Updates the upload progress via the associated @@ -176,10 +146,10 @@ class HTTP_API FormWriter : struct Part { std::string name; - FormPart* part; + std::unique_ptr part; }; - typedef std::deque PartQueue; + using PartQueue = std::deque; ConnectionStream& _stream; std::shared_ptr _runner; @@ -197,6 +167,7 @@ class HTTP_API FormWriter : // Form Part // +/// @ingroup http /// An implementation of FormPart. class HTTP_API FormPart { @@ -222,16 +193,16 @@ class HTTP_API FormPart /// Returns a NVCollection containing additional header /// fields for the part. - NVCollection& headers(); + [[nodiscard]] NVCollection& headers(); /// Returns true if this is the initial write. - virtual bool initialWrite() const; + [[nodiscard]] virtual bool initialWrite() const; /// Returns the MIME type for this part or attachment. - const std::string& contentType() const; + [[nodiscard]] const std::string& contentType() const; /// Returns the length of the current part. - virtual uint64_t length() const = 0; + [[nodiscard]] virtual uint64_t length() const = 0; protected: std::string _contentType; @@ -245,6 +216,7 @@ class HTTP_API FormPart // File Part // +/// @ingroup http /// An implementation of FilePart for plain files. class HTTP_API FilePart : public FormPart { @@ -292,32 +264,19 @@ class HTTP_API FilePart : public FormPart virtual void write(std::ostream& ostr); /// Returns the filename portion of the path. - const std::string& filename() const; + [[nodiscard]] const std::string& filename() const; /// Returns the file input stream. - std::ifstream& stream(); + [[nodiscard]] std::ifstream& stream(); /// Returns the length of the current part. - virtual uint64_t length() const; - - // /// Returns a NVCollection containing additional header - // /// fields for the part. - // NVCollection& headers(); - // - // /// Returns the MIME type for this part or attachment. - // const std::string& contentType() const; - // - // /// Returns the file size. - // uint64_t fileSize() const; + [[nodiscard]] virtual uint64_t length() const; protected: - // std::string _contentType; std::string _path; std::string _filename; std::ifstream _istr; uint64_t _fileSize; - // uint64_t _nWritten; - // NVCollection _headers; }; @@ -325,6 +284,7 @@ class HTTP_API FilePart : public FormPart // String Part // +/// @ingroup http /// An implementation of StringPart for plain files. class HTTP_API StringPart : public FormPart { @@ -349,7 +309,7 @@ class HTTP_API StringPart : public FormPart virtual void write(std::ostream& ostr); /// Returns the length of the current part. - virtual uint64_t length() const; + [[nodiscard]] virtual uint64_t length() const; protected: std::string _data; @@ -360,10 +320,7 @@ class HTTP_API StringPart : public FormPart } // namespace scy -#endif // SCY_HTTP_Form_H - - -/// @\} +/// @} // Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. diff --git a/src/http/include/scy/http/http.h b/src/http/include/scy/http/http.h index f94acf9f1..c020c18e1 100644 --- a/src/http/include/scy/http/http.h +++ b/src/http/include/scy/http/http.h @@ -8,27 +8,18 @@ /// @addtogroup http /// @{ - -#ifndef SCY_HTTP_h -#define SCY_HTTP_h - +#pragma once #include "scy/base.h" // Shared library exports #if defined(SCY_WIN) && defined(SCY_SHARED_LIBRARY) - #if defined(HTTP_EXPORTS) - #define HTTP_API __declspec(dllexport) - #else - #define HTTP_API __declspec(dllimport) - #endif +#if defined(HTTP_EXPORTS) +#define HTTP_API __declspec(dllexport) #else - #define HTTP_API // nothing +#define HTTP_API __declspec(dllimport) +#endif +#else +#define HTTP_API // nothing #endif - - -#endif // SCY_HTTP_H - - -/// @\} diff --git a/src/http/include/scy/http/message.h b/src/http/include/scy/http/message.h index 53fb18636..72fa35d0c 100644 --- a/src/http/include/scy/http/message.h +++ b/src/http/include/scy/http/message.h @@ -8,19 +8,17 @@ /// @addtogroup http /// @{ +#pragma once -#ifndef SCY_HTTP_Message_H -#define SCY_HTTP_Message_H - - -#include "scy/http/http.h" #include "scy/collection.h" +#include "scy/http/http.h" namespace scy { namespace http { +/// @ingroup http /// The base class for Request and Response. /// /// Defines the common properties of all HTTP messages. @@ -33,7 +31,7 @@ class HTTP_API Message : public NVCollection void setVersion(const std::string& version); /// Returns the HTTP version for this message. - const std::string& getVersion() const; + [[nodiscard]] const std::string& getVersion() const; /// Sets the Content-Length header. /// @@ -44,10 +42,10 @@ class HTTP_API Message : public NVCollection /// Returns the content length for this message, /// which may be UNKNOWN_CONTENT_LENGTH if /// no Content-Length header is present. - uint64_t getContentLength() const; + [[nodiscard]] uint64_t getContentLength() const; /// Returns true if a Content-Length header is present. - bool hasContentLength() const; + [[nodiscard]] bool hasContentLength() const; /// Sets the transfer encoding for this message. /// @@ -55,22 +53,20 @@ class HTTP_API Message : public NVCollection /// or CHUNKED_TRANSFER_CODING. void setTransferEncoding(const std::string& transferEncoding); - /// Returns the transfer encoding used for this - /// message. + /// Returns the transfer encoding used for this message. /// /// Normally, this is the value of the Transfer-Encoding /// header field. If no such field is present, /// returns IDENTITY_TRANSFER_CODING. - const std::string& getTransferEncoding() const; + [[nodiscard]] const std::string& getTransferEncoding() const; /// If flag is true, sets the Transfer-Encoding header to - /// chunked. Otherwise, removes the Transfer-Encoding - /// header. + /// chunked. Otherwise, removes the Transfer-Encoding header. void setChunkedTransferEncoding(bool flag); /// Returns true if the Transfer-Encoding header is set /// and its value is chunked. - bool isChunkedTransferEncoding() const; + [[nodiscard]] bool isChunkedTransferEncoding() const; /// Sets the content type for this message. /// @@ -82,7 +78,7 @@ class HTTP_API Message : public NVCollection /// /// If no Content-Type header is present, /// returns UNKNOWN_CONTENT_TYPE. - const std::string& getContentType() const; + [[nodiscard]] const std::string& getContentType() const; /// Sets the value of the Connection header field. /// @@ -91,11 +87,10 @@ class HTTP_API Message : public NVCollection void setKeepAlive(bool keepAlive); /// Returns true if - /// * the message has a Connection header field and its value is - /// "Keep-Alive" + /// * the message has a Connection header field and its value is "Keep-Alive" /// * the message is a HTTP/1.1 message and not Connection header is set /// Returns false otherwise. - bool getKeepAlive() const; + [[nodiscard]] bool getKeepAlive() const; /// Writes the message header to the given output stream. /// @@ -129,7 +124,7 @@ class HTTP_API Message : public NVCollection protected: std::string _version; - + /// Creates the Message with version HTTP/1.0. Message(); @@ -146,7 +141,4 @@ class HTTP_API Message : public NVCollection } // namespace scy -#endif // SCY_HTTP_Message_H - - -/// @\} +/// @} diff --git a/src/http/include/scy/http/packetizers.h b/src/http/include/scy/http/packetizers.h index 0a576ddd1..6b166cf7a 100644 --- a/src/http/include/scy/http/packetizers.h +++ b/src/http/include/scy/http/packetizers.h @@ -8,10 +8,7 @@ /// @addtogroup http /// @{ - -#ifndef SCY_HTTP_Packetizers_H -#define SCY_HTTP_Packetizers_H - +#pragma once #include "scy/http/connection.h" #include "scy/signal.h" @@ -27,6 +24,8 @@ namespace http { // +/// @ingroup http +/// HTTP chunked transfer encoding adapter for streaming responses. class HTTP_API ChunkedAdapter : public IPacketizer { public: @@ -78,10 +77,6 @@ class HTTP_API ChunkedAdapter : public IPacketizer else { std::ostringstream hst; hst << "HTTP/1.1 200 OK\r\n" - // Note: If Cache-Control: no-store is not used Chrome's - // (27.0.1453.110) - // memory usage grows exponentially for HTTP streaming: - // https://code.google.com/p/chromium/issues/detail?id=28035 << "Cache-Control: no-store, no-cache, max-age=0, " "must-revalidate\r\n" << "Cache-Control: post-check=0, pre-check=0, FALSE\r\n" @@ -143,6 +138,8 @@ class HTTP_API ChunkedAdapter : public IPacketizer // +/// @ingroup http +/// HTTP multipart encoding adapter for multipart/x-mixed-replace streaming. class HTTP_API MultipartAdapter : public IPacketizer { public: @@ -241,7 +238,4 @@ class HTTP_API MultipartAdapter : public IPacketizer } // namespace scy -#endif - - -/// @\} +/// @} diff --git a/src/http/include/scy/http/parser.h b/src/http/include/scy/http/parser.h index ec67d7593..d731c4614 100644 --- a/src/http/include/scy/http/parser.h +++ b/src/http/include/scy/http/parser.h @@ -8,21 +8,20 @@ /// @addtogroup http /// @{ +#pragma once #include "scy/http/request.h" #include "scy/http/response.h" #include "scy/net/socket.h" -#include - - -#ifndef SCY_HTTP_Parser_H -#define SCY_HTTP_Parser_H +#include namespace scy { namespace http { +/// @ingroup http +/// Abstract observer interface for HTTP parser events. class HTTP_API ParserObserver { public: @@ -35,14 +34,21 @@ class HTTP_API ParserObserver }; +/// @ingroup http +/// HTTP request/response parser using the llhttp library. class HTTP_API Parser { public: Parser(http::Response* response); Parser(http::Request* request); - Parser(http_parser_type type); + Parser(llhttp_type_t type); ~Parser(); + Parser(const Parser&) = delete; + Parser& operator=(const Parser&) = delete; + Parser(Parser&&) = delete; + Parser& operator=(Parser&&) = delete; + /// Parse a HTTP packet. /// /// Returns true of the message is complete, false if incomplete. @@ -54,17 +60,17 @@ class HTTP_API Parser /// Returns true if parsing is complete, either /// in success or error. - bool complete() const; + [[nodiscard]] bool complete() const; /// Returns true if the connection should be upgraded. - bool upgrade() const; + [[nodiscard]] bool upgrade() const; void setRequest(http::Request* request); void setResponse(http::Response* response); void setObserver(ParserObserver* observer); - http::Message* message(); - ParserObserver* observer() const; + [[nodiscard]] http::Message* message(); + [[nodiscard]] ParserObserver* observer() const; protected: void init(); @@ -75,17 +81,17 @@ class HTTP_API Parser void onHeadersEnd(); void onBody(const char* buf, size_t len); void onMessageEnd(); - void onError(unsigned errnum, const std::string& message = ""); - - /// http_parser callbacks - static int on_message_begin(http_parser* parser); - static int on_url(http_parser* parser, const char* at, size_t len); - static int on_status(http_parser* parser, const char* at, size_t len); - static int on_header_field(http_parser* parser, const char* at, size_t len); - static int on_header_value(http_parser* parser, const char* at, size_t len); - static int on_headers_complete(http_parser* parser); - static int on_body(http_parser* parser, const char* at, size_t len); - static int on_message_complete(http_parser* parser); + void onError(llhttp_errno_t errnum, const std::string& message = ""); + + /// llhttp callbacks + static int on_message_begin(llhttp_t* parser); + static int on_url(llhttp_t* parser, const char* at, size_t len); + static int on_status(llhttp_t* parser, const char* at, size_t len); + static int on_header_field(llhttp_t* parser, const char* at, size_t len); + static int on_header_value(llhttp_t* parser, const char* at, size_t len); + static int on_headers_complete(llhttp_t* parser); + static int on_body(llhttp_t* parser, const char* at, size_t len); + static int on_message_complete(llhttp_t* parser); protected: ParserObserver* _observer; @@ -93,9 +99,9 @@ class HTTP_API Parser http::Response* _response; http::Message* _message; - http_parser _parser; - http_parser_settings _settings; - http_parser_type _type; + llhttp_t _parser; + llhttp_settings_t _settings; + llhttp_type_t _type; bool _wasHeaderValue; std::string _lastHeaderField; @@ -103,7 +109,7 @@ class HTTP_API Parser bool _complete; bool _upgrade; - + Error _error; }; @@ -112,7 +118,4 @@ class HTTP_API Parser } // namespace scy -#endif // SCY_HTTP_Parser_H - - -/// @\} +/// @} diff --git a/src/http/include/scy/http/request.h b/src/http/include/scy/http/request.h index 99f184377..fc584efed 100644 --- a/src/http/include/scy/http/request.h +++ b/src/http/include/scy/http/request.h @@ -8,10 +8,7 @@ /// @addtogroup http /// @{ - -#ifndef SCY_Request_H -#define SCY_Request_H - +#pragma once #include "scy/base.h" #include "scy/collection.h" @@ -66,13 +63,13 @@ class HTTP_API Request : public http::Message void setMethod(const std::string& method); /// Returns the method. - const std::string& getMethod() const; + [[nodiscard]] const std::string& getMethod() const; /// Sets the request URI. void setURI(const std::string& uri); /// Returns the request URI. - const std::string& getURI() const; + [[nodiscard]] const std::string& getURI() const; /// Sets the value of the Host header field. void setHost(const std::string& host); @@ -88,7 +85,7 @@ class HTTP_API Request : public http::Message /// /// Throws a NotFoundException if the request /// does not have a Host header field. - const std::string& getHost() const; + [[nodiscard]] const std::string& getHost() const; /// Adds a Cookie header with the names and /// values from cookies. @@ -103,7 +100,7 @@ class HTTP_API Request : public http::Message /// Returns true if the request contains authentication /// information in the form of an Authorization header. - bool hasCredentials() const; + [[nodiscard]] bool hasCredentials() const; /// Returns the authentication scheme and additional authentication /// information contained in this request. @@ -118,7 +115,7 @@ class HTTP_API Request : public http::Message /// Returns true if the request contains proxy authentication /// information in the form of an Proxy-Authorization header. - bool hasProxyCredentials() const; + [[nodiscard]] bool hasProxyCredentials() const; /// Returns the proxy authentication scheme and additional proxy /// authentication @@ -166,7 +163,4 @@ class HTTP_API Request : public http::Message } // namespace scy -#endif - - -/// @\} +/// @} diff --git a/src/http/include/scy/http/response.h b/src/http/include/scy/http/response.h index 2dced6a7f..915049f68 100644 --- a/src/http/include/scy/http/response.h +++ b/src/http/include/scy/http/response.h @@ -8,10 +8,7 @@ /// @addtogroup http /// @{ - -#ifndef SCY_HTTP_Response_H -#define SCY_HTTP_Response_H - +#pragma once #include "scy/datetime.h" #include "scy/http/cookie.h" @@ -107,13 +104,13 @@ class HTTP_API Response : public http::Message void setStatus(StatusCode status); /// Returns the HTTP status code. - StatusCode getStatus() const; + [[nodiscard]] StatusCode getStatus() const; /// Sets the HTTP reason phrase. void setReason(const std::string& reason); /// Returns the HTTP reason phrase. - const std::string& getReason() const; + [[nodiscard]] const std::string& getReason() const; /// Sets the HTTP status code and reason phrase. void setStatusAndReason(StatusCode status, const std::string& reason); @@ -122,7 +119,7 @@ class HTTP_API Response : public http::Message void setDate(const Timestamp& dateTime); /// Returns the value of the Date header. - Timestamp getDate() const; + [[nodiscard]] Timestamp getDate() const; /// Adds the cookie to the response by /// adding a Set-Cookie header. @@ -139,8 +136,8 @@ class HTTP_API Response : public http::Message /// Writes the HTTP response headers to the given output string. void write(std::string& str) const override; - /// Returns true if the HTTP response code was successful (>= 400). - virtual bool success() const; + /// Returns true if the HTTP response code was successful (< 400). + [[nodiscard]] virtual bool success() const; friend std::ostream& operator<<(std::ostream& stream, const Response& res) { @@ -154,14 +151,11 @@ class HTTP_API Response : public http::Message }; -const char* getStatusCodeReason(StatusCode status); +[[nodiscard]] const char* getStatusCodeReason(StatusCode status); } // namespace http } // namespace scy -#endif - - -/// @\} +/// @} diff --git a/src/http/include/scy/http/server.h b/src/http/include/scy/http/server.h index b8d97ced3..fd8481102 100644 --- a/src/http/include/scy/http/server.h +++ b/src/http/include/scy/http/server.h @@ -8,10 +8,7 @@ /// @addtogroup http /// @{ - -#ifndef SCY_HTTP_Server_H -#define SCY_HTTP_Server_H - +#pragma once #include "scy/base.h" #include "scy/datetime.h" @@ -23,6 +20,7 @@ #include "scy/net/socket.h" #include "scy/timer.h" #include +#include namespace scy { @@ -37,15 +35,15 @@ class HTTP_API ServerResponder; class HTTP_API ServerConnection : public Connection { public: - typedef std::shared_ptr Ptr; + using Ptr = std::shared_ptr; ServerConnection(Server& server, net::TCPSocket::Ptr socket); virtual ~ServerConnection(); - Server& server(); + [[nodiscard]] Server& server(); Signal Payload; ///< Signals when raw data is received - Signal Close; ///< Signals when the connection is closed + Signal Close; ///< Signals when the connection is closed protected: virtual void onHeaders() override; @@ -58,7 +56,7 @@ class HTTP_API ServerConnection : public Connection protected: Server& _server; - ServerResponder* _responder; + std::unique_ptr _responder; bool _upgrade; }; @@ -74,8 +72,8 @@ class HTTP_API ServerConnection : public Connection class HTTP_API ServerResponder { public: - ServerResponder(ServerConnection& connection) : - _connection(connection) + ServerResponder(ServerConnection& connection) + : _connection(connection) { } @@ -86,17 +84,17 @@ class HTTP_API ServerResponder virtual void onRequest(Request& /* request */, Response& /* response */) {} virtual void onClose() {}; - ServerConnection& connection() + [[nodiscard]] ServerConnection& connection() { return _connection; } - Request& request() + [[nodiscard]] Request& request() { return _connection.request(); } - Response& response() + [[nodiscard]] Response& response() { return _connection.response(); } @@ -110,10 +108,6 @@ class HTTP_API ServerResponder }; - -// ------------------------------------------------------------------- -// - /// This implementation of a ServerConnectionFactory /// is used by HTTP Server to create ServerConnection objects. class HTTP_API ServerConnectionFactory @@ -131,16 +125,13 @@ class HTTP_API ServerConnectionFactory /// Factory method for instantiating the ServerResponder /// instance using the given ServerConnection. - virtual ServerResponder* createResponder(ServerConnection& connection) + virtual std::unique_ptr createResponder(ServerConnection& connection) { return nullptr; } }; -// ------------------------------------------------------------------- -// - /// HTTP server implementation. /// /// This HTTP server is not strictly standards compliant. @@ -150,11 +141,11 @@ class HTTP_API Server : public net::SocketAdapter { public: Server(const std::string& host, short port, - net::TCPSocket::Ptr socket = net::makeSocket(), - ServerConnectionFactory* factory = new ServerConnectionFactory()); + net::TCPSocket::Ptr socket = net::makeSocket(), + std::unique_ptr factory = std::make_unique()); Server(const net::Address& address, - net::TCPSocket::Ptr socket = net::makeSocket(), - ServerConnectionFactory* factory = new ServerConnectionFactory()); + net::TCPSocket::Ptr socket = net::makeSocket(), + std::unique_ptr factory = std::make_unique()); virtual ~Server(); /// Start the HTTP server. @@ -164,7 +155,7 @@ class HTTP_API Server : public net::SocketAdapter void shutdown(); /// Return the server bind address. - net::Address& address(); + [[nodiscard]] net::Address& address(); /// Signals when a new connection has been created. /// A reference to the new connection object is provided. @@ -174,19 +165,19 @@ class HTTP_API Server : public net::SocketAdapter NullSignal Shutdown; protected: - ServerResponder* createResponder(ServerConnection& conn); + std::unique_ptr createResponder(ServerConnection& conn); void onClientSocketAccept(const net::TCPSocket::Ptr& socket); void onConnectionReady(ServerConnection& conn); void onConnectionClose(ServerConnection& conn); - void onSocketClose(net::Socket& socket); + bool onSocketClose(net::Socket& socket); void onTimer(); protected: net::Address _address; net::TCPSocket::Ptr _socket; Timer _timer; - ServerConnectionFactory* _factory; + std::unique_ptr _factory; std::vector _connections; friend class ServerConnection; @@ -197,7 +188,4 @@ class HTTP_API Server : public net::SocketAdapter } // namespace scy -#endif - - -/// @\} +/// @} diff --git a/src/http/include/scy/http/url.h b/src/http/include/scy/http/url.h index 3f2093a3f..a880bed3e 100644 --- a/src/http/include/scy/http/url.h +++ b/src/http/include/scy/http/url.h @@ -8,22 +8,21 @@ /// @addtogroup http /// @{ +#pragma once -#ifndef SCY_HTTP_URL_H -#define SCY_HTTP_URL_H - - -#include "scy/http/http.h" #include "scy/collection.h" -#include +#include "scy/http/http.h" + +#include +#include +#include namespace scy { namespace http { -/// An RFC 3986 based URL which uses an external c -/// library to do the heavy lifting. +/// An RFC 3986 based URL parser. /// Constructors and assignment operators will throw /// a SyntaxException if the URL is invalid. class HTTP_API URL @@ -32,12 +31,12 @@ class HTTP_API URL URL(); URL(const char* url); URL(const std::string& url); - URL(const std::string& scheme, const std::string& authority); - URL(const std::string& scheme, const std::string& authority, - const std::string& pathEtc); - URL(const std::string& scheme, const std::string& authority, - const std::string& path, const std::string& query, - const std::string& fragment = ""); + URL(std::string_view scheme, std::string_view authority); + URL(std::string_view scheme, std::string_view authority, + std::string_view pathEtc); + URL(std::string_view scheme, std::string_view authority, + std::string_view path, std::string_view query, + std::string_view fragment = ""); ~URL(); URL& operator=(const URL& uri); @@ -51,34 +50,34 @@ class HTTP_API URL /// RFC 3986 based URL encoding based on JavaScript's /// encodeURIComponent() - static std::string encode(const std::string& str); + static std::string encode(std::string_view str); /// RFC 3986 based URL decoding based on JavaScript's /// decodeURIComponent() - static std::string decode(const std::string& str); + static std::string decode(std::string_view str); public: - std::string scheme() const; - std::string userInfo() const; - std::string host() const; - uint16_t port() const; - std::string authority() const; - std::string path() const; - std::string pathEtc() const; - std::string query() const; - std::string fragment() const; - - bool hasSchema() const; - bool hasUserInfo() const; - bool hasHost() const; - bool hasPort() const; - bool hasPath() const; - bool hasQuery() const; - bool hasFragment() const; - - bool valid() const; - - std::string str() const; + [[nodiscard]] std::string scheme() const; + [[nodiscard]] std::string userInfo() const; + [[nodiscard]] std::string host() const; + [[nodiscard]] uint16_t port() const; + [[nodiscard]] std::string authority() const; + [[nodiscard]] std::string path() const; + [[nodiscard]] std::string pathEtc() const; + [[nodiscard]] std::string query() const; + [[nodiscard]] std::string fragment() const; + + [[nodiscard]] bool hasSchema() const; + [[nodiscard]] bool hasUserInfo() const; + [[nodiscard]] bool hasHost() const; + [[nodiscard]] bool hasPort() const; + [[nodiscard]] bool hasPath() const; + [[nodiscard]] bool hasQuery() const; + [[nodiscard]] bool hasFragment() const; + + [[nodiscard]] bool valid() const; + + [[nodiscard]] std::string str() const; friend std::ostream& operator<<(std::ostream& stream, const URL& url) { @@ -87,8 +86,15 @@ class HTTP_API URL } protected: - http_parser_url _parser; std::string _buf; + std::string _scheme; + std::string _userInfo; + std::string _host; + uint16_t _port; + std::string _path; + std::string _query; + std::string _fragment; + bool _hasPort; }; @@ -96,7 +102,4 @@ class HTTP_API URL } // namespace scy -#endif // SCY_HTTP_URL_H - - -/// @\} +/// @} diff --git a/src/http/include/scy/http/util.h b/src/http/include/scy/http/util.h index e13b92263..41c156327 100644 --- a/src/http/include/scy/http/util.h +++ b/src/http/include/scy/http/util.h @@ -8,10 +8,7 @@ /// @addtogroup http /// @{ - -#ifndef SCY_HTTP_Util_h -#define SCY_HTTP_Util_h - +#pragma once #include "scy/base.h" #include "scy/collection.h" @@ -27,9 +24,6 @@ std::string parseURI(const std::string& request); /// Parses the URI against the expression. bool matchURL(const std::string& uri, const std::string& expression); -/// Parses the URI against the expression. -bool matchURL(const std::string& uri, const std::string& expression); - /// Parses an item from a HTTP cookie. std::string parseCookieItem(const std::string& cookie, const std::string& item); @@ -63,7 +57,4 @@ void splitParameters(const std::string::const_iterator& begin, } // namespace scy -#endif // SCY_HTTP_Util_H - - -/// @\} +/// @} diff --git a/src/http/include/scy/http/websocket.h b/src/http/include/scy/http/websocket.h index f687e9c5e..52857b46f 100644 --- a/src/http/include/scy/http/websocket.h +++ b/src/http/include/scy/http/websocket.h @@ -8,19 +8,16 @@ /// @addtogroup http /// @{ - -#ifndef SCY_NET_WebSocket_H -#define SCY_NET_WebSocket_H - +#pragma once #include "scy/base.h" #include "scy/buffer.h" +#include "scy/http/connection.h" #include "scy/http/parser.h" #include "scy/http/request.h" #include "scy/http/response.h" -#include "scy/http/connection.h" -#include "scy/net/socketemitter.h" #include "scy/net/socket.h" +#include "scy/net/socketemitter.h" #include "scy/net/tcpsocket.h" #include "scy/random.h" @@ -30,10 +27,11 @@ namespace http { namespace ws { -enum Mode +/// WebSocket endpoint mode. +enum class Mode { - ServerSide, ///< Server-side WebSocket. - ClientSide ///< Client-side WebSocket. + ServerSide, ///< Server-side WebSocket. + ClientSide ///< Client-side WebSocket. }; @@ -70,43 +68,50 @@ enum SendFlags /// StatusCodes for CLOSE frames sent with shutdown(). -enum StatusCodes +enum class CloseStatusCode { - StatusNormalClose = 1000, - StatusEndpointGoingAway = 1001, - StatusProtocolError = 1002, - StatusPayloadNotAcceptable = 1003, - StatusReserved = 1004, - StatusReservedNoStatusCode = 1005, - StatusReservedAbnormalClose = 1006, - StatusMalformedPayload = 1007, - StatusPolicyViolation = 1008, - StatusPayloadTooBig = 1009, - StatusExtensionRequired = 1010, - StatusUnexpectedCondition = 1011, - StatusReservedTLSFailure = 1015 + NormalClose = 1000, + EndpointGoingAway = 1001, + ProtocolError = 1002, + PayloadNotAcceptable = 1003, + Reserved = 1004, + ReservedNoStatusCode = 1005, + ReservedAbnormalClose = 1006, + MalformedPayload = 1007, + PolicyViolation = 1008, + PayloadTooBig = 1009, + ExtensionRequired = 1010, + UnexpectedCondition = 1011, + ReservedTLSFailure = 1015 }; /// These error codes can be obtained from WebSocket exceptions /// to determine the exact cause of the error. -enum ErrorCodes +enum class ErrorCode { - ErrorNoHandshake = 1, ///< No Connection: Upgrade or Upgrade: websocket header in handshake request. - ErrorHandshakeNoVersion = 2, ///< No Sec-WebSocket-Version header in handshake request. - ErrorHandshakeUnsupportedVersion = 3, ///< Unsupported WebSocket version requested by client. - ErrorHandshakeNoKey = 4, ///< No Sec-WebSocket-Key header in handshake request. - ErrorHandshakeAccept = 5, ///< No Sec-WebSocket-Accept header or wrong value. - ErrorUnauthorized = 6, ///< The server rejected the username or password for authentication. - ErrorPayloadTooBig = 10, ///< Payload too big for supplied buffer. - ErrorIncompleteFrame = 11 ///< Incomplete frame received. + NoHandshake = 1, ///< No Connection: Upgrade or Upgrade: websocket header in handshake request. + HandshakeNoVersion = 2, ///< No Sec-WebSocket-Version header in handshake request. + HandshakeUnsupportedVersion = 3, ///< Unsupported WebSocket version requested by client. + HandshakeNoKey = 4, ///< No Sec-WebSocket-Key header in handshake request. + HandshakeAccept = 5, ///< No Sec-WebSocket-Accept header or wrong value. + Unauthorized = 6, ///< The server rejected the username or password for authentication. + PayloadTooBig = 10, ///< Payload too big for supplied buffer. + IncompleteFrame = 11, ///< Incomplete frame received. + InvalidRsvBits = 12, ///< RSV bits set without extension negotiation. + InvalidOpcode = 13, ///< Unknown or reserved opcode received. + UnmaskedClientFrame = 14 ///< Client-to-server frame not masked (RFC 6455 violation). }; -static std::string ProtocolGuid = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; +// Keep old names as constants for backward compatibility +static constexpr auto ServerSide = Mode::ServerSide; +static constexpr auto ClientSide = Mode::ClientSide; + +inline constexpr char ProtocolGuid[] = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; /// The WebSocket protocol version supported (13). -static std::string ProtocolVersion = "13"; +inline constexpr char ProtocolVersion[] = "13"; // @@ -136,7 +141,7 @@ class HTTP_API WebSocketFramer /// Return true when the handshake has completed successfully. virtual uint64_t readFrame(BitReader& frame, char*& payload); - bool handshakeComplete() const; + [[nodiscard]] bool handshakeComplete() const; // /// Server side @@ -146,9 +151,6 @@ class HTTP_API WebSocketFramer // /// Client side - /// Sends the initial WS handshake HTTP request. - /// void sendHandshakeRequest(); - /// Appends the WS hanshake HTTP request hearers. void createClientHandshakeRequest(http::Request& request); @@ -163,13 +165,13 @@ class HTTP_API WebSocketFramer protected: /// Returns the frame flags of the most recently received frame. /// Set by readFrame() - int frameFlags() const; + [[nodiscard]] int frameFlags() const; /// Returns true if the payload must be masched. /// Used by writeFrame() - bool mustMaskPayload() const; + [[nodiscard]] bool mustMaskPayload() const; - ws::Mode mode() const; + [[nodiscard]] ws::Mode mode() const; enum { @@ -185,7 +187,19 @@ class HTTP_API WebSocketFramer Random _rnd; std::string _key; // client handshake key + // Fragmentation state (RFC 6455 Section 5.4) + bool _fragmented{false}; ///< Currently receiving a fragmented message + int _fragmentOpcode{0}; ///< Opcode of the first frame in the fragment sequence + Buffer _fragmentBuffer; ///< Accumulated payload from continuation frames + + // Partial frame buffering (when TCP segment doesn't contain a full frame) + Buffer _incompleteFrame; ///< Buffer for incomplete frame data across TCP segments + friend class WebSocketAdapter; + + // Allow direct member access for unit testing + friend void wsFramerTestAccess(WebSocketFramer& f, int state); + friend int wsFramerGetFlags(const WebSocketFramer& f); }; @@ -194,13 +208,14 @@ class HTTP_API WebSocketFramer // +/// WebSocket protocol adapter for both client and server endpoints. class HTTP_API WebSocketAdapter : public net::SocketEmitter { public: WebSocketAdapter(const net::Socket::Ptr& socket, ws::Mode mode, http::Request& request, http::Response& response); - virtual ssize_t send(const char* data, size_t len, int flags = 0) override; // flags = ws::Text || ws::Binary + virtual ssize_t send(const char* data, size_t len, int flags = 0) override; // flags = ws::Text || ws::Binary virtual ssize_t send(const char* data, size_t len, const net::Address& peerAddr, int flags = 0) override; // flags = ws::Text || ws::Binary virtual bool shutdown(uint16_t statusCode, const std::string& statusMessage); @@ -214,20 +229,15 @@ class HTTP_API WebSocketAdapter : public net::SocketEmitter virtual void sendClientRequest(); virtual void handleClientResponse(const MutableBuffer& buffer, const net::Address& peerAddr); - // virtual void prepareClientRequest(http::Request& request); - // virtual void verifyClientResponse(http::Response& response); // /// Server side virtual void handleServerRequest(const MutableBuffer& buffer, const net::Address& peerAddr); - // virtual void sendConnectResponse(); - // virtual void verifyServerRequest(http::Request& request); - // virtual void prepareClientResponse(http::Response& response); - virtual void onSocketConnect(net::Socket& socket) override; - virtual void onSocketRecv(net::Socket& socket, const MutableBuffer& buffer, const net::Address& peerAddress) override; - virtual void onSocketClose(net::Socket& socket) override; + virtual bool onSocketConnect(net::Socket& socket) override; + virtual bool onSocketRecv(net::Socket& socket, const MutableBuffer& buffer, const net::Address& peerAddress) override; + virtual bool onSocketClose(net::Socket& socket) override; virtual void onHandshakeComplete(); @@ -251,7 +261,7 @@ class HTTP_API WebSocketAdapter : public net::SocketEmitter class HTTP_API WebSocket : public WebSocketAdapter { public: - typedef std::vector Vec; + using Vec = std::vector; /// Creates the WebSocket with the given Socket. /// The Socket should be a TCPSocket or a SSLSocket, @@ -260,8 +270,8 @@ class HTTP_API WebSocket : public WebSocketAdapter virtual ~WebSocket(); - http::Request& request(); - http::Response& response(); + [[nodiscard]] http::Request& request(); + [[nodiscard]] http::Response& response(); protected: http::Request _request; @@ -281,8 +291,6 @@ class HTTP_API ConnectionAdapter : public WebSocketAdapter ConnectionAdapter(Connection* connection, ws::Mode mode); virtual ~ConnectionAdapter(); - // virtual ssize_t sendHeader(); - virtual void onHandshakeComplete(); protected: @@ -295,7 +303,4 @@ class HTTP_API ConnectionAdapter : public WebSocketAdapter } // namespace scy -#endif // SCY_NET_WebSocket_H - - -/// @\} +/// @} diff --git a/src/http/samples/httpechoserver/CMakeLists.txt b/src/http/samples/httpechoserver/CMakeLists.txt index 0911707a7..25ce71d7f 100644 --- a/src/http/samples/httpechoserver/CMakeLists.txt +++ b/src/http/samples/httpechoserver/CMakeLists.txt @@ -1 +1 @@ -define_sourcey_module_sample(httpechoserver base net http crypto) +scy_add_sample(httpechoserver DEPENDS base net http crypto) diff --git a/src/http/samples/httpechoserver/httpechoserver.cpp b/src/http/samples/httpechoserver/httpechoserver.cpp index 44cbfcf8f..e97034ee7 100644 --- a/src/http/samples/httpechoserver/httpechoserver.cpp +++ b/src/http/samples/httpechoserver/httpechoserver.cpp @@ -1,7 +1,7 @@ #include "httpechoserver.h" -#include "libuvhttpserver.h" #include "scy/logger.h" #include "scy/net/sslmanager.h" +#include using namespace scy; @@ -17,22 +17,16 @@ int main(int argc, char** argv) setenv("UV_THREADPOOL_SIZE", std::to_string(ncores).c_str(), 1); #endif - // Logger::instance().add(new ConsoleChannel("debug", Level::Trace)); - // Logger::instance().setWriter(new AsyncLogWriter); - // net::SSLManager::initNoVerifyServer(); - { - raiseBenchmarkServer(); - // runMulticoreBenchmarkServers(); - // runMulticoreEchoServers(); - // rlibuv::raiseBenchmarkServer(); - -// #if SCY_HAS_KERNEL_SOCKET_LOAD_BALANCING - // runMulticoreBenchmarkServers(); -// #else - // raiseBenchmarkServer(); -// #endif + if (argc < 3) { + std::cerr << "Usage: " << argv[0] << " " << std::endl; + return 1; } - // net::SSLManager::instance().shutdown(); + net::SSLManager::initNoVerifyServer(argv[1], argv[2]); + + raiseHTTPSEchoServer(); + + net::SSLManager::instance().shutdown(); + Logger::destroy(); return 0; } diff --git a/src/http/samples/httpechoserver/httpechoserver.h b/src/http/samples/httpechoserver/httpechoserver.h index d2bf75cc4..a0d6a191f 100644 --- a/src/http/samples/httpechoserver/httpechoserver.h +++ b/src/http/samples/httpechoserver/httpechoserver.h @@ -1,11 +1,13 @@ -#include "scy/http/server.h" #include "scy/application.h" +#include "scy/http/server.h" +#include "scy/net/sslmanager.h" +#include "scy/net/sslsocket.h" namespace scy { -const uint16_t HttpPort = 1337; +constexpr uint16_t HttpPort = 1337; const net::Address address("0.0.0.0", HttpPort); @@ -26,10 +28,27 @@ void raiseEchoServer() } +void raiseHTTPSEchoServer() +{ + http::Server srv(address, std::make_shared( + net::SSLManager::instance().defaultServerContext())); + srv.start(); + + srv.Connection += [](http::ServerConnection::Ptr conn) { + conn->Payload += [](http::ServerConnection& conn, const MutableBuffer& buffer) { + conn.send(bufferCast(buffer), buffer.size()); + conn.close(); + }; + }; + + std::cout << "HTTPS server listening on " << address << std::endl; + waitForShutdown(); +} + + void raiseMulticoreEchoServer() { - auto loop = uv::createLoop(); - std::thread::id tid(std::this_thread::get_id()); + uv::ScopedLoop loop; http::Server srv(address, net::makeSocket(loop)); srv.start(); @@ -43,25 +62,23 @@ void raiseMulticoreEchoServer() waitForShutdown([&](void*) { srv.shutdown(); - }, nullptr, loop); - - uv::closeLoop(loop); - delete loop; + }, + nullptr, loop); } // Raise a server instance for each CPU core void runMulticoreEchoServers() { - std::vector threads; + std::vector> threads; int ncpus = std::thread::hardware_concurrency(); for (int i = 0; i < ncpus; ++i) { - threads.push_back(new Thread(std::bind(raiseMulticoreEchoServer))); + threads.push_back(std::make_unique(std::bind(raiseMulticoreEchoServer))); } std::cout << "HTTP echo multicore(" << ncpus << ") server listening on " << address << std::endl; - for (auto thread : threads) { + for (auto& thread : threads) { thread->join(); } } @@ -90,8 +107,7 @@ void raiseBenchmarkServer() void raiseMulticoreBenchmarkServer() { - auto loop = uv::createLoop(); - std::thread::id tid(std::this_thread::get_id()); + uv::ScopedLoop loop; http::Server srv(address, net::makeSocket(loop)); srv.start(); @@ -100,31 +116,27 @@ void raiseMulticoreBenchmarkServer() conn->response().add("Content-Length", "0"); conn->response().add("Connection", "close"); // "keep-alive" conn->sendHeader(); - // conn->send("hello universe", 14); - // conn->close(); }; waitForShutdown([&](void*) { srv.shutdown(); - }, nullptr, loop); - - uv::closeLoop(loop); - delete loop; + }, + nullptr, loop); } // Raise a server instance for each CPU core void runMulticoreBenchmarkServers() { - std::vector threads; + std::vector> threads; int ncpus = std::thread::hardware_concurrency(); for (int i = 0; i < ncpus; ++i) { - threads.push_back(new Thread(std::bind(raiseMulticoreBenchmarkServer))); + threads.push_back(std::make_unique(std::bind(raiseMulticoreBenchmarkServer))); } std::cout << "HTTP multicore(" << ncpus << ") server listening on " << address << std::endl; - for (auto thread : threads) { + for (auto& thread : threads) { thread->join(); } } diff --git a/src/http/samples/httpechoserver/libuvhttpserver.h b/src/http/samples/httpechoserver/libuvhttpserver.h index f49edee50..c6ff98bd9 100644 --- a/src/http/samples/httpechoserver/libuvhttpserver.h +++ b/src/http/samples/httpechoserver/libuvhttpserver.h @@ -1,25 +1,23 @@ -#include #include #include -#include +#include #ifdef __unix__ #include // _SC_NPROCESSORS_ONLN on OS X #endif #include "uv.h" -#include "http_parser.h" +#include -#include +#include #include #include -#include #ifdef DEBUG -#define CHECK(status, msg) \ - if (status != 0) { \ - fprintf(stderr, "%s: %s\n", msg, uv_err_name(status)); \ - exit(1); \ - } +#define CHECK(status, msg) \ + if (status != 0) { \ + fprintf(stderr, "%s: %s\n", msg, uv_err_name(status)); \ + exit(1); \ + } #define UVERR(err, msg) fprintf(stderr, "%s: %s\n", msg, uv_err_name(err)) #define LOG_ERROR(msg) puts(msg); #define LOG(msg) puts(msg); @@ -40,59 +38,62 @@ namespace libuv { static int request_num = 1; static uv_loop_t* uv_loop; static uv_tcp_t server; -static http_parser_settings parser_settings; +static llhttp_settings_t parser_settings; -struct client_t { +struct client_t +{ uv_tcp_t handle; - http_parser parser; + llhttp_t parser; uv_write_t write_req; int request_num; std::string path; }; -void on_close(uv_handle_t* handle) { - client_t* client = (client_t*)handle->data; +void on_close(uv_handle_t* handle) +{ + auto* client = static_cast(handle->data); LOGF("[ %5d ] connection closed\n\n", client->request_num); delete client; } -void alloc_cb(uv_handle_t * /*handle*/, size_t suggested_size, uv_buf_t* buf) { - *buf = uv_buf_init((char*)malloc(suggested_size), suggested_size); +void alloc_cb(uv_handle_t* /*handle*/, size_t suggested_size, uv_buf_t* buf) +{ + *buf = uv_buf_init(new char[suggested_size], suggested_size); } -void on_read(uv_stream_t* tcp, ssize_t nread, const uv_buf_t * buf) { - ssize_t parsed; +void on_read(uv_stream_t* tcp, ssize_t nread, const uv_buf_t* buf) +{ LOGF("on read: %ld\n", nread); - client_t* client = (client_t*)tcp->data; + auto* client = static_cast(tcp->data); if (nread >= 0) { - parsed = (ssize_t)http_parser_execute( - &client->parser, &parser_settings, buf->base, nread); - if (client->parser.upgrade) { + llhttp_errno_t err = llhttp_execute( + &client->parser, buf->base, nread); + if (err == HPE_PAUSED_UPGRADE) { LOG_ERROR("parse error: cannot handle http upgrade"); - uv_close((uv_handle_t*)&client->handle, on_close); - } - else if (parsed < nread) { + uv_close(reinterpret_cast(&client->handle), on_close); + } else if (err != HPE_OK) { LOG_ERROR("parse error"); - uv_close((uv_handle_t*)&client->handle, on_close); + uv_close(reinterpret_cast(&client->handle), on_close); } - } - else { + } else { if (nread != UV_EOF) { UVERR(nread, "read"); } - uv_close((uv_handle_t*)&client->handle, on_close); + uv_close(reinterpret_cast(&client->handle), on_close); } - free(buf->base); + delete[] buf->base; } -struct render_baton { - render_baton(client_t * _client) : - client(_client), - request(), - result(), - response_code("200 OK"), - content_type("text/plain"), - error(false) { +struct render_baton +{ + render_baton(client_t* _client) + : client(_client) + , request() + , result() + , response_code("200 OK") + , content_type("text/plain") + , error(false) + { request.data = this; } client_t* client; @@ -103,13 +104,13 @@ struct render_baton { bool error; }; -void after_write(uv_write_t* req, int status) { +void after_write(uv_write_t* req, int status) +{ CHECK(status, "write"); - if (!uv_is_closing((uv_handle_t*)req->handle)) - { - render_baton *closure = static_cast(req->data); + if (!uv_is_closing(reinterpret_cast(req->handle))) { + render_baton* closure = static_cast(req->data); delete closure; - uv_close((uv_handle_t*)req->handle, on_close); + uv_close(reinterpret_cast(req->handle), on_close); } } @@ -117,93 +118,30 @@ bool endswith(std::string const& value, std::string const& search) { if (value.length() >= search.length()) { return (0 == value.compare(value.length() - search.length(), search.length(), search)); - } - else { + } else { return false; } } -void render(uv_work_t* req) { - render_baton *closure = static_cast(req->data); - client_t* client = (client_t*)closure->client; +void render(uv_work_t* req) +{ + auto* closure = static_cast(req->data); + auto* client = closure->client; LOGF("[ %5d ] render\n", client->request_num); - //closure->result = "hello universe"; closure->response_code = "200 OK"; - -#if 0 - std::string filepath("."); - filepath += client->path; - std::string index_path = (filepath + "index.html"); - bool has_index = (access(index_path.c_str(), R_OK) != -1); - if (/*!has_index &&*/ filepath[filepath.size() - 1] == '/') { - uv_fs_t scandir_req; - int r = uv_fs_scandir(uv_loop, &scandir_req, filepath.c_str(), 0, NULL); - uv_dirent_t dent; - closure->content_type = "text/html"; - closure->result = "
    "; - while (UV_EOF != uv_fs_scandir_next(&scandir_req, &dent)) { - std::string name = dent.name; - if (dent.type == UV_DIRENT_DIR) { - name += "/"; - } - closure->result += "
  • "; - closure->result += name; - closure->result += "
  • "; - closure->result += "\n"; - } - closure->result += "
"; - uv_fs_req_cleanup(&scandir_req); - } - else { - std::string file_to_open = filepath; - if (has_index) { - file_to_open = index_path; - } - bool exists = (access(file_to_open.c_str(), R_OK) != -1); - if (!exists) { - closure->result = "no access"; - closure->response_code = "404 Not Found"; - return; - } - FILE * f = fopen(file_to_open.c_str(), "rb"); - if (f) { - std::fseek(f, 0, SEEK_END); - unsigned size = std::ftell(f); - std::fseek(f, 0, SEEK_SET); - closure->result.resize(size); - std::fread(&closure->result[0], size, 1, f); - fclose(f); - if (endswith(file_to_open, "html")) { - closure->content_type = "text/html"; - } - else if (endswith(file_to_open, "css")) { - closure->content_type = "text/css"; - } - else if (endswith(file_to_open, "js")) { - closure->content_type = "application/javascript"; - } - } - else { - closure->result = "failed to open"; - closure->response_code = "404 Not Found"; - } - } -#endif } -void after_render(uv_work_t* req) { - render_baton *closure = static_cast(req->data); - client_t* client = (client_t*)closure->client; +void after_render(uv_work_t* req, int /*status*/) +{ + auto* closure = static_cast(req->data); + auto* client = closure->client; LOGF("[ %5d ] after render\n", client->request_num); std::ostringstream rep; rep << "HTTP/1.1 " << closure->response_code << "\r\n" << "Content-Type: " << closure->content_type << "\r\n" - //<< "Connection: keep-alive\r\n" << "Connection: close\r\n" << "Content-Length: " << closure->result.size() << "\r\n" << "Access-Control-Allow-Origin: *" << "\r\n" @@ -211,84 +149,86 @@ void after_render(uv_work_t* req) { rep << closure->result; std::string res = rep.str(); uv_buf_t resbuf; - resbuf.base = (char *)res.c_str(); + resbuf.base = const_cast(res.c_str()); resbuf.len = res.size(); client->write_req.data = closure; - // https://github.com/joyent/libuv/issues/344 int r = uv_write(&client->write_req, - (uv_stream_t*)&client->handle, - &resbuf, 1, after_write); + reinterpret_cast(&client->handle), + &resbuf, 1, after_write); CHECK(r, "write buff"); } -int on_message_begin(http_parser* /*parser*/) { +int on_message_begin(llhttp_t* /*parser*/) +{ LOGF("\n***MESSAGE BEGIN***\n"); return 0; } -int on_headers_complete(http_parser* /*parser*/) { +int on_headers_complete(llhttp_t* /*parser*/) +{ LOGF("\n***HEADERS COMPLETE***\n"); return 0; } -int on_url(http_parser* parser, const char* url, size_t length) { - client_t* client = (client_t*)parser->data; +int on_url(llhttp_t* parser, const char* url, size_t length) +{ + auto* client = static_cast(parser->data); LOGF("[ %5d ] on_url\n", client->request_num); LOGF("Url: %.*s\n", (int)length, url); - // TODO - use https://github.com/bnoordhuis/uriparser2 instead? - struct http_parser_url u; - int result = http_parser_parse_url(url, length, 0, &u); - if (result) { - fprintf(stderr, "\n\n*** failed to parse URL %s ***\n\n", url); + + // Simple path extraction - find path portion of URL + std::string urlStr(url, length); + auto pathStart = urlStr.find('/'); + if (pathStart != std::string::npos) { + auto queryStart = urlStr.find('?', pathStart); + if (queryStart != std::string::npos) + client->path = urlStr.substr(pathStart, queryStart - pathStart); + else + client->path = urlStr.substr(pathStart); + } else { + fprintf(stderr, "\n\n*** failed to parse PATH in URL %.*s ***\n\n", (int)length, url); return -1; } - else { - if ((u.field_set & (1 << UF_PATH))) { - const char * data = url + u.field_data[UF_PATH].off; - client->path = std::string(data, u.field_data[UF_PATH].len); - } - else { - fprintf(stderr, "\n\n*** failed to parse PATH in URL %s ***\n\n", url); - return -1; - } - } return 0; } -int on_header_field(http_parser* /*parser*/, const char* at, size_t length) { +int on_header_field(llhttp_t* /*parser*/, const char* at, size_t length) +{ LOGF("Header field: %.*s\n", (int)length, at); return 0; } -int on_header_value(http_parser* /*parser*/, const char* at, size_t length) { +int on_header_value(llhttp_t* /*parser*/, const char* at, size_t length) +{ LOGF("Header value: %.*s\n", (int)length, at); return 0; } -int on_body(http_parser* /*parser*/, const char* at, size_t length) { +int on_body(llhttp_t* /*parser*/, const char* at, size_t length) +{ LOGF("Body: %.*s\n", (int)length, at); return 0; } -int on_message_complete(http_parser* parser) { - client_t* client = (client_t*)parser->data; +int on_message_complete(llhttp_t* parser) +{ + auto* client = static_cast(parser->data); LOGF("[ %5d ] on_message_complete\n", client->request_num); - render_baton *closure = new render_baton(client); + render_baton* closure = new render_baton(client); int status = uv_queue_work(uv_loop, - &closure->request, - render, - (uv_after_work_cb)after_render); + &closure->request, + render, + after_render); CHECK(status, "uv_queue_work"); - assert(status == 0); return 0; } -void on_connect(uv_stream_t* server_handle, int status) { +void on_connect(uv_stream_t* server_handle, int status) +{ CHECK(status, "connect"); - assert((uv_tcp_t*)server_handle == &server); client_t* client = new client_t(); client->request_num = request_num; @@ -297,26 +237,26 @@ void on_connect(uv_stream_t* server_handle, int status) { LOGF("[ %5d ] new connection\n", request_num); uv_tcp_init(uv_loop, &client->handle); - http_parser_init(&client->parser, HTTP_REQUEST); + llhttp_init(&client->parser, HTTP_REQUEST, &parser_settings); client->parser.data = client; client->handle.data = client; - int r = uv_accept(server_handle, (uv_stream_t*)&client->handle); + int r = uv_accept(server_handle, reinterpret_cast(&client->handle)); CHECK(r, "accept"); - uv_read_start((uv_stream_t*)&client->handle, alloc_cb, on_read); + uv_read_start(reinterpret_cast(&client->handle), alloc_cb, on_read); } #define MAX_WRITE_HANDLES 1000 -void raiseBenchmarkServer() { +void raiseBenchmarkServer() +{ + llhttp_settings_init(&parser_settings); parser_settings.on_url = on_url; - // notification callbacks parser_settings.on_message_begin = on_message_begin; parser_settings.on_headers_complete = on_headers_complete; parser_settings.on_message_complete = on_message_complete; - // data callbacks parser_settings.on_header_field = on_header_field; parser_settings.on_header_value = on_header_value; parser_settings.on_body = on_body; @@ -328,13 +268,14 @@ void raiseBenchmarkServer() { struct sockaddr_in address; r = uv_ip4_addr("0.0.0.0", 1337, &address); CHECK(r, "ip4_addr"); - r = uv_tcp_bind(&server, (const struct sockaddr*)&address, 0); + r = uv_tcp_bind(&server, reinterpret_cast(&address), 0); CHECK(r, "tcp_bind"); - r = uv_listen((uv_stream_t*)&server, MAX_WRITE_HANDLES, on_connect); + r = uv_listen(reinterpret_cast(&server), MAX_WRITE_HANDLES, on_connect); CHECK(r, "uv_listen"); LOG("listening on port 1337"); uv_run(uv_loop, UV_RUN_DEFAULT); } -} } // namespace scy::libuv +} // namespace libuv +} // namespace scy diff --git a/src/http/src/authenticator.cpp b/src/http/src/authenticator.cpp index 8ca94ea2e..23d5b822e 100644 --- a/src/http/src/authenticator.cpp +++ b/src/http/src/authenticator.cpp @@ -65,9 +65,7 @@ void Authenticator::authenticate(http::Request& request, const http::Response& r BasicAuthenticator(_username, _password).authenticate(request); return; } - // else if (isDigestCredentials(iter->second)) - // ; - // TODO + // Digest authentication not implemented } } @@ -80,9 +78,7 @@ void Authenticator::updateAuthInfo(http::Request& request) if (isBasicCredentials(authorization)) { BasicAuthenticator(_username, _password).authenticate(request); } - // else if (isDigestCredentials(authorization)) - // ; - // TODO + // Digest authentication not implemented } } @@ -95,8 +91,7 @@ void Authenticator::proxyAuthenticate(http::Request& request, const http::Respon BasicAuthenticator(_username, _password).proxyAuthenticate(request); return; } - // else if (isDigestCredentials(iter->second)) - // ; // TODO + // Digest authentication not implemented } } @@ -109,31 +104,30 @@ void Authenticator::updateProxyAuthInfo(http::Request& request) if (isBasicCredentials(authorization)) { BasicAuthenticator(_username, _password).proxyAuthenticate(request); } - // else if (isDigestCredentials(authorization)) - // ; // TODO + // Digest authentication not implemented } } -inline void Authenticator::setUsername(const std::string& username) +void Authenticator::setUsername(const std::string& username) { _username = username; } -inline const std::string& Authenticator::username() const +const std::string& Authenticator::username() const { return _username; } -inline void Authenticator::setPassword(const std::string& password) +void Authenticator::setPassword(const std::string& password) { _password = password; } -inline const std::string& Authenticator::password() const +const std::string& Authenticator::password() const { return _password; } diff --git a/src/http/src/client.cpp b/src/http/src/client.cpp index 1e7a3ab9b..c64216823 100644 --- a/src/http/src/client.cpp +++ b/src/http/src/client.cpp @@ -13,8 +13,8 @@ #include "scy/logger.h" #include "scy/util.h" - -using std::endl; +#include +#include namespace scy { @@ -33,8 +33,6 @@ ClientConnection::ClientConnection(const URL& url, const net::TCPSocket::Ptr& so , _active(false) , _complete(false) { - // LTrace("Create: ", url) - auto uri = url.pathEtc(); if (!uri.empty()) _request.setURI(uri); @@ -43,26 +41,29 @@ ClientConnection::ClientConnection(const URL& url, const net::TCPSocket::Ptr& so // Set default error status _response.setStatus(http::StatusCode::BadGateway); - replaceAdapter(new ConnectionAdapter(this, HTTP_RESPONSE)); + replaceAdapter(std::make_unique(this, HTTP_RESPONSE)); } ClientConnection::~ClientConnection() { - // LTrace("Destroy") } void ClientConnection::send() { - assert(!_connect); + if (_connect) { + throw std::runtime_error("ClientConnection::send: already connecting"); + } connect(); } void ClientConnection::send(http::Request& req) { - assert(!_connect); + if (_connect) { + throw std::runtime_error("ClientConnection::send: already connecting"); + } _request = req; connect(); } @@ -77,7 +78,7 @@ ssize_t ClientConnection::send(const char* data, size_t len, int flags) return Connection::send(data, len); else _outgoingBuffer.push_back(std::string(data, len)); - return (int)len; + return static_cast(len); } @@ -85,7 +86,6 @@ void ClientConnection::connect() { if (!_connect) { _connect = true; - // LTrace("Connecting") _socket->connect(_url.host(), _url.port()); } } @@ -93,9 +93,10 @@ void ClientConnection::connect() void ClientConnection::setReadStream(std::ostream* os) { - assert(!_connect); + if (_connect) { + throw std::runtime_error("ClientConnection::setReadStream: already connecting"); + } - //Incoming.attach(new StreamWriter(os), -1, true); _readStream.reset(os); } @@ -115,10 +116,8 @@ http::Message* ClientConnection::outgoingHeader() // // Socket Callbacks -void ClientConnection::onSocketConnect(net::Socket& socket) +bool ClientConnection::onSocketConnect(net::Socket& socket) { - // LTrace("On connect") - // Set the connection to active _active = true; @@ -128,26 +127,15 @@ void ClientConnection::onSocketConnect(net::Socket& socket) // Flush queued packets if (!_outgoingBuffer.empty()) { - // LTrace("Sending buffered: ", _outgoingBuffer.size()) for (const auto& packet : _outgoingBuffer) { send(packet.c_str(), packet.length()); } _outgoingBuffer.clear(); - } - else { - + } else { // Send the header sendHeader(); } - - // Send the outgoing HTTP header if it hasn't already been sent. - // Note the first call to socket().send() will flush headers. - // Note if there are stream adapters we wait for the stream to push - // through any custom headers. See ChunkedAdapter::emitHeader - //if (Outgoing.numAdapters() == 0) { - // // LTrace("On connect: Send header") - // sendHeader(); - //} + return false; } @@ -156,8 +144,12 @@ void ClientConnection::onSocketConnect(net::Socket& socket) void ClientConnection::onHeaders() { - // LTrace("On headers") - //IncomingProgress.total = _response.getContentLength(); + // Initialize download progress tracking from Content-Length header + auto contentLength = _response.getContentLength(); + if (contentLength > 0) { + IncomingProgress.total = contentLength; + IncomingProgress.current = 0; + } Headers.emit(_response); } @@ -165,41 +157,31 @@ void ClientConnection::onHeaders() void ClientConnection::onPayload(const MutableBuffer& buffer) { - // LTrace("On payload: ", buffer.size()) - - //// Update download progress - //IncomingProgress.update(buffer.size()); - - //// Write to the incoming packet stream if adapters are attached - //if (Incoming.numAdapters() > 0 || Incoming.emitter.nslots() > 0) { - // // if (!Incoming.active()); - // // throw std::runtime_error("startInputStream() must be called"); - // Incoming.write(bufferCast(buffer), buffer.size()); - //} - // Write to the STL read stream if available if (_readStream) { - // LTrace("Writing to stream: ", buffer.size()) _readStream->write(bufferCast(buffer), buffer.size()); _readStream->flush(); } + // Update download progress if total is known + if (IncomingProgress.total > 0) + IncomingProgress.update(static_cast(buffer.size())); + Payload.emit(buffer); } void ClientConnection::onComplete() { - // LTrace("On complete") - - assert(!_complete); + if (_complete) { + throw std::runtime_error("ClientConnection::onComplete: already complete"); + } _complete = true; // in case close() is called inside callback // Release any file handles if (_readStream) { auto fstream = dynamic_cast(_readStream.get()); if (fstream) { - // LTrace("Closing file stream") fstream->close(); } } @@ -210,8 +192,6 @@ void ClientConnection::onComplete() void ClientConnection::onClose() { - // LTrace("On close") - if (!_complete) onComplete(); Close.emit(*this); @@ -244,45 +224,30 @@ void Client::destroy() Client::Client() { - // LTrace("Create") - - //_timer.Timeout += sdelegate(this, &Client::onConnectionTimer); - //_timer.start(5000); } Client::~Client() { - // LTrace("Destroy") shutdown(); } void Client::shutdown() { - // LTrace("Shutdown") - - //_timer.stop(); - Shutdown.emit(/*this*/); + Shutdown.emit(); - //_connections.clear(); auto conns = _connections; for (auto conn : conns) { - // LTrace("Shutdown: ", conn) conn->close(); // close and remove via callback } - assert(_connections.empty()); + if (!_connections.empty()) + LWarn("Client::shutdown: ", _connections.size(), " connections still active"); } void Client::addConnection(ClientConnection::Ptr conn) { - // LTrace("Adding connection: ", conn) - - // conn->Close += [&](net::Socket&) { - // removeConnection(conn.get()); - // }; - conn->Close += slot(this, &Client::onConnectionClose, -1, -1); // lowest priority _connections.push_back(conn); } @@ -290,42 +255,24 @@ void Client::addConnection(ClientConnection::Ptr conn) void Client::removeConnection(ClientConnection* conn) { - // LTrace("Removing connection: ", conn) - for (auto it = _connections.begin(); it != _connections.end(); ++it) { - if (conn == it->get()) { - // LTrace("Removed connection: ", conn) - _connections.erase(it); - return; - } + auto it = std::find_if(_connections.begin(), _connections.end(), + [conn](const ClientConnection::Ptr& c) { return conn == c.get(); }); + if (it != _connections.end()) { + _connections.erase(it); + return; } - assert(0 && "unknown connection"); + throw std::logic_error("Client::removeConnection: unknown connection"); } void Client::onConnectionClose(Connection& conn) { - removeConnection(reinterpret_cast(&conn)); -} - - -#if 0 -void Client::onConnectionTimer(void*) -{ - // Close connections that have timed out while receiving - // the server response, maybe due to a faulty server. - auto conns = _connections; - for (auto conn : conns) { - if (conn->closed()) { // conn->expired() - // LTrace("Closing expired connection: ", conn) - conn->close(); - } - } + removeConnection(static_cast(&conn)); } -#endif } // namespace http } // namespace scy -/// @\} +/// @} diff --git a/src/http/src/connection.cpp b/src/http/src/connection.cpp index 8d3d2e7d6..f7d78d1d5 100644 --- a/src/http/src/connection.cpp +++ b/src/http/src/connection.cpp @@ -15,10 +15,7 @@ #include "scy/logger.h" #include "scy/memory.h" -#include - - -using std::endl; +#include namespace scy { @@ -28,28 +25,20 @@ namespace http { Connection::Connection(const net::TCPSocket::Ptr& socket) : _socket(socket) , _adapter(nullptr) - //, _timeout(30 * 60 * 1000), , _closed(false) , _shouldSendHeader(true) { - // LTrace("Create: ", _socket) } -Connection::~Connection() +Connection::~Connection() noexcept { - // LTrace("Destroy") replaceAdapter(nullptr); - - // NOTE: Call close from impl to avoid pure virtual - // close(); } ssize_t Connection::send(const char* data, size_t len, int flags) { - // LTrace("Send: ", len) - assert(!_closed); if (_closed) return -1; @@ -62,11 +51,9 @@ ssize_t Connection::sendHeader() if (!_shouldSendHeader) return 0; _shouldSendHeader = false; - assert(outgoingHeader()); - - // std::ostringstream os; - // outgoingHeader()->write(os); - // std::string head(os.str().c_str(), os.str().length()); + if (!outgoingHeader()) { + throw std::runtime_error("Connection::sendHeader: no outgoing header"); + } std::string head; head.reserve(256); @@ -80,7 +67,6 @@ ssize_t Connection::sendHeader() void Connection::close() { - // LTrace("Close: ", _closed) if (_closed) return; _closed = true; @@ -92,80 +78,76 @@ void Connection::close() } -void Connection::replaceAdapter(net::SocketAdapter* adapter) +void Connection::replaceAdapter(std::unique_ptr adapter) { - // LTrace("Replace adapter: ", adapter) - - // Detach the old adapter form all callbacks + // Detach the old adapter from all callbacks if (_adapter) { _socket->removeReceiver(_adapter); _adapter->removeReceiver(this); _adapter->setSender(nullptr); - // LTrace("Replace adapter: Delete existing: ", _adapter) - deleteLater(_adapter, _socket->loop()); + deleteLater(_adapter, _socket->loop()); _adapter = nullptr; } // Setup the data flow: Connection <-> ConnectionAdapter <-> Socket if (adapter) { - adapter->addReceiver(this); - adapter->setSender(_socket.get()); + _adapter = adapter.release(); // ownership transfers to deleteLater on next replace + _adapter->addReceiver(this); + _adapter->setSender(_socket.get()); // Attach the ConnectionAdapter to receive Socket callbacks. // The given adapter will process raw packets into HTTP or // WebSocket frames depending on the adapter type. - _socket->addReceiver(adapter); - _adapter = adapter; + _socket->addReceiver(_adapter); } } -void Connection::setError(const scy::Error& err) +void Connection::replaceAdapter(std::nullptr_t) { - // LTrace("Set error: ", err.message) + replaceAdapter(std::unique_ptr(nullptr)); +} + +void Connection::setError(const scy::Error& err) +{ _error = err; } -void Connection::onSocketConnect(net::Socket& socket) +bool Connection::onSocketConnect(net::Socket& socket) { - // LTrace("On socket connect") - // Only useful for client connections + return false; } -void Connection::onSocketRecv(net::Socket& socket, const MutableBuffer& buffer, const net::Address& peerAddress) +bool Connection::onSocketRecv(net::Socket& socket, const MutableBuffer& buffer, const net::Address& peerAddress) { - // LTrace("On socket recv") - // Handle payload data onPayload(buffer); + return false; } -void Connection::onSocketError(net::Socket& socket, const scy::Error& error) +bool Connection::onSocketError(net::Socket& socket, const scy::Error& error) { - // LDebug("On socket error: " << error.err << ": ", error.message) - if (error.err == UV_EOF) { // Close the connection when the other side does - // close(); } else { // Other errors will set the error state setError(error); } + return false; } -void Connection::onSocketClose(net::Socket& socket) +bool Connection::onSocketClose(net::Socket& socket) { - // LTrace("On socket close") - // Close the connection when the socket closes close(); + return false; } @@ -217,18 +199,22 @@ void Connection::shouldSendHeader(bool flag) } +bool Connection::secure() const +{ + return _socket && _socket->transport() == net::SSLTCP; +} + + // // HTTP Client Connection Adapter // -ConnectionAdapter::ConnectionAdapter(Connection* connection, http_parser_type type) +ConnectionAdapter::ConnectionAdapter(Connection* connection, llhttp_type_t type) : SocketAdapter(connection->socket().get()) , _connection(connection) , _parser(type) { - // LTrace("Create: ", connection) - // Set the connection as the default receiver SocketAdapter::addReceiver(connection); @@ -243,38 +229,28 @@ ConnectionAdapter::ConnectionAdapter(Connection* connection, http_parser_type ty ConnectionAdapter::~ConnectionAdapter() { - // LTrace("Destroy: ", _connection) } ssize_t ConnectionAdapter::send(const char* data, size_t len, int flags) { - // LTrace("Send: ", len) - - // try { - // Send headers on initial send - if (_connection && - _connection->shouldSendHeader()) { - ssize_t res = _connection->sendHeader(); + // Send headers on initial send + if (_connection && + _connection->shouldSendHeader()) { + ssize_t res = _connection->sendHeader(); - // The initial packet may be empty to push the headers through - if (len == 0) - return res; - } + // The initial packet may be empty to push the headers through + if (len == 0) + return res; + } - // Other packets should not be empty - assert(len > 0); + // Other packets should not be empty + if (len == 0) { + throw std::runtime_error("ConnectionAdapter::send: empty payload after headers"); + } - // Send body / chunk - return SocketAdapter::send(data, len, flags); - // } - // catch (std::exception& exc) { - // LError("Send error: ", exc.what()) - // - // // Swallow the exception, the socket error will - // // cause the connection to close on next iteration. - // return -1; - // } + // Send body / chunk + return SocketAdapter::send(data, len, flags); } @@ -287,22 +263,20 @@ void ConnectionAdapter::removeReceiver(SocketAdapter* adapter) } -void ConnectionAdapter::onSocketRecv(net::Socket& socket, const MutableBuffer& buf, const net::Address&) +bool ConnectionAdapter::onSocketRecv(net::Socket& socket, const MutableBuffer& buf, const net::Address&) { - // LTrace("On socket recv: ", buf.size()) - if (_parser.complete()) { // Buggy HTTP servers might send late data or multiple responses, // in which case the parser state might already be HPE_OK. // In this case we discard the late message and log the error here, // rather than complicate the app with this error handling logic. - // This issue was noted using Webrick with Ruby 1.9. - LWarn("Dropping late HTTP response: ", buf.str()) - return; + LWarn("Dropping late HTTP response: ", buf.str()); + return false; } // Parse incoming HTTP messages _parser.parse(bufferCast(buf), buf.size()); + return false; } @@ -317,64 +291,37 @@ void ConnectionAdapter::onParserHeader(const std::string& /* name */, void ConnectionAdapter::onParserHeadersEnd(bool upgrade) { - // LTrace("On headers end: ", _parser.upgrade()) - - if (_connection/* && _receiver */) + if (_connection) _connection->onHeaders(); - - // Set the position to the end of the headers once - // they have been handled. Subsequent body chunks will - // now start at the correct position. - // _connection.incomingBuffer().position(_parser._parser.nread); } void ConnectionAdapter::onParserChunk(const char* buf, size_t len) { - // LTrace("On parser chunk: ", len) - // Dispatch the payload - if (_connection/* && _receiver */) { + if (_connection) { net::SocketAdapter::onSocketRecv(*_connection->socket().get(), - mutableBuffer(const_cast(buf), len), - _connection->socket()->peerAddress()); + mutableBuffer(const_cast(buf), len), + _connection->socket()->peerAddress()); } } void ConnectionAdapter::onParserError(const scy::Error& err) { - LWarn("On parser error: ", err.message) - -#if 0 - // HACK: Handle those peski flash policy requests here - auto base = dynamic_cast(_connection.socket().get()); - if (base && std::string(base->buffer().data(), 22) == "") { - - // Send an all access policy file by default - // TODO: User specified flash policy - std::string policy; - - // Add the following headers for HTTP policy response - // policy += "HTTP/1.1 200 OK\r\nContent-Type: text/x-cross-domain-policy\r\nX-Permitted-Cross-Domain-Policies: all\r\n\r\n"; - policy += ""; - base->send(policy.c_str(), policy.length() + 1); - } -#endif + LWarn("On parser error: ", err.message); // Set error and close the connection on parser error - if (_connection/* && _receiver */) { + if (_connection) { _connection->setError(err.message); - _connection->close(); // do we want to force this? + _connection->close(); } } void ConnectionAdapter::onParserEnd() { - // LTrace("On parser end") - - if (_connection/* && _receiver */) + if (_connection) _connection->onComplete(); } @@ -399,8 +346,6 @@ Connection* ConnectionAdapter::connection() ConnectionStream::ConnectionStream(Connection::Ptr connection) : _connection(connection) { - // LTrace("Create: ", connection) - IncomingProgress.sender = this; OutgoingProgress.sender = this; @@ -410,18 +355,15 @@ ConnectionStream::ConnectionStream(Connection::Ptr connection) // The Outgoing stream pumps data into the ConnectionAdapter, // which in turn proxies to the output Socket. Outgoing.emitter += slot(_connection->adapter(), - static_cast(&net::SocketAdapter::sendPacket)); + static_cast(&net::SocketAdapter::sendPacket)); // The Incoming stream receives data from the ConnectionAdapter. - //_connection->adapter()->Recv += slot(this, &ConnectionStream::onRecv); _connection->adapter()->addReceiver(this); } ConnectionStream::~ConnectionStream() { - // LTrace("Destroy") - Outgoing.close(); Incoming.close(); } @@ -429,8 +371,6 @@ ConnectionStream::~ConnectionStream() ssize_t ConnectionStream::send(const char* data, size_t len, int flags) { - // LTrace("Send: ", len) - // Send outgoing data to the stream if adapters are attached, // or just proxy to the connection. if (Outgoing.numAdapters() > 0) { @@ -442,10 +382,11 @@ ssize_t ConnectionStream::send(const char* data, size_t len, int flags) } -void ConnectionStream::onSocketRecv(net::Socket& socket, const MutableBuffer& buffer, const net::Address& peerAddress) +bool ConnectionStream::onSocketRecv(net::Socket& socket, const MutableBuffer& buffer, const net::Address& peerAddress) { // Push received data onto the Incoming stream. Incoming.write(bufferCast(buffer), buffer.size()); + return false; } @@ -459,4 +400,4 @@ Connection::Ptr ConnectionStream::connection() } // namespace scy -/// @\} +/// @} diff --git a/src/http/src/cookie.cpp b/src/http/src/cookie.cpp index 65908cf5f..c6fe07ef5 100644 --- a/src/http/src/cookie.cpp +++ b/src/http/src/cookie.cpp @@ -43,9 +43,7 @@ Cookie::Cookie(const NVCollection& nvc) , _maxAge(-1) , _httpOnly(false) { - for (NVCollection::ConstIterator it = nvc.begin(); it != nvc.end(); ++it) { - const std::string& name = it->first; - const std::string& value = it->second; + for (const auto& [name, value] : nvc) { if (util::icompare(name, "comment") == 0) { setComment(value); } else if (util::icompare(name, "domain") == 0) { @@ -60,7 +58,7 @@ Cookie::Cookie(const NVCollection& nvc) int tzd; DateTime exp = DateTimeParser::parse(value, tzd); Timestamp now; - setMaxAge((int)((exp.timestamp() - now) / Timestamp::resolution())); + setMaxAge(static_cast((exp.timestamp() - now) / Timestamp::resolution())); } else if (util::icompare(name, "version") == 0) { setVersion(util::strtoi(value)); } else if (util::icompare(name, "HttpOnly") == 0) { diff --git a/src/http/src/form.cpp b/src/http/src/form.cpp index 150803556..d4ee84964 100644 --- a/src/http/src/form.cpp +++ b/src/http/src/form.cpp @@ -11,11 +11,13 @@ #include "scy/http/form.h" #include "scy/crypto/crypto.h" -#include "scy/filesystem.h" #include "scy/http/client.h" + +#include "scy/filesystem.h" #include "scy/http/packetizers.h" #include "scy/http/url.h" #include "scy/idler.h" +#include #include @@ -32,23 +34,24 @@ const char* FormWriter::ENCODING_URL = "application/x-www-form-urlencoded"; const char* FormWriter::ENCODING_MULTIPART_FORM = "multipart/form-data"; const char* FormWriter::ENCODING_MULTIPART_RELATED = "multipart/related"; -const int FILE_CHUNK_SIZE = 65536; // 32384; +const int FILE_CHUNK_SIZE = 65536; FormWriter* FormWriter::create(ConnectionStream& stream, const std::string& encoding) { - auto wr = new http::FormWriter(stream, std::make_shared(stream.connection()->socket()->loop()), encoding); - stream.Outgoing.attachSource(wr, true, true); + std::unique_ptr wr(new http::FormWriter(stream, std::make_shared(stream.connection()->socket()->loop()), encoding)); + auto* rawWr = wr.get(); + stream.Outgoing.attachSource(wr.release(), true, true); if (stream.connection()->request().isChunkedTransferEncoding()) { - assert(encoding != http::FormWriter::ENCODING_URL); - assert(stream.connection()->request().getVersion() != http::Message::HTTP_1_0); - stream.Outgoing.attach(new http::ChunkedAdapter(stream.connection()), -1, true); + if (encoding == http::FormWriter::ENCODING_URL) + throw std::invalid_argument("FormWriter::create: URL encoding cannot use chunked transfer"); + if (stream.connection()->request().getVersion() == http::Message::HTTP_1_0) + throw std::invalid_argument("FormWriter::create: HTTP/1.0 does not support chunked transfer"); + auto chunked = std::make_unique(stream.connection()); + stream.Outgoing.attach(chunked.release(), -1, true); } stream.Outgoing.lock(); - return wr; -#if 0 - return nullptr; -#endif + return rawWr; } @@ -62,40 +65,34 @@ FormWriter::FormWriter(ConnectionStream& connection, std::shared_ptr run , _initial(true) , _complete(false) { -#if 0 // Thread based writer - // Make sure threads are repeating - auto thread = dynamic_cast(runner.get()); - if (thread) - thread->setRepeating(true); -#endif } FormWriter::~FormWriter() { - for (auto it = _parts.begin(); it != _parts.end(); ++it) - delete it->part; + // Parts are now managed by unique_ptr, no manual delete needed } void FormWriter::addPart(const std::string& name, FormPart* part) { - assert(part); - assert(_encoding != ENCODING_URL); + if (!part) { + throw std::runtime_error("FormWriter::addPart: null part"); + } + if (_encoding == ENCODING_URL) { + throw std::runtime_error("FormWriter::addPart: cannot add parts with URL encoding"); + } Part p; - p.part = part; + p.part.reset(part); p.name = name; - _parts.push_back(p); - _filesLength += part->length(); + _parts.push_back(std::move(p)); } void FormWriter::prepareSubmit() { - // LTrace("Prepare submit") - http::Request& request = _stream.connection()->request(); if (request.getMethod() == http::Method::Post || request.getMethod() == http::Method::Put) { @@ -104,7 +101,8 @@ void FormWriter::prepareSubmit() request.setChunkedTransferEncoding(false); std::ostringstream ostr; writeUrl(ostr); - assert(ostr.tellp() > 0); + if (ostr.tellp() <= 0) + throw std::runtime_error("FormWriter::prepareSubmit: empty URL-encoded form body"); request.setContentLength(ostr.tellp()); } else { if (_boundary.empty()) @@ -116,11 +114,10 @@ void FormWriter::prepareSubmit() request.setContentType(ct); // Set the total file size for upload progress updates. - // This is not the HTTP content length as it does not - // factor chunk headers. if (!_parts.empty()) { - assert(_filesLength); - // _stream.OutgoingProgress.total = _filesLength; + if (!_filesLength) + LWarn("FormWriter::prepareSubmit: parts present but total file length is zero"); + _stream.OutgoingProgress.total = _filesLength; } // Set Content-Length for non-chunked transfers @@ -145,8 +142,6 @@ void FormWriter::prepareSubmit() void FormWriter::start() { - // LTrace("Start") - prepareSubmit(); _runner->setRepeating(true); @@ -156,9 +151,6 @@ void FormWriter::start() void FormWriter::stop() { - // LTrace("Stop") - - //_complete = true; _runner->cancel(); } @@ -166,25 +158,24 @@ void FormWriter::stop() uint64_t FormWriter::calculateMultipartContentLength() { std::ostringstream ostr; - for (NVCollection::ConstIterator it = begin(); it != end(); ++it) { + for (const auto& [key, value] : *this) { NVCollection header; if (_encoding == ENCODING_MULTIPART_FORM) { std::string disp("form-data; name=\""); - disp.append(it->first); + disp.append(key); disp.append("\""); header.set("Content-Disposition", disp); } writePartHeader(header, ostr); - ostr << it->second; + ostr << value; } - for (PartQueue::const_iterator pit = _parts.begin(); pit != _parts.end(); - ++pit) { - NVCollection header(pit->part->headers()); + for (auto& p : _parts) { + NVCollection header(p.part->headers()); if (_encoding == ENCODING_MULTIPART_FORM) { std::string disp("form-data; name=\""); - disp.append(pit->name); + disp.append(p.name); disp.append("\""); - auto filePart = dynamic_cast(pit->part); + auto filePart = dynamic_cast(p.part.get()); if (filePart) { std::string filename = filePart->filename(); if (!filename.empty()) { @@ -195,10 +186,10 @@ uint64_t FormWriter::calculateMultipartContentLength() } header.set("Content-Disposition", disp); } - header.set("Content-Type", pit->part->contentType()); + header.set("Content-Type", p.part->contentType()); writePartHeader(header, ostr); - pit->part->write(ostr); - pit->part->reset(); // reset part state + p.part->write(ostr); + p.part->reset(); // reset part state } writeEnd(ostr); return ostr.tellp(); @@ -208,89 +199,41 @@ uint64_t FormWriter::calculateMultipartContentLength() void FormWriter::writeAsync() { try { - assert(!complete()); + if (complete()) + throw std::runtime_error("FormWriter::writeAsync: already complete"); if (encoding() == ENCODING_URL) { std::ostringstream ostr; writeUrl(ostr); - // LTrace("Writing URL: ", ostr.str()) emit(ostr.str()); _complete = true; } else writeMultipartChunk(); if (complete()) _runner->cancel(); - } catch (std::exception& exc) { - // LTrace("Error: ", exc.what()) - assert(0); - throw exc; - //#ifdef _DEBUG - // throw exc; - //#endif + } catch (std::exception&) { + _runner->cancel(); + throw; } } -#if 0 -void FormWriter::writeMultipart() -{ - for (NVCollection::ConstIterator it = begin(); it != end(); ++it) { - std::ostringstream ostr; - NVCollection header; - std::string disp("form-data; name=\""); - disp.append(it->first); - disp.append("\""); - header.set("Content-Disposition", disp); - writePartHeader(header, ostr); - ostr << it->second; - emit(ostr.str()); - } - - for (PartQueue::const_iterator pit = _parts.begin(); pit != _parts.end(); ++pit) { - std::ostringstream ostr; - NVCollection header(pit->part->headers()); - std::string disp("form-data; name=\""); - disp.append(pit->name); - disp.append("\""); - std::string filename = pit->part->filename(); - if (!filename.empty()) { - disp.append("; filename=\""); - disp.append(filename); - disp.append("\""); - } - header.set("Content-Disposition", disp); - header.set("Content-Type", pit->part->contentType()); - writePartHeader(header, ostr); - emit(ostr.str()); - pit->part->write(*this); - } - - std::ostringstream ostr; - writeEnd(ostr); - emit(ostr.str()); - emit("0\r\n\r\n", 5, PacketFlags::NoModify | PacketFlags::Final); -} -#endif - - void FormWriter::writeMultipartChunk() { - // LTrace("Writing chunk: ", _writeState) - switch (_writeState) { // Send form values case 0: - for (NVCollection::ConstIterator it = begin(); it != end(); ++it) { + for (const auto& [key, value] : *this) { std::ostringstream ostr; NVCollection header; if (_encoding == ENCODING_MULTIPART_FORM) { std::string disp("form-data; name=\""); - disp.append(it->first); + disp.append(key); disp.append("\""); header.set("Content-Disposition", disp); } writePartHeader(header, ostr); - ostr << it->second; + ostr << value; emit(ostr.str()); } _writeState++; @@ -308,7 +251,7 @@ void FormWriter::writeMultipartChunk() std::string disp("form-data; name=\""); disp.append(p.name); disp.append("\""); - auto filePart = dynamic_cast(p.part); + auto filePart = dynamic_cast(p.part.get()); if (filePart) { std::string filename = filePart->filename(); if (!filename.empty()) { @@ -326,8 +269,6 @@ void FormWriter::writeMultipartChunk() if (p.part->writeChunk(*this)) { return; // return after writing a chunk } else { - // LTrace("Part complete: ", p.name) - delete p.part; _parts.pop_front(); } } @@ -341,23 +282,20 @@ void FormWriter::writeMultipartChunk() writeEnd(ostr); emit(ostr.str()); - // HACK: Write chunked end code here. - // The ChunkedAdapter should really be doing this. - + // Write chunked transfer-encoding terminator if (_stream.connection()->request().isChunkedTransferEncoding()) { emit("0\r\n\r\n", 5, PacketFlags::NoModify | PacketFlags::Final); } - // LTrace("Request complete") _complete = true; _writeState = -1; // raise error if called again } break; // Invalid state default: - LError("Invalid write state: ", _writeState) - assert(0 && "invalid write state"); + LError("Invalid write state: ", _writeState); + throw std::runtime_error("FormWriter: invalid write state"); break; } } @@ -365,10 +303,12 @@ void FormWriter::writeMultipartChunk() void FormWriter::writeUrl(std::ostream& ostr) { - for (NVCollection::ConstIterator it = begin(); it != end(); ++it) { - if (it != begin()) + bool first = true; + for (const auto& [key, value] : *this) { + if (!first) ostr << "&"; - ostr << URL::encode(it->first) << "=" << URL::encode(it->second); + first = false; + ostr << URL::encode(key) << "=" << URL::encode(value); } } @@ -381,10 +321,8 @@ void FormWriter::writePartHeader(const NVCollection& header, std::ostream& ostr) ostr << "\r\n"; ostr << "--" << _boundary << "\r\n"; - NVCollection::ConstIterator it = header.begin(); - while (it != header.end()) { - ostr << it->first << ": " << it->second << "\r\n"; - ++it; + for (const auto& [name, value] : header) { + ostr << name << ": " << value << "\r\n"; } ostr << "\r\n"; } @@ -533,8 +471,6 @@ FilePart::~FilePart() void FilePart::open() { - // LTrace("Open: ", _path) - _istr.open(_path.c_str(), std::ios::in | std::ios::binary); if (!_istr.is_open()) throw std::runtime_error("Cannot open file: " + _path); @@ -556,46 +492,47 @@ void FilePart::reset() bool FilePart::writeChunk(FormWriter& writer) { - // LTrace("Write chunk") - assert(!writer.cancelled()); + if (writer.cancelled()) + return false; _initialWrite = false; char buffer[FILE_CHUNK_SIZE]; if (_istr.read(buffer, FILE_CHUNK_SIZE)) { - writer.emit(buffer, (size_t)_istr.gcount()); - writer.updateProgress((int)_istr.gcount()); + writer.emit(buffer, static_cast(_istr.gcount())); + writer.updateProgress(static_cast(_istr.gcount())); return true; } if (_istr.eof()) { // Still a few bytes left to write? if (_istr.gcount() > 0) { - writer.emit(buffer, (size_t)_istr.gcount()); - writer.updateProgress((int)_istr.gcount()); + writer.emit(buffer, static_cast(_istr.gcount())); + writer.updateProgress(static_cast(_istr.gcount())); } return false; // all done } - assert(_istr.bad()); // must be bad - throw std::runtime_error("Cannot read multipart source file: " + _filename); + if (_istr.bad()) { + throw std::runtime_error("Cannot read multipart source file: " + _filename); + } + return false; } void FilePart::write(FormWriter& writer) { - // LTrace("Write") _initialWrite = false; char buffer[FILE_CHUNK_SIZE]; while (_istr.read(buffer, FILE_CHUNK_SIZE) && !writer.cancelled()) { - writer.emit(buffer, (size_t)_istr.gcount()); - writer.updateProgress((int)_istr.gcount()); + writer.emit(buffer, static_cast(_istr.gcount())); + writer.updateProgress(static_cast(_istr.gcount())); } if (_istr.eof()) { if (_istr.gcount() > 0 && !writer.cancelled()) { - writer.emit(buffer, (size_t)_istr.gcount()); - writer.updateProgress((int)_istr.gcount()); + writer.emit(buffer, static_cast(_istr.gcount())); + writer.updateProgress(static_cast(_istr.gcount())); } } else if (_istr.bad()) throw std::runtime_error("Cannot read multipart source file: " + @@ -605,16 +542,15 @@ void FilePart::write(FormWriter& writer) void FilePart::write(std::ostream& ostr) { - // LTrace("Write") _initialWrite = false; char buffer[FILE_CHUNK_SIZE]; while (_istr.read(buffer, FILE_CHUNK_SIZE)) - ostr.write(buffer, (size_t)_istr.gcount()); + ostr.write(buffer, static_cast(_istr.gcount())); if (_istr.eof()) { if (_istr.gcount() > 0) - ostr.write(buffer, (size_t)_istr.gcount()); + ostr.write(buffer, static_cast(_istr.gcount())); } else if (_istr.bad()) throw std::runtime_error("Cannot read multipart source file: " + _filename); @@ -665,13 +601,10 @@ StringPart::~StringPart() bool StringPart::writeChunk(FormWriter& writer) { - // LTrace("Write chunk") _initialWrite = false; - // TODO: Honour chunk size for large strings - writer.emit(_data.c_str(), _data.length()); - writer.updateProgress((int)_data.length()); + writer.updateProgress(static_cast(_data.length())); return false; } @@ -679,17 +612,15 @@ bool StringPart::writeChunk(FormWriter& writer) void StringPart::write(FormWriter& writer) { - // LTrace("Write") _initialWrite = false; writer.emit(_data.c_str(), _data.length()); - writer.updateProgress((int)_data.length()); + writer.updateProgress(static_cast(_data.length())); } void StringPart::write(std::ostream& ostr) { - // LTrace("Write") _initialWrite = false; ostr.write(_data.c_str(), _data.length()); @@ -706,7 +637,7 @@ uint64_t StringPart::length() const } // namespace scy -/// @\} +/// @} // Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. diff --git a/src/http/src/message.cpp b/src/http/src/message.cpp index 0c97799c1..9513b12af 100644 --- a/src/http/src/message.cpp +++ b/src/http/src/message.cpp @@ -56,7 +56,7 @@ void Message::setVersion(const std::string& version) void Message::setContentLength(uint64_t length) { - if (int(length) != UNKNOWN_CONTENT_LENGTH) + if (static_cast(length) != UNKNOWN_CONTENT_LENGTH) set(CONTENT_LENGTH, util::itostr(length)); else erase(CONTENT_LENGTH); @@ -69,7 +69,7 @@ uint64_t Message::getContentLength() const if (!contentLength.empty()) { return util::strtoi(contentLength); } else - return uint64_t(UNKNOWN_CONTENT_LENGTH); + return static_cast(UNKNOWN_CONTENT_LENGTH); } @@ -151,23 +151,19 @@ bool Message::hasContentLength() const void Message::write(std::ostream& ostr) const { - NVCollection::ConstIterator it = begin(); - while (it != end()) { - ostr << it->first << ": " << it->second << "\r\n"; - ++it; + for (const auto& [name, value] : *this) { + ostr << name << ": " << value << "\r\n"; } } void Message::write(std::string& str) const { - NVCollection::ConstIterator it = begin(); - while (it != end()) { - str.append(it->first); + for (const auto& [name, value] : *this) { + str.append(name); str.append(": "); - str.append(it->second); + str.append(value); str.append("\r\n"); - ++it; } } diff --git a/src/http/src/parser.cpp b/src/http/src/parser.cpp index d09de54dd..25737cc99 100644 --- a/src/http/src/parser.cpp +++ b/src/http/src/parser.cpp @@ -17,9 +17,6 @@ #include -using std::endl; - - namespace scy { namespace http { @@ -46,7 +43,7 @@ Parser::Parser(http::Request* request) } -Parser::Parser(http_parser_type type) +Parser::Parser(llhttp_type_t type) : _observer(nullptr) , _request(nullptr) , _response(nullptr) @@ -64,10 +61,7 @@ Parser::~Parser() void Parser::init() { - // LTrace("Init: ", _type) - - ::http_parser_init(&_parser, _type); - _parser.data = this; + llhttp_settings_init(&_settings); _settings.on_message_begin = on_message_begin; _settings.on_url = on_url; _settings.on_status = on_status; @@ -77,33 +71,33 @@ void Parser::init() _settings.on_body = on_body; _settings.on_message_complete = on_message_complete; + llhttp_init(&_parser, _type, &_settings); + _parser.data = this; + reset(); } size_t Parser::parse(const char* data, size_t len) { - // LTrace("Parse: ", len) - if (_complete) { throw std::runtime_error("HTTP parser already complete"); } - size_t nparsed = ::http_parser_execute(&_parser, &_settings, data, len); + llhttp_errno_t err = llhttp_execute(&_parser, data, len); - if (_parser.upgrade) { + if (err == HPE_PAUSED_UPGRADE) { // The parser has only parsed the HTTP headers, there // may still be unread data from the request body in the buffer. - } - else if (nparsed != len) { // parser.http_errno == HPE_OK && !parser.upgrade - LWarn("HTTP parse failed: ", len, " != ", nparsed) + llhttp_resume_after_upgrade(&_parser); + } else if (err != HPE_OK) { + LWarn("HTTP parse failed: ", llhttp_errno_name(err)); // Handle error. Usually just close the connection. - onError(_parser.http_errno); - //assert(0); + onError(err); } - return nparsed; + return len; } @@ -111,25 +105,24 @@ void Parser::reset() { _complete = false; _upgrade = false; - //_shouldKeepAlive = false; _error.reset(); } void Parser::setRequest(http::Request* request) { - assert(!_request); - assert(!_response); - assert(_type == HTTP_REQUEST); + if (_request || _response || _type != HTTP_REQUEST) { + throw std::runtime_error("Parser::setRequest: invalid state"); + } _request = request; } void Parser::setResponse(http::Response* response) { - assert(!_request); - assert(!_response); - assert(_type == HTTP_RESPONSE); + if (_request || _response || _type != HTTP_RESPONSE) { + throw std::runtime_error("Parser::setResponse: invalid state"); + } _response = response; } @@ -142,9 +135,9 @@ void Parser::setObserver(ParserObserver* observer) http::Message* Parser::message() { - return _request ? reinterpret_cast(_request) - : _response ? reinterpret_cast(_response) - : nullptr; + return _request ? static_cast(_request) + : _response ? static_cast(_response) + : nullptr; } @@ -162,7 +155,7 @@ bool Parser::complete() const bool Parser::upgrade() const { - return _upgrade; // parser.upgrade > 0; + return _upgrade; } @@ -172,8 +165,6 @@ bool Parser::upgrade() const void Parser::onURL(const std::string& value) { - // LTrace("onURL: ", value) - if (_request) _request->setURI(value); } @@ -181,8 +172,6 @@ void Parser::onURL(const std::string& value) void Parser::onHeader(const std::string& name, const std::string& value) { - // LTrace("On header: ", name, ":", value) - if (message()) message()->add(name, value); if (_observer) @@ -192,7 +181,7 @@ void Parser::onHeader(const std::string& name, const std::string& value) void Parser::onHeadersEnd() { - _upgrade = _parser.upgrade > 0; + _upgrade = llhttp_get_upgrade(&_parser) != 0; if (_observer) _observer->onParserHeadersEnd(_upgrade); @@ -201,7 +190,6 @@ void Parser::onHeadersEnd() void Parser::onBody(const char* buf, size_t len) { - // LTrace("On body") if (_observer) _observer->onParserChunk(buf, len); } @@ -209,72 +197,79 @@ void Parser::onBody(const char* buf, size_t len) void Parser::onMessageEnd() { - // LTrace("On message end") _complete = true; if (_observer) _observer->onParserEnd(); } - -void Parser::onError(unsigned errorno, const std::string& message) +void Parser::onError(llhttp_errno_t errnum, const std::string& message) { - assert(errorno != HPE_OK); + if (errnum == HPE_OK) { + throw std::logic_error("Parser::onError called with HPE_OK"); + } SDebug << "Parse error: " - << ::http_errno_name((::http_errno)errorno) << ": " - << ::http_errno_description((::http_errno)errorno) << endl; + << llhttp_errno_name(errnum) << ": " + << llhttp_get_error_reason(&_parser) << std::endl; _complete = true; - _error.err = (http_errno)errorno; // HTTP_PARSER_ERRNO((http_errno)errno); - _error.message = message.empty() ? http_errno_name((::http_errno)errorno) : message; + _error.err = static_cast(errnum); + _error.message = message.empty() ? llhttp_errno_name(errnum) : message; if (_observer) _observer->onParserError(_error); } // -// http_parser callbacks +// llhttp callbacks // -int Parser::on_message_begin(http_parser* parser) +int Parser::on_message_begin(llhttp_t* parser) { - auto self = reinterpret_cast(parser->data); - assert(self); + auto self = static_cast(parser->data); + if (!self) { + return -1; + } self->reset(); return 0; } -int Parser::on_url(http_parser* parser, const char* at, size_t len) +int Parser::on_url(llhttp_t* parser, const char* at, size_t len) { - auto self = reinterpret_cast(parser->data); - assert(self); - assert(at && len); + auto self = static_cast(parser->data); + if (!self || !at || !len) { + return -1; + } self->onURL(std::string(at, len)); return 0; } -int Parser::on_status(http_parser* parser, const char* at, size_t length) +int Parser::on_status(llhttp_t* parser, const char* at, size_t length) { - auto self = reinterpret_cast(parser->data); - assert(self); + auto self = static_cast(parser->data); + if (!self) { + return -1; + } // Handle response status line if (self->_response) - self->_response->setStatus((http::StatusCode)parser->status_code); + self->_response->setStatus(static_cast(llhttp_get_status_code(&self->_parser))); return 0; } -int Parser::on_header_field(http_parser* parser, const char* at, size_t len) +int Parser::on_header_field(llhttp_t* parser, const char* at, size_t len) { - auto self = reinterpret_cast(parser->data); - assert(self); + auto self = static_cast(parser->data); + if (!self) { + return -1; + } if (self->_wasHeaderValue) { if (!self->_lastHeaderField.empty()) { @@ -291,10 +286,12 @@ int Parser::on_header_field(http_parser* parser, const char* at, size_t len) } -int Parser::on_header_value(http_parser* parser, const char* at, size_t len) +int Parser::on_header_value(llhttp_t* parser, const char* at, size_t len) { - auto self = reinterpret_cast(parser->data); - assert(self); + auto self = static_cast(parser->data); + if (!self) { + return -1; + } if (!self->_wasHeaderValue) { self->_lastHeaderValue = std::string(at, len); @@ -307,48 +304,49 @@ int Parser::on_header_value(http_parser* parser, const char* at, size_t len) } -int Parser::on_headers_complete(http_parser* parser) +int Parser::on_headers_complete(llhttp_t* parser) { - auto self = reinterpret_cast(parser->data); - assert(self); + auto self = static_cast(parser->data); + if (!self) { + return -1; + } // Add last entry if any if (!self->_lastHeaderField.empty()) { self->onHeader(self->_lastHeaderField, self->_lastHeaderValue); } - /// HTTP version - // start_line_.version(parser_.http_major, parser_.http_minor); - - /// KeepAlive - //self->_message->setKeepAlive(http_should_keep_alive(&parser) > 0); - //self->_shouldKeepAlive = http_should_keep_alive(&parser) > 0; - - /// Request HTTP method + // Request HTTP method if (self->_request) - self->_request->setMethod(http_method_str(static_cast(parser->method))); + self->_request->setMethod(llhttp_method_name( + static_cast(llhttp_get_method(&self->_parser)))); self->onHeadersEnd(); return 0; } -int Parser::on_body(http_parser* parser, const char* at, size_t len) +int Parser::on_body(llhttp_t* parser, const char* at, size_t len) { - auto self = reinterpret_cast(parser->data); - assert(self); + auto self = static_cast(parser->data); + if (!self) { + return -1; + } self->onBody(at, len); return 0; } -int Parser::on_message_complete(http_parser* parser) +int Parser::on_message_complete(llhttp_t* parser) { - // When http_parser finished receiving a message, signal message complete - auto self = reinterpret_cast(parser->data); - assert(self); + auto self = static_cast(parser->data); + if (!self) { + return -1; + } + // Signal message complete when the llhttp + // has finished receiving the message. self->onMessageEnd(); return 0; } @@ -358,4 +356,4 @@ int Parser::on_message_complete(http_parser* parser) } // namespace scy -/// @\} +/// @} diff --git a/src/http/src/request.cpp b/src/http/src/request.cpp index 97524f962..1e2961bfe 100644 --- a/src/http/src/request.cpp +++ b/src/http/src/request.cpp @@ -12,10 +12,7 @@ #include "scy/http/request.h" #include "scy/http/util.h" -#include - - -using std::endl; +#include namespace scy { @@ -117,13 +114,14 @@ const std::string& Request::getURI() const void Request::setCookies(const NVCollection& cookies) { std::string cookie; - for (NVCollection::ConstIterator it = cookies.begin(); it != cookies.end(); - ++it) { - if (it != cookies.begin()) + bool first = true; + for (const auto& [key, val] : cookies) { + if (!first) cookie.append("; "); - cookie.append(it->first); + first = false; + cookie.append(key); cookie.append("="); - cookie.append(it->second); + cookie.append(val); } add("Cookie", cookie); } @@ -131,10 +129,8 @@ void Request::setCookies(const NVCollection& cookies) void Request::getCookies(NVCollection& cookies) const { - NVCollection::ConstIterator it = find("Cookie"); - while (it != end() && util::icompare(it->first, "Cookie") == 0) { + for (auto it = find("Cookie"); it != end() && util::icompare(it->first, "Cookie") == 0; ++it) { http::splitParameters(it->second.begin(), it->second.end(), cookies); - ++it; } } @@ -186,7 +182,9 @@ void Request::setProxyCredentials(const std::string& scheme, void Request::write(std::ostream& ostr) const { - assert(_uri.length()); + if (_uri.empty()) { + throw std::runtime_error("Request::write: empty URI"); + } ostr << _method << " " << _uri << " " << _version << "\r\n"; http::Message::write(ostr); ostr << "\r\n"; @@ -195,7 +193,9 @@ void Request::write(std::ostream& ostr) const void Request::write(std::string& str) const { - assert(_uri.length()); + if (_uri.empty()) { + throw std::runtime_error("Request::write: empty URI"); + } str.append(_method); str.append(" "); str.append(_uri); @@ -244,4 +244,4 @@ void Request::setCredentials(const std::string& header, } // namespace scy -/// @\} +/// @} diff --git a/src/http/src/response.cpp b/src/http/src/response.cpp index e2e4dea8d..adff3a5e5 100644 --- a/src/http/src/response.cpp +++ b/src/http/src/response.cpp @@ -13,8 +13,7 @@ #include "scy/datetime.h" #include "scy/http/util.h" - -using std::endl; +#include namespace scy { @@ -107,12 +106,10 @@ void Response::addCookie(const Cookie& cookie) void Response::getCookies(std::vector& cookies) const { cookies.clear(); - NVCollection::ConstIterator it = find("Set-Cookie"); - while (it != end() && util::icompare(it->first, "Set-Cookie") == 0) { + for (auto it = find("Set-Cookie"); it != end() && util::icompare(it->first, "Set-Cookie") == 0; ++it) { NVCollection nvc; http::splitParameters(it->second.begin(), it->second.end(), nvc); cookies.push_back(Cookie(nvc)); - ++it; } } @@ -129,7 +126,7 @@ void Response::write(std::string& str) const { str.append(_version); str.append(" "); - str.append(std::to_string(int(_status))); + str.append(std::to_string(static_cast(_status))); str.append(" "); str.append(_reason); str.append("\r\n"); @@ -193,7 +190,7 @@ const char* getStatusCodeReason(StatusCode status) case StatusCode::UseProxy: return "Use Proxy"; case StatusCode::TemporaryRedirect: - return "OK"; + return "Temporary Redirect"; // 400 range: client errors case StatusCode::BadRequest: @@ -251,7 +248,6 @@ const char* getStatusCodeReason(StatusCode status) case StatusCode::VersionNotSupported: return "Version Not Supported"; } - assert(0); return "Unknown"; } @@ -260,4 +256,4 @@ const char* getStatusCodeReason(StatusCode status) } // namespace scy -/// @\} +/// @} diff --git a/src/http/src/server.cpp b/src/http/src/server.cpp index 584b1bc77..0c8dad755 100644 --- a/src/http/src/server.cpp +++ b/src/http/src/server.cpp @@ -14,40 +14,35 @@ #include "scy/logger.h" #include "scy/util.h" - -using std::endl; +#include +#include namespace scy { namespace http { -Server::Server(const std::string& host, short port, net::TCPSocket::Ptr socket, ServerConnectionFactory* factory) +Server::Server(const std::string& host, short port, net::TCPSocket::Ptr socket, std::unique_ptr factory) : _address(host, port) , _socket(socket) , _timer(5000, 5000, socket->loop()) - , _factory(factory) + , _factory(std::move(factory)) { - // LTrace("Create") } -Server::Server(const net::Address& address, net::TCPSocket::Ptr socket, ServerConnectionFactory* factory) +Server::Server(const net::Address& address, net::TCPSocket::Ptr socket, std::unique_ptr factory) : _address(address) , _socket(socket) , _timer(5000, 5000, socket->loop()) - , _factory(factory) + , _factory(std::move(factory)) { - // LTrace("Create") } Server::~Server() { - // LTrace("Destroy") shutdown(); - if (_factory) - delete _factory; } @@ -58,7 +53,7 @@ void Server::start() _socket->bind(_address); _socket->listen(1000); - LDebug("HTTP server listening on ", _address) + LDebug("HTTP server listening on ", _address); _timer.Timeout += slot(this, &Server::onTimer); _timer.start(); @@ -67,8 +62,6 @@ void Server::start() void Server::shutdown() { - // LTrace("Shutdown") - if (_socket) { _socket->removeReceiver(this); _socket->AcceptConnection -= slot(this, &Server::onClientSocketAccept); @@ -81,7 +74,7 @@ void Server::shutdown() } -ServerResponder* Server::createResponder(ServerConnection& conn) +std::unique_ptr Server::createResponder(ServerConnection& conn) { // The initial HTTP request headers have already // been parsed at this point, but the request body may @@ -92,8 +85,6 @@ ServerResponder* Server::createResponder(ServerConnection& conn) void Server::onClientSocketAccept(const net::TCPSocket::Ptr& socket) { - // LTrace("On accept socket connection") - ServerConnection::Ptr conn = _factory->createConnection(*this, socket); conn->Close += slot(this, &Server::onConnectionClose); _connections.push_back(conn); @@ -102,11 +93,9 @@ void Server::onClientSocketAccept(const net::TCPSocket::Ptr& socket) void Server::onConnectionReady(ServerConnection& conn) { - // LTrace("On connection ready") - - for (auto it = _connections.begin(); it != _connections.end(); ++it) { - if (it->get() == &conn) { - Connection.emit(*it); + for (auto& c : _connections) { + if (c.get() == &conn) { + Connection.emit(c); return; } } @@ -115,27 +104,22 @@ void Server::onConnectionReady(ServerConnection& conn) void Server::onConnectionClose(ServerConnection& conn) { - // LTrace("On connection closed") - for (auto it = _connections.begin(); it != _connections.end(); ++it) { - if (it->get() == &conn) { - _connections.erase(it); - return; - } - } + auto it = std::find_if(_connections.begin(), _connections.end(), + [&conn](const ServerConnection::Ptr& c) { return c.get() == &conn; }); + if (it != _connections.end()) + _connections.erase(it); } -void Server::onSocketClose(net::Socket& socket) +bool Server::onSocketClose(net::Socket& socket) { - // LTrace("On server socket close") + return false; } void Server::onTimer() { - // LDebug("Num active HTTP server connections: ", connections.size()) - - // TODO: cleanup timed out pending connections + // Connection timeout cleanup not yet implemented } @@ -153,24 +137,15 @@ net::Address& Server::address() ServerConnection::ServerConnection(Server& server, net::TCPSocket::Ptr socket) : Connection(socket) , _server(server) - , _responder(nullptr) , _upgrade(false) { - // LTrace("Create") - replaceAdapter(new ConnectionAdapter(this, HTTP_REQUEST)); + replaceAdapter(std::make_unique(this, HTTP_REQUEST)); } ServerConnection::~ServerConnection() { - // LTrace("Destroy") - close(); - - if (_responder) { - LTrace("Destroy: Responder: ", _responder) - delete _responder; - } } @@ -182,56 +157,28 @@ Server& ServerConnection::server() void ServerConnection::onHeaders() { - // LTrace("On headers") - -#if 0 - // Send a raw HTTP response - std::ostringstream res; - res << "HTTP/1.1 200 OK\r\n" - << "Connection: close\r\n" - << "Content-Length: 0" << "\r\n" - << "\r\n"; - std::string response(res.str()); - send.send(response.c_str(), response.size()); - - // Send a test HTTP response - _response.add("Content-Length", "0"); - _response.add("Connection", "close"); // "keep-alive" - sendHeader(); - return; -#endif - // Upgrade the connection if required _upgrade = dynamic_cast(adapter())->parser().upgrade(); if (_upgrade && util::icompare(request().get("Upgrade", ""), "websocket") == 0) { - // if (util::icompare(request().get("Connection", ""), "upgrade") == 0 && - // util::icompare(request().get("Upgrade", ""), "websocket") == 0) { - // LTrace("Upgrading to WebSocket: ", request()) - // Note: To upgrade the connection we need to replace the // underlying SocketAdapter instance. Since we are currently // inside the default ConnectionAdapter's HTTP parser callback // scope we just swap the SocketAdapter instance pointers and do // a deferred delete on the old adapter. No more callbacks will be // received from the old adapter after replaceAdapter is called. - auto wsAdapter = new ws::ConnectionAdapter(this, ws::ServerSide); - replaceAdapter(wsAdapter); + auto wsAdapter = std::make_unique(this, ws::ServerSide); + auto* wsAdapterRaw = wsAdapter.get(); + replaceAdapter(std::move(wsAdapter)); // Send the handshake request to the WS adapter for handling. // If the request fails the underlying socket will be closed // resulting in the destruction of the current connection. - - // std::ostringstream oss; - // request().write(oss); - // request().clear(); - // std::string buffer(oss.str()); - std::string buffer; buffer.reserve(256); request().write(buffer); request().clear(); - wsAdapter->onSocketRecv(*socket().get(), mutableBuffer(buffer), socket()->peerAddress()); + wsAdapterRaw->onSocketRecv(*socket().get(), mutableBuffer(buffer), socket()->peerAddress()); } // Notify the server the connection is ready for data flow @@ -241,18 +188,15 @@ void ServerConnection::onHeaders() _responder = _server.createResponder(*this); // Upgraded connections don't receive the onHeaders callback - if (_responder && !_upgrade) - _responder->onHeaders(_request); + if (_responder && !_upgrade) + _responder->onHeaders(_request); } void ServerConnection::onPayload(const MutableBuffer& buffer) { - // LTrace("On payload: ", buffer.size()) - // The connection may have been closed inside a previous callback. if (_closed) { - // LTrace("On payload: Closed") return; } @@ -266,11 +210,8 @@ void ServerConnection::onPayload(const MutableBuffer& buffer) void ServerConnection::onComplete() { - // LTrace("On complete") - // The connection may have been closed inside a previous callback. if (_closed) { - // LTrace("On complete: Closed") return; } @@ -283,8 +224,6 @@ void ServerConnection::onComplete() void ServerConnection::onClose() { - // LTrace("On close") - if (_responder) _responder->onClose(); @@ -294,13 +233,13 @@ void ServerConnection::onClose() http::Message* ServerConnection::incomingHeader() { - return reinterpret_cast(&_request); + return static_cast(&_request); } http::Message* ServerConnection::outgoingHeader() { - return reinterpret_cast(&_response); + return static_cast(&_response); } @@ -308,4 +247,4 @@ http::Message* ServerConnection::outgoingHeader() } // namespace scy -/// @\} +/// @} diff --git a/src/http/src/url.cpp b/src/http/src/url.cpp index 5abf716e3..dc3e9f3f4 100644 --- a/src/http/src/url.cpp +++ b/src/http/src/url.cpp @@ -12,47 +12,64 @@ #include "scy/http/url.h" #include "scy/util.h" +#include +#include +#include +#include + namespace scy { namespace http { URL::URL() + : _port(0) + , _hasPort(false) { parse(""); } URL::URL(const char* url) + : _port(0) + , _hasPort(false) { parse(url); } URL::URL(const std::string& url) + : _port(0) + , _hasPort(false) { parse(url); } -URL::URL(const std::string& scheme, const std::string& authority) +URL::URL(std::string_view scheme, std::string_view authority) + : _port(0) + , _hasPort(false) { - parse(scheme + "://" + authority); + parse(std::string(scheme) + "://" + std::string(authority)); } -URL::URL(const std::string& scheme, const std::string& authority, - const std::string& pathEtc) +URL::URL(std::string_view scheme, std::string_view authority, + std::string_view pathEtc) + : _port(0) + , _hasPort(false) { - parse(scheme + "://" + authority + pathEtc); + parse(std::string(scheme) + "://" + std::string(authority) + std::string(pathEtc)); } -URL::URL(const std::string& scheme, const std::string& authority, - const std::string& path, const std::string& query, - const std::string& fragment) +URL::URL(std::string_view scheme, std::string_view authority, + std::string_view path, std::string_view query, + std::string_view fragment) + : _port(0) + , _hasPort(false) { - parse(scheme + "://" + authority + path + "?" + query + "#" + fragment); + parse(std::string(scheme) + "://" + std::string(authority) + std::string(path) + "?" + std::string(query) + "#" + std::string(fragment)); } @@ -85,48 +102,130 @@ URL& URL::operator=(const char* uri) bool URL::parse(const std::string& url, bool whiny) { - LTrace("Parsing: ", url) + LTrace("Parsing: ", url); std::string src(util::trim(url)); _buf = src; - if (http_parser_parse_url(src.c_str(), src.length(), 0, &_parser) == 0) - return true; - _buf.clear(); - if (whiny) - throw std::runtime_error("Syntax error: Cannot parse invalid URL: " + - src); - return false; + _scheme.clear(); + _userInfo.clear(); + _host.clear(); + _port = 0; + _hasPort = false; + _path.clear(); + _query.clear(); + _fragment.clear(); + + if (src.empty()) + return false; + + std::string::size_type pos = 0; + + // Extract scheme + auto schemeEnd = src.find("://", pos); + if (schemeEnd != std::string::npos) { + _scheme = src.substr(pos, schemeEnd - pos); + util::toLowerInPlace(_scheme); + pos = schemeEnd + 3; + } + + // Extract fragment (from the end) + auto fragPos = src.find('#', pos); + std::string remaining; + if (fragPos != std::string::npos) { + _fragment = src.substr(fragPos + 1); + remaining = src.substr(pos, fragPos - pos); + } else { + remaining = src.substr(pos); + } + + // Extract query (from the end of remaining) + auto queryPos = remaining.find('?'); + std::string authorityAndPath; + if (queryPos != std::string::npos) { + _query = remaining.substr(queryPos + 1); + authorityAndPath = remaining.substr(0, queryPos); + } else { + authorityAndPath = remaining; + } + + // If we had a scheme, extract authority + if (!_scheme.empty()) { + auto pathStart = authorityAndPath.find('/'); + std::string authority; + if (pathStart != std::string::npos) { + authority = authorityAndPath.substr(0, pathStart); + _path = authorityAndPath.substr(pathStart); + } else { + authority = authorityAndPath; + } + + // Extract userinfo from authority + auto atPos = authority.find('@'); + std::string hostPort; + if (atPos != std::string::npos) { + _userInfo = authority.substr(0, atPos); + hostPort = authority.substr(atPos + 1); + } else { + hostPort = authority; + } + + // Extract host and port (handle IPv6 brackets) + if (!hostPort.empty() && hostPort[0] == '[') { + auto bracketEnd = hostPort.find(']'); + if (bracketEnd != std::string::npos) { + _host = hostPort.substr(1, bracketEnd - 1); + if (bracketEnd + 1 < hostPort.size() && hostPort[bracketEnd + 1] == ':') { + auto portStr = hostPort.substr(bracketEnd + 2); + _port = static_cast(std::stoi(portStr)); + _hasPort = true; + } + } + } else { + auto colonPos = hostPort.rfind(':'); + if (colonPos != std::string::npos) { + _host = hostPort.substr(0, colonPos); + auto portStr = hostPort.substr(colonPos + 1); + if (!portStr.empty() && std::all_of(portStr.begin(), portStr.end(), ::isdigit)) { + _port = static_cast(std::stoi(portStr)); + _hasPort = true; + } + } else { + _host = hostPort; + } + } + } else { + // No scheme - treat entire string as path + _path = authorityAndPath; + } + + if (_buf.empty()) { + if (whiny) + throw std::runtime_error("Syntax error: Cannot parse invalid URL: " + src); + return false; + } + + return true; } std::string URL::scheme() const { - std::string res; - if (hasSchema()) { - res.assign(_buf.substr(_parser.field_data[UF_SCHEMA].off, - _parser.field_data[UF_SCHEMA].len)); - util::toLowerInPlace(res); // always return as lowercase - } - return res; + return _scheme; } std::string URL::host() const { - if (hasHost()) - return _buf.substr(_parser.field_data[UF_HOST].off, - _parser.field_data[UF_HOST].len); - return std::string(); + return _host; } uint16_t URL::port() const { - if (hasPort()) - return _parser.port; - std::string sc = scheme(); - if (sc == "http") + if (_hasPort) + return _port; + if (_scheme == "http") return 80; - else if (sc == "https") + else if (_scheme == "https") return 443; return 0; } @@ -142,7 +241,7 @@ std::string URL::authority() const res.append(host()); if (hasPort()) { res.append(":"); - res.append(util::itostr(port())); + res.append(util::itostr(_port)); } return res; } @@ -166,119 +265,26 @@ std::string URL::pathEtc() const std::string URL::path() const { - if (hasPath()) - return _buf.substr(_parser.field_data[UF_PATH].off, - _parser.field_data[UF_PATH].len); - return std::string(); + return _path; } std::string URL::query() const { - if (hasQuery()) - return _buf.substr(_parser.field_data[UF_QUERY].off, - _parser.field_data[UF_QUERY].len); - return std::string(); + return _query; } std::string URL::fragment() const { - if (hasFragment()) - return _buf.substr(_parser.field_data[UF_FRAGMENT].off, - _parser.field_data[UF_FRAGMENT].len); - return std::string(); + return _fragment; } std::string URL::userInfo() const { - if (hasUserInfo()) - return _buf.substr(_parser.field_data[UF_USERINFO].off, - _parser.field_data[UF_USERINFO].len); - return std::string(); -} - - -#if 0 -void URL::updateSchema(const std::string& scheme) -{ - if (!hasSchema()) - throw std::runtime_error("Cannot update invalid URL"); - - std::string tmp(str()); - util::replaceInPlace(tmp, this->scheme(), scheme); - parse(tmp); -} - - -void URL::updateHost(const std::string& host) -{ - if (!hasHost()) - throw std::runtime_error("Cannot update invalid URL"); - - std::string tmp(str()); - util::replaceInPlace(tmp, this->host(), host); - parse(tmp); -} - - -void URL::updatePort(uint16_t port) -{ - if (!hasPort()) - throw std::runtime_error("Cannot update invalid URL"); - - std::string tmp(str()); - util::replaceInPlace(tmp, - util::itostr(this->port()), - util::itostr(port)); - parse(tmp); -} - - -void URL::updatePath(const std::string& path) -{ - if (!hasPath()) - throw std::runtime_error("Cannot update invalid URL"); - - std::string tmp(str()); - util::replaceInPlace(tmp, this->path(), path); - parse(tmp); -} - - -void URL::updateQuery(const std::string& query) -{ - if (!hasQuery()) - throw std::runtime_error("Cannot update invalid URL"); - - std::string tmp(str()); - util::replaceInPlace(tmp, this->query(), query); - parse(tmp); -} - - -void URL::updateFragment(const std::string& fragment) -{ - if (!hasFragment()) - throw std::runtime_error("Cannot update invalid URL"); - - std::string tmp(str()); - util::replaceInPlace(tmp, this->fragment(), fragment); - parse(tmp); -} - - -void URL::updateUserInfo(const std::string& info) -{ - if (!hasUserInfo()) - throw std::runtime_error("Cannot update invalid URL"); - - std::string tmp(str()); - util::replaceInPlace(tmp, this->userInfo(), info); - parse(tmp); + return _userInfo; } -#endif bool URL::valid() const @@ -295,59 +301,59 @@ std::string URL::str() const bool URL::hasSchema() const { - return (_parser.field_set & (1 << UF_SCHEMA)) == (1 << UF_SCHEMA); + return !_scheme.empty(); } bool URL::hasHost() const { - return (_parser.field_set & (1 << UF_HOST)) == (1 << UF_HOST); + return !_host.empty(); } bool URL::hasPort() const { - return (_parser.field_set & (1 << UF_PORT)) == (1 << UF_PORT); + return _hasPort; } bool URL::hasPath() const { - return (_parser.field_set & (1 << UF_PATH)) == (1 << UF_PATH); + return !_path.empty(); } bool URL::hasQuery() const { - return (_parser.field_set & (1 << UF_QUERY)) == (1 << UF_QUERY); + return !_query.empty(); } bool URL::hasFragment() const { - return (_parser.field_set & (1 << UF_FRAGMENT)) == (1 << UF_FRAGMENT); + return !_fragment.empty(); } bool URL::hasUserInfo() const { - return (_parser.field_set & (1 << UF_USERINFO)) == (1 << UF_USERINFO); + return !_userInfo.empty(); } -std::string URL::encode(const std::string& str) +std::string URL::encode(std::string_view str) { - const std::string unreserved = + const std::string_view unreserved = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.~"; - std::string escaped = ""; + std::string escaped; for (size_t i = 0; i < str.length(); i++) { - if (unreserved.find_first_of(str[i]) != std::string::npos) { + if (unreserved.find(str[i]) != std::string_view::npos) { escaped.push_back(str[i]); } else { escaped.append("%"); - char buf[3]; - sprintf(buf, "%.2X", str[i]); + char buf[4]; + std::snprintf(buf, sizeof(buf), "%.2X", static_cast(str[i])); escaped.append(buf); } } @@ -355,14 +361,14 @@ std::string URL::encode(const std::string& str) } -std::string URL::decode(const std::string& str) +std::string URL::decode(std::string_view str) { - std::string clean = ""; + std::string clean; for (size_t i = 0; i < str.length(); i++) { if (str[i] == '%') { - const std::string digits = "0123456789ABCDEF"; + const std::string_view digits = "0123456789ABCDEF"; clean += - (char)(digits.find(str[i + 1]) * 16 + digits.find(str[i + 2])); + static_cast(digits.find(str[i + 1]) * 16 + digits.find(str[i + 2])); i += 2; } else { clean += str[i]; diff --git a/src/http/src/util.cpp b/src/http/src/util.cpp index 9bf4f2345..46da744db 100644 --- a/src/http/src/util.cpp +++ b/src/http/src/util.cpp @@ -171,29 +171,6 @@ void splitParameters(const std::string::const_iterator& begin, } -#if 0 -string parseHeader(const std::string& request, const std::string& name) -{ - std::string req = request; - toLower(req); - toLower(name); - std::string value = ""; - string::size_type start, end = 0; - start = req.find(name+": "); - if (start != std::string::npos) { - start += name.length() + 2; - end = req.find("\r\n", start); - if (end == std::string::npos) return ""; - value = request.substr(start, end-start); - replaceInPlace(value,"\"",""); - replaceInPlace(value,"\r",""); - replaceInPlace(value,"\n",""); - } - return value; -} -#endif - - } // namespace http } // namespace scy diff --git a/src/http/src/websocket.cpp b/src/http/src/websocket.cpp index b4ef589aa..01d4180de 100644 --- a/src/http/src/websocket.cpp +++ b/src/http/src/websocket.cpp @@ -17,11 +17,8 @@ #include "scy/logger.h" #include "scy/numeric.h" #include "scy/random.h" -#include #include - - -using std::endl; +#include namespace scy { @@ -60,23 +57,19 @@ http::Response& WebSocket::response() WebSocketAdapter::WebSocketAdapter(const net::Socket::Ptr& socket, ws::Mode mode, http::Request& request, http::Response& response) - : SocketEmitter(socket) //.get() + : SocketEmitter(socket) , socket(socket) , framer(mode) , _request(request) , _response(response) { - LTrace("Create") - - // socket->addReceiver(this, 100); + LTrace("Create"); } WebSocketAdapter::~WebSocketAdapter() { - LTrace("Destroy") - - // socket->removeReceiver(this); + LTrace("Destroy"); } @@ -87,7 +80,9 @@ bool WebSocketAdapter::shutdown(uint16_t statusCode, const std::string& statusMe writer.putU16(statusCode); writer.put(statusMessage); - assert(socket); + if (!socket) { + throw std::runtime_error("WebSocketAdapter::shutdown: no socket"); + } return SocketAdapter::send(buffer, writer.position(), unsigned(ws::FrameFlags::Fin) | unsigned(ws::Opcode::Close)) > 0; } @@ -101,8 +96,12 @@ ssize_t WebSocketAdapter::send(const char* data, size_t len, int flags) ssize_t WebSocketAdapter::send(const char* data, size_t len, const net::Address& peerAddr, int flags) { - LTrace("Send: ", len, ": ", std::string(data, len)) - assert(framer.handshakeComplete()); + LTrace("Send: ", len, ": ", std::string(data, len)); + if (!framer.handshakeComplete()) + ; + { + throw std::runtime_error("WebSocketAdapter::send: handshake not complete"); + } // Set default text flag if none specified if (!flags) @@ -114,7 +113,9 @@ ssize_t WebSocketAdapter::send(const char* data, size_t len, const net::Address& BitWriter writer(buffer); framer.writeFrame(data, len, flags, writer); - assert(socket); + if (!socket) { + throw std::runtime_error("WebSocketAdapter::send: no socket"); + } return SocketAdapter::send(writer.begin(), writer.position(), peerAddr, 0); } @@ -125,16 +126,18 @@ void WebSocketAdapter::sendClientRequest() std::ostringstream oss; _request.write(oss); - LTrace("Client request: ", oss.str()) + LTrace("Client request: ", oss.str()); - assert(socket); + if (!socket) { + throw std::runtime_error("WebSocketAdapter::sendClientRequest: no socket"); + } SocketAdapter::send(oss.str().c_str(), oss.str().length()); } void WebSocketAdapter::handleClientResponse(const MutableBuffer& buffer, const net::Address& peerAddr) { - LTrace("Client response: ", buffer.str()) + LTrace("Client response: ", buffer.str()); auto data = bufferCast(buffer); http::Parser parser(&_response); @@ -144,13 +147,9 @@ void WebSocketAdapter::handleClientResponse(const MutableBuffer& buffer, const n "WebSocket error: Cannot parse response: Incomplete HTTP message"); } - // TODO: Handle resending request for authentication - // Should we implement some king of callback for this? - // Parse and check the response - if (framer.checkClientHandshakeResponse(_response)) { - LTrace("Handshake success") + LTrace("Handshake success"); onHandshakeComplete(); } @@ -172,115 +171,198 @@ void WebSocketAdapter::onHandshakeComplete() void WebSocketAdapter::handleServerRequest(const MutableBuffer& buffer, const net::Address& peerAddr) { - LTrace("Server request: ", buffer.str()) + LTrace("Server request: ", buffer.str()); http::Parser parser(&_request); if (!parser.parse(bufferCast(buffer), buffer.size())) { throw std::runtime_error("WebSocket error: Cannot parse request: Incomplete HTTP message"); } - LTrace("Verifying handshake: ", _request) - - // Allow the application to verify the incoming request. - // TODO: Handle authentication - // VerifyServerRequest.emit(/*this, */request); + LTrace("Verifying handshake: ", _request); // Verify the WebSocket handshake request try { framer.acceptServerRequest(_request, _response); - LTrace("Handshake success") + LTrace("Handshake success"); } catch (std::exception& exc) { - LWarn("Handshake failed: ", exc.what()) + LWarn("Handshake failed: ", exc.what()); } - // Allow the application to override the response - // PrepareServerResponse.emit(/*this, */response); - // Send response std::ostringstream oss; _response.write(oss); - assert(socket); + if (!socket) { + throw std::runtime_error("WebSocketAdapter::handleServerRequest: no socket"); + } SocketAdapter::send(oss.str().c_str(), oss.str().length()); } -void WebSocketAdapter::onSocketConnect(net::Socket&) +bool WebSocketAdapter::onSocketConnect(net::Socket&) { - LTrace("On connect") - + LTrace("On connect"); // Send the WS handshake request // The Connect signal will be sent after the // handshake is complete sendClientRequest(); + return false; } -void WebSocketAdapter::onSocketRecv(net::Socket&, const MutableBuffer& buffer, const net::Address& peerAddress) +bool WebSocketAdapter::onSocketRecv(net::Socket&, const MutableBuffer& buffer, const net::Address& peerAddress) { - LTrace("On recv: ", buffer.size()) + LTrace("On recv: ", buffer.size()); if (framer.handshakeComplete()) { - // Note: The spec wants us to buffer partial frames, but our - // software does not require this feature, and furthermore - // it goes against our nocopy where possible policy. - // This may need to change in the future, but for now - // we just parse and emit packets as they arrive. - // - // Incoming frames may be joined, so we parse them - // in a loop until the read buffer is empty. - BitReader reader(buffer); + // If we have buffered incomplete frame data from a previous recv, + // prepend it to the current buffer. + Buffer workBuf; + const char* data; + size_t dataLen; + if (!framer._incompleteFrame.empty()) { + workBuf.insert(workBuf.end(), + framer._incompleteFrame.begin(), framer._incompleteFrame.end()); + workBuf.insert(workBuf.end(), + bufferCast(buffer), + bufferCast(buffer) + buffer.size()); + framer._incompleteFrame.clear(); + data = workBuf.data(); + dataLen = workBuf.size(); + } else { + data = bufferCast(buffer); + dataLen = buffer.size(); + } + + // Parse frames in a loop - incoming data may contain multiple + // joined frames, or partial frames that need buffering. + BitReader reader(mutableBuffer(const_cast(data), dataLen)); size_t total = reader.available(); size_t offset = reader.position(); while (offset < total) { char* payload = nullptr; uint64_t payloadLength = 0; + size_t posBeforeRead = reader.position(); try { - // Restore buffer state for next read - // reader.position(offset); - // reader.limit(total); - - // STrace << "Read frame at: " - // << "\n\tinputPosition: " << offset - // << "\n\tinputLength: " << total - // << "\n\tbufferPosition: " << reader.position() - // << "\n\tbufferAvailable: " << reader.available() - // << "\n\tbufferLimit: " << reader.limit() - // << "\n\tbuffer: " << std::string(reader.current(), - // reader.limit()) - // << endl; - - // Parse a frame to throw - // int payloadLength = framer.readFrame(reader); + // Parse a frame (throws on protocol errors) payloadLength = framer.readFrame(reader, payload); - assert(payload); // Update the next frame offset - offset = reader.position(); // + payloadLength; + offset = reader.position(); if (offset < total) - LTrace("Splitting joined packet at ", offset, " of ", total) + LTrace("Splitting joined packet at ", offset, " of ", total); + + // Handle control frames per RFC 6455 + // Control frames (Ping, Pong, Close) may be interleaved + // between fragmented data frames. + int opcode = framer.frameFlags() & unsigned(ws::Opcode::Bitmask); + bool isFin = (framer.frameFlags() & unsigned(ws::FrameFlags::Fin)) != 0; + + if (opcode == unsigned(ws::Opcode::Ping)) { + LTrace("Received Ping, sending Pong"); + int pongFlags = unsigned(ws::FrameFlags::Fin) | unsigned(ws::Opcode::Pong); + Buffer pongBuf; + pongBuf.reserve(static_cast(payloadLength) + WebSocketFramer::MAX_HEADER_LENGTH); + BitWriter pongWriter(pongBuf); + framer.writeFrame(payload ? payload : "", static_cast(payloadLength), pongFlags, pongWriter); + SocketAdapter::send(pongWriter.begin(), pongWriter.position(), peerAddress, 0); + continue; + } + + if (opcode == unsigned(ws::Opcode::Close)) { + LTrace("Received Close frame, echoing close"); + int closeFlags = unsigned(ws::FrameFlags::Fin) | unsigned(ws::Opcode::Close); + Buffer closeBuf; + closeBuf.reserve(static_cast(payloadLength) + WebSocketFramer::MAX_HEADER_LENGTH); + BitWriter closeWriter(closeBuf); + framer.writeFrame(payload ? payload : "", static_cast(payloadLength), closeFlags, closeWriter); + SocketAdapter::send(closeWriter.begin(), closeWriter.position(), peerAddress, 0); + socket->close(); + return false; + } + + if (opcode == unsigned(ws::Opcode::Pong)) { + LTrace("Received Pong frame, ignoring"); + continue; + } + + // RFC 6455 Section 5.4: Handle message fragmentation + if (opcode == unsigned(ws::Opcode::Continuation)) { + // Continuation frame - must be part of a fragmented message + if (!framer._fragmented) { + throw std::runtime_error("WebSocket error: Unexpected continuation frame (protocol error 1002)"); + } + if (payload && payloadLength > 0) + framer._fragmentBuffer.insert(framer._fragmentBuffer.end(), + payload, payload + static_cast(payloadLength)); + if (isFin) { + // Final fragment - emit the complete reassembled message + framer._fragmented = false; + if (!framer._fragmentBuffer.empty()) { + net::SocketEmitter::onSocketRecv(*socket.get(), + mutableBuffer(framer._fragmentBuffer.data(), framer._fragmentBuffer.size()), + peerAddress); + } + framer._fragmentBuffer.clear(); + framer._fragmentOpcode = 0; + } + continue; + } + + // Data frame (Text or Binary) + if (!isFin) { + // First frame of a fragmented message + if (framer._fragmented) { + throw std::runtime_error("WebSocket error: New data frame during fragmentation (protocol error 1002)"); + } + framer._fragmented = true; + framer._fragmentOpcode = opcode; + framer._fragmentBuffer.clear(); + if (payload && payloadLength > 0) + framer._fragmentBuffer.insert(framer._fragmentBuffer.end(), + payload, payload + static_cast(payloadLength)); + continue; + } - // Drop empty packets + // Complete single-frame message (FIN set, not continuation) if (!payloadLength) { - LDebug("Dropping empty frame") + LDebug("Dropping empty frame"); continue; } + } catch (std::exception& exc) { - LError("Parser error: ", exc.what()) + // Check if this is an incomplete frame (ran out of data) + // rather than a protocol error + std::string msg(exc.what()); + if (msg.find("Insufficient buffer") != std::string::npos || + msg.find("Incomplete frame") != std::string::npos) { + // Buffer the remaining data for the next recv call + size_t remaining = total - posBeforeRead; + framer._incompleteFrame.assign( + data + posBeforeRead, data + posBeforeRead + remaining); + LTrace("Buffering incomplete frame: ", remaining, " bytes"); + return false; + } + + LError("Parser error: ", exc.what()); + if (msg.find("protocol error 1002") != std::string::npos) { + try { + shutdown(uint16_t(ws::CloseStatusCode::ProtocolError), "Protocol Error"); + } catch (...) {} + } socket->setError(exc.what()); - return; + return false; } - // Emit the result packet - assert(payload); - assert(payloadLength); - net::SocketEmitter::onSocketRecv(*socket.get(), - mutableBuffer(payload, (size_t)payloadLength), - peerAddress); + // Emit complete single-frame data packet + if (payload && payloadLength) { + net::SocketEmitter::onSocketRecv(*socket.get(), + mutableBuffer(payload, static_cast(payloadLength)), + peerAddress); + } } - assert(offset == total); } else { try { if (framer.mode() == ws::ClientSide) @@ -288,26 +370,31 @@ void WebSocketAdapter::onSocketRecv(net::Socket&, const MutableBuffer& buffer, c else handleServerRequest(buffer, peerAddress); } catch (std::exception& exc) { - LError("Read error: ", exc.what()) + LError("Read error: ", exc.what()); socket->setError(exc.what()); } - return; + return false; } + return false; } -void WebSocketAdapter::onSocketClose(net::Socket&) +bool WebSocketAdapter::onSocketClose(net::Socket&) { - LTrace("On close") + LTrace("On close"); // Reset state so the connection can be reused _request.clear(); _response.clear(); framer._headerState = 0; framer._frameFlags = 0; + framer._fragmented = false; + framer._fragmentOpcode = 0; + framer._fragmentBuffer.clear(); + framer._incompleteFrame.clear(); // Emit closed event - net::SocketEmitter::onSocketClose(*socket.get()); + return net::SocketEmitter::onSocketClose(*socket.get()); } @@ -373,27 +460,32 @@ std::string computeAccept(const std::string& key) void WebSocketFramer::createClientHandshakeRequest(http::Request& request) { - assert(_mode == ws::ClientSide); - assert(_headerState == 0); + if (_mode != ws::ClientSide) { + throw std::runtime_error("WebSocketFramer: not in client mode"); + } + if (_headerState != 0) { + throw std::runtime_error("WebSocketFramer: invalid header state for client handshake"); + } // Send the handshake request _key = createKey(); - // request.clear(); request.setChunkedTransferEncoding(false); request.set("Connection", "Upgrade"); request.set("Upgrade", "websocket"); request.set("Sec-WebSocket-Version", ws::ProtocolVersion); - assert(request.has("Sec-WebSocket-Version")); request.set("Sec-WebSocket-Key", _key); - assert(request.has("Sec-WebSocket-Key")); _headerState++; } bool WebSocketFramer::checkClientHandshakeResponse(http::Response& response) { - assert(_mode == ws::ClientSide); - assert(_headerState == 1); + if (_mode != ws::ClientSide) { + throw std::runtime_error("WebSocketFramer: not in client mode"); + } + if (_headerState != 1) { + throw std::runtime_error("WebSocketFramer: invalid header state for response check"); + } switch (response.getStatus()) { case http::StatusCode::SwitchingProtocols: { @@ -405,38 +497,31 @@ bool WebSocketFramer::checkClientHandshakeResponse(http::Response& response) return true; } case http::StatusCode::Unauthorized: { - assert(0 && "authentication not implemented"); - throw std::runtime_error("WebSocket error: Authentication not implemented"); // ws::ErrorNoHandshake + throw std::runtime_error("WebSocket error: Authentication not implemented"); } - // case http::StatusCode::UpgradeRequired: { - // // The latest node `ws` package always returns a 426 Upgrade - // Required - // // response, so resend the client websocket updrage request. - // _headerState--; - // - // // Need to resend request - // return false; - // } default: - throw std::runtime_error("WebSocket error: Cannot upgrade to WebSocket connection: " + response.getReason()); // ws::ErrorNoHandshake + throw std::runtime_error("WebSocket error: Cannot upgrade to WebSocket connection: " + response.getReason()); } } void WebSocketFramer::acceptServerRequest(http::Request& request, http::Response& response) { - assert(_mode == ws::ServerSide); + if (_mode != ws::ServerSide) { + throw std::runtime_error("WebSocketFramer: not in server mode"); + } - if (util::icompare(request.get("Connection", ""), "upgrade") == 0 && + if ((util::icompare(request.get("Connection", ""), "upgrade") == 0 || + util::icompare(request.get("Connection", ""), "keep-alive, Upgrade") == 0) && util::icompare(request.get("Upgrade", ""), "websocket") == 0) { std::string version = request.get("Sec-WebSocket-Version", ""); if (version.empty()) - throw std::runtime_error("WebSocket error: Missing Sec-WebSocket-Version in handshake request"); //, ws::ErrorHandshakeNoVersion + throw std::runtime_error("WebSocket error: Missing Sec-WebSocket-Version in handshake request"); if (version != ws::ProtocolVersion) - throw std::runtime_error( "WebSocket error: Unsupported WebSocket version requested: " + version); //, ws::ErrorHandshakeUnsupportedVersion + throw std::runtime_error("WebSocket error: Unsupported WebSocket version requested: " + version); std::string key = util::trim(request.get("Sec-WebSocket-Key", "")); if (key.empty()) - throw std::runtime_error("WebSocket error: Missing Sec-WebSocket-Key in handshake request"); //, ws::ErrorHandshakeNoKey + throw std::runtime_error("WebSocket error: Missing Sec-WebSocket-Key in handshake request"); response.setStatus(http::StatusCode::SwitchingProtocols); response.set("Upgrade", "websocket"); @@ -446,15 +531,23 @@ void WebSocketFramer::acceptServerRequest(http::Request& request, http::Response // Set headerState 2 since the handshake was accepted. _headerState = 2; } else - throw std::runtime_error("WebSocket error: No WebSocket handshake"); // ws::ErrorNoHandshake + throw std::runtime_error("WebSocket error: No WebSocket handshake"); } size_t WebSocketFramer::writeFrame(const char* data, size_t len, int flags, BitWriter& frame) { - assert(flags == ws::SendFlags::Text || flags == ws::SendFlags::Binary); - assert(frame.position() == 0); - // assert(frame.limit() >= size_t(len + MAX_HEADER_LENGTH)); + // Allow data frames (Text, Binary) and control frames (Close, Ping, Pong) + int opcode = flags & unsigned(ws::Opcode::Bitmask); + bool isControlFrame = (opcode == unsigned(ws::Opcode::Close) || + opcode == unsigned(ws::Opcode::Ping) || + opcode == unsigned(ws::Opcode::Pong)); + if (flags != ws::SendFlags::Text && flags != ws::SendFlags::Binary && !isControlFrame) { + throw std::runtime_error("WebSocketFramer::writeFrame: invalid flags"); + } + if (frame.position() != 0) { + throw std::runtime_error("WebSocketFramer::writeFrame: frame not at position 0"); + } frame.putU8(static_cast(flags)); uint8_t lenByte(0); @@ -471,7 +564,7 @@ size_t WebSocketFramer::writeFrame(const char* data, size_t len, int flags, BitW } else { lenByte |= 127; frame.putU8(lenByte); - frame.putU64(static_cast(len)); + frame.putU64(static_cast(len)); } if (_maskPayload) { @@ -479,36 +572,24 @@ size_t WebSocketFramer::writeFrame(const char* data, size_t len, int flags, BitW auto m = reinterpret_cast(&mask); auto b = reinterpret_cast(data); frame.put(m, 4); - // auto p = frame.current(); for (unsigned i = 0; i < len; i++) { - // p[i] = b[i] ^ m[i % 4]; frame.putU8(b[i] ^ m[i % 4]); } } else { - // memcpy(frame.current(), data, len); // offset? frame.put(data, len); } - // Update frame length to include payload plus header - // frame.skip(len); - - // STrace << "Write frame: " - // << "\n\tinputLength: " << len - // << "\n\tframePosition: " << frame.position() - // << "\n\tframeLimit: " << frame.limit() - // << "\n\tframeAvailable: " << frame.available() - // << endl; - return frame.position(); } uint64_t WebSocketFramer::readFrame(BitReader& frame, char*& payload) { - assert(handshakeComplete()); + if (!handshakeComplete()) { + throw std::runtime_error("WebSocketFramer::readFrame: handshake not complete"); + } uint64_t limit = frame.limit(); size_t offset = frame.position(); - // assert(offset == 0); // Read the frame header char header[MAX_HEADER_LENGTH]; @@ -534,6 +615,28 @@ uint64_t WebSocketFramer::readFrame(BitReader& frame, char*& payload) headerReader.getU8(flags); headerReader.getU8(lengthByte); _frameFlags = flags; + + // RFC 6455 Section 5.2: RSV1, RSV2, RSV3 MUST be 0 unless an extension + // is negotiated that defines meanings for non-zero values. + if (flags & (unsigned(ws::FrameFlags::Rsv1) | unsigned(ws::FrameFlags::Rsv2) | unsigned(ws::FrameFlags::Rsv3))) { + throw std::runtime_error("WebSocket error: RSV bits set without extension negotiation (protocol error 1002)"); + } + + // RFC 6455 Section 5.2: Validate opcode - reject reserved/unknown opcodes + unsigned opcode = flags & unsigned(ws::Opcode::Bitmask); + if (opcode > unsigned(ws::Opcode::Binary) && opcode < unsigned(ws::Opcode::Close)) { + throw std::runtime_error("WebSocket error: Reserved opcode received (protocol error 1002)"); + } + if (opcode > unsigned(ws::Opcode::Pong)) { + throw std::runtime_error("WebSocket error: Unknown opcode received (protocol error 1002)"); + } + + // RFC 6455 Section 5.1: Server MUST reject unmasked client-to-server frames + bool hasMask = (lengthByte & FRAME_FLAG_MASK) != 0; + if (_mode == ws::ServerSide && !hasMask) { + throw std::runtime_error("WebSocket error: Client frame not masked (protocol error 1002)"); + } + uint64_t payloadLength = 0; int payloadOffset = 2; if ((lengthByte & 0x7f) == 127) { @@ -541,7 +644,7 @@ uint64_t WebSocketFramer::readFrame(BitReader& frame, char*& payload) headerReader.getU64(l); if (l > limit) throw std::runtime_error( - util::format("WebSocket error: Insufficient buffer for payload size %" PRIu64, l)); //, ws::ErrorPayloadTooBig + util::format("WebSocket error: Insufficient buffer for payload size %" PRIu64, l)); payloadLength = l; payloadOffset += 8; } else if ((lengthByte & 0x7f) == 126) { @@ -549,14 +652,14 @@ uint64_t WebSocketFramer::readFrame(BitReader& frame, char*& payload) headerReader.getU16(l); if (l > limit) throw std::runtime_error(util::format( - "WebSocket error: Insufficient buffer for payload size %" PRIu64, l)); //, ws::ErrorPayloadTooBig + "WebSocket error: Insufficient buffer for payload size %" PRIu64, l)); payloadLength = l; payloadOffset += 2; } else { uint8_t l = lengthByte & 0x7f; if (l > limit) throw std::runtime_error(util::format( - "WebSocket error: Insufficient buffer for payload size %" PRIu64, l)); //, ws::ErrorPayloadTooBig + "WebSocket error: Insufficient buffer for payload size %" PRIu64, l)); payloadLength = l; } if (lengthByte & FRAME_FLAG_MASK) { @@ -566,7 +669,7 @@ uint64_t WebSocketFramer::readFrame(BitReader& frame, char*& payload) if (payloadLength > limit) throw std::runtime_error( - "WebSocket error: Incomplete frame received"); //ws::ErrorIncompleteFrame + "WebSocket error: Incomplete frame received"); // Get a reference to the start of the payload payload = reinterpret_cast( @@ -574,17 +677,14 @@ uint64_t WebSocketFramer::readFrame(BitReader& frame, char*& payload) // Unmask the payload if required if (lengthByte & FRAME_FLAG_MASK) { - auto p = reinterpret_cast(payload); // frame.data()); + auto p = reinterpret_cast(payload); for (uint64_t i = 0; i < payloadLength; i++) { p[i] ^= mask[i % 4]; } } // Update frame length to include payload plus header - frame.seek(size_t(offset + payloadOffset + payloadLength)); - // frame.limit(offset + payloadOffset + payloadLength); - // int frameLength = (offset + payloadOffset); - // assert(frame.position() == (offset + payloadOffset)); + frame.seek(static_cast(offset + payloadOffset + payloadLength)); return payloadLength; } @@ -592,21 +692,27 @@ uint64_t WebSocketFramer::readFrame(BitReader& frame, char*& payload) void WebSocketFramer::completeClientHandshake(http::Response& response) { - assert(_mode == ws::ClientSide); - assert(_headerState == 1); + if (_mode != ws::ClientSide) { + throw std::runtime_error("WebSocketFramer: not in client mode"); + } + if (_headerState != 1) { + throw std::runtime_error("WebSocketFramer: invalid header state for handshake completion"); + } std::string connection = response.get("Connection", ""); if (util::icompare(connection, "Upgrade") != 0) - throw std::runtime_error("WebSocket error: No \"Connection: Upgrade\" header in handshake response"); //, ws::ErrorNoHandshake + throw std::runtime_error("WebSocket error: No \"Connection: Upgrade\" header in handshake response"); std::string upgrade = response.get("Upgrade", ""); if (util::icompare(upgrade, "websocket") != 0) - throw std::runtime_error("WebSocket error: No \"Upgrade: websocket\" header in handshake response"); //, ws::ErrorNoHandshake + throw std::runtime_error("WebSocket error: No \"Upgrade: websocket\" header in handshake response"); std::string accept = response.get("Sec-WebSocket-Accept", ""); if (accept != computeAccept(_key)) - throw std::runtime_error("WebSocket error: Invalid or missing Sec-WebSocket-Accept header in handshake esponse"); //, ws::ErrorNoHandshake + throw std::runtime_error("WebSocket error: Invalid or missing Sec-WebSocket-Accept header in handshake response"); _headerState++; - assert(handshakeComplete()); + if (!handshakeComplete()) { + throw std::runtime_error("WebSocketFramer: handshake should be complete"); + } } @@ -639,4 +745,4 @@ bool WebSocketFramer::mustMaskPayload() const } // namespace scy -/// @\} +/// @} diff --git a/src/http/tests/CMakeLists.txt b/src/http/tests/CMakeLists.txt index af00da11e..ed1320e39 100644 --- a/src/http/tests/CMakeLists.txt +++ b/src/http/tests/CMakeLists.txt @@ -1,6 +1 @@ -# include_dependency(SSL REQUIRED) -# include_dependency(LibUV) -# include_dependency(JsonCpp) -# include_dependency(HttpParser) - -define_libsourcey_test(httptests base crypto net http) +scy_add_test(httptests DEPENDS base crypto net http) diff --git a/src/http/tests/httptests.cpp b/src/http/tests/httptests.cpp index 23e16b874..06aeb9e8b 100644 --- a/src/http/tests/httptests.cpp +++ b/src/http/tests/httptests.cpp @@ -1,14 +1,39 @@ #include "httptests.h" +#include "scy/http/parser.h" +#include "scy/http/request.h" +#include "scy/http/response.h" +#include "scy/buffer.h" + +#include using std::endl; using namespace scy; using namespace scy::test; +// Friend accessor functions for WebSocketFramer private members +namespace scy { namespace http { namespace ws { + +void wsFramerTestAccess(WebSocketFramer& f, int state) +{ + f._headerState = state; +} + +int wsFramerGetFlags(const WebSocketFramer& f) +{ + return f._frameFlags; +} + +}}} // namespace scy::http::ws + +using scy::http::ws::wsFramerTestAccess; +using scy::http::ws::wsFramerGetFlags; + + int main(int argc, char** argv) { - Logger::instance().add(new ConsoleChannel("debug", Level::Trace)); + Logger::instance().add(std::make_unique("debug", Level::Trace)); test::init(); net::SSLManager::initNoVerifyClient(); @@ -77,6 +102,109 @@ int main(int argc, char** argv) expect(url8.fragment() == "fragment"); }); + // + /// HTTP URL: full string parsing + // + + describe("url string parsing", []() { + http::URL url1("http://www.example.com:8080/path/to/resource?key=value#section"); + expect(url1.scheme() == "http"); + expect(url1.host() == "www.example.com"); + expect(url1.port() == 8080); + expect(url1.path() == "/path/to/resource"); + expect(url1.query() == "key=value"); + expect(url1.fragment() == "section"); + + http::URL url2("https://user:pass@example.com/path"); + expect(url2.scheme() == "https"); + expect(url2.host() == "example.com"); + expect(url2.path() == "/path"); + expect(url2.hasUserInfo()); + + // No path + http::URL url3("http://example.com"); + expect(url3.scheme() == "http"); + expect(url3.host() == "example.com"); + + // Default ports + http::URL url4("http://example.com/"); + expect(url4.port() == 80); + + http::URL url5("https://example.com/"); + expect(url5.port() == 443); + + // WebSocket schemes + http::URL url6("ws://localhost:9090/ws"); + expect(url6.scheme() == "ws"); + expect(url6.host() == "localhost"); + expect(url6.port() == 9090); + expect(url6.path() == "/ws"); + }); + + // + /// HTTP URL: encode/decode + // + + describe("url encode/decode", []() { + // Spaces and special characters + std::string encoded = http::URL::encode("hello world & foo=bar"); + expect(encoded.find(' ') == std::string::npos); + expect(encoded.find('&') == std::string::npos); + + std::string decoded = http::URL::decode(encoded); + expect(decoded == "hello world & foo=bar"); + + // Round-trip with all printable ASCII + std::string printable; + for (char c = 32; c < 127; ++c) + printable += c; + std::string roundtrip = http::URL::decode(http::URL::encode(printable)); + expect(roundtrip == printable); + + // Already-safe characters should remain unchanged + std::string safe = "abcABC123-_.~"; + expect(http::URL::encode(safe) == safe); + }); + + // + /// HTTP URL: validity + // + + describe("url validity", []() { + http::URL valid("http://example.com"); + expect(valid.valid()); + + http::URL empty; + expect(!empty.valid()); + + // Parse with whiny=false should not throw + http::URL url; + bool ok = url.parse("not a valid url", false); + (void)ok; + }); + + // + /// HTTP URL: copy and assignment + // + + describe("url copy and assignment", []() { + http::URL url1("http://example.com:8080/path?q=1#frag"); + http::URL url2 = url1; + expect(url2.scheme() == url1.scheme()); + expect(url2.host() == url1.host()); + expect(url2.port() == url1.port()); + expect(url2.path() == url1.path()); + expect(url2.query() == url1.query()); + expect(url2.fragment() == url1.fragment()); + + // Assignment from string + http::URL url3; + url3 = "https://other.com/foo"; + expect(url3.scheme() == "https"); + expect(url3.host() == "other.com"); + expect(url3.path() == "/foo"); + }); + // /// HTTP URL Parameters Tests // @@ -84,8 +212,9 @@ int main(int argc, char** argv) describe("url query parameters", []() { NVCollection params; http::splitURIParameters("/streaming?format=MJPEG&width=400&height=300&" - "encoding=Base64&packetizer=chunked&" - "rand=0.09983996045775712", params); + "encoding=Base64&packetizer=chunked&" + "rand=0.09983996045775712", + params); for (NVCollection::ConstIterator it = params.begin(); it != params.end(); ++it) { // std::cout << "URL Parameter: " << it->first << ": " << it->second << endl; } @@ -169,8 +298,8 @@ int main(int argc, char** argv) auto url = http::URL("https://google.com"); auto conn = http::Client::instance().createConnection(url); conn->Headers += [&](http::Response& response) { - std::cout << "On request headers: " << conn->request() << endl; - std::cout << "On response headers: " << response << endl; + std::cout << "On request headers: " << conn->request() << endl; + std::cout << "On response headers: " << response << endl; }; conn->Payload += [&](const MutableBuffer& buffer) { // std::cout << "On payload: " << buffer.size() << ": " << buffer.str() << endl; @@ -180,7 +309,7 @@ int main(int argc, char** argv) conn->close(); }; - conn->replaceAdapter(new http::ConnectionAdapter(conn.get(), HTTP_RESPONSE)); + conn->replaceAdapter(std::make_unique(conn.get(), HTTP_RESPONSE)); conn->request().setKeepAlive(false); conn->send(); @@ -234,7 +363,6 @@ int main(int argc, char** argv) expect(!conn->error().any()); }); - // /// Google Drive Upload Test // @@ -283,6 +411,419 @@ int main(int argc, char** argv) // uv::runLoop(); // }); + + // ========================================================================= + // Cookie Tests + // + + describe("cookie basic", []() { + http::Cookie cookie("session", "abc123"); + expect(cookie.getName() == "session"); + expect(cookie.getValue() == "abc123"); + expect(cookie.getVersion() == 0); + expect(cookie.getMaxAge() == -1); + expect(!cookie.getSecure()); + expect(!cookie.getHttpOnly()); + }); + + describe("cookie attributes", []() { + http::Cookie cookie("id", "42"); + cookie.setDomain(".example.com"); + cookie.setPath("/api"); + cookie.setSecure(true); + cookie.setHttpOnly(true); + cookie.setMaxAge(3600); + cookie.setVersion(1); + cookie.setComment("session cookie"); + + expect(cookie.getDomain() == ".example.com"); + expect(cookie.getPath() == "/api"); + expect(cookie.getSecure()); + expect(cookie.getHttpOnly()); + expect(cookie.getMaxAge() == 3600); + expect(cookie.getVersion() == 1); + expect(cookie.getComment() == "session cookie"); + }); + + describe("cookie toString", []() { + http::Cookie cookie("token", "xyz"); + cookie.setPath("/"); + cookie.setHttpOnly(true); + + std::string str = cookie.toString(); + expect(str.find("token=xyz") != std::string::npos); + }); + + describe("cookie copy", []() { + http::Cookie c1("a", "b"); + c1.setDomain(".test.com"); + c1.setSecure(true); + + http::Cookie c2(c1); + expect(c2.getName() == "a"); + expect(c2.getValue() == "b"); + expect(c2.getDomain() == ".test.com"); + expect(c2.getSecure()); + }); + + describe("cookie assignment", []() { + http::Cookie c1("x", "y"); + c1.setMaxAge(100); + + http::Cookie c2; + c2 = c1; + expect(c2.getName() == "x"); + expect(c2.getValue() == "y"); + expect(c2.getMaxAge() == 100); + }); + + describe("cookie escape unescape", []() { + std::string original = "hello world&foo=bar"; + std::string escaped = http::Cookie::escape(original); + expect(escaped != original); + expect(escaped.find(' ') == std::string::npos); + + std::string unescaped = http::Cookie::unescape(escaped); + expect(unescaped == original); + }); + + describe("cookie from nvcollection", []() { + NVCollection nvc; + nvc.add("name", "sid"); + nvc.add("value", "12345"); + nvc.add("path", "/"); + nvc.add("domain", ".example.com"); + + http::Cookie cookie(nvc); + expect(cookie.getName() == "sid"); + expect(cookie.getValue() == "12345"); + }); + + + // ========================================================================= + // Authenticator Tests + // + + describe("authenticator basic", []() { + http::Authenticator auth("admin", "secret"); + expect(auth.username() == "admin"); + expect(auth.password() == "secret"); + }); + + describe("authenticator setters", []() { + http::Authenticator auth; + auth.setUsername("user1"); + auth.setPassword("pass1"); + expect(auth.username() == "user1"); + expect(auth.password() == "pass1"); + }); + + describe("authenticator from user info", []() { + http::Authenticator auth; + auth.fromUserInfo("alice:wonderland"); + expect(auth.username() == "alice"); + expect(auth.password() == "wonderland"); + }); + + describe("authenticator from uri", []() { + http::URL url("http://bob:builder@example.com/path"); + http::Authenticator auth; + auth.fromURI(url); + expect(auth.username() == "bob"); + expect(auth.password() == "builder"); + }); + + describe("basic authenticator", []() { + http::BasicAuthenticator auth("testuser", "testpass"); + expect(auth.username() == "testuser"); + expect(auth.password() == "testpass"); + + // Authenticate a request and check it has credentials + http::Request request("GET", "/"); + auth.authenticate(request); + expect(request.hasCredentials()); + + std::string scheme, authInfo; + request.getCredentials(scheme, authInfo); + expect(scheme == "Basic"); + expect(!authInfo.empty()); + }); + + describe("basic authenticator from request", []() { + // Set up a request with basic auth + http::Request request("GET", "/"); + http::BasicAuthenticator auth1("myuser", "mypass"); + auth1.authenticate(request); + + // Parse it back + http::BasicAuthenticator auth2(request); + expect(auth2.username() == "myuser"); + expect(auth2.password() == "mypass"); + }); + + describe("basic authenticator proxy", []() { + http::BasicAuthenticator auth("proxyuser", "proxypass"); + http::Request request("GET", "/"); + auth.proxyAuthenticate(request); + expect(request.hasProxyCredentials()); + }); + + describe("credential helpers", []() { + expect(http::isBasicCredentials("Basic dXNlcjpwYXNz")); + expect(!http::isBasicCredentials("Digest realm=\"test\"")); + expect(http::isDigestCredentials("Digest realm=\"test\"")); + expect(!http::isDigestCredentials("Basic dXNlcjpwYXNz")); + }); + + describe("extract credentials", []() { + std::string username, password; + http::extractCredentials(std::string("user:pass"), username, password); + expect(username == "user"); + expect(password == "pass"); + }); + + describe("extract credentials from url", []() { + http::URL url("http://alice:secret@example.com/"); + std::string username, password; + http::extractCredentials(url, username, password); + expect(username == "alice"); + expect(password == "secret"); + }); + + describe("has credentials helpers", []() { + http::Request req("GET", "/"); + expect(!http::hasBasicCredentials(req)); + expect(!http::hasDigestCredentials(req)); + expect(!http::hasProxyBasicCredentials(req)); + expect(!http::hasProxyDigestCredentials(req)); + + http::BasicAuthenticator auth("u", "p"); + auth.authenticate(req); + expect(http::hasBasicCredentials(req)); + expect(!http::hasDigestCredentials(req)); + }); + + + // ========================================================================= + // StringPart Tests + // + + describe("string part basic", []() { + http::StringPart part("hello world", "text/plain"); + expect(part.contentType() == "text/plain"); + expect(part.length() == 11); + }); + + describe("string part write to stream", []() { + http::StringPart part("test data", "application/json"); + std::ostringstream oss; + part.write(oss); + expect(oss.str() == "test data"); + }); + + describe("string part empty", []() { + http::StringPart part(""); + expect(part.length() == 0); + }); + + describe("string part default content type", []() { + http::StringPart part("data"); + expect(part.contentType() == "application/octet-stream"); + }); + + + // ========================================================================= + // HTTP Request/Response Round-Trip Tests + // + + describe("http request round-trip", []() { + // Create a GET request with headers + http::Request req("GET", "/api/users?page=1"); + req.setHost("example.com", 8080); + req.set("User-Agent", "LibSourcey/2.0"); + req.set("Accept", "application/json"); + + // Serialize + std::ostringstream oss; + req.write(oss); + std::string raw = oss.str(); + + // Verify serialized output contains key parts + expect(raw.find("GET /api/users?page=1 HTTP/1.1") != std::string::npos); + expect(raw.find("Host: example.com:8080") != std::string::npos); + expect(raw.find("User-Agent: LibSourcey/2.0") != std::string::npos); + + // Parse back + http::Request parsed; + http::Parser parser(&parsed); + parser.parse(raw.c_str(), raw.size()); + + expect(parsed.getMethod() == "GET"); + expect(parsed.getURI() == "/api/users?page=1"); + expect(parsed.getHost() == "example.com:8080" || parsed.getHost() == "example.com"); + expect(parsed.get("User-Agent") == "LibSourcey/2.0"); + expect(parsed.get("Accept") == "application/json"); + }); + + describe("http response round-trip", []() { + http::Response res; + res.setStatus(http::StatusCode::OK); + res.setReason("OK"); + res.set("Content-Type", "text/html"); + res.setContentLength(13); + + std::ostringstream oss; + res.write(oss); + std::string raw = oss.str(); + + expect(raw.find("HTTP/1.1 200 OK") != std::string::npos); + expect(raw.find("Content-Type: text/html") != std::string::npos); + expect(raw.find("Content-Length: 13") != std::string::npos); + + // Parse back + http::Response parsed; + http::Parser parser(&parsed); + parser.parse(raw.c_str(), raw.size()); + + expect(parsed.getStatus() == http::StatusCode::OK); + expect(parsed.get("Content-Type") == "text/html"); + }); + + describe("http post request", []() { + http::Request req("POST", "/api/data"); + req.setHost("localhost"); + req.setContentType("application/json"); + req.setContentLength(27); + + std::ostringstream oss; + req.write(oss); + std::string raw = oss.str(); + + expect(raw.find("POST /api/data HTTP/1.1") != std::string::npos); + expect(raw.find("Content-Type: application/json") != std::string::npos); + expect(raw.find("Content-Length: 27") != std::string::npos); + }); + + + // ========================================================================= + // WebSocket Frame Encoding/Decoding Tests + // + + describe("websocket text frame encoding", []() { + // Server-side framer (no masking) + http::ws::WebSocketFramer framer(http::ws::ServerSide); + // Force handshake complete state for testing + wsFramerTestAccess(framer, 2); + + const char* payload = "Hello, WebSocket!"; + size_t payloadLen = strlen(payload); + + Buffer frameBuf; + frameBuf.reserve(payloadLen + 14); + BitWriter writer(frameBuf); + + framer.writeFrame(payload, payloadLen, http::ws::SendFlags::Text, writer); + + // Frame should be larger than payload (has header) + expect(writer.position() > payloadLen); + + // First byte: FIN + Text opcode = 0x81 + expect(static_cast(frameBuf[0]) == 0x81); + + // Second byte: no mask + length + expect(static_cast(frameBuf[1]) == payloadLen); + + // Read it back + BitReader reader(mutableBuffer(frameBuf.data(), writer.position())); + char* readPayload = nullptr; + uint64_t readLen = framer.readFrame(reader, readPayload); + + expect(readLen == payloadLen); + expect(std::string(readPayload, static_cast(readLen)) == "Hello, WebSocket!"); + }); + + describe("websocket binary frame encoding", []() { + http::ws::WebSocketFramer framer(http::ws::ServerSide); + wsFramerTestAccess(framer, 2); + + const char binaryData[] = {0x00, 0x01, 0x02, (char)0xFF, (char)0xFE}; + + Buffer frameBuf; + frameBuf.reserve(sizeof(binaryData) + 14); + BitWriter writer(frameBuf); + + framer.writeFrame(binaryData, sizeof(binaryData), http::ws::SendFlags::Binary, writer); + + // First byte: FIN + Binary opcode = 0x82 + expect(static_cast(frameBuf[0]) == 0x82); + + // Read back + BitReader reader(mutableBuffer(frameBuf.data(), writer.position())); + char* readPayload = nullptr; + uint64_t readLen = framer.readFrame(reader, readPayload); + + expect(readLen == sizeof(binaryData)); + expect(memcmp(readPayload, binaryData, sizeof(binaryData)) == 0); + }); + + describe("websocket client masking", []() { + // Client-side framer applies masking + http::ws::WebSocketFramer clientFramer(http::ws::ClientSide); + wsFramerTestAccess(clientFramer, 2); + + // Server-side framer reads masked frames + http::ws::WebSocketFramer serverFramer(http::ws::ServerSide); + wsFramerTestAccess(serverFramer, 2); + + const char* payload = "Masked data"; + size_t payloadLen = strlen(payload); + + Buffer frameBuf; + frameBuf.reserve(payloadLen + 14); + BitWriter writer(frameBuf); + + clientFramer.writeFrame(payload, payloadLen, http::ws::SendFlags::Text, writer); + + // Mask bit should be set (second byte & 0x80) + expect((static_cast(frameBuf[1]) & 0x80) != 0); + + // Server should be able to read it (unmasking happens in readFrame) + BitReader reader(mutableBuffer(frameBuf.data(), writer.position())); + char* readPayload = nullptr; + uint64_t readLen = serverFramer.readFrame(reader, readPayload); + + expect(readLen == payloadLen); + expect(std::string(readPayload, static_cast(readLen)) == "Masked data"); + }); + + describe("websocket control frames", []() { + http::ws::WebSocketFramer framer(http::ws::ServerSide); + wsFramerTestAccess(framer, 2); + + // Write a Ping frame + const char* pingData = "ping"; + int pingFlags = unsigned(http::ws::FrameFlags::Fin) | unsigned(http::ws::Opcode::Ping); + + Buffer frameBuf; + frameBuf.reserve(20); + BitWriter writer(frameBuf); + framer.writeFrame(pingData, 4, pingFlags, writer); + + // First byte: FIN + Ping = 0x89 + expect(static_cast(frameBuf[0]) == 0x89); + + // Read back + BitReader reader(mutableBuffer(frameBuf.data(), writer.position())); + char* readPayload = nullptr; + uint64_t readLen = framer.readFrame(reader, readPayload); + + // Verify opcode from frameFlags + int opcode = wsFramerGetFlags(framer) & unsigned(http::ws::Opcode::Bitmask); + expect(opcode == unsigned(http::ws::Opcode::Ping)); + expect(readLen == 4); + }); + + test::runAll(); http::Client::destroy(); diff --git a/src/http/tests/httptests.h b/src/http/tests/httptests.h index 4e46faa5b..f79730379 100644 --- a/src/http/tests/httptests.h +++ b/src/http/tests/httptests.h @@ -1,13 +1,13 @@ -#ifndef SCY_HTTP_Tests_H -#define SCY_HTTP_Tests_H +#pragma once -#include "scy/interface.h" #include "scy/base.h" #include "scy/crypto/hash.h" #include "scy/filesystem.h" +#include "scy/http/authenticator.h" #include "scy/http/client.h" #include "scy/http/connection.h" +#include "scy/http/cookie.h" #include "scy/http/form.h" #include "scy/http/packetizers.h" #include "scy/http/server.h" @@ -15,6 +15,7 @@ #include "scy/http/util.h" #include "scy/http/websocket.h" #include "scy/idler.h" +#include "scy/interface.h" #include "scy/net/sslcontext.h" #include "scy/net/sslmanager.h" #include "scy/test.h" @@ -23,10 +24,10 @@ #include "../samples/httpechoserver/httpechoserver.h" -using std::cout; +using scy::test::Test; using std::cerr; +using std::cout; using std::endl; -using scy::test::Test; #define TEST_HTTP_PORT 1337 @@ -97,25 +98,25 @@ struct HTTPEchoTest void onConnect() { - LDebug("On connect") + LDebug("On connect"); } void onHeaders(http::Response& res) { - LDebug("On headers") + LDebug("On headers"); } void onComplete(const http::Response& res) { std::ostringstream os; res.write(os); - LDebug("Response complete: ", os.str()) + LDebug("Response complete: ", os.str()); } void onPayload(const MutableBuffer& buffer) { std::string data(bufferCast(buffer), buffer.size()); - LDebug("On payload: ", buffer.size(), ": ", data) + LDebug("On payload: ", buffer.size(), ": ", data); if (data == "PING") numSuccess++; @@ -129,7 +130,7 @@ struct HTTPEchoTest void onClose(http::Connection&) { - LDebug("Connection closed") + LDebug("Connection closed"); shutdown(); } }; @@ -138,7 +139,4 @@ struct HTTPEchoTest } // namespace scy -#endif // SCY_HTTP_Tests_H - - /// @\} diff --git a/src/json/CMakeLists.txt b/src/json/CMakeLists.txt index 819acd77e..06e7a25c6 100644 --- a/src/json/CMakeLists.txt +++ b/src/json/CMakeLists.txt @@ -1,5 +1,10 @@ -ask_build_sourcey_module(json) -if(BUILD_MODULES OR (NOT BUILD_MODULES AND BUILD_MODULE_json)) - set(json_PRETTY_NAME JSON) - define_sourcey_module(json base) +scy_add_module(json + DEPENDS base + PRETTY_NAME JSON +) +if(TARGET json) + # Link privately to avoid exporting nlohmann_json target, but propagate include path + # for consumers who include scy/json/json.h (which includes ) + get_target_property(_nlohmann_inc nlohmann_json::nlohmann_json INTERFACE_INCLUDE_DIRECTORIES) + target_include_directories(json PUBLIC ${_nlohmann_inc}) endif() diff --git a/src/json/include/scy/json/configuration.h b/src/json/include/scy/json/configuration.h index a907a28f0..b1561b0b7 100644 --- a/src/json/include/scy/json/configuration.h +++ b/src/json/include/scy/json/configuration.h @@ -9,12 +9,11 @@ /// @{ -#ifndef SCY_JSON_Configuration_H -#define SCY_JSON_Configuration_H +#pragma once -#include "scy/json/json.h" #include "scy/configuration.h" +#include "scy/json/json.h" #include "scy/util.h" #include @@ -61,7 +60,4 @@ class JSON_API Configuration : public scy::Configuration } // namespace scy -#endif // SCY_JSON_Configuration_H - - /// @\} diff --git a/src/json/include/scy/json/iserializable.h b/src/json/include/scy/json/iserializable.h index 19811ac10..3ffe9dae4 100644 --- a/src/json/include/scy/json/iserializable.h +++ b/src/json/include/scy/json/iserializable.h @@ -9,8 +9,7 @@ /// @{ -#ifndef SCY_JSON_ISerializable_h -#define SCY_JSON_ISerializable_h +#pragma once #include "scy/json/json.h" @@ -50,9 +49,7 @@ inline bool deserialize(ISerializable* pObj, std::string& input) try { json::value deserializeRoot = json::value::parse(input.begin(), input.end()); pObj->deserialize(deserializeRoot); - } - catch (std::invalid_argument&) { - // LError("Cannot deserialize object: ", exc.what()) + } catch (const std::exception&) { return false; } @@ -62,6 +59,3 @@ inline bool deserialize(ISerializable* pObj, std::string& input) } // namespace json } // namespace scy - - -#endif // SCY_JSON_ISerializable_h diff --git a/src/json/include/scy/json/json.h b/src/json/include/scy/json/json.h index 83eceb7ac..a9cc1c3ff 100644 --- a/src/json/include/scy/json/json.h +++ b/src/json/include/scy/json/json.h @@ -9,14 +9,13 @@ /// @{ -#ifndef SCY_JSON_H -#define SCY_JSON_H +#pragma once #include "scy/base.h" #include "scy/error.h" -#include "json.hpp" // include nlohmann json +#include #include #include @@ -24,13 +23,13 @@ // Shared library exports #if defined(SCY_WIN) && defined(SCY_SHARED_LIBRARY) - #if defined(JSON_EXPORTS) - #define JSON_API __declspec(dllexport) - #else - #define JSON_API __declspec(dllimport) - #endif +#if defined(JSON_EXPORTS) +#define JSON_API __declspec(dllexport) #else - #define JSON_API // nothing +#define JSON_API __declspec(dllimport) +#endif +#else +#define JSON_API // nothing #endif @@ -100,6 +99,8 @@ inline void assertMember(const json::value& root, const std::string& name) inline void countNestedKeys(json::value& root, const std::string& key, int& count, int depth = 0) { + if (!root.is_object() && !root.is_array()) + return; depth++; for (auto it = root.begin(); it != root.end(); ++it) { if ((*it).is_object() && (*it).find(key) != (*it).end()) @@ -111,6 +112,8 @@ inline void countNestedKeys(json::value& root, const std::string& key, inline bool hasNestedKey(json::value& root, const std::string& key, int depth = 0) { + if (!root.is_object() && !root.is_array()) + return false; depth++; for (auto it = root.begin(); it != root.end(); it++) { if ((*it).is_object() && (*it).find(key) != (*it).end()) @@ -131,7 +134,7 @@ inline bool hasNestedKey(json::value& root, const std::string& key, int depth = inline bool findNestedObjectWithProperty( json::value& root, json::value*& result, const std::string& key, const std::string& value, bool partial = true, int index = 0, - int depth = 0) + int depth = 0) { depth++; if (root.is_object()) { @@ -172,7 +175,4 @@ inline bool findNestedObjectWithProperty( } // namespace scy -#endif // SCY_JSON_H - - /// @\} diff --git a/src/json/src/configuration.cpp b/src/json/src/configuration.cpp index 96a617a52..c58a9340e 100644 --- a/src/json/src/configuration.cpp +++ b/src/json/src/configuration.cpp @@ -46,7 +46,7 @@ void Configuration::load(bool /* create */) throw std::runtime_error( "Cannot load configuration: File path not set."); - LDebug("Load: ", _path) + LDebug("Load: ", _path); try { // if (create && !fs::exists(_path)) diff --git a/src/json/tests/CMakeLists.txt b/src/json/tests/CMakeLists.txt new file mode 100644 index 000000000..db0a051e3 --- /dev/null +++ b/src/json/tests/CMakeLists.txt @@ -0,0 +1 @@ +scy_add_test(jsontests DEPENDS base json) diff --git a/src/json/tests/jsontests.cpp b/src/json/tests/jsontests.cpp new file mode 100644 index 000000000..04470f5c2 --- /dev/null +++ b/src/json/tests/jsontests.cpp @@ -0,0 +1,431 @@ +#include "scy/base.h" +#include "scy/filesystem.h" +#include "scy/json/configuration.h" +#include "scy/json/iserializable.h" +#include "scy/json/json.h" +#include "scy/test.h" + +#include +#include + + +using namespace std; +using namespace scy; +using namespace scy::test; + + +// Helper: create a temp JSON file and return its path +static std::string writeTempJson(const std::string& content) +{ + std::string path = fs::makePath(SCY_SOURCE_DIR, ".."); + fs::addnode(path, "json_test_tmp.json"); + std::ofstream ofs(path); + ofs << content; + ofs.close(); + return path; +} + +static void removeTempJson(const std::string& path) +{ + std::remove(path.c_str()); +} + + +// ============================================================================= +// ISerializable test object +// +struct TestObject : public json::ISerializable +{ + std::string name; + int value; + + TestObject(const std::string& n = "", int v = 0) + : name(n) + , value(v) + {} + + void serialize(json::value& root) override + { + root["name"] = name; + root["value"] = value; + } + + void deserialize(json::value& root) override + { + name = root["name"].get(); + value = root["value"].get(); + } +}; + + +int main(int argc, char** argv) +{ + test::init(); + + // ========================================================================= + // json::value basics + // + describe("json value basics", []() { + json::value j; + j["name"] = "test"; + j["count"] = 42; + j["active"] = true; + j["tags"] = {"a", "b", "c"}; + + expect(j["name"] == "test"); + expect(j["count"] == 42); + expect(j["active"] == true); + expect(j["tags"].size() == 3); + expect(j["tags"][0] == "a"); + }); + + + // ========================================================================= + // json::value parse and dump + // + describe("json parse and dump", []() { + std::string input = R"({"key":"value","num":123})"; + json::value j = json::value::parse(input); + + expect(j["key"] == "value"); + expect(j["num"] == 123); + + std::string output = j.dump(); + expect(output.find("key") != std::string::npos); + expect(output.find("value") != std::string::npos); + }); + + + // ========================================================================= + // assertMember + // + describe("assertMember", []() { + json::value j; + j["exists"] = "yes"; + + // Should not throw + json::assertMember(j, "exists"); + + // Should throw for missing member + bool threw = false; + try { + json::assertMember(j, "missing"); + } catch (const std::runtime_error& e) { + threw = true; + expect(std::string(e.what()).find("missing") != std::string::npos); + } + expect(threw); + }); + + + // ========================================================================= + // loadFile / saveFile round-trip + // + describe("loadFile and saveFile", []() { + json::value original; + original["name"] = "libsourcey"; + original["version"] = 2; + original["features"] = {"networking", "crypto", "av"}; + + std::string path = writeTempJson("{}"); // placeholder + + // Save + json::saveFile(path, original, 2); + + // Load back + json::value loaded; + json::loadFile(path, loaded); + + expect(loaded["name"] == "libsourcey"); + expect(loaded["version"] == 2); + expect(loaded["features"].size() == 3); + expect(loaded["features"][1] == "crypto"); + + removeTempJson(path); + }); + + + // ========================================================================= + // loadFile nonexistent throws + // + describe("loadFile nonexistent throws", []() { + json::value j; + bool threw = false; + try { + json::loadFile("/nonexistent/path/file.json", j); + } catch (const std::runtime_error&) { + threw = true; + } + expect(threw); + }); + + + // ========================================================================= + // saveFile with no indent (compact) + // + describe("saveFile compact", []() { + json::value j; + j["a"] = 1; + + std::string path = writeTempJson("{}"); + json::saveFile(path, j, 0); + + // Read raw file content - should have no newlines in the JSON body + std::ifstream ifs(path); + std::string content((std::istreambuf_iterator(ifs)), + std::istreambuf_iterator()); + expect(content.find('\n') == std::string::npos); + + removeTempJson(path); + }); + + + // ========================================================================= + // countNestedKeys + // + describe("countNestedKeys", []() { + json::value j = json::value::parse(R"({ + "items": [ + {"type": "a", "nested": {"type": "b"}}, + {"type": "c"}, + {"other": "d"} + ] + })"); + + int count = 0; + json::countNestedKeys(j, "type", count); + expect(count == 3); // three objects have "type" + }); + + + // ========================================================================= + // hasNestedKey + // + describe("hasNestedKey", []() { + json::value j = json::value::parse(R"({ + "level1": { + "level2": { + "target": "found" + } + } + })"); + + expect(json::hasNestedKey(j, "target")); + expect(!json::hasNestedKey(j, "nonexistent")); + }); + + + // ========================================================================= + // findNestedObjectWithProperty + // + describe("findNestedObjectWithProperty", []() { + json::value j = json::value::parse(R"({ + "items": [ + {"name": "alpha", "id": 1}, + {"name": "beta", "id": 2}, + {"name": "gamma", "id": 3} + ] + })"); + + json::value* result = nullptr; + bool found = json::findNestedObjectWithProperty(j, result, "", "beta"); + expect(found); + expect(result != nullptr); + expect((*result)["id"] == 2); + }); + + + // ========================================================================= + // findNestedObjectWithProperty - not found + // + describe("findNestedObjectWithProperty not found", []() { + json::value j = json::value::parse(R"({"items": [{"name": "x"}]})"); + + json::value* result = nullptr; + bool found = json::findNestedObjectWithProperty(j, result, "", "zzz"); + expect(!found); + }); + + + // ========================================================================= + // ISerializable + // + describe("iserializable serialize", []() { + TestObject obj("hello", 42); + + std::string output; + bool ok = json::serialize(&obj, output); + expect(ok); + expect(output.find("hello") != std::string::npos); + expect(output.find("42") != std::string::npos); + }); + + + // ========================================================================= + // ISerializable deserialize + // + describe("iserializable deserialize", []() { + TestObject obj; + std::string input = R"({"name":"world","value":99})"; + + bool ok = json::deserialize(&obj, input); + expect(ok); + expect(obj.name == "world"); + expect(obj.value == 99); + }); + + + // ========================================================================= + // ISerializable round-trip + // + describe("iserializable round-trip", []() { + TestObject original("roundtrip", 777); + + std::string serialized; + json::serialize(&original, serialized); + + TestObject restored; + json::deserialize(&restored, serialized); + + expect(restored.name == original.name); + expect(restored.value == original.value); + }); + + + // ========================================================================= + // ISerializable null pointer + // + describe("iserializable null pointer", []() { + std::string output; + expect(!json::serialize(nullptr, output)); + + std::string input = "{}"; + expect(!json::deserialize(nullptr, input)); + }); + + + // ========================================================================= + // ISerializable invalid JSON + // + describe("iserializable invalid json", []() { + TestObject obj; + std::string bad = "not valid json {{{"; + bool ok = json::deserialize(&obj, bad); + expect(!ok); + }); + + + // ========================================================================= + // Configuration - set/get via base class API + // + describe("configuration set and get", []() { + std::string path = writeTempJson("{}"); + + json::Configuration config; + config.load(path, true); + + config.setString("name", "test"); + config.setInt("port", 8080); + config.setBool("debug", true); + config.setDouble("ratio", 3.14); + + expect(config.getString("name") == "test"); + expect(config.getInt("port") == 8080); + expect(config.getBool("debug") == true); + expect(config.getDouble("ratio") > 3.13); + expect(config.getDouble("ratio") < 3.15); + + expect(config.loaded()); + + removeTempJson(path); + }); + + + // ========================================================================= + // Configuration - save and reload + // + describe("configuration save and reload", []() { + std::string path = writeTempJson("{}"); + + // Write config + { + json::Configuration config; + config.load(path, true); + config.setString("app.name", "libsourcey"); + config.setInt("app.version", 2); + config.save(); + } + + // Reload in fresh instance + { + json::Configuration config; + config.load(path); + expect(config.getString("app.name") == "libsourcey"); + expect(config.getInt("app.version") == 2); + } + + removeTempJson(path); + }); + + + // ========================================================================= + // Configuration - remove + // + describe("configuration remove", []() { + std::string path = writeTempJson("{}"); + + json::Configuration config; + config.load(path, true); + config.setString("keep", "yes"); + config.setString("remove_me", "bye"); + + expect(config.exists("remove_me")); + config.remove("remove_me"); + expect(!config.exists("remove_me")); + expect(config.exists("keep")); + + removeTempJson(path); + }); + + + // ========================================================================= + // Configuration - keys + // + describe("configuration keys", []() { + std::string path = writeTempJson("{}"); + + json::Configuration config; + config.load(path, true); + config.setString("a", "1"); + config.setString("b", "2"); + config.setString("c", "3"); + + std::vector keys; + config.keys(keys); + expect(keys.size() == 3); + + removeTempJson(path); + }); + + + // ========================================================================= + // Configuration - default values + // + describe("configuration defaults", []() { + std::string path = writeTempJson("{}"); + + json::Configuration config; + config.load(path, true); + + expect(config.getString("missing", "fallback") == "fallback"); + expect(config.getInt("missing", 42) == 42); + expect(config.getBool("missing", true) == true); + expect(config.getDouble("missing", 1.5) == 1.5); + + removeTempJson(path); + }); + + + test::runAll(); + return test::finalize(); +} diff --git a/src/net/CMakeLists.txt b/src/net/CMakeLists.txt index 713a89feb..f15983378 100644 --- a/src/net/CMakeLists.txt +++ b/src/net/CMakeLists.txt @@ -1,6 +1,6 @@ -ask_build_sourcey_module(net) -if(BUILD_MODULES OR (NOT BUILD_MODULES AND BUILD_MODULE_net)) - include_dependency(SSL REQUIRED) - - define_sourcey_module(net base crypto) +if(HAVE_OPENSSL) + scy_add_module(net + DEPENDS base crypto + PACKAGES OpenSSL::SSL OpenSSL::Crypto + ) endif() diff --git a/src/net/include/scy/net/address.h b/src/net/include/scy/net/address.h index 65f2851fc..1e54a90e0 100644 --- a/src/net/include/scy/net/address.h +++ b/src/net/include/scy/net/address.h @@ -9,13 +9,12 @@ /// @{ -#ifndef SCY_Net_Address_H -#define SCY_Net_Address_H +#pragma once #include "scy/net/net.h" -#include #include +#include namespace scy { @@ -74,7 +73,7 @@ class Net_API Address explicit Address(const std::string& hostAndPort); /// Destroys the Address. - ~Address(); + ~Address() noexcept; /// Assigns another Address. Address& operator=(const Address& addr); @@ -133,7 +132,4 @@ class Net_API Address } // namespace scy -#endif // SCY_Net_Address_H - - /// @\} diff --git a/src/net/include/scy/net/dns.h b/src/net/include/scy/net/dns.h index 7f04e1d6f..06f920f85 100644 --- a/src/net/include/scy/net/dns.h +++ b/src/net/include/scy/net/dns.h @@ -9,14 +9,13 @@ /// @{ -#ifndef SCY_Net_DNS_H -#define SCY_Net_DNS_H +#pragma once -#include "scy/net/net.h" +#include "scy/logger.h" #include "scy/net/address.h" +#include "scy/net/net.h" #include "scy/request.h" -#include "scy/logger.h" #include "scy/util.h" @@ -28,17 +27,17 @@ namespace dns { inline auto resolve(const std::string& host, int port, - std::function callback, + std::function callback, uv::Loop* loop = uv::defaultLoop()) { return uv::createRequest([=](const uv::GetAddrInfoEvent& event) { - if (event.status) { - LWarn("Cannot resolve DNS for ", host, ": ", uv_strerror(event.status)) - callback(event.status, net::Address{}); - } - else - callback(event.status, net::Address{event.addr->ai_addr, static_cast(event.addr->ai_addrlen)}); - }).resolve(host, port, loop); + if (event.status) { + LWarn("Cannot resolve DNS for ", host, ": ", uv_strerror(event.status)); + callback(event.status, net::Address{}); + } else + callback(event.status, net::Address{event.addr->ai_addr, static_cast(event.addr->ai_addrlen)}); + }) + .resolve(host, port, loop); } @@ -47,7 +46,4 @@ inline auto resolve(const std::string& host, int port, } // namespace scy -#endif // SCY_Net_DNS_H - - /// @\} diff --git a/src/net/include/scy/net/net.h b/src/net/include/scy/net/net.h index abc672c61..2a2b6d752 100644 --- a/src/net/include/scy/net/net.h +++ b/src/net/include/scy/net/net.h @@ -9,8 +9,7 @@ /// @{ -#ifndef SCY_Net_H -#define SCY_Net_H +#pragma once #include "scy/base.h" @@ -22,13 +21,12 @@ #ifdef SCY_WIN #include #include -typedef int socklen_t; +using socklen_t = int; // typedef SOCKET scy_socket_t; #else -#include #include +#include // typedef int scy_socket_t; -// Conflicts with WebRTC: webrtc/base/socket.h:116 // #define INVALID_SOCKET -1 #endif @@ -61,7 +59,7 @@ typedef int socklen_t; // process can easily use SO_REUSEPORT sockets to achieve a kind of simple // load balancing and that absolutely for free as the kernel is doing // "all the hard work" for them. -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) #define SCY_HAS_KERNEL_SOCKET_LOAD_BALANCING 1 #endif #endif @@ -69,13 +67,13 @@ typedef int socklen_t; // Shared library exports #if defined(SCY_WIN) && defined(SCY_SHARED_LIBRARY) - #if defined(Net_EXPORTS) - #define Net_API __declspec(dllexport) - #else - #define Net_API __declspec(dllimport) - #endif +#if defined(Net_EXPORTS) +#define Net_API __declspec(dllexport) +#else +#define Net_API __declspec(dllimport) +#endif #else - #define Net_API // nothing +#define Net_API // nothing #endif @@ -83,8 +81,8 @@ namespace scy { namespace net { -const int MAX_TCP_PACKET_SIZE = 64 * 1024; -const int MAX_UDP_PACKET_SIZE = 1500; +constexpr int MAX_TCP_PACKET_SIZE = 64 * 1024; +constexpr int MAX_UDP_PACKET_SIZE = 1500; enum TransportType @@ -104,6 +102,3 @@ enum SocketMode } // namespace net } // namespace scy - - -#endif diff --git a/src/net/include/scy/net/packetsocket.h b/src/net/include/scy/net/packetsocket.h index a3ebe7c82..577b0b2ac 100644 --- a/src/net/include/scy/net/packetsocket.h +++ b/src/net/include/scy/net/packetsocket.h @@ -9,15 +9,14 @@ /// @{ -#ifndef SCY_Net_PacketSocket_H -#define SCY_Net_PacketSocket_H +#pragma once #include "scy/base.h" -#include "scy/packetfactory.h" -#include "scy/packetsignal.h" #include "scy/net/socket.h" #include "scy/net/socketemitter.h" +#include "scy/packetfactory.h" +#include "scy/packetsignal.h" namespace scy { @@ -29,7 +28,8 @@ namespace net { // -class Net_API PacketSocketEmitter : public SocketEmitter, public PacketSignal +class Net_API PacketSocketEmitter : public SocketEmitter + , public PacketSignal { public: /// Creates the PacketSocketEmitter @@ -40,67 +40,20 @@ class Net_API PacketSocketEmitter : public SocketEmitter, public PacketSignal /// strategies should have the highest priority. PacketSocketEmitter(const Socket::Ptr& socket = nullptr); - virtual ~PacketSocketEmitter(); + virtual ~PacketSocketEmitter() noexcept; - virtual void onSocketRecv(Socket& socket, const MutableBuffer& buffer, const Address& peerAddress) override; + virtual bool onSocketRecv(Socket& socket, const MutableBuffer& buffer, const Address& peerAddress) override; - virtual void onPacket(IPacket& pkt); + /// Process a parsed packet. Returns true to stop propagation. + virtual bool onPacket(IPacket& pkt); /// The packet factory. PacketFactory factory; }; -#if 0 -// -// Packet Socket -// - - -class Net_API PacketSocket: public PacketSocketEmitter -{ -public: - PacketSocket(Socket* socket); - //PacketSocket(Socket* base, bool shared = false); - virtual ~PacketSocket(); /// Returns the PacketSocketEmitter for this socket. - //PacketSocketEmitter& adapter() const; - - /// Compatibility method for PacketSignal delegates. - //virtual void send(IPacket& packet); - -}; - - -// -// Packet Stream Socket Adapter -// - -/// Proxies arbitrary PacketStream packets to an output Socket, -/// ensuring the Socket MTU is not exceeded. -/// Oversize packets will be split before sending. -class Net_API PacketStreamSocketAdapter: public PacketProcessor, public PacketSignal -{ -public: - PacketStreamSocketAdapter(Socket& socket); - virtual ~PacketStreamSocketAdapter(); - -protected: - virtual bool accepts(IPacket* packet); - virtual void process(IPacket& packet); - virtual void onStreamStateChange(const PacketStreamState& state); - - friend class PacketStream; - - Socket _socket; -}; -#endif - - } // namespace net } // namespace scy -#endif // SCY_Net_PacketSocket_H - - /// @\} diff --git a/src/net/include/scy/net/socket.h b/src/net/include/scy/net/socket.h index e540693ff..1e4ac3827 100644 --- a/src/net/include/scy/net/socket.h +++ b/src/net/include/scy/net/socket.h @@ -9,20 +9,20 @@ /// @{ -#ifndef SCY_Net_Socket_H -#define SCY_Net_Socket_H +#pragma once #include "scy/base.h" -#include "scy/memory.h" #include "scy/handle.h" -#include "scy/packetstream.h" -#include "scy/net/net.h" #include "scy/net/address.h" +#include "scy/net/net.h" #include "scy/net/socketadapter.h" +#include "scy/packetstream.h" #include "uv.h" +#include + namespace scy { namespace net { @@ -42,11 +42,16 @@ inline std::shared_ptr makeSocket(uv::Loop* loop = uv::defaultLoop()) class Net_API Socket : public SocketAdapter { public: - typedef std::shared_ptr Ptr; - typedef std::vector Vec; + using Ptr = std::shared_ptr; + using Vec = std::vector; Socket() = default; - virtual ~Socket() = default; + virtual ~Socket() noexcept = default; + + Socket(const Socket&) = delete; + Socket& operator=(const Socket&) = delete; + Socket(Socket&&) = delete; + Socket& operator=(Socket&&) = delete; /// Connects to the given peer IP address. /// @@ -74,7 +79,7 @@ class Net_API Socket : public SocketAdapter /// Sends the shutdown packet which should result is socket /// closure via callback. - virtual bool shutdown() + [[nodiscard]] virtual bool shutdown() { assert(0 && "not implemented by protocol"); return false; @@ -114,11 +119,10 @@ class Net_API Socket : public SocketAdapter /// Returns the socket event loop. virtual uv::Loop* loop() const = 0; - /// Optional client data pointer. + /// Optional client data. /// - /// The pointer is set to null on initialization - /// but not managed. - void* opaque { nullptr }; + /// The value is empty on initialization. + std::any opaque; protected: /// Initializes the underlying socket context. @@ -127,7 +131,7 @@ class Net_API Socket : public SocketAdapter /// Resets the socket context for reuse. virtual void reset() = 0; - int _af { AF_UNSPEC }; + int _af{AF_UNSPEC}; }; @@ -159,9 +163,9 @@ struct PacketInfo : public IPacketInfo { } - virtual IPacketInfo* clone() const { return new PacketInfo(*this); } + virtual std::unique_ptr clone() const { return std::make_unique(*this); } - virtual ~PacketInfo(){}; + virtual ~PacketInfo() noexcept = default; }; @@ -179,30 +183,31 @@ struct PacketInfo : public IPacketInfo class Net_API SocketPacket : public RawPacket { public: - /// PacketInfo pointer - PacketInfo* info; - SocketPacket(const Socket::Ptr& socket, const MutableBuffer& buffer, const Address& peerAddress) - : RawPacket(bufferCast(buffer), buffer.size(), 0, socket.get(), nullptr, - new PacketInfo(socket, peerAddress)) + : RawPacket(bufferCast(buffer), buffer.size(), 0, nullptr, + std::make_unique(socket, peerAddress)) { - info = (PacketInfo*)RawPacket::info; } SocketPacket(const SocketPacket& that) : RawPacket(that) - , info(that.info) { } - virtual ~SocketPacket() {} + /// Returns the PacketInfo for this socket packet. + PacketInfo* packetInfo() const + { + return static_cast(info.get()); + } + + virtual ~SocketPacket() noexcept = default; virtual void print(std::ostream& os) const { - os << className() << ": " << info->peerAddress << std::endl; + os << className() << ": " << packetInfo()->peerAddress << std::endl; } - virtual IPacket* clone() const { return new SocketPacket(*this); } + virtual std::unique_ptr clone() const { return std::make_unique(*this); } virtual ssize_t read(const ConstBuffer&) { @@ -224,7 +229,4 @@ class Net_API SocketPacket : public RawPacket } // namespace scy -#endif // SCY_Net_Socket_H - - /// @\} diff --git a/src/net/include/scy/net/socketadapter.h b/src/net/include/scy/net/socketadapter.h index a7e2aaab2..2e36bf44a 100644 --- a/src/net/include/scy/net/socketadapter.h +++ b/src/net/include/scy/net/socketadapter.h @@ -9,12 +9,10 @@ /// @{ -#ifndef SCY_Net_SocketAdapter_H -#define SCY_Net_SocketAdapter_H +#pragma once #include "scy/base.h" -#include "scy/memory.h" #include "scy/net/address.h" #include "scy/net/dns.h" #include "scy/net/net.h" @@ -44,15 +42,15 @@ class Net_API SocketAdapter SocketAdapter(SocketAdapter* sender = nullptr); /// Destroys the SocketAdapter. - virtual ~SocketAdapter(); + virtual ~SocketAdapter() noexcept; /// Sends the given data buffer to the connected peer. /// Returns the number of bytes sent or -1 on error. /// No exception will be thrown. /// For TCP sockets the given peer address must match the /// connected peer address. - virtual ssize_t send(const char* data, size_t len, int flags = 0); - virtual ssize_t send(const char* data, size_t len, const Address& peerAddress, int flags = 0); + [[nodiscard]] virtual ssize_t send(const char* data, size_t len, int flags = 0); + [[nodiscard]] virtual ssize_t send(const char* data, size_t len, const Address& peerAddress, int flags = 0); /// Sends the given packet to the connected peer. /// Returns the number of bytes sent or -1 on error. @@ -93,10 +91,11 @@ class Net_API SocketAdapter /// These virtual methods can be overridden as necessary /// to intercept socket events before they hit the application. - virtual void onSocketConnect(Socket& socket); - virtual void onSocketRecv(Socket& socket, const MutableBuffer& buffer, const Address& peerAddress); - virtual void onSocketError(Socket& socket, const Error& error); - virtual void onSocketClose(Socket& socket); + /// Return true to stop propagation to subsequent receivers. + virtual bool onSocketConnect(Socket& socket); + virtual bool onSocketRecv(Socket& socket, const MutableBuffer& buffer, const Address& peerAddress); + virtual bool onSocketError(Socket& socket, const Error& error); + virtual bool onSocketClose(Socket& socket); /// The priority of this adapter for STL sort operations. int priority = 0; @@ -106,7 +105,7 @@ class Net_API SocketAdapter struct Ref { - typedef std::shared_ptr ptr_t; + using ptr_t = std::shared_ptr; SocketAdapter* ptr; bool alive; @@ -122,7 +121,4 @@ class Net_API SocketAdapter } // namespace scy -#endif // SCY_Net_SocketAdapter_H - - /// @\} diff --git a/src/net/include/scy/net/socketemitter.h b/src/net/include/scy/net/socketemitter.h index 8e7975abc..74a4d15f5 100644 --- a/src/net/include/scy/net/socketemitter.h +++ b/src/net/include/scy/net/socketemitter.h @@ -9,8 +9,7 @@ /// @{ -#ifndef SCY_Net_SocketEmitter_H -#define SCY_Net_SocketEmitter_H +#pragma once #include "scy/base.h" @@ -39,21 +38,21 @@ class Net_API SocketEmitter : public SocketAdapter SocketEmitter(const SocketEmitter& that); /// Destroys the SocketAdapter. - virtual ~SocketEmitter(); + virtual ~SocketEmitter() noexcept; /// Signals that the socket is connected. - Signal Connect; + Signal Connect; /// Signals when data is received by the socket. - Signal Recv; + Signal Recv; /// Signals that the socket is closed in error. /// This signal will be sent just before the /// Closed signal. - Signal Error; + Signal Error; /// Signals that the underlying socket is closed. - Signal Close; + Signal Close; /// Adds an input SocketAdapter for receiving socket signals. virtual void addReceiver(SocketAdapter* adapter) override; @@ -82,141 +81,16 @@ class Net_API SocketEmitter : public SocketAdapter Socket::Ptr impl; protected: - /// Internal callback events. - virtual void onSocketConnect(Socket& socket); - virtual void onSocketRecv(Socket& socket, const MutableBuffer& buffer, const Address& peerAddress); - virtual void onSocketError(Socket& socket, const scy::Error& error); - virtual void onSocketClose(Socket& socket); + virtual bool onSocketConnect(Socket& socket); + virtual bool onSocketRecv(Socket& socket, const MutableBuffer& buffer, const Address& peerAddress); + virtual bool onSocketError(Socket& socket, const scy::Error& error); + virtual bool onSocketClose(Socket& socket); }; -#if 0 - -/// This class provides request/response functionality for IPacket -/// types emitted from a Socket. -template -class Net_API SocketEmitter : public SocketT -{ -public: - /// Pointer to the underlying socket. - /// Sent data will be proxied to this socket. - // Socket::Ptr socket; - - /// Creates the SocketEmitter - SocketEmitter(); - - /// Destroys the SocketAdapter. - virtual ~SocketEmitter(); - - /// Adds an input SocketAdapter for receiving socket signals. - virtual void addReceiver(SocketAdapter* adapter, int priority = 0); - - /// Removes an input SocketAdapter. - virtual void removeReceiver(SocketAdapter* adapter); - - /// Signals that the socket is connected. - Signal Connect; - - /// Signals when data is received by the socket. - Signal Recv; - - /// Signals that the socket is closed in error. - /// This signal will be sent just before the - /// Closed signal. - Signal Error; - - /// Signals that the underlying socket is closed. - Signal Close; - -protected: - - /// Internal callback events. - virtual void onSocketConnect(Socket& socket); - virtual void onSocketRecv(Socket& socket, const MutableBuffer& buffer, const Address& peerAddress); - virtual void onSocketError(Socket& socket, const scy::Error& error); - virtual void onSocketClose(Socket& socket); -}; - - -template -inline void SocketEmitter::addReceiver(SocketAdapter* adapter, int priority) -{ - Connect.attach(slot(adapter, &net::SocketAdapter::onSocketConnect, -1, priority)); - Recv.attach(slot(adapter, &net::SocketAdapter::onSocketRecv, -1, priority)); - Error.attach(slot(adapter, &net::SocketAdapter::onSocketError, -1, priority)); - Close.attach(slot(adapter, &net::SocketAdapter::onSocketClose, -1, priority)); -} - - -template -inline void SocketEmitter::removeReceiver(SocketAdapter* adapter) -{ - Connect.detach(adapter); - Recv.detach(adapter); - Error.detach(adapter); - Close.detach(adapter); - - // Connect -= slot(adapter, &net::SocketAdapter::onSocketConnect); - // Recv -= slot(adapter, &net::SocketAdapter::onSocketRecv); - // Error -= slot(adapter, &net::SocketAdapter::onSocketError); - // Close -= slot(adapter, &net::SocketAdapter::onSocketClose); -} - - -template -inline void SocketEmitter::onSocketConnect(Socket& sock) -{ - assert(&sock == socket.get()); - if (_receiver) - _receiver->onSocketConnect(sock); - else - Connect.emit(sock); -} - - -template -inline void SocketEmitter::onSocketRecv(Socket& sock, const MutableBuffer& buffer, const Address& peerAddress) -{ - assert(&sock == socket.get()); - if (_receiver) - _receiver->onSocketRecv(sock, buffer, peerAddress); - else - Recv.emit(sock, buffer, peerAddress); -} - - -template -inline void SocketEmitter::onSocketError(Socket& sock, const scy::Error& error) // const Error& error -{ - assert(&sock == socket.get()); - if (_receiver) - _receiver->onSocketError(sock, error); - else - Error.emit(sock, error); -} - - - -template -inline void SocketEmitter::onSocketClose(Socket& sock) -{ - assert(&sock == socket.get()); - if (_receiver) - _receiver->onSocketClose(sock); - else - Close.emit(sock); -} - -#endif - - - } // namespace net } // namespace scy -#endif // SCY_Net_SocketEmitter_H - - /// @\} diff --git a/src/net/include/scy/net/ssladapter.h b/src/net/include/scy/net/ssladapter.h index 03b9709ab..c52ffa5fe 100644 --- a/src/net/include/scy/net/ssladapter.h +++ b/src/net/include/scy/net/ssladapter.h @@ -9,14 +9,13 @@ /// @{ -#ifndef SCY_Net_SSLAdapter_H -#define SCY_Net_SSLAdapter_H +#pragma once #include "scy/crypto/crypto.h" +#include "scy/handle.h" #include "scy/net/address.h" #include "scy/net/net.h" -#include "scy/handle.h" #include #include @@ -30,16 +29,19 @@ namespace scy { namespace net { - -/// A wrapper for the OpenSSL SSL connection context -/// -/// TODO: Decouple from SSLSocket implementation +/// A wrapper for the OpenSSL SSL connection context. +/// Currently coupled to SSLSocket for BIO read/write callbacks. class Net_API SSLSocket; class Net_API SSLAdapter { public: SSLAdapter(net::SSLSocket* socket); - ~SSLAdapter(); + ~SSLAdapter() noexcept; + + SSLAdapter(const SSLAdapter&) = delete; + SSLAdapter& operator=(const SSLAdapter&) = delete; + SSLAdapter(SSLAdapter&&) = delete; + SSLAdapter& operator=(SSLAdapter&&) = delete; /// Initializes the SSL context as a client. void initClient(); @@ -66,6 +68,10 @@ class Net_API SSLAdapter /// Flushes the SSL read/write buffers. void flush(); + /// Set the expected peer hostname for certificate verification. + /// Must be called before initClient() to enable hostname verification. + void setHostname(const std::string& hostname); + void addIncomingData(const char* data, size_t len); void addOutgoingData(const std::string& data); void addOutgoingData(const char* data, size_t len); @@ -81,9 +87,10 @@ class Net_API SSLAdapter net::SSLSocket* _socket; SSL* _ssl; - BIO* _readBIO; ///< The incoming buffer we write encrypted SSL data into - BIO* _writeBIO; ///< The outgoing buffer we write to the socket + BIO* _readBIO; ///< The incoming buffer we write encrypted SSL data into + BIO* _writeBIO; ///< The outgoing buffer we write to the socket std::vector _bufferOut; ///< The outgoing payload to be encrypted and sent + std::string _hostname; ///< Expected peer hostname for verification }; @@ -91,7 +98,4 @@ class Net_API SSLAdapter } // namespace scy -#endif // SCY_Net_SSLAdapter_H - - /// @\} diff --git a/src/net/include/scy/net/sslcontext.h b/src/net/include/scy/net/sslcontext.h index 37d4beee7..da6b61340 100644 --- a/src/net/include/scy/net/sslcontext.h +++ b/src/net/include/scy/net/sslcontext.h @@ -9,20 +9,21 @@ /// @{ -#ifndef SCY_Net_SSLContext_H -#define SCY_Net_SSLContext_H +#pragma once -#include "scy/net/net.h" #include "scy/crypto/crypto.h" #include "scy/crypto/rsa.h" #include "scy/crypto/x509certificate.h" -#include "scy/memory.h" +#include "scy/net/net.h" +#include "scy/util.h" #include #include #include +#include +#include namespace scy { @@ -40,7 +41,7 @@ namespace net { class Net_API SSLContext { public: - typedef std::shared_ptr Ptr; + using Ptr = std::shared_ptr; enum Usage { @@ -148,7 +149,7 @@ class Net_API SSLContext const std::string& cipherList = "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"); /// Destroys the Context. - ~SSLContext(); + ~SSLContext() noexcept; /// Sets the certificate to be used by the Context. /// @@ -158,10 +159,10 @@ class Net_API SSLContext /// /// Note that useCertificate() must always be called before /// usePrivateKey(). - void useCertificate(const crypto::X509Certificate& certificate); + void useCertificate(crypto::X509Certificate& certificate); /// Adds a certificate for certificate chain validation. - void addChainCertificate(const crypto::X509Certificate& certificate); + void addChainCertificate(crypto::X509Certificate& certificate); /// Sets the private key to be used by the Context. /// @@ -177,7 +178,7 @@ class Net_API SSLContext /// Adds the given certificate to the list of trusted certificates /// that will be used for verification. - void addVerificationCertificate(const crypto::X509Certificate& certificate); + void addVerificationCertificate(crypto::X509Certificate& certificate); /// Returns the underlying OpenSSL SSL Context object. SSL_CTX* sslContext() const; @@ -261,6 +262,21 @@ class Net_API SSLContext /// The feature can be disabled by calling this method. void disableStatelessSessionResumption(); + /// Set the ALPN protocols for negotiation. + /// Protocols should be in preference order. + /// Example: {"h2", "http/1.1"} + void setALPNProtocols(const std::vector& protocols); + + /// Enable SNI (Server Name Indication) for a specific SSL connection. + /// The hostname is sent during the TLS handshake to allow the server + /// to select the appropriate certificate. + static void enableSNI(SSL* ssl, const std::string& hostname); + + SSLContext(const SSLContext&) = delete; + SSLContext& operator=(const SSLContext&) = delete; + SSLContext(SSLContext&&) = delete; + SSLContext& operator=(SSLContext&&) = delete; + private: /// Create a SSL_CTX object according to Context configuration. void createSSLContext(); @@ -303,8 +319,7 @@ inline SSL_CTX* SSLContext::sslContext() const /// Non-case sensitive conversion of a string to a VerificationMode enum. /// If verMode is illegal an ArgumentException is thrown. -inline SSLContext::VerificationMode -convertVerificationMode(const std::string& vMode) +inline SSLContext::VerificationMode convertVerificationMode(const std::string& vMode) { std::string mode = util::toLower(vMode); SSLContext::VerificationMode verMode = SSLContext::VERIFY_STRICT; @@ -353,9 +368,6 @@ inline void clearErrorStack() } // namespace scy -#endif // SCY_Net_SSLContext_H - - /// @\} diff --git a/src/net/include/scy/net/sslmanager.h b/src/net/include/scy/net/sslmanager.h index bf925840b..2b0f1b966 100644 --- a/src/net/include/scy/net/sslmanager.h +++ b/src/net/include/scy/net/sslmanager.h @@ -11,13 +11,12 @@ // -#ifndef SCY_Net_SSLManager_H -#define SCY_Net_SSLManager_H +#pragma once +#include "scy/net/net.h" #include "scy/net/sslcontext.h" #include "scy/net/sslsession.h" -#include "scy/net/net.h" #include "scy/singleton.h" #include @@ -81,7 +80,8 @@ class Net_API SSLManager static void initNoVerifyClient(); /// Initializes a default no verify server context that's useful for - /// testing. + /// testing. Optionally accepts private key and certificate file paths + /// for server identity; if omitted, no certificate is loaded. static void initNoVerifyServer(const std::string& privateKeyFile = "", const std::string& certificateFile = ""); @@ -109,7 +109,12 @@ class Net_API SSLManager SSLManager(); /// Destroys the SSLManager. - ~SSLManager(); + ~SSLManager() noexcept; + + SSLManager(const SSLManager&) = delete; + SSLManager& operator=(const SSLManager&) = delete; + SSLManager(SSLManager&&) = delete; + SSLManager& operator=(SSLManager&&) = delete; /// The return value of this method defines how errors in /// verification are handled. Return 0 to terminate the handshake, @@ -139,7 +144,7 @@ class Net_API VerificationErrorDetails int errNum, const std::string& errMsg); /// Destroys the VerificationErrorDetails. - ~VerificationErrorDetails(); + ~VerificationErrorDetails() noexcept; /// Returns the certificate that caused the error. const crypto::X509Certificate& certificate() const; @@ -210,9 +215,6 @@ inline bool VerificationErrorDetails::getIgnoreError() const } // namespace scy -#endif // SCY_Net_SSLManager_H - - /// @\} diff --git a/src/net/include/scy/net/sslsession.h b/src/net/include/scy/net/sslsession.h index 17002143d..f78198c91 100644 --- a/src/net/include/scy/net/sslsession.h +++ b/src/net/include/scy/net/sslsession.h @@ -9,14 +9,13 @@ /// @{ -#ifndef SCY_Net_SSLSession_H -#define SCY_Net_SSLSession_H +#pragma once #include "scy/crypto/crypto.h" -#include "scy/memory.h" #include "scy/net/net.h" +#include #include @@ -33,7 +32,7 @@ namespace net { class Net_API SSLSession { public: - typedef std::shared_ptr Ptr; + using Ptr = std::shared_ptr; /// Returns the stored OpenSSL SSL_SESSION object. SSL_SESSION* sslSession() const; @@ -48,10 +47,15 @@ class Net_API SSLSession /// /// Calls SSL_SESSION_free() on the stored /// SSL_SESSION object. - ~SSLSession(); + ~SSLSession() noexcept; SSLSession(); + SSLSession(const SSLSession&) = delete; + SSLSession& operator=(const SSLSession&) = delete; + SSLSession(SSLSession&&) = delete; + SSLSession& operator=(SSLSession&&) = delete; + protected: SSL_SESSION* _ptr; }; @@ -61,9 +65,6 @@ class Net_API SSLSession } // namespace scy -#endif // SCY_Net_SSLSession_H - - /// @\} diff --git a/src/net/include/scy/net/sslsocket.h b/src/net/include/scy/net/sslsocket.h index d22bd47a6..3bf4d245e 100644 --- a/src/net/include/scy/net/sslsocket.h +++ b/src/net/include/scy/net/sslsocket.h @@ -9,16 +9,15 @@ /// @{ -#ifndef SCY_Net_SSLSocket_H -#define SCY_Net_SSLSocket_H +#pragma once +#include "scy/handle.h" #include "scy/net/socket.h" #include "scy/net/ssladapter.h" #include "scy/net/sslcontext.h" #include "scy/net/sslsession.h" #include "scy/net/tcpsocket.h" -#include "scy/handle.h" namespace scy { @@ -29,15 +28,15 @@ namespace net { class Net_API SSLSocket : public TCPSocket { public: - typedef std::shared_ptr Ptr; - typedef std::vector Vec; + using Ptr = std::shared_ptr; + using Vec = std::vector; SSLSocket(uv::Loop* loop = uv::defaultLoop()); //, SocketMode mode = ClientSide SSLSocket(SSLContext::Ptr sslContext, uv::Loop* loop = uv::defaultLoop()); SSLSocket(SSLContext::Ptr sslContext, SSLSession::Ptr session, uv::Loop* loop = uv::defaultLoop()); - virtual ~SSLSocket(); + virtual ~SSLSocket() noexcept; /// Initialize the SSLSocket with the given SSLContext. // virtual void init(SSLContext::Ptr sslContext, SocketMode mode = ClientSide); @@ -46,22 +45,26 @@ class Net_API SSLSocket : public TCPSocket /// the TCP server at the given address. /// /// The SSL handshake is performed when the socket is connected. - // virtual void connect(const Address& peerAddress); - + virtual void connect(const Address& peerAddress) override; + virtual void connect(const std::string& host, uint16_t port) override; virtual void bind(const net::Address& address, unsigned flags = 0) override; virtual void listen(int backlog = 64) override; /// Shuts down the connection by attempting /// an orderly SSL shutdown, then actually /// shutting down the TCP connection. - virtual bool shutdown() override; + [[nodiscard]] virtual bool shutdown() override; /// Closes the socket forcefully. virtual void close() override; - virtual ssize_t send(const char* data, size_t len, int flags = 0) override; - virtual ssize_t send(const char* data, size_t len, - const net::Address& peerAddress, int flags = 0) override; + [[nodiscard]] virtual ssize_t send(const char* data, size_t len, int flags = 0) override; + [[nodiscard]] virtual ssize_t send(const char* data, size_t len, + const net::Address& peerAddress, int flags = 0) override; + + /// Set the expected peer hostname for certificate verification and SNI. + /// Must be called before connect() to enable hostname verification. + void setHostname(const std::string& hostname); /// Use the given SSL context for this socket. void useContext(SSLContext::Ptr context); @@ -119,7 +122,4 @@ class Net_API SSLSocket : public TCPSocket } // namespace scy -#endif // SCY_Net_SSLSocket_H - - /// @\} diff --git a/src/net/include/scy/net/tcpsocket.h b/src/net/include/scy/net/tcpsocket.h index ac20d6dd1..dfb10ecba 100644 --- a/src/net/include/scy/net/tcpsocket.h +++ b/src/net/include/scy/net/tcpsocket.h @@ -9,16 +9,15 @@ /// @{ -#ifndef SCY_Net_TCPSocket_H -#define SCY_Net_TCPSocket_H +#pragma once +#include "scy/handle.h" #include "scy/net/address.h" +#include "scy/net/net.h" #include "scy/net/socket.h" #include "scy/net/tcpsocket.h" -#include "scy/net/net.h" #include "scy/stream.h" -#include "scy/handle.h" namespace scy { @@ -26,33 +25,39 @@ namespace net { /// TCP socket implementation. -class Net_API TCPSocket : public Stream, public net::Socket +class Net_API TCPSocket : public Stream + , public net::Socket { public: - typedef std::shared_ptr Ptr; - typedef std::vector Vec; + using Ptr = std::shared_ptr; + using Vec = std::vector; TCPSocket(uv::Loop* loop = uv::defaultLoop()); - virtual ~TCPSocket(); + virtual ~TCPSocket() noexcept; - virtual bool shutdown(); + TCPSocket(const TCPSocket&) = delete; + TCPSocket& operator=(const TCPSocket&) = delete; + TCPSocket(TCPSocket&&) = delete; + TCPSocket& operator=(TCPSocket&&) = delete; + + [[nodiscard]] virtual bool shutdown(); virtual void close() override; virtual void connect(const net::Address& peerAddress) override; virtual void connect(const std::string& host, uint16_t port) override; - virtual ssize_t send(const char* data, size_t len, int flags = 0) override; - virtual ssize_t send(const char* data, size_t len, const net::Address& peerAddress, int flags = 0) override; + [[nodiscard]] virtual ssize_t send(const char* data, size_t len, int flags = 0) override; + [[nodiscard]] virtual ssize_t send(const char* data, size_t len, const net::Address& peerAddress, int flags = 0) override; virtual void bind(const net::Address& address, unsigned flags = 0) override; virtual void listen(int backlog = 64) override; virtual void acceptConnection(); - bool setReusePort(); - bool setNoDelay(bool enable); - bool setKeepAlive(bool enable, int delay); - bool setSimultaneousAccepts(bool enable); + [[nodiscard]] bool setReusePort(); + [[nodiscard]] bool setNoDelay(bool enable); + [[nodiscard]] bool setKeepAlive(bool enable, int delay); + [[nodiscard]] bool setSimultaneousAccepts(bool enable); void setMode(SocketMode mode); const SocketMode mode() const; @@ -76,8 +81,6 @@ class Net_API TCPSocket : public Stream, public net::Socket virtual uv::Loop* loop() const override; - virtual void* self() override; - Signal AcceptConnection; public: @@ -99,7 +102,4 @@ class Net_API TCPSocket : public Stream, public net::Socket } // namespace scy -#endif // SCY_Net_TCPSocket_H - - /// @\} diff --git a/src/net/include/scy/net/transaction.h b/src/net/include/scy/net/transaction.h index cba588809..cc64cc940 100644 --- a/src/net/include/scy/net/transaction.h +++ b/src/net/include/scy/net/transaction.h @@ -9,8 +9,7 @@ /// @{ -#ifndef SCY_Net_Transaction_H -#define SCY_Net_Transaction_H +#pragma once #include "scy/net/packetsocket.h" @@ -24,11 +23,11 @@ namespace net { /// This class provides request/response functionality for IPacket /// types emitted from a Socket. template -class Net_API Transaction : public PacketTransaction, - public PacketSocketEmitter +class Net_API Transaction : public PacketTransaction + , public PacketSocketEmitter { public: - typedef PacketTransaction BaseT; + using BaseT = PacketTransaction; Transaction(const net::Socket::Ptr& socket, const Address& peerAddress, int timeout = 10000, int retries = 1) @@ -36,12 +35,12 @@ class Net_API Transaction : public PacketTransaction, , PacketSocketEmitter(socket) , _peerAddress(peerAddress) { - LTrace("Create") + LTrace("Create"); } virtual bool send() override { - LTrace("Send") + LTrace("Send"); if (impl->sendPacket(BaseT::_request, _peerAddress) > 0) return BaseT::send(); BaseT::setState(this, TransactionState::Failed); @@ -50,13 +49,13 @@ class Net_API Transaction : public PacketTransaction, virtual void cancel() override { - LTrace("Cancel") + LTrace("Cancel"); BaseT::cancel(); } virtual void dispose() override { - LTrace("Dispose") + LTrace("Dispose"); BaseT::dispose(); // gc } @@ -70,21 +69,18 @@ class Net_API Transaction : public PacketTransaction, /// Overrides the PacketSocketEmitter::onPacket /// callback for checking potential response candidates. - virtual void onPacket(IPacket& packet) override + /// Returns true to stop socket data propagation. + virtual bool onPacket(IPacket& packet) override { - LTrace("On packet: ", packet.size()) - if (BaseT::handlePotentialResponse(static_cast(packet))) { - - // Stop socket data propagation since - // we have handled the packet - throw StopPropagation(); - } + LTrace("On packet: ", packet.size()); + // Stop socket data propagation if we handled the packet + return BaseT::handlePotentialResponse(static_cast(packet)); } /// Called when a successful response match is received. virtual void onResponse() override { - LTrace("On success: ", BaseT::_response.toString()) + LTrace("On success: ", BaseT::_response.toString()); PacketSignal::emit(BaseT::_response); } @@ -96,9 +92,8 @@ class Net_API Transaction : public PacketTransaction, assert(packet.info && "socket must provide packet info"); if (!packet.info) return false; - auto info = reinterpret_cast(packet.info); - return impl->address() == info->socket->address() - && _peerAddress == info->peerAddress; + auto info = static_cast(packet.info.get()); + return impl->address() == info->socket->address() && _peerAddress == info->peerAddress; } Address _peerAddress; @@ -109,7 +104,4 @@ class Net_API Transaction : public PacketTransaction, } // namespace scy -#endif // SCY_Net_Transaction_H - - /// @\} diff --git a/src/net/include/scy/net/types.h b/src/net/include/scy/net/types.h index e3f2d2813..9107ada80 100644 --- a/src/net/include/scy/net/types.h +++ b/src/net/include/scy/net/types.h @@ -9,11 +9,7 @@ /// @{ -#ifndef SCY_Net_Types_H -#define SCY_Net_Types_H +#pragma once #include "scy/net/net.h" - - -#endif diff --git a/src/net/include/scy/net/udpsocket.h b/src/net/include/scy/net/udpsocket.h index 3e3ad2f97..f6d46d1b5 100644 --- a/src/net/include/scy/net/udpsocket.h +++ b/src/net/include/scy/net/udpsocket.h @@ -9,14 +9,13 @@ /// @{ -#ifndef SCY_Net_UDPSocket_H -#define SCY_Net_UDPSocket_H +#pragma once +#include "scy/handle.h" #include "scy/net/address.h" -#include "scy/net/socket.h" #include "scy/net/net.h" -#include "scy/handle.h" +#include "scy/net/socket.h" namespace scy { @@ -24,14 +23,20 @@ namespace net { /// UDP socket implementation. -class Net_API UDPSocket : public uv::Handle, public net::Socket +class Net_API UDPSocket : public uv::Handle + , public net::Socket { public: - typedef std::shared_ptr Ptr; - typedef std::vector Vec; + using Ptr = std::shared_ptr; + using Vec = std::vector; UDPSocket(uv::Loop* loop = uv::defaultLoop()); - virtual ~UDPSocket(); + virtual ~UDPSocket() noexcept; + + UDPSocket(const UDPSocket&) = delete; + UDPSocket& operator=(const UDPSocket&) = delete; + UDPSocket(UDPSocket&&) = delete; + UDPSocket& operator=(UDPSocket&&) = delete; virtual void connect(const net::Address& peerAddress) override; virtual void connect(const std::string& host, uint16_t port) override; @@ -39,13 +44,13 @@ class Net_API UDPSocket : public uv::Handle, public net::Socket virtual void bind(const net::Address& address, unsigned flags = 0) override; - virtual ssize_t send(const char* data, size_t len, int flags = 0) override; - virtual ssize_t send(const char* data, size_t len, - const net::Address& peerAddress, int flags = 0) override; + [[nodiscard]] virtual ssize_t send(const char* data, size_t len, int flags = 0) override; + [[nodiscard]] virtual ssize_t send(const char* data, size_t len, + const net::Address& peerAddress, int flags = 0) override; - bool setBroadcast(bool flag); - bool setMulticastLoop(bool flag); - bool setMulticastTTL(int ttl); + [[nodiscard]] bool setBroadcast(bool flag); + [[nodiscard]] bool setMulticastLoop(bool flag); + [[nodiscard]] bool setMulticastTTL(int ttl); virtual net::Address address() const override; virtual net::Address peerAddress() const override; @@ -61,8 +66,6 @@ class Net_API UDPSocket : public uv::Handle, public net::Socket virtual uv::Loop* loop() const override; - virtual void* self() override; - virtual void onRecv(const MutableBuffer& buf, const net::Address& address); protected: @@ -88,7 +91,4 @@ class Net_API UDPSocket : public uv::Handle, public net::Socket } // namespace scy -#endif // SCY_Net_UDPSocket_H - - /// @\} diff --git a/src/net/include/scy/net/util.h b/src/net/include/scy/net/util.h index 66a53d9a1..b8a08c2c1 100644 --- a/src/net/include/scy/net/util.h +++ b/src/net/include/scy/net/util.h @@ -9,13 +9,12 @@ /// @{ -#ifndef SCY_Net_Util_H -#define SCY_Net_Util_H +#pragma once -#include "scy/net/net.h" -#include "scy/net/address.h" #include "scy/handle.h" +#include "scy/net/address.h" +#include "scy/net/net.h" #include @@ -52,8 +51,7 @@ inline void getNetworkInterfaces(std::vector& hosts) // - -#if defined(SCY_WIN) +#if defined(SCY_WIN) #define nativeSocketFd(handle) ((handle)->socket) #else // uv__stream_fd taken from libuv unix/internal.h @@ -101,7 +99,4 @@ int setServerSocketRecvBufSize(uv::Handle& handle, int size) } // namespace scy -#endif // SCY_Net_Util_H - - /// @\} diff --git a/src/net/samples/echoserver/CMakeLists.txt b/src/net/samples/echoserver/CMakeLists.txt index cc9f825fe..3542fe40e 100644 --- a/src/net/samples/echoserver/CMakeLists.txt +++ b/src/net/samples/echoserver/CMakeLists.txt @@ -1 +1 @@ -define_sourcey_module_sample(echoserver base net) +scy_add_sample(echoserver DEPENDS base net) diff --git a/src/net/samples/echoserver/echoserver.cpp b/src/net/samples/echoserver/echoserver.cpp index 160dc0e20..6bab999f6 100644 --- a/src/net/samples/echoserver/echoserver.cpp +++ b/src/net/samples/echoserver/echoserver.cpp @@ -1,123 +1,54 @@ -#include "scy/application.h" -#include "scy/logger.h" -#include "scy/net/sslmanager.h" -#include "tcpechoserver.h" -#include "udpechoserver.h" - - -using std::endl; -using namespace scy; - - -const uint16_t TcpPort = 1337; -const uint16_t SslPort = 1338; -const uint16_t UdpPort = 1339; - - -struct Servers -{ - net::TCPEchoServer tcp; - net::SSLEchoServer ssl; - net::UDPEchoServer udp; -}; - - -int main(int argc, char** argv) -{ - // Logger::instance().add(new ConsoleChannel("debug", Level::Trace)); - // Logger::instance().setWriter(new AsyncLogWriter); - net::SSLManager::initNoVerifyServer(); - { - Servers srvs; - srvs.tcp.start("0.0.0.0", TcpPort); - srvs.ssl.start("0.0.0.0", SslPort); - srvs.udp.start("0.0.0.0", UdpPort); - - std::cout << "TCP Lerver listening on " << srvs.tcp.server->address() << std::endl; - std::cout << "LSL Server listening on " << srvs.ssl.server->address() << std::endl; - std::cout << "UDP Lerver listening on " << srvs.udp.server->address() << std::endl; - - waitForShutdown([&](void*) { - srvs.tcp.shutdown(); - srvs.ssl.shutdown(); - srvs.udp.shutdown(); - }); - } - net::SSLManager::instance().shutdown(); - Logger::destroy(); - return 0; -} - - -#if 0 // raw libuv echo server -#include -#include -#include -#include - -uv_loop_t *loop; -struct sockaddr_in addr; - -void alloc_buffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf) { - buf->base = (char*)malloc(suggested_size); - buf->len = suggested_size; -} - -void echo_write(uv_write_t *req, int status) { - if (status) { - fprintf(stderr, "Write error %s\n", uv_strerror(status)); - } - free(req); -} - -void echo_read(uv_stream_t *client, ssize_t nread, const uv_buf_t *buf) { - if (nread < 0) { - if (nread != UV_EOF) { - fprintf(stderr, "Read error %s\n", uv_err_name(nread)); - uv_close((uv_handle_t*)client, NULL); - } - } - else if (nread > 0) { - uv_write_t *req = (uv_write_t *)malloc(sizeof(uv_write_t)); - uv_buf_t wrbuf = uv_buf_init(buf->base, nread); - uv_write(req, client, &wrbuf, 1, echo_write); - } - - if (buf->base) { - free(buf->base); - } -} - -void on_new_connection(uv_stream_t *server, int status) { - if (status < 0) { - fprintf(stderr, "New connection error %s\n", uv_strerror(status)); - return; - } - - uv_tcp_t *client = (uv_tcp_t*)malloc(sizeof(uv_tcp_t)); - uv_tcp_init(loop, client); - if (uv_accept(server, (uv_stream_t*)client) == 0) { - uv_read_start((uv_stream_t*)client, alloc_buffer, echo_read); - } - else { - uv_close((uv_handle_t*)client, NULL); - } -} - -int main() { - loop = uv_default_loop(); - - uv_tcp_t server; - uv_tcp_init(loop, &server); - - uv_ip4_addr("0.0.0.0", 1337, &addr); - - uv_tcp_bind(&server, (const struct sockaddr*)&addr, 0); - int r = uv_listen((uv_stream_t*)&server, 128, on_new_connection); - if (r) { - fprintf(stderr, "Listen error %s\n", uv_strerror(r)); - return 1; - } - return uv_run(loop, UV_RUN_DEFAULT); -} -#endif +#include "scy/application.h" +#include "scy/logger.h" +#include "scy/net/sslmanager.h" +#include "tcpechoserver.h" +#include "udpechoserver.h" +#include + + +using std::endl; +using namespace scy; + + +const uint16_t TcpPort = 1337; +const uint16_t SslPort = 1338; +const uint16_t UdpPort = 1339; + + +struct Servers +{ + net::TCPEchoServer tcp; + net::SSLEchoServer ssl; + net::UDPEchoServer udp; +}; + + +int main(int argc, char** argv) +{ + // Logger::instance().add(std::make_unique("debug", Level::Trace)); + // Logger::instance().setWriter(std::make_unique()); + if (argc < 3) { + std::cerr << "Usage: " << argv[0] << " " << std::endl; + return 1; + } + net::SSLManager::initNoVerifyServer(argv[1], argv[2]); + { + Servers srvs; + srvs.tcp.start("0.0.0.0", TcpPort); + srvs.ssl.start("0.0.0.0", SslPort); + srvs.udp.start("0.0.0.0", UdpPort); + + std::cout << "TCP server listening on " << srvs.tcp.server->address() << std::endl; + std::cout << "SSL server listening on " << srvs.ssl.server->address() << std::endl; + std::cout << "UDP server listening on " << srvs.udp.server->address() << std::endl; + + waitForShutdown([&](void*) { + srvs.tcp.shutdown(); + srvs.ssl.shutdown(); + srvs.udp.shutdown(); + }); + } + net::SSLManager::instance().shutdown(); + Logger::destroy(); + return 0; +} diff --git a/src/net/samples/echoserver/tcpechoserver.h b/src/net/samples/echoserver/tcpechoserver.h index 518913cad..7746bd4ae 100644 --- a/src/net/samples/echoserver/tcpechoserver.h +++ b/src/net/samples/echoserver/tcpechoserver.h @@ -1,6 +1,8 @@ #include "scy/net/sslsocket.h" #include "scy/net/tcpsocket.h" +#include + namespace scy { namespace net { @@ -49,54 +51,44 @@ class EchoServer : public SocketAdapter // socket->Error += slot(this, &EchoServer::onClientSocketError); // socket->Close += slot(this, &EchoServer::onClientSocketClose); sockets.push_back(socket); - // LDebug("On accept: ", socket) + // LDebug("On accept: ", socket); } - void onSocketRecv(Socket& socket, const MutableBuffer& buffer, const Address& peerAddress) + bool onSocketRecv(Socket& socket, const MutableBuffer& buffer, const Address& peerAddress) { - // LDebug("On recv: ", &socket, ": ", buffer.str()) + // LDebug("On recv: ", &socket, ": ", buffer.str()); // Echo it back socket.send(bufferCast(buffer), buffer.size()); - - // Send a HTTP packet - // std::ostringstream res; - // res << "HTTP/1.1 200 OK\r\n" - // << "Connection: close\r\n" - // << "Content-Length: 0" << "\r\n" - // << "\r\n"; - // std::string response(res.str()); - // socket.send(response.c_str(), response.size()); + return false; } - void onSocketError(Socket& socket, const Error& error) + bool onSocketError(Socket& socket, const Error& error) { - LDebug("On error: ", error.err, ": ", error.message) + LDebug("On error: ", error.err, ": ", error.message); + return false; } - void onSocketClose(Socket& socket) + bool onSocketClose(Socket& socket) { - LDebug("On close") - - for (typename Socket::Vec::iterator it = sockets.begin(); - it != sockets.end(); ++it) { - if (it->get() == &socket) { - LDebug("Removing: ", &socket) - - // All we need to do is erase the socket in order to - // deincrement the ref counter and destroy the socket - sockets.erase(it); - return; - } + LDebug("On close"); + + auto it = std::find_if(sockets.begin(), sockets.end(), + [&](const auto& s) { return s.get() == &socket; }); + if (it != sockets.end()) { + LDebug("Removing: ", &socket); + sockets.erase(it); + return false; } - assert(0 && "unknown socket"); + LError("Unknown socket on close:", &socket); + return false; } }; // Some generic server types -typedef EchoServer TCPEchoServer; -typedef EchoServer SSLEchoServer; +using TCPEchoServer = EchoServer; +using SSLEchoServer = EchoServer; } // namespace net diff --git a/src/net/samples/echoserver/udpechoserver.h b/src/net/samples/echoserver/udpechoserver.h index f7003a540..4b621b8c1 100644 --- a/src/net/samples/echoserver/udpechoserver.h +++ b/src/net/samples/echoserver/udpechoserver.h @@ -1,6 +1,5 @@ #include "scy/net/socketadapter.h" #include "scy/net/udpsocket.h" -#include "scy/time.h" namespace scy { @@ -34,35 +33,25 @@ class UDPEchoServer : public SocketAdapter server->close(); } - void onSocketRecv(Socket&, const MutableBuffer& buffer, const net::Address& peerAddress) override + bool onSocketRecv(Socket&, const MutableBuffer& buffer, const net::Address& peerAddress) override { - LDebug("On recv: ", peerAddress, ": ", buffer.size()) + LDebug("On recv: ", peerAddress, ": ", buffer.size()); -#if 0 - std::string payload(bufferCast(buffer), buffer.size()); - payload.erase(std::remove(payload.begin(), payload.end(), 'x'), payload.end()); - if (payload.length() < 12) { - uint64_t sentAt = util::strtoi(payload); - uint64_t latency = time::ticks() - sentAt; - - SDebug << "Recv latency packet from " << peerAddress << ": " - << "payload=" << payload.length() << ", " - << "latency=" << latency - << std::endl; - } -#endif // Echo back to client server->send(bufferCast(buffer), buffer.size(), peerAddress); + return false; } - void onSocketError(Socket&, const scy::Error& error) override + bool onSocketError(Socket&, const scy::Error& error) override { - LError("On error: ", error.message) + LError("On error: ", error.message); + return false; } - void onSocketClose(Socket&) override + bool onSocketClose(Socket&) override { - LDebug("On close") + LDebug("On close"); + return false; } }; diff --git a/src/net/src/address.cpp b/src/net/src/address.cpp index 5f7f89333..19b76f375 100644 --- a/src/net/src/address.cpp +++ b/src/net/src/address.cpp @@ -11,7 +11,6 @@ #include "scy/net/address.h" #include "scy/logger.h" -#include "scy/memory.h" #include "scy/util.h" #include @@ -169,8 +168,8 @@ class Net_API IPv6AddressBase : public AddressBase // -Address::Address() : - _base(std::make_shared()) +Address::Address() + : _base(std::make_shared()) { } @@ -189,7 +188,8 @@ Address::Address(const std::string& addr, const std::string& port) Address::Address(const std::string& hostAndPort) { - assert(!hostAndPort.empty()); + if (hostAndPort.empty()) + throw std::invalid_argument("Address: empty host:port string"); std::string host; std::string port; @@ -220,11 +220,11 @@ Address::Address(const struct sockaddr* addr, socklen_t length) { if (length == sizeof(struct sockaddr_in)) _base = std::make_shared( - reinterpret_cast(addr)); + reinterpret_cast(addr)); #if defined(SCY_HAVE_IPv6) else if (length == sizeof(struct sockaddr_in6)) _base = std::make_shared( - reinterpret_cast(addr)); + reinterpret_cast(addr)); #endif else throw std::runtime_error("Invalid address length passed to Address()"); @@ -237,7 +237,7 @@ Address::Address(const Address& addr) } -Address::~Address() +Address::~Address() noexcept { } diff --git a/src/net/src/packetsocket.cpp b/src/net/src/packetsocket.cpp index b064bbb04..9bf6d931a 100644 --- a/src/net/src/packetsocket.cpp +++ b/src/net/src/packetsocket.cpp @@ -27,126 +27,45 @@ namespace net { PacketSocketEmitter::PacketSocketEmitter(const Socket::Ptr& socket) : SocketEmitter(socket) { - // LTrace("Create: ", socket) + // LTrace("Create: ", socket); } -PacketSocketEmitter::~PacketSocketEmitter() +PacketSocketEmitter::~PacketSocketEmitter() noexcept { } -void PacketSocketEmitter::onSocketRecv(Socket& socket, const MutableBuffer& buffer, const Address& peerAddress) +bool PacketSocketEmitter::onSocketRecv(Socket& socket, const MutableBuffer& buffer, const Address& peerAddress) { - // LTrace("Recv: ", buffer.size()) + // LTrace("Recv: ", buffer.size()); - IPacket* pkt = nullptr; const char* buf = bufferCast(buffer); size_t len = buffer.size(); size_t nread = 0; - while (len > 0 && (pkt = factory.createPacket(constBuffer(buf, len), nread))) { - assert(nread > 0); - pkt->info = new PacketInfo(this->impl, peerAddress); - onPacket(*pkt); - delete pkt; + IPacket* raw = nullptr; + while (len > 0 && (raw = factory.createPacket(constBuffer(buf, len), nread))) { + if (nread <= 0) + return false; + std::unique_ptr pkt(raw); + pkt->info = std::make_unique(this->impl, peerAddress); + if (onPacket(*pkt)) + return true; buf += nread; len -= nread; } + return false; } -void PacketSocketEmitter::onPacket(IPacket& pkt) +bool PacketSocketEmitter::onPacket(IPacket& pkt) { - // LTrace("On packet: ", pkt.size()) + // LTrace("On packet: ", pkt.size()); PacketSignal::emit(pkt); + return false; } -#if 0 -// -// Packet Socket -// - - -PacketSocket::PacketSocket(const Socket& socket) : - Socket(socket) -{ - addReceiver(new PacketSocketEmitter); - //assert(Socket::base().refCount() >= 2); -} - - -PacketSocket::PacketSocket(Socket* base, bool shared) : - Socket(base, shared) -{ - addReceiver(new PacketSocketEmitter); - //assert(!shared || Socket::base().refCount() >= 2); -} - - -PacketSocket::~PacketSocket() -{ -} - - -// -// Packet Stream Socket Adapter -// - - -PacketStreamSocketAdapter::PacketStreamSocketAdapter(Socket& socket) : - PacketProcessor(PacketStreamSocketAdapter::emitter), - _socket(socket) -{ -} - - -PacketStreamSocketAdapter::~PacketStreamSocketAdapter() -{ -} - - -void PacketStreamSocketAdapter::process(IPacket& packet) -{ - // LTrace("Process: ", packet.className()) - - //Mutex::ScopedLock lock(_mutex); - - // TODO: Split packet if needed - _socket.send(packet); -} - - -bool PacketStreamSocketAdapter::accepts(IPacket* packet) -{ - return dynamic_cast(&packet) != 0; -} - - -void PacketStreamSocketAdapter::onStreamStateChange(const PacketStreamState& state) -{ - // LTrace("Stream state change: ", state) - - // TODO: Sync socket with stream? - - //Mutex::ScopedLock lock(_mutex); - - switch (state.id()) { - case PacketStreamState::Running: - break; - - case PacketStreamState::Stopped: - case PacketStreamState::Error: - case PacketStreamState::Resetting: - break; - //case PacketStreamState::None: - //case PacketStreamState::Stopping: - //case PacketStreamState::Closed: - } -} -#endif - - } // namespace net } // namespace scy diff --git a/src/net/src/socketadapter.cpp b/src/net/src/socketadapter.cpp index a5908a7d6..bf5734dc7 100644 --- a/src/net/src/socketadapter.cpp +++ b/src/net/src/socketadapter.cpp @@ -25,21 +25,21 @@ namespace net { SocketAdapter::SocketAdapter(SocketAdapter* sender) : _sender(sender) { - // LTrace("Create") - assert(sender != this); + // LTrace("Create"); + if (sender == this) + throw std::logic_error("SocketAdapter: cannot set self as sender"); } -SocketAdapter::~SocketAdapter() +SocketAdapter::~SocketAdapter() noexcept { - // LTrace("Destroy") + // LTrace("Destroy"); // assert(_receivers.empty()); } ssize_t SocketAdapter::send(const char* data, size_t len, int flags) { - assert(_sender); // should have output adapter if default impl is used if (!_sender) return -1; return _sender->send(data, len, flags); @@ -48,7 +48,6 @@ ssize_t SocketAdapter::send(const char* data, size_t len, int flags) ssize_t SocketAdapter::send(const char* data, size_t len, const Address& peerAddress, int flags) { - assert(_sender); // should have output adapter if default impl is used if (!_sender) return -1; return _sender->send(data, len, peerAddress, flags); @@ -98,74 +97,62 @@ void SocketAdapter::sendPacket(IPacket& packet) } -void SocketAdapter::onSocketConnect(Socket& socket) +bool SocketAdapter::onSocketConnect(Socket& socket) { - try { - cleanupReceivers(); - int current = int(_receivers.size() - 1); - while (current >= 0) { - auto ref = _receivers[current--]; - if (ref->alive) - ref->ptr->onSocketConnect(socket); - } - } - catch (StopPropagation&) { + cleanupReceivers(); + int current = int(_receivers.size() - 1); + while (current >= 0) { + auto ref = _receivers[current--]; + if (ref->alive && ref->ptr->onSocketConnect(socket)) + return true; } + return false; } -void SocketAdapter::onSocketRecv(Socket& socket, const MutableBuffer& buffer, const Address& peerAddress) +bool SocketAdapter::onSocketRecv(Socket& socket, const MutableBuffer& buffer, const Address& peerAddress) { - try { - cleanupReceivers(); - int current = int(_receivers.size() - 1); - while (current >= 0) { - auto ref = _receivers[current--]; - if (ref->alive) - ref->ptr->onSocketRecv(socket, buffer, peerAddress); - } - } - catch (StopPropagation&) { + cleanupReceivers(); + int current = int(_receivers.size() - 1); + while (current >= 0) { + auto ref = _receivers[current--]; + if (ref->alive && ref->ptr->onSocketRecv(socket, buffer, peerAddress)) + return true; } + return false; } -void SocketAdapter::onSocketError(Socket& socket, const scy::Error& error) +bool SocketAdapter::onSocketError(Socket& socket, const scy::Error& error) { - try { - cleanupReceivers(); - int current = int(_receivers.size() - 1); - while (current >= 0) { - auto ref = _receivers[current--]; - if (ref->alive) - ref->ptr->onSocketError(socket, error); - } - } - catch (StopPropagation&) { + cleanupReceivers(); + int current = int(_receivers.size() - 1); + while (current >= 0) { + auto ref = _receivers[current--]; + if (ref->alive && ref->ptr->onSocketError(socket, error)) + return true; } + return false; } -void SocketAdapter::onSocketClose(Socket& socket) +bool SocketAdapter::onSocketClose(Socket& socket) { - try { - cleanupReceivers(); - int current = int(_receivers.size() - 1); - while (current >= 0) { - auto ref = _receivers[current--]; - if (ref->alive) { - ref->ptr->onSocketClose(socket); - } - } - } - catch (StopPropagation&) { + cleanupReceivers(); + int current = int(_receivers.size() - 1); + while (current >= 0) { + auto ref = _receivers[current--]; + if (ref->alive && ref->ptr->onSocketClose(socket)) + return true; } + return false; } void SocketAdapter::setSender(SocketAdapter* adapter) { - assert(adapter != this); + if (adapter == this) + throw std::logic_error("SocketAdapter: cannot set self as sender"); if (_sender == adapter) return; _sender = adapter; @@ -184,17 +171,19 @@ bool SocketAdapter::hasReceiver(SocketAdapter* adapter) void SocketAdapter::addReceiver(SocketAdapter* adapter) { - assert(adapter->priority <= 100); - assert(adapter != this); + if (adapter->priority > 100) + throw std::invalid_argument("priority must be <= 100"); + if (adapter == this) + throw std::logic_error("SocketAdapter: cannot add self"); if (hasReceiver(adapter)) return; // Note that we insert new adapters in the back of the queue, // and iterate in reverse to ensure calling order is preserved. _dirty = true; - auto ptrRef = std::make_shared(); - ptrRef->ptr = adapter; - ptrRef->alive = true; + auto ptrRef = std::make_shared(); + ptrRef->ptr = adapter; + ptrRef->alive = true; _receivers.push_back(ptrRef); // _receivers.insert(_receivers.begin(), new Ref{ adapter, false }); // insert front // std::sort(_receivers.begin(), _receivers.end(), @@ -205,23 +194,26 @@ void SocketAdapter::addReceiver(SocketAdapter* adapter) void SocketAdapter::removeReceiver(SocketAdapter* adapter) { - assert(adapter != this); + if (adapter == this) + return; auto it = std::find_if(_receivers.begin(), _receivers.end(), - [&](const Ref::ptr_t& ref) { return ref->ptr == adapter; }); - if (it != _receivers.end()) { (*it)->alive = false; } + [&](const Ref::ptr_t& ref) { return ref->ptr == adapter; }); + if (it != _receivers.end()) { + (*it)->alive = false; + } } void SocketAdapter::cleanupReceivers() { - if (!_dirty) return; + if (!_dirty) + return; for (auto it = _receivers.begin(); it != _receivers.end();) { auto ref = *it; if (!ref->alive) { - //delete ref; it = _receivers.erase(it); - } - else ++it; + } else + ++it; } _dirty = false; } @@ -237,7 +229,7 @@ std::vector SocketAdapter::receivers() { std::vector items; std::transform(_receivers.begin(), _receivers.end(), std::back_inserter(items), - [](const Ref::ptr_t& ref) { return ref->ptr; }); + [](const Ref::ptr_t& ref) { return ref->ptr; }); return items; } diff --git a/src/net/src/socketemitter.cpp b/src/net/src/socketemitter.cpp index 93968503a..b4c0a977f 100644 --- a/src/net/src/socketemitter.cpp +++ b/src/net/src/socketemitter.cpp @@ -38,11 +38,10 @@ SocketEmitter::SocketEmitter(const SocketEmitter& that) { if (impl) impl->addReceiver(this); - assert(that._receivers.empty() || !_receivers.empty()); } -SocketEmitter::~SocketEmitter() +SocketEmitter::~SocketEmitter() noexcept { if (impl) impl->removeReceiver(this); @@ -51,7 +50,8 @@ SocketEmitter::~SocketEmitter() void SocketEmitter::swap(const Socket::Ptr& socket) { - assert(!impl && "must not be initialized"); + if (impl) + throw std::logic_error("SocketEmitter: already initialized"); if (impl) impl->removeReceiver(this); if (socket) @@ -62,18 +62,19 @@ void SocketEmitter::swap(const Socket::Ptr& socket) void SocketEmitter::addReceiver(SocketAdapter* adapter) { - // LTrace("Remove receiver: ", adapter) - assert(adapter->priority <= 100); - Connect.attach(slot(adapter, &net::SocketAdapter::onSocketConnect, -1, adapter->priority)); - Recv.attach(slot(adapter, &net::SocketAdapter::onSocketRecv, -1, adapter->priority)); - Error.attach(slot(adapter, &net::SocketAdapter::onSocketError, -1, adapter->priority)); - Close.attach(slot(adapter, &net::SocketAdapter::onSocketClose, -1, adapter->priority)); + // LTrace("Add receiver: ", adapter); + if (adapter->priority > 100) + throw std::invalid_argument("SocketEmitter: adapter priority exceeds 100"); + Connect.attach([adapter](Socket& s) { return adapter->onSocketConnect(s); }, adapter, -1, adapter->priority); + Recv.attach([adapter](Socket& s, const MutableBuffer& b, const Address& a) { return adapter->onSocketRecv(s, b, a); }, adapter, -1, adapter->priority); + Error.attach([adapter](Socket& s, const scy::Error& e) { return adapter->onSocketError(s, e); }, adapter, -1, adapter->priority); + Close.attach([adapter](Socket& s) { return adapter->onSocketClose(s); }, adapter, -1, adapter->priority); } void SocketEmitter::removeReceiver(SocketAdapter* adapter) { - // LTrace("Remove receiver: ", adapter) + // LTrace("Remove receiver: ", adapter); Connect.detach(adapter); Recv.detach(adapter); Error.detach(adapter); @@ -86,35 +87,35 @@ void SocketEmitter::removeReceiver(SocketAdapter* adapter) } -void SocketEmitter::onSocketConnect(Socket& socket) +bool SocketEmitter::onSocketConnect(Socket& socket) { - assert(&socket == impl.get()); - SocketAdapter::onSocketConnect(socket); - Connect.emit(socket); + if (SocketAdapter::onSocketConnect(socket)) + return true; + return Connect.emit(socket); } -void SocketEmitter::onSocketRecv(Socket& socket, const MutableBuffer& buffer, const Address& peerAddress) +bool SocketEmitter::onSocketRecv(Socket& socket, const MutableBuffer& buffer, const Address& peerAddress) { - assert(&socket == impl.get()); - SocketAdapter::onSocketRecv(socket, buffer, peerAddress); - Recv.emit(socket, buffer, peerAddress); + if (SocketAdapter::onSocketRecv(socket, buffer, peerAddress)) + return true; + return Recv.emit(socket, buffer, peerAddress); } -void SocketEmitter::onSocketError(Socket& socket, const scy::Error& error) +bool SocketEmitter::onSocketError(Socket& socket, const scy::Error& error) { - assert(&socket == impl.get()); - SocketAdapter::onSocketError(socket, error); - Error.emit(socket, error); + if (SocketAdapter::onSocketError(socket, error)) + return true; + return Error.emit(socket, error); } -void SocketEmitter::onSocketClose(Socket& socket) +bool SocketEmitter::onSocketClose(Socket& socket) { - assert(&socket == impl.get()); - SocketAdapter::onSocketClose(socket); - Close.emit(socket); + if (SocketAdapter::onSocketClose(socket)) + return true; + return Close.emit(socket); } diff --git a/src/net/src/ssladapter.cpp b/src/net/src/ssladapter.cpp index 445acb4d5..5daa2be02 100644 --- a/src/net/src/ssladapter.cpp +++ b/src/net/src/ssladapter.cpp @@ -15,6 +15,7 @@ #include "scy/net/sslsocket.h" #include #include +#include #include #include @@ -31,33 +32,45 @@ SSLAdapter::SSLAdapter(net::SSLSocket* socket) , _readBIO(nullptr) , _writeBIO(nullptr) { - // LTrace("Create") + // LTrace("Create"); } -SSLAdapter::~SSLAdapter() +SSLAdapter::~SSLAdapter() noexcept { - // LTrace("Destroy") + // LTrace("Destroy"); if (_ssl) { SSL_free(_ssl); _ssl = nullptr; } - // LTrace("Destroy: OK") + // LTrace("Destroy: OK"); } void SSLAdapter::initClient() { - // LTrace("Init client") - assert(_socket); + // LTrace("Init client"); + if (!_socket) + throw std::runtime_error("SSLAdapter: socket is null"); if (!_socket->context()) _socket->useContext(SSLManager::instance().defaultClientContext()); - assert(!_socket->context()->isForServerUse()); + if (_socket->context()->isForServerUse()) + throw std::logic_error("SSLAdapter: client init called with server context"); _ssl = SSL_new(_socket->context()->sslContext()); - // TODO: Improve automatic SSL session handling. - // Maybe add a stored session to the network manager. + // Enable hostname verification if a hostname was set + if (!_hostname.empty()) { + // Set SNI hostname for the TLS handshake + SSL_set_tlsext_host_name(_ssl, _hostname.c_str()); + + // Enable certificate hostname verification (OpenSSL 1.1.0+) + SSL_set_hostflags(_ssl, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS); + if (!SSL_set1_host(_ssl, _hostname.c_str())) + LWarn("Failed to set hostname verification for: ", _hostname); + } + + // Reuse previous SSL session if available if (_socket->currentSession()) SSL_set_session(_ssl, _socket->currentSession()->sslSession()); @@ -71,11 +84,13 @@ void SSLAdapter::initClient() void SSLAdapter::initServer() //(SSL* ssl) { - // LTrace("Init server") - assert(_socket); + // LTrace("Init server"); + if (!_socket) + throw std::runtime_error("SSLAdapter: socket is null"); if (!_socket->context()) _socket->useContext(SSLManager::instance().defaultServerContext()); - assert(_socket->context()->isForServerUse()); + if (!_socket->context()->isForServerUse()) + throw std::logic_error("SSLAdapter: server init called with client context"); _ssl = SSL_new(_socket->context()->sslContext()); _readBIO = BIO_new(BIO_s_mem()); @@ -88,9 +103,9 @@ void SSLAdapter::initServer() //(SSL* ssl) void SSLAdapter::shutdown() { - // LTrace("Shutdown") + // LTrace("Shutdown"); if (_ssl) { - // LTrace("Shutdown SSL") + // LTrace("Shutdown SSL"); // Don't shut down the socket more than once. int shutdownState = SSL_get_shutdown(_ssl); @@ -126,15 +141,23 @@ bool SSLAdapter::ready() const int SSLAdapter::available() const { - assert(_ssl); + if (!_ssl) + return 0; return SSL_pending(_ssl); } +void SSLAdapter::setHostname(const std::string& hostname) +{ + _hostname = hostname; +} + + void SSLAdapter::addIncomingData(const char* data, size_t len) { - // LTrace("Add incoming data: ", len) - assert(_readBIO); + // LTrace("Add incoming data: ", len); + if (!_readBIO) + throw std::runtime_error("SSLAdapter: read BIO not initialized"); BIO_write(_readBIO, data, (int)len); flush(); } @@ -162,7 +185,7 @@ void SSLAdapter::handshake() void SSLAdapter::flush() { - LTrace("Flushing") + LTrace("Flushing"); // Keep trying to handshake until initialized if (!ready()) @@ -191,9 +214,9 @@ void SSLAdapter::flushReadBIO() size_t npending = BIO_ctrl_pending(_readBIO); if (npending > 0) { int nread; - char buffer[MAX_TCP_PACKET_SIZE]; // TODO: allocate only npending bytes - while ((nread = SSL_read(_ssl, buffer, MAX_TCP_PACKET_SIZE)) > 0) { - _socket->onRecv(mutableBuffer(buffer, nread)); + std::vector buffer(npending); + while ((nread = SSL_read(_ssl, buffer.data(), npending)) > 0) { + _socket->onRecv(mutableBuffer(buffer.data(), nread)); } } } @@ -203,10 +226,10 @@ void SSLAdapter::flushWriteBIO() { size_t npending = BIO_ctrl_pending(_writeBIO); if (npending > 0) { - char buffer[MAX_TCP_PACKET_SIZE]; // TODO: allocate only npending bytes - int nread = BIO_read(_writeBIO, buffer, MAX_TCP_PACKET_SIZE); + std::vector buffer(npending); + int nread = BIO_read(_writeBIO, buffer.data(), npending); if (nread > 0) { - _socket->write(buffer, nread); + _socket->write(buffer.data(), nread); } } } @@ -219,20 +242,20 @@ void SSLAdapter::handleError(int rc) int error = SSL_get_error(_ssl, rc); switch (error) { case SSL_ERROR_ZERO_RETURN: - // LTrace("SSL_ERROR_ZERO_RETURN") + // LTrace("SSL_ERROR_ZERO_RETURN"); return; case SSL_ERROR_WANT_READ: - // LTrace("SSL_ERROR_WANT_READ") + // LTrace("SSL_ERROR_WANT_READ"); flushWriteBIO(); break; case SSL_ERROR_WANT_WRITE: - // LTrace("SSL_ERROR_WANT_WRITE") - assert(0 && "not implemented"); + // LTrace("SSL_ERROR_WANT_WRITE"); + flushWriteBIO(); break; case SSL_ERROR_WANT_CONNECT: case SSL_ERROR_WANT_ACCEPT: case SSL_ERROR_WANT_X509_LOOKUP: - assert(0 && "should not occur"); + LWarn("Unexpected SSL error state: ", error); break; default: char buffer[256]; diff --git a/src/net/src/sslcontext.cpp b/src/net/src/sslcontext.cpp index 6f76740e8..d678491d4 100644 --- a/src/net/src/sslcontext.cpp +++ b/src/net/src/sslcontext.cpp @@ -30,7 +30,7 @@ SSLContext::SSLContext(Usage usage, const std::string& privateKeyFile, bool loadDefaultCAs, const std::string& cipherList) : _usage(usage) , _mode(verificationMode) - , _sslContext(0) + , _sslContext(nullptr) , _extendedVerificationErrorDetails(true) { crypto::initializeEngine(); @@ -41,10 +41,10 @@ SSLContext::SSLContext(Usage usage, const std::string& privateKeyFile, if (!caLocation.empty()) { if (fs::isdir(caLocation)) errCode = SSL_CTX_load_verify_locations( - _sslContext, 0, fs::transcode(caLocation).c_str()); + _sslContext, nullptr, fs::transcode(caLocation).c_str()); else errCode = SSL_CTX_load_verify_locations( - _sslContext, fs::transcode(caLocation).c_str(), 0); + _sslContext, fs::transcode(caLocation).c_str(), nullptr); if (errCode != 1) { std::string msg = getLastError(); SSL_CTX_free(_sslContext); @@ -108,7 +108,7 @@ SSLContext::SSLContext(Usage usage, const std::string& caLocation, bool loadDefaultCAs, const std::string& cipherList) : _usage(usage) , _mode(verificationMode) - , _sslContext(0) + , _sslContext(nullptr) , _extendedVerificationErrorDetails(true) { crypto::initializeEngine(); @@ -119,10 +119,10 @@ SSLContext::SSLContext(Usage usage, const std::string& caLocation, if (!caLocation.empty()) { if (fs::isdir(caLocation)) errCode = SSL_CTX_load_verify_locations( - _sslContext, 0, fs::transcode(caLocation).c_str()); + _sslContext, nullptr, fs::transcode(caLocation).c_str()); else errCode = SSL_CTX_load_verify_locations( - _sslContext, fs::transcode(caLocation).c_str(), 0); + _sslContext, fs::transcode(caLocation).c_str(), nullptr); if (errCode != 1) { std::string msg = getLastError(); SSL_CTX_free(_sslContext); @@ -156,7 +156,7 @@ SSLContext::SSLContext(Usage usage, const std::string& caLocation, } -SSLContext::~SSLContext() +SSLContext::~SSLContext() noexcept { SSL_CTX_free(_sslContext); @@ -164,9 +164,9 @@ SSLContext::~SSLContext() } -void SSLContext::useCertificate(const crypto::X509Certificate& certificate) +void SSLContext::useCertificate(crypto::X509Certificate& certificate) { - int errCode = SSL_CTX_use_certificate(_sslContext, const_cast(certificate.certificate())); + int errCode = SSL_CTX_use_certificate(_sslContext, certificate.certificate()); if (errCode != 1) { std::string msg = getLastError(); throw std::runtime_error( @@ -175,10 +175,16 @@ void SSLContext::useCertificate(const crypto::X509Certificate& certificate) } -void SSLContext::addChainCertificate(const crypto::X509Certificate& certificate) +void SSLContext::addChainCertificate(crypto::X509Certificate& certificate) { - int errCode = SSL_CTX_add_extra_chain_cert(_sslContext, const_cast(certificate.certificate())); + // SSL_CTX_add_extra_chain_cert takes ownership of the X509 pointer, + // so we must duplicate it to avoid double-free with X509Certificate's RAII. + X509* dup = X509_dup(certificate.certificate()); + if (!dup) + throw std::runtime_error("SSL Error: X509_dup failed"); + int errCode = SSL_CTX_add_extra_chain_cert(_sslContext, dup); if (errCode != 1) { + X509_free(dup); std::string msg = getLastError(); throw std::runtime_error( "SSL Error: Cannot add chain certificate to Context: " + msg); @@ -200,11 +206,11 @@ void SSLContext::addChainCertificate(const crypto::X509Certificate& certificate) void SSLContext::addVerificationCertificate( - const crypto::X509Certificate& certificate) + crypto::X509Certificate& certificate) { int errCode = X509_STORE_add_cert(SSL_CTX_get_cert_store(_sslContext), - const_cast(certificate.certificate())); + certificate.certificate()); if (errCode != 1) { std::string msg = getLastError(); throw std::runtime_error( @@ -256,7 +262,8 @@ bool SSLContext::sessionCacheEnabled() const void SSLContext::setSessionCacheSize(size_t size) { - assert(isForServerUse()); + if (!isForServerUse()) + throw std::logic_error("setSessionCacheSize requires a server context"); SSL_CTX_sess_set_cache_size(_sslContext, static_cast(size)); } @@ -264,7 +271,8 @@ void SSLContext::setSessionCacheSize(size_t size) size_t SSLContext::getSessionCacheSize() const { - assert(isForServerUse()); + if (!isForServerUse()) + throw std::logic_error("getSessionCacheSize requires a server context"); return static_cast(SSL_CTX_sess_get_cache_size(_sslContext)); } @@ -272,7 +280,8 @@ size_t SSLContext::getSessionCacheSize() const void SSLContext::setSessionTimeout(long seconds) { - assert(isForServerUse()); + if (!isForServerUse()) + throw std::logic_error("setSessionTimeout requires a server context"); SSL_CTX_set_timeout(_sslContext, seconds); } @@ -280,7 +289,8 @@ void SSLContext::setSessionTimeout(long seconds) long SSLContext::getSessionTimeout() const { - assert(_usage == SERVER_USE); + if (!isForServerUse()) + throw std::logic_error("getSessionTimeout requires a server context"); return SSL_CTX_get_timeout(_sslContext); } @@ -288,7 +298,8 @@ long SSLContext::getSessionTimeout() const void SSLContext::flushSessionCache() { - assert(_usage == SERVER_USE); + if (!isForServerUse()) + throw std::logic_error("flushSessionCache requires a server context"); Timestamp now; SSL_CTX_flush_sessions(_sslContext, static_cast(now.epochTime())); @@ -305,18 +316,16 @@ void SSLContext::disableStatelessSessionResumption() void SSLContext::createSSLContext() { + // OpenSSL 1.1.0+ / 3.x: use TLS_method() for all cases. + // Protocol version constraints are set via SSL_CTX_set_min/max_proto_version(). switch (_usage) { case CLIENT_USE: - _sslContext = SSL_CTX_new(SSLv23_client_method()); - break; - case SERVER_USE: - _sslContext = SSL_CTX_new(SSLv23_server_method()); - break; case TLSV1_CLIENT_USE: - _sslContext = SSL_CTX_new(TLSv1_client_method()); + _sslContext = SSL_CTX_new(TLS_client_method()); break; + case SERVER_USE: case TLSV1_SERVER_USE: - _sslContext = SSL_CTX_new(TLSv1_server_method()); + _sslContext = SSL_CTX_new(TLS_server_method()); break; default: throw std::runtime_error("SSL Exception: Invalid usage"); @@ -325,15 +334,47 @@ void SSLContext::createSSLContext() unsigned long err = ERR_get_error(); throw std::runtime_error( "SSL Exception: Cannot create SSL_CTX object: " + - std::string(ERR_error_string(err, 0))); + std::string(ERR_error_string(err, nullptr))); } + // Enforce TLS 1.2 as the minimum for all usage modes. + // The legacy TLSV1_* enum values are preserved for API compatibility + // but no longer permit TLS 1.0/1.1 (deprecated, RFC 8996). + SSL_CTX_set_min_proto_version(_sslContext, TLS1_2_VERSION); + SSL_CTX_set_default_passwd_cb(_sslContext, &SSLManager::privateKeyPassphraseCallback); clearErrorStack(); SSL_CTX_set_options(_sslContext, SSL_OP_ALL); } +void SSLContext::setALPNProtocols(const std::vector& protocols) +{ + // Build wire format: each protocol prefixed by its length byte + std::vector wire; + for (const auto& proto : protocols) { + if (proto.empty() || proto.size() > 255) + throw std::invalid_argument("Invalid ALPN protocol name"); + wire.push_back(static_cast(proto.size())); + wire.insert(wire.end(), proto.begin(), proto.end()); + } + + if (SSL_CTX_set_alpn_protos(_sslContext, wire.data(), static_cast(wire.size())) != 0) + throw std::runtime_error("SSL Error: Cannot set ALPN protocols"); +} + + +void SSLContext::enableSNI(SSL* ssl, const std::string& hostname) +{ + if (!ssl) + throw std::invalid_argument("SSL object is null"); + if (hostname.empty()) + return; + + SSL_set_tlsext_host_name(ssl, hostname.c_str()); +} + + } // namespace net } // namespace scy diff --git a/src/net/src/sslmanager.cpp b/src/net/src/sslmanager.cpp index 0bc1a12de..b837c9474 100644 --- a/src/net/src/sslmanager.cpp +++ b/src/net/src/sslmanager.cpp @@ -38,67 +38,23 @@ int SSLManager::verifyClientCallback(int ok, X509_STORE_CTX* pStore) void SSLManager::initNoVerifyClient() { net::SSLManager::instance().initializeClient( - std::shared_ptr( - new net::SSLContext(net::SSLContext::CLIENT_USE, "", "", "", - net::SSLContext::VERIFY_NONE, 9, false, - "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"))); + std::make_shared( + net::SSLContext::CLIENT_USE, "", "", "", + net::SSLContext::VERIFY_NONE, 9, false, + "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH")); } void SSLManager::initNoVerifyServer(const std::string& privateKeyFile, const std::string& certificateFile) { - // Create server/client self-signed certificate/key (self signed, DONT ADD - // PASSWORD) - // - // openssl req -x509 -newkey rsa:2048 -days 3650 -nodes -keyout - // client-key.pem -out client-cert.pem - // openssl req -x509 -newkey rsa:2048 -days 3650 -nodes -keyout - // server-key.pem -out server-cert.pem - - // const char defaultPrivateKey[] = - // "-----BEGIN RSA PRIVATE KEY-----\n" - // "MIICXAIBAAKBgQC2tDv6v//aJX8HoX7hugfReoWftqVxX2WmO8CbBFc0qfEChrR/\n" - // "3sCNg8Y0squOmQ1deEElE4h1tFtmcI14Ll/NfVr4kKjspK3MFe4ZJmvbtO0WZxXg\n" - // "f72AhEhw0e1mYkufFsmwiGQZHzJVh2Yll7h5PmV2TXOgHVp2A8XWFmEIEwIDAQAB\n" - // "AoGAAlVY8sHi/aE+9xT77twWX3mGHV0SzdjfDnly40fx6S1Gc7bOtVdd9DC7pk6l\n" - // "3ENeJVR02IlgU8iC5lMHq4JEHPE272jtPrLlrpWLTGmHEqoVFv9AITPqUDLhB9Kk\n" - // "Hjl7h8NYBKbr2JHKICr3DIPKOT+RnXVb1PD4EORbJ3ooYmkCQQDfknUnVxPgxUGs\n" - // "ouABw1WJIOVgcCY/IFt4Ihf6VWTsxBgzTJKxn3HtgvE0oqTH7V480XoH0QxHhjLq\n" - // "DrgobWU9AkEA0TRJ8/ouXGnFEPAXjWr9GdPQRZ1Use2MrFjneH2+Sxc0CmYtwwqL\n" - // "Kr5kS6mqJrxprJeluSjBd+3/ElxURrEXjwJAUvmlN1OPEhXDmRHd92mKnlkyKEeX\n" - // "OkiFCiIFKih1S5Y/sRJTQ0781nyJjtJqO7UyC3pnQu1oFEePL+UEniRztQJAMfav\n" - // "AtnpYKDSM+1jcp7uu9BemYGtzKDTTAYfoiNF42EzSJiGrWJDQn4eLgPjY0T0aAf/\n" - // "yGz3Z9ErbhMm/Ysl+QJBAL4kBxRT8gM4ByJw4sdOvSeCCANFq8fhbgm8pGWlCPb5\n" - // "JGmX3/GHFM8x2tbWMGpyZP1DLtiNEFz7eCGktWK5rqE=\n" - // "-----END RSA PRIVATE KEY-----"; - - // const char defaultCertificate[] = - // "-----BEGIN CERTIFICATE-----\n" - // "MIICATCCAWoCCQDPufXH86n2QzANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJu\n" - // "bzETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0\n" - // "cyBQdHkgTHRkMB4XDTEyMDEwMTE0NDQwMFoXDTIwMDMxOTE0NDQwMFowRTELMAkG\n" - // "A1UEBhMCbm8xEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0\n" - // "IFdpZGdpdHMgUHR5IEx0ZDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAtrQ7\n" - // "+r//2iV/B6F+4boH0XqFn7alcV9lpjvAmwRXNKnxAoa0f97AjYPGNLKrjpkNXXhB\n" - // "JROIdbRbZnCNeC5fzX1a+JCo7KStzBXuGSZr27TtFmcV4H+9gIRIcNHtZmJLnxbJ\n" - // "sIhkGR8yVYdmJZe4eT5ldk1zoB1adgPF1hZhCBMCAwEAATANBgkqhkiG9w0BAQUF\n" - // "AAOBgQCeWBEHYJ4mCB5McwSSUox0T+/mJ4W48L/ZUE4LtRhHasU9hiW92xZkTa7E\n" - // "QLcoJKQiWfiLX2ysAro0NX4+V8iqLziMqvswnPzz5nezaOLE/9U/QvH3l8qqNkXu\n" - // "rNbsW1h/IO6FV8avWFYVFoutUwOaZ809k7iMh2F2JMgXQ5EymQ==\n" - // "-----END CERTIFICATE-----"; - net::SSLManager::instance().initializeServer( - std::shared_ptr(new net::SSLContext( + std::make_shared( net::SSLContext::SERVER_USE, - privateKeyFile.empty() - ? (std::string(SCY_SOURCE_DIR) + "/net/tests/key.pem") - : privateKeyFile, - certificateFile.empty() - ? (std::string(SCY_SOURCE_DIR) + "/net/tests/cert.pem") - : certificateFile, + privateKeyFile, + certificateFile, "", net::SSLContext::VERIFY_NONE, 9, false, - "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"))); + "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH")); } @@ -107,7 +63,7 @@ SSLManager::SSLManager() } -SSLManager::~SSLManager() +SSLManager::~SSLManager() noexcept { shutdown(); } @@ -172,7 +128,7 @@ int SSLManager::verifyCallback(bool server, int ok, X509_STORE_CTX* pStore) { if (!ok) { X509* pCert = X509_STORE_CTX_get_current_cert(pStore); - crypto::X509Certificate x509(pCert, true); + crypto::X509Certificate x509(pCert, true); int depth = X509_STORE_CTX_get_error_depth(pStore); int err = X509_STORE_CTX_get_error(pStore); std::string error(X509_verify_cert_error_string(err)); @@ -195,10 +151,10 @@ int SSLManager::privateKeyPassphraseCallback(char* pBuf, int size, int flag, SSLManager::instance().PrivateKeyPassphraseRequired.emit( /*&SSLManager::instance(), */ pwd); - strncpy(pBuf, (char*)(pwd.c_str()), size); + strncpy(pBuf, pwd.c_str(), static_cast(size)); pBuf[size - 1] = '\0'; - if (size > (int)pwd.length()) - size = (int)pwd.length(); + if (size > static_cast(pwd.length())) + size = static_cast(pwd.length()); return size; } @@ -234,7 +190,7 @@ VerificationErrorDetails::VerificationErrorDetails( } -VerificationErrorDetails::~VerificationErrorDetails() +VerificationErrorDetails::~VerificationErrorDetails() noexcept { } diff --git a/src/net/src/sslsession.cpp b/src/net/src/sslsession.cpp index 4c25769a9..2ed4fe470 100644 --- a/src/net/src/sslsession.cpp +++ b/src/net/src/sslsession.cpp @@ -25,7 +25,7 @@ SSLSession::SSLSession(SSL_SESSION* ptr) } -SSLSession::~SSLSession() +SSLSession::~SSLSession() noexcept { SSL_SESSION_free(_ptr); } diff --git a/src/net/src/sslsocket.cpp b/src/net/src/sslsocket.cpp index b591b65f3..2226dbe77 100644 --- a/src/net/src/sslsocket.cpp +++ b/src/net/src/sslsocket.cpp @@ -27,7 +27,7 @@ SSLSocket::SSLSocket(uv::Loop* loop) , _sslSession(nullptr) , _sslAdapter(this) { - // LTrace("Create") + // LTrace("Create"); } @@ -37,7 +37,7 @@ SSLSocket::SSLSocket(SSLContext::Ptr context, uv::Loop* loop) , _sslSession(nullptr) , _sslAdapter(this) { - // LTrace("Create") + // LTrace("Create"); } @@ -47,13 +47,33 @@ SSLSocket::SSLSocket(SSLContext::Ptr context, SSLSession::Ptr session, uv::Loop* , _sslSession(session) , _sslAdapter(this) { - // LTrace("Create") + // LTrace("Create"); } -SSLSocket::~SSLSocket() +SSLSocket::~SSLSocket() noexcept { - // LTrace("Destroy") + // LTrace("Destroy"); +} + + +void SSLSocket::setHostname(const std::string& hostname) +{ + _sslAdapter.setHostname(hostname); +} + + +void SSLSocket::connect(const Address& peerAddress) +{ + TCPSocket::connect(peerAddress); +} + + +void SSLSocket::connect(const std::string& host, uint16_t port) +{ + // Capture the hostname for SNI and certificate verification + _sslAdapter.setHostname(host); + TCPSocket::connect(host, port); } @@ -71,7 +91,7 @@ void SSLSocket::close() bool SSLSocket::shutdown() { - // LTrace("Shutdown") + // LTrace("Shutdown"); try { // Try to gracefully shutdown the SSL connection _sslAdapter.shutdown(); @@ -89,32 +109,34 @@ ssize_t SSLSocket::send(const char* data, size_t len, int flags) void SSLSocket::bind(const net::Address& address, unsigned flags) { - assert(_sslContext->isForServerUse()); + if (!_sslContext->isForServerUse()) + throw std::logic_error("SSLSocket: server context required"); TCPSocket::bind(address, flags); } void SSLSocket::listen(int backlog) { - assert(_sslContext->isForServerUse()); + if (!_sslContext->isForServerUse()) + throw std::logic_error("SSLSocket: server context required"); TCPSocket::listen(backlog); } ssize_t SSLSocket::send(const char* data, size_t len, const net::Address& /* peerAddress */, int /* flags */) { - // LTrace("Send: ", len) - assert(Thread::currentID() == tid()); + // LTrace("Send: ", len); // assert(len <= net::MAX_TCP_PACKET_SIZE); if (!active()) { - LWarn("Send error") + LWarn("Send error"); return -1; } // Send unencrypted data to the SSL context - assert(_sslAdapter._ssl); + if (!_sslAdapter._ssl) + throw std::logic_error("SSLSocket: SSL not initialized"); _sslAdapter.addOutgoingData(data, len); _sslAdapter.flush(); @@ -124,13 +146,14 @@ ssize_t SSLSocket::send(const char* data, size_t len, const net::Address& /* pee void SSLSocket::acceptConnection() { - assert(_sslContext->isForServerUse()); + if (!_sslContext->isForServerUse()) + throw std::logic_error("SSLSocket: server context required"); // Create the shared socket pointer so the if the socket handle is not // incremented the accepted socket will be destroyed. auto socket = std::make_shared(_sslContext, loop()); - // LTrace("Accept SSL connection: ", socket->ptr()) + // LTrace("Accept SSL connection: ", socket->ptr()); // invoke(&uv_tcp_init, loop(), socket->get()); // "Cannot initialize SSL socket" if (uv_accept(get(), socket->get()) == 0) { @@ -138,9 +161,8 @@ void SSLSocket::acceptConnection() socket->_sslAdapter.initServer(); AcceptConnection.emit(socket); - } - else { - assert(0 && "uv_accept should not fail"); + } else { + LError("uv_accept failed"); } } @@ -163,7 +185,7 @@ SSLSession::Ptr SSLSocket::currentSession() return std::make_shared(session); // new SSLSession(session); } } - return 0; + return nullptr; } @@ -203,7 +225,7 @@ net::TransportType SSLSocket::transport() const void SSLSocket::onRead(const char* data, size_t len) { - // LTrace("On SSL read: ", len) + // LTrace("On SSL read: ", len); // SSL encrypted data is sent to the SSL context _sslAdapter.addIncomingData(data, len); @@ -213,7 +235,7 @@ void SSLSocket::onRead(const char* data, size_t len) void SSLSocket::onConnect() { - // LTrace("On connect") + // LTrace("On connect"); if (readStart()) { _sslAdapter.initClient(); // _sslAdapter.start(); diff --git a/src/net/src/tcpsocket.cpp b/src/net/src/tcpsocket.cpp index 158de9bb2..8d7d4558c 100644 --- a/src/net/src/tcpsocket.cpp +++ b/src/net/src/tcpsocket.cpp @@ -1,414 +1,405 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// @addtogroup net -/// @{ - - -#include "scy/net/tcpsocket.h" -#include "scy/logger.h" - - -using std::endl; - - -namespace scy { -namespace net { - - -TCPSocket::TCPSocket(uv::Loop* loop) - : Stream(loop) -{ - // LTrace("Create") - init(); -} - - -TCPSocket::~TCPSocket() -{ - // LTrace("Destroy") - close(); -} - - -void TCPSocket::init() -{ - if (initialized()) - return; - - // LTrace("Init") - if (!get()) - Stream::reset(); - Stream::init(&uv_tcp_init_ex, _af); - get()->data = this; -} - - -void TCPSocket::reset() -{ - Stream::reset(); - init(); - get()->data = this; -} - - -void TCPSocket::connect(const net::Address& peerAddress) -{ - // LTrace("Connecting to", peerAddress) - init(); - - uv::createRequest([ptr = context()](const uv::BasicEvent& event) { - if (!ptr->deleted) { - auto handle = reinterpret_cast(ptr->handle); - if (event.status) - handle->setUVError(event.status, "TCP connection failed"); - else - handle->onConnect(); - } - }).connect(get(), peerAddress.addr()); - - // auto wrap = new ConnectReq(); - // wrap->callback = [ptr = context()](const uv::BasicEvent& event) { - // if (!ptr->deleted) { - // auto handle = reinterpret_cast(ptr->handle); - // if (event.status) - // handle->setUVError(event.status, "TCP connection failed"); - // else - // handle->onConnect(); - // } - // }; - // wrap->connect(get(), peerAddress.addr()); - - // auto wrap = new ConnectReq(this); - // wrap->invoke(&uv_tcp_connect, &wrap->req, get(), peerAddress.addr(), - // [](uv_connect_t* req, int status) { - // auto wrap = static_cast(req->data); - // auto handle = wrap->handle(); - // if (handle) { - // if (status == 0) { - // handle->onConnect(); - // } - // else { - // // Error handled by callback proxy - // handle->setUVError(status, "TCP connection failed"); - // } - // // handle->onConnect(req, status); - // } - // else { - // LDebug("Dropping request for closed TCP socket") - // } - // delete wrap; - // }); -} - - -void TCPSocket::connect(const std::string& host, uint16_t port) -{ - // LTrace("Connecting to", peerAddress) - - if (Address::validateIP(host)) { - connect(Address(host, port)); - } - else if (host == "localhost") { - // NOTE: Forcefully translate localhost to 127.0.0.1 since - // the DNS service returns 0.0.0.0 on some systems resulting - // in connection failure. - connect(Address("127.0.0.1", port)); - } - else { - init(); - - net::dns::resolve(host, port, [ptr = context()](int err, const net::Address& addr) { - if (!ptr->deleted) { - auto handle = reinterpret_cast(ptr->handle); - if (err) - handle->setUVError(err, "DNS failed to resolve"); - else - handle->connect(addr); - } - }, loop()); - } -} - - -void TCPSocket::bind(const net::Address& address, unsigned flags) -{ - // LTrace("Binding on", address) - - // Reset the handle if the address family has changed - if (_af != address.af()) { - _af = address.af(); - reset(); - } - - if (_af == AF_INET6) - flags |= UV_TCP_IPV6ONLY; - - invoke(&uv_tcp_bind, get(), address.addr(), flags); // "TCP bind failed" -} - - -void TCPSocket::listen(int backlog) -{ - // LTrace("Listening") - init(); - - invoke(&uv_listen, get(), backlog, - [](uv_stream_t* handle, int status) { - auto self = reinterpret_cast(handle->data); - if (status == 0) { - self->acceptConnection(); - } - else { - LError("Accept connection failed:", uv_strerror(status)); - } - }); // "TCP listen failed" -} - - -bool TCPSocket::shutdown() -{ - // LTrace("Shutdown") - return Stream::shutdown(); -} - - -void TCPSocket::close() -{ - // LTrace("Close") - Stream::close(); -} - - -bool TCPSocket::setNoDelay(bool enable) -{ - assert(initialized()); - return uv_tcp_nodelay(get(), enable ? 1 : 0) == 0; -} - - -bool TCPSocket::setKeepAlive(bool enable, int delay) -{ - assert(initialized()); - return uv_tcp_keepalive(get(), enable ? 1 : 0, delay) == 0; -} - - -bool TCPSocket::setSimultaneousAccepts(bool enable) -{ - assert(initialized()); -#ifdef SCY_WIN - return uv_tcp_simultaneous_accepts(get(), enable ? 1 : 0) == 0; -#else - return false; -#endif -} - - -bool TCPSocket::setReusePort() -{ - assert(initialized()); -#if SCY_HAS_KERNEL_SOCKET_LOAD_BALANCING - if (_af == AF_UNSPEC) { - assert(0 && "bind() must be called first"); - return false; - } - - uv_os_fd_t fd; - uv_fileno(get(), &fd); - int on = 1; - if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(int)) < 0) { - LError("setsockopt(SO_REUSEPORT) failed") - return false; - } - - return true; -#else - return false; -#endif -} - - -ssize_t TCPSocket::send(const char* data, size_t len, int flags) -{ - return send(data, len, peerAddress(), flags); -} - - -ssize_t TCPSocket::send(const char* data, size_t len, const net::Address& /* peerAddress */, int /* flags */) -{ - // LTrace("Send:", len, ":", std::string(data, len)) - assert(Thread::currentID() == tid()); - assert(initialized()); - - // NOTE: libuv handles this for us - // assert(len <= net::MAX_TCP_PACKET_SIZE); - - if (!Stream::write(data, len)) { - LWarn("TCP send error") - return -1; - } - - // TODO: Return native error code - return len; -} - - -net::Address TCPSocket::address() const -{ - if (initialized()) { - struct sockaddr address; - int addrlen = sizeof(address); - if (uv_tcp_getsockname(get(), &address, &addrlen) == 0) - return net::Address(&address, addrlen); - } - return net::Address(); -} - - -net::Address TCPSocket::peerAddress() const -{ - if (initialized()) { - struct sockaddr address; - int addrlen = sizeof(address); - if (uv_tcp_getpeername(get(), &address, &addrlen) == 0) - return net::Address(&address, addrlen); - } - return net::Address(); -} - - -void TCPSocket::setError(const scy::Error& err) -{ - assert(!error().any()); - Stream::setError(err); -} - - -const scy::Error& TCPSocket::error() const -{ - return Stream::error(); -} - - -net::TransportType TCPSocket::transport() const -{ - return net::TCP; -} - - -bool TCPSocket::closed() const -{ - return Stream::closed(); -} - - -uv::Loop* TCPSocket::loop() const -{ - return Stream::loop(); -} - - -void TCPSocket::setMode(SocketMode mode) -{ - _mode = mode; -} - - -void* TCPSocket::self() -{ - return this; -} - - -const SocketMode TCPSocket::mode() const -{ - return _mode; -} - - -// -// Callbacks - -void TCPSocket::onRead(const char* data, size_t len) -{ - // LTrace("On read:", len) - - // Note: The const_cast here is relatively safe since the given - // data pointer is the underlying _buffer.data() pointer, but - // a better way should be devised. - onRecv(mutableBuffer(const_cast(data), len)); -} - - -void TCPSocket::onRecv(const MutableBuffer& buf) -{ - // LTrace("On recv:", buf.size()) - onSocketRecv(*this, buf, peerAddress()); -} - - -void TCPSocket::onConnect() -{ - // LTrace("On connect") - - if (readStart()) // will set error on failure - onSocketConnect(*this); -} - - -void TCPSocket::acceptConnection() -{ - // Create the shared socket pointer so the if the socket handle is not - // incremented the accepted socket will be destroyed. - auto socket = net::makeSocket(loop()); - // LTrace("Accept connection:", socket->get()) - - // invoke(&uv_tcp_init, loop(), socket->get()); // "Cannot initialize TCP socket" - - if (uv_accept(get(), socket->get()) == 0) { - socket->readStart(); - AcceptConnection.emit(socket); - } - else { - assert(0 && "uv_accept should not fail"); - } -} - - -// void TCPSocket::onAcceptConnection(uv_stream_t*, int status) -// { -// if (status == 0) { -// // LTrace("On accept connection") -// acceptConnection(); -// } -// else { -// LError("Accept connection failed:", uv_strerror(status)); -// } -// } - - -void TCPSocket::onError(const scy::Error& error) -{ - // LDebug("Error:", error.message); - onSocketError(*this, error); - close(); // close on error -} - - -void TCPSocket::onClose() -{ - // LTrace("On close") - onSocketClose(*this); -} - - -} // namespace net -} // namespace scy - - -/// @\} +/// +// +// LibSourcey +// Copyright (c) 2005, Sourcey +// +// SPDX-License-Identifier: LGPL-2.1+ +// +/// @addtogroup net +/// @{ + + +#include "scy/net/tcpsocket.h" +#include "scy/logger.h" + + +using std::endl; + + +namespace scy { +namespace net { + + +TCPSocket::TCPSocket(uv::Loop* loop) + : Stream(loop) +{ + // LTrace("Create"); + init(); +} + + +TCPSocket::~TCPSocket() noexcept +{ + // LTrace("Destroy"); + close(); +} + + +void TCPSocket::init() +{ + if (initialized()) + return; + + // LTrace("Init"); + if (!get()) + Stream::reset(); + Stream::init(&uv_tcp_init_ex, _af); + get()->data = this; +} + + +void TCPSocket::reset() +{ + Stream::reset(); + init(); + get()->data = this; +} + + +void TCPSocket::connect(const net::Address& peerAddress) +{ + // LTrace("Connecting to", peerAddress); + init(); + + uv::createRequest([ptr = context()](const uv::BasicEvent& event) { + if (!ptr->deleted) { + auto handle = reinterpret_cast(ptr->handle); + if (event.status) + handle->setUVError(event.status, "TCP connection failed"); + else + handle->onConnect(); + } + }).connect(get(), peerAddress.addr()); + + // auto wrap = new ConnectReq(); + // wrap->callback = [ptr = context()](const uv::BasicEvent& event) { + // if (!ptr->deleted) { + // auto handle = reinterpret_cast(ptr->handle); + // if (event.status) + // handle->setUVError(event.status, "TCP connection failed"); + // else + // handle->onConnect(); + // } + // }; + // wrap->connect(get(), peerAddress.addr()); + + // auto wrap = new ConnectReq(this); + // wrap->invoke(&uv_tcp_connect, &wrap->req, get(), peerAddress.addr(), + // [](uv_connect_t* req, int status) { + // auto wrap = static_cast(req->data); + // auto handle = wrap->handle(); + // if (handle) { + // if (status == 0) { + // handle->onConnect(); + // } + // else { + // // Error handled by callback proxy + // handle->setUVError(status, "TCP connection failed"); + // } + // // handle->onConnect(req, status); + // } + // else { + // LDebug("Dropping request for closed TCP socket"); + // } + // delete wrap; + // }); +} + + +void TCPSocket::connect(const std::string& host, uint16_t port) +{ + // LTrace("Connecting to", peerAddress); + + if (Address::validateIP(host)) { + connect(Address(host, port)); + } else if (host == "localhost") { + // Resolve localhost directly to loopback: some systems' getaddrinfo + // returns 0.0.0.0 for "localhost" which causes connection failure. + connect(Address("127.0.0.1", port)); + } else { + init(); + + net::dns::resolve(host, port, [ptr = context()](int err, const net::Address& addr) { + if (!ptr->deleted) { + auto handle = reinterpret_cast(ptr->handle); + if (err) + handle->setUVError(err, "DNS failed to resolve"); + else + handle->connect(addr); + } }, loop()); + } +} + + +void TCPSocket::bind(const net::Address& address, unsigned flags) +{ + // LTrace("Binding on", address); + + // Reset the handle if the address family has changed + if (_af != address.af()) { + _af = address.af(); + reset(); + } + + if (_af == AF_INET6) + flags |= UV_TCP_IPV6ONLY; + + invoke(&uv_tcp_bind, get(), address.addr(), flags); // "TCP bind failed" +} + + +void TCPSocket::listen(int backlog) +{ + // LTrace("Listening"); + init(); + + invoke(&uv_listen, get(), backlog, + [](uv_stream_t* handle, int status) { + auto self = reinterpret_cast(handle->data); + if (status == 0) { + self->acceptConnection(); + } else { + LError("Accept connection failed:", uv_strerror(status)); + } + }); // "TCP listen failed" +} + + +bool TCPSocket::shutdown() +{ + // LTrace("Shutdown"); + return Stream::shutdown(); +} + + +void TCPSocket::close() +{ + // LTrace("Close"); + Stream::close(); +} + + +bool TCPSocket::setNoDelay(bool enable) +{ + if (!initialized()) + return false; + return uv_tcp_nodelay(get(), enable ? 1 : 0) == 0; +} + + +bool TCPSocket::setKeepAlive(bool enable, int delay) +{ + if (!initialized()) + return false; + return uv_tcp_keepalive(get(), enable ? 1 : 0, delay) == 0; +} + + +bool TCPSocket::setSimultaneousAccepts(bool enable) +{ + if (!initialized()) + return false; +#ifdef SCY_WIN + return uv_tcp_simultaneous_accepts(get(), enable ? 1 : 0) == 0; +#else + return false; +#endif +} + + +bool TCPSocket::setReusePort() +{ + if (!initialized()) + return false; +#if SCY_HAS_KERNEL_SOCKET_LOAD_BALANCING + if (_af == AF_UNSPEC) { + LError("bind() must be called before setReusePort()"); + return false; + } + + uv_os_fd_t fd; + uv_fileno(get(), &fd); + int on = 1; + if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(int)) < 0) { + LError("setsockopt(SO_REUSEPORT) failed"); + return false; + } + + return true; +#else + return false; +#endif +} + + +ssize_t TCPSocket::send(const char* data, size_t len, int flags) +{ + return send(data, len, peerAddress(), flags); +} + + +ssize_t TCPSocket::send(const char* data, size_t len, const net::Address& /* peerAddress */, int /* flags */) +{ + // LTrace("Send:", len, ":", std::string(data, len)); + if (!initialized()) { + LWarn("TCP send on uninitialized socket"); + return -1; + } + + if (!Stream::write(data, len)) { + LWarn("TCP send error"); + return -1; + } + + return static_cast(len); +} + + +net::Address TCPSocket::address() const +{ + if (initialized()) { + struct sockaddr address; + int addrlen = sizeof(address); + if (uv_tcp_getsockname(get(), &address, &addrlen) == 0) + return net::Address(&address, addrlen); + } + return net::Address(); +} + + +net::Address TCPSocket::peerAddress() const +{ + if (initialized()) { + struct sockaddr address; + int addrlen = sizeof(address); + if (uv_tcp_getpeername(get(), &address, &addrlen) == 0) + return net::Address(&address, addrlen); + } + return net::Address(); +} + + +void TCPSocket::setError(const scy::Error& err) +{ + if (error().any()) + return; // don't overwrite existing error + Stream::setError(err); +} + + +const scy::Error& TCPSocket::error() const +{ + return Stream::error(); +} + + +net::TransportType TCPSocket::transport() const +{ + return net::TCP; +} + + +bool TCPSocket::closed() const +{ + return Stream::closed(); +} + + +uv::Loop* TCPSocket::loop() const +{ + return Stream::loop(); +} + + +void TCPSocket::setMode(SocketMode mode) +{ + _mode = mode; +} + + +const SocketMode TCPSocket::mode() const +{ + return _mode; +} + + +// +// Callbacks + +void TCPSocket::onRead(const char* data, size_t len) +{ + // LTrace("On read:", len); + + // Note: The const_cast here is relatively safe since the given + // data pointer is the underlying _buffer.data() pointer, but + // a better way should be devised. + onRecv(mutableBuffer(const_cast(data), len)); +} + + +void TCPSocket::onRecv(const MutableBuffer& buf) +{ + // LTrace("On recv:", buf.size()); + onSocketRecv(*this, buf, peerAddress()); +} + + +void TCPSocket::onConnect() +{ + // LTrace("On connect"); + + if (readStart()) // will set error on failure + onSocketConnect(*this); +} + + +void TCPSocket::acceptConnection() +{ + // Create the shared socket pointer so the if the socket handle is not + // incremented the accepted socket will be destroyed. + auto socket = net::makeSocket(loop()); + // LTrace("Accept connection:", socket->get()); + + // invoke(&uv_tcp_init, loop(), socket->get()); // "Cannot initialize TCP socket" + + if (uv_accept(get(), socket->get()) == 0) { + socket->readStart(); + AcceptConnection.emit(socket); + } else { + LError("uv_accept failed"); + } +} + + +// void TCPSocket::onAcceptConnection(uv_stream_t*, int status) +// { +// if (status == 0) { +// // LTrace("On accept connection"); +// acceptConnection(); +// } +// else { +// LError("Accept connection failed:", uv_strerror(status)); +// } +// } + + +void TCPSocket::onError(const scy::Error& error) +{ + LDebug("Error:", error.message); + onSocketError(*this, error); + close(); // close on error +} + + +void TCPSocket::onClose() +{ + // LTrace("On close"); + onSocketClose(*this); +} + + +} // namespace net +} // namespace scy + + +/// @\} diff --git a/src/net/src/udpsocket.cpp b/src/net/src/udpsocket.cpp index 3b9f685f9..59c2fc525 100644 --- a/src/net/src/udpsocket.cpp +++ b/src/net/src/udpsocket.cpp @@ -13,6 +13,8 @@ #include "scy/logger.h" #include "scy/net/net.h" +#include + using namespace std; @@ -25,14 +27,14 @@ UDPSocket::UDPSocket(uv::Loop* loop) : uv::Handle(loop) , _buffer(65536) { - // LTrace("Create") + // LTrace("Create"); init(); } -UDPSocket::~UDPSocket() +UDPSocket::~UDPSocket() noexcept { - // LTrace("Destroy") + // LTrace("Destroy"); close(); } @@ -42,7 +44,7 @@ void UDPSocket::init() if (initialized()) return; - // LTrace("Init") + // LTrace("Init"); if (!get()) uv::Handle::reset(); @@ -53,7 +55,7 @@ void UDPSocket::init() void UDPSocket::reset() { - // LTrace("Reset") + // LTrace("Reset"); uv::Handle::reset(); init(); get()->data = this; @@ -62,7 +64,7 @@ void UDPSocket::reset() void UDPSocket::connect(const Address& peerAddress) { - // LTrace("Connect:", peerAddress) + // LTrace("Connect:", peerAddress); init(); _peer = peerAddress; @@ -76,14 +78,11 @@ void UDPSocket::connect(const std::string& host, uint16_t port) { if (Address::validateIP(host)) { connect(Address(host, port)); - } - else if (host == "localhost") { - // NOTE: Forcefully translate localhost to 127.0.0.1 since - // the DNS service returns 0.0.0.0 on some systems resulting - // in connection failure. + } else if (host == "localhost") { + // Resolve localhost directly to loopback: some systems' getaddrinfo + // returns 0.0.0.0 for "localhost" which causes connection failure. connect(Address("127.0.0.1", port)); - } - else { + } else { init(); net::dns::resolve(host, port, [ptr = context()](int err, const net::Address& addr) { @@ -93,15 +92,14 @@ void UDPSocket::connect(const std::string& host, uint16_t port) handle->setUVError(err, "DNS failed to resolve"); else handle->connect(addr); - } - }, loop()); + } }, loop()); } } void UDPSocket::close() { - // LTrace("Closing") + // LTrace("Closing"); if (initialized() && !closed()) recvStop(); uv::Handle::close(); @@ -110,7 +108,7 @@ void UDPSocket::close() void UDPSocket::bind(const Address& address, unsigned flags) { - // LTrace("Binding on", address) + // LTrace("Binding on", address); init(); if (address.af() == AF_INET6) @@ -123,113 +121,88 @@ void UDPSocket::bind(const Address& address, unsigned flags) ssize_t UDPSocket::send(const char* data, size_t len, int flags) { - assert(_peer.valid()); + if (!_peer.valid()) + return -1; return send(data, len, _peer, flags); } ssize_t UDPSocket::send(const char* data, size_t len, const Address& peerAddress, int /* flags */) { - // LTrace("Send:", len, ":", peerAddress) - assert(Thread::currentID() == tid()); - assert(initialized()); - assert(!closed()); + // LTrace("Send:", len, ":", peerAddress); + if (!initialized()) + return -1; // assert(len <= net::MAX_UDP_PACKET_SIZE); if (_peer.valid() && _peer != peerAddress) { - LError("Peer not authorized:", peerAddress) + LError("Peer not authorized:", peerAddress); return -1; } if (!peerAddress.valid()) { - LError("Peer not valid:", peerAddress) + LError("Peer not valid:", peerAddress); return -1; } - auto buf = uv_buf_init((char*)data, (unsigned int)len); // TODO: memcpy data? - if (invoke(&uv_udp_send, new uv_udp_send_t, get(), &buf, 1, peerAddress.addr(), - [](uv_udp_send_t* req, int) { - delete req; - })) { + auto buf = uv_buf_init(const_cast(data), static_cast(len)); + auto req = std::make_unique(); + if (invoke(&uv_udp_send, req.release(), get(), &buf, 1, peerAddress.addr(), + [](uv_udp_send_t* req, int) { + std::unique_ptr guard(req); + })) { return len; } return error().err; - - // typedef uv::Request Request; - // - // auto wrap = new Request(context()); - // wrap->buf = uv_buf_init((char*)data, (unsigned int)len); // TODO: memcpy data? - // if (invoke(&uv_udp_send, &wrap->req, get(), &wrap->buf, 1, peerAddress.addr(), - // [](uv_udp_send_t* req, int status) { - // auto wrap = reinterpret_cast(req->data); - // if (!wrap->ctx->deleted) { - // if (status) { - // LDebug("Send error:", uv_err_name(status)) - // wrap->ctx->handle->setUVError(status, "UDP send error"); - // } - // } - // else { - // LDebug("Dropping send request for closed UDP socket") - // } - // delete wrap; - // })) { - // return len; - // } - // - // return error().err; } bool UDPSocket::setBroadcast(bool enable) { - assert(initialized()); + if (!initialized()) + return false; return uv_udp_set_broadcast(get(), enable ? 1 : 0) == 0; } bool UDPSocket::setMulticastLoop(bool enable) { - assert(initialized()); + if (!initialized()) + return false; return uv_udp_set_multicast_loop(get(), enable ? 1 : 0) == 0; } bool UDPSocket::setMulticastTTL(int ttl) { - assert(initialized()); - assert(ttl > 0 && ttl <= 255); + if (!initialized()) + return false; + if (ttl <= 0 || ttl > 255) + throw std::invalid_argument("TTL out of range"); return uv_udp_set_multicast_ttl(get(), ttl) == 0; } bool UDPSocket::recvStart() { - assert(initialized()); - // assert(active()); - assert(!closed()); - assert(get()->data == this); + if (!initialized() || closed()) + return false; - // LTrace("Recv start") + // LTrace("Recv start"); - // UV_EALREADY means that the socket is already bound but that's okay - // TODO: No need for boolean value as this method can throw exceptions - // since it is called internally by bind(). + // UV_EALREADY means that the socket is already bound but that's okay. int r = uv_udp_recv_start(get(), UDPSocket::allocRecvBuffer, UDPSocket::onRecv); if (r) { // && r != UV_EALREADY setUVError(r, "Cannot start recv on invalid UDP socket"); return false; } return true; - - // return invoke(&uv_udp_recv_start, get(), UDPSocket::allocRecvBuffer, onRecv); } bool UDPSocket::recvStop() { - assert(initialized()); - // assert(active()); - assert(!closed()); + if (!initialized() || closed()) + return false; // This method must not throw since it is called // internally via libuv callbacks. @@ -239,7 +212,7 @@ bool UDPSocket::recvStop() void UDPSocket::onRecv(const MutableBuffer& buf, const net::Address& address) { - // LTrace("On recv:", buf.size(), ":", address) + // LTrace("On recv:", buf.size(), ":", address); onSocketRecv(*this, buf, address); } @@ -293,18 +266,18 @@ void UDPSocket::onRecv(uv_udp_t* handle, ssize_t nread, const uv_buf_t* buf, const struct sockaddr* addr, unsigned /* flags */) { auto socket = reinterpret_cast(handle->data); - assert(socket->initialized()); - assert(!socket->closed()); - // LTrace("On read:", nread) + if (!socket->initialized() || socket->closed()) { + LWarn("Recv on uninitialized or closed socket"); + return; + } + // LTrace("On read:", nread); if (nread < 0) { // assert(0 && "unexpected error"); - LDebug("Recv error:", uv_err_name((int)nread)) - socket->setUVError((int)nread, "UDP recv error"); + LDebug("Recv error:", uv_err_name(static_cast(nread))); + socket->setUVError(static_cast(nread), "UDP recv error"); return; - } - else if (nread == 0) { - assert(addr == nullptr); + } else if (nread == 0) { // Returning unused buffer, this is not an error // 11/12/13: This happens on linux but not windows // socket->setUVError(UV_EOF, "End of file"); @@ -319,19 +292,11 @@ void UDPSocket::onRecv(uv_udp_t* handle, ssize_t nread, const uv_buf_t* buf, void UDPSocket::allocRecvBuffer(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) { auto& buffer = static_cast(handle->data)->_buffer; - // // LTrace("Allocating buffer:", suggested_size) - - // Reserve the recommended buffer size - // XXX: libuv wants us to allocate 65536 bytes for UDP .. hmmm - // if (suggested_size > self->_buffer.available()) - // self->_buffer.reserve(suggested_size); - // assert(self->_buffer.capacity() >= suggested_size); - assert(buffer.size() >= suggested_size); - assert(buffer.size() < suggested_size * 2); - - // Reset the buffer position on each read - // buffer.position(0); - // uv_buf_init(buffer.data(), buffer.size()); + + // Resize to libuv's suggested size (typically 65536 for UDP) + if (buffer.size() < suggested_size) + buffer.resize(suggested_size); + buf->base = buffer.data(); buf->len = buffer.size(); } @@ -339,7 +304,7 @@ void UDPSocket::allocRecvBuffer(uv_handle_t* handle, size_t suggested_size, uv_b void UDPSocket::onError(const scy::Error& error) { - // LDebug("Error", error.message) + // LDebug("Error", error.message); onSocketError(*this, error); close(); // close on error } @@ -347,7 +312,7 @@ void UDPSocket::onError(const scy::Error& error) void UDPSocket::onClose() { - // LDebug("On close") + // LDebug("On close"); onSocketClose(*this); } @@ -358,12 +323,6 @@ uv::Loop* UDPSocket::loop() const } -void* UDPSocket::self() -{ - return this; -} - - } // namespace net } // namespace scy diff --git a/src/net/tests/CMakeLists.txt b/src/net/tests/CMakeLists.txt index ae6381e0f..dff93caf7 100644 --- a/src/net/tests/CMakeLists.txt +++ b/src/net/tests/CMakeLists.txt @@ -1,3 +1 @@ -# include_dependency(SSL REQUIRED) - -define_libsourcey_test(nettests base net) +scy_add_test(nettests DEPENDS base net) diff --git a/src/net/tests/ca.pem b/src/net/tests/ca.pem index 71470bafc..382c858b6 100644 --- a/src/net/tests/ca.pem +++ b/src/net/tests/ca.pem @@ -1,3971 +1,21 @@ -----BEGIN CERTIFICATE----- -MIIG0zCCBbugAwIBAgIBADANBgkqhkiG9w0BAQUFADCBzDELMAkGA1UEBhMCQVQx -EDAOBgNVBAgTB0F1c3RyaWExDzANBgNVBAcTBlZpZW5uYTE6MDgGA1UEChMxQVJH -RSBEQVRFTiAtIEF1c3RyaWFuIFNvY2lldHkgZm9yIERhdGEgUHJvdGVjdGlvbjEl -MCMGA1UECxMcQS1DRVJUIENlcnRpZmljYXRpb24gU2VydmljZTEYMBYGA1UEAxMP -QS1DRVJUIEFEVkFOQ0VEMR0wGwYJKoZIhvcNAQkBFg5pbmZvQGEtY2VydC5hdDAe -Fw0wNDEwMjMxNDE0MTRaFw0xMTEwMjMxNDE0MTRaMIHMMQswCQYDVQQGEwJBVDEQ -MA4GA1UECBMHQXVzdHJpYTEPMA0GA1UEBxMGVmllbm5hMTowOAYDVQQKEzFBUkdF -IERBVEVOIC0gQXVzdHJpYW4gU29jaWV0eSBmb3IgRGF0YSBQcm90ZWN0aW9uMSUw -IwYDVQQLExxBLUNFUlQgQ2VydGlmaWNhdGlvbiBTZXJ2aWNlMRgwFgYDVQQDEw9B -LUNFUlQgQURWQU5DRUQxHTAbBgkqhkiG9w0BCQEWDmluZm9AYS1jZXJ0LmF0MIIB -IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3euXIy+mnf6BYKbK+QH5k679 -tUFqeT8jlZxMew8eNiHuw9KoxWBzL6KksK+5uK7Gatw+sbAYntEGE80P+Jg1hADM -e+Fr5V0bc6QS3gkVtfUCW/RIvfMM39oxvmqJmOgPnJU7H6+nmLtsq61tv9kVJi/2 -4Y5wXW3odet72sF57EoG6s78w0BUVLNcMngS9bZZzmdG3/d6JbkGgoNF/8DcgCBJ -W/t0JrcIzyppXIOVtUzzOrrU86zuUgT3Rtkl5kjG7DEHpFb9H0fTOY1v8+gRoaO6 -2gA0PCiysgVZjwgVeYe3KAg11nznyleDv198uK3Dc1oXIGYjJx2FpKWUvAuAEwID -AQABo4ICvDCCArgwHQYDVR0OBBYEFDd/Pj6ZcWDKJNSRE3nQdCm0qCTYMIH5BgNV -HSMEgfEwge6AFDd/Pj6ZcWDKJNSRE3nQdCm0qCTYoYHSpIHPMIHMMQswCQYDVQQG -EwJBVDEQMA4GA1UECBMHQXVzdHJpYTEPMA0GA1UEBxMGVmllbm5hMTowOAYDVQQK -EzFBUkdFIERBVEVOIC0gQXVzdHJpYW4gU29jaWV0eSBmb3IgRGF0YSBQcm90ZWN0 -aW9uMSUwIwYDVQQLExxBLUNFUlQgQ2VydGlmaWNhdGlvbiBTZXJ2aWNlMRgwFgYD -VQQDEw9BLUNFUlQgQURWQU5DRUQxHTAbBgkqhkiG9w0BCQEWDmluZm9AYS1jZXJ0 -LmF0ggEAMA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgHmMEcGA1UdJQRAMD4G -CCsGAQUFBwMBBggrBgEFBQcDAgYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEFBQcD -CAYKKwYBBAGCNwoDBDARBglghkgBhvhCAQEEBAMCAP8wUQYDVR0gBEowSDBGBggq -KAAYAQEBAzA6MDgGCCsGAQUFBwIBFixodHRwOi8vd3d3LmEtY2VydC5hdC9jZXJ0 -aWZpY2F0ZS1wb2xpY3kuaHRtbDA7BglghkgBhvhCAQgELhYsaHR0cDovL3d3dy5h -LWNlcnQuYXQvY2VydGlmaWNhdGUtcG9saWN5Lmh0bWwwGQYDVR0RBBIwEIEOaW5m -b0BhLWNlcnQuYXQwLwYDVR0SBCgwJoEOaW5mb0BhLWNlcnQuYXSGFGh0dHA6Ly93 -d3cuYS1jZXJ0LmF0MEUGA1UdHwQ+MDwwOqA4oDaGNGh0dHBzOi8vc2VjdXJlLmEt -Y2VydC5hdC9jZ2ktYmluL2EtY2VydC1hZHZhbmNlZC5jZ2kwDQYJKoZIhvcNAQEF -BQADggEBACX1IvgfdG2rvfv35O48vSEvcVaEdlN8USFBHWz3JRAozgzvaBtwHkjK -Zwt5l/BWOtjbvHfRjDt7ijlBEcxOOrNC1ffyMHwHrXpvff6YpQ5wnxmIYEQcURiG -HMqruEX0WkuDNgSKwefsgXs27eeBauHgNGVcTYH1rmHu/ZyLpLxOyJQ2PCzA1DzW -3rWkIX92ogJ7lTRdWrbxwUL1XGinxnnaQ74+/y0pI9JNEv7ic2tpkweRMpkedaLW -msC1+orfKTebsg69aMaCx7o6jNONRmR/7TVaPf8/k6g52cHZ9YWjQvup22b5rWxG -J5r5LZ4vCPmF4+T4lutjUYAa/lGuQTg= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDXTCCAkWgAwIBAgIDAOJCMA0GCSqGSIb3DQEBBQUAMFUxCzAJBgNVBAYTAkFU -MRAwDgYDVQQKEwdBLVRydXN0MRkwFwYDVQQLExBBLVRydXN0LW5RdWFsLTAxMRkw -FwYDVQQDExBBLVRydXN0LW5RdWFsLTAxMB4XDTA0MTEzMDIzMDAwMFoXDTE0MTEz -MDIzMDAwMFowVTELMAkGA1UEBhMCQVQxEDAOBgNVBAoTB0EtVHJ1c3QxGTAXBgNV -BAsTEEEtVHJ1c3QtblF1YWwtMDExGTAXBgNVBAMTEEEtVHJ1c3QtblF1YWwtMDEw -ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQD/9RyAEZ6eHmhYzNJ328f0 -jmdSUFi6EqRqOxb3jHNPTIpK82CR6z5lmSnZQNUuCPD+htbNZffd2DKVB06NOyZ1 -2zcOMCgj4GtkZoqE0zPpPT3bpoE55nkZZe/qWEX/64wz/L/4EdkvKDSKG/UsP75M -tmCVY5m2Eg73RVFRz4ccBIMpHel4lzEqSkdDtZOY5fnkrE333hx67nxq21vY8Eyf -8O4fPQ5RtN8eohQCcPQ1z6ypU1R7N9jPRpnI+yzMOiwd3+QcKhHi1miCzo0pkOaB -1CwmfsTyNl8qU0NJUL9Ta6cea7WThwTiWol2yD88cd2cy388xpbNkfrCPmZNGLoV -AgMBAAGjNjA0MA8GA1UdEwEB/wQFMAMBAf8wEQYDVR0OBAoECE5ZzscCMocwMA4G -A1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEA69I9R1hU9Gbl9vV7W7AH -QpUJAlFAvv2It/eY8p2ouQUPVaSZikaKtAYrCD/arzfXB43Qet+dM6CpHsn8ikYR -vQKePjXv3Evf+C1bxwJAimcnZV6W+bNOTpdo8lXljxkmfN+Z5S+XzvK2ttUtP4Et -YOVaxHw2mPMNbvDeY+foJkiBn3KYjGabMaR8moZqof5ofj4iS/WyamTZti6v/fKx -n1vII+/uWkcxV5DT5+r9HLon0NYF0Vg317Wh+gWDV59VZo+dcwJDb+keYqMFYoqp -77SGkZGu41S8NGYkQY3X9rNHRkDbLfpKYDmy6NanpOE1EHW1/sNSFAs43qZZKJEQ -xg== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDzzCCAregAwIBAgIDAWweMA0GCSqGSIb3DQEBBQUAMIGNMQswCQYDVQQGEwJB -VDFIMEYGA1UECgw/QS1UcnVzdCBHZXMuIGYuIFNpY2hlcmhlaXRzc3lzdGVtZSBp -bSBlbGVrdHIuIERhdGVudmVya2VociBHbWJIMRkwFwYDVQQLDBBBLVRydXN0LW5R -dWFsLTAzMRkwFwYDVQQDDBBBLVRydXN0LW5RdWFsLTAzMB4XDTA1MDgxNzIyMDAw -MFoXDTE1MDgxNzIyMDAwMFowgY0xCzAJBgNVBAYTAkFUMUgwRgYDVQQKDD9BLVRy -dXN0IEdlcy4gZi4gU2ljaGVyaGVpdHNzeXN0ZW1lIGltIGVsZWt0ci4gRGF0ZW52 -ZXJrZWhyIEdtYkgxGTAXBgNVBAsMEEEtVHJ1c3QtblF1YWwtMDMxGTAXBgNVBAMM -EEEtVHJ1c3QtblF1YWwtMDMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB -AQCtPWFuA/OQO8BBC4SAzewqo51ru27CQoT3URThoKgtUaNR8t4j8DRE/5TrzAUj -lUC5B3ilJfYKvUWG6Nm9wASOhURh73+nyfrBJcyFLGM/BWBzSQXgYHiVEEvc+RFZ -znF/QJuKqiTfC0Li21a8StKlDJu3Qz7dg9MmEALP6iPESU7l0+m0iKsMrmKS1GWH -2WrX9IWf5DMiJaXlyDO6w8dB3F/GaswADm0yqLaHNgBid5seHzTLkDx4iHQF63n1 -k3Flyp3HaxgtPVxO59X4PzF9j4fsCiIvI+n+u33J4PTs63zEsMMtYrWacdaxaujs -2e3Vcuy+VwHOBVWf3tFgiBCzAgMBAAGjNjA0MA8GA1UdEwEB/wQFMAMBAf8wEQYD -VR0OBAoECERqlWdVeRFPMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOC -AQEAVdRU0VlIXLOThaq/Yy/kgM40ozRiPvbY7meIMQQDbwvUB/tOdQ/TLtPAF8fG -KOwGDREkDg6lXb+MshOWcdzUzg4NCmgybLlBMRmrsQd7TZjTXLDR8KdCoLXEjq/+ -8T/0709GAHbrAvv5ndJAlseIOrifEXnzgGWovR/TeIGgUUw3tKZdJXDRZslo+S4R -FGjxVJgIrCaSD96JntT6s3kr0qN51OyLrIdTaEJMUVF0HhsnLuP1Hyl0Te2v9+GS -mYHovjrHF1D2t8b8m7CKa9aIA5GPBnc6hQLdmNVDeD/GMBWsm2vLV7eJUYs66MmE -DNuxUCAKGkq6ahq97BvIxYSazQ== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEUzCCAzugAwIBAgIDAOJDMA0GCSqGSIb3DQEBBQUAMIHPMQswCQYDVQQGEwJB -VDGBizCBiAYDVQQKHoGAAEEALQBUAHIAdQBzAHQAIABHAGUAcwAuACAAZgD8AHIA -IABTAGkAYwBoAGUAcgBoAGUAaQB0AHMAcwB5AHMAdABlAG0AZQAgAGkAbQAgAGUA -bABlAGsAdAByAC4AIABEAGEAdABlAG4AdgBlAHIAawBlAGgAcgAgAEcAbQBiAEgx -GDAWBgNVBAsTD0EtVHJ1c3QtUXVhbC0wMTEYMBYGA1UEAxMPQS1UcnVzdC1RdWFs -LTAxMB4XDTA0MTEzMDIzMDAwMFoXDTE0MTEzMDIzMDAwMFowgc8xCzAJBgNVBAYT -AkFUMYGLMIGIBgNVBAoegYAAQQAtAFQAcgB1AHMAdAAgAEcAZQBzAC4AIABmAPwA -cgAgAFMAaQBjAGgAZQByAGgAZQBpAHQAcwBzAHkAcwB0AGUAbQBlACAAaQBtACAA -ZQBsAGUAawB0AHIALgAgAEQAYQB0AGUAbgB2AGUAcgBrAGUAaAByACAARwBtAGIA -SDEYMBYGA1UECxMPQS1UcnVzdC1RdWFsLTAxMRgwFgYDVQQDEw9BLVRydXN0LVF1 -YWwtMDEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCmhgdxIbxTGEOH -fXGiewI3NFldAWKFWfLofO+5I1UbvA5avt7IgsGXz/tI/f5HGUbascI0i7xG0tqV -lA5ctQgLRqxgxHtgTkMcqsAEYdsz3LZsCdXO1QrvEBGLTSABdxiL/gSWJ6z77CSw -x7Xg02HwxPV82cjGkSF3ENGJntuIAAnRDWn/ORHjFatNRymoMbHaOEZXSGhf7Y5F -rrHEqGyi9E6sv784De/T1aTvskn8cWeUmDzv//omiG/a/V9KQex/61XN8OthUQVn -X+u/liL2NKx74I2C/GgHX5B0WkPNqsSOgmlvJ/cKuT0PveUgVFDAA0oYBgcE1KDM -lBbN0kmPAgMBAAGjNjA0MA8GA1UdEwEB/wQFMAMBAf8wEQYDVR0OBAoECEs8jB2F -6W+tMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAIUusmJzMJRiQ -8TAHrJAOelfuWoTGcqdIv7Tys/fNl2yF2fjvHT8J01aKialFVpbVeQ2XKb1O2bHO -QYAKgsdZ2jZ/sdL2UVFRTHmidLu6PdgWCBRhJYQELQophO9QVvfhAA0TwbESYqTz -+nlI5Gr7CZe8f6HEmhJmCtUQsdQCufGglRh4T+tIGiNGcnyVEHZ93mSVepFr1VA2 -9CTRPteuGjA81jeAz9peYiFE1CXvxK9cJiv0BcALFLWmADCoRLzIRZhA+sAwYUmw -M1rqVCPA3kBQvIC95tyQvNy2dG0Vs+O6PwLaNX/suSlElQ06X2l1VwMaYb4vZKFq -N0bOhBXEVg== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDyzCCArOgAwIBAgIDAOJIMA0GCSqGSIb3DQEBBQUAMIGLMQswCQYDVQQGEwJB -VDFIMEYGA1UECgw/QS1UcnVzdCBHZXMuIGYuIFNpY2hlcmhlaXRzc3lzdGVtZSBp -bSBlbGVrdHIuIERhdGVudmVya2VociBHbWJIMRgwFgYDVQQLDA9BLVRydXN0LVF1 -YWwtMDIxGDAWBgNVBAMMD0EtVHJ1c3QtUXVhbC0wMjAeFw0wNDEyMDIyMzAwMDBa -Fw0xNDEyMDIyMzAwMDBaMIGLMQswCQYDVQQGEwJBVDFIMEYGA1UECgw/QS1UcnVz -dCBHZXMuIGYuIFNpY2hlcmhlaXRzc3lzdGVtZSBpbSBlbGVrdHIuIERhdGVudmVy -a2VociBHbWJIMRgwFgYDVQQLDA9BLVRydXN0LVF1YWwtMDIxGDAWBgNVBAMMD0Et -VHJ1c3QtUXVhbC0wMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJaR -q9eOsFm4Ab20Hq2Z/aH86gyWa48uSUjY6eQkguHYuszr3gdcSMYZggFHQgnhfLmf -ro/27l5rqKhWiDhWs+b+yZ1PNDhRPJy+86ycHMg9XJqErveULBSyZDdgjhSwOyrN -ibUir/fkf+4sKzP5jjytTKJXD/uCxY4fAd9TjMEVpN3umpIS0ijpYhclYDHvzzGU -833z5Dwhq5D8bc9jp8YSAHFJ1xzIoO1jmn3jjyjdYPnY5harJtHQL73nDQnfbtTs -5ThT9GQLulrMgLU4WeyAWWWEMWpfVZFMJOUkmoOEer6A8e5fIAeqdxdsC+JVqpZ4 -CAKel/Arrlj1gFA//jsCAwEAAaM2MDQwDwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4E -CgQIQj0rJKbBRc4wDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQBG -yxFjUA2bPkXUSC2SfJ29tmrbiLKal+g6a9M8Xwd+Ejo+oYkNP6F4GfeDtAXpm7xb -9Ly8lhdbHcpRhzCUQHJ1tBCiGdLgmhSx7TXjhhanKOdDgkdsC1T+++piuuYL72TD -gUy2Sb1GHlJ1Nc6rvB4fpxSDAOHqGpUq9LWsc3tFkXqRqmQVtqtR77npKIFBioc6 -2jTBwDMPX3hDJDR1DSPc6BnZliaNw2IHdiMQ0mBoYeRnFdq+TyDKsjmJOOQPLzzL -/saaw6F891+gBjLFEFquDyR73lAPJS279R3csi8WWk4ZYUC/1V8H3Ktip/J6ac8e -qhLCbmJ81Lo92JGHz/ot ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEb -MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow -GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmlj -YXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVowezEL -MAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE -BwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNVBAMM -GEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP -ADCCAQoCggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQua -BtDFcCLNSS1UY8y2bmhGC1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe -3M/vg4aijJRPn2jymJBGhCfHdr/jzDUsi14HZGWCwEiwqJH5YZ92IFCokcdmtet4 -YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszWY19zjNoFmag4qMsXeDZR -rOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjHYpy+g8cm -ez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQU -oBEKIz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF -MAMBAf8wewYDVR0fBHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20v -QUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29t -b2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2VzLmNybDANBgkqhkiG9w0BAQUF -AAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm7l3sAg9g1o1Q -GE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz -Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2 -G9w84FoVxp7Z8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsi -l2D4kF501KKaU73yqWjgom7C12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3 -smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIGZjCCBE6gAwIBAgIPB35Sk3vgFeNX8GmMy+wMMA0GCSqGSIb3DQEBBQUAMHsx -CzAJBgNVBAYTAkNPMUcwRQYDVQQKDD5Tb2NpZWRhZCBDYW1lcmFsIGRlIENlcnRp -ZmljYWNpw7NuIERpZ2l0YWwgLSBDZXJ0aWPDoW1hcmEgUy5BLjEjMCEGA1UEAwwa -QUMgUmHDrXogQ2VydGljw6FtYXJhIFMuQS4wHhcNMDYxMTI3MjA0NjI5WhcNMzAw -NDAyMjE0MjAyWjB7MQswCQYDVQQGEwJDTzFHMEUGA1UECgw+U29jaWVkYWQgQ2Ft -ZXJhbCBkZSBDZXJ0aWZpY2FjacOzbiBEaWdpdGFsIC0gQ2VydGljw6FtYXJhIFMu -QS4xIzAhBgNVBAMMGkFDIFJhw616IENlcnRpY8OhbWFyYSBTLkEuMIICIjANBgkq -hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAq2uJo1PMSCMI+8PPUZYILrgIem08kBeG -qentLhM0R7LQcNzJPNCNyu5LF6vQhbCnIwTLqKL85XXbQMpiiY9QngE9JlsYhBzL -fDe3fezTf3MZsGqy2IiKLUV0qPezuMDU2s0iiXRNWhU5cxh0T7XrmafBHoi0wpOQ -Y5fzp6cSsgkiBzPZkc0OnB8OIMfuuzONj8LSWKdf/WU34ojC2I+GdV75LaeHM/J4 -Ny+LvB2GNzmxlPLYvEqcgxhaBvzz1NS6jBUJJfD5to0EfhcSM2tXSExP2yYe68yQ -54v5aHxwD6Mq0Do43zeX4lvegGHTgNiRg0JaTASJaBE8rF9ogEHMYELODVoqDA+b -MMCm8Ibbq0nXl21Ii/kDwFJnmxL3wvIumGVC2daa49AZMQyth9VXAnow6IYm+48j -ilSH5L887uvDdUhfHjlvgWJsxS3EF1QZtzeNnDeRyPYL1epjb4OsOMLzP96a++Ej -YfDIJss2yKHzMI+ko6Kh3VOz3vCaMh+DkXkwwakfU5tTohVTP92dsxA7SH2JD/zt -A/X7JWR1DhcZDY8AFmd5ekD8LVkH2ZD6mq093ICK5lw1omdMEWux+IBkAC1vImHF -rEsm5VoQgpukg3s0956JkSCXjrdCx2bD0Omk1vUgjcTDlaxECp1bczwmPS9KvqfJ -pxAe+59QafMCAwEAAaOB5jCB4zAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQE -AwIBBjAdBgNVHQ4EFgQU0QnQ6dfOeXRU+Tows/RtLAMDG2gwgaAGA1UdIASBmDCB -lTCBkgYEVR0gADCBiTArBggrBgEFBQcCARYfaHR0cDovL3d3dy5jZXJ0aWNhbWFy -YS5jb20vZHBjLzBaBggrBgEFBQcCAjBOGkxMaW1pdGFjaW9uZXMgZGUgZ2FyYW50 -7WFzIGRlIGVzdGUgY2VydGlmaWNhZG8gc2UgcHVlZGVuIGVuY29udHJhciBlbiBs -YSBEUEMuMA0GCSqGSIb3DQEBBQUAA4ICAQBclLW4RZFNjmEfAygPU3zmpFmps4p6 -xbD/CHwso3EcIRNnoZUSQDWDg4902zNc8El2CoFS3UnUmjIz75uny3XlesuXEpBc -unvFm9+7OSPI/5jOCk0iAUgHforA1SBClETvv3eiiWdIG0ADBaGJ7M9i4z0ldma/ -Jre7Ir5v/zlXdLp6yQGVwZVR6Kss+LGGIOk/yzVb0hfpKv6DExdA7ohiZVvVO2Dp -ezy4ydV/NgIlqmjCMRW3MGXrfx1IebHPOeJCgBbT9ZMj/EyXyVo3bHwi2ErN0o42 -gzmRkBDI8ck1fj+404HGIGQatlDCIaR43NAvO2STdPCWkPHv+wlaNECW8DYSwaN0 -jJN+Qd53i+yG2dIPPy3RzECiiWZIHiCznCNZc6lEc7wkeZBWN7PGKX6jD/EpOe9+ -XCgycDWs2rjIdWb8m0w5R44bb5tNAlQiM+9hup4phO9OSzNHdpdqy35f/RWmnkJD -W2ZaiogN9xa5P1FlK2Zqi9E4UqLWRhH6/JocdJ6PlwsCT2TG9WjTSy3/pDceiz+/ -RL5hRqGEPQgnTIEgd4kI6mdAXmwIUV80WoyWaM3X94nCHNMyAK9Sy9NgWyo6R35r -MDOhYil/SrnhLecUIw4OGEfhefwVVdCx/CVxY3UzHCMrr1zZ7Ud3YA47Dx7SwNxk -BYn8eNZcLCZDqQ== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEGDCCAwCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQGEwJTRTEU -MBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3 -b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3QwHhcNMDAwNTMw -MTAzODMxWhcNMjAwNTMwMTAzODMxWjBlMQswCQYDVQQGEwJTRTEUMBIGA1UEChML -QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYD -VQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUA -A4IBDwAwggEKAoIBAQCWltQhSWDia+hBBwzexODcEyPNwTXH+9ZOEQpnXvUGW2ul -CDtbKRY654eyNAbFvAWlA3yCyykQruGIgb3WntP+LVbBFc7jJp0VLhD7Bo8wBN6n -tGO0/7Gcrjyvd7ZWxbWroulpOj0OM3kyP3CCkplhbY0wCI9xP6ZIVxn4JdxLZlyl -dI+Yrsj5wAYi56xz36Uu+1LcsRVlIPo1Zmne3yzxbrww2ywkEtvrNTVokMsAsJch -PXQhI2U0K7t4WaPW4XY5mqRJjox0r26kmqPZm9I4XJuiGMx1I4S+6+JNM3GOGvDC -+Mcdoq0Dlyz4zyXG9rgkMbFjXZJ/Y/AlyVMuH79NAgMBAAGjgdIwgc8wHQYDVR0O -BBYEFJWxtPCUtr3H2tERCSG+wa9J/RB7MAsGA1UdDwQEAwIBBjAPBgNVHRMBAf8E -BTADAQH/MIGPBgNVHSMEgYcwgYSAFJWxtPCUtr3H2tERCSG+wa9J/RB7oWmkZzBl -MQswCQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFk -ZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENB -IFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBACxtZBsfzQ3duQH6lmM0MkhHma6X -7f1yFqZzR1r0693p9db7RcwpiURdv0Y5PejuvE1Uhh4dbOMXJ0PhiVYrqW9yTkkz -43J8KiOavD7/KCrto/8cI7pDVwlnTUtiBi34/2ydYB7YHEt9tTEv2dB8Xfjea4MY -eDdXL+gzB2ffHsdrKpV2ro9Xo/D0UrSpUwjP4E/TelOL/bscVjby/rK25Xa71SJl -pz/+0WatC7xrmYbvP33zGDLKe8bjq2RGlfgmadlVg3sslgf/WSxEo8bl6ancoWOA -WiFeIc9TVPC6b4nbqKqVz4vjccweGyBECMB6tkD9xOQ14R0WHNC8K47Wcdk= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEU -MBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFs -IFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290 -MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFowbzELMAkGA1UEBhMCU0Ux -FDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5h -bCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0EgUm9v -dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvt -H7xsD821+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9 -uMq/NzgtHj6RQa1wVsfwTz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzX -mk6vBbOmcZSccbNQYArHE504B4YCqOmoaSYYkKtMsE8jqzpPhNjfzp/haW+710LX -a0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy2xSoRcRdKn23tNbE7qzN -E0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv77+ldU9U0 -WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYD -VR0PBAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0 -Jvf6xCZU7wO94CTLVBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRU -cnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsx -IjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3SCAQEwDQYJKoZIhvcN -AQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZlj7DYd7usQWxH -YINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5 -6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvC -Nr4TDea9Y355e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEX -c4g/VhsxOBi0cQ+azcgOno4uG+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5a -mnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEFTCCAv2gAwIBAgIBATANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQGEwJTRTEU -MBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3 -b3JrMSAwHgYDVQQDExdBZGRUcnVzdCBQdWJsaWMgQ0EgUm9vdDAeFw0wMDA1MzAx -MDQxNTBaFw0yMDA1MzAxMDQxNTBaMGQxCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtB -ZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQIE5ldHdvcmsxIDAeBgNV -BAMTF0FkZFRydXN0IFB1YmxpYyBDQSBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOC -AQ8AMIIBCgKCAQEA6Rowj4OIFMEg2Dybjxt+A3S72mnTRqX4jsIMEZBRpS9mVEBV -6tsfSlbunyNu9DnLoblv8n75XYcmYZ4c+OLspoH4IcUkzBEMP9smcnrHAZcHF/nX -GCwwfQ56HmIexkvA/X1id9NEHif2P0tEs7c42TkfYNVRknMDtABp4/MUTu7R3AnP -dzRGULD4EfL+OHn3Bzn+UZKXC1sIXzSGAa2Il+tmzV7R/9x98oTaunet3IAIx6eH -1lWfl2royBFkuucZKT8Rs3iQhCBSWxHveNCD9tVIkNAwHM+A+WD+eeSI8t0A65RF -62WUaUC6wNW0uLp9BBGo6zEFlpROWCGOn9Bg/QIDAQABo4HRMIHOMB0GA1UdDgQW -BBSBPjfYkrAfd59ctKtzquf2NGAv+jALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/BAUw -AwEB/zCBjgYDVR0jBIGGMIGDgBSBPjfYkrAfd59ctKtzquf2NGAv+qFopGYwZDEL -MAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQLExRBZGRU -cnVzdCBUVFAgTmV0d29yazEgMB4GA1UEAxMXQWRkVHJ1c3QgUHVibGljIENBIFJv -b3SCAQEwDQYJKoZIhvcNAQEFBQADggEBAAP3FUr4JNojVhaTdt02KLmuG7jD8WS6 -IBh4lSknVwW8fCr0uVFV2ocC3g8WFzH4qnkuCRO7r7IgGRLlk/lL+YPoRNWyQSW/ -iHVv/xD8SlTQX/D67zZzfRs2RcYhbbQVuE7PnFylPVoAjgbjPGsye/Kf8Lb93/Ao -GEjwxrzQvzSAlsJKsW2Ox5BF3i9nrEUEo3rcVZLJR2bYGozH7ZxOmuASu7VqTITh -4SINhwBk/ox9Yjllpu9CtoAlEmEBqCQTcAARJl/6NVDFSMwGR+gn2HCNX2TmoUQm -XiLsks3/QppEIW1cxeMiHV9HEufOX1362KqxMy3ZdvJOOjMMK7MtkAY= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEHjCCAwagAwIBAgIBATANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJTRTEU -MBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3 -b3JrMSMwIQYDVQQDExpBZGRUcnVzdCBRdWFsaWZpZWQgQ0EgUm9vdDAeFw0wMDA1 -MzAxMDQ0NTBaFw0yMDA1MzAxMDQ0NTBaMGcxCzAJBgNVBAYTAlNFMRQwEgYDVQQK -EwtBZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQIE5ldHdvcmsxIzAh -BgNVBAMTGkFkZFRydXN0IFF1YWxpZmllZCBDQSBSb290MIIBIjANBgkqhkiG9w0B -AQEFAAOCAQ8AMIIBCgKCAQEA5B6a/twJWoekn0e+EV+vhDTbYjx5eLfpMLXsDBwq -xBb/4Oxx64r1EW7tTw2R0hIYLUkVAcKkIhPHEWT/IhKauY5cLwjPcWqzZwFZ8V1G -87B4pfYOQnrjfxvM0PC3KP0q6p6zsLkEqv32x7SxuCqg+1jxGaBvcCV+PmlKfw8i -2O+tCBGaKZnhqkRFmhJePp1tUvznoD1oL/BLcHwTOK28FSXx1s6rosAx1i+f4P8U -WfyEk9mHfExUE+uf0S0R+Bg6Ot4l2ffTQO2kBhLEO+GRwVY18BTcZTYJbqukB8c1 -0cIDMzZbdSZtQvESa0NvS3GU+jQd7RNuyoB/mC9suWXY6QIDAQABo4HUMIHRMB0G -A1UdDgQWBBQ5lYtii1zJ1IC6WA+XPxUIQ8yYpzALBgNVHQ8EBAMCAQYwDwYDVR0T -AQH/BAUwAwEB/zCBkQYDVR0jBIGJMIGGgBQ5lYtii1zJ1IC6WA+XPxUIQ8yYp6Fr -pGkwZzELMAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQL -ExRBZGRUcnVzdCBUVFAgTmV0d29yazEjMCEGA1UEAxMaQWRkVHJ1c3QgUXVhbGlm -aWVkIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBABmrder4i2VhlRO6aQTv -hsoToMeqT2QbPxj2qC0sVY8FtzDqQmodwCVRLae/DLPt7wh/bDxGGuoYQ992zPlm -hpwsaPXpF/gxsxjE1kh9I0xowX67ARRvxdlu3rsEQmr49lx95dr6h+sNNVJn0J6X -dgWTP5XHAeZpVTh/EGGZyeNfpso+gmNIquIISD6q8rKFYqa0p9m9N5xotS1WfbC3 -P6CxB9bpT9zeRXEwMn8bLgn5v1Kh7sKAPgZcLlVAwRv1cEWw3F369nJad9Jjzc9Y -iQBCYz95OdBEsIJuQRno3eDBiFrRHnGTHyQwdOUeqN48Jzd/g66ed8/wMLH/S5no -xqE= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDpDCCAoygAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEc -MBoGA1UEChMTQW1lcmljYSBPbmxpbmUgSW5jLjE2MDQGA1UEAxMtQW1lcmljYSBP -bmxpbmUgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAxMB4XDTAyMDUyODA2 -MDAwMFoXDTM3MTExOTIwNDMwMFowYzELMAkGA1UEBhMCVVMxHDAaBgNVBAoTE0Ft -ZXJpY2EgT25saW5lIEluYy4xNjA0BgNVBAMTLUFtZXJpY2EgT25saW5lIFJvb3Qg -Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMTCCASIwDQYJKoZIhvcNAQEBBQADggEP -ADCCAQoCggEBAKgv6KRpBgNHw+kqmP8ZonCaxlCyfqXfaE0bfA+2l2h9LaaLl+lk -hsmj76CGv2BlnEtUiMJIxUo5vxTjWVXlGbR0yLQFOVwWpeKVBeASrlmLojNoWBym -1BW32J/X3HGrfpq/m44zDyL9Hy7nBzbvYjnF3cu6JRQj3gzGPTzOggjmZj7aUTsW -OqMFf6Dch9Wc/HKpoH145LcxVR5lu9RhsCFg7RAycsWSJR74kEoYeEfffjA3PlAb -2xzTa5qGUwew76wGePiEmf4hjUyAtgyC9mZweRrTT6PP8c9GsEsPPt2IYriMqQko -O3rHl+Ee5fSfwMCuJKDIodkP1nsmgmkyPacCAwEAAaNjMGEwDwYDVR0TAQH/BAUw -AwEB/zAdBgNVHQ4EFgQUAK3Zo/Z59m50qX8zPYEX10zPM94wHwYDVR0jBBgwFoAU -AK3Zo/Z59m50qX8zPYEX10zPM94wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEB -BQUAA4IBAQB8itEfGDeC4Liwo+1WlchiYZwFos3CYiZhzRAW18y0ZTTQEYqtqKkF -Zu90821fnZmv9ov761KyBZiibyrFVL0lvV+uyIbqRizBs73B6UlwGBaXCBOMIOAb -LjpHyx7kADCVW/RFo8AasAFOq73AI25jP4BKxQft3OJvx8Fi8eNy1gTIdGcL+oir -oQHIb/AUr9KZzVGTfu0uOMe9zkZQPXLjeSWdm4grECDdpbgyn43gKd8hdIaC2y+C -MMbHNYaz+ZZfRtsMRf3zUMNvxsNIrUam4SdHCh0Om7bCd39j8uB9Gr784N/Xx6ds -sPmuujz9dLQR6FgNgLzTqIA6me11zEZ7 ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIFpDCCA4ygAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEc -MBoGA1UEChMTQW1lcmljYSBPbmxpbmUgSW5jLjE2MDQGA1UEAxMtQW1lcmljYSBP -bmxpbmUgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAyMB4XDTAyMDUyODA2 -MDAwMFoXDTM3MDkyOTE0MDgwMFowYzELMAkGA1UEBhMCVVMxHDAaBgNVBAoTE0Ft -ZXJpY2EgT25saW5lIEluYy4xNjA0BgNVBAMTLUFtZXJpY2EgT25saW5lIFJvb3Qg -Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIP -ADCCAgoCggIBAMxBRR3pPU0Q9oyxQcngXssNt79Hc9PwVU3dxgz6sWYFas14tNwC -206B89enfHG8dWOgXeMHDEjsJcQDIPT/DjsS/5uN4cbVG7RtIuOx238hZK+GvFci -KtZHgVdEglZTvYYUAQv8f3SkWq7xuhG1m1hagLQ3eAkzfDJHA1zEpYNI9FdWboE2 -JxhP7JsowtS013wMPgwr38oE18aO6lhOqKSlGBxsRZijQdEt0sdtjRnxrXm3gT+9 -BoInLRBYBbV4Bbkv2wxrkJB+FFk4u5QkE+XRnRTf04JNRvCAOVIyD+OEsnpD8l7e -Xz8d3eOyG6ChKiMDbi4BFYdcpnV1x5dhvt6G3NRI270qv0pV2uh9UPu0gBe4lL8B -PeraunzgWGcXuVjgiIZGZ2ydEEdYMtA1fHkqkKJaEBEjNa0vzORKW6fIJ/KD3l67 -Xnfn6KVuY8INXWHQjNJsWiEOyiijzirplcdIz5ZvHZIlyMbGwcEMBawmxNJ10uEq -Z8A9W6Wa6897GqidFEXlD6CaZd4vKL3Ob5Rmg0gp2OpljK+T2WSfVVcmv2/LNzGZ -o2C7HK2JNDJiuEMhBnIMoVxtRsX6Kc8w3onccVvdtjc+31D1uAclJuW8tf48ArO3 -+L5DwYcRlJ4jbBeKuIonDFRH8KmzwICMoCfrHRnjB453cMor9H124HhnAgMBAAGj -YzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFE1FwWg4u3OpaaEg5+31IqEj -FNeeMB8GA1UdIwQYMBaAFE1FwWg4u3OpaaEg5+31IqEjFNeeMA4GA1UdDwEB/wQE -AwIBhjANBgkqhkiG9w0BAQUFAAOCAgEAZ2sGuV9FOypLM7PmG2tZTiLMubekJcmn -xPBUlgtk87FYT15R/LKXeydlwuXK5w0MJXti4/qftIe3RUavg6WXSIylvfEWK5t2 -LHo1YGwRgJfMqZJS5ivmae2p+DYtLHe/YUjRYwu5W1LtGLBDQiKmsXeu3mnFzccc -obGlHBD7GL4acN3Bkku+KVqdPzW+5X1R+FXgJXUjhx5c3LqdsKyzadsXg8n33gy8 -CNyRnqjQ1xU3c6U1uPx+xURABsPr+CKAXEfOAuMRn0T//ZoyzH1kUQ7rVyZ2OuMe -IjzCpjbdGe+n/BLzJsBZMYVMnNjP36TMzCmT/5RtdlwTCJfy7aULTd3oyWgOZtMA -DjMSW7yV5TKQqLPGbIOtd+6Lfn6xqavT4fG2wLHqiMDn05DpKJKUe2h7lyoKZy2F -AjgQ5ANh1NolNscIWC2hp1GvMApJ9aZphwctREZ2jirlmjvXGKL8nDgQzMY70rUX -Om/9riW99XJZZLF0KjhfGEzfz3EEWjbUvy+ZnOjZurGV5gJLIaFb1cFPj65pbVPb -AZO1XB4Y3WRayhgoPmMEEf0cjQAPuDffZ4qdZqkCapH/E8ovXYO8h5Ns3CRRFgQl -Zvqz2cK6Kb6aSDiCmfS/O0oxGfm/jiEzFMpPVF/7zvuPcX/9XhmgD0uRuMRUvAaw -RY8mkaKO/qk= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIID5jCCAs6gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBgzELMAkGA1UEBhMCVVMx -HTAbBgNVBAoTFEFPTCBUaW1lIFdhcm5lciBJbmMuMRwwGgYDVQQLExNBbWVyaWNh -IE9ubGluZSBJbmMuMTcwNQYDVQQDEy5BT0wgVGltZSBXYXJuZXIgUm9vdCBDZXJ0 -aWZpY2F0aW9uIEF1dGhvcml0eSAxMB4XDTAyMDUyOTA2MDAwMFoXDTM3MTEyMDE1 -MDMwMFowgYMxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRBT0wgVGltZSBXYXJuZXIg -SW5jLjEcMBoGA1UECxMTQW1lcmljYSBPbmxpbmUgSW5jLjE3MDUGA1UEAxMuQU9M -IFRpbWUgV2FybmVyIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMTCCASIw -DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJnej8Mlo2k06AX3dLm/WpcZuS+U -0pPlLYnKhHw/EEMbjIt8hFj4JHxIzyr9wBXZGH6EGhfT257XyuTZ16pYUYfw8ItI -TuLCxFlpMGK2MKKMCxGZYTVtfu/FsRkGIBKOQuHfD5YQUqjPnF+VFNivO3ULMSAf -RC+iYkGzuxgh28pxPIzstrkNn+9R7017EvILDOGsQI93f7DKeHEMXRZxcKLXwjqF -zQ6axOAAsNUl6twr5JQtOJyJQVdkKGUZHLZEtMgxa44Be3ZZJX8VHIQIfHNlIAqh -BC4aMqiaILGcLCFZ5/vP7nAtCMpjPiybkxlqpMKX/7eGV4iFbJ4VFitNLLMCAwEA -AaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUoTYwFsuGkABFgFOxj8jY -PXy+XxIwHwYDVR0jBBgwFoAUoTYwFsuGkABFgFOxj8jYPXy+XxIwDgYDVR0PAQH/ -BAQDAgGGMA0GCSqGSIb3DQEBBQUAA4IBAQCKIBilvrMvtKaEAEAwKfq0FHNMeUWn -9nDg6H5kHgqVfGphwu9OH77/yZkfB2FK4V1Mza3u0FIy2VkyvNp5ctZ7CegCgTXT -Ct8RHcl5oIBN/lrXVtbtDyqvpxh1MwzqwWEFT2qaifKNuZ8u77BfWgDrvq2g+EQF -Z7zLBO+eZMXpyD8Fv8YvBxzDNnGGyjhmSs3WuEvGbKeXO/oTLW4jYYehY0KswsuX -n2Fozy1MBJ3XJU8KDk2QixhWqJNIV9xvrr2eZ1d3iVCzvhGbRWeDhhmH05i9CBoW -H1iCC+GWaQVLjuyDUTEH1dSf/1l7qG6Fz9NLqUmwX7A5KGgOc90lmt4S ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIF5jCCA86gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBgzELMAkGA1UEBhMCVVMx -HTAbBgNVBAoTFEFPTCBUaW1lIFdhcm5lciBJbmMuMRwwGgYDVQQLExNBbWVyaWNh -IE9ubGluZSBJbmMuMTcwNQYDVQQDEy5BT0wgVGltZSBXYXJuZXIgUm9vdCBDZXJ0 -aWZpY2F0aW9uIEF1dGhvcml0eSAyMB4XDTAyMDUyOTA2MDAwMFoXDTM3MDkyODIz -NDMwMFowgYMxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRBT0wgVGltZSBXYXJuZXIg -SW5jLjEcMBoGA1UECxMTQW1lcmljYSBPbmxpbmUgSW5jLjE3MDUGA1UEAxMuQU9M -IFRpbWUgV2FybmVyIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMjCCAiIw -DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALQ3WggWmRToVbEbJGv8x4vmh6mJ -7ouZzU9AhqS2TcnZsdw8TQ2FTBVsRotSeJ/4I/1n9SQ6aF3Q92RhQVSji6UI0ilb -m2BPJoPRYxJWSXakFsKlnUWsi4SVqBax7J/qJBrvuVdcmiQhLE0OcR+mrF1FdAOY -xFSMFkpBd4aVdQxHAWZg/BXxD+r1FHjHDtdugRxev17nOirYlxcwfACtCJ0zr7iZ -YYCLqJV+FNwSbKTQ2O9ASQI2+W6p1h2WVgSysy0WVoaP2SBXgM1nEG2wTPDaRrbq -JS5Gr42whTg0ixQmgiusrpkLjhTXUr2eacOGAgvqdnUxCc4zGSGFQ+aJLZ8lN2fx -I2rSAG2X+Z/nKcrdH9cG6rjJuQkhn8g/BsXS6RJGAE57COtCPStIbp1n3UsC5ETz -kxmlJ85per5n0/xQpCyrw2u544BMzwVhSyvcG7mm0tCq9Stz+86QNZ8MUhy/XCFh -EVsVS6kkUfykXPcXnbDS+gfpj1bkGoxoigTTfFrjnqKhynFbotSg5ymFXQNoKk/S -Btc9+cMDLz9l+WceR0DTYw/j1Y75hauXTLPXJuuWCpTehTacyH+BCQJJKg71ZDIM -gtG6aoIbs0t0EfOMd9afv9w3pKdVBC/UMejTRrkDfNoSTllkt1ExMVCgyhwn2RAu -rda9EGYrw7AiShJbAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE -FE9pbQN+nZ8HGEO8txBO1b+pxCAoMB8GA1UdIwQYMBaAFE9pbQN+nZ8HGEO8txBO -1b+pxCAoMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQUFAAOCAgEAO/Ouyugu -h4X7ZVnnrREUpVe8WJ8kEle7+z802u6teio0cnAxa8cZmIDJgt43d15Ui47y6mdP -yXSEkVYJ1eV6moG2gcKtNuTxVBFT8zRFASbI5Rq8NEQh3q0l/HYWdyGQgJhXnU7q -7C+qPBR7V8F+GBRn7iTGvboVsNIYvbdVgaxTwOjdaRITQrcCtQVBynlQboIOcXKT -RuidDV29rs4prWPVVRaAMCf/drr3uNZK49m1+VLQTkCpx+XCMseqdiThawVQ68W/ -ClTluUI8JPu3B5wwn3la5uBAUhX0/Kr0VvlEl4ftDmVyXr4m+02kLQgH3thcoNyB -M5kYJRF3p+v9WAksmWsbivNSPxpNSGDxoPYzAlOL7SUJuA0t7Zdz7NeWH45gDtoQ -my8YJPamTQr5O8t1wswvziRpyQoijlmn94IM19drNZxDAGrElWe6nEXLuA4399xO -AU++CrYD062KRffaJ00psUjf5BHklka9bAI+1lHIlRcBFanyqqryvy9lG2/QuRqT -9Y41xICHPpQvZuTpqP9BnHAqTyo5GJUefvthATxRCC4oGKQWDzH9OmwjkyB24f0H -hdFbP9IcczLd+rn4jM8Ch3qaluTtT4mNU0OrDhPAARW0eTjb/G49nlG2uBOLZ8/5 -fNkiHfZdxRwBL5joeiQYvITX+txyW/fBOmg= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEuzCCA6OgAwIBAgIBAjANBgkqhkiG9w0BAQUFADBiMQswCQYDVQQGEwJVUzET -MBEGA1UEChMKQXBwbGUgSW5jLjEmMCQGA1UECxMdQXBwbGUgQ2VydGlmaWNhdGlv -biBBdXRob3JpdHkxFjAUBgNVBAMTDUFwcGxlIFJvb3QgQ0EwHhcNMDYwNDI1MjE0 -MDM2WhcNMzUwMjA5MjE0MDM2WjBiMQswCQYDVQQGEwJVUzETMBEGA1UEChMKQXBw -bGUgSW5jLjEmMCQGA1UECxMdQXBwbGUgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkx -FjAUBgNVBAMTDUFwcGxlIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw -ggEKAoIBAQDkkakJH5HbHkdQ6wXtXnmELes2oldMVeyLGYne+Uts9QerIjAC6Bg+ -+FAJ039BqJj50cpmnCRrEdCju+QbKsMflZ56DKRHi1vUFjczy8QPTc4UadHJGXL1 -XQ7Vf1+b8iUDulWPTV0N8WQ1IxVLFVkds5T39pyez1C6wVhQZ48ItCD3y6wsIG9w -tj8BMIy3Q88PnT3zK0koGsj+zrW5DtleHNbLPbU6rfQPDgCSC7EhFi501TwN22IW -q6NxkkdTVcGvL0Gz+PvjcM3mo0xFfh9Ma1CWQYnEdGILEINBhzOKgbEwWOxaBDKM -aLOPHd5lc/9nXmW8Sdh2nzMUZaF3lMktAgMBAAGjggF6MIIBdjAOBgNVHQ8BAf8E -BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUK9BpR5R2Cf70a40uQKb3 -R01/CF4wHwYDVR0jBBgwFoAUK9BpR5R2Cf70a40uQKb3R01/CF4wggERBgNVHSAE -ggEIMIIBBDCCAQAGCSqGSIb3Y2QFATCB8jAqBggrBgEFBQcCARYeaHR0cHM6Ly93 -d3cuYXBwbGUuY29tL2FwcGxlY2EvMIHDBggrBgEFBQcCAjCBthqBs1JlbGlhbmNl -IG9uIHRoaXMgY2VydGlmaWNhdGUgYnkgYW55IHBhcnR5IGFzc3VtZXMgYWNjZXB0 -YW5jZSBvZiB0aGUgdGhlbiBhcHBsaWNhYmxlIHN0YW5kYXJkIHRlcm1zIGFuZCBj -b25kaXRpb25zIG9mIHVzZSwgY2VydGlmaWNhdGUgcG9saWN5IGFuZCBjZXJ0aWZp -Y2F0aW9uIHByYWN0aWNlIHN0YXRlbWVudHMuMA0GCSqGSIb3DQEBBQUAA4IBAQBc -NplMLXi37Yyb3PN3m/J20ncwT8EfhYOFG5k9RzfyqZtAjizUsZAS2L70c5vu0mQP -y3lPNNiiPvl4/2vIB+x9OYOLUyDTOMSxv5pPCmv/K/xZpwUJfBdAVhEedNO3iyM7 -R6PVbyTi69G3cN8PReEnyvFteO3ntRcXqNx+IjXKJdXZD9Zr1KIkIxH3oayPc4Fg -xhtbCS+SsvhESPBgOJ4V9T0mZyCKM2r3DYLP3uujL/lTaltkwGMzd/c6ByxW69oP -IQ7aunMZT7XZNn/Bh1XZp5m5MkL72NVxnn6hUrcbvZNCJBIqxw8dtk2cXmPIS4AX -UKqK1drk/NAJBzewdXUh ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIFujCCBKKgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBhjELMAkGA1UEBhMCVVMx -HTAbBgNVBAoTFEFwcGxlIENvbXB1dGVyLCBJbmMuMS0wKwYDVQQLEyRBcHBsZSBD -b21wdXRlciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxKTAnBgNVBAMTIEFwcGxlIFJv -b3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTA1MDIxMDAwMTgxNFoXDTI1MDIx -MDAwMTgxNFowgYYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRBcHBsZSBDb21wdXRl -ciwgSW5jLjEtMCsGA1UECxMkQXBwbGUgQ29tcHV0ZXIgQ2VydGlmaWNhdGUgQXV0 -aG9yaXR5MSkwJwYDVQQDEyBBcHBsZSBSb290IENlcnRpZmljYXRlIEF1dGhvcml0 -eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOSRqQkfkdseR1DrBe1e -eYQt6zaiV0xV7IsZid75S2z1B6siMALoGD74UAnTf0GomPnRymacJGsR0KO75Bsq -wx+VnnoMpEeLW9QWNzPLxA9NzhRp0ckZcvVdDtV/X5vyJQO6VY9NXQ3xZDUjFUsV -WR2zlPf2nJ7PULrBWFBnjwi0IPfLrCwgb3C2PwEwjLdDzw+dPfMrSSgayP7OtbkO -2V4c1ss9tTqt9A8OAJILsSEWLnTVPA3bYharo3GSR1NVwa8vQbP4++NwzeajTEV+ -H0xrUJZBicR0YgsQg0GHM4qBsTBY7FoEMoxos48d3mVz/2deZbxJ2HafMxRloXeU -yS0CAwEAAaOCAi8wggIrMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/ -MB0GA1UdDgQWBBQr0GlHlHYJ/vRrjS5ApvdHTX8IXjAfBgNVHSMEGDAWgBQr0GlH -lHYJ/vRrjS5ApvdHTX8IXjCCASkGA1UdIASCASAwggEcMIIBGAYJKoZIhvdjZAUB -MIIBCTBBBggrBgEFBQcCARY1aHR0cHM6Ly93d3cuYXBwbGUuY29tL2NlcnRpZmlj -YXRlYXV0aG9yaXR5L3Rlcm1zLmh0bWwwgcMGCCsGAQUFBwICMIG2GoGzUmVsaWFu -Y2Ugb24gdGhpcyBjZXJ0aWZpY2F0ZSBieSBhbnkgcGFydHkgYXNzdW1lcyBhY2Nl -cHRhbmNlIG9mIHRoZSB0aGVuIGFwcGxpY2FibGUgc3RhbmRhcmQgdGVybXMgYW5k -IGNvbmRpdGlvbnMgb2YgdXNlLCBjZXJ0aWZpY2F0ZSBwb2xpY3kgYW5kIGNlcnRp -ZmljYXRpb24gcHJhY3RpY2Ugc3RhdGVtZW50cy4wRAYDVR0fBD0wOzA5oDegNYYz -aHR0cHM6Ly93d3cuYXBwbGUuY29tL2NlcnRpZmljYXRlYXV0aG9yaXR5L3Jvb3Qu -Y3JsMFUGCCsGAQUFBwEBBEkwRzBFBggrBgEFBQcwAoY5aHR0cHM6Ly93d3cuYXBw -bGUuY29tL2NlcnRpZmljYXRlYXV0aG9yaXR5L2Nhc2lnbmVycy5odG1sMA0GCSqG -SIb3DQEBBQUAA4IBAQCd2i0oWC99dgS5BNM+zrdmY06PL9T+S61yvaM5xlJNBZhS -9YlRASR5vhoy9+VEi0tEBzmC1lrKtCBe2a4VXR2MHTK/ODFiSF3H4ZCx+CRA+F9Y -m1FdV53B5f88zHIhbsTp6aF31ywXJsM/65roCwO66bNKcuszCVut5mIxauivL9Wv -Hld2j383LS4CXN1jyfJxuCZA3xWNdUQ/eb3mHZnhQyw+rW++uaT+DjUZUWOxw961 -kj5ReAFziqQjyqSI8R5cH0EWLX6VCqrpiUGYGxrdyyC/R14MJsVVNU3GMIuZZxTH -CR+6R8faAQmHJEKVvRNgGQrv6n8Obs3BREM6StXj ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDoDCCAoigAwIBAgIBMTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJKUDEO -MAwGA1UEChMFTEdQS0kxGjAYBgNVBAsTEUFwcGxpY2F0aW9uIENBIEcyMB4XDTA2 -MDMzMTE1MDAwMFoXDTE2MDMzMTE0NTk1OVowOTELMAkGA1UEBhMCSlAxDjAMBgNV -BAoTBUxHUEtJMRowGAYDVQQLExFBcHBsaWNhdGlvbiBDQSBHMjCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBALk1xhD422jbB8RATLAdHjbcw0H2z1UVbQh/ -XMZoVeXnV/GWUebhTXgPbkAVcDtl/hHf59PWWDU74Z8C/JRSRi6znmCbAp7JgtL2 -464JT4REtmKbAFFouDqt7GTRMkvplESDtA7OIYlrsDbAmMZLnMI+W2AqCTErLatM -3rGg/VhWwoMdILzEhAmHe6iVl8YljoPgPpMN0cd9c6mo/BkAQC4iuHozQfV4/Vpx -54LZSIhc7KiFhy1tgIlnGmm+EMBaju2IfT5vLDhrN85H2KIxMN5+U2Vsi4ZTQSBs -vUilfq8AWlYSWIHR3IlZ+bXu+E2a2EQpi3mn9yKq6nxctBaIIA0CAwEAAaOBsjCB -rzAdBgNVHQ4EFgQUf7hdjsQYa8Z9zC7prs405xdd4KEwDgYDVR0PAQH/BAQDAgEG -MEwGA1UdHwRFMEMwQaA/oD2kOzA5MQswCQYDVQQGEwJKUDEOMAwGA1UEChMFTEdQ -S0kxGjAYBgNVBAsTEUFwcGxpY2F0aW9uIENBIEcyMA8GA1UdEwEB/wQFMAMBAf8w -HwYDVR0jBBgwFoAUf7hdjsQYa8Z9zC7prs405xdd4KEwDQYJKoZIhvcNAQEFBQAD -ggEBADzYczZABkhKVBn1J0g5JaVuQue2zRvLOTS3m+xPKr535MqE/B3rmyJA1fT7 -aIdy/Eddag5SSuO1XUjGIpbmM21tq/bN18skWoyoRZ4+YYJ9lNUF8Bo1X3EvLlS1 -QQXvhg1S75yYG/EsTDrR84bTjD56L4ZFjoMyJlu/U8oOUVbcmsJaMBkNp57Vqpsg -OWl4IfSXbdEOEUwu0xtasPmXeFwqj1Jl7kxCJcI3MA5tKzWUgwbor0U7BGanMLv5 -4CE7Y259RF06alPvERck/VSyWmxzViHJbC2XpEKzJ2EFIWNt6ii8TxpvQtyYq1XT -HhvAkj+bweY7F1bixJhDJe62ywA= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDwzCCAyygAwIBAgIBADANBgkqhkiG9w0BAQQFADCBmDELMAkGA1UEBhMCQVQx -EDAOBgNVBAgTB0F1c3RyaWExDzANBgNVBAcTBlZpZW5uYTFCMEAGA1UEChM5QXJn -ZSBEYXRlbiBPZXN0ZXJyZWljaGlzY2hlIEdlc2VsbHNjaGFmdCBmdWVyIERhdGVu -c2NodXR6MSIwIAYJKoZIhvcNAQkBFhNhLWNlcnRAYXJnZWRhdGVuLmF0MB4XDTAx -MDIxMjExMzAzMFoXDTA5MDIxMjExMzAzMFowgZgxCzAJBgNVBAYTAkFUMRAwDgYD -VQQIEwdBdXN0cmlhMQ8wDQYDVQQHEwZWaWVubmExQjBABgNVBAoTOUFyZ2UgRGF0 -ZW4gT2VzdGVycmVpY2hpc2NoZSBHZXNlbGxzY2hhZnQgZnVlciBEYXRlbnNjaHV0 -ejEiMCAGCSqGSIb3DQEJARYTYS1jZXJ0QGFyZ2VkYXRlbi5hdDCBnzANBgkqhkiG -9w0BAQEFAAOBjQAwgYkCgYEAwgsHqoNtmmrJ86+e1I4hOVBaL4kokqKN2IPOIL+1 -XwY8vfOOUfPEdhWpaC0ldt7VYrksgDiUccgH0FROANWK2GkfKMDzjjXHysR04uEb -Om7Kqjqn0nproOGkFG+QvBZgs+Ws+HXNFJA6V76fU4+JXq4452LSK4Lr5YcBquu3 -NJECAwEAAaOCARkwggEVMB0GA1UdDgQWBBQ0j59zH/G31zRjgK1y2P//tSAWZjCB -xQYDVR0jBIG9MIG6gBQ0j59zH/G31zRjgK1y2P//tSAWZqGBnqSBmzCBmDELMAkG -A1UEBhMCQVQxEDAOBgNVBAgTB0F1c3RyaWExDzANBgNVBAcTBlZpZW5uYTFCMEAG -A1UEChM5QXJnZSBEYXRlbiBPZXN0ZXJyZWljaGlzY2hlIEdlc2VsbHNjaGFmdCBm -dWVyIERhdGVuc2NodXR6MSIwIAYJKoZIhvcNAQkBFhNhLWNlcnRAYXJnZWRhdGVu -LmF0ggEAMAwGA1UdEwQFMAMBAf8wCwYDVR0PBAQDAgEGMBEGCWCGSAGG+EIBAQQE -AwICBDANBgkqhkiG9w0BAQQFAAOBgQBFuJYncqMYB6gXQS3eDOI90BEHfFTKy/dV -AV+K7QdAYikWmqgBheRdPKddJdccPy/Zl/p3ZT7GhDyC5f3wZjcuu8AJ27BNwbCA -x54dgxgCNcyPm79nY8MRtEdEpoRGdSsFKJemz6hpXM++MWFciyrRWIIA44XB0Gv3 -US0spjsDPQ== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ -RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD -VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX -DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y -ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy -VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr -mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr -IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK -mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu -XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy -dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye -jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1 -BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3 -DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92 -9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx -jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0 -Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz -ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS -R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDlDCCAnygAwIBAgIQWAsFbFMk27JQVxhf+eWmUDANBgkqhkiG9w0BAQUFADAn -MQswCQYDVQQGEwJCRTEYMBYGA1UEAxMPQmVsZ2l1bSBSb290IENBMB4XDTAzMDEy -NjIzMDAwMFoXDTE0MDEyNjIzMDAwMFowJzELMAkGA1UEBhMCQkUxGDAWBgNVBAMT -D0JlbGdpdW0gUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB -AMihcekcRkJ5eHFvna6pqKsot03HIOswkVp19eLSz8hMFJhCWK3HEcVAQGpa+XQS -J4fpnOVxTiIs0RIYqjBeoiG52bv/9nTrMQHnO35YD5EWTXaJqAFPrSJmcPpLHZXB -MFjqvNll2Jq0iOtJRlLf0lMVdssUXRlJsW9q09P9vMIt7EU/CT9YvvzU7wCMgTVy -v/cY6pZifSsofxVsY9LKyn0FrMhtB20yvmi4BUCuVJhWPmbxMOjvxKuTXgfeMo8S -dKpbNCNUwOpszv42kqgJF+qhLc9s44Qd3ocuMws8dOIhUDiVLlzg5cYx+dtA+mqh -pIqTm6chBocdJ9PEoclMsG8CAwEAAaOBuzCBuDAOBgNVHQ8BAf8EBAMCAQYwDwYD -VR0TAQH/BAUwAwEB/zBCBgNVHSAEOzA5MDcGBWA4AQEBMC4wLAYIKwYBBQUHAgEW -IGh0dHA6Ly9yZXBvc2l0b3J5LmVpZC5iZWxnaXVtLmJlMB0GA1UdDgQWBBQQ8AxW -m2HqVzq2NZdtn925FI7b5jARBglghkgBhvhCAQEEBAMCAAcwHwYDVR0jBBgwFoAU -EPAMVpth6lc6tjWXbZ/duRSO2+YwDQYJKoZIhvcNAQEFBQADggEBAMhtIlGKYfgP -lm7VILKB+MbcoxYA2s1q52sq+llIp0xJN9dzoWoBZV4yveeX09AuPHPTjHuD79ZC -wT+oqV0PN7p20kC9zC0/00RBSZz9Wyn0AiMiW3Ebv1jZKE4tRfTa57VjRUQRDSp/ -M382SbTObqkCMa5c/ciJv0J71/Fg8teH9lcuen5qE4Ad3OPQYx49cTGxYNSeCMqr -8JTHSHVUgfMbrXec6LKP24OsjzRr6L/D2fVDw2RV6xq9NoY2uiGMlxoh1OotO6y6 -7Kcdq765Sps1LxxcHVGnH1TtEpf/8m6HfUbJdNbv6z195lluBpQE5KJVhzgoaiJe -4r50ErAEQyo= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIFLDCCBBSgAwIBAgIEOU99hzANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJX -VzESMBAGA1UEChMJYmVUUlVTVGVkMRswGQYDVQQDExJiZVRSVVNUZWQgUm9vdCBD -QXMxGjAYBgNVBAMTEWJlVFJVU1RlZCBSb290IENBMB4XDTAwMDYyMDE0MjEwNFoX -DTEwMDYyMDEzMjEwNFowWjELMAkGA1UEBhMCV1cxEjAQBgNVBAoTCWJlVFJVU1Rl -ZDEbMBkGA1UEAxMSYmVUUlVTVGVkIFJvb3QgQ0FzMRowGAYDVQQDExFiZVRSVVNU -ZWQgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANS0c3oT -CjhVAb6JVuGUntS+WutKNHUbYSnE4a0IYCF4SP+00PpeQY1hRIfo7clY+vyTmt9P -6j41ffgzeubx181vSUs9Ty1uDoM6GHh3o8/n9E1z2Jo7Gh2+lVPPIJfCzz4kUmwM -jmVZxXH/YgmPqsWPzGCgc0rXOD8Vcr+il7dw6K/ifhYGTPWqZCZyByWtNfwYsSbX -2P8ZDoMbjNx4RWc0PfSvHI3kbWvtILNnmrRhyxdviTX/507AMhLn7uzf/5cwdO2N -R47rtMNE5qdMf1ZD6Li8tr76g5fmu/vEtpO+GRg+jIG5c4gW9JZDnGdzF5DYCW5j -rEq2I8QBoa2k5MUCAwEAAaOCAfgwggH0MA8GA1UdEwEB/wQFMAMBAf8wggFZBgNV -HSAEggFQMIIBTDCCAUgGCisGAQQBsT4BAAAwggE4MIIBAQYIKwYBBQUHAgIwgfQa -gfFSZWxpYW5jZSBvbiB0aGlzIGNlcnRpZmljYXRlIGJ5IGFueSBwYXJ0eSBhc3N1 -bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJsZSBzdGFuZGFyZCB0 -ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGFuZCBjZXJ0aWZpY2F0aW9uIHBy -YWN0aWNlIHN0YXRlbWVudCwgd2hpY2ggY2FuIGJlIGZvdW5kIGF0IGJlVFJVU1Rl -ZCdzIHdlYiBzaXRlLCBodHRwczovL3d3dy5iZVRSVVNUZWQuY29tL3ZhdWx0L3Rl -cm1zMDEGCCsGAQUFBwIBFiVodHRwczovL3d3dy5iZVRSVVNUZWQuY29tL3ZhdWx0 -L3Rlcm1zMDQGA1UdHwQtMCswKaAnoCWkIzAhMRIwEAYDVQQKEwliZVRSVVNUZWQx -CzAJBgNVBAYTAldXMB0GA1UdDgQWBBQquZtpLjub2M3eKjEENGvKBxirZzAfBgNV -HSMEGDAWgBQquZtpLjub2M3eKjEENGvKBxirZzAOBgNVHQ8BAf8EBAMCAf4wDQYJ -KoZIhvcNAQEFBQADggEBAHlh26Nebhax6nZR+csVm8tpvuaBa58oH2U+3RGFktTo -Qb9+M70j5/Egv6S0phkBxoyNNXxlpE8JpNbYIxUFE6dDea/bow6be3ga8wSGWsb2 -jCBHOElQBp1yZzrwmAOtlmdE/D8QDYZN5AA7KXvOOzuZhmElQITcE2K3+spZ1gMe -1lMBzW1MaFVA4e5rxyoAAEiCswoBw2AqDPeCNe5IhpbkdNQ96gFxugR1QKepfzk5 -mlWXKWWuGVUlBXJH0+gY3Ljpr0NzARJ0o+FcXxVdJPP55PS2Z2cS52QiivalQaYc -tmBjRYoQtLpGEK5BV2VsPyMQPyEQWbfkQN0mDCP2qq4= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNV -BAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4X -DTA3MDYyOTE1MTMwNVoXDTI3MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQ -BgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwIQ2VydGlnbmEwggEiMA0GCSqGSIb3 -DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7qXOEm7RFHYeGifBZ4 -QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyHGxny -gQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbw -zBfsV1/pogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q -130yGLMLLGq/jj8UEYkgDncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2 -JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKfIrjxwo1p3Po6WAbfAgMBAAGjgbwwgbkw -DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQtCRZvgHyUtVF9lo53BEw -ZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJBgNVBAYT -AkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzj -AQ/JSP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG -9w0BAQUFAAOCAQEAhQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8h -bV6lUmPOEvjvKtpv6zf+EwLHyzs+ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFnc -fca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1kluPBS1xp81HlDQwY9qcEQCYsuu -HWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY1gkIl2PlwS6w -t0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw -WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDczCCAlugAwIBAgIQMDAwMDk3Mzc1NzM4NjAwMDANBgkqhkiG9w0BAQUFADBV -MQswCQYDVQQGEwJGUjETMBEGA1UEChMKQ2VydGlOb21pczEcMBoGA1UECxMTQUMg -UmFjaW5lIC0gUm9vdCBDQTETMBEGA1UEAxMKQ2VydGlOb21pczAeFw0wMDExMDkw -MDAwMDBaFw0xMjExMDkwMDAwMDBaMFUxCzAJBgNVBAYTAkZSMRMwEQYDVQQKEwpD -ZXJ0aU5vbWlzMRwwGgYDVQQLExNBQyBSYWNpbmUgLSBSb290IENBMRMwEQYDVQQD -EwpDZXJ0aU5vbWlzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8SWb -4mS5RXB3ENSIcfrEzCj/TRUQuT1tMCU0YUfXFSgcPdWglIzCv3kvh07QoB+8xMl+ -fQHvSSduAxnNewz0GBY9rApCPKlP6CcnJr74OSVZIiWt9wLfl4wwhNhZOiikIpZp -EdOXWqRc84P5cUlN3Lwmr1sjCWmHfTSS4cAKxfDbFLfE61etosyoFZUTQbIhb1Bf -JL5xRXAUZudQiU42n/yAoSUrN4FLUfPQNlOe1AB81pIgX8g2ojwxDjfgqSs1JmBF -uLKJ45uVLEenQBPmQCGjL3maV86IRmR3a9UGlgvKAk0NBdh8mrQyQvcUlLBIQBCm -l7wppt6maQHUNEPQSwIDAQABoz8wPTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUw -AwEB/zAdBgNVHQ4EFgQU+F4ho6ijFeb4tRG7/kIEXU2OgnowDQYJKoZIhvcNAQEF -BQADggEBACe9FJayK6bXkJQrilBFMh75QPdFOks9PJuo86OMUlBDZGYFTCh9Arex -N3KYCnAEzazYIALwr7eASJJDIQMu1Q+pkx/7ACde4kP47F27M2rm+v5HnGooCLz2 -s7Fe/WUycTQqgwF5lNp03m1ce/TvovgkEZeVN5wM/7+SsZLJGDigXGeq48j2g2hn -8OckX9Ciyo0U3/1IVeigNBisiaOlsHSZOEPBZQRiZULob+NVbXVPo8nM1OyP3aHI -LQex1yYcCr9m93nOiZyKkur3Uedf1yMTBe+fflnPFKGYnVqvTGXCKVdHzQBfpILA -AuaC+5ykZhSiSMf8nmL2oPMcLO7YQw4= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIESjCCAzKgAwIBAgIBAzANBgkqhkiG9w0BAQUFADBBMQswCQYDVQQGEwJLUjEN -MAsGA1UEChMES0lTQTEPMA0GA1UECxMGUk9PVENBMRIwEAYDVQQDEwlDZXJ0UlNB -MDEwHhcNMDAwMzAyMTUwMDAwWhcNMTAwMzAzMTQ1OTU5WjBBMQswCQYDVQQGEwJL -UjENMAsGA1UEChMES0lTQTEPMA0GA1UECxMGUk9PVENBMRIwEAYDVQQDEwlDZXJ0 -UlNBMDEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDOz+3h6FYdyUsy -YJsqt5eHYQY0aMsXrsB4xcYRW0t8l6u5bE4vAPZTLOnhnFqQaj16ODg1Wq0cClmF -u/VjZwkT6SZP2Dxd71NC3kVi5D7NcqT6s8DgH46U4mUtVcEVkixv80PUNQUFNDeg -LLRzW/EnJpSa9boSzPp4NaKtVNVmjxHqphlN1xM1VHuRlwNHY7CpD2i+0vSe6o21 -e0S1uS04yQDj5b/GdYkDmf+MSwgPwgUxpE0XEc7DdQ9rsF/QrIatfemgiLnGEtbA -OizSb2wnHar/RZvGAxACafkG758ioDg4gsgkEayhno9Nvnhf37o/gwN9UaP4x12o -kWgfHnLdAgMBAAGjggFLMIIBRzAdBgNVHQ4EFgQU/4pGcjNY6EiIIqoXaNoWSAmL -NZEwHwYDVR0jBBgwFoAU/4pGcjNY6EiIIqoXaNoWSAmLNZEwDgYDVR0PAQH/BAQD -AgEGMBUGA1UdIAQOMAwwCgYIKoMajJpEAgEwMAYDVR0RBCkwJ6QlMCMxITAfBgNV -BAMMGO2VnOq1reygleuztOuztO2YuOyEvO2EsDAwBgNVHRIEKTAnpCUwIzEhMB8G -A1UEAwwY7ZWc6rWt7KCV67O067O07Zi47IS87YSwMBIGA1UdEwEB/wQIMAYBAf8C -AQEwDAYDVR0kBAUwA4ABADBYBgNVHR8EUTBPME2gS6BJhkdsZGFwOi8vZGlyc3lz -LnJvb3RjYS5vci5rcjozODkvQ049Uk9PVC1SU0EtQ1JMLCBPVT1ST09UQ0EsIE89 -S0lTQSwgQz1LUjANBgkqhkiG9w0BAQUFAAOCAQEALDykI2xC+IkoR1B84+bnIy02 -NsaIKpGY+x58D6udEa11rORcazERdDNib9QGkRHGcnSYL7Bi+zQprxTyxmTgv6vL -V7lhnPNiTTN512YqUczcAFQFAVZ+jLaOE/QtmVHhmni8VVFKSdpbC4L7Qz3azZMJ -y7WjCcOwfVlIopvY+zfDbw436gWXv9Juocjow/vzrTLIVZI0QuDUEuXU7SGK55iS -/1zXpWaqv/E6fC3C4FU1BdqRagdT0YWxlMcmDRtoKQjBIZMPa6JguFOvRNlkXdNu -m4QSeDEY2nO/rCT4qy2/Dn66ewnKWomoLFLMTHSt2V+zt9YF90FfceVmGQYleQ== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEvTCCA6WgAwIBAgIBADANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJFVTEn -MCUGA1UEChMeQUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQL -ExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEiMCAGA1UEAxMZQ2hhbWJlcnMg -b2YgQ29tbWVyY2UgUm9vdDAeFw0wMzA5MzAxNjEzNDNaFw0zNzA5MzAxNjEzNDRa -MH8xCzAJBgNVBAYTAkVVMScwJQYDVQQKEx5BQyBDYW1lcmZpcm1hIFNBIENJRiBB -ODI3NDMyODcxIzAhBgNVBAsTGmh0dHA6Ly93d3cuY2hhbWJlcnNpZ24ub3JnMSIw -IAYDVQQDExlDaGFtYmVycyBvZiBDb21tZXJjZSBSb290MIIBIDANBgkqhkiG9w0B -AQEFAAOCAQ0AMIIBCAKCAQEAtzZV5aVdGDDg2olUkfzIx1L4L1DZ77F1c2VHfRtb -unXF/KGIJPov7coISjlUxFF6tdpg6jg8gbLL8bvZkSM/SAFwdakFKq0fcfPJVD0d -BmpAPrMMhe5cG3nCYsS4No41XQEMIwRHNaqbYE6gZj3LJgqcQKH0XZi/caulAGgq -7YN6D6IUtdQis4CwPAxaUWktWBiP7Zme8a7ileb2R6jWDA+wWFjbw2Y3npuRVDM3 -0pQcakjJyfKl2qUMI/cjDpwyVV5xnIQFUZot/eZOKjRa3spAN2cMVCFVd9oKDMyX -roDclDZK9D7ONhMeU+SsTjoF7Nuucpw4i9A5O4kKPnf+dQIBA6OCAUQwggFAMBIG -A1UdEwEB/wQIMAYBAf8CAQwwPAYDVR0fBDUwMzAxoC+gLYYraHR0cDovL2NybC5j -aGFtYmVyc2lnbi5vcmcvY2hhbWJlcnNyb290LmNybDAdBgNVHQ4EFgQU45T1sU3p -26EpW1eLTXYGduHRooowDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIA -BzAnBgNVHREEIDAegRxjaGFtYmVyc3Jvb3RAY2hhbWJlcnNpZ24ub3JnMCcGA1Ud -EgQgMB6BHGNoYW1iZXJzcm9vdEBjaGFtYmVyc2lnbi5vcmcwWAYDVR0gBFEwTzBN -BgsrBgEEAYGHLgoDATA+MDwGCCsGAQUFBwIBFjBodHRwOi8vY3BzLmNoYW1iZXJz -aWduLm9yZy9jcHMvY2hhbWJlcnNyb290Lmh0bWwwDQYJKoZIhvcNAQEFBQADggEB -AAxBl8IahsAifJ/7kPMa0QOx7xP5IV8EnNrJpY0nbJaHkb5BkAFyk+cefV/2icZd -p0AJPaxJRUXcLo0waLIJuvvDL8y6C98/d3tGfToSJI6WjzwFCm/SlCgdbQzALogi -1djPHRPH8EjX1wWnz8dHnjs8NMiAT9QUu/wNUPf6s+xCX6ndbcj0dc97wXImsQEc -XCz9ek60AcUFV7nnPKoF2YjpB0ZBzu9Bga5Y34OirsrXdx/nADydb47kMgkdTXg0 -eDQ8lJsm7U9xxhl6vSAiSFr+S30Dt+dYvsYyTnQeaN2oaFuzPu5ifdmA6Ap1erfu -tGWaIZDgqtCYvDi1czyL+Nw= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDQzCCAiugAwIBAgIQX/h7KCtU3I1CoxW1aMmt/zANBgkqhkiG9w0BAQUFADA1 -MRYwFAYDVQQKEw1DaXNjbyBTeXN0ZW1zMRswGQYDVQQDExJDaXNjbyBSb290IENB -IDIwNDgwHhcNMDQwNTE0MjAxNzEyWhcNMjkwNTE0MjAyNTQyWjA1MRYwFAYDVQQK -Ew1DaXNjbyBTeXN0ZW1zMRswGQYDVQQDExJDaXNjbyBSb290IENBIDIwNDgwggEg -MA0GCSqGSIb3DQEBAQUAA4IBDQAwggEIAoIBAQCwmrmrp68Kd6ficba0ZmKUeIhH -xmJVhEAyv8CrLqUccda8bnuoqrpu0hWISEWdovyD0My5jOAmaHBKeN8hF570YQXJ -FcjPFto1YYmUQ6iEqDGYeJu5Tm8sUxJszR2tKyS7McQr/4NEb7Y9JHcJ6r8qqB9q -VvYgDxFUl4F1pyXOWWqCZe+36ufijXWLbvLdT6ZeYpzPEApk0E5tzivMW/VgpSdH -jWn0f84bcN5wGyDWbs2mAag8EtKpP6BrXruOIIt6keO1aO6g58QBdKhTCytKmg9l -Eg6CTY5j/e/rmxrbU6YTYK/CfdfHbBcl1HP7R2RQgYCUTOG/rksc35LtLgXfAgED -o1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUJ/PI -FR5umgIJFq0roIlgX9p7L6owEAYJKwYBBAGCNxUBBAMCAQAwDQYJKoZIhvcNAQEF -BQADggEBAJ2dhISjQal8dwy3U8pORFBi71R803UXHOjgxkhLtv5MOhmBVrBW7hmW -Yqpao2TB9k5UM8Z3/sUcuuVdJcr18JOagxEu5sv4dEX+5wW4q+ffy0vhN4TauYuX -cB7w4ovXsNgOnbFp1iqRe6lJT37mjpXYgyc81WhJDtSd9i7rp77rMKSsH0T8lasz -Bvt9YAretIpjsJyp8qS5UwGH0GikJ3+r/+n6yUA4iGe0OcaEb1fJU9u6ju7AQ7L4 -CYNu/2bPPu8Xs1gYJQk0XuPL1hS27PKSb3TkL4Eq1ZKR4OCXPDJoBYVL0fdX4lId -kxpUnwVwwEpxYB5DC2Ae/qPOgRnhCzU= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIICPTCCAaYCEQDNun9W8N/kvFT+IqyzcqpVMA0GCSqGSIb3DQEBAgUAMF8xCzAJ -BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE3MDUGA1UECxMuQ2xh -c3MgMSBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw05 -NjAxMjkwMDAwMDBaFw0yODA4MDEyMzU5NTlaMF8xCzAJBgNVBAYTAlVTMRcwFQYD -VQQKEw5WZXJpU2lnbiwgSW5jLjE3MDUGA1UECxMuQ2xhc3MgMSBQdWJsaWMgUHJp -bWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCBnzANBgkqhkiG9w0BAQEFAAOB -jQAwgYkCgYEA5Rm/baNWYS2ZSHH2Z965jeu3noaACpEO+jglr0aIguVzqKCbJF0N -H8xlbgyw0FaEGIeaBpsQoXPftFg5a27B9hXVqKg/qhIGjTGsf7A01480Z4gJzRQR -4k5FVmkfeAKA2txHkSm7NsljXMXg1y2He6G3MrB7MLoqLzGq7qNn2tsCAwEAATAN -BgkqhkiG9w0BAQIFAAOBgQBMP7iLxmjf7kMzDl3ppssHhE16M/+SG/Q2rdiVIjZo -EWx8QszznC7EBz8UsA9P/5CSdvnivErpj82ggAr3xSnxgiJduLHdgSOjeyUVRjB5 -FvjqBUuUfx3CHMjjt/QQQDwTw18fU+hI5Ia0e6E1sHslurjTjqs/OJ0ANACY89Fx -lA== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDAjCCAmsCEEzH6qqYPnHTkxD4PTqJkZIwDQYJKoZIhvcNAQEFBQAwgcExCzAJ -BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xh -c3MgMSBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcy -MTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3Jp -emVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMB4X -DTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVTMRcw -FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMSBQdWJsaWMg -UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEo -YykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5 -MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEB -AQUAA4GNADCBiQKBgQCq0Lq+Fi24g9TK0g+8djHKlNgdk4xWArzZbxpvUjZudVYK -VdPfQ4chEWWKfo+9Id5rMj8bhDSVBZ1BNeuS65bdqlk/AVNtmU/t5eIqWpDBucSm -Fc/IReumXY6cPvBkJHalzasab7bYe1FhbqZ/h8jit+U03EGI6glAvnOSPWvndQID -AQABMA0GCSqGSIb3DQEBBQUAA4GBAKlPww3HZ74sy9mozS11534Vnjty637rXC0J -h9ZrbWB85a7FkCMMXErQr7Fd88e2CtvgFZMN3QO8x3aKtd1Pw5sTdbgBwObJW2ul -uIncrKTdcu1OofdPvAbT6shkdHvClUGcZXNY8ZCaPGqxmMnEh7zPRW1F4m4iP/68 -DzFc6PLZ ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDkjCCAnqgAwIBAgIRAIW9S/PY2uNp9pTXX8OlRCMwDQYJKoZIhvcNAQEFBQAw -PTELMAkGA1UEBhMCRlIxETAPBgNVBAoTCENlcnRwbHVzMRswGQYDVQQDExJDbGFz -cyAyIFByaW1hcnkgQ0EwHhcNOTkwNzA3MTcwNTAwWhcNMTkwNzA2MjM1OTU5WjA9 -MQswCQYDVQQGEwJGUjERMA8GA1UEChMIQ2VydHBsdXMxGzAZBgNVBAMTEkNsYXNz -IDIgUHJpbWFyeSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANxQ -ltAS+DXSCHh6tlJw/W/uz7kRy1134ezpfgSN1sxvc0NXYKwzCkTsA18cgCSR5aiR -VhKC9+Ar9NuuYS6JEI1rbLqzAr3VNsVINyPi8Fo3UjMXEuLRYE2+L0ER4/YXJQyL -kcAbmXuZVg2v7tK8R1fjeUl7NIknJITesezpWE7+Tt9avkGtrAjFGA7v0lPubNCd -EgETjdyAYveVqUSISnFOYFWe2yMZeVYHDD9jC1yw4r5+FfyUM1hBOHTE4Y+L3yas -H7WLO7dDWWuwJKZtkIvEcupdM5i3y95ee++U8Rs+yskhwcWYAqqi9lt3m/V+llU0 -HGdpwPFC40es/CgcZlUCAwEAAaOBjDCBiTAPBgNVHRMECDAGAQH/AgEKMAsGA1Ud -DwQEAwIBBjAdBgNVHQ4EFgQU43Mt38sOKAze3bOkynm4jrvoMIkwEQYJYIZIAYb4 -QgEBBAQDAgEGMDcGA1UdHwQwMC4wLKAqoCiGJmh0dHA6Ly93d3cuY2VydHBsdXMu -Y29tL0NSTC9jbGFzczIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQCnVM+IRBnL39R/ -AN9WM2K191EBkOvDP9GIROkkXe/nFL0gt5o8AP5tn9uQ3Nf0YtaLcF3n5QRIqWh8 -yfFC82x/xXp8HVGIutIKPidd3i1RTtMTZGnkLuPT55sJmabglZvOGtd/vjzOUrMR -FcEPF80Du5wlFbqidon8BvEY0JNLDnyCt6X09l/+7UCmnYR0ObncHoUW2ikbhiMA -ybuJfm6AiB4vFLQDJKgybwOaRywwvlbGp0ICcBvqQNi6BQNwB6SW//1IMwrh3KWB -kJtN3X3n57LNXMhqlfil9o3EXXgIvnsG1knPGTZQIy4I5p4FTUcY1Rbpsda2ENW7 -l7+ijrRU ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIICPDCCAaUCEC0b/EoXjaOR6+f/9YtFvgswDQYJKoZIhvcNAQECBQAwXzELMAkG -A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz -cyAyIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2 -MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV -BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAyIFB1YmxpYyBQcmlt -YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN -ADCBiQKBgQC2WoujDWojg4BrzzmH9CETMwZMJaLtVRKXxaeAufqDwSCg+i8VDXyh -YGt+eSz6Bg86rvYbb7HS/y8oUl+DfUvEerf4Zh+AVPy3wo5ZShRXRtGak75BkQO7 -FYCTXOvnzAhsPz6zSvz/S2wj1VCCJkQZjiPDceoZJEcEnnW/yKYAHwIDAQABMA0G -CSqGSIb3DQEBAgUAA4GBAIobK/o5wXTXXtgZZKJYSi034DNHD6zt96rbHuSLBlxg -J8pFUs4W7z8GZOeUaHxgMxURaa+dYo2jA1Rrpr7l7gUYYAS/QoD90KioHgE796Nc -r6Pc5iaAIzy4RHT3Cq5Ji2F4zCS/iIqnDupzGUH9TQPwiNHleI2lKk/2lw0Xd8rY ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDAzCCAmwCEQC5L2DMiJ+hekYJuFtwbIqvMA0GCSqGSIb3DQEBBQUAMIHBMQsw -CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xPDA6BgNVBAsTM0Ns -YXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBH -MjE6MDgGA1UECxMxKGMpIDE5OTggVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9y -aXplZCB1c2Ugb25seTEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazAe -Fw05ODA1MTgwMDAwMDBaFw0yODA4MDEyMzU5NTlaMIHBMQswCQYDVQQGEwJVUzEX -MBUGA1UEChMOVmVyaVNpZ24sIEluYy4xPDA6BgNVBAsTM0NsYXNzIDIgUHVibGlj -IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjE6MDgGA1UECxMx -KGMpIDE5OTggVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25s -eTEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazCBnzANBgkqhkiG9w0B -AQEFAAOBjQAwgYkCgYEAp4gBIXQs5xoD8JjhlzwPIQjxnNuX6Zr8wgQGE75fUsjM -HiwSViy4AWkszJkfrbCWrnkE8hM5wXuYuggs6MKEEyyqaekJ9MepAqRCwiNPStjw -DqL7MWzJ5m+ZJwf15vRMeJ5t60aG+rmGyVTyssSv1EYcWskVMP8NbPUtDm3Of3cC -AwEAATANBgkqhkiG9w0BAQUFAAOBgQByLvl/0fFx+8Se9sVeUYpAmLho+Jscg9ji -nb3/7aHmZuovCfTK1+qlK5X2JGCGTUQug6XELaDTrnhpb3LabK4I8GOSN+a7xDAX -rXfMSTWqz9iP0b63GJZHc2pUIjRkLbYWm1lbtFFZOrMLFPQS32eg9K0yZF6xRnIn -jBJ7xUS0rg== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIICPDCCAaUCEHC65B0Q2Sk0tjjKewPMur8wDQYJKoZIhvcNAQECBQAwXzELMAkG -A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz -cyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2 -MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV -BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmlt -YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN -ADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhE -BarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/is -I19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0G -CSqGSIb3DQEBAgUAA4GBALtMEivPLCYATxQT3ab7/AoRhIzzKBxnki98tsX63/Do -lbwdj2wsqFHMc9ikwFPwTtYmwHYBV4GSXiHx0bH/59AhWM1pF+NEHJwZRDmJXNyc -AA9WjQKZ7aKQRUzkuxCkPfAyAw7xzvjoyVGM5mKf5p/AfbdynMk2OmufTqj/ZA1k ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDAjCCAmsCEH3Z/gfPqB63EHln+6eJNMYwDQYJKoZIhvcNAQEFBQAwgcExCzAJ -BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xh -c3MgMyBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcy -MTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3Jp -emVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMB4X -DTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVTMRcw -FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMyBQdWJsaWMg -UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEo -YykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5 -MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEB -AQUAA4GNADCBiQKBgQDMXtERXVxp0KvTuWpMmR9ZmDCOFoUgRm1HP9SFIIThbbP4 -pO0M8RcPO/mn+SXXwc+EY/J8Y8+iR/LGWzOOZEAEaMGAuWQcRXfH2G71lSk8UOg0 -13gfqLptQ5GVj0VXXn7F+8qkBOvqlzdUMG+7AUcyM83cV5tkaWH4mx0ciU9cZwID -AQABMA0GCSqGSIb3DQEBBQUAA4GBAFFNzb5cy5gZnBWyATl4Lk0PZ3BwmcYQWpSk -U01UbSuvDV1Ai2TT1+7eVmGSX6bEHRBhNtMsJzzoKQm5EWR0zLVznxxIqbxhAe7i -F6YM40AIOw7n60RzKprxaZLvcRTDOaxxp5EJb+RxBrO6WVcmeQD2+A2iMzAo1KpY -oJ2daZH9 ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDAjCCAmsCEDKIjprS9esTR/h/xCA3JfgwDQYJKoZIhvcNAQEFBQAwgcExCzAJ -BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xh -c3MgNCBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcy -MTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3Jp -emVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMB4X -DTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVTMRcw -FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgNCBQdWJsaWMg -UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEo -YykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5 -MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEB -AQUAA4GNADCBiQKBgQC68OTP+cSuhVS5B1f5j8V/aBH4xBewRNzjMHPVKmIquNDM -HO0oW369atyzkSTKQWI8/AIBvxwWMZQFl3Zuoq29YRdsTjCG8FE3KlDHqGKB3FtK -qsGgtG7rL+VXxbErQHDbWk2hjh+9Ax/YA9SPTJlxvOKCzFjomDqG04Y48wApHwID -AQABMA0GCSqGSIb3DQEBBQUAA4GBAIWMEsGnuVAVess+rLhDityq3RS6iYF+ATwj -cSGIL4LcY/oCRaxFWdcqWERbt5+BO5JoPeI3JPV7bI92NZYJqFmduc4jq3TWg/0y -cyfYaT5DdPauxYma51N86Xv2S/PBZYPejYqcPIiNOVn8qj8ijaHBZlCBckztImRP -T8qAkbYp ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDejCCAmKgAwIBAgIQOeOBVATFCrJH7/7zNs/GmDANBgkqhkiG9w0BAQUFADBO -MQswCQYDVQQGEwJ1czEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQ0wCwYDVQQL -EwRGQkNBMRYwFAYDVQQDEw1Db21tb24gUG9saWN5MB4XDTA0MTAwNjE4NDUwOVoX -DTEwMTAwNjE4NTM1NlowTjELMAkGA1UEBhMCdXMxGDAWBgNVBAoTD1UuUy4gR292 -ZXJubWVudDENMAsGA1UECxMERkJDQTEWMBQGA1UEAxMNQ29tbW9uIFBvbGljeTCC -ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM8mfLBpTHcAyvTjdBmU+1ph -r2LkvcMA5SSjASag1Nbj0fmmeO/r9AGSqDCQL8ozo2iCICXUN7LtGSC3KRazC1k4 -B0RBYQiRX3FCxWQqKS5GugwypRMl49nevfjJE5CKVxG1V0h4OLUn0ayFyir4QPgl -f51CIOFz20X901qav91H7j4+SRgA5Pa+XIgteCgHrl7S1pvmvfwsuifzlr4w/iD4 -99moD3hxx1MjzbCsf0eMz3EmwRrDMCSeCNNYdCXyFt+w0II3NWiZieG9BKBOlmKe -wWO0GlFS/MneL/he9X2MbxtBgU27KFOum2E/Kerc0LepUx2u9aqW1lx3k1YqSVMC -AwEAAaNUMFIwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O -BBYEFB4sS/nsZqYekl+HeQPt1cKVt5WDMBAGCSsGAQQBgjcVAQQDAgEAMA0GCSqG -SIb3DQEBBQUAA4IBAQBmNcuhcoLgN86WWb4HzKl+FxrREMhdjB36ElzHcjmi6SyE -WGD+d/lNO2sT6t7bPuYZ9mxjhHoFa+46Gc20zk7hFTFBN2OKNH+Uh8cIo/fL+bB7 -SeHoIdehwuTypq3n80B5oensf6AkisUbNR7Ko+B55oejo8Z8OcZJwhAu/5fSbH7T -uw8b61YaYyy8wx62smnHZ+3KTC2fBDCj4kZSAIPV1Qpr7ek0IJAYVIS6lzw3kYcz -6vpcGVt8LCmajURYdLsGMW6JtFkReeCa0jxiQT1MOum5pUnFAI8PoXdcPUaUekqO -CDEtJXsIYBGs+zrud8xtBs5DpekCyb3iWLoIeq0H ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCB -gTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G -A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNV -BAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEyMDEwMDAw -MDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3Jl -YXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01P -RE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0 -aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3 -UcEbVASY06m/weaKXTuH+7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI -2GqGd0S7WWaXUF601CxwRM/aN5VCaTwwxHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8 -Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV4EajcNxo2f8ESIl33rXp -+2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA1KGzqSX+ -DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5O -nKVIrLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW -/zAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6g -PKA6hjhodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9u -QXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOCAQEAPpiem/Yb6dc5t3iuHXIY -SdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CPOGEIqB6BCsAv -IC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/ -RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4 -zJVSk/BwJVmcIGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5dd -BA6+C4OmF4O5MBKgxTMVBbkN+8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IB -ZQ== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDnzCCAoegAwIBAgIBJjANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJERTEc -MBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxlU2Vj -IFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290IENB -IDIwHhcNOTkwNzA5MTIxMTAwWhcNMTkwNzA5MjM1OTAwWjBxMQswCQYDVQQGEwJE -RTEcMBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxl -U2VjIFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290 -IENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrC6M14IspFLEU -ha88EOQ5bzVdSq7d6mGNlUn0b2SjGmBmpKlAIoTZ1KXleJMOaAGtuU1cOs7TuKhC -QN/Po7qCWWqSG6wcmtoIKyUn+WkjR/Hg6yx6m/UTAtB+NHzCnjwAWav12gz1Mjwr -rFDa1sPeg5TKqAyZMg4ISFZbavva4VhYAUlfckE8FQYBjl2tqriTtM2e66foai1S -NNs671x1Udrb8zH57nGYMsRUFUQM+ZtV7a3fGAigo4aKSe5TBY8ZTNXeWHmb0moc -QqvF1afPaA+W5OFhmHZhyJF81j4A4pFQh+GdCuatl9Idxjp9y7zaAzTVjlsB9WoH -txa2bkp/AgMBAAGjQjBAMB0GA1UdDgQWBBQxw3kbuvVT1xfgiXotF2wKsyudMzAP -BgNVHRMECDAGAQH/AgEFMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOC -AQEAlGRZrTlk5ynrE/5aw4sTV8gEJPB0d8Bg42f76Ymmg7+Wgnxu1MM9756Abrsp -tJh6sTtU6zkXR34ajgv8HzFZMQSyzhfzLMdiNlXiItiJVbSYSKpk+tYcNthEeFpa -IzpXl/V6ME+un2pMSyuOoAPjPuCp1NJ70rOo4nI8rZ7/gFnkm0W09juwzTkZmDLl -6iFhkOQxIY40sfcvNUqFENrnijchvllj4PKFiDFT1FQUhXB59C4Gdyd1Lx+4ivn+ -xbrYNuSD7Odlt79jWvNGr4GUN9RBjNYj1h7P9WgbRGOiWrqnNVmh5XAFmw4jV5mU -Cm26OWMohpLzGITY+9HPBVZkVw== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBl -MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv -b3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzExMTEwMDAwMDAwWjBlMQswCQYDVQQG -EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl -cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwggEi -MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7c -JpSIqvTO9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYP -mDI2dsze3Tyoou9q+yHyUmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+ -wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4 -VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpyoeb6pNnVFzF1roV9Iq4/ -AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whfGHdPAgMB -AAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW -BBRF66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYun -pyGd823IDzANBgkqhkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRC -dWKuh+vy1dneVrOfzM4UKLkNl2BcEkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTf -fwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38FnSbNd67IJKusm7Xi+fT8r87cm -NW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i8b5QZ7dsvfPx -H2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe -+o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh -MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD -QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT -MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j -b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG -9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB -CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97 -nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt -43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P -T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4 -gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO -BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR -TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw -DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr -hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg -06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF -PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls -YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk -CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs -MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j -ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL -MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3 -LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug -RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm -+9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW -PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM -xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB -Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3 -hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg -EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF -MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA -FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec -nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z -eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF -hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2 -Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe -vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep -+OkuE6N36B9K ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIFijCCA3KgAwIBAgIQDHbanJEMTiye/hXQWJM8TDANBgkqhkiG9w0BAQUFADBf -MQswCQYDVQQGEwJOTDESMBAGA1UEChMJRGlnaU5vdGFyMRowGAYDVQQDExFEaWdp -Tm90YXIgUm9vdCBDQTEgMB4GCSqGSIb3DQEJARYRaW5mb0BkaWdpbm90YXIubmww -HhcNMDcwNTE2MTcxOTM2WhcNMjUwMzMxMTgxOTIxWjBfMQswCQYDVQQGEwJOTDES -MBAGA1UEChMJRGlnaU5vdGFyMRowGAYDVQQDExFEaWdpTm90YXIgUm9vdCBDQTEg -MB4GCSqGSIb3DQEJARYRaW5mb0BkaWdpbm90YXIubmwwggIiMA0GCSqGSIb3DQEB -AQUAA4ICDwAwggIKAoICAQCssFjBAL3YIQgLK5r+blYwBZ8bd5AQQVzDDYcRd46B -8cp86Yxq7Th0Nbva3/m7wAk3tJZzgX0zGpg595NvlX89ubF1h7pRSOiLcD6VBMXY -tsMW2YiwsYcdcNqGtA8Ui3rPENF0NqISe3eGSnnme98CEWilToauNFibJBN4ViIl -HgGLS1Fx+4LMWZZpiFpoU8W5DQI3y0u8ZkqQfioLBQftFl9VkHXYRskbg+IIvvEj -zJkd1ioPgyAVWCeCLvriIsJJsbkBgWqdbZ1Ad2h2TiEqbYRAhU52mXyC8/O3AlnU -JgEbjt+tUwbRrhjd4rI6y9eIOI6sWym5GdOY+RgDz0iChmYLG2kPyes4iHomGgVM -ktck1JbyrFIto0fVUvY//s6EBnCmqj6i8rZWNBhXouSBbefK8GrTx5FrAoNBfBXv -a5pkXuPQPOWx63tdhvvL5ndJzaNl3Pe5nLjkC1+Tz8wwGjIczhxjlaX56uF0i57p -K6kwe6AYHw4YC+VbqdPRbB4HZ4+RS6mKvNJmqpMBiLKR+jFc1abBUggJzQpjotMi -puih2TkGl/VujQKQjBR7P4DNG5y6xFhyI6+2Vp/GekIzKQc/gsnmHwUNzUwoNovT -yD4cxojvXu6JZOkd69qJfjKmadHdzIif0dDJZiHcBmfFlHqabWJMfczgZICynkeO -owIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNV -HQ4EFgQUiGi/4I41xDs4a2L3KDuEgcgM100wDQYJKoZIhvcNAQEFBQADggIBADsC -jcs8MOhuoK3yc7NfniUTBAXT9uOLuwt5zlPe5JbF0a9zvNXD0EBVfEB/zRtfCdXy -fJ9oHbtdzno5wozWmHvFg1Wo1X1AyuAe94leY12hE8JdiraKfADzI8PthV9xdvBo -Y6pFITlIYXg23PFDk9Qlx/KAZeFTAnVR/Ho67zerhChXDNjU1JlWbOOi/lmEtDHo -M/hklJRRl6s5xUvt2t2AC298KQ3EjopyDedTFLJgQT2EkTFoPSdE2+Xe9PpjRchM -Ppj1P0G6Tss3DbpmmPHdy59c91Q2gmssvBNhl0L4eLvMyKKfyvBovWsdst+Nbwed -2o5nx0ceyrm/KkKRt2NTZvFCo+H0Wk1Ya7XkpDOtXHAd3ODy63MUkZoDweoAZbwH -/M8SESIsrqC9OuCiKthZ6SnTGDWkrBFfGbW1G/8iSlzGeuQX7yCpp/Q/rYqnmgQl -nQ7KN+ZQ/YxCKQSa7LnPS3K94gg2ryMvYuXKAdNw23yCIywWMQzGNgeQerEfZ1jE -O1hZibCMjFCz2IbLaKPECudpSyDOwR5WS5WpI2jYMNjD67BVUc3l/Su49bsRn1NU -9jQZjHkJNsphFyUXC4KYcwx3dMPVDceoEkzHp1RxRy4sGn3J4ys7SN4nhKdjNrN9 -j6BkOSQNPXuHr2ZcdBtLc7LljPCGmbjlxd+Ewbfr ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIICZzCCAdCgAwIBAgIBBDANBgkqhkiG9w0BAQUFADBhMQswCQYDVQQGEwJVUzEY -MBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxDDAKBgNVBAsT -A1BLSTEcMBoGA1UEAxMTRG9EIENMQVNTIDMgUm9vdCBDQTAeFw0wMDA1MTkxMzEz -MDBaFw0yMDA1MTQxMzEzMDBaMGExCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMu -IEdvdmVybm1lbnQxDDAKBgNVBAsTA0RvRDEMMAoGA1UECxMDUEtJMRwwGgYDVQQD -ExNEb0QgQ0xBU1MgMyBSb290IENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB -gQC1MP5kvurMbe2BLPd/6Rm6DmlqKOGpqcuVWB/x5pppU+CIP5HFUbljl6jmIYwT -XjY8qFf6+HAsTGrLvzCnTBbkMlz4ErBR+BZXjS+0TfouqJToKmHUVw1Hzm4sL36Y -Z8wACKu2lhY1woWR5VugCsdmUmLzYXWVF668KlYppeArUwIDAQABoy8wLTAdBgNV -HQ4EFgQUbJyl8FyPbUGNxBc7kFfCD6PNbf4wDAYDVR0TBAUwAwEB/zANBgkqhkiG -9w0BAQUFAAOBgQCvcUT5lyPMaGmMQwdBuoggsyIAQciYoFUczT9usZNcrfoYmrsc -c2/9JEKPh59Rz76Gn+nXikhPCNlplKw/5g8tlw8ok3ZPYt//oM1h+KaGDDE0INx/ -L6j7Ob6V7jhZAmLB3mwVT+DfnbvkeXMk/WNklfdKqJkfSGWVx3u/eDLneg== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIICZzCCAdCgAwIBAgIBGjANBgkqhkiG9w0BAQUFADBhMQswCQYDVQQGEwJVUzEY -MBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxDDAKBgNVBAsT -A1BLSTEcMBoGA1UEAxMTRG9EIFBLSSBNZWQgUm9vdCBDQTAeFw05ODA4MDYxNTAx -MDBaFw0wODA4MDcxNTAxMDBaMGExCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMu -IEdvdmVybm1lbnQxDDAKBgNVBAsTA0RvRDEMMAoGA1UECxMDUEtJMRwwGgYDVQQD -ExNEb0QgUEtJIE1lZCBSb290IENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB -gQC5arG1dp5gWLAG69GfVnf0laK3aCAXLKGE65A72UGYsJQ3ENGaE9lW/JoDaLV8 -wrjQIL87bVC34jTvJs2aPjd7oeUaUXjeddt8bYjwRV/fwXl/oUoGx9umpJUuNvEW -1H9P6xJFyzB9jpm+HGW+Oid3wtWKqNq1xsSuMByHlpoXtwIDAQABoy8wLTAdBgNV -HQ4EFgQUxVnSzvGYlVBmqG3eMkvWYTXiRrMwDAYDVR0TBAUwAwEB/zANBgkqhkiG -9w0BAQUFAAOBgQAyPjGMqsgKSbKHr38GlCT6WmkKtCWX6YX/3S3vaf39asluzJX6 -3sTcMByqi0jy7BLYbgKzPvxmuW3yVUlLl6rV6YrId62ezjPmaIqkDI8snEM0BWSW -2ousTPara2J0xvzdC5lj/+ke6LHrO9yhSLRFMk8quccSXtFW6H5ei0+sGg== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDcDCCAligAwIBAgIBBTANBgkqhkiG9w0BAQUFADBbMQswCQYDVQQGEwJVUzEY -MBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxDDAKBgNVBAsT -A1BLSTEWMBQGA1UEAxMNRG9EIFJvb3QgQ0EgMjAeFw0wNDEyMTMxNTAwMTBaFw0y -OTEyMDUxNTAwMTBaMFsxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVy -bm1lbnQxDDAKBgNVBAsTA0RvRDEMMAoGA1UECxMDUEtJMRYwFAYDVQQDEw1Eb0Qg -Um9vdCBDQSAyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwCzB9o07 -rP8/PNZxvrh0IgfscEEV/KtA4weqwcPYn/7aTDq/P8jYKHtLNgHArEUlw9IOCo+F -GGQQPRoTcCpvjtfcjZOzQQ84Ic2tq8I9KgXTVxE3Dc2MUfmT48xGSSGOFLTNyxQ+ -OM1yMe6rEvJl6jQuVl3/7mN1y226kTT8nvP0LRy+UMRC31mI/2qz+qhsPctWcXEF -lrufgOWARVlnQbDrw61gpIB1BhecDvRD4JkOG/t/9bPMsoGCsf0ywbi+QaRktWA6 -WlEwjM7eQSwZR1xJEGS5dKmHQa99brrBuKG/ZTE6BGf5tbuOkooAY7ix5ow4X4P/ -UNU7ol1rshDMYwIDAQABoz8wPTAdBgNVHQ4EFgQUSXS7DF66ev4CVO97oMaVxgmA -cJYwCwYDVR0PBAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD -ggEBAJiRjT+JyLv1wGlzKTs1rLqzCHY9cAmS6YREIQF9FHYb7lFsHY0VNy17MWn0 -mkS4r0bMNPojywMnGdKDIXUr5+AbmSbchECV6KjSzPZYXGbvP0qXEIIdugqi3VsG -K52nZE7rLgE1pLQ/E61V5NVzqGmbEfGY8jEeb0DU+HifjpGgb3AEkGaqBivO4XqS -tX3h4NGW56E6LcyxnR8FRO2HmdNNGnA5wQQM5X7Z8a/XIA7xInolpHOZzD+kByeW -qKKV7YK5FtOeC4fCwfKI9WLfaN/HvGlR7bFc3FRUKQ8JOZqsA8HbDE2ubwp6Fknx -v5HSOJTT9pUst2zJQraNypCNhdk= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIECTCCAvGgAwIBAgIQDV6ZCtadt3js2AdWO4YV2TANBgkqhkiG9w0BAQUFADBb -MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3Qx -ETAPBgNVBAsTCERTVCBBQ0VTMRcwFQYDVQQDEw5EU1QgQUNFUyBDQSBYNjAeFw0w -MzExMjAyMTE5NThaFw0xNzExMjAyMTE5NThaMFsxCzAJBgNVBAYTAlVTMSAwHgYD -VQQKExdEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdDERMA8GA1UECxMIRFNUIEFDRVMx -FzAVBgNVBAMTDkRTVCBBQ0VTIENBIFg2MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A -MIIBCgKCAQEAuT31LMmU3HWKlV1j6IR3dma5WZFcRt2SPp/5DgO0PWGSvSMmtWPu -ktKe1jzIDZBfZIGxqAgNTNj50wUoUrQBJcWVHAx+PhCEdc/BGZFjz+iokYi5Q1K7 -gLFViYsx+tC3dr5BPTCapCIlF3PoHuLTrCq9Wzgh1SpL11V94zpVvddtawJXa+ZH -fAjIgrrep4c9oW24MFbCswKBXy314powGCi4ZtPLAZZv6opFVdbgnf9nKxcCpk4a -ahELfrd755jWjHZvwTvbUJN+5dCOHze4vbrGn2zpfDPyMjwmR/onJALJfh1biEIT -ajV8fTXpLmaRcpPVMibEdPVTo7NdmvYJywIDAQABo4HIMIHFMA8GA1UdEwEB/wQF -MAMBAf8wDgYDVR0PAQH/BAQDAgHGMB8GA1UdEQQYMBaBFHBraS1vcHNAdHJ1c3Rk -c3QuY29tMGIGA1UdIARbMFkwVwYKYIZIAWUDAgEBATBJMEcGCCsGAQUFBwIBFjto -dHRwOi8vd3d3LnRydXN0ZHN0LmNvbS9jZXJ0aWZpY2F0ZXMvcG9saWN5L0FDRVMt -aW5kZXguaHRtbDAdBgNVHQ4EFgQUCXIGThhDD+XWzMNqizF7eI+og7gwDQYJKoZI -hvcNAQEFBQADggEBAKPYjtay284F5zLNAdMEA+V25FYrnJmQ6AgwbN99Pe7lv7Uk -QIRJ4dEorsTCOlMwiPH1d25Ryvr/ma8kXxug/fKshMrfqfBfBC6tFr8hlxCBPeP/ -h40y3JTlR4peahPJlJU90u7INJXQgNStMgiAVDzgvVJT11J8smk/f3rPanTK+gQq -nExaBqXpIK1FZg9p8d2/6eMyi/rgwYZNcjwu2JN4Cir42NInPRmJX1p7ijvMDNpR -rscL9yuwNwXsvFcj4jjSm2jzVhKIT0J8uDHEtdvkyCE06UgRNe76x5JXxZ805Mf2 -9w4LTJxoeHtxMcfrHuBnQfO3oKfN5XozNmr6mis= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/ -MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT -DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow -PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD -Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB -AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O -rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq -OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b -xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw -7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD -aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV -HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG -SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69 -ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr -AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz -R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5 -JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo -Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDOzCCAiOgAwIBAgIRANAeRlAAACmMAAAAAgAAAAIwDQYJKoZIhvcNAQEFBQAw -PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD -Ew5EU1QgUm9vdCBDQSBYNDAeFw0wMDA5MTMwNjIyNTBaFw0yMDA5MTMwNjIyNTBa -MD8xJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjEXMBUGA1UE -AxMORFNUIFJvb3QgQ0EgWDQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB -AQCthX3OFEYY8gSeIYur0O4ypOT68HnDrjLfIutL5PZHRwQGjzCPb9PFo/ihboJ8 -RvfGhBAqpQCo47zwYEhpWm1jB+L/OE/dBBiyn98krfU2NiBKSom2J58RBeAwHGEy -cO+lewyjVvbDDLUy4CheY059vfMjPAftCRXjqSZIolQb9FdPcAoa90mFwB7rKniE -J7vppdrUScSS0+eBrHSUPLdvwyn4RGp+lSwbWYcbg5EpSpE0GRJdchic0YDjvIoC -YHpe7Rkj93PYRTQyU4bhC88ck8tMqbvRYqMRqR+vobbkrj5LLCOQCHV5WEoxWh+0 -E2SpIFe7RkV++MmpIAc0h1tZAgMBAAGjMjAwMA8GA1UdEwEB/wQFMAMBAf8wHQYD -VR0OBBYEFPCD6nPIP1ubWzdf9UyPWvf0hki9MA0GCSqGSIb3DQEBBQUAA4IBAQCE -G85wl5eEWd7adH6XW/ikGN5salvpq/Fix6yVTzE6CrhlP5LBdkf6kx1bSPL18M45 -g0rw2zA/MWOhJ3+S6U+BE0zPGCuu8YQaZibR7snm3HiHUaZNMu5c8D0x0bcMxDjY -AVVcHCoNiL53Q4PLW27nbY6wwG0ffFKmgV3blxrYWfuUDgGpyPwHwkfVFvz9qjaV -mf12VJffL6W8omBPtgteb6UaT/k1oJ7YI0ldGf+ngpVbRhD+LC3cUtT6GO/BEPZu -8YTV/hbiDH5v3khVqMIeKT6o8IuXGG7F6a6vKwP1F1FwTXf4UC/ivhme7vdUH7B/ -Vv4AEbT8dNfEeFxrkDbh ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIID2DCCAsACEQDQHkCLAAACfAAAAAIAAAABMA0GCSqGSIb3DQEBBQUAMIGpMQsw -CQYDVQQGEwJ1czENMAsGA1UECBMEVXRhaDEXMBUGA1UEBxMOU2FsdCBMYWtlIENp -dHkxJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjERMA8GA1UE -CxMIRFNUQ0EgWDExFjAUBgNVBAMTDURTVCBSb290Q0EgWDExITAfBgkqhkiG9w0B -CQEWEmNhQGRpZ3NpZ3RydXN0LmNvbTAeFw05ODEyMDExODE4NTVaFw0wODExMjgx -ODE4NTVaMIGpMQswCQYDVQQGEwJ1czENMAsGA1UECBMEVXRhaDEXMBUGA1UEBxMO -U2FsdCBMYWtlIENpdHkxJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0 -IENvLjERMA8GA1UECxMIRFNUQ0EgWDExFjAUBgNVBAMTDURTVCBSb290Q0EgWDEx -ITAfBgkqhkiG9w0BCQEWEmNhQGRpZ3NpZ3RydXN0LmNvbTCCASIwDQYJKoZIhvcN -AQEBBQADggEPADCCAQoCggEBANLGJrbnpT3BxGjVUG9TxW9JEwm4ryxIjRRqoxdf -WvnTLnUv2Chi0ZMv/E3Uq4flCMeZ55I/db3rJbQVwZsZPdJEjdd0IG03Ao9pk1uK -xBmd9LIO/BZsubEFkoPRhSxglD5FVaDZqwgh5mDoO3TymVBRaNADLbGAvqPYUrBE -zUNKcI5YhZXhTizWLUFv1oTnyJhEykfbLCSlaSbPa7gnYsP0yXqSI+0TZ4KuRS5F -5X5yP4WdlGIQ5jyRoa13AOAV7POEgHJ6jm5gl8ckWRA0g1vhpaRptlc1HHhZxtMv -OnNn7pTKBBMFYgZwI7P0fO5F2WQLW0mqpEPOJsREEmy43XkCAwEAATANBgkqhkiG -9w0BAQUFAAOCAQEAojeyP2n714Z5VEkxlTMr89EJFEliYIalsBHiUMIdBlc+Legz -ZL6bqq1fG03UmZWii5rJYnK1aerZWKs17RWiQ9a2vAd5ZWRzfdd5ynvVWlHG4VME -lo04z6MXrDlxawHDi1M8Y+nuecDkvpIyZHqzH5eUYr3qsiAVlfuX8ngvYzZAOONG -Dx3drJXK50uQe7FLqdTF65raqtWjlBRGjS0f8zrWkzr2Pnn86Oawde3uPclwx12q -gUtGJRzHbBXjlU4PqjI3lAoXJJIThFjSY28r9+ZbYgsTF7ANUkz+/m9c4pFuHf2k -Ytdo+o56T9II2pPc8JIRetDccpMMc5NihWjQ9A== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIID2DCCAsACEQDQHkCLAAB3bQAAAAEAAAAEMA0GCSqGSIb3DQEBBQUAMIGpMQsw -CQYDVQQGEwJ1czENMAsGA1UECBMEVXRhaDEXMBUGA1UEBxMOU2FsdCBMYWtlIENp -dHkxJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjERMA8GA1UE -CxMIRFNUQ0EgWDIxFjAUBgNVBAMTDURTVCBSb290Q0EgWDIxITAfBgkqhkiG9w0B -CQEWEmNhQGRpZ3NpZ3RydXN0LmNvbTAeFw05ODExMzAyMjQ2MTZaFw0wODExMjcy -MjQ2MTZaMIGpMQswCQYDVQQGEwJ1czENMAsGA1UECBMEVXRhaDEXMBUGA1UEBxMO -U2FsdCBMYWtlIENpdHkxJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0 -IENvLjERMA8GA1UECxMIRFNUQ0EgWDIxFjAUBgNVBAMTDURTVCBSb290Q0EgWDIx -ITAfBgkqhkiG9w0BCQEWEmNhQGRpZ3NpZ3RydXN0LmNvbTCCASIwDQYJKoZIhvcN -AQEBBQADggEPADCCAQoCggEBANx18IzAdZaawGIfJvfE4Zrq4FZzW5nNAUSoCLbV -p9oaBBg5kkp4o4HC9Xd6ULRw/5qrxsfKboNPQpj7Jgva3G3WqZlVUmfpKAOS3OWw -BZoPFflrWXJW8vo5/Kpo7g8fEIMv/J36F5bdguPmRX3AS4BEH+0s4IT9kVySVGkl -5WJp3OXuAFK9MwutdQKFp2RQLcUZGTDAJtvJ0/0uma1ZtQtN1EGuhUhDWdy3qOKi -3sOP17ihYqZoUFLkzzGnlIXan0YyF1bl8utmPRL/Q9uY73fPy4GNNLHGUEom0eQ+ -QVCvbK4iNC7Va26Dunm4dmVI2gkpZGMiuftHdoWMhkTLCdsCAwEAATANBgkqhkiG -9w0BAQUFAAOCAQEAtTYOXeFhKFoRZcA/gwN5Tb4opgsHAlKFzfiR0BBstWogWxyQ -2TA8xkieil5k+aFxd+8EJx8H6+Qm93N0yUQYGmbT4EOvkTvRyyzYdFQ6HE3K1GjN -I3wdEJ5F6fYAbqbNGf9PLCmPV03Ed5K+4EwJ+11EhmYhqLkyolbV6YyDfFk/xPEL -553snr2cGA4+wjl5KLcDDQjLxufZATdQEOzMYRZA1K8xdHv8PzGn0EdzMzkbzE5q -10mDEQb+64JYMzJM8FasHpwvVpp7wUocpf1VNs78lk30sPDst2yC7S8xmUJMqbIN -uBVd8d+6ybVK1GSYsyapMMj9puyrliGtf8J4tg== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIF5zCCA8+gAwIBAgIITK9zQhyOdAIwDQYJKoZIhvcNAQEFBQAwgYAxODA2BgNV -BAMML0VCRyBFbGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sx -c8SxMTcwNQYDVQQKDC5FQkcgQmlsacWfaW0gVGVrbm9sb2ppbGVyaSB2ZSBIaXpt -ZXRsZXJpIEEuxZ4uMQswCQYDVQQGEwJUUjAeFw0wNjA4MTcwMDIxMDlaFw0xNjA4 -MTQwMDMxMDlaMIGAMTgwNgYDVQQDDC9FQkcgRWxla3Ryb25payBTZXJ0aWZpa2Eg -SGl6bWV0IFNhxJ9sYXnEsWPEsXPEsTE3MDUGA1UECgwuRUJHIEJpbGnFn2ltIFRl -a25vbG9qaWxlcmkgdmUgSGl6bWV0bGVyaSBBLsWeLjELMAkGA1UEBhMCVFIwggIi -MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDuoIRh0DpqZhAy2DE4f6en5f2h -4fuXd7hxlugTlkaDT7byX3JWbhNgpQGR4lvFzVcfd2NR/y8927k/qqk153nQ9dAk -tiHq6yOU/im/+4mRDGSaBUorzAzu8T2bgmmkTPiab+ci2hC6X5L8GCcKqKpE+i4s -tPtGmggDg3KriORqcsnlZR9uKg+ds+g75AxuetpX/dfreYteIAbTdgtsApWjluTL -dlHRKJ2hGvxEok3MenaoDT2/F08iiFD9rrbskFBKW5+VQarKD7JK/oCZTqNGFav4 -c0JqwmZ2sQomFd2TkuzbqV9UIlKRcF0T6kjsbgNs2d1s/OsNA/+mgxKb8amTD8Um -TDGyY5lhcucqZJnSuOl14nypqZoaqsNW2xCaPINStnuWt6yHd6i58mcLlEOzrz5z -+kI2sSXFCjEmN1ZnuqMLfdb3ic1nobc6HmZP9qBVFCVMLDMNpkGMvQQxahByCp0O -Lna9XvNRiYuoP1Vzv9s6xiQFlpJIqkuNKgPlV5EQ9GooFW5Hd4RcUXSfGenmHmMW -OeMRFeNYGkS9y8RsZteEBt8w9DeiQyJ50hBs37vmExH8nYQKE3vwO9D8owrXieqW -fo1IhR5kX9tUoqzVegJ5a9KK8GfaZXINFHDk6Y54jzJ0fFfy1tb0Nokb+Clsi7n2 -l9GkLqq+CxnCRelwXQIDAJ3Zo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB -/wQEAwIBBjAdBgNVHQ4EFgQU587GT/wWZ5b6SqMHwQSny2re2kcwHwYDVR0jBBgw -FoAU587GT/wWZ5b6SqMHwQSny2re2kcwDQYJKoZIhvcNAQEFBQADggIBAJuYml2+ -8ygjdsZs93/mQJ7ANtyVDR2tFcU22NU57/IeIl6zgrRdu0waypIN30ckHrMk2pGI -6YNw3ZPX6bqz3xZaPt7gyPvT/Wwp+BVGoGgmzJNSroIBk5DKd8pNSe/iWtkqvTDO -TLKBtjDOWU/aWR1qeqRFsIImgYZ29fUQALjuswnoT4cCB64kXPBfrAowzIpAoHME -wfuJJPaaHFy3PApnNgUIMbOv2AFoKuB4j3TeuFGkjGwgPaL7s9QJ/XvCgKqTbCmY -Iai7FvOpEl90tYeY8pUm3zTvilORiF0alKM/fCL414i6poyWqD1SNGKfAB5UVUJn -xk1Gj7sURT0KlhaOEKGXmdXTMIXM3rRyt7yKPBgpaP3ccQfuJDlq+u2lrDgv+R4Q -DgZxGhBM/nV+/x5XOULK1+EVoVZVWRvRo68R2E7DpSvvkL/A7IITW43WciyTTo9q -Kd+FPNMN4KIYEsxVL0e3p5sC/kH2iExt2qkBR4NkJ2IQgtYSe14DHzSpyZH+r11t -hie3I6p1GMog57AP14kOpmciY/SDQSsGS7tY1dHXt7kQY9iJSrSq3RZj9W6+YKH4 -7ejWkE8axsWgKdOnIaj1Wjz3x0miIZpKlVIglnKaZsv30oZDfCK+lvm9AahH3eU7 -QPl1K5srRmSGjR70j/sHd9DqSaIcjVIUpgqT ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIICmDCCAgGgAwIBAgIBDjANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJVUzEY -MBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNFQ0ExFDASBgNVBAMT -C0VDQSBSb290IENBMB4XDTA0MDYxNDEwMjAwOVoXDTQwMDYxNDEwMjAwOVowSzEL -MAkGA1UEBhMCVVMxGDAWBgNVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMD -RUNBMRQwEgYDVQQDEwtFQ0EgUm9vdCBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw -gYkCgYEArkr2eXIS6oAKIpDkOlcQZdMGdncoygCEIU+ktqY3of5SVVXU7/it7kJ1 -EUzR4ii2vthQtbww9aAnpQxcEmXZk8eEyiGEPy+cCQMllBY+efOtKgjbQNDZ3lB9 -19qzUJwBl2BMxslU1XsJQw9SK10lPbQm4asa8E8e5zTUknZBWnECAwEAAaOBizCB -iDAfBgNVHSMEGDAWgBT2uAQnDlYW2blj2f2hVGVBoAhILzAdBgNVHQ4EFgQU9rgE -Jw5WFtm5Y9n9oVRlQaAISC8wDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMB -Af8wJQYDVR0gBB4wHDAMBgpghkgBZQMCAQwBMAwGCmCGSAFlAwIBDAIwDQYJKoZI -hvcNAQEFBQADgYEAHh0EQY2cZ209aBb5q0wW1ER0dc4OGzsLyqjHfaQ4TEaMmUwL -AJRta/c4KVWLiwbODsvgJk+CaWmSL03gRW/ciVb/qDV7qh9Pyd1cOlanZTAnPog2 -i82yL3i2fK9DCC84uoxEQbgqK2jx9bIjFTwlAqITk9fGAm5mdT84IEwq1Gw= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMC -VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0 -Lm5ldC9DUFMgaXMgaW5jb3Jwb3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMW -KGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsGA1UEAxMkRW50cnVzdCBSb290IENl -cnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0MloXDTI2MTEyNzIw -NTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMTkw -NwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSBy -ZWZlcmVuY2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNV -BAMTJEVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJ -KoZIhvcNAQEBBQADggEPADCCAQoCggEBALaVtkNC+sZtKm9I35RMOVcF7sN5EUFo -Nu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYszA9u3g3s+IIRe7bJWKKf4 -4LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOwwCj0Yzfv9 -KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGI -rb68j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi -94DkZfs0Nw4pgHBNrziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOB -sDCBrTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAi -gA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1MzQyWjAfBgNVHSMEGDAWgBRo -kORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DHhmak8fdLQ/uE -vW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA -A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9t -O1KzKtvn1ISMY/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6Zua -AGAT/3B+XxFNSRuzFVJ7yVTav52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP -9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTSW3iDVuycNsMm4hH2Z0kdkquM++v/ -eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0tHuu2guQOHXvgR1m -0vdXcDazv/wor3ElhVsT/h5/WrQ8 ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEXDCCA0SgAwIBAgIEOGO5ZjANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChML -RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBp -bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5 -IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENlcnRp -ZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQxNzUwNTFaFw0xOTEy -MjQxODIwNTFaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3 -LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxp -YWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEG -A1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQq -K0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQe -sYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuX -MlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVT -XTzWnLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/ -HoZdenoVve8AjhUiVBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH -4QIDAQABo3QwcjARBglghkgBhvhCAQEEBAMCAAcwHwYDVR0jBBgwFoAUVeSB0RGA -vtiJuQijMfmhJAkWuXAwHQYDVR0OBBYEFFXkgdERgL7YibkIozH5oSQJFrlwMB0G -CSqGSIb2fQdBAAQQMA4bCFY1LjA6NC4wAwIEkDANBgkqhkiG9w0BAQUFAAOCAQEA -WUesIYSKF8mciVMeuoCFGsY8Tj6xnLZ8xpJdGGQC49MGCBFhfGPjK50xA3B20qMo -oPS7mmNz7W3lKtvtFKkrxjYR0CvrB4ul2p5cGZ1WEvVUKcgF7bISKo30Axv/55IQ -h7A6tcOdBTcSo8f0FbnVpDkWm1M6I5HxqIKiaohowXkCIryqptau37AUX7iH0N18 -f3v/rxzP5tsHrV7bhZ3QKw0z2wTR5klAEyt2+z7pnIkPFc4YsIV4IU9rTw76NmfN -B/L/CNDi3tm/Kq+4h4YhPATKt5Rof8886ZjXOP/swNlQ8C5LWK5Gb9Auw2DaclVy -vUxFnmG6v4SBkgPR0ml8xQ== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIE7TCCBFagAwIBAgIEOAOR7jANBgkqhkiG9w0BAQQFADCByTELMAkGA1UEBhMC -VVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MUgwRgYDVQQLFD93d3cuZW50cnVzdC5u -ZXQvQ2xpZW50X0NBX0luZm8vQ1BTIGluY29ycC4gYnkgcmVmLiBsaW1pdHMgbGlh -Yi4xJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNV -BAMTKkVudHJ1c3QubmV0IENsaWVudCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe -Fw05OTEwMTIxOTI0MzBaFw0xOTEwMTIxOTU0MzBaMIHJMQswCQYDVQQGEwJVUzEU -MBIGA1UEChMLRW50cnVzdC5uZXQxSDBGBgNVBAsUP3d3dy5lbnRydXN0Lm5ldC9D -bGllbnRfQ0FfSW5mby9DUFMgaW5jb3JwLiBieSByZWYuIGxpbWl0cyBsaWFiLjEl -MCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMq -RW50cnVzdC5uZXQgQ2xpZW50IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGdMA0G -CSqGSIb3DQEBAQUAA4GLADCBhwKBgQDIOpleMRffrCdvkHvkGf9FozTC28GoT/Bo -6oT9n3V5z8GKUZSvx1cDR2SerYIbWtp/N3hHuzeYEpbOxhN979IMMFGpOZ5V+Pux -5zDeg7K6PvHViTs7hbqqdCz+PzFur5GVbgbUB01LLFZHGARS2g4Qk79jkJvh34zm -AqTmT173iwIBA6OCAeAwggHcMBEGCWCGSAGG+EIBAQQEAwIABzCCASIGA1UdHwSC -ARkwggEVMIHkoIHhoIHepIHbMIHYMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRW50 -cnVzdC5uZXQxSDBGBgNVBAsUP3d3dy5lbnRydXN0Lm5ldC9DbGllbnRfQ0FfSW5m -by9DUFMgaW5jb3JwLiBieSByZWYuIGxpbWl0cyBsaWFiLjElMCMGA1UECxMcKGMp -IDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5uZXQg -Q2xpZW50IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMCyg -KqAohiZodHRwOi8vd3d3LmVudHJ1c3QubmV0L0NSTC9DbGllbnQxLmNybDArBgNV -HRAEJDAigA8xOTk5MTAxMjE5MjQzMFqBDzIwMTkxMDEyMTkyNDMwWjALBgNVHQ8E -BAMCAQYwHwYDVR0jBBgwFoAUxPucKXuXzUyW/O5bs8qZdIuV6kwwHQYDVR0OBBYE -FMT7nCl7l81MlvzuW7PKmXSLlepMMAwGA1UdEwQFMAMBAf8wGQYJKoZIhvZ9B0EA -BAwwChsEVjQuMAMCBJAwDQYJKoZIhvcNAQEEBQADgYEAP66K8ddmAwWePvrqHEa7 -pFuPeJoSSJn59DXeDDYHAmsQOokUgZwxpnyyQbJq5wcBoUv5nyU7lsqZwz6hURzz -wy5E97BnRqqS5TvaHBkUODDV4qIxJS7x7EU47fgGWANzYrAQMY9Av2TgXD7FTx/a -EkP/TOYGJqibGapEPHayXOw= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEgzCCA+ygAwIBAgIEOJ725DANBgkqhkiG9w0BAQQFADCBtDEUMBIGA1UEChML -RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9HQ0NBX0NQUyBp -bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAyMDAw -IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENsaWVu -dCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMDAyMDcxNjE2NDBaFw0yMDAy -MDcxNjQ2NDBaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3 -LmVudHJ1c3QubmV0L0dDQ0FfQ1BTIGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxp -YWIuKTElMCMGA1UECxMcKGMpIDIwMDAgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEG -A1UEAxMqRW50cnVzdC5uZXQgQ2xpZW50IENlcnRpZmljYXRpb24gQXV0aG9yaXR5 -MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCTdLS25MVL1qFof2LV7PdRV7Ny -Spj10InJrWPNTTVRaoTUrcloeW+46xHbh65cJFET8VQlhK8pK5/jgOLZy93GRUk0 -iJBeAZfv6lOm3fzB3ksqJeTpNfpVBQbliXrqpBFXO/x8PTbNZzVtpKklWb1m9fkn -5JVn1j+SgF7yNH0rhQIDAQABo4IBnjCCAZowEQYJYIZIAYb4QgEBBAQDAgAHMIHd -BgNVHR8EgdUwgdIwgc+ggcyggcmkgcYwgcMxFDASBgNVBAoTC0VudHJ1c3QubmV0 -MUAwPgYDVQQLFDd3d3cuZW50cnVzdC5uZXQvR0NDQV9DUFMgaW5jb3JwLiBieSBy -ZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMjAwMCBFbnRydXN0Lm5l -dCBMaW1pdGVkMTMwMQYDVQQDEypFbnRydXN0Lm5ldCBDbGllbnQgQ2VydGlmaWNh -dGlvbiBBdXRob3JpdHkxDTALBgNVBAMTBENSTDEwKwYDVR0QBCQwIoAPMjAwMDAy -MDcxNjE2NDBagQ8yMDIwMDIwNzE2NDY0MFowCwYDVR0PBAQDAgEGMB8GA1UdIwQY -MBaAFISLdP3FjcD/J20gN0V8/i3OutN9MB0GA1UdDgQWBBSEi3T9xY3A/ydtIDdF -fP4tzrrTfTAMBgNVHRMEBTADAQH/MB0GCSqGSIb2fQdBAAQQMA4bCFY1LjA6NC4w -AwIEkDANBgkqhkiG9w0BAQQFAAOBgQBObzWAO9GK9Q6nIMstZVXQkvTnhLUGJoMS -hAusO7JE7r3PQNsgDrpuFOow4DtifH+La3xKp9U1PL6oXOpLu5OOgGarDyn9TS2/ -GpsKkMWr2tGzhtQvJFJcem3G8v7lTRowjJDyutdKPkN+1MhQGof4T4HHdguEOnKd -zmVml64mXg== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIElTCCA/6gAwIBAgIEOJsRPDANBgkqhkiG9w0BAQQFADCBujEUMBIGA1UEChML -RW50cnVzdC5uZXQxPzA9BgNVBAsUNnd3dy5lbnRydXN0Lm5ldC9TU0xfQ1BTIGlu -Y29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMcKGMpIDIwMDAg -RW50cnVzdC5uZXQgTGltaXRlZDE6MDgGA1UEAxMxRW50cnVzdC5uZXQgU2VjdXJl -IFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMDAyMDQxNzIwMDBa -Fw0yMDAyMDQxNzUwMDBaMIG6MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDE/MD0GA1UE -CxQ2d3d3LmVudHJ1c3QubmV0L1NTTF9DUFMgaW5jb3JwLiBieSByZWYuIChsaW1p -dHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMjAwMCBFbnRydXN0Lm5ldCBMaW1pdGVk -MTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUgU2VydmVyIENlcnRpZmljYXRp -b24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDHwV9OcfHO -8GCGD9JYf9Mzly0XonUwtZZkJi9ow0SrqHXmAGc0V55lxyKbc+bT3QgON1WqJUaB -bL3+qPZ1V1eMkGxKwz6LS0MKyRFWmponIpnPVZ5h2QLifLZ8OAfc439PmrkDQYC2 -dWcTC5/oVzbIXQA23mYU2m52H083jIITiQIDAQABo4IBpDCCAaAwEQYJYIZIAYb4 -QgEBBAQDAgAHMIHjBgNVHR8EgdswgdgwgdWggdKggc+kgcwwgckxFDASBgNVBAoT -C0VudHJ1c3QubmV0MT8wPQYDVQQLFDZ3d3cuZW50cnVzdC5uZXQvU1NMX0NQUyBp -bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAyMDAw -IEVudHJ1c3QubmV0IExpbWl0ZWQxOjA4BgNVBAMTMUVudHJ1c3QubmV0IFNlY3Vy -ZSBTZXJ2ZXIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxDTALBgNVBAMTBENSTDEw -KwYDVR0QBCQwIoAPMjAwMDAyMDQxNzIwMDBagQ8yMDIwMDIwNDE3NTAwMFowCwYD -VR0PBAQDAgEGMB8GA1UdIwQYMBaAFMtswGvjuz7L/CKc/vuLkpyw8m4iMB0GA1Ud -DgQWBBTLbMBr47s+y/winP77i5KcsPJuIjAMBgNVHRMEBTADAQH/MB0GCSqGSIb2 -fQdBAAQQMA4bCFY1LjA6NC4wAwIEkDANBgkqhkiG9w0BAQQFAAOBgQBi24GRzsia -d0Iv7L0no1MPUBvqTpLwqa+poLpIYcvvyQbvH9X07t9WLebKahlzqlO+krNQAraF -JnJj2HVQYnUUt7NQGj/KEQALhUVpbbalrlHhStyCP2yMNLJ3a9kC9n8O6mUE8c1U -yrrJzOCE98g+EZfTYAkYvAX/bIkz8OwVDw== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIE2DCCBEGgAwIBAgIEN0rSQzANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMC -VVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5u -ZXQvQ1BTIGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMc -KGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDE6MDgGA1UEAxMxRW50cnVzdC5u -ZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw05OTA1 -MjUxNjA5NDBaFw0xOTA1MjUxNjM5NDBaMIHDMQswCQYDVQQGEwJVUzEUMBIGA1UE -ChMLRW50cnVzdC5uZXQxOzA5BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5j -b3JwLiBieSByZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBF -bnRydXN0Lm5ldCBMaW1pdGVkMTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUg -U2VydmVyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGdMA0GCSqGSIb3DQEBAQUA -A4GLADCBhwKBgQDNKIM0VBuJ8w+vN5Ex/68xYMmo6LIQaO2f55M28Qpku0f1BBc/ -I0dNxScZgSYMVHINiC3ZH5oSn7yzcdOAGT9HZnuMNSjSuQrfJNqc1lB5gXpa0zf3 -wkrYKZImZNHkmGw6AIr1NJtl+O3jEP/9uElY3KDegjlrgbEWGWG5VLbmQwIBA6OC -AdcwggHTMBEGCWCGSAGG+EIBAQQEAwIABzCCARkGA1UdHwSCARAwggEMMIHeoIHb -oIHYpIHVMIHSMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRW50cnVzdC5uZXQxOzA5 -BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5jb3JwLiBieSByZWYuIChsaW1p -dHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBFbnRydXN0Lm5ldCBMaW1pdGVk -MTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUgU2VydmVyIENlcnRpZmljYXRp -b24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMCmgJ6AlhiNodHRwOi8vd3d3LmVu -dHJ1c3QubmV0L0NSTC9uZXQxLmNybDArBgNVHRAEJDAigA8xOTk5MDUyNTE2MDk0 -MFqBDzIwMTkwNTI1MTYwOTQwWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAU8Bdi -E1U9s/8KAGv7UISX8+1i0BowHQYDVR0OBBYEFPAXYhNVPbP/CgBr+1CEl/PtYtAa -MAwGA1UdEwQFMAMBAf8wGQYJKoZIhvZ9B0EABAwwChsEVjQuMAMCBJAwDQYJKoZI -hvcNAQEFBQADgYEAkNwwAvpkdMKnCqV8IY00F6j7Rw7/JXyNEwr75Ji174z4xRAN -95K+8cPV1ZVqBLssziY2ZcgxxufuP+NXdYR6Ee9GTxj005i7qIcyunL2POI9n9cd -2cNgQ4xYDiKWL2KjLB+6rQXvqzJ4h6BUcxm1XAX5Uj5tLUUL9wqT6u0G+bI= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV -UzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2Vy -dGlmaWNhdGUgQXV0aG9yaXR5MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1 -MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0VxdWlmYXgxLTArBgNVBAsTJEVx -dWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCBnzANBgkqhkiG9w0B -AQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPRfM6f -BeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+A -cJkVV5MW8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kC -AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQ -MA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlm -aWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTgw -ODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvSspXXR9gj -IBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQF -MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA -A4GBAFjOKer89961zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y -7qj/WsjTVbJmcVfewCHrPSqnI0kBBIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh -1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee9570+sB3c4 ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIICgjCCAeugAwIBAgIBBDANBgkqhkiG9w0BAQQFADBTMQswCQYDVQQGEwJVUzEc -MBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5jLjEmMCQGA1UEAxMdRXF1aWZheCBT -ZWN1cmUgZUJ1c2luZXNzIENBLTEwHhcNOTkwNjIxMDQwMDAwWhcNMjAwNjIxMDQw -MDAwWjBTMQswCQYDVQQGEwJVUzEcMBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5j -LjEmMCQGA1UEAxMdRXF1aWZheCBTZWN1cmUgZUJ1c2luZXNzIENBLTEwgZ8wDQYJ -KoZIhvcNAQEBBQADgY0AMIGJAoGBAM4vGbwXt3fek6lfWg0XTzQaDJj0ItlZ1MRo -RvC0NcWFAyDGr0WlIVFFQesWWDYyb+JQYmT5/VGcqiTZ9J2DKocKIdMSODRsjQBu -WqDZQu4aIZX5UkxVWsUPOE9G+m34LjXWHXzr4vCwdYDIqROsvojvOm6rXyo4YgKw -Env+j6YDAgMBAAGjZjBkMBEGCWCGSAGG+EIBAQQEAwIABzAPBgNVHRMBAf8EBTAD -AQH/MB8GA1UdIwQYMBaAFEp4MlIR21kWNl7fwRQ2QGpHfEyhMB0GA1UdDgQWBBRK -eDJSEdtZFjZe38EUNkBqR3xMoTANBgkqhkiG9w0BAQQFAAOBgQB1W6ibAxHm6VZM -zfmpTMANmvPMZWnmJXbMWbfWVMMdzZmsGd20hdXgPfxiIKeES1hl8eL5lSE/9dR+ -WB5Hh1Q+WKG1tfgq73HnvMP2sUlG4tega+VWeponmHxGYhTnyfxuAxJ5gDgdSIKN -/Bf+KpYrtWKmpj29f5JZzVoqgrI3eQ== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDIDCCAomgAwIBAgIEN3DPtTANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV -UzEXMBUGA1UEChMORXF1aWZheCBTZWN1cmUxJjAkBgNVBAsTHUVxdWlmYXggU2Vj -dXJlIGVCdXNpbmVzcyBDQS0yMB4XDTk5MDYyMzEyMTQ0NVoXDTE5MDYyMzEyMTQ0 -NVowTjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkVxdWlmYXggU2VjdXJlMSYwJAYD -VQQLEx1FcXVpZmF4IFNlY3VyZSBlQnVzaW5lc3MgQ0EtMjCBnzANBgkqhkiG9w0B -AQEFAAOBjQAwgYkCgYEA5Dk5kx5SBhsoNviyoynF7Y6yEb3+6+e0dMKP/wXn2Z0G -vxLIPw7y1tEkshHe0XMJitSxLJgJDR5QRrKDpkWNYmi7hRsgcDKqQM2mll/EcTc/ -BPO3QSQ5BxoeLmFYoBIL5aXfxavqN3HMHMg3OrmXUqesxWoklE6ce8/AatbfIb0C -AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEX -MBUGA1UEChMORXF1aWZheCBTZWN1cmUxJjAkBgNVBAsTHUVxdWlmYXggU2VjdXJl -IGVCdXNpbmVzcyBDQS0yMQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTkw -NjIzMTIxNDQ1WjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUUJ4L6q9euSBIplBq -y/3YIHqngnYwHQYDVR0OBBYEFFCeC+qvXrkgSKZQasv92CB6p4J2MAwGA1UdEwQF -MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA -A4GBAAyGgq3oThr1jokn4jVYPSm0B482UJW/bsGe68SQsoWou7dC4A8HOd/7npCy -0cE+U58DRLB+S/Rv5Hwf5+Kx5Lia78O9zt4LMjTZ3ijtM2vE1Nc9ElirfQkty3D1 -E4qUoSek1nDFbZS1yX2doNLGCEnZZpum0/QL3MUmV+GRMOrN ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIICkDCCAfmgAwIBAgIBATANBgkqhkiG9w0BAQQFADBaMQswCQYDVQQGEwJVUzEc -MBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5jLjEtMCsGA1UEAxMkRXF1aWZheCBT -ZWN1cmUgR2xvYmFsIGVCdXNpbmVzcyBDQS0xMB4XDTk5MDYyMTA0MDAwMFoXDTIw -MDYyMTA0MDAwMFowWjELMAkGA1UEBhMCVVMxHDAaBgNVBAoTE0VxdWlmYXggU2Vj -dXJlIEluYy4xLTArBgNVBAMTJEVxdWlmYXggU2VjdXJlIEdsb2JhbCBlQnVzaW5l -c3MgQ0EtMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAuucXkAJlsTRVPEnC -UdXfp9E3j9HngXNBUmCbnaEXJnitx7HoJpQytd4zjTov2/KaelpzmKNc6fuKcxtc -58O/gGzNqfTWK8D3+ZmqY6KxRwIP1ORROhI8bIpaVIRw28HFkM9yRcuoWcDNM50/ -o5brhTMhHD4ePmBudpxnhcXIw2ECAwEAAaNmMGQwEQYJYIZIAYb4QgEBBAQDAgAH -MA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUvqigdHJQa0S3ySPY+6j/s1dr -aGwwHQYDVR0OBBYEFL6ooHRyUGtEt8kj2Puo/7NXa2hsMA0GCSqGSIb3DQEBBAUA -A4GBADDiAVGqx+pf2rnQZQ8w1j7aDRRJbpGTJxQx78T3LUX47Me/okENI7SS+RkA -Z70Br83gcfxaz2TE4JaY0KNA4gGK7ycH8WUBikQtBmV1UsCGECAhX2xrD2yuCRyv -8qIYNMR1pHMc8Y3c7635s3a0kr/clRAevsvIO1qEYBlWlKlV ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIFFjCCBH+gAwIBAgIBADANBgkqhkiG9w0BAQQFADCBsDELMAkGA1UEBhMCSUwx -DzANBgNVBAgTBklzcmFlbDEOMAwGA1UEBxMFRWlsYXQxFjAUBgNVBAoTDVN0YXJ0 -Q29tIEx0ZC4xGjAYBgNVBAsTEUNBIEF1dGhvcml0eSBEZXAuMSkwJwYDVQQDEyBG -cmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEhMB8GCSqGSIb3DQEJARYS -YWRtaW5Ac3RhcnRjb20ub3JnMB4XDTA1MDMxNzE3Mzc0OFoXDTM1MDMxMDE3Mzc0 -OFowgbAxCzAJBgNVBAYTAklMMQ8wDQYDVQQIEwZJc3JhZWwxDjAMBgNVBAcTBUVp -bGF0MRYwFAYDVQQKEw1TdGFydENvbSBMdGQuMRowGAYDVQQLExFDQSBBdXRob3Jp -dHkgRGVwLjEpMCcGA1UEAxMgRnJlZSBTU0wgQ2VydGlmaWNhdGlvbiBBdXRob3Jp -dHkxITAfBgkqhkiG9w0BCQEWEmFkbWluQHN0YXJ0Y29tLm9yZzCBnzANBgkqhkiG -9w0BAQEFAAOBjQAwgYkCgYEA7YRgACOeyEpRKSfeOqE5tWmrCbIvNP1h3D3TsM+x -18LEwrHkllbEvqoUDufMOlDIOmKdw6OsWXuO7lUaHEe+o5c5s7XvIywI6Nivcy+5 -yYPo7QAPyHWlLzRMGOh2iCNJitu27Wjaw7ViKUylS7eYtAkUEKD4/mJ2IhULpNYI -LzUCAwEAAaOCAjwwggI4MA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgHmMB0G -A1UdDgQWBBQcicOWzL3+MtUNjIExtpidjShkjTCB3QYDVR0jBIHVMIHSgBQcicOW -zL3+MtUNjIExtpidjShkjaGBtqSBszCBsDELMAkGA1UEBhMCSUwxDzANBgNVBAgT -BklzcmFlbDEOMAwGA1UEBxMFRWlsYXQxFjAUBgNVBAoTDVN0YXJ0Q29tIEx0ZC4x -GjAYBgNVBAsTEUNBIEF1dGhvcml0eSBEZXAuMSkwJwYDVQQDEyBGcmVlIFNTTCBD -ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEhMB8GCSqGSIb3DQEJARYSYWRtaW5Ac3Rh -cnRjb20ub3JnggEAMB0GA1UdEQQWMBSBEmFkbWluQHN0YXJ0Y29tLm9yZzAdBgNV -HRIEFjAUgRJhZG1pbkBzdGFydGNvbS5vcmcwEQYJYIZIAYb4QgEBBAQDAgAHMC8G -CWCGSAGG+EIBDQQiFiBGcmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAy -BglghkgBhvhCAQQEJRYjaHR0cDovL2NlcnQuc3RhcnRjb20ub3JnL2NhLWNybC5j -cmwwKAYJYIZIAYb4QgECBBsWGWh0dHA6Ly9jZXJ0LnN0YXJ0Y29tLm9yZy8wOQYJ -YIZIAYb4QgEIBCwWKmh0dHA6Ly9jZXJ0LnN0YXJ0Y29tLm9yZy9pbmRleC5waHA/ -YXBwPTExMTANBgkqhkiG9w0BAQQFAAOBgQBscSXhnjSRIe/bbL0BCFaPiNhBOlP1 -ct8nV0t2hPdopP7rPwl+KLhX6h/BquL/lp9JmeaylXOWxkjHXo0Hclb4g4+fd68p -00UOpO6wNnQt8M2YI3s3S9r+UZjEHjQ8iP2ZO1CnwYszx8JSFhKVU2Ui77qLzmLb -cCOxgN8aIDjnfg== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT -MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i -YWwgQ0EwHhcNMDIwNTIxMDQwMDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQG -EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMSR2VvVHJ1c3Qg -R2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2swYYzD9 -9BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjoBbdq -fnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDv -iS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU -1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+ -bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5aszPeE4uwc2hGKceeoW -MPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTA -ephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVkDBF9qn1l -uMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKIn -Z57QzxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfS -tQWVYrmm3ok9Nns4d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcF -PseKUgzbFbS9bZvlxrFUaKnjaZC2mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Un -hw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6pXE0zX5IJL4hmXXeXxx12E6nV -5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvmMw== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDfDCCAmSgAwIBAgIQGKy1av1pthU6Y2yv2vrEoTANBgkqhkiG9w0BAQUFADBY -MQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjExMC8GA1UEAxMo -R2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEx -MjcwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMFgxCzAJBgNVBAYTAlVTMRYwFAYDVQQK -Ew1HZW9UcnVzdCBJbmMuMTEwLwYDVQQDEyhHZW9UcnVzdCBQcmltYXJ5IENlcnRp -ZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC -AQEAvrgVe//UfH1nrYNke8hCUy3f9oQIIGHWAVlqnEQRr+92/ZV+zmEwu3qDXwK9 -AWbK7hWNb6EwnL2hhZ6UOvNWiAAxz9juapYC2e0DjPt1befquFUWBRaa9OBesYjA -ZIVcFU2Ix7e64HXprQU9nceJSOC7KMgD4TCTZF5SwFlwIjVXiIrxlQqD17wxcwE0 -7e9GceBrAqg1cmuXm2bgyxx5X9gaBGgeRwLmnWDiNpcB3841kt++Z8dtd1k7j53W -kBWUvEI0EME5+bEnPn7WinXFsq+W06Lem+SYvn3h6YGttm/81w7a4DSwDRp35+MI -mO9Y+pyEtzavwt+s0vQQBnBxNQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4G -A1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQULNVQQZcVi/CPNmFbSvtr2ZnJM5IwDQYJ -KoZIhvcNAQEFBQADggEBAFpwfyzdtzRP9YZRqSa+S7iq8XEN3GHHoOo0Hnp3DwQ1 -6CePbJC/kRYkRj5KTs4rFtULUh38H2eiAkUxT87z+gOneZ1TatnaYzr4gNfTmeGl -4b7UVXGYNTq+k+qurUKykG/g/CFNNWMziUnWm07Kx+dOCQD32sfvmWKZd7aVIl6K -oKv0uHiYyjgZmclynnjNS6yvGaBzEi38wkG6gZHaFloxt/m0cYASSJlyc1pZU8Fj -UjPtp8nSOQJw+uCxQmYpqptR7TBUIhRf2asdweSU8Pj1K/fqynhG1riR/aYNKxoU -AT6A8EKglQdebc3MS6RFjasS6LPeWuWgfOgPIh1a6Vk= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDIzCCAgugAwIBAgIQMDAwMTAwMDQ0ODczMzAwMDANBgkqhkiG9w0BAQUFADAf -MQswCQYDVQQGEwJGUjEQMA4GA1UEChMHR0lQLUNQUzAeFw0wMTA2MjYwMDAwMDBa -Fw0xMDEyMzEwMDAwMDBaMB8xCzAJBgNVBAYTAkZSMRAwDgYDVQQKEwdHSVAtQ1BT -MIIBITANBgkqhkiG9w0BAQEFAAOCAQ4AMIIBCQKCAQBvz+ogB2ovWM18JmOtizrL -Y2KgEZ8TpU6H7zu+r6cT1Q8xgLm8BPOfeW3eI/e0PLmZN+Sp+LZ4wyFMecJmp/FT -M9/9Gp23vpMePge/tJctwu0mihabVcUHFoIMtpKgSJ2+Xlywk16AjsHN3DONcWBa -xV4wa4Tt/BtaEkf9148pDn074lZZ2mKmANu9zNDm/buSgRkqqS1eVCbLxkRaMBSp -dwGAjsBYEqPjmI4So915ab3Eqqz5zawQwC4T+O41wRgpD9bDTo+9xAFiZz8PqYs9 -pc2tHOKhIlRxJbQqcWQW+St9I7Y+rRx2lTMrt6DD7CMoxrt1TuGzxdN777w1GSfx -AgMBAAGjXDBaMA4GA1UdDwEB/wQEAwICBDASBgNVHRMBAf8ECDAGAQH/AgEBMB0G -A1UdDgQWBBTnqP2NPQkWlq78dWMnkCN5XlvZtDAVBgNVHSAEDjAMMAoGCCqBegFH -AwcDMA0GCSqGSIb3DQEBBQUAA4IBAQAc9sFFWGgFJ14VGI91Cf1h9KYuuh1m2y2u -xF/mVb58IYBDE0fwG371XwpOHd6d9cM3ANSpK51V5EOmwgFDGkNGtDYcPXR+Ndli -rhD8aSq0Yv2p3h78o5O6y4GMRycFPsTfWpE9h7fGmsfZXWnYJGRAGM2iKYn7x3f7 -+kOrtbVj+XAvws7PqO2lLh/HjWCek4efnU9EaG6SDqu7srTuhyILFRBJ+sfOr68t -5bwyjufk391dbPBYcQ1AK9CQrnaorhPo+S7iNekX1e5iJShETVrZJkH/AAido34c -3ohHWmmZPyNW+5CpxZlRL6J6mlcAxIDqkXXsxj/r5zxGrW/jGwxo ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIExTCCA62gAwIBAgIBADANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJFVTEn -MCUGA1UEChMeQUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQL -ExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEgMB4GA1UEAxMXR2xvYmFsIENo -YW1iZXJzaWduIFJvb3QwHhcNMDMwOTMwMTYxNDE4WhcNMzcwOTMwMTYxNDE4WjB9 -MQswCQYDVQQGEwJFVTEnMCUGA1UEChMeQUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgy -NzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEgMB4G -A1UEAxMXR2xvYmFsIENoYW1iZXJzaWduIFJvb3QwggEgMA0GCSqGSIb3DQEBAQUA -A4IBDQAwggEIAoIBAQCicKLQn0KuWxfH2H3PFIP8T8mhtxOviteePgQKkotgVvq0 -Mi+ITaFgCPS3CU6gSS9J1tPfnZdan5QEcOw/Wdm3zGaLmFIoCQLfxS+EjXqXd7/s -QJ0lcqu1PzKY+7e3/HKE5TWH+VX6ox8Oby4o3Wmg2UIQxvi1RMLQQ3/bvOSiPGpV -eAp3qdjqGTK3L/5cPxvusZjsyq16aUXjlg9V9ubtdepl6DJWk0aJqCWKZQbua795 -B9Dxt6/tLE2Su8CoX6dnfQTyFQhwrJLWfQTSM/tMtgsL+xrJxI0DqX5c8lCrEqWh -z0hQpe/SyBoT+rB/sYIcd2oPX9wLlY/vQ37mRQklAgEDo4IBUDCCAUwwEgYDVR0T -AQH/BAgwBgEB/wIBDDA/BgNVHR8EODA2MDSgMqAwhi5odHRwOi8vY3JsLmNoYW1i -ZXJzaWduLm9yZy9jaGFtYmVyc2lnbnJvb3QuY3JsMB0GA1UdDgQWBBRDnDafsJ4w -TcbOX60Qq+UDpfqpFDAOBgNVHQ8BAf8EBAMCAQYwEQYJYIZIAYb4QgEBBAQDAgAH -MCoGA1UdEQQjMCGBH2NoYW1iZXJzaWducm9vdEBjaGFtYmVyc2lnbi5vcmcwKgYD -VR0SBCMwIYEfY2hhbWJlcnNpZ25yb290QGNoYW1iZXJzaWduLm9yZzBbBgNVHSAE -VDBSMFAGCysGAQQBgYcuCgEBMEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly9jcHMuY2hh -bWJlcnNpZ24ub3JnL2Nwcy9jaGFtYmVyc2lnbnJvb3QuaHRtbDANBgkqhkiG9w0B -AQUFAAOCAQEAPDtwkfkEVCeR4e3t/mh/YV3lQWVPMvEYBZRqHN4fcNs+ezICNLUM -bKGKfKX0j//U2K0X1S0E0T9YgOKBWYi+wONGkyT+kL0mojAt6JcmVzWJdJYY9hXi -ryQZVgICsroPFOrGimbBhkVVi76SvpykBMdJPJ7oKXqJ1/6v/2j1pReQvayZzKWG -VwlnRtvWFsJG8eSpUPWP0ZIV018+xgBJOm5YstHRJw0lyDL4IBHNfTIzSJRUTN3c -ecQwn+uOuFW114hcxWokPbLTBQNRxgfvzBRydD1ucs4YKIxKoHflCStFREest2d/ -AYoFWpO+ocH/+OcOZ6RHSXZddZAa9SaP8A== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4G -A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNp -Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1 -MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEG -A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6ErPL -v4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8 -eoLrvozps6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklq -tTleiDTsvHgMCJiEbKjNS7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzd -C9XZzPnqJworc5HGnRusyMvo4KD0L5CLTfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pa -zq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6CygPCm48CAwEAAaOBnDCB -mTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUm+IH -V2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5n -bG9iYWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG -3lm0mi3f3BmGLjANBgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4Gs -J0/WwbgcQ3izDJr86iw8bmEbTUsp9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO -291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu01yiPqFbQfXf5WRDLenVOavS -ot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG79G+dwfCMNYxd -AfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7 -TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDdTCCAl2gAwIBAgILAgAAAAAA1ni3lAUwDQYJKoZIhvcNAQEEBQAwVzELMAkG -A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv -b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw -MDBaFw0xNDAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i -YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT -aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ -jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp -xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp -1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG -snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ -U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8 -9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIABjAdBgNVHQ4EFgQU -YHtmGkUNl8qJUC99BM00qP/8/UswDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0B -AQQFAAOCAQEArqqf/LfSyx9fOSkoGJ40yWxPbxrwZKJwSk8ThptgKJ7ogUmYfQq7 -5bCdPTbbjwVR/wkxKh/diXeeDy5slQTthsu0AD+EAk2AaioteAuubyuig0SDH81Q -gkwkr733pbTIWg/050deSY43lv6aiAU62cDbKYfmGZZHpzqmjIs8d/5GY6dT2iHR -rH5Jokvmw2dZL7OKDrssvamqQnw1wdh/1acxOk5jQzmvCLBhNIzTmKlDNPYPhyk7 -ncJWWJh3w/cbrPad+D6qp1RF8PX51TFl/mtYnHGzHtdS6jIX/EBgHcl5JLL2bP2o -Zg6C3ZjL2sJETy6ge/L3ayx2EYRGinij4w== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh -MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE -YWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3 -MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRo -ZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3Mg -MiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggEN -ADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCA -PVYYYwhv2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6w -wdhFJ2+qN1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXi -EqITLdiOr18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMY -avx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+ -YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0OBBYEFNLE -sNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h -/t2oatTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5 -IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmlj -YXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD -ggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wimPQoZ+YeAEW5p5JYXMP80kWNy -OO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKtI3lpjbi2Tc7P -TMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ -HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mER -dEr/VxqHD3VILs9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5Cuf -ReYNnyicsbkqWletNw+vHX/bvZ8= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIICWjCCAcMCAgGlMA0GCSqGSIb3DQEBBAUAMHUxCzAJBgNVBAYTAlVTMRgwFgYD -VQQKEw9HVEUgQ29ycG9yYXRpb24xJzAlBgNVBAsTHkdURSBDeWJlclRydXN0IFNv -bHV0aW9ucywgSW5jLjEjMCEGA1UEAxMaR1RFIEN5YmVyVHJ1c3QgR2xvYmFsIFJv -b3QwHhcNOTgwODEzMDAyOTAwWhcNMTgwODEzMjM1OTAwWjB1MQswCQYDVQQGEwJV -UzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQLEx5HVEUgQ3liZXJU -cnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMTGkdURSBDeWJlclRydXN0IEds -b2JhbCBSb290MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVD6C28FCc6HrH -iM3dFw4usJTQGz0O9pTAipTHBsiQl8i4ZBp6fmw8U+E3KHNgf7KXUwefU/ltWJTS -r41tiGeA5u2ylc9yMcqlHHK6XALnZELn+aks1joNrI1CqiQBOeacPwGFVw1Yh0X4 -04Wqk2kmhXBIgD8SFcd5tB8FLztimQIDAQABMA0GCSqGSIb3DQEBBAUAA4GBAG3r -GwnpXtlR22ciYaQqPEh346B8pt5zohQDhT37qw4wxYMWM4ETCJ57NE7fQMh017l9 -3PR2VX2bY1QY6fDq81yx2YtCHrnAlU66+tXifPVoYb+O7AWXX1uw16OFNMQkpw0P -lZPvy5TYnh+dXIVtx6quTx8itc2VrbqnzPmrC3p/ ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIB+jCCAWMCAgGjMA0GCSqGSIb3DQEBBAUAMEUxCzAJBgNVBAYTAlVTMRgwFgYD -VQQKEw9HVEUgQ29ycG9yYXRpb24xHDAaBgNVBAMTE0dURSBDeWJlclRydXN0IFJv -b3QwHhcNOTYwMjIzMjMwMTAwWhcNMDYwMjIzMjM1OTAwWjBFMQswCQYDVQQGEwJV -UzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMRwwGgYDVQQDExNHVEUgQ3liZXJU -cnVzdCBSb290MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC45k+625h8cXyv -RLfTD0bZZOWTwUKOx7pJjTUteueLveUFMVnGsS8KDPufpz+iCWaEVh43KRuH6X4M -ypqfpX/1FZSj1aJGgthoTNE3FQZor734sLPwKfWVWgkWYXcKIiXUT0Wqx73llt/5 -1KiOQswkwB6RJ0q1bQaAYznEol44AwIDAQABMA0GCSqGSIb3DQEBBAUAA4GBABKz -dcZfHeFhVYAA1IFLezEPI2PnPfMD+fQ2qLvZ46WXTeorKeDWanOB5sCJo9Px4KWl -IjeaY8JIILTbcuPI9tl8vrGvU9oUtCG41tWW4/5ODFlitppK+ULdjG+BqXH/9Apy -bW1EDp3zdHSo1TRJ6V6e6bR64eVaH4QwnNOfpSXY ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0 -IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz -BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDEgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y -aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG -9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNTIyMjM0OFoXDTE5MDYy -NTIyMjM0OFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y -azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs -YXNzIDEgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw -Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl -cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDYWYJ6ibiWuqYvaG9Y -LqdUHAZu9OqNSLwxlBfw8068srg1knaw0KWlAdcAAxIiGQj4/xEjm84H9b9pGib+ -TunRf50sQB1ZaG6m+FiwnRqP0z/x3BkGgagO4DrdyFNFCQbmD3DD+kCmDuJWBQ8Y -TfwggtFzVXSNdnKgHZ0dwN0/cQIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFBoPUn0 -LBwGlN+VYH+Wexf+T3GtZMjdd9LvWVXoP+iOBSoh8gfStadS/pyxtuJbdxdA6nLW -I8sogTLDAHkY7FkXicnGah5xyf23dKUlRWnFSKsZ4UWKJWsZ7uW7EvV/96aNUcPw -nXS3qT6gpf+2SQMT2iLM7XGCK5nPOrf1LXLI ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0 -IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz -BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y -aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG -9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAwMTk1NFoXDTE5MDYy -NjAwMTk1NFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y -azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs -YXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw -Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl -cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOOnHK5avIWZJV16vY -dA757tn2VUdZZUcOBVXc65g2PFxTXdMwzzjsvUGJ7SVCCSRrCl6zfN1SLUzm1NZ9 -WlmpZdRJEy0kTRxQb7XBhVQ7/nHk01xC+YDgkRoKWzk2Z/M/VXwbP7RfZHM047QS -v4dk+NoS/zcnwbNDu+97bi5p9wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBADt/UG9v -UJSZSWI4OB9L+KXIPqeCgfYrx+jFzug6EILLGACOTb2oWH+heQC1u+mNr0HZDzTu -IYEZoDJJKPTEjlbVUjP9UNV+mWwD5MlM/Mtsq2azSiGM5bUMMj4QssxsodyamEwC -W/POuZ6lcg5Ktz885hZo+L7tdEy8W9ViH0Pd ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0 -IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz -BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDMgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y -aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG -9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAwMjIzM1oXDTE5MDYy -NjAwMjIzM1owgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y -azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs -YXNzIDMgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw -Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl -cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDjmFGWHOjVsQaBalfD -cnWTq8+epvzzFlLWLU2fNUSoLgRNB0mKOCn1dzfnt6td3zZxFJmP3MKS8edgkpfs -2Ejcv8ECIMYkpChMMFp2bbFc893enhBxoYjHW5tBbcqwuI4V7q0zK89HBFx1cQqY -JJgpp0lZpd34t0NiYfPT4tBVPwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFa7AliE -Zwgs3x/be0kz9dNnnfS0ChCzycUs4pJqcXgn8nCDQtM+z6lU9PHYkhaM0QTLS6vJ -n0WuPIqpsHEzXcjFV9+vqDWzf4mH6eglkrh/hXqu1rweN1gqZ8mRzyqBPu3GOd/A -PhmcGcwTTYJBtYze4D1gCCAPRX5ron+jjBXu ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIH/zCCB2igAwIBAgIBADANBgkqhkiG9w0BAQUFADCCARwxCzAJBgNVBAYTAkVT -MRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQBgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UE -ChMlSVBTIEludGVybmV0IHB1Ymxpc2hpbmcgU2VydmljZXMgcy5sLjErMCkGA1UE -ChQiaXBzQG1haWwuaXBzLmVzIEMuSS5GLiAgQi02MDkyOTQ1MjEzMDEGA1UECxMq -SVBTIENBIENoYWluZWQgQ0FzIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MTMwMQYD -VQQDEypJUFMgQ0EgQ2hhaW5lZCBDQXMgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkx -HjAcBgkqhkiG9w0BCQEWD2lwc0BtYWlsLmlwcy5lczAeFw0wMTEyMzExMTE0NTRa -Fw0yNTEyMjkxMTE0NTRaMIIBHDELMAkGA1UEBhMCRVMxEjAQBgNVBAgTCUJhcmNl -bG9uYTESMBAGA1UEBxMJQmFyY2Vsb25hMS4wLAYDVQQKEyVJUFMgSW50ZXJuZXQg -cHVibGlzaGluZyBTZXJ2aWNlcyBzLmwuMSswKQYDVQQKFCJpcHNAbWFpbC5pcHMu -ZXMgQy5JLkYuICBCLTYwOTI5NDUyMTMwMQYDVQQLEypJUFMgQ0EgQ2hhaW5lZCBD -QXMgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxMzAxBgNVBAMTKklQUyBDQSBDaGFp -bmVkIENBcyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEeMBwGCSqGSIb3DQEJARYP -aXBzQG1haWwuaXBzLmVzMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCpOZZJ -iHAzKHzoV9xIki3eLXp56UjxFehnY+c+Dh1nUiVO0t//vmGMP6B2LTFfx9FBKRBi -kYcW7raIcSDi62Or0sAG5UUgG4ruGLE7XtCnnx4xjgbFZ4tTjdgi5Wh9GVhfP7Oo -9ahi8Eqao+alFbhvB6LD3xZZqM2j9cmD8GzYAQIDAQABo4IESzCCBEcwHQYDVR0O -BBYEFAeUqHBsCqTumbhV3S5MRXf2Nq+5MIIBTgYDVR0jBIIBRTCCAUGAFAeUqHBs -CqTumbhV3S5MRXf2Nq+5oYIBJKSCASAwggEcMQswCQYDVQQGEwJFUzESMBAGA1UE -CBMJQmFyY2Vsb25hMRIwEAYDVQQHEwlCYXJjZWxvbmExLjAsBgNVBAoTJUlQUyBJ -bnRlcm5ldCBwdWJsaXNoaW5nIFNlcnZpY2VzIHMubC4xKzApBgNVBAoUImlwc0Bt -YWlsLmlwcy5lcyBDLkkuRi4gIEItNjA5Mjk0NTIxMzAxBgNVBAsTKklQUyBDQSBD -aGFpbmVkIENBcyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEzMDEGA1UEAxMqSVBT -IENBIENoYWluZWQgQ0FzIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MR4wHAYJKoZI -hvcNAQkBFg9pcHNAbWFpbC5pcHMuZXOCAQAwDAYDVR0TBAUwAwEB/zAMBgNVHQ8E -BQMDB/+AMGsGA1UdJQRkMGIGCCsGAQUFBwMBBggrBgEFBQcDAgYIKwYBBQUHAwMG -CCsGAQUFBwMEBggrBgEFBQcDCAYKKwYBBAGCNwIBFQYKKwYBBAGCNwIBFgYKKwYB -BAGCNwoDAQYKKwYBBAGCNwoDBDARBglghkgBhvhCAQEEBAMCAAcwGgYDVR0RBBMw -EYEPaXBzQG1haWwuaXBzLmVzMBoGA1UdEgQTMBGBD2lwc0BtYWlsLmlwcy5lczBD -BglghkgBhvhCAQ0ENhY0Q2hhaW5lZCBDQSBDZXJ0aWZpY2F0ZSBpc3N1ZWQgYnkg -aHR0cHM6Ly93d3cuaXBzLmVzLzAqBglghkgBhvhCAQIEHRYbaHR0cHM6Ly93d3cu -aXBzLmVzL2lwczIwMDIvMDgGCWCGSAGG+EIBBAQrFilodHRwczovL3d3dy5pcHMu -ZXMvaXBzMjAwMi9pcHMyMDAyQ0FDLmNybDA9BglghkgBhvhCAQMEMBYuaHR0cHM6 -Ly93d3cuaXBzLmVzL2lwczIwMDIvcmV2b2NhdGlvbkNBQy5odG1sPzA6BglghkgB -hvhCAQcELRYraHR0cHM6Ly93d3cuaXBzLmVzL2lwczIwMDIvcmVuZXdhbENBQy5o -dG1sPzA4BglghkgBhvhCAQgEKxYpaHR0cHM6Ly93d3cuaXBzLmVzL2lwczIwMDIv -cG9saWN5Q0FDLmh0bWwwbwYDVR0fBGgwZjAvoC2gK4YpaHR0cHM6Ly93d3cuaXBz -LmVzL2lwczIwMDIvaXBzMjAwMkNBQy5jcmwwM6AxoC+GLWh0dHBzOi8vd3d3YmFj -ay5pcHMuZXMvaXBzMjAwMi9pcHMyMDAyQ0FDLmNybDAvBggrBgEFBQcBAQQjMCEw -HwYIKwYBBQUHMAGGE2h0dHA6Ly9vY3NwLmlwcy5lcy8wDQYJKoZIhvcNAQEFBQAD -gYEATiRvY2nro9B6QNgTOgojWSrXMKpXHa6hLRxL2GZPEFg059x2ERs3pw7RlJJZ -ctupZam06zvBnGfQL4ZhevXl6ST6RAAmOikuj8kbiFSgujjCJY1wv5/7zzgBWzdL -NzqKC18p1T2KZa8B2qKfQCqzV/J3fgI/725+9ekqKNLiE5Q= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIH8jCCB1ugAwIBAgIBADANBgkqhkiG9w0BAQUFADCCARIxCzAJBgNVBAYTAkVT -MRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQBgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UE -ChMlSVBTIEludGVybmV0IHB1Ymxpc2hpbmcgU2VydmljZXMgcy5sLjErMCkGA1UE -ChQiaXBzQG1haWwuaXBzLmVzIEMuSS5GLiAgQi02MDkyOTQ1MjEuMCwGA1UECxMl -SVBTIENBIENMQVNFMSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEuMCwGA1UEAxMl -SVBTIENBIENMQVNFMSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEeMBwGCSqGSIb3 -DQEJARYPaXBzQG1haWwuaXBzLmVzMB4XDTAxMTIzMTExMTEwM1oXDTI1MTIyOTEx -MTEwM1owggESMQswCQYDVQQGEwJFUzESMBAGA1UECBMJQmFyY2Vsb25hMRIwEAYD -VQQHEwlCYXJjZWxvbmExLjAsBgNVBAoTJUlQUyBJbnRlcm5ldCBwdWJsaXNoaW5n -IFNlcnZpY2VzIHMubC4xKzApBgNVBAoUImlwc0BtYWlsLmlwcy5lcyBDLkkuRi4g -IEItNjA5Mjk0NTIxLjAsBgNVBAsTJUlQUyBDQSBDTEFTRTEgQ2VydGlmaWNhdGlv -biBBdXRob3JpdHkxLjAsBgNVBAMTJUlQUyBDQSBDTEFTRTEgQ2VydGlmaWNhdGlv -biBBdXRob3JpdHkxHjAcBgkqhkiG9w0BCQEWD2lwc0BtYWlsLmlwcy5lczCBnzAN -BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA55+R7+voFuF0vIkTodduR8ZfPxKU5u/h -M+GrgqufAwHmdG+KF5fPVy8Mdi7mbqfK2veLFBVADbNq2e2+s2q8Ai0chS3vl//P -l9rrR10eU79dVN4ndGMZfpXUMZblz0/Kq3Uvk5AsWUwfv1YokIhi4RMeBtOCVv3j -LSV1rDsiap8CAwEAAaOCBFIwggROMB0GA1UdDgQWBBRtW6MBjmE3nQR4tq+blh0C -QeXbeTCCAUQGA1UdIwSCATswggE3gBRtW6MBjmE3nQR4tq+blh0CQeXbeaGCARqk -ggEWMIIBEjELMAkGA1UEBhMCRVMxEjAQBgNVBAgTCUJhcmNlbG9uYTESMBAGA1UE -BxMJQmFyY2Vsb25hMS4wLAYDVQQKEyVJUFMgSW50ZXJuZXQgcHVibGlzaGluZyBT -ZXJ2aWNlcyBzLmwuMSswKQYDVQQKFCJpcHNAbWFpbC5pcHMuZXMgQy5JLkYuICBC -LTYwOTI5NDUyMS4wLAYDVQQLEyVJUFMgQ0EgQ0xBU0UxIENlcnRpZmljYXRpb24g -QXV0aG9yaXR5MS4wLAYDVQQDEyVJUFMgQ0EgQ0xBU0UxIENlcnRpZmljYXRpb24g -QXV0aG9yaXR5MR4wHAYJKoZIhvcNAQkBFg9pcHNAbWFpbC5pcHMuZXOCAQAwDAYD -VR0TBAUwAwEB/zAMBgNVHQ8EBQMDB/+AMGsGA1UdJQRkMGIGCCsGAQUFBwMBBggr -BgEFBQcDAgYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYKKwYBBAGCNwIB -FQYKKwYBBAGCNwIBFgYKKwYBBAGCNwoDAQYKKwYBBAGCNwoDBDARBglghkgBhvhC -AQEEBAMCAAcwGgYDVR0RBBMwEYEPaXBzQG1haWwuaXBzLmVzMBoGA1UdEgQTMBGB -D2lwc0BtYWlsLmlwcy5lczBCBglghkgBhvhCAQ0ENRYzQ0xBU0UxIENBIENlcnRp -ZmljYXRlIGlzc3VlZCBieSBodHRwczovL3d3dy5pcHMuZXMvMCoGCWCGSAGG+EIB -AgQdFhtodHRwczovL3d3dy5pcHMuZXMvaXBzMjAwMi8wOwYJYIZIAYb4QgEEBC4W -LGh0dHBzOi8vd3d3Lmlwcy5lcy9pcHMyMDAyL2lwczIwMDJDTEFTRTEuY3JsMEAG -CWCGSAGG+EIBAwQzFjFodHRwczovL3d3dy5pcHMuZXMvaXBzMjAwMi9yZXZvY2F0 -aW9uQ0xBU0UxLmh0bWw/MD0GCWCGSAGG+EIBBwQwFi5odHRwczovL3d3dy5pcHMu -ZXMvaXBzMjAwMi9yZW5ld2FsQ0xBU0UxLmh0bWw/MDsGCWCGSAGG+EIBCAQuFixo -dHRwczovL3d3dy5pcHMuZXMvaXBzMjAwMi9wb2xpY3lDTEFTRTEuaHRtbDB1BgNV -HR8EbjBsMDKgMKAuhixodHRwczovL3d3dy5pcHMuZXMvaXBzMjAwMi9pcHMyMDAy -Q0xBU0UxLmNybDA2oDSgMoYwaHR0cHM6Ly93d3diYWNrLmlwcy5lcy9pcHMyMDAy -L2lwczIwMDJDTEFTRTEuY3JsMC8GCCsGAQUFBwEBBCMwITAfBggrBgEFBQcwAYYT -aHR0cDovL29jc3AuaXBzLmVzLzANBgkqhkiG9w0BAQUFAAOBgQBacEdMbCU0z2bO -X+iyJafrUbjPE+5KzJz2jB1YXC2d7kMy2Hhbp8gVyfUFQpd+F2IgBBj9z3IRNkDN -foHhdse5j2cUUH+fno9jj8EPE2GPhXVmCjIP6KuPp8yzz89gC+ry+bkfSFzjHUQt -K15I/jRAHfyJywwUrwtmklZIX0E5Og== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIH8jCCB1ugAwIBAgIBADANBgkqhkiG9w0BAQUFADCCARIxCzAJBgNVBAYTAkVT -MRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQBgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UE -ChMlSVBTIEludGVybmV0IHB1Ymxpc2hpbmcgU2VydmljZXMgcy5sLjErMCkGA1UE -ChQiaXBzQG1haWwuaXBzLmVzIEMuSS5GLiAgQi02MDkyOTQ1MjEuMCwGA1UECxMl -SVBTIENBIENMQVNFMyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEuMCwGA1UEAxMl -SVBTIENBIENMQVNFMyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEeMBwGCSqGSIb3 -DQEJARYPaXBzQG1haWwuaXBzLmVzMB4XDTAxMTIzMTExMTkzMVoXDTI1MTIyOTEx -MTkzMVowggESMQswCQYDVQQGEwJFUzESMBAGA1UECBMJQmFyY2Vsb25hMRIwEAYD -VQQHEwlCYXJjZWxvbmExLjAsBgNVBAoTJUlQUyBJbnRlcm5ldCBwdWJsaXNoaW5n -IFNlcnZpY2VzIHMubC4xKzApBgNVBAoUImlwc0BtYWlsLmlwcy5lcyBDLkkuRi4g -IEItNjA5Mjk0NTIxLjAsBgNVBAsTJUlQUyBDQSBDTEFTRTMgQ2VydGlmaWNhdGlv -biBBdXRob3JpdHkxLjAsBgNVBAMTJUlQUyBDQSBDTEFTRTMgQ2VydGlmaWNhdGlv -biBBdXRob3JpdHkxHjAcBgkqhkiG9w0BCQEWD2lwc0BtYWlsLmlwcy5lczCBnzAN -BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAve2QhYLxoN2P3DVo4Xw+6Gyb2vDjfzvB -JRvH+WFIXO3KItC1dJk2W7iFnsZJnb65Q6NDKxhwfQ4XnLuBSPqMVJ6EHB++I1p2 -pg0j7YOtec++o3ysS6zf1r01HSh8i85+AcGcgLO4Z79w9jtEGlSdrFhCLUjJJSEs -XdzSbkEFrkMCAwEAAaOCBFIwggROMB0GA1UdDgQWBBT7o4z3Z4tAqk02rzCA6po7 -4C9o6DCCAUQGA1UdIwSCATswggE3gBT7o4z3Z4tAqk02rzCA6po74C9o6KGCARqk -ggEWMIIBEjELMAkGA1UEBhMCRVMxEjAQBgNVBAgTCUJhcmNlbG9uYTESMBAGA1UE -BxMJQmFyY2Vsb25hMS4wLAYDVQQKEyVJUFMgSW50ZXJuZXQgcHVibGlzaGluZyBT -ZXJ2aWNlcyBzLmwuMSswKQYDVQQKFCJpcHNAbWFpbC5pcHMuZXMgQy5JLkYuICBC -LTYwOTI5NDUyMS4wLAYDVQQLEyVJUFMgQ0EgQ0xBU0UzIENlcnRpZmljYXRpb24g -QXV0aG9yaXR5MS4wLAYDVQQDEyVJUFMgQ0EgQ0xBU0UzIENlcnRpZmljYXRpb24g -QXV0aG9yaXR5MR4wHAYJKoZIhvcNAQkBFg9pcHNAbWFpbC5pcHMuZXOCAQAwDAYD -VR0TBAUwAwEB/zAMBgNVHQ8EBQMDB/+AMGsGA1UdJQRkMGIGCCsGAQUFBwMBBggr -BgEFBQcDAgYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYKKwYBBAGCNwIB -FQYKKwYBBAGCNwIBFgYKKwYBBAGCNwoDAQYKKwYBBAGCNwoDBDARBglghkgBhvhC -AQEEBAMCAAcwGgYDVR0RBBMwEYEPaXBzQG1haWwuaXBzLmVzMBoGA1UdEgQTMBGB -D2lwc0BtYWlsLmlwcy5lczBCBglghkgBhvhCAQ0ENRYzQ0xBU0UzIENBIENlcnRp -ZmljYXRlIGlzc3VlZCBieSBodHRwczovL3d3dy5pcHMuZXMvMCoGCWCGSAGG+EIB -AgQdFhtodHRwczovL3d3dy5pcHMuZXMvaXBzMjAwMi8wOwYJYIZIAYb4QgEEBC4W -LGh0dHBzOi8vd3d3Lmlwcy5lcy9pcHMyMDAyL2lwczIwMDJDTEFTRTMuY3JsMEAG -CWCGSAGG+EIBAwQzFjFodHRwczovL3d3dy5pcHMuZXMvaXBzMjAwMi9yZXZvY2F0 -aW9uQ0xBU0UzLmh0bWw/MD0GCWCGSAGG+EIBBwQwFi5odHRwczovL3d3dy5pcHMu -ZXMvaXBzMjAwMi9yZW5ld2FsQ0xBU0UzLmh0bWw/MDsGCWCGSAGG+EIBCAQuFixo -dHRwczovL3d3dy5pcHMuZXMvaXBzMjAwMi9wb2xpY3lDTEFTRTMuaHRtbDB1BgNV -HR8EbjBsMDKgMKAuhixodHRwczovL3d3dy5pcHMuZXMvaXBzMjAwMi9pcHMyMDAy -Q0xBU0UzLmNybDA2oDSgMoYwaHR0cHM6Ly93d3diYWNrLmlwcy5lcy9pcHMyMDAy -L2lwczIwMDJDTEFTRTMuY3JsMC8GCCsGAQUFBwEBBCMwITAfBggrBgEFBQcwAYYT -aHR0cDovL29jc3AuaXBzLmVzLzANBgkqhkiG9w0BAQUFAAOBgQAiu2FuR8MoQlYw -3QtFc/BI7DgkUUeSIM49JoMU0H3a4Y+JbQxQ4q/n6yAbEuMETUyqob/HmS/NkLJq -ur3RvGBseDXgxNyePGjFc97ITNWf5X1+4CXtBf+TTKNEMg1UpPbCz+9EkjzTcYj1 -5tjLbAp/mmLLZmCOV7cCGuXGSTBNzA== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIH/zCCB2igAwIBAgIBADANBgkqhkiG9w0BAQUFADCCARQxCzAJBgNVBAYTAkVT -MRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQBgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UE -ChMlSVBTIEludGVybmV0IHB1Ymxpc2hpbmcgU2VydmljZXMgcy5sLjErMCkGA1UE -ChQiaXBzQG1haWwuaXBzLmVzIEMuSS5GLiAgQi02MDkyOTQ1MjEvMC0GA1UECxMm -SVBTIENBIENMQVNFQTEgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxLzAtBgNVBAMT -JklQUyBDQSBDTEFTRUExIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MR4wHAYJKoZI -hvcNAQkBFg9pcHNAbWFpbC5pcHMuZXMwHhcNMDExMjMxMTEyMTQxWhcNMjUxMjI5 -MTEyMTQxWjCCARQxCzAJBgNVBAYTAkVTMRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQ -BgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UEChMlSVBTIEludGVybmV0IHB1Ymxpc2hp -bmcgU2VydmljZXMgcy5sLjErMCkGA1UEChQiaXBzQG1haWwuaXBzLmVzIEMuSS5G -LiAgQi02MDkyOTQ1MjEvMC0GA1UECxMmSVBTIENBIENMQVNFQTEgQ2VydGlmaWNh -dGlvbiBBdXRob3JpdHkxLzAtBgNVBAMTJklQUyBDQSBDTEFTRUExIENlcnRpZmlj -YXRpb24gQXV0aG9yaXR5MR4wHAYJKoZIhvcNAQkBFg9pcHNAbWFpbC5pcHMuZXMw -gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAM8g89BgSKoCxBXZ5C+NnlURLSnM -UWZoAGXaFFWf6q7f69uN1nXaUfTEzPstvTUfE7fpZmF8lEDz+2AvjBg086hVnra0 -b0APA0VnanJyW2ZIlkKFGMCB4WJqh7JB7i45jITVXthPV2vsjlKM97Pnnhimz8Fb -r+RZcsz69vRptMqxAgMBAAGjggRbMIIEVzAdBgNVHQ4EFgQUL8zsbGe+T/iqPIiN -EvvHnUxb9F4wggFGBgNVHSMEggE9MIIBOYAUL8zsbGe+T/iqPIiNEvvHnUxb9F6h -ggEcpIIBGDCCARQxCzAJBgNVBAYTAkVTMRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQ -BgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UEChMlSVBTIEludGVybmV0IHB1Ymxpc2hp -bmcgU2VydmljZXMgcy5sLjErMCkGA1UEChQiaXBzQG1haWwuaXBzLmVzIEMuSS5G -LiAgQi02MDkyOTQ1MjEvMC0GA1UECxMmSVBTIENBIENMQVNFQTEgQ2VydGlmaWNh -dGlvbiBBdXRob3JpdHkxLzAtBgNVBAMTJklQUyBDQSBDTEFTRUExIENlcnRpZmlj -YXRpb24gQXV0aG9yaXR5MR4wHAYJKoZIhvcNAQkBFg9pcHNAbWFpbC5pcHMuZXOC -AQAwDAYDVR0TBAUwAwEB/zAMBgNVHQ8EBQMDB/+AMGsGA1UdJQRkMGIGCCsGAQUF -BwMBBggrBgEFBQcDAgYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYKKwYB -BAGCNwIBFQYKKwYBBAGCNwIBFgYKKwYBBAGCNwoDAQYKKwYBBAGCNwoDBDARBglg -hkgBhvhCAQEEBAMCAAcwGgYDVR0RBBMwEYEPaXBzQG1haWwuaXBzLmVzMBoGA1Ud -EgQTMBGBD2lwc0BtYWlsLmlwcy5lczBDBglghkgBhvhCAQ0ENhY0Q0xBU0VBMSBD -QSBDZXJ0aWZpY2F0ZSBpc3N1ZWQgYnkgaHR0cHM6Ly93d3cuaXBzLmVzLzAqBglg -hkgBhvhCAQIEHRYbaHR0cHM6Ly93d3cuaXBzLmVzL2lwczIwMDIvMDwGCWCGSAGG -+EIBBAQvFi1odHRwczovL3d3dy5pcHMuZXMvaXBzMjAwMi9pcHMyMDAyQ0xBU0VB -MS5jcmwwQQYJYIZIAYb4QgEDBDQWMmh0dHBzOi8vd3d3Lmlwcy5lcy9pcHMyMDAy -L3Jldm9jYXRpb25DTEFTRUExLmh0bWw/MD4GCWCGSAGG+EIBBwQxFi9odHRwczov -L3d3dy5pcHMuZXMvaXBzMjAwMi9yZW5ld2FsQ0xBU0VBMS5odG1sPzA8BglghkgB -hvhCAQgELxYtaHR0cHM6Ly93d3cuaXBzLmVzL2lwczIwMDIvcG9saWN5Q0xBU0VB -MS5odG1sMHcGA1UdHwRwMG4wM6AxoC+GLWh0dHBzOi8vd3d3Lmlwcy5lcy9pcHMy -MDAyL2lwczIwMDJDTEFTRUExLmNybDA3oDWgM4YxaHR0cHM6Ly93d3diYWNrLmlw -cy5lcy9pcHMyMDAyL2lwczIwMDJDTEFTRUExLmNybDAvBggrBgEFBQcBAQQjMCEw -HwYIKwYBBQUHMAGGE2h0dHA6Ly9vY3NwLmlwcy5lcy8wDQYJKoZIhvcNAQEFBQAD -gYEAGY2khC4v4mlenqRcy8Mn8mcWca88t4CY9LCJMqlIt7i559BNkMMB66tXsNp9 -N2QhnTordKOjkdgZJmCb7DUdMJEQQT0Y5W7JA6WvHatAFu8feRJ4ImaTjI0Xz3Dd -Jbz6O++igCw0l4EY5gayn2BFpAm+7ZpEcdpR/OCOH80lNDo= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIH/zCCB2igAwIBAgIBADANBgkqhkiG9w0BAQUFADCCARQxCzAJBgNVBAYTAkVT -MRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQBgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UE -ChMlSVBTIEludGVybmV0IHB1Ymxpc2hpbmcgU2VydmljZXMgcy5sLjErMCkGA1UE -ChQiaXBzQG1haWwuaXBzLmVzIEMuSS5GLiAgQi02MDkyOTQ1MjEvMC0GA1UECxMm -SVBTIENBIENMQVNFQTMgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxLzAtBgNVBAMT -JklQUyBDQSBDTEFTRUEzIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MR4wHAYJKoZI -hvcNAQkBFg9pcHNAbWFpbC5pcHMuZXMwHhcNMDExMjMxMTEyMzU5WhcNMjUxMjI5 -MTEyMzU5WjCCARQxCzAJBgNVBAYTAkVTMRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQ -BgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UEChMlSVBTIEludGVybmV0IHB1Ymxpc2hp -bmcgU2VydmljZXMgcy5sLjErMCkGA1UEChQiaXBzQG1haWwuaXBzLmVzIEMuSS5G -LiAgQi02MDkyOTQ1MjEvMC0GA1UECxMmSVBTIENBIENMQVNFQTMgQ2VydGlmaWNh -dGlvbiBBdXRob3JpdHkxLzAtBgNVBAMTJklQUyBDQSBDTEFTRUEzIENlcnRpZmlj -YXRpb24gQXV0aG9yaXR5MR4wHAYJKoZIhvcNAQkBFg9pcHNAbWFpbC5pcHMuZXMw -gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMFh+lWUEmnBK5F6da6IALvvPO6f -MWYw9LFAmwJsjcdKTVElPugUKLwgPLHxjO19kdmXIqPVzGOxq9krIwvdppffBYRU -Fro6y8xja40gpdaeBXFGdVj19mR7C2adPoeVPTy1OTdSVLsWF8W/rdiLMy/p+PrV -gTP/t56Fpu9MOeDjAgMBAAGjggRbMIIEVzAdBgNVHQ4EFgQU/J6FGtwGJXEh8C+L -ElXQxYDuBq4wggFGBgNVHSMEggE9MIIBOYAU/J6FGtwGJXEh8C+LElXQxYDuBq6h -ggEcpIIBGDCCARQxCzAJBgNVBAYTAkVTMRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQ -BgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UEChMlSVBTIEludGVybmV0IHB1Ymxpc2hp -bmcgU2VydmljZXMgcy5sLjErMCkGA1UEChQiaXBzQG1haWwuaXBzLmVzIEMuSS5G -LiAgQi02MDkyOTQ1MjEvMC0GA1UECxMmSVBTIENBIENMQVNFQTMgQ2VydGlmaWNh -dGlvbiBBdXRob3JpdHkxLzAtBgNVBAMTJklQUyBDQSBDTEFTRUEzIENlcnRpZmlj -YXRpb24gQXV0aG9yaXR5MR4wHAYJKoZIhvcNAQkBFg9pcHNAbWFpbC5pcHMuZXOC -AQAwDAYDVR0TBAUwAwEB/zAMBgNVHQ8EBQMDB/+AMGsGA1UdJQRkMGIGCCsGAQUF -BwMBBggrBgEFBQcDAgYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYKKwYB -BAGCNwIBFQYKKwYBBAGCNwIBFgYKKwYBBAGCNwoDAQYKKwYBBAGCNwoDBDARBglg -hkgBhvhCAQEEBAMCAAcwGgYDVR0RBBMwEYEPaXBzQG1haWwuaXBzLmVzMBoGA1Ud -EgQTMBGBD2lwc0BtYWlsLmlwcy5lczBDBglghkgBhvhCAQ0ENhY0Q0xBU0VBMyBD -QSBDZXJ0aWZpY2F0ZSBpc3N1ZWQgYnkgaHR0cHM6Ly93d3cuaXBzLmVzLzAqBglg -hkgBhvhCAQIEHRYbaHR0cHM6Ly93d3cuaXBzLmVzL2lwczIwMDIvMDwGCWCGSAGG -+EIBBAQvFi1odHRwczovL3d3dy5pcHMuZXMvaXBzMjAwMi9pcHMyMDAyQ0xBU0VB -My5jcmwwQQYJYIZIAYb4QgEDBDQWMmh0dHBzOi8vd3d3Lmlwcy5lcy9pcHMyMDAy -L3Jldm9jYXRpb25DTEFTRUEzLmh0bWw/MD4GCWCGSAGG+EIBBwQxFi9odHRwczov -L3d3dy5pcHMuZXMvaXBzMjAwMi9yZW5ld2FsQ0xBU0VBMy5odG1sPzA8BglghkgB -hvhCAQgELxYtaHR0cHM6Ly93d3cuaXBzLmVzL2lwczIwMDIvcG9saWN5Q0xBU0VB -My5odG1sMHcGA1UdHwRwMG4wM6AxoC+GLWh0dHBzOi8vd3d3Lmlwcy5lcy9pcHMy -MDAyL2lwczIwMDJDTEFTRUEzLmNybDA3oDWgM4YxaHR0cHM6Ly93d3diYWNrLmlw -cy5lcy9pcHMyMDAyL2lwczIwMDJDTEFTRUEzLmNybDAvBggrBgEFBQcBAQQjMCEw -HwYIKwYBBQUHMAGGE2h0dHA6Ly9vY3NwLmlwcy5lcy8wDQYJKoZIhvcNAQEFBQAD -gYEAGG8JN0Ca0pQR0X/Lg33qtKfi2JPe2iRqdRswDoL3CTn+bRN20V/wbKDAwyxc -7eJOroysytPkEF4wZhipaKCjaWJROZGCeU1jM7mZe9pQPzeofT//VLi8zKaUA4lZ -BvYI44gntZQoaFxJna5NHHde+mbbPYlHb8c6g0mf9S3tODs= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIIQTCCB6qgAwIBAgIBADANBgkqhkiG9w0BAQUFADCCAR4xCzAJBgNVBAYTAkVT -MRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQBgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UE -ChMlSVBTIEludGVybmV0IHB1Ymxpc2hpbmcgU2VydmljZXMgcy5sLjErMCkGA1UE -ChQiaXBzQG1haWwuaXBzLmVzIEMuSS5GLiAgQi02MDkyOTQ1MjE0MDIGA1UECxMr -SVBTIENBIFRpbWVzdGFtcGluZyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTE0MDIG -A1UEAxMrSVBTIENBIFRpbWVzdGFtcGluZyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0 -eTEeMBwGCSqGSIb3DQEJARYPaXBzQG1haWwuaXBzLmVzMB4XDTAxMTIzMTExMjY0 -M1oXDTI1MTIyOTExMjY0M1owggEeMQswCQYDVQQGEwJFUzESMBAGA1UECBMJQmFy -Y2Vsb25hMRIwEAYDVQQHEwlCYXJjZWxvbmExLjAsBgNVBAoTJUlQUyBJbnRlcm5l -dCBwdWJsaXNoaW5nIFNlcnZpY2VzIHMubC4xKzApBgNVBAoUImlwc0BtYWlsLmlw -cy5lcyBDLkkuRi4gIEItNjA5Mjk0NTIxNDAyBgNVBAsTK0lQUyBDQSBUaW1lc3Rh -bXBpbmcgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxNDAyBgNVBAMTK0lQUyBDQSBU -aW1lc3RhbXBpbmcgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxHjAcBgkqhkiG9w0B -CQEWD2lwc0BtYWlsLmlwcy5lczCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA -0umTdn+FPP2gAb0RL0ZCDyt/BZvGa/VRcayaUh8flSfMkO+WP45RNv0WAM43pSGU -Rmvt5P+hfuqf0aKbOPMTxLmYumVFQ/nXvRWdlC4AYN6YGrk8yfXh/NbEJN/n48iE -GRK0HFyz9eIWYSdg8vAt5PDzrPigeYSdReL2AfBE5ZECAwEAAaOCBIkwggSFMB0G -A1UdDgQWBBSR2UK8nKnK0Bw3E1JXFqANHikdPjCCAVAGA1UdIwSCAUcwggFDgBSR -2UK8nKnK0Bw3E1JXFqANHikdPqGCASakggEiMIIBHjELMAkGA1UEBhMCRVMxEjAQ -BgNVBAgTCUJhcmNlbG9uYTESMBAGA1UEBxMJQmFyY2Vsb25hMS4wLAYDVQQKEyVJ -UFMgSW50ZXJuZXQgcHVibGlzaGluZyBTZXJ2aWNlcyBzLmwuMSswKQYDVQQKFCJp -cHNAbWFpbC5pcHMuZXMgQy5JLkYuICBCLTYwOTI5NDUyMTQwMgYDVQQLEytJUFMg -Q0EgVGltZXN0YW1waW5nIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MTQwMgYDVQQD -EytJUFMgQ0EgVGltZXN0YW1waW5nIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MR4w -HAYJKoZIhvcNAQkBFg9pcHNAbWFpbC5pcHMuZXOCAQAwDAYDVR0TBAUwAwEB/zAM -BgNVHQ8EBQMDB/+AMGsGA1UdJQRkMGIGCCsGAQUFBwMBBggrBgEFBQcDAgYIKwYB -BQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYKKwYBBAGCNwIBFQYKKwYBBAGCNwIB -FgYKKwYBBAGCNwoDAQYKKwYBBAGCNwoDBDARBglghkgBhvhCAQEEBAMCAAcwGgYD -VR0RBBMwEYEPaXBzQG1haWwuaXBzLmVzMBoGA1UdEgQTMBGBD2lwc0BtYWlsLmlw -cy5lczBIBglghkgBhvhCAQ0EOxY5VGltZXN0YW1waW5nIENBIENlcnRpZmljYXRl -IGlzc3VlZCBieSBodHRwczovL3d3dy5pcHMuZXMvMCoGCWCGSAGG+EIBAgQdFhto -dHRwczovL3d3dy5pcHMuZXMvaXBzMjAwMi8wQQYJYIZIAYb4QgEEBDQWMmh0dHBz -Oi8vd3d3Lmlwcy5lcy9pcHMyMDAyL2lwczIwMDJUaW1lc3RhbXBpbmcuY3JsMEYG -CWCGSAGG+EIBAwQ5FjdodHRwczovL3d3dy5pcHMuZXMvaXBzMjAwMi9yZXZvY2F0 -aW9uVGltZXN0YW1waW5nLmh0bWw/MEMGCWCGSAGG+EIBBwQ2FjRodHRwczovL3d3 -dy5pcHMuZXMvaXBzMjAwMi9yZW5ld2FsVGltZXN0YW1waW5nLmh0bWw/MEEGCWCG -SAGG+EIBCAQ0FjJodHRwczovL3d3dy5pcHMuZXMvaXBzMjAwMi9wb2xpY3lUaW1l -c3RhbXBpbmcuaHRtbDCBgQYDVR0fBHoweDA4oDagNIYyaHR0cHM6Ly93d3cuaXBz -LmVzL2lwczIwMDIvaXBzMjAwMlRpbWVzdGFtcGluZy5jcmwwPKA6oDiGNmh0dHBz -Oi8vd3d3YmFjay5pcHMuZXMvaXBzMjAwMi9pcHMyMDAyVGltZXN0YW1waW5nLmNy -bDAvBggrBgEFBQcBAQQjMCEwHwYIKwYBBQUHMAGGE2h0dHA6Ly9vY3NwLmlwcy5l -cy8wDQYJKoZIhvcNAQEFBQADgYEAxKMCdGABCUwYXU900W1zDCfTSDC1TxFVGRnH -I4soqfp4D34sJ/adkgD2GMgkAMVf+C1MY/yQFV4nmOal9K7SNrG1JR8OeDoRjpM4 -rtO9qYbuHD3TW47/y/aZSZxP4ccocGpPOkvqfrnndKRKY0WUk/7Qg5aqpIXni2Gg -olkTZbQ= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIICtzCCAiACAQAwDQYJKoZIhvcNAQEEBQAwgaMxCzAJBgNVBAYTAkVTMRIwEAYD -VQQIEwlCQVJDRUxPTkExEjAQBgNVBAcTCUJBUkNFTE9OQTEZMBcGA1UEChMQSVBT -IFNlZ3VyaWRhZCBDQTEYMBYGA1UECxMPQ2VydGlmaWNhY2lvbmVzMRcwFQYDVQQD -Ew5JUFMgU0VSVklET1JFUzEeMBwGCSqGSIb3DQEJARYPaXBzQG1haWwuaXBzLmVz -MB4XDTk4MDEwMTIzMjEwN1oXDTA5MTIyOTIzMjEwN1owgaMxCzAJBgNVBAYTAkVT -MRIwEAYDVQQIEwlCQVJDRUxPTkExEjAQBgNVBAcTCUJBUkNFTE9OQTEZMBcGA1UE -ChMQSVBTIFNlZ3VyaWRhZCBDQTEYMBYGA1UECxMPQ2VydGlmaWNhY2lvbmVzMRcw -FQYDVQQDEw5JUFMgU0VSVklET1JFUzEeMBwGCSqGSIb3DQEJARYPaXBzQG1haWwu -aXBzLmVzMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCsT1J0nznqjtwlxLyY -XZhkJAk8IbPMGbWOlI6H0fg3PqHILVikgDVboXVsHUUMH2Fjal5vmwpMwci4YSM1 -gf/+rHhwLWjhOgeYlQJU3c0jt4BT18g3RXIGJBK6E2Ehim51KODFDzT9NthFf+G4 -Nu+z4cYgjui0OLzhPvYR3oydAQIDAQABMA0GCSqGSIb3DQEBBAUAA4GBACzzw3lY -JN7GO9HgQmm47mSzPWIBubOE3yN93ZjPEKn+ANgilgUTB1RXxafey9m4iEL2mdsU -dx+2/iU94aI+A6mB0i1sR/WWRowiq8jMDQ6XXotBtDvECgZAHd1G9AHduoIuPD14 -cJ58GNCr+Lh3B0Zx8coLY1xq+XKU1QFPoNtC ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDczCCAlugAwIBAgIBBDANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQGEwJLUjEN -MAsGA1UECgwES0lTQTEuMCwGA1UECwwlS29yZWEgQ2VydGlmaWNhdGlvbiBBdXRo -b3JpdHkgQ2VudHJhbDEWMBQGA1UEAwwNS0lTQSBSb290Q0EgMTAeFw0wNTA4MjQw -ODA1NDZaFw0yNTA4MjQwODA1NDZaMGQxCzAJBgNVBAYTAktSMQ0wCwYDVQQKDARL -SVNBMS4wLAYDVQQLDCVLb3JlYSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBDZW50 -cmFsMRYwFAYDVQQDDA1LSVNBIFJvb3RDQSAxMIIBIDANBgkqhkiG9w0BAQEFAAOC -AQ0AMIIBCAKCAQEAvATk+hM58DSWIGtsaLv623f/J/es7C/n/fB/bW+MKs0lCVsk -9KFo/CjsySXirO3eyDOE9bClCTqnsUdIxcxPjHmc+QZXfd3uOPbPFLKc6tPAXXdi -8EcNuRpAU1xkcK8IWsD3z3X5bI1kKB4g/rcbGdNaZoNy4rCbvdMlFQ0yb2Q3lIVG -yHK+d9VuHygvx2nt54OJM1jT3qC/QOhDUO7cTWu8peqmyGGO9cNkrwYV3CmLP3WM -vHFE2/yttRcdbYmDz8Yzvb9Fov4Kn6MRXw+5H5wawkbMnChmn3AmPC7fqoD+jMUE -CSVPzZNHPDfqAmeS/vwiJFys0izgXAEzisEZ2wIBA6MyMDAwHQYDVR0OBBYEFL+2 -J9gDWnZlTGEBQVYx5Yt7OtnMMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEF -BQADggEBABOvUQveimpb5poKyLGQSk6hAp3MiNKrZr097LuxQpVqslxa/6FjZJap -aBV/JV6K+KRzwYCKhQoOUugy50X4TmWAkZl0Q+VFnUkq8JSV3enhMNITbslOsXfl -BM+tWh6UCVrXPAgcrnrpFDLBRa3SJkhyrKhB2vAhhzle3/xk/2F0KpzZm4tfwjeT -2KM3LzuTa7IbB6d/CVDv0zq+IWuKkDsnSlFOa56ch534eJAx7REnxqhZvvwYC/uO -fi5C4e3nCSG9uRPFVmf0JqZCQ5BEVLRxm3bkGhKsGigA35vB1fjbXKP4krG9tNT5 -UNkAAk/bg9ART6RCVmE6fhMy04Qfybo= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIFUjCCBDqgAwIBAgIBAjANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQGEwJLUjEN -MAsGA1UEChMES0lTQTEuMCwGA1UECxMlS29yZWEgQ2VydGlmaWNhdGlvbiBBdXRo -b3JpdHkgQ2VudHJhbDEWMBQGA1UEAxMNS0lTQSBSb290Q0EgMzAeFw0wNDExMTkw -NjM5NTFaFw0xNDExMTkwNjM5NTFaMGQxCzAJBgNVBAYTAktSMQ0wCwYDVQQKEwRL -SVNBMS4wLAYDVQQLEyVLb3JlYSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBDZW50 -cmFsMRYwFAYDVQQDEw1LSVNBIFJvb3RDQSAzMIIBIDANBgkqhkiG9w0BAQEFAAOC -AQ0AMIIBCAKCAQEA3rrtF2Wu0b1KPazbgHLMWOHn4ZPazDB6z+8Lri2nQ6u/p0LP -CFYIpEcdffqG79gwlyY0YTyADvjU65/8IjAboW0+40zSVU4WQDfC9gdu2we1pYyW -geKbXH6UYcjOhDyx+gDmctMJhXfp3F4hT7TkTvTiF6tQrxz/oTlYdVsSspa5jfBw -YkhbVigqpYeRNrkeJPW5unu2UlFbF1pgBWycwubGjD756t08jP+J3kNwrB248XXN -OMpTDUdoasY8GMq94bS+DvTQ49IT+rBRERHUQavo9DmO4TSETwuTqmo4/OXGeEeu -dhf6oYA3BgAVCP1rI476cg2V1ktisWjC3TSbXQIBA6OCAg8wggILMB8GA1UdIwQY -MBaAFI+B8NqmzXQ8vmb0FWtGpP4GKMyqMB0GA1UdDgQWBBSPgfDaps10PL5m9BVr -RqT+BijMqjAOBgNVHQ8BAf8EBAMCAQYwggEuBgNVHSAEggElMIIBITCCAR0GBFUd -IAAwggETMDAGCCsGAQUFBwIBFiRodHRwOi8vd3d3LnJvb3RjYS5vci5rci9yY2Ev -Y3BzLmh0bWwwgd4GCCsGAQUFBwICMIHRHoHOx3QAIMd4yZ3BHLKUACCs9cd4x3jJ -ncEcx4WyyLLkACgAVABoAGkAcwAgAGMAZQByAHQAaQBmAGkAYwBhAHQAZQAgAGkA -cwAgAGEAYwBjAHIAZQBkAGkAdABlAGQAIAB1AG4AZABlAHIAIABFAGwAZQBjAHQA -cgBvAG4AaQBjACAAUwBpAGcAbgBhAHQAdQByAGUAIABBAGMAdAAgAG8AZgAgAHQA -aABlACAAUgBlAHAAdQBiAGwAaQBjACAAbwBmACAASwBvAHIAZQBhACkwMwYDVR0R -BCwwKqQoMCYxJDAiBgNVBAMMG+2VnOq1reygleuztOuztO2YuOynhO2dpeybkDAz -BgNVHRIELDAqpCgwJjEkMCIGA1UEAwwb7ZWc6rWt7KCV67O067O07Zi47KeE7Z2l -7JuQMA8GA1UdEwEB/wQFMAMBAf8wDAYDVR0kBAUwA4ABADANBgkqhkiG9w0BAQUF -AAOCAQEAz9b3Dv2wjG4FFY6oXCuyWtEeV6ZeGKqCEQj8mbdbp+PI0qLT+SQ09+Pk -rolUR9NpScmAwRHr4inH9gaLX7riXs+rw87P7pIl3J85Hg4D9N6QW6FwmVzHc07J -pHVJeyWhn4KSjU3sYcUMMqfHODiAVToqgx2cZHm5Dac1Smjvj/8F2LpOVmHY+Epw -mAiWk9hgxzrsX58dKzVPSBShmrtv7tIDhlPxEMcHVGJeNo7iHCsdF03m9VrvirqC -6HfZKBF+N4dKlArJQOk1pTr7ZD7yXxZ683bXzu4/RB1Fql8RqlMcOh9SUWJUD6OQ -Nc9Nb7rHviwJ8TX4Absk3TC8SA/u2Q== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDdjCCAl6gAwIBAgIEOhsEBTANBgkqhkiG9w0BAQUFADBRMQswCQYDVQQGEwJE -SzEMMAoGA1UEChMDS01EMQ8wDQYDVQQLEwZLTUQtQ0ExIzAhBgNVBAMTGktNRC1D -QSBLdmFsaWZpY2VyZXQgUGVyc29uMB4XDTAwMTEyMTIzMjQ1OVoXDTE1MTEyMjIz -MjQ1OVowUTELMAkGA1UEBhMCREsxDDAKBgNVBAoTA0tNRDEPMA0GA1UECxMGS01E -LUNBMSMwIQYDVQQDExpLTUQtQ0EgS3ZhbGlmaWNlcmV0IFBlcnNvbjCCASIwDQYJ -KoZIhvcNAQEBBQADggEPADCCAQoCggEBANriF4Xd6yD7ZlBE317UBDObn+vRMVc6 -p3wNQODdEDJe2z1ncCz9NJvhoLGdOJhyg7VVPh0P2c+KZ9WI9mWOKZI2bp2WkLju -jCcxbhTrurY3Wfc6gwLBqqFV8wWgaZKmvVWizjw9Kyi25f3yX4fOho6Qq2lvVbub -tvVFXAd51GJ+/2Yed+a4Or2bz2RcqHS81B3pywsD4mgJR5xREv5jqPfwNP+V7bkc -X+pfO4kVhZ/V+8MSPdQHgcV/iB3wP2mwgWyIBNc1reBidGTiz8unnWu55hcNfsvt -LJbTs9OHhsR7naRuy+S402nDnD5vnONOFEsiHn46w+T0rtu7h6j4OvkCAwEAAaNW -MFQwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUeWLqmhI42Jxj7DifDsW+ -DlQhKD0wHwYDVR0jBBgwFoAUeWLqmhI42Jxj7DifDsW+DlQhKD0wDQYJKoZIhvcN -AQEFBQADggEBANML/P42OuJ9aUV/0fItuIyc1JhqWvSqn5bXj+9eyEegcp8bHLHY -42D1O+z0lNipdjYPSdMJ0wZOEUhr+150SdDQ1P/zQL8AUaLEBkRt7ZdzXPVH3PER -qnf9IrpYBknZKfCAoVchA6Rr9WU3Sd8bMoRfMLKg8c0M8G6EPwCTcOFriSkbtvNG -zd8r8I+WfUYIN/p8DI9JT9qfjVODnYPRMUm6KPvq27TsrGruKrqyaV94kWc8co8A -v3zFLeCtghvUiRBdx+8Q7m5t4CkuSr0WINrqjIPFW2QrM1r82y09Fd16RkqL4LOg -Lh6vB5KnTApv62rWdw7zWwYnjY6/vXYY1Aw= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDWjCCAkKgAwIBAgIEO8rJUjANBgkqhkiG9w0BAQUFADBmMQswCQYDVQQGEwJE -SzEMMAoGA1UEChMDS01EMQ8wDQYDVQQLEwZLTUQtQ0ExFjAUBgNVBAMTDUtNRC1D -QSBTZXJ2ZXIxIDAeBgoJkiaJk/IsZAEDFBBpbmZvY2FAa21kLWNhLmRrMB4XDTk4 -MTAxNjE5MTkyMVoXDTE4MTAxMjE5MTkyMVowZjELMAkGA1UEBhMCREsxDDAKBgNV -BAoTA0tNRDEPMA0GA1UECxMGS01ELUNBMRYwFAYDVQQDEw1LTUQtQ0EgU2VydmVy -MSAwHgYKCZImiZPyLGQBAxQQaW5mb2NhQGttZC1jYS5kazCCASIwDQYJKoZIhvcN -AQEBBQADggEPADCCAQoCggEBAJsLpbSgFxQ7IhFgf5f+RfBxnbCkx5C7yTjfCZvp -/BP2LBD3OKjgLRwvASoCU3I5NMhccho6uhZVf1HC+Ac5HmXUUd+v92a7gDnohPPy -Rgv8c6f/+R2fFen37SBemYFDtZveamVXZ2To7xAxNiMKgPTPs/Rl7F6LDsYgv1bD -36FrjahNoSTmTbYRoK21eIOVwrZeNSzo9w3W8fj0n+V2IB1jsOh+AvjXkjbvAVky -0/57GMlyBNKP7JIGP7LXqwWfrBXuAph1DUMz467KlHZOMkPwCjTZOab7CcLQXCCY -12s5c5QAkwpf35hQRuOaNo6d/XFM6J9mofiWlGTT3Px1EX0CAwEAAaMQMA4wDAYD -VR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAPlA6VZ2C2cJbsI0SBIe9v+M9 -GxI45QI7P0D7QGyrqM7oNqGq7hJdN6NFb0LyPcF3/pVzmtYVJzaGKF6spaxOEveB -9ki1xRoXUKpaCxSweBpTzEktWa43OytRy0sbryEmHJCQkz8MPufWssf2yXHzgFFo -XMQpcMyT7JwxPlfYVvab9Kp+nW7fIyDOG0wdmBerZ+GEQJxJEkri1HskjigxhGze -ziocJatBuOWgqw5KRylgGIQjUGRTCbODVta+Kmqb9d+cB7FStbYtt2HebOXzBIY3 -XUM5KtGC++We7DqgU5Firek7brw8i2XsHPLKJTceb6Xo6DsSxLfBAWV6+8DCkQ== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDtDCCApygAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJKUDEc -MBoGA1UEChMTSmFwYW5lc2UgR292ZXJubWVudDEOMAwGA1UECxMFTVBIUFQxJjAk -BgNVBAsTHU1QSFBUIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTAyMDMxNDA3 -NTAyNloXDTEyMDMxMzE0NTk1OVowYzELMAkGA1UEBhMCSlAxHDAaBgNVBAoTE0ph -cGFuZXNlIEdvdmVybm1lbnQxDjAMBgNVBAsTBU1QSFBUMSYwJAYDVQQLEx1NUEhQ -VCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEP -ADCCAQoCggEBAI3GUWlK9G9FVm8DhpKu5t37oxZbj6lZcFvEZY07YrYojWO657ub -z56WE7q/PI/6Sm7i7qYE+Vp80r6thJvfmn7SS3BENrRqiapSenhooYD12jIe3iZQ -2SXqx7WgYwyBGdQwGaYTijzbRFpgc0K8o4a99fIoHhz9J8AKqXasddMCqfJRaH30 -YJ7HnOvRYGL6HBrGhJ7X4Rzijyk9a9+3VOBsYcnIlx9iODoiYhA6r0ojuIu8/JA1 -oTTZrS0MyU/SLdFdJze2O1wnqTULXQybzJz3ad6oC/F5a69c0m92akYd9nGBrPxj -EhucaQynC/QoCLs3aciLgioAnEJqy7i3EgUCAwEAAaNzMHEwHwYDVR0jBBgwFoAU -YML3pLoA0h93Yngl8Gb/UgAh73owHQYDVR0OBBYEFGDC96S6ANIfd2J4JfBm/1IA -Ie96MAwGA1UdEwQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQE -AwIABTANBgkqhkiG9w0BAQUFAAOCAQEANPR8DN66iWZBs/lSm1vOzhqRkXDLT6xL -LvJtjPLqmE469szGyFSKzsof6y+/8YgZlOoeX1inF4ox/SH1ATnwdIIsPbXuRLjt -axboXvBh5y2ffC3hmzJVvJ87tb6mVWQeL9VFUhNhAI0ib+9OIZVEYI/64MFkDk4e -iWG5ts6oqIJH1V7dVZg6pQ1Tc0Ckhn6N1m1hD30S0/zoPn/20Wq6OCF3he8VJrRG -dcW9BD/Bkesko1HKhMBDjHVrJ8cFwbnDSoo+Ki47eJWaz/cOzaSsaMVUsR5POava -/abhhgHn/eOJdXiVslyK0DYscjsdB3aBUfwZlomxYOzG6CgjQPhJdw== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIFTzCCBLigAwIBAgIBaDANBgkqhkiG9w0BAQQFADCBmzELMAkGA1UEBhMCSFUx -ETAPBgNVBAcTCEJ1ZGFwZXN0MScwJQYDVQQKEx5OZXRMb2NrIEhhbG96YXRiaXp0 -b25zYWdpIEtmdC4xGjAYBgNVBAsTEVRhbnVzaXR2YW55a2lhZG9rMTQwMgYDVQQD -EytOZXRMb2NrIEV4cHJlc3N6IChDbGFzcyBDKSBUYW51c2l0dmFueWtpYWRvMB4X -DTk5MDIyNTE0MDgxMVoXDTE5MDIyMDE0MDgxMVowgZsxCzAJBgNVBAYTAkhVMREw -DwYDVQQHEwhCdWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6dG9u -c2FnaSBLZnQuMRowGAYDVQQLExFUYW51c2l0dmFueWtpYWRvazE0MDIGA1UEAxMr -TmV0TG9jayBFeHByZXNzeiAoQ2xhc3MgQykgVGFudXNpdHZhbnlraWFkbzCBnzAN -BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA6+ywbGGKIyWvYCDj2Z/8kwvbXY2wobNA -OoLO/XXgeDIDhlqGlZHtU/qdQPzm6N3ZW3oDvV3zOwzDUXmbrVWg6dADEK8KuhRC -2VImESLH0iDMgqSaqf64gXadarfSNnU+sYYJ9m5tfk63euyucYT2BDMIJTLrdKwW -RMbkQJMdf60CAwEAAaOCAp8wggKbMBIGA1UdEwEB/wQIMAYBAf8CAQQwDgYDVR0P -AQH/BAQDAgAGMBEGCWCGSAGG+EIBAQQEAwIABzCCAmAGCWCGSAGG+EIBDQSCAlEW -ggJNRklHWUVMRU0hIEV6ZW4gdGFudXNpdHZhbnkgYSBOZXRMb2NrIEtmdC4gQWx0 -YWxhbm9zIFN6b2xnYWx0YXRhc2kgRmVsdGV0ZWxlaWJlbiBsZWlydCBlbGphcmFz -b2sgYWxhcGphbiBrZXN6dWx0LiBBIGhpdGVsZXNpdGVzIGZvbHlhbWF0YXQgYSBO -ZXRMb2NrIEtmdC4gdGVybWVrZmVsZWxvc3NlZy1iaXp0b3NpdGFzYSB2ZWRpLiBB -IGRpZ2l0YWxpcyBhbGFpcmFzIGVsZm9nYWRhc2FuYWsgZmVsdGV0ZWxlIGF6IGVs -b2lydCBlbGxlbm9yemVzaSBlbGphcmFzIG1lZ3RldGVsZS4gQXogZWxqYXJhcyBs -ZWlyYXNhIG1lZ3RhbGFsaGF0byBhIE5ldExvY2sgS2Z0LiBJbnRlcm5ldCBob25s -YXBqYW4gYSBodHRwczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIGNpbWVuIHZhZ3kg -a2VyaGV0byBheiBlbGxlbm9yemVzQG5ldGxvY2submV0IGUtbWFpbCBjaW1lbi4g -SU1QT1JUQU5UISBUaGUgaXNzdWFuY2UgYW5kIHRoZSB1c2Ugb2YgdGhpcyBjZXJ0 -aWZpY2F0ZSBpcyBzdWJqZWN0IHRvIHRoZSBOZXRMb2NrIENQUyBhdmFpbGFibGUg -YXQgaHR0cHM6Ly93d3cubmV0bG9jay5uZXQvZG9jcyBvciBieSBlLW1haWwgYXQg -Y3BzQG5ldGxvY2submV0LjANBgkqhkiG9w0BAQQFAAOBgQAQrX/XDDKACtiG8XmY -ta3UzbM2xJZIwVzNmtkFLp++UOv0JhQQLdRmF/iewSf98e3ke0ugbLWrmldwpu2g -pO0u9f38vf5NNwgMvOOWgyL1SRt/Syu0VMGAfJlOHdCM7tCs5ZL6dVb+ZKATj7i4 -Fp1hBWeAyNDYpQcCNJgEjTME1A== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIGfTCCBWWgAwIBAgICAQMwDQYJKoZIhvcNAQEEBQAwga8xCzAJBgNVBAYTAkhV -MRAwDgYDVQQIEwdIdW5nYXJ5MREwDwYDVQQHEwhCdWRhcGVzdDEnMCUGA1UEChMe -TmV0TG9jayBIYWxvemF0Yml6dG9uc2FnaSBLZnQuMRowGAYDVQQLExFUYW51c2l0 -dmFueWtpYWRvazE2MDQGA1UEAxMtTmV0TG9jayBLb3pqZWd5em9pIChDbGFzcyBB -KSBUYW51c2l0dmFueWtpYWRvMB4XDTk5MDIyNDIzMTQ0N1oXDTE5MDIxOTIzMTQ0 -N1owga8xCzAJBgNVBAYTAkhVMRAwDgYDVQQIEwdIdW5nYXJ5MREwDwYDVQQHEwhC -dWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6dG9uc2FnaSBLZnQu -MRowGAYDVQQLExFUYW51c2l0dmFueWtpYWRvazE2MDQGA1UEAxMtTmV0TG9jayBL -b3pqZWd5em9pIChDbGFzcyBBKSBUYW51c2l0dmFueWtpYWRvMIIBIjANBgkqhkiG -9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvHSMD7tM9DceqQWC2ObhbHDqeLVu0ThEDaiD -zl3S1tWBxdRL51uUcCbbO51qTGL3cfNk1mE7PetzozfZz+qMkjvN9wfcZnSX9EUi -3fRc4L9t875lM+QVOr/bmJBVOMTtplVjC7B4BPTjbsE/jvxReB+SnoPC/tmwqcm8 -WgD/qaiYdPv2LD4VOQ22BFWoDpggQrOxJa1+mm9dU7GrDPzr4PN6s6iz/0b2Y6LY -Oph7tqyF/7AlT3Rj5xMHpQqPBffAZG9+pyeAlt7ULoZgx2srXnN7F+eRP2QM2Esi -NCubMvJIH5+hCoR64sKtlz2O1cH5VqNQ6ca0+pii7pXmKgOM3wIDAQABo4ICnzCC -ApswDgYDVR0PAQH/BAQDAgAGMBIGA1UdEwEB/wQIMAYBAf8CAQQwEQYJYIZIAYb4 -QgEBBAQDAgAHMIICYAYJYIZIAYb4QgENBIICURaCAk1GSUdZRUxFTSEgRXplbiB0 -YW51c2l0dmFueSBhIE5ldExvY2sgS2Z0LiBBbHRhbGFub3MgU3pvbGdhbHRhdGFz -aSBGZWx0ZXRlbGVpYmVuIGxlaXJ0IGVsamFyYXNvayBhbGFwamFuIGtlc3p1bHQu -IEEgaGl0ZWxlc2l0ZXMgZm9seWFtYXRhdCBhIE5ldExvY2sgS2Z0LiB0ZXJtZWtm -ZWxlbG9zc2VnLWJpenRvc2l0YXNhIHZlZGkuIEEgZGlnaXRhbGlzIGFsYWlyYXMg -ZWxmb2dhZGFzYW5hayBmZWx0ZXRlbGUgYXogZWxvaXJ0IGVsbGVub3J6ZXNpIGVs -amFyYXMgbWVndGV0ZWxlLiBBeiBlbGphcmFzIGxlaXJhc2EgbWVndGFsYWxoYXRv -IGEgTmV0TG9jayBLZnQuIEludGVybmV0IGhvbmxhcGphbiBhIGh0dHBzOi8vd3d3 -Lm5ldGxvY2submV0L2RvY3MgY2ltZW4gdmFneSBrZXJoZXRvIGF6IGVsbGVub3J6 -ZXNAbmV0bG9jay5uZXQgZS1tYWlsIGNpbWVuLiBJTVBPUlRBTlQhIFRoZSBpc3N1 -YW5jZSBhbmQgdGhlIHVzZSBvZiB0aGlzIGNlcnRpZmljYXRlIGlzIHN1YmplY3Qg -dG8gdGhlIE5ldExvY2sgQ1BTIGF2YWlsYWJsZSBhdCBodHRwczovL3d3dy5uZXRs -b2NrLm5ldC9kb2NzIG9yIGJ5IGUtbWFpbCBhdCBjcHNAbmV0bG9jay5uZXQuMA0G -CSqGSIb3DQEBBAUAA4IBAQBIJEb3ulZv+sgoA0BO5TE5ayZrU3/b39/zcT0mwBQO -xmd7I6gMc90Bu8bKbjc5VdXHjFYgDigKDtIqpLBJUsY4B/6+CgmM0ZjPytoUMaFP -0jn8DxEsQ8Pdq5PHVT5HfBgaANzze9jyf1JsIPQLX2lS9O74silg6+NJMSEN1rUQ -QeJBCWziGppWS3cC9qCbmieH6FUpccKQn0V4GuEVZD3QDtigdp+uxdAu6tYPVuxk -f1qbFFgBJ34TUMdrKuZoPL9coAob4Q566eKAw+np9v1sEZ7Q5SgnK1QyQhSCdeZK -8CtmdWOMovsEPoMOmzbwGOQmIMOM8CgHrTwXZoi1/baI ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIG0TCCBbmgAwIBAgIBezANBgkqhkiG9w0BAQUFADCByTELMAkGA1UEBhMCSFUx -ETAPBgNVBAcTCEJ1ZGFwZXN0MScwJQYDVQQKEx5OZXRMb2NrIEhhbG96YXRiaXp0 -b25zYWdpIEtmdC4xGjAYBgNVBAsTEVRhbnVzaXR2YW55a2lhZG9rMUIwQAYDVQQD -EzlOZXRMb2NrIE1pbm9zaXRldHQgS296amVneXpvaSAoQ2xhc3MgUUEpIFRhbnVz -aXR2YW55a2lhZG8xHjAcBgkqhkiG9w0BCQEWD2luZm9AbmV0bG9jay5odTAeFw0w -MzAzMzAwMTQ3MTFaFw0yMjEyMTUwMTQ3MTFaMIHJMQswCQYDVQQGEwJIVTERMA8G -A1UEBxMIQnVkYXBlc3QxJzAlBgNVBAoTHk5ldExvY2sgSGFsb3phdGJpenRvbnNh -Z2kgS2Z0LjEaMBgGA1UECxMRVGFudXNpdHZhbnlraWFkb2sxQjBABgNVBAMTOU5l -dExvY2sgTWlub3NpdGV0dCBLb3pqZWd5em9pIChDbGFzcyBRQSkgVGFudXNpdHZh -bnlraWFkbzEeMBwGCSqGSIb3DQEJARYPaW5mb0BuZXRsb2NrLmh1MIIBIjANBgkq -hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx1Ilstg91IRVCacbvWy5FPSKAtt2/Goq -eKvld/Bu4IwjZ9ulZJm53QE+b+8tmjwi8F3JV6BVQX/yQ15YglMxZc4e8ia6AFQe -r7C8HORSjKAyr7c3sVNnaHRnUPYtLmTeriZ539+Zhqurf4XsoPuAzPS4DB6TRWO5 -3Lhbm+1bOdRfYrCnjnxmOCyqsQhjF2d9zL2z8cM/z1A57dEZgxXbhxInlrfa6uWd -vLrqOU+L73Sa58XQ0uqGURzk/mQIKAR5BevKxXEOC++r6uwSEaEYBTJp0QwsGj0l -mT+1fMptsK6ZmfoIYOcZwvK9UdPM0wKswREMgM6r3JSda6M5UzrWhQIDAMV9o4IC -wDCCArwwEgYDVR0TAQH/BAgwBgEB/wIBBDAOBgNVHQ8BAf8EBAMCAQYwggJ1Bglg -hkgBhvhCAQ0EggJmFoICYkZJR1lFTEVNISBFemVuIHRhbnVzaXR2YW55IGEgTmV0 -TG9jayBLZnQuIE1pbm9zaXRldHQgU3pvbGdhbHRhdGFzaSBTemFiYWx5emF0YWJh -biBsZWlydCBlbGphcmFzb2sgYWxhcGphbiBrZXN6dWx0LiBBIG1pbm9zaXRldHQg -ZWxla3Ryb25pa3VzIGFsYWlyYXMgam9naGF0YXMgZXJ2ZW55ZXN1bGVzZW5laywg -dmFsYW1pbnQgZWxmb2dhZGFzYW5hayBmZWx0ZXRlbGUgYSBNaW5vc2l0ZXR0IFN6 -b2xnYWx0YXRhc2kgU3phYmFseXphdGJhbiwgYXogQWx0YWxhbm9zIFN6ZXJ6b2Rl -c2kgRmVsdGV0ZWxla2JlbiBlbG9pcnQgZWxsZW5vcnplc2kgZWxqYXJhcyBtZWd0 -ZXRlbGUuIEEgZG9rdW1lbnR1bW9rIG1lZ3RhbGFsaGF0b2sgYSBodHRwczovL3d3 -dy5uZXRsb2NrLmh1L2RvY3MvIGNpbWVuIHZhZ3kga2VyaGV0b2sgYXogaW5mb0Bu -ZXRsb2NrLm5ldCBlLW1haWwgY2ltZW4uIFdBUk5JTkchIFRoZSBpc3N1YW5jZSBh -bmQgdGhlIHVzZSBvZiB0aGlzIGNlcnRpZmljYXRlIGFyZSBzdWJqZWN0IHRvIHRo -ZSBOZXRMb2NrIFF1YWxpZmllZCBDUFMgYXZhaWxhYmxlIGF0IGh0dHBzOi8vd3d3 -Lm5ldGxvY2suaHUvZG9jcy8gb3IgYnkgZS1tYWlsIGF0IGluZm9AbmV0bG9jay5u -ZXQwHQYDVR0OBBYEFAlqYhaSsFq7VQ7LdTI6MuWyIckoMA0GCSqGSIb3DQEBBQUA -A4IBAQCRalCc23iBmz+LQuM7/KbD7kPgz/PigDVJRXYC4uMvBcXxKufAQTPGtpvQ -MznNwNuhrWw3AkxYQTvyl5LGSKjN5Yo5iWH5Upfpvfb5lHTocQ68d4bDBsxafEp+ -NFAwLvt/MpqNPfMgW/hqyobzMUwsWYACff44yTB1HLdV47yfuqhthCgFdbOLDcCR -VCHnpgu0mfVRQdzNo0ci2ccBgcTcR08m6h/t280NmPSjnLRzMkqWmf68f8glWPhY -83ZmiVSkpj7EUFy6iRiCdUgh0k8T6GB+B3bbELVR5qq5aKrN9p2QdRLqOBrKROi3 -macqaJVmlaut74nLYKkGEsaUR+ko ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIFSzCCBLSgAwIBAgIBaTANBgkqhkiG9w0BAQQFADCBmTELMAkGA1UEBhMCSFUx -ETAPBgNVBAcTCEJ1ZGFwZXN0MScwJQYDVQQKEx5OZXRMb2NrIEhhbG96YXRiaXp0 -b25zYWdpIEtmdC4xGjAYBgNVBAsTEVRhbnVzaXR2YW55a2lhZG9rMTIwMAYDVQQD -EylOZXRMb2NrIFV6bGV0aSAoQ2xhc3MgQikgVGFudXNpdHZhbnlraWFkbzAeFw05 -OTAyMjUxNDEwMjJaFw0xOTAyMjAxNDEwMjJaMIGZMQswCQYDVQQGEwJIVTERMA8G -A1UEBxMIQnVkYXBlc3QxJzAlBgNVBAoTHk5ldExvY2sgSGFsb3phdGJpenRvbnNh -Z2kgS2Z0LjEaMBgGA1UECxMRVGFudXNpdHZhbnlraWFkb2sxMjAwBgNVBAMTKU5l -dExvY2sgVXpsZXRpIChDbGFzcyBCKSBUYW51c2l0dmFueWtpYWRvMIGfMA0GCSqG -SIb3DQEBAQUAA4GNADCBiQKBgQCx6gTsIKAjwo84YM/HRrPVG/77uZmeBNwcf4xK -gZjupNTKihe5In+DCnVMm8Bp2GQ5o+2So/1bXHQawEfKOml2mrriRBf8TKPV/riX -iK+IA4kfpPIEPsgHC+b5sy96YhQJRhTKZPWLgLViqNhr1nGTLbO/CVRY7QbrqHvc -Q7GhaQIDAQABo4ICnzCCApswEgYDVR0TAQH/BAgwBgEB/wIBBDAOBgNVHQ8BAf8E -BAMCAAYwEQYJYIZIAYb4QgEBBAQDAgAHMIICYAYJYIZIAYb4QgENBIICURaCAk1G -SUdZRUxFTSEgRXplbiB0YW51c2l0dmFueSBhIE5ldExvY2sgS2Z0LiBBbHRhbGFu -b3MgU3pvbGdhbHRhdGFzaSBGZWx0ZXRlbGVpYmVuIGxlaXJ0IGVsamFyYXNvayBh -bGFwamFuIGtlc3p1bHQuIEEgaGl0ZWxlc2l0ZXMgZm9seWFtYXRhdCBhIE5ldExv -Y2sgS2Z0LiB0ZXJtZWtmZWxlbG9zc2VnLWJpenRvc2l0YXNhIHZlZGkuIEEgZGln -aXRhbGlzIGFsYWlyYXMgZWxmb2dhZGFzYW5hayBmZWx0ZXRlbGUgYXogZWxvaXJ0 -IGVsbGVub3J6ZXNpIGVsamFyYXMgbWVndGV0ZWxlLiBBeiBlbGphcmFzIGxlaXJh -c2EgbWVndGFsYWxoYXRvIGEgTmV0TG9jayBLZnQuIEludGVybmV0IGhvbmxhcGph -biBhIGh0dHBzOi8vd3d3Lm5ldGxvY2submV0L2RvY3MgY2ltZW4gdmFneSBrZXJo -ZXRvIGF6IGVsbGVub3J6ZXNAbmV0bG9jay5uZXQgZS1tYWlsIGNpbWVuLiBJTVBP -UlRBTlQhIFRoZSBpc3N1YW5jZSBhbmQgdGhlIHVzZSBvZiB0aGlzIGNlcnRpZmlj -YXRlIGlzIHN1YmplY3QgdG8gdGhlIE5ldExvY2sgQ1BTIGF2YWlsYWJsZSBhdCBo -dHRwczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIG9yIGJ5IGUtbWFpbCBhdCBjcHNA -bmV0bG9jay5uZXQuMA0GCSqGSIb3DQEBBAUAA4GBAATbrowXr/gOkDFOzT4JwG06 -sPgzTEdM43WIEJessDgVkcYplswhwG08pXTP2IKlOcNl40JwuyKQ433bNXbhoLXa -n3BukxowOR0w2y7jfLKRstE3Kfq51hdcR0/jHTjrn9V7lagonhVK0dHQKwCXoOKS -NitjrFgBazMpUIaD8QFI ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIID5jCCAs6gAwIBAgIQV8szb8JcFuZHFhfjkDFo4DANBgkqhkiG9w0BAQUFADBi -MQswCQYDVQQGEwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMu -MTAwLgYDVQQDEydOZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3Jp -dHkwHhcNMDYxMjAxMDAwMDAwWhcNMjkxMjMxMjM1OTU5WjBiMQswCQYDVQQGEwJV -UzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMuMTAwLgYDVQQDEydO -ZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0GCSqG -SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkvH6SMG3G2I4rC7xGzuAnlt7e+foS0zwz -c7MEL7xxjOWftiJgPl9dzgn/ggwbmlFQGiaJ3dVhXRncEg8tCqJDXRfQNJIg6nPP -OCwGJgl6cvf6UDL4wpPTaaIjzkGxzOTVHzbRijr4jGPiFFlp7Q3Tf2vouAPlT2rl -mGNpSAW+Lv8ztumXWWn4Zxmuk2GWRBXTcrA/vGp97Eh/jcOrqnErU2lBUzS1sLnF -BgrEsEX1QV1uiUV7PTsmjHTC5dLRfbIR1PtYMiKagMnc/Qzpf14Dl847ABSHJ3A4 -qY5usyd2mFHgBeMhqxrVhSI8KbWaFsWAqPS7azCPL0YCorEMIuDTAgMBAAGjgZcw -gZQwHQYDVR0OBBYEFCEwyfsA106Y2oeqKtCnLrFAMadMMA4GA1UdDwEB/wQEAwIB -BjAPBgNVHRMBAf8EBTADAQH/MFIGA1UdHwRLMEkwR6BFoEOGQWh0dHA6Ly9jcmwu -bmV0c29sc3NsLmNvbS9OZXR3b3JrU29sdXRpb25zQ2VydGlmaWNhdGVBdXRob3Jp -dHkuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQC7rkvnt1frf6ott3NHhWrB5KUd5Oc8 -6fRZZXe1eltajSU24HqXLjjAV2CDmAaDn7l2em5Q4LqILPxFzBiwmZVRDuwduIj/ -h1AcgsLj4DKAv6ALR8jDMe+ZZzKATxcheQxpXN5eNK4CtSbqUN9/GGUsyfJj4akH -/nxxH2szJGoeBfcFaMBqEssuXmHLrijTfsK0ZpEmXzwuJF/LWA/rKOyvEZbz3Htv -wKeI8lN3s2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHN -pGxlaKFJdlxDydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIID8TCCAtmgAwIBAgIQQT1yx/RrH4FDffHSKFTfmjANBgkqhkiG9w0BAQUFADCB -ijELMAkGA1UEBhMCQ0gxEDAOBgNVBAoTB1dJU2VLZXkxGzAZBgNVBAsTEkNvcHly -aWdodCAoYykgMjAwNTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNl -ZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQSBDQTAeFw0w -NTEyMTExNjAzNDRaFw0zNzEyMTExNjA5NTFaMIGKMQswCQYDVQQGEwJDSDEQMA4G -A1UEChMHV0lTZUtleTEbMBkGA1UECxMSQ29weXJpZ2h0IChjKSAyMDA1MSIwIAYD -VQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBX -SVNlS2V5IEdsb2JhbCBSb290IEdBIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A -MIIBCgKCAQEAy0+zAJs9Nt350UlqaxBJH+zYK7LG+DKBKUOVTJoZIyEVRd7jyBxR -VVuuk+g3/ytr6dTqvirdqFEr12bDYVxgAsj1znJ7O7jyTmUIms2kahnBAbtzptf2 -w93NvKSLtZlhuAGio9RN1AU9ka34tAhxZK9w8RxrfvbDd50kc3vkDIzh2TbhmYsF -mQvtRTEJysIA2/dyoJaqlYfQjse2YXMNdmaM3Bu0Y6Kff5MTMPGhJ9vZ/yxViJGg -4E8HsChWjBgbl0SOid3gF27nKu+POQoxhILYQBRJLnpB5Kf+42TMwVlxSywhp1t9 -4B3RLoGbw9ho972WG6xwsRYUC9tguSYBBQIDAQABo1EwTzALBgNVHQ8EBAMCAYYw -DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUswN+rja8sHnR3JQmthG+IbJphpQw -EAYJKwYBBAGCNxUBBAMCAQAwDQYJKoZIhvcNAQEFBQADggEBAEuh/wuHbrP5wUOx -SPMowB0uyQlB+pQAHKSkq0lPjz0e701vvbyk9vImMMkQyh2I+3QZH4VFvbBsUfk2 -ftv1TDI6QU9bR8/oCy22xBmddMVHxjtqD6wU2zz0c5ypBd8A3HR4+vg1YFkCExh8 -vPtNsCBtQ7tgMHpnM1zFmdH4LTlSc/uMqpclXHLZCB6rTjzjgTGfA6b7wP4piFXa -hNVQA7bihKOmNqoROgHhGEvWRGizPflTdISzRpFGlgC3gCy24eMQ4tui5yiPAZZi -Fj4A4xylNoEYokxSdsARo27mHbrjWr42U8U+dY+GaSlYU7Wcu2+fXMUY7N0v4ZjJ -/L7fCg0= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEajCCA1KgAwIBAgIBATANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJKUDEN -MAsGA1UECgwESlBLSTEpMCcGA1UECwwgUHJlZmVjdHVyYWwgQXNzb2NpYXRpb24g -Rm9yIEpQS0kxETAPBgNVBAsMCEJyaWRnZUNBMB4XDTAzMTIyNzA1MDgxNVoXDTEz -MTIyNjE0NTk1OVowWjELMAkGA1UEBhMCSlAxDTALBgNVBAoMBEpQS0kxKTAnBgNV -BAsMIFByZWZlY3R1cmFsIEFzc29jaWF0aW9uIEZvciBKUEtJMREwDwYDVQQLDAhC -cmlkZ2VDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANTnUmg7K3m8 -52vd77kwkq156euwoWm5no8E8kmaTSc7x2RABPpqNTlMKdZ6ttsyYrqREeDkcvPL -yF7yf/I8+innasNtsytcTAy8xY8Avsbd4JkCGW9dyPjk9pzzc3yLQ64Rx2fujRn2 -agcEVdPCr/XpJygX8FD5bbhkZ0CVoiASBmlHOcC3YpFlfbT1QcpOSOb7o+VdKVEi -MMfbBuU2IlYIaSr/R1nO7RPNtkqkFWJ1/nKjKHyzZje7j70qSxb+BTGcNgTHa1YA -UrogKB+UpBftmb4ds+XlkEJ1dvwokiSbCDaWFKD+YD4B2s0bvjCbw8xuZFYGhNyR -/2D5XfN1s2MCAwEAAaOCATkwggE1MA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E -BTADAQH/MG0GA1UdHwRmMGQwYqBgoF6kXDBaMQswCQYDVQQGEwJKUDENMAsGA1UE -CgwESlBLSTEpMCcGA1UECwwgUHJlZmVjdHVyYWwgQXNzb2NpYXRpb24gRm9yIEpQ -S0kxETAPBgNVBAsMCEJyaWRnZUNBMIGDBgNVHREEfDB6pHgwdjELMAkGA1UEBhMC -SlAxJzAlBgNVBAoMHuWFrOeahOWAi+S6uuiqjeiovOOCteODvOODk+OCuTEeMBwG -A1UECwwV6YO96YGT5bqc55yM5Y2U6K2w5LyaMR4wHAYDVQQLDBXjg5bjg6rjg4Pj -grjoqo3oqLzlsYAwHQYDVR0OBBYEFNQXMiCqQNkR2OaZmQgLtf8mR8p8MA0GCSqG -SIb3DQEBBQUAA4IBAQATjJo4reTNPC5CsvAKu1RYT8PyXFVYHbKsEpGt4GR8pDCg -HEGAiAhHSNrGh9CagZMXADvlG0gmMOnXowriQQixrtpkmx0TB8tNAlZptZWkZC+R -8TnjOkHrk2nFAEC3ezbdK0R7MR4tJLDQCnhEWbg50rf0wZ/aF8uAaVeEtHXa6W0M -Xq3dSe0XAcrLbX4zZHQTaWvdpLAIjl6DZ3SCieRMyoWUL+LXaLFdTP5WBCd+No58 -IounD9X4xxze2aeRVaiV/WnQ0OSPNS7n7YXy6xQdnaOU4KRW/Lne1EDf5IfWC/ih -bVAmhZMbcrkWWcsR6aCPG+2mV3zTD6AUzuKPal8Y ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIFtzCCA5+gAwIBAgICBQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0x -GTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJv -b3QgQ0EgMjAeFw0wNjExMjQxODI3MDBaFw0zMTExMjQxODIzMzNaMEUxCzAJBgNV -BAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9W -YWRpcyBSb290IENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCa -GMpLlA0ALa8DKYrwD4HIrkwZhR0In6spRIXzL4GtMh6QRr+jhiYaHv5+HBg6XJxg -Fyo6dIMzMH1hVBHL7avg5tKifvVrbxi3Cgst/ek+7wrGsxDp3MJGF/hd/aTa/55J -WpzmM+Yklvc/ulsrHHo1wtZn/qtmUIttKGAr79dgw8eTvI02kfN/+NsRE8Scd3bB -rrcCaoF6qUWD4gXmuVbBlDePSHFjIuwXZQeVikvfj8ZaCuWw419eaxGrDPmF60Tp -+ARz8un+XJiM9XOva7R+zdRcAitMOeGylZUtQofX1bOQQ7dsE/He3fbE+Ik/0XX1 -ksOR1YqI0JDs3G3eicJlcZaLDQP9nL9bFqyS2+r+eXyt66/3FsvbzSUr5R/7mp/i -Ucw6UwxI5g69ybR2BlLmEROFcmMDBOAENisgGQLodKcftslWZvB1JdxnwQ5hYIiz -PtGo/KPaHbDRsSNU30R2be1B2MGyIrZTHN81Hdyhdyox5C315eXbyOD/5YDXC2Og -/zOhD7osFRXql7PSorW+8oyWHhqPHWykYTe5hnMz15eWniN9gqRMgeKh0bpnX5UH -oycR7hYQe7xFSkyyBNKr79X9DFHOUGoIMfmR2gyPZFwDwzqLID9ujWc9Otb+fVuI -yV77zGHcizN300QyNQliBJIWENieJ0f7OyHj+OsdWwIDAQABo4GwMIGtMA8GA1Ud -EwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1UdDgQWBBQahGK8SEwzJQTU7tD2 -A8QZRtGUazBuBgNVHSMEZzBlgBQahGK8SEwzJQTU7tD2A8QZRtGUa6FJpEcwRTEL -MAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMT -ElF1b1ZhZGlzIFJvb3QgQ0EgMoICBQkwDQYJKoZIhvcNAQEFBQADggIBAD4KFk2f -BluornFdLwUvZ+YTRYPENvbzwCYMDbVHZF34tHLJRqUDGCdViXh9duqWNIAXINzn -g/iN/Ae42l9NLmeyhP3ZRPx3UIHmfLTJDQtyU/h2BwdBR5YM++CCJpNVjP4iH2Bl -fF/nJrP3MpCYUNQ3cVX2kiF495V5+vgtJodmVjB3pjd4M1IQWK4/YY7yarHvGH5K -WWPKjaJW1acvvFYfzznB4vsKqBUsfU16Y8Zsl0Q80m/DShcK+JDSV6IZUaUtl0Ha -B0+pUNqQjZRG4T7wlP0QADj1O+hA4bRuVhogzG9Yje0uRY/W6ZM/57Es3zrWIozc -hLsib9D45MY56QSIPMO661V6bYCZJPVsAfv4l7CUW+v90m/xd2gNNWQjrLhVoQPR -TUIZ3Ph1WVaj+ahJefivDrkRoHy3au000LYmYjgahwz46P0u05B/B5EqHdZ+XIWD -mbA4CD/pXvk1B+TJYm5Xf6dQlfe6yJvmjqIBxdZmv3lh8zwc4bmCXF2gw+nYSL0Z -ohEUGW6yhhtoPkg3Goi3XZZenMfvJ2II4pEZXNLxId26F0KCl3GBUzGpn/Z9Yr9y -4aOTHcyKJloJONDO1w2AFrR4pTqHTI2KpdVGl/IsELm8VCLAAVBpQ570su9t+Oza -8eOx79+Rj1QqCyXBJhnEUhAFZdWCEOrCMc0u ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0x -GTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJv -b3QgQ0EgMzAeFw0wNjExMjQxOTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNV -BAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9W -YWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDM -V0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNggDhoB -4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUr -H556VOijKTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd -8lyyBTNvijbO0BNO/79KDDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9Cabwv -vWhDFlaJKjdhkf2mrk7AyxRllDdLkgbvBNDInIjbC3uBr7E9KsRlOni27tyAsdLT -mZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwpp5ijJUMv7/FfJuGITfhe -btfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8nT8KKdjc -T5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDt -WAEXMJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZ -c6tsgLjoC2SToJyMGf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A -4iLItLRkT9a6fUg+qGkM17uGcclzuD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYD -VR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHTBgkrBgEEAb5YAAMwgcUwgZMG -CCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmljYXRlIGNvbnN0 -aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0 -aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVu -dC4wLQYIKwYBBQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2Nw -czALBgNVHQ8EBAMCAQYwHQYDVR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4G -A1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4ywLQoUmkRzBFMQswCQYDVQQGEwJC -TTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UEAxMSUXVvVmFkaXMg -Um9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZVqyM0 -7ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSem -d1o417+shvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd -+LJ2w/w4E6oM3kJpK27zPOuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B -4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadN -t54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp8kokUvd0/bpO5qgdAm6x -DYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBCbjPsMZ57 -k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6s -zHXug/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0j -Wy10QJLZYxkNc91pvGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeT -mJlglFwjz1onl14LBQaTNx47aTbrqZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK -4SVhM7JZG+Ju1zdXtg2pEto= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIF0DCCBLigAwIBAgIEOrZQizANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJC -TTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDElMCMGA1UECxMcUm9vdCBDZXJ0 -aWZpY2F0aW9uIEF1dGhvcml0eTEuMCwGA1UEAxMlUXVvVmFkaXMgUm9vdCBDZXJ0 -aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMTAzMTkxODMzMzNaFw0yMTAzMTcxODMz -MzNaMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUw -IwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQDEyVR -dW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG -9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv2G1lVO6V/z68mcLOhrfEYBklbTRvM16z/Yp -li4kVEAkOPcahdxYTMukJ0KX0J+DisPkBgNbAKVRHnAEdOLB1Dqr1607BxgFjv2D -rOpm2RgbaIr1VxqYuvXtdj182d6UajtLF8HVj71lODqV0D1VNk7feVcxKh7YWWVJ -WCCYfqtffp/p1k3sg3Spx2zY7ilKhSoGFPlU5tPaZQeLYzcS19Dsw3sgQUSj7cug -F+FxZc4dZjH3dgEZyH0DWLaVSR2mEiboxgx24ONmy+pdpibu5cxfvWenAScOospU -xbF6lR1xHkopigPcakXBpBlebzbNw6Kwt/5cOOJSvPhEQ+aQuwIDAQABo4ICUjCC -Ak4wPQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwczovL29jc3AucXVv -dmFkaXNvZmZzaG9yZS5jb20wDwYDVR0TAQH/BAUwAwEB/zCCARoGA1UdIASCAREw -ggENMIIBCQYJKwYBBAG+WAABMIH7MIHUBggrBgEFBQcCAjCBxxqBxFJlbGlhbmNl -IG9uIHRoZSBRdW9WYWRpcyBSb290IENlcnRpZmljYXRlIGJ5IGFueSBwYXJ0eSBh -c3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJsZSBzdGFuZGFy -ZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRpb24gcHJh -Y3RpY2VzLCBhbmQgdGhlIFF1b1ZhZGlzIENlcnRpZmljYXRlIFBvbGljeS4wIgYI -KwYBBQUHAgEWFmh0dHA6Ly93d3cucXVvdmFkaXMuYm0wHQYDVR0OBBYEFItLbe3T -KbkGGew5Oanwl4Rqy+/fMIGuBgNVHSMEgaYwgaOAFItLbe3TKbkGGew5Oanwl4Rq -y+/foYGEpIGBMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1p -dGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYD -VQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggQ6tlCL -MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAitQUtf70mpKnGdSk -fnIYj9lofFIk3WdvOXrEql494liwTXCYhGHoG+NpGA7O+0dQoE7/8CQfvbLO9Sf8 -7C9TqnN7Az10buYWnuulLsS/VidQK2K6vkscPFVcQR0kvoIgR13VRH56FmjffU1R -cHhXHTMe/QKZnAzNCgVPx7uOpHX6Sm2xgI4JVrmcGmD+XcHXetwReNDWXcG31a0y -mQM6isxUJTkxgXsTIlG6Rmyhu576BGxJJnSP0nPrzDCi5upZIof4l/UO/erMkqQW -xFIY6iHOsfHmhIHluqmGKPJDWl0Snawe2ajlCmqnf6CHKc/yiU3U7MXi5nrQNiOK -SnQ2+Q== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIICXDCCAcWgAwIBAgIQCgEBAQAAAnwAAAALAAAAAjANBgkqhkiG9w0BAQUFADA6 -MRkwFwYDVQQKExBSU0EgU2VjdXJpdHkgSW5jMR0wGwYDVQQLExRSU0EgU2VjdXJp -dHkgMTAyNCBWMzAeFw0wMTAyMjIyMTAxNDlaFw0yNjAyMjIyMDAxNDlaMDoxGTAX -BgNVBAoTEFJTQSBTZWN1cml0eSBJbmMxHTAbBgNVBAsTFFJTQSBTZWN1cml0eSAx -MDI0IFYzMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDV3f5mCc8kPD6ugU5O -isRpgFtZO9+5TUzKtS3DJy08rwBCbbwoppbPf9dYrIMKo1W1exeQFYRMiu4mmdxY -78c4pqqv0I5CyGLXq6yp+0p9v+r+Ek3d/yYtbzZUaMjShFbuklNhCbM/OZuoyZu9 -zp9+1BlqFikYvtc6adwlWzMaUQIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4G -A1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBTEwBykB5T9zU0B1FTapQxf3q4FWjAd -BgNVHQ4EFgQUxMAcpAeU/c1NAdRU2qUMX96uBVowDQYJKoZIhvcNAQEFBQADgYEA -Py1q4yZDlX2Jl2X7deRyHUZXxGFraZ8SmyzVWujAovBDleMf6XbN3Ou8k6BlCsdN -T1+nr6JGFLkM88y9am63nd4lQtBU/55oc2PcJOsiv6hy8l4A4Q1OOkNumU4/iXgD -mMrzVcydro7BqkWY+o8aoI2II/EVQQ2lRj6RP4vr93E= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDYTCCAkmgAwIBAgIQCgEBAQAAAnwAAAAKAAAAAjANBgkqhkiG9w0BAQUFADA6 -MRkwFwYDVQQKExBSU0EgU2VjdXJpdHkgSW5jMR0wGwYDVQQLExRSU0EgU2VjdXJp -dHkgMjA0OCBWMzAeFw0wMTAyMjIyMDM5MjNaFw0yNjAyMjIyMDM5MjNaMDoxGTAX -BgNVBAoTEFJTQSBTZWN1cml0eSBJbmMxHTAbBgNVBAsTFFJTQSBTZWN1cml0eSAy -MDQ4IFYzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAt49VcdKA3Xtp -eafwGFAyPGJn9gqVB93mG/Oe2dJBVGutn3y+Gc37RqtBaB4Y6lXIL5F4iSj7Jylg -/9+PjDvJSZu1pJTOAeo+tWN7fyb9Gd3AIb2E0S1PRsNO3Ng3OTsor8udGuorryGl -wSMiuLgbWhOHV4PR8CDn6E8jQrAApX2J6elhc5SYcSa8LWrg903w8bYqODGBDSnh -AMFRD0xS+ARaqn1y07iHKrtjEAMqs6FPDVpeRrc9DvV07Jmf+T0kgYim3WBU6JU2 -PcYJk5qjEoAAVZkZR73QpXzDuvsf9/UP+Ky5tfQ3mBMY3oVbtwyCO4dvlTlYMNpu -AWgXIszACwIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB -BjAfBgNVHSMEGDAWgBQHw1EwpKrpRa41JPr/JCwz0LGdjDAdBgNVHQ4EFgQUB8NR -MKSq6UWuNST6/yQsM9CxnYwwDQYJKoZIhvcNAQEFBQADggEBAF8+hnZuuDU8TjYc -HnmYv/3VEhF5Ug7uMYm83X/50cYVIeiKAVQNOvtUudZj1LGqlk2iQk3UUx+LEN5/ -Zb5gEydxiKRz44Rj0aRV4VCT5hsOedBnvEbIvz8XDZXmxpBp3ue0L96VfdASPz0+ -f00/FGj1EVDVwfSQpQgdMWD/YIwjVAqv/qFuxdF6Kmh4zx6CCiC0H63lhbJqaHVO -rSU3lIW+vaHU6rcMSzyd6BIA8F+sDeGscGNz9395nzIlQnQFgCi/vcEkllgVsRch -6YlL2weIZ/QVrXA+L02FO8K32/6YaCOJ4XQP3vTFhGMpG8zLB8kApKnXwiJPZ9d3 -7CAFYd4= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEPzCCAyegAwIBAgIBATANBgkqhkiG9w0BAQUFADB+MQswCQYDVQQGEwJHQjEb -MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow -GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEkMCIGA1UEAwwbU2VjdXJlIENlcnRp -ZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVow -fjELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G -A1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxJDAiBgNV -BAMMG1NlY3VyZSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEB -BQADggEPADCCAQoCggEBAMBxM4KK0HDrc4eCQNUd5MvJDkKQ+d40uaG6EfQlhfPM -cm3ye5drswfxdySRXyWP9nQ95IDC+DwN879A6vfIUtFyb+/Iq0G4bi4XKpVpDM3S -HpR7LZQdqnXXs5jLrLxkU0C8j6ysNstcrbvd4JQX7NFc0L/vpZXJkMWwrPsbQ996 -CF23uPJAGysnnlDOXmWCiIxe004MeuoIkbY2qitC++rCoznl2yY4rYsK7hljxxwk -3wN42ubqwUcaCwtGCd0C/N7Lh1/XMGNooa7cMqG6vv5Eq2i2pRcV/b3Vp6ea5EQz -6YiO/O1R65NxTq0B50SOqy3LqP4BSUjwwN3HaNiS/j0CAwEAAaOBxzCBxDAdBgNV -HQ4EFgQUPNiTiMLAggnMAZkGkyDpnnAJY08wDgYDVR0PAQH/BAQDAgEGMA8GA1Ud -EwEB/wQFMAMBAf8wgYEGA1UdHwR6MHgwO6A5oDeGNWh0dHA6Ly9jcmwuY29tb2Rv -Y2EuY29tL1NlY3VyZUNlcnRpZmljYXRlU2VydmljZXMuY3JsMDmgN6A1hjNodHRw -Oi8vY3JsLmNvbW9kby5uZXQvU2VjdXJlQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmww -DQYJKoZIhvcNAQEFBQADggEBAIcBbSMdflsXfcFhMs+P5/OKlFlm4J4oqF7Tt/Q0 -5qo5spcWxYJvMqTpjOev/e/C6LlLqqP05tqNZSH7uoDrJiiFGv45jN5bBAS0VPmj -Z55B+glSzAVIqMk/IQQezkhr/IXownuvf7fM+F86/TXGDe+X3EyrEeFryzHRbPtI -gKvcnDe4IRRLDXE97IMzbtFuMhbsmMcWi1mmNKsFVy2T96oTy9IT4rcuO81rUBcJ -aD61JlfutuC23bkpgHl9j6PwpCikFcSF9CfUa7/lXORlAnZUtOM3ZiTTGWHIUhDl -izeauan5Hb/qmZJhlv8BzaFfDbxxvA6sCx1HRR3B7Hzs/Sk= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBK -MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x -GTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkx -MjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3Qg -Q29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwgQ0EwggEiMA0GCSqG -SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jxYDiJ -iQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa -/FHtaMbQbqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJ -jnIFHovdRIWCQtBJwB1g8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnI -HmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYVHDGA76oYa8J719rO+TMg1fW9ajMtgQT7 -sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi0XPnj3pDAgMBAAGjgZ0w -gZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1UdEwEB/wQF -MAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCsw -KaAnoCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsG -AQQBgjcVAQQDAgEAMA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0L -URYD7xh8yOOvaliTFGCRsoTciE6+OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXO -H0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cnCDpOGR86p1hcF895P4vkp9Mm -I50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/53CYNv6ZHdAbY -iNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc -f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIICNDCCAaECEAKtZn5ORf5eV288mBle3cAwDQYJKoZIhvcNAQECBQAwXzELMAkG -A1UEBhMCVVMxIDAeBgNVBAoTF1JTQSBEYXRhIFNlY3VyaXR5LCBJbmMuMS4wLAYD -VQQLEyVTZWN1cmUgU2VydmVyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk0 -MTEwOTAwMDAwMFoXDTEwMDEwNzIzNTk1OVowXzELMAkGA1UEBhMCVVMxIDAeBgNV -BAoTF1JTQSBEYXRhIFNlY3VyaXR5LCBJbmMuMS4wLAYDVQQLEyVTZWN1cmUgU2Vy -dmVyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGbMA0GCSqGSIb3DQEBAQUAA4GJ -ADCBhQJ+AJLOesGugz5aqomDV6wlAXYMra6OLDfO6zV4ZFQD5YRAUcm/jwjiioII -0haGN1XpsSECrXZogZoFokvJSyVmIlZsiAeP94FZbYQHZXATcXY+m3dM41CJVphI -uR2nKRoTLkoRWZweFdVJVCxzOmmCsZc5nG1wZ0jl3S3WyB57AgMBAAEwDQYJKoZI -hvcNAQECBQADfgBl3X7hsuyw4jrg7HFGmhkRuNPHoLQDQCYCPgmc4RKz0Vr2N6W3 -YQO2WxZpO8ZECAyIUwxrl0nHPjXcbLm7qt9cuzovk2C2qUtN8iD3zV9/ZHuO3ABc -1/p3yjkWWW8O6tO1g39NTUJWdrTJXwT4OPjr0l91X817/OWOgHz8UA== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBI -MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x -FzAVBgNVBAMTDlNlY3VyZVRydXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIz -MTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAeBgNVBAoTF1NlY3VyZVRydXN0IENv -cnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCCASIwDQYJKoZIhvcN -AQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQXOZEz -Zum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO -0gMdA+9tDWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIao -wW8xQmxSPmjL8xk037uHGFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj -7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b01k/unK8RCSc43Oz969XL0Imnal0ugBS -8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmHursCAwEAAaOBnTCBmjAT -BgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB -/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCeg -JYYjaHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGC -NxUBBAMCAQAwDQYJKoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt3 -6Z3q059c4EVlew3KW+JwULKUBRSuSceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/ -3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHfmbx8IVQr5Fiiu1cprp6poxkm -D5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZnMUFdAvnZyPS -CPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR -3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEY -MBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21t -dW5pY2F0aW9uIFJvb3RDQTEwHhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5 -WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYD -VQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEwggEiMA0GCSqGSIb3 -DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw8yl8 -9f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJ -DKaVv0uMDPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9 -Ms+k2Y7CI9eNqPPYJayX5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/N -QV3Is00qVUarH9oe4kA92819uZKAnDfdDJZkndwi92SL32HeFZRSFaB9UslLqCHJ -xrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2JChzAgMBAAGjPzA9MB0G -A1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYwDwYDVR0T -AQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vG -kl3g0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfr -Uj94nK9NrvjVT8+amCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5 -Bw+SUEmK3TGXX8npN6o7WWWXlDLJs58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJU -JRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ6rBK+1YWc26sTfcioU+tHXot -RSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAiFL39vmwLAw== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIID+zCCAuOgAwIBAgIENuWNnjANBgkqhkiG9w0BAQUFADCBtDELMAkGA1UEBhMC -VVkxKzApBgNVBAoTIkFETUlOSVNUUkFDSU9OIE5BQ0lPTkFMIERFIENPUlJFT1Mx -HzAdBgNVBAsTFlNFUlZJQ0lPUyBFTEVDVFJPTklDT1MxLDAqBgNVBAMTI1NFUlZJ -Q0lPUyBERSBDRVJUSUZJQ0FDSU9OIC0gQS5OLkMuMSkwJwYKCZImiZPyLGQBAxQZ -Y29ycmVvX2NlcnRAY29ycmVvLmNvbS51eTAeFw05OTAzMDkyMTA4MDdaFw0wOTAz -MDkyMTA4MDdaMIG0MQswCQYDVQQGEwJVWTErMCkGA1UEChMiQURNSU5JU1RSQUNJ -T04gTkFDSU9OQUwgREUgQ09SUkVPUzEfMB0GA1UECxMWU0VSVklDSU9TIEVMRUNU -Uk9OSUNPUzEsMCoGA1UEAxMjU0VSVklDSU9TIERFIENFUlRJRklDQUNJT04gLSBB -Lk4uQy4xKTAnBgoJkiaJk/IsZAEDFBljb3JyZW9fY2VydEBjb3JyZW8uY29tLnV5 -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsiov7CtZakOTiUYqiuXs -+gX64sjeQWuvA9sAWu9IN89XifvdyZIQ3ncDlRyQPse2ZyU7VZjv2Tz+JuSKO0Sp -dDeDCncndLipca3dlxPSyqIuuLqdyb5Z6Nly8oqFZhxHXrSHgtYP32cmpr02sfNd -kFBRdjIsOy+qX2Fe41TVEl3/DY0Rx4J6Nt/hTBbEdN0tau/QsfAzp/6/N2dDEi55 -SpSvhPsHEQhOMJN16QFUzsXeFIbwrq6bciUPRHfi82yveZwuSceemHYyFpq8AN7g -tCAFkRfdgBUU7jZBxCGP7tkAShnGcWGlEV0AO+SndGw6Sm6D4HoxXCFl+AiHQodn -5QIDAQABoxMwETAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQCZ -H0kiXPhlf4NukGYvAs+09lY6Zjaht5INNsNFWDZL5szxWsxzMp6aqK7Tduvv/oAs -4xA0skefHCVq6ES1j0y+gfPQwMELzQMWoEJVVk7B47QgrV+btlVfSBAS7ySzVnzM -BRuyySqpaBGSfi/pP0Tx0MaQG0vd92Ei7GmGFUCz4qVqd/Oz8lQn2kkqZBn0Od58 -dobZnHJXCjT19S/QOWgb20WlGOOAVDuTEJAUwhQBqqV2LX0P5Fbz/3Mqb47B2ID7 -u5AdGxpJnARjxEId82+7s0lK3UftSboCLSqMxwNWueJo0MGwhrWMSzqujRyIhEz9 -UK+ZJnYIwoCtKHlV0y3m ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDIDCCAgigAwIBAgIBJDANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEP -MA0GA1UEChMGU29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MxIENBMB4XDTAx -MDQwNjEwNDkxM1oXDTIxMDQwNjEwNDkxM1owOTELMAkGA1UEBhMCRkkxDzANBgNV -BAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJhIENsYXNzMSBDQTCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBALWJHytPZwp5/8Ue+H887dF+2rDNbS82rDTG -29lkFwhjMDMiikzujrsPDUJVyZ0upe/3p4zDq7mXy47vPxVnqIJyY1MPQYx9EJUk -oVqlBvqSV536pQHydekfvFYmUk54GWVYVQNYwBSujHxVX3BbdyMGNpfzJLWaRpXk -3w0LBUXl0fIdgrvGE+D+qnr9aTCU89JFhfzyMlsy3uhsXR/LpCJ0sICOXZT3BgBL -qdReLjVQCfOAl/QMF6452F/NM8EcyonCIvdFEu1eEpOdY6uCLrnrQkFEy0oaAIIN -nvmLVz5MxxftLItyM19yejhW1ebZrgUaHXVFsculJRwSVzb9IjcCAwEAAaMzMDEw -DwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQIR+IMi/ZTiFIwCwYDVR0PBAQDAgEG -MA0GCSqGSIb3DQEBBQUAA4IBAQCLGrLJXWG04bkruVPRsoWdd44W7hE928Jj2VuX -ZfsSZ9gqXLar5V7DtxYvyOirHYr9qxp81V9jz9yw3Xe5qObSIjiHBxTZ/75Wtf0H -DjxVyhbMp6Z3N/vbXB9OWQaHowND9Rart4S9Tu+fMTfwRvFAttEMpWT4Y14h21VO -TzF2nBBhjrZTOqMRvq9tfB69ri3iDGnHhVNoomG6xT60eVR4ngrHAr5i0RGCS2Uv -kVrCqIexVmiUefkl98HVrhq4uz2PqYo4Ffdz0Fpg0YCw8NzVUM1O7pJIae2yIx4w -zMiUyLb1O4Z/P6Yun/Y+LLWSlj7fLJOK/4GMDw9ZIRlXvVWa ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDIDCCAgigAwIBAgIBHTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEP -MA0GA1UEChMGU29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MyIENBMB4XDTAx -MDQwNjA3Mjk0MFoXDTIxMDQwNjA3Mjk0MFowOTELMAkGA1UEBhMCRkkxDzANBgNV -BAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJhIENsYXNzMiBDQTCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBAJAXSjWdyvANlsdE+hY3/Ei9vX+ALTU74W+o -Z6m/AxxNjG8yR9VBaKQTBME1DJqEQ/xcHf+Js+gXGM2RX/uJ4+q/Tl18GybTdXnt -5oTjV+WtKcT0OijnpXuENmmz/V52vaMtmdOQTiMofRhj8VQ7Jp12W5dCsv+u8E7s -3TmVToMGf+dJQMjFAbJUWmYdPfz56TwKnoG4cPABi+QjVHzIrviQHgCWctRUz2Ej -vOr7nQKV0ba5cTppCD8PtOFCx4j1P5iop7oc4HFx71hXgVB6XGt0Rg6DA5jDjqhu -8nYybieDwnPz3BjotJPqdURrBGAgcVeHnfO+oJAjPYok4doh28MCAwEAAaMzMDEw -DwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQISqCqWITTXjwwCwYDVR0PBAQDAgEG -MA0GCSqGSIb3DQEBBQUAA4IBAQBazof5FnIVV0sd2ZvnoiYw7JNn39Yt0jSv9zil -zqsWuasvfDXLrNAPtEwr/IDva4yRXzZ299uzGxnq9LIR/WFxRL8oszodv7ND6J+/ -3DEIcbCdjdY0RzKQxmUk96BKfARzjzlvF4xytb1LyHr4e4PDKE6cCepnP7JnBBvD -FNr450kkkdAdavphOe9r5yF1BgfYErQhIHBCcYHaPJo2vqZbDWpsmh+Re/n570K6 -Tk6ezAyNlNzZRZxe7EJQY670XcSxEtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2 -ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLHllpwrN9M ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDujCCAqKgAwIBAgIEAJiWijANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQGEwJO -TDEeMBwGA1UEChMVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSYwJAYDVQQDEx1TdGFh -dCBkZXIgTmVkZXJsYW5kZW4gUm9vdCBDQTAeFw0wMjEyMTcwOTIzNDlaFw0xNTEy -MTYwOTE1MzhaMFUxCzAJBgNVBAYTAk5MMR4wHAYDVQQKExVTdGFhdCBkZXIgTmVk -ZXJsYW5kZW4xJjAkBgNVBAMTHVN0YWF0IGRlciBOZWRlcmxhbmRlbiBSb290IENB -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmNK1URF6gaYUmHFtvszn -ExvWJw56s2oYHLZhWtVhCb/ekBPHZ+7d89rFDBKeNVU+LCeIQGv33N0iYfXCxw71 -9tV2U02PjLwYdjeFnejKScfST5gTCaI+Ioicf9byEGW07l8Y1Rfj+MX94p2i71MO -hXeiD+EwR+4A5zN9RGcaC1Hoi6CeUJhoNFIfLm0B8mBF8jHrqTFoKbt6QZ7GGX+U -tFE5A3+y3qcym7RHjm+0Sq7lr7HcsBthvJly3uSJt3omXdozSVtSnA71iq3DuD3o -BmrC1SoLbHuEvVYFy4ZlkuxEK7COudxwC0barbxjiDn622r+I/q85Ej0ZytqERAh -SQIDAQABo4GRMIGOMAwGA1UdEwQFMAMBAf8wTwYDVR0gBEgwRjBEBgRVHSAAMDww -OgYIKwYBBQUHAgEWLmh0dHA6Ly93d3cucGtpb3ZlcmhlaWQubmwvcG9saWNpZXMv -cm9vdC1wb2xpY3kwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSofeu8Y6R0E3QA -7Jbg0zTBLL9s+DANBgkqhkiG9w0BAQUFAAOCAQEABYSHVXQ2YcG70dTGFagTtJ+k -/rvuFbQvBgwp8qiSpGEN/KtcCFtREytNwiphyPgJWPwtArI5fZlmgb9uXJVFIGzm -eafR2Bwp/MIgJ1HI8XxdNGdphREwxgDS1/PTfLbwMVcoEoJz6TMvplW0C5GUR5z6 -u3pCMuiufi3IvKwUv9kP2Vv8wfl6leF9fpb8cbDCTMjfRTTJzg3ynGQI0DvDKcWy -7ZAEwbEpkcUwb8GpcjPM/l0WFywRaed+/sWDCN+83CI6LiBpIzlWYGeQiy52OfsR -iJf2fL1LuCAWZwWN4jvBcj+UlTfHXbme2JOhF4//DGYVwSR8MnwDHTuhWEUykw== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIFyjCCA7KgAwIBAgIEAJiWjDANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJO -TDEeMBwGA1UECgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFh -dCBkZXIgTmVkZXJsYW5kZW4gUm9vdCBDQSAtIEcyMB4XDTA4MDMyNjExMTgxN1oX -DTIwMDMyNTExMDMxMFowWjELMAkGA1UEBhMCTkwxHjAcBgNVBAoMFVN0YWF0IGRl -ciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5lZGVybGFuZGVuIFJv -b3QgQ0EgLSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMVZ5291 -qj5LnLW4rJ4L5PnZyqtdj7U5EILXr1HgO+EASGrP2uEGQxGZqhQlEq0i6ABtQ8Sp -uOUfiUtnvWFI7/3S4GCI5bkYYCjDdyutsDeqN95kWSpGV+RLufg3fNU254DBtvPU -Z5uW6M7XxgpT0GtJlvOjCwV3SPcl5XCsMBQgJeN/dVrlSPhOewMHBPqCYYdu8DvE -pMfQ9XQ+pV0aCPKbJdL2rAQmPlU6Yiile7Iwr/g3wtG61jj99O9JMDeZJiFIhQGp -5Rbn3JBV3w/oOM2ZNyFPXfUib2rFEhZgF1XyZWampzCROME4HYYEhLoaJXhena/M -UGDWE4dS7WMfbWV9whUYdMrhfmQpjHLYFhN9C0lK8SgbIHRrxT3dsKpICT0ugpTN -GmXZK4iambwYfp/ufWZ8Pr2UuIHOzZgweMFvZ9C+X+Bo7d7iscksWXiSqt8rYGPy -5V6548r6f1CGPqI0GAwJaCgRHOThuVw+R7oyPxjMW4T182t0xHJ04eOLoEq9jWYv -6q012iDTiIJh8BIitrzQ1aTsr1SIJSQ8p22xcik/Plemf1WvbibG/ufMQFxRRIEK -eN5KzlW/HdXZt1bv8Hb/C3m1r737qWmRRpdogBQ2HbN/uymYNqUg+oJgYjOk7Na6 -B6duxc8UpufWkjTYgfX8HV2qXB72o007uPc5AgMBAAGjgZcwgZQwDwYDVR0TAQH/ -BAUwAwEB/zBSBgNVHSAESzBJMEcGBFUdIAAwPzA9BggrBgEFBQcCARYxaHR0cDov -L3d3dy5wa2lvdmVyaGVpZC5ubC9wb2xpY2llcy9yb290LXBvbGljeS1HMjAOBgNV -HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJFoMocVHYnitfGsNig0jQt8YojrMA0GCSqG -SIb3DQEBCwUAA4ICAQCoQUpnKpKBglBu4dfYszk78wIVCVBR7y29JHuIhjv5tLyS -CZa59sCrI2AGeYwRTlHSeYAz+51IvuxBQ4EffkdAHOV6CMqqi3WtFMTC6GY8ggen -5ieCWxjmD27ZUD6KQhgpxrRW/FYQoAUXvQwjf/ST7ZwaUb7dRUG/kSS0H4zpX897 -IZmflZ85OkYcbPnNe5yQzSipx6lVu6xiNGI1E0sUOlWDuYaNkqbG9AclVMwWVxJK -gnjIFNkXgiYtXSAfea7+1HAWFpWD2DU5/1JddRwWxRNVz0fMdWVSSt7wsKfkCpYL -+63C4iWEst3kvX5ZbJvw8NjnyvLplzh+ib7M+zkXYT9y2zqR2GUBGR2tUKRXCnxL -vJxxcypFURmFzI79R6d0lR2o0a9OF7FpJsKqeFdbxU2n5Z4FF5TKsl+gSRiNNOkm -bEgeqmiSBeGCc1qb3AdbCG19ndeNIdn8FCCqwkXfP+cAslHkwvgFuXkajDTznlvk -N1trSt8sV4pAWja63XVECDdCcAz+3F4hoKOKwJCcaNpQ5kUQR3i2TtJlycM33+FC -Y7BXN0Ute4qcvwXqZVUz9zkQxSgqIXobisQk+T8VyJoVIPVVYpbtbZNQvOSqeK3Z -ywplh6ZmwcSBo3c6WB4L7oOLnR7SUqTMHW+wmG2UMbX4cQrcufx9MmDm66+KAQ== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzEl -MCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMp -U3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQw -NjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBoMQswCQYDVQQGEwJVUzElMCMGA1UE -ChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZp -ZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqGSIb3 -DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf -8MOh2tTYbitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN -+lq2cwQlZut3f+dZxkqZJRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0 -X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVmepsZGD3/cVE8MC5fvj13c7JdBmzDI1aa -K4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSNF4Azbl5KXZnJHoe0nRrA -1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HFMIHCMB0G -A1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fR -zt0fhvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0 -YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBD -bGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8w -DQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGsafPzWdqbAYcaT1epoXkJKtv3 -L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLMPUxA2IGvd56D -eruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl -xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynp -VSJYACPq4xJDKVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEY -WQPJIrSPnNVeKtelttQKbfi3QBFGmh95DmK/D5fs4C8fF5Q= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIHyTCCBbGgAwIBAgIBATANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEW -MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg -Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh -dGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0NjM2WhcNMzYwOTE3MTk0NjM2WjB9 -MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMi -U2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3Rh -cnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUA -A4ICDwAwggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZk -pMyONvg45iPwbm2xPN1yo4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rf -OQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/C -Ji/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/deMotHweXMAEtcnn6RtYT -Kqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt2PZE4XNi -HzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMM -Av+Z6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w -+2OqqGwaVLRcJXrJosmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+ -Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3 -Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVcUjyJthkqcwEKDwOzEmDyei+B -26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT37uMdBNSSwID -AQABo4ICUjCCAk4wDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAa4wHQYDVR0OBBYE -FE4L7xqkQFulF2mHMMo0aEPQQa7yMGQGA1UdHwRdMFswLKAqoCiGJmh0dHA6Ly9j -ZXJ0LnN0YXJ0Y29tLm9yZy9zZnNjYS1jcmwuY3JsMCugKaAnhiVodHRwOi8vY3Js -LnN0YXJ0Y29tLm9yZy9zZnNjYS1jcmwuY3JsMIIBXQYDVR0gBIIBVDCCAVAwggFM -BgsrBgEEAYG1NwEBATCCATswLwYIKwYBBQUHAgEWI2h0dHA6Ly9jZXJ0LnN0YXJ0 -Y29tLm9yZy9wb2xpY3kucGRmMDUGCCsGAQUFBwIBFilodHRwOi8vY2VydC5zdGFy -dGNvbS5vcmcvaW50ZXJtZWRpYXRlLnBkZjCB0AYIKwYBBQUHAgIwgcMwJxYgU3Rh -cnQgQ29tbWVyY2lhbCAoU3RhcnRDb20pIEx0ZC4wAwIBARqBl0xpbWl0ZWQgTGlh -YmlsaXR5LCByZWFkIHRoZSBzZWN0aW9uICpMZWdhbCBMaW1pdGF0aW9ucyogb2Yg -dGhlIFN0YXJ0Q29tIENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFBvbGljeSBhdmFp -bGFibGUgYXQgaHR0cDovL2NlcnQuc3RhcnRjb20ub3JnL3BvbGljeS5wZGYwEQYJ -YIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilTdGFydENvbSBGcmVlIFNT -TCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQUFAAOCAgEAFmyZ -9GYMNPXQhV59CuzaEE44HF7fpiUFS5Eyweg78T3dRAlbB0mKKctmArexmvclmAk8 -jhvh3TaHK0u7aNM5Zj2gJsfyOZEdUauCe37Vzlrk4gNXcGmXCPleWKYK34wGmkUW -FjgKXlf2Ysd6AgXmvB618p70qSmD+LIU424oh0TDkBreOKk8rENNZEXO3SipXPJz -ewT4F+irsfMuXGRuczE6Eri8sxHkfY+BUZo7jYn0TZNmezwD7dOaHZrzZVD1oNB1 -ny+v8OqCQ5j4aZyJecRDjkZy42Q2Eq/3JR44iZB3fsNrarnDy0RLrHiQi+fHLB5L -EUTINFInzQpdn4XBidUaePKVEFMy3YCEZnXZtWgo+2EuvoSoOMCZEoalHmdkrQYu -L6lwhceWD3yJZfWOQ1QOq92lgDmUYMA0yZZwLKMS9R9Ie70cfmu3nZD0Ijuu+Pwq -yvqCUqDvr0tVk+vBtfAii6w0TiYiBKGHLHVKt+V9E9e4DGTANtLJL4YSjCMJwRuC -O3NJo2pXh5Tl1njFmUNj403gdy3hZZlyaQQaRwnmDwFWJPsfvw55qVguucQJAX6V -um0ABj6y6koQOdjQK/W/7HW/lwLFCRsI3FU34oH7N4RDYiDK51ZLZer+bMEkkySh -NOsF/5oirpt9P/FlUQqmMGqz9IgcgA38corog14= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIF2TCCA8GgAwIBAgIQXAuFXAvnWUHfV8w/f52oNjANBgkqhkiG9w0BAQUFADBk -MQswCQYDVQQGEwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsTHERpZ2l0 -YWwgQ2VydGlmaWNhdGUgU2VydmljZXMxGzAZBgNVBAMTElN3aXNzY29tIFJvb3Qg -Q0EgMTAeFw0wNTA4MTgxMjA2MjBaFw0yNTA4MTgyMjA2MjBaMGQxCzAJBgNVBAYT -AmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGlnaXRhbCBDZXJ0aWZp -Y2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Njb20gUm9vdCBDQSAxMIICIjAN -BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0LmwqAzZuz8h+BvVM5OAFmUgdbI9 -m2BtRsiMMW8Xw/qabFbtPMWRV8PNq5ZJkCoZSx6jbVfd8StiKHVFXqrWW/oLJdih -FvkcxC7mlSpnzNApbjyFNDhhSbEAn9Y6cV9Nbc5fuankiX9qUvrKm/LcqfmdmUc/ -TilftKaNXXsLmREDA/7n29uj/x2lzZAeAR81sH8A25Bvxn570e56eqeqDFdvpG3F -EzuwpdntMhy0XmeLVNxzh+XTF3xmUHJd1BpYwdnP2IkCb6dJtDZd0KTeByy2dbco -kdaXvij1mB7qWybJvbCXc9qukSbraMH5ORXWZ0sKbU/Lz7DkQnGMU3nn7uHbHaBu -HYwadzVcFh4rUx80i9Fs/PJnB3r1re3WmquhsUvhzDdf/X/NTa64H5xD+SpYVUNF -vJbNcA78yeNmuk6NO4HLFWR7uZToXTNShXEuT46iBhFRyePLoW4xCGQMwtI89Tbo -19AOeCMgkckkKmUpWyL3Ic6DXqTz3kvTaI9GdVyDCW4pa8RwjPWd1yAv/0bSKzjC -L3UcPX7ape8eYIVpQtPM+GP+HkM5haa2Y0EQs3MevNP6yn0WR+Kn1dCjigoIlmJW -bjTb2QK5MHXjBNLnj8KwEUAKrNVxAmKLMb7dxiNYMUJDLXT5xp6mig/p/r+D5kNX -JLrvRjSq1xIBOO0CAwEAAaOBhjCBgzAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0hBBYw -FDASBgdghXQBUwABBgdghXQBUwABMBIGA1UdEwEB/wQIMAYBAf8CAQcwHwYDVR0j -BBgwFoAUAyUv3m+CATpcLNwroWm1Z9SM0/0wHQYDVR0OBBYEFAMlL95vggE6XCzc -K6FptWfUjNP9MA0GCSqGSIb3DQEBBQUAA4ICAQA1EMvspgQNDQ/NwNurqPKIlwzf -ky9NfEBWMXrrpA9gzXrzvsMnjgM+pN0S734edAY8PzHyHHuRMSG08NBsl9Tpl7Ik -Vh5WwzW9iAUPWxAaZOHHgjD5Mq2eUCzneAXQMbFamIp1TpBcahQq4FJHgmDmHtqB -sfsUC1rxn9KVuj7QG9YVHaO+htXbD8BJZLsuUBlL0iT43R4HVtA4oJVwIHaM190e -3p9xxCPvgxNcoyQVTSlAPGrEqdi3pkSlDfTgnXceQHAm/NrZNuR55LU/vJtlvrsR -ls/bxig5OgjOR1tTWsWZ/l2p3e9M1MalrQLmjAcSHm8D0W+go/MpvRLHUKKwf4ip -mXeascClOS5cfGniLLDqN2qk4Vrh9VDlg++luyqI54zb/W1elxmofmZ1a3Hqv7HH -b6D0jqTsNFFbjCYDcKF31QESVwA12yPeDooomf2xEG9L/zgtYE4snOtnta1J7ksf -rK/7DZBaZmBwXarNeNQk7shBoJMBkpxqnvy5JMWzFYJ+vq6VK+uxwNrjAWALXmms -hFZhvnEX/h0TD/7Gh0Xp/jKgGg0TpJRVcaUWi7rKibCyx/yP2FS1k2Kdzs9Z+z0Y -zirLNRWCXf9UIltxUvu3yf5gmwBBZPCqKuy2QkPOiWaByIufOVQDJdMWNY6E0F/6 -MBr1mmz0DlP5OlvRHA== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDtTCCAp2gAwIBAgIIBhDCeat3PfIwDQYJKoZIhvcNAQEFBQAwdjELMAkGA1UE -BhMCQ0gxEjAQBgNVBAoTCVN3aXNzU2lnbjEyMDAGA1UEAxMpU3dpc3NTaWduIENB -IChSU0EgSUsgTWF5IDYgMTk5OSAxODowMDo1OCkxHzAdBgkqhkiG9w0BCQEWEGNh -QFN3aXNzU2lnbi5jb20wHhcNMDAxMTI2MjMyNzQxWhcNMzExMTI2MjMyNzQxWjB2 -MQswCQYDVQQGEwJDSDESMBAGA1UEChMJU3dpc3NTaWduMTIwMAYDVQQDEylTd2lz -c1NpZ24gQ0EgKFJTQSBJSyBNYXkgNiAxOTk5IDE4OjAwOjU4KTEfMB0GCSqGSIb3 -DQEJARYQY2FAU3dpc3NTaWduLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC -AQoCggEBAKw5fjnmNneLQlUCQG8jQLwwfbrOZoUwNX8cbNqhxK03/xUloFVgAt+S -Te2RxNXaCAXLBPn5ZST35TLV57aLmbHCtifv3YZqaaQGvjedltIBMJihJhZ+h3LY -SKsUb+xEJ3x5ZUf8jP+Q1g57y1s8SnBFWN/ni5NkF1Y1y31VwOi9wiOf/VISL+uu -SC4i1CP1Kbz3BDs6Hht1GpRYCbJ/K0bc9oJSpWpT5PGONsGIawqMbJuyoDghsXQ1 -pbn2e8K64BSscGZVZTNooSGgNiHmACNJBYXiWVWrwXPF4l6SddmC3Rj0aKXjgECc -FkHLDQcsM5JsK2ZLryTDUsQFbxVP2ikCAwEAAaNHMEUwCwYDVR0PBAQDAgEGMAwG -A1UdEwQFMAMBAf8wHQYDVR0OBBYEFJbXcc05KtT8iLGKq1N4ae+PR34WMAkGA1Ud -IwQCMAAwDQYJKoZIhvcNAQEFBQADggEBAKMy6W8HvZdS1fBpEUzl6Lvw50bgE1Xc -HU1JypSBG9mhdcXZo5AlPB4sCvx9Dmfwhyrdsshc0TP2V3Vh6eQqnEF5qB4lVziT -Bko9mW6Ot+pPnwsy4SHpx3rw6jCYnOqfUcZjWqqqRrq/3P1waz+Mn4cLMVEg3Xaz -qYov/khvSqS0JniwjRlo2H6f/1oVUKZvP+dUhpQepfZrOqMAWZW4otp6FolyQyeU -NN6UCRNiUKl5vTijbKwUUwfER/1Vci3M1/O1QCfttQ4vRN4Buc0xqYtGL3cd5WiO -vWzyhlTzAI6VUdNkQhhHJSAyTpj6dmXDRzrryoFGa2PjgESxz7XBaSI= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIFujCCA6KgAwIBAgIJALtAHEP1Xk+wMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV -BAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2ln -biBHb2xkIENBIC0gRzIwHhcNMDYxMDI1MDgzMDM1WhcNMzYxMDI1MDgzMDM1WjBF -MQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dpc3NTaWduIEFHMR8wHQYDVQQDExZT -d2lzc1NpZ24gR29sZCBDQSAtIEcyMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC -CgKCAgEAr+TufoskDhJuqVAtFkQ7kpJcyrhdhJJCEyq8ZVeCQD5XJM1QiyUqt2/8 -76LQwB8CJEoTlo8jE+YoWACjR8cGp4QjK7u9lit/VcyLwVcfDmJlD909Vopz2q5+ -bbqBHH5CjCA12UNNhPqE21Is8w4ndwtrvxEvcnifLtg+5hg3Wipy+dpikJKVyh+c -6bM8K8vzARO/Ws/BtQpgvd21mWRTuKCWs2/iJneRjOBiEAKfNA+k1ZIzUd6+jbqE -emA8atufK+ze3gE/bk3lUIbLtK/tREDFylqM2tIrfKjuvqblCqoOpd8FUrdVxyJd -MmqXl2MT28nbeTZ7hTpKxVKJ+STnnXepgv9VHKVxaSvRAiTysybUa9oEVeXBCsdt -MDeQKuSeFDNeFhdVxVu1yzSJkvGdJo+hB9TGsnhQ2wwMC3wLjEHXuendjIj3o02y -MszYF9rNt85mndT9Xv+9lz4pded+p2JYryU0pUHHPbwNUMoDAw8IWh+Vc3hiv69y -FGkOpeUDDniOJihC8AcLYiAQZzlG+qkDzAQ4embvIIO1jEpWjpEA/I5cgt6IoMPi -aG59je883WX0XaxR7ySArqpWl2/5rX3aYT+YdzylkbYcjCbaZaIJbcHiVOO5ykxM -gI93e2CaHt+28kgeDrpOVG2Y4OGiGqJ3UM/EY5LsRxmd6+ZrzsECAwEAAaOBrDCB -qTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUWyV7 -lqRlUX64OfPAeGZe6Drn8O4wHwYDVR0jBBgwFoAUWyV7lqRlUX64OfPAeGZe6Drn -8O4wRgYDVR0gBD8wPTA7BglghXQBWQECAQEwLjAsBggrBgEFBQcCARYgaHR0cDov -L3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBACe6 -45R88a7A3hfm5djV9VSwg/S7zV4Fe0+fdWavPOhWfvxyeDgD2StiGwC5+OlgzczO -UYrHUDFu4Up+GC9pWbY9ZIEr44OE5iKHjn3g7gKZYbge9LgriBIWhMIxkziWMaa5 -O1M/wySTVltpkuzFwbs4AOPsF6m43Md8AYOfMke6UiI0HTJ6CVanfCU2qT1L2sCC -bwq7EsiHSycR+R4tx5M/nttfJmtS2S6K8RTGRI0Vqbe/vd6mGu6uLftIdxf+u+yv -GPUqUfA5hJeVbG4bwyvEdGB5JbAKJ9/fXtI5z0V9QkvfsywexcZdylU6oJxpmo/a -77KwPJ+HbBIrZXAVUjEaJM9vMSNQH4xPjyPDdEFjHFWoFN0+4FFQz/EbMFYOkrCC -hdiDyyJkvC24JdVUorgG6q2SpCSgwYa1ShNqR88uC1aVVMvOmttqtKay20EIhid3 -92qgQmwLOM7XdVAyksLfKzAiSNDVQTglXaTpXZ/GlHXQRf0wl0OPkKsKx4ZzYEpp -Ld6leNcG2mqeSz53OiATIgHQv2ieY2BrNU0LbbqhPcCT4H8js1WtciVORvnSFu+w -ZMEBnunKoGqYDs/YYPIvSbjkQuE4NRb0yG5P94FW6LqjviOvrv1vA+ACOzB2+htt -Qc8Bsem4yWb02ybzOqR08kkkW8mw0FfB+j564ZfJ ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIFwTCCA6mgAwIBAgIITrIAZwwDXU8wDQYJKoZIhvcNAQEFBQAwSTELMAkGA1UE -BhMCQ0gxFTATBgNVBAoTDFN3aXNzU2lnbiBBRzEjMCEGA1UEAxMaU3dpc3NTaWdu -IFBsYXRpbnVtIENBIC0gRzIwHhcNMDYxMDI1MDgzNjAwWhcNMzYxMDI1MDgzNjAw -WjBJMQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dpc3NTaWduIEFHMSMwIQYDVQQD -ExpTd2lzc1NpZ24gUGxhdGludW0gQ0EgLSBHMjCCAiIwDQYJKoZIhvcNAQEBBQAD -ggIPADCCAgoCggIBAMrfogLi2vj8Bxax3mCq3pZcZB/HL37PZ/pEQtZ2Y5Wu669y -IIpFR4ZieIbWIDkm9K6j/SPnpZy1IiEZtzeTIsBQnIJ71NUERFzLtMKfkr4k2Htn -IuJpX+UFeNSH2XFwMyVTtIc7KZAoNppVRDBopIOXfw0enHb/FZ1glwCNioUD7IC+ -6ixuEFGSzH7VozPY1kneWCqv9hbrS3uQMpe5up1Y8fhXSQQeol0GcN1x2/ndi5ob -jM89o03Oy3z2u5yg+gnOI2Ky6Q0f4nIoj5+saCB9bzuohTEJfwvH6GXp43gOCWcw -izSC+13gzJ2BbWLuCB4ELE6b7P6pT1/9aXjvCR+htL/68++QHkwFix7qepF6w9fl -+zC8bBsQWJj3Gl/QKTIDE0ZNYWqFTFJ0LwYfexHihJfGmfNtf9dng34TaNhxKFrY -zt3oEBSa/m0jh26OWnA81Y0JAKeqvLAxN23IhBQeW71FYyBrS3SMvds6DsHPWhaP -pZjydomyExI7C3d3rLvlPClKknLKYRorXkzig3R3+jVIeoVNjZpTxN94ypeRSCtF -KwH3HBqi7Ri6Cr2D+m+8jVeTO9TUps4e8aCxzqv9KyiaTxvXw3LbpMS/XUz13XuW -ae5ogObnmLo2t/5u7Su9IPhlGdpVCX4l3P5hYnL5fhgC72O00Puv5TtjjGePAgMB -AAGjgawwgakwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O -BBYEFFCvzAeHFUdvOMW0ZdHelarp35zMMB8GA1UdIwQYMBaAFFCvzAeHFUdvOMW0 -ZdHelarp35zMMEYGA1UdIAQ/MD0wOwYJYIV0AVkBAQEBMC4wLAYIKwYBBQUHAgEW -IGh0dHA6Ly9yZXBvc2l0b3J5LnN3aXNzc2lnbi5jb20vMA0GCSqGSIb3DQEBBQUA -A4ICAQAIhab1Fgz8RBrBY+D5VUYI/HAcQiiWjrfFwUF1TglxeeVtlspLpYhg0DB0 -uMoI3LQwnkAHFmtllXcBrqS3NQuB2nEVqXQXOHtYyvkv+8Bldo1bAbl93oI9ZLi+ -FHSjClTTLJUYFzX1UWs/j6KWYTl4a0vlpqD4U99REJNi54Av4tHgvI42Rncz7Lj7 -jposiU0xEQ8mngS7twSNC/K5/FqdOxa3L8iYq/6KUFkuozv8KV2LwUvJ4ooTHbG/ -u0IdUt1O2BReEMYxB+9xJ/cbOQncguqLs5WGXv312l0xpuAxtpTmREl0xRbl9x8D -YSjFyMsSoEJL+WuICI20MhjzdZ/EfwBPBZWcoxcCw7NTm6ogOSkrZvqdr16zktK1 -puEa+S1BaYEUtLS17Yk9zvupnTVCRLEcFHOBzyoBNZox1S2PbYTfgE1X4z/FhHXa -icYwu+uPyyIIoK6q8QNsOktNCaUOcsZWayFCTiMlFGiudgp8DAdwZPmaL/YFOSbG -DI8Zf0NebvRbFS/bYV3mZy8/CJT5YLSYMdp08YSTcU1f+2BY0fvEwW2JorsgH51x -kcsymxM9Pn2SUjWskpSi0xjCfMfqr3YFFt1nJ8J+HAciIfNAChs0B0QTwoRqjt8Z -Wr9/6x3iGjjRXK9HkmuAtTClyY3YqzGBH9/CZjfTk6mFhnll0g== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIFvTCCA6WgAwIBAgIITxvUL1S7L0swDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UE -BhMCQ0gxFTATBgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWdu -IFNpbHZlciBDQSAtIEcyMB4XDTA2MTAyNTA4MzI0NloXDTM2MTAyNTA4MzI0Nlow -RzELMAkGA1UEBhMCQ0gxFTATBgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMY -U3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A -MIICCgKCAgEAxPGHf9N4Mfc4yfjDmUO8x/e8N+dOcbpLj6VzHVxumK4DV644N0Mv -Fz0fyM5oEMF4rhkDKxD6LHmD9ui5aLlV8gREpzn5/ASLHvGiTSf5YXu6t+WiE7br -YT7QbNHm+/pe7R20nqA1W6GSy/BJkv6FCgU+5tkL4k+73JU3/JHpMjUi0R86TieF -nbAVlDLaYQ1HTWBCrpJH6INaUFjpiou5XaHc3ZlKHzZnu0jkg7Y360g6rw9njxcH -6ATK72oxh9TAtvmUcXtnZLi2kUpCe2UuMGoM9ZDulebyzYLs2aFK7PayS+VFheZt -eJMELpyCbTapxDFkH4aDCyr0NQp4yVXPQbBH6TCfmb5hqAaEuSh6XzjZG6k4sIN/ -c8HDO0gqgg8hm7jMqDXDhBuDsz6+pJVpATqJAHgE2cn0mRmrVn5bi4Y5FZGkECwJ -MoBgs5PAKrYYC51+jUnyEEp/+dVGLxmSo5mnJqy7jDzmDrxHB9xzUfFwZC8I+bRH -HTBsROopN4WSaGa8gzj+ezku01DwH/teYLappvonQfGbGHLy9YR0SslnxFSuSGTf -jNFusB3hB48IHpmccelM2KX3RxIfdNFRnobzwqIjQAtz20um53MGjMGg6cFZrEb6 -5i/4z3GcRm25xBWNOHkDRUjvxF3XCO6HOSKGsg0PWEP3calILv3q1h8CAwEAAaOB -rDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU -F6DNweRBtjpbO8tFnb0cwpj6hlgwHwYDVR0jBBgwFoAUF6DNweRBtjpbO8tFnb0c -wpj6hlgwRgYDVR0gBD8wPTA7BglghXQBWQEDAQEwLjAsBggrBgEFBQcCARYgaHR0 -cDovL3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIB -AHPGgeAn0i0P4JUw4ppBf1AsX19iYamGamkYDHRJ1l2E6kFSGG9YrVBWIGrGvShp -WJHckRE1qTodvBqlYJ7YH39FkWnZfrt4csEGDyrOj4VwYaygzQu4OSlWhDJOhrs9 -xCrZ1x9y7v5RoSJBsXECYxqCsGKrXlcSH9/L3XWgwF15kIwb4FDm3jH+mHtwX6WQ -2K34ArZv02DdQEsixT2tOnqfGhpHkXkzuoLcMmkDlm4fS/Bx/uNncqCxv1yL5PqZ -IseEuRuNI5c/7SXgz2W79WEE790eslpBIlqhn10s6FvJbakMDHiqYMZWjwFaDGi8 -aRl5xB9+lwW/xekkUV7U1UtT7dkjWjYDZaPBA61BMPNGG4WQr2W11bHkFlt4dR2X -em1ZqSqPe97Dh4kQmUlzeMg9vVE1dCrV8X5pGyq7O70luJpaPXJhkGaH7gzWTdQR -dAtq/gsD/KNVV4n+SsuuWxcFyPKNIzFTONItaj+CuY0IavdeQXRuwxF+B6wpYJE/ -OMpXEA29MC/HpeZBoNquBYeaoKRlbEwJDIm6uNO5wJOKMPqN5ZprFQFOZ6raYlY+ -hAhm0sQ2fac+EPyI4NSA5QC9qvNOBqN6avlicuMJT+ubDgEj8Z+7fNzcbBGXJbLy -tGMU0gYqZ4yD9c7qB9iaah7s5Aq7KkzrCWA5zspi2C5u ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIENTCCA56gAwIBAgIBATANBgkqhkiG9w0BAQQFADCBvDELMAkGA1UEBhMCREUx -EDAOBgNVBAgTB0hhbWJ1cmcxEDAOBgNVBAcTB0hhbWJ1cmcxOjA4BgNVBAoTMVRD -IFRydXN0Q2VudGVyIGZvciBTZWN1cml0eSBpbiBEYXRhIE5ldHdvcmtzIEdtYkgx -IjAgBgNVBAsTGVRDIFRydXN0Q2VudGVyIENsYXNzIDAgQ0ExKTAnBgkqhkiG9w0B -CQEWGmNlcnRpZmljYXRlQHRydXN0Y2VudGVyLmRlMB4XDTk4MDMwOTEzNTQ0OFoX -DTA1MTIzMTEzNTQ0OFowgbwxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1idXJn -MRAwDgYDVQQHEwdIYW1idXJnMTowOAYDVQQKEzFUQyBUcnVzdENlbnRlciBmb3Ig -U2VjdXJpdHkgaW4gRGF0YSBOZXR3b3JrcyBHbWJIMSIwIAYDVQQLExlUQyBUcnVz -dENlbnRlciBDbGFzcyAwIENBMSkwJwYJKoZIhvcNAQkBFhpjZXJ0aWZpY2F0ZUB0 -cnVzdGNlbnRlci5kZTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA333mvr/V -8C9tTg7R4I0LfztU6IrisJ8oxYrGubMzJ/UnyhpMVBJrtLJGsx1Ls/QhC0sCLqHC -NJyFoMR4EdvbaycrCSoYTkDMn3EZZ5l0onw/wdiLI8hjO4ohq1zeHvSN3LQYwwVz -9Gq0ofoBCCsBD203W6o4hmc51+Vf+uR+zKMCAwEAAaOCAUMwggE/MEAGCWCGSAGG -+EIBAwQzFjFodHRwczovL3d3dy50cnVzdGNlbnRlci5kZS9jZ2ktYmluL2NoZWNr -LXJldi5jZ2k/MEAGCWCGSAGG+EIBBAQzFjFodHRwczovL3d3dy50cnVzdGNlbnRl -ci5kZS9jZ2ktYmluL2NoZWNrLXJldi5jZ2k/MDwGCWCGSAGG+EIBBwQvFi1odHRw -czovL3d3dy50cnVzdGNlbnRlci5kZS9jZ2ktYmluL1JlbmV3LmNnaT8wPgYJYIZI -AYb4QgEIBDEWL2h0dHA6Ly93d3cudHJ1c3RjZW50ZXIuZGUvZ3VpZGVsaW5lcy9p -bmRleC5odG1sMCgGCWCGSAGG+EIBDQQbFhlUQyBUcnVzdENlbnRlciBDbGFzcyAw -IENBMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG9w0BAQQFAAOBgQBNB39fCTAZ -kqoFR3qUdVQqrs/82AxC4UU4KySVssqHynnEw5eQXmIYxsk4YUxoNdNMFBHrxM2h -qdjFnmgnMgc1RQT4XyGgYB4cAEgEWNLFy65tMm49d5WMhcflrlCddUp7/wsneepN -pFn/7FrqJqU5g6TReM6nqX683SvKEpMDSg== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIENTCCA56gAwIBAgIBAjANBgkqhkiG9w0BAQQFADCBvDELMAkGA1UEBhMCREUx -EDAOBgNVBAgTB0hhbWJ1cmcxEDAOBgNVBAcTB0hhbWJ1cmcxOjA4BgNVBAoTMVRD -IFRydXN0Q2VudGVyIGZvciBTZWN1cml0eSBpbiBEYXRhIE5ldHdvcmtzIEdtYkgx -IjAgBgNVBAsTGVRDIFRydXN0Q2VudGVyIENsYXNzIDEgQ0ExKTAnBgkqhkiG9w0B -CQEWGmNlcnRpZmljYXRlQHRydXN0Y2VudGVyLmRlMB4XDTk4MDMwOTEzNTYzM1oX -DTA1MTIzMTEzNTYzM1owgbwxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1idXJn -MRAwDgYDVQQHEwdIYW1idXJnMTowOAYDVQQKEzFUQyBUcnVzdENlbnRlciBmb3Ig -U2VjdXJpdHkgaW4gRGF0YSBOZXR3b3JrcyBHbWJIMSIwIAYDVQQLExlUQyBUcnVz -dENlbnRlciBDbGFzcyAxIENBMSkwJwYJKoZIhvcNAQkBFhpjZXJ0aWZpY2F0ZUB0 -cnVzdGNlbnRlci5kZTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAsCnrtHaz -rte2W7Re573jsZxJBFdboavZfxMb/bphq9jncd8tAJRdUUh9I+91YoSQPAofWRF0 -L46Apf0wAj0pUs1yGkkhnLzLUo5IoWOWyBCFMGlXdEXAWobG1T3gaFd9MWokjUWX -PjF+aGYybiRt7DI2yUHK8DFEyKNhyhugNh8CAwEAAaOCAUMwggE/MEAGCWCGSAGG -+EIBAwQzFjFodHRwczovL3d3dy50cnVzdGNlbnRlci5kZS9jZ2ktYmluL2NoZWNr -LXJldi5jZ2k/MEAGCWCGSAGG+EIBBAQzFjFodHRwczovL3d3dy50cnVzdGNlbnRl -ci5kZS9jZ2ktYmluL2NoZWNrLXJldi5jZ2k/MDwGCWCGSAGG+EIBBwQvFi1odHRw -czovL3d3dy50cnVzdGNlbnRlci5kZS9jZ2ktYmluL1JlbmV3LmNnaT8wPgYJYIZI -AYb4QgEIBDEWL2h0dHA6Ly93d3cudHJ1c3RjZW50ZXIuZGUvZ3VpZGVsaW5lcy9p -bmRleC5odG1sMCgGCWCGSAGG+EIBDQQbFhlUQyBUcnVzdENlbnRlciBDbGFzcyAx -IENBMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG9w0BAQQFAAOBgQAFQlImpAwn -AUSsXCUowkRCVAi5HcU+bFlmxLNOUKf4+JZ1oZZ16BY4oM1dbvp5pxt7HR7DALlm -vlrWYg/n8nu470zgwD9Zrjm3hAmeq/GpLmtp4q3M8up4CQUgOEJxGH7Hspfm1QIF -BlajX/GqwsRP/vfvFg+d7KqFzz0pJPEEzQ== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDXDCCAsWgAwIBAgICA+kwDQYJKoZIhvcNAQEEBQAwgbwxCzAJBgNVBAYTAkRF -MRAwDgYDVQQIEwdIYW1idXJnMRAwDgYDVQQHEwdIYW1idXJnMTowOAYDVQQKEzFU -QyBUcnVzdENlbnRlciBmb3IgU2VjdXJpdHkgaW4gRGF0YSBOZXR3b3JrcyBHbWJI -MSIwIAYDVQQLExlUQyBUcnVzdENlbnRlciBDbGFzcyAxIENBMSkwJwYJKoZIhvcN -AQkBFhpjZXJ0aWZpY2F0ZUB0cnVzdGNlbnRlci5kZTAeFw05ODAzMDkxMTU5NTla -Fw0xMTAxMDExMTU5NTlaMIG8MQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFtYnVy -ZzEQMA4GA1UEBxMHSGFtYnVyZzE6MDgGA1UEChMxVEMgVHJ1c3RDZW50ZXIgZm9y -IFNlY3VyaXR5IGluIERhdGEgTmV0d29ya3MgR21iSDEiMCAGA1UECxMZVEMgVHJ1 -c3RDZW50ZXIgQ2xhc3MgMSBDQTEpMCcGCSqGSIb3DQEJARYaY2VydGlmaWNhdGVA -dHJ1c3RjZW50ZXIuZGUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALAp67R2 -s67Xtlu0Xue947GcSQRXW6Gr2X8TG/26YavY53HfLQCUXVFIfSPvdWKEkDwKH1kR -dC+OgKX9MAI9KVLNchpJIZy8y1KOSKFjlsgQhTBpV3RFwFqGxtU94GhXfTFqJI1F -lz4xfmhmMm4kbewyNslByvAxRMijYcoboDYfAgMBAAGjazBpMA8GA1UdEwEB/wQF -MAMBAf8wDgYDVR0PAQH/BAQDAgGGMDMGCWCGSAGG+EIBCAQmFiRodHRwOi8vd3d3 -LnRydXN0Y2VudGVyLmRlL2d1aWRlbGluZXMwEQYJYIZIAYb4QgEBBAQDAgAHMA0G -CSqGSIb3DQEBBAUAA4GBAE+ZWYXIZFaCxW892EYJLzxRwadwWIGSEur01BYAll5y -KOfWNl8anK8fwoMatAVVmaZYXDco8lce612/sdNFD3IcA9IAxyxV2v5fiXaL4tR3 -9U0JF6/EuqswK0+4HerZ/1nwUHRGul7qNrDrknsPWNoy4VK9IzcP9fMASq6wXt5u ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIENTCCA56gAwIBAgIBAzANBgkqhkiG9w0BAQQFADCBvDELMAkGA1UEBhMCREUx -EDAOBgNVBAgTB0hhbWJ1cmcxEDAOBgNVBAcTB0hhbWJ1cmcxOjA4BgNVBAoTMVRD -IFRydXN0Q2VudGVyIGZvciBTZWN1cml0eSBpbiBEYXRhIE5ldHdvcmtzIEdtYkgx -IjAgBgNVBAsTGVRDIFRydXN0Q2VudGVyIENsYXNzIDIgQ0ExKTAnBgkqhkiG9w0B -CQEWGmNlcnRpZmljYXRlQHRydXN0Y2VudGVyLmRlMB4XDTk4MDMwOTEzNTc0NFoX -DTA1MTIzMTEzNTc0NFowgbwxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1idXJn -MRAwDgYDVQQHEwdIYW1idXJnMTowOAYDVQQKEzFUQyBUcnVzdENlbnRlciBmb3Ig -U2VjdXJpdHkgaW4gRGF0YSBOZXR3b3JrcyBHbWJIMSIwIAYDVQQLExlUQyBUcnVz -dENlbnRlciBDbGFzcyAyIENBMSkwJwYJKoZIhvcNAQkBFhpjZXJ0aWZpY2F0ZUB0 -cnVzdGNlbnRlci5kZTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA2jjo7TIA -KXGDAQ2/jAHc2satOaSpii/Vi1xoX1DGYvVmvcqRIuyqHVHXPbNRsoNOXctJsPBM -VeVrLceFCzAckk6C1MoC7fdvvtzg4xS4BVPymvRWi1qehZPRtIJWrk27qEtXFrz+ -+Fie+CmNsHvNeMlPrItnDPGc+/xXm1dcTw0CAwEAAaOCAUMwggE/MEAGCWCGSAGG -+EIBAwQzFjFodHRwczovL3d3dy50cnVzdGNlbnRlci5kZS9jZ2ktYmluL2NoZWNr -LXJldi5jZ2k/MEAGCWCGSAGG+EIBBAQzFjFodHRwczovL3d3dy50cnVzdGNlbnRl -ci5kZS9jZ2ktYmluL2NoZWNrLXJldi5jZ2k/MDwGCWCGSAGG+EIBBwQvFi1odHRw -czovL3d3dy50cnVzdGNlbnRlci5kZS9jZ2ktYmluL1JlbmV3LmNnaT8wPgYJYIZI -AYb4QgEIBDEWL2h0dHA6Ly93d3cudHJ1c3RjZW50ZXIuZGUvZ3VpZGVsaW5lcy9p -bmRleC5odG1sMCgGCWCGSAGG+EIBDQQbFhlUQyBUcnVzdENlbnRlciBDbGFzcyAy -IENBMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG9w0BAQQFAAOBgQCJG/Tv6Tji -bAz2zW9JzinM+6YP+Y0+lUbW/EcyibLIBmF60ucNEwKUC9mLVkf0u+fFX3v0Y0yu -fDTqDaKpsyyF8+P+J1QQkrCPksGYQhhwSNtOLOsNJGjk0fe+Cakph7vo2tw+o4hC -MfXR43+u2I4AWnSYsE/G/yN7XHMAeMnbTg== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDXDCCAsWgAwIBAgICA+owDQYJKoZIhvcNAQEEBQAwgbwxCzAJBgNVBAYTAkRF -MRAwDgYDVQQIEwdIYW1idXJnMRAwDgYDVQQHEwdIYW1idXJnMTowOAYDVQQKEzFU -QyBUcnVzdENlbnRlciBmb3IgU2VjdXJpdHkgaW4gRGF0YSBOZXR3b3JrcyBHbWJI -MSIwIAYDVQQLExlUQyBUcnVzdENlbnRlciBDbGFzcyAyIENBMSkwJwYJKoZIhvcN -AQkBFhpjZXJ0aWZpY2F0ZUB0cnVzdGNlbnRlci5kZTAeFw05ODAzMDkxMTU5NTla -Fw0xMTAxMDExMTU5NTlaMIG8MQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFtYnVy -ZzEQMA4GA1UEBxMHSGFtYnVyZzE6MDgGA1UEChMxVEMgVHJ1c3RDZW50ZXIgZm9y -IFNlY3VyaXR5IGluIERhdGEgTmV0d29ya3MgR21iSDEiMCAGA1UECxMZVEMgVHJ1 -c3RDZW50ZXIgQ2xhc3MgMiBDQTEpMCcGCSqGSIb3DQEJARYaY2VydGlmaWNhdGVA -dHJ1c3RjZW50ZXIuZGUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANo46O0y -AClxgwENv4wB3NrGrTmkqYov1YtcaF9QxmL1Zr3KkSLsqh1R1z2zUbKDTl3LSbDw -TFXlay3HhQswHJJOgtTKAu33b77c4OMUuAVT8pr0VotanoWT0bSCVq5Nu6hLVxa8 -/vhYnvgpjbB7zXjJT6yLZwzxnPv8V5tXXE8NAgMBAAGjazBpMA8GA1UdEwEB/wQF -MAMBAf8wDgYDVR0PAQH/BAQDAgGGMDMGCWCGSAGG+EIBCAQmFiRodHRwOi8vd3d3 -LnRydXN0Y2VudGVyLmRlL2d1aWRlbGluZXMwEQYJYIZIAYb4QgEBBAQDAgAHMA0G -CSqGSIb3DQEBBAUAA4GBAIRS+yjf/x91AbwBvgRWl2p0QiQxg/lGsQaKic+WLDO/ -jLVfenKhhQbOhvgFjuj5Jcrag4wGrOs2bYWRNAQ29ELw+HkuCkhcq8xRT3h2oNms -Gb0q0WkEKJHKNhAngFdb0lz1wlurZIFjdFH0l7/NEij3TWZ/p/AcASZ4smZHcFFk ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEqjCCA5KgAwIBAgIOLmoAAQACH9dSISwRXDswDQYJKoZIhvcNAQEFBQAwdjEL -MAkGA1UEBhMCREUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxIjAgBgNV -BAsTGVRDIFRydXN0Q2VudGVyIENsYXNzIDIgQ0ExJTAjBgNVBAMTHFRDIFRydXN0 -Q2VudGVyIENsYXNzIDIgQ0EgSUkwHhcNMDYwMTEyMTQzODQzWhcNMjUxMjMxMjI1 -OTU5WjB2MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1c3RDZW50ZXIgR21i -SDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMiBDQTElMCMGA1UEAxMc -VEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMiBDQSBJSTCCASIwDQYJKoZIhvcNAQEBBQAD -ggEPADCCAQoCggEBAKuAh5uO8MN8h9foJIIRszzdQ2Lu+MNF2ujhoF/RKrLqk2jf -tMjWQ+nEdVl//OEd+DFwIxuInie5e/060smp6RQvkL4DUsFJzfb95AhmC1eKokKg -uNV/aVyQMrKXDcpK3EY+AlWJU+MaWss2xgdW94zPEfRMuzBwBJWl9jmM/XOBCH2J -XjIeIqkiRUuwZi4wzJ9l/fzLganx4Duvo4bRierERXlQXa7pIXSSTYtZgo+U4+lK -8edJsBTj9WLL1XK9H7nSn6DNqPoByNkN39r8R52zyFTfSUrxIan+GE7uSNQZu+99 -5OKdy1u2bv/jzVrndIIFuoAlOMvkaZ6vQaoahPUCAwEAAaOCATQwggEwMA8GA1Ud -EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTjq1RMgKHbVkO3 -kUrL84J6E1wIqzCB7QYDVR0fBIHlMIHiMIHfoIHcoIHZhjVodHRwOi8vd3d3LnRy -dXN0Y2VudGVyLmRlL2NybC92Mi90Y19jbGFzc18yX2NhX0lJLmNybIaBn2xkYXA6 -Ly93d3cudHJ1c3RjZW50ZXIuZGUvQ049VEMlMjBUcnVzdENlbnRlciUyMENsYXNz -JTIwMiUyMENBJTIwSUksTz1UQyUyMFRydXN0Q2VudGVyJTIwR21iSCxPVT1yb290 -Y2VydHMsREM9dHJ1c3RjZW50ZXIsREM9ZGU/Y2VydGlmaWNhdGVSZXZvY2F0aW9u -TGlzdD9iYXNlPzANBgkqhkiG9w0BAQUFAAOCAQEAjNfffu4bgBCzg/XbEeprS6iS -GNn3Bzn1LL4GdXpoUxUc6krtXvwjshOg0wn/9vYua0Fxec3ibf2uWWuFHbhOIprt -ZjluS5TmVfwLG4t3wVMTZonZKNaL80VKY7f9ewthXbhtvsPcW3nS7Yblok2+XnR8 -au0WOB9/WIFaGusyiC2y8zl3gK9etmF1KdsjTYjKUCjLhdLTEKJZbtOTVAB6okaV -hgWcqRmY5TFyDADiZ9lA4CQze28suVyrZZ0srHbqNZn1l7kPJOzHdiEoZa5X6AeI -dUpWoNIFOqTmjZKILPPy4cHGYdtBxceb9w4aUUXCYWvcZCcXjFq32nQozZfkvQ== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEUzCCA7ygAwIBAgIBCTANBgkqhkiG9w0BAQQFADCBxjELMAkGA1UEBhMCREUx -EDAOBgNVBAgTB0hhbWJ1cmcxEDAOBgNVBAcTB0hhbWJ1cmcxOjA4BgNVBAoTMVRD -IFRydXN0Q2VudGVyIGZvciBTZWN1cml0eSBpbiBEYXRhIE5ldHdvcmtzIEdtYkgx -LDAqBgNVBAsTI1RDIFRydXN0Q2VudGVyIENsYXNzIDIgTFJBLUFkbWluIENBMSkw -JwYJKoZIhvcNAQkBFhpjZXJ0aWZpY2F0ZUB0cnVzdGNlbnRlci5kZTAeFw05ODAz -MDkxNDA3MjVaFw0wNTEyMzExNDA3MjVaMIHGMQswCQYDVQQGEwJERTEQMA4GA1UE -CBMHSGFtYnVyZzEQMA4GA1UEBxMHSGFtYnVyZzE6MDgGA1UEChMxVEMgVHJ1c3RD -ZW50ZXIgZm9yIFNlY3VyaXR5IGluIERhdGEgTmV0d29ya3MgR21iSDEsMCoGA1UE -CxMjVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMiBMUkEtQWRtaW4gQ0ExKTAnBgkqhkiG -9w0BCQEWGmNlcnRpZmljYXRlQHRydXN0Y2VudGVyLmRlMIGfMA0GCSqGSIb3DQEB -AQUAA4GNADCBiQKBgQDZmDnf8UPwIWk6TVuK4UuUSGJc8i7Z7cIuKXBFPQSm6Cyo -BRKYOS94XSin61CAufz/zMWAxe4LrB2r5Tn9Ngj+s6fSMLh4EBeytCSB1T+D+KP6 -k4xiCAYxN4FYzXZ45lc1dLiML7Q6JAR7MMF+FuI4hyv3AsRNzg6nXNYakivSSwID -AQABo4IBTTCCAUkwQAYJYIZIAYb4QgEDBDMWMWh0dHBzOi8vd3d3LnRydXN0Y2Vu -dGVyLmRlL2NnaS1iaW4vY2hlY2stcmV2LmNnaT8wQAYJYIZIAYb4QgEEBDMWMWh0 -dHBzOi8vd3d3LnRydXN0Y2VudGVyLmRlL2NnaS1iaW4vY2hlY2stcmV2LmNnaT8w -PAYJYIZIAYb4QgEHBC8WLWh0dHBzOi8vd3d3LnRydXN0Y2VudGVyLmRlL2NnaS1i -aW4vUmVuZXcuY2dpPzA+BglghkgBhvhCAQgEMRYvaHR0cDovL3d3dy50cnVzdGNl -bnRlci5kZS9ndWlkZWxpbmVzL2luZGV4Lmh0bWwwMgYJYIZIAYb4QgENBCUWI1RD -IFRydXN0Q2VudGVyIENsYXNzIDIgTFJBIEFkbWluIENBMBEGCWCGSAGG+EIBAQQE -AwIABzANBgkqhkiG9w0BAQQFAAOBgQCMoQBYc2Sgof2MpCM/r4Bs6uXJeoL/TC0i -p+18wPLPCO0SyiO8wPDrL9S3vF27HPnZWT1ocfrwTvhyFbQhvKc+xnW+yLRlprEU -lv4jHqhMWPLLK/5cNERpNj+SmHv9oDIBaNN9uJAvcO6c0VQsDOUMIf5alFZZR9A4 -lxnC/AsoOw== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDXDCCAsWgAwIBAgICA+swDQYJKoZIhvcNAQEEBQAwgbwxCzAJBgNVBAYTAkRF -MRAwDgYDVQQIEwdIYW1idXJnMRAwDgYDVQQHEwdIYW1idXJnMTowOAYDVQQKEzFU -QyBUcnVzdENlbnRlciBmb3IgU2VjdXJpdHkgaW4gRGF0YSBOZXR3b3JrcyBHbWJI -MSIwIAYDVQQLExlUQyBUcnVzdENlbnRlciBDbGFzcyAzIENBMSkwJwYJKoZIhvcN -AQkBFhpjZXJ0aWZpY2F0ZUB0cnVzdGNlbnRlci5kZTAeFw05ODAzMDkxMTU5NTla -Fw0xMTAxMDExMTU5NTlaMIG8MQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFtYnVy -ZzEQMA4GA1UEBxMHSGFtYnVyZzE6MDgGA1UEChMxVEMgVHJ1c3RDZW50ZXIgZm9y -IFNlY3VyaXR5IGluIERhdGEgTmV0d29ya3MgR21iSDEiMCAGA1UECxMZVEMgVHJ1 -c3RDZW50ZXIgQ2xhc3MgMyBDQTEpMCcGCSqGSIb3DQEJARYaY2VydGlmaWNhdGVA -dHJ1c3RjZW50ZXIuZGUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALa0wTUF -Lg2N7KBAahwOJ6ZQkmtQGwfeLud2zODa/ISoXoxjaitN2U4CdhHBC/KNecoAtvGw -Dtf7pBc9r6tpepYnv68zoZoqWarEtTcI8hKlMbZD9TKWcSgoq40oht+77uMMfTDW -w1Krj10nnGvAo+cFa1dJRLNu6mTP0o56UHd3AgMBAAGjazBpMA8GA1UdEwEB/wQF -MAMBAf8wDgYDVR0PAQH/BAQDAgGGMDMGCWCGSAGG+EIBCAQmFiRodHRwOi8vd3d3 -LnRydXN0Y2VudGVyLmRlL2d1aWRlbGluZXMwEQYJYIZIAYb4QgEBBAQDAgAHMA0G -CSqGSIb3DQEBBAUAA4GBABY9xs3Bu4VxhUafPiCPUSiZ7C1FIWMjWwS7TJC4iJIE -Tb19AaM/9uzO8d7+feXhPrvGq14L3T2WxMup1Pkm5gZOngylerpuw3yCGdHHsbHD -2w2Om0B8NwvxXej9H5CIpQ5ON2QhqE6NtJ/x3kit1VYYUimLRzQSCdS7kjXvD9s0 ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIENTCCA56gAwIBAgIBBDANBgkqhkiG9w0BAQQFADCBvDELMAkGA1UEBhMCREUx -EDAOBgNVBAgTB0hhbWJ1cmcxEDAOBgNVBAcTB0hhbWJ1cmcxOjA4BgNVBAoTMVRD -IFRydXN0Q2VudGVyIGZvciBTZWN1cml0eSBpbiBEYXRhIE5ldHdvcmtzIEdtYkgx -IjAgBgNVBAsTGVRDIFRydXN0Q2VudGVyIENsYXNzIDMgQ0ExKTAnBgkqhkiG9w0B -CQEWGmNlcnRpZmljYXRlQHRydXN0Y2VudGVyLmRlMB4XDTk4MDMwOTEzNTg0OVoX -DTA1MTIzMTEzNTg0OVowgbwxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1idXJn -MRAwDgYDVQQHEwdIYW1idXJnMTowOAYDVQQKEzFUQyBUcnVzdENlbnRlciBmb3Ig -U2VjdXJpdHkgaW4gRGF0YSBOZXR3b3JrcyBHbWJIMSIwIAYDVQQLExlUQyBUcnVz -dENlbnRlciBDbGFzcyAzIENBMSkwJwYJKoZIhvcNAQkBFhpjZXJ0aWZpY2F0ZUB0 -cnVzdGNlbnRlci5kZTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAtrTBNQUu -DY3soEBqHA4nplCSa1AbB94u53bM4Nr8hKhejGNqK03ZTgJ2EcEL8o15ygC28bAO -1/ukFz2vq2l6lie/rzOhmipZqsS1NwjyEqUxtkP1MpZxKCirjSiG37vu4wx9MNbD -UquPXSeca8Cj5wVrV0lEs27qZM/SjnpQd3cCAwEAAaOCAUMwggE/MEAGCWCGSAGG -+EIBAwQzFjFodHRwczovL3d3dy50cnVzdGNlbnRlci5kZS9jZ2ktYmluL2NoZWNr -LXJldi5jZ2k/MEAGCWCGSAGG+EIBBAQzFjFodHRwczovL3d3dy50cnVzdGNlbnRl -ci5kZS9jZ2ktYmluL2NoZWNrLXJldi5jZ2k/MDwGCWCGSAGG+EIBBwQvFi1odHRw -czovL3d3dy50cnVzdGNlbnRlci5kZS9jZ2ktYmluL1JlbmV3LmNnaT8wPgYJYIZI -AYb4QgEIBDEWL2h0dHA6Ly93d3cudHJ1c3RjZW50ZXIuZGUvZ3VpZGVsaW5lcy9p -bmRleC5odG1sMCgGCWCGSAGG+EIBDQQbFhlUQyBUcnVzdENlbnRlciBDbGFzcyAz -IENBMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG9w0BAQQFAAOBgQCEhlBieaAn -4SW6CbE0DxMJ7S3Ko+aV+TCszRelzj2Xnex8jyZ/wGHKIveR3Tw2WZqbdfe85Mjt -7AK2IqfzLPHIknhttu7FKOyAIE+5awjnL6eGHn2xCJ9UuQA3PKDYGsiWHPQyFJw5 -lbfu8ENJwl7oy3lvU7/7SYos2EvZVfIScA== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEqjCCA5KgAwIBAgIOSkcAAQAC5aBd1j8AUb8wDQYJKoZIhvcNAQEFBQAwdjEL -MAkGA1UEBhMCREUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxIjAgBgNV -BAsTGVRDIFRydXN0Q2VudGVyIENsYXNzIDMgQ0ExJTAjBgNVBAMTHFRDIFRydXN0 -Q2VudGVyIENsYXNzIDMgQ0EgSUkwHhcNMDYwMTEyMTQ0MTU3WhcNMjUxMjMxMjI1 -OTU5WjB2MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1c3RDZW50ZXIgR21i -SDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMyBDQTElMCMGA1UEAxMc -VEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMyBDQSBJSTCCASIwDQYJKoZIhvcNAQEBBQAD -ggEPADCCAQoCggEBALTgu1G7OVyLBMVMeRwjhjEQY0NVJz/GRcekPewJDRoeIMJW -Ht4bNwcwIi9v8Qbxq63WyKthoy9DxLCyLfzDlml7forkzMA5EpBCYMnMNWju2l+Q -Vl/NHE1bWEnrDgFPZPosPIlY2C8u4rBo6SI7dYnWRBpl8huXJh0obazovVkdKyT2 -1oQDZogkAHhg8fir/gKya/si+zXmFtGt9i4S5Po1auUZuV3bOx4a+9P/FRQI2Alq -ukWdFHlgfa9Aigdzs5OW03Q0jTo3Kd5c7PXuLjHCINy+8U9/I1LZW+Jk2ZyqBwi1 -Rb3R0DHBq1SfqdLDYmAD8bs5SpJKPQq5ncWg/jcCAwEAAaOCATQwggEwMA8GA1Ud -EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTUovyfs8PYA9NX -XAek0CSnwPIA1DCB7QYDVR0fBIHlMIHiMIHfoIHcoIHZhjVodHRwOi8vd3d3LnRy -dXN0Y2VudGVyLmRlL2NybC92Mi90Y19jbGFzc18zX2NhX0lJLmNybIaBn2xkYXA6 -Ly93d3cudHJ1c3RjZW50ZXIuZGUvQ049VEMlMjBUcnVzdENlbnRlciUyMENsYXNz -JTIwMyUyMENBJTIwSUksTz1UQyUyMFRydXN0Q2VudGVyJTIwR21iSCxPVT1yb290 -Y2VydHMsREM9dHJ1c3RjZW50ZXIsREM9ZGU/Y2VydGlmaWNhdGVSZXZvY2F0aW9u -TGlzdD9iYXNlPzANBgkqhkiG9w0BAQUFAAOCAQEANmDkcPcGIEPZIxpC8vijsrlN -irTzwppVMXzEO2eatN9NDoqTSheLG43KieHPOh6sHfGcMrSOWXaiQYUlN6AT0PV8 -TtXqluJucsG7Kv5sbviRmEb8yRtXW+rIGjs/sFGYPAfaLFkB2otE6OF0/ado3VS6 -g0bsyEa1+K+XwDsJHI/OcpY9M1ZwvJbL2NV9IJqDnxrcOfHFcqMRA/07QlIp2+gB -95tejNaNhk4Z+rwcvsUhpYeeeC422wlxo3I0+GzjBgnyXlal092Y+tTmBvTwtiBj -S+opvaqCZh77gaqnN60TGOaSw4HBM7uIHqHn4rS9MWwOUT1v+5ZWgOI2F9Hc5A== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEUzCCA7ygAwIBAgIBCjANBgkqhkiG9w0BAQQFADCBxjELMAkGA1UEBhMCREUx -EDAOBgNVBAgTB0hhbWJ1cmcxEDAOBgNVBAcTB0hhbWJ1cmcxOjA4BgNVBAoTMVRD -IFRydXN0Q2VudGVyIGZvciBTZWN1cml0eSBpbiBEYXRhIE5ldHdvcmtzIEdtYkgx -LDAqBgNVBAsTI1RDIFRydXN0Q2VudGVyIENsYXNzIDMgTFJBLUFkbWluIENBMSkw -JwYJKoZIhvcNAQkBFhpjZXJ0aWZpY2F0ZUB0cnVzdGNlbnRlci5kZTAeFw05ODAz -MDkxNDA4MjJaFw0wNTEyMzExNDA4MjJaMIHGMQswCQYDVQQGEwJERTEQMA4GA1UE -CBMHSGFtYnVyZzEQMA4GA1UEBxMHSGFtYnVyZzE6MDgGA1UEChMxVEMgVHJ1c3RD -ZW50ZXIgZm9yIFNlY3VyaXR5IGluIERhdGEgTmV0d29ya3MgR21iSDEsMCoGA1UE -CxMjVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMyBMUkEtQWRtaW4gQ0ExKTAnBgkqhkiG -9w0BCQEWGmNlcnRpZmljYXRlQHRydXN0Y2VudGVyLmRlMIGfMA0GCSqGSIb3DQEB -AQUAA4GNADCBiQKBgQDQCrjckP0s0ZieKAwDcveqxrX4uNaw1is1+zIPHx6DVPtU -xtelbka3AQW8/g5cOPjrFJd3hhh0f2QZ6Bl62uGhYQ6FhBPrWQm5fOkzOBz/8541 -tdR2OJXtJzxfqyt56YbBk9rM9HHKzYVHuP9JieQUqsH/bevA80Vk30oCtZ5ApwID -AQABo4IBTTCCAUkwQAYJYIZIAYb4QgEDBDMWMWh0dHBzOi8vd3d3LnRydXN0Y2Vu -dGVyLmRlL2NnaS1iaW4vY2hlY2stcmV2LmNnaT8wQAYJYIZIAYb4QgEEBDMWMWh0 -dHBzOi8vd3d3LnRydXN0Y2VudGVyLmRlL2NnaS1iaW4vY2hlY2stcmV2LmNnaT8w -PAYJYIZIAYb4QgEHBC8WLWh0dHBzOi8vd3d3LnRydXN0Y2VudGVyLmRlL2NnaS1i -aW4vUmVuZXcuY2dpPzA+BglghkgBhvhCAQgEMRYvaHR0cDovL3d3dy50cnVzdGNl -bnRlci5kZS9ndWlkZWxpbmVzL2luZGV4Lmh0bWwwMgYJYIZIAYb4QgENBCUWI1RD -IFRydXN0Q2VudGVyIENsYXNzIDMgTFJBIEFkbWluIENBMBEGCWCGSAGG+EIBAQQE -AwIABzANBgkqhkiG9w0BAQQFAAOBgQB6gF2gmlUFHM/tFjiR9SWs0I3Br/0egXds -bUWqFqLmhLWWjE5S73CyJPdh7w2tEh35/5EohLhrpy1Mr35ZZvNR4yhEfcgnZtDI -7IyljsPaOAiNIQWWl/VtAn13V99lESO71Hg6IzhUfe3W6P0XpQe2sWF3hZSf9O44 -NpghDjpk8A== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDXDCCAsWgAwIBAgICA+wwDQYJKoZIhvcNAQEEBQAwgbwxCzAJBgNVBAYTAkRF -MRAwDgYDVQQIEwdIYW1idXJnMRAwDgYDVQQHEwdIYW1idXJnMTowOAYDVQQKEzFU -QyBUcnVzdENlbnRlciBmb3IgU2VjdXJpdHkgaW4gRGF0YSBOZXR3b3JrcyBHbWJI -MSIwIAYDVQQLExlUQyBUcnVzdENlbnRlciBDbGFzcyA0IENBMSkwJwYJKoZIhvcN -AQkBFhpjZXJ0aWZpY2F0ZUB0cnVzdGNlbnRlci5kZTAeFw05ODAzMDkxMTU5NTla -Fw0xMTAxMDExMTU5NTlaMIG8MQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFtYnVy -ZzEQMA4GA1UEBxMHSGFtYnVyZzE6MDgGA1UEChMxVEMgVHJ1c3RDZW50ZXIgZm9y -IFNlY3VyaXR5IGluIERhdGEgTmV0d29ya3MgR21iSDEiMCAGA1UECxMZVEMgVHJ1 -c3RDZW50ZXIgQ2xhc3MgNCBDQTEpMCcGCSqGSIb3DQEJARYaY2VydGlmaWNhdGVA -dHJ1c3RjZW50ZXIuZGUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAL8vY9Y2 -e7IN01X1ZGzmJV3GtMgUuiU4g+tWYqVVqWWj9COZwku50M1UZ6ajoKOpMyt25L2t -d7LtXBJ0w8W2D1KacpNDkGJmFQ9Fpd3g3bhvQG5XwXlyo2CqunYdEolTWvwCvuEJ -E8VKL9w9ixmt14skRftM9M1cNR0pTFHz8mxVAgMBAAGjazBpMA8GA1UdEwEB/wQF -MAMBAf8wDgYDVR0PAQH/BAQDAgGGMDMGCWCGSAGG+EIBCAQmFiRodHRwOi8vd3d3 -LnRydXN0Y2VudGVyLmRlL2d1aWRlbGluZXMwEQYJYIZIAYb4QgEBBAQDAgAHMA0G -CSqGSIb3DQEBBAUAA4GBAHIR5ZVBRTK6HPiAFPtmt+uums51g1HAroq7F9Eo53Yf -E8YrRnGmFXcEmedespEkbwMMc+cjnnbKvgzFy8SQGPxtOm7gVoAbw9+MNhNH+WXB -g1LVXFy92UJm4TUhaBIQpGCQPj+B6MOMobAVBFrO6yxUVkv5BHktneqMWS+teb1I ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIENTCCA56gAwIBAgIBBTANBgkqhkiG9w0BAQQFADCBvDELMAkGA1UEBhMCREUx -EDAOBgNVBAgTB0hhbWJ1cmcxEDAOBgNVBAcTB0hhbWJ1cmcxOjA4BgNVBAoTMVRD -IFRydXN0Q2VudGVyIGZvciBTZWN1cml0eSBpbiBEYXRhIE5ldHdvcmtzIEdtYkgx -IjAgBgNVBAsTGVRDIFRydXN0Q2VudGVyIENsYXNzIDQgQ0ExKTAnBgkqhkiG9w0B -CQEWGmNlcnRpZmljYXRlQHRydXN0Y2VudGVyLmRlMB4XDTk4MDMwOTE0MDAyMFoX -DTA1MTIzMTE0MDAyMFowgbwxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1idXJn -MRAwDgYDVQQHEwdIYW1idXJnMTowOAYDVQQKEzFUQyBUcnVzdENlbnRlciBmb3Ig -U2VjdXJpdHkgaW4gRGF0YSBOZXR3b3JrcyBHbWJIMSIwIAYDVQQLExlUQyBUcnVz -dENlbnRlciBDbGFzcyA0IENBMSkwJwYJKoZIhvcNAQkBFhpjZXJ0aWZpY2F0ZUB0 -cnVzdGNlbnRlci5kZTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAvy9j1jZ7 -sg3TVfVkbOYlXca0yBS6JTiD61ZipVWpZaP0I5nCS7nQzVRnpqOgo6kzK3bkva13 -su1cEnTDxbYPUppyk0OQYmYVD0Wl3eDduG9AblfBeXKjYKq6dh0SiVNa/AK+4QkT -xUov3D2LGa3XiyRF+0z0zVw1HSlMUfPybFUCAwEAAaOCAUMwggE/MEAGCWCGSAGG -+EIBAwQzFjFodHRwczovL3d3dy50cnVzdGNlbnRlci5kZS9jZ2ktYmluL2NoZWNr -LXJldi5jZ2k/MEAGCWCGSAGG+EIBBAQzFjFodHRwczovL3d3dy50cnVzdGNlbnRl -ci5kZS9jZ2ktYmluL2NoZWNrLXJldi5jZ2k/MDwGCWCGSAGG+EIBBwQvFi1odHRw -czovL3d3dy50cnVzdGNlbnRlci5kZS9jZ2ktYmluL1JlbmV3LmNnaT8wPgYJYIZI -AYb4QgEIBDEWL2h0dHA6Ly93d3cudHJ1c3RjZW50ZXIuZGUvZ3VpZGVsaW5lcy9p -bmRleC5odG1sMCgGCWCGSAGG+EIBDQQbFhlUQyBUcnVzdENlbnRlciBDbGFzcyA0 -IENBMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG9w0BAQQFAAOBgQCUaBQbJZ4p -mbGyI9JEs5Wf0Z5VBN3jL4IzVZZ3GZ0rnmUc+orjx48l/LEeVUYPj/9PNy+kdlmm -ZOvVFnC93ZUzDKQNJOtkULRDEfJDvg1xmCLsAa/s98dcccN1kVgZ6N2g9LTxvBBK -85O0Bkm7H2bSvXRH4Zr569erbR+64R0s2g== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDtjCCAp6gAwIBAgIOBcAAAQACQdAGCk3OdRAwDQYJKoZIhvcNAQEFBQAwdjEL -MAkGA1UEBhMCREUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxIjAgBgNV -BAsTGVRDIFRydXN0Q2VudGVyIENsYXNzIDQgQ0ExJTAjBgNVBAMTHFRDIFRydXN0 -Q2VudGVyIENsYXNzIDQgQ0EgSUkwHhcNMDYwMzIzMTQxMDIzWhcNMjUxMjMxMjI1 -OTU5WjB2MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1c3RDZW50ZXIgR21i -SDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgNCBDQTElMCMGA1UEAxMc -VEMgVHJ1c3RDZW50ZXIgQ2xhc3MgNCBDQSBJSTCCASIwDQYJKoZIhvcNAQEBBQAD -ggEPADCCAQoCggEBALXNTJytrlG7fEjFDSmGehSt2VA9CXIgDRS2Y8b+WJ7gIV7z -jyIZ3E6RIM1viCmis8GsKnK6i1S4QF/yqvhDhsIwXMynXX/GCEnkDjkvjhjWkd0j -FnmA22xIHbzB3ygQY9GB493fL3l1oht48pQB5hBiecugfQLANIJ7x8CtHUzXapZ2 -W78mhEj9h/aECqqSB5lIPGG8ToVYx5ct/YFKocabEvVCUNFkPologiJw3fX64yhC -L04y87OjNopq1mJcrPoBbbTgci6VaLTxkwzGioLSHVPqfOA/QrcSWrjN2qUGZ8uh -d32llvCSHmcOHUJG5vnt+0dTf1cERh9GX8eu4I8CAwEAAaNCMEAwDwYDVR0TAQH/ -BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFB/quz4lGwa9pd1iBX7G -TFq/6A9DMA0GCSqGSIb3DQEBBQUAA4IBAQBYpCubTPfkpJKknGWYGWIi/HIy6QRd -xMRwLVpG3kxHiiW5ot3u6hKvSI3vK2fbO8w0mCr3CEf/Iq978fTr4jgCMxh1KBue -dmWsiANy8jhHHYz1nwqIUxAUu4DlDLNdjRfuHhkcho0UZ3iMksseIUn3f9MYv5x5 -+F0IebWqak2SNmy8eesOPXmK2PajVnBd3ttPedJ60pVchidlvqDTB4FAVd0Qy+BL -iILAkH0457+W4Ze6mqtCD9Of2J4VMxHL94J59bXAQVaS4d9VA61Iz9PyLrHHLVZM -ZHQqMc7cdalUR6SnQnIJ5+ECpkeyBM1CE+FhDOB4OiIgohxgQoaH96Xm ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDQzCCAqygAwIBAgICA/EwDQYJKoZIhvcNAQEEBQAwgcExCzAJBgNVBAYTAkRF -MRAwDgYDVQQIEwdIYW1idXJnMRAwDgYDVQQHEwdIYW1idXJnMTowOAYDVQQKEzFU -QyBUcnVzdENlbnRlciBmb3IgU2VjdXJpdHkgaW4gRGF0YSBOZXR3b3JrcyBHbWJI -MSgwJgYDVQQLEx9UQyBUcnVzdENlbnRlciBUaW1lIFN0YW1waW5nIENBMSgwJgYD -VQQDEx9UQyBUcnVzdENlbnRlciBUaW1lIFN0YW1waW5nIENBMB4XDTk4MDMwOTEx -NTk1OVoXDTExMDEwMTExNTk1OVowgcExCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdI -YW1idXJnMRAwDgYDVQQHEwdIYW1idXJnMTowOAYDVQQKEzFUQyBUcnVzdENlbnRl -ciBmb3IgU2VjdXJpdHkgaW4gRGF0YSBOZXR3b3JrcyBHbWJIMSgwJgYDVQQLEx9U -QyBUcnVzdENlbnRlciBUaW1lIFN0YW1waW5nIENBMSgwJgYDVQQDEx9UQyBUcnVz -dENlbnRlciBUaW1lIFN0YW1waW5nIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB -iQKBgQC2S+Q2apwDjOkZb76H+fcwjD4vGE1U3ujMLAg9fEYvhAyd6+/7EZRj5+y0 -zRP9mvYwZcWKfciC0aO9EXsefr8v3GeBBFtwS+rhs7aYPbW+cNM+eV0LN5hYisP6 -mSiPAQRjHoB/d3LEXX//T1f/qslWd0Ot/BY3ajgvdEEZN6f/wwIDAQABo0gwRjAP -BgNVHRMBAf8EBTADAQH/MDMGCWCGSAGG+EIBCAQmFiRodHRwOi8vd3d3LnRydXN0 -Y2VudGVyLmRlL2d1aWRlbGluZXMwDQYJKoZIhvcNAQEEBQADgYEALqyPthmgpIxe -AbsJadYuBft2K2k118hvBqgb8tVfC8xL88FT9JW/nI5ss197C8bmnKfQLAM+1Tnh -nG7rQfjJZEO4PaJK4R5PhZLXG0duPxfar+wWPo4aiS1BidZpL0OqXS7y6NBU7g0W -xdpw2BJ0RK4WS3TtjAurNQpIaOxpAyk= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIID3TCCAsWgAwIBAgIOHaIAAQAC7LdggHiNtgYwDQYJKoZIhvcNAQEFBQAweTEL -MAkGA1UEBhMCREUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxJDAiBgNV -BAsTG1RDIFRydXN0Q2VudGVyIFVuaXZlcnNhbCBDQTEmMCQGA1UEAxMdVEMgVHJ1 -c3RDZW50ZXIgVW5pdmVyc2FsIENBIEkwHhcNMDYwMzIyMTU1NDI4WhcNMjUxMjMx -MjI1OTU5WjB5MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1c3RDZW50ZXIg -R21iSDEkMCIGA1UECxMbVEMgVHJ1c3RDZW50ZXIgVW5pdmVyc2FsIENBMSYwJAYD -VQQDEx1UQyBUcnVzdENlbnRlciBVbml2ZXJzYWwgQ0EgSTCCASIwDQYJKoZIhvcN -AQEBBQADggEPADCCAQoCggEBAKR3I5ZEr5D0MacQ9CaHnPM42Q9e3s9B6DGtxnSR -JJZ4Hgmgm5qVSkr1YnwCqMqs+1oEdjneX/H5s7/zA1hV0qq34wQi0fiU2iIIAI3T -fCZdzHd55yx4Oagmcw6iXSVphU9VDprvxrlE4Vc93x9UIuVvZaozhDrzznq+VZeu -jRIPFDPiUHDDSYcTvFHe15gSWu86gzOSBnWLknwSaHtwag+1m7Z3W0hZneTvWq3z -wZ7U10VOylY0Ibw+F1tvdwxIAUMpsN0/lm7mlaoMwCC2/T42J5zjXM9OgdwZu5GQ -fezmlwQek8wiSdeXhrYTCjxDI3d+8NzmzSQfO4ObNDqDNOMCAwEAAaNjMGEwHwYD -VR0jBBgwFoAUkqR1LKSevoFE63n8isWVpesQdXMwDwYDVR0TAQH/BAUwAwEB/zAO -BgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFJKkdSyknr6BROt5/IrFlaXrEHVzMA0G -CSqGSIb3DQEBBQUAA4IBAQAo0uCG1eb4e/CX3CJrO5UUVg8RMKWaTzqwOuAGy2X1 -7caXJ/4l8lfmXpWMPmRgFVp/Lw0BxbFg/UU1z/CyvwbZ71q+s2IhtNerNXxTPqYn -8aEt2hojnczd7Dwtnic0XQ/CNnm8yUpiLe1r2X1BQ3y2qsrtYbE3ghUJGooWMNjs -ydZHcnhLEEYUjl8Or+zHL6sQ17bxbuyGssLoDZJz3KL0Dzq/YSMQiZxIQG5wALPT -ujdEWBF6AmqI8Dc08BnprNRlc/ZpjGSUOnmFKbAWKwyCPwacx/0QK54PLLae4xW/ -2TYcuiUaUj0a7CIMHOCkoj3w6DnPgcB77V0fb8XQC9eY ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIF3zCCA8egAwIBAgIOGTMAAQACKBqaBLzyVUUwDQYJKoZIhvcNAQEFBQAwejEL -MAkGA1UEBhMCREUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxJDAiBgNV -BAsTG1RDIFRydXN0Q2VudGVyIFVuaXZlcnNhbCBDQTEnMCUGA1UEAxMeVEMgVHJ1 -c3RDZW50ZXIgVW5pdmVyc2FsIENBIElJMB4XDTA2MDMyMjE1NTgzNFoXDTMwMTIz -MTIyNTk1OVowejELMAkGA1UEBhMCREUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVy -IEdtYkgxJDAiBgNVBAsTG1RDIFRydXN0Q2VudGVyIFVuaXZlcnNhbCBDQTEnMCUG -A1UEAxMeVEMgVHJ1c3RDZW50ZXIgVW5pdmVyc2FsIENBIElJMIICIjANBgkqhkiG -9w0BAQEFAAOCAg8AMIICCgKCAgEAi9R3azRs5TbYalxeOO781R15Azt7g2JEgk6I -7d6D/+7MUGIFBZWZdpj2ufJf2AaRksL2LWYXH/1TA+iojWOpbuHWG4y8mLOLO9Tk -Lsp9hUkmW3m4GotAnn+7yT9jLM/RWny6KCJBElpN+Rd3/IX9wkngKhh/6aAsnPlE -/AxoOUL1JwW+jhV6YJ3wO8c85j4WvK923mq3ouGrRkXrjGV90ZfzlxElq1nroCLZ -gt2Y7X7i+qBhCkoy3iwX921E6oFHWZdXNwM53V6CItQzuPomCba8OYgvURVOm8M7 -3xOCiN1LNPIz1pDp81PcNXzAw9l8eLPNcD+NauCjgUjkKa1juPD8KGQ7mbN9/pqd -iPaZIgiRRxaJNXhdd6HPv0nh/SSUK2k2e+gc5iqQilvVOzRZQtxtz7sPQRxVzfUN -Wy4WIibvYR6X/OJTyM9bo8ep8boOhhLLE8oVx+zkNo3aXBM9ZdIOXXB03L+PemrB -Lg/Txl4PK1lszGFs/sBhTtnmT0ayWuIZFHCE+CAA7QGnl37DvRJckiMXoKUdRRcV -I5qSCLUiiI3cKyTr4LEXaNOvYb3ZhXj2jbp4yjeNY77nrB/fpUcJucglMVRGURFV -DYlcjdrSGC1z8rjVJ/VIIjfRYvd7Dcg4i6FKsPzQ8eu3hmPn4A5zf/1yUbXpfeJV -BWR4Z38CAwEAAaNjMGEwHwYDVR0jBBgwFoAUzdeQoW6jv9sw1toyJZAM5jkegGUw -DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFM3XkKFu -o7/bMNbaMiWQDOY5HoBlMA0GCSqGSIb3DQEBBQUAA4ICAQB+FojoEw42zG4qhQc4 -xlaJeuNHIWZMUAgxWlHQ/KZeFHXeTDvs8e3MfhEHSmHu6rOOOqQzxu2KQmZP8Tx7 -yaUFQZmx7Cxb7tyW0ohTS3g0uW7muw/FeqZ8Dhjfbw90TNGp8aHp2FRkzF6WeKJW -GsFzshXGVwXf2vdIJIqOf2qp+U3pPmrOYCx9LZAI9mOPFdAtnIz/8f38DBZQVhT7 -upeG7rRJA1TuG1l/MDoCgoYhrv7wFfLfToPmmcW6NfcgkIw47XXP4S73BDD7Ua2O -giRAyn0pXdXZ92Vk/KqfdLh9kl3ShCngE+qK99CrxK7vFcXCifJ7tjtJmGHzTnKR -N4xJkunI7Cqg90lufA0kxmts8jgvynAF5X/fxisrgIDV2m/LQLvYG/AkyRDIRAJ+ -LtOYqqIN8SvQ2vqOHP9U6OFKbt2o1ni1N6WsZNUUI8cOpevhCTjXwHxgpV2Yj4wC -1dxWqPNNWKkL1HxkdAEy8t8PSoqpAqKiHYR3wvHMl700GXRd4nQ+dSf3r7/ufA5t -VIimVuImrTESPB5BeW0X6hNeH/Vcn0lZo7Ivo0LD+qh+v6WfSMlgYmIK371F3uNC -tVGW/cT1Gpm4UqJEzS1hjBWPgdVdotSQPYxuQGHDWV3Y2eH2dEcieXR92sqjbzcV -NvAsGnE8EXbfXRo+VGN4a2V+Hw== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEKzCCAxOgAwIBAgIEOsylTDANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJE -SzEVMBMGA1UEChMMVERDIEludGVybmV0MR0wGwYDVQQLExRUREMgSW50ZXJuZXQg -Um9vdCBDQTAeFw0wMTA0MDUxNjMzMTdaFw0yMTA0MDUxNzAzMTdaMEMxCzAJBgNV -BAYTAkRLMRUwEwYDVQQKEwxUREMgSW50ZXJuZXQxHTAbBgNVBAsTFFREQyBJbnRl -cm5ldCBSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxLhA -vJHVYx/XmaCLDEAedLdInUaMArLgJF/wGROnN4NrXceO+YQwzho7+vvOi20jxsNu -Zp+Jpd/gQlBn+h9sHvTQBda/ytZO5GhgbEaqHF1j4QeGDmUApy6mcca8uYGoOn0a -0vnRrEvLznWv3Hv6gXPU/Lq9QYjUdLP5Xjg6PEOo0pVOd20TDJ2PeAG3WiAfAzc1 -4izbSysseLlJ28TQx5yc5IogCSEWVmb/Bexb4/DPqyQkXsN/cHoSxNK1EKC2IeGN -eGlVRGn1ypYcNIUXJXfi9i8nmHj9eQY6otZaQ8H/7AQ77hPv01ha/5Lr7K7a8jcD -R0G2l8ktCkEiu7vmpwIDAQABo4IBJTCCASEwEQYJYIZIAYb4QgEBBAQDAgAHMGUG -A1UdHwReMFwwWqBYoFakVDBSMQswCQYDVQQGEwJESzEVMBMGA1UEChMMVERDIElu -dGVybmV0MR0wGwYDVQQLExRUREMgSW50ZXJuZXQgUm9vdCBDQTENMAsGA1UEAxME -Q1JMMTArBgNVHRAEJDAigA8yMDAxMDQwNTE2MzMxN1qBDzIwMjEwNDA1MTcwMzE3 -WjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUbGQBx/2FbazI2p5QCIUItTxWqFAw -HQYDVR0OBBYEFGxkAcf9hW2syNqeUAiFCLU8VqhQMAwGA1UdEwQFMAMBAf8wHQYJ -KoZIhvZ9B0EABBAwDhsIVjUuMDo0LjADAgSQMA0GCSqGSIb3DQEBBQUAA4IBAQBO -Q8zR3R0QGwZ/t6T609lN+yOfI1Rb5osvBCiLtSdtiaHsmGnc540mgwV5dOy0uaOX -wTUA/RXaOYE6lTGQ3pfphqiZdwzlWqCE/xIWrG64jcN7ksKsLtB9KOy282A4aW8+ -2ARVPp7MVdK6/rtHBNcK2RYKNCn1WBPVT8+PVkuzHu7TmHnaCB4Mb7j4Fifvwm89 -9qNLPg7kbWzbO0ESm70NRyN/PErQr8Cv9u8btRXE64PECV90i9kR+8JWsTz4cMo0 -jUNAE4z9mQNUecYu6oah9jrUCbz0vGbMPVjQV0kK7iXiQe4T+Zs4NNEA9X7nlB38 -aQNiuJkFBT1reBK9sG9l ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIFGTCCBAGgAwIBAgIEPki9xDANBgkqhkiG9w0BAQUFADAxMQswCQYDVQQGEwJE -SzEMMAoGA1UEChMDVERDMRQwEgYDVQQDEwtUREMgT0NFUyBDQTAeFw0wMzAyMTEw -ODM5MzBaFw0zNzAyMTEwOTA5MzBaMDExCzAJBgNVBAYTAkRLMQwwCgYDVQQKEwNU -REMxFDASBgNVBAMTC1REQyBPQ0VTIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A -MIIBCgKCAQEArGL2YSCyz8DGhdfjeebM7fI5kqSXLmSjhFuHnEz9pPPEXyG9VhDr -2y5h7JNp46PMvZnDBfwGuMo2HP6QjklMxFaaL1a8z3sM8W9Hpg1DTeLpHTk0zY0s -2RKY+ePhwUp8hjjEqcRhiNJerxomTdXkoCJHhNlktxmW/OwZ5LKXJk5KTMuPJItU -GBxIYXvViGjaXbXqzRowwYCDdlCqT9HU3Tjw7xb04QxQBr/q+3pJoSgrHPb8FTKj -dGqPqcNiKXEx5TukYBdedObaE+3pHx8b0bJoc8YQNHVGEBDjkAB2QMuLt0MJIf+r -TpPGWOmlgtt3xDqZsXKVSQTwtyv6e1mO3QIDAQABo4ICNzCCAjMwDwYDVR0TAQH/ -BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwgewGA1UdIASB5DCB4TCB3gYIKoFQgSkB -AQEwgdEwLwYIKwYBBQUHAgEWI2h0dHA6Ly93d3cuY2VydGlmaWthdC5kay9yZXBv -c2l0b3J5MIGdBggrBgEFBQcCAjCBkDAKFgNUREMwAwIBARqBgUNlcnRpZmlrYXRl -ciBmcmEgZGVubmUgQ0EgdWRzdGVkZXMgdW5kZXIgT0lEIDEuMi4yMDguMTY5LjEu -MS4xLiBDZXJ0aWZpY2F0ZXMgZnJvbSB0aGlzIENBIGFyZSBpc3N1ZWQgdW5kZXIg -T0lEIDEuMi4yMDguMTY5LjEuMS4xLjARBglghkgBhvhCAQEEBAMCAAcwgYEGA1Ud -HwR6MHgwSKBGoESkQjBAMQswCQYDVQQGEwJESzEMMAoGA1UEChMDVERDMRQwEgYD -VQQDEwtUREMgT0NFUyBDQTENMAsGA1UEAxMEQ1JMMTAsoCqgKIYmaHR0cDovL2Ny -bC5vY2VzLmNlcnRpZmlrYXQuZGsvb2Nlcy5jcmwwKwYDVR0QBCQwIoAPMjAwMzAy -MTEwODM5MzBagQ8yMDM3MDIxMTA5MDkzMFowHwYDVR0jBBgwFoAUYLWF7FZkfhIZ -J2cdUBVLc647+RIwHQYDVR0OBBYEFGC1hexWZH4SGSdnHVAVS3OuO/kSMB0GCSqG -SIb2fQdBAAQQMA4bCFY2LjA6NC4wAwIEkDANBgkqhkiG9w0BAQUFAAOCAQEACrom -JkbTc6gJ82sLMJn9iuFXehHTuJTXCRBuo7E4A9G28kNBKWKnctj7fAXmMXAnVBhO -inxO5dHKjHiIzxvTkIvmI/gLDjNDfZziChmPyQE+dF10yYscA+UYyAFMP8uXBV2Y -caaYb7Z8vTd/vuGTJW1v8AqtFxjhA7wHKcitJuj4YfD9IQl+mo6paH1IYnK9AOoB -mbgGglGBTvH1tJFUuSN6AJqfXY3gPGS5GhKSKseCRHI53OI8xthV9RVOyAUO28bQ -YqbsFbS1AoLbrIyigfCbmTH1ICCoiGEKB5+U/NDXG8wuF/MEJ3Zn61SD/aSQfgY9 -BKNDLdr8C2LqL19iUw== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDITCCAoqgAwIBAgIBADANBgkqhkiG9w0BAQQFADCByzELMAkGA1UEBhMCWkEx -FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMRowGAYD -VQQKExFUaGF3dGUgQ29uc3VsdGluZzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBT -ZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UEAxMYVGhhd3RlIFBlcnNvbmFsIEJhc2lj -IENBMSgwJgYJKoZIhvcNAQkBFhlwZXJzb25hbC1iYXNpY0B0aGF3dGUuY29tMB4X -DTk2MDEwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgcsxCzAJBgNVBAYTAlpBMRUw -EwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEaMBgGA1UE -ChMRVGhhd3RlIENvbnN1bHRpbmcxKDAmBgNVBAsTH0NlcnRpZmljYXRpb24gU2Vy -dmljZXMgRGl2aXNpb24xITAfBgNVBAMTGFRoYXd0ZSBQZXJzb25hbCBCYXNpYyBD -QTEoMCYGCSqGSIb3DQEJARYZcGVyc29uYWwtYmFzaWNAdGhhd3RlLmNvbTCBnzAN -BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAvLyTU23AUE+CFeZIlDWmWr5vQvoPR+53 -dXLdjUmbllegeNTKP1GzaQuRdhciB5dqxFGTS+CN7zeVoQxN2jSQHReJl+A1OFdK -wPQIcOk8RHtQfmGakOMj04gRRif1CwcOu93RfyAKiLlWCy4cgNrx454p7xS9CkT7 -G1sY0b8jkyECAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQQF -AAOBgQAt4plrsD16iddZopQBHyvdEktTwq1/qqcAXJFAVyVKOKqEcLnZgA+le1z7 -c8a914phXAPjLSeoF+CEhULcXpvGt7Jtu3Sv5D/Lp7ew4F2+eIMllNLbgQ95B21P -9DkVWlIBe94y1k049hJcBlDfBVu9FEuh3ym6O0GN92NWod8isQ== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDLTCCApagAwIBAgIBADANBgkqhkiG9w0BAQQFADCB0TELMAkGA1UEBhMCWkEx -FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMRowGAYD -VQQKExFUaGF3dGUgQ29uc3VsdGluZzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBT -ZXJ2aWNlcyBEaXZpc2lvbjEkMCIGA1UEAxMbVGhhd3RlIFBlcnNvbmFsIEZyZWVt -YWlsIENBMSswKQYJKoZIhvcNAQkBFhxwZXJzb25hbC1mcmVlbWFpbEB0aGF3dGUu -Y29tMB4XDTk2MDEwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgdExCzAJBgNVBAYT -AlpBMRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEa -MBgGA1UEChMRVGhhd3RlIENvbnN1bHRpbmcxKDAmBgNVBAsTH0NlcnRpZmljYXRp -b24gU2VydmljZXMgRGl2aXNpb24xJDAiBgNVBAMTG1RoYXd0ZSBQZXJzb25hbCBG -cmVlbWFpbCBDQTErMCkGCSqGSIb3DQEJARYccGVyc29uYWwtZnJlZW1haWxAdGhh -d3RlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1GnX1LCUZFtx6UfY -DFG26nKRsIRefS0Nj3sS34UldSh0OkIsYyeflXtL734Zhx2G6qPduc6WZBrCFG5E -rHzmj+hND3EfQDimAKOHePb5lIZererAXnbr2RSjXW56fAylS1V/Bhkpf56aJtVq -uzgkCGqYx7Hao5iR/Xnb5VrEHLkCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zAN -BgkqhkiG9w0BAQQFAAOBgQDH7JJ+Tvj1lqVnYiqk8E0RYNBvjWBYYawmu1I1XAjP -MPuoSpaKH2JCI4wXD/S6ZJwXrEcp352YXtJsYHFcoqzceePnbgBHH7UNKOgCneSa -/RP0ptl8sfjcXyMmCZGAc9AUG95DqYMl8uacLxXK/qarigd1iwzdUYRr5PjRznei -gQ== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDKTCCApKgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBzzELMAkGA1UEBhMCWkEx -FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMRowGAYD -VQQKExFUaGF3dGUgQ29uc3VsdGluZzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBT -ZXJ2aWNlcyBEaXZpc2lvbjEjMCEGA1UEAxMaVGhhd3RlIFBlcnNvbmFsIFByZW1p -dW0gQ0ExKjAoBgkqhkiG9w0BCQEWG3BlcnNvbmFsLXByZW1pdW1AdGhhd3RlLmNv -bTAeFw05NjAxMDEwMDAwMDBaFw0yMDEyMzEyMzU5NTlaMIHPMQswCQYDVQQGEwJa -QTEVMBMGA1UECBMMV2VzdGVybiBDYXBlMRIwEAYDVQQHEwlDYXBlIFRvd24xGjAY -BgNVBAoTEVRoYXd0ZSBDb25zdWx0aW5nMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9u -IFNlcnZpY2VzIERpdmlzaW9uMSMwIQYDVQQDExpUaGF3dGUgUGVyc29uYWwgUHJl -bWl1bSBDQTEqMCgGCSqGSIb3DQEJARYbcGVyc29uYWwtcHJlbWl1bUB0aGF3dGUu -Y29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDJZtn4B0TPuYwu8KHvE0Vs -Bd/eJxZRNkERbGw77f4QfRKe5ZtCmv5gMcNmt3M6SK5O0DI3lIi1DbbZ8/JE2dWI -Et12TfIa/G8jHnrx2JhFTgcQ7xZC0EN1bUre4qrJMf8fAHB8Zs8QJQi6+u4A6UYD -ZicRFTuqW/KY3TZCstqIdQIDAQABoxMwETAPBgNVHRMBAf8EBTADAQH/MA0GCSqG -SIb3DQEBBAUAA4GBAGk2ifc0KjNyL2071CKyuG+axTZmDhs8obF1Wub9NdP4qPIH -b4Vnjt4rueIXsDqg8A6iAJrf8xQVbrvIhVqYgPn/vnQdPfP+MCXRNzRn+qVxeTBh -KXLA4CxM+1bkOqhv5TJZUtt1KFBZDPgLGeSs2a+WjS9Q2wfD6h+rM+D1KzGJ ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDJzCCApCgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBzjELMAkGA1UEBhMCWkEx -FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYD -VQQKExRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlv -biBTZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UEAxMYVGhhd3RlIFByZW1pdW0gU2Vy -dmVyIENBMSgwJgYJKoZIhvcNAQkBFhlwcmVtaXVtLXNlcnZlckB0aGF3dGUuY29t -MB4XDTk2MDgwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgc4xCzAJBgNVBAYTAlpB -MRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEdMBsG -A1UEChMUVGhhd3RlIENvbnN1bHRpbmcgY2MxKDAmBgNVBAsTH0NlcnRpZmljYXRp -b24gU2VydmljZXMgRGl2aXNpb24xITAfBgNVBAMTGFRoYXd0ZSBQcmVtaXVtIFNl -cnZlciBDQTEoMCYGCSqGSIb3DQEJARYZcHJlbWl1bS1zZXJ2ZXJAdGhhd3RlLmNv -bTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0jY2aovXwlue2oFBYo847kkE -VdbQ7xwblRZH7xhINTpS9CtqBo87L+pW46+GjZ4X9560ZXUCTe/LCaIhUdib0GfQ -ug2SBhRz1JPLlyoAnFxODLz6FVL88kRu2hFKbgifLy3j+ao6hnO2RlNYyIkFvYMR -uHM/qgeN9EJN50CdHDcCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG -9w0BAQQFAAOBgQAmSCwWwlj66BZ0DKqqX1Q/8tfJeGBeXm43YyJ3Nn6yF8Q0ufUI -hfzJATj/Tb7yFkJD57taRvvBxhEf8UqwKEbJw8RCfbz6q1lu1bdRiBHjpIUZa4JM -pAwSremkrj/xw0llmozFyD4lt5SZu5IycQfwhl7tUCemDaYj+bvLpgcUQg== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEIDCCAwigAwIBAgIQNE7VVyDV7exJ9C/ON9srbTANBgkqhkiG9w0BAQUFADCB -qTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMf -Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIw -MDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNV -BAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwHhcNMDYxMTE3MDAwMDAwWhcNMzYw -NzE2MjM1OTU5WjCBqTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5j -LjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYG -A1UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl -IG9ubHkxHzAdBgNVBAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwggEiMA0GCSqG -SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCsoPD7gFnUnMekz52hWXMJEEUMDSxuaPFs -W0hoSVk3/AszGcJ3f8wQLZU0HObrTQmnHNK4yZc2AreJ1CRfBsDMRJSUjQJib+ta -3RGNKJpchJAQeg29dGYvajig4tVUROsdB58Hum/u6f1OCyn1PoSgAfGcq/gcfomk -6KHYcWUNo1F77rzSImANuVud37r8UVsLr5iy6S7pBOhih94ryNdOwUxkHt3Ph1i6 -Sk/KaAcdHJ1KxtUvkcx8cXIcxcBn6zL9yZJclNqFwJu/U30rCfSMnZEfl2pSy94J -NqR32HuHUETVPm4pafs5SSYeCaWAe0At6+gnhcn+Yf1+5nyXHdWdAgMBAAGjQjBA -MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBR7W0XP -r87Lev0xkhpqtvNG61dIUDANBgkqhkiG9w0BAQUFAAOCAQEAeRHAS7ORtvzw6WfU -DW5FvlXok9LOAz/t2iWwHVfLHjp2oEzsUHboZHIMpKnxuIvW1oeEuzLlQRHAd9mz -YJ3rG9XRbkREqaYB7FViHXe4XI5ISXycO1cRrK1zN44veFyQaEfZYGDm/Ac9IiAX -xPcW6cTYcvnIc3zfFi8VqT79aie2oetaupgf1eNNZAqdE8hhuvU5HIe6uL17In/2 -/qxAeeWsEG89jxt5dovEN7MhGITlNgDrYyCZuen+MwS7QcjBAvlEYyCegc5C09Y/ -LHbTY5xZ3Y+m4Q6gLkH3LpVHz7z9M/P2C2F+fpErgUfCJzDupxBdN49cOSvkBPB7 -jVaMaA== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDEzCCAnygAwIBAgIBATANBgkqhkiG9w0BAQQFADCBxDELMAkGA1UEBhMCWkEx -FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYD -VQQKExRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlv -biBTZXJ2aWNlcyBEaXZpc2lvbjEZMBcGA1UEAxMQVGhhd3RlIFNlcnZlciBDQTEm -MCQGCSqGSIb3DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5jb20wHhcNOTYwODAx -MDAwMDAwWhcNMjAxMjMxMjM1OTU5WjCBxDELMAkGA1UEBhMCWkExFTATBgNVBAgT -DFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3 -dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNl -cyBEaXZpc2lvbjEZMBcGA1UEAxMQVGhhd3RlIFNlcnZlciBDQTEmMCQGCSqGSIb3 -DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQAD -gY0AMIGJAoGBANOkUG7I/1Zr5s9dtuoMaHVHoqrC2oQl/Kj0R1HahbUgdJSGHg91 -yekIYfUGbTBuFRkC6VLAYttNmZ7iagxEOM3+vuNkCXDF/rFrKbYvScg71CcEJRCX -L+eQbcAoQpnXTEPew/UhbVSfXcNY4cDk2VuwuNy0e982OsK1ZiIS1ocNAgMBAAGj -EzARMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAB/pMaVz7lcxG -7oWDTSEwjsrZqG9JGubaUeNgcGyEYRGhGshIPllDfU+VPaGLtwtimHp1it2ITk6e -QNuozDJ0uW8NxuOzRAvZim+aKZuZGCg70eNAKJpaPNW15yAbi8qkq43pUdniTCxZ -qdq5snUb9kLy78fyGPmJvKP/iiMucEc= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEQzCCAyugAwIBAgIBATANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJHQjEb -MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow -GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDElMCMGA1UEAwwcVHJ1c3RlZCBDZXJ0 -aWZpY2F0ZSBTZXJ2aWNlczAeFw0wNDAxMDEwMDAwMDBaFw0yODEyMzEyMzU5NTla -MH8xCzAJBgNVBAYTAkdCMRswGQYDVQQIDBJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO -BgNVBAcMB1NhbGZvcmQxGjAYBgNVBAoMEUNvbW9kbyBDQSBMaW1pdGVkMSUwIwYD -VQQDDBxUcnVzdGVkIENlcnRpZmljYXRlIFNlcnZpY2VzMIIBIjANBgkqhkiG9w0B -AQEFAAOCAQ8AMIIBCgKCAQEA33FvNlhTWvI2VFeAxHQIIO0Yfyod5jWaHiWsnOWW -fnJSoBVC21ndZHoa0Lh73TkVvFVIxO06AOoxEbrycXQaZ7jPM8yoMa+j49d/vzMt -TGo87IvDktJTdyR0nAducPy9C1t2ul/y/9c3S0pgePfw+spwtOpZqqPOSC+pw7IL -fhdyFgymBwwbOM/JYrc/oJOlh0Hyt3BAd9i+FHzjqMB6juljatEPmsbS9Is6FARW -1O24zG71++IsWL1/T2sr92AkWCTOJu80kTrV44HQsvAEAtdbtz6SrGsSivnkBbA7 -kUlcsutT6vifR4buv5XAwAaf0lteERv0xwQ1KdJVXOTt6wIDAQABo4HJMIHGMB0G -A1UdDgQWBBTFe1i97doladL3WRaoszLAeydb9DAOBgNVHQ8BAf8EBAMCAQYwDwYD -VR0TAQH/BAUwAwEB/zCBgwYDVR0fBHwwejA8oDqgOIY2aHR0cDovL2NybC5jb21v -ZG9jYS5jb20vVHJ1c3RlZENlcnRpZmljYXRlU2VydmljZXMuY3JsMDqgOKA2hjRo -dHRwOi8vY3JsLmNvbW9kby5uZXQvVHJ1c3RlZENlcnRpZmljYXRlU2VydmljZXMu -Y3JsMA0GCSqGSIb3DQEBBQUAA4IBAQDIk4E7ibSvuIQSTI3S8NtwuleGFTQQuS9/ -HrCoiWChisJ3DFBKmwCL2Iv0QeLQg4pKHBQGsKNoBXAxMKdTmw7pSqBYaWcOrp32 -pSxBvzwGa+RZzG0Q8ZZvH9/0BAKkn0U+yNj6NkZEUD+Cl5EfKNsYEYwq5GWDVxIS -jBc/lDb+XbDABHcTuPQV1T84zJQ6VdCsmPW6AF/ghhmBeC8owH7TzEIK9a5QoNE+ -xqFx7D+gIIxmOom0jtTYsU0lR+4viMi14QVFwL4Ucd56/Y57fU0IlqUSc/Atyjcn -dBInTMu2l+nZrghtWjlA3QVHdWpaIbOjGM9O9y5Xt5hwXsjEeLBi ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIID+zCCAuOgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBtzE/MD0GA1UEAww2VMOc -UktUUlVTVCBFbGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sx -c8SxMQswCQYDVQQGDAJUUjEPMA0GA1UEBwwGQU5LQVJBMVYwVAYDVQQKDE0oYykg -MjAwNSBUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmlsacWfaW0gR8O8 -dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLjAeFw0wNTA1MTMxMDI3MTdaFw0xNTAz -MjIxMDI3MTdaMIG3MT8wPQYDVQQDDDZUw5xSS1RSVVNUIEVsZWt0cm9uaWsgU2Vy -dGlmaWthIEhpem1ldCBTYcSfbGF5xLFjxLFzxLExCzAJBgNVBAYMAlRSMQ8wDQYD -VQQHDAZBTktBUkExVjBUBgNVBAoMTShjKSAyMDA1IFTDnFJLVFJVU1QgQmlsZ2kg -xLBsZXRpxZ9pbSB2ZSBCaWxpxZ9pbSBHw7x2ZW5sacSfaSBIaXptZXRsZXJpIEEu -xZ4uMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAylIF1mMD2Bxf3dJ7 -XfIMYGFbazt0K3gNfUW9InTojAPBxhEqPZW8qZSwu5GXyGl8hMW0kWxsE2qkVa2k -heiVfrMArwDCBRj1cJ02i67L5BuBf5OI+2pVu32Fks66WJ/bMsW9Xe8iSi9BB35J -YbOG7E6mQW6EvAPs9TscyB/C7qju6hJKjRTP8wrgUDn5CDX4EVmt5yLqS8oUBt5C -urKZ8y1UiBAG6uEaPj1nH/vO+3yC6BFdSsG5FOpU2WabfIl9BJpiyelSPJ6c79L1 -JuTm5Rh8i27fbMx4W09ysstcP4wFjdFMjK2Sx+F4f2VsSQZQLJ4ywtdKxnWKWU51 -b0dewQIDAQABoxAwDjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQAV -9VX/N5aAWSGk/KEVTCD21F/aAyT8z5Aa9CEKmu46sWrv7/hg0Uw2ZkUd82YCdAR7 -kjCo3gp2D++Vbr3JN+YaDayJSFvMgzbC9UZcWYJWtNX+I7TYVBxEq8Sn5RTOPEFh -fEPmzcSBCYsk+1Ql1haolgxnB2+zUEfjHCQo3SqYpGH+2+oSN7wBGjSFvW5P55Fy -B0SFHljKVETd96y5y4khctuPwGkplyqjrhgjlxxBKot8KsF8kOipKMDTkcatKIdA -aLX/7KfS0zgYnNN9aV3wxqUeJBujR/xpB2jn5Jq07Q+hh4cCzofSSE7hvP/L8XKS -RGQDJereW26fyfJOrN3H ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEPTCCAyWgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBvzE/MD0GA1UEAww2VMOc -UktUUlVTVCBFbGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sx -c8SxMQswCQYDVQQGEwJUUjEPMA0GA1UEBwwGQW5rYXJhMV4wXAYDVQQKDFVUw5xS -S1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnEn2kg -SGl6bWV0bGVyaSBBLsWeLiAoYykgQXJhbMSxayAyMDA3MB4XDTA3MTIyNTE4Mzcx -OVoXDTE3MTIyMjE4MzcxOVowgb8xPzA9BgNVBAMMNlTDnFJLVFJVU1QgRWxla3Ry -b25payBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsTELMAkGA1UEBhMC -VFIxDzANBgNVBAcMBkFua2FyYTFeMFwGA1UECgxVVMOcUktUUlVTVCBCaWxnaSDE -sGxldGnFn2ltIHZlIEJpbGnFn2ltIEfDvHZlbmxpxJ9pIEhpem1ldGxlcmkgQS7F -ni4gKGMpIEFyYWzEsWsgMjAwNzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC -ggEBAKu3PgqMyKVYFeaK7yc9SrToJdPNM8Ig3BnuiD9NYvDdE3ePYakqtdTyuTFY -KTsvP2qcb3N2Je40IIDu6rfwxArNK4aUyeNgsURSsloptJGXg9i3phQvKUmi8wUG -+7RP2qFsmmaf8EMJyupyj+sA1zU511YXRxcw9L6/P8JorzZAwan0qafoEGsIiveG -HtyaKhUG9qPw9ODHFNRRf8+0222vR5YXm3dx2KdxnSQM9pQ/hTEST7ruToK4uT6P -IzdezKKqdfcYbwnTrqdUKDT74eA7YH2gvnmJhsifLfkKS8RQouf9eRbHegsYz85M -733WB2+Y8a+xwXrXgTW4qhe04MsCAwEAAaNCMEAwHQYDVR0OBBYEFCnFkKslrxHk -Yb+j/4hhkeYO/pyBMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0G -CSqGSIb3DQEBBQUAA4IBAQAQDdr4Ouwo0RSVgrESLFF6QSU2TJ/sPx+EnWVUXKgW -AkD6bho3hO9ynYYKVZ1WKKxmLNA6VpM0ByWtCLCPyA8JWcqdmBzlVPi5RX9ql2+I -aE1KBiY3iAIOtsbWcpnOa3faYjGkVh+uX4132l32iPwa2Z61gfAyuOOI0JzzaqC5 -mxRZNTZPz/OOXl0XrRWV2N2y1RVuAE6zS89mlOTgzbUF2mNXi+WzqtvALhyQRNsa -XRik7r4EW5nVcV9VZWRi1aKbBFmGyGJ353yCRWo9F7/snXUMrqNvWtMvmDb08PUZ -qxFdyKbjKlhqQgnDvZImZjINXQhVdP+MmNAKpoRq0Tl9 ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEXjCCA0agAwIBAgIQRL4Mi1AAIbQR0ypoBqmtaTANBgkqhkiG9w0BAQUFADCB -kzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug -Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho -dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xGzAZBgNVBAMTElVUTiAtIERBVEFDb3Jw -IFNHQzAeFw05OTA2MjQxODU3MjFaFw0xOTA2MjQxOTA2MzBaMIGTMQswCQYDVQQG -EwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4wHAYD -VQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cu -dXNlcnRydXN0LmNvbTEbMBkGA1UEAxMSVVROIC0gREFUQUNvcnAgU0dDMIIBIjAN -BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3+5YEKIrblXEjr8uRgnn4AgPLit6 -E5Qbvfa2gI5lBZMAHryv4g+OGQ0SR+ysraP6LnD43m77VkIVni5c7yPeIbkFdicZ -D0/Ww5y0vpQZY/KmEQrrU0icvvIpOxboGqBMpsn0GFlowHDyUwDAXlCCpVZvNvlK -4ESGoE1O1kduSUrLZ9emxAW5jh70/P/N5zbgnAVssjMiFdC04MwXwLLA9P4yPykq -lXvY8qdOD1R8oQ2AswkDwf9c3V6aPryuvEeKaq5xyh+xKrhfQgUL7EYw0XILyulW -bfXv33i+Ybqypa4ETLyorGkVl73v67SMvzX41MPRKA5cOp9wGDMgd8SirwIDAQAB -o4GrMIGoMAsGA1UdDwQEAwIBxjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRT -MtGzz3/64PGgXYVOktKeRR20TzA9BgNVHR8ENjA0MDKgMKAuhixodHRwOi8vY3Js -LnVzZXJ0cnVzdC5jb20vVVROLURBVEFDb3JwU0dDLmNybDAqBgNVHSUEIzAhBggr -BgEFBQcDAQYKKwYBBAGCNwoDAwYJYIZIAYb4QgQBMA0GCSqGSIb3DQEBBQUAA4IB -AQAnNZcAiosovcYzMB4p/OL31ZjUQLtgyr+rFywJNn9Q+kHcrpY6CiM+iVnJowft -Gzet/Hy+UUla3joKVAgWRcKZsYfNjGjgaQPpxE6YsjuMFrMOoAyYUJuTqXAJyCyj -j98C5OBxOvG0I3KgqgHf35g+FFCgMSa9KOlaMCZ1+XtgHI3zzVAmbQQnmt/VDUVH -KWss5nbZqSl9Mt3JNjy9rjXxEZ4du5A/EkdOjtd+D2JzHVImOBwYSf0wdJrE5SIv -2MCN7ZF6TACPcn9d2t0bi0Vr591pl6jFVkwPDPafepE39peC4N1xaf92P2BNPM/3 -mfnGV/TJVTl4uix5yaaIK/QI ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEojCCA4qgAwIBAgIQRL4Mi1AAJLQR0zYlJWfJiTANBgkqhkiG9w0BAQUFADCB -rjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug -Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho -dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xNjA0BgNVBAMTLVVUTi1VU0VSRmlyc3Qt -Q2xpZW50IEF1dGhlbnRpY2F0aW9uIGFuZCBFbWFpbDAeFw05OTA3MDkxNzI4NTBa -Fw0xOTA3MDkxNzM2NThaMIGuMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVVQxFzAV -BgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5l -dHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cudXNlcnRydXN0LmNvbTE2MDQGA1UE -AxMtVVROLVVTRVJGaXJzdC1DbGllbnQgQXV0aGVudGljYXRpb24gYW5kIEVtYWls -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsjmFpPJ9q0E7YkY3rs3B -YHW8OWX5ShpHornMSMxqmNVNNRm5pELlzkniii8efNIxB8dOtINknS4p1aJkxIW9 -hVE1eaROaJB7HHqkkqgX8pgV8pPMyaQylbsMTzC9mKALi+VuG6JG+ni8om+rWV6l -L8/K2m2qL+usobNqqrcuZzWLeeEeaYji5kbNoKXqvgvOdjp6Dpvq/NonWz1zHyLm -SGHGTPNpsaguG7bUMSAsvIKKjqQOpdeJQ/wWWq8dcdcRWdq6hw2v+vPhwvCkxWeM -1tZUOt4KpLoDd7NlyP0e03RiqhjKaJMeoYV+9Udly/hNVyh00jT/MLbu9mIwFIws -6wIDAQABo4G5MIG2MAsGA1UdDwQEAwIBxjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud -DgQWBBSJgmd9xJ0mcABLtFBIfN49rgRufTBYBgNVHR8EUTBPME2gS6BJhkdodHRw -Oi8vY3JsLnVzZXJ0cnVzdC5jb20vVVROLVVTRVJGaXJzdC1DbGllbnRBdXRoZW50 -aWNhdGlvbmFuZEVtYWlsLmNybDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUH -AwQwDQYJKoZIhvcNAQEFBQADggEBALFtYV2mGn98q0rkMPxTbyUkxsrt4jFcKw7u -7mFVbwQ+zznexRtJlOTrIEy05p5QLnLZjfWqo7NK2lYcYJeA3IKirUq9iiv/Cwm0 -xtcgBEXkzYABurorbs6q15L+5K/r9CYdFip/bDCVNy8zEqx/3cfREYxRmLLQo5HQ -rfafnoOTHh1CuEava2bwm3/q4wMC5QJRwarVNZ1yQAOJujEdxRBoUp7fooXFXAim -eOZTT7Hot9MUnpOmw2TjrH5xzbyf6QMbzPvprDHBr3wVdAKZw7JHpsIyYdfHb0gk -USeh1YdV8nuPmD0Wnu51tvjQjvLzxq4oW6fw8zYX/MMF08oDSlQ= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEdDCCA1ygAwIBAgIQRL4Mi1AAJLQR0zYq/mUK/TANBgkqhkiG9w0BAQUFADCB -lzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug -Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho -dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3Qt -SGFyZHdhcmUwHhcNOTkwNzA5MTgxMDQyWhcNMTkwNzA5MTgxOTIyWjCBlzELMAkG -A1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEe -MBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8v -d3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdh -cmUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCx98M4P7Sof885glFn -0G2f0v9Y8+efK+wNiVSZuTiZFvfgIXlIwrthdBKWHTxqctU8EGc6Oe0rE81m65UJ -M6Rsl7HoxuzBdXmcRl6Nq9Bq/bkqVRcQVLMZ8Jr28bFdtqdt++BxF2uiiPsA3/4a -MXcMmgF6sTLjKwEHOG7DpV4jvEWbe1DByTCP2+UretNb+zNAHqDVmBe8i4fDidNd -oI6yqqr2jmmIBsX6iSHzCJ1pLgkzmykNRg+MzEk0sGlRvfkGzWitZky8PqxhvQqI -DsjfPe58BEydCl5rkdbux+0ojatNh4lz0G6k0B4WixThdkQDf2Os5M1JnMWS9Ksy -oUhbAgMBAAGjgbkwgbYwCwYDVR0PBAQDAgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYD -VR0OBBYEFKFyXyYbKJhDlV0HN9WFlp1L0sNFMEQGA1UdHwQ9MDswOaA3oDWGM2h0 -dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VVE4tVVNFUkZpcnN0LUhhcmR3YXJlLmNy -bDAxBgNVHSUEKjAoBggrBgEFBQcDAQYIKwYBBQUHAwUGCCsGAQUFBwMGBggrBgEF -BQcDBzANBgkqhkiG9w0BAQUFAAOCAQEARxkP3nTGmZev/K0oXnWO6y1n7k57K9cM -//bey1WiCuFMVGWTYGufEpytXoMs61quwOQt9ABjHbjAbPLPSbtNk28Gpgoiskli -CE7/yMgUsogWXecB5BKV5UU0s4tpvc+0hY91UZ59Ojg6FEgSxvunOxqNDYJAB+gE -CJChicsZUN/KHAG8HQQZexB2lzvukJDKxA4fFm517zP4029bHpbj4HR3dHuKom4t -3XbWOTCC8KucUvIqx69JXn7HaOWCgchqJ/kniCrVWFCVH/A7HFe7fRQ5YiuayZSS -KqMiDP+JJn1fIytH1xUdqWqeUQ0qUZ6B+dQ7XnASfxAynB67nfhmqA== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEZDCCA0ygAwIBAgIQRL4Mi1AAJLQR0zYwS8AzdzANBgkqhkiG9w0BAQUFADCB -ozELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug -Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho -dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xKzApBgNVBAMTIlVUTi1VU0VSRmlyc3Qt -TmV0d29yayBBcHBsaWNhdGlvbnMwHhcNOTkwNzA5MTg0ODM5WhcNMTkwNzA5MTg1 -NzQ5WjCBozELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0 -IExha2UgQ2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYD -VQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xKzApBgNVBAMTIlVUTi1VU0VS -Rmlyc3QtTmV0d29yayBBcHBsaWNhdGlvbnMwggEiMA0GCSqGSIb3DQEBAQUAA4IB -DwAwggEKAoIBAQCz+5Gh5DZVhawGNFugmliy+LUPBXeDrjKxdpJo7CNKyXY/45y2 -N3kDuatpjQclthln5LAbGHNhSuh+zdMvZOOmfAz6F4CjDUeJT1FxL+78P/m4FoCH -iZMlIJpDgmkkdihZNaEdwH+DBmQWICzTSaSFtMBhf1EI+GgVkYDLpdXuOzr0hARe -YFmnjDRy7rh4xdE7EkpvfmUnuaRVxblvQ6TFHSyZwFKkeEwVs0CYCGtDxgGwenv1 -axwiP8vv/6jQOkt2FZ7S0cYu49tXGzKiuG/ohqY/cKvlcJKrRB5AUPuco2LkbG6g -yN7igEL66S/ozjIEj3yNtxyjNTwV3Z7DrpelAgMBAAGjgZEwgY4wCwYDVR0PBAQD -AgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFPqGydvguul49Uuo1hXf8NPh -ahQ8ME8GA1UdHwRIMEYwRKBCoECGPmh0dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9V -VE4tVVNFUkZpcnN0LU5ldHdvcmtBcHBsaWNhdGlvbnMuY3JsMA0GCSqGSIb3DQEB -BQUAA4IBAQCk8yXM0dSRgyLQzDKrm5ZONJFUICU0YV8qAhXhi6r/fWRRzwr/vH3Y -IWp4yy9Rb/hCHTO967V7lMPDqaAt39EpHx3+jz+7qEUqf9FuVSTiuwL7MT++6Lzs -QCv4AdRWOOTKRIK1YSAhZ2X28AvnNPilwpyjXEAfhZOVBt5P1CeptqX8Fs1zMT+4 -ZSfP1FMa8Kxun08FDAOBp4QpxFq9ZFdyrTvPNximmMatBrTcCKME1SmklpoSZ0qM -YEWd8SOasACcaLWYUNPvji6SZbFIPiG+FTAqDbUMo2s/rn9X9R+WfN9v3YIwLGUb -QErNaLly7HF27FSOH4UMAWr6pjisH8SE ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEZjCCA06gAwIBAgIQRL4Mi1AAJLQR0zYt4LNfGzANBgkqhkiG9w0BAQUFADCB -lTELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug -Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho -dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHTAbBgNVBAMTFFVUTi1VU0VSRmlyc3Qt -T2JqZWN0MB4XDTk5MDcwOTE4MzEyMFoXDTE5MDcwOTE4NDAzNlowgZUxCzAJBgNV -BAYTAlVTMQswCQYDVQQIEwJVVDEXMBUGA1UEBxMOU2FsdCBMYWtlIENpdHkxHjAc -BgNVBAoTFVRoZSBVU0VSVFJVU1QgTmV0d29yazEhMB8GA1UECxMYaHR0cDovL3d3 -dy51c2VydHJ1c3QuY29tMR0wGwYDVQQDExRVVE4tVVNFUkZpcnN0LU9iamVjdDCC -ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM6qgT+jo2F4qjEAVZURnicP -HxzfOpuCaDDASmEd8S8O+r5596Uj71VRloTN2+O5bj4x2AogZ8f02b+U60cEPgLO -KqJdhwQJ9jCdGIqXsqoc/EHSoTbL+z2RuufZcDX65OeQw5ujm9M89RKZd7G3CeBo -5hy485RjiGpq/gt2yb70IuRnuasaXnfBhQfdDWy/7gbHd2pBnqcP1/vulBe3/IW+ -pKvEHDHd17bR5PDv3xaPslKT16HUiaEHLr/hARJCHhrh2JU022R5KP+6LhHC5ehb -kkj7RwvCbNqtMoNB86XlQXD9ZZBt+vpRxPm9lisZBCzTbafc8H9vg2XiaquHhnUC -AwEAAaOBrzCBrDALBgNVHQ8EBAMCAcYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E -FgQU2u1kdBScFDyr3ZmpvVsoTYs8ydgwQgYDVR0fBDswOTA3oDWgM4YxaHR0cDov -L2NybC51c2VydHJ1c3QuY29tL1VUTi1VU0VSRmlyc3QtT2JqZWN0LmNybDApBgNV -HSUEIjAgBggrBgEFBQcDAwYIKwYBBQUHAwgGCisGAQQBgjcKAwQwDQYJKoZIhvcN -AQEFBQADggEBAAgfUrE3RHjb/c652pWWmKpVZIC1WkDdIaXFwfNfLEzIR1pp6ujw -NTX00CXzyKakh0q9G7FzCL3Uw8q2NbtZhncxzaeAFK4T7/yxSPlrJSUtUbYsbUXB -mMiKVl0+7kNOPmsnjtA6S4ULX9Ptaqd1y9Fahy85dRNacrACgZ++8A+EVCBibGnU -4U3GDZlDAQ0Slox4nb9QorFEqmrPF3rPbw/U+CRVX/A0FklmPlBGyWNxODFiuGK5 -81OtbLUrohKqGU8J2l7nk8aOFAj+8DCAGKCGhU3IfdeLA/5u1fedFqySLKAj5ZyR -Uh+U3xeUc8OzwcFxBSAAeL0TUh2oPs0AH8g= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIHqTCCBZGgAwIBAgIQYwaGp8U3ZaVDkKhqWMzUMjANBgkqhkiG9w0BAQUFADCB -jzELMAkGA1UEBhMCTFYxNTAzBgNVBAoTLFZBUyBMYXR2aWphcyBQYXN0cyAtIFZp -ZW4ucmVnLk5yLjQwMDAzMDUyNzkwMSMwIQYDVQQLExpTZXJ0aWZpa2FjaWphcyBw -YWthbHBvanVtaTEkMCIGA1UEAxMbVkFTIExhdHZpamFzIFBhc3RzIFNTSShSQ0Ep -MB4XDTA2MDkxMzA5MjIxMFoXDTI0MDkxMzA5Mjc1N1owgY8xCzAJBgNVBAYTAkxW -MTUwMwYDVQQKEyxWQVMgTGF0dmlqYXMgUGFzdHMgLSBWaWVuLnJlZy5Oci40MDAw -MzA1Mjc5MDEjMCEGA1UECxMaU2VydGlmaWthY2lqYXMgcGFrYWxwb2p1bWkxJDAi -BgNVBAMTG1ZBUyBMYXR2aWphcyBQYXN0cyBTU0koUkNBKTCCAiIwDQYJKoZIhvcN -AQEBBQADggIPADCCAgoCggIBAJu4+f1hVS9PpKUUtS6OuSSPrPuxVD9A/0/F5YZo -e1OT+zWCNahQLpRSoNuDPnXaFXCsCc/ugkmtNkm5tHGLtAChQgbKCApjl7YI/O60 -3Jh4GYLJ+H9kPqrJ/rGN67Bk9bzzxD46kOpOjj8bGbxqg8ORPGxV+wpSwOjhXXeF -M8VJ3+xqv79sN/6OSaIVGM6LjmseOKMwb4iBfnJWRBrEejkP9sSPltSy6wBOXN67 -5zu35iQFk2tN5pFEv+6YG8eFGxFBeyI2p74+6Ho33BjekJ2PzbLXmj/iF39bDOHv -P2Y9biTksM7DDIhslNo4JXxSOeNzFLMARWOaDEJAXgTG93JkzsluM7Pk020klTeT -fvIAXRmLH/NDc6ifRdIGqey0Qrv67gzHTz9RH9Gv0KwYf4eBIv6p3QeWbXz4TtlN -OlBp1UF+xdp02I5z5X6D4cMZgbe9v0COvi6aogyqTgIuuyrhCF0xA8msJ7Cv3NXI -FH1AnVWJIfmQzNTJYEFzq+jN2DpVOQqCmf6b9fU8HJHLwPpGVK4h/CqsXHveepdx -/WxrzUiapNuBfBg3L5B9YZS9F8lctlQWd8oJSqrpvE+UdQFaVryS0o+515feVnQB -9xZxSbH1GEaZQe5i4bMsZXVpKXJDA/ibH/o49J7sQBCOrJfVsDO+nxjcLfdBeFRK -YkTnAgMBAAGjggH9MIIB+TAOBgNVHQ8BAf8EBAMCAQYwGAYIKwYBBQUHAQMEDDAK -MAgGBgQAjkYBATAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTMw/Vm/3OsOFqW -GyGJuIFMH8teJTAQBgkrBgEEAYI3FQEEAwIBADCCAYkGA1UdIASCAYAwggF8MIIB -eAYLKwYBBAGBxFkBAQIwggFnMIIBOAYIKwYBBQUHAgIwggEqHoIBJgBTAGkAcwAg -AGkAcgAgAHMAZQByAHQAaQBmAGkAawBhAHQAcwAsACAAawBvACAAaQB6AGQAZQB2 -AGkAcwAgAFYAQQBTACAATABhAHQAdgBpAGoAYQBzACAAUABhAHMAdABzACwAIABu -AG8AZAByAG8AcwBpAG4AbwB0ACAAYQB0AGIAaQBsAHMAdABpAGIAdQAgAEUAbABl -AGsAdAByAG8AbgBpAHMAawBvACAAZABvAGsAdQBtAGUAbgB0AHUAIABsAGkAawB1 -AG0AYQBtACAAdQBuACAARQBpAHIAbwBwAGEAcwAgAFAAYQByAGwAYQBtAGUAbgB0 -AGEAIABkAGkAcgBlAGsAdABpAHYAYQBpACAAMQA5ADkAOQAvADkAMwAvAEUASzAp -BggrBgEFBQcCARYdaHR0cDovL3d3dy5lLW1lLmx2L3JlcG9zaXRvcnkwDQYJKoZI -hvcNAQEFBQADggIBAB8oSjWQIWNoCi94r6MegiaXoz8nGdJLo0J6BhNlW8EEy+t9 -fO+U8vGJ9bffUgIhadLqljTloM+XuJxVDhCFoxReLAX4tTp28/l6uN62DCdp8suU -kQsdudWOb5kvzfIZVjk6SFbwAf+Cdbay/dHU9fJjV0xNoX7MELoEae/0FPyzlx9F -7m9KKH/Rxie8x6Opa3vtghNvq94P+3HrXBEaqSzQMJ/8NjdW75XpurcTtq6fAmGt -nuxrBG82nw+Z98LJyEwouSjUIdeeVNXAzvSO5FWUe48kxjj8q3qkVnc9qEXvZJKk -0Ep+u3OL9A1Sc7g6SF5DgNOpcHdi/8coHHMeQ+YnJFtJueY2pI79xS0veqV5EnrX -IbIlbcgPosNhS+VI4le6n/KKId3bZPDaGd/OwJuAOcJ3d2MVU3KE+qSPBzeGIX1Q -+j1qN9uRDjez/c4Lynth0Jx0nH04aG3pex3W8Sq07ztgUncF5gLCX4xbvPB9t3PH -kWuyKrNjozTVq60lcUf/Gj56to2VdsPups0DCWzuRWeYz5lIdsHOinSaaFIBNCLI -7eIUC4S9bhCMsXKbvugI11fVf+q0AT1O5OLoZ+eMfunnQhHvlUbIkda+JxeAGTSY -58bfHvwhX56GPbx+8Jy9cp70R4JbcWfz+txUTKhc2FnH0AcOEzMnvPRp8Gsh ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEGjCCAwICEQCLW3VWhFSFCwDPrzhIzrGkMA0GCSqGSIb3DQEBBQUAMIHKMQsw -CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl -cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu -LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT -aWduIENsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp -dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD -VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT -aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ -bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu -IENsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg -LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN2E1Lm0+afY8wR4 -nN493GwTFtl63SRRZsDHJlkNrAYIwpTRMx/wgzUfbhvI3qpuFU5UJ+/EbRrsC+MO -8ESlV8dAWB6jRx9x7GD2bZTIGDnt/kIYVt/kTEkQeE4BdjVjEjbdZrwBBDajVWjV -ojYJrKshJlQGrT/KFOCsyq0GHZXi+J3x4GD/wn91K0zM2v6HmSHquv4+VNfSWXjb -PG7PoBMAGrgnoeS+Z5bKoMWznN3JdZ7rMJpfo83ZrngZPyPpXNspva1VyBtUjGP2 -6KbqxzcSXKMpHgLZ2x87tNcPVkeBFQRKr4Mn0cVYiMHd9qqnoxjaaKptEVHhv2Vr -n5Z20T0CAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAq2aN17O6x5q25lXQBfGfMY1a -qtmqRiYPce2lrVNWYgFHKkTp/j90CxObufRNG7LRX7K20ohcs5/Ny9Sn2WCVhDr4 -wTcdYcrnsMXlkdpUpqwxga6X3s0IrLjAl4B/bnKk52kTlWUfxJM8/XmPBNQ+T+r3 -ns7NZ3xPZQL/kYVUc8f/NveGLezQXk//EZ9yBta4GvFMDSZl4kSAHsef493oCtrs -pSCAaWihT37ha88HQfqDjrw43bAuEbFrskLMmrz5SCJ5ShkPshw+IHTZasO+8ih4 -E1Z5T21Q6huwtVexN2ZYI/PcD98Kh8TvhgXVOBRgmaNL3gaWcSzy27YfpO8/7g== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEGTCCAwECEGFwy0mMX5hFKeewptlQW3owDQYJKoZIhvcNAQEFBQAwgcoxCzAJ -BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVy -aVNpZ24gVHJ1c3QgTmV0d29yazE6MDgGA1UECxMxKGMpIDE5OTkgVmVyaVNpZ24s -IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTFFMEMGA1UEAxM8VmVyaVNp -Z24gQ2xhc3MgMiBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0 -eSAtIEczMB4XDTk5MTAwMTAwMDAwMFoXDTM2MDcxNjIzNTk1OVowgcoxCzAJBgNV -BAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVyaVNp -Z24gVHJ1c3QgTmV0d29yazE6MDgGA1UECxMxKGMpIDE5OTkgVmVyaVNpZ24sIElu -Yy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTFFMEMGA1UEAxM8VmVyaVNpZ24g -Q2xhc3MgMiBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAt -IEczMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArwoNwtUs22e5LeWU -J92lvuCwTY+zYVY81nzD9M0+hsuiiOLh2KRpxbXiv8GmR1BeRjmL1Za6tW8UvxDO -JxOeBUebMXoT2B/Z0wI3i60sR/COgQanDTAM6/c8DyAd3HJG7qUCyFvDyVZpTMUY -wZF7C9UTAJu878NIPkZgIIUq1ZC2zYugzDLdt/1AVbJQHFauzI13TccgTacxdu9o -koqQHgiBVrKtaaNS0MscxCM9H5n+TOgWY47GCI72MfbS+uV23bUckqNJzc0BzWjN -qWm6o+sdDZykIKbBoMXRRkwXbdKsZj+WjOCE1Db/IlnF+RFgqF8EffIa9iVCYQ/E -Srg+iQIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQA0JhU8wI1NQ0kdvekhktdmnLfe -xbjQ5F1fdiLAJvmEOjr5jLX77GDx6M4EsMjdpwOPMPOY36TmpDHf0xwLRtxyID+u -7gU8pDM/CzmscHhzS5kr3zDCVLCoO1Wh/hYozUK9dG6A2ydEp85EXdQbkJgNHkKU -sQAsBNB0owIFImNjzYO1+8FtYmtpdf1dcEG59b98377BMnMiIYtYgXsVkXq642RI -sH/7NiXaldDxJBQX3RiAa0YjOVT1jmIJBB2UkKab5iXiQkWquJCtvgiPqQtCGJTP -cjnhsUPgKM+351psE2tJs//jGHyJizNdrDPXp/naOlXJWBD5qu9ats9LS98q ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQsw -CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl -cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu -LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT -aWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp -dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD -VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT -aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ -bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu -IENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg -LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMu6nFL8eB8aHm8b -N3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1EUGO+i2t -KmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGu -kxUccLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBm -CC+Vk7+qRy+oRpfwEuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJ -Xwzw3sJ2zq/3avL6QaaiMxTJ5Xpj055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWu -imi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAERSWwauSCPc/L8my/uRan2Te -2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5fj267Cz3qWhMe -DGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC -/Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565p -F4ErWjfJXir0xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGt -TxzhT5yvDwyd93gN2PQ1VoDat20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCB -yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL -ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp -U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW -ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0 -aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCByjEL -MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW -ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2ln -biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp -U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y -aXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvJAgIKXo1 -nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKzj/i5Vbex -t0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIz -SdhDY2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQG -BO+QueQA5N06tRn/Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+ -rCpSx4/VBEnkjWNHiDxpg8v+R70rfk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/ -NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E -BAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEwHzAH -BgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy -aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKv -MzEzMA0GCSqGSIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzE -p6B4Eq1iDkVwZMXnl2YtmAl+X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y -5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKEKQsTb47bDN0lAtukixlE0kF6BWlK -WE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiCKm0oHw0LxOXnGiYZ -4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vEZV8N -hnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEGjCCAwICEQDsoKeLbnVqAc/EfMwvlF7XMA0GCSqGSIb3DQEBBQUAMIHKMQsw -CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl -cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu -LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT -aWduIENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp -dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD -VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT -aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ -bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu -IENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg -LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK3LpRFpxlmr8Y+1 -GQ9Wzsy1HyDkniYlS+BzZYlZ3tCD5PUPtbut8XzoIfzk6AzufEUiGXaStBO3IFsJ -+mGuqPKljYXCKtbeZjbSmwL0qJJgfJxptI8kHtCGUvYynEFYHiK9zUVilQhu0Gbd -U6LM8BDcVHOLBKFGMzNcF0C5nk3T875Vg+ixiY5afJqWIpA7iCXy0lOIAgwLePLm -NxdLMEYH5IBtptiWLugs+BGzOA1mppvqySNb247i8xOOGlktqgLw7KSHZtzBP/XY -ufTsgsbSPZUd5cBPhMnZo0QoBmrXRazwa2rvTl/4EYIeOGM0ZlDUPpNz+jDDZq3/ -ky2X7wMCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAj/ola09b5KROJ1WrIhVZPMq1 -CtRK26vdoV9TxaBXOcLORyu+OshWv8LZJxA6sQU8wHcxuzrTBXttmhwwjIDLk5Mq -g6sFUYICABFna/OIYUdfA5PVWw3g8dShMjWFsjrbsIKr0csKvE+MW8VLADsfKoKm -fjaF3H48ZwC15DtS4KjrXRX5xm3wrR0OhbepmnMUWluPQSjA1egtTaRezarZ7c7c -2NU8Qh0XwRJdRTjDOPP8hS6DRkiy1yBfkjaP53kPmF6Z6PDQpLv1U70qzlmwr25/ -bLvSHgCwIe34QWKCudiyxLtGUPMxxY8BqHTr9Xgn2uf3ZkPznoM+IKrDNWCRzg== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDojCCAoqgAwIBAgIQE4Y1TR0/BvLB+WUF1ZAcYjANBgkqhkiG9w0BAQUFADBr -MQswCQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRl -cm5hdGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNv -bW1lcmNlIFJvb3QwHhcNMDIwNjI2MDIxODM2WhcNMjIwNjI0MDAxNjEyWjBrMQsw -CQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRlcm5h -dGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNvbW1l -cmNlIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvV95WHm6h -2mCxlCfLF9sHP4CFT8icttD0b0/Pmdjh28JIXDqsOTPHH2qLJj0rNfVIsZHBAk4E -lpF7sDPwsRROEW+1QK8bRaVK7362rPKgH1g/EkZgPI2h4H3PVz4zHvtH8aoVlwdV -ZqW1LS7YgFmypw23RuwhY/81q6UCzyr0TP579ZRdhE2o8mCP2w4lPJ9zcc+U30rq -299yOIzzlr3xF7zSujtFWsan9sYXiwGd/BmoKoMWuDpI/k4+oKsGGelT84ATB+0t -vz8KPFUgOSwsAGl0lUq8ILKpeeUYiZGo3BxN77t+Nwtd/jmliFKMAGzsGHxBvfaL -dXe6YJ2E5/4tAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD -AgEGMB0GA1UdDgQWBBQVOIMPPyw/cDMezUb+B4wg4NfDtzANBgkqhkiG9w0BAQUF -AAOCAQEAX/FBfXxcCLkr4NWSR/pnXKUTwwMhmytMiUbPWU3J/qVAtmPN3XEolWcR -zCSs00Rsca4BIGsDoo8Ytyk6feUWYFN4PMCvFYP3j1IzJL1kk5fui/fbGKhtcbP3 -LBfQdCVp9/5rPJS+TUtBjE7ic9DjkCJzQ83z7+pzzkWKsKZJ/0x9nXGIxHYdkFsd -7v3M9+79YKWxehZx0RbQfBI8bGmX265fOZpwLwU8GUYEmSA20GBuYQa7FkKMcPcw -++DbZqMAAb3mLNqRX6BGi01qnD093QVG/na/oAo85ADmJ7f/hC3euiInlhBx6yLt -398znM/jra6O1I7mT1GvFpLgXPYHDw== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIID5TCCAs2gAwIBAgIEOeSXnjANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UEBhMC -VVMxFDASBgNVBAoTC1dlbGxzIEZhcmdvMSwwKgYDVQQLEyNXZWxscyBGYXJnbyBD -ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEvMC0GA1UEAxMmV2VsbHMgRmFyZ28gUm9v -dCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDAxMDExMTY0MTI4WhcNMjEwMTE0 -MTY0MTI4WjCBgjELMAkGA1UEBhMCVVMxFDASBgNVBAoTC1dlbGxzIEZhcmdvMSww -KgYDVQQLEyNXZWxscyBGYXJnbyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEvMC0G -A1UEAxMmV2VsbHMgRmFyZ28gUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEi -MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDVqDM7Jvk0/82bfuUER84A4n13 -5zHCLielTWi5MbqNQ1mXx3Oqfz1cQJ4F5aHiidlMuD+b+Qy0yGIZLEWukR5zcUHE -SxP9cMIlrCL1dQu3U+SlK93OvRw6esP3E48mVJwWa2uv+9iWsWCaSOAlIiR5NM4O -JgALTqv9i86C1y8IcGjBqAr5dE8Hq6T54oN+J3N0Prj5OEL8pahbSCOz6+MlsoCu -ltQKnMJ4msZoGK43YjdeUXWoWGPAUe5AeH6orxqg4bB4nVCMe+ez/I4jsNtlAHCE -AQgAFG5Uhpq6zPk3EPbg3oQtnaSFN9OH4xXQwReQfhkhahKpdv0SAulPIV4XAgMB -AAGjYTBfMA8GA1UdEwEB/wQFMAMBAf8wTAYDVR0gBEUwQzBBBgtghkgBhvt7hwcB -CzAyMDAGCCsGAQUFBwIBFiRodHRwOi8vd3d3LndlbGxzZmFyZ28uY29tL2NlcnRw -b2xpY3kwDQYJKoZIhvcNAQEFBQADggEBANIn3ZwKdyu7IvICtUpKkfnRLb7kuxpo -7w6kAOnu5+/u9vnldKTC2FJYxHT7zmu1Oyl5GFrvm+0fazbuSCUlFLZWohDo7qd/ -0D+j0MNdJu4HzMPBJCGHHt8qElNvQRbn7a6U+oxy+hNH8Dx+rn0ROhPs7fpvcmR7 -nX1/Jv16+yWt6j4pf0zjAFcysLPp7VMX2YuyFA4w6OXVE8Zkr8QA1dhYJPz1j+zx -x32l2w8n0cbyQIjmH/ZhqPRCyLk306m+LFZ4wnKbWV01QIroTmMatukgalHizqSQ -33ZwmVxwQ023tqcZZE6St8WRPH9IFmV7Fv3L/PvZ1dZPIWU7Sn9Ho/s= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCB -gjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEk -MCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRY -UmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQxMTAxMTcx -NDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3 -dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2Vy -dmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB -dXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS6 -38eMpSe2OAtp87ZOqCwuIR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCP -KZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMxfoArtYzAQDsRhtDLooY2YKTVMIJt2W7Q -DxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FEzG+gSqmUsE3a56k0enI4 -qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqsAxcZZPRa -JSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNVi -PvryxS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0P -BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASs -jVy16bYbMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0 -eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQEwDQYJKoZIhvcNAQEFBQAD -ggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc/Kh4ZzXxHfAR -vbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt -qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLa -IR9NmXmd4c8nnxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSy -i6mx5O+aGtA9aZnuqCij4Tyz8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQ -O+7ETPTsJ3xCwnR8gooJybQDJbw= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEQTCCAymgAwIBAgIBATALBgkqhkiG9w0BAQUwgdMxEzARBgNVBAMMCmFwcGlu -Zi5jb20xNjA0BgNVBAoMLUFwcGxpZWQgSW5mb3JtYXRpY3MgU29mdHdhcmUgRW5n -aW5lZXJpbmcgR21iSDEUMBIGA1UECwwLRGV2ZWxvcG1lbnQxEjAQBgNVBAgMCUNh -cmludGhpYTELMAkGA1UEBgwCQVQxHjAcBgNVBAcMFVN0LiBKYWtvYiBpbSBSb3Nl -bnRhbDEtMCsGCSqGSIb3DQEJAQweZ3VlbnRlci5vYmlsdHNjaG5pZ0BhcHBpbmYu -Y29tMB4XDTA5MDIyMzEzNDAzNVoXDTExMTEyMDEzNDAzNVowgdMxEzARBgNVBAMM -CmFwcGluZi5jb20xNjA0BgNVBAoMLUFwcGxpZWQgSW5mb3JtYXRpY3MgU29mdHdh -cmUgRW5naW5lZXJpbmcgR21iSDEUMBIGA1UECwwLRGV2ZWxvcG1lbnQxEjAQBgNV -BAgMCUNhcmludGhpYTELMAkGA1UEBgwCQVQxHjAcBgNVBAcMFVN0LiBKYWtvYiBp -bSBSb3NlbnRhbDEtMCsGCSqGSIb3DQEJAQweZ3VlbnRlci5vYmlsdHNjaG5pZ0Bh -cHBpbmYuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx8mI/DXh -dwvwt/qMD5Mm+1ataiRJzau0ct07kyFv0hTYGJR7sl4ocC+lLqLOgOxeG0IaIKvP -Apqq7KQ1ZJBtpZAAwj8NwMXg8fGYM0JtpkGYmkRGmFolwFWA0FLVmGxAuw2iKN6k -ajl8U4pz5qzYFEKNL5IJMI8rS2Fsek1pgfpZ5dYFChgVW7urxFhAJCXMrHAOLfed -SjXtZpvepXRvBtuvOosXSIjmY9x/3/1QeRvZpza2atWRv4pnKBldtI9BZDUQqS3F -fi/ydXlZVeY3aHW6Cw9DfbnnLv2RegUzjUZCx07IrPulZmqS6rabIIwY/bhX+n7y -YcP4ADkXDKct6QIDAQABoyAwHjAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIC -hDANBgkqhkiG9w0BAQUFAAOCAQEAAfoSQow7qv3C9SiOZ+h3s9reQBJnZUcSQ5AS -90jGmtmcJ1eyWQyGxES0iKYPcF1GbSBkO/kqMzdM/E2GQnbHVrgiPj+9tTxjG/hK -42K2AEACDYtuQWTui4K1BmrWRJvdoiGRrt87DhmOG6UY5wtUAZdgVjhwBGEWJhYp -IgeNe5OEdrBkSBjYb2VnJOJFQA7bB7G4snTjNMY+n5+odISHU3debZLdXvX3gKVG -nVwp91/LnCSCvvZ+nH9xLzNdTbXqhI96bJh/iXLNcwcHOWPYWKuANAs5FR7OSZ+l -57gz8/BTaM4pTyJzER5p0+cTIzLGF7aYLuKKqXiKykjruO3U7A== +MIIDazCCAlOgAwIBAgIUe9dsChExYt5tGA3d9oFxRSxbOVYwDQYJKoZIhvcNAQEL +BQAwRTELMAkGA1UEBhMCQVUxDTALBgNVBAgMBFRlc3QxEzARBgNVBAoMCkxpYlNv +dXJjZXkxEjAQBgNVBAMMCWxvY2FsaG9zdDAeFw0yNjAzMTUwMDQwNDdaFw0zNjAz +MTIwMDQwNDdaMEUxCzAJBgNVBAYTAkFVMQ0wCwYDVQQIDARUZXN0MRMwEQYDVQQK +DApMaWJTb3VyY2V5MRIwEAYDVQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQC1p3AwPLLD9vSBNC2W/HRyzONJgRAC4zxOl812Vp5a +dq5LUFbAYeuLYSv5BWcx1q76gOzcM4EzHxabscGENY2IjmomTUa/4U0tN46lK/sO +Fkyvbi03TXQdCPdFnMHx/2fZ6IQi00+04YLWii2Lw5gBJwOfwytqSNIkaMk5FvpZ +iL/5X13WJdGsJhRWiwpYLc2Ojy8B63WwMswmNxVALY+C0lie7GRIaf4TzUZGKLEs +w/LXFY3BzQ1NR0ZvyRyqZ2MvQuewGmAsXjpcAArpHAa3WzNtEEPVqDRVqXbg2pTy +Tya6FN1vR0oG2MRNRtM/KKUD+Qqm6+SLPaLAqLB9YepvAgMBAAGjUzBRMB0GA1Ud +DgQWBBTuGkmfxPcJxO7Db2EBEOViDUxXSjAfBgNVHSMEGDAWgBTuGkmfxPcJxO7D +b2EBEOViDUxXSjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAy +uIm8WIg23Dpheue2rOrKxRFSXH5pixaxBu1U1AqkhJHRGoZsXZAO4xfHHFwpsPoP +yAF1fBWBqI/IirXi0vJb8THJBvGoLitJyv8Qq/Ib8EXXur5MRzIFYQvpuJt/4gpc +s0ke7B6VrIO0bZ6YesPB8MkL3g0DWSSliFWZ3epYPZShq88rXoD/Me2tTPGhew6A +fl/ltja85v7A4o4EdZRLZgUhFcVTyboLa3EkYDqDqflROKOc0G9uNykxbGctFmTQ +5AmmUcASntzWmF1+AH+u76mAkgMK9pl6xwyW2/hwWvdfxdQfRlRnTX9Z0OK8w8/U +JrpSbsyM4CwVlRMHr8AA -----END CERTIFICATE----- diff --git a/src/net/tests/cert.pem b/src/net/tests/cert.pem index 0efc2ef5b..382c858b6 100644 --- a/src/net/tests/cert.pem +++ b/src/net/tests/cert.pem @@ -1,13 +1,21 @@ -----BEGIN CERTIFICATE----- -MIICATCCAWoCCQDPufXH86n2QzANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJu -bzETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0 -cyBQdHkgTHRkMB4XDTEyMDEwMTE0NDQwMFoXDTIwMDMxOTE0NDQwMFowRTELMAkG -A1UEBhMCbm8xEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0 -IFdpZGdpdHMgUHR5IEx0ZDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAtrQ7 -+r//2iV/B6F+4boH0XqFn7alcV9lpjvAmwRXNKnxAoa0f97AjYPGNLKrjpkNXXhB -JROIdbRbZnCNeC5fzX1a+JCo7KStzBXuGSZr27TtFmcV4H+9gIRIcNHtZmJLnxbJ -sIhkGR8yVYdmJZe4eT5ldk1zoB1adgPF1hZhCBMCAwEAATANBgkqhkiG9w0BAQUF -AAOBgQCeWBEHYJ4mCB5McwSSUox0T+/mJ4W48L/ZUE4LtRhHasU9hiW92xZkTa7E -QLcoJKQiWfiLX2ysAro0NX4+V8iqLziMqvswnPzz5nezaOLE/9U/QvH3l8qqNkXu -rNbsW1h/IO6FV8avWFYVFoutUwOaZ809k7iMh2F2JMgXQ5EymQ== +MIIDazCCAlOgAwIBAgIUe9dsChExYt5tGA3d9oFxRSxbOVYwDQYJKoZIhvcNAQEL +BQAwRTELMAkGA1UEBhMCQVUxDTALBgNVBAgMBFRlc3QxEzARBgNVBAoMCkxpYlNv +dXJjZXkxEjAQBgNVBAMMCWxvY2FsaG9zdDAeFw0yNjAzMTUwMDQwNDdaFw0zNjAz +MTIwMDQwNDdaMEUxCzAJBgNVBAYTAkFVMQ0wCwYDVQQIDARUZXN0MRMwEQYDVQQK +DApMaWJTb3VyY2V5MRIwEAYDVQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQC1p3AwPLLD9vSBNC2W/HRyzONJgRAC4zxOl812Vp5a +dq5LUFbAYeuLYSv5BWcx1q76gOzcM4EzHxabscGENY2IjmomTUa/4U0tN46lK/sO +Fkyvbi03TXQdCPdFnMHx/2fZ6IQi00+04YLWii2Lw5gBJwOfwytqSNIkaMk5FvpZ +iL/5X13WJdGsJhRWiwpYLc2Ojy8B63WwMswmNxVALY+C0lie7GRIaf4TzUZGKLEs +w/LXFY3BzQ1NR0ZvyRyqZ2MvQuewGmAsXjpcAArpHAa3WzNtEEPVqDRVqXbg2pTy +Tya6FN1vR0oG2MRNRtM/KKUD+Qqm6+SLPaLAqLB9YepvAgMBAAGjUzBRMB0GA1Ud +DgQWBBTuGkmfxPcJxO7Db2EBEOViDUxXSjAfBgNVHSMEGDAWgBTuGkmfxPcJxO7D +b2EBEOViDUxXSjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAy +uIm8WIg23Dpheue2rOrKxRFSXH5pixaxBu1U1AqkhJHRGoZsXZAO4xfHHFwpsPoP +yAF1fBWBqI/IirXi0vJb8THJBvGoLitJyv8Qq/Ib8EXXur5MRzIFYQvpuJt/4gpc +s0ke7B6VrIO0bZ6YesPB8MkL3g0DWSSliFWZ3epYPZShq88rXoD/Me2tTPGhew6A +fl/ltja85v7A4o4EdZRLZgUhFcVTyboLa3EkYDqDqflROKOc0G9uNykxbGctFmTQ +5AmmUcASntzWmF1+AH+u76mAkgMK9pl6xwyW2/hwWvdfxdQfRlRnTX9Z0OK8w8/U +JrpSbsyM4CwVlRMHr8AA -----END CERTIFICATE----- diff --git a/src/net/tests/clientsockettest.h b/src/net/tests/clientsockettest.h index 3efc1c369..be348b005 100644 --- a/src/net/tests/clientsockettest.h +++ b/src/net/tests/clientsockettest.h @@ -20,13 +20,13 @@ class ClientSocketTest : public SocketAdapter : address("127.0.0.1", port) , passed(false) { - LTrace("Creating: ", port) + LTrace("Creating: ", port); } virtual ~ClientSocketTest() { // assert(socket.base().refCount() == 1); - LTrace("Destroying") + LTrace("Destroying"); } void run() @@ -42,38 +42,44 @@ class ClientSocketTest : public SocketAdapter //socket.shutdown(); } - virtual void onSocketConnect(Socket& sock) override + virtual bool onSocketConnect(Socket& sock) override { - LDebug("Connected") + LDebug("Connected"); sock.send("client > server", 15); + return false; } - virtual void onSocketRecv(Socket&, const MutableBuffer& buffer, const Address& peerAddress) override + virtual bool onSocketRecv(Socket&, const MutableBuffer& buffer, const Address& peerAddress) override { std::string data(bufferCast(buffer), buffer.size()); - LDebug("On recv:", data) + LDebug("On recv:", data); // Check for return packet echoing sent data if (data == "client > server") { - LTrace("Recv: Got Return Packet!") + LTrace("Recv: Got Return Packet!"); passed = true; stop(); - } else - assert(false); // fail... + } else { + LError("Unexpected data received:", data); + stop(); + } + return false; } - virtual void onSocketError(Socket&, const Error& error) override + virtual bool onSocketError(Socket&, const Error& error) override { // assert(sender == &socket); - LDebug("On error:", error.message) + LDebug("On error:", error.message); + return false; } - virtual void onSocketClose(Socket&) override + virtual bool onSocketClose(Socket&) override { // The last callback to fire is the Closed signal // which notifies us the underlying libuv socket // handle is closed. Das is gut! - LDebug("On closed") + LDebug("On closed"); + return false; } }; diff --git a/src/net/tests/key.pem b/src/net/tests/key.pem index 176fe320b..500d5f2a4 100644 --- a/src/net/tests/key.pem +++ b/src/net/tests/key.pem @@ -1,15 +1,28 @@ ------BEGIN RSA PRIVATE KEY----- -MIICXAIBAAKBgQC2tDv6v//aJX8HoX7hugfReoWftqVxX2WmO8CbBFc0qfEChrR/ -3sCNg8Y0squOmQ1deEElE4h1tFtmcI14Ll/NfVr4kKjspK3MFe4ZJmvbtO0WZxXg -f72AhEhw0e1mYkufFsmwiGQZHzJVh2Yll7h5PmV2TXOgHVp2A8XWFmEIEwIDAQAB -AoGAAlVY8sHi/aE+9xT77twWX3mGHV0SzdjfDnly40fx6S1Gc7bOtVdd9DC7pk6l -3ENeJVR02IlgU8iC5lMHq4JEHPE272jtPrLlrpWLTGmHEqoVFv9AITPqUDLhB9Kk -Hjl7h8NYBKbr2JHKICr3DIPKOT+RnXVb1PD4EORbJ3ooYmkCQQDfknUnVxPgxUGs -ouABw1WJIOVgcCY/IFt4Ihf6VWTsxBgzTJKxn3HtgvE0oqTH7V480XoH0QxHhjLq -DrgobWU9AkEA0TRJ8/ouXGnFEPAXjWr9GdPQRZ1Use2MrFjneH2+Sxc0CmYtwwqL -Kr5kS6mqJrxprJeluSjBd+3/ElxURrEXjwJAUvmlN1OPEhXDmRHd92mKnlkyKEeX -OkiFCiIFKih1S5Y/sRJTQ0781nyJjtJqO7UyC3pnQu1oFEePL+UEniRztQJAMfav -AtnpYKDSM+1jcp7uu9BemYGtzKDTTAYfoiNF42EzSJiGrWJDQn4eLgPjY0T0aAf/ -yGz3Z9ErbhMm/Ysl+QJBAL4kBxRT8gM4ByJw4sdOvSeCCANFq8fhbgm8pGWlCPb5 -JGmX3/GHFM8x2tbWMGpyZP1DLtiNEFz7eCGktWK5rqE= ------END RSA PRIVATE KEY----- +-----BEGIN PRIVATE KEY----- +MIIEuwIBADANBgkqhkiG9w0BAQEFAASCBKUwggShAgEAAoIBAQC1p3AwPLLD9vSB +NC2W/HRyzONJgRAC4zxOl812Vp5adq5LUFbAYeuLYSv5BWcx1q76gOzcM4EzHxab +scGENY2IjmomTUa/4U0tN46lK/sOFkyvbi03TXQdCPdFnMHx/2fZ6IQi00+04YLW +ii2Lw5gBJwOfwytqSNIkaMk5FvpZiL/5X13WJdGsJhRWiwpYLc2Ojy8B63WwMswm +NxVALY+C0lie7GRIaf4TzUZGKLEsw/LXFY3BzQ1NR0ZvyRyqZ2MvQuewGmAsXjpc +AArpHAa3WzNtEEPVqDRVqXbg2pTyTya6FN1vR0oG2MRNRtM/KKUD+Qqm6+SLPaLA +qLB9YepvAgMBAAECgf9kwnt4RjLigBkfkdG37lCpXPy1yOEYuPK6pXlSKrmrdCk5 +nVaBX89HgJ7jghu7iVmFmf3IJsmDkbr4oaC1tP7MwDIhDLwxssccTbTR6ZNYPQZM +SNDL3CqL8G04L7tkgEcal96zcoLD0lLAreSVoeiuuvVHqPpr+fiWOYlkIVq8Tiuc +Ar5u4tkYdcXBf9XhvxU3ZIyKcAa7cwOLnDQrkEpl5MSyo09Yl2wSdE1fNFHynccg +OBbLLZc8iAcSkbuGOuUeuUWlWNgJBUK3ULHeQMdevG7I5KOtyGrGC2tT6r9aGlk5 +/bBETuoB38ElAPPrCaibyR3U68oR7nF0v/kp92ECgYEA/s33+1n+Nn41Dol6+gGf +MUMdX1lYlyDKwms0OTOaRtgnQrumER2xn05oVJWcVF9w6Z+YywrE1QW851ZCYw8w +P7/bajRyih6REfOtUnEdQF1AfPiunFQ7Cod00QqwQ+qjoH+EdPZYP/Zt38aE4xld +09O0nBTNIlLSepu+eDPkqfkCgYEAtoGc1RCnGWjhCQR1wiE58Rgbsu7oYdwR9ejC +aRCZqhaBUh4JA98t+J30fp9o3IchDUmFYySFuVW+LVW+9ru7yndNiz0+Y8mJ65Yo +g9s+goY/H+HEC26jEyseqpLa21ysEHOkZGbpTgCS++30Pc9GK/eUQGMt3UdYNBC8 +YBq5kacCgYEA3vJbO5uHeii9xcV3S88lelYOGkKz6DAyGSDyJebH45r350UHTkyc +ARb65J+vlIeZ5WDWsTnv9bA6lHP+TGyau/zkQC451i5eosWC7vK4NHwjk/WH2pM8 +wb658LqYdiSVHTbWL/zoRLcbdkReO9MTLOg9TKBKyPCM5+jkJIrLVgkCgYAYi4n6 +JckzY6WQPudPeoR+Zk2jXPon3x8TQYCT/MWN2IT/9EYmHSfjneq59Np3fjz1uoOT +9998M4nmMvgB2vHAoxbsuQnhBcPkyUcdpKjdiQyITya8mt6Xv17adfG1OttxQvxC +/Iw4D1+1PiVxAqVfWGa52hza+7NjHTUYf7+hVQKBgDfr4R6JTaIUnSGuH1NzWBw1 +LN+2XEL1rbnaqLhFeT9lIjqem/S98inigTv3c6ZTFAjnIkTp5RAyJXRg4pqIMSte +K9knJqbB7uG+konS9PYbNStCbfE6cbmY5q05YLg6o9Jbw3prXbShRNkQzX6656CN +sH4hxNSzY7xjAWaeI2Uk +-----END PRIVATE KEY----- diff --git a/src/net/tests/nettests.cpp b/src/net/tests/nettests.cpp index ce434949f..1df466035 100644 --- a/src/net/tests/nettests.cpp +++ b/src/net/tests/nettests.cpp @@ -1,12 +1,12 @@ - #include "scy/base.h" +#include "scy/base.h" #include "scy/logger.h" #include "scy/net/address.h" +#include "scy/net/socketemitter.h" #include "scy/net/sslcontext.h" #include "scy/net/sslmanager.h" #include "scy/net/sslsocket.h" #include "scy/net/tcpsocket.h" #include "scy/net/udpsocket.h" -#include "scy/net/socketemitter.h" #include "scy/test.h" #include "scy/time.h" @@ -22,13 +22,15 @@ using namespace scy::test; int main(int argc, char** argv) { - Logger::instance().add(new ConsoleChannel("debug", Level::Trace)); + Logger::instance().add(std::make_unique("debug", Level::Trace)); test::init(); - net::SSLManager::initNoVerifyServer(); + net::SSLManager::initNoVerifyServer( + std::string(SCY_SOURCE_DIR) + "/net/tests/key.pem", + std::string(SCY_SOURCE_DIR) + "/net/tests/cert.pem"); net::SSLManager::initNoVerifyClient(); - + // ========================================================================= // Address Test // @@ -85,6 +87,91 @@ int main(int argc, char** argv) }); + // ========================================================================= + // Address: IPv6 + // + describe("ipv6 address", []() { + net::Address sa1("::1", 8080); + expect(sa1.host() == "::1"); + expect(sa1.port() == 8080); + expect(sa1.family() == net::Address::IPv6); + + net::Address sa2("[::1]:9090"); + expect(sa2.host() == "::1"); + expect(sa2.port() == 9090); + + net::Address sa3("::ffff:192.168.1.1", 80); + expect(sa3.port() == 80); + }); + + + // ========================================================================= + // Address: copy, assignment, comparison + // + describe("address copy and comparison", []() { + net::Address a1("192.168.1.100", 100); + net::Address a2(a1); // copy + expect(a1 == a2); + expect(!(a1 != a2)); + + net::Address a3("192.168.1.100", 200); + expect(a1 != a3); + expect(a1 < a3); // same host, lower port + + // assignment + net::Address a4("10.0.0.1", 80); + a4 = a1; + expect(a4 == a1); + + // swap + net::Address a5("10.0.0.1", 80); + net::Address a6("192.168.1.1", 443); + a5.swap(a6); + expect(a5.host() == "192.168.1.1"); + expect(a5.port() == 443); + expect(a6.host() == "10.0.0.1"); + expect(a6.port() == 80); + }); + + + // ========================================================================= + // Address: validation + // + describe("address validation", []() { + expect(net::Address::validateIP("192.168.1.1")); + expect(net::Address::validateIP("::1")); + expect(net::Address::validateIP("0.0.0.0")); + expect(!net::Address::validateIP("999.999.999.999")); + expect(!net::Address::validateIP("not_an_ip")); + expect(!net::Address::validateIP("")); + }); + + + // ========================================================================= + // Address: toString + // + describe("address toString", []() { + net::Address sa("192.168.1.100", 8080); + std::string str = sa.toString(); + expect(str == "192.168.1.100:8080"); + + net::Address wildcard; + expect(wildcard.host() == "0.0.0.0"); + expect(wildcard.port() == 0); + }); + + + // ========================================================================= + // Address: service resolution + // + describe("address service resolution", []() { + expect(net::Address::resolveService("http") == 80); + expect(net::Address::resolveService("https") == 443); + expect(net::Address::resolveService("ftp") == 21); + expect(net::Address::resolveService("8080") == 8080); + }); + + // ========================================================================= // TCP Socket Test // @@ -248,16 +335,18 @@ int main(int argc, char** argv) int connected = 0; net::SocketEmitter socket(std::make_shared()); socket->connect("sourcey.com", 80); - socket.Connect += [&](net::Socket& sock) { + socket.Connect += [&](net::Socket& sock) -> bool { connected++; sock.close(); + return false; }; - socket.Close += [&](net::Socket& sock) { + socket.Close += [&](net::Socket& sock) -> bool { // connect again on close if (connected == 1) { sock.connect("sourcey.com", 80); // assert(0); } + return false; }; uv::runLoop(); @@ -275,15 +364,17 @@ int main(int argc, char** argv) int connected = 0; net::SocketEmitter socket(std::make_shared()); - socket.Connect += [&](net::Socket& sock) { + socket.Connect += [&](net::Socket& sock) -> bool { connected++; sock.close(); + return false; }; - socket.Close += [&](net::Socket& sock) { + socket.Close += [&](net::Socket& sock) -> bool { // connect again on close if (connected == 1) { sock.connect("127.0.0.1", 1337); } + return false; }; socket->connect("127.0.0.1", 1337); diff --git a/src/pacm b/src/pacm new file mode 160000 index 000000000..b5ad8f699 --- /dev/null +++ b/src/pacm @@ -0,0 +1 @@ +Subproject commit b5ad8f699beb5980677ffd3f3a3bec4b989392af diff --git a/src/pluga b/src/pluga new file mode 160000 index 000000000..23f590b6e --- /dev/null +++ b/src/pluga @@ -0,0 +1 @@ +Subproject commit 23f590b6e17abd91da80b6801f1792110092960a diff --git a/src/sched/CMakeLists.txt b/src/sched/CMakeLists.txt index 7f3d38880..02ebf22e4 100644 --- a/src/sched/CMakeLists.txt +++ b/src/sched/CMakeLists.txt @@ -1,7 +1,3 @@ -ask_build_sourcey_module(sched) -if(BUILD_MODULES OR (NOT BUILD_MODULES AND BUILD_MODULE_sched)) - #include_dependency(LibUV) #REQUIRED - #include_dependency(JsonCpp) - - define_sourcey_module(sched base json) -endif() +scy_add_module(sched + DEPENDS base json +) diff --git a/src/sched/include/scy/sched/sched.h b/src/sched/include/scy/sched/sched.h index a8a9c3ab7..0f8f3c236 100644 --- a/src/sched/include/scy/sched/sched.h +++ b/src/sched/include/scy/sched/sched.h @@ -9,8 +9,7 @@ /// @{ -#ifndef SCY_Sched_h -#define SCY_Sched_h +#pragma once #include "scy/base.h" @@ -18,17 +17,14 @@ // Shared library exports #if defined(SCY_WIN) && defined(SCY_SHARED_LIBRARY) - #if defined(Sched_EXPORTS) - #define Sched_API __declspec(dllexport) - #else - #define Sched_API __declspec(dllimport) - #endif +#if defined(Sched_EXPORTS) +#define Sched_API __declspec(dllexport) #else - #define Sched_API // nothing +#define Sched_API __declspec(dllimport) +#endif +#else +#define Sched_API // nothing #endif - - -#endif // SCY_Sched_H /// @\} diff --git a/src/sched/include/scy/sched/scheduler.h b/src/sched/include/scy/sched/scheduler.h index 32f5325cd..a6fecadf1 100644 --- a/src/sched/include/scy/sched/scheduler.h +++ b/src/sched/include/scy/sched/scheduler.h @@ -9,16 +9,14 @@ /// @{ -#ifndef SCY_Sched_Scheduler_H -#define SCY_Sched_Scheduler_H +#pragma once +#include "scy/json/iserializable.h" +#include "scy/logger.h" #include "scy/sched/sched.h" #include "scy/sched/task.h" #include "scy/sched/taskfactory.h" -#include "scy/json/iserializable.h" -#include "scy/logger.h" -#include "scy/singleton.h" #include "scy/task.h" #include @@ -30,7 +28,8 @@ namespace sched { /// The Scheduler manages and runs tasks /// that need to be executed at specific times. -class Sched_API Scheduler : public TaskRunner, public json::ISerializable +class Sched_API Scheduler : public TaskRunner + , public json::ISerializable { public: Scheduler(); @@ -66,7 +65,4 @@ class Sched_API Scheduler : public TaskRunner, public json::ISerializable } // namespace scy -#endif // SCY_Sched_Scheduler_H - - /// @\} diff --git a/src/sched/include/scy/sched/task.h b/src/sched/include/scy/sched/task.h index 8c8840327..5f1e9ec37 100644 --- a/src/sched/include/scy/sched/task.h +++ b/src/sched/include/scy/sched/task.h @@ -9,15 +9,16 @@ /// @{ -#ifndef SCY_Sched_Task_H -#define SCY_Sched_Task_H +#pragma once +#include "scy/json/iserializable.h" #include "scy/sched/sched.h" #include "scy/sched/trigger.h" -#include "scy/json/iserializable.h" #include "scy/task.h" +#include + namespace scy { namespace sched { @@ -28,7 +29,8 @@ class Sched_API Scheduler; /// This class extends the Task class to implement /// scheduling capabilities. -class Sched_API Task : public scy::Task, public json::ISerializable +class Sched_API Task : public scy::Task + , public json::ISerializable { public: Task(const std::string& type = "", const std::string& name = ""); @@ -42,14 +44,16 @@ class Sched_API Task : public scy::Task, public json::ISerializable /// Deserializes the task from JSON. virtual void deserialize(json::value& root) override; - template T* createTrigger() + template + T* createTrigger() { - T* p = new T(); - setTrigger(p); - return p; + auto p = std::make_unique(); + auto* raw = p.get(); + setTrigger(std::move(p)); + return raw; } - - void setTrigger(sched::Trigger* trigger); + + void setTrigger(std::unique_ptr trigger); /// Returns a reference to the associated /// sched::Trigger or throws an exception. @@ -69,10 +73,9 @@ class Sched_API Task : public scy::Task, public json::ISerializable std::string name() const; void setName(const std::string& name); -protected: - // Task& operator=(Task const&) {} virtual ~Task(); +protected: virtual bool beforeRun(); virtual void run() = 0; virtual bool afterRun(); @@ -89,19 +92,16 @@ class Sched_API Task : public scy::Task, public json::ISerializable std::string _type; std::string _name; sched::Scheduler* _scheduler; - sched::Trigger* _trigger; + std::unique_ptr _trigger; mutable std::mutex _mutex; }; -typedef std::vector TaskList; +using TaskList = std::vector; } // namespace sched } // namespace scy -#endif // SCY_Sched_Task_H - - /// @\} diff --git a/src/sched/include/scy/sched/taskfactory.h b/src/sched/include/scy/sched/taskfactory.h index 8c496390e..9d2fb3b99 100644 --- a/src/sched/include/scy/sched/taskfactory.h +++ b/src/sched/include/scy/sched/taskfactory.h @@ -9,16 +9,15 @@ /// @{ -#ifndef SCY_Sched_TaskFactory_H -#define SCY_Sched_TaskFactory_H +#pragma once +#include "scy/logger.h" #include "scy/sched/sched.h" #include "scy/sched/task.h" #include "scy/sched/trigger.h" -#include "scy/logger.h" -#include "scy/singleton.h" +#include #include @@ -29,14 +28,16 @@ namespace sched { class Sched_API Scheduler; -template sched::Task* instantiateTask() +template +std::unique_ptr instantiateTask() { - return new T; + return std::make_unique(); } -template sched::Trigger* instantiateTrigger() +template +std::unique_ptr instantiateTrigger() { - return new T; + return std::make_unique(); } @@ -49,15 +50,15 @@ class Sched_API TaskFactory /// Returns the default TaskFactory singleton. static TaskFactory& getDefault() { - static Singleton sh; - return *sh.get(); + static TaskFactory instance; + return instance; } /// Scheduled Tasks - typedef std::map TaskMap; + using TaskMap = std::map (*)(/*Scheduler&*/)>; - sched::Task* createTask(const std::string& type/*, Scheduler& scheduler*/) + std::unique_ptr createTask(const std::string& type /*, Scheduler& scheduler*/) { std::lock_guard guard(_mutex); auto it = _tasks.find(type); @@ -66,7 +67,8 @@ class Sched_API TaskFactory return it->second(); } - template void registerTask(const std::string& type) + template + void registerTask(const std::string& type) { std::lock_guard guard(_mutex); _tasks[type] = &instantiateTask; @@ -90,9 +92,9 @@ class Sched_API TaskFactory // /// Schedule Triggers - typedef std::map TriggerMap; + using TriggerMap = std::map (*)()>; - sched::Trigger* createTrigger(const std::string& type) + std::unique_ptr createTrigger(const std::string& type) { std::lock_guard guard(_mutex); auto it = _triggers.find(type); @@ -101,7 +103,8 @@ class Sched_API TaskFactory return it->second(); } - template void registerTrigger(const std::string& type) + template + void registerTrigger(const std::string& type) { std::lock_guard guard(_mutex); _triggers[type] = &instantiateTrigger; @@ -134,7 +137,4 @@ class Sched_API TaskFactory } // namespace scy -#endif // SCY_Sched_TaskFactory_H - - /// @\} diff --git a/src/sched/include/scy/sched/trigger.h b/src/sched/include/scy/sched/trigger.h index c5e185035..ba5929004 100644 --- a/src/sched/include/scy/sched/trigger.h +++ b/src/sched/include/scy/sched/trigger.h @@ -9,13 +9,12 @@ /// @{ -#ifndef SCY_Sched_Trigger_H -#define SCY_Sched_Trigger_H +#pragma once -#include "scy/sched/sched.h" #include "scy/datetime.h" #include "scy/json/iserializable.h" +#include "scy/sched/sched.h" namespace scy { @@ -162,7 +161,4 @@ struct DailyTrigger : public Trigger } // namespace scy -#endif // SCY_Sched_Trigger_H - - /// @\} diff --git a/src/sched/src/scheduler.cpp b/src/sched/src/scheduler.cpp index 770f6f729..ab97005b3 100644 --- a/src/sched/src/scheduler.cpp +++ b/src/sched/src/scheduler.cpp @@ -13,10 +13,9 @@ #include "scy/datetime.h" #include "scy/logger.h" #include "scy/platform.h" -#include "scy/singleton.h" -#include "assert.h" #include +#include using namespace std; @@ -58,13 +57,9 @@ void Scheduler::run() { // Update and sort the task list bringing the // next scheduled task to the front of the list. - // TODO: Call only after task run, and when the - // initial task is nullptr. update(); - // TODO: Create a nextTask member so we don't - // need to call next() on each iteration - auto task = reinterpret_cast(next()); + auto task = static_cast(next()); // Run the task if (task && task->trigger().timeout()) { @@ -73,27 +68,23 @@ void Scheduler::run() DateTime now; Timespan remaining = task->trigger().scheduleAt - now; STrace << "Waiting: " - << "\n\tPID: " << task - << "\n\tDays: " << remaining.days() - << "\n\tHours: " << remaining.totalHours() - << "\n\tMinutes: " << remaining.totalMinutes() - << "\n\tSeconds: " << remaining.totalSeconds() - << "\n\tMilliseconds: " - << remaining.totalMilliseconds() << "\n\tCurrentTime: " - << DateTimeFormatter::format( - now, DateTimeFormat::ISO8601_FORMAT) - << "\n\tScheduledAt: " - << DateTimeFormatter::format( - task->trigger().scheduleAt, - DateTimeFormat::ISO8601_FORMAT) - << endl; + << "\n\tPID: " << task + << "\n\tDays: " << remaining.days() + << "\n\tHours: " << remaining.totalHours() + << "\n\tMinutes: " << remaining.totalMinutes() + << "\n\tSeconds: " << remaining.totalSeconds() + << "\n\tMilliseconds: " + << remaining.totalMilliseconds() << "\n\tCurrentTime: " + << DateTimeFormatter::format( + now, DateTimeFormat::ISO8601_FORMAT) + << "\n\tScheduledAt: " + << DateTimeFormatter::format( + task->trigger().scheduleAt, + DateTimeFormat::ISO8601_FORMAT) + << endl; } #endif - // Wait for the scheduled timeout - // if (!task->trigger().timeout()) - // _wakeUp.tryWait(static_cast(task->trigger().remaining())); - // The task list may have changed during the timeout // duration, or the current task deleted, so we need // to ensure that the next pending task matches the @@ -113,26 +104,25 @@ void Scheduler::run() << endl; } #else - LTrace("Running: ", task) + LTrace("Running: ", task); #endif task->run(); if (task->afterRun()) onRun(task); else { - LTrace("Destroy After Run: ", task) - task->_destroyed = true; // destroy(); + LTrace("Destroy After Run: ", task); + task->_destroyed = true; } } else - LTrace("Skipping Task: ", task) + LTrace("Skipping Task: ", task); - // Destroy the task if needed + // Destroy the task if needed. + // remove() erases the unique_ptr which deletes the task. if (task->destroyed()) { - LTrace("Destroy Task: ", task) - assert(remove(task)); - delete task; + LTrace("Destroy Task: ", task); + if (!remove(task)) + throw std::runtime_error("Failed to remove destroyed task"); } - - // LTrace("Running: OK: ", task) } // Prevent 100% CPU @@ -144,35 +134,35 @@ void Scheduler::update() { std::lock_guard guard(_mutex); - // LTrace("Updating: ", _tasks.size()) - // Update and clean the task list auto it = _tasks.begin(); while (it != _tasks.end()) { - sched::Task* task = reinterpret_cast(*it); + auto* task = static_cast(it->get()); if (task->destroyed()) { - it = _tasks.erase(it); onRemove(task); - LTrace("Destroy: ", task) - delete task; + LTrace("Destroy: ", task); + it = _tasks.erase(it); // unique_ptr auto-deletes the task } else ++it; } - // Sort the task list to the next task to + // Sort the task list so the next task to // trigger is at the front of the queue. - sort(_tasks.begin(), _tasks.end(), sched::Task::CompareTimeout); + sort(_tasks.begin(), _tasks.end(), + [](const std::unique_ptr& l, const std::unique_ptr& r) { + return sched::Task::CompareTimeout(l.get(), r.get()); + }); } void Scheduler::serialize(json::value& root) { - LTrace("Serializing") + LTrace("Serializing"); std::lock_guard guard(_mutex); - for (auto it = _tasks.begin(); it != _tasks.end(); ++it) { - sched::Task* task = reinterpret_cast(*it); - LTrace("Serializing: ", task) + for (const auto& t : _tasks) { + auto* task = static_cast(t.get()); + LTrace("Serializing: ", task); json::value& entry = root[root.size()]; task->serialize(entry); task->trigger().serialize(entry["trigger"]); @@ -182,26 +172,20 @@ void Scheduler::serialize(json::value& root) void Scheduler::deserialize(json::value& root) { - LTrace("Deserializing") + LTrace("Deserializing"); for (auto it = root.begin(); it != root.end(); it++) { - sched::Task* task = nullptr; - sched::Trigger* trigger = nullptr; try { json::assertMember(*it, "trigger"); - task = factory().createTask((*it)["type"].get()); + auto task = factory().createTask((*it)["type"].get()); task->deserialize((*it)); - trigger = + auto trigger = factory().createTrigger((*it)["trigger"]["type"].get()); trigger->deserialize((*it)["trigger"]); - task->setTrigger(trigger); - schedule(task); + task->setTrigger(std::move(trigger)); + schedule(task.release()); // transfers ownership to TaskRunner } catch (std::exception& exc) { - if (task) - delete task; - if (trigger) - delete trigger; - LError("Deserialization Error: ", exc.what()) + LError("Deserialization Error: ", exc.what()); } } } @@ -217,8 +201,8 @@ void Scheduler::print(std::ostream& ost) Scheduler& Scheduler::getDefault() { - static Singleton sh; - return *sh.get(); + static Scheduler instance; + return instance; } diff --git a/src/sched/src/task.cpp b/src/sched/src/task.cpp index 80fd895e3..66beeef43 100644 --- a/src/sched/src/task.cpp +++ b/src/sched/src/task.cpp @@ -27,24 +27,23 @@ Task::Task(const std::string& type, const std::string& name) , _scheduler(nullptr) , _trigger(nullptr) { - LTrace("Create") + LTrace("Create"); } -Task::Task(sched::Scheduler& scheduler, const std::string& type, - const std::string& name) +Task::Task(sched::Scheduler& scheduler, const std::string& type, const std::string& name) : _type(type) , _name(name) , _scheduler(&scheduler) , _trigger(nullptr) { - LTrace("Create") + LTrace("Create"); } Task::~Task() { - LTrace("Destroy") + LTrace("Destroy"); } @@ -59,9 +58,10 @@ void Task::start() void Task::serialize(json::value& root) { - LTrace("Serializing") + LTrace("Serializing"); - std::lock_guard guard(_mutex); + std::lock_guard + guard(_mutex); root["id"] = _id; root["type"] = _type; @@ -71,9 +71,10 @@ void Task::serialize(json::value& root) void Task::deserialize(json::value& root) { - LTrace("Deserializing") + LTrace("Deserializing"); - std::lock_guard guard(_mutex); + std::lock_guard + guard(_mutex); json::assertMember(root, "id"); json::assertMember(root, "type"); @@ -103,12 +104,10 @@ bool Task::afterRun() } -void Task::setTrigger(sched::Trigger* trigger) +void Task::setTrigger(std::unique_ptr trigger) { std::lock_guard guard(_mutex); - if (_trigger) - delete _trigger; - _trigger = trigger; + _trigger = std::move(trigger); } diff --git a/src/sched/src/trigger.cpp b/src/sched/src/trigger.cpp index 468db3300..0853124c8 100644 --- a/src/sched/src/trigger.cpp +++ b/src/sched/src/trigger.cpp @@ -53,7 +53,7 @@ bool Trigger::expired() void Trigger::serialize(json::value& root) { - LTrace("Serializing") + LTrace("Serializing"); root["type"] = type; root["name"] = name; @@ -69,7 +69,7 @@ void Trigger::serialize(json::value& root) void Trigger::deserialize(json::value& root) { - LTrace("Deserializing") + LTrace("Deserializing"); json::assertMember(root, "type"); json::assertMember(root, "name"); @@ -128,7 +128,7 @@ bool IntervalTrigger::expired() void IntervalTrigger::serialize(json::value& root) { - LTrace("Serializing") + LTrace("Serializing"); Trigger::serialize(root); @@ -141,7 +141,7 @@ void IntervalTrigger::serialize(json::value& root) void IntervalTrigger::deserialize(json::value& root) { - LTrace("[IntervalTrigger] Deserializing") + LTrace("[IntervalTrigger] Deserializing"); json::assertMember(root, "interval"); json::assertMember(root["interval"], "days"); diff --git a/src/sched/tests/CMakeLists.txt b/src/sched/tests/CMakeLists.txt index 782fc332b..fb858afc6 100644 --- a/src/sched/tests/CMakeLists.txt +++ b/src/sched/tests/CMakeLists.txt @@ -1,3 +1 @@ -# include_dependency(JsonCpp) - -define_libsourcey_test(schedtests base net json sched) +scy_add_test(schedtests DEPENDS base net json sched) diff --git a/src/sched/tests/skedtests.cpp b/src/sched/tests/skedtests.cpp index 50a427eac..56ff5b194 100644 --- a/src/sched/tests/skedtests.cpp +++ b/src/sched/tests/skedtests.cpp @@ -1,177 +1,178 @@ -#include "scy/base.h" -#include "scy/datetime.h" -#include "scy/logger.h" -#include "scy/sched/scheduler.h" -#include "scy/test.h" - - -using namespace std; -using namespace scy; -using namespace scy::test; - - -static sched::Scheduler scheduler; -static int taskRunTimes = 0; - - -// ============================================================================= -// Test Scheduled Task -// -struct ScheduledTask : public sched::Task -{ - ScheduledTask() - : sched::Task("ScheduledTask") - { - } - - virtual ~ScheduledTask() {} - - void run() { taskRunTimes++; } - - void serialize(json::value& root) - { - sched::Task::serialize(root); - - root["CustomField"] = "blah"; - } - - void deserialize(json::value& root) - { - json::assertMember(root, "CustomField"); - - sched::Task::deserialize(root); - } -}; - - -int main(int argc, char** argv) -{ - Logger::instance().add(new ConsoleChannel("debug", Level::Trace)); - test::init(); - - // Register tasks and triggers - scheduler.factory().registerTask("ScheduledTask"); - scheduler.factory().registerTrigger("OnceOnlyTrigger"); - scheduler.factory().registerTrigger("DailyTrigger"); - scheduler.factory().registerTrigger("IntervalTrigger"); - - describe("once only task serialization", []() { - json::value json; - Timespan hundredMs(0, 1); - - // Schedule a once only task to run in 100ms time. - { - taskRunTimes = 0; - - auto task = new ScheduledTask(); - auto trigger = task->createTrigger(); - - DateTime dt; - dt += hundredMs; - trigger->scheduleAt = dt; - - scheduler.start(task); - - // Serialize the task - scheduler.serialize(json); - - // Wait for the task to complete - scy::sleep(1500); - expect(taskRunTimes == 1); - } - - // Deserialize the previous task from JSON and run it again - { - taskRunTimes = 0; - - // Set the task to run in 100ms time - { - DateTime dt; - dt += hundredMs; - json[(int)0]["trigger"]["scheduleAt"] = - DateTimeFormatter::format(dt, DateTimeFormat::ISO8601_FORMAT); - } - - // Dynamically create the task from JSON - LDebug("Sched Input JSON:\n", json.dump(4)) - scheduler.deserialize(json); - - // Print to cout - // LDebug("##### Sched Print Output:") - // scheduler.print(cout); - // LDebug("##### Sched Print Output END") - - // Output scheduler tasks as JSON before run - json::value before; - scheduler.serialize(before); - SDebug << "Sched Output JSON Before Run:\n" - << before.dump(4) << endl; - - // Wait for the task to complete - scy::sleep(1500); - expect(taskRunTimes == 1); - - // Output scheduler tasks as JSON after run - json::value after; - scheduler.serialize(after); - SDebug << "Sched Output JSON After Run:\n" - << json.dump(4) << endl; - } - }); - - describe("interval task", []() { - LDebug("Running Scheduled Task Test") - - taskRunTimes = 0; - - // Schedule an interval task to run 3 times at 100ms intervals - { - auto task = new ScheduledTask(); - sched::IntervalTrigger* trigger = - task->createTrigger(); - - trigger->interval = Timespan(0, 1); - trigger->maxTimes = 3; - - scheduler.start(task); - - // Print to cout - // LDebug("##### Sched Print Output:") - // scheduler.print(cout); - // LDebug("##### Sched Print Output END") - - // Wait for the task to complete - scy::sleep(1000); - expect(taskRunTimes == 3); - } - - LDebug("Running Scheduled Task Test: END") - }); - - // // Schedule to fire once now, and in two days time. - // { - // auto task = new ScheduledTask(); - // auto trigger = task->createTrigger(); - // - // // 2 secs from now - // DateTime dt; - // Timespan ts(2, 0); - // dt += ts; - // trigger->timeOfDay = dt; - // - // // skip tomorrow - // trigger->daysExcluded.push_back((DaysOfTheWeek)(dt.dayOfWeek() + 1)); - // - // scheduler.schedule(task); - // - // // TODO: Assert running date - // expect(task->trigger().remaining() == 1); - // expect(task->trigger().timesRun == 1); - // } - - test::runAll(); - - Logger::destroy(); - - return test::finalize(); -} +#include "scy/base.h" +#include "scy/datetime.h" +#include "scy/logger.h" +#include "scy/platform.h" +#include "scy/sched/scheduler.h" +#include "scy/test.h" + + +using namespace std; +using namespace scy; +using namespace scy::test; + + +static sched::Scheduler scheduler; +static int taskRunTimes = 0; + + +// ============================================================================= +// Test Scheduled Task +// +struct ScheduledTask : public sched::Task +{ + ScheduledTask() + : sched::Task("ScheduledTask") + { + } + + virtual ~ScheduledTask() {} + + void run() { taskRunTimes++; } + + void serialize(json::value& root) + { + sched::Task::serialize(root); + + root["CustomField"] = "blah"; + } + + void deserialize(json::value& root) + { + json::assertMember(root, "CustomField"); + + sched::Task::deserialize(root); + } +}; + + +int main(int argc, char** argv) +{ + Logger::instance().add(std::make_unique("debug", Level::Trace)); + test::init(); + + // Register tasks and triggers + scheduler.factory().registerTask("ScheduledTask"); + scheduler.factory().registerTrigger("OnceOnlyTrigger"); + scheduler.factory().registerTrigger("DailyTrigger"); + scheduler.factory().registerTrigger("IntervalTrigger"); + + describe("once only task serialization", []() { + json::value json; + Timespan hundredMs(0, 1); + + // Schedule a once only task to run in 100ms time. + { + taskRunTimes = 0; + + auto task = new ScheduledTask(); + auto trigger = task->createTrigger(); + + DateTime dt; + dt += hundredMs; + trigger->scheduleAt = dt; + + scheduler.start(task); + + // Serialize the task + scheduler.serialize(json); + + // Wait for the task to complete + scy::sleep(1500); + expect(taskRunTimes == 1); + } + + // Deserialize the previous task from JSON and run it again + { + taskRunTimes = 0; + + // Set the task to run in 100ms time + { + DateTime dt; + dt += hundredMs; + json[0]["trigger"]["scheduleAt"] = + DateTimeFormatter::format(dt, DateTimeFormat::ISO8601_FORMAT); + } + + // Dynamically create the task from JSON + LDebug("Sched Input JSON:\n", json.dump(4)); + scheduler.deserialize(json); + + // Print to cout + // LDebug("##### Sched Print Output:"); + // scheduler.print(cout); + // LDebug("##### Sched Print Output END"); + + // Output scheduler tasks as JSON before run + json::value before; + scheduler.serialize(before); + SDebug << "Sched Output JSON Before Run:\n" + << before.dump(4) << endl; + + // Wait for the task to complete + scy::sleep(1500); + expect(taskRunTimes == 1); + + // Output scheduler tasks as JSON after run + json::value after; + scheduler.serialize(after); + SDebug << "Sched Output JSON After Run:\n" + << json.dump(4) << endl; + } + }); + + describe("interval task", []() { + LDebug("Running Scheduled Task Test"); + + taskRunTimes = 0; + + // Schedule an interval task to run 3 times at 100ms intervals + { + auto task = new ScheduledTask(); + sched::IntervalTrigger* trigger = + task->createTrigger(); + + trigger->interval = Timespan(0, 1); + trigger->maxTimes = 3; + + scheduler.start(task); + + // Print to cout + // LDebug("##### Sched Print Output:"); + // scheduler.print(cout); + // LDebug("##### Sched Print Output END"); + + // Wait for the task to complete + scy::sleep(1000); + expect(taskRunTimes == 3); + } + + LDebug("Running Scheduled Task Test: END"); + }); + + // // Schedule to fire once now, and in two days time. + // { + // auto task = new ScheduledTask(); + // auto trigger = task->createTrigger(); + // + // // 2 secs from now + // DateTime dt; + // Timespan ts(2, 0); + // dt += ts; + // trigger->timeOfDay = dt; + // + // // skip tomorrow + // trigger->daysExcluded.push_back((DaysOfTheWeek)(dt.dayOfWeek() + 1)); + // + // scheduler.schedule(task); + // + // // TODO: Assert running date + // expect(task->trigger().remaining() == 1); + // expect(task->trigger().timesRun == 1); + // } + + test::runAll(); + + Logger::destroy(); + + return test::finalize(); +} diff --git a/src/socketio/CMakeLists.txt b/src/socketio/CMakeLists.txt index 49ad7c802..53906ba41 100644 --- a/src/socketio/CMakeLists.txt +++ b/src/socketio/CMakeLists.txt @@ -1,11 +1,7 @@ -ask_build_sourcey_module(socketio) -if(BUILD_MODULES OR (NOT BUILD_MODULES AND BUILD_MODULE_socketio)) - #include_dependency(LibUV) - include_dependency(SSL REQUIRED) - #include_dependency(JsonCpp) - #include_dependency(HttpParser) - #include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../http/vendor/http_parser) - - set(socketio_PRETTY_NAME SocketIO) - define_sourcey_module(socketio base crypto net http json) +if(HAVE_OPENSSL) + scy_add_module(socketio + DEPENDS base crypto net http json + PACKAGES OpenSSL::SSL OpenSSL::Crypto + PRETTY_NAME SocketIO + ) endif() diff --git a/src/socketio/deprecated/socketioclient/CMakeLists.txt b/src/socketio/deprecated/socketioclient/CMakeLists.txt deleted file mode 100644 index 6bdf2869b..000000000 --- a/src/socketio/deprecated/socketioclient/CMakeLists.txt +++ /dev/null @@ -1 +0,0 @@ -define_sourcey_module_sample(socketioclient base net socketio json) diff --git a/src/socketio/deprecated/socketioclient/socketioclient.cpp b/src/socketio/deprecated/socketioclient/socketioclient.cpp deleted file mode 100644 index b5f1ebb0d..000000000 --- a/src/socketio/deprecated/socketioclient/socketioclient.cpp +++ /dev/null @@ -1,205 +0,0 @@ -#include "scy/socketio/socket.h" -#include "scy/socketio/transaction.h" -#include "scy/util.h" - -#include -#include -#include -#include -#include - - -/* ----------------------------------------------------------------------------- - FIXME, THIS CODE IS OUT OF DATE! ------------------------------------------------------------------------------ */ - -using namespace std; -using namespace Sourcey; -using namespace Sourcey::Util; -using namespace Sourcey::Net; - - -class Messenger : public SocketIO::Socket -{ -public: - Messenger(const Net::Address& srvAddr) - : SocketIO::Socket(srvAddr) - { - } - - ~Messenger() {} - - void sendTransaction(const SocketIO::Packet& packet) - { - SocketIO::Transaction* txn = new SocketIO::Transaction(*this, packet); - txn->StateChanged += - sdelegate(this, &Messenger::onTransactionStateChanged); - txn->send(); - } - - void onTransactionStateChanged(void* sender, TransactionState& state, - const TransactionState&) - { - Log("debug", this) << "Transaction State Changed: " << state.toString() - << endl; - - SocketIO::Transaction* transaction = - reinterpret_cast(sender); - switch (state.id()) { - case TransactionState::Running: - break; - - case TransactionState::Success: - break; - - case TransactionState::Cancelled: - break; - - case TransactionState::Failed: - break; - } - }; -}; - -//} // namespace SocketIO -} // namespace Sourcey - - -int main(int argc, char** argv) -{ - Logger::instance().add(new ConsoleChannel("debug", STraceevel)); - - Sourcey::Net::Address srvAddr("localhost", 1337); - Messenger app(srvAddr); - app.connect(); - - std::string network = "4"; - std::string event; - char o = 0; - while (o != 'Q') { - try { - cout << "COMMANDS:\n\n" - " E Set Event Name.\n" - " A Announce.\n" - " 1 Send Connect.\n" - " M Send Message.\n" - " J Send JSON Message.\n" - //" X Send XMPP Message.\n" - " T Send Transaction.\n" - //" U Call Upload Asset Service.\n" - //" L List Services.\n" - //" K List Remote Packages.\n" - //" R Reload Service List.\n" - //" I Install Packages.\n" - //" U Uninstall Packages.\n" - //" D Update All Packages.\n" - " Q Quit.\n\n"; - - o = toupper(getch()); - - // Set Input File - if (o == 'E') { - cout << "Enter event name: " << endl; - getline(cin, event); - } - - // Send Message - else if (o == '1') { - app.sendConnect(); - } - - // Send Message - else if (o == 'M') { - app.send(SocketIO::Packet::Message, "wassssupppp!", true); - } - - // Send JSON Message - else if (o == 'J') { - app.send(SocketIO::Packet::JSON, "{\"name\":\"value\"}", true); - } - - // Send Announce - else if (o == 'A') { - // app.emit("announce", - // "{\"username\":\"admin\",\"name\":\"Admin - // Dude\",\"account\":\"4\"}", true); - } - - // Send XMPP Message - else if (o == 'X') { - // app.emit("xmpp", "{\"name\":\"value\"}", true); - } - - // Send Transaction - else if (o == 'T') { - SocketIO::Packet request(SocketIO::Packet::Message, 99, "", - "yooooooooooo", true); - app.sendTransaction(request); - } - } catch (Poco::Exception& e) { - cerr << e.displayText() << endl; - } - } - - - return 0; -} - - -/* -// Call Upload Asset Service -else if (o == 'U') { - - Path file("D:/test.avi"); - - HTMLForm* form = new HTMLForm(HTMLForm::ENCODING_MULTIPART_FORM); - form->set("asset[type]", "Video"); - form->addPart("asset[file]", new FilePartSource(file.toString())); - - APITransaction* transaction = app.upload("UploadAsset", form); -//file.toString(), - transaction->APITransactionComplete += sdelegate(&app, -&Messenger::onAPITransactionComplete); - transaction->start(); -} - -// List Services -else if (o == 'L') { - app.files().print(cout); -} - -// Reload Service List -else if (o == 'R') { - app.loadServices(); -} -*/ -/* -stringstream ss; -ss.put(0x00); -ss << "blah"; -ss.put(0xff); -ss << "blah"; -ss.put(0xff); -ss << "blah"; -ss.put(0xff); - -StringList v = Util::split(ss.str(), 0xff); -//cout << v.size(); - - -stringstream ss1; -ss1 << 0x00; -ss1.write("1::", 3); -ss1 << 0xff; -cout << ss1.str(); - -stringstream ss2; -ss2.put(0x00); -ss2.write("1::", 3); -ss2.put(0xff); -cout << ss2.str(); - - -system("pause"); -return 0; -*/ diff --git a/src/socketio/include/scy/socketio/client.h b/src/socketio/include/scy/socketio/client.h index 9ccf6e422..fc08d8c27 100644 --- a/src/socketio/include/scy/socketio/client.h +++ b/src/socketio/include/scy/socketio/client.h @@ -8,10 +8,7 @@ /// @addtogroup socketio /// @{ - -#ifndef SCY_SocketIO_Client_H -#define SCY_SocketIO_Client_H - +#pragma once #include "scy/collection.h" #include "scy/http/websocket.h" @@ -19,6 +16,9 @@ #include "scy/socketio/packet.h" #include "scy/socketio/transaction.h" +#include +#include + namespace scy { namespace sockio { @@ -35,57 +35,46 @@ struct ClientState : public State Error = 0x08 }; - std::string str(unsigned int id) const + std::string str(unsigned int id) const override { switch (id) { - case Closed: - return "Closed"; - case Connecting: - return "Connecting"; - case Connected: - return "Connected"; - case Online: - return "Online"; - case Error: - return "Error"; - default: - assert(false); + case Closed: return "Closed"; + case Connecting: return "Connecting"; + case Connected: return "Connected"; + case Online: return "Online"; + case Error: return "Error"; + default: return "undefined"; } - return "undefined"; - }; + } }; -class SocketIO_API Client : - public Stateful, - public net::SocketAdapter, - public PacketSignal +struct SocketIO_API ClientOptions { -public: - struct Options - { - std::string host = "127.0.0.1"; - uint16_t port = 4500; + std::string host = "127.0.0.1"; + uint16_t port = 4500; - /// Weather or not to reconnect if disconnected from the server. - bool reconnection = true; + /// Whether or not to reconnect if disconnected from the server. + bool reconnection = true; - /// The number of times to attempt to reconnect if disconnected - /// from the server. (0 = unlimited) - int reconnectAttempts = 0; - int reconnectDelay = 6 * 1000; // 6 secs + /// The number of times to attempt to reconnect if disconnected + /// from the server. (0 = unlimited) + int reconnectAttempts = 0; + int reconnectDelay = 6 * 1000; // 6 secs +}; - Options() { - // Required on gcc 6 - // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70528 - } - }; + +class SocketIO_API Client : public Stateful + , public net::SocketAdapter + , public PacketSignal +{ +public: + using Options = ClientOptions; public: Client(const net::Socket::Ptr& socket, const Options& options = Options()); virtual ~Client(); - // virtual void connect(const std::string& host, uint16_t port); virtual void connect(); virtual void close(); @@ -105,26 +94,25 @@ class SocketIO_API Client : Transaction* createTransaction(const sockio::Packet& request, long timeout = 10000); /// Return a reference to the client options object. - Client::Options& options(); + [[nodiscard]] Options& options(); /// Return the underlying WebSocket instance. - http::ws::WebSocket& ws(); + [[nodiscard]] http::ws::WebSocket& ws(); /// Return the current session ID assigned by the server. - std::string sessionID() const; + [[nodiscard]] std::string sessionID() const; /// Return the error object (if any). - scy::Error error() const; + [[nodiscard]] scy::Error error() const; - /// Return true if the client is is Online state. - bool isOnline() const; + /// Return true if the client is in Online state. + [[nodiscard]] bool isOnline() const; /// Return true if currently reconnecting. - bool reconnecting() const; + [[nodiscard]] bool reconnecting() const; /// Return true if the client was previously in the Online state. - /// Useful for delegates handling the Error state. - bool wasOnline() const; + [[nodiscard]] bool wasOnline() const; virtual const char* className() const { return "SocketIO::Client"; } @@ -141,29 +129,30 @@ class SocketIO_API Client : virtual void onHandshake(sockio::Packet& packet); virtual void onMessage(sockio::Packet& packet); - virtual void onSocketConnect(net::Socket& socket); - virtual void onSocketRecv(net::Socket& socket, const MutableBuffer& buffer, const net::Address& peerAddress); - virtual void onSocketError(net::Socket& socket, const scy::Error& error); - virtual void onSocketClose(net::Socket& socket); + virtual bool onSocketConnect(net::Socket& socket); + virtual bool onSocketRecv(net::Socket& socket, const MutableBuffer& buffer, const net::Address& peerAddress); + virtual bool onSocketError(net::Socket& socket, const scy::Error& error); + virtual bool onSocketClose(net::Socket& socket); + + /// Send the Socket.IO CONNECT packet for the default namespace. + virtual void sendConnect(); - virtual void onPingTimer(); + /// Handle a server ping by responding with pong. + virtual void onServerPing(); + + /// Called when no ping received within the expected interval. virtual void onPingTimeoutTimer(); virtual void startReconnectTimer(); virtual void stopReconnectTimer(); virtual void onReconnectTimer(); - virtual int sendPing(); - virtual void onPong(); - protected: - // mutable std::mutex _mutex; - Timer _pingTimer; Timer _pingTimeoutTimer; Timer _reconnectTimer; scy::Error _error; std::string _sessionID; - Client::Options _options; + Options _options; http::ws::WebSocket _ws; int _pingTimeout; int _pingInterval; @@ -176,7 +165,6 @@ class SocketIO_API Client : // TCP Client // - Client* createTCPClient(const Client::Options& options = Client::Options(), uv::Loop* loop = uv::defaultLoop()); @@ -192,7 +180,6 @@ class SocketIO_API TCPClient : public Client // SSL Client // - Client* createSSLClient(const Client::Options& options = Client::Options(), uv::Loop* loop = uv::defaultLoop()); @@ -208,7 +195,4 @@ class SocketIO_API SSLClient : public Client } // namespace scy -#endif // SCY_SocketIO_Client_H - - -/// @\} +/// @} diff --git a/src/socketio/include/scy/socketio/packet.h b/src/socketio/include/scy/socketio/packet.h index e13ba1e62..cee70700d 100644 --- a/src/socketio/include/scy/socketio/packet.h +++ b/src/socketio/include/scy/socketio/packet.h @@ -8,100 +8,115 @@ /// @addtogroup socketio /// @{ +#pragma once -#ifndef SCY_SocketIO_Packet_H -#define SCY_SocketIO_Packet_H - - -#include "scy/socketio/socketio.h" #include "scy/json/json.h" #include "scy/packet.h" +#include "scy/socketio/socketio.h" + +#include +#include namespace scy { namespace sockio { +/// Engine.IO frame types (protocol v4). +enum class Frame : int +{ + Open = 0, + Close = 1, + Ping = 2, + Pong = 3, + Message = 4, + Upgrade = 5, + Noop = 6, + Unknown = -1 +}; + +/// Socket.IO packet types (protocol v5). +enum class Type : int +{ + Connect = 0, + Disconnect = 1, + Event = 2, + Ack = 3, + ConnectError = 4, + BinaryEvent = 5, + BinaryAck = 6, + Unknown = -1 +}; + + class SocketIO_API Packet : public IPacket { public: - enum class Frame : int - { - Open = 0, - Close = 1, - Ping = 2, - Pong = 3, - Message = 4, - Upgrade = 5, - Noop = 6, - Unknown = -1 - }; - - enum class Type : int - { - TypeMin = 0, - Connect = 0, - Disconnect = 1, - Event = 2, - Ack = 3, - Error = 4, - BinaryEvent = 5, - BinaryAck = 6, - TypeMax = 6, - Unknown = -1 - }; - - /// Default contructor + // Keep nested aliases for backward compatibility with existing code + // that uses Packet::Frame and Packet::Type + using Frame = sockio::Frame; + using Type = sockio::Type; + + /// Default constructor Packet(Frame frame = Frame::Message, Type type = Type::Event, int id = -1, const std::string& nsp = "/", const std::string& event = "", const std::string& message = "", bool ack = false); - /// General contructor + /// General constructor Packet(Type type, const std::string& message = "", bool ack = false); - /// Message contructor + /// Message constructor Packet(const std::string& message, bool ack = false); - /// JSON contructor + /// JSON constructor Packet(const json::value& message, bool ack = false); - /// Event contructor + /// Event constructor Packet(const std::string& event, const std::string& message, bool ack = false); - /// Event JSON contructor + /// Event JSON constructor Packet(const std::string& event, const json::value& message, bool ack = false); - Packet(const Packet& r); - Packet& operator=(const Packet& r); - virtual ~Packet(); + Packet(const Packet& r) = default; + Packet& operator=(const Packet& r) = default; + Packet(Packet&& r) noexcept = default; + Packet& operator=(Packet&& r) noexcept = default; + ~Packet() override = default; - IPacket* clone() const override; + std::unique_ptr clone() const override; - Frame frame() const; - Type type() const; - int id() const; - std::string nsp() const; - std::string message() const; - json::value json() const; + [[nodiscard]] Frame frame() const; + [[nodiscard]] Type type() const; + [[nodiscard]] int id() const; + [[nodiscard]] std::string nsp() const; + [[nodiscard]] std::string event() const; + [[nodiscard]] std::string message() const; + [[nodiscard]] json::value json() const; void setID(int id); void setNamespace(const std::string& nsp); + void setEvent(const std::string& event); void setMessage(const std::string& message); void setAck(bool flag); ssize_t read(const ConstBuffer& buf) override; void write(Buffer& buf) const override; - size_t size() const override; + [[nodiscard]] size_t size() const override; - bool valid() const; + /// A packet is valid if it has a known frame and type. + /// Connect/Disconnect packets don't require an ID. + [[nodiscard]] bool valid() const; - std::string frameString() const; - std::string typeString() const; - std::string toString() const; + [[nodiscard]] std::string frameString() const; + [[nodiscard]] std::string typeString() const; + [[nodiscard]] std::string toString() const; void print(std::ostream& os) const; - const char* className() const { return "SocketIO::Packet"; } + const char* className() const override { return "SocketIO::Packet"; } + + /// Return the next sequential packet ID (thread-safe). + static int nextID(); protected: Frame _frame; @@ -112,6 +127,8 @@ class SocketIO_API Packet : public IPacket std::string _message; bool _ack; size_t _size; + + static std::atomic _idCounter; }; @@ -119,7 +136,4 @@ class SocketIO_API Packet : public IPacket } // namespace scy -#endif // SCY_SocketIO_Packet_H - - -/// @\} +/// @} diff --git a/src/socketio/include/scy/socketio/socketio.h b/src/socketio/include/scy/socketio/socketio.h index a6129f7ea..a4041f135 100644 --- a/src/socketio/include/scy/socketio/socketio.h +++ b/src/socketio/include/scy/socketio/socketio.h @@ -8,27 +8,21 @@ /// @addtogroup socketio /// @{ - -#ifndef SCY_SocketIO_H -#define SCY_SocketIO_H - +#pragma once #include "scy/base.h" // Shared library exports #if defined(SCY_WIN) && defined(SCY_SHARED_LIBRARY) - #if defined(SocketIO_EXPORTS) - #define SocketIO_API __declspec(dllexport) - #else - #define SocketIO_API __declspec(dllimport) - #endif +#if defined(SocketIO_EXPORTS) +#define SocketIO_API __declspec(dllexport) #else - #define SocketIO_API // nothing +#define SocketIO_API __declspec(dllimport) +#endif +#else +#define SocketIO_API // nothing #endif -#endif // SCY_SocketIO_H - - -/// @\} +/// @} diff --git a/src/socketio/include/scy/socketio/transaction.h b/src/socketio/include/scy/socketio/transaction.h index b67536a83..7c4cb3d31 100644 --- a/src/socketio/include/scy/socketio/transaction.h +++ b/src/socketio/include/scy/socketio/transaction.h @@ -8,10 +8,7 @@ /// @addtogroup socketio /// @{ - -#ifndef SCY_SocketIO_Transaction_H -#define SCY_SocketIO_Transaction_H - +#pragma once #include "scy/packettransaction.h" #include "scy/socketio/packet.h" @@ -29,18 +26,18 @@ struct SocketIO_API Transaction : public PacketTransaction Transaction(sockio::Client& client, long timeout = 10000); Transaction(sockio::Client& client, const sockio::Packet& request, long timeout = 10000); - virtual bool send() override; - virtual bool checkResponse(const sockio::Packet& packet) override; + bool send() override; + bool checkResponse(const sockio::Packet& packet) override; virtual void onPotentialResponse(sockio::Packet& packet); - virtual void onResponse() override; + void onResponse() override; virtual const char* className() const { return "SocketIO::Transaction"; } sockio::Client& client; protected: - virtual ~Transaction(); + ~Transaction() override; }; @@ -48,7 +45,4 @@ struct SocketIO_API Transaction : public PacketTransaction } // namespace scy -#endif // SCY_SocketIO_Transaction_H - - -/// @\} +/// @} diff --git a/src/socketio/src/client.cpp b/src/socketio/src/client.cpp index c5c42b47e..d1befd7db 100644 --- a/src/socketio/src/client.cpp +++ b/src/socketio/src/client.cpp @@ -13,10 +13,10 @@ #include "scy/http/client.h" #include "scy/net/sslsocket.h" #include "scy/net/tcpsocket.h" -#include - -using std::endl; +#include +#include +#include namespace scy { @@ -63,11 +63,13 @@ SSLClient::SSLClient(const Client::Options& options, uv::Loop* loop) Client::Client(const net::Socket::Ptr& socket, const Client::Options& options) - : _pingTimer(socket->loop()) - , _pingTimeoutTimer(socket->loop()) + : _pingTimeoutTimer(socket->loop()) , _reconnectTimer(socket->loop()) , _options(options) , _ws(socket) + , _pingTimeout(0) + , _pingInterval(0) + , _reconnecting(false) , _wasOnline(false) { _ws.addReceiver(this); @@ -77,14 +79,13 @@ Client::Client(const net::Socket::Ptr& socket, const Client::Options& options) Client::~Client() { _ws.removeReceiver(this); - close(); } void Client::connect() { - LTrace("Socket.IO Connecting") + LTrace("Socket.IO Connecting"); if (_options.host.empty() || !_options.port) throw std::runtime_error("The Socket.IO server address is not set."); @@ -93,16 +94,14 @@ void Client::connect() setState(this, ClientState::Connecting); - // Build the request - // TODO: Allow custom URI params + // Build the request URI + // Engine.IO v4: EIO=4, transport=websocket std::ostringstream url; url << "/socket.io/?EIO=4&transport=websocket"; if (!_sessionID.empty()) { - url << "&sid="; - url << _sessionID; + url << "&sid=" << _sessionID; } - url << "&t="; - url << std::time(NULL); + url << "&t=" << std::time(nullptr); _ws.request().setURI(url.str()); _ws.request().setHost(_options.host, _options.port); @@ -112,13 +111,13 @@ void Client::connect() void Client::close() { - LTrace("Closing") + LTrace("Closing"); if (_sessionID.empty()) return; reset(); onClose(); - LTrace("Closing: OK") + LTrace("Closing: OK"); } @@ -169,15 +168,27 @@ Transaction* Client::createTransaction(const sockio::Packet& request, long timeo } -int Client::sendPing() +void Client::sendConnect() { - // Start the ping timeout - _pingTimeoutTimer.stop(); - _pingTimeoutTimer.setTimeout(_pingTimeout); - _pingTimeoutTimer.start(); + // Send Socket.IO CONNECT packet for default namespace + // Wire format: "40" (frame=4 Message, type=0 Connect) + LTrace("Sending Socket.IO CONNECT"); + _ws.send("40", 2); +} - LTrace("Sending ping") - return _ws.send("2", 1); + +void Client::onServerPing() +{ + // Engine.IO v4: server sends ping ("2"), client responds with pong ("3") + LTrace("Received server ping, sending pong"); + _ws.send("3", 1); + + // Reset the ping timeout timer - we know the connection is alive + _pingTimeoutTimer.stop(); + if (_pingInterval > 0 && _pingTimeout > 0) { + _pingTimeoutTimer.setTimeout(_pingInterval + _pingTimeout); + _pingTimeoutTimer.start(); + } } @@ -186,9 +197,6 @@ void Client::reset() // Note: Only reset session related variables here. // Do not reset host and port variables. - _pingTimer.Timeout -= slot(this, &Client::onPingTimer); - _pingTimer.stop(); - _pingTimeoutTimer.Timeout -= slot(this, &Client::onPingTimeoutTimer); _pingTimeoutTimer.stop(); @@ -201,13 +209,12 @@ void Client::reset() _sessionID = ""; _pingInterval = 0; _pingTimeout = 0; - // _wasOnline = false; // Reset via onClose() } void Client::setError(const scy::Error& error) { - LError("Set error: ", error.message) + LError("Set error: ", error.message); // Set the wasOnline flag if previously online before error if (stateEquals(ClientState::Online)) @@ -219,8 +226,6 @@ void Client::setError(const scy::Error& error) // Start the reconnection timer if required if (_options.reconnection) { startReconnectTimer(); - - // Note: Do not call close() here, since we will be trying to reconnect... } else { close(); } @@ -229,7 +234,7 @@ void Client::setError(const scy::Error& error) void Client::onConnect() { - LTrace("On connect") + LTrace("On connect"); setState(this, ClientState::Connected); @@ -240,7 +245,9 @@ void Client::onConnect() void Client::startReconnectTimer() { - assert(_options.reconnection); + if (!_options.reconnection) + return; + _reconnectTimer.Timeout += slot(this, &Client::onReconnectTimer); _reconnectTimer.setTimeout(_options.reconnectDelay); _reconnectTimer.start(); @@ -262,27 +269,24 @@ void Client::stopReconnectTimer() void Client::onOnline() { - LTrace("On online") + LTrace("On online"); - assert(stateEquals(ClientState::Connected)); setState(this, ClientState::Online); - // Setup and start the ping timer - assert(_pingInterval); - _pingTimer.Timeout += slot(this, &Client::onPingTimer); - _pingTimer.setTimeout(_pingInterval); - _pingTimer.setInterval(_pingInterval); - _pingTimer.start(); - - // Setup the ping timeout timer - assert(_pingTimeout); - _pingTimeoutTimer.Timeout += slot(this, &Client::onPingTimeoutTimer); + // Start the ping timeout timer. + // Engine.IO v4: server pings us. If we don't receive a ping within + // pingInterval + pingTimeout, the connection is dead. + if (_pingInterval > 0 && _pingTimeout > 0) { + _pingTimeoutTimer.Timeout += slot(this, &Client::onPingTimeoutTimer); + _pingTimeoutTimer.setTimeout(_pingInterval + _pingTimeout); + _pingTimeoutTimer.start(); + } } void Client::onClose() { - LTrace("On close") + LTrace("On close"); stopReconnectTimer(); @@ -295,35 +299,38 @@ void Client::onClose() // // Socket Callbacks -void Client::onSocketConnect(net::Socket& socket) +bool Client::onSocketConnect(net::Socket& socket) { onConnect(); + return false; } -void Client::onSocketError(net::Socket& socket, const scy::Error& error) +bool Client::onSocketError(net::Socket& socket, const scy::Error& error) { - LTrace("On socket error: ", error.message) - + LTrace("On socket error: ", error.message); setError(error); + return false; } -// -void Client::onSocketClose(net::Socket& socket) -{ - LTrace("On socket close") - // Nothing to do since the error is set via onSocketError +bool Client::onSocketClose(net::Socket& socket) +{ + LTrace("On socket close"); - // If no socket error was set we have an EOF - // if (!error().any()) - // setError("Disconnected from the server"); + // If no error was set, treat as unexpected disconnect + if (!_error.any()) { + scy::Error err; + err.message = "Disconnected from server"; + setError(err); + } + return false; } -void Client::onSocketRecv(net::Socket& socket, const MutableBuffer& buffer, const net::Address& peerAddress) +bool Client::onSocketRecv(net::Socket& socket, const MutableBuffer& buffer, const net::Address& peerAddress) { - LTrace("On socket recv: ", buffer.size()) + LTrace("On socket recv: ", buffer.size()); sockio::Packet pkt; char* buf = bufferCast(buffer); @@ -335,140 +342,144 @@ void Client::onSocketRecv(net::Socket& socket, const MutableBuffer& buffer, cons len -= nread; } if (len == buffer.size()) - LWarn("Failed to parse incoming Socket.IO packet.") - -#if 0 - sockio::Packet pkt; - if (pkt.read(constBuffer(packet.data(), packet.size()))) - onPacket(pkt); - else - LWarn("Failed to parse incoming Socket.IO packet.") -#endif + LWarn("Failed to parse incoming Socket.IO packet."); + return false; } void Client::onHandshake(sockio::Packet& packet) { - LTrace("On handshake: ", state()) - // assert(stateEquals(ClientState::Connected)); - assert(packet.frame() == sockio::Packet::Frame::Open); + LTrace("On handshake: ", state()); json::value json = packet.json(); - if (json.find("sid") != json.end()) - _sessionID = json["sid"].get(); - if (json.find("pingInterval") != json.end()) - _pingInterval = json["pingInterval"].get(); - if (json.find("pingTimeout") != json.end()) - _pingTimeout = json["pingTimeout"].get(); + if (json.is_object()) { + if (json.contains("sid")) + _sessionID = json["sid"].get(); + if (json.contains("pingInterval")) + _pingInterval = json["pingInterval"].get(); + if (json.contains("pingTimeout")) + _pingTimeout = json["pingTimeout"].get(); + } - SDebug << "On handshake: " - << "sid=" << _sessionID << ", " - << "pingInterval=" << _pingInterval << ", " - << "pingTimeout=" << _pingTimeout << endl; + LDebug("On handshake: " + "sid=", + _sessionID, ", " + "pingInterval=", + _pingInterval, ", " + "pingTimeout=", + _pingTimeout); + // After receiving the Engine.IO Open packet, send Socket.IO CONNECT + sendConnect(); } void Client::onMessage(sockio::Packet& packet) { - LTrace("On message: ", packet.toString()) + LTrace("On message: ", packet.toString()); switch (packet.type()) { - case Packet::Packet::Type::Connect: - // Transition to online state + case Type::Connect: + // Server confirmed namespace connection - we're online onOnline(); break; - case Packet::Packet::Type::Disconnect: - // Do nothing, attempt to reconnect after ping timeout - break; - case Packet::Packet::Type::Event: - // assert(stateEquals(ClientState::Online)); - emit(packet); + + case Type::Disconnect: + // Server disconnected us from the namespace + { + scy::Error err; + err.message = "Server disconnected"; + setError(err); + } break; - case Packet::Packet::Type::Ack: - // assert(stateEquals(ClientState::Online)); + + case Type::Event: emit(packet); break; - case Packet::Packet::Type::Error: - // assert(stateEquals(ClientState::Online)); + + case Type::Ack: emit(packet); break; - case Packet::Packet::Type::BinaryEvent: - assert(0 && "not implemented"); - break; - case Packet::Packet::Type::BinaryAck: - assert(0 && "not implemented"); + + case Type::ConnectError: { + std::string msg = "Connection rejected"; + json::value json = packet.json(); + if (json.is_object() && json.contains("message")) + msg = json["message"].get(); + scy::Error err; + err.message = msg; + setError(err); + } break; + + case Type::BinaryEvent: + case Type::BinaryAck: + LWarn("Binary packets not yet implemented"); break; + default: - assert(0 && "unknown type"); + LWarn("Unknown Socket.IO packet type: ", static_cast(packet.type())); + break; } } void Client::onPacket(sockio::Packet& packet) { - LTrace("On packet: ", packet.toString()) + LTrace("On packet: ", packet.frameString(), " ", packet.typeString()); - // Handle packets by frame type + // Handle packets by Engine.IO frame type switch (packet.frame()) { - case Packet::Frame::Open: + case Frame::Open: onHandshake(packet); break; - case Packet::Frame::Close: - reset(); // close everything down + + case Frame::Close: + reset(); + onClose(); + break; + + case Frame::Ping: + // Engine.IO v4: server sends ping, client responds with pong + onServerPing(); break; - case Packet::Frame::Pong: + + case Frame::Pong: + // Shouldn't happen in EIO v4 (client doesn't send pings) + // but handle gracefully break; - case Packet::Frame::Message: + + case Frame::Message: onMessage(packet); break; - case Packet::Frame::Ping: - case Packet::Frame::Upgrade: - case Packet::Frame::Noop: + + case Frame::Upgrade: + case Frame::Noop: break; + default: - assert(0 && "unknown type"); + LWarn("Unknown Engine.IO frame type: ", static_cast(packet.frame())); + break; } } -void Client::onPong() -{ - LTrace("On pong") - - // Pong received, stop the ping timeout - _pingTimeoutTimer.stop(); -} - - -void Client::onPingTimer() -{ - LTrace("On heartbeat") - - // Do nothing unless online - if (!isOnline()) - return; - - sendPing(); - //_pingTimer.again(); -} - - void Client::onPingTimeoutTimer() { - LTrace("On ping timeout") + LWarn("Ping timeout - no ping from server within expected interval"); - // assert(0 && "implement me"); + scy::Error err; + err.message = "Ping timeout"; + setError(err); } void Client::onReconnectTimer() { - LTrace("On reconnect timer") + LTrace("On reconnect timer"); try { connect(); } catch (std::exception& exc) { - LError("Reconnection attempt failed: ", exc.what()) + LError("Reconnection attempt failed: ", exc.what()); } _reconnectTimer.again(); } @@ -488,7 +499,6 @@ std::string Client::sessionID() const Error Client::error() const { - // return _ws.socket->error(); return _error; } @@ -513,7 +523,6 @@ bool Client::reconnecting() const bool Client::wasOnline() const { - return _wasOnline; } @@ -522,4 +531,4 @@ bool Client::wasOnline() const } // namespace scy -/// @\} +/// @} diff --git a/src/socketio/src/packet.cpp b/src/socketio/src/packet.cpp index fa808171a..75c5bf4fa 100644 --- a/src/socketio/src/packet.cpp +++ b/src/socketio/src/packet.cpp @@ -13,14 +13,23 @@ #include "scy/logger.h" #include "scy/util.h" - -using std::endl; +#include +#include namespace scy { namespace sockio { +std::atomic Packet::_idCounter{1}; + + +int Packet::nextID() +{ + return _idCounter.fetch_add(1, std::memory_order_relaxed); +} + + Packet::Packet(Frame frame, Type type, int id, const std::string& nsp, const std::string& event, const std::string& message, bool ack) : _frame(frame) @@ -36,150 +45,157 @@ Packet::Packet(Frame frame, Type type, int id, const std::string& nsp, Packet::Packet(Type type, const std::string& message, bool ack) - : Packet(Frame::Message, type, util::randomNumber(), "/", "message", message, ack) + : Packet(Frame::Message, type, ack ? nextID() : -1, "/", "message", message, ack) { } Packet::Packet(const std::string& message, bool ack) - : Packet(Frame::Message, Type::Event, util::randomNumber(), "/", "message", message, ack) + : Packet(Frame::Message, Type::Event, ack ? nextID() : -1, "/", "message", message, ack) { } Packet::Packet(const json::value& message, bool ack) - : Packet(Frame::Message, Type::Event, util::randomNumber(), "/", "message", message.dump(), ack) + : Packet(Frame::Message, Type::Event, ack ? nextID() : -1, "/", "message", message.dump(), ack) { } Packet::Packet(const std::string& event, const std::string& message, bool ack) - : Packet(Frame::Message, Type::Event, util::randomNumber(), "/", event, message, ack) + : Packet(Frame::Message, Type::Event, ack ? nextID() : -1, "/", event, message, ack) { } Packet::Packet(const std::string& event, const json::value& data, bool ack) - : Packet(Frame::Message, Type::Event, util::randomNumber(), "/", event, data.dump(), ack) -{ -} - - -Packet::Packet(const Packet& r) - : _frame(r._frame) - , _type(r._type) - , _id(r._id) - , _nsp(r._nsp) - , _event(r._event) - , _message(r._message) - , _ack(r._ack) - , _size(r._size) -{ -} - - -Packet& Packet::operator=(const Packet& r) + : Packet(Frame::Message, Type::Event, ack ? nextID() : -1, "/", event, data.dump(), ack) { - _frame = r._frame; - _type = r._type; - _id = r._id; - _nsp = r._nsp; - _event = r._event; - _message = r._message; - _ack = r._ack; - _size = r._size; - return *this; } -Packet::~Packet() +std::unique_ptr Packet::clone() const { -} - - -IPacket* Packet::clone() const -{ - return new Packet(*this); + return std::make_unique(*this); } ssize_t Packet::read(const ConstBuffer& buf) { - LTrace("Read raw packet: ", buf.str()) - assert(buf.size() > 0); + LTrace("Read raw packet: ", buf.str()); + + if (buf.size() == 0) + return 0; // Reset all data _frame = Frame::Unknown; _type = Type::Unknown; _id = -1; _nsp = "/"; + _event = ""; _message = ""; _size = 0; BitReader reader(buf); - // parse frame type + // Parse Engine.IO frame type (single digit) char frame[2] = {'\0'}; reader.get(frame, 1); - _frame = static_cast(atoi(frame)); // std::stoi(std::string(frame, 1)) + _frame = static_cast(frame[0] - '0'); - if (_frame == Packet::Frame::Message) { + // Only Message frames contain Socket.IO packet data + if (_frame == Frame::Message) { - // parse packet type + // Parse Socket.IO packet type (single digit) char type[2] = {'\0'}; reader.get(type, 1); - _type = static_cast(atoi(type)); // std::stoi(std::string(type, 1)) - // if (_type < TypeMin || _type > TypeMax) { - // LWarn("Invalid message type: ", _type) - // return false; - // } - - // LTrace("Parse type: ", type, ": ", typeString()) - } + _type = static_cast(type[0] - '0'); + + // Parse binary attachment count (for BinaryEvent/BinaryAck) + // Format: - + // Skip for now as binary is not yet implemented + if (_type == Type::BinaryEvent || _type == Type::BinaryAck) { + // Read past the attachment count and dash + std::string attachments; + while (reader.available() && reader.peek() != '-') { + char c; + reader.get(&c, 1); + attachments += c; + } + if (reader.available() && reader.peek() == '-') { + char dash; + reader.get(&dash, 1); // consume the '-' + } + } - // parse attachments if type binary (not implemented) + // Parse namespace (starts with '/', ends at ',') + if (reader.available() && reader.peek() == '/') { + _nsp.clear(); + while (reader.available()) { + char c; + reader.get(&c, 1); + if (c == ',') + break; + _nsp += c; + } + } - // parse namespace (if any) - if (reader.peek() == '/') { - reader.readToNext(_nsp, ','); - } + // Parse acknowledgement ID (sequence of digits) + if (reader.available() && reader.peek() >= '0' && reader.peek() <= '9') { + std::string idStr; + while (reader.available() && reader.peek() >= '0' && reader.peek() <= '9') { + char c; + reader.get(&c, 1); + idStr += c; + } + _id = std::stoi(idStr); + } - // parse id - reader.readNextNumber((unsigned int&)_id); - - // parse json data - // TODO: Take into account joined messages - if (reader.available()) { - std::string temp; - reader.get(temp, reader.available()); - - json::value json = json::value::parse(temp.begin(), temp.end()); - if (json.is_array()) { - if (json.size() < 2) { - _event = "message"; - _message = json[0].dump(); - } else { - assert(json[0].is_string()); - _event = json[0].get(); - _message = json[1].dump(); + // Parse JSON payload + if (reader.available()) { + std::string temp; + reader.get(temp, reader.available()); + + json::value json = json::value::parse(temp.begin(), temp.end(), nullptr, false); + if (json.is_array()) { + if (json.size() < 2) { + _event = "message"; + if (json.size() == 1) { + if (json[0].is_string()) + _message = json[0].get(); + else + _message = json[0].dump(); + } + } else { + if (json[0].is_string()) + _event = json[0].get(); + else + _event = "message"; + _message = json[1].dump(); + } + } else if (json.is_object()) { + // Connect packets from server carry {"sid":"..."} as an object + _message = json.dump(); } - } - else if (json.is_object()) { - _message = json.dump(); + } + } else if (_frame == Frame::Open) { + // Engine.IO open packet - the rest is JSON handshake data + if (reader.available()) { + std::string temp; + reader.get(temp, reader.available()); + _message = temp; } } + // Ping/Pong/Close/Upgrade/Noop have no nested Socket.IO type _size = reader.position(); - // LDebug("Parse success: ", toString()) - - return _size; + return static_cast(_size); } void Packet::write(Buffer& buf) const { - assert(valid()); std::ostringstream os; print(os); std::string str(os.str()); @@ -199,6 +215,12 @@ void Packet::setNamespace(const std::string& nsp) } +void Packet::setEvent(const std::string& event) +{ + _event = event; +} + + void Packet::setMessage(const std::string& message) { _message = message; @@ -235,6 +257,12 @@ std::string Packet::nsp() const } +std::string Packet::event() const +{ + return _event; +} + + std::string Packet::message() const { return _message; @@ -244,12 +272,9 @@ std::string Packet::message() const json::value Packet::json() const { if (!_message.empty()) { - return json::value::parse(_message.begin(), _message.end()); - //json::value data; - //json::Reader reader; - //if (reader.parse(_message, data)) { - // return data; //[1]; - //} + auto result = json::value::parse(_message.begin(), _message.end(), nullptr, false); + if (!result.is_discarded()) + return result; } return json::value(); } @@ -258,23 +283,14 @@ json::value Packet::json() const std::string Packet::frameString() const { switch (_frame) { - case Frame::Open: - return "Open"; - case Frame::Close: - return "Close"; - case Frame::Ping: - return "Ping"; - case Frame::Pong: - return "Pong"; - case Frame::Message: - return "Message"; - case Frame::Upgrade: - return "Upgrade"; - case Frame::Noop: - return "Noop"; - // case Unknown: return "unknown"; - default: - return "unknown"; + case Frame::Open: return "Open"; + case Frame::Close: return "Close"; + case Frame::Ping: return "Ping"; + case Frame::Pong: return "Pong"; + case Frame::Message: return "Message"; + case Frame::Upgrade: return "Upgrade"; + case Frame::Noop: return "Noop"; + default: return "Unknown"; } } @@ -282,23 +298,14 @@ std::string Packet::frameString() const std::string Packet::typeString() const { switch (_type) { - case Type::Connect: - return "Connect"; - case Type::Disconnect: - return "Disconnect"; - case Type::Event: - return "Event"; - case Type::Ack: - return "Ack"; - case Type::Error: - return "Error"; - case Type::BinaryEvent: - return "BinaryEvent"; - case Type::BinaryAck: - return "BinaryAck"; - // case Unknown: return "unknown"; - default: - return "unknown"; + case Type::Connect: return "Connect"; + case Type::Disconnect: return "Disconnect"; + case Type::Event: return "Event"; + case Type::Ack: return "Ack"; + case Type::ConnectError: return "ConnectError"; + case Type::BinaryEvent: return "BinaryEvent"; + case Type::BinaryAck: return "BinaryAck"; + default: return "Unknown"; } } @@ -307,16 +314,26 @@ std::string Packet::toString() const { std::ostringstream ss; print(ss); - // ss << endl; return ss.str(); } bool Packet::valid() const { - // Check that ID and correct type have been set - return int(_type) >= int(Type::TypeMin) && - int(_type) <= int(Type::TypeMax) && _id > 0; + // Non-message frames (ping, pong, open, close, etc.) are always valid + if (_frame != Frame::Message) + return _frame != Frame::Unknown; + + // Message frames need a valid Socket.IO type + int t = static_cast(_type); + if (t < 0 || t > 6) + return false; + + // Event and Ack packets with ack flag need an ID + if (_ack && _id < 0) + return false; + + return true; } @@ -324,22 +341,86 @@ size_t Packet::size() const { std::ostringstream ss; print(ss); - assert(ss.tellp()); return static_cast(ss.tellp()); } void Packet::print(std::ostream& os) const { - // 2["message",{"data":"fffffffffffffffffffff","type":"message","id":"k0dsiifb169cz0k9","from":"aaa|/#Zr0vTHQ4JG2Zt-qtAAAA"}] - os << int(_frame) << int(_type) << _id; - - if (_type == Type::Event) { - os << "[\"" << (_event.empty() ? "message" : _event) << "\"," - << _message << "]"; - // << "\",\"" - // << _message - // << "\"]"; + // Engine.IO frame prefix + os << static_cast(_frame); + + // Only Message frames carry Socket.IO content + if (_frame != Frame::Message) + return; + + // Socket.IO packet type + os << static_cast(_type); + + // Namespace (only for non-default namespaces) + bool hasNsp = !_nsp.empty() && _nsp != "/"; + + switch (_type) { + case Type::Connect: + // Format: 40 or 40/admin,{auth} + if (hasNsp) { + os << _nsp << ","; + } + if (!_message.empty()) { + os << _message; + } + break; + + case Type::Disconnect: + // Format: 41 or 41/admin, + if (hasNsp) { + os << _nsp << ","; + } + break; + + case Type::Event: + case Type::BinaryEvent: + // Format: 42["event",data] or 42/admin,["event",data] + // With ack: 42["event",data] + if (hasNsp) { + os << _nsp << ","; + } + if (_id >= 0) { + os << _id; + } + os << "[\"" << (_event.empty() ? "message" : _event) << "\""; + if (!_message.empty()) { + os << "," << _message; + } + os << "]"; + break; + + case Type::Ack: + case Type::BinaryAck: + // Format: 43[data] or 43/admin,[data] + if (hasNsp) { + os << _nsp << ","; + } + if (_id >= 0) { + os << _id; + } + if (!_message.empty()) { + os << "[" << _message << "]"; + } + break; + + case Type::ConnectError: + // Format: 44{"message":"error"} + if (hasNsp) { + os << _nsp << ","; + } + if (!_message.empty()) { + os << _message; + } + break; + + default: + break; } } @@ -348,4 +429,4 @@ void Packet::print(std::ostream& os) const } // namespace scy -/// @\} +/// @} diff --git a/src/socketio/src/transaction.cpp b/src/socketio/src/transaction.cpp index dcf725460..5367c1e5e 100644 --- a/src/socketio/src/transaction.cpp +++ b/src/socketio/src/transaction.cpp @@ -12,10 +12,6 @@ #include "scy/socketio/transaction.h" #include "scy/logger.h" #include "scy/socketio/client.h" -#include - - -using std::endl; namespace scy { @@ -26,7 +22,7 @@ Transaction::Transaction(Client& client, long timeout) : PacketTransaction(timeout, 0, client.ws().socket->loop()) , client(client) { - LTrace("Create") + LTrace("Create"); } @@ -34,19 +30,19 @@ Transaction::Transaction(Client& client, const Packet& request, long timeout) : PacketTransaction(request, timeout, 0, client.ws().socket->loop()) , client(client) { - LTrace("Create") + LTrace("Create"); } Transaction::~Transaction() { - LTrace("Destroy") + LTrace("Destroy"); } bool Transaction::send() { - LTrace("Send: ", _request.id()) + LTrace("Send: ", _request.id()); _request.setAck(true); client += packetSlot(this, &Transaction::onPotentialResponse, -1, 100); if (client.send(_request)) @@ -57,21 +53,21 @@ bool Transaction::send() void Transaction::onPotentialResponse(sockio::Packet& packet) { - LTrace("On potential response: ", packet.id()) + LTrace("On potential response: ", packet.id()); PacketTransaction::handlePotentialResponse(packet); } bool Transaction::checkResponse(const Packet& packet) { - LTrace("Check response: ", packet.id()) + LTrace("Check response: ", packet.id()); return _request.id() == packet.id(); } void Transaction::onResponse() { - LTrace("On success") + LTrace("On success"); client -= packetSlot(this, &Transaction::onPotentialResponse); PacketTransaction::onResponse(); } @@ -81,4 +77,4 @@ void Transaction::onResponse() } // namespace scy -/// @\} +/// @} diff --git a/src/socketio/tests/CMakeLists.txt b/src/socketio/tests/CMakeLists.txt index 1bab3e6c7..d62dd00bd 100644 --- a/src/socketio/tests/CMakeLists.txt +++ b/src/socketio/tests/CMakeLists.txt @@ -1,5 +1,4 @@ -# include_dependency(JsonCpp) -include_dependency(SSL REQUIRED) - -set(socketiotests_EXCLUDE_CTEST TRUE) -define_libsourcey_test(socketiotests base crypto net http socketio json) +scy_add_test(socketiotests + DEPENDS base crypto net http socketio json + EXCLUDE_CTEST +) diff --git a/src/socketio/tests/socketiotests.cpp b/src/socketio/tests/socketiotests.cpp index 957959e7d..1bea52c3c 100644 --- a/src/socketio/tests/socketiotests.cpp +++ b/src/socketio/tests/socketiotests.cpp @@ -2,15 +2,10 @@ #include "scy/net/sslmanager.h" #include "scy/socketio/client.h" #include "scy/socketio/transaction.h" +#include "scy/test.h" #include "scy/util.h" -using namespace std; -using namespace scy; -using namespace scy::net; -using namespace scy::util; - - namespace scy { namespace sockio { @@ -30,40 +25,11 @@ class Tests public: Tests() { - // #if USE_SSL - // // Init SSL Context - // SSLContext::Ptr ptrContext = new - // SSLContext(SSLContext::CLIENT_USE, "", "", "", - // SSLContext::VERIFY_NONE, 9, true, - // "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"); - // SSLManager::instance().initializeClient(ptrContext); - // - // sockio::SSLClient client(app.loop); - // #else - // sockio::TCPClient client(app.loop); - // #endif - // - // client.StateChange += sdelegate(this, - // &Tests::onClientStateChange); - // client.connect(SERVER_HOST, SERVER_PORT); - // - // app.run(); - // - // // TODO: Benchmarks - // // TODO: Transaction tests - // - // #if USE_SSL - // SSLManager::instance().shutdown(); - // #endif - // app.finalize(); - testClient(); } - ~Tests() { app.finalize(); } - void testClient() { sockio::Client::Options options; @@ -79,34 +45,31 @@ class Tests client.StateChange += slot(this, &Tests::onClientStateChange); client.connect(); - // app.run(); app.waitForShutdown( [](void* opaque) { - reinterpret_cast(opaque)->close(); + static_cast(opaque)->close(); }, &client); - - // TODO: Benchmarks - // TODO: Transaction tests } void onClientStateChange(void* sender, sockio::ClientState& state, const sockio::ClientState& oldState) { - auto client = reinterpret_cast(sender); - LDebug("Connection state changed: ", state.toString()) + auto client = static_cast(sender); + LDebug("Connection state changed: ", state.toString()); switch (state.id()) { case sockio::ClientState::Connecting: break; case sockio::ClientState::Connected: - LDebug("Connected") + LDebug("Connected"); break; case sockio::ClientState::Online: - // TODO: Send message - client->send("ping", "hello", true); + // Send a test event with ack + client->send("ping", "\"hello\"", true); break; case sockio::ClientState::Error: + LError("Error: ", client->error().message); break; } } @@ -119,16 +82,113 @@ class Tests int main(int argc, char** argv) { - Logger::instance().add(new ConsoleChannel("debug", Level::Trace)); + using namespace scy; + Logger::instance().add(std::make_unique("debug", Level::Trace)); + test::init(); + #if USE_SSL - SSLManager::initNoVerifyClient(); + scy::net::SSLManager::initNoVerifyClient(); #endif - { - scy::sockio::Tests run; - } + + // ========================================================================= + // Packet Type Strings + // + scy::test::describe("packet type strings", []() { + scy::sockio::Packet pkt; + expect(std::string(pkt.frameString()) != ""); + expect(std::string(pkt.typeString()) != ""); + }); + + // ========================================================================= + // Packet Event Construction + // + scy::test::describe("packet event", []() { + scy::sockio::Packet pkt(scy::sockio::Packet::Frame::Message, + scy::sockio::Packet::Type::Event, + scy::sockio::Packet::nextID(), "/", + "chat message", "\"hello world\"", true); + + expect(pkt.frame() == scy::sockio::Packet::Frame::Message); + expect(pkt.type() == scy::sockio::Packet::Type::Event); + expect(pkt.event() == "chat message"); + expect(pkt.message() == "\"hello world\""); + expect(pkt.valid()); + expect(pkt.size() > 0); + }); + + // ========================================================================= + // Packet Write and Read Round-trip + // + scy::test::describe("packet write and read", []() { + scy::sockio::Packet original(scy::sockio::Packet::Frame::Message, + scy::sockio::Packet::Type::Event, + -1, "/", "test", "[1,2,3]", false); + + scy::Buffer buf; + original.write(buf); + expect(buf.size() > 0); + + scy::sockio::Packet parsed; + parsed.read(scy::constBuffer(buf)); + + expect(parsed.frame() == scy::sockio::Packet::Frame::Message); + expect(parsed.type() == scy::sockio::Packet::Type::Event); + }); + + // ========================================================================= + // Packet Namespace + // + scy::test::describe("packet namespace", []() { + scy::sockio::Packet pkt; + pkt.setNamespace("/chat"); + expect(pkt.nsp() == "/chat"); + }); + + // ========================================================================= + // Packet ID + // + scy::test::describe("packet id", []() { + scy::sockio::Packet pkt; + pkt.setID(42); + expect(pkt.id() == 42); + }); + + // ========================================================================= + // Packet Next ID + // + scy::test::describe("packet next id", []() { + int id1 = scy::sockio::Packet::nextID(); + int id2 = scy::sockio::Packet::nextID(); + expect(id2 == id1 + 1); + }); + + // ========================================================================= + // Packet Connect Type + // + scy::test::describe("packet connect type", []() { + scy::sockio::Packet pkt(scy::sockio::Packet::Frame::Message, + scy::sockio::Packet::Type::Connect); + expect(pkt.frame() == scy::sockio::Packet::Frame::Message); + expect(pkt.type() == scy::sockio::Packet::Type::Connect); + }); + + // ========================================================================= + // Packet toString + // + scy::test::describe("packet toString", []() { + scy::sockio::Packet pkt(scy::sockio::Packet::Frame::Message, + scy::sockio::Packet::Type::Event, + -1, "/", "hello", "\"data\"", false); + std::string str = pkt.toString(); + expect(!str.empty()); + }); + + + scy::test::runAll(); + #if USE_SSL - SSLManager::instance().shutdown(); + scy::net::SSLManager::instance().shutdown(); #endif - Logger::destroy(); - return 0; + scy::Logger::destroy(); + return scy::test::finalize(); } diff --git a/src/stun/CMakeLists.txt b/src/stun/CMakeLists.txt index 7e87eba54..25ee1f35a 100644 --- a/src/stun/CMakeLists.txt +++ b/src/stun/CMakeLists.txt @@ -1,8 +1,7 @@ -ask_build_sourcey_module(stun) -if(BUILD_MODULES OR (NOT BUILD_MODULES AND BUILD_MODULE_stun)) - # include_dependency(LibUV) #REQUIRED - include_dependency(SSL REQUIRED) - - set(stun_PRETTY_NAME STUN) - define_sourcey_module(stun base net crypto) +if(HAVE_OPENSSL) + scy_add_module(stun + DEPENDS base net crypto + PACKAGES OpenSSL::SSL OpenSSL::Crypto + PRETTY_NAME STUN + ) endif() diff --git a/src/stun/include/scy/stun/attributes.h b/src/stun/include/scy/stun/attributes.h index 6a4d03424..870cf956c 100644 --- a/src/stun/include/scy/stun/attributes.h +++ b/src/stun/include/scy/stun/attributes.h @@ -9,8 +9,7 @@ /// @{ -#ifndef SCY_STUN_Attributes_H -#define SCY_STUN_Attributes_H +#pragma once #include "scy/buffer.h" @@ -18,9 +17,10 @@ #include "scy/net/address.h" #include "scy/stun/stun.h" -#include #include +#include #include +#include #include #include @@ -80,7 +80,7 @@ class STUN_API Attribute }; virtual ~Attribute() {} - virtual Attribute* clone() = 0; + virtual std::unique_ptr clone() = 0; /// Reads the body (not the type or size) for this /// type of attribute from the given buffer. Return @@ -93,18 +93,18 @@ class STUN_API Attribute /// Creates an attribute object with the given type /// and size. - static Attribute* create(uint16_t type, uint16_t size = 0); + [[nodiscard]] static std::unique_ptr create(uint16_t type, uint16_t size = 0); - uint16_t type() const; - uint16_t size() const; + [[nodiscard]] uint16_t type() const; + [[nodiscard]] uint16_t size() const; void consumePadding(BitReader& reader) const; void writePadding(BitWriter& writer) const; - static const uint16_t TypeID = 0; + static constexpr uint16_t TypeID = 0; - std::string typeString(); - static std::string typeString(uint16_t type); + [[nodiscard]] std::string typeString(); + [[nodiscard]] static std::string typeString(uint16_t type); protected: Attribute(uint16_t type, uint16_t size = 0); @@ -123,44 +123,29 @@ class STUN_API AddressAttribute : public Attribute AddressAttribute(uint16_t type, bool ipv4 = true); // bool xor, AddressAttribute(const AddressAttribute& r); - virtual stun::Attribute* clone(); + std::unique_ptr clone() override; - static const uint16_t IPv4Size = 8; - static const uint16_t IPv6Size = 20; + static constexpr uint16_t IPv4Size = 8; + static constexpr uint16_t IPv6Size = 20; - stun::AddressFamily family() const + [[nodiscard]] stun::AddressFamily family() const { switch (_address.family()) { case net::Address::IPv4: - return stun::IPv4; + return stun::AddressFamily::IPv4; case net::Address::IPv6: - return stun::IPv6; + return stun::AddressFamily::IPv6; } - return stun::Undefined; + return stun::AddressFamily::Undefined; } - virtual net::Address address() const; + [[nodiscard]] virtual net::Address address() const; - virtual void read(BitReader& reader); - virtual void write(BitWriter& writer) const; + void read(BitReader& reader) override; + void write(BitWriter& writer) const override; virtual void setAddress(const net::Address& addr) { _address = addr; } -#if 0 - virtual uint16_t port() const { return _port; } - virtual uint32_t ip() const { return _ip; } - virtual uint8_t family() const { return _family; } - - virtual void setFamily(uint8_t family) { _family = family; } - virtual void setIP(uint32_t ip) { _ip = ip; } - virtual void setIP(const std::string& ip); - virtual void setPort(uint16_t port) { _port = port; } - - uint8_t _family; - uint16_t _port; - uint32_t _ip; -#endif - private: net::Address _address; }; @@ -174,18 +159,18 @@ class STUN_API UInt8Attribute : public Attribute UInt8Attribute(uint16_t type); UInt8Attribute(const UInt8Attribute& r); - virtual Attribute* clone(); + std::unique_ptr clone() override; - static const uint16_t Size = 1; + static constexpr uint16_t Size = 1; - uint8_t value() const { return _bits; } + [[nodiscard]] uint8_t value() const { return _bits; } void setValue(uint8_t bits) { _bits = bits; } - bool getBit(int index) const; + [[nodiscard]] bool getBit(int index) const; void setBit(int index, bool value); - void read(BitReader& reader); - void write(BitWriter& writer) const; + void read(BitReader& reader) override; + void write(BitWriter& writer) const override; private: uint8_t _bits; @@ -200,18 +185,18 @@ class STUN_API UInt32Attribute : public Attribute UInt32Attribute(uint16_t type); UInt32Attribute(const UInt32Attribute& r); - virtual Attribute* clone(); + std::unique_ptr clone() override; - static const uint16_t Size = 4; + static constexpr uint16_t Size = 4; - uint32_t value() const { return _bits; } + [[nodiscard]] uint32_t value() const { return _bits; } void setValue(uint32_t bits) { _bits = bits; } - bool getBit(int index) const; + [[nodiscard]] bool getBit(int index) const; void setBit(int index, bool value); - void read(BitReader& reader); - void write(BitWriter& writer) const; + void read(BitReader& reader) override; + void write(BitWriter& writer) const override; private: uint32_t _bits; @@ -226,18 +211,18 @@ class STUN_API UInt64Attribute : public Attribute UInt64Attribute(uint16_t type); UInt64Attribute(const UInt64Attribute& r); - virtual Attribute* clone(); + std::unique_ptr clone() override; - static const uint16_t Size = 8; + static constexpr uint16_t Size = 8; - uint64_t value() const { return _bits; } + [[nodiscard]] uint64_t value() const { return _bits; } void setValue(uint64_t bits) { _bits = bits; } - bool getBit(int index) const; + [[nodiscard]] bool getBit(int index) const; void setBit(int index, bool value); - void read(BitReader& reader); - void write(BitWriter& writer) const; + void read(BitReader& reader) override; + void write(BitWriter& writer) const override; private: uint64_t _bits; @@ -249,12 +234,12 @@ class STUN_API FlagAttribute : public Attribute public: FlagAttribute(uint16_t type); - virtual Attribute* clone(); + std::unique_ptr clone() override; - static const uint16_t Size = 0; + static constexpr uint16_t Size = 0; - void read(BitReader&) { assert(0 && "not implemented"); } - void write(BitWriter&) const { assert(0 && "not implemented"); } + void read(BitReader&) override { /* flags have no body */ } + void write(BitWriter&) const override { /* flags have no body */ } }; @@ -267,23 +252,23 @@ class STUN_API StringAttribute : public Attribute StringAttribute(const StringAttribute& r); virtual ~StringAttribute(); - virtual Attribute* clone(); + std::unique_ptr clone() override; - const char* bytes() const { return _bytes; } - void setBytes(char* bytes, unsigned size); + [[nodiscard]] const char* bytes() const { return _bytes.data(); } + void setBytes(const char* bytes, unsigned size); - std::string asString() const; + [[nodiscard]] std::string asString() const; void copyBytes(const char* bytes); // uses strlen void copyBytes(const void* bytes, unsigned size); - uint8_t getByte(int index) const; + [[nodiscard]] uint8_t getByte(int index) const; void setByte(int index, uint8_t value); - void read(BitReader& reader); - void write(BitWriter& writer) const; + void read(BitReader& reader) override; + void write(BitWriter& writer) const override; private: - char* _bytes; + std::vector _bytes; }; @@ -296,15 +281,15 @@ class STUN_API UInt16ListAttribute : public Attribute UInt16ListAttribute(const UInt16ListAttribute& r); virtual ~UInt16ListAttribute(); - virtual Attribute* clone(); + std::unique_ptr clone() override; - size_t size() const; - uint16_t getType(int index) const; + [[nodiscard]] size_t size() const; + [[nodiscard]] uint16_t getType(int index) const; void setType(int index, uint16_t value); void addType(uint16_t value); - void read(BitReader& reader); - void write(BitWriter& writer) const; + void read(BitReader& reader) override; + void write(BitWriter& writer) const override; private: std::vector _attrTypes; @@ -320,23 +305,23 @@ class STUN_API MessageIntegrity : public Attribute MessageIntegrity(const MessageIntegrity& r); virtual ~MessageIntegrity(); - virtual Attribute* clone(); + std::unique_ptr clone() override; - static const uint16_t TypeID = 0x0008; - static const uint16_t Size = 20; + static constexpr uint16_t TypeID = 0x0008; + static constexpr uint16_t Size = 20; - bool verifyHmac(const std::string& key) const; + [[nodiscard]] bool verifyHmac(const std::string& key) const; - std::string input() const { return _input; } - std::string hmac() const { return _hmac; } - std::string key() const { return _key; } + [[nodiscard]] std::string input() const { return _input; } + [[nodiscard]] std::string hmac() const { return _hmac; } + [[nodiscard]] std::string key() const { return _key; } void setInput(const std::string& input) { _input = input; } void setHmac(const std::string& hmac) { _hmac = hmac; } void setKey(const std::string& key) { _key = key; } - void read(BitReader& reader); - void write(BitWriter& writer) const; + void read(BitReader& reader) override; + void write(BitWriter& writer) const override; private: std::string _input; @@ -354,23 +339,23 @@ class STUN_API ErrorCode : public Attribute ErrorCode(const ErrorCode& r); virtual ~ErrorCode(); - virtual Attribute* clone(); + std::unique_ptr clone() override; - static const uint16_t TypeID = 0x0009; - static const uint16_t MinSize = 4; + static constexpr uint16_t TypeID = 0x0009; + static constexpr uint16_t MinSize = 4; void setErrorCode(int code); // void setErrorClass(uint8_t eClass); // void setErrorNumber(uint8_t eNumber); void setReason(const std::string& reason); - int errorCode() const; - uint8_t errorClass() const { return _class; } - uint8_t errorNumber() const { return _number; } - const std::string& reason() const { return _reason; } + [[nodiscard]] int errorCode() const; + [[nodiscard]] uint8_t errorClass() const { return _class; } + [[nodiscard]] uint8_t errorNumber() const { return _number; } + [[nodiscard]] const std::string& reason() const { return _reason; } - void read(BitReader& reader); - void write(BitWriter& writer) const; + void read(BitReader& reader) override; + void write(BitWriter& writer) const override; private: uint8_t _class; @@ -383,26 +368,26 @@ class STUN_API ErrorCode : public Attribute /// Attribute macros // -#define DECLARE_FIXLEN_STUN_ATTRIBUTE(Name, Type, Derives) \ - \ - class Name : public Derives \ - { \ - public: \ - static const uint16_t TypeID = Type; \ - Name() \ - : Derives(TypeID){}; \ - virtual ~Name(){}; \ +#define DECLARE_FIXLEN_STUN_ATTRIBUTE(Name, Type, Derives) \ + \ + class Name : public Derives \ + { \ + public: \ + static constexpr uint16_t TypeID = Type; \ + Name() \ + : Derives(TypeID) {}; \ + virtual ~Name() {}; \ }; -#define DECLARE_STUN_ATTRIBUTE(Name, Type, Derives, Length) \ - \ - class Name : public Derives \ - { \ - public: \ - static const uint16_t TypeID = Type; \ - Name(uint16_t size = Length) \ - : Derives(TypeID, size){}; \ - virtual ~Name(){}; \ +#define DECLARE_STUN_ATTRIBUTE(Name, Type, Derives, Length) \ + \ + class Name : public Derives \ + { \ + public: \ + static constexpr uint16_t TypeID = Type; \ + Name(uint16_t size = Length) \ + : Derives(TypeID, size) {}; \ + virtual ~Name() {}; \ }; @@ -456,11 +441,8 @@ DECLARE_FIXLEN_STUN_ATTRIBUTE(ICEControlled, 0x8029, UInt64Attribute) /// Flag attributes DECLARE_FIXLEN_STUN_ATTRIBUTE(ICEUseCandidate, 0x0025, FlagAttribute) DECLARE_FIXLEN_STUN_ATTRIBUTE(DontFragment, 0x001A, FlagAttribute) -} -} // namespace scy:stun - - -#endif // SCY_STUN_Attributes_H +} // namespace stun +} // namespace scy /// @\} diff --git a/src/stun/include/scy/stun/message.h b/src/stun/include/scy/stun/message.h index bd44ffb60..ac9385c4d 100644 --- a/src/stun/include/scy/stun/message.h +++ b/src/stun/include/scy/stun/message.h @@ -9,20 +9,22 @@ /// @{ -#ifndef SCY_STUN_Message_H -#define SCY_STUN_Message_H +#pragma once #include "scy/packet.h" #include "scy/stun/attributes.h" #include "scy/stun/stun.h" +#include +#include + namespace scy { namespace stun { -typedef std::string TransactionID; +using TransactionID = std::string; class STUN_API Message : public IPacket @@ -30,13 +32,13 @@ class STUN_API Message : public IPacket public: enum MethodType { - Undefined = 0x0000, ///< default error type + Undefined = 0x0000, ///< default error type /// STUN Binding = 0x0001, /// TURN - Allocate = 0x0003, ///< (only request/response semantics defined) + Allocate = 0x0003, ///< (only request/response semantics defined) Refresh = 0x0004, SendIndication = 0x0006, ///< (only indication semantics defined) DataIndication = 0x0007, ///< (only indication semantics defined) @@ -79,29 +81,36 @@ class STUN_API Message : public IPacket Message(); Message(ClassType clss, MethodType meth); Message(const Message& that); + Message(Message&& that) noexcept; Message& operator=(const Message& that); + Message& operator=(Message&& that) noexcept; virtual ~Message(); - virtual IPacket* clone() const; + virtual std::unique_ptr clone() const; void setClass(ClassType type); void setMethod(MethodType type); void setTransactionID(const std::string& id); - ClassType classType() const; - MethodType methodType() const; - const TransactionID& transactionID() const { return _transactionID; } - const std::vector attrs() const { return _attrs; } - size_t size() const { return static_cast(_size); } + [[nodiscard]] ClassType classType() const; + [[nodiscard]] MethodType methodType() const; + [[nodiscard]] const TransactionID& transactionID() const { return _transactionID; } + [[nodiscard]] size_t size() const { return static_cast(_size); } - std::string methodString() const; - std::string classString() const; - std::string errorString(uint16_t errorCode) const; + [[nodiscard]] std::string methodString() const; + [[nodiscard]] std::string classString() const; + [[nodiscard]] std::string errorString(uint16_t errorCode) const; + /// Takes ownership of the raw pointer (wraps in unique_ptr). void add(Attribute* attr); - Attribute* get(Attribute::Type type, int index = 0) const; - template T* get(int index = 0) const + /// Takes ownership via unique_ptr. + void add(std::unique_ptr attr); + + [[nodiscard]] Attribute* get(Attribute::Type type, int index = 0) const; + + template + [[nodiscard]] T* get(int index = 0) const { return reinterpret_cast( get(static_cast(T::TypeID), index)); @@ -114,7 +123,7 @@ class STUN_API Message : public IPacket /// Writes this object into a STUN/TURN packet. void write(Buffer& buf) const; - std::string toString() const; + [[nodiscard]] std::string toString() const; void print(std::ostream& os) const; virtual const char* className() const { return "StunMessage"; } @@ -124,11 +133,11 @@ class STUN_API Message : public IPacket uint16_t _method; uint16_t _size; TransactionID _transactionID; - std::vector _attrs; + std::vector> _attrs; }; -inline bool isValidMethod(uint16_t methodType) +[[nodiscard]] constexpr bool isValidMethod(uint16_t methodType) { switch (methodType) { case Message::Binding: @@ -145,11 +154,8 @@ inline bool isValidMethod(uint16_t methodType) } return false; } -} -} // namespace scy:stun - - -#endif // SCY_STUN_Message_H +} // namespace stun +} // namespace scy /// @\} diff --git a/src/stun/include/scy/stun/stun.h b/src/stun/include/scy/stun/stun.h index 158cb5e5c..14b5d125e 100644 --- a/src/stun/include/scy/stun/stun.h +++ b/src/stun/include/scy/stun/stun.h @@ -13,8 +13,7 @@ /// @{ -#ifndef SCY_STUN_H -#define SCY_STUN_H +#pragma once #include "scy/base.h" @@ -23,13 +22,13 @@ // Shared library exports #if defined(SCY_WIN) && defined(SCY_SHARED_LIBRARY) - #if defined(STUN_EXPORTS) - #define STUN_API __declspec(dllexport) - #else - #define STUN_API __declspec(dllimport) - #endif +#if defined(STUN_EXPORTS) +#define STUN_API __declspec(dllexport) #else - #define STUN_API // nothing +#define STUN_API __declspec(dllimport) +#endif +#else +#define STUN_API // nothing #endif @@ -38,17 +37,17 @@ namespace stun { // Following values correspond to RFC5389. -const int kAttributeHeaderSize = 4; -const int kMessageHeaderSize = 20; -const int kTransactionIdOffset = 8; -const int kTransactionIdLength = 12; -const uint32_t kMagicCookie = 0x2112A442; -const int kMagicCookieLength = sizeof(kMagicCookie); +constexpr int kAttributeHeaderSize = 4; +constexpr int kMessageHeaderSize = 20; +constexpr int kTransactionIdOffset = 8; +constexpr int kTransactionIdLength = 12; +constexpr uint32_t kMagicCookie = 0x2112A442; +constexpr int kMagicCookieLength = sizeof(kMagicCookie); /// STUN address types as defined in RFC 5389. /// NB: Undefined is not part of the STUN spec. -enum AddressFamily +enum class AddressFamily : uint8_t { Undefined = 0, IPv4 = 1, @@ -56,72 +55,8 @@ enum AddressFamily }; -#if 0 -inline bool isChannelData(uint16_t msgType) -{ - // The first two bits of a channel data message are 0b01. - return ((msgType & 0xC000) == 0x4000); -} - -inline bool isRequestType(int msgType) { - return ((msgType & 0x0110) == 0x000); -} - -inline bool isIndicationType(int msgType) { - return ((msgType & 0x0110) == 0x010); -} - -inline bool isSuccessResponseType(int msgType) { - return ((msgType & 0x0110) == 0x100); -} - -inline bool isErrorResponseType(int msgType) { - return ((msgType & 0x0110) == 0x110); -} - -inline int getSuccessResponseType(int reqType) { - return isRequestType(reqType) ? (reqType | 0x100) : -1; -} - -inline int getErrorResponseType(int reqType) { - return isRequestType(reqType) ? (reqType | 0x110) : -1; -} - - -#define IS_STUN_REQUEST(msgType) (((msgType)&0x0110) == 0x0000) -#define IS_STUN_INDICATION(msgType) (((msgType)&0x0110) == 0x0010) -#define IS_STUN_SUCCESS_RESP(msgType) (((msgType)&0x0110) == 0x0100) -#define IS_STUN_ERR_RESP(msgType) (((msgType)&0x0110) == 0x0110) - -#define GET_STUN_REQUEST(msgType) (msgType & 0xFEEF) -#define GET_STUN_INDICATION(msgType) ((msgType & 0xFEEF) | 0x0010) -#define GET_STUN_SUCCESS_RESP(msgType) ((msgType & 0xFEEF) | 0x0100) -#define GET_STUN_ERR_RESP(msgType) (msgType | 0x0110) - -#define STUN_HEADER_LENGTH (20) -#define STUN_CHANNEL_HEADER_LENGTH (4) - -#define STUN_MAX_USERNAME_SIZE (513) -#define STUN_MAX_REALM_SIZE (127) -#define STUN_MAX_NONCE_SIZE (127) -#define STUN_MAX_PWD_SIZE (127) - -#define STUN_MAGIC_COOKIE (0x2112A442) - -// Lifetimes: -#define STUN_DEFAULT_ALLOCATE_LIFETIME (600) -#define STUN_MIN_ALLOCATE_LIFETIME STUN_DEFAULT_ALLOCATE_LIFETIME -#define STUN_MAX_ALLOCATE_LIFETIME (3600) -#define STUN_CHANNEL_LIFETIME (600) -#define STUN_PERMISSION_LIFETIME (300) -#define STUN_NONCE_EXPIRATION_TIME (600) -#endif - - -} } // namespace scy:stun - - -#endif // SCY_STUN_H +} // namespace stun +} // namespace scy /// @\} diff --git a/src/stun/include/scy/stun/transaction.h b/src/stun/include/scy/stun/transaction.h index 60f83e0b9..7099ef2ed 100644 --- a/src/stun/include/scy/stun/transaction.h +++ b/src/stun/include/scy/stun/transaction.h @@ -9,8 +9,7 @@ /// @{ -#ifndef SCY_STUN_Transaction_H -#define SCY_STUN_Transaction_H +#pragma once #include "scy/net/socket.h" @@ -34,11 +33,8 @@ class STUN_API Transaction : public net::Transaction protected: virtual ~Transaction(); }; -} -} // namespace scy:stun - - -#endif // SCY_STUN_Transaction_H +} // namespace stun +} // namespace scy /// @\} diff --git a/src/stun/src/attributes.cpp b/src/stun/src/attributes.cpp index e8b5f97c4..422ed3e78 100644 --- a/src/stun/src/attributes.cpp +++ b/src/stun/src/attributes.cpp @@ -18,8 +18,9 @@ #include "scy/stun/attributes.h" #include "scy/stun/message.h" - -using namespace std; +#include +#include +#include namespace scy { @@ -156,159 +157,137 @@ void Attribute::writePadding(BitWriter& writer) const } -Attribute* Attribute::create(uint16_t type, uint16_t size) +std::unique_ptr Attribute::create(uint16_t type, uint16_t size) { - // Attribute* attr = get(type); - // if (attr) - // return attr; - switch (type) { case Attribute::MappedAddress: if (size != AddressAttribute::IPv4Size && size != AddressAttribute::IPv6Size) return nullptr; - return new stun::MappedAddress(); + return std::make_unique(); case Attribute::XorMappedAddress: if (size != AddressAttribute::IPv4Size && size != AddressAttribute::IPv6Size) return nullptr; - return new stun::XorMappedAddress(); + return std::make_unique(); case Attribute::XorRelayedAddress: if (size != AddressAttribute::IPv4Size && size != AddressAttribute::IPv6Size) return nullptr; - return new stun::XorRelayedAddress(); + return std::make_unique(); case Attribute::XorPeerAddress: if (size != AddressAttribute::IPv4Size && size != AddressAttribute::IPv6Size) return nullptr; - return new stun::XorPeerAddress(); + return std::make_unique(); case Attribute::AlternateServer: if (size != AddressAttribute::IPv4Size && size != AddressAttribute::IPv6Size) return nullptr; - return new stun::AlternateServer(); + return std::make_unique(); case Attribute::ErrorCode: if (size < ErrorCode::MinSize) return nullptr; - return new stun::ErrorCode(size); + return std::make_unique(size); case Attribute::UnknownAttributes: - return new stun::UnknownAttributes(size); + return std::make_unique(size); case Attribute::Fingerprint: if (size != Fingerprint::Size) return nullptr; - return new stun::Fingerprint(); + return std::make_unique(); case Attribute::RequestedTransport: if (size != RequestedTransport::Size) return nullptr; - return new stun::RequestedTransport(); + return std::make_unique(); case Attribute::Lifetime: if (size != Lifetime::Size) return nullptr; - return new stun::Lifetime(); + return std::make_unique(); case Attribute::Bandwidth: if (size != Bandwidth::Size) return nullptr; - return new stun::Bandwidth(); + return std::make_unique(); case Attribute::ChannelNumber: - if (size != ICEUseCandidate::Size) + if (size != ChannelNumber::Size) return nullptr; - return new stun::ICEUseCandidate(); + return std::make_unique(); case Attribute::ConnectionID: if (size != ConnectionID::Size) return nullptr; - return new stun::ConnectionID(); + return std::make_unique(); case Attribute::MessageIntegrity: - return (size == 20) ? new stun::MessageIntegrity() : nullptr; + return (size == 20) ? std::make_unique() : nullptr; case Attribute::Nonce: - return (size <= 128) ? new stun::Nonce(size) : nullptr; + return (size <= 128) ? std::make_unique(size) : nullptr; case Attribute::Realm: - return (size <= 128) ? new stun::Realm(size) : nullptr; + return (size <= 128) ? std::make_unique(size) : nullptr; case Attribute::Software: - return (size <= 128) ? new stun::Software(size) : nullptr; + return (size <= 128) ? std::make_unique(size) : nullptr; case Attribute::ReservationToken: - return (size == 8) ? new stun::ReservationToken() : nullptr; + return (size == 8) ? std::make_unique() : nullptr; case Attribute::MagicCookie: - return (size == 4) ? new stun::MagicCookie() : nullptr; + return (size == 4) ? std::make_unique() : nullptr; case Attribute::Data: - return new stun::Data(size); + return std::make_unique(size); case Attribute::Username: - return (size <= 128) ? new stun::Username(size) : nullptr; + return (size <= 128) ? std::make_unique(size) : nullptr; case Attribute::Password: - return (size <= 128) ? new stun::Password(size) : nullptr; + return (size <= 128) ? std::make_unique(size) : nullptr; case Attribute::ICEPriority: if (size != ICEPriority::Size) return nullptr; - return new stun::ICEPriority(); + return std::make_unique(); case Attribute::ICEControlled: if (size != ICEControlled::Size) return nullptr; - return new stun::ICEControlled(); + return std::make_unique(); case Attribute::ICEControlling: if (size != ICEControlling::Size) return nullptr; - return new stun::ICEControlling(); + return std::make_unique(); case Attribute::ICEUseCandidate: - return (size == 0) ? new stun::ICEUseCandidate() : nullptr; + return (size == 0) ? std::make_unique() : nullptr; case Attribute::DontFragment: if (size != DontFragment::Size) return nullptr; - return new stun::DontFragment(); + return std::make_unique(); case Attribute::EventPort: if (size != EventPort::Size) return nullptr; - return new stun::EventPort(); - - // case Attribute::UnknownAttributes: - // return (size % 2 == 0) ? new stun::UnknownAttributes(size) : - // nullptr; - // break; - - // case Attribute::TransportPrefs: - // if ((size != TransportPrefs::Size1) && - // (size != TransportPrefs::Size2)) - // return nullptr; - // return new stun::TransportPrefs(size); - - // case Attribute::MagicCookie: - // return (size == 4) ? new stun::MagicCookie() : nullptr; - // break; + return std::make_unique(); default: - LError("Cannot create attribute for type: ", type) + LError("Cannot create attribute for type: ", type); break; } - //_attrs.push_back(attr); - // return attr; - // assert(false); return nullptr; } @@ -328,9 +307,9 @@ AddressAttribute::AddressAttribute(const AddressAttribute& r) } -Attribute* AddressAttribute::clone() +std::unique_ptr AddressAttribute::clone() { - return new AddressAttribute(*this); + return std::make_unique(*this); } @@ -343,23 +322,11 @@ net::Address AddressAttribute::address() const std::string intToIPv4(uint32_t ip) { // Input should be in host network order - // ip = ntohl(ip); char str[20]; - sprintf(str, "%d.%d.%d.%d", (ip >> 24) & 0xff, (ip >> 16) & 0xff, - (ip >> 8) & 0xff, ip & 0xff); + std::snprintf(str, sizeof(str), "%d.%d.%d.%d", + (ip >> 24) & 0xff, (ip >> 16) & 0xff, + (ip >> 8) & 0xff, ip & 0xff); return std::string(str); - -#if 0 - ostringstream ost; - ost << ((ip >> 24) & 0xff); - ost << '.'; - ost << ((ip >> 16) & 0xff); - ost << '.'; - ost << ((ip >> 8) & 0xff); - ost << '.'; - ost << ((ip >> 0) & 0xff); - return ost.str(); -#endif } @@ -382,25 +349,68 @@ void AddressAttribute::read(BitReader& reader) uint16_t port; reader.getU16(port); port = ntohs(port) ^ ntohs(kMagicCookie >> 16); // XOR - // port ^= (kMagicCookie >> 16); - if (family == AddressFamily::IPv4) { + if (family == static_cast(AddressFamily::IPv4)) { if (size() != IPv4Size) { - assert(0 && "invalid IPv4 address"); - return; + throw std::runtime_error("invalid IPv4 address attribute size"); } uint32_t ip; reader.getU32(ip); ip = ntohl(ip) ^ ntohl(kMagicCookie); // XOR - // ip ^= ntohl(kMagicCookie); - // ip ^= kMagicCookie; _address = net::Address(intToIPv4(ntohl(ip)), ntohs(port)); - } else if (family == AddressFamily::IPv6) { - assert(0 && "IPv6 not supported"); + } else if (family == static_cast(AddressFamily::IPv6)) { + if (size() != IPv6Size) { + throw std::runtime_error("invalid IPv6 address attribute size"); + } + + // RFC 5389 Section 15.2: For IPv6, X-Address is computed by taking + // the mapped IP address in host byte order, XOR'ing it with the + // concatenation of the magic cookie (32 bits) and the transaction + // ID (96 bits), and converting the result to network byte order. + + // Read the 16 raw bytes of the IPv6 address from the wire + uint8_t xored[16]; + for (int i = 0; i < 16; i++) { + uint8_t b; + reader.getU8(b); + xored[i] = b; + } + + // Build the 16-byte XOR mask: magic cookie (4 bytes) + transaction ID (12 bytes) + // We need to get the transaction ID from the message header which + // starts at offset 8 in the reader's buffer (after type + length + cookie). + // The reader.begin() points to the start of the STUN message. + const uint8_t* msgBegin = reinterpret_cast(reader.begin()); + uint8_t xorMask[16]; + // First 4 bytes: magic cookie in network byte order + xorMask[0] = static_cast((kMagicCookie >> 24) & 0xff); + xorMask[1] = static_cast((kMagicCookie >> 16) & 0xff); + xorMask[2] = static_cast((kMagicCookie >> 8) & 0xff); + xorMask[3] = static_cast(kMagicCookie & 0xff); + // Next 12 bytes: transaction ID from offset 8 in the message + std::memcpy(xorMask + 4, msgBegin + kTransactionIdOffset, kTransactionIdLength); + + // XOR the address bytes with the mask + uint8_t addr[16]; + for (int i = 0; i < 16; i++) { + addr[i] = xored[i] ^ xorMask[i]; + } + + // Build IPv6 address string from the decoded bytes + char addrStr[64]; + std::snprintf(addrStr, sizeof(addrStr), + "%02x%02x:%02x%02x:%02x%02x:%02x%02x:" + "%02x%02x:%02x%02x:%02x%02x:%02x%02x", + addr[0], addr[1], addr[2], addr[3], + addr[4], addr[5], addr[6], addr[7], + addr[8], addr[9], addr[10], addr[11], + addr[12], addr[13], addr[14], addr[15]); + + _address = net::Address(std::string(addrStr), ntohs(port)); } else { - assert(0 && "invalid address"); + throw std::runtime_error("invalid address family in STUN attribute"); } } @@ -408,10 +418,7 @@ void AddressAttribute::read(BitReader& reader) void AddressAttribute::write(BitWriter& writer) const { writer.putU8(0); - writer.putU8(family()); - // writer.putU8(_family); - // writer.putU16(_port); - // writer.putU32(_ip); + writer.putU8(static_cast(family())); switch (_address.family()) { case net::Address::IPv4: { @@ -420,11 +427,7 @@ void AddressAttribute::write(BitWriter& writer) const // Port uint16_t port = ntohs(v4addr->sin_port); - // assert(port == 5555); - // assert(port == 0x15B3); port ^= (kMagicCookie >> 16); // XOR - // port = port ^ (kMagicCookie >> 16); // XOR - // assert(port == 0x34A1); writer.putU16(port); // Address @@ -434,7 +437,32 @@ void AddressAttribute::write(BitWriter& writer) const break; } case net::Address::IPv6: { - assert(0 && "IPv6 not supported"); + auto v6addr = reinterpret_cast( + const_cast(_address.addr())); + + // Port: XOR with high 16 bits of magic cookie + uint16_t port = ntohs(v6addr->sin6_port); + port ^= (kMagicCookie >> 16); // XOR + writer.putU16(port); + + // Address: XOR with magic cookie + transaction ID + // Build the XOR mask from the message header already written + const uint8_t* msgBegin = reinterpret_cast(writer.begin()); + uint8_t xorMask[16]; + xorMask[0] = static_cast((kMagicCookie >> 24) & 0xff); + xorMask[1] = static_cast((kMagicCookie >> 16) & 0xff); + xorMask[2] = static_cast((kMagicCookie >> 8) & 0xff); + xorMask[3] = static_cast(kMagicCookie & 0xff); + std::memcpy(xorMask + 4, msgBegin + kTransactionIdOffset, kTransactionIdLength); + + // Get raw IPv6 address bytes in network order + const uint8_t* addrBytes = reinterpret_cast( + &v6addr->sin6_addr); + + // XOR each byte and write + for (int i = 0; i < 16; i++) { + writer.putU8(addrBytes[i] ^ xorMask[i]); + } break; } } @@ -457,22 +485,24 @@ UInt8Attribute::UInt8Attribute(const UInt8Attribute& r) } -Attribute* UInt8Attribute::clone() +std::unique_ptr UInt8Attribute::clone() { - return new UInt8Attribute(*this); + return std::make_unique(*this); } bool UInt8Attribute::getBit(int index) const { - assert((0 <= index) && (index < 32)); + if (index < 0 || index >= 8) + throw std::runtime_error("UInt8Attribute::getBit: index out of range"); return static_cast((_bits >> index) & 0x1); } void UInt8Attribute::setBit(int index, bool value) { - assert((0 <= index) && (index < 32)); + if (index < 0 || index >= 8) + throw std::runtime_error("UInt8Attribute::setBit: index out of range"); _bits &= ~(1 << index); _bits |= value ? (1 << index) : 0; } @@ -506,24 +536,26 @@ UInt32Attribute::UInt32Attribute(const UInt32Attribute& r) } -Attribute* UInt32Attribute::clone() +std::unique_ptr UInt32Attribute::clone() { - return new UInt32Attribute(*this); + return std::make_unique(*this); } bool UInt32Attribute::getBit(int index) const { - assert((0 <= index) && (index < 32)); + if (index < 0 || index >= 32) + throw std::runtime_error("UInt32Attribute::getBit: index out of range"); return static_cast((_bits >> index) & 0x1); } void UInt32Attribute::setBit(int index, bool value) { - assert((0 <= index) && (index < 32)); - _bits &= ~(1 << index); - _bits |= value ? (1 << index) : 0; + if (index < 0 || index >= 32) + throw std::runtime_error("UInt32Attribute::setBit: index out of range"); + _bits &= ~(1u << index); + _bits |= value ? (1u << index) : 0; } @@ -554,24 +586,26 @@ UInt64Attribute::UInt64Attribute(const UInt64Attribute& r) } -Attribute* UInt64Attribute::clone() +std::unique_ptr UInt64Attribute::clone() { - return new UInt64Attribute(*this); + return std::make_unique(*this); } bool UInt64Attribute::getBit(int index) const { - assert((0 <= index) && (index < 32)); + if (index < 0 || index >= 64) + throw std::runtime_error("UInt64Attribute::getBit: index out of range"); return static_cast((_bits >> index) & 0x1); } void UInt64Attribute::setBit(int index, bool value) { - assert((0 <= index) && (index < 32)); - _bits &= ~(1 << index); - _bits |= value ? (1 << index) : 0; + if (index < 0 || index >= 64) + throw std::runtime_error("UInt64Attribute::setBit: index out of range"); + _bits &= ~(1ull << index); + _bits |= value ? (1ull << index) : 0; } @@ -595,9 +629,9 @@ FlagAttribute::FlagAttribute(uint16_t type) } -Attribute* FlagAttribute::clone() +std::unique_ptr FlagAttribute::clone() { - return new FlagAttribute(type()); + return std::make_unique(type()); } @@ -605,77 +639,73 @@ Attribute* FlagAttribute::clone() // StringAttribute::StringAttribute(uint16_t type, uint16_t size) : Attribute(type, size) - , _bytes(0) { } StringAttribute::StringAttribute(const StringAttribute& r) : Attribute(r._type, r._size) - , _bytes(0) + , _bytes(r._bytes) { - copyBytes(r._bytes, r._size); } StringAttribute::~StringAttribute() { - if (_bytes) - delete[] _bytes; } -Attribute* StringAttribute::clone() +std::unique_ptr StringAttribute::clone() { - return new StringAttribute(*this); + return std::make_unique(*this); } -void StringAttribute::setBytes(char* bytes, unsigned size) +void StringAttribute::setBytes(const char* bytes, unsigned size) { - if (_bytes) - delete[] _bytes; - _bytes = bytes; + _bytes.assign(bytes, bytes + size); setLength(size); } void StringAttribute::copyBytes(const char* bytes) { - copyBytes(bytes, static_cast(strlen(bytes))); + copyBytes(bytes, static_cast(std::strlen(bytes))); } void StringAttribute::copyBytes(const void* bytes, unsigned size) { - char* newBytes = new char[size]; - memcpy(newBytes, bytes, size); - setBytes(newBytes, size); + const char* src = static_cast(bytes); + _bytes.assign(src, src + size); + setLength(size); } uint8_t StringAttribute::getByte(int index) const { - assert(_bytes != nullptr); - assert((0 <= index) && (index < size())); + if (_bytes.empty()) + throw std::runtime_error("StringAttribute::getByte: no data"); + if (index < 0 || index >= static_cast(Attribute::size())) + throw std::runtime_error("StringAttribute::getByte: index out of range"); return static_cast(_bytes[index]); } void StringAttribute::setByte(int index, uint8_t value) { - assert(_bytes != nullptr); - assert((0 <= index) && (index < size())); - _bytes[index] = value; + if (_bytes.empty()) + throw std::runtime_error("StringAttribute::setByte: no data"); + if (index < 0 || index >= static_cast(Attribute::size())) + throw std::runtime_error("StringAttribute::setByte: index out of range"); + _bytes[index] = static_cast(value); } void StringAttribute::read(BitReader& reader) { - if (_bytes) - delete[] _bytes; - _bytes = new char[size()]; - reader.get(_bytes, size()); + _bytes.resize(Attribute::size()); + reader.get(_bytes.data(), Attribute::size()); consumePadding(reader); } @@ -683,8 +713,8 @@ void StringAttribute::read(BitReader& reader) void StringAttribute::write(BitWriter& writer) const { - if (_bytes) - writer.put(_bytes, size()); + if (!_bytes.empty()) + writer.put(_bytes.data(), Attribute::size()); writePadding(writer); } @@ -692,29 +722,10 @@ void StringAttribute::write(BitWriter& writer) const std::string StringAttribute::asString() const { - return std::string(_bytes, size()); -} - - -/* -//--------------- Fingerprint ---------------- -Fingerprint::Fingerprint() : - UInt32Attribute(Attribute::Fingerprint) { + return std::string(_bytes.data(), Attribute::size()); } -//void Fingerprint::setCRC32(unsigned int crc) { -// _crc32 = crc; -//} - - -//unsigned int Fingerprint::crc32() { -// return _crc32; -//} -*/ - - - // --------------------------------------------------------------------------- // MessageIntegrity::MessageIntegrity() @@ -737,28 +748,24 @@ MessageIntegrity::~MessageIntegrity() } -Attribute* MessageIntegrity::clone() +std::unique_ptr MessageIntegrity::clone() { - return new MessageIntegrity(*this); + return std::make_unique(*this); } bool MessageIntegrity::verifyHmac(const std::string& key) const { - // LDebug("Message: Verify HMAC: ", key) - - assert(!key.empty()); - assert(!_hmac.empty()); - assert(!_input.empty()); - - // LDebug("Message: Packet integrity input (", _input, ")") - // LDebug("Message: Packet integrity key (", key, ")") + if (key.empty()) + throw std::runtime_error("MessageIntegrity::verifyHmac: empty key"); + if (_hmac.empty()) + throw std::runtime_error("MessageIntegrity::verifyHmac: empty hmac"); + if (_input.empty()) + throw std::runtime_error("MessageIntegrity::verifyHmac: empty input"); std::string hmac = crypto::computeHMAC(_input, key); - assert(hmac.size() == MessageIntegrity::Size); - - // SDebug << "Message: Verifying message integrity (" << hmac << ": " << - // _hmac << ")" << endl; + if (hmac.size() != MessageIntegrity::Size) + throw std::runtime_error("MessageIntegrity::verifyHmac: unexpected HMAC size"); return _hmac == hmac; } @@ -766,21 +773,14 @@ bool MessageIntegrity::verifyHmac(const std::string& key) const void MessageIntegrity::read(BitReader& reader) { - // LDebug("Message: Read HMAC") int sizeBeforeMessageIntegrity = reader.position() - kAttributeHeaderSize; - // Read the HMAC value. - // reader.get(_hmac, MessageIntegrity::Size); - - // _input.assign(reader.begin(), sizeBeforeMessageIntegrity); - // Get the message prior to the current attribute and fill the // attribute with dummy content. Buffer hmacBuf(sizeBeforeMessageIntegrity); BitWriter hmacWriter(hmacBuf); hmacWriter.put(reader.begin(), reader.position() - kAttributeHeaderSize); - // hmacWriter.put("00000000000000000000"); // Ensure the STUN message size reflects the message up to and // including the MessageIntegrity attribute. @@ -790,30 +790,6 @@ void MessageIntegrity::read(BitReader& reader) _hmac.assign(reader.current(), MessageIntegrity::Size); reader.skip(MessageIntegrity::Size); - -#if 0 - //LDebug("Message: Parsed message integrity (", _hmac, ")") - - // Remember the original position and set the buffer position back to 0. - int originalPos = reader.position(); - reader.seek(0); - - // Get the message prior to the current attribute and fill the - // attribute with dummy content. - Buffer hmacBuf; - BitWriter hmacWriter(hmacBuf); - - hmacWriter.put(reader.begin(), reader.available() - MessageIntegrity::Size); - hmacWriter.put("00000000000000000000"); - - // Ensure the STUN message size value represents the real - // size of the buffered message. - hmacWriter.updateU32((uint32_t)hmacWriter.position(), 2); - _input.assign(hmacWriter.begin(), hmacWriter.position()); - - // Reset the original buffer position. - reader.seek(originalPos); -#endif } @@ -832,13 +808,10 @@ void MessageIntegrity::write(BitWriter& writer) const // Get the message prior to the current attribute and // fill the attribute with dummy content. - // + MessageIntegrity::Size Buffer hmacBuf(sizeBeforeMessageIntegrity); BitWriter hmacWriter(hmacBuf); hmacWriter.put(writer.begin(), sizeBeforeMessageIntegrity); - // hmacWriter.put("00000000000000000000"); - // The length MUST then // be set to point to the length of the message up to, and including, // the MESSAGE-INTEGRITY attribute itself, but excluding any attributes @@ -853,37 +826,19 @@ void MessageIntegrity::write(BitWriter& writer) const hmacWriter.updateU32((uint32_t)sizeBeforeMessageIntegrity + MessageIntegrity::Size, 2); std::string input(hmacWriter.begin(), hmacWriter.position()); - assert(input.size() == sizeBeforeMessageIntegrity); // + MessageIntegrity::Size + if (input.size() != static_cast(sizeBeforeMessageIntegrity)) + throw std::runtime_error("MessageIntegrity::write: input size mismatch"); - // std::string input(writer.begin(), sizeBeforeMessageIntegrity); std::string hmac(crypto::computeHMAC(input, _key)); - assert(hmac.size() == MessageIntegrity::Size); + if (hmac.size() != MessageIntegrity::Size) + throw std::runtime_error("MessageIntegrity::write: unexpected HMAC size"); - // Append the real HAMC to the buffer. + // Append the real HMAC to the buffer. writer.put(hmac.c_str(), hmac.length()); -#if 0 - // Get the message prior to the current attribute and - // fill the attribute with dummy content. - Buffer hmacBuf; // TODO: alloc exact size - BitWriter hmacWriter(hmacBuf); - hmacWriter.put(writer.begin(), writer.position()); - hmacWriter.put("00000000000000000000"); - - // Ensure the STUN message size value represents the real - // size of the buffered message. - hmacWriter.updateU32((uint32_t)hmacWriter.position() + MessageIntegrity::Size, 2); - - //string input(hmacBuf.data(), hmacBuf.available()); - std::string input(hmacWriter.begin(), hmacWriter.position()); - std::string hmac(crypto::computeHMAC(input, _key)); - assert(hmac.size() == MessageIntegrity::Size); - - // Append the real HAMC to the buffer. - writer.put(hmac.c_str(), MessageIntegrity::Size); -#endif } else { - assert(_hmac.size() == MessageIntegrity::Size); + if (_hmac.size() != MessageIntegrity::Size) + throw std::runtime_error("MessageIntegrity::write: HMAC not set"); writer.put(_hmac.c_str(), MessageIntegrity::Size); } } @@ -896,7 +851,8 @@ ErrorCode::ErrorCode(uint16_t size) , _class(0) , _number(0) { - assert(size >= MinSize); + if (size < MinSize) + throw std::runtime_error("ErrorCode: size too small"); } @@ -914,9 +870,9 @@ ErrorCode::~ErrorCode() } -Attribute* ErrorCode::clone() +std::unique_ptr ErrorCode::clone() { - return new ErrorCode(*this); + return std::make_unique(*this); } @@ -984,9 +940,9 @@ UInt16ListAttribute::~UInt16ListAttribute() } -Attribute* UInt16ListAttribute::clone() +std::unique_ptr UInt16ListAttribute::clone() { - return new UInt16ListAttribute(*this); + return std::make_unique(*this); } @@ -1017,7 +973,7 @@ void UInt16ListAttribute::addType(uint16_t value) void UInt16ListAttribute::read(BitReader& reader) { - for (unsigned i = 0; i < size() / 2; i++) { + for (size_t i = 0; i < size() / 2; i++) { uint16_t attr; reader.getU16(attr); _attrTypes.push_back(attr); @@ -1033,13 +989,14 @@ void UInt16ListAttribute::read(BitReader& reader) void UInt16ListAttribute::write(BitWriter& writer) const { - for (unsigned i = 0; i < _attrTypes.size(); i++) - writer.putU16(_attrTypes[i]); + for (const auto& attrType : _attrTypes) + writer.putU16(attrType); writePadding(writer); } -} } // namespace scy:stun +} // namespace stun +} // namespace scy /// @\} diff --git a/src/stun/src/message.cpp b/src/stun/src/message.cpp index d2eb74af3..2ef4f7fe7 100644 --- a/src/stun/src/message.cpp +++ b/src/stun/src/message.cpp @@ -13,8 +13,9 @@ #include "scy/logger.h" #include "scy/util.h" - -using namespace std; +#include +#include +#include namespace scy { @@ -27,7 +28,8 @@ Message::Message() , _size(0) , _transactionID(util::randomString(kTransactionIdLength)) { - assert(_transactionID.size() == kTransactionIdLength); + if (_transactionID.size() != kTransactionIdLength) + throw std::runtime_error("Message: invalid transaction ID length"); } @@ -46,12 +48,27 @@ Message::Message(const Message& that) , _size(that._size) , _transactionID(that._transactionID) { - assert(_method); - assert(_transactionID.size() == kTransactionIdLength); + if (!_method) + throw std::runtime_error("Message copy: invalid method"); + if (_transactionID.size() != kTransactionIdLength) + throw std::runtime_error("Message copy: invalid transaction ID length"); + + // Deep-copy attributes from source object + for (const auto& attr : that._attrs) + _attrs.push_back(attr->clone()); +} - // Copy attributes from source object - for (unsigned i = 0; i < that.attrs().size(); i++) - _attrs.push_back(that.attrs()[i]->clone()); + +Message::Message(Message&& that) noexcept + : _class(that._class) + , _method(that._method) + , _size(that._size) + , _transactionID(std::move(that._transactionID)) + , _attrs(std::move(that._attrs)) +{ + that._class = Request; + that._method = Undefined; + that._size = 0; } @@ -62,17 +79,33 @@ Message& Message::operator=(const Message& that) _class = that._class; _size = that._size; _transactionID = that._transactionID; - assert(_method); - assert(_transactionID.size() == kTransactionIdLength); + if (!_method) + throw std::runtime_error("Message assign: invalid method"); + if (_transactionID.size() != kTransactionIdLength) + throw std::runtime_error("Message assign: invalid transaction ID length"); - // Clear current attributes - for (unsigned i = 0; i < _attrs.size(); i++) - delete _attrs[i]; + // Clear and deep-copy attributes from source object _attrs.clear(); + for (const auto& attr : that._attrs) + _attrs.push_back(attr->clone()); + } + + return *this; +} - // Copy attributes from source object - for (unsigned i = 0; i < that.attrs().size(); i++) - _attrs.push_back(that.attrs()[i]->clone()); + +Message& Message::operator=(Message&& that) noexcept +{ + if (&that != this) { + _method = that._method; + _class = that._class; + _size = that._size; + _transactionID = std::move(that._transactionID); + _attrs = std::move(that._attrs); + + that._class = Request; + that._method = Undefined; + that._size = 0; } return *this; @@ -81,34 +114,37 @@ Message& Message::operator=(const Message& that) Message::~Message() { - for (unsigned i = 0; i < _attrs.size(); i++) - delete _attrs[i]; } -IPacket* Message::clone() const +std::unique_ptr Message::clone() const { - return new Message(*this); + return std::make_unique(*this); } void Message::add(Attribute* attr) { - _attrs.push_back(attr); + add(std::unique_ptr(attr)); +} + + +void Message::add(std::unique_ptr attr) +{ size_t attrLength = attr->size(); if (attrLength % 4 != 0) attrLength += (4 - (attrLength % 4)); _size += attrLength + kAttributeHeaderSize; - //_size += attr->size() + kAttributeHeaderSize; + _attrs.push_back(std::move(attr)); } Attribute* Message::get(Attribute::Type type, int index) const { - for (unsigned i = 0; i < _attrs.size(); i++) { - if (_attrs[i]->type() == type) { + for (const auto& attr : _attrs) { + if (attr->type() == type) { if (index == 0) - return _attrs[i]; + return attr.get(); else index--; } @@ -119,7 +155,7 @@ Attribute* Message::get(Attribute::Type type, int index) const ssize_t Message::read(const ConstBuffer& buf) { - LTrace("Parse STUN packet: ", buf.size()) + LTrace("Parse STUN packet: ", buf.size()); try { BitReader reader(buf); @@ -130,50 +166,43 @@ ssize_t Message::read(const ConstBuffer& buf) if (type & 0x8000) { // RTP and RTCP set MSB of first byte, since first two bits are version, // and version is always 2 (10). If set, this is not a STUN packet. - LWarn("Not STUN packet") + LWarn("Not STUN packet"); return 0; } - // uint16_t method = (type & 0x000F) | ((type & 0x00E0)>>1) | - // ((type & 0x0E00)>>2) | ((type & 0x3000)>>2); - uint16_t classType = type & 0x0110; uint16_t methodType = type & 0x000F; if (!isValidMethod(methodType)) { - LWarn("STUN message unknown method: ", methodType) + LWarn("STUN message unknown method: ", methodType); return 0; } - _class = classType; // static_cast(type & 0x0110); - _method = methodType; // static_cast(type & 0x000F); + _class = classType; + _method = methodType; // Message length reader.getU16(_size); if (_size > buf.size()) { - LWarn("STUN message larger than buffer: " , _size, " > ", buf.size()) + LWarn("STUN message larger than buffer: ", _size, " > ", buf.size()); return 0; } - // TODO: Check valid method - // TODO: Parse message class (Message::State) - // Magic cookie reader.skip(kMagicCookieLength); - // std::string magicCookie; - // reader.get(magicCookie, kMagicCookieLength); // Transaction ID std::string transactionID; reader.get(transactionID, kTransactionIdLength); - assert(transactionID.size() == kTransactionIdLength); + if (transactionID.size() != kTransactionIdLength) + throw std::runtime_error("invalid transaction ID length"); _transactionID = transactionID; // Attributes _attrs.clear(); - // int errors = 0; int rest = _size; uint16_t attrType, attrLength, padLength; - assert(int(reader.available()) >= rest); + if (static_cast(reader.available()) < rest) + throw std::runtime_error("insufficient data for attributes"); while (rest > 0) { reader.getU16(attrType); reader.getU16(attrLength); @@ -182,24 +211,23 @@ ssize_t Message::read(const ConstBuffer& buf) auto attr = Attribute::create(attrType, attrLength); if (attr) { attr->read(reader); // parse or throw - _attrs.push_back(attr); - - // STrace << "Parse attribute: " << Attribute::typeString(attrType) << ": " - // << attrLength << endl; + _attrs.push_back(std::move(attr)); } else SWarn << "Failed to parse attribute: " << Attribute::typeString(attrType) << ": " << attrLength - << endl; + << std::endl; rest -= (attrLength + kAttributeHeaderSize + padLength); } - LTrace("Parse success: ", reader.position(), ": ", buf.size()) - assert(rest == 0); - assert(reader.position() == _size + kMessageHeaderSize); + LTrace("Parse success: ", reader.position(), ": ", buf.size()); + if (rest != 0) + throw std::runtime_error("attribute parsing left non-zero remainder"); + if (reader.position() != _size + kMessageHeaderSize) + throw std::runtime_error("reader position mismatch after parsing"); return reader.position(); } catch (std::exception& exc) { - LDebug("Parse error: ", exc.what()) + LDebug("Parse error: ", exc.what()); } return 0; @@ -208,10 +236,6 @@ ssize_t Message::read(const ConstBuffer& buf) void Message::write(Buffer& buf) const { - // assert(_method); - // assert(_size); - - // BitWriter writer(buf); DynamicBitWriter writer(buf); writer.putU16((uint16_t)(_class | _method)); writer.putU16(_size); @@ -220,10 +244,10 @@ void Message::write(Buffer& buf) const // Note: MessageIntegrity must be at the end - for (unsigned i = 0; i < _attrs.size(); i++) { - writer.putU16(_attrs[i]->type()); - writer.putU16(_attrs[i]->size()); - _attrs[i]->write(writer); + for (const auto& attr : _attrs) { + writer.putU16(attr->type()); + writer.putU16(attr->size()); + attr->write(writer); } } @@ -311,8 +335,8 @@ std::string Message::toString() const { std::ostringstream os; os << "STUN[" << methodString() << ":" << transactionID(); - for (unsigned i = 0; i < _attrs.size(); i++) - os << ":" << _attrs[i]->typeString(); + for (const auto& attr : _attrs) + os << ":" << attr->typeString(); os << "]"; return os.str(); } @@ -321,15 +345,16 @@ std::string Message::toString() const void Message::print(std::ostream& os) const { os << "STUN[" << methodString() << ":" << transactionID(); - for (unsigned i = 0; i < _attrs.size(); i++) - os << ":" << _attrs[i]->typeString(); + for (const auto& attr : _attrs) + os << ":" << attr->typeString(); os << "]"; } void Message::setTransactionID(const std::string& id) { - assert(id.size() == kTransactionIdLength); + if (id.size() != kTransactionIdLength) + throw std::runtime_error("Message::setTransactionID: invalid length"); _transactionID = id; } @@ -355,8 +380,8 @@ void Message::setMethod(MethodType type) { _method = type; } -} -} // namespace scy:stun +} // namespace stun +} // namespace scy /// @\} diff --git a/src/stun/src/transaction.cpp b/src/stun/src/transaction.cpp index 62a1fda4c..987912003 100644 --- a/src/stun/src/transaction.cpp +++ b/src/stun/src/transaction.cpp @@ -15,13 +15,6 @@ #include -using namespace std; - -using scy::net::Transaction; -using scy::net::Address; -using scy::net::Socket; - - namespace scy { namespace stun { @@ -30,7 +23,7 @@ Transaction::Transaction(const net::Socket::Ptr& socket, const net::Address& peerAddress, long timeout, int retries) : net::Transaction(socket, peerAddress, timeout, retries) { - LDebug("Create") + LDebug("Create"); // Register STUN message creation strategy net::Transaction::factory.registerPacketType(0); @@ -39,7 +32,7 @@ Transaction::Transaction(const net::Socket::Ptr& socket, Transaction::~Transaction() { - LDebug("Destroy") + LDebug("Destroy"); } @@ -52,11 +45,11 @@ bool Transaction::checkResponse(const Message& message) void Transaction::onResponse() { - LDebug("On response") + LDebug("On response"); _response.setMethod(_request.methodType()); _response.setClass(Message::SuccessResponse); - if (_response.get()) + if (_response.get() != nullptr) _response.setClass(Message::ErrorResponse); else if (_response.methodType() == Message::SendIndication || _response.methodType() == Message::DataIndication) @@ -64,8 +57,8 @@ void Transaction::onResponse() net::Transaction::onResponse(); } -} -} // namespace scy:stun +} // namespace stun +} // namespace scy /// @\} diff --git a/src/stun/tests/CMakeLists.txt b/src/stun/tests/CMakeLists.txt index 70fb7781f..70ac7e142 100644 --- a/src/stun/tests/CMakeLists.txt +++ b/src/stun/tests/CMakeLists.txt @@ -1 +1 @@ -define_libsourcey_test(stuntests base stun crypto net) +scy_add_test(stuntests DEPENDS base stun crypto net) diff --git a/src/stun/tests/stuntests.cpp b/src/stun/tests/stuntests.cpp index b8e09f4da..09535a89c 100644 --- a/src/stun/tests/stuntests.cpp +++ b/src/stun/tests/stuntests.cpp @@ -1,107 +1,355 @@ -#include "scy/base.h" -#include "scy/logger.h" -#include "scy/stun/message.h" -#include "scy/test.h" -#include "scy/util.h" - -#include -#include - - -using namespace std; -using namespace scy; -using namespace scy::test; - - -// TODO: Test vectors from http://tools.ietf.org/html/rfc5769 - - -int main(int argc, char** argv) -{ - // Logger::instance().add(new ConsoleChannel("Test", Level::Trace)); - test::init(); - - // ========================================================================= - // Message Integrity - // - describe("message integrity", []() { - std::string username("someuser"); - std::string password("somepass"); - - stun::Message request(stun::Message::Request, stun::Message::Allocate); - // request.setType(stun::Message::Allocate); - - auto usernameAttr = new stun::Username; - usernameAttr->copyBytes(username.c_str(), username.size()); - request.add(usernameAttr); - - auto integrityAttr = new stun::MessageIntegrity; - integrityAttr->setKey(password); - request.add(integrityAttr); - - Buffer buf; - request.write(buf); - - stun::Message response; - auto nread = response.read(constBuffer(buf)); - - integrityAttr = response.get(); - expect(integrityAttr != nullptr); - expect(integrityAttr->verifyHmac(password)); - }); - - // ========================================================================= - // Request Types - // - describe("request types", []() { - uint16_t type = stun::Message::Indication | stun::Message::SendIndication; - uint16_t classType = type & 0x0110; - uint16_t methodType = type & 0x000F; - - expect(classType == stun::Message::Indication); - expect(methodType == stun::Message::SendIndication); - - stun::Message request(stun::Message::Indication, stun::Message::SendIndication); - // expect(IS_STUN_INDICATION(request.classType() | request.methodType())); - - expect(request.classType() != stun::Message::Request); - expect(request.classType() == stun::Message::Indication); - - stun::Message request1(stun::Message::Request, stun::Message::Allocate); - // expect(IS_STUN_REQUEST(request1.classType() | request1.methodType())); - }); - - // ========================================================================= - // Xor Address - // - describe("xor address", []() { - expect(5555 == 0x15B3); - expect((5555 ^ (stun::kMagicCookie >> 16)) == 0x34A1); - - net::Address addr("192.168.1.1", 5555); - // LDebug("Source Address: ", addr) - - stun::Message request(stun::Message::Request, stun::Message::Allocate); - // stun::Message request; - // request.setType(stun::Message::Allocate); - - auto addrAttr = new stun::XorRelayedAddress; - addrAttr->setAddress(addr); - request.add(addrAttr); - // LDebug("Request Address: ", addrAttr->address()) - - Buffer buf; - request.write(buf); - - stun::Message response; - response.read(constBuffer(buf)); - - addrAttr = response.get(); - - // LDebug("Response Address: ", addrAttr->address()) - expect(addrAttr->address() == addr); - }); - - test::runAll(); - return test::finalize(); -} +#include "scy/base.h" +#include "scy/logger.h" +#include "scy/stun/message.h" +#include "scy/test.h" +#include "scy/util.h" + +#include +#include + + +using namespace std; +using namespace scy; +using namespace scy::test; + + +// TODO: Test vectors from http://tools.ietf.org/html/rfc5769 + + +int main(int argc, char** argv) +{ + // Logger::instance().add(std::make_unique("Test", Level::Trace)); + test::init(); + + // ========================================================================= + // Message Integrity + // + describe("message integrity", []() { + std::string username("someuser"); + std::string password("somepass"); + + stun::Message request(stun::Message::Request, stun::Message::Allocate); + // request.setType(stun::Message::Allocate); + + auto usernameAttr = new stun::Username; + usernameAttr->copyBytes(username.c_str(), username.size()); + request.add(usernameAttr); + + auto integrityAttr = new stun::MessageIntegrity; + integrityAttr->setKey(password); + request.add(integrityAttr); + + Buffer buf; + request.write(buf); + + stun::Message response; + auto nread = response.read(constBuffer(buf)); + + integrityAttr = response.get(); + expect(integrityAttr != nullptr); + expect(integrityAttr->verifyHmac(password)); + }); + + // ========================================================================= + // Request Types + // + describe("request types", []() { + uint16_t type = stun::Message::Indication | stun::Message::SendIndication; + uint16_t classType = type & 0x0110; + uint16_t methodType = type & 0x000F; + + expect(classType == stun::Message::Indication); + expect(methodType == stun::Message::SendIndication); + + stun::Message request(stun::Message::Indication, stun::Message::SendIndication); + // expect(IS_STUN_INDICATION(request.classType() | request.methodType())); + + expect(request.classType() != stun::Message::Request); + expect(request.classType() == stun::Message::Indication); + + stun::Message request1(stun::Message::Request, stun::Message::Allocate); + // expect(IS_STUN_REQUEST(request1.classType() | request1.methodType())); + }); + + // ========================================================================= + // Xor Address + // + describe("xor address", []() { + expect(5555 == 0x15B3); + expect((5555 ^ (stun::kMagicCookie >> 16)) == 0x34A1); + + net::Address addr("192.168.1.1", 5555); + // LDebug("Source Address: ", addr); + + stun::Message request(stun::Message::Request, stun::Message::Allocate); + // stun::Message request; + // request.setType(stun::Message::Allocate); + + auto addrAttr = new stun::XorRelayedAddress; + addrAttr->setAddress(addr); + request.add(addrAttr); + // LDebug("Request Address: ", addrAttr->address()); + + Buffer buf; + request.write(buf); + + stun::Message response; + response.read(constBuffer(buf)); + + addrAttr = response.get(); + + // LDebug("Response Address: ", addrAttr->address()); + expect(addrAttr->address() == addr); + }); + + // ========================================================================= + // Binding Request Round-Trip + // + describe("binding request round-trip", []() { + stun::Message request(stun::Message::Request, stun::Message::Binding); + expect(request.classType() == stun::Message::Request); + expect(request.methodType() == stun::Message::Binding); + + // Serialize + Buffer buf; + request.write(buf); + expect(buf.size() >= 20); // STUN header is 20 bytes minimum + + // Deserialize + stun::Message parsed; + auto nread = parsed.read(constBuffer(buf)); + expect(nread == static_cast(buf.size())); + expect(parsed.classType() == stun::Message::Request); + expect(parsed.methodType() == stun::Message::Binding); + expect(parsed.transactionID() == request.transactionID()); + }); + + + // ========================================================================= + // Success Response + // + describe("success response", []() { + stun::Message response(stun::Message::SuccessResponse, stun::Message::Binding); + expect(response.classType() == stun::Message::SuccessResponse); + expect(response.methodType() == stun::Message::Binding); + + // Add a mapped address + net::Address addr("10.0.0.1", 3478); + auto addrAttr = new stun::XorMappedAddress; + addrAttr->setAddress(addr); + response.add(addrAttr); + + // Round-trip + Buffer buf; + response.write(buf); + + stun::Message parsed; + parsed.read(constBuffer(buf)); + expect(parsed.classType() == stun::Message::SuccessResponse); + + auto parsedAddr = parsed.get(); + expect(parsedAddr != nullptr); + expect(parsedAddr->address() == addr); + }); + + + // ========================================================================= + // Multiple Attributes + // + describe("multiple attributes", []() { + stun::Message msg(stun::Message::Request, stun::Message::Allocate); + + auto username = new stun::Username; + std::string user = "testuser"; + username->copyBytes(user.c_str(), user.size()); + msg.add(username); + + net::Address addr("192.168.1.1", 5555); + auto addrAttr = new stun::XorRelayedAddress; + addrAttr->setAddress(addr); + msg.add(addrAttr); + + // Serialize and parse back + Buffer buf; + msg.write(buf); + + stun::Message parsed; + parsed.read(constBuffer(buf)); + + auto parsedUser = parsed.get(); + expect(parsedUser != nullptr); + + auto parsedAddr = parsed.get(); + expect(parsedAddr != nullptr); + expect(parsedAddr->address() == addr); + }); + + + // ========================================================================= + // Copy Constructor + // + describe("message copy", []() { + stun::Message original(stun::Message::Request, stun::Message::Binding); + + stun::Message copy(original); + expect(copy.classType() == original.classType()); + expect(copy.methodType() == original.methodType()); + expect(copy.transactionID() == original.transactionID()); + }); + + + // ========================================================================= + // Method and Class Strings + // + describe("method and class strings", []() { + stun::Message msg(stun::Message::Request, stun::Message::Binding); + expect(!msg.methodString().empty()); + expect(!msg.classString().empty()); + + stun::Message msg2(stun::Message::ErrorResponse, stun::Message::Allocate); + expect(!msg2.classString().empty()); + expect(!msg2.errorString(stun::Message::NotAuthorized).empty()); + }); + + // ========================================================================= + // Attribute Factory + // + describe("attribute factory", []() { + // Create known attribute types via factory + auto username = stun::Attribute::create(stun::Attribute::Username, 0); + expect(username != nullptr); + expect(username->type() == stun::Attribute::Username); + + auto lifetime = stun::Attribute::create(stun::Attribute::Lifetime, 4); + expect(lifetime != nullptr); + expect(lifetime->type() == stun::Attribute::Lifetime); + + auto realm = stun::Attribute::create(stun::Attribute::Realm, 0); + expect(realm != nullptr); + + auto nonce = stun::Attribute::create(stun::Attribute::Nonce, 0); + expect(nonce != nullptr); + + auto software = stun::Attribute::create(stun::Attribute::Software, 0); + expect(software != nullptr); + }); + + + // ========================================================================= + // UInt32 Attribute (Lifetime) + // + describe("uint32 attribute lifetime", []() { + stun::Message msg(stun::Message::Request, stun::Message::Allocate); + + auto lifetime = new stun::Lifetime; + lifetime->setValue(600); + msg.add(lifetime); + + Buffer buf; + msg.write(buf); + + stun::Message parsed; + parsed.read(constBuffer(buf)); + + auto parsedLifetime = parsed.get(); + expect(parsedLifetime != nullptr); + expect(parsedLifetime->value() == 600); + }); + + + // ========================================================================= + // String Attribute (Software) + // + describe("string attribute software", []() { + stun::Message msg(stun::Message::Request, stun::Message::Binding); + + std::string sw = "LibSourcey STUN"; + auto software = new stun::Software; + software->copyBytes(sw.c_str(), sw.size()); + msg.add(software); + + Buffer buf; + msg.write(buf); + + stun::Message parsed; + parsed.read(constBuffer(buf)); + + auto parsedSw = parsed.get(); + expect(parsedSw != nullptr); + expect(parsedSw->asString() == sw); + }); + + + // ========================================================================= + // Error Code Attribute + // + describe("error code attribute", []() { + stun::Message msg(stun::Message::ErrorResponse, stun::Message::Allocate); + + auto err = new stun::ErrorCode; + err->setErrorCode(401); + err->setReason("Unauthorized"); + msg.add(err); + + Buffer buf; + msg.write(buf); + + stun::Message parsed; + parsed.read(constBuffer(buf)); + + auto parsedErr = parsed.get(); + expect(parsedErr != nullptr); + expect(parsedErr->errorCode() == 401); + expect(parsedErr->errorClass() == 4); + expect(parsedErr->errorNumber() == 1); + expect(parsedErr->reason() == "Unauthorized"); + }); + + + // ========================================================================= + // Multiple Address Attributes + // + describe("multiple address types", []() { + stun::Message msg(stun::Message::SuccessResponse, stun::Message::Allocate); + + net::Address relay("10.0.0.1", 5000); + auto relayAttr = new stun::XorRelayedAddress; + relayAttr->setAddress(relay); + msg.add(relayAttr); + + net::Address mapped("192.168.1.100", 6000); + auto mappedAttr = new stun::XorMappedAddress; + mappedAttr->setAddress(mapped); + msg.add(mappedAttr); + + Buffer buf; + msg.write(buf); + + stun::Message parsed; + parsed.read(constBuffer(buf)); + + auto parsedRelay = parsed.get(); + expect(parsedRelay != nullptr); + expect(parsedRelay->address() == relay); + + auto parsedMapped = parsed.get(); + expect(parsedMapped != nullptr); + expect(parsedMapped->address() == mapped); + }); + + + // ========================================================================= + // Attribute Type Strings + // + describe("attribute type string", []() { + auto username = stun::Attribute::create(stun::Attribute::Username, 0); + expect(!username->typeString().empty()); + expect(username->typeString().find("Username") != std::string::npos || + username->typeString().find("USERNAME") != std::string::npos || + !username->typeString().empty()); + }); + + + test::runAll(); + return test::finalize(); +} diff --git a/src/symple/CMakeLists.txt b/src/symple/CMakeLists.txt index e9873e260..eedbfd224 100644 --- a/src/symple/CMakeLists.txt +++ b/src/symple/CMakeLists.txt @@ -1,16 +1,6 @@ -ask_build_sourcey_module(symple) -if(BUILD_MODULES OR (NOT BUILD_MODULES AND BUILD_MODULE_symple)) - #include_dependency(LibUV) - include_dependency(SSL REQUIRED) - #include_dependency(JsonCpp) - #include_dependency(HttpParser) - - # FIXME: Including OpenCV dependency here for MediaServer - # sample although it is not directly required by Symple. - # include_dependency for samples does not include the - # dependency libraries properly. - #include_dependency(OpenCV REQUIRED) - #include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../http/vendor/http_parser) - - define_sourcey_module(symple base crypto net http socketio json util) +if(HAVE_OPENSSL) + scy_add_module(symple + DEPENDS base crypto net http socketio json + PACKAGES OpenSSL::SSL OpenSSL::Crypto + ) endif() diff --git a/src/symple/include/scy/symple/address.h b/src/symple/include/scy/symple/address.h index f0a3f73d4..35e07ded8 100644 --- a/src/symple/include/scy/symple/address.h +++ b/src/symple/include/scy/symple/address.h @@ -9,8 +9,7 @@ /// @{ -#ifndef SCY_Symple_Address_H -#define SCY_Symple_Address_H +#pragma once #include "scy/symple/symple.h" @@ -32,14 +31,14 @@ struct Symple_API Address Address(const std::string& addr); Address(const std::string& user, const std::string& id); - // const std::string& group, + // const std::string& group, virtual ~Address(); bool parse(const std::string& addr); - bool valid() const; + [[nodiscard]] bool valid() const; void print(std::ostream& os) const; - std::string toString() const; + [[nodiscard]] std::string toString() const; bool operator==(const Address& r); bool operator==(std::string& r); @@ -56,11 +55,8 @@ struct Symple_API Address }; -} // namespace scy } // namespace smpl - - -#endif // SCY_Symple_Address_H +} // namespace scy /// @\} diff --git a/src/symple/include/scy/symple/client.h b/src/symple/include/scy/symple/client.h index 9944cd486..2e66f58f9 100644 --- a/src/symple/include/scy/symple/client.h +++ b/src/symple/include/scy/symple/client.h @@ -9,11 +9,13 @@ /// @{ -#ifndef SCY_Symple_Client_H -#define SCY_Symple_Client_H +#pragma once -#include "scy/symple/symple.h" +#include "scy/bitwise.h" +#include "scy/http/websocket.h" +#include "scy/net/socket.h" +#include "scy/socketio/client.h" #include "scy/symple/command.h" #include "scy/symple/event.h" #include "scy/symple/form.h" @@ -21,18 +23,15 @@ #include "scy/symple/peer.h" #include "scy/symple/presence.h" #include "scy/symple/roster.h" -#include "scy/socketio/client.h" -#include "scy/bitwise.h" -#include "scy/http/websocket.h" -#include "scy/net/socket.h" -#include "scy/util/timedmanager.h" +#include "scy/symple/symple.h" +#include "scy/timedmanager.h" namespace scy { namespace smpl { -typedef TimedManager PersistenceT; +using PersistenceT = TimedManager; // @@ -60,7 +59,8 @@ class Symple_API Client : public sockio::Client std::string type; std::string token; - Options() { + Options() + { // Required on gcc 6 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70528 } @@ -105,10 +105,10 @@ class Symple_API Client : public sockio::Client /// Return the session ID of our current peer object. /// Return an empty string when offline. - virtual std::string ourID() const; + [[nodiscard]] virtual std::string ourID() const; /// Return a list of rooms the client has joined. - StringVec rooms() const; + [[nodiscard]] StringVec rooms() const; /// Return the peer object for the current session, /// or throws an exception when offline. @@ -253,92 +253,8 @@ struct Filter //: public Flaggable // -#if 0 -struct MessageDelegate: public PacketDelegateBase -{ - typedef Filter DataT; - Filter filter; - - MessageDelegate(const Filter& filter = Filter()) : filter(filter) {}; - MessageDelegate(const MessageDelegate& r) : filter(r.filter) {}; - - virtual bool accepts(void* /* sender */, IPacket& data, void*, void*, void*) - { - auto packet = dynamic_cast(&data); - if (packet && - (!filter.flags.has(AcceptRequests) || - (filter.flags.has(AcceptRequests) && packet->isRequest())) && - (!filter.flags.has(AcceptResponses) || - (filter.flags.has(AcceptResponses) && !packet->isRequest()))) { - return true; - } - return false; - } -}; - - -struct CommandDelegate: public MessageDelegate -{ - CommandDelegate(const Filter& filter = Filter()) : MessageDelegate(filter) {}; - CommandDelegate(const CommandDelegate& r) : MessageDelegate(r) {}; - - virtual bool accepts(void* sender, IPacket& data, void* empty2, void* empty3, void* empty4) - { - if (MessageDelegate::accepts(sender, data, empty2, empty3, empty4)) { - auto c = dynamic_cast(&data); - return c && c->matches(filter.path); - } - return false; - } -}; - - -struct PresenceDelegate: public MessageDelegate -{ - PresenceDelegate() : MessageDelegate(AcceptRequests) {}; - PresenceDelegate(const PresenceDelegate& r) : MessageDelegate(r) {}; - - virtual bool accepts(void* sender, IPacket& data, void* empty2, void* empty3, void* empty4) - { - if (MessageDelegate::accepts(sender, data, empty2, empty3, empty4)) { - auto p = dynamic_cast(&data); - return p && p->type() == "presence"; - } - return false; - } -}; - - -struct EventDelegate: public MessageDelegate -{ - EventDelegate() : MessageDelegate(AcceptRequests) {}; - EventDelegate(const EventDelegate& r) : MessageDelegate(r) {}; - - virtual bool accepts(void* sender, IPacket& data, void* empty2, void* empty3, void* empty4) - { - if (MessageDelegate::accepts(sender, data, empty2, empty3, empty4)) { - auto e = dynamic_cast(&data); - return e && e->type() == "event" && ( - filter.path.empty() || filter.path == "*" || - util::matchNodes(e->name(), filter.path, ":")); - } - return false; - } -}; - - -DefinePolymorphicDelegateWithArg(messageDelegate, IPacket, MessageDelegate, const Filter&, Filter()) -DefinePolymorphicDelegateWithArg(commandDelegate, IPacket, CommandDelegate, const Filter&, Filter()) -DefinePolymorphicDelegate(presenceDelegate, IPacket, PresenceDelegate) -DefinePolymorphicDelegate(eventDelegate, IPacket, EventDelegate) -#endif - - } // namespace smpl } // namespace scy -#endif // SCY_Symple_Client_H - - /// @\} diff --git a/src/symple/include/scy/symple/command.h b/src/symple/include/scy/symple/command.h index 42ef4560e..4572718bd 100644 --- a/src/symple/include/scy/symple/command.h +++ b/src/symple/include/scy/symple/command.h @@ -9,12 +9,11 @@ /// @{ -#ifndef SCY_Symple_Command_H -#define SCY_Symple_Command_H +#pragma once -#include "scy/symple/symple.h" #include "scy/symple/message.h" +#include "scy/symple/symple.h" namespace scy { @@ -29,17 +28,17 @@ class Symple_API Command : public Message Command(const Command& root); virtual ~Command(); - std::string node() const; - std::string action() const; + [[nodiscard]] std::string node() const; + [[nodiscard]] std::string action() const; void setNode(const std::string& node); void setAction(const std::string& action); bool valid() const override; - std::string param(int n) const; + [[nodiscard]] std::string param(int n) const; std::vector params(); - bool matches(const std::string& xnode) const; + [[nodiscard]] bool matches(const std::string& xnode) const; }; @@ -47,7 +46,4 @@ class Symple_API Command : public Message } // namespace scy -#endif // SCY_Symple_Command_H - - /// @\} diff --git a/src/symple/include/scy/symple/event.h b/src/symple/include/scy/symple/event.h index 1f5e5c669..76ddb581a 100644 --- a/src/symple/include/scy/symple/event.h +++ b/src/symple/include/scy/symple/event.h @@ -9,12 +9,11 @@ /// @{ -#ifndef SCY_Symple_Event_H -#define SCY_Symple_Event_H +#pragma once -#include "scy/symple/symple.h" #include "scy/symple/message.h" +#include "scy/symple/symple.h" #include @@ -30,11 +29,11 @@ class Symple_API Event : public Message Event(const Event& root); virtual ~Event(); - bool valid() const; + [[nodiscard]] bool valid() const; - std::string name() const; + [[nodiscard]] std::string name() const; // std::string message() const; - std::time_t time() const; + [[nodiscard]] std::time_t time() const; void setName(const std::string& name); // void setMessage(const std::string& message); @@ -49,7 +48,4 @@ class Symple_API Event : public Message } // namespace scy -#endif // SCY_Symple_Event_H - - /// @\} diff --git a/src/symple/include/scy/symple/form.h b/src/symple/include/scy/symple/form.h index 095a58568..12a46b16a 100644 --- a/src/symple/include/scy/symple/form.h +++ b/src/symple/include/scy/symple/form.h @@ -9,12 +9,11 @@ /// @{ -#ifndef SCY_Symple_Form_H -#define SCY_Symple_Form_H +#pragma once -#include "scy/symple/symple.h" #include "scy/symple/command.h" +#include "scy/symple/symple.h" namespace scy { @@ -36,9 +35,9 @@ class Symple_API FormElement FormElement& operator=(const FormElement& r); virtual ~FormElement(); - std::string type() const; - std::string id() const; - std::string label() const; + [[nodiscard]] std::string type() const; + [[nodiscard]] std::string id() const; + [[nodiscard]] std::string label() const; /// Possible "type" values /// page, section, text, text-multi, @@ -77,7 +76,7 @@ class Symple_API FormElement /// Returns true if this field is live, meaning the /// form-processing entity should auto-update this /// field's value whenever it changes. - bool live() const; + [[nodiscard]] bool live() const; /// Clears child elements matching the given ID. bool clearElements(const std::string& id, bool partial = false); @@ -86,7 +85,7 @@ class Symple_API FormElement void clear(); /// Returns true if the form element is valid. - bool valid() const; + [[nodiscard]] bool valid() const; /// Returns the number of child elements. int numElements(); @@ -97,7 +96,7 @@ class Symple_API FormElement /// Returns true if the form has multiple pages. bool hasPages(); - json::value& root() const; + [[nodiscard]] json::value& root() const; protected: /// The root pointer is just a reference to @@ -116,8 +115,8 @@ class Symple_API Form : public FormElement bool valid(); - std::string action() const; - bool partial() const; + [[nodiscard]] std::string action() const; + [[nodiscard]] bool partial() const; /// Possible "action" values /// `form` The form-processing entity is asking the form-submitting entity @@ -167,10 +166,10 @@ class Symple_API FormField : public FormElement /// Returns the first value. /// Most formats (except multi) only /// require single value. - std::string value() const; - int intValue() const; - double doubleValue() const; - bool boolValue() const; + [[nodiscard]] std::string value() const; + [[nodiscard]] int intValue() const; + [[nodiscard]] double doubleValue() const; + [[nodiscard]] bool boolValue() const; }; @@ -178,7 +177,4 @@ class Symple_API FormField : public FormElement } // namespace scy -#endif // SCY_Symple_Form_H - - /// @\} diff --git a/src/symple/include/scy/symple/message.h b/src/symple/include/scy/symple/message.h index b1601c241..b8cfcc186 100644 --- a/src/symple/include/scy/symple/message.h +++ b/src/symple/include/scy/symple/message.h @@ -9,21 +9,21 @@ /// @{ -#ifndef SCY_Symple_Message_H -#define SCY_Symple_Message_H +#pragma once -#include "scy/symple/symple.h" +#include "scy/packet.h" #include "scy/symple/address.h" #include "scy/symple/peer.h" -#include "scy/packet.h" +#include "scy/symple/symple.h" namespace scy { namespace smpl { -class Symple_API Message : public json::value, public IPacket +class Symple_API Message : public json::value + , public IPacket { public: Message(); @@ -31,18 +31,18 @@ class Symple_API Message : public json::value, public IPacket Message(const Message& root); virtual ~Message(); - virtual IPacket* clone() const; + virtual std::unique_ptr clone() const; virtual bool valid() const; virtual void clear(); virtual void clearData(); virtual void clearNotes(); - std::string type() const; - std::string id() const; - Address to() const; - Address from() const; - int status() const; + [[nodiscard]] std::string type() const; + [[nodiscard]] std::string id() const; + [[nodiscard]] Address to() const; + [[nodiscard]] Address from() const; + [[nodiscard]] int status() const; void setType(const std::string& type); void setTo(const Peer& to); @@ -77,7 +77,7 @@ class Symple_API Message : public json::value, public IPacket virtual ssize_t read(const std::string& root); virtual void write(Buffer& buf) const; - bool isRequest() const; + [[nodiscard]] bool isRequest() const; virtual size_t size() const; void print(std::ostream& os) const; @@ -90,7 +90,4 @@ class Symple_API Message : public json::value, public IPacket } // namespace scy -#endif // SCY_Symple_Message_H - - /// @\} diff --git a/src/symple/include/scy/symple/peer.h b/src/symple/include/scy/symple/peer.h index b1734e0ab..0fb4aafe3 100644 --- a/src/symple/include/scy/symple/peer.h +++ b/src/symple/include/scy/symple/peer.h @@ -9,13 +9,12 @@ /// @{ -#ifndef SCY_Symple_Peer_H -#define SCY_Symple_Peer_H +#pragma once -#include "scy/symple/symple.h" -#include "scy/symple/address.h" #include "scy/json/json.h" +#include "scy/symple/address.h" +#include "scy/symple/symple.h" namespace scy { @@ -34,14 +33,14 @@ class Symple_API Peer : public json::value Peer(const json::value& r); virtual ~Peer(); - Address address() const; + [[nodiscard]] Address address() const; - std::string id() const; - std::string user() const; - std::string name() const; + [[nodiscard]] std::string id() const; + [[nodiscard]] std::string user() const; + [[nodiscard]] std::string name() const; // std::string group() const; - std::string type() const; - std::string host() const; + [[nodiscard]] std::string type() const; + [[nodiscard]] std::string host() const; void setID(const std::string& id); void setUser(const std::string& user); @@ -71,7 +70,4 @@ class Symple_API Peer : public json::value } // namespace scy -#endif // SCY_Symple_Peer_H - - /// @\} diff --git a/src/symple/include/scy/symple/presence.h b/src/symple/include/scy/symple/presence.h index 4bf28c5d2..c06c756d8 100644 --- a/src/symple/include/scy/symple/presence.h +++ b/src/symple/include/scy/symple/presence.h @@ -9,12 +9,11 @@ /// @{ -#ifndef SCY_Symple_Presence_H -#define SCY_Symple_Presence_H +#pragma once -#include "scy/symple/symple.h" #include "scy/symple/message.h" +#include "scy/symple/symple.h" namespace scy { @@ -38,7 +37,4 @@ class Symple_API Presence : public Message } // namespace scy -#endif // SCY_Symple_Presence_H - - /// @\} diff --git a/src/symple/include/scy/symple/roster.h b/src/symple/include/scy/symple/roster.h index 91d772f01..45bb68c33 100644 --- a/src/symple/include/scy/symple/roster.h +++ b/src/symple/include/scy/symple/roster.h @@ -9,14 +9,13 @@ /// @{ -#ifndef SCY_Symple_Roster_H -#define SCY_Symple_Roster_H +#pragma once -#include "scy/symple/symple.h" +#include "scy/collection.h" #include "scy/symple/address.h" #include "scy/symple/peer.h" -#include "scy/collection.h" +#include "scy/symple/symple.h" namespace scy { @@ -28,8 +27,8 @@ namespace smpl { class Symple_API Roster : public LiveCollection { public: - typedef LiveCollection Manager; - typedef Manager::Map PeerMap; + using Manager = LiveCollection; + using PeerMap = Manager::Map; public: Roster(); @@ -38,7 +37,8 @@ class Symple_API Roster : public LiveCollection /// Returns the first peer which matches the given host address. Peer* getByHost(const std::string& host); - virtual PeerMap peers() const; + /// Returns a copy of the peer map for thread-safe iteration. + [[nodiscard]] virtual PeerMap peers() const; virtual void print(std::ostream& os) const; @@ -50,7 +50,4 @@ class Symple_API Roster : public LiveCollection } // namespace scy -#endif // SCY_Symple_Roster_H - - /// @\} diff --git a/src/symple/include/scy/symple/symple.h b/src/symple/include/scy/symple/symple.h index e1d4a660f..3d39aa181 100644 --- a/src/symple/include/scy/symple/symple.h +++ b/src/symple/include/scy/symple/symple.h @@ -9,8 +9,7 @@ /// @{ -#ifndef SCY_Symple_H -#define SCY_Symple_H +#pragma once #include "scy/base.h" @@ -18,17 +17,14 @@ // Shared library exports #if defined(SCY_WIN) && defined(SCY_SHARED_LIBRARY) - #if defined(Symple_EXPORTS) - #define Symple_API __declspec(dllexport) - #else - #define Symple_API __declspec(dllimport) - #endif +#if defined(Symple_EXPORTS) +#define Symple_API __declspec(dllexport) #else - #define Symple_API // nothing +#define Symple_API __declspec(dllimport) +#endif +#else +#define Symple_API // nothing #endif - - -#endif // SCY_Symple_Roster_H /// @\} diff --git a/src/symple/samples/sympleconsole/CMakeLists.txt b/src/symple/samples/sympleconsole/CMakeLists.txt index eea170fb3..077afb3d6 100644 --- a/src/symple/samples/sympleconsole/CMakeLists.txt +++ b/src/symple/samples/sympleconsole/CMakeLists.txt @@ -1 +1 @@ -define_sourcey_module_sample(sympleconsole base crypto net http socketio symple json util) +scy_add_sample(sympleconsole DEPENDS base crypto net http socketio symple json) diff --git a/src/symple/samples/sympleconsole/main.cpp b/src/symple/samples/sympleconsole/main.cpp index 10a1297a2..240690db6 100644 --- a/src/symple/samples/sympleconsole/main.cpp +++ b/src/symple/samples/sympleconsole/main.cpp @@ -1,364 +1,328 @@ -#include "scy/application.h" -#include "scy/filesystem.h" -#include "scy/ipc.h" -#include "scy/net/sslmanager.h" -#include "scy/symple/client.h" -#include "scy/util.h" - -#include - - -using std::cout; -using std::cerr; -using std::endl; -using namespace scy; -using namespace scy::net; -using namespace scy::util; - - -// -// Symple Console Application -// -// Examples: -// symple -help -// symple -host localhost -port 4500 -token nLIgQ2R8DUiVsxm3kLG0xQtt -user 42 -name Somedude -// symple -host mydomain.com -port 80 -token nLIgQ2R8DUiVsxm3kLG0xQtt -user 42 -name Somedude -// - - -#define USE_SSL 0 - - -class SympleApplication : public scy::Application -{ -public: -#if USE_SSL - smpl::SSLClient client; -#else - smpl::TCPClient client; -#endif - ipc::SyncQueue<> ipc; - bool showHelp; - - SympleApplication() - : showHelp(false) - { - } - - virtual ~SympleApplication() {} - - void printHelp() - { - cout - << "\nSymple Console Client v0.1.0" - "\n(c) Sourcey" - "\nhttps://sourcey.com/symple" - "\n" - "\nGeneral options:" - "\n -help Print help" - "\n -logfile Log file path" - "\n" - "\nClient options:" - "\n -host Symple server hostname or IP address" - "\n -port Symple server port" - "\n -token Session token to authenticate with" - "\n -user User ID to register on the server with" - "\n -name Display name to register on the server with" - "\n -type User type to register on the server with (optional)" - << endl; - } - - void parseOptions(int argc, char* argv[]) - { - OptionParser optparse(argc, argv, "-"); - for (auto& kv : optparse.args) { - const std::string& key = kv.first; - const std::string& value = kv.second; - LDebug("Setting option: ", key, ": ", value) - - if (key == "help") { - showHelp = true; - } else if (key == "host") { - client.options().host = value; - } else if (key == "port") { - client.options().port = util::strtoi(value); - } else if (key == "token") { - client.options().token = value; - } else if (key == "user") { - client.options().user = value; - } else if (key == "name") { - client.options().name = value; - } else if (key == "type") { - client.options().type = value; - } else if (key == "logfile") { - auto log = dynamic_cast(scy::Logger::instance().get("Symple")); - log->setPath(value); - } else { - LWarn("Unknown option: ", key, "=", value) - } - } - } - - void shutdown() - { - ipc.close(); - client.close(); - Application::stop(); - Application::finalize(); - } - - void start() - { - try { - // Print help - if (showHelp) { - printHelp(); - return; - } - - // client.options().host = "chat.mytommy.com"; - // client.options().port = 443; - // client.options().token = "g5A2VIcQJQ3FTdQJB1JFDwtt"; - // client.options().user = "2"; - - // client.options().host = "localhost"; - // client.options().port = 4500; - // client.options().user = "2"; - - // Setup the client - client += packetSlot(this, &SympleApplication::onRecvMessage); - client += packetSlot(this, &SympleApplication::onRecvPresence); - client += packetSlot(this, &SympleApplication::onRecvEvent); - client.Announce += slot(this, &SympleApplication::onClientAnnounce); - client.StateChange += slot(this, &SympleApplication::onClientStateChange); - client.CreatePresence += slot(this, &SympleApplication::onCreatePresence); - client.connect(); - - // Start the console thread - Thread console([](void* arg) { - auto app = reinterpret_cast(arg); - - char o = 0; - while (o != 'Q') { - cout << "COMMANDS:\n" - " M Send a message.\n" - " J Join a room.\n" - " L Leave a room.\n" - " C Print contacts list.\n" - " Q Quit.\n"; - - o = char(toupper(std::getchar())); - std::cin.ignore(); - - // Send a message - if (o == 'M') { - cout << "Compose your message: " << endl; - std::string data; - std::getline(std::cin, data); - - auto message = new smpl::Message(); - message->setData(data); - - cout << "Lending message: " << data << endl; - // app->client.send(message, true); - - // Synchronize the message with the main thread - app->ipc.push(new ipc::Action( - std::bind(&SympleApplication::onSyncMessage, app, std::placeholders::_1), - message)); - } - - // Join a room - else if (o == 'J') { - cout << "Join a room: " << endl; - auto data = new std::string(); - std::getline(std::cin, *data); - - app->ipc.push(new ipc::Action( - std::bind(&SympleApplication::onSyncCommand, app, std::placeholders::_1), - data, "join")); - } - - // Leave a room - else if (o == 'L') { - cout << "Leave a room: " << endl; - auto data = new std::string(); - std::getline(std::cin, *data); - - app->ipc.push(new ipc::Action( - std::bind(&SympleApplication::onSyncCommand, app, std::placeholders::_1), - data, "leave")); - } - - // List contacts - else if (o == 'C') { - cout << "Listing contacts:" << endl; - app->client.roster().print(cout); - cout << endl; - } - } - - cout << "Quiting" << endl; - app->shutdown(); - }, this); - - // Run the event loop - waitForShutdown([](void* opaque) { - reinterpret_cast(opaque)->shutdown(); - }, this); - } catch (std::exception& exc) { - cerr << "Symple runtime error: " << exc.what() << endl; - } - } - - void onSyncMessage(const ipc::Action& action) - { - // Send the message on the main thread - auto message = reinterpret_cast(action.arg); - - // Send without transaction - // client.send(*message); - - // Send with transaction - auto transaction = client.createTransaction(*message); - transaction->StateChange += slot(this, &SympleApplication::onAckState); - transaction->send(); - - delete message; - } - - void onSyncCommand(const ipc::Action& action) - { - auto arg = reinterpret_cast(action.arg); - - if (action.data == "join") { - client.joinRoom(*arg); - } else if (action.data == "leave") { - client.leaveRoom(*arg); - } - } - - void onAckState(void* sender, TransactionState& state, const TransactionState&) - { - LDebug("####### On announce response: ", state) - - // auto transaction = reinterpret_cast(sender); - switch (state.id()) { - case TransactionState::Success: - // Handle transaction success - break; - - case TransactionState::Failed: - // Handle transaction failure - break; - } - } - - //void onRecvPacket(IPacket& raw) - //{ - // LDebug("####### On raw packet: ", raw.className()) - - // auto message = dynamic_cast(&raw); - // if (message) { - // return onRecvMessage(*message); - // } - - // auto packet = dynamic_cast(&raw); - // if (packet) { - // return onRecvPacket(*packet); - // } - - // // Handle incoming raw packets here - //} - - void onRecvMessage(smpl::Message& message) - { - LDebug("####### On message: ", message.className()) - - // Handle incoming Symple messages here - } - - void onRecvPresence(smpl::Presence& presence) - { - LDebug("####### On presence: ", presence.className()) - - // Handle incoming Symple presences here - } - - void onRecvEvent(smpl::Event& event) - { - LDebug("####### On event: ", event.className()) - - // Handle incoming Symple events here - } - - void onClientAnnounce(const int& status) - { - LDebug("####### On announce: ", status) - assert(status == 200); - } - - void onClientStateChange(void*, sockio::ClientState& state, const sockio::ClientState& oldState) - { - SDebug << "Client state changed: " << state << ": " - << client.ws().socket->address() << endl; - - switch (state.id()) { - case sockio::ClientState::Connecting: - break; - case sockio::ClientState::Connected: - break; - case sockio::ClientState::Online: - cout << "Client online" << endl; - - // Join the public room - client.joinRoom("public"); - break; - case sockio::ClientState::Error: - cout << "Client disconnected" << endl; - break; - } - } - - void onCreatePresence(smpl::Peer& peer) - { - LDebug("####### Updating presence data") - - // Update the peer object to be broadcast with presence. - // Any arbitrary data can be broadcast with presence. - peer["agent"] = "SympleConsole"; - peer["version"] = "0.1.0"; - } -}; - - -int main(int argc, char** argv) -{ - // Setup the logger - // std::string logPath(getCwd()); - // fs::addnode(logPath, util::format("Symple_%Ld.log", static_cast(Timestamp().epochTime()))); - // cout << "Log path: " << logPath << endl; - // Logger::instance().add(new FileChannel("Symple", logPath, Level::Debug)); - Logger::instance().add(new ConsoleChannel("debug", Level::Trace)); - - // Init SSL client context -#if USE_SSL - net::SSLManager::initNoVerifyClient(); -#endif - - // Run the application - { - SympleApplication app; - app.parseOptions(argc, argv); - app.start(); - } - - // Cleanup all singletons - // http::Client::destroy(); -#if USE_SSL - net::SSLManager::destroy(); -#endif - GarbageCollector::destroy(); - Logger::destroy(); - return 0; -} +#include "scy/application.h" +#include "scy/filesystem.h" +#include "scy/ipc.h" +#include "scy/net/sslmanager.h" +#include "scy/symple/client.h" +#include "scy/util.h" + +#include +#include + + +// +// Symple Console Application +// +// Examples: +// symple -help +// symple -host localhost -port 4500 -token nLIgQ2R8DUiVsxm3kLG0xQtt -user 42 -name Somedude +// symple -host mydomain.com -port 80 -token nLIgQ2R8DUiVsxm3kLG0xQtt -user 42 -name Somedude +// + + +#define USE_SSL 0 + + +class SympleApplication : public scy::Application +{ +public: +#if USE_SSL + scy::smpl::SSLClient client; +#else + scy::smpl::TCPClient client; +#endif + scy::ipc::SyncQueue<> ipc; + bool showHelp; + + SympleApplication() + : showHelp(false) + { + } + + virtual ~SympleApplication() {} + + void printHelp() + { + std::cout + << "\nSymple Console Client v0.1.0" + "\n(c) Sourcey" + "\nhttps://sourcey.com/symple" + "\n" + "\nGeneral options:" + "\n -help Print help" + "\n -logfile Log file path" + "\n" + "\nClient options:" + "\n -host Symple server hostname or IP address" + "\n -port Symple server port" + "\n -token Session token to authenticate with" + "\n -user User ID to register on the server with" + "\n -name Display name to register on the server with" + "\n -type User type to register on the server with (optional)" + << std::endl; + } + + void parseOptions(int argc, char* argv[]) + { + scy::util::OptionParser optparse(argc, argv, "-"); + for (auto& kv : optparse.args) { + const std::string& key = kv.first; + const std::string& value = kv.second; + LDebug("Setting option: ", key, ": ", value); + + if (key == "help") { + showHelp = true; + } else if (key == "host") { + client.options().host = value; + } else if (key == "port") { + client.options().port = scy::util::strtoi(value); + } else if (key == "token") { + client.options().token = value; + } else if (key == "user") { + client.options().user = value; + } else if (key == "name") { + client.options().name = value; + } else if (key == "type") { + client.options().type = value; + } else if (key == "logfile") { + auto log = dynamic_cast(scy::Logger::instance().get("Symple")); + log->setPath(value); + } else { + LWarn("Unknown option: ", key, "=", value); + } + } + } + + void shutdown() + { + ipc.close(); + client.close(); + Application::stop(); + Application::finalize(); + } + + void start() + { + try { + // Print help + if (showHelp) { + printHelp(); + return; + } + + // Setup the client + client += packetSlot(this, &SympleApplication::onRecvMessage); + client += packetSlot(this, &SympleApplication::onRecvPresence); + client += packetSlot(this, &SympleApplication::onRecvEvent); + client.Announce += slot(this, &SympleApplication::onClientAnnounce); + client.StateChange += slot(this, &SympleApplication::onClientStateChange); + client.CreatePresence += slot(this, &SympleApplication::onCreatePresence); + client.connect(); + + // Start the console thread + scy::Thread console([](void* arg) { + auto app = static_cast(arg); + + char o = 0; + while (o != 'Q') { + std::cout << "COMMANDS:\n" + " M Send a message.\n" + " J Join a room.\n" + " L Leave a room.\n" + " C Print contacts list.\n" + " Q Quit.\n"; + + o = char(toupper(std::getchar())); + std::cin.ignore(); + + // Send a message + if (o == 'M') { + std::cout << "Compose your message: " << std::endl; + std::string data; + std::getline(std::cin, data); + + auto message = new scy::smpl::Message(); + message->setData(data); + + std::cout << "Sending message: " << data << std::endl; + // app->client.send(message, true); + + // Synchronize the message with the main thread + app->ipc.push(new scy::ipc::Action( + std::bind(&SympleApplication::onSyncMessage, app, std::placeholders::_1), + message)); + } + + // Join a room + else if (o == 'J') { + std::cout << "Join a room: " << std::endl; + auto data = new std::string(); + std::getline(std::cin, *data); + + app->ipc.push(new scy::ipc::Action( + std::bind(&SympleApplication::onSyncCommand, app, std::placeholders::_1), + data, "join")); + } + + // Leave a room + else if (o == 'L') { + std::cout << "Leave a room: " << std::endl; + auto data = new std::string(); + std::getline(std::cin, *data); + + app->ipc.push(new scy::ipc::Action( + std::bind(&SympleApplication::onSyncCommand, app, std::placeholders::_1), + data, "leave")); + } + + // List contacts + else if (o == 'C') { + std::cout << "Listing contacts:" << std::endl; + app->client.roster().print(std::cout); + std::cout << std::endl; + } + } + + std::cout << "Quiting" << std::endl; + app->shutdown(); + }, + this); + + // Run the event loop + waitForShutdown([](void* opaque) { + static_cast(opaque)->shutdown(); + }, + this); + } catch (std::exception& exc) { + std::cerr << "Symple runtime error: " << exc.what() << std::endl; + } + } + + void onSyncMessage(const scy::ipc::Action& action) + { + // Send the message on the main thread + auto message = static_cast(action.arg); + + // Send without transaction + // client.send(*message); + + // Send with transaction + auto transaction = client.createTransaction(*message); + transaction->StateChange += slot(this, &SympleApplication::onAckState); + transaction->send(); + + delete message; + } + + void onSyncCommand(const scy::ipc::Action& action) + { + auto arg = static_cast(action.arg); + + if (action.data == "join") { + client.joinRoom(*arg); + } else if (action.data == "leave") { + client.leaveRoom(*arg); + } + } + + void onAckState(void* sender, scy::TransactionState& state, const scy::TransactionState&) + { + LDebug("####### On announce response: ", state); + + // auto transaction = static_cast(sender); + switch (state.id()) { + case scy::TransactionState::Success: + // Handle transaction success + break; + + case scy::TransactionState::Failed: + // Handle transaction failure + break; + } + } + + void onRecvMessage(scy::smpl::Message& message) + { + LDebug("####### On message: ", message.className()); + + // Handle incoming Symple messages here + } + + void onRecvPresence(scy::smpl::Presence& presence) + { + LDebug("####### On presence: ", presence.className()); + + // Handle incoming Symple presences here + } + + void onRecvEvent(scy::smpl::Event& event) + { + LDebug("####### On event: ", event.className()); + + // Handle incoming Symple events here + } + + void onClientAnnounce(const int& status) + { + LDebug("####### On announce: ", status); + if (status != 200) + throw std::runtime_error("Announce failed with status: " + std::to_string(status)); + } + + void onClientStateChange(void*, scy::sockio::ClientState& state, const scy::sockio::ClientState& oldState) + { + SDebug << "Client state changed: " << state << ": " + << client.ws().socket->address() << std::endl; + + switch (state.id()) { + case scy::sockio::ClientState::Connecting: + break; + case scy::sockio::ClientState::Connected: + break; + case scy::sockio::ClientState::Online: + std::cout << "Client online" << std::endl; + + // Join the public room + client.joinRoom("public"); + break; + case scy::sockio::ClientState::Error: + std::cout << "Client disconnected" << std::endl; + break; + } + } + + void onCreatePresence(scy::smpl::Peer& peer) + { + LDebug("####### Updating presence data"); + + // Update the peer object to be broadcast with presence. + // Any arbitrary data can be broadcast with presence. + peer["agent"] = "SympleConsole"; + peer["version"] = "0.1.0"; + } +}; + + +int main(int argc, char** argv) +{ + // Setup the logger + scy::Logger::instance().add(std::make_unique("debug", scy::Level::Trace)); + + // Init SSL client context +#if USE_SSL + scy::net::SSLManager::initNoVerifyClient(); +#endif + + // Run the application + { + SympleApplication app; + app.parseOptions(argc, argv); + app.start(); + } + + // Cleanup all singletons +#if USE_SSL + scy::net::SSLManager::destroy(); +#endif + scy::Logger::destroy(); + return 0; +} diff --git a/src/symple/src/address.cpp b/src/symple/src/address.cpp index d9559459f..f20b087bd 100644 --- a/src/symple/src/address.cpp +++ b/src/symple/src/address.cpp @@ -10,12 +10,10 @@ #include "scy/symple/address.h" -#include "assert.h" #include "scy/util.h" -#include "sstream" - -using std::endl; +#include +#include namespace scy { @@ -51,7 +49,6 @@ bool Address::parse(const std::string& addr) return false; std::vector params = util::split(addr, '|'); - // assert(params.size() > 1); if (params.empty()) return false; if (params.size() > 0) diff --git a/src/symple/src/client.cpp b/src/symple/src/client.cpp index bea238163..1185837a3 100644 --- a/src/symple/src/client.cpp +++ b/src/symple/src/client.cpp @@ -13,8 +13,8 @@ #include "scy/net/sslsocket.h" #include "scy/net/tcpsocket.h" - -using std::endl; +#include +#include namespace scy { @@ -65,21 +65,23 @@ Client::Client(const net::Socket::Ptr& socket, const Client::Options& options) , _options(options) , _announceStatus(0) { - LTrace("Create") + LTrace("Create"); } Client::~Client() { - LTrace("Destroy") + LTrace("Destroy"); } void Client::connect() { - LTrace("Connecting") - assert(!_options.host.empty()); - assert(!_options.user.empty()); + LTrace("Connecting"); + if (_options.host.empty()) + throw std::runtime_error("Symple client host must not be empty"); + if (_options.user.empty()) + throw std::runtime_error("Symple client user must not be empty"); // Update the Socket.IO options with local values before connecting sockio::Client::options().host = _options.host; @@ -93,7 +95,7 @@ void Client::connect() void Client::close() { - LTrace("Closing") + LTrace("Closing"); sockio::Client::close(); } @@ -104,22 +106,21 @@ void assertCanSend(Client* client, Message& m) throw std::runtime_error("Cannot send message while offline."); } - assert(client->ourPeer()); + if (!client->ourPeer()) + throw std::runtime_error("No active peer session is available."); m.setFrom(client->ourPeer()->address()); if (m.to().id == m.from().id) { - LError("Invalid Symple address: ", m.to().id, ": ", m.from().id) - assert(0); + LError("Invalid Symple address: ", m.to().id, ": ", m.from().id); throw std::runtime_error("Cannot send message with matching sender and recipient."); } if (!m.valid()) { - assert(0); throw std::runtime_error("Cannot send invalid message."); } #ifdef _DEBUG - LTrace("Sending message:", m.dump(4)) + LTrace("Sending message:", m.dump(4)); #endif } @@ -157,22 +158,25 @@ int Client::respond(Message& m, bool ack) void Client::createPresence(Presence& p) { - LTrace("Create presence") + LTrace("Create presence"); auto peer = ourPeer(); if (peer) { CreatePresence.emit(*peer); - assert(peer->is_object()); + if (!peer->is_object()) + throw std::runtime_error("Peer must be a JSON object"); p["data"] = (json::value&)*peer; - assert(p["data"].is_object()); - } else - assert(0 && "no peer session object"); + if (!p["data"].is_object()) + throw std::runtime_error("Presence data must be a JSON object"); + } else { + throw std::runtime_error("No peer session object available for presence"); + } } int Client::sendPresence(bool probe) { - LTrace("Broadcasting presence") + LTrace("Broadcasting presence"); Presence p; createPresence(p); @@ -183,7 +187,7 @@ int Client::sendPresence(bool probe) int Client::sendPresence(const Address& to, bool probe) { - LTrace("Sending presence") + LTrace("Sending presence"); Presence p; createPresence(p); @@ -195,7 +199,7 @@ int Client::sendPresence(const Address& to, bool probe) int Client::announce() { - LTrace("Announcing") + LTrace("Announcing"); json::value data; data["user"] = _options.user; @@ -211,7 +215,7 @@ int Client::announce() int Client::joinRoom(const std::string& room) { - LDebug("Join room:", room) + LDebug("Join room:", room); _rooms.push_back(room); sockio::Packet pkt("join", "\"" + room + "\""); @@ -221,7 +225,7 @@ int Client::joinRoom(const std::string& room) int Client::leaveRoom(const std::string& room) { - LDebug("Leave room:", room) + LDebug("Leave room:", room); _rooms.erase(std::remove(_rooms.begin(), _rooms.end(), room), _rooms.end()); sockio::Packet pkt("leave", "\"" + room + "\""); @@ -231,9 +235,9 @@ int Client::leaveRoom(const std::string& room) void Client::onAnnounceState(void* sender, TransactionState& state, const TransactionState&) { - LTrace("On announce response:", state) + LTrace("On announce response:", state); - auto transaction = reinterpret_cast(sender); + auto transaction = static_cast(sender); switch (state.id()) { case TransactionState::Success: try { @@ -287,42 +291,45 @@ void Client::onOnline() void Client::emit(IPacket& raw) { - auto packet = reinterpret_cast(raw); - LTrace("Emit packet:", packet.toString()) + auto& packet = static_cast(raw); + LTrace("Emit packet:", packet.toString()); // Parse Symple messages from Socket.IO packets - if (packet.type() == sockio::Packet::Type::Event) { - LTrace("JSON packet:", packet.toString()) + if (packet.type() == sockio::Type::Event) { + LTrace("JSON packet:", packet.toString()); json::value data = packet.json(); #ifdef _DEBUG - LTrace("Received ", data.dump(4)) + LTrace("Received ", data.dump(4)); #endif - assert(data.is_object()); + if (!data.is_object()) { + LWarn("Invalid Symple message: expected JSON object"); + return; + } std::string type(data.value("type", "")); if (!type.empty()) { - // KLUDGE: Note we are currently creating the JSON object - // twice with these polymorphic message classes. Perhaps - // free functions are a better for working with messages. + // NOTE: The polymorphic message classes re-parse the JSON + // data since they each construct from a json::value. + // Consider free functions for working with messages. if (type == "message") { Message m(data); if (!m.valid()) { - LWarn("Dropping invalid message: ", data.dump()) + LWarn("Dropping invalid message: ", data.dump()); return; } PacketSignal::emit(m); } else if (type == "event") { Event e(data); if (!e.valid()) { - LWarn("Dropping invalid event: ", data.dump()) + LWarn("Dropping invalid event: ", data.dump()); return; } PacketSignal::emit(e); } else if (type == "presence") { Presence p(data); if (!p.valid()) { - LWarn("Dropping invalid presence: ", data.dump()) + LWarn("Dropping invalid presence: ", data.dump()); return; } PacketSignal::emit(p); @@ -334,35 +341,34 @@ void Client::emit(IPacket& raw) } else if (type == "command") { Command c(data); if (!c.valid()) { - LWarn("Dropping invalid command: ", data.dump()) + LWarn("Dropping invalid command: ", data.dump()); return; } PacketSignal::emit(c); if (c.isRequest()) { c.setStatus(404); - LWarn("Command not handled: " , c.id(), ": ", c.node()) + LWarn("Command not handled: ", c.id(), ": ", c.node()); respond(c); } } else { - LDebug("Received non-standard message:", type) + LDebug("Received non-standard message:", type); // Attempt to parse custom packets as a message type Message m(data); if (!m.valid()) { - LWarn("Dropping invalid message: ", data.dump()) + LWarn("Dropping invalid message: ", data.dump()); return; } PacketSignal::emit(m); } } else { - assert(0 && "invalid packet"); - LWarn("Invalid Symple message") + LWarn("Invalid Symple message: missing type field"); } } // Other packet types are proxied directly else { - LTrace("Proxying packet:", PacketSignal::nslots()) + LTrace("Proxying packet:", PacketSignal::nslots()); PacketSignal::emit(packet); } } @@ -370,7 +376,7 @@ void Client::emit(IPacket& raw) void Client::onPresenceData(const json::value& data, bool whiny) { - LTrace("Updating:", data.dump(4)) + LTrace("Updating:", data.dump(4)); if (data.is_object() && data.find("id") != data.end() && @@ -382,57 +388,28 @@ void Client::onPresenceData(const json::value& data, bool whiny) auto peer = _roster.get(id, false); if (online) { if (!peer) { - peer = new Peer(data); - _roster.add(id, peer); - LDebug("Peer connected:", peer->address().toString()) + _roster.add(id, std::make_unique(data)); + peer = _roster.get(id, false); + LDebug("Peer connected:", peer->address().toString()); PeerConnected.emit(*peer); } else { static_cast(*peer) = data; } } else { if (peer) { - LDebug("Peer disconnected:", peer->address().toString()) + LDebug("Peer disconnected:", peer->address().toString()); PeerDisconnected.emit(*peer); _roster.free(id); } else { - LWarn("Unknown peer disconnected:", peer->address().toString()) + LWarn("Unknown peer disconnected"); } } } else { std::string error("Bad presence data: " + data.dump()); - LError(error) + LError(error); if (whiny) throw std::runtime_error(error); } - -#if 0 - if (data.is_object() && - data.isMember("id") && - data.isMember("user") && - data.isMember("name") //&& - //data.isMember("type") - ) { - LTrace("Updating:", json::stringify(data, true)) - std::string id = data["id"].get(); - Peer* peer = get(id, false); - if (!peer) { - peer = new Peer(data); - add(id, peer); - } else - static_cast(*peer) = data; - } - else if (data.isArray()) { - for (auto it = data.begin(); it != data.end(); it++) { - onPresenceData(*it, whiny); - } - } - else { - std::string error("Bad presence data: " + json::stringify(data)); - LError(error, ) - if (whiny) - throw std::runtime_error(error); - } -#endif } @@ -485,7 +462,7 @@ Peer* Client::ourPeer() { if (_ourID.empty()) return nullptr; - // throw std::runtime_error("No active peer session is available."); + // throw std::runtime_error("No active peer session is available."); return _roster.get(_ourID, false); } diff --git a/src/symple/src/command.cpp b/src/symple/src/command.cpp index a8ce3d854..e1994eebc 100644 --- a/src/symple/src/command.cpp +++ b/src/symple/src/command.cpp @@ -10,11 +10,9 @@ #include "scy/symple/command.h" -#include "assert.h" #include "scy/util.h" - -using std::endl; +#include namespace scy { @@ -31,7 +29,7 @@ Command::Command(const Command& root) : Message(root) { // if (find("type") == end()) - (*this)["type"] = "command"; + (*this)["type"] = "command"; } @@ -39,7 +37,7 @@ Command::Command(const json::value& root) : Message(root) { // if (find("type") == end()) - (*this)["type"] = "command"; + (*this)["type"] = "command"; } @@ -50,8 +48,7 @@ Command::~Command() bool Command::valid() const { - return Message::valid() - && find("node") != end(); + return Message::valid() && find("node") != end(); } @@ -82,9 +79,8 @@ void Command::setAction(const std::string& action) std::string Command::param(int n) const { std::vector params = util::split(node(), ':'); - assert(int(params.size()) >= n); if (int(params.size()) < n) - return ""; + throw std::out_of_range("Command param index out of range: " + std::to_string(n)); return params[n - 1].c_str(); } diff --git a/src/symple/src/event.cpp b/src/symple/src/event.cpp index 3b6bbba8c..aa7137d01 100644 --- a/src/symple/src/event.cpp +++ b/src/symple/src/event.cpp @@ -13,9 +13,6 @@ #include "scy/util.h" -using std::endl; - - namespace scy { namespace smpl { @@ -23,7 +20,7 @@ namespace smpl { Event::Event() { setType("event"); - setTime(::time(0)); + setTime(::time(nullptr)); } @@ -31,9 +28,9 @@ Event::Event(const Event& root) : Message(root) { // if (find("type") == end()) - setType("event"); + setType("event"); if (find("time") == end()) - setTime(::time(0)); + setTime(::time(nullptr)); } @@ -41,9 +38,9 @@ Event::Event(const json::value& root) : Message(root) { // if (find("type") == end()) - setType("event"); + setType("event"); if (find("time") == end()) - setTime(::time(0)); + setTime(::time(nullptr)); } @@ -54,8 +51,7 @@ Event::~Event() bool Event::valid() const { - return Message::valid() - && find("name") != end(); + return Message::valid() && find("name") != end(); } @@ -80,9 +76,6 @@ void Event::setName(const std::string& name) void Event::setTime(time_t time) { (*this)["time"] = static_cast(time); - // DateTimeFormatter::format( - // Timestamp::fromEpochTime(time), - // DateTimeFormat::ISO8601_FORMAT); } diff --git a/src/symple/src/form.cpp b/src/symple/src/form.cpp index 456bbfb7a..58b5a3121 100644 --- a/src/symple/src/form.cpp +++ b/src/symple/src/form.cpp @@ -10,11 +10,9 @@ #include "scy/symple/form.h" -#include "assert.h" #include "scy/util.h" - -using std::endl; +#include namespace scy { @@ -65,8 +63,8 @@ void Form::setPartial(bool flag) void Form::setAction(const std::string& action) { - assert(action == "form" || action == "submit" || action == "cancel" || - action == "result"); + if (action != "form" && action != "submit" && action != "cancel" && action != "result") + throw std::invalid_argument("Invalid form action: " + action); root()["action"] = action; } @@ -182,10 +180,11 @@ FormElement FormElement::addSection(const std::string& id, FormField FormElement::addField(const std::string& type, const std::string& id, const std::string& label) { - assert(type == "text" || type == "text-multi" || type == "list" || - type == "list-multi" || type == "boolean" || type == "number" || - type == "media" || type == "date" || type == "time" || - type == "datetime" || type == "horizontal-set" || type == "custom"); + if (type != "text" && type != "text-multi" && type != "list" && + type != "list-multi" && type != "boolean" && type != "number" && + type != "media" && type != "date" && type != "time" && + type != "datetime" && type != "horizontal-set" && type != "custom") + throw std::invalid_argument("Invalid form field type: " + type); return FormField(root()["elements"][root()["elements"].size()], type, id, label); @@ -241,15 +240,16 @@ bool FormElement::clearElements(const std::string& id, bool partial) for (unsigned x = 0; x < root()["elements"].size(); x++) { json::value& element = root()["elements"][x]; std::string curID = element["id"].get(); - if (// element.is_object() && + if ( // element.is_object() && // element.isMember("id") && partial ? curID.find(id) != std::string::npos : curID == id) { - LTrace("Symple form: Removing redundant: ", curID) + LTrace("Symple form: Removing redundant: ", curID); match = true; } else { - LTrace("Symple form: Keeping: ", curID) - result["elements"].push_back(element); + LTrace("Symple form: Keeping: ", curID); + result["elements"] + .push_back(element); } } } diff --git a/src/symple/src/message.cpp b/src/symple/src/message.cpp index 90d406358..41a3de286 100644 --- a/src/symple/src/message.cpp +++ b/src/symple/src/message.cpp @@ -10,12 +10,10 @@ #include "scy/symple/message.h" -#include "assert.h" #include "scy/logger.h" #include "scy/util.h" - -using std::endl; +#include namespace scy { @@ -28,7 +26,8 @@ Message::Message() (*this)["id"] = util::randomString(16); (*this)["type"] = "message"; - assert(is_object()); + if (!is_object()) + throw std::runtime_error("Message must be a JSON object"); } @@ -40,7 +39,8 @@ Message::Message(const Message& root) if (find("type") == end()) (*this)["type"] = "message"; - assert(is_object()); + if (!is_object()) + throw std::runtime_error("Message must be a JSON object"); } @@ -52,7 +52,8 @@ Message::Message(const json::value& root) if (find("type") == end()) (*this)["type"] = "message"; - assert(is_object()); + if (!is_object()) + throw std::runtime_error("Message must be a JSON object"); } @@ -61,9 +62,9 @@ Message::~Message() } -IPacket* Message::clone() const +std::unique_ptr Message::clone() const { - return new Message(*this); + return std::make_unique(*this); } @@ -91,7 +92,6 @@ void Message::write(Buffer& buf) const size_t Message::size() const { - // KLUDGE: is there a better way? return dump().size(); } @@ -104,10 +104,9 @@ void Message::print(std::ostream& os) const bool Message::valid() const { - return find("type") != end() - && find("id") != end(); - // && find("from") != end() - // && (*this)["from"].get().length() + return find("type") != end() && find("id") != end(); + // && find("from") != end() + // && (*this)["from"].get().length() } @@ -215,7 +214,8 @@ void Message::setFrom(const Peer& from) void Message::setFrom(const Address& from) { - assert(is_object()); + if (!is_object()) + throw std::runtime_error("Message must be a JSON object"); (*this)["from"] = from.toString(); } @@ -228,7 +228,8 @@ void Message::setFrom(const std::string& from) void Message::setStatus(int code) { - assert(code > 100 && code < 505); + if (code <= 100 || code >= 505) + throw std::invalid_argument("HTTP status code out of range: " + std::to_string(code)); (*this)["status"] = code; } @@ -241,7 +242,8 @@ void Message::setNote(const std::string& type, const std::string& text) void Message::addNote(const std::string& type, const std::string& text) { - assert(type == "info" || type == "warn" || type == "error"); + if (type != "info" && type != "warn" && type != "error") + throw std::invalid_argument("Invalid note type: " + type); json::value note; note["type"] = type; diff --git a/src/symple/src/peer.cpp b/src/symple/src/peer.cpp index c3a112722..c4fb26b50 100644 --- a/src/symple/src/peer.cpp +++ b/src/symple/src/peer.cpp @@ -10,7 +10,6 @@ #include "scy/symple/peer.h" -#include "assert.h" #include "scy/logger.h" @@ -51,9 +50,7 @@ void Peer::print(std::ostream& os) const bool Peer::valid() { - return find("id") != end() - && find("user") != end() - && find("type") != end(); + return find("id") != end() && find("user") != end() && find("type") != end(); } diff --git a/src/symple/src/presence.cpp b/src/symple/src/presence.cpp index 8f673472f..b61de207c 100644 --- a/src/symple/src/presence.cpp +++ b/src/symple/src/presence.cpp @@ -10,13 +10,9 @@ #include "scy/symple/presence.h" -#include "assert.h" #include "scy/util.h" -using std::endl; - - namespace scy { namespace smpl { @@ -31,7 +27,7 @@ Presence::Presence(const Presence& root) : Message(root) { // if (find("type") == end()) - (*this)["type"] = "presence"; + (*this)["type"] = "presence"; } @@ -39,7 +35,7 @@ Presence::Presence(const json::value& root) : Message(root) { // if (find("type") == end()) - (*this)["type"] = "presence"; + (*this)["type"] = "presence"; } diff --git a/src/symple/src/roster.cpp b/src/symple/src/roster.cpp index 54891a9eb..6d539af70 100644 --- a/src/symple/src/roster.cpp +++ b/src/symple/src/roster.cpp @@ -13,88 +13,58 @@ #include "scy/logger.h" -using std::endl; - - namespace scy { namespace smpl { Roster::Roster() { - // LTrace("Create") + // LTrace("Create"); } Roster::~Roster() { - // LTrace("Destroy") + // LTrace("Destroy"); } Peer* Roster::getByHost(const std::string& host) { - std::lock_guard guard(_mutex); - for (auto it = _map.begin(); it != _map.end(); ++it) { - if (it->second->host() == host) - return it->second; + std::shared_lock guard(_mutex); + for (auto& [id, peer] : _map) { + if (peer->host() == host) + return peer.get(); } - return NULL; + return nullptr; } Roster::PeerMap Roster::peers() const { - std::lock_guard guard(_mutex); - return _map; + std::shared_lock guard(_mutex); + // Return a deep copy of the map for thread-safe iteration. + // Each unique_ptr entry is cloned as a new Peer allocation. + PeerMap copy; + for (auto& [id, peer] : _map) { + copy.emplace(id, std::make_unique(*peer)); + } + return copy; } void Roster::print(std::ostream& os) const { - std::lock_guard guard(_mutex); + std::shared_lock guard(_mutex); os << "Roster["; - for (auto it = _map.begin(); it != _map.end(); ++it) { - os << "\n\t" << it->second << ": " << it->first; + for (auto& [id, peer] : _map) { + os << "\n\t" << peer.get() << ": " << id; } os << "\n]"; } -#if 0 -void Roster::update(const json::value& data, bool whiny) -{ - if (data.is_object() && - data.isMember("id") && - data.isMember("user") && - data.isMember("name") //&& - //data.isMember("type") - ) { - LTrace("Updating: ", json::stringify(data, true)) - std::string id = data["id"].get(); - Peer* peer = get(id, false); - if (!peer) { - peer = new Peer(data); - add(id, peer); - } else - static_cast(*peer) = data; - } - else if (data.isArray()) { - for (auto it = data.begin(); it != data.end(); it++) { - update(*it, whiny); - } - } - else { - std::string error("Bad presence data: " + json::stringify(data)); - LError(error, ) - if (whiny) - throw std::runtime_error(error); - } -} -#endif - - } // namespace smpl } // namespace scy diff --git a/src/symple/tests/CMakeLists.txt b/src/symple/tests/CMakeLists.txt index a0713bdab..d54f47dae 100644 --- a/src/symple/tests/CMakeLists.txt +++ b/src/symple/tests/CMakeLists.txt @@ -1 +1 @@ -define_libsourcey_test(sympletests base crypto net http json socketio symple util) +scy_add_test(sympletests DEPENDS base crypto net http json socketio symple) diff --git a/src/symple/tests/sympletests.cpp b/src/symple/tests/sympletests.cpp index 77bbf6a6d..507a88365 100644 --- a/src/symple/tests/sympletests.cpp +++ b/src/symple/tests/sympletests.cpp @@ -1,108 +1,258 @@ -#include "sympletests.h" - - -using namespace std; -using namespace scy; -using namespace scy::test; - - -int main(int argc, char** argv) -{ - // Logger::instance().add(new ConsoleChannel("debug", Level::Trace)); - test::init(); - -#if USE_SSL - net::SSLManager::initNoVerifyClient(); -#endif - - - // ========================================================================= - // Address - // - describe("address", []() { - smpl::Address a1("user|"); - assert(a1.user == "user"); - assert(a1.id == ""); - assert(a1.valid()); - - smpl::Address a2("user"); - assert(a2.user == "user"); - assert(a2.id == ""); - assert(a2.valid()); - - smpl::Address a3(""); - assert(a3.user == ""); - assert(a3.id == ""); - assert(!a3.valid()); - - smpl::Address a4("|567257247245275"); - assert(a4.user == ""); - assert(a4.id == "567257247245275"); - assert(a4.valid()); - }); - - - // ========================================================================= - // Client - // - describe("client", []() { - - // Run the test server - // If not available the test will fail gracefully with a warning - // NOTE: The server must allow anonymous authentication for this test - Process proc; - if (!openTestServer(proc)) { - std::cerr << "cannot start test server, skipping..." << std::endl; - return; - } - - smpl::Client::Options loptions; - loptions.host = SERVER_HOST; - loptions.port = SERVER_PORT; - loptions.user = "l"; - loptions.name = "Left"; - // loptions.token = "2NuMmyXw2YDuQfyPCKDO2Qtta"; - - smpl::Client::Options roptions; - roptions.host = SERVER_HOST; - roptions.port = SERVER_PORT; - roptions.user = "r"; - roptions.name = "Right"; - // roptions.token = "2NuMmyXw2YDuQfyPCKDO2Qtta"; - - TestClient lclient(loptions); - TestClient rclient(roptions); - - lclient.connect(); - rclient.connect(); - - while (!lclient.completed() || !rclient.completed()) { - - // LDebug("waiting for test completion") - uv::runLoop(uv::defaultLoop(), UV_RUN_ONCE); - - // // Connect the rclient when lclient is online - // if (lclient.client.isOnline() && - // rclient.client.stateEquals(sockio::ClientState::Closed)) - // rclient.connect(); - } - - lclient.check(); - rclient.check(); - }); - - // TODO: - // - Obtain authentication token - // - Transaction test - // - Presence test - // - Ack test - // - Benchmarks - - test::runAll(); - -#if USE_SSL - net::SSLManager::instance().shutdown(); -#endif - Logger::destroy(); - return test::finalize(); -} +#include "sympletests.h" +#include "scy/symple/command.h" +#include "scy/symple/event.h" +#include "scy/symple/peer.h" +#include "scy/symple/presence.h" +#include "scy/symple/roster.h" + +#include + + +namespace scy_test = scy::test; + + +int main(int argc, char** argv) +{ + // Logger::instance().add(new ConsoleChannel("debug", Level::Trace)); + scy_test::init(); + +#if USE_SSL + scy::net::SSLManager::initNoVerifyClient(); +#endif + + + // ========================================================================= + // Address + // + scy_test::describe("address", []() { + scy::smpl::Address a1("user|"); + if (a1.user != "user") + throw std::runtime_error("Expected user == 'user'"); + if (!a1.id.empty()) + throw std::runtime_error("Expected id to be empty"); + if (!a1.valid()) + throw std::runtime_error("Expected a1 to be valid"); + + scy::smpl::Address a2("user"); + if (a2.user != "user") + throw std::runtime_error("Expected user == 'user'"); + if (!a2.id.empty()) + throw std::runtime_error("Expected id to be empty"); + if (!a2.valid()) + throw std::runtime_error("Expected a2 to be valid"); + + scy::smpl::Address a3(""); + if (!a3.user.empty()) + throw std::runtime_error("Expected user to be empty"); + if (!a3.id.empty()) + throw std::runtime_error("Expected id to be empty"); + if (a3.valid()) + throw std::runtime_error("Expected a3 to be invalid"); + + scy::smpl::Address a4("|567257247245275"); + if (!a4.user.empty()) + throw std::runtime_error("Expected user to be empty"); + if (a4.id != "567257247245275") + throw std::runtime_error("Expected id == '567257247245275'"); + if (!a4.valid()) + throw std::runtime_error("Expected a4 to be valid"); + }); + + + // ========================================================================= + // Client + // + scy_test::describe("client", []() { + // Run the test server + // If not available the test will fail gracefully with a warning + // NOTE: The server must allow anonymous authentication for this test + scy::Process proc; + if (!scy::openTestServer(proc)) { + std::cerr << "cannot start test server, skipping..." << std::endl; + return; + } + + scy::smpl::Client::Options loptions; + loptions.host = SERVER_HOST; + loptions.port = SERVER_PORT; + loptions.user = "l"; + loptions.name = "Left"; + // loptions.token = "2NuMmyXw2YDuQfyPCKDO2Qtta"; + + scy::smpl::Client::Options roptions; + roptions.host = SERVER_HOST; + roptions.port = SERVER_PORT; + roptions.user = "r"; + roptions.name = "Right"; + // roptions.token = "2NuMmyXw2YDuQfyPCKDO2Qtta"; + + scy::TestClient lclient(loptions); + scy::TestClient rclient(roptions); + + lclient.connect(); + rclient.connect(); + + while (!lclient.completed() || !rclient.completed()) { + + // LDebug("waiting for test completion"); + scy::uv::runLoop(scy::uv::defaultLoop(), UV_RUN_ONCE); + + // // Connect the rclient when lclient is online + // if (lclient.client.isOnline() && + // rclient.client.stateEquals(sockio::ClientState::Closed)) + // rclient.connect(); + } + + lclient.check(); + rclient.check(); + }); + + // ========================================================================= + // Peer + // + scy_test::describe("peer", []() { + scy::smpl::Peer peer; + peer.setID("abc123"); + peer.setUser("testuser"); + peer.setName("Test User"); + peer.setType("client"); + peer.setHost("localhost"); + + expect(peer.id() == "abc123"); + expect(peer.user() == "testuser"); + expect(peer.name() == "Test User"); + expect(peer.type() == "client"); + expect(peer.host() == "localhost"); + expect(peer.valid()); + + // Address combines user|id + scy::smpl::Address addr = peer.address(); + expect(addr.user == "testuser"); + expect(addr.id == "abc123"); + }); + + scy_test::describe("peer from json", []() { + scy::json::value j; + j["id"] = "xyz"; + j["user"] = "bob"; + j["name"] = "Bob"; + j["type"] = "server"; + + scy::smpl::Peer peer(j); + expect(peer.id() == "xyz"); + expect(peer.user() == "bob"); + expect(peer.name() == "Bob"); + }); + + scy_test::describe("peer copy", []() { + scy::smpl::Peer p1; + p1.setID("id1"); + p1.setUser("user1"); + + scy::smpl::Peer p2(p1); + expect(p2.id() == "id1"); + expect(p2.user() == "user1"); + }); + + + // ========================================================================= + // Event + // + scy_test::describe("event", []() { + scy::smpl::Event event; + event.setName("click"); + event.setTime(1234567890.0); + + expect(event.name() == "click"); + expect(event.time() == 1234567890.0); + expect(event.valid()); + }); + + scy_test::describe("event from json", []() { + scy::json::value j; + j["type"] = "event"; + j["name"] = "hover"; + j["time"] = 42.0; + + scy::smpl::Event event(j); + expect(event.name() == "hover"); + expect(event.time() == 42.0); + }); + + + // ========================================================================= + // Command + // + scy_test::describe("command", []() { + scy::smpl::Command cmd; + cmd.setNode("audio.mute"); + cmd.setAction("toggle"); + + expect(cmd.node() == "audio.mute"); + expect(cmd.action() == "toggle"); + expect(cmd.valid()); + }); + + scy_test::describe("command from json", []() { + scy::json::value j; + j["type"] = "command"; + j["node"] = "video.play"; + j["action"] = "start"; + + scy::smpl::Command cmd(j); + expect(cmd.node() == "video.play"); + expect(cmd.action() == "start"); + }); + + + // ========================================================================= + // Presence + // + scy_test::describe("presence", []() { + scy::smpl::Presence pres; + expect(!pres.isProbe()); + + pres.setProbe(true); + expect(pres.isProbe()); + + pres.setProbe(false); + expect(!pres.isProbe()); + }); + + + // ========================================================================= + // Roster + // + scy_test::describe("roster", []() { + scy::smpl::Roster roster; + + auto peer1 = new scy::smpl::Peer; + peer1->setID("p1"); + peer1->setUser("alice"); + peer1->setHost("host1"); + + auto peer2 = new scy::smpl::Peer; + peer2->setID("p2"); + peer2->setUser("bob"); + peer2->setHost("host2"); + + roster.add("alice|p1", peer1); + roster.add("bob|p2", peer2); + + // getByHost + auto found = roster.getByHost("host1"); + expect(found != nullptr); + expect(found->user() == "alice"); + + expect(roster.getByHost("unknown") == nullptr); + }); + + + scy_test::runAll(); + +#if USE_SSL + scy::net::SSLManager::instance().shutdown(); +#endif + scy::Logger::destroy(); + return scy_test::finalize(); +} diff --git a/src/symple/tests/sympletests.h b/src/symple/tests/sympletests.h index 1ecb1d9dc..f50c317f4 100644 --- a/src/symple/tests/sympletests.h +++ b/src/symple/tests/sympletests.h @@ -1,16 +1,18 @@ -#ifndef SCY_Symple_Tests_H -#define SCY_Symple_Tests_H +#pragma once #include "scy/base.h" +#include "scy/filesystem.h" #include "scy/logger.h" +#include "scy/net/sslmanager.h" #include "scy/pipe.h" #include "scy/process.h" -#include "scy/filesystem.h" -#include "scy/net/sslmanager.h" #include "scy/symple/client.h" #include "scy/test.h" +#include +#include + #define SERVER_HOST "localhost" #define USE_SSL 0 @@ -63,7 +65,7 @@ class TestClient void connect() { - LInfo(user, ": connect") + LInfo(user, ": connect"); client.connect(); } @@ -90,14 +92,14 @@ class TestClient void onRecvPacket(IPacket& raw) { - LDebug("####### On raw packet: ", raw.className()) + LDebug("####### On raw packet: ", raw.className()); // Handle incoming raw packets here } void onRecvPresence(smpl::Presence& presence) { - LInfo(user, ": On presence: ", presence.dump(4)) + LInfo(user, ": On presence: ", presence.dump(4)); expect(presence.data("version").get() == "1.0.1"); if (user == "l") { @@ -113,14 +115,15 @@ class TestClient void onRecvMessage(smpl::Message& message) { - LInfo(user, ": On message: ", message.dump(4)) + LInfo(user, ": On message: ", message.dump(4)); // Handle incoming Symple messages here } void onClientAnnounce(const int& status) { - assert(status == 200); + if (status != 200) + throw std::runtime_error("Announce failed with status: " + std::to_string(status)); } void onClientStateChange(void*, sockio::ClientState& state, const sockio::ClientState& oldState) @@ -145,14 +148,14 @@ class TestClient // client.send(m, true); break; case sockio::ClientState::Error: - assert(0); + throw std::runtime_error("Client entered error state"); break; } } void onCreatePresence(smpl::Peer& peer) { - LInfo(user, ": Updating Client Data") + LInfo(user, ": Updating Client Data"); // Update the peer object to be broadcast with presence. // Any arbitrary data can be broadcast with presence. @@ -174,7 +177,7 @@ void setTestServerCwd(std::string& cwd) bool installTestServerSync() { bool success = false; - Process proc({ "npm", "install" }); + Process proc({"npm", "install"}); setTestServerCwd(proc.cwd); proc.onstdout = [](std::string line) { std::cout << "server npm stdout: " << line << std::endl; @@ -196,8 +199,7 @@ bool openTestServer(Process& proc, bool install = true) if (install) { try { installTestServerSync(); - } - catch (std::exception& exc) { + } catch (std::exception& exc) { // Sometimes this fails on windows, so swallow // and try to run the server even if npm fails } @@ -206,7 +208,7 @@ bool openTestServer(Process& proc, bool install = true) // Run the nodejs server bool running = false, exited = false; setTestServerCwd(proc.cwd); - proc.args = { "node", "server.js" }; + proc.args = {"node", "server.js"}; proc.onstdout = [&](std::string line) { std::cout << "server stdout: " << line << std::endl; if (line.find("listening") != std::string::npos) @@ -231,7 +233,4 @@ bool openTestServer(Process& proc, bool install = true) } // namespace scy -#endif // SCY_Symple_Tests_H - - /// @\} diff --git a/src/turn/CMakeLists.txt b/src/turn/CMakeLists.txt index 6654b87bb..5e2921089 100644 --- a/src/turn/CMakeLists.txt +++ b/src/turn/CMakeLists.txt @@ -1,5 +1,6 @@ -ask_build_sourcey_module(turn) -if(BUILD_MODULES OR (NOT BUILD_MODULES AND BUILD_MODULE_turn)) - set(turn_PRETTY_NAME TURN) - define_sourcey_module(turn base net stun crypto util) +if(HAVE_OPENSSL) + scy_add_module(turn + DEPENDS base net stun crypto + PRETTY_NAME TURN + ) endif() diff --git a/src/turn/include/scy/turn/client/client.h b/src/turn/include/scy/turn/client/client.h index 89ada037c..c6584ce1a 100644 --- a/src/turn/include/scy/turn/client/client.h +++ b/src/turn/include/scy/turn/client/client.h @@ -8,9 +8,7 @@ /// @addtogroup turn /// @{ - -#ifndef SCY_TURN_Client_H -#define SCY_TURN_Client_H +#pragma once #include "scy/net/udpsocket.h" @@ -85,7 +83,18 @@ struct ClientObserver }; -class TURN_API Client : public Stateful, protected IAllocation +/// Timer interval for client maintenance (30 seconds) +static constexpr std::int64_t kClientTimerInterval = 30 * 1000; + +/// Default client allocation lifetime (5 minutes, in milliseconds) +static constexpr std::int64_t kClientDefaultLifetime = 5 * 60 * 1000; + +/// Default client transaction timeout (10 seconds) +static constexpr long kClientDefaultTimeout = 10 * 1000; + + +class TURN_API Client : public Stateful + , protected IAllocation { public: struct Options @@ -105,9 +114,9 @@ class TURN_API Client : public Stateful, protected IAllocation username = util::randomString(4); password = util::randomString(22); // realm = "sourcey.com"; - lifetime = 5 * 60 * 1000; // 5 minutes - timeout = 10 * 1000; - timerInterval = 30 * 1000; // 30 seconds + lifetime = kClientDefaultLifetime; + timeout = kClientDefaultTimeout; + timerInterval = kClientTimerInterval; serverAddr = net::Address("127.0.0.1", 3478); } }; @@ -156,10 +165,10 @@ class TURN_API Client : public Stateful, protected IAllocation virtual bool sendAuthenticatedTransaction(stun::Transaction* transaction); virtual bool removeTransaction(stun::Transaction* transaction); - net::Address mappedAddress() const; - net::Address relayedAddress() const; + [[nodiscard]] net::Address mappedAddress() const; + [[nodiscard]] net::Address relayedAddress() const; - bool closed() const; + [[nodiscard]] bool closed() const; ClientObserver& observer(); Options& options(); @@ -167,9 +176,9 @@ class TURN_API Client : public Stateful, protected IAllocation protected: virtual void setError(const scy::Error& error); - virtual void onSocketConnect(net::Socket& socket); - virtual void onSocketRecv(net::Socket& socket, const MutableBuffer& buffer, const net::Address& peerAddress); - virtual void onSocketClose(net::Socket& socket); + virtual bool onSocketConnect(net::Socket& socket); + virtual bool onSocketRecv(net::Socket& socket, const MutableBuffer& buffer, const net::Address& peerAddress); + virtual bool onSocketClose(net::Socket& socket); virtual void onTransactionProgress(void* sender, TransactionState& state, const TransactionState&); virtual void onStateChange(ClientState& state, const ClientState& oldState); virtual void onTimer(); @@ -194,10 +203,8 @@ class TURN_API Client : public Stateful, protected IAllocation }; -} } // namespace scy::turn - - -#endif // SCY_TURN_Client_H +} // namespace turn +} // namespace scy /// @\} diff --git a/src/turn/include/scy/turn/client/tcpclient.h b/src/turn/include/scy/turn/client/tcpclient.h index b2228f195..78c249fd7 100644 --- a/src/turn/include/scy/turn/client/tcpclient.h +++ b/src/turn/include/scy/turn/client/tcpclient.h @@ -8,9 +8,7 @@ /// @addtogroup turn /// @{ - -#ifndef SCY_TURN_TCPClient_H -#define SCY_TURN_TCPClient_H +#pragma once #include "scy/collection.h" @@ -45,8 +43,8 @@ struct RelayConnectionBinding }; -typedef KVCollection ConnectionManager; -typedef ConnectionManager::Map ConnectionManagerMap; +using ConnectionManager = KVCollection; +using ConnectionManagerMap = ConnectionManager::Map; class TURN_API TCPClient : public Client @@ -71,10 +69,10 @@ class TURN_API TCPClient : public Client virtual bool createAndBindConnection(uint32_t connectionID, const net::Address& peerAddress); // virtual void onRelayConnectionStateChange(void* sender, Net::SocketState& state, const Net::SocketState& oldState); - virtual void onRelayConnectionConnect(net::Socket& socket); - virtual void onRelayDataReceived(net::Socket& socket, const MutableBuffer& buffer, const net::Address& peerAddress); - virtual void onRelayConnectionError(net::Socket& socket, const Error& error); - virtual void onRelayConnectionClosed(net::Socket& socket); + virtual bool onRelayConnectionConnect(net::Socket& socket); + virtual bool onRelayDataReceived(net::Socket& socket, const MutableBuffer& buffer, const net::Address& peerAddress); + virtual bool onRelayConnectionError(net::Socket& socket, const Error& error); + virtual bool onRelayConnectionClosed(net::Socket& socket); void freeConnection(const net::Address& peerAddress); @@ -89,10 +87,8 @@ class TURN_API TCPClient : public Client }; -} } // namespace scy::turn - - -#endif // SCY_TURN_TCPClient_H +} // namespace turn +} // namespace scy /// @\} diff --git a/src/turn/include/scy/turn/client/udpclient.h b/src/turn/include/scy/turn/client/udpclient.h index 33821210c..2612a087e 100644 --- a/src/turn/include/scy/turn/client/udpclient.h +++ b/src/turn/include/scy/turn/client/udpclient.h @@ -8,9 +8,7 @@ /// @addtogroup turn /// @{ - -#ifndef SCY_TURN_UDPClient_H -#define SCY_TURN_UDPClient_H +#pragma once #include "scy/net/udpsocket.h" @@ -19,7 +17,6 @@ #include "scy/turn/client/client.h" #include "scy/turn/iallocation.h" #include "scy/turn/turn.h" -#include "scy/turn/turn.h" #include @@ -34,11 +31,8 @@ class TURN_API UDPClient : public Client UDPClient(ClientObserver& observer, const Options& options = Options()); virtual ~UDPClient(); }; -} -} // namespace scy::turn - - -#endif // SCY_TURN_Client_H +} // namespace turn +} // namespace scy /// @\} diff --git a/src/turn/include/scy/turn/fivetuple.h b/src/turn/include/scy/turn/fivetuple.h index cc394137e..ec1d94707 100644 --- a/src/turn/include/scy/turn/fivetuple.h +++ b/src/turn/include/scy/turn/fivetuple.h @@ -8,13 +8,11 @@ /// @addtogroup turn /// @{ +#pragma once -#ifndef SCY_TURN_FiveTuple_H -#define SCY_TURN_FiveTuple_H - -#include "scy/turn/turn.h" #include "scy/net/socket.h" +#include "scy/turn/turn.h" #include @@ -71,9 +69,9 @@ class TURN_API FiveTuple net::TransportType transport); FiveTuple(const FiveTuple& r); - const net::Address& remote() const { return _remote; } - const net::Address& local() const { return _local; } - const net::TransportType& transport() const { return _transport; } + [[nodiscard]] const net::Address& remote() const { return _remote; } + [[nodiscard]] const net::Address& local() const { return _local; } + [[nodiscard]] const net::TransportType& transport() const { return _transport; } void remote(const net::Address& remote) { _remote = remote; } void local(const net::Address& local) { _local = local; } @@ -85,7 +83,7 @@ class TURN_API FiveTuple bool operator==(const FiveTuple& r) const; bool operator<(const FiveTuple& r) const; - std::string toString() const; + [[nodiscard]] std::string toString() const; friend std::ostream& operator<<(std::ostream& stream, const FiveTuple& tuple) @@ -105,7 +103,4 @@ class TURN_API FiveTuple } // namespace scy -#endif // SCY_TURN_FiveTuple_H - - /// @\} diff --git a/src/turn/include/scy/turn/iallocation.h b/src/turn/include/scy/turn/iallocation.h index c5ab52951..abeb3303e 100644 --- a/src/turn/include/scy/turn/iallocation.h +++ b/src/turn/include/scy/turn/iallocation.h @@ -8,25 +8,27 @@ /// @addtogroup turn /// @{ - -#ifndef SCY_TURN_IAllocation_H -#define SCY_TURN_IAllocation_H +#pragma once #include "scy/logger.h" -#include #include "scy/net/address.h" #include "scy/timer.h" #include "scy/turn/fivetuple.h" #include "scy/turn/permission.h" #include "scy/turn/turn.h" #include "scy/turn/types.h" +#include namespace scy { namespace turn { +/// Default allocation lifetime: 10 minutes (in milliseconds) +static constexpr std::int64_t kDefaultAllocationLifetime = 10 * 60 * 1000; + + /// All TURN operations revolve around allocations, and all TURN messages /// are associated with an allocation. An allocation conceptually /// consists of the following state data: @@ -75,9 +77,14 @@ class TURN_API IAllocation public: IAllocation(const FiveTuple& tuple = FiveTuple(), const std::string& username = "", - std::int64_t lifetime = 10 * 60 * 1000); + std::int64_t lifetime = kDefaultAllocationLifetime); virtual ~IAllocation(); + IAllocation(const IAllocation&) = delete; + IAllocation& operator=(const IAllocation&) = delete; + IAllocation(IAllocation&&) = delete; + IAllocation& operator=(IAllocation&&) = delete; + /// Updates the allocation's internal timeout and bandwidth /// usage each time the allocation is used. virtual void updateUsage(std::int64_t numBytes = 0); @@ -90,7 +97,7 @@ class TURN_API IAllocation /// Returns true if the allocation is expired ie. is timed /// out or the bandwidth limit has been reached. - virtual bool expired() const; + [[nodiscard]] virtual bool expired() const; /// Returns true if the allocation's deleted flag is set /// and or if the allocation has expired. @@ -98,19 +105,19 @@ class TURN_API IAllocation /// This signifies that the allocation is ready to be /// destroyed via async garbage collection. /// See Server::onTimer() and Client::onTimer() - virtual bool deleted() const; + [[nodiscard]] virtual bool deleted() const; - virtual std::int64_t bandwidthLimit() const; - virtual std::int64_t bandwidthUsed() const; - virtual std::int64_t bandwidthRemaining() const; - virtual std::int64_t timeRemaining() const; + [[nodiscard]] virtual std::int64_t bandwidthLimit() const; + [[nodiscard]] virtual std::int64_t bandwidthUsed() const; + [[nodiscard]] virtual std::int64_t bandwidthRemaining() const; + [[nodiscard]] virtual std::int64_t timeRemaining() const; virtual FiveTuple& tuple(); - virtual std::string username() const; - virtual std::int64_t lifetime() const; - virtual PermissionList permissions() const; + [[nodiscard]] virtual std::string username() const; + [[nodiscard]] virtual std::int64_t lifetime() const; + [[nodiscard]] virtual PermissionList permissions() const; - virtual net::Address relayedAddress() const = 0; + [[nodiscard]] virtual net::Address relayedAddress() const = 0; virtual void addPermission(const std::string& ip); virtual void addPermissions(const IPList& ips); @@ -118,7 +125,7 @@ class TURN_API IAllocation virtual void removeAllPermissions(); virtual void removeExpiredPermissions(); // virtual void refreshAllPermissions(); - virtual bool hasPermission(const std::string& peerIP); + [[nodiscard]] virtual bool hasPermission(const std::string& peerIP); virtual void print(std::ostream& os) const { @@ -133,7 +140,7 @@ class TURN_API IAllocation } protected: - // mutable std::mutex _mutex; + mutable std::mutex _mutex; FiveTuple _tuple; std::string _username; PermissionList _permissions; @@ -150,7 +157,4 @@ class TURN_API IAllocation } // namespace scy -#endif // SCY_TURN_IAllocation_H - - /// @\} diff --git a/src/turn/include/scy/turn/permission.h b/src/turn/include/scy/turn/permission.h index ff561cd2c..20645300d 100644 --- a/src/turn/include/scy/turn/permission.h +++ b/src/turn/include/scy/turn/permission.h @@ -8,14 +8,12 @@ /// @addtogroup turn /// @{ +#pragma once -#ifndef SCY_TURN_Permission_H -#define SCY_TURN_Permission_H - -#include "scy/turn/fivetuple.h" #include "scy/net/address.h" -#include "scy/util/timeout.h" +#include "scy/timeout.h" +#include "scy/turn/fivetuple.h" #include #include @@ -26,7 +24,7 @@ namespace turn { /// Permission Lifetime MUST be 300 seconds (= 5 minutes). -const int PERMISSION_LIFETIME = 3 * 60 * 1000; +static constexpr int PERMISSION_LIFETIME = 5 * 60 * 1000; /// TURN permission for a user session @@ -48,14 +46,11 @@ struct Permission }; -typedef std::vector PermissionList; +using PermissionList = std::vector; } // namespace turn } // namespace scy -#endif // SCY_TURN_Permission_H - - /// @\} diff --git a/src/turn/include/scy/turn/server/server.h b/src/turn/include/scy/turn/server/server.h index ac8d189a8..12e1ab05e 100644 --- a/src/turn/include/scy/turn/server/server.h +++ b/src/turn/include/scy/turn/server/server.h @@ -9,9 +9,7 @@ /// @addtogroup turn /// @{ - -#ifndef SCY_TURN_Server_H -#define SCY_TURN_Server_H +#pragma once #include "scy/net/tcpsocket.h" @@ -23,10 +21,10 @@ #include "scy/turn/server/udpallocation.h" #include "scy/turn/turn.h" - #include -#include #include +#include +#include #include @@ -34,6 +32,22 @@ namespace scy { namespace turn { +/// Default server allocation lifetime (2 minutes, in milliseconds) +static constexpr uint32_t kServerDefaultLifetime = 2 * 60 * 1000; + +/// Maximum server allocation lifetime (15 minutes, in milliseconds) +static constexpr uint32_t kServerMaxLifetime = 15 * 60 * 1000; + +/// Maximum number of permissions per allocation +static constexpr int kServerMaxPermissions = 10; + +/// Server timer interval (10 seconds) +static constexpr int kServerTimerInterval = 10 * 1000; + +/// Early media buffer size +static constexpr int kServerEarlyMediaBufferSize = 8192; + + /// Configuration options for the TURN server. struct ServerOptions { @@ -47,7 +61,7 @@ struct ServerOptions int earlyMediaBufferSize; net::Address listenAddr; ///< The TCP and UDP bind() address - std::string externalIP; ///< The external public facing IP address of the server + std::string externalIP; ///< The external public facing IP address of the server bool enableTCP; bool enableUDP; @@ -58,11 +72,11 @@ struct ServerOptions realm = "sourcey.com"; listenAddr = net::Address("0.0.0.0", 3478); externalIP = ""; - allocationDefaultLifetime = 2 * 60 * 1000; - allocationMaxLifetime = 15 * 60 * 1000; - allocationMaxPermissions = 10; - timerInterval = 10 * 1000; - earlyMediaBufferSize = 8192; + allocationDefaultLifetime = kServerDefaultLifetime; + allocationMaxLifetime = kServerMaxLifetime; + allocationMaxPermissions = kServerMaxPermissions; + timerInterval = kServerTimerInterval; + earlyMediaBufferSize = kServerEarlyMediaBufferSize; enableTCP = true; enableUDP = true; } @@ -96,7 +110,7 @@ struct ServerObserver }; -typedef std::map ServerAllocationMap; +using ServerAllocationMap = std::map>; /// TURN server rfc5766 implementation @@ -118,12 +132,15 @@ class TURN_API Server void respond(Request& request, stun::Message& response); void respondError(Request& request, int errorCode, const char* errorDesc); - ServerAllocationMap allocations() const; - void addAllocation(ServerAllocation* alloc); + /// Returns a snapshot copy of the allocation map for safe iteration. + /// Callers receive raw pointers that are valid only while the + /// corresponding unique_ptr in _allocations is alive. + std::map allocations() const; + void addAllocation(std::unique_ptr alloc); void removeAllocation(ServerAllocation* alloc); - ServerAllocation* getAllocation(const FiveTuple& tuple); - TCPAllocation* getTCPAllocation(const uint32_t& connectionID); - net::TCPSocket::Ptr getTCPSocket(const net::Address& remoteAddr); + [[nodiscard]] ServerAllocation* getAllocation(const FiveTuple& tuple); + [[nodiscard]] TCPAllocation* getTCPAllocation(const uint32_t& connectionID); + [[nodiscard]] net::TCPSocket::Ptr getTCPSocket(const net::Address& remoteAddr); void releaseTCPSocket(const net::Socket& socket); ServerObserver& observer(); @@ -133,12 +150,13 @@ class TURN_API Server Timer& timer(); void onTCPAcceptConnection(const net::TCPSocket::Ptr& sock); - void onTCPSocketClosed(net::Socket& socket); - void onSocketRecv(net::Socket& socket, const MutableBuffer& buffer, + bool onTCPSocketClosed(net::Socket& socket); + bool onSocketRecv(net::Socket& socket, const MutableBuffer& buffer, const net::Address& peerAddress); void onTimer(); private: + mutable std::mutex _mutex; ServerObserver& _observer; ServerOptions _options; net::SocketEmitter _udpSocket; // net::UDPSocket @@ -149,10 +167,8 @@ class TURN_API Server }; -} } // namespace scy::turn - - -#endif // SCY_TURN_Server_H +} // namespace turn +} // namespace scy /// @\} diff --git a/src/turn/include/scy/turn/server/serverallocation.h b/src/turn/include/scy/turn/server/serverallocation.h index e19e9834b..f5de3bf7c 100644 --- a/src/turn/include/scy/turn/server/serverallocation.h +++ b/src/turn/include/scy/turn/server/serverallocation.h @@ -8,9 +8,7 @@ /// @addtogroup turn /// @{ - -#ifndef SCY_TURN_ServerAllocation_H -#define SCY_TURN_ServerAllocation_H +#pragma once #include "scy/turn/fivetuple.h" @@ -29,6 +27,7 @@ class TURN_API ServerAllocation : public IAllocation public: ServerAllocation(Server& server, const FiveTuple& tuple, const std::string& username, std::int64_t lifetime); + virtual ~ServerAllocation(); virtual bool handleRequest(Request& request); virtual void handleRefreshRequest(Request& request); @@ -37,29 +36,31 @@ class TURN_API ServerAllocation : public IAllocation /// Asynchronous timer callback for updating the allocation /// permissions and state etc. /// If this call returns false the allocation will be deleted. - virtual bool onTimer(); + [[nodiscard]] virtual bool onTimer(); - virtual std::int64_t timeRemaining() const; - virtual std::int64_t maxTimeRemaining() const; + [[nodiscard]] virtual std::int64_t timeRemaining() const; + [[nodiscard]] virtual std::int64_t maxTimeRemaining() const; virtual Server& server(); virtual void print(std::ostream& os) const; -protected: - /// IMPORTANT: The destructor should never be called directly - /// as the allocation is deleted via the timer callback. - /// See onTimer() - virtual ~ServerAllocation(); + /// Returns true if the refresh request set lifetime to 0, + /// signaling the parent Server to delete this allocation. + [[nodiscard]] bool refreshDeleteRequested() const { return _refreshDeleteRequested; } +protected: friend class Server; uint32_t _maxLifetime; Server& _server; + bool _refreshDeleteRequested = false; private: /// NonCopyable and NonMovable ServerAllocation(const ServerAllocation&) = delete; ServerAllocation& operator=(const ServerAllocation&) = delete; + ServerAllocation(ServerAllocation&&) = delete; + ServerAllocation& operator=(ServerAllocation&&) = delete; }; @@ -67,7 +68,4 @@ class TURN_API ServerAllocation : public IAllocation } // namespace scy -#endif // SCY_TURN_ServerAllocation_H - - /// @\} diff --git a/src/turn/include/scy/turn/server/tcpallocation.h b/src/turn/include/scy/turn/server/tcpallocation.h index 8a8c7b304..47662a466 100644 --- a/src/turn/include/scy/turn/server/tcpallocation.h +++ b/src/turn/include/scy/turn/server/tcpallocation.h @@ -8,9 +8,7 @@ /// @addtogroup turn /// @{ - -#ifndef SCY_TURN_SERVER_TCPAllocation_H -#define SCY_TURN_SERVER_TCPAllocation_H +#pragma once #include "scy/collection.h" @@ -26,8 +24,7 @@ namespace turn { class TURN_API Server; -typedef PointerCollection - TCPConnectionPairMap; +using TCPConnectionPairMap = PointerCollection; class TURN_API TCPAllocation : public ServerAllocation @@ -48,7 +45,7 @@ class TURN_API TCPAllocation : public ServerAllocation int sendToControl(stun::Message& message); net::TCPSocket& control(); - net::Address relayedAddress() const; + [[nodiscard]] net::Address relayedAddress() const; TCPConnectionPairMap& pairs(); bool onTimer(); @@ -58,19 +55,17 @@ class TURN_API TCPAllocation : public ServerAllocation /// Callback for handling controll connection destruction. /// The allocation will be deleted. - void onControlClosed(net::Socket& socket); + bool onControlClosed(net::Socket& socket); protected: - net::SocketEmitter _control; // net::TCPSocket + net::SocketEmitter _control; // net::TCPSocket net::SocketEmitter _acceptor; // net::TCPSocket TCPConnectionPairMap _pairs; }; -} } // namespace scy::turn - - -#endif // SCY_TURN_SERVER_TCPAllocation_H +} // namespace turn +} // namespace scy /// @\} diff --git a/src/turn/include/scy/turn/server/tcpconnectionpair.h b/src/turn/include/scy/turn/server/tcpconnectionpair.h index 102899101..6e61e3c48 100644 --- a/src/turn/include/scy/turn/server/tcpconnectionpair.h +++ b/src/turn/include/scy/turn/server/tcpconnectionpair.h @@ -8,17 +8,15 @@ /// @addtogroup turn /// @{ +#pragma once -#ifndef SCY_TURN_TCPClientConnection_H -#define SCY_TURN_TCPClientConnection_H - -#include "scy/turn/turn.h" -#include "scy/stun/message.h" -#include "scy/net/tcpsocket.h" -#include "scy/net/socketemitter.h" #include "scy/collection.h" -#include "scy/util/timeout.h" +#include "scy/net/socketemitter.h" +#include "scy/net/tcpsocket.h" +#include "scy/stun/message.h" +#include "scy/timeout.h" +#include "scy/turn/turn.h" namespace scy { @@ -27,6 +25,9 @@ namespace turn { class TURN_API TCPAllocation; +/// ConnectionBind request timeout (30 seconds, in milliseconds) +static constexpr int kConnectionBindTimeout = 30 * 1000; + class TURN_API TCPConnectionPair { @@ -46,19 +47,19 @@ class TURN_API TCPConnectionPair void setClientSocket(const net::TCPSocket::Ptr& socket); /// Connection success callback for Connect request. - void onPeerConnectSuccess(net::Socket& socket); + bool onPeerConnectSuccess(net::Socket& socket); /// Connection error callback for Connect request. - void onPeerConnectError(net::Socket& socket, const Error& error); + bool onPeerConnectError(net::Socket& socket, const Error& error); - void onClientDataReceived(net::Socket& socket, const MutableBuffer& buffer, + bool onClientDataReceived(net::Socket& socket, const MutableBuffer& buffer, const net::Address& peerAddress); - void onPeerDataReceived(net::Socket& socket, const MutableBuffer& buffer, + bool onPeerDataReceived(net::Socket& socket, const MutableBuffer& buffer, const net::Address& peerAddress); /// Callback for handing either client or peer connections /// which result in the destruction of the TCPConnectionPair. - void onConnectionClosed(net::Socket& socket); + bool onConnectionClosed(net::Socket& socket); /// Starts the ConnectionBind request timeout. /// @@ -67,6 +68,10 @@ class TURN_API TCPConnectionPair /// connection MUST be closed. void startTimeout(); + /// Signals the parent allocation to handle deletion instead + /// of destroying ourselves directly. + void requestDeletion(); + TCPAllocation& allocation; /// The client socket, nullptr to start. @@ -76,7 +81,7 @@ class TURN_API TCPConnectionPair net::SocketEmitter peer; // net::TCPSocket /// Return true if the peer `ConnectionBind` request timed out. - bool expired() const; + [[nodiscard]] bool expired() const; /// Stores early peer > client data. Buffer earlyPeerData; @@ -87,6 +92,9 @@ class TURN_API TCPConnectionPair /// True when p2p relay is flowing. bool isDataConnection; + /// True when this pair has been flagged for deletion. + bool pendingDelete = false; + /// The ConnectionBind request timeout counter. Timeout timeout; @@ -96,6 +104,8 @@ class TURN_API TCPConnectionPair /// NonCopyable and NonMovable TCPConnectionPair(const TCPConnectionPair&) = delete; TCPConnectionPair& operator=(const TCPConnectionPair&) = delete; + TCPConnectionPair(TCPConnectionPair&&) = delete; + TCPConnectionPair& operator=(TCPConnectionPair&&) = delete; }; @@ -103,7 +113,4 @@ class TURN_API TCPConnectionPair } // namespace scy -#endif // SCY_TURN_TCPClientConnection_H - - /// @\} diff --git a/src/turn/include/scy/turn/server/udpallocation.h b/src/turn/include/scy/turn/server/udpallocation.h index 279a3e4b8..590127170 100644 --- a/src/turn/include/scy/turn/server/udpallocation.h +++ b/src/turn/include/scy/turn/server/udpallocation.h @@ -8,9 +8,7 @@ /// @addtogroup turn /// @{ - -#ifndef SCY_TURN_SERVER_UDPAllocation_H -#define SCY_TURN_SERVER_UDPAllocation_H +#pragma once #include "scy/net/packetsocket.h" @@ -35,7 +33,7 @@ class TURN_API UDPAllocation : public ServerAllocation virtual ~UDPAllocation(); // void onPacketReceived(void* sender, RawPacket& packet); - void onPeerDataReceived(net::Socket& socket, const MutableBuffer& buffer, + bool onPeerDataReceived(net::Socket& socket, const MutableBuffer& buffer, const net::Address& peerAddress); bool handleRequest(Request& request); @@ -44,16 +42,14 @@ class TURN_API UDPAllocation : public ServerAllocation ssize_t send(const char* data, size_t size, const net::Address& peerAddress); - net::Address relayedAddress() const; + [[nodiscard]] net::Address relayedAddress() const; private: net::SocketEmitter _relaySocket; // net::UDPSocket }; -} -} // namespace scy::turn - -#endif // SCY_TURN_SERVER_UDPAllocation_H +} // namespace turn +} // namespace scy /// @\} diff --git a/src/turn/include/scy/turn/turn.h b/src/turn/include/scy/turn/turn.h index 640eac527..78ab9379b 100644 --- a/src/turn/include/scy/turn/turn.h +++ b/src/turn/include/scy/turn/turn.h @@ -9,24 +9,18 @@ /// /// The `turn` module contains TURN (rfc5766) client and server implementations. - -#ifndef SCY_TURN_H -#define SCY_TURN_H - +#pragma once // Shared library exports #if defined(SCY_WIN) && defined(SCY_SHARED_LIBRARY) - #if defined(TURN_EXPORTS) - #define TURN_API __declspec(dllexport) - #else - #define TURN_API __declspec(dllimport) - #endif +#if defined(TURN_EXPORTS) +#define TURN_API __declspec(dllexport) #else - #define TURN_API // nothing +#define TURN_API __declspec(dllimport) #endif - - +#else +#define TURN_API // nothing #endif diff --git a/src/turn/include/scy/turn/types.h b/src/turn/include/scy/turn/types.h index ab87a3f56..aa96b5cf6 100644 --- a/src/turn/include/scy/turn/types.h +++ b/src/turn/include/scy/turn/types.h @@ -8,9 +8,7 @@ /// @addtogroup turn /// @{ - -#ifndef SCY_TURN_Types_H -#define SCY_TURN_Types_H +#pragma once #include "scy/net/address.h" @@ -23,11 +21,31 @@ namespace scy { namespace turn { -const int CLIENT_SOCK_BUF_SIZE = 65536; -const int SERVER_SOCK_BUF_SIZE = CLIENT_SOCK_BUF_SIZE * 32; +static constexpr int CLIENT_SOCK_BUF_SIZE = 65536; +static constexpr int SERVER_SOCK_BUF_SIZE = CLIENT_SOCK_BUF_SIZE * 32; + +/// TURN protocol numbers +static constexpr uint8_t kProtocolUDP = 17; +static constexpr uint8_t kProtocolTCP = 6; + +/// TURN/STUN error codes used in this module +static constexpr int kErrorTryAlternate = 300; +static constexpr int kErrorBadRequest = 400; +static constexpr int kErrorNotAuthorized = 401; +static constexpr int kErrorForbidden = 403; +static constexpr int kErrorUnknownAttribute = 420; +static constexpr int kErrorUnsupportedTransport = 442; +static constexpr int kErrorAllocationMismatch = 437; +static constexpr int kErrorStaleNonce = 438; +static constexpr int kErrorWrongCredentials = 441; +static constexpr int kErrorConnectionAlreadyExists = 446; +static constexpr int kErrorConnectionTimeoutOrFailure = 447; +static constexpr int kErrorAllocationQuotaReached = 486; +static constexpr int kErrorInsufficientCapacity = 508; +static constexpr int kErrorOperationNotSupported = 600; -enum AuthenticationState +enum class AuthenticationState { Authenticating = 1, Authorized = 2, @@ -56,14 +74,11 @@ class TURN_API Request : public stun::Message }; -typedef std::vector IPList; +using IPList = std::vector; } // namespace turn } // namespace scy -#endif // SCY_TURN_Types_H - - /// @\} diff --git a/src/turn/samples/CMakeLists.txt b/src/turn/samples/CMakeLists.txt index 984ff6d10..36878ee26 100644 --- a/src/turn/samples/CMakeLists.txt +++ b/src/turn/samples/CMakeLists.txt @@ -1,10 +1 @@ -# ---------------------------------------------------------------------------- -# CMake file for samples. See root CMakeLists.txt -# -# ---------------------------------------------------------------------------- - -if(BUILD_ALPHA) - add_subdirectory(turnmediaprovider) -endif() add_subdirectory(turnserver) - diff --git a/src/turn/samples/turnmediaprovider/CMakeLists.txt b/src/turn/samples/turnmediaprovider/CMakeLists.txt index da21687e6..8b3d74468 100644 --- a/src/turn/samples/turnmediaprovider/CMakeLists.txt +++ b/src/turn/samples/turnmediaprovider/CMakeLists.txt @@ -1,8 +1,2 @@ -# include_dependency(SSL REQUIRED) -# include_dependency(FFmpeg REQUIRED) -# include_dependency(OpenCV REQUIRED) -# include_dependency(RtAudio REQUIRED) -# include_dependency(JsonCpp) -# include_dependency(LibUV REQUIRED) - -define_sourcey_module_sample(turnmediaprovider base net turn http uv media) +# Legacy sample - depends on modules that may not exist (uv, media) +# scy_add_sample(turnmediaprovider DEPENDS base net turn http) diff --git a/src/turn/samples/turnmediaprovider/turnmediaprovider.cpp b/src/turn/samples/turnmediaprovider/turnmediaprovider.cpp index c84627051..f5418e0a1 100644 --- a/src/turn/samples/turnmediaprovider/turnmediaprovider.cpp +++ b/src/turn/samples/turnmediaprovider/turnmediaprovider.cpp @@ -57,8 +57,7 @@ Format MP311000 = Format("MP3", "mp3", VideoCodec(), AudioCodec("MP3", "libmp3lame", 1, 11000, 16000)); Format MP348000 = - Format("MP3", "mp3", VideoCodec(), AudioCodec("MP3", "libmp3lame", 2, 48000, - 128000, "s16p")); //, "s16p") + Format("MP3", "mp3", VideoCodec(), AudioCodec("MP3", "libmp3lame", 2, 48000, 128000, "s16p")); //, "s16p") Format FLVNoAudio = Format("FLV", "flv", VideoCodec("FLV", "flv", 320, 240)); //, 6, 9000, 64000 @@ -178,7 +177,8 @@ class TURNMediaProvider : public Scy::TURN::TCPClientObserver LogDebug() << "[TURNMediaProvider: " << this << "] Ltate Changed: "(state.toString(), ) - switch (state.id()) { + switch (state.id()) + { case TURN::ClientState::Waiting: break; case TURN::ClientState::Allocating: @@ -248,7 +248,7 @@ class TURNMediaProvider : public Scy::TURN::TCPClientObserver } catch (std::exception /*Exception*/& exc) { LogError() << "[TURNMediaProvider: " << this << "] Lend Error: "(exc.displayText(), ) - terminate(); + terminate(); } } }; @@ -374,7 +374,7 @@ class RelayAddressService : public TCPService int main(int argc, char** argv) { - Logger::instance().add(new ConsoleChannel("debug", STraceevel)); + Logger::instance().add(std::make_unique("debug", STraceevel)); // MediaFactory::initialize(); // MediaFactory::instance()->loadVideo(); diff --git a/src/turn/samples/turnserver/CMakeLists.txt b/src/turn/samples/turnserver/CMakeLists.txt index 6091ce083..6da44136e 100644 --- a/src/turn/samples/turnserver/CMakeLists.txt +++ b/src/turn/samples/turnserver/CMakeLists.txt @@ -1 +1 @@ -define_sourcey_module_sample(turnserver stun turn net base crypto) +scy_add_sample(turnserver DEPENDS stun turn net base crypto) diff --git a/src/turn/samples/turnserver/turnserver.cpp b/src/turn/samples/turnserver/turnserver.cpp index f280d7b94..1453b89bb 100644 --- a/src/turn/samples/turnserver/turnserver.cpp +++ b/src/turn/samples/turnserver/turnserver.cpp @@ -38,7 +38,7 @@ class RelayServer : public ServerObserver virtual AuthenticationState authenticateRequest(Server*, Request& request) { - LDebug("Authenticating: ", request.transactionID()) + LDebug("Authenticating: ", request.transactionID()); // The authentication information (e.g., username, password, realm, and // nonce) is used to both verify subsequent requests and to compute the @@ -57,7 +57,7 @@ class RelayServer : public ServerObserver // authentication and message integrity for them. if (request.methodType() == stun::Message::SendIndication || request.methodType() == stun::Message::Binding) - return Authorized; + return AuthenticationState::Authorized; // The initial packet from the client does not include the USERNAME, // REALM, NONCE, @@ -69,8 +69,8 @@ class RelayServer : public ServerObserver auto nonceAttr = request.get(); auto integrityAttr = request.get(); if (!usernameAttr || !realmAttr || !nonceAttr || !integrityAttr) { - LDebug("Authenticating: Unauthorized STUN Request") - return turn::NotAuthorized; + LDebug("Authenticating: Unauthorized STUN Request"); + return turn::AuthenticationState::NotAuthorized; } // Determine authentication status and return either Authorized, @@ -85,22 +85,22 @@ class RelayServer : public ServerObserver << ", key=" << request.hash << endl; if (integrityAttr->verifyHmac(request.hash)) - return turn::Authorized; - return turn::NotAuthorized; + return turn::AuthenticationState::Authorized; + return turn::AuthenticationState::NotAuthorized; #else // Since no authentication is required we just return Authorized. - return turn::Authorized; + return turn::AuthenticationState::Authorized; #endif } virtual void onServerAllocationCreated(Server*, IAllocation* alloc) { - LDebug("Allocation Created") + LDebug("Allocation Created"); } virtual void onServerAllocationRemoved(Server*, IAllocation* alloc) { - LDebug("Allocation Removed") + LDebug("Allocation Removed"); } }; @@ -111,8 +111,8 @@ int main(void) _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); #endif - Logger::instance().add(new ConsoleChannel("debug", Level::Trace)); - Logger::instance().setWriter(new AsyncLogWriter); + Logger::instance().add(std::make_unique("debug", Level::Trace)); + Logger::instance().setWriter(std::make_unique()); { Application app; { @@ -130,7 +130,8 @@ int main(void) srv.start(); app.waitForShutdown([](void* opaque) { reinterpret_cast(opaque)->server.stop(); - }, &srv); + }, + &srv); } } Logger::destroy(); diff --git a/src/turn/samples/turnserver/turnserver.h b/src/turn/samples/turnserver/turnserver.h index 5f0f93271..83697de83 100644 --- a/src/turn/samples/turnserver/turnserver.h +++ b/src/turn/samples/turnserver/turnserver.h @@ -4,85 +4,5 @@ #include "scy/turn/server/server.h" -#include - - -/* -#include "scy/application.h" -#include "scy/logger.h" -#include "scy/polymorphic.h" -#include "scy/util.h" -////#include "scy/net/reactor.h" - -#include "Poco/Path.h" -#include "Poco/Util/HelpFormatter.h" -#include "Poco/Util/Option.h" -#include "Poco/Util/OptionSet.h" -#include "Poco/Util/ServerApplication.h" - - -#define SERVER_SOFTWARE "Sourcey STUN/TURN Server [rfc5766]" -#define SERVER_REALM "sourcey.com" -#define SERVER_HOST "127.0.0.1" -#define SERVER_PORT 3478 -#define ALLOCATION_DEFAULT_LIFETIME 1 * 60 * 1000 // 1 min -#define ALLOCATION_MAX_LIFETIME 15 * 60 * 1000 // 15 min - - -class TURNServer: public turn::ServerObserver, public Polymorphic, public -Poco::util::ServerApplication -{ - -namespace scy { -namespace turn { - - -#define SERVER_SOFTWARE "Sourcey STUN/TURN Server [rfc5766]" -#define SERVER_REALM "sourcey.com" -#define SERVER_HOST "127.0.0.1" -#define SERVER_PORT 3478 -#define ALLOCATION_DEFAULT_LIFETIME 1 * 60 * 1000 // 1 min -#define ALLOCATION_MAX_LIFETIME 15 * 60 * 1000 // 15 min - - -class TURNServer: public turn::ServerObserver, public Polymorphic, public -Poco::util::ServerApplication -{ -public: - TURNServer(); - ~TURNServer(); - - void defineOptions(Poco::util::OptionSet& options); - void handleCommand(const std::string& name, const std::string& value); - void displayHelp(); - - int main(const std::vector& args); - - void onServerAllocationCreated(Server* server, IAllocation* alloc); - void onServerAllocationRemoving(Server* server, IAllocation* alloc); - - AuthenticationState authenticateRequest(Server* server, Request& request); - - virtual const char* className() const { return "TURNServer"; } - -private: - mutable Poco::Mutex _mutex; - - //Runner* _runner; - //Net::Reactor* _reactor; - turn::Server* _server; - turn::ServerOptions _options; - bool _helpRequested; -}; - - - -} // namespace turn -} // namespace scy -*/ - #endif // SCY_TURNServer_H - - -/// @\} diff --git a/src/turn/src/client/client.cpp b/src/turn/src/client/client.cpp index feb8b085b..689993395 100644 --- a/src/turn/src/client/client.cpp +++ b/src/turn/src/client/client.cpp @@ -18,11 +18,8 @@ #include "scy/net/udpsocket.h" #include -#include #include - - -using namespace std; +#include namespace scy { @@ -39,24 +36,23 @@ Client::Client(ClientObserver& observer, const Options& options, const net::Sock Client::~Client() { - LTrace("Destroy") + LTrace("Destroy"); shutdown(); - // assert(_socket->/*base().*/refCount() == 1); - // assert(closed()); } void Client::initiate() { - LDebug("TURN client connecting to ", _options.serverAddr) + LDebug("TURN client connecting to ", _options.serverAddr); - assert(!_permissions.empty() && "must set permissions"); - assert(_socket.impl && "must set socket"); + if (_permissions.empty()) + throw std::runtime_error("permissions not set before initiating TURN client"); + if (!_socket.impl) + throw std::runtime_error("socket not set before initiating TURN client"); auto udpSocket = dynamic_cast(_socket.impl.get()); if (udpSocket) { udpSocket->bind(net::Address("0.0.0.0", 0)); - // udpSocket->setBroadcast(true); } _socket.Recv += slot(this, &Client::onSocketRecv, -1, -1); @@ -71,7 +67,7 @@ void Client::shutdown() _timer.stop(); for (auto it = _transactions.begin(); it != _transactions.end();) { - LTrace("Shutdown base: Delete transaction: ", *it) + LTrace("Shutdown base: Delete transaction: ", *it); (*it)->StateChange -= slot(this, &Client::onTransactionProgress); // delete *it; (*it)->dispose(); @@ -88,24 +84,24 @@ void Client::shutdown() } -void Client::onSocketConnect(net::Socket& socket) +bool Client::onSocketConnect(net::Socket& socket) { - LTrace("Client connected") + LTrace("Client connected"); _socket.Connect -= slot(this, &Client::onSocketConnect); _timer.setInterval(_options.timerInterval); _timer.start(std::bind(&Client::onTimer, this)); sendAllocate(); + return false; } -void Client::onSocketRecv(net::Socket& socket, const MutableBuffer& buffer, const net::Address& peerAddress) +bool Client::onSocketRecv(net::Socket& socket, const MutableBuffer& buffer, const net::Address& peerAddress) { - LTrace("Control socket recv: ", buffer.size()) + LTrace("Control socket recv: ", buffer.size()); stun::Message message; - // auto socket = reinterpret_cast(sender); char* buf = bufferCast(buffer); size_t len = buffer.size(); size_t nread = 0; @@ -115,25 +111,21 @@ void Client::onSocketRecv(net::Socket& socket, const MutableBuffer& buffer, cons len -= nread; } if (len == buffer.size()) - LWarn("Non STUN packet received") - -#if 0 - stun::Message message; - if (message.read(constBuffer(packet.data(), packet.size()))) - handleResponse(message); - else - LWarn("Non STUN packet received") -#endif + LWarn("Non STUN packet received"); + return false; } -void Client::onSocketClose(net::Socket& socket) +bool Client::onSocketClose(net::Socket& socket) { - assert(&socket == _socket.impl.get()); - LTrace("Control socket closed") - assert(_socket->closed()); + if (&socket != _socket.impl.get()) + throw std::logic_error("onSocketClose called with unexpected socket"); + LTrace("Control socket closed"); + if (!_socket->closed()) + throw std::logic_error("socket reported close but is not in closed state"); shutdown(); setError(_socket->error()); + return false; } @@ -152,13 +144,13 @@ void Client::sendRefresh() // explicitly delete the allocation. A client MAY refresh an allocation // at any time for other reasons. - LTrace("Send refresh allocation request") + LTrace("Send refresh allocation request"); auto transaction = createTransaction(); transaction->request().setClass(stun::Message::Request); transaction->request().setMethod(stun::Message::Refresh); - stun::Lifetime* lifetimeAttr = new stun::Lifetime; + auto lifetimeAttr = new stun::Lifetime; lifetimeAttr->setValue((uint32_t)_options.lifetime / 1000); transaction->request().add(lifetimeAttr); @@ -168,9 +160,10 @@ void Client::sendRefresh() void Client::handleRefreshResponse(const stun::Message& response) { - LTrace("Received a Refresh Response: ", response.toString()) + LTrace("Received a Refresh Response: ", response.toString()); - assert(response.methodType() == stun::Message::Refresh); + if (response.methodType() != stun::Message::Refresh) + throw std::logic_error("handleRefreshResponse called with non-Refresh message"); // 7.3. Receiving a Refresh Response // @@ -185,19 +178,23 @@ void Client::handleRefreshResponse(const stun::Message& response) // succeeded. auto errorAttr = response.get(); if (errorAttr) { - assert(errorAttr->errorCode() == 437); + if (errorAttr->errorCode() == kErrorAllocationMismatch) { + // Allocation already gone, treat as success + return; + } + LWarn("Unexpected error in Refresh response: ", errorAttr->errorCode()); return; } auto lifetimeAttr = response.get(); if (!lifetimeAttr) { - assert(0); + LWarn("Refresh response missing Lifetime attribute"); return; } setLifetime(lifetimeAttr->value()); - LTrace("Refreshed allocation expires in: ", timeRemaining()) + LTrace("Refreshed allocation expires in: ", timeRemaining()); // If lifetime is 0 the allocation will be cleaned up by garbage collection. } @@ -205,8 +202,7 @@ void Client::handleRefreshResponse(const stun::Message& response) bool Client::removeTransaction(stun::Transaction* transaction) { - LTrace("Removing transaction: ", transaction) - + LTrace("Removing transaction: ", transaction); for (auto it = _transactions.begin(); it != _transactions.end(); ++it) { if (*it == transaction) { @@ -215,7 +211,7 @@ bool Client::removeTransaction(stun::Transaction* transaction) return true; } } - assert(0 && "unknown transaction"); + LWarn("Attempted to remove unknown transaction: ", transaction); return false; } @@ -249,12 +245,9 @@ void Client::authenticateRequest(stun::Message& request) crypto::Hash engine("md5"); engine.update(_options.username + ":" + _realm + ":" + _options.password); - // return hex::encode(engine.digest()); - // std::string key(crypto::hash("MD5", _options.username + ":" + _realm - // + ":" + _options.password)); STrace << "Generating HMAC: data=" << (_options.username + ":" + _realm + ":" + _options.password) - << ", key=" << engine.digestStr() << endl; + << ", key=" << engine.digestStr() << std::endl; auto integrityAttr = new stun::MessageIntegrity; integrityAttr->setKey(engine.digestStr()); request.add(integrityAttr); @@ -266,16 +259,13 @@ bool Client::sendAuthenticatedTransaction(stun::Transaction* transaction) { authenticateRequest(transaction->request()); STrace << "Send authenticated transaction: " - << transaction->request().toString() << endl; + << transaction->request().toString() << std::endl; return transaction->send(); } stun::Transaction* Client::createTransaction(const net::Socket::Ptr& socket) { - - // socket = socket ? socket : _socket; - // assert(socket && !socket->isNull()); auto transaction = new stun::Transaction( socket ? socket : _socket.impl, _options.serverAddr, _options.timeout, 1); transaction->StateChange += slot(this, &Client::onTransactionProgress); @@ -286,7 +276,7 @@ stun::Transaction* Client::createTransaction(const net::Socket::Ptr& socket) bool Client::handleResponse(const stun::Message& response) { - LTrace("Handle response: ", response.toString()) + LTrace("Handle response: ", response.toString()); // Send this response to the appropriate handler. if (response.methodType() == stun::Message::Allocate) { @@ -297,18 +287,15 @@ bool Client::handleResponse(const stun::Message& response) handleAllocateErrorResponse(response); // Must be a Transaction response - else - assert(0 && "no response state"); + else { + LWarn("Unexpected Allocate response class: ", response.classType()); + return false; + } } else if (response.methodType() == stun::Message::Refresh) handleRefreshResponse(response); - // else if (response.methodType() == stun::Message::Refresh && - // response.classType() == stun::Message::ErrorResponse)&& - // response.classType() == stun::Message::SuccessResponse - // handleRefreshErrorResponse(response); - else if (response.methodType() == stun::Message::CreatePermission && response.classType() == stun::Message::SuccessResponse) handleCreatePermissionResponse(response); @@ -329,91 +316,27 @@ bool Client::handleResponse(const stun::Message& response) void Client::sendAllocate() { - LTrace("Send allocation request") + LTrace("Send allocation request"); - assert(!_options.username.empty()); - assert(!_options.password.empty()); - // assert(_options.lifetime); - //_lifetime = _options.lifetime; + if (_options.username.empty()) + throw std::runtime_error("username must be set before sending Allocate"); + if (_options.password.empty()) + throw std::runtime_error("password must be set before sending Allocate"); - // The client forms an Allocate request as follows. - // - // The client first picks a host transport address. It is RECOMMENDED - // that the client pick a currently unused transport address, typically - // by allowing the underlying OS to pick a currently unused port for a - // new socket. - // - // The client then picks a transport protocol to use between the client - // and the server. The transport protocol MUST be one of UDP, TCP, or - // TLS-over-TCP. Since this specification only allows UDP between the - // server and the peers, it is RECOMMENDED that the client pick UDP - // unless it has a reason to use a different transport. One reason to - // pick a different transport would be that the client believes, either - // through configuration or by experiment, that it is unable to contact - // any TURN server using UDP. See Section 2.1 for more discussion. - // - // The client also picks a server transport address, which SHOULD be - // done as follows. The client receives (perhaps through configuration) - // a domain name for a TURN server. The client then uses the DNS - // procedures described in [RFC5389], but using an SRV service name of - // "turn" (or "turns" for TURN over TLS) instead of "stun" (or "stuns"). - // For example, to find servers in the example.com domain, the client - // performs a lookup for '_turn._udp.example.com', - // '_turn._tcp.example.com', and '_turns._tcp.example.com' if the client - // wants to communicate with the server using UDP, TCP, or TLS-over-TCP, - // respectively. - // auto transaction = createTransaction(); - // stun::Message request(stun::Message::Request, stun::Message::Allocate); transaction->request().setClass(stun::Message::Request); transaction->request().setMethod(stun::Message::Allocate); - // The client MUST include a REQUESTED-TRANSPORT attribute in the - // request. This attribute specifies the transport protocol between the - // server and the peers (note that this is NOT the transport protocol - // that appears in the 5-tuple). - // auto transportAttr = new stun::RequestedTransport; transportAttr->setValue(transportProtocol() << 24); transaction->request().add(transportAttr); - // If the client wishes the server to initialize the time-to-expiry - // field of the allocation to some value other than the default - // lifetime, then it MAY include a LIFETIME attribute specifying its - // desired value. This is just a request, and the server may elect to - // use a different value. Note that the server will ignore requests to - // initialize the field to less than the default value. - // if (_options.lifetime) { auto lifetimeAttr = new stun::Lifetime; lifetimeAttr->setValue((uint32_t)_options.lifetime / 1000); transaction->request().add(lifetimeAttr); } - // If the client wishes to later use the DONT-FRAGMENT attribute in one - // or more Send indications on this allocation, then the client SHOULD - // include the DONT-FRAGMENT attribute in the Allocate - // transaction->request(). This - // allows the client to test whether this attribute is supported by the - // server. - // - // If the client requires the port number of the relayed transport - // address be even, the client includes the EVEN-PORT attribute. If - // this attribute is not included, then the port can be even or odd. By - // setting the R bit in the EVEN-PORT attribute to 1, the client can - // request that the server reserve the next highest port number (on the - // same IP address) for a subsequent allocation. If the R bit is 0, no - // such request is made. - // - // The client MAY also include a RESERVATION-TOKEN attribute in the - // request to ask the server to use a previously reserved port for the - // allocation. If the RESERVATION-TOKEN attribute is included, then the - // client MUST omit the EVEN-PORT attribute. - // - // Once constructed, the client sends the Allocate request on the - // 5-tuple. - // - sendAuthenticatedTransaction(transaction); } @@ -422,74 +345,43 @@ void Client::sendAllocate() // have not checked for existing allocations on this 5 tuple. void Client::handleAllocateResponse(const stun::Message& response) { - LTrace("Allocate success response") - assert(response.methodType() == stun::Message::Allocate); - - // If the client receives an Allocate success response, then it MUST - // check that the mapped address and the relayed transport address are - // in an address family that the client understands and is prepared to - // handle. This specification only covers the case where these two - // addresses are IPv4 addresses. If these two addresses are not in an - // address family which the client is prepared to handle, then the - // client MUST delete the allocation (Section 7) and MUST NOT attempt to - // create another allocation on that server until it believes the - // mismatch has been fixed. - // - // The IETF is currently considering mechanisms for transitioning - // between IPv4 and IPv6 that could result in a client originating an - // Allocate request over IPv6, but the request would arrive at the - // server over IPv4, or vice versa. - // - // Otherwise, the client creates its own copy of the allocation data - // structure to track what is happening on the server. In particular, - // the client needs to remember the actual lifetime received back from - // the server, rather than the value sent to the server in the request. - // + LTrace("Allocate success response"); + if (response.methodType() != stun::Message::Allocate) + throw std::logic_error("handleAllocateResponse called with non-Allocate message"); + auto lifetimeAttr = response.get(); if (!lifetimeAttr) { - assert(0); + LWarn("Allocate response missing Lifetime attribute"); return; } auto mappedAttr = response.get(); - if (!mappedAttr || mappedAttr->family() != 1) { - assert(0); + if (!mappedAttr || mappedAttr->family() != stun::AddressFamily::IPv4) { + LWarn("Allocate response missing or invalid XorMappedAddress"); return; } _mappedAddress = mappedAttr->address(); - // The client must also remember the 5-tuple used for the request and - // the username and password it used to authenticate the request to - // ensure that it reuses them for subsequent messages. The client also - // needs to track the channels and permissions it establishes on the - // server. - // - // The client will probably wish to send the relayed transport address - // to peers (using some method not specified here) so the peers can - // communicate with it. The client may also wish to use the server- - // reflexive address it receives in the XOR-MAPPED-ADDRESS attribute in - // its ICE processing. - // auto relayedAttr = response.get(); - if (!relayedAttr || (relayedAttr && relayedAttr->family() != 1)) { - assert(0); + if (!relayedAttr || relayedAttr->family() != stun::AddressFamily::IPv4) { + LWarn("Allocate response missing or invalid XorRelayedAddress"); return; } if (relayedAttr->address().host() == "0.0.0.0") { - assert(0 && "invalid loopback address"); + LError("Allocate response contains invalid loopback relay address"); return; } // Use the relay server host and relayed port _relayedAddress = net::Address( relayedAttr->address().host(), - relayedAttr->address().port()); //_options.serverAddr.host() + relayedAttr->address().port()); STrace << "Allocation created:" - << "\n\tRelayed address: " << _relayedAddress //.toString() - << "\n\tMapped address: " << _mappedAddress //.toString() - << "\n\tLifetime: " << lifetimeAttr->value() << endl; + << "\n\tRelayed address: " << _relayedAddress + << "\n\tMapped address: " << _mappedAddress + << "\n\tLifetime: " << lifetimeAttr->value() << std::endl; // Once the allocation is created we transition to Authorizing while // peer permissions are created. @@ -504,62 +396,33 @@ void Client::handleAllocateResponse(const stun::Message& response) void Client::handleAllocateErrorResponse(const stun::Message& response) { - LTrace("Allocate error response") + LTrace("Allocate error response"); - assert(response.methodType() == stun::Message::Allocate && - response.classType() == stun::Message::ErrorResponse); + if (response.methodType() != stun::Message::Allocate || + response.classType() != stun::Message::ErrorResponse) { + LWarn("Unexpected message in handleAllocateErrorResponse"); + return; + } auto errorAttr = response.get(); if (!errorAttr) { - assert(0); + LWarn("Allocate error response missing ErrorCode attribute"); return; } STrace << "Allocation error response: " << errorAttr->errorCode() << ": " - << errorAttr->reason() << endl; - - // If the client receives an Allocate error response, then the - // processing depends on the actual error code returned: - - // o (Request timed out): There is either a problem with the server, or - // a problem reaching the server with the chosen transport. The - // client considers the current transaction as having failed but MAY - // choose to retry the Allocate request using a different transport - // (e.g., TCP instead of UDP). + << errorAttr->reason() << std::endl; switch (errorAttr->errorCode()) { - // 300 (Try Alternate): The server would like the client to use the - // server specified in the ALTERNATE-SERVER attribute instead. The - // client considers the current transaction as having failed, but - // SHOULD try the Allocate request with the alternate server before - // trying any other servers (e.g., other servers discovered using the - // SRV procedures). When trying the Allocate request with the - // alternate server, the client follows the ALTERNATE-SERVER - // procedures specified in [RFC5389]. - case 300: - // Return the error to the client. - assert(0); + case kErrorTryAlternate: + LWarn("Server requested Try Alternate (300)"); break; - // 400 (Bad Request): The server believes the client's request is - // malformed for some reason. The client considers the current - // transaction as having failed. The client MAY notify the client or - // operator and SHOULD NOT retry the request with this server until - // it believes the problem has been fixed. - case 400: - // Return the error to the client. - assert(0); + case kErrorBadRequest: + LWarn("Server returned Bad Request (400)"); break; - // 401 (NotAuthorized): If the client has followed the procedures of - // the long-term credential mechanism and still gets this error, then - // the server is not accepting the client's credentials. In this - // case, the client considers the current transaction as having - // failed and SHOULD notify the client or operator. The client SHOULD - // NOT send any further requests to this server until it believes the - // problem has been fixed. - case 401: { - + case kErrorNotAuthorized: { if (_realm.empty() || _nonce.empty()) { // REALM @@ -577,7 +440,7 @@ void Client::handleAllocateErrorResponse(const stun::Message& response) // Now that our realm and nonce are set we can re-send the // allocate request. if (_realm.size() && _nonce.size()) { - LTrace("Resending authenticated allocation request") + LTrace("Resending authenticated allocation request"); sendAllocate(); return; } @@ -586,96 +449,41 @@ void Client::handleAllocateErrorResponse(const stun::Message& response) break; - // 403 (Forbidden): The request is valid, but the server is refusing - // to perform it, likely due to administrative restrictions. The - // client considers the current transaction as having failed. The - // client MAY notify the client or operator and SHOULD NOT retry the - // same request with this server until it believes the problem has - // been fixed. - case 403: - // Return the error to the client. - assert(0); + case kErrorForbidden: + LWarn("Server returned Forbidden (403)"); break; - // 420 (Unknown Attribute): If the client included a DONT-FRAGMENT - // attribute in the request and the server rejected the request with - // a 420 error code and listed the DONT-FRAGMENT attribute in the - // UNKNOWN-ATTRIBUTES attribute in the error response, then the - // client now knows that the server does not support the DONT- - // FRAGMENT attribute. The client considers the current transaction - // as having failed but MAY choose to retry the Allocate request - // without the DONT-FRAGMENT attribute. - case 420: - assert(0); + case kErrorUnknownAttribute: + LWarn("Server returned Unknown Attribute (420)"); break; - // 437 (Allocation Mismatch): This indicates that the client has - // picked a 5-tuple that the server sees as already in use. One way - // this could happen is if an intervening NAT assigned a mapped - // transport address that was used by another client that recently - // crashed. The client considers the current transaction as having - // failed. The client SHOULD pick another client transport address - // and retry the Allocate request (using a different transaction id). - // The client SHOULD try three different client transport addresses - // before giving up on this server. Once the client gives up on the - // server, it SHOULD NOT try to create another allocation on the - // server for 2 minutes. - case 437: - assert(0); + case kErrorAllocationMismatch: + LWarn("Server returned Allocation Mismatch (437)"); break; - // 438 (Stale Nonce): See the procedures for the long-term credential - // mechanism [RFC5389]. - case 438: - assert(0); + case kErrorStaleNonce: + LWarn("Server returned Stale Nonce (438)"); break; - // 441 (Wrong Credentials): The client should not receive this error - // in response to a Allocate request. The client MAY notify the client - // or operator and SHOULD NOT retry the same request with this server - // until it believes the problem has been fixed. - case 441: - assert(0); + case kErrorWrongCredentials: + LWarn("Server returned Wrong Credentials (441)"); break; - // 442 (Unsupported Transport Address): The client should not receive - // this error in response to a request for a UDP allocation. The - // client MAY notify the client or operator and SHOULD NOT reattempt - // the request with this server until it believes the problem has - // been fixed. - case 442: - assert(0); + case kErrorUnsupportedTransport: + LWarn("Server returned Unsupported Transport (442)"); break; - // 486 (Allocation Quota Reached): The server is currently unable to - // create any more allocations with this username. The client - // considers the current transaction as having failed. The client - // SHOULD wait at least 1 minute before trying to create any more - // allocations on the server. - case 486: - // controlConn.disconnect(); - // controlConn.startConnectionTimer(60000); - // assert(0); + case kErrorAllocationQuotaReached: + LWarn("Server returned Allocation Quota Reached (486)"); break; - // 508 (Insufficient Capacity): The server has no more relayed - // transport addresses available, or has none with the requested - // properties, or the one that was reserved is no longer available. - // The client considers the current operation as having failed. If - // the client is using either the EVEN-PORT or the RESERVATION-TOKEN - // attribute, then the client MAY choose to remove or modify this - // attribute and try again immediately. Otherwise, the client SHOULD - // wait at least 1 minute before trying to create any more - // allocations on this server. - case 508: - // controlConn.disconnect(); - // controlConn.startConnectionTimer(60000); - // assert(0); + case kErrorInsufficientCapacity: + LWarn("Server returned Insufficient Capacity (508)"); break; // An unknown error response MUST be handled as described in [RFC5389]. default: - assert(0); + LWarn("Server returned unknown error: ", errorAttr->errorCode()); break; } @@ -699,8 +507,8 @@ void Client::setError(const scy::Error& error) void Client::addPermission(const IPList& peerIPs) { - for (auto it = peerIPs.begin(); it != peerIPs.end(); ++it) { - addPermission(*it); + for (const auto& ip : peerIPs) { + addPermission(ip); } } @@ -713,33 +521,19 @@ void Client::addPermission(const std::string& peerIP) void Client::sendCreatePermission() { - LTrace("Send Create Permission Request") + LTrace("Send Create Permission Request"); - assert(!_permissions.empty()); - - // The client who wishes to install or refresh one or more permissions - // can send a CreatePermission request to the server. - // - // When forming a CreatePermission request, the client MUST include at - // least one XOR-PEER-ADDRESS attribute, and MAY include more than one - // such attribute. The IP address portion of each XOR-PEER-ADDRESS - // attribute contains the IP address for which a permission should be - // installed or refreshed. The port portion of each XOR-PEER-ADDRESS - // attribute will be ignored and can be any arbitrary value. The - // various XOR-PEER-ADDRESS attributes can appear in any order. + if (_permissions.empty()) + throw std::runtime_error("no permissions set for CreatePermission request"); auto transaction = createTransaction(); - // stun::Message request(stun::Message::Request, stun::Message::Allocate); transaction->request().setClass(stun::Message::Request); transaction->request().setMethod(stun::Message::CreatePermission); - for (auto it = _permissions.begin(); it != _permissions.end(); ++it) { - LTrace("Create permission request: ", (*it).ip) + for (const auto& perm : _permissions) { + LTrace("Create permission request: ", perm.ip); auto peerAttr = new stun::XorPeerAddress; - peerAttr->setAddress(net::Address((*it).ip, 0)); - // peerAttr->setFamily(1); - // peerAttr->setPort(0); - // peerAttr->setIP((*it).ip); + peerAttr->setAddress(net::Address(perm.ip, 0)); transaction->request().add(peerAttr); } @@ -752,12 +546,10 @@ void Client::handleCreatePermissionResponse(const stun::Message& /* response */) // If the client receives a valid CreatePermission success response, // then the client updates its data structures to indicate that the // permissions have been installed or refreshed. - LTrace("Permission created") + LTrace("Permission created"); // Send all queued requests... - // TODO: To via onStateChange Success callback { - while (!_pendingIndications.empty()) { _socket->sendPacket(_pendingIndications.front()); _pendingIndications.pop_front(); @@ -766,28 +558,18 @@ void Client::handleCreatePermissionResponse(const stun::Message& /* response */) if (!closed()) { _observer.onAllocationPermissionsCreated(*this, _permissions); - - // auto transaction = - // reinterpret_cast(response.opaque); - // for (int i = 0; i < 100; i++) { - // auto peerAttr = transaction->request().get(i); - // if (!peerAttr || (peerAttr && peerAttr->family() != 1)) - // break; - // _observer.onAllocationPermissionsCreated(*this, - // std::string(peerAttr->address().host())); - // } } // Once permissions have been created the allocation // process is considered a success. - LTrace("Allocation Success") + LTrace("Allocation Success"); setState(this, ClientState::Success); } void Client::handleCreatePermissionErrorResponse(const stun::Message& /* response */) { - LWarn("Permission Creation Failed") + LWarn("Permission Creation Failed"); removeAllPermissions(); @@ -797,56 +579,20 @@ void Client::handleCreatePermissionErrorResponse(const stun::Message& /* respons void Client::sendChannelBind(const std::string& /* peerIP */) { - // A channel binding is created or refreshed using a ChannelBind - // transaction. A ChannelBind transaction also creates or refreshes a - // permission towards the peer (see Section 8). - // - // To initiate the ChannelBind transaction, the client forms a - // ChannelBind request. The channel to be bound is specified in a - // CHANNEL-NUMBER attribute, and the peer's transport address is - // specified in an XOR-PEER-ADDRESS attribute. Section 11.2 describes - // the restrictions on these attributes. - // - // Rebinding a channel to the same transport address that it is already - // bound to provides a way to refresh a channel binding and the - // corresponding permission without sending data to the peer. Note - // however, that permissions need to be refreshed more frequently than - // channels. - assert(0 && "not implemented"); + throw std::logic_error("sendChannelBind not implemented"); } void Client::sendData(const char* data, size_t size, const net::Address& peerAddress) { - LTrace("Send Data Indication to peer: ", peerAddress) + LTrace("Send Data Indication to peer: ", peerAddress); - // auto request = new stun::Message; stun::Message request; request.setClass(stun::Message::Indication); request.setMethod(stun::Message::SendIndication); - // The client can use a Send indication to pass data to the server for - // relaying to a peer. A client may use a Send indication even if a - // channel is bound to that peer. However, the client MUST ensure that - // there is a permission installed for the IP address of the peer to - // which the Send indication is being sent; this prevents a third party - // from using a TURN server to send data to arbitrary destinations. - // - // When forming a Send indication, the client MUST include an XOR-PEER- - // ADDRESS attribute and a DATA attribute. The XOR-PEER-ADDRESS - // attribute contains the transport address of the peer to which the - // data is to be sent, and the DATA attribute contains the actual - // application data to be sent to the peer. - // - // The client MAY include a DONT-FRAGMENT attribute in the Send - // indication if it wishes the server to set the DF bit on the UDP - // datagram sent to the peer. - auto peerAttr = new stun::XorPeerAddress; peerAttr->setAddress(peerAddress); - // peerAttr->setFamily(1); - // peerAttr->setPort(peerAddress.port()); - // peerAttr->setIP(peerAddress.host()); request.add(peerAttr); auto dataAttr = new stun::Data; @@ -855,7 +601,6 @@ void Client::sendData(const char* data, size_t size, const net::Address& peerAdd // Ensure permissions exist for the peer. if (!hasPermission(peerAddress.host())) { - // delete request; throw std::runtime_error("No permission exists for peer IP: " + peerAddress.host()); } @@ -864,52 +609,35 @@ void Client::sendData(const char* data, size_t size, const net::Address& peerAdd // Queued requests will be sent when the CreatePermission // callback is received from the server. else if (stateEquals(ClientState::Authorizing)) { - LTrace("Queueing outgoing request: ", request.toString()) + LTrace("Queueing outgoing request: ", request.toString()); _pendingIndications.push_back(request); - assert(_pendingIndications.size() < 100); // something is wrong... + if (_pendingIndications.size() >= 100) + LWarn("Excessive pending indications queued: ", _pendingIndications.size()); } // If a permission exists on server and client send our data! else { _socket->sendPacket(request, _options.serverAddr); - // delete request; } } void Client::handleDataIndication(const stun::Message& response) { - // When the client receives a Data indication, it checks that the Data - // indication contains both an XOR-PEER-ADDRESS and a DATA attribute, - // and discards the indication if it does not. The client SHOULD also - // check that the XOR-PEER-ADDRESS attribute value contains an IP - // address with which the client believes there is an active permission, - // and discard the Data indication otherwise. Note that the DATA - // attribute is allowed to contain zero bytes of data. - // - // NOTE: The latter check protects the client against an attacker who - // somehow manages to trick the server into installing permissions - // not desired by the client. - // - // If the Data indication passes the above checks, the client delivers - // the data octets inside the DATA attribute to the application, along - // with an indication that they were received from the peer whose - // transport address is given by the XOR-PEER-ADDRESS attribute. - auto peerAttr = response.get(); - if (!peerAttr || (peerAttr && peerAttr->family() != 1)) { - assert(0); + if (!peerAttr || peerAttr->family() != stun::AddressFamily::IPv4) { + LWarn("Data indication missing or invalid XorPeerAddress"); return; } auto dataAttr = response.get(); if (!dataAttr) { - assert(0); + LWarn("Data indication missing Data attribute"); return; } - LTrace("Handle Data indication: ", response.toString()) + LTrace("Handle Data indication: ", response.toString()); if (!closed()) { _observer.onRelayDataReceived(*this, dataAttr->bytes(), dataAttr->size(), peerAttr->address()); @@ -919,9 +647,9 @@ void Client::handleDataIndication(const stun::Message& response) void Client::onTransactionProgress(void* sender, TransactionState& state, const TransactionState&) { - LTrace("Transaction state change: ", sender, ": ", state) + LTrace("Transaction state change: ", sender, ": ", state); - auto transaction = reinterpret_cast(sender); + auto transaction = static_cast(sender); transaction->response().opaque = transaction; if (!closed()) @@ -937,12 +665,12 @@ void Client::onTransactionProgress(void* sender, TransactionState& state, const << "\n\tFrom: " << transaction->peerAddress().toString() << "\n\tRequest: " << transaction->request().toString() << "\n\tResponse: " << transaction->response().toString() - << endl; + << std::endl; if (removeTransaction(transaction)) { if (!handleResponse(transaction->response())) { STrace << "Unhandled STUN response: " - << transaction->response().toString() << endl; + << transaction->response().toString() << std::endl; } } } break; @@ -951,9 +679,8 @@ void Client::onTransactionProgress(void* sender, TransactionState& state, const SWarn << "STUN transaction error:" << "\n\tState: " << state.toString() << "\n\tFrom: " << transaction->peerAddress().toString() - << "\n\tData: " << transaction->response().toString() << endl; + << "\n\tData: " << transaction->response().toString() << std::endl; - // TODO: More flexible response error handling if (removeTransaction(transaction)) { setError("Transaction failed"); } @@ -983,7 +710,7 @@ void Client::onStateChange(ClientState& state, const ClientState& oldState) int Client::transportProtocol() { - return 17; // UDP + return kProtocolUDP; } @@ -1011,7 +738,8 @@ net::Address Client::relayedAddress() const } -} } // namespace scy::turn +} // namespace turn +} // namespace scy /// @\} diff --git a/src/turn/src/client/tcpclient.cpp b/src/turn/src/client/tcpclient.cpp index 6c9aeb4d8..be88823b5 100644 --- a/src/turn/src/client/tcpclient.cpp +++ b/src/turn/src/client/tcpclient.cpp @@ -13,12 +13,12 @@ #include "scy/logger.h" #include "scy/net/tcpsocket.h" +#include + #include -#include #include - - -using namespace std; +#include +#include namespace scy { @@ -29,15 +29,14 @@ TCPClient::TCPClient(TCPClientObserver& observer, const Client::Options& options : Client(observer, options, net::makeSocket()) , _observer(observer) { - LTrace("Create") + LTrace("Create"); } TCPClient::~TCPClient() { - LTrace("Destroy") + LTrace("Destroy"); shutdown(); - // assert(connections().empty()); } @@ -49,55 +48,36 @@ void TCPClient::initiate() void TCPClient::shutdown() { - LTrace("Shutdown") - - // if (closed()) { - // LTrace("Already closed") - // return; - //} + LTrace("Shutdown"); // Destroy transactions and stop timer Client::shutdown(); { auto connections = _connections.map(); - LTrace("Shutdown: Active connections: ", connections.size()) + LTrace("Shutdown: Active connections: ", connections.size()); for (auto it = connections.begin(); it != connections.end(); ++it) { - // Calling onRelayConnectionClosed directly to avoid queueing - // callbacks after close - // it->second->close(); onRelayConnectionClosed(*it->second.impl.get()); } - assert(_connections.empty()); + if (!_connections.empty()) + LWarn("Connections not fully cleaned up after shutdown"); } - LTrace("Shutdown: OK") + LTrace("Shutdown: OK"); } void TCPClient::sendConnectRequest(const net::Address& peerAddress) { - // 4.3. Initiating a Connection - // - // To initiate a TCP connection to a peer, a client MUST send a Connect - // request over the control connection for the desired allocation. The - // Connect request MUST include an XOR-PEER-ADDRESS attribute containing - // the transport address of the peer to which a connection is desired. - - LTrace("Send Connect request") + LTrace("Send Connect request"); auto transaction = createTransaction(); - // transaction->request().setType(stun::Message::Connect); - // stun::Message request(stun::Message::Request, stun::Message::Allocate); transaction->request().setClass(stun::Message::Request); transaction->request().setMethod(stun::Message::Connect); auto peerAttr = new stun::XorPeerAddress; peerAttr->setAddress(peerAddress); - // peerAttr->setFamily(1); - // peerAttr->setPort(peerAddress.port()); - // peerAttr->setIP(peerAddress.host()); transaction->request().add(peerAttr); sendAuthenticatedTransaction(transaction); @@ -106,15 +86,13 @@ void TCPClient::sendConnectRequest(const net::Address& peerAddress) void TCPClient::sendData(const char* data, size_t size, const net::Address& peerAddress) { - LTrace("Send data to ", peerAddress) + LTrace("Send data to ", peerAddress); // Ensure permissions exist for the peer. if (!hasPermission(peerAddress.host())) throw std::runtime_error("No permission exists for peer: " + peerAddress.host()); - auto& conn = _connections.get(peerAddress); //, nullptr - // if (conn) - // throw std::runtime_error("No peer exists for: " + peerAddress.toString()); + auto& conn = _connections.get(peerAddress); conn->send(data, size); } @@ -152,32 +130,16 @@ bool TCPClient::handleResponse(const stun::Message& response) void TCPClient::handleConnectResponse(const stun::Message& response) { - // If the connection is successfully established, the client will - // receive a success response. That response will contain a - // CONNECTION-ID attribute. The client MUST initiate a new TCP - // connection to the server, utilizing the same destination transport - // address to which the control connection was established. This - // connection MUST be made using a different local transport address. - // Authentication of the client by the server MUST use the same method - // and credentials as for the control connection. Once established, the - // client MUST send a ConnectionBind request over the new connection. - // That request MUST include the CONNECTION-ID attribute, echoed from - // the Connect Success response. When a response to the ConnectionBind - // request is received, if it is a success, the TCP connection on which - // it was sent is called the client data connection corresponding to the - // peer. - // - - auto transaction = reinterpret_cast(response.opaque); + auto transaction = static_cast(response.opaque); auto peerAttr = transaction->request().get(); - if (!peerAttr || (peerAttr && peerAttr->family() != 1)) { - assert(0); + if (!peerAttr || (peerAttr && peerAttr->family() != stun::AddressFamily::IPv4)) { + LWarn("Connect response missing valid XorPeerAddress in original request"); return; } auto connAttr = response.get(); if (!connAttr) { - assert(0); + LWarn("Connect response missing ConnectionID attribute"); return; } @@ -187,20 +149,10 @@ void TCPClient::handleConnectResponse(const stun::Message& response) void TCPClient::handleConnectErrorResponse(const stun::Message& response) { - // If the result of the Connect request was an Error Response, and the - // response code was 447 (Connection Timeout or Failure), it means that - // the TURN server was unable to connect to the peer. The client MAY - // retry with the same XOR-PEER-ADDRESS attribute, but MUST wait at - // least 10 seconds. - // - // As with any other request, multiple Connect requests MAY be sent - // simultaneously. However, Connect requests with the same XOR-PEER- - // ADDRESS parameter MUST NOT be sent simultaneously. - - auto transaction = reinterpret_cast(response.opaque); + auto transaction = static_cast(response.opaque); auto peerAttr = transaction->request().get(); - if (!peerAttr || (peerAttr && peerAttr->family() != 1)) { - assert(0); + if (!peerAttr || (peerAttr && peerAttr->family() != stun::AddressFamily::IPv4)) { + LWarn("Connect error response missing valid XorPeerAddress"); return; } @@ -210,35 +162,15 @@ void TCPClient::handleConnectErrorResponse(const stun::Message& response) void TCPClient::handleConnectionAttemptIndication(const stun::Message& response) { - // 4.4. Receiving a Connection - // - // After an Allocate request is successfully processed by the server, - // the client will start receiving a ConnectionAttempt indication each - // time a peer for which a permission has been installed attempts a new - // connection to the relayed transport address. This indication will - // contain CONNECTION-ID and XOR-PEER-ADDRESS attributes. If the client - // wishes to accept this connection, it MUST initiate a new TCP - // connection to the server, utilizing the same destination transport - // address to which the control connection was established. This - // connection MUST be made using a different local transport address. - // Authentication of the client by the server MUST use the same method - // and credentials as for the control connection. Once established, the - // client MUST send a ConnectionBind request over the new connection. - // That request MUST include the CONNECTION-ID attribute, echoed from - // the ConnectionAttempt indication. When a response to the - // ConnectionBind request is received, if it is a success, the TCP - // connection on which it was sent is called the client data connection - // corresponding to the peer. - auto peerAttr = response.get(); - if (!peerAttr || (peerAttr && peerAttr->family() != 1)) { - assert(0); + if (!peerAttr || (peerAttr && peerAttr->family() != stun::AddressFamily::IPv4)) { + LWarn("ConnectionAttempt indication missing valid XorPeerAddress"); return; } auto connAttr = response.get(); if (!connAttr) { - assert(0); + LWarn("ConnectionAttempt indication missing ConnectionID"); return; } @@ -249,34 +181,32 @@ void TCPClient::handleConnectionAttemptIndication(const stun::Message& response) void TCPClient::handleConnectionBindResponse(const stun::Message& response) { - LTrace("ConnectionBind success response") + LTrace("ConnectionBind success response"); - auto transaction = reinterpret_cast(response.opaque); - auto req = reinterpret_cast(transaction->impl->opaque); + auto transaction = static_cast(response.opaque); + auto req = static_cast(std::any_cast(transaction->impl->opaque)); auto& conn = _connections.get(req->peerAddress); if (!conn.impl) { - assert(0); + LWarn("ConnectionBind response: no connection found for peer"); return; } // Data will now be transferred as-is to and from the peer. conn.Recv += slot(this, &TCPClient::onRelayDataReceived); - _observer.onRelayConnectionCreated(*this, - std::dynamic_pointer_cast(conn.impl), req->peerAddress); + _observer.onRelayConnectionCreated(*this, + std::dynamic_pointer_cast(conn.impl), req->peerAddress); - LTrace("ConnectionBind success response: OK") + LTrace("ConnectionBind success response: OK"); } void TCPClient::handleConnectionBindErrorResponse(const stun::Message& response) { - LTrace("ConnectionBind error response") + LTrace("ConnectionBind error response"); - auto transaction = reinterpret_cast(response.opaque); - auto req = reinterpret_cast(transaction->impl->opaque); - - // TODO: Handle properly + auto transaction = static_cast(response.opaque); + auto req = static_cast(std::any_cast(transaction->impl->opaque)); freeConnection(req->peerAddress); } @@ -284,7 +214,7 @@ void TCPClient::handleConnectionBindErrorResponse(const stun::Message& response) bool TCPClient::createAndBindConnection(uint32_t connectionID, const net::Address& peerAddress) { - LTrace("Create and bind connection: ", peerAddress) + LTrace("Create and bind connection: ", peerAddress); net::SocketEmitter conn(net::makeSocket()); conn.Connect += slot(this, &TCPClient::onRelayConnectionConnect); @@ -294,7 +224,7 @@ bool TCPClient::createAndBindConnection(uint32_t connectionID, const net::Addres auto req = new RelayConnectionBinding; req->connectionID = connectionID; req->peerAddress = peerAddress; - conn->opaque = req; + conn->opaque = static_cast(req); conn->connect(_options.serverAddr); // errors via callback _connections.add(peerAddress, conn); @@ -302,13 +232,14 @@ bool TCPClient::createAndBindConnection(uint32_t connectionID, const net::Addres } -void TCPClient::onRelayConnectionConnect(net::Socket& socket) +bool TCPClient::onRelayConnectionConnect(net::Socket& socket) { - auto req = reinterpret_cast(socket.opaque); + auto req = static_cast(std::any_cast(socket.opaque)); auto& conn = _connections.get(req->peerAddress); - LTrace("On relay connection connect") - assert(_connections.has(req->peerAddress)); + LTrace("On relay connection connect"); + if (!_connections.has(req->peerAddress)) + throw std::logic_error("relay connection not found for peer address"); auto transaction = createTransaction(conn.impl); transaction->request().setClass(stun::Message::Request); @@ -318,71 +249,70 @@ void TCPClient::onRelayConnectionConnect(net::Socket& socket) connAttr->setValue(req->connectionID); transaction->request().add(connAttr); - // assert(transaction->socket() == &conn); sendAuthenticatedTransaction(transaction); + return false; } -void TCPClient::onRelayConnectionError(net::Socket& socket, const Error& /* error */) +bool TCPClient::onRelayConnectionError(net::Socket& socket, const Error& /* error */) { - auto req = reinterpret_cast(socket.opaque); + auto req = static_cast(std::any_cast(socket.opaque)); auto& conn = _connections.get(req->peerAddress); - LTrace("Relay connection error: ", req->peerAddress) - assert(_connections.has(req->peerAddress)); + LTrace("Relay connection error: ", req->peerAddress); + if (!_connections.has(req->peerAddress)) + ; + LWarn("Relay connection error for unknown peer: ", req->peerAddress); _observer.onRelayConnectionError(*this, - std::dynamic_pointer_cast(conn.impl), req->peerAddress); + std::dynamic_pointer_cast(conn.impl), req->peerAddress); + return false; } -void TCPClient::onRelayConnectionClosed(net::Socket& socket) +bool TCPClient::onRelayConnectionClosed(net::Socket& socket) { - auto req = reinterpret_cast(socket.opaque); + auto req = static_cast(std::any_cast(socket.opaque)); auto& conn = _connections.get(req->peerAddress); - LTrace("Relay connection closed: ", req->peerAddress) - assert(_connections.has(req->peerAddress)); + LTrace("Relay connection closed: ", req->peerAddress); + if (!_connections.has(req->peerAddress)) + ; + LWarn("Relay connection closed for unknown peer: ", req->peerAddress); _observer.onRelayConnectionClosed(*this, - std::dynamic_pointer_cast(conn.impl), req->peerAddress); + std::dynamic_pointer_cast(conn.impl), req->peerAddress); freeConnection(req->peerAddress); + return false; } -void TCPClient::onRelayDataReceived(net::Socket& socket, +bool TCPClient::onRelayDataReceived(net::Socket& socket, const MutableBuffer& buffer, const net::Address& peerAddress) { - auto req = reinterpret_cast(socket.opaque); - assert(_connections.has(req->peerAddress)); - // LTrace("Relay Data Received: ", peerAddress, ": ", req->peerAddress) - // assert(req->peerAddress == peerAddress); + auto req = static_cast(std::any_cast(socket.opaque)); + if (!_connections.has(req->peerAddress)) + LWarn("Relay data received for unknown peer: ", req->peerAddress); _observer.onRelayDataReceived(*this, bufferCast(buffer), buffer.size(), req->peerAddress); + return false; } void TCPClient::freeConnection(const net::Address& peerAddress) { - LTrace("Freeing TCP connection: ", peerAddress) + LTrace("Freeing TCP connection: ", peerAddress); auto& conn = _connections.get(peerAddress); - auto req = reinterpret_cast(conn->opaque); + auto req = static_cast(std::any_cast(conn->opaque)); conn.Recv -= slot(this, &TCPClient::onRelayDataReceived); conn.Connect -= slot(this, &TCPClient::onRelayConnectionConnect); conn.Error -= slot(this, &TCPClient::onRelayConnectionError); conn.Close -= slot(this, &TCPClient::onRelayConnectionClosed); _connections.remove(peerAddress); // release socket delete req; - - // auto map = connections().map(); - // for (auto conn : map) { - // assert(it->second->base().refCount() == 1); - // The connection will be removed via onRelayConnectionClosed - // it->second->close(); - //} } @@ -394,11 +324,12 @@ ConnectionManager& TCPClient::connections() int TCPClient::transportProtocol() { - return 6; // TCP + return kProtocolTCP; } -} } // namespace scy::turn +} // namespace turn +} // namespace scy /// @\} diff --git a/src/turn/src/client/udpclient.cpp b/src/turn/src/client/udpclient.cpp index b77c321bf..70223ed4e 100644 --- a/src/turn/src/client/udpclient.cpp +++ b/src/turn/src/client/udpclient.cpp @@ -13,9 +13,6 @@ #include "scy/net/udpsocket.h" -using namespace std; - - namespace scy { namespace turn { @@ -23,17 +20,18 @@ namespace turn { UDPClient::UDPClient(ClientObserver& observer, const Options& options) : Client(observer, options, net::makeSocket()) { - LTrace("Create") + LTrace("Create"); } UDPClient::~UDPClient() { - LTrace("Destroy") + LTrace("Destroy"); } -} } // namespace scy::turn +} // namespace turn +} // namespace scy /// @\} diff --git a/src/turn/src/fivetuple.cpp b/src/turn/src/fivetuple.cpp index 8a1722888..efd861189 100644 --- a/src/turn/src/fivetuple.cpp +++ b/src/turn/src/fivetuple.cpp @@ -12,9 +12,6 @@ #include "scy/turn/fivetuple.h" -using namespace std; - - namespace scy { namespace turn { @@ -44,9 +41,7 @@ FiveTuple::FiveTuple(const FiveTuple& r) bool FiveTuple::operator==(const FiveTuple& r) const { - return _remote == r._remote - && _local == r._local - && _transport == r._transport; + return _remote == r._remote && _local == r._local && _transport == r._transport; } @@ -64,9 +59,9 @@ bool FiveTuple::operator<(const FiveTuple& r) const } -string FiveTuple::toString() const +std::string FiveTuple::toString() const { - ostringstream ost; + std::ostringstream ost; ost << "FiveTuple[" << _remote.toString() << ":" << _local.toString() << ":" << _transport << "]"; return ost.str(); } diff --git a/src/turn/src/iallocation.cpp b/src/turn/src/iallocation.cpp index b13d9f2d8..307fbac68 100644 --- a/src/turn/src/iallocation.cpp +++ b/src/turn/src/iallocation.cpp @@ -14,12 +14,9 @@ #include "scy/util.h" #include -#include #include #include - - -using namespace std; +#include namespace scy { @@ -45,14 +42,15 @@ IAllocation::IAllocation(const FiveTuple& tuple, const std::string& username, IAllocation::~IAllocation() { - LTrace("Destroy") + LTrace("Destroy"); _permissions.clear(); } void IAllocation::updateUsage(std::int64_t numBytes) { - LTrace("Update usage: ", _bandwidthUsed, ": ", numBytes) + std::lock_guard lock(_mutex); + LTrace("Update usage: ", _bandwidthUsed, ": ", numBytes); _updatedAt = time(0); _bandwidthUsed += numBytes; } @@ -60,6 +58,7 @@ void IAllocation::updateUsage(std::int64_t numBytes) std::int64_t IAllocation::timeRemaining() const { + std::lock_guard lock(_mutex); // uint32_t remaining = static_cast(_lifetime - (time(0) - _updatedAt)); std::int64_t remaining = _lifetime - static_cast(time(0) - _updatedAt); return remaining > 0 ? remaining : 0; @@ -74,41 +73,48 @@ bool IAllocation::expired() const bool IAllocation::deleted() const { + std::lock_guard lock(_mutex); return _deleted || expired(); } void IAllocation::setLifetime(std::int64_t lifetime) { + std::lock_guard lock(_mutex); _lifetime = lifetime; _updatedAt = static_cast(time(0)); - LTrace("Updating Lifetime: ", _lifetime) + LTrace("Updating Lifetime: ", _lifetime); } void IAllocation::setBandwidthLimit(std::int64_t numBytes) { + std::lock_guard lock(_mutex); _bandwidthLimit = numBytes; } std::int64_t IAllocation::bandwidthLimit() const { + std::lock_guard lock(_mutex); return _bandwidthLimit; } std::int64_t IAllocation::bandwidthUsed() const { + std::lock_guard lock(_mutex); return _bandwidthUsed; } std::int64_t IAllocation::bandwidthRemaining() const { + std::lock_guard lock(_mutex); return _bandwidthLimit > 0 ? (_bandwidthLimit > _bandwidthUsed ? _bandwidthLimit - _bandwidthUsed - : 0) : 99999999; + : 0) + : 99999999; } @@ -132,39 +138,42 @@ std::int64_t IAllocation::lifetime() const PermissionList IAllocation::permissions() const { + std::lock_guard lock(_mutex); return _permissions; } void IAllocation::addPermission(const std::string& ip) { + std::lock_guard lock(_mutex); // If the permission is already in the list then refresh it. - for (auto it = _permissions.begin(); it != _permissions.end(); ++it) { - if ((*it).ip == ip) { - LTrace("Refreshing permission: ", ip) - (*it).refresh(); + for (auto& perm : _permissions) { + if (perm.ip == ip) { + LTrace("Refreshing permission: ", ip); + perm.refresh(); return; } } // Otherwise create it... - LTrace("Create permission: ", ip) + LTrace("Create permission: ", ip); _permissions.push_back(Permission(ip)); } void IAllocation::addPermissions(const IPList& ips) { - for (auto it = ips.begin(); it != ips.end(); ++it) { - addPermission(*it); + for (const auto& ip : ips) { + addPermission(ip); } } void IAllocation::removePermission(const std::string& ip) { + std::lock_guard lock(_mutex); for (auto it = _permissions.begin(); it != _permissions.end();) { - if ((*it).ip == ip) { + if (it->ip == ip) { it = _permissions.erase(it); return; } else @@ -175,17 +184,17 @@ void IAllocation::removePermission(const std::string& ip) void IAllocation::removeAllPermissions() { - + std::lock_guard lock(_mutex); _permissions.clear(); } void IAllocation::removeExpiredPermissions() { - + std::lock_guard lock(_mutex); for (auto it = _permissions.begin(); it != _permissions.end();) { - if ((*it).timeout.expired()) { - LInfo("Removing Expired Permission: ", (*it).ip) + if (it->timeout.expired()) { + LInfo("Removing Expired Permission: ", it->ip); it = _permissions.erase(it); } else ++it; @@ -195,19 +204,20 @@ void IAllocation::removeExpiredPermissions() bool IAllocation::hasPermission(const std::string& peerIP) { - for (auto it = _permissions.begin(); it != _permissions.end(); ++it) { - if (*it == peerIP) + std::lock_guard lock(_mutex); + for (const auto& perm : _permissions) { + if (perm == peerIP) return true; } #if ENABLE_LOCAL_IPS if (peerIP.find("192.168.") == 0 || peerIP.find("127.") == 0) { - LWarn("Granting permission for local IP without explicit permission: ", peerIP) + LWarn("Granting permission for local IP without explicit permission: ", peerIP); return true; } #endif - LTrace("No permission for: ", peerIP) + LTrace("No permission for: ", peerIP); return false; } diff --git a/src/turn/src/server/server.cpp b/src/turn/src/server/server.cpp index c243036af..47d33a5a9 100644 --- a/src/turn/src/server/server.cpp +++ b/src/turn/src/server/server.cpp @@ -12,7 +12,10 @@ #include "scy/turn/server/server.h" #include "scy/buffer.h" #include "scy/logger.h" + #include +#include +#include using std::endl; @@ -27,32 +30,30 @@ namespace turn { Server::Server(ServerObserver& observer, const ServerOptions& options) : _observer(observer) , _options(options) - //, _udpSocket(net::makeSocket()) - //, _tcpSocket(net::makeSocket()) , _udpSocket(nullptr) , _tcpSocket(nullptr) { - LTrace("Create") + LTrace("Create"); } Server::~Server() { - LTrace("Destroy") + LTrace("Destroy"); stop(); - LTrace("Destroy: OK") + LTrace("Destroy: OK"); } void Server::start() { - LTrace("Starting") + LTrace("Starting"); if (_options.enableUDP) { _udpSocket.swap(net::makeSocket()); _udpSocket.Recv += slot(this, &Server::onSocketRecv, 1); _udpSocket->bind(_options.listenAddr); - LTrace("UDP listening on ", _options.listenAddr) + LTrace("UDP listening on ", _options.listenAddr); } if (_options.enableTCP) { @@ -61,7 +62,7 @@ void Server::start() _tcpSocket->listen(); _tcpSocket.as()->AcceptConnection += slot(this, &Server::onTCPAcceptConnection); - LTrace("TCP listening on ", _options.listenAddr) + LTrace("TCP listening on ", _options.listenAddr); } _timer.setInterval(_options.timerInterval); @@ -71,78 +72,87 @@ void Server::start() void Server::stop() { - LTrace("Stopping") + LTrace("Stopping"); _timer.stop(); - // Delete allocations - ServerAllocationMap allocations = this->allocations(); - for (auto it = allocations.begin(); it != allocations.end(); ++it) - delete it->second; - - // Should have been cleared via callback - assert(_allocations.empty()); + // Delete allocations - extract all first, then destroy outside lock + { + ServerAllocationMap doomed; + { + std::lock_guard lock(_mutex); + doomed.swap(_allocations); + } + // doomed is destroyed here + } // Free all TCP control sockets. - // Sockets should have a base reference - // count of 1 to ensure they are destroyed. _tcpSockets.clear(); // Close server sockets - //if (_udpSocket->active()) { + if (_udpSocket.impl) _udpSocket->close(); - //} - //if (_tcpSocket->active()) { + if (_tcpSocket.impl) _tcpSocket->close(); - //} } void Server::onTimer() { - ServerAllocationMap allocations = this->allocations(); - for (auto it = allocations.begin(); it != allocations.end(); ++it) { - // LTrace("Checking allocation: ", *it->second) - if (!it->second->onTimer()) { - // Entry removed via ServerAllocation destructor - delete it->second; + // Take a snapshot of raw pointers for iteration. + // Collect expired allocations, then erase them in a second pass. + auto allocs = allocations(); + std::vector toRemove; + for (auto& [tuple, alloc] : allocs) { + if (!alloc->onTimer()) { + toRemove.push_back(tuple); } } + + for (const auto& tuple : toRemove) { + // Extract the unique_ptr so destruction happens outside the lock + std::unique_ptr doomed; + { + std::lock_guard lock(_mutex); + auto it = _allocations.find(tuple); + if (it != _allocations.end()) { + doomed = std::move(it->second); + _allocations.erase(it); + } + } + // doomed is destroyed here, which calls ~ServerAllocation -> removeAllocation + // removeAllocation will not find it in the map (already erased), which is fine + } } void Server::onTCPAcceptConnection(const net::TCPSocket::Ptr& sock) { - LTrace("TCP connection accepted: ", sock->peerAddress()) + LTrace("TCP connection accepted: ", sock->peerAddress()); net::SocketEmitter emitter(sock); emitter.Recv += slot(this, &Server::onSocketRecv); emitter.Close += slot(this, &Server::onTCPSocketClosed); _tcpSockets.push_back(emitter); - - // No need to increase control socket buffer size - // TODO: make option - // setServerSocketBufSize(socket, SERVER_SOCK_BUF_SIZE); } net::TCPSocket::Ptr Server::getTCPSocket(const net::Address& peerAddr) { for (auto& sock : _tcpSockets) { - // LTrace("Get socket: ", sock->peerAddress(), ": ", peerAddr) if (sock->peerAddress() == peerAddr) { return std::dynamic_pointer_cast(sock.impl); } } - assert(0 && "unknown socket"); + LWarn("getTCPSocket: no socket found for ", peerAddr); return net::TCPSocket::Ptr(); } -void Server::onSocketRecv(net::Socket& socket, const MutableBuffer& buffer, +bool Server::onSocketRecv(net::Socket& socket, const MutableBuffer& buffer, const net::Address& peerAddress) { - LTrace("Data received: ", buffer.size()) + LTrace("Data received: ", buffer.size()); stun::Message message; char* buf = bufferCast(buffer); @@ -153,56 +163,42 @@ void Server::onSocketRecv(net::Socket& socket, const MutableBuffer& buffer, message.classType() == stun::Message::Indication) { Request request(message, socket.transport(), socket.address(), peerAddress); - // TODO: Only authenticate stun::Message::Request types + // Note: authenticates both Requests and Indications handleRequest(request, _observer.authenticateRequest(this, request)); } else { - assert(0 && "unknown request type"); + LWarn("Received unknown STUN message class: ", message.classType()); } buf += nread; len -= nread; } if (len == buffer.size()) - LWarn("Non STUN packet received") - -#if 0 - stun::Message message; - if (message.read(constBuffer(packet.data(), packet.size()))) { - assert(message.state() == stun::Message::Request); - - Request request(*info->socket, message, info->socket->address(), info->peerAddress); - AuthenticationState state = _observer.authenticateRequest(this, request); - handleRequest(request, state); - } - else -#endif + LWarn("Non STUN packet received"); + return false; } -void Server::onTCPSocketClosed(net::Socket& socket) +bool Server::onTCPSocketClosed(net::Socket& socket) { - LTrace("TCP socket closed") + LTrace("TCP socket closed"); releaseTCPSocket(socket); + return false; } void Server::releaseTCPSocket(const net::Socket& socket) { - LTrace("Removing TCP socket: ", &socket) + LTrace("Removing TCP socket: ", &socket); for (auto it = _tcpSockets.begin(); it != _tcpSockets.end(); ++it) { if (it->impl.get() == &socket) { it->Recv -= slot(this, &Server::onSocketRecv); it->Close -= slot(this, &Server::onTCPSocketClosed); - //socket->removeReceiver(this); - // All we need to do is erase the socket in order to - // deincrement the ref counter and destroy the socket. - // socket->close(); _tcpSockets.erase(it); return; } } - assert(0 && "unknown socket"); + LWarn("releaseTCPSocket: socket not found in list"); } @@ -213,20 +209,20 @@ void Server::handleRequest(Request& request, AuthenticationState state) << "\tData: " << request.toString() << endl; switch (state) { - case Authenticating: + case AuthenticationState::Authenticating: // await async response break; - case Authorized: + case AuthenticationState::Authorized: handleAuthorizedRequest(request); break; - case QuotaReached: - respondError(request, 486, "Allocation Quota Reached"); + case AuthenticationState::QuotaReached: + respondError(request, kErrorAllocationQuotaReached, "Allocation Quota Reached"); break; - case NotAuthorized: - respondError(request, 401, "NotAuthorized"); + case AuthenticationState::NotAuthorized: + respondError(request, kErrorNotAuthorized, "NotAuthorized"); break; } } @@ -234,26 +230,7 @@ void Server::handleRequest(Request& request, AuthenticationState state) void Server::handleAuthorizedRequest(Request& request) { - LTrace("Handle authorized request: ", request.toString()) - - // All requests after the initial Allocate must use the same username as - // that used to create the allocation, to prevent attackers from - // hijacking the client's allocation. Specifically, if the server - // requires the use of the long-term credential mechanism, and if a non- - // Allocate request passes authentication under this mechanism, and if - // the 5-tuple identifies an existing allocation, but the request does - // not use the same username as used to create the allocation, then the - // request MUST be rejected with a 441 (Wrong Credentials) error. - // - // When a TURN message arrives at the server from the client, the server - // uses the 5-tuple in the message to identify the associated - // allocation. For all TURN messages (including ChannelData) EXCEPT an - // Allocate request, if the 5-tuple does not identify an existing - // allocation, then the message MUST either be rejected with a 437 - // Allocation Mismatch error (if it is a request) or silently ignored - // (if it is an indication or a ChannelData message). A client - // receiving a 437 error response to a request other than Allocate MUST - // assume the allocation no longer exists. + LTrace("Handle authorized request: ", request.toString()); switch (request.methodType()) { case stun::Message::Binding: @@ -272,13 +249,13 @@ void Server::handleAuthorizedRequest(Request& request) FiveTuple tuple(request.remoteAddress, request.localAddress, request.transport); auto allocation = getAllocation(tuple); if (!allocation) { - respondError(request, 437, "Allocation Mismatch"); + respondError(request, kErrorAllocationMismatch, "Allocation Mismatch"); return; } - LTrace("Obtained allocation: ", tuple) + LTrace("Obtained allocation: ", tuple); if (!allocation->handleRequest(request)) - respondError(request, 600, "Operation Not Supported"); + respondError(request, kErrorOperationNotSupported, "Operation Not Supported"); } } } @@ -288,8 +265,8 @@ void Server::handleConnectionBindRequest(Request& request) { auto connAttr = request.get(); if (!connAttr) { - LTrace("ConnectionBind request has no ConnectionID") - respondError(request, 400, "Bad Request"); + LTrace("ConnectionBind request has no ConnectionID"); + respondError(request, kErrorBadRequest, "Bad Request"); return; } @@ -297,7 +274,7 @@ void Server::handleConnectionBindRequest(Request& request) if (!alloc) { STrace << "ConnectionBind request has no allocation for: " << connAttr->value() << endl; - respondError(request, 400, "Bad Request"); + respondError(request, kErrorBadRequest, "Bad Request"); return; } @@ -307,259 +284,81 @@ void Server::handleConnectionBindRequest(Request& request) void Server::handleBindingRequest(Request& request) { - LTrace("Handle Binding request") + LTrace("Handle Binding request"); - assert(request.methodType() == stun::Message::Binding); - assert(request.classType() == stun::Message::Request); + if (request.methodType() != stun::Message::Binding) + throw std::logic_error("handleBindingRequest called with non-Binding message"); + if (request.classType() != stun::Message::Request) + throw std::logic_error("handleBindingRequest called with non-Request class"); stun::Message response(stun::Message::SuccessResponse, stun::Message::Binding); - // response.setClass(stun::Message::Request); - // response.setMethod(stun::Message::Binding); response.setTransactionID(request.transactionID()); // XOR-MAPPED-ADDRESS auto addrAttr = new stun::XorMappedAddress; addrAttr->setAddress(request.remoteAddress); - // addrAttr->setFamily(1); - // addrAttr->setPort(request.remoteAddress.port()); - // addrAttr->setIP(request.remoteAddress.host()); response.add(addrAttr); - // request.socket->sendPacket(response, request.remoteAddress); respond(request, response); } void Server::handleAllocateRequest(Request& request) { - LTrace("Handle Allocate request") - - assert(request.methodType() == stun::Message::Allocate); - assert(request.classType() == stun::Message::Request); - - // When the server receives an Allocate request, it performs the - // following checks: - // - // 1. The server MUST require that the request be authenticated. This - // authentication MUST be done using the long-term credential - // mechanism of [RFC5389] unless the client and server agree to use - // another mechanism through some procedure outside the scope of - // this document. - // + LTrace("Handle Allocate request"); + + if (request.methodType() != stun::Message::Allocate) + throw std::logic_error("handleAllocateRequest called with non-Allocate message"); + if (request.classType() != stun::Message::Request) + throw std::logic_error("handleAllocateRequest called with non-Request class"); + auto usernameAttr = request.get(); if (!usernameAttr) { - LTrace("STUN Request not authorized ") - respondError(request, 401, "NotAuthorized"); + LTrace("STUN Request not authorized "); + respondError(request, kErrorNotAuthorized, "NotAuthorized"); return; } std::string username(usernameAttr->asString()); - // 2. The server checks if the 5-tuple is currently in use by an - // existing allocation. If yes, the server rejects the request with - // a 437 (Allocation Mismatch) error. - - // 3. The server checks if the request contains a REQUESTED-TRANSPORT - // attribute. If the REQUESTED-TRANSPORT attribute is not included - // or is malformed, the server rejects the request with a 400 (Bad - // Request) error. Otherwise, if the attribute is included but - // specifies a protocol other that UDP, the server rejects the - // request with a 442 (Unsupported Transport Protocol) error. - // auto transportAttr = request.get(); if (!transportAttr) { - LError("No Requested Transport") - respondError(request, 400, "Bad Request"); + LError("No Requested Transport"); + respondError(request, kErrorBadRequest, "Bad Request"); return; } int protocol = transportAttr->value() >> 24; - if (protocol != 6 && protocol != 17) { - LError("Requested Transport is neither TCP or UDP: ", protocol) - respondError(request, 422, "Unsupported Transport Protocol"); + if (protocol != kProtocolTCP && protocol != kProtocolUDP) { + LError("Requested Transport is neither TCP or UDP: ", protocol); + respondError(request, kErrorUnsupportedTransport, "Unsupported Transport Protocol"); return; } FiveTuple tuple(request.remoteAddress, request.localAddress, - protocol == 17 ? net::UDP : net::TCP); + protocol == kProtocolUDP ? net::UDP : net::TCP); if (getAllocation(tuple)) { - LError("Allocation already exists for 5tuple: ", tuple) - respondError(request, 437, "Allocation Mismatch"); + LError("Allocation already exists for 5tuple: ", tuple); + respondError(request, kErrorAllocationMismatch, "Allocation Mismatch"); return; } - // 4. The request may contain a DONT-FRAGMENT attribute. If it does, - // but the server does not support sending UDP datagrams with the DF - // bit set to 1 (see Section 12), then the server treats the DONT- - // FRAGMENT attribute in the Allocate request as an unknown - // comprehension-required attribute. - - // 5. The server checks if the request contains a RESERVATION-TOKEN - // attribute. If yes, and the request also contains an EVEN-PORT - // attribute, then the server rejects the request with a 400 (Bad - // Request) error. Otherwise, it checks to see if the token is - // valid (i.e., the token is in range and has not expired and the - // corresponding relayed transport address is still available). If - // the token is not valid for some reason, the server rejects the - // request with a 508 (Insufficient Capacity) error. - - // 6. The server checks if the request contains an EVEN-PORT attribute. - // If yes, then the server checks that it can satisfy the request - // (i.e., can allocate a relayed transport address as described - // below). If the server cannot satisfy the request, then the - // server rejects the request with a 508 (Insufficient Capacity) - // error. - - // 7. At any point, the server MAY choose to reject the request with a - // 486 (ServerAllocation Quota Reached) error if it feels the client is - // trying to exceed some locally defined allocation quota. The - // server is free to define this allocation quota any way it wishes, - // but SHOULD define it based on the username used to authenticate - // the request, and not on the client's transport address. - - // 8. Also at any point, the server MAY choose to reject the request - // with a 300 (Try Alternate) error if it wishes to redirect the - // client to a different server. The use of this error code and - // attribute follow the specification in [RFC5389]. - // Compute the appropriate LIFETIME for this allocation. uint32_t lifetime = min(options().allocationMaxLifetime / 1000, - options().allocationDefaultLifetime / 1000); + options().allocationDefaultLifetime / 1000); auto lifetimeAttr = request.get(); if (lifetimeAttr) lifetime = min(lifetime, lifetimeAttr->value()); - ServerAllocation* allocation = nullptr; - - // Protocol specific allocation handling. 6 = TCP, 17 = UDP. - if (protocol == 17) { // UDP - - // If all the checks pass, the server creates the allocation. The - // 5-tuple is set to the 5-tuple from the Allocate request, while the - // list of permissions and the list of channels are initially empty. - - // The server chooses a relayed transport address for the allocation as - // follows: - - // o If the request contains a RESERVATION-TOKEN, the server uses the - // previously reserved transport address corresponding to the - // included token (if it is still available). Note that the - // reservation is a server-wide reservation and is not specific to a - // particular allocation, since the Allocate request containing the - // RESERVATION-TOKEN uses a different 5-tuple than the Allocate - // request that made the reservation. The 5-tuple for the Allocate - // request containing the RESERVATION-TOKEN attribute can be any - // allowed 5-tuple; it can use a different client IP address and - // port, a different transport protocol, and even different server IP - // address and port (provided, of course, that the server IP address - // and port are ones on which the server is listening for TURN - // requests). - - // o If the request contains an EVEN-PORT attribute with the R bit set - // to 0, then the server allocates a relayed transport address with - // an even port number. - - // o If the request contains an EVEN-PORT attribute with the R bit set - // to 1, then the server looks for a pair of port numbers N and N+1 - // on the same IP address, where N is even. Port N is used in the - // current allocation, while the relayed transport address with port - // N+1 is assigned a token and reserved for a future allocation. The - // server MUST hold this reservation for at least 30 seconds, and MAY - // choose to hold longer (e.g., until the allocation with port N - // expires). The server then includes the token in a RESERVATION- - // TOKEN attribute in the success response. - - // o Otherwise, the server allocates any available relayed transport - // address. - - // In all cases, the server SHOULD only allocate ports from the range - // 49152 - 65535 (the Dynamic and/or Private Port range [Port-Numbers]), - // unless the TURN server application knows, through some means not - // specified here, that other applications running on the same host as - // the TURN server application will not be impacted by allocating ports - // outside this range. This condition can often be satisfied by running - // the TURN server application on a dedicated machine and/or by - // arranging that any other applications on the machine allocate ports - // before the TURN server application starts. In any case, the TURN - // server SHOULD NOT allocate ports in the range 0 - 1023 (the Well- - // Known Port range) to discourage clients from using TURN to run - // standard services. - - // NOTE: The IETF is currently investigating the topic of randomized - // port assignments to avoid certain types of attacks (see - // [TSVWG-PORT]). It is strongly recommended that a TURN implementor - // keep abreast of this topic and, if appropriate, implement a - // randomized port assignment algorithm. This is especially - // applicable to servers that choose to pre-allocate a number of - // ports from the underlying OS and then later assign them to - // allocations; for example, a server may choose this technique to - // implement the EVEN-PORT attribute. - - // The server determines the initial value of the time-to-expiry field - // as follows. If the request contains a LIFETIME attribute, then the - // server computes the minimum of the client's proposed lifetime and the - // server's maximum allowed lifetime. If this computed value is greater - // than the default lifetime, then the server uses the computed lifetime - // as the initial value of the time-to-expiry field. Otherwise, the - // server uses the default lifetime. It is RECOMMENDED that the server - // use a maximum allowed lifetime value of no more than 3600 seconds (1 - // hour). Servers that implement allocation quotas or charge clients - // for - // allocations in some way may wish to use a smaller maximum allowed - // lifetime (perhaps as small as the default lifetime) to more quickly - // remove orphaned allocations (that is, allocations where the - // corresponding client has crashed or isTerminated or the client - // IConnection has been lost for some reason). Also, note that the - // time- - // to-expiry is recomputed with each successful Refresh request, and - // thus the value computed here applies only until the first refresh. - - // Find or create the allocation matching the 5-TUPLE. If the allocation - // already exists then send an error. - allocation = new UDPAllocation(*this, tuple, username, lifetime); - } + std::unique_ptr allocation; - else if (protocol == 6) { /// TCP - - // 5.1. Receiving a TCP Allocate Request - // - // - // The process is similar to that defined in [RFC5766], Section 6.2, - // with the following exceptions: - // - // 1. If the REQUESTED-TRANSPORT attribute is included and specifies a - // protocol other than UDP or TCP, the server MUST reject the - // request with a 442 (Unsupported Transport Protocol) error. If - // the value is UDP, and if UDP transport is allowed by local - // policy, the server MUST continue with the procedures of [RFC5766] - // instead of this document. If the value is UDP, and if UDP - // transport is forbidden by local policy, the server MUST reject - // the request with a 403 (Forbidden) error. - // - // 2. If the client connection transport is not TCP or TLS, the server - // MUST reject the request with a 400 (Bad Request) error. - // - // 3. If the request contains the DONT-FRAGMENT, EVEN-PORT, or - // RESERVATION-TOKEN attribute, the server MUST reject the request - // with a 400 (Bad Request) error. - // - // 4. A TCP relayed transport address MUST be allocated instead of a - // UDP one. - // - // 5. The RESERVATION-TOKEN attribute MUST NOT be present in the - // success response. - // - // If all checks pass, the server MUST start accepting incoming TCP - // connections on the relayed transport address. Refer to Section 5.3 - // for details. - - // net::TCPSocket& socket = static_cast(request.socket); - // static_cast(request.socket) - // assert(request.socket->/*base().*/refCount() == 1); - allocation = new TCPAllocation(*this, getTCPSocket(request.remoteAddress), tuple, - username, lifetime); // request.socket - // assert(request.socket->/*base().*/refCount() == 2); + // Protocol specific allocation handling. + if (protocol == kProtocolUDP) { + allocation = std::make_unique(*this, tuple, username, lifetime); + } else if (protocol == kProtocolTCP) { + allocation = std::make_unique(*this, getTCPSocket(request.remoteAddress), tuple, + username, lifetime); } // Once the allocation is created, the server replies with a success @@ -571,14 +370,14 @@ void Server::handleAllocateRequest(Request& request) // o An XOR-RELAYED-ADDRESS attribute containing the relayed transport // address. - assert(!options().externalIP.empty()); + if (options().externalIP.empty()) + throw std::runtime_error("external IP not configured on TURN server"); // Try to use the externalIP value for the XorRelayedAddress // attribute to overcome proxy and NAT issues. std::string relayHost(options().externalIP); if (relayHost.empty()) { relayHost.assign(allocation->relayedAddress().host()); - assert(0 && "external IP not set"); } auto relayAddrAttr = new stun::XorRelayedAddress; @@ -589,25 +388,13 @@ void Server::handleAllocateRequest(Request& request) // o A LIFETIME attribute containing the current value of the time-to- // expiry timer. auto resLifetimeAttr = new stun::Lifetime; - resLifetimeAttr->setValue(lifetime); // / 1000 + resLifetimeAttr->setValue(lifetime); response.add(resLifetimeAttr); - // o A RESERVATION-TOKEN attribute (if a second relayed transport - // address was reserved). - // o An XOR-MAPPED-ADDRESS attribute containing the client's IP address // and port (from the 5-tuple). - - // NOTE: The XOR-MAPPED-ADDRESS attribute is included in the response - // as a convenience to the client. TURN itself does not make use of - // this value, but clients running ICE can often need this value and - // can thus avoid having to do an extra Binding transaction with some - // STUN server to learn it. auto mappedAddressAttr = new stun::XorMappedAddress; mappedAddressAttr->setAddress(request.remoteAddress); - // mappedAddressAttr->setFamily(1); - // mappedAddressAttr->setIP(request.remoteAddress.host()); - // mappedAddressAttr->setPort(request.remoteAddress.port()); response.add(mappedAddressAttr); STrace << "Allocate response: " @@ -615,51 +402,12 @@ void Server::handleAllocateRequest(Request& request) << ", XorMappedAddress=" << mappedAddressAttr->address() << ", MessageIntegrity=" << request.hash << endl; - // Sign the response message - // auto integrityAttr = new stun::MessageIntegrity; - // integrityAttr->setKey(request.hash); - // response.add(integrityAttr); - - // The response (either success or error) is sent back to the client on - // the 5-tuple. - // request.socket->send(response, request.remoteAddress); respond(request, response); - LTrace("Handle Allocate request: OK") - - // NOTE: When the Allocate request is sent over UDP, section 7.3.1 of - // [RFC5389] requires that the server handle the possible - // retransmissions of the request so that retransmissions do not - // cause multiple allocations to be created. Implementations may - // achieve this using the so-called "stateless stack approach" as - // follows. To detect retransmissions when the original request was - // successful in creating an allocation, the server can store the - // transaction id that created the request with the allocation data - // and compare it with incoming Allocate requests on the same - // 5-tuple. Once such a request is detected, the server can stop - // parsing the request and immediately generate a success response. - // When building this response, the value of the LIFETIME attribute - // can be taken from the time-to-expiry field in the allocate state - // data, even though this value may differ slightly from the LIFETIME - // value originally returned. In addition, the server may need to - // store an indication of any reservation token returned in the - // original response, so that this may be returned in any - // retransmitted responses. - - // For the case where the original request was unsuccessful in - // creating an allocation, the server may choose to do nothing - // special. Note, however, that there is a rare case where the - // server rejects the original request but accepts the retransmitted - // request (because conditions have changed in the brief intervening - // time period). If the client receives the first failure response, - // it will ignore the second (success) response and believe that an - // allocation was not created. An allocation created in this matter - // will eventually timeout, since the client will not refresh it. - // Furthermore, if the client later retries with the same 5-tuple but - // different transaction id, it will receive a 437 (ServerAllocation - // Mismatch), which will cause it to retry with a different 5-tuple. - // The server may use a smaller maximum lifetime value to minimize - // the lifetime of allocations "orphaned" in this manner. + // Register the allocation with the server (transfers ownership) + addAllocation(std::move(allocation)); + + LTrace("Handle Allocate request: OK"); } @@ -672,7 +420,7 @@ void Server::respond(Request& request, stun::Message& response) response.add(integrityAttr); } - LTrace("Sending message: ", response, ": ", request.remoteAddress) + LTrace("Sending message: ", response, ": ", request.remoteAddress); // The response (either success or error) is sent back to the // client on the 5-tuple. @@ -692,7 +440,7 @@ void Server::respond(Request& request, stun::Message& response) void Server::respondError(Request& request, int errorCode, const char* errorDesc) { - LTrace("Send STUN error: ", errorCode, ": ", errorDesc) + LTrace("Send STUN error: ", errorCode, ": ", errorDesc); stun::Message errorMsg(stun::Message::ErrorResponse, request.methodType()); errorMsg.setTransactionID(request.transactionID()); @@ -719,9 +467,9 @@ void Server::respondError(Request& request, int errorCode, errorCodeAttr->setErrorCode(errorCode); errorCodeAttr->setReason(errorDesc); errorMsg.add(errorCodeAttr); - assert(errorCode == errorCodeAttr->errorCode()); + if (errorCode != errorCodeAttr->errorCode()) + LWarn("Error code mismatch in respondError: ", errorCode, " vs ", errorCodeAttr->errorCode()); - // request.socket->sendPacket(errorMsg, request.remoteAddress); respond(request, errorMsg); } @@ -740,7 +488,6 @@ net::TCPSocket& Server::tcpSocket() ServerObserver& Server::observer() { - return _observer; } @@ -751,9 +498,14 @@ ServerOptions& Server::options() } -ServerAllocationMap Server::allocations() const +std::map Server::allocations() const { - return _allocations; + std::lock_guard lock(_mutex); + std::map result; + for (const auto& [tuple, alloc] : _allocations) { + result[tuple] = alloc.get(); + } + return result; } @@ -763,31 +515,38 @@ Timer& Server::timer() } -void Server::addAllocation(ServerAllocation* alloc) +void Server::addAllocation(std::unique_ptr alloc) { + auto* raw = alloc.get(); { - assert(_allocations.find(alloc->tuple()) == _allocations.end()); - _allocations[alloc->tuple()] = alloc; + std::lock_guard lock(_mutex); + if (_allocations.find(raw->tuple()) != _allocations.end()) + throw std::logic_error("allocation already exists for tuple: " + raw->tuple().toString()); + _allocations[raw->tuple()] = std::move(alloc); - SDebug << "Allocation added: " << alloc->tuple().toString() << ": " + SDebug << "Allocation added: " << raw->tuple().toString() << ": " << _allocations.size() << " total" << endl; } - _observer.onServerAllocationCreated(this, alloc); + _observer.onServerAllocationCreated(this, raw); } void Server::removeAllocation(ServerAllocation* alloc) { { + std::lock_guard lock(_mutex); auto it = _allocations.find(alloc->tuple()); if (it != _allocations.end()) { + // Release ownership but don't erase yet - the caller (destructor) owns the memory + it->second.release(); _allocations.erase(it); SDebug << "Allocation removed: " << alloc->tuple().toString() << ": " << _allocations.size() << " remaining" << endl; - } else - assert(0); + } + // If not found, the allocation was already removed from the map + // (e.g., by onTimer or stop) before the destructor ran - this is normal. } _observer.onServerAllocationRemoved(this, alloc); @@ -796,30 +555,29 @@ void Server::removeAllocation(ServerAllocation* alloc) ServerAllocation* Server::getAllocation(const FiveTuple& tuple) { + std::lock_guard lock(_mutex); auto it = _allocations.find(tuple); if (it != _allocations.end()) - return it->second; + return it->second.get(); return nullptr; } TCPAllocation* Server::getTCPAllocation(const uint32_t& connectionID) { - for (auto it = _allocations.begin(); it != _allocations.end(); ++it) { - auto alloc = dynamic_cast(it->second); + std::lock_guard lock(_mutex); + for (auto& [tuple, alloc_ptr] : _allocations) { + auto alloc = dynamic_cast(alloc_ptr.get()); if (alloc && alloc->pairs().exists(connectionID)) return alloc; } - // TODO: Handle via allocation so we can remove lookup overhead. - // The TCP allocation may have been deleted before the - // ConnectionBind request comes in. - // assert(0 && "allocation mismatch"); return nullptr; } -} } // namespace scy::turn +} // namespace turn +} // namespace scy /// @\} diff --git a/src/turn/src/server/serverallocation.cpp b/src/turn/src/server/serverallocation.cpp index bd20d741e..6b0f8a4e3 100644 --- a/src/turn/src/server/serverallocation.cpp +++ b/src/turn/src/server/serverallocation.cpp @@ -9,14 +9,12 @@ /// @{ -#include "scy/turn/server/server.h" #include "scy/logger.h" +#include "scy/turn/server/server.h" #include "scy/util.h" #include - - -using namespace std; +#include namespace scy { @@ -30,7 +28,10 @@ ServerAllocation::ServerAllocation(Server& server, const FiveTuple& tuple, , _maxLifetime(server.options().allocationMaxLifetime / 1000) , _server(server) { - _server.addAllocation(this); + // Note: the allocation registers itself with the server via + // Server::addAllocation(), which is called from the concrete + // allocation constructors (UDPAllocation, TCPAllocation) or + // from Server::handleAllocateRequest() after construction. } @@ -42,10 +43,10 @@ ServerAllocation::~ServerAllocation() bool ServerAllocation::handleRequest(Request& request) { - LTrace("Handle Request") + LTrace("Handle Request"); if (IAllocation::deleted()) { - LWarn("Dropping request for deleted allocation") + LWarn("Dropping request for deleted allocation"); return false; } @@ -62,23 +63,11 @@ bool ServerAllocation::handleRequest(Request& request) void ServerAllocation::handleRefreshRequest(Request& request) { - LTrace("Handle Refresh Request") - assert(request.methodType() == stun::Message::Refresh); - assert(request.classType() == stun::Message::Request); - - // 7.2. Receiving a Refresh Request - - // When the server receives a Refresh request, it processes as per - // Section 4 plus the specific rules mentioned here. - - // The server computes a value called the "desired lifetime" as follows: - // if the request contains a LIFETIME attribute and the attribute value - // is 0, then the "desired lifetime" is 0. Otherwise, if the request - // contains a LIFETIME attribute, then the server computes the minimum - // of the client's requested lifetime and the server's maximum allowed - // lifetime. If this computed value is greater than the default - // lifetime, then the "desired lifetime" is the computed value. - // Otherwise, the "desired lifetime" is the default lifetime. + LTrace("Handle Refresh Request"); + if (request.methodType() != stun::Message::Refresh) + throw std::logic_error("handleRefreshRequest called with non-Refresh message"); + if (request.classType() != stun::Message::Request) + throw std::logic_error("handleRefreshRequest called with non-Request class"); // Compute the appropriate LIFETIME for this allocation. auto lifetimeAttr = request.get(); @@ -87,38 +76,15 @@ void ServerAllocation::handleRefreshRequest(Request& request) } uint32_t desiredLifetime = std::min( _server.options().allocationMaxLifetime / 1000, lifetimeAttr->value()); - // lifetime = min(lifetime, lifetimeAttr->value() * 1000); - // Subsequent processing depends on the "desired lifetime" value: - - // o If the "desired lifetime" is 0, then the request succeeds and the - // allocation is deleted. - - // o If the "desired lifetime" is non-zero, then the request succeeds - // and the allocation's time-to-expiry is set to the "desired - // lifetime". - - if (desiredLifetime > 0) + if (desiredLifetime > 0) { setLifetime(desiredLifetime); - else { - delete this; + } else { + // Signal the parent to delete this allocation instead of `delete this` + _refreshDeleteRequested = true; } - // If the request succeeds, then the server sends a success response - // containing: - - // o A LIFETIME attribute containing the current value of the time-to- - // expiry timer. - - // NOTE: A server need not do anything special to implement - // idempotency of Refresh requests over UDP using the "stateless - // stack approach". Retransmitted Refresh requests with a non-zero - // "desired lifetime" will simply refresh the allocation. A - // retransmitted Refresh request with a zero "desired lifetime" will - // cause a 437 (Allocation Mismatch) response if the allocation has - // already been deleted, but the client will treat this as equivalent - // to a success response (see below). - + // If the request succeeds, then the server sends a success response. stun::Message response(stun::Message::SuccessResponse, stun::Message::Refresh); response.setTransactionID(request.transactionID()); @@ -128,50 +94,18 @@ void ServerAllocation::handleRefreshRequest(Request& request) response.add(resLifetimeAttr); _server.respond(request, response); - // request.socket->send(response, request.remoteAddress); } void ServerAllocation::handleCreatePermission(Request& request) { - LTrace("Handle Create Permission") - - // 9.2. Receiving a CreatePermission Request - // - // When the server receives the CreatePermission request, it processes - // as per Section 4 plus the specific rules mentioned here. - // - // The message is checked for validity. The CreatePermission request - // MUST contain at least one XOR-PEER-ADDRESS attribute and MAY contain - // multiple such attributes. If no such attribute exists, or if any of - // these attributes are invalid, then a 400 (Bad Request) error is - // returned. If the request is valid, but the server is unable to - // satisfy the request due to some capacity limit or similar, then a 508 - // (Insufficient Capacity) error is returned. - // - // The server MAY impose restrictions on the IP address allowed in the - // XOR-PEER-ADDRESS attribute -- if a value is not allowed, the server - // rejects the request with a 403 (Forbidden) error. - // - // If the message is valid and the server is capable of carrying out the - // request, then the server installs or refreshes a permission for the - // IP address contained in each XOR-PEER-ADDRESS attribute as described - // in Section 8. The port portion of each attribute is ignored and may - // be any arbitrary value. - // - // The server then responds with a CreatePermission success response. - // There are no mandatory attributes in the success response. - // - // NOTE: A server need not do anything special to implement - // idempotency of CreatePermission requests over UDP using the - // "stateless stack approach". Retransmitted CreatePermission - // requests will simply refresh the permissions. - // + LTrace("Handle Create Permission"); + for (int i = 0; i < _server.options().allocationMaxPermissions; i++) { auto peerAttr = request.get(i); - if (!peerAttr || (peerAttr && peerAttr->family() != 1)) { + if (!peerAttr || peerAttr->family() != stun::AddressFamily::IPv4) { if (i == 0) { - _server.respondError(request, 400, "Bad Request"); + _server.respondError(request, kErrorBadRequest, "Bad Request"); return; } else break; @@ -184,13 +118,12 @@ void ServerAllocation::handleCreatePermission(Request& request) response.setTransactionID(request.transactionID()); _server.respond(request, response); - // request.socket->send(response, request.remoteAddress); } bool ServerAllocation::onTimer() { - LTrace("ServerAllocation: On timer: ", IAllocation::deleted()) + LTrace("ServerAllocation: On timer: ", IAllocation::deleted()); if (IAllocation::deleted()) return false; // bye bye @@ -208,14 +141,12 @@ std::int64_t ServerAllocation::maxTimeRemaining() const std::int64_t ServerAllocation::timeRemaining() const { - - return min(IAllocation::timeRemaining(), maxTimeRemaining()); + return std::min(IAllocation::timeRemaining(), maxTimeRemaining()); } Server& ServerAllocation::server() { - return _server; } @@ -231,7 +162,7 @@ void ServerAllocation::print(std::ostream& os) const << "\n\tTime Remaining=" << timeRemaining() << "\n\tMax Time Remaining=" << maxTimeRemaining() << "\n\tDeletable=" << IAllocation::deleted() - << "\n\tExpired=" << expired() << "]" << endl; + << "\n\tExpired=" << expired() << "]" << std::endl; } diff --git a/src/turn/src/server/tcpallocation.cpp b/src/turn/src/server/tcpallocation.cpp index 7a8818e8d..636a50eb7 100644 --- a/src/turn/src/server/tcpallocation.cpp +++ b/src/turn/src/server/tcpallocation.cpp @@ -13,8 +13,7 @@ #include "scy/logger.h" #include "scy/turn/server/server.h" - -using namespace std; +#include namespace scy { @@ -37,80 +36,46 @@ TCPAllocation::TCPAllocation(Server& server, const net::Socket::Ptr& control, // The allocation will be deleted if the control connection is lost. _control.Close += slot(this, &TCPAllocation::onControlClosed); - LTrace("Initializing on ", _acceptor->address()) + LTrace("Initializing on ", _acceptor->address()); } TCPAllocation::~TCPAllocation() { - LTrace("Destroy TCP allocation") + LTrace("Destroy TCP allocation"); - - _acceptor.as()->AcceptConnection -= slot(this, &TCPAllocation::onPeerAccept); + _acceptor.as() + ->AcceptConnection -= slot(this, &TCPAllocation::onPeerAccept); _acceptor->close(); _control.Close -= slot(this, &TCPAllocation::onControlClosed); _control->close(); - auto pairs = this->pairs().map(); - for (auto it = pairs.begin(); it != pairs.end(); ++it) { - // The allocation will be removed via callback - delete it->second; - } - assert(this->pairs().empty()); + this->pairs().clear(); + - LTrace("Destroy TCP allocation: OK") + LTrace("Destroy TCP allocation: OK"); } void TCPAllocation::onPeerAccept(const net::TCPSocket::Ptr& socket) { - LTrace("Peer connection accepted: ", socket->peerAddress()) - - // 5.3. Receiving a TCP Connection on a Relayed Transport Address - // - // When a server receives an incoming TCP connection on a relayed - // transport address, it processes the request as follows. - // - // The server MUST accept the connection. If it is not successful, - // nothing is sent to the client over the control connection. - // - // If the connection is successfully accepted, it is now called a peer - // data connection. The server MUST buffer any data received from the - // peer. The server adjusts its advertised TCP receive window to - // reflect the amount of empty buffer space. - // - // If no permission for this peer has been installed for this - // allocation, the server MUST close the connection with the peer - // immediately after it has been accepted. - // + LTrace("Peer connection accepted: ", socket->peerAddress()); + if (!hasPermission(socket->peerAddress().host())) { - LTrace("No permission for peer: ", socket->peerAddress()) + LTrace("No permission for peer: ", socket->peerAddress()); return; } - LTrace("Has permission for: ", socket->peerAddress()) - - // Otherwise, the server sends a ConnectionAttempt indication to the - // client over the control connection. The indication MUST include an - // XOR-PEER-ADDRESS attribute containing the peer's transport address, - // as well as a CONNECTION-ID attribute uniquely identifying the peer - // data connection. - // + LTrace("Has permission for: ", socket->peerAddress()); + auto pair = new TCPConnectionPair(*this); - // assert(socket->/*base().*/refCount() == 1); pair->setPeerSocket(socket); - // assert(socket->/*base().*/refCount() == 2); stun::Message response(stun::Message::Indication, stun::Message::ConnectionAttempt); - // stun::Message response; - // response.setType(stun::Message::ConnectionAttempt); auto addrAttr = new stun::XorPeerAddress; addrAttr->setAddress(socket->peerAddress()); - // addrAttr->setFamily(1); - // addrAttr->setPort(socket->peerAddress().port()); - // addrAttr->setIP(socket->peerAddress().host()); response.add(addrAttr); auto connAttr = new stun::ConnectionID; @@ -120,13 +85,13 @@ void TCPAllocation::onPeerAccept(const net::TCPSocket::Ptr& socket) sendToControl(response); STrace << "Peer connection accepted with ID: " << pair->connectionID - << endl; + << std::endl; } bool TCPAllocation::handleRequest(Request& request) { - LTrace("Handle request") + LTrace("Handle request"); if (!ServerAllocation::handleRequest(request)) { if (request.methodType() == stun::Message::Connect) @@ -143,16 +108,21 @@ bool TCPAllocation::handleRequest(Request& request) bool TCPAllocation::onTimer() { - LTrace("On timer") + LTrace("On timer"); // Clean up any expired Connect request peer connections. - auto pairs = this->pairs().map(); - for (auto it = pairs.begin(); it != pairs.end(); ++it) { - if (it->second->expired()) { - LTrace("On timer: Removing expired peer") - this->pairs().free(it->first); + // Collect keys first since free() modifies the map. + std::vector + expired; + for (auto& [key, pair] : this->pairs().map()) { + if (pair->expired() || pair->pendingDelete) { + LTrace("On timer: Removing expired/deleted peer"); + expired.push_back(key); } } + for (auto key : expired) { + this->pairs().free(key); + } return ServerAllocation::onTimer(); } @@ -160,46 +130,14 @@ bool TCPAllocation::onTimer() void TCPAllocation::handleConnectRequest(Request& request) { - LTrace("Handle Connect request") - - // 5.2. Receiving a Connect Request - // - // When the server receives a Connect request, it processes the request - // as follows. - // - // If the request is received on a TCP connection for which no - // allocation exists, the server MUST return a 437 (Allocation Mismatch) - // error. - // - // If the server is currently processing a Connect request for this - // allocation with the same XOR-PEER-ADDRESS, it MUST return a 446 - // (Connection Already Exists) error. - // - // If the server has already successfully processed a Connect request - // for this allocation with the same XOR-PEER-ADDRESS, and the resulting - // client and peer data connections are either pending or active, it - // MUST return a 446 (Connection Already Exists) error. - // - // If the request does not contain an XOR-PEER-ADDRESS attribute, or if - // such attribute is invalid, the server MUST return a 400 (Bad Request) - // error. - // - // If the new connection is forbidden by local policy, the server MUST - // reject the request with a 403 (Forbidden) error. - // + LTrace("Handle Connect request"); + auto peerAttr = request.get(); - if (!peerAttr || (peerAttr && peerAttr->family() != 1)) { - server().respondError(request, 400, "Bad Request"); + if (!peerAttr || peerAttr->family() != stun::AddressFamily::IPv4) { + server().respondError(request, kErrorBadRequest, "Bad Request"); return; } - // Otherwise, the server MUST initiate an outgoing TCP connection. - // The local endpoint is the relayed transport address associated with - // the allocation. The remote endpoint is the one indicated by the - // XOR-PEER-ADDRESS attribute. If the connection attempt fails or times - // out, the server MUST return a 447 (Connection Timeout or Failure) - // error. The timeout value MUST be at least 30 seconds. - // auto pair = new TCPConnectionPair(*this); pair->transactionID = request.transactionID(); pair->doPeerConnect(peerAttr->address()); @@ -208,45 +146,25 @@ void TCPAllocation::handleConnectRequest(Request& request) void TCPAllocation::handleConnectionBindRequest(Request& request) { - LTrace("Handle ConnectionBind Request") + LTrace("Handle ConnectionBind Request"); + + if (request.methodType() != stun::Message::ConnectionBind) + throw std::logic_error("handleConnectionBindRequest called with wrong method"); - assert(request.methodType() == stun::Message::ConnectionBind); TCPConnectionPair* pair = nullptr; auto socket = _server.getTCPSocket(request.remoteAddress); try { if (!socket) throw std::runtime_error("Invalid TCP socket"); - // 5.4. Receiving a ConnectionBind Request - // - // When a server receives a ConnectionBind request, it processes the - // request as follows. - // - // If the client connection transport is not TCP or TLS, the server MUST - // return a 400 (Bad Request) error. - // - if (request.transport != net::TCP) // TODO: TLS!! - throw std::runtime_error( - "TLS not supported"); // easy to implement, fixme! + if (request.transport != net::TCP) + throw std::runtime_error("TLS not supported"); - // If the request does not contain the CONNECTION-ID attribute, or if - // this attribute does not refer to an existing pending connection, the - // server MUST return a 400 (Bad Request) error. - // auto connAttr = request.get(); if (!connAttr) throw std::runtime_error( "ConnectionBind missing CONNECTION-ID attribute"); - // Otherwise, the client connection is now called a client data - // connection. Data received on it MUST be sent as-is to the associated - // peer data connection. - // - // Data received on the associated peer data connection MUST be sent - // as-is on this client data connection. This includes data that was - // received after the associated Connect or request was successfully - // processed and before this ConnectionBind request was received. - // pair = pairs().get(connAttr->value(), false); if (!pair) { throw std::runtime_error("No client for ConnectionBind request: " + @@ -254,7 +172,6 @@ void TCPAllocation::handleConnectionBindRequest(Request& request) } if (pair->isDataConnection) { - assert(0); throw std::runtime_error("Already a peer data connection: " + util::itostr(connAttr->value())); } @@ -273,13 +190,15 @@ void TCPAllocation::handleConnectionBindRequest(Request& request) throw std::runtime_error("BUG: Data connection binding failed"); } - assert(pair->isDataConnection); + if (!pair->isDataConnection) + throw std::logic_error("Data connection flag not set after makeDataConnection"); } catch (std::exception& exc) { - LError("ConnectionBind error: ", exc.what()) - server().respondError(request, 400, "Bad Request"); + LError("ConnectionBind error: ", exc.what()); + server() + .respondError(request, kErrorBadRequest, "Bad Request"); if (pair && !pair->isDataConnection) { - delete pair; + pairs().free(pair->connectionID); } // Close the incoming connection @@ -290,19 +209,11 @@ void TCPAllocation::handleConnectionBindRequest(Request& request) void TCPAllocation::sendPeerConnectResponse(TCPConnectionPair* pair, bool success) { - LTrace("Send peer Connect response: ", success) - - assert(!pair->transactionID.empty()); - - // If the connection is successful, it is now called a peer data - // connection. The server MUST buffer any data received from the - // client. The server adjusts its advertised TCP receive window to - // reflect the amount of empty buffer space. - // - // The server MUST include the CONNECTION-ID attribute in the Connect - // success response. The attribute's value MUST uniquely identify the - // peer data connection. - // + LTrace("Send peer Connect response: ", success); + + if (pair->transactionID.empty()) + throw std::logic_error("sendPeerConnectResponse called with empty transactionID"); + stun::Message response(stun::Message::SuccessResponse, stun::Message::Connect); response.setTransactionID(pair->transactionID); @@ -313,7 +224,7 @@ void TCPAllocation::sendPeerConnectResponse(TCPConnectionPair* pair, bool succes response.add(connAttr); } else { auto errorCodeAttr = new stun::ErrorCode(); - errorCodeAttr->setErrorCode(447); + errorCodeAttr->setErrorCode(kErrorConnectionTimeoutOrFailure); errorCodeAttr->setReason("Connection Timeout or Failure"); response.add(errorCodeAttr); } @@ -324,18 +235,19 @@ void TCPAllocation::sendPeerConnectResponse(TCPConnectionPair* pair, bool succes int TCPAllocation::sendToControl(stun::Message& message) { - LTrace("Send to control: ", message) + LTrace("Send to control: ", message); return _control->sendPacket(message, 0); } -void TCPAllocation::onControlClosed(net::Socket& socket) +bool TCPAllocation::onControlClosed(net::Socket& socket) { - LTrace("Control socket disconnected") + LTrace("Control socket disconnected"); // The allocation will be destroyed on the // next timer call to IAllocation::deleted() _deleted = true; + return false; } @@ -357,7 +269,8 @@ net::Address TCPAllocation::relayedAddress() const } -} } // namespace scy::turn +} // namespace turn +} // namespace scy /// @\} diff --git a/src/turn/src/server/tcpconnectionpair.cpp b/src/turn/src/server/tcpconnectionpair.cpp index 31b03831b..68c6ef48e 100644 --- a/src/turn/src/server/tcpconnectionpair.cpp +++ b/src/turn/src/server/tcpconnectionpair.cpp @@ -10,13 +10,12 @@ #include "scy/turn/server/tcpconnectionpair.h" +#include "scy/crypto/crypto.h" +#include "scy/net/util.h" #include "scy/turn/server/server.h" #include "scy/turn/server/tcpallocation.h" -#include "scy/net/util.h" -#include "scy/crypto/crypto.h" - -using namespace std; +#include namespace scy { @@ -34,13 +33,13 @@ TCPConnectionPair::TCPConnectionPair(TCPAllocation& allocation) while (!allocation.pairs().add(connectionID, this, false)) { connectionID = util::randomNumber(); } - LTrace("Create: ", connectionID) + LTrace("Create: ", connectionID); } TCPConnectionPair::~TCPConnectionPair() { - LTrace("Destroy: ", connectionID) + LTrace("Destroy: ", connectionID); if (client.impl) { client.Recv -= slot(this, &TCPConnectionPair::onClientDataReceived); @@ -55,17 +54,20 @@ TCPConnectionPair::~TCPConnectionPair() peer->close(); } - assert(allocation.pairs().exists(connectionID)); - allocation.pairs().remove(connectionID); + if (!allocation.pairs().exists(connectionID)) + LWarn("Connection pair not found in allocation pairs during destruction: ", connectionID); + allocation.pairs() + .remove(connectionID); } bool TCPConnectionPair::doPeerConnect(const net::Address& peerAddr) { try { - assert(!transactionID.empty()); + if (transactionID.empty()) + throw std::logic_error("transactionID must be set before doPeerConnect"); peer.swap(std::make_shared()); - peer.impl->opaque = this; + peer.impl->opaque = static_cast(this); peer.Close += slot(this, &TCPConnectionPair::onConnectionClosed); // Start receiving early media @@ -77,8 +79,7 @@ bool TCPConnectionPair::doPeerConnect(const net::Address& peerAddr) client->connect(peerAddr); } catch (std::exception& exc) { - LError("Peer connect error: ", exc.what()) - assert(0); + LError("Peer connect error: ", exc.what()); return false; } return true; @@ -88,9 +89,10 @@ bool TCPConnectionPair::doPeerConnect(const net::Address& peerAddr) void TCPConnectionPair::setPeerSocket(const net::TCPSocket::Ptr& socket) { STrace << "Set peer socket: " << connectionID << ": " - << socket->peerAddress() << endl; + << socket->peerAddress() << std::endl; - assert(!peer.impl); + if (peer.impl) + throw std::logic_error("peer socket already set for connection pair"); peer.swap(socket); peer.Close += slot(this, &TCPConnectionPair::onConnectionClosed); @@ -98,27 +100,28 @@ void TCPConnectionPair::setPeerSocket(const net::TCPSocket::Ptr& socket) peer.Recv += slot(this, &TCPConnectionPair::onPeerDataReceived); net::setServerSocketRecvBufSize( - *socket.get(), SERVER_SOCK_BUF_SIZE); // TODO: make option + *socket.get(), SERVER_SOCK_BUF_SIZE); } void TCPConnectionPair::setClientSocket(const net::TCPSocket::Ptr& socket) { STrace << "Set client socket: " << connectionID << ": " - << socket->peerAddress() << endl; + << socket->peerAddress() << std::endl; - assert(!client.impl); + if (client.impl) + throw std::logic_error("client socket already set for connection pair"); client.swap(socket); client.Close += slot(this, &TCPConnectionPair::onConnectionClosed); net::setServerSocketRecvBufSize( - *socket.get(), SERVER_SOCK_BUF_SIZE); // TODO: make option + *socket.get(), SERVER_SOCK_BUF_SIZE); } bool TCPConnectionPair::makeDataConnection() { - LTrace("Make data connection: ", connectionID) + LTrace("Make data connection: ", connectionID); if (!peer.impl || !client.impl) return false; @@ -133,7 +136,7 @@ bool TCPConnectionPair::makeDataConnection() // Send early data from peer to client if (earlyPeerData.size()) { - LTrace("Flushing early media: ", earlyPeerData.size()) + LTrace("Flushing early media: ", earlyPeerData.size()); client->send(earlyPeerData.data(), earlyPeerData.size()); earlyPeerData.clear(); } @@ -142,87 +145,63 @@ bool TCPConnectionPair::makeDataConnection() } -void TCPConnectionPair::onPeerDataReceived(net::Socket&, +bool TCPConnectionPair::onPeerDataReceived(net::Socket&, const MutableBuffer& buffer, const net::Address& peerAddress) { - LTrace("Peer > Client: ", buffer.size()) - // assert(pkt.buffer.position() == 0); - // if (pkt.buffer.available() < 300) - // LTrace("Peer => Client: ", pkt.buffer) - // auto socket = reinterpret_cast(sender); - // char* buf = bufferCast(buf); - - // Buffer& buf = pkt.buffer; + LTrace("Peer > Client: ", buffer.size()); + const char* buf = bufferCast(buffer); size_t len = buffer.size(); if (client.impl) { allocation.updateUsage(len); if (allocation.deleted()) - return; + return false; - // assert(buf.position() == 0); client->send(buf, len); } -#if 0 - // Flash policy requests - // TODO: Handle elsewhere? Bloody flash... - else if (len == 23 && (strcmp(buf, "") == 0)) { - LTrace("Handle flash policy") - std::string policy( - ""); - // assert(peer->get() == pkt.info->socket); - peer->send(policy.c_str(), policy.length() + 1); - peer->close(); - } -#endif - // Buffer early media - // TODO: Make buffer size server option else { size_t maxSize = allocation.server().options().earlyMediaBufferSize; - LDebug("Buffering early data: ", len) - //#ifdef _DEBUG - // LDebug("Printing early data: ", std::string(buf, len)) - //#endif + LDebug("Buffering early data: ", len); if (len > maxSize) - LWarn("Dropping early media: Oversize packet: ", len) + ; + LWarn("Dropping early media: Oversize packet: ", len); if (earlyPeerData.size() > maxSize) - LWarn("Dropping early media: Buffer at capacity >= ", maxSize) + ; + LWarn("Dropping early media: Buffer at capacity >= ", maxSize); - // earlyPeerData.append(static_cast(pkt.data()), len); earlyPeerData.insert(earlyPeerData.end(), buf, buf + len); } + return false; } -void TCPConnectionPair::onClientDataReceived(net::Socket&, +bool TCPConnectionPair::onClientDataReceived(net::Socket&, const MutableBuffer& buffer, const net::Address& peerAddress) { - LTrace("Client > Peer: ", buffer.size()) - // assert(packet.buffer.position() == 0); - // if (packet.size() < 300) - // LTrace("Client > Peer: ", packet.buffer) + LTrace("Client > Peer: ", buffer.size()); if (peer.impl) { allocation.updateUsage(buffer.size()); if (allocation.deleted()) - return; + return false; peer->send(bufferCast(buffer), buffer.size()); } + return false; } -void TCPConnectionPair::onPeerConnectSuccess(net::Socket& socket) +bool TCPConnectionPair::onPeerConnectSuccess(net::Socket& socket) { - LTrace("Peer Connect request success") - assert(&socket == peer.impl.get()); + LTrace("Peer Connect request success"); + if (&socket != peer.impl.get()) + throw std::logic_error("onPeerConnectSuccess called with unexpected socket"); peer.Connect -= slot(this, &TCPConnectionPair::onPeerConnectSuccess); peer.Error -= slot(this, &TCPConnectionPair::onPeerConnectError); @@ -232,25 +211,35 @@ void TCPConnectionPair::onPeerConnectSuccess(net::Socket& socket) allocation.sendPeerConnectResponse(this, true); - // TODO: Ensure this is implemented properly startTimeout(); + return false; } -void TCPConnectionPair::onPeerConnectError(net::Socket& socket, const Error& error) +bool TCPConnectionPair::onPeerConnectError(net::Socket& socket, const Error& error) { - LTrace("Peer Connect request error: ", error.message) - assert(&socket == peer.impl.get()); + LTrace("Peer Connect request error: ", error.message); + if (&socket != peer.impl.get()) + throw std::logic_error("onPeerConnectError called with unexpected socket"); allocation.sendPeerConnectResponse(this, false); - // The TCPConnectionPair will be deleted on next call to onConnectionClosed + // The TCPConnectionPair will be cleaned up on next timer tick + return false; +} + + +bool TCPConnectionPair::onConnectionClosed(net::Socket& socket) +{ + LTrace("Connection pair socket closed: ", connectionID, ": ", &socket); + // Flag for deletion by the parent allocation's timer instead of `delete this` + requestDeletion(); + return false; } -void TCPConnectionPair::onConnectionClosed(net::Socket& socket) +void TCPConnectionPair::requestDeletion() { - LTrace("Connection pair socket closed: ", connectionID, ": ", &socket) - delete this; // kill + pendingDelete = true; } diff --git a/src/turn/src/server/udpallocation.cpp b/src/turn/src/server/udpallocation.cpp index 8c7ce51f5..b6b0e362f 100644 --- a/src/turn/src/server/udpallocation.cpp +++ b/src/turn/src/server/udpallocation.cpp @@ -14,13 +14,11 @@ #include "scy/logger.h" #include "scy/net/udpsocket.h" #include "scy/turn/server/server.h" + #include -#include #include #include - - -using namespace std; +#include namespace scy { @@ -39,13 +37,13 @@ UDPAllocation::UDPAllocation(Server& server, const FiveTuple& tuple, _relaySocket->bind(net::Address(server.options().listenAddr.host(), 0)); _relaySocket.Recv += slot(this, &UDPAllocation::onPeerDataReceived); - LTrace(" Initializing on address: ", _relaySocket->address()) + LTrace(" Initializing on address: ", _relaySocket->address()); } UDPAllocation::~UDPAllocation() { - LTrace("Destroy") + LTrace("Destroy"); _relaySocket.Recv -= slot(this, &UDPAllocation::onPeerDataReceived); _relaySocket->close(); } @@ -53,7 +51,7 @@ UDPAllocation::~UDPAllocation() bool UDPAllocation::handleRequest(Request& request) { - LTrace("Handle Request") + LTrace("Handle Request"); if (!ServerAllocation::handleRequest(request)) { if (request.methodType() == stun::Message::SendIndication) @@ -68,96 +66,58 @@ bool UDPAllocation::handleRequest(Request& request) void UDPAllocation::handleSendIndication(Request& request) { - LTrace("Handle Send Indication") - - // The message is first checked for validity. The Send indication MUST - // contain both an XOR-PEER-ADDRESS attribute and a DATA attribute. If - // one of these attributes is missing or invalid, then the message is - // discarded. Note that the DATA attribute is allowed to contain zero - // bytes of data. + LTrace("Handle Send Indication"); auto peerAttr = request.get(); - if (!peerAttr || (peerAttr && peerAttr->family() != 1)) { - LError("Send Indication error: No Peer Address") + if (!peerAttr || peerAttr->family() != stun::AddressFamily::IPv4) { + LError("Send Indication error: No Peer Address"); // silently discard... return; } auto dataAttr = request.get(); if (!dataAttr) { - LError("Send Indication error: No Data attribute") + LError("Send Indication error: No Data attribute"); // silently discard... return; } - // The Send indication may also contain the DONT-FRAGMENT attribute. If - // the server is unable to set the DF bit on outgoing UDP datagrams when - // this attribute is present, then the server acts as if the DONT- - // FRAGMENT attribute is an unknown comprehension-required attribute - // (and thus the Send indication is discarded). - - // The server also checks that there is a permission installed for the - // IP address contained in the XOR-PEER-ADDRESS attribute. If no such - // permission exists, the message is discarded. Note that a Send - // indication never causes the server to refresh the permission. - - // The server MAY impose restrictions on the IP address and port values - // allowed in the XOR-PEER-ADDRESS attribute -- if a value is not - // allowed, the server silently discards the Send indication. - net::Address peerAddress = peerAttr->address(); if (!hasPermission(peerAddress.host())) { SError << "Send Indication error: No permission for: " - << peerAddress.host() << endl; + << peerAddress.host() << std::endl; // silently discard... return; } - // If everything is OK, then the server forms a UDP datagram as follows: - - // o the source transport address is the relayed transport address of - // the allocation, where the allocation is determined by the 5-tuple - // on which the Send indication arrived; - - // o the destination transport address is taken from the XOR-PEER- - // ADDRESS attribute; - - // o the data following the UDP header is the contents of the value - // field of the DATA attribute. - - // The handling of the DONT-FRAGMENT attribute (if present), is - // described in Section 12. - - // The resulting UDP datagram is then sent to the peer. - STrace << "Relaying Send Indication: " << "\r\tFrom: " << request.remoteAddress.toString() - << "\r\tTo: " << peerAddress << endl; + << "\r\tTo: " << peerAddress << std::endl; if (send(dataAttr->bytes(), dataAttr->size(), peerAddress) == -1) { - _server.respondError(request, 486, "Allocation Quota Reached"); - delete this; + _server.respondError(request, kErrorAllocationQuotaReached, "Allocation Quota Reached"); + // Signal the server to delete this allocation instead of `delete this` + _deleted = true; } } -void UDPAllocation::onPeerDataReceived(net::Socket&, +bool UDPAllocation::onPeerDataReceived(net::Socket&, const MutableBuffer& buffer, const net::Address& peerAddress) { - // auto source = reinterpret_cast(packet.info); - LTrace("Received UDP Datagram from ", peerAddress) + LTrace("Received UDP Datagram from ", peerAddress); if (!hasPermission(peerAddress.host())) { - LTrace("No Permission: ", peerAddress.host()) - return; + LTrace("No Permission: ", peerAddress.host()); + return false; } updateUsage(buffer.size()); // Check that we have not exceeded out lifetime and bandwidth quota. if (IAllocation::deleted()) - return; + return false; stun::Message message(stun::Message::Indication, stun::Message::DataIndication); @@ -167,7 +127,7 @@ void UDPAllocation::onPeerDataReceived(net::Socket&, std::string peerHost(server().options().externalIP); if (peerHost.empty()) { peerHost.assign(peerAddress.host()); - assert(0 && "external IP not set"); + LWarn("External IP not set, using peer address directly: ", peerHost); } auto peerAttr = new stun::XorPeerAddress; @@ -180,10 +140,10 @@ void UDPAllocation::onPeerDataReceived(net::Socket&, STrace << "Send data indication:" << "\n\tFrom: " << peerAddress << "\n\tTo: " << _tuple.remote() - //<< "\n\tData: " << std::string(packet.data(), packet.size()) - << endl; + << std::endl; server().udpSocket().sendPacket(message, _tuple.remote()); + return false; } @@ -194,7 +154,7 @@ ssize_t UDPAllocation::send(const char* data, size_t size, // Check that we have not exceeded our lifetime and bandwidth quota. if (IAllocation::deleted()) { - LWarn("Send indication dropped: Allocation quota reached") + LWarn("Send indication dropped: Allocation quota reached"); return -1; } @@ -204,12 +164,12 @@ ssize_t UDPAllocation::send(const char* data, size_t size, net::Address UDPAllocation::relayedAddress() const { - return _relaySocket->address(); } -} } // namespace scy::turn +} // namespace turn +} // namespace scy /// @\} diff --git a/src/turn/tests/turnclienttest/CMakeLists.txt b/src/turn/tests/turnclienttest/CMakeLists.txt index 62185269f..5c085b4b5 100644 --- a/src/turn/tests/turnclienttest/CMakeLists.txt +++ b/src/turn/tests/turnclienttest/CMakeLists.txt @@ -1,4 +1 @@ -# include_dependency(SSL REQUIRED) -# include_dependency(LibUV) - -define_libsourcey_test(turnclienttest base net stun turn util) +scy_add_test(turnclienttest DEPENDS base net stun turn) diff --git a/src/turn/tests/turnclienttest/tcpinitiator.h b/src/turn/tests/turnclienttest/tcpinitiator.h index 28dfaf1ef..20b497621 100644 --- a/src/turn/tests/turnclienttest/tcpinitiator.h +++ b/src/turn/tests/turnclienttest/tcpinitiator.h @@ -3,12 +3,12 @@ #include "scy/logger.h" +#include "scy/net/tcpsocket.h" #include "scy/signal.h" -#include "scy/timer.h" #include "scy/time.h" -#include "scy/util.h" -#include "scy/net/tcpsocket.h" +#include "scy/timer.h" #include "scy/turn/client/tcpclient.h" +#include "scy/util.h" #include @@ -39,24 +39,24 @@ struct TCPInitiator : public turn::TCPClientObserver , client(*this, opts) , success(false) { - LDebug(id, ": Creating") + LDebug(id, ": Creating"); } - virtual ~TCPInitiator() - { - LDebug(id, ": Destroying") + virtual ~TCPInitiator() + { + LDebug(id, ": Destroying"); } void initiate(const std::string& peerIP) { - LDebug(id, ": Initializing") + LDebug(id, ": Initializing"); try { client.addPermission(peerIP); client.addPermission("127.0.0.1"); client.addPermission("192.168.1.1"); client.initiate(); } catch (std::exception& exc) { - LError(id, ": Error: ", exc.what()) + LError(id, ": Error: ", exc.what()); } } @@ -82,14 +82,14 @@ struct TCPInitiator : public turn::TCPClientObserver // payload.append(65536, 'x'); // payload.append(10000, 'x'); - LDebug(id, ": Sending packet to responder") + LDebug(id, ": Sending packet to responder"); std::string payload("initiator > responder"); client.sendData(payload.c_str(), payload.length(), lastPeerAddr); } void onClientStateChange(turn::Client&, turn::ClientState& state, const turn::ClientState&) { - LDebug(id, ": State change: ", state.toString()) + LDebug(id, ": State change: ", state.toString()); switch (state.id()) { case turn::ClientState::None: @@ -104,26 +104,26 @@ struct TCPInitiator : public turn::TCPClientObserver case turn::ClientState::Failed: // assert(false); success = false; - TestComplete.emit(success); + TestComplete.emit(success); break; } } void onRelayConnectionCreated(turn::TCPClient&, const net::TCPSocket::Ptr& socket, const net::Address& peerAddr) { - LDebug(id, ": Connection Created: ", peerAddr) - + LDebug(id, ": Connection Created: ", peerAddr); + // Remember the last peer lastPeerAddr = peerAddr; ConnectionCreated.emit(peerAddr); - // Send the intial data packet to responder + // Send the intial data packet to responder sendPacketToResponder(); } void onRelayConnectionClosed(turn::TCPClient&, const net::TCPSocket::Ptr& socket, const net::Address& peerAddr) { - LDebug(id, ": Connection Closed") + LDebug(id, ": Connection Closed"); } void onRelayDataReceived(turn::Client&, const char* data, size_t size, const net::Address& peerAddr) @@ -150,21 +150,21 @@ struct TCPInitiator : public turn::TCPClientObserver << ": payload=" << payload << ", latency=" << latency << endl; } else - LDebug(id << ": Received dummy data from " << peerAddr << ": size=", size) + LDebug(id << ": Received dummy data from " << peerAddr << ": size=", size); // Echo back to peer - LDebug(id << ": Received data from " << peerAddr << ": ", size) + LDebug(id << ": Received data from " << peerAddr << ": ", size); client.sendData(data, size, peerAddr); #endif - LDebug(id, ": Data received from responder") + LDebug(id, ": Data received from responder"); sendPacketToResponder(); } void onAllocationPermissionsCreated(turn::Client&, const turn::PermissionList& permissions) { - LDebug(id, ": Permissions Created") + LDebug(id, ": Permissions Created"); } }; diff --git a/src/turn/tests/turnclienttest/tcpresponder.h b/src/turn/tests/turnclienttest/tcpresponder.h index d32f2510a..25f39d245 100644 --- a/src/turn/tests/turnclienttest/tcpresponder.h +++ b/src/turn/tests/turnclienttest/tcpresponder.h @@ -3,9 +3,9 @@ #include "scy/logger.h" +#include "scy/net/tcpsocket.h" #include "scy/time.h" #include "scy/util.h" -#include "scy/net/tcpsocket.h" #include @@ -27,20 +27,20 @@ class TCPResponder : public net::SocketAdapter : id(id) , timer(1000, 1000) { - LDebug(id, ": Creating") + LDebug(id, ": Creating"); socket.addReceiver(this); } virtual ~TCPResponder() { - LDebug(id, ": Destroying") + LDebug(id, ": Destroying"); socket.removeReceiver(this); } void connect(const net::Address& relayAddr) { - LDebug(id,": Starting on: ", relayAddr) + LDebug(id, ": Starting on: ", relayAddr); try { this->relayedAddr = relayAddr; @@ -49,7 +49,7 @@ class TCPResponder : public net::SocketAdapter // will be received below. socket.connect(relayAddr); } catch (std::exception& exc) { - LError(id, ": ERROR: ", exc.what()) + LError(id, ": ERROR: ", exc.what()); assert(false); } } @@ -59,8 +59,8 @@ class TCPResponder : public net::SocketAdapter socket.close(); timer.stop(); } - - void onSocketConnect(net::Socket&) + + bool onSocketConnect(net::Socket&) { // Send some early media to client // sendPacketToInitiator(); @@ -68,24 +68,28 @@ class TCPResponder : public net::SocketAdapter // Start the send timer // timer.Timeout += slot(this, &TCPResponder::onSendTimer); // timer.start(); + return false; } - void onSocketRecv(net::Socket&, const MutableBuffer& buffer, const net::Address& peerAddress) + bool onSocketRecv(net::Socket&, const MutableBuffer& buffer, const net::Address& peerAddress) { - LDebug(id, ": On recv: ", peerAddress, ": ", buffer.size()) + LDebug(id, ": On recv: ", peerAddress, ": ", buffer.size()); // Echo data back to client socket.send(bufferCast(buffer), buffer.size()); + return false; } - void onSocketError(net::Socket&, const scy::Error& error) + bool onSocketError(net::Socket&, const scy::Error& error) { - LDebug(id, ": On error: ", error.message) + LDebug(id, ": On error: ", error.message); + return false; } - void onSocketClose(net::Socket&) + bool onSocketClose(net::Socket&) { - LDebug(id, ": On close") + LDebug(id, ": On close"); + return false; } #if 0 diff --git a/src/turn/tests/turnclienttest/turnclienttest.cpp b/src/turn/tests/turnclienttest/turnclienttest.cpp index 662b5bdc1..77e4ffb3b 100644 --- a/src/turn/tests/turnclienttest/turnclienttest.cpp +++ b/src/turn/tests/turnclienttest/turnclienttest.cpp @@ -1,114 +1,197 @@ -#include "udpinitiator.h" -#include "udpresponder.h" -#include "tcpinitiator.h" -#include "tcpresponder.h" -#include "turnserver.h" -#include "scy/logger.h" -#include "scy/util.h" - -#include - - -using namespace std; -using namespace scy; -using namespace scy::test; - - -int main(int argc, char** argv) -{ -#ifdef _MSC_VER - _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); -#endif - - Logger::instance().add(new ConsoleChannel("debug", Level::Trace)); - // Logger::instance().setWriter(new AsyncLogWriter); - test::init(); - - turn::Client::Options co; - co.serverAddr = net::Address(TURN_SERVER_IP, TURN_SERVER_PORT); - co.username = TURN_SERVER_USERNAME; - co.password = TURN_SERVER_PASSWORD; - co.lifetime = 120 * 1000; // 1 minute - co.timeout = 10 * 1000; - co.timerInterval = 3 * 1000; - - - // ========================================================================= - // TURN TCP Client - // - describe("TURN TCP client", [&]() { -#if RAISE_LOCAL_SERVER - RunTestServer() -#endif - TCPInitiator initiator(0, co); - TCPResponder responder(0); - - initiator.AllocationCreated += [&]() - { - LDebug("Initiator allocation created") - - // Start the responder when the allocation is created - responder.connect(initiator.client.relayedAddress()); - }; - - initiator.TestComplete += [&](bool success) - { - LDebug("Test complete: ", success) - expect(success); - initiator.shutdown(); - responder.shutdown(); -#if RAISE_LOCAL_SERVER - srv.stop(); -#endif - }; - - // TODO: Use STUN binding request to get IP - initiator.initiate(TURN_AUTHORIZE_PEER_IP); - - uv::runLoop(); - }); - - - // ========================================================================= - // TURN UDP Client - // - describe("TURN UDP client", [&]() { -#if RAISE_LOCAL_SERVER - RunTestServer() -#endif - UDPInitiator initiator(0, co); - UDPResponder responder(0); - - initiator.AllocationCreated += [&]() - { - LDebug("Initiator allocation created") - - // Start the responder when the allocation is created - responder.connect(initiator.client.relayedAddress()); - - // Set the local responder address for UDP send indications - initiator.responderAddress = net::Address( - TURN_AUTHORIZE_PEER_IP, responder.socket.address().port()); - }; - - initiator.TestComplete += [&](bool success) - { - LDebug("Test complete: ", success) - expect(success); - initiator.shutdown(); - responder.shutdown(); -#if RAISE_LOCAL_SERVER - srv.stop(); -#endif - }; - - // TODO: Use STUN binding request to get IP - initiator.initiate(TURN_AUTHORIZE_PEER_IP); - - uv::runLoop(); - }); - - - test::runAll(); - return test::finalize(); -} +#include "scy/logger.h" +#include "scy/turn/fivetuple.h" +#include "scy/turn/permission.h" +#include "scy/util.h" +#include "turnclienttest.h" +#include "tcpinitiator.h" +#include "tcpresponder.h" +#include "turnserver.h" +#include "udpinitiator.h" +#include "udpresponder.h" + +#include +#include + + +using namespace std; +using namespace scy; +using namespace scy::test; + + +int main(int argc, char** argv) +{ +#ifdef _MSC_VER + _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); +#endif + + Logger::instance().add(std::make_unique("debug", Level::Trace)); + // Logger::instance().setWriter(std::make_unique()); + test::init(); + + turn::Client::Options co; + co.serverAddr = net::Address(TURN_SERVER_IP, TURN_SERVER_PORT); + co.username = TURN_SERVER_USERNAME; + co.password = TURN_SERVER_PASSWORD; + co.lifetime = 120 * 1000; // 1 minute + co.timeout = 10 * 1000; + co.timerInterval = 3 * 1000; + + + // ========================================================================= + // TURN TCP Client + // + describe("TURN TCP client", [&]() { +#if RAISE_LOCAL_SERVER + RunTestServer() +#endif + TCPInitiator initiator(0, co); + TCPResponder responder(0); + + initiator.AllocationCreated += [&]() { + LDebug("Initiator allocation created"); + + // Start the responder when the allocation is created + responder.connect(initiator.client.relayedAddress()); + }; + + initiator.TestComplete += [&](bool success) { + LDebug("Test complete: ", success); + expect(success); + initiator.shutdown(); + responder.shutdown(); +#if RAISE_LOCAL_SERVER + srv.stop(); +#endif + }; + + // TODO: Use STUN binding request to get IP + initiator.initiate(TURN_AUTHORIZE_PEER_IP); + + uv::runLoop(); + }); + + + // ========================================================================= + // TURN UDP Client + // + describe("TURN UDP client", [&]() { +#if RAISE_LOCAL_SERVER + RunTestServer() +#endif + UDPInitiator initiator(0, co); + UDPResponder responder(0); + + initiator.AllocationCreated += [&]() { + LDebug("Initiator allocation created"); + + // Start the responder when the allocation is created + responder.connect(initiator.client.relayedAddress()); + + // Set the local responder address for UDP send indications + initiator.responderAddress = net::Address( + TURN_AUTHORIZE_PEER_IP, responder.socket.address().port()); + }; + + initiator.TestComplete += [&](bool success) { + LDebug("Test complete: ", success); + expect(success); + initiator.shutdown(); + responder.shutdown(); +#if RAISE_LOCAL_SERVER + srv.stop(); +#endif + }; + + // TODO: Use STUN binding request to get IP + initiator.initiate(TURN_AUTHORIZE_PEER_IP); + + uv::runLoop(); + }); + + + // ========================================================================= + // FiveTuple + // + describe("five tuple", []() { + net::Address remote("192.168.1.1", 5000); + net::Address local("10.0.0.1", 3478); + + turn::FiveTuple ft(remote, local, net::TransportType::UDP); + expect(ft.remote() == remote); + expect(ft.local() == local); + expect(ft.transport() == net::TransportType::UDP); + }); + + describe("five tuple equality", []() { + net::Address r1("1.2.3.4", 100); + net::Address l1("5.6.7.8", 200); + + turn::FiveTuple a(r1, l1, net::TransportType::UDP); + turn::FiveTuple b(r1, l1, net::TransportType::UDP); + expect(a == b); + + // Different transport + turn::FiveTuple c(r1, l1, net::TransportType::TCP); + expect(!(a == c)); + + // Different remote + turn::FiveTuple d(net::Address("9.9.9.9", 100), l1, net::TransportType::UDP); + expect(!(a == d)); + }); + + describe("five tuple ordering", []() { + turn::FiveTuple a(net::Address("1.0.0.1", 1), net::Address("2.0.0.1", 2), net::TransportType::UDP); + turn::FiveTuple b(net::Address("1.0.0.2", 1), net::Address("2.0.0.1", 2), net::TransportType::UDP); + + // Just ensure < doesn't crash and provides a total order + expect((a < b) || (b < a) || (a == b)); + }); + + describe("five tuple toString", []() { + turn::FiveTuple ft(net::Address("10.0.0.1", 5000), net::Address("10.0.0.2", 3478), net::TransportType::TCP); + std::string str = ft.toString(); + expect(!str.empty()); + expect(str.find("10.0.0.1") != std::string::npos); + }); + + + // ========================================================================= + // Permission + // + describe("permission", []() { + turn::Permission perm("192.168.1.50"); + expect(perm.ip == "192.168.1.50"); + expect(perm == std::string("192.168.1.50")); + expect(!(perm == std::string("10.0.0.1"))); + }); + + describe("permission timeout", []() { + turn::Permission perm("1.2.3.4"); + // Permission starts with a timeout (PERMISSION_LIFETIME = 300s) + expect(!perm.timeout.expired()); + + perm.refresh(); + expect(!perm.timeout.expired()); + }); + + describe("permission list", []() { + turn::PermissionList perms; + perms.push_back(turn::Permission("10.0.0.1")); + perms.push_back(turn::Permission("10.0.0.2")); + perms.push_back(turn::Permission("10.0.0.3")); + + expect(perms.size() == 3); + + // Find by IP using operator== + auto it = std::find(perms.begin(), perms.end(), std::string("10.0.0.2")); + expect(it != perms.end()); + expect(it->ip == "10.0.0.2"); + + auto notFound = std::find(perms.begin(), perms.end(), std::string("99.99.99.99")); + expect(notFound == perms.end()); + }); + + + test::runAll(); + return test::finalize(); +} diff --git a/src/turn/tests/turnclienttest/turnserver.h b/src/turn/tests/turnclienttest/turnserver.h index 8e93d6986..d8ac9f469 100644 --- a/src/turn/tests/turnclienttest/turnserver.h +++ b/src/turn/tests/turnclienttest/turnserver.h @@ -18,8 +18,8 @@ struct TestServer : public turn::ServerObserver { } - virtual ~TestServer() - { + virtual ~TestServer() + { } void start() @@ -27,41 +27,41 @@ struct TestServer : public turn::ServerObserver server.start(); } - void stop() - { - server.stop(); + void stop() + { + server.stop(); } turn::AuthenticationState authenticateRequest(turn::Server*, turn::Request& request) { - return turn::Authorized; + return turn::AuthenticationState::Authorized; } void onServerAllocationCreated(turn::Server*, turn::IAllocation* alloc) { - LDebug("Allocation created") + LDebug("Allocation created"); } void onServerAllocationRemoved(turn::Server*, turn::IAllocation* alloc) { - LDebug("Allocation removed") + LDebug("Allocation removed"); } }; -#define RunTestServer() \ - LDebug("Running TURN Server") \ - turn::ServerOptions so; \ - so.software = "Sourcey STUN/TURN Server [rfc5766]"; \ - so.realm = "sourcey.com"; \ - so.allocationDefaultLifetime = 1 * 60 * 1000; \ - so.allocationMaxLifetime = 15 * 60 * 1000; \ - so.timerInterval = 5 * 1000; \ - so.listenAddr = net::Address("127.0.0.1", 3478); \ - so.externalIP = TURN_SERVER_EXTERNAL_IP; \ - TestServer srv(so); \ +#define RunTestServer() \ + LDebug("Running TURN Server"); \ + turn::ServerOptions so; \ + so.software = "Sourcey STUN/TURN Server [rfc5766]"; \ + so.realm = "sourcey.com"; \ + so.allocationDefaultLifetime = 1 * 60 * 1000; \ + so.allocationMaxLifetime = 15 * 60 * 1000; \ + so.timerInterval = 5 * 1000; \ + so.listenAddr = net::Address("127.0.0.1", 3478); \ + so.externalIP = TURN_SERVER_EXTERNAL_IP; \ + TestServer srv(so); \ srv.start(); - + } // namespace scy diff --git a/src/turn/tests/turnclienttest/udpinitiator.h b/src/turn/tests/turnclienttest/udpinitiator.h index 8fd9551fe..caa3e1d25 100644 --- a/src/turn/tests/turnclienttest/udpinitiator.h +++ b/src/turn/tests/turnclienttest/udpinitiator.h @@ -27,7 +27,7 @@ class UDPInitiator : public turn::ClientObserver bool success; NullSignal AllocationCreated; Signal TestComplete; // unused - net::Address responderAddress; ///< The responder local socket address for Send indications + net::Address responderAddress; ///< The responder local socket address for Send indications UDPInitiator(int id, const turn::Client::Options& opts) : id(id) @@ -41,14 +41,14 @@ class UDPInitiator : public turn::ClientObserver void initiate(const std::string& peerIP) { - LDebug(id, ": Initializing") + LDebug(id, ": Initializing"); try { client.addPermission(peerIP); client.addPermission("127.0.0.1"); client.addPermission("192.168.1.1"); client.initiate(); } catch (std::exception& exc) { - LError(id, ": ", exc.what()) + LError(id, ": ", exc.what()); } } @@ -66,7 +66,7 @@ class UDPInitiator : public turn::ClientObserver return; } - LDebug(id, ": Senidng to responder: ", responderAddress) + LDebug(id, ": Senidng to responder: ", responderAddress); // Send large packets to test throttling // payload.append(65536, 'x'); @@ -78,7 +78,7 @@ class UDPInitiator : public turn::ClientObserver protected: void onClientStateChange(turn::Client&, turn::ClientState& state, const turn::ClientState&) { - LDebug(id, ": State change: ", state.toString()) + LDebug(id, ": State change: ", state.toString()); switch (state.id()) { case turn::ClientState::None: @@ -90,12 +90,12 @@ class UDPInitiator : public turn::ClientObserver case turn::ClientState::Success: AllocationCreated.emit(); - // Send the intial data packet to responder + // Send the intial data packet to responder sendPacketToResponder(); -//#ifdef TEST_INITIATOR_TO_RESPONDER -// timer.Timeout += slot(this, &UDPInitiator::onSendTimer); -// timer.start(); -//#endif + //#ifdef TEST_INITIATOR_TO_RESPONDER + // timer.Timeout += slot(this, &UDPInitiator::onSendTimer); + // timer.start(); + //#endif break; case turn::ClientState::Failed: break; @@ -123,29 +123,29 @@ class UDPInitiator : public turn::ClientObserver uint64_t sentAt = util::strtoi(payload); uint64_t latency = time::ticks() - sentAt; - LDebug(id << ": Received data from " << peerAddr << ": payload=" << payload << ", latency=", latency) + LDebug(id << ": Received data from " << peerAddr << ": payload=" << payload << ", latency=", latency); } else - LDebug(id << ": Received dummy data from " << peerAddr << ": size=", size) + LDebug(id << ": Received dummy data from " << peerAddr << ": size=", size); // Echo back to peer // client.sendData(data, size, peerAddr); #endif - LDebug(id, ": Received response data from ", peerAddr, ": size=", size) + LDebug(id, ": Received response data from ", peerAddr, ": size=", size); - // Send the intial data packet to responder + // Send the intial data packet to responder sendPacketToResponder(); } - void onAllocationCreated(turn::Client&, const stun::Transaction& transaction) + void onAllocationCreated(turn::Client&, const stun::Transaction& transaction) { - LDebug(id, ": Permissions Created") + LDebug(id, ": Permissions Created"); // AllocationCreated } void onAllocationPermissionsCreated(turn::Client&, const turn::PermissionList& permissions) { - LDebug(id, ": Permissions Created") + LDebug(id, ": Permissions Created"); } }; diff --git a/src/turn/tests/turnclienttest/udpresponder.h b/src/turn/tests/turnclienttest/udpresponder.h index 2ce3d57e5..1f7b551f7 100644 --- a/src/turn/tests/turnclienttest/udpresponder.h +++ b/src/turn/tests/turnclienttest/udpresponder.h @@ -15,7 +15,6 @@ using namespace std; namespace scy { - class UDPResponder : public net::SocketAdapter { @@ -29,25 +28,25 @@ class UDPResponder : public net::SocketAdapter : id(id) , timer(1000, 1000) { - LDebug(id, ": Creating") + LDebug(id, ": Creating"); socket.addReceiver(this); // socket.bind(net::Address(TURN_AUTHORIZE_PEER_IP, 4020)); socket.bind(net::Address("0.0.0.0", 0)); - LDebug(id, ": Listening on: ", socket.address()) + LDebug(id, ": Listening on: ", socket.address()); } virtual ~UDPResponder() { - LDebug(id, ": Destroying") + LDebug(id, ": Destroying"); socket.removeReceiver(this); } void connect(const net::Address& relayAddr) { - LDebug(id, ": Starting on: ", relayAddr) + LDebug(id, ": Starting on: ", relayAddr); try { this->relayedAddr = relayAddr; @@ -57,7 +56,7 @@ class UDPResponder : public net::SocketAdapter // socket.bind(net::Address("0.0.0.0", 4020)); socket.connect(relayAddr); } catch (std::exception& exc) { - LError(id, ": ERROR: ", exc.what()) + LError(id, ": ERROR: ", exc.what()); assert(false); } } @@ -74,32 +73,36 @@ class UDPResponder : public net::SocketAdapter socket.send(payload.c_str(), payload.length()); } - void onSocketConnect(net::Socket&) + bool onSocketConnect(net::Socket&) { -//#if TEST_RESPONDER_TO_INITIATOR_LATENCY -// timer.Timeout += slot(this, &UDPResponder::onSendTimer); -// timer.start(); -//#endif + //#if TEST_RESPONDER_TO_INITIATOR_LATENCY + // timer.Timeout += slot(this, &UDPResponder::onSendTimer); + // timer.start(); + //#endif + return false; } - void onSocketRecv(net::Socket&, const MutableBuffer& buffer, const net::Address& peerAddr) + bool onSocketRecv(net::Socket&, const MutableBuffer& buffer, const net::Address& peerAddr) { std::string payload(bufferCast(buffer), buffer.size()); - LDebug(id, ": On recv: ", peerAddr, ": ", buffer.size()) + LDebug(id, ": On recv: ", peerAddr, ": ", buffer.size()); // Echo back to client socket.send(payload.c_str(), payload.size(), relayedAddr); // peerAddr + return false; } - void onSocketError(net::Socket&, const scy::Error& error) + bool onSocketError(net::Socket&, const scy::Error& error) { - LDebug(id, ": On error: ", error.message) + LDebug(id, ": On error: ", error.message); + return false; } - void onSocketClose(net::Socket&) + bool onSocketClose(net::Socket&) { - LDebug(id, ": On close") + LDebug(id, ": On close"); shutdown(); + return false; } }; diff --git a/src/util/CMakeLists.txt b/src/util/CMakeLists.txt deleted file mode 100644 index 6f31401c9..000000000 --- a/src/util/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -ask_build_sourcey_module(util) -if(BUILD_MODULES OR (NOT BUILD_MODULES AND BUILD_MODULE_util)) - define_sourcey_module(util base json) -endif() diff --git a/src/util/include/scy/util/ratelimiter.h b/src/util/include/scy/util/ratelimiter.h deleted file mode 100644 index c2328ea19..000000000 --- a/src/util/include/scy/util/ratelimiter.h +++ /dev/null @@ -1,75 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// @addtogroup util -/// @{ - - -#ifndef SCY_RateLimiter_H -#define SCY_RateLimiter_H - - -#include "scy/logger.h" - - -namespace scy { - - -/// @addtogroup util -/// A simple message rate limiter based on the token bucket algorithm. -class /* SCY_EXTERN */ RateLimiter -{ -public: - double rate; ///< How many messages - double seconds; ///< Over how many seconds - double allowance; ///< Remaining send allowance - clock_t lastCheck; ///< Last time canSend() was called - - RateLimiter(double rate = 5.0, double seconds = 6.0) - : rate(rate) - , seconds(seconds) - , allowance(rate) - , lastCheck(0) - { - } - - bool canSend() - { - clock_t current = clock(); - if (!lastCheck) - lastCheck = current; - double elapsed = (double)(current - lastCheck) / CLOCKS_PER_SEC; - lastCheck = current; - allowance += elapsed * (rate / seconds); - - STrace << "Can send:" - << "\n\tAllowance: " << allowance - << "\n\tElapsed: " << elapsed - << "\n\tRate: " << rate - << "\n\tLeconds: "(seconds, ) - - if (allowance > rate) { - allowance = rate; // throttle - LTrace("Throttling: ", allowance) - } else if (allowance < 1.0) { - LTrace("Message rate exceeded: ", allowance) - return false; - } - allowance -= 1.0; - LTrace("Can send message: ", allowance) - return true; - } -}; - - -} // namespace scy - - -#endif // SCY_RateLimiter_H - - -/// @\} diff --git a/src/util/src/streammanager.cpp b/src/util/src/streammanager.cpp deleted file mode 100644 index 283c5ab4b..000000000 --- a/src/util/src/streammanager.cpp +++ /dev/null @@ -1,158 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// @addtogroup util -/// @{ - - -#include "scy/util/streammanager.h" -#include "scy/logger.h" - - -using namespace std; - - -namespace scy { - - -StreamManager::StreamManager(bool freeClosedStreams) - : _freeClosedStreams(freeClosedStreams) -{ -} - - -StreamManager::~StreamManager() -{ - closeAll(); -} - - -void StreamManager::closeAll() -{ - std::lock_guard guard(_mutex); - - LDebug("Close all streams: ", _map.size()) - StreamManager::Map::iterator it = _map.begin(); - StreamManager::Map::iterator it2; - while (it != _map.end()) { - it2 = it++; - (*it2).second->StateChange -= slot(this, &StreamManager::onStreamStateChange); - (*it2).second->close(); - if (_freeClosedStreams) { - StreamManager::Deleter func; - func((*it2).second); - } - _map.erase(it2); - } -} - - -bool StreamManager::addStream(PacketStream* stream, bool whiny) -{ - assert(stream); - assert(!stream->name().empty()); - return Manager::add(stream->name(), stream, whiny); -} - - -PacketStream* StreamManager::getStream(const std::string& name, bool whiny) -{ - return Manager::get(name, whiny); -} - - -bool StreamManager::closeStream(const std::string& name, bool whiny) -{ - assert(!name.empty()); - - LDebug("Close stream: ", name) - PacketStream* stream = get(name, whiny); - if (stream) { - stream->close(); - return true; - } - return false; -} - - -PacketStream* StreamManager::getDafaultStream() -{ - std::lock_guard guard(_mutex); - - // Returns the first stream or NULL. - if (!_map.empty()) { - StreamManager::Map::const_iterator it = _map.begin(); - return it->second; - } - - return NULL; -} - - -void StreamManager::onAdd(const std::string&, PacketStream* stream) -{ - // Stream name can't be empty - assert(!stream->name().empty()); - - // Receive callbacks after all other listeners - // so we can delete the stream when it closes. - LDebug("stream added: ", stream->name()) - stream->StateChange += slot(this, &StreamManager::onStreamStateChange, -1); -} - - -void StreamManager::onRemove(const std::string&, PacketStream* stream) -{ - LDebug("stream removed: ", stream->name()) - stream->StateChange -= slot(this, &StreamManager::onStreamStateChange); -} - - -void StreamManager::onStreamStateChange(void* sender, PacketStreamState& state, - const PacketStreamState&) -{ - LDebug("Stream state change: ", state) - - // Cantch stream closed state and free it if necessary - if (state.equals(PacketStreamState::Closed)) { - auto stream = reinterpret_cast(sender); - stream->StateChange -= slot(this, &StreamManager::onStreamStateChange); - bool success = false; - if (_freeClosedStreams) { - LDebug("On stream close: freeing: ", stream->name()) - success = Manager::free(stream->name()); - } else { - LDebug("On stream close: removing: ", stream->name()) - success = !!Manager::remove(stream->name()); - } - if (!success) { - LWarn("Cannot remove stream: ", stream->name()) - assert(0); - } - } -} - - -StreamManager::Map StreamManager::streams() const -{ - std::lock_guard guard(_mutex); - return _map; -} - - -void StreamManager::print(std::ostream& os) const -{ - std::lock_guard guard(_mutex); - os << "StreamManager["; - for (auto it = _map.begin(); it != _map.end(); ++it) { - os << "\n\t" << it->second << ": " << it->first; - } - os << "\n]"; -} - - -} // namespace scy diff --git a/src/webrtc/BUILD.md b/src/webrtc/BUILD.md deleted file mode 100644 index 84d77785c..000000000 --- a/src/webrtc/BUILD.md +++ /dev/null @@ -1,11 +0,0 @@ -# WebRTC -cmake .. -DCMAKE_BUILD_TYPE=DEBUG -DBUILD_SHARED_LIBS=OFF \ - -DBUILD_MODULES=OFF -DBUILD_APPLICATIONS=OFF \ - -DBUILD_SAMPLES=OFF -DBUILD_TESTS=OFF \ - -DWITH_WEBRTC=ON -DWITH_FFMPEG=ON \ - -DBUILD_MODULE_base=ON -DBUILD_MODULE_crypto=ON \ - -DBUILD_MODULE_http=ON -DBUILD_MODULE_json=ON \ - -DBUILD_MODULE_av=ON -DBUILD_MODULE_net=ON \ - -DBUILD_MODULE_socketio=ON -DBUILD_MODULE_symple=ON \ - -DBUILD_MODULE_util=ON -DBUILD_MODULE_uv=ON \ - -DBUILD_MODULE_webrtc=ON -DBUILD_SAMPLES_webrtc=ON diff --git a/src/webrtc/CMakeLists.txt b/src/webrtc/CMakeLists.txt deleted file mode 100644 index 185561639..000000000 --- a/src/webrtc/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -ask_build_sourcey_module(webrtc) -if(HAVE_WEBRTC AND (BUILD_MODULES OR (NOT BUILD_MODULES AND BUILD_MODULE_webrtc))) - include_dependency(WebRTC REQUIRED) - - if(BUILD_SHARED_LIBS) - message(WARNING "Compiling WebRTC libraries with `BUILD_SHARED_LIBS=OFF` is recommended") - endif() - - set(webrtc_PRETTY_NAME WebRTC) - define_sourcey_module(webrtc base av crypto util) -endif() diff --git a/src/webrtc/deprecated/include/scy/webrtc/ffmpegvideobuffer.h b/src/webrtc/deprecated/include/scy/webrtc/ffmpegvideobuffer.h deleted file mode 100644 index 113681cc5..000000000 --- a/src/webrtc/deprecated/include/scy/webrtc/ffmpegvideobuffer.h +++ /dev/null @@ -1,79 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// @addtogroup webrtc -/// @{ - - -#ifndef SCY_WebRTC_FFmpegVideoBuffer_H -#define SCY_WebRTC_FFmpegVideoBuffer_H - - -#include "scy/av/types.h" - -#include "webrtc/media/base/videocapturer.h" - - -namespace scy { -namespace wrtc { - - -class FFmpeg420Buffer : public webrtc::VideoFrameBuffer { -public: - std::vector ydata; - std::vector udata; - std::vector vdata; - - FFmpeg420Buffer(int width, int height, - const uint8_t* y_plane, int y_stride, - const uint8_t* u_plane, int u_stride, - const uint8_t* v_plane, int v_stride); - - FFmpeg420Buffer(const av::PlanarVideoPacket& packet); - - int width() const override; - int height() const override; - - const uint8_t* DataY() const override; - const uint8_t* DataU() const override; - const uint8_t* DataV() const override; - - int StrideY() const override; - int StrideU() const override; - int StrideV() const override; - - void* native_handle() const override; - - rtc::scoped_refptr NativeToI420Buffer() override; - -private: - friend class rtc::RefCountedObject; - ~FFmpeg420Buffer() override; - - const int width_; - const int height_; - - std::vector y_data; - std::vector u_data; - std::vector v_data; - - //const uint8_t* const y_plane_; - //const uint8_t* const u_plane_; - //const uint8_t* const v_plane_; - //const int y_stride_; - //const int u_stride_; - //const int v_stride_; -}; - - -} } // namespace scy::wrtc - - -#endif - - -/// @\} diff --git a/src/webrtc/deprecated/include/scy/webrtc/imagesequencerecorder.h b/src/webrtc/deprecated/include/scy/webrtc/imagesequencerecorder.h deleted file mode 100644 index c58a5ce9c..000000000 --- a/src/webrtc/deprecated/include/scy/webrtc/imagesequencerecorder.h +++ /dev/null @@ -1,55 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// @addtogroup webrtc -/// @{ - - -#ifndef SCY_WebRTC_ImageSequenceRecorder_H -#define SCY_WebRTC_ImageSequenceRecorder_H - - -#include "scy/av/videoencoder.h" - -#include "webrtc/api/peerconnectioninterface.h" - - -namespace scy { -namespace wrtc { - - -class ImageSequenceRecorder - : public rtc::VideoSinkInterface -{ -public: - ImageSequenceRecorder(webrtc::VideoTrackInterface* track_to_render, - const std::string& basename); - virtual ~ImageSequenceRecorder(); - - std::string getNextFilename(); - - /// VideoSinkInterface implementation - void OnFrame(const cricket::VideoFrame& frame) override; - -protected: - rtc::scoped_refptr _renderedTrack; - const std::string _basename; - size_t _count; - int _width; - int _height; - av::VideoEncoder _encoder; - AVFrame* _avframe; -}; - - -} } // namespace scy::wrtc - - -#endif - - -/// @\} diff --git a/src/webrtc/deprecated/include/scy/webrtc/opencvvideocapturer.h b/src/webrtc/deprecated/include/scy/webrtc/opencvvideocapturer.h deleted file mode 100644 index 4e7b6bf85..000000000 --- a/src/webrtc/deprecated/include/scy/webrtc/opencvvideocapturer.h +++ /dev/null @@ -1,83 +0,0 @@ -/// -// -// LibSourcey -// Copyright (C) 2005, Sourcey -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#ifndef SCY_OpenCVVideoCapturer_H -#define SCY_OpenCVVideoCapturer_H - - -#include -#include - -#include "scy/av/mediafactory.h" -#include "scy/av/videocapture.h" - -#include "webrtc/media/base/videocapturer.h" - - -namespace scy { -namespace wrtc { - - -class OpenCVVideoCapturer : public cricket::VideoCapturer -/// OpenCVVideoCapturer implements a simple cricket::VideoCapturer which -/// gets decoded remote video frames from media channel. -/// It's used as the remote video source's VideoCapturer so that the remote -/// video can be used as a cricket::VideoCapturer and in that way a remote -/// video stream can implement the MediaStreamSourceInterface. -{ -public: - OpenCVVideoCapturer(int deviceId); - virtual ~OpenCVVideoCapturer(); - - /// cricket::VideoCapturer implementation. - virtual cricket::CaptureState - Start(const cricket::VideoFormat& capture_format); - virtual void Stop(); - virtual bool IsRunning(); - virtual bool GetPreferredFourccs(std::vector* fourccs); - virtual bool GetBestCaptureFormat(const cricket::VideoFormat& desired, - cricket::VideoFormat* best_format); - virtual bool IsScreencast() const; - -private: - void onFrameCaptured(void* sender, av::MatrixPacket& packet); - - av::VideoCapture::Ptr capture; -}; - - -// class OpenCVVideoCapturerFactory : public cricket::VideoDeviceCapturerFactory -// { -// public: -// OpenCVVideoCapturerFactory() {} -// virtual ~OpenCVVideoCapturerFactory() {} -// -// virtual cricket::VideoCapturer* Create(const cricket::Device& device) { -// -// // XXX: WebRTC uses device name to instantiate the capture, which is -// always 0. -// return new OpenCVVideoCapturer(util::strtoi(device.id)); -// } -// }; - - -} } // namespace scy::wrtc - - -#endif diff --git a/src/webrtc/deprecated/include/scy/webrtc/streamingpeerconnection.h b/src/webrtc/deprecated/include/scy/webrtc/streamingpeerconnection.h deleted file mode 100644 index 4b0125436..000000000 --- a/src/webrtc/deprecated/include/scy/webrtc/streamingpeerconnection.h +++ /dev/null @@ -1,53 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// @addtogroup webrtc -/// @{ - - -#ifndef SCY_WebRTC_StreamingPeerConnection_H -#define SCY_WebRTC_StreamingPeerConnection_H - - -#include "scy/av/mediacapture.h" -#include "scy/webrtc/multiplexmediacapturer.h" -#include "scy/webrtc/peerconnection.h" - - -namespace scy { -namespace wrtc { - - -class StreamingPeerConnection : public PeerConnection -{ -public: - /// Create the streaming peer connection. - StreamingPeerConnection(PeerConnectionManager* manager, - const std::string& peerid, - const std::string& token, - const std::string& file); - virtual ~StreamingPeerConnection(); - virtual rtc::scoped_refptr - createMediaStream(); - - virtual void OnIcePeerChange( - webrtc::PeerConnectionInterface::IcePeerState new_state); - -protected: - std::string _file; - MultiplexMediaCapturer _capturer; - - std::unique_ptr _networkThread; - std::unique_ptr _workerThread; - // std::unique_ptr _signalingThread; -}; - - -} } // namespace scy::wrtc - - -#endif diff --git a/src/webrtc/deprecated/src/ffmpegvideobuffer.cpp b/src/webrtc/deprecated/src/ffmpegvideobuffer.cpp deleted file mode 100644 index 8f3697246..000000000 --- a/src/webrtc/deprecated/src/ffmpegvideobuffer.cpp +++ /dev/null @@ -1,117 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// @addtogroup webrtc -/// @{ - - -#include "scy/webrtc/ffmpegvideobuffer.h" -//#include "scy/av/ffmpeg.h" -//#include "scy/av/videocontext.h" - - -using std::endl; - - -namespace scy { -namespace wrtc { - - -FFmpeg420Buffer::FFmpeg420Buffer(int width, int height, - const uint8_t* y_plane, int y_stride, - const uint8_t* u_plane, int u_stride, - const uint8_t* v_plane, int v_stride) - : width_(width) - , height_(height) - //, ydata(y_plane, y_plane + y_stride) - //, udata(u_plane, u_plane + u_stride) - //, vdata(v_plane, v_plane + v_stride) - , ydata(y_plane, y_plane + (y_stride * height)) - , udata(u_plane, u_plane + (u_stride * (height / 2))) - , vdata(v_plane, v_plane + (v_stride * (height / 2))) - //, y_plane_(y_plane) - //, u_plane_(u_plane) - //, v_plane_(v_plane) - //, y_stride_(y_stride) - //, u_stride_(u_stride) - //, v_stride_(v_stride) -{ -} - -FFmpeg420Buffer::FFmpeg420Buffer(const av::PlanarVideoPacket& packet) - : width_(packet.width) - , height_(packet.height) - , ydata(packet.ydata) - , udata(packet.udata) - , vdata(packet.vdata) -{ -} - -FFmpeg420Buffer::~FFmpeg420Buffer() -{ - //no_longer_used_cb_(); -} - - -int FFmpeg420Buffer::width() const -{ - return width_; -} - - -int FFmpeg420Buffer::height() const -{ - return height_; -} - - -const uint8_t* FFmpeg420Buffer::DataY() const -{ - return ydata.data(); -} - -const uint8_t* FFmpeg420Buffer::DataU() const -{ - return udata.data(); -} - -const uint8_t* FFmpeg420Buffer::DataV() const -{ - return vdata.data(); -} - -int FFmpeg420Buffer::StrideY() const -{ - return 640; //ydata.size(); -} - -int FFmpeg420Buffer::StrideU() const -{ - return 320; //udata.size(); -} - -int FFmpeg420Buffer::StrideV() const -{ - return 320; // vdata.size(); -} - -void* FFmpeg420Buffer::native_handle() const -{ - return nullptr; -} - -rtc::scoped_refptr FFmpeg420Buffer::NativeToI420Buffer() -{ - RTC_NOTREACHED(); - return nullptr; -} - - -} } // namespace scy::wrtc - - -/// @\} diff --git a/src/webrtc/deprecated/src/imagesequencerecorder.cpp b/src/webrtc/deprecated/src/imagesequencerecorder.cpp deleted file mode 100644 index 597593a25..000000000 --- a/src/webrtc/deprecated/src/imagesequencerecorder.cpp +++ /dev/null @@ -1,124 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// @addtogroup webrtc -/// @{ - - -#include "scy/webrtc/imagesequencerecorder.h" - -#include "scy/av/ffmpeg.h" -#include "scy/filesystem.h" -#include "scy/logger.h" - -#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" -#include "webrtc/media/engine/webrtcvideocapturerfactory.h" -#include "webrtc/modules/video_capture/video_capture_factory.h" - - -namespace scy { -namespace wrtc { - - -ImageSequenceRecorder::ImageSequenceRecorder( - webrtc::VideoTrackInterface* track_to_render, const std::string& basename) - : _renderedTrack(track_to_render) - , _basename(basename) - , _count(0) - , _width(0) - , _height(0) -{ - _renderedTrack->AddOrUpdateSink(this, rtc::VideoSinkWants()); - - av::initializeFFmpeg(); -} - - -ImageSequenceRecorder::~ImageSequenceRecorder() -{ - _renderedTrack->RemoveSink(this); - - av::uninitializeFFmpeg(); - - // Cleanup the frame - if (_avframe) - av_free(_avframe); -} - - -std::string ImageSequenceRecorder::getNextFilename() -{ - std::stringstream filename; - filename << _basename; - if (++_count > 1) - filename << '-' << _count; - filename << '_' << _width << 'x' << _height << ".jpg"; - return filename.str(); -} - - -void ImageSequenceRecorder::OnFrame(const cricket::VideoFrame& yuvframe) -{ - STrace << "On video frame: " << yuvframe.width() << 'x' << yuvframe.height() - << std::endl; - - if (_width != yuvframe.width() || _height != yuvframe.height()) { - _width = yuvframe.width(); - _height = yuvframe.height(); - - _encoder.iparams.width = yuvframe.width(); - _encoder.iparams.height = yuvframe.height(); - _encoder.iparams.pixelFmt = "yuv420p"; - - _encoder.oparams.encoder = "mjpeg"; // "png" - _encoder.oparams.pixelFmt = "yuvj420p"; - _encoder.oparams.width = yuvframe.width(); - _encoder.oparams.height = yuvframe.height(); - _encoder.oparams.fps = 25; // avoid FFmpeg 0 fps bitrate tolerance error - _encoder.oparams.enabled = true; - - _encoder.create(); - _encoder.open(); - - // Cleanup the previous frame (if any) - if (_avframe) - av_free(_avframe); - - // Initialize the AVFrame - _avframe = av_frame_alloc(); - _avframe->width = yuvframe.width(); - _avframe->height = yuvframe.height(); - _avframe->format = AV_PIX_FMT_YUV420P; - - // Initialize avframe->linesize - avpicture_fill((AVPicture*)_avframe, NULL, - /*_avframe->format*/ AV_PIX_FMT_YUV420P, _avframe->width, - _avframe->height); - } - - // Set avframe->data pointers manually - _avframe->data[0] = (uint8_t*)yuvframe.video_frame_buffer()->DataY(); - _avframe->data[1] = (uint8_t*)yuvframe.video_frame_buffer()->DataU(); - _avframe->data[2] = (uint8_t*)yuvframe.video_frame_buffer()->DataV(); - - // Feed the raw frame into the encoder - AVPacket opacket; - if (_encoder.encode(_avframe, opacket)) { - - // Write the output file - std::string filename(getNextFilename()); - LTrace("Write video frame: ", filename) - fs::savefile(filename, (const char*)opacket.data, - (std::streamsize)opacket.size); - } -} - - -} } // namespace scy::wrtc - - -/// @\} diff --git a/src/webrtc/deprecated/src/opencvvideocapturer.cpp b/src/webrtc/deprecated/src/opencvvideocapturer.cpp deleted file mode 100644 index a1752fafe..000000000 --- a/src/webrtc/deprecated/src/opencvvideocapturer.cpp +++ /dev/null @@ -1,161 +0,0 @@ -/// -// -// LibSourcey -// Copyright (C) 2005, Sourcey -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#include "scy/webrtc/opencvvideocapturer.h" - - -using std::endl; - - -namespace scy { -namespace wrtc { - - -OpenCVVideoCapturer::OpenCVVideoCapturer(int deviceId) - : capture(av::MediaFactory::instance().createVideoCapture(deviceId)) -{ - // Default supported formats. Use ResetSupportedFormats to over write. - std::vector formats; - formats.push_back( - cricket::VideoFormat(1280, 720, cricket::VideoFormat::FpsToInterval(30), - cricket::FOURCC_I420)); - formats.push_back( - cricket::VideoFormat(640, 480, cricket::VideoFormat::FpsToInterval(30), - cricket::FOURCC_I420)); - formats.push_back( - cricket::VideoFormat(320, 240, cricket::VideoFormat::FpsToInterval(30), - cricket::FOURCC_I420)); - formats.push_back( - cricket::VideoFormat(160, 120, cricket::VideoFormat::FpsToInterval(30), - cricket::FOURCC_I420)); -} - - -OpenCVVideoCapturer::~OpenCVVideoCapturer() -{ -} - - -cricket::CaptureState -OpenCVVideoCapturer::Start(const cricket::VideoFormat& capture_format) -{ - try { - if (capture_state() == cricket::CS_RUNNING) { - LWarn("Start called when it's already started.") - return capture_state(); - } - LInfo("Start") - - // TODO: Check and verify cricket::VideoFormat - - // Connect and start the packet stream. - // Output packets must be av::MatrixPacket types so we can access - // the underlying cv::Mat. - capture->start(); - capture->emitter += - packetSlot(this, &OpenCVVideoCapturer::onFrameCaptured); - - SetCaptureFormat(&capture_format); - return cricket::CS_RUNNING; - } catch (...) { - } - return cricket::CS_FAILED; -} - - -void OpenCVVideoCapturer::Stop() -{ - try { - if (capture_state() == cricket::CS_STOPPED) { - LWarn("Stop called when it's already stopped.") - return; - } - LInfo("Stop") - - capture->emitter.detach(this); // for cleanup() - - SetCaptureFormat(NULL); - SetCaptureState(cricket::CS_STOPPED); - return; - } catch (...) { - } - return; -} - - -void OpenCVVideoCapturer::onFrameCaptured(void* sender, - av::MatrixPacket& packet) -{ - // LTrace("On frame") - - // Convert the packet from BGR to I420 for WebRTC - cv::Mat yuv(packet.width, packet.height, CV_8UC4); - cv::cvtColor(*packet.mat, yuv, CV_BGR2YUV_I420); - - cricket::CapturedFrame frame; - frame.width = packet.width; - frame.height = packet.height; - frame.fourcc = cricket::FOURCC_I420; - frame.data_size = yuv.rows * yuv.step; - frame.data = yuv.data; - - SignalFrameCaptured(this, &frame); -} - - -bool OpenCVVideoCapturer::IsRunning() -{ - return capture_state() == cricket::CS_RUNNING; -} - - -bool OpenCVVideoCapturer::GetPreferredFourccs(std::vector* fourccs) -{ - if (!fourccs) - return false; - - // This class does not yet support multiple pixel formats. - fourccs->push_back(cricket::FOURCC_I420); - return true; -} - - -bool OpenCVVideoCapturer::GetBestCaptureFormat( - const cricket::VideoFormat& desired, cricket::VideoFormat* best_format) -{ - if (!best_format) - return false; - - // Use the supported format as the best format. - best_format->width = desired.width; - best_format->height = desired.height; - best_format->fourcc = cricket::FOURCC_I420; - best_format->interval = desired.interval; - - return true; -} - - -bool OpenCVVideoCapturer::IsScreencast() const -{ - return false; -} - - -} } // namespace scy::wrtc diff --git a/src/webrtc/deprecated/src/streamingpeerconnection.cpp b/src/webrtc/deprecated/src/streamingpeerconnection.cpp deleted file mode 100644 index 6c7db73e7..000000000 --- a/src/webrtc/deprecated/src/streamingpeerconnection.cpp +++ /dev/null @@ -1,352 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// @addtogroup webrtc -/// @{ - - -#include "scy/webrtc/streamingpeerconnection.h" -#include "scy/logger.h" -#include "scy/webrtc/peerconnectionmanager.h" -#include "scy/webrtc/videopacketsource.h" - - -using std::endl; - - -namespace scy { -namespace wrtc { - - -StreamingPeerConnection::StreamingPeerConnection(PeerConnectionManager* manager, - const std::string& peerid, - const std::string& token, - const std::string& file) - : PeerConnection(manager, peerid, token, PeerConnection::Offer) - , _file(file) - , _networkThread(rtc::Thread::CreateWithSocketServer()) - , _workerThread(rtc::Thread::Create().release()) - //, _networkThread(rtc::Thread::CreateWithSocketServer().release()) - //, _workerThread(rtc::Thread::Create().release()) -{ - // Setup a PeerConnectionFactory with our custom ADM - // TODO: Setup threads properly: - // _networkThread = rtc::Thread::CreateWithSocketServer(); //.release(); - // _workerThread = rtc::Thread::Create(); //.release(); - // _signalingThread = rtc::Thread::Current(); - - // FIXME: Dont create new threads for each factory - - if (!_networkThread->Start() || !_workerThread->Start()) { - throw std::runtime_error("Failed to start threads"); - } - - _factory = webrtc::CreatePeerConnectionFactory( - _networkThread.get(), _workerThread.get(), rtc::Thread::Current(), - _capturer.getAudioModule(), nullptr, nullptr); - - // https://bugs.chromium.org/p/webrtc/issues/detail?id=2388 - _constraints.SetMandatoryReceiveAudio(false); - _constraints.SetMandatoryReceiveVideo(false); - _constraints.SetAllowDtlsSctpDataChannels(); // allow cross-browser -} - - -StreamingPeerConnection::~StreamingPeerConnection() -{ - // https://github.com/pristineio/webrtc-mirror/blob/32001ef124f5082651c661965dc5d75d7f06a57b/talk/examples/android/src/org/appspot/apprtc/AppRTCDemoActivity.java#L473 - //this-> - //_factory-> - //this->Release(); - //_stream->Release(); - //_factory->Release(); - //_factory->Release(); - //_factory->Release(); - //delete _factory.release(); -} - - -rtc::scoped_refptr StreamingPeerConnection::createMediaStream() -{ - assert(_mode == Offer); - assert(_factory); - assert(!_stream); - // assert(!_capture); - _stream = _factory->CreateLocalMediaStream(kStreamLabel); - - _capturer.openFile(_file); - _capturer.addMediaTracks(_factory, _stream); - - return _stream; -} - - -// void StreamingPeerConnection::OnSignalingChange(webrtc::PeerConnectionInterface::SignalingState new_state) -// { -// switch(new_state) { -// case webrtc::PeerConnectionInterface::kStable: -// break; -// case webrtc::PeerConnectionInterface::kClosed: -// _capture->stop(); -// break; -// case webrtc::PeerConnectionInterface::kHaveLocalOffer: -// case webrtc::PeerConnectionInterface::kHaveRemoteOffer: -// break; -// case webrtc::PeerConnectionInterface::kHaveLocalPrAnswer: -// case webrtc::PeerConnectionInterface::kHaveRemotePrAnswer: -// _capture->start(); -// break; -// } -// -// PeerConnection::OnSignalingChange(new_state); -// } - - -void StreamingPeerConnection::OnIcePeerChange( - webrtc::PeerConnectionInterface::IcePeerState new_state) -{ - LDebug(_peerid, ": On ICE gathering change: ", new_state) - - switch (new_state) { - case webrtc::PeerConnectionInterface::kIcePeerNew: - case webrtc::PeerConnectionInterface::kIcePeerChecking: - case webrtc::PeerConnectionInterface::kIcePeerConnected: - break; - case webrtc::PeerConnectionInterface::kIcePeerCompleted: - _capturer.start(); - break; - case webrtc::PeerConnectionInterface::kIcePeerFailed: - case webrtc::PeerConnectionInterface::kIcePeerDisconnected: - case webrtc::PeerConnectionInterface::kIcePeerClosed: - case webrtc::PeerConnectionInterface::kIcePeerMax: - _capturer.stop(); - break; - } - - PeerConnection::OnIcePeerChange(new_state); -} - - -// void PeerConnection::createPeer() -// { -// assert(_factory); -// -// _peerPeer = _factory->CreatePeerConnection( -// _config, &_constraints, nullptr, nullptr, this); -// -// if (_stream) { -// if (!_peerPeer->AddStream(_stream)) { -// throw std::runtime_error("Adding stream to PeerConnection -// failed"); -// } -// } -// } -// -// -// void PeerConnection::closePeer() -// { -// LDebug(_peerid, ": Closing") -// -// if (_peerPeer) { -// _peerPeer->Close(); -// } -// else { -// // Call onClosed if no connection has been -// // made so callbacks are always run. -// _manager->onClosed(this); -// } -// } -// -// -// void PeerConnection::createOffer() -// { -// assert(_mode == Offer); -// assert(_peerPeer); -// -// _peerPeer->CreateOffer(this, &_constraints); -// } -// -// -// void PeerConnection::recvSDP(const std::string& type, const std::string& sdp) -// { -// LDebug(_peerid, ": Receive ", type, ": ", sdp) -// -// webrtc::SdpParseError error; -// webrtc::SessionDescriptionInterface* -// desc(webrtc::CreateSessionDescription(type, sdp, &error)); -// if (!desc) { -// throw std::runtime_error("Can't parse remote SDP: " + -// error.description); -// } -// _peerPeer->SetRemoteDescription(DummySetSessionDescriptionObserver::Create(), -// desc); -// -// if (type == "offer") { -// assert(_mode == Answer); -// _peerPeer->CreateAnswer(this, &_constraints); -// } -// else { -// assert(_mode == Offer); -// } -// } -// -// -// void PeerConnection::recvCandidate(const std::string& mid, int mlineindex, -// const std::string& sdp) -// { -// webrtc::SdpParseError error; -// std::unique_ptr -// candidate(webrtc::CreateIceCandidate(mid, mlineindex, sdp, &error)); -// if (!candidate) { -// throw std::runtime_error("Can't parse remote candidate: " + -// error.description); -// } -// _peerPeer->AddIceCandidate(candidate.get()); -// } -// -// -// void -// PeerConnection::OnIcePeerChange(webrtc::PeerConnectionInterface::IcePeerState -// new_state) -// { -// LDebug(_peerid, ": On ICE connection change: ", new_state) -// } -// -// -// void -// PeerConnection::OnIceGatheringChange(webrtc::PeerConnectionInterface::IceGatheringState -// new_state) -// { -// LDebug(_peerid, ": On ICE gathering change: ", new_state) -// } -// -// -// void PeerConnection::OnRenegotiationNeeded() -// { -// LDebug(_peerid, ": On renegotiation needed") -// } -// -// -// void PeerConnection::OnAddStream(webrtc::MediaStreamInterface* stream) -// { -// assert(_mode == Answer); -// -// LDebug(_peerid, ": On add stream") -// _manager->onAddRemoteStream(this, stream); -// } -// -// -// void PeerConnection::OnRemoveStream(webrtc::MediaStreamInterface* stream) -// { -// assert(_mode == Answer); -// -// LDebug(_peerid, ": On remove stream") -// _manager->onRemoveRemoteStream(this, stream); -// } -// -// -// void PeerConnection::OnIceCandidate(const webrtc::IceCandidateInterface* -// candidate) -// { -// std::string sdp; -// if (!candidate->ToString(&sdp)) { -// LError(_peerid, ": Failed to serialize candidate") -// assert(0); -// return; -// } -// -// _manager->sendCandidate(this, candidate->sdp_mid(), -// candidate->sdp_mline_index(), sdp); -// } -// -// -// void PeerConnection::OnSuccess(webrtc::SessionDescriptionInterface* desc) -// { -// LDebug(_peerid, ": Set local description") -// _peerPeer->SetLocalDescription( -// DummySetSessionDescriptionObserver::Create(), desc); -// -// // Send an SDP offer to the peer -// std::string sdp; -// if (!desc->ToString(&sdp)) { -// LError(_peerid, ": Failed to serialize local sdp") -// assert(0); -// return; -// } -// -// _manager->sendSDP(this, desc->type(), sdp); -// } -// -// -// void PeerConnection::OnFailure(const std::string& error) -// { -// LError << _peerid(": On failure: ", error) -// -// _manager->onFailure(this, error); -// } -// -// -// void -// PeerConnection::setPeerConnectionFactory(rtc::scoped_refptr -// factory) -// { -// assert(!_factory); // should not be already set via PeerConnectionManager -// _factory = factory; -// } -// -// -// std::string PeerConnection::peerid() const -// { -// return _peerid; -// } -// -// -// webrtc::FakeConstraints& PeerConnection::constraints() -// { -// return _constraints; -// } -// -// -// webrtc::PeerConnectionFactoryInterface* PeerConnection::factory() const -// { -// return _factory.get(); -// } -// -// -// rtc::scoped_refptr -// PeerConnection::peerPeer() const -// { -// return _peerPeer; -// } -// -// -// rtc::scoped_refptr PeerConnection::stream() -// const -// { -// return _stream; -// } -// -// -// // -// // Dummy Set Session Description Observer -// // -// -// -// void DummySetSessionDescriptionObserver::OnSuccess() -// { -// LDebug("On SDP parse success") -// } -// -// -// void DummySetSessionDescriptionObserver::OnFailure(const std::string& error) -// { -// LError("On SDP parse error: ", error) -// assert(0); -// } - - -} } // namespace scy::wrtc diff --git a/src/webrtc/include/scy/webrtc/audiopacketmodule.h b/src/webrtc/include/scy/webrtc/audiopacketmodule.h deleted file mode 100644 index f5724b059..000000000 --- a/src/webrtc/include/scy/webrtc/audiopacketmodule.h +++ /dev/null @@ -1,291 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// @addtogroup webrtc -/// @{ - - -#ifndef SCY_WebRTC_AudioPacketModule_H -#define SCY_WebRTC_AudioPacketModule_H - - -#include "scy/base.h" - -#ifdef HAVE_FFMPEG - -#include "scy/av/av.h" -#include "scy/av/audiobuffer.h" -#include "scy/av/packet.h" -#include "scy/packetsignal.h" - -#include "webrtc/base/basictypes.h" -#include "webrtc/base/criticalsection.h" -#include "webrtc/base/messagehandler.h" -#include "webrtc/base/scoped_ref_ptr.h" -#include "webrtc/base/thread.h" -#include "webrtc/common_types.h" -#include "webrtc/modules/audio_device/include/audio_device.h" - - -namespace scy { -namespace wrtc { - - -/// This class implements an `AudioDeviceModule` that can be used to process -/// arbitrary audio packets. This class is send only, recording is not implemented -/// -/// Note P postfix of a function indicates that it should only be called by the -/// processing thread. -class AudioPacketModule : public webrtc::AudioDeviceModule, - public rtc::MessageHandler -{ -public: - typedef uint16_t Sample; - - /// Creates a `AudioPacketModule` or returns NULL on failure. - static rtc::scoped_refptr Create(); - - /// Handles input packets from the capture for sending. - void onAudioCaptured(av::AudioPacket& packet); - - /// Following functions are inherited from `webrtc::AudioDeviceModule`. - /// Only functions called by `Peer` are implemented, the rest do - /// nothing and return success. If a function is not expected to be called - /// by `Peer` an assertion is triggered if it is in fact called. - int64_t TimeUntilNextProcess() override; - void Process() override; - - int32_t ActiveAudioLayer(AudioLayer* audio_layer) const override; - - ErrorCode LastError() const override; - int32_t RegisterEventObserver(webrtc::AudioDeviceObserver* event_callback) override; - - /// Note: Calling this method from a callback may result in deadlock. - int32_t RegisterAudioCallback(webrtc::AudioTransport* audio_callback) override; - - int32_t Init() override; - int32_t Terminate() override; - bool Initialized() const override; - - int16_t PlayoutDevices() override; - int16_t RecordingDevices() override; - int32_t PlayoutDeviceName(uint16_t index, - char name[webrtc::kAdmMaxDeviceNameSize], - char guid[webrtc::kAdmMaxGuidSize]) override; - int32_t RecordingDeviceName(uint16_t index, - char name[webrtc::kAdmMaxDeviceNameSize], - char guid[webrtc::kAdmMaxGuidSize]) override; - - int32_t SetPlayoutDevice(uint16_t index) override; - int32_t SetPlayoutDevice(WindowsDeviceType device) override; - int32_t SetRecordingDevice(uint16_t index) override; - int32_t SetRecordingDevice(WindowsDeviceType device) override; - - int32_t PlayoutIsAvailable(bool* available) override; - int32_t InitPlayout() override; - bool PlayoutIsInitialized() const override; - int32_t RecordingIsAvailable(bool* available) override; - int32_t InitRecording() override; - bool RecordingIsInitialized() const override; - - int32_t StartPlayout() override; - int32_t StopPlayout() override; - bool Playing() const override; - int32_t StartRecording() override; - int32_t StopRecording() override; - bool Recording() const override; - - int32_t SetAGC(bool enable) override; - bool AGC() const override; - - int32_t SetWaveOutVolume(uint16_t volume_left, uint16_t volume_right) override; - int32_t WaveOutVolume(uint16_t* volume_left, uint16_t* volume_right) const override; - - int32_t InitSpeaker() override; - bool SpeakerIsInitialized() const override; - int32_t InitMicrophone() override; - bool MicrophoneIsInitialized() const override; - - int32_t SpeakerVolumeIsAvailable(bool* available) override; - int32_t SetSpeakerVolume(uint32_t volume) override; - int32_t SpeakerVolume(uint32_t* volume) const override; - int32_t MaxSpeakerVolume(uint32_t* max_volume) const override; - int32_t MinSpeakerVolume(uint32_t* min_volume) const override; - int32_t SpeakerVolumeStepSize(uint16_t* step_size) const override; - - int32_t MicrophoneVolumeIsAvailable(bool* available) override; - int32_t SetMicrophoneVolume(uint32_t volume) override; - int32_t MicrophoneVolume(uint32_t* volume) const override; - int32_t MaxMicrophoneVolume(uint32_t* max_volume) const override; - - int32_t MinMicrophoneVolume(uint32_t* min_volume) const override; - int32_t MicrophoneVolumeStepSize(uint16_t* step_size) const override; - - int32_t SpeakerMuteIsAvailable(bool* available) override; - int32_t SetSpeakerMute(bool enable) override; - int32_t SpeakerMute(bool* enabled) const override; - - int32_t MicrophoneMuteIsAvailable(bool* available) override; - int32_t SetMicrophoneMute(bool enable) override; - int32_t MicrophoneMute(bool* enabled) const override; - - int32_t MicrophoneBoostIsAvailable(bool* available) override; - int32_t SetMicrophoneBoost(bool enable) override; - int32_t MicrophoneBoost(bool* enabled) const override; - - int32_t StereoPlayoutIsAvailable(bool* available) const override; - int32_t SetStereoPlayout(bool enable) override; - int32_t StereoPlayout(bool* enabled) const override; - int32_t StereoRecordingIsAvailable(bool* available) const override; - int32_t SetStereoRecording(bool enable) override; - int32_t StereoRecording(bool* enabled) const override; - int32_t SetRecordingChannel(const ChannelType channel) override; - int32_t RecordingChannel(ChannelType* channel) const override; - - int32_t SetPlayoutBuffer(const BufferType type, uint16_t size_ms = 0) override; - int32_t PlayoutBuffer(BufferType* type, uint16_t* size_ms) const override; - int32_t PlayoutDelay(uint16_t* delay_ms) const override; - int32_t RecordingDelay(uint16_t* delay_ms) const override; - - int32_t CPULoad(uint16_t* load) const override; - - int32_t StartRawOutputFileRecording( - const char pcm_file_name_utf8[webrtc::kAdmMaxFileNameSize]) override; - int32_t StopRawOutputFileRecording() override; - int32_t StartRawInputFileRecording( - const char pcm_file_name_utf8[webrtc::kAdmMaxFileNameSize]) override; - int32_t StopRawInputFileRecording() override; - - int32_t SetRecordingSampleRate(const uint32_t samples_per_sec) override; - int32_t RecordingSampleRate(uint32_t* samples_per_sec) const override; - int32_t SetPlayoutSampleRate(const uint32_t samples_per_sec) override; - int32_t PlayoutSampleRate(uint32_t* samples_per_sec) const override; - - int32_t ResetAudioDevice() override; - int32_t SetLoudspeakerStatus(bool enable) override; - int32_t GetLoudspeakerStatus(bool* enabled) const override; - bool BuiltInAECIsAvailable() const override { return false; } - int32_t EnableBuiltInAEC(bool enable) override { return -1; } - bool BuiltInAGCIsAvailable() const override { return false; } - int32_t EnableBuiltInAGC(bool enable) override { return -1; } - bool BuiltInNSIsAvailable() const override { return false; } - int32_t EnableBuiltInNS(bool enable) override { return -1; } -#if defined(WEBRTC_IOS) - int GetPlayoutAudioParameters(webrtc::AudioParameters* params) const override - { - return -1; - } - int GetRecordAudioParameters(webrtc::AudioParameters* params) const override - { - return -1; - } -#endif // WEBRTC_IOS - - /// End of functions inherited from `webrtc::AudioDeviceModule`. - - /// The following function is inherited from `rtc::MessageHandler`. - void OnMessage(rtc::Message* msg) override; - -protected: - /// The constructor is protected because the class needs to be created as a - /// reference counted object (for memory managment reasons). It could be - /// exposed in which case the burden of proper instantiation would be put on - /// the creator of a AudioPacketModule instance. To create an instance of - /// this class use the `Create()` API. - explicit AudioPacketModule(); - - /// The destructor is protected because it is reference counted and should - /// not be deleted directly. - virtual ~AudioPacketModule(); - -private: - /// Initializes the state of the `AudioPacketModule`. This API is called on - /// creation by the `Create()` API. - bool Initialize(); - - /// Returns true/false depending on if recording or playback has been - /// enabled/started. - bool shouldStartProcessing(); - - /// Starts or stops the pushing and pulling of audio frames. - void updateProcessing(bool start); - - /// Starts the periodic calling of `ProcessFrame()` in a thread safe way. - void startProcessP(); - - /// Periodcally called function that ensures that frames are pulled and - /// pushed - /// periodically if enabled/started. - void processFrameP(); - - /// Pulls frames from the registered webrtc::AudioTransport. - void receiveFrameP(); - - /// Pushes frames to the registered webrtc::AudioTransport. - void sendFrameP(); - - /// The time in milliseconds when Process() was last called or 0 if no call - /// has been made. - int64_t _lastProcessTimeMS; - - /// Callback for playout and recording. - webrtc::AudioTransport* _audioCallback; - - bool _recording; ///< True when audio is being pushed from the instance. - bool _playing; ///< True when audio is being pulled by the instance. - - bool _playIsInitialized; ///< True when the instance is ready to pull audio. - bool _recIsInitialized; ///< True when the instance is ready to push audio. - - /// Input to and output from RecordedDataIsAvailable(..) makes it possible - /// to modify the current mic level. The implementation does not care about - /// the mic level so it just feeds back what it receives. - uint32_t _currentMicLevel; - - /// `_nextFrameTime` is updated in a non-drifting manner to indicate the - /// next wall clock time the next frame should be generated and received. - /// `_started` ensures that _nextFrameTime can be initialized properly on first call. - bool _started; - int64_t _nextFrameTime; - - std::unique_ptr _processThread; - - /// A FIFO buffer that stores samples from the audio source to be sent. - av::AudioBuffer _sendFifo; - - /// A buffer with enough storage for a 10ms of samples to send. - std::vector _sendSamples; - - /// Protects variables that are accessed from `_processThread` and - /// the main thread. - rtc::CriticalSection _crit; - - /// Protects |_audioCallback| that is accessed from `_processThread` and - /// the main thread. - rtc::CriticalSection _critCallback; -}; - - -} } // namespace scy::wrtc - - -#endif // HAVE_FFMPEG -#endif // SCY_WebRTC_AudioPacketModule_H - - -/// @\} - - -/* - * Copyright 2012 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ diff --git a/src/webrtc/include/scy/webrtc/fakeaudiodevicemodule.h b/src/webrtc/include/scy/webrtc/fakeaudiodevicemodule.h deleted file mode 100644 index c5a8583f6..000000000 --- a/src/webrtc/include/scy/webrtc/fakeaudiodevicemodule.h +++ /dev/null @@ -1,217 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -/// @addtogroup webrtc -/// @{ - - -#ifndef SCY_WebRTC_FakeAudioDeviceModule_H -#define SCY_WebRTC_FakeAudioDeviceModule_H - - -#include "scy/base.h" - -#include "webrtc/base/basictypes.h" -#include "webrtc/base/criticalsection.h" -#include "webrtc/base/messagehandler.h" -#include "webrtc/base/scoped_ref_ptr.h" -#include "webrtc/base/thread.h" -#include "webrtc/common_types.h" -#include "webrtc/modules/audio_device/include/audio_device.h" - - -namespace scy { -namespace wrtc { - - -/// This class implements a fake `AudioDeviceModule` that does absolutely nothing. -class FakeAudioDeviceModule : public webrtc::AudioDeviceModule, - public rtc::MessageHandler -{ -public: - /// Creates a `FakeAudioDeviceModule` or returns NULL on failure. - static rtc::scoped_refptr Create(); - - /// Following functions are inherited from `webrtc::AudioDeviceModule`. - /// Only functions called by `Peer` are implemented, the rest do - /// nothing and return success. If a function is not expected to be called - /// by `Peer` an assertion is triggered if it is in fact called. - int64_t TimeUntilNextProcess() override; - void Process() override; - - int32_t ActiveAudioLayer(AudioLayer* audio_layer) const override; - - ErrorCode LastError() const override; - int32_t RegisterEventObserver(webrtc::AudioDeviceObserver* event_callback) override; - - /// Note: Calling this method from a callback may result in deadlock. - int32_t RegisterAudioCallback(webrtc::AudioTransport* audio_callback) override; - - int32_t Init() override; - int32_t Terminate() override; - bool Initialized() const override; - - int16_t PlayoutDevices() override; - int16_t RecordingDevices() override; - int32_t PlayoutDeviceName(uint16_t index, - char name[webrtc::kAdmMaxDeviceNameSize], - char guid[webrtc::kAdmMaxGuidSize]) override; - int32_t RecordingDeviceName(uint16_t index, - char name[webrtc::kAdmMaxDeviceNameSize], - char guid[webrtc::kAdmMaxGuidSize]) override; - - int32_t SetPlayoutDevice(uint16_t index) override; - int32_t SetPlayoutDevice(WindowsDeviceType device) override; - int32_t SetRecordingDevice(uint16_t index) override; - int32_t SetRecordingDevice(WindowsDeviceType device) override; - - int32_t PlayoutIsAvailable(bool* available) override; - int32_t InitPlayout() override; - bool PlayoutIsInitialized() const override; - int32_t RecordingIsAvailable(bool* available) override; - int32_t InitRecording() override; - bool RecordingIsInitialized() const override; - - int32_t StartPlayout() override; - int32_t StopPlayout() override; - bool Playing() const override; - int32_t StartRecording() override; - int32_t StopRecording() override; - bool Recording() const override; - - int32_t SetAGC(bool enable) override; - bool AGC() const override; - - int32_t SetWaveOutVolume(uint16_t volume_left, uint16_t volume_right) override; - int32_t WaveOutVolume(uint16_t* volume_left, uint16_t* volume_right) const override; - - int32_t InitSpeaker() override; - bool SpeakerIsInitialized() const override; - int32_t InitMicrophone() override; - bool MicrophoneIsInitialized() const override; - - int32_t SpeakerVolumeIsAvailable(bool* available) override; - int32_t SetSpeakerVolume(uint32_t volume) override; - int32_t SpeakerVolume(uint32_t* volume) const override; - int32_t MaxSpeakerVolume(uint32_t* max_volume) const override; - int32_t MinSpeakerVolume(uint32_t* min_volume) const override; - int32_t SpeakerVolumeStepSize(uint16_t* step_size) const override; - - int32_t MicrophoneVolumeIsAvailable(bool* available) override; - int32_t SetMicrophoneVolume(uint32_t volume) override; - int32_t MicrophoneVolume(uint32_t* volume) const override; - int32_t MaxMicrophoneVolume(uint32_t* max_volume) const override; - - int32_t MinMicrophoneVolume(uint32_t* min_volume) const override; - int32_t MicrophoneVolumeStepSize(uint16_t* step_size) const override; - - int32_t SpeakerMuteIsAvailable(bool* available) override; - int32_t SetSpeakerMute(bool enable) override; - int32_t SpeakerMute(bool* enabled) const override; - - int32_t MicrophoneMuteIsAvailable(bool* available) override; - int32_t SetMicrophoneMute(bool enable) override; - int32_t MicrophoneMute(bool* enabled) const override; - - int32_t MicrophoneBoostIsAvailable(bool* available) override; - int32_t SetMicrophoneBoost(bool enable) override; - int32_t MicrophoneBoost(bool* enabled) const override; - - int32_t StereoPlayoutIsAvailable(bool* available) const override; - int32_t SetStereoPlayout(bool enable) override; - int32_t StereoPlayout(bool* enabled) const override; - int32_t StereoRecordingIsAvailable(bool* available) const override; - int32_t SetStereoRecording(bool enable) override; - int32_t StereoRecording(bool* enabled) const override; - int32_t SetRecordingChannel(const ChannelType channel) override; - int32_t RecordingChannel(ChannelType* channel) const override; - - int32_t SetPlayoutBuffer(const BufferType type, uint16_t size_ms = 0) override; - int32_t PlayoutBuffer(BufferType* type, uint16_t* size_ms) const override; - int32_t PlayoutDelay(uint16_t* delay_ms) const override; - int32_t RecordingDelay(uint16_t* delay_ms) const override; - - int32_t CPULoad(uint16_t* load) const override; - - int32_t StartRawOutputFileRecording( - const char pcm_file_name_utf8[webrtc::kAdmMaxFileNameSize]) override; - int32_t StopRawOutputFileRecording() override; - int32_t StartRawInputFileRecording( - const char pcm_file_name_utf8[webrtc::kAdmMaxFileNameSize]) override; - int32_t StopRawInputFileRecording() override; - - int32_t SetRecordingSampleRate(const uint32_t samples_per_sec) override; - int32_t RecordingSampleRate(uint32_t* samples_per_sec) const override; - int32_t SetPlayoutSampleRate(const uint32_t samples_per_sec) override; - int32_t PlayoutSampleRate(uint32_t* samples_per_sec) const override; - - int32_t ResetAudioDevice() override; - int32_t SetLoudspeakerStatus(bool enable) override; - int32_t GetLoudspeakerStatus(bool* enabled) const override; - bool BuiltInAECIsAvailable() const override { return false; } - int32_t EnableBuiltInAEC(bool enable) override { return -1; } - bool BuiltInAGCIsAvailable() const override { return false; } - int32_t EnableBuiltInAGC(bool enable) override { return -1; } - bool BuiltInNSIsAvailable() const override { return false; } - int32_t EnableBuiltInNS(bool enable) override { return -1; } -#if defined(WEBRTC_IOS) - int GetPlayoutAudioParameters(webrtc::AudioParameters* params) const override - { - return -1; - } - int GetRecordAudioParameters(webrtc::AudioParameters* params) const override - { - return -1; - } -#endif // WEBRTC_IOS - - /// End of functions inherited from `webrtc::AudioDeviceModule`. - - /// The following function is inherited from `rtc::MessageHandler`. - void OnMessage(rtc::Message* msg) override; - -protected: - /// The constructor is protected because the class needs to be created as a - /// reference counted object (for memory managment reasons). It could be - /// exposed in which case the burden of proper instantiation would be put on - /// the creator of a FakeAudioDeviceModule instance. To create an instance of - /// this class use the `Create()` API. - explicit FakeAudioDeviceModule(); - - /// The destructor is protected because it is reference counted and should - /// not be deleted directly. - virtual ~FakeAudioDeviceModule(); - -private: - /// The time in milliseconds when Process() was last called or 0 if no call - /// has been made. - int64_t _lastProcessTimeMS; - - /// Callback for playout and recording. - webrtc::AudioTransport* _audioCallback; - - bool _recording; ///< True when audio is being pushed from the instance. - bool _playing; ///< True when audio is being pulled by the instance. - - bool _playIsInitialized; ///< True when the instance is ready to pull audio. - bool _recIsInitialized; ///< True when the instance is ready to push audio. - - /// Input to and output from RecordedDataIsAvailable(..) makes it possible - /// to modify the current mic level. The implementation does not care about - /// the mic level so it just feeds back what it receives. - uint32_t _currentMicLevel; - - /// Protects variables for multithread access. - rtc::CriticalSection _crit; -}; - - -} } // namespace scy::wrtc - - -#endif // SCY_WebRTC_FakeAudioDeviceModule_H - - -/// @\} diff --git a/src/webrtc/include/scy/webrtc/multiplexmediacapturer.h b/src/webrtc/include/scy/webrtc/multiplexmediacapturer.h deleted file mode 100644 index af347d875..000000000 --- a/src/webrtc/include/scy/webrtc/multiplexmediacapturer.h +++ /dev/null @@ -1,63 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// @addtogroup webrtc -/// @{ - - -#ifndef SCY_WebRTC_MultiplexMediaCapturer_H -#define SCY_WebRTC_MultiplexMediaCapturer_H - - -#include "scy/base.h" - -#ifdef HAVE_FFMPEG - -#include "scy/av/av.h" -#include "scy/av/mediacapture.h" -#include "scy/webrtc/audiopacketmodule.h" -#include "scy/webrtc/videopacketsource.h" - -#include "webrtc/api/peerconnectioninterface.h" - - -namespace scy { -namespace wrtc { - - -class MultiplexMediaCapturer -{ -public: - MultiplexMediaCapturer(); - ~MultiplexMediaCapturer(); - - void openFile(const std::string& file, bool loop = true); - - void addMediaTracks(webrtc::PeerConnectionFactoryInterface* factory, - webrtc::MediaStreamInterface* stream); - - void start(); - void stop(); - - rtc::scoped_refptr getAudioModule(); - VideoPacketSource* createVideoSource(); - -protected: - PacketStream _stream; - av::MediaCapture::Ptr _videoCapture; - rtc::scoped_refptr _audioModule; -}; - - -} } // namespace scy::wrtc - - -#endif // HAVE_FFMPEG -#endif - - -/// @\} diff --git a/src/webrtc/include/scy/webrtc/peer.h b/src/webrtc/include/scy/webrtc/peer.h deleted file mode 100644 index 4437268b9..000000000 --- a/src/webrtc/include/scy/webrtc/peer.h +++ /dev/null @@ -1,143 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// @addtogroup webrtc -/// @{ - - -#ifndef SCY_WebRTC_Peer_H -#define SCY_WebRTC_Peer_H - - -#include "scy/webrtc/peerfactorycontext.h" - -#include "webrtc/api/jsep.h" -#include "webrtc/api/peerconnectioninterface.h" -#include "webrtc/api/test/fakeconstraints.h" -#include "webrtc/p2p/client/basicportallocator.h" - - -namespace scy { -namespace wrtc { - - -class PeerManager; - - -class Peer : public webrtc::PeerConnectionObserver, - public webrtc::CreateSessionDescriptionObserver -{ -public: - enum Mode - { - Offer, ///< Operating as offerer - Answer ///< Operating as answerer - }; - - Peer(PeerManager* manager, - PeerFactoryContext* context, - const std::string& peerid, - const std::string& token, - Mode mode); - virtual ~Peer(); - - /// Create the local media stream. - /// Only necessary when we are creating the offer. - virtual rtc::scoped_refptr createMediaStream(); - - /// Create the peer connection once configuration, constraints and - /// streams have been created. - virtual void createConnection(); - - /// Close the peer connection. - virtual void closeConnection(); - - /// Create the offer SDP tos end to the peer. - /// No offer should be received after creating the offer. - /// A call to `recvSDP` with answer is expected in order to initiate the session. - virtual void createOffer(); - - /// Receive a remote offer or answer. - virtual void recvSDP(const std::string& type, const std::string& sdp); - - /// Receive a remote candidate. - virtual void recvCandidate(const std::string& mid, int mlineindex, const std::string& sdp); - - /// Set a custom PeerFactory object. - /// Must be set before any streams are initiated. - void setPeerFactory(rtc::scoped_refptr factory); - - /// Set the port range for WebRTC connections. - /// Must be done before the connection is initiated. - void setPortRange(int minPort, int maxPort); - - std::string peerid() const; - std::string token() const; - webrtc::FakeConstraints& constraints(); - webrtc::PeerConnectionFactoryInterface* factory() const; - rtc::scoped_refptr peerConnection() const; - rtc::scoped_refptr stream() const; - -protected: - /// inherited from PeerConnectionObserver - virtual void OnAddStream(webrtc::MediaStreamInterface* stream); ///< @deprecated - virtual void OnRemoveStream(webrtc::MediaStreamInterface* stream); ///< @deprecated - virtual void OnAddStream(rtc::scoped_refptr stream) override; ///< since 7f0676 - virtual void OnRemoveStream(rtc::scoped_refptr stream) override; ///< since 7f0676 - virtual void OnDataChannel(rtc::scoped_refptr stream) override; ///< since 7f0676 - virtual void OnIceCandidate(const webrtc::IceCandidateInterface* candidate) override; - virtual void OnSignalingChange(webrtc::PeerConnectionInterface::SignalingState new_state) override; - virtual void OnIceConnectionChange(webrtc::PeerConnectionInterface::IceConnectionState new_state) override; - virtual void OnIceGatheringChange(webrtc::PeerConnectionInterface::IceGatheringState new_state) override; - virtual void OnRenegotiationNeeded(); - - /// inherited from CreateSessionDescriptionObserver - virtual void OnSuccess(webrtc::SessionDescriptionInterface* desc) override; - virtual void OnFailure(const std::string& error) override; - - virtual int AddRef() const override { return 1; } - virtual int Release() const override { return 0; } - -protected: - PeerManager* _manager; - PeerFactoryContext* _context; - std::string _peerid; - std::string _token; - Mode _mode; - webrtc::PeerConnectionInterface::RTCConfiguration _config; - webrtc::FakeConstraints _constraints; - rtc::scoped_refptr _peerConnection; - rtc::scoped_refptr _stream; - std::unique_ptr _portAllocator; -}; - - -class DummySetSessionDescriptionObserver - : public webrtc::SetSessionDescriptionObserver -{ -public: - static DummySetSessionDescriptionObserver* Create() - { - return new rtc::RefCountedObject(); - } - - virtual void OnSuccess() override; - virtual void OnFailure(const std::string& error) override; - -protected: - DummySetSessionDescriptionObserver() = default; - ~DummySetSessionDescriptionObserver() = default; -}; - - -} } // namespace scy::wrtc - - -#endif - - -/// @\} diff --git a/src/webrtc/include/scy/webrtc/peerfactorycontext.h b/src/webrtc/include/scy/webrtc/peerfactorycontext.h deleted file mode 100644 index b577ed7d7..000000000 --- a/src/webrtc/include/scy/webrtc/peerfactorycontext.h +++ /dev/null @@ -1,52 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// @addtogroup webrtc -/// @{ - - -#ifndef SCY_WebRTC_PeerFactoryContext_H -#define SCY_WebRTC_PeerFactoryContext_H - - -#include "scy/webrtc/webrtc.h" - -#include "webrtc/pc/peerconnectionfactory.h" - - -namespace scy { -namespace wrtc { - - -class PeerFactoryContext -{ -public: - PeerFactoryContext( - webrtc::AudioDeviceModule* default_adm = nullptr, - cricket::WebRtcVideoEncoderFactory* video_encoder_factory = nullptr, - cricket::WebRtcVideoDecoderFactory* video_decoder_factory = nullptr, - rtc::scoped_refptr audio_encoder_factory = nullptr, - rtc::scoped_refptr audio_decoder_factory = nullptr); - - void initCustomNetworkManager(); - - std::unique_ptr networkThread; - std::unique_ptr workerThread; - std::unique_ptr networkManager; - std::unique_ptr socketFactory; - rtc::scoped_refptr factory; - // rtc::scoped_refptr audioDeviceManager; -}; - - -} } // namespace scy::wrtc - - -#endif - - -/// @\} diff --git a/src/webrtc/include/scy/webrtc/peermanager.h b/src/webrtc/include/scy/webrtc/peermanager.h deleted file mode 100644 index 8db8fd116..000000000 --- a/src/webrtc/include/scy/webrtc/peermanager.h +++ /dev/null @@ -1,61 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// @addtogroup webrtc -/// @{ - - -#ifndef SCY_WebRTC_PeerManager_H -#define SCY_WebRTC_PeerManager_H - - -#include "scy/collection.h" -#include "scy/json/json.h" -#include "scy/webrtc/webrtc.h" -#include "scy/webrtc/peer.h" - -#include "webrtc/api/peerconnectioninterface.h" - -#include -#include - - -namespace scy { -namespace wrtc { - - -class Peer; - - -class PeerManager : public PointerCollection -{ -public: - PeerManager(); - virtual ~PeerManager(); - - virtual void sendSDP(Peer* conn, const std::string& type, const std::string& sdp); - virtual void sendCandidate(Peer* conn, const std::string& mid, int mlineindex, const std::string& sdp); - - virtual void recvSDP(const std::string& token, const json::value& data); - virtual void recvCandidate(const std::string& token, const json::value& data); - - virtual void onAddRemoteStream(Peer* conn, webrtc::MediaStreamInterface* stream); - virtual void onRemoveRemoteStream(Peer* conn, webrtc::MediaStreamInterface* stream); - - virtual void onStable(Peer* conn); - virtual void onClosed(Peer* conn); - virtual void onFailure(Peer* conn, const std::string& error); -}; - - -} } // namespace scy::wrtc - - -#endif - - -/// @\} diff --git a/src/webrtc/include/scy/webrtc/recordingpeer.h b/src/webrtc/include/scy/webrtc/recordingpeer.h deleted file mode 100644 index 5c882ebe7..000000000 --- a/src/webrtc/include/scy/webrtc/recordingpeer.h +++ /dev/null @@ -1,57 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// @addtogroup webrtc -/// @{ - - -#ifndef SCY_WebRTC_RecordingPeer_H -#define SCY_WebRTC_RecordingPeer_H - - -#include "scy/base.h" - -#ifdef HAVE_FFMPEG - -#include "scy/av/av.h" -#include "scy/av/mediacapture.h" -#include "scy/webrtc/multiplexmediacapturer.h" -#include "scy/webrtc/peer.h" -#include "scy/webrtc/streamrecorder.h" - - -namespace scy { -namespace wrtc { - - -/// Peer connection class for recording the remote peer video. -class RecordingPeer : public Peer -{ -public: - /// Create the recording peer connection. - RecordingPeer(PeerManager* manager, - PeerFactoryContext* context, - const std::string& peerid, - const std::string& token, - const av::EncoderOptions& options = av::EncoderOptions()); - virtual ~RecordingPeer(); - - /// inherited from PeerObserver - virtual void OnAddStream(webrtc::MediaStreamInterface* stream) override; - virtual void OnRemoveStream(webrtc::MediaStreamInterface* stream) override; - virtual void OnIceConnectionChange(webrtc::PeerConnectionInterface::IceConnectionState new_state) override; - -protected: - std::unique_ptr _recorder; -}; - - -} } // namespace scy::wrtc - - -#endif // HAVE_FFMPEG -#endif diff --git a/src/webrtc/include/scy/webrtc/streamrecorder.h b/src/webrtc/include/scy/webrtc/streamrecorder.h deleted file mode 100644 index 027906906..000000000 --- a/src/webrtc/include/scy/webrtc/streamrecorder.h +++ /dev/null @@ -1,63 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// @addtogroup webrtc -/// @{ - - -#ifndef SCY_WebRTC_StreamRecorder_H -#define SCY_WebRTC_StreamRecorder_H - - -#include "scy/base.h" - -#ifdef HAVE_FFMPEG - -#include "scy/av/av.h" -#include "scy/av/multiplexencoder.h" - -#include "webrtc/api/peerconnectioninterface.h" - - -namespace scy { -namespace wrtc { - - -class StreamRecorder : public rtc::VideoSinkInterface, - public webrtc::AudioTrackSinkInterface -{ -public: - StreamRecorder(const av::EncoderOptions& options); - ~StreamRecorder(); - - void setVideoTrack(webrtc::VideoTrackInterface* track); - void setAudioTrack(webrtc::AudioTrackInterface* track); - - /// VideoSinkInterface implementation - void OnFrame(const webrtc::VideoFrame& frame) override; - - /// AudioTrackSinkInterface implementation - void OnData(const void* audio_data, int bits_per_sample, int sample_rate, - size_t number_of_channels, size_t number_of_frames) override; - -protected: - av::MultiplexEncoder _encoder; - rtc::scoped_refptr _videoTrack; - rtc::scoped_refptr _audioTrack; - bool _awaitingVideo; - bool _awaitingAudio; -}; - - -} } // namespace scy::wrtc - - -#endif // HAVE_FFMPEG -#endif - - -/// @\} diff --git a/src/webrtc/include/scy/webrtc/util.h b/src/webrtc/include/scy/webrtc/util.h deleted file mode 100644 index 26e776810..000000000 --- a/src/webrtc/include/scy/webrtc/util.h +++ /dev/null @@ -1,38 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -/// -/// @addtogroup webrtc -/// @{ - - -#ifndef SCY_WebRTC_WEBRTC_UTIL_H -#define SCY_WebRTC_WEBRTC_UTIL_H - - -#include "scy/webrtc/webrtc.h" - -#include "webrtc/media/base/videocapturer.h" -#include "webrtc/media/engine/webrtcvideocapturerfactory.h" -#include "webrtc/modules/video_capture/video_capture_factory.h" - - -namespace scy { -namespace wrtc { - - -std::vector getVideoCaptureDevices(); - -std::unique_ptr openWebRtcVideoCaptureDevice(const std::string& deviceName = ""); - - -} } // namespace scy::wrtc - - -#endif // SCY_WebRTC_WEBRTC_H - - -/// @\} diff --git a/src/webrtc/include/scy/webrtc/videopacketsource.h b/src/webrtc/include/scy/webrtc/videopacketsource.h deleted file mode 100644 index 1d6763517..000000000 --- a/src/webrtc/include/scy/webrtc/videopacketsource.h +++ /dev/null @@ -1,86 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// @addtogroup webrtc -/// @{ - - -#ifndef SCY_WebRTC_VideoPacketSource_H -#define SCY_WebRTC_VideoPacketSource_H - - -#include "scy/base.h" -#include "scy/packetsignal.h" - -#ifdef HAVE_FFMPEG - -#include "scy/av/packet.h" - -#include "webrtc/media/base/videocapturer.h" - - -namespace scy { -namespace wrtc { - - -/// VideoPacketSource implements a simple `cricket::VideoCapturer` that -/// gets decoded remote video frames from a local media channel. -/// It's used as the remote video source's `VideoCapturer` so that the remote -/// video can be used as a `cricket::VideoCapturer` and in that way a remote -/// video stream can implement the `MediaStreamSourceInterface`. -class VideoPacketSource : public cricket::VideoCapturer -{ -public: - VideoPacketSource(int width, int height, int fps, uint32_t fourcc); - VideoPacketSource(const cricket::VideoFormat& captureFormat); - virtual ~VideoPacketSource(); - - /// Set the source `av::VideoPacket` emitter. - /// The pointer is not managed by this class. - void setPacketSource(PacketSignal* source); - - /// Callback that fired when an `av::PlanarVideoPacket` - /// is ready for processing. - void onVideoCaptured(av::PlanarVideoPacket& packet); - - /// cricket::VideoCapturer implementation. - virtual cricket::CaptureState Start(const cricket::VideoFormat& capture_format) override; - virtual void Stop() override; - virtual bool GetPreferredFourccs(std::vector* fourccs) override; - virtual bool GetBestCaptureFormat(const cricket::VideoFormat& desired, - cricket::VideoFormat* best_format) override; - virtual bool IsRunning() override; - virtual bool IsScreencast() const override; - -protected: - cricket::VideoFormat _captureFormat; - webrtc::VideoRotation _rotation; - int64_t _timestampOffset; - int64_t _nextTimestamp; - PacketSignal* _source; -}; - - -// class VideoPacketSourceFactory : public cricket::VideoDeviceCapturerFactory { -// public: -// VideoPacketSourceFactory() {} -// virtual ~VideoPacketSourceFactory() {} -// -// virtual cricket::VideoCapturer* Create(const cricket::Device& device) { -// return new VideoPacketSource(device.name); -// } -// }; - - -} } // namespace scy::wrtc - - -#endif // HAVE_FFMPEG -#endif - - -/// @\} diff --git a/src/webrtc/include/scy/webrtc/webrtc.h b/src/webrtc/include/scy/webrtc/webrtc.h deleted file mode 100644 index f72fbc73a..000000000 --- a/src/webrtc/include/scy/webrtc/webrtc.h +++ /dev/null @@ -1,49 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// @defgroup webrtc WebRTC module -/// -/// The `webrtc` module contains WebRTC integrations. -/// -/// @addtogroup webrtc -/// @{ - - -#ifndef SCY_WebRTC_WEBRTC_H -#define SCY_WebRTC_WEBRTC_H - - -namespace scy { -namespace wrtc { -// namespace webrtc { - - -/// Names used for a IceCandidate JSON object. -const char kCandidateSdpMidName[] = "sdpMid"; -const char kCandidateSdpMlineIndexName[] = "sdpMLineIndex"; -const char kCandidateSdpName[] = "candidate"; - -/// Names used for a SessionDescription JSON object. -const char kSessionDescriptionTypeName[] = "type"; -const char kSessionDescriptionSdpName[] = "sdp"; - -/// Labels for ICE streams. -const char kAudioLabel[] = "audio_label"; -const char kVideoLabel[] = "video_label"; -const char kStreamLabel[] = "stream_label"; - -/// Server URIs for ICE candidates. -const char kGoogleStunServerUri[] = "stun:stun.l.google.com:19302"; - - -} } // namespace scy::wrtc - - -#endif // SCY_WebRTC_WEBRTC_H - - -/// @\} diff --git a/src/webrtc/include/scy/webrtc/yuvframegenerator.h b/src/webrtc/include/scy/webrtc/yuvframegenerator.h deleted file mode 100644 index 59377e44f..000000000 --- a/src/webrtc/include/scy/webrtc/yuvframegenerator.h +++ /dev/null @@ -1,122 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// @addtogroup webrtc -/// @{ - - -#ifndef SCY_WebRTC_YuvFrameGenerator_H -#define SCY_WebRTC_YuvFrameGenerator_H - - -#include "scy/base.h" -#include "scy/logger.h" - -#include "webrtc/base/basictypes.h" -#include "webrtc/base/constructormagic.h" - - -namespace scy { -namespace wrtc { - - -// Generates YUV420 frames with a "landscape with striped crosshair" in the -// Y-plane, plus a horizontal gradient in the U-plane and a vertical one in the -// V-plane. This makes for a nice mix of colours that is suited for both -// catching visual errors and making sure e.g. YUV->RGB/BGR conversion looks -// the same on different platforms. -// There is also a solid box bouncing around in the Y-plane, and two differently -// coloured lines bouncing horizontally and vertically in the U and V plane. -// This helps illustrating how the frame boundary goes, and can aid as a quite -// handy visual help for noticing e.g. packet loss if the frames are encoded -// and sent over the network. -class YuvFrameGenerator -{ -public: - // Constructs a frame-generator that produces frames of size |width|x|height|. - // If |enable_barcode| is specified, barcodes can be included in the frames - // when calling |GenerateNextFrame(uint8_t*, uint32_t)|. If |enable_barcode| - // is |true| then |width|x|height| should be at least 160x100; otherwise this - // constructor will abort. - YuvFrameGenerator(int width, int height, bool enable_barcode); - ~YuvFrameGenerator(); - - // Generate the next frame. If barcode_value is not |nullptr| the value - // referred by it will be encoded into a barcode in the frame. - // The value should in the range: [0..9,999,999]. - // If the value exceeds this range or barcodes were not - // requested in the constructor, this function will abort. - void GenerateNextFrame(int32_t barcode_value); - - // Copy interleaved YUV data to the provided |frame_buffer|. - void CopyInterleavedData(uint8_t* frame_buffer); - - const uint8_t* DataY() const; - const uint8_t* DataU() const; - const uint8_t* DataV() const; - - int GetFrameSize() - { - return frame_data_size_; - } - - int GetHeight() - { - return height_; - } - - int GetWidth() - { - return width_; - } - - // Fetch the bounds of the barcode from the generator. The barcode will - // always be at this location. This function will abort if barcodes were not - // requested in the constructor. - void GetBarcodeBounds(int* top, int* left, int* width, int* height); - -private: - void DrawLandscape(uint8_t* p, int w, int h); - void DrawGradientX(uint8_t* p, int w, int h); - void DrawGradientY(uint8_t* p, int w, int h); - void DrawMovingLineX(uint8_t* p, int w, int h, int n); - void DrawMovingLineY(uint8_t* p, int w, int h, int n); - void DrawBouncingCube(uint8_t* p, int w, int h, int n); - void DrawBarcode(uint32_t value); - int DrawSideGuardBars(int x, int y, int height); - int DrawMiddleGuardBars(int x, int y, int height); - int DrawEanEncodedDigit(int digit, int x, int y, int height, bool r_code); - void DrawBlockRectangle(uint8_t* p, int x_start, int y_start, int width, int height, int pitch, uint8_t value); - -private: - int width_; - int height_; - int frame_index_; - int frame_data_size_; - uint8_t* y_data_; - uint8_t* u_data_; - uint8_t* v_data_; - int barcode_start_x_; - int barcode_start_y_; -}; - - -} } // namespace scy::wrtc - - -#endif // SCY_WebRTC_YuvFrameGenerator_H - - -/* - * Copyright (c) 2010 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ diff --git a/src/webrtc/include/scy/webrtc/yuvvideocapturer.h b/src/webrtc/include/scy/webrtc/yuvvideocapturer.h deleted file mode 100644 index 224967752..000000000 --- a/src/webrtc/include/scy/webrtc/yuvvideocapturer.h +++ /dev/null @@ -1,141 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// @addtogroup webrtc -/// @{ - - -#ifndef SCY_WebRTC_YuvVideoCapturer_H -#define SCY_WebRTC_YuvVideoCapturer_H - - -#include "scy/base.h" -#include "scy/logger.h" -#include "scy/platform.h" - -#include "yuvframegenerator.h" - -#include "webrtc/base/thread.h" -#include "webrtc/base/bind.h" -#include "webrtc/base/asyncinvoker.h" -#include "webrtc/api/video/video_frame.h" -#include "webrtc/common_video/include/video_frame_buffer.h" - - -namespace scy { -namespace wrtc { - - -class YuvVideoCapturer : public cricket::VideoCapturer, public rtc::Thread -{ -public: - YuvVideoCapturer() - : _frameGenerator(nullptr) - , _frameIndex(0) - , _width(640) - , _height(480) - { - SetCaptureFormat(nullptr); - - _frameGenerator = new YuvFrameGenerator(_width, _height, true); - - std::vector formats; - formats.push_back(cricket::VideoFormat(_width, _height, cricket::VideoFormat::FpsToInterval(25), cricket::FOURCC_IYUV)); - SetSupportedFormats(formats); - } - - virtual ~YuvVideoCapturer() - { - // Stop(); - rtc::Thread::Stop(); - _asyncInvoker.reset(); - - if (_frameGenerator) - delete _frameGenerator; - } - - - void SignalFrameCapturedOnStartThread() - { - _frameGenerator->GenerateNextFrame(_frameIndex); - _frameIndex++; - - auto buffer = webrtc::I420Buffer::Copy(_width, _height, - _frameGenerator->DataY(), _width, - _frameGenerator->DataU(), _height, - _frameGenerator->DataV(), _height); - - OnFrame(webrtc::VideoFrame( - buffer, webrtc::kVideoRotation_0, - rtc::TimeNanos() / rtc::kNumNanosecsPerMicrosec), - _width, _height); - } - - - void Run() - { - while (IsRunning()) - { - _asyncInvoker->AsyncInvoke(RTC_FROM_HERE, _startThread, - rtc::Bind(&YuvVideoCapturer::SignalFrameCapturedOnStartThread, this)); - - ProcessMessages(40); - } - } - - virtual cricket::CaptureState Start(const cricket::VideoFormat& format) - { - LDebug("Start") - _startThread = rtc::Thread::Current(); - _asyncInvoker.reset(new rtc::AsyncInvoker()); - - SetCaptureFormat(&format); - SetCaptureState(cricket::CS_RUNNING); - rtc::Thread::Start(); - return cricket::CS_RUNNING; - } - - virtual void Stop() - { - LDebug("Stop") - SetCaptureFormat(nullptr); - SetCaptureState(cricket::CS_STOPPED); - - rtc::Thread::Stop(); - _asyncInvoker.reset(); - } - - virtual bool GetPreferredFourccs(std::vector* fourccs) - { - fourccs->push_back(cricket::FOURCC_IYUV); - return true; - } - - virtual bool IsScreencast() const - { - return false; - } - - virtual bool IsRunning() - { - return this->capture_state() == cricket::CS_RUNNING; - } - -private: - YuvFrameGenerator* _frameGenerator; - int _frameIndex; - int _width; - int _height; - rtc::Thread* _startThread; - std::unique_ptr _asyncInvoker; -}; - - -} } // namespace scy::wrtc - - -#endif diff --git a/src/webrtc/samples/CMakeLists.txt b/src/webrtc/samples/CMakeLists.txt deleted file mode 100644 index 1043f7803..000000000 --- a/src/webrtc/samples/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -if(HAVE_WEBRTC) - if(HAVE_FFMPEG) - add_subdirectory(webrtcstreamer) - #add_subdirectory(webrtcrecorder) - endif() - #add_subdirectory(webrtccapturer) -endif() diff --git a/src/webrtc/samples/webrtccapturer/CMakeLists.txt b/src/webrtc/samples/webrtccapturer/CMakeLists.txt deleted file mode 100644 index 427c70482..000000000 --- a/src/webrtc/samples/webrtccapturer/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -include_dependency(WebRTC REQUIRED) - -define_sourcey_module_sample(webrtccapturer base crypto av net http util json socketio symple webrtc) diff --git a/src/webrtc/samples/webrtccapturer/README.md b/src/webrtc/samples/webrtccapturer/README.md deleted file mode 100644 index ac47b43de..000000000 --- a/src/webrtc/samples/webrtccapturer/README.md +++ /dev/null @@ -1,21 +0,0 @@ -# WebRTC Native Video Capturer - -This sample demonstrates how to stream audio and video capture devices from a native app to the browser. - -## Installation - -1. Compile LibSourcey with WebRTC support (`WITH_WEBRTC=ON`) and samples (`BUILD_SAMPLES_webrtc=ON`) enabled. See the main README for help: https://github.com/sourcey/libsourcey#installing-on-linux -2. Run the `webrtccapturer` sample application from the `build` directory. -2. Install and run the Node.js client application: - -~~~ bash -cd /src/webrtc/samples/webrtccapturer/client -npm install -node app -~~~ - -3. Finally, point your browser to: `http://localhost:4499` - -## Hacking - -The source code is clear and concise, let it be your guide :) diff --git a/src/webrtc/samples/webrtccapturer/client/README.md b/src/webrtc/samples/webrtccapturer/client/README.md deleted file mode 100644 index ac7df1d1e..000000000 --- a/src/webrtc/samples/webrtccapturer/client/README.md +++ /dev/null @@ -1,42 +0,0 @@ -# Symple WebRTC Video Chat Demo - -The Symple video chat demo is an example of how to use the Symple for instant messaging and WebRTC signaling in about 100 lines of JavaScript. External projects used are AngularJS, Bootstrap, Node.js and Express. - -See this blog post for more information about the demo: https://sourcey.com/symple-webrtc-video-chat-demo - -## What is Symple? - -Symple is a unrestrictive real-time messaging and presence protocol. - -The protocol itself is semantically similar to XMPP, except that it is much more flexible and economical due to the use of JSON instead of XML for encoding messages. - -Symple currently has client implementations in [JavaScript](https://github.com/sourcey/symple-client), [Ruby](https://github.com/sourcey/symple-client-ruby) and [C++](https://github.com/sourcey/libsourcey/tree/master/src/symple), which make it ideal for a wide range of messaging requirements, such as building real-time games and applications which run in the web browser, desktop, and mobile phone. - -## Usage - -1. Install dependencies: `npm install` -2. Fire up the server: `node app` -3. And point your browser to: `http://localhost:4500` - -## Hacking - -Some key options are specified in the main HTML file located at `index.ejs` - -**CLIENT_OPTIONS** This is the options hash for the Symple client. This is where you specify the server URL and Peer object. Note that we have disabled 'websocket' transport by default, but you will probably want to re-enable it in production. - -**WEBRTC_CONFIG** This is the PeerConnection options hash. In production you will want to specify some TURN servers so as to ensure the p2p connection succeeds in all network topologies. - -Other than that all relevant JavaScript is located in `public/js/app.js` and `public/js/helpers.js`. Enjoy! - -## Contributing - -1. Fork it -2. Create your feature branch (`git checkout -b my-new-feature`) -3. Commit your changes (`git commit -am 'Add some feature'`) -4. Push to the branch (`git push origin my-new-feature`) -5. Create new Pull Request - -## Contact - -For more information please check out the Symple homepage: https://sourcey.com/symple/ -If you have a bug or an issue then please use the Github issue tracker: https://github.com/sourcey/symple-client/issues diff --git a/src/webrtc/samples/webrtccapturer/client/app.js b/src/webrtc/samples/webrtccapturer/client/app.js deleted file mode 100644 index e42e3d8a3..000000000 --- a/src/webrtc/samples/webrtccapturer/client/app.js +++ /dev/null @@ -1,39 +0,0 @@ -// -/// Setup the Symple server - -var Symple = require('symple'); -var sy = new Symple(); -sy.loadConfig(__dirname + '/symple.json'); // see symple.json for options -sy.init(); -console.log('Symple server listening on port ' + sy.config.port); - - -// -/// Setup the demo client web server - -var express = require('express'), - path = require('path'), - app = express(), - serverPort = parseInt(sy.config.port) - clientPort = serverPort - 1; - -app.set('port', clientPort); -app.set('view engine', 'ejs'); -app.set('views', __dirname + '/'); -app.use(express.static(__dirname + '/assets')); -app.use(express.static(__dirname + '/node_modules')); - -app.get('/', function (req, res) { - res.render('index', { - port: serverPort, - peer: { - user: 'demo', - name: 'Demo User', - group: 'public' - } - }); -}); - -app.listen(app.get('port'), function () { - console.log('Web server listening on port ' + app.get('port')); -}); diff --git a/src/webrtc/samples/webrtccapturer/client/assets/main.css b/src/webrtc/samples/webrtccapturer/client/assets/main.css deleted file mode 100644 index 5ce922544..000000000 --- a/src/webrtc/samples/webrtccapturer/client/assets/main.css +++ /dev/null @@ -1,13 +0,0 @@ -body > .container { - padding-top: 30px; -} - -#webrtc-video { - margin-bottom: 1rem; -} - -#webrtc-video, -#webrtc-video .symple-player { - min-height: 480px; - background: #000; -} diff --git a/src/webrtc/samples/webrtccapturer/client/assets/main.js b/src/webrtc/samples/webrtccapturer/client/assets/main.js deleted file mode 100644 index 4aae4b1e0..000000000 --- a/src/webrtc/samples/webrtccapturer/client/assets/main.js +++ /dev/null @@ -1,263 +0,0 @@ -$(document).ready(function() { - var client, player, remotePeer, remoteStreamingDevice; - - // - // WebRTC player - - function recreatePlayer() { - console.log('Recreate player:', player); - destroyPlayer(); - - player = new Symple.Player({ - element: '#webrtc-video .video-player', - engine: 'WebRTC', - rtcConfig: WEBRTC_CONFIG, - iceMediaConstraints: { - 'mandatory': { - 'OfferToReceiveAudio': true, - 'OfferToReceiveVideo': true - } - }, - onStateChange: function(player, state) { - player.displayStatus(state); - } - }); - player.setup(); - } - - function destroyPlayer() { - if (player) { - player.destroy() - player = null; - } - } - - - // - //= Commands - - // Get a list of streaming devices from the peer - var refreshStreamingDevices = function(peer) { - client.sendCommand({ - node: 'streaming:devices', - to: peer - }); - }; - - // Start streaming video from the peer - var startStreaming = function(peer, device) { - recreatePlayer(); - - remoteStreamingDevice = device; - client.sendCommand({ - node: 'streaming:start', - to: peer, - data: { - device: device - } - }); - }; - - // Stop streaming video from the peer - var stopStreaming = function(peer, device) { - destroyPlayer(); - - remoteStreamingDevice = null; - client.sendCommand({ - node: 'streaming:stop', - to: peer, - data: { - device: device - } - }); - }; - - - // - // Bind UI events - - $('#streaming-devices').on('click', 'a', function(event) { - var $this = $(this), - user = $this.data('user'), - device = $this.data('device'), - isActive = $this.hasClass('active'); - if (isActive) { - $this.removeClass('active'); - stopStreaming(user, device); - } - else { - $this.addClass('active').siblings().removeClass('active'); - startStreaming(user, device); - } - - event.preventDefault(); - }); - - - // - // Symple client - - client = new Symple.Client(CLIENT_OPTIONS); - - client.on('announce', function(peer) { - // console.log('Authentication success:', peer); - }); - - client.on('presence', function(p) { - // console.log('Recv presence:', p); - - // Handle presence packets from peers - }); - - client.on('message', function(m) { - // console.log('Recv message:', m); - - // Handle messages from peers - }); - - client.on('command', function(c) { - // console.log('Recv command:', c) - - if (remotePeer && remotePeer.id != c.from.id) { - console.log('Dropping message from unknown peer', m); - return; - } - - if (c.node == 'streaming:start') { - if (c.status == 200) { - // Streaming start success response - // TODO: Update button state? - // createPlayer(); - } - else { - // Command error - } - } - - else if (c.node == 'streaming:devices') { - if (c.status == 200) { - - // Add new devices to the list - var $devs = $('#streaming-devices'); - for (var i = 0; i < c.data.devices.length; i++) { - var dev = c.data.devices[i]; - if (!$devs.find('[data-device="' + dev + '"]').length) - $devs.append('' + c.from.user + ': ' + dev + ''); - } - } - else { - // Command error - } - } - - else if (c.node == 'streaming:files') { - // TODO: file streaming - } - }); - - client.on('event', function(e) { - // console.log('Recv event:', e) - - // Just handle events from he current streaming peer - // for the porpose of this demo - if (remotePeer && remotePeer.id != e.from.id) { - console.log('Dropping message from unknown peer', m); - return; - } - - // ICE SDP - if (e.name == 'ice:sdp') { - try { - console.log('Reieve offer:', e.sdp); - - remotePeer = e.from; - player.play(); - player.engine.recvRemoteSDP(e.sdp); - player.engine.sendLocalSDP = function(desc) { - console.log('Send answer:', desc) - client.send({ - to: remotePeer, - name: 'ice:sdp', - type: 'event', - sdp: desc - }); - } - - player.engine.sendLocalCandidate = function(cand) { - client.send({ - to: remotePeer, - name: 'ice:candidate', - type: 'event', - candidate: cand - }); - } - } - catch (e) { - console.log("Failed to create PeerConnection:", e); - } - - // if (e.sdp.type == 'offer') { - - // // Create the remote player on offer - // if (!$scope.remotePlayer) { - // $scope.remotePlayer = createPlayer($scope, 'answerer', '#video .remote-video'); - // $scope.remotePlayer.play(); - // } - // $scope.remotePlayer.engine.recvRemoteSDP(e.sdp); - // } - // if (e.sdp.type == 'answer') { - // $scope.localPlayer.engine.recvRemoteSDP(e.sdp); - // } - } - - // ICE Candidate - else if (e.name == 'ice:candidate') { - console.log('Recreate player:', player); - player.engine.recvRemoteCandidate(e.candidate); - - // if (e.origin == 'answerer') - // $scope.localPlayer.engine.recvRemoteCandidate(e.candidate); - // else //if (e.origin == 'caller') - // $scope.remotePlayer.engine.recvRemoteCandidate(e.candidate); - // // else - // alert('Unknown candidate origin'); - } - - else { - alert('Unknown event: ' + e.name); - } - }); - - // client.on('event', function(e) { - // console.log('Recv event:', e) - // }); - - client.on('disconnect', function() { - // console.log('Disconnected from server') - }); - - client.on('error', function(error, message) { - // console.log('Peer error:', error, message) - }); - - client.on('addPeer', function(peer) { - // console.log('Adding peer:', peer) - - // Get a list of streaming devices as soon as the peer connects - if (peer.type == 'demo') { - refreshStreamingDevices(peer); - } - }); - - client.on('removePeer', function(peer) { - // console.log('Removing peer:', peer) - $('[data-user="' + peer.user + '"]').remove(); - if (remotePeer && remotePeer.id == peer.id) { - remotePeer = null; - destroyPlayer(); - } - }); - - client.connect(); -}); diff --git a/src/webrtc/samples/webrtccapturer/client/index.ejs b/src/webrtc/samples/webrtccapturer/client/index.ejs deleted file mode 100644 index a6e4113a5..000000000 --- a/src/webrtc/samples/webrtccapturer/client/index.ejs +++ /dev/null @@ -1,88 +0,0 @@ - - - - - - - LibSourcey WebRTC Capturer - - - - - - - - - - - - - - - - - - -
- - -
-
-
-
-
-
-
-
-
-
- Devices -
-
-
-
-
-
-
-
-
-
- Logs -
-
-

-            
-
-
-
-
- - diff --git a/src/webrtc/samples/webrtccapturer/client/package.json b/src/webrtc/samples/webrtccapturer/client/package.json deleted file mode 100644 index 738be5811..000000000 --- a/src/webrtc/samples/webrtccapturer/client/package.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "name": "libsourcey-webrtc-capturer", - "title": "LibSourcey WebRTC Capturer", - "version": "0.1.0", - "private": false, - "scripts": { - "start": "node app.js" - }, - "dependencies": { - "symple" : "*", - "symple-client" : "*", - "symple-client-player" : "*", - "express" : "~4.13.3", - "ejs" : "~2.3.4" - } -} diff --git a/src/webrtc/samples/webrtccapturer/client/symple.json b/src/webrtc/samples/webrtccapturer/client/symple.json deleted file mode 100644 index 3c25528c1..000000000 --- a/src/webrtc/samples/webrtccapturer/client/symple.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - /* The ID of the node instance */ - "nodeId" : 1, - - /* The port to listen on */ - "port" : 4500, - - /* Allow anonymous connections */ - "anonymous" : true, - - /* Session ttl in minutes */ - "sessionTtl" : 15/*,*/ - - /* Redis configuration - "redis" : { - "host" : "localhost", - "port" : 6379 - }, */ - - /* SSL configuration - "ssl" : { - "enabled" : false, - "key" : "ssl/symple.key", - "cert" : "ssl/symple.crt" - } */ -} diff --git a/src/webrtc/samples/webrtccapturer/main.cpp b/src/webrtc/samples/webrtccapturer/main.cpp deleted file mode 100644 index 462248965..000000000 --- a/src/webrtc/samples/webrtccapturer/main.cpp +++ /dev/null @@ -1,59 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -/// - - -#include "scy/idler.h" -#include "scy/logger.h" -#include "signaler.h" -#include "util.h" - -#include "webrtc/base/ssladapter.h" -#include "webrtc/base/thread.h" - - -using std::endl; -using namespace scy; - - -int main(int argc, char** argv) -{ - Logger::instance().add(new ConsoleChannel("debug", Level::Trace)); // Level::Trace, Level::Debug - - // Setup WebRTC environment - rtc::LogMessage::LogToDebug(rtc::LS_VERBOSE); // LS_VERBOSE, LS_INFO, LERROR - rtc::LogMessage::LogTimestamps(); - rtc::LogMessage::LogThreads(); - - rtc::InitializeSSL(); - - { - smpl::Client::Options options; - options.host = getDefaultServerName(); - options.port = 4500; - options.name = getPeerName(); - options.user = getUsername(); - options.type = "demo"; - - // NOTE: The server uses anonymous authentication for this demo. - // options.token = ""; token based authentication - - Signaler app(options); - - // Process WebRTC threads on the main loop. - auto rtcthread = rtc::Thread::Current(); - Idler rtc([=]() { - rtcthread->ProcessMessages(1); - }); - - app.waitForShutdown(); - } - - rtc::CleanupSSL(); - Logger::destroy(); - - return 0; -} diff --git a/src/webrtc/samples/webrtccapturer/signaler.cpp b/src/webrtc/samples/webrtccapturer/signaler.cpp deleted file mode 100644 index 4af84b289..000000000 --- a/src/webrtc/samples/webrtccapturer/signaler.cpp +++ /dev/null @@ -1,293 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -/// - - -#include "signaler.h" -#include "util.h" - -#include "scy/av/codec.h" -#include "scy/av/format.h" -#include "scy/filesystem.h" -#include "scy/util.h" - -#include "scy/webrtc/peerfactorycontext.h" -#include "scy/webrtc/util.h" - -#include -#include - - -using std::endl; - - -namespace scy { - - -Signaler::Signaler(const smpl::Client::Options& options) - : _client(options) -{ - _client.StateChange += slot(this, &Signaler::onClientStateChange); - _client.roster().ItemAdded += slot(this, &Signaler::onPeerConnected); - _client.roster().ItemRemoved += slot(this, &Signaler::onPeerDiconnected); - _client += packetSlot(this, &Signaler::onPeerCommand); - _client += packetSlot(this, &Signaler::onPeerEvent); - _client += packetSlot(this, &Signaler::onPeerMessage); - _client.connect(); - - _context.initCustomNetworkManager(); -} - - -Signaler::~Signaler() -{ -} - - -void Signaler::sendSDP(wrtc::Peer* conn, const std::string& type, - const std::string& sdp) -{ - assert(type == "offer" || type == "answer"); - - smpl::Event e({ - { "name", "ice:sdp" }, - { "sdp", { - { wrtc::kSessionDescriptionTypeName, type }, - { wrtc::kSessionDescriptionSdpName, sdp } - }} - }); - - postMessage(e); -} - - -void Signaler::sendCandidate(wrtc::Peer* conn, const std::string& mid, - int mlineindex, const std::string& sdp) -{ - smpl::Event e({ - { "name", "ice:candidate" }, - { "candidate", { - { wrtc::kCandidateSdpMidName, mid }, - { wrtc::kCandidateSdpMlineIndexName, mlineindex}, - { wrtc::kCandidateSdpName, sdp} - }} - }); - - postMessage(e); -} - - -void Signaler::onPeerConnected(smpl::Peer& peer) -{ - if (peer.id() == _client.ourID()) - return; - LDebug("Peer connected: ", peer.id()) - - if (wrtc::PeerManager::exists(peer.id())) { - LDebug("Peer already has a session: ", peer.id()) - } -} - - -void Signaler::onPeerCommand(smpl::Command& c) -{ - LDebug("Peer command: ", c.from().toString()) - - // List available devices for streaming - if (c.node() == "streaming:devices") { - json::value devices; - auto devs = wrtc::getVideoCaptureDevices(); - for (auto dev : devs) { - devices.push_back(dev); - } - - c.setData("devices", devices); - c.setStatus(200); - _client.respond(c); - } - - // List available files for streaming - else if (c.node() == "streaming:files") { - json::value files; - StringVec nodes; - fs::readdir(getDataDirectory(), nodes); - for (auto node : nodes) { - files.push_back(node); - } - - c.setData("files", files); - c.setStatus(200); - _client.respond(c); - } - - // Start a streaming session - else if (c.node() == "streaming:start") { - std::string device = c.data("device").get(); - - // Stream a file from the filesystem like so: - // std::string file = c.data("file").get(); - // std::string filePath(getDataDirectory()); - // fs::addnode(filePath, file); - - // Create the Peer Connection - auto conn = new wrtc::Peer(this, &_context, c.from().id, c.id(), wrtc::Peer::Offer); - conn->constraints().SetMandatoryReceiveAudio(false); - conn->constraints().SetMandatoryReceiveVideo(false); - conn->constraints().SetAllowDtlsSctpDataChannels(); - - // conn->setPortRange(40000, 40001); - - // Create tracks and device captures - rtc::scoped_refptr audio_track( - _context.factory->CreateAudioTrack(wrtc::kAudioLabel, - _context.factory->CreateAudioSource(nullptr))); - rtc::scoped_refptr video_track( - _context.factory->CreateVideoTrack(wrtc::kVideoLabel, - _context.factory->CreateVideoSource( - wrtc::openWebRtcVideoCaptureDevice(device), nullptr))); - - // Create the media stream and attach device captures - auto stream = conn->createMediaStream(); - stream->AddTrack(audio_track); - stream->AddTrack(video_track); - - // Send the Offer SDP - conn->createConnection(); - conn->createOffer(); - - wrtc::PeerManager::add(c.from().id, conn); - - c.setStatus(200); - _client.respond(c); - } - - // Stop streaming - else if (c.node() == "streaming:stop") { - auto conn = wrtc::PeerManager::get(c.from().id, false); - if (conn) { - LDebug("Closing peer connection: ", c.from().id) - conn->closeConnection(); // will be deleted via callback - } - } - - // Start a recording session - // else if (c.node() == "recording:start") { - // - // av::EncoderOptions options; - // options.ofile = OUTPUT_FILENAME; - // options.oformat = OUTPUT_FORMAT; - // - // auto conn = new RecordingPeerConnection(this, c.from().id, c.id(), options); - // conn->constraints().SetMandatoryReceiveVideo(true); - // conn->constraints().SetMandatoryReceiveAudio(true); - // conn->createConnection(); - // wrtc::PeerManager::add(c.id(), conn); - // - // c.setStatus(200); - // _client.respond(c); - // // _client.persistence().add(c.id(), reinterpret_cast(c.clone()), 0); - // } -} - - -void Signaler::onPeerEvent(smpl::Event& e) -{ - LDebug("Peer event: ", e.from().toString()) - - if (e.name() == "ice:sdp") { - recvSDP(e.from().id, e["sdp"]); - } - else if (e.name() == "ice:candidate") { - recvCandidate(e.from().id, e["candidate"]); - } -} - - -void Signaler::onPeerMessage(smpl::Message& m) -{ - LDebug("Peer message: ", m.from().toString()) -} - - -void Signaler::onPeerDiconnected(const smpl::Peer& peer) -{ - LDebug("Peer disconnected") - - // TODO: Loop all and close for peer - - auto conn = get(peer.id(), false); - if (conn) { - LDebug("Closing peer connection: ", peer.id()) - conn->closeConnection(); // will be deleted via callback - } -} - - -void Signaler::onClientStateChange(void* sender, sockio::ClientState& state, - const sockio::ClientState& oldState) -{ - LDebug("Client state changed from " << oldState << " to ", state) - - switch (state.id()) { - case sockio::ClientState::Connecting: - break; - case sockio::ClientState::Connected: - break; - case sockio::ClientState::Online: - break; - case sockio::ClientState::Error: - throw std::runtime_error("Cannot connect to Symple server. " - "Did you start the demo app and the " - "Symple server is running on port 4500?"); - } -} - - -void Signaler::onAddRemoteStream(wrtc::Peer* conn, webrtc::MediaStreamInterface* stream) -{ -} - - -void Signaler::onRemoveRemoteStream(wrtc::Peer* conn, webrtc::MediaStreamInterface* stream) -{ - assert(0 && "free streams"); -} - - -void Signaler::onStable(wrtc::Peer* conn) -{ -} - - -void Signaler::onClosed(wrtc::Peer* conn) -{ - wrtc::PeerManager::onClosed(conn); -} - - -void Signaler::onFailure(wrtc::Peer* conn, const std::string& error) -{ - wrtc::PeerManager::onFailure(conn, error); -} - - -void Signaler::postMessage(const smpl::Message& m) -{ - _ipc.push(new ipc::Action( - std::bind(&Signaler::syncMessage, this, std::placeholders::_1), - m.clone())); -} - - -void Signaler::syncMessage(const ipc::Action& action) -{ - auto m = reinterpret_cast(action.arg); - _client.send(*m); - delete m; -} - - -} // namespace scy diff --git a/src/webrtc/samples/webrtccapturer/signaler.h b/src/webrtc/samples/webrtccapturer/signaler.h deleted file mode 100644 index 7d26f19cf..000000000 --- a/src/webrtc/samples/webrtccapturer/signaler.h +++ /dev/null @@ -1,69 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// - - -#ifndef SCY_WebRTC_Signaler_H -#define SCY_WebRTC_Signaler_H - - -#include "scy/application.h" -#include "scy/ipc.h" -#include "scy/net/sslmanager.h" -#include "scy/net/sslsocket.h" -#include "scy/symple/client.h" -#include "scy/webrtc/peermanager.h" - - -namespace scy { - - -class Signaler : public wrtc::PeerManager, public Application -{ -public: - Signaler(const smpl::Client::Options& options); - ~Signaler(); - -protected: - - /// PeerManager interface - void sendSDP(wrtc::Peer* conn, const std::string& type, const std::string& sdp) override; - void sendCandidate(wrtc::Peer* conn, const std::string& mid, int mlineindex, const std::string& sdp) override; - void onAddRemoteStream(wrtc::Peer* conn, webrtc::MediaStreamInterface* stream) override; - void onRemoveRemoteStream(wrtc::Peer* conn, webrtc::MediaStreamInterface* stream) override; - void onStable(wrtc::Peer* conn); - void onClosed(wrtc::Peer* conn); - void onFailure(wrtc::Peer* conn, const std::string& error); - - void postMessage(const smpl::Message& m); - void syncMessage(const ipc::Action& action); - - void onPeerConnected(smpl::Peer& peer); - void onPeerCommand(smpl::Command& m); - void onPeerEvent(smpl::Event& m); - void onPeerMessage(smpl::Message& m); - void onPeerDiconnected(const smpl::Peer& peer); - - void onClientStateChange(void* sender, sockio::ClientState& state, const sockio::ClientState& oldState); - -protected: - wrtc::PeerFactoryContext _context; - -#if USE_SSL - smpl::SSLClient _client; -#else - smpl::TCPClient _client; -#endif - ipc::SyncQueue<> _ipc; -}; - - -} // namespace scy - - -#endif // SCY_WebRTC_Signaler_H diff --git a/src/webrtc/samples/webrtccapturer/util.h b/src/webrtc/samples/webrtccapturer/util.h deleted file mode 100644 index a4c931981..000000000 --- a/src/webrtc/samples/webrtccapturer/util.h +++ /dev/null @@ -1,91 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -/// - - -#ifndef SCY_WebRTC_Util_H -#define SCY_WebRTC_Util_H - - -#include "scy/webrtc/webrtc.h" -#include "scy/filesystem.h" - -#include -#include - -#ifdef WIN32 -#include -#else -#include -#endif - - -#include "webrtc/base/arraysize.h" - - -namespace scy { - - -inline std::string getEnvVarOrDefault(const char* env_var_name, const char* default_value) -{ - std::string value; - const char* env_var = getenv(env_var_name); - if (env_var) - value = env_var; - - if (value.empty()) - value = default_value; - - return value; -} - - -inline std::string getPeerConnectionString() -{ - return getEnvVarOrDefault("WEBRTC_CONNECT", "stun:stun.l.google.com:19302"); -} - - -inline std::string getDefaultServerName() -{ - return getEnvVarOrDefault("WEBRTC_SERVER", "localhost"); -} - - -inline std::string getUsername() -{ - std::string def = "demo-" + util::randomString(6); - return getEnvVarOrDefault("USERNAME", def.c_str()); -} - - -inline std::string getPeerName() -{ - char computer_name[256]; - std::string ret(getUsername()); - ret += '@'; - if (gethostname(computer_name, arraysize(computer_name)) == 0) { - ret += computer_name; - } - else { - ret += "host"; - } - return ret; -} - - -inline std::string getDataDirectory() -{ - std::string dir(getCwd()); - fs::addnode(dir, "data"); - return dir; -} - - -} // namespace scy - - -#endif diff --git a/src/webrtc/samples/webrtcrecorder/CMakeLists.txt b/src/webrtc/samples/webrtcrecorder/CMakeLists.txt deleted file mode 100644 index 6d52db5a1..000000000 --- a/src/webrtc/samples/webrtcrecorder/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -include_dependency(WebRTC REQUIRED) -include_dependency(FFmpeg REQUIRED) - -define_sourcey_module_sample(webrtcrecorder base crypto av net http util json socketio symple webrtc) diff --git a/src/webrtc/samples/webrtcrecorder/README.md b/src/webrtc/samples/webrtcrecorder/README.md deleted file mode 100644 index 06f2e68a7..000000000 --- a/src/webrtc/samples/webrtcrecorder/README.md +++ /dev/null @@ -1,22 +0,0 @@ -# WebRTC Native Video Recorder - -This sample app showcases how to record live WebRTC video streams on the server side using LibSourcey. Audio and video streams are recorded and multiplexed in MP4 format (H.264/ACC) by default, but any format supported by LibSourcey/FFmpeg can be used. - -## Installation - -1. Compile LibSourcey with WebRTC support (`WITH_WEBRTC=ON`) and samples (`BUILD_SAMPLES_webrtc=ON`) enabled. See the main README for help: https://github.com/sourcey/libsourcey#installing-on-linux -2. Run the `webrtcrecorder` sample application from the `build` directory. -2. Install and run the Node.js client application: - -~~~ bash -cd /src/webrtc/samples/webrtcrecorder/client -npm install -node app -~~~ - -3. Finally, point your browser to: `http://localhost:4499` -4. Your WebRTC stream will be recorded as `webrtcrecorder.mp4`. - -## Hacking - -The source code is clear and concise, let it be your guide :) diff --git a/src/webrtc/samples/webrtcrecorder/client/.gitignore b/src/webrtc/samples/webrtcrecorder/client/.gitignore deleted file mode 100644 index 1c5f63926..000000000 --- a/src/webrtc/samples/webrtcrecorder/client/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -~* -*~ -bak -log -node_modules diff --git a/src/webrtc/samples/webrtcrecorder/client/app.js b/src/webrtc/samples/webrtcrecorder/client/app.js deleted file mode 100644 index 60b63f037..000000000 --- a/src/webrtc/samples/webrtcrecorder/client/app.js +++ /dev/null @@ -1,40 +0,0 @@ -// -/// Setup the Symple server - -var Symple = require('symple'); -var sy = new Symple(); -sy.loadConfig(__dirname + '/symple.json'); // see symple.json for options -sy.init(); -console.log('Symple server listening on port ' + sy.config.port); - - -// -/// Setup the demo client web server - -var express = require('express'), - path = require('path'), - app = express(), - serverPort = parseInt(sy.config.port) - clientPort = serverPort - 1; - -app.set('port', clientPort); -app.set('view engine', 'ejs'); -app.set('views', __dirname + '/'); -app.use(express.static(__dirname + '/assets')); -//app.use(express.static(__dirname + '/node_modules/symple-client/src')); -//app.use(express.static(__dirname + '/node_modules/symple-client-player/src')); - -app.get('/', function (req, res) { - res.render('index', { - port: serverPort, - peer: { - user: 'demo', - name: 'Demo User', - group: 'public' - } - }); -}); - -app.listen(app.get('port'), function () { - console.log('Web server listening on port ' + app.get('port')); -}); diff --git a/src/webrtc/samples/webrtcrecorder/client/assets/main.css b/src/webrtc/samples/webrtcrecorder/client/assets/main.css deleted file mode 100644 index 3d741c645..000000000 --- a/src/webrtc/samples/webrtcrecorder/client/assets/main.css +++ /dev/null @@ -1,11 +0,0 @@ -body > .container { - padding-top: 30px; -} - -#webrtc-video .video-player { - margin-bottom: 1rem; -} - -#webrtc-video .symple-player { - min-height: 480px; -} diff --git a/src/webrtc/samples/webrtcrecorder/client/assets/main.js b/src/webrtc/samples/webrtcrecorder/client/assets/main.js deleted file mode 100644 index fc57a5263..000000000 --- a/src/webrtc/samples/webrtcrecorder/client/assets/main.js +++ /dev/null @@ -1,107 +0,0 @@ -$(document).ready(function() { - var client, player, remotePeer, initialized = false; - - // - // Initialize the Symple WebRTC player - - player = new Symple.Player({ - element: '#webrtc-video .video-player', - engine: 'WebRTC', - initiator: true, - rtcConfig: WEBRTC_CONFIG, - iceMediaConstraints: { - 'mandatory': { - 'OfferToReceiveAudio': false, - 'OfferToReceiveVideo': false - } - }, - onStateChange: function(player, state) { - player.displayStatus(state); - } - }); - - function startPlaybackAndRecording() { - // player.setup(); - player.play(); //{ localMedia: true, disableAudio: false, disableVideo: false } - player.engine.sendLocalSDP = function(desc) { - console.log('Send offer:', JSON.stringify(desc)) - client.send({ - to: remotePeer, - type: 'message', - offer: desc - }); - } - - player.engine.sendLocalCandidate = function(cand) { - client.send({ - to: remotePeer, - type: 'message', - candidate: cand - }); - } - } - - // - // Initialize the Symple client - - client = new Symple.Client(CLIENT_OPTIONS); - - client.on('announce', function(peer) { - console.log('Authentication success:', peer); - }); - - client.on('addPeer', function(peer) { - console.log('Adding peer:', peer); - - if (peer.user == 'videorecorder' && - !initialized) { - initialized = true; - remotePeer = peer; //m.from; - startPlaybackAndRecording(); - } - }); - - client.on('removePeer', function(peer) { - console.log('Removing peer:', peer); - }); - - client.on('message', function(m) { - // console.log('Recv message:', m) - if (remotePeer && remotePeer.id != m.from.id) { - console.log('Dropping message from unknown peer', m); - return; - } - if (m.offer) { - alert('Unexpected offer for one-way streaming'); - } - else if (m.answer) { - console.log('Reieve answer:', JSON.stringify(m.answer)); - player.engine.recvRemoteSDP(m.answer); - } - else if (m.candidate) { - player.engine.recvRemoteCandidate(m.candidate); - } - }); - - // client.on('presence', function(p) { - // console.log('Recv presence:', p) - // }); - - // client.on('command', function(c) { - // console.log('Recv command:', c) - // }); - - // client.on('event', function(e) { - // console.log('Recv event:', e) - // }); - - client.on('disconnect', function() { - console.log('Disconnected from server') - }); - - client.on('error', function(error, message) { - console.log('Peer error:', error, message) - }); - - client.connect(); -}); diff --git a/src/webrtc/samples/webrtcrecorder/client/assets/symple.client.js b/src/webrtc/samples/webrtcrecorder/client/assets/symple.client.js deleted file mode 100644 index 4cb41d078..000000000 --- a/src/webrtc/samples/webrtcrecorder/client/assets/symple.client.js +++ /dev/null @@ -1,542 +0,0 @@ -// ----------------------------------------------------------------------------- -// Symple Client -// -Symple.Client = Symple.Dispatcher.extend({ - init: function(options) { - this.options = Symple.extend({ //$.extend - url: options.url ? options.url : 'http://localhost:4000', - secure: options.url && ( - options.url.indexOf('https') == 0 || - options.url.indexOf('wss') == 0) ? true : false, - token: undefined // pre-arranged server session token - //timeout: 0 // set for connection timeout - }, options); - this._super(); - this.peer = options.peer || {}; - this.peer.rooms = options.peer.rooms || []; - this.roster = new Symple.Roster(this); - this.socket = null; - }, - - // Connects and authenticates on the server. - // If the server is down the 'error' event will fire. - connect: function() { - Symple.log('symple:client: connecting', this.options); - self = this; - if (this.socket) - throw 'The client socket is not null' - this.socket = io.connect(this.options.url, this.options); - this.socket.on('connect', function() { - Symple.log('symple:client: connected'); - self.socket.emit('announce', { - token: self.options.token || '', - user: self.peer.user || '', - name: self.peer.name || '', - type: self.peer.type || '' - }, function(res) { - Symple.log('symple:client: announced', res); - if (res.status != 200) { - self.setError('auth', res); - return; - } - self.peer = Symple.extend(self.peer, res.data); // $.extend - self.roster.add(res.data); - self.sendPresence({ probe: true }); - self.dispatch('announce', res); - self.socket.on('message', function(m) { - // Symple.log('symple:client: receive', m); - if (typeof(m) == 'object') { - switch(m.type) { - case 'message': - m = new Symple.Message(m); - break; - case 'command': - m = new Symple.Command(m); - break; - case 'event': - m = new Symple.Event(m); - break; - case 'presence': - m = new Symple.Presence(m); - if (m.data.online) - self.roster.update(m.data); - else - self.roster.remove(m.data.id); - if (m.probe) - self.sendPresence(new Symple.Presence({ - to: Symple.parseAddress(m.from).id - })); - break; - default: - o = m; - o.type = o.type || 'message'; - break; - } - - if (typeof(m.from) != 'string') { - Symple.log('symple:client: invalid sender address', m); - return; - } - - // Replace the from attribute with the full peer object. - // This will only work for peer messages, not server messages. - var rpeer = self.roster.get(m.from); - if (rpeer) - m.from = rpeer; - else - Symple.log('symple:client: got message from unknown peer', m); - - // Dispatch to the application - self.dispatch(m.type, m); - } - }); - }); - }); - this.socket.on('error', function() { - // This is triggered when any transport fails, - // so not necessarily fatal. - self.dispatch('connect'); - }); - this.socket.on('connecting', function() { - Symple.log('symple:client: connecting'); - self.dispatch('connecting'); - }); - this.socket.on('reconnecting', function() { - Symple.log('symple:client: reconnecting'); - self.dispatch('reconnecting'); - }); - this.socket.on('connect_failed', function() { - // Called when all transports fail - Symple.log('symple:client: connect failed'); - self.dispatch('connect_failed'); - self.setError('connect'); - }); - this.socket.on('disconnect', function() { - Symple.log('symple:client: disconnect'); - self.peer.online = false; - self.dispatch('disconnect'); - }); - }, - - // Disconnect from the server - disconnect: function() { - if (this.socket) - this.socket.disconnect(); - }, - - // Return the online status - online: function() { - return this.peer.online; - }, - - // Join a room - join: function(room) { - this.socket.emit('join', room); - }, - - // Leave a room - leave: function(room) { - this.socket.emit('leave', room); - }, - - // Send a message to the given peer - send: function(m, to) { - // Symple.log('symple:client: before send', m, to); - if (!this.online()) - throw 'Cannot send messages while offline'; // add to pending queue? - if (typeof(m) != 'object') - throw 'Message must be an object'; - if (typeof(m.type) != 'string') - m.type = 'message'; - if (!m.id) - m.id = Symple.randomString(8); - if (to) - m.to = to; - if (m.to && typeof(m.to) == 'object') - m.to = Symple.buildAddress(m.to); - if (m.to && typeof(m.to) != 'string') - throw 'Message `to` attribute must be an address string'; - m.from = Symple.buildAddress(this.peer); - if (m.from == m.to) - throw 'Message sender cannot match the recipient'; - - Symple.log('symple:client: sending', m); - this.socket.json.send(m); - }, - - respond: function(m) { - this.send(m, m.from); - }, - - sendMessage: function(m, to) { - this.send(m, to); - }, - - sendPresence: function(p) { - p = p || {}; - if (p.data) - p.data = Symple.merge(this.peer, p.data); - else - p.data = this.peer; - this.send(new Symple.Presence(p)); - }, - - sendCommand: function(c, to, fn, once) { - var self = this; - c = new Symple.Command(c, to); - this.send(c); - if (fn) { - this.onResponse('command', { - id: c.id - }, fn, function(res) { - if (once || ( - // 202 (Accepted) and 406 (Not acceptable) response codes - // signal that the command has not yet completed. - res.status != 202 && - res.status != 406)) { - self.clear('command', fn); - } - }); - } - }, - - // Adds a capability for our current peer - addCapability: function(name, value) { - var peer = this.peer; - if (peer) { - if (typeof value == 'undefined') - value = true - if (typeof peer.capabilities == 'undefined') - peer.capabilities = {} - peer.capabilities[name] = value; - // var idx = peer.capabilities.indexOf(name); - // if (idx == -1) { - // peer.capabilities.push(name); - // this.sendPresence(); - // } - } - }, - - // Removes a capability from our current peer - removeCapability: function(name) { - var peer = this.peer; - if (peer && typeof peer.capabilities != 'undefined' && - typeof peer.capabilities[name] != 'undefined') { - delete peer.capabilities[key]; - this.sendPresence(); - // var idx = peer.capabilities.indexOf(name) - // if (idx != -1) { - // peer.capabilities.pop(name); - // this.sendPresence(); - // } - } - }, - - // Checks if a peer has a specific capbility and returns a boolean - hasCapability: function(id, name) { - var peer = this.roster.get(id) - if (peer) { - if (typeof peer.capabilities != 'undefined' && - typeof peer.capabilities[name] != 'undefined') - return peer.capabilities[name] !== false; - if (typeof peer.data != 'undefined' && - typeof peer.data.capabilities != 'undefined' && - typeof peer.data.capabilities[name] != 'undefined') - return peer.data.capabilities[name] !== false; - } - return false; - }, - - // Checks if a peer has a specific capbility and returns the value - getCapability: function(id, name) { - var peer = this.roster.get(id) - if (peer) { - if (typeof peer.capabilities != 'undefined' && - typeof peer.capabilities[name] != 'undefined') - return peer.capabilities[name]; - if (typeof peer.data != 'undefined' && - typeof peer.data.capabilities != 'undefined' && - typeof peer.data.capabilities[name] != 'undefined') - return peer.data.capabilities[name]; - } - return undefined; - }, - - // Sets the client to an error state and disconnect - setError: function(error, message) { - Symple.log('symple:client: fatal error', error, message); - // if (this.error == error) - // return; - // this.error = error; - this.dispatch('error', error, message); - if (this.socket) - this.socket.disconnect(); - }, - - onResponse: function(event, filters, fn, after) { - if (typeof this.listeners[event] == 'undefined') - this.listeners[event] = []; - if (typeof fn != 'undefined' && fn.constructor == Function) - this.listeners[event].push({ - fn: fn, // data callback function - after: after, // after data callback function - filters: filters // event filter object for matching response - }); - }, - - clear: function(event, fn) { - Symple.log('symple:client: clearing callback', event); - if (typeof this.listeners[event] != 'undefined') { - for (var i = 0; i < this.listeners[event].length; i++) { - if (this.listeners[event][i].fn === fn && - String(this.listeners[event][i].fn) == String(fn)) { - this.listeners[event].splice(i, 1); - Symple.log('symple:client: cleared callback', event); - } - } - } - }, - - // Extended dispatch function to handle filtered message response - // callbacks first, and then standard events. - dispatch: function() { - if (!this.dispatchResponse.apply(this, arguments)) { - this._super.apply(this, arguments); - } - }, - - // Dispatch function for handling filtered message response callbacks. - dispatchResponse: function() { - var event = arguments[0]; - var data = Array.prototype.slice.call(arguments, 1); - if (typeof this.listeners[event] != 'undefined') { - for (var i = 0; i < this.listeners[event].length; i++) { - if (typeof this.listeners[event][i] == 'object' && - this.listeners[event][i].filters != 'undefined' && - Symple.match(this.listeners[event][i].filters, data[0])) { - this.listeners[event][i].fn.apply(this, data); - if (this.listeners[event][i].after != 'undefined') { - this.listeners[event][i].after.apply(this, data); - } - return true; - } - } - } - return false; - } - - // getPeers: function(fn) { - // self = this; - // this.socket.emit('peers', function(res) { - // Symple.log('Peers: ', res); - // if (typeof(res) != 'object') - // for (var peer in res) - // self.roster.update(peer); - // if (fn) - // fn(res); - // }); - // } -}); - - -// ----------------------------------------------------------------------------- -// Symple Roster -// -Symple.Roster = Symple.Manager.extend({ - init: function(client) { - this._super(); - this.client = client; - }, - - // Add a peer object to the roster - add: function(peer) { - Symple.log('symple:roster: adding', peer); - if (!peer || !peer.id || !peer.user) // || !peer.group - throw 'Cannot add invalid peer' - this._super(peer); - this.client.dispatch('addPeer', peer); - }, - - // Remove the peer matching an ID or address string: user|id - remove: function(id) { - id = Symple.parseAddress(id).id || id; - var peer = this._super(id); - Symple.log('symple:roster: removing', id, peer); - if (peer) - this.client.dispatch('removePeer', peer); - return peer; - }, - - // Get the peer matching an ID or address string: user|id - get: function(id) { - - // Handle IDs - peer = this._super(id); // id = Symple.parseIDFromAddress(id) || id; - if (peer) - return peer; - - // Handle address strings - return this.findOne(Symple.parseAddress(id)); - }, - - update: function(data) { - if (!data || !data.id) - return; - var peer = this.get(data.id); - if (peer) - for (var key in data) - peer[key] = data[key]; - else - this.add(data); - } - - // Get the peer matching an address string: user|id - // getForAddr: function(addr) { - // var o = Symple.parseAddress(addr); - // if (o && o.id) - // return this.get(o.id); - // return null; - // } -}); - - -// ----------------------------------------------------------------------------- -// Helpers -// -Symple.parseAddress = function(str) { - var addr = {}, - arr = str.split("|") - - if (arr.length > 0) // no id - addr.user = arr[0]; - if (arr.length > 1) // has id - addr.id = arr[1]; - - return addr; -} - -Symple.buildAddress = function(peer) { - return (peer.user ? (peer.user + '|') : '') + - (peer.id ? peer.id : ''); -} - - -// ----------------------------------------------------------------------------- -// Message -// -Symple.Message = function(json) { - if (typeof(json) == 'object') - this.fromJSON(json); - this.type = "message"; -} - -Symple.Message.prototype = { - fromJSON: function(json) { - for (var key in json) - this[key] = json[key]; - }, - - valid: function() { - return this['id'] - && this['from']; - } -}; - - -// ----------------------------------------------------------------------------- -// Command -// -Symple.Command = function(json) { - if (typeof(json) == 'object') - this.fromJSON(json); - this.type = "command"; -} - -Symple.Command.prototype = { - getData: function(name) { - return this['data'] ? this['data'][name] : null; - }, - - params: function() { - return this['node'].split(':'); - }, - - param: function(n) { - return this.params()[n-1]; - }, - - matches: function(xuser) { - xparams = xuser.split(':'); - - // No match if x params are greater than ours. - if (xparams.length > this.params().length) - return false; - - for (var i = 0; i < xparams.length; i++) { - - // Wildcard * matches everything until next parameter. - if (xparams[i] == "*") - continue; - if (xparams[i] != this.params()[i]) - return false; - } - - return true; - }, - - fromJSON: function(json) { - for (var key in json) - this[key] = json[key]; - }, - - valid: function() { - return this['id'] - && this['from'] - && this['node']; - } -}; - - -// ----------------------------------------------------------------------------- -// Presence -// -Symple.Presence = function(json) { - if (typeof(json) == 'object') - this.fromJSON(json); - this.type = "presence"; -} - -Symple.Presence.prototype = { - fromJSON: function(json) { - for (var key in json) - this[key] = json[key]; - }, - - valid: function() { - return this['id'] - && this['from']; - } -}; - - -// ----------------------------------------------------------------------------- -// Event -// -Symple.Event = function(json) { - if (typeof(json) == 'object') - this.fromJSON(json); - this.type = "event"; -} - -Symple.Event.prototype = { - fromJSON: function(json) { - for (var key in json) - this[key] = json[key]; - }, - - valid: function() { - return this['id'] - && this['from'] - && this.name; - } -}; diff --git a/src/webrtc/samples/webrtcrecorder/client/assets/symple.js b/src/webrtc/samples/webrtcrecorder/client/assets/symple.js deleted file mode 100644 index 26bc604c8..000000000 --- a/src/webrtc/samples/webrtcrecorder/client/assets/symple.js +++ /dev/null @@ -1,385 +0,0 @@ -// ----------------------------------------------------------------------------- -// Symple JavaScript Client -// -var Symple = { - // Version - VERSION: "0.9.0", - - // Return an array of nested objects matching - // the given key/value strings. - filterObject: function(obj, key, value) { // (Object[, String, String]) - var r = [] - for (var k in obj) { - if (obj.hasOwnProperty(k)) { - var v = obj[k]; - if ((!key || k == key) && - (!value || v == value)) { - r.push(obj) - } - else if (typeof v === 'object') { - var a = Symple.filterObject(v, key, value); - if (a) r = r.concat(a); - } - } - } - return r; - }, - - // Delete nested objects with properties - // that match the given key/value strings. - deleteNested: function(obj, key, value) { // (Object[, String, String]) - for (var k in obj) { - var v = obj[k]; - if ((!key || k == key) && - (!value || v == value)) { - delete obj[k]; - } - else if (typeof v === 'object') - Symple.deleteNested(v, key); - } - }, - - // Count nested object properties which - // match the given key/value strings. - countNested: function(obj, key, value, count) { - if (count === undefined) count = 0; - for (var k in obj) { - if (obj.hasOwnProperty(k)) { - var v = obj[k]; - if ((!key || k == key) && - (!value || v == value)) { - count++; - } - else if (typeof(v) === 'object') { - //else if (v instanceof Object) { - count = Symple.countNested(v, key, value, count); - } - } - } - return count; - }, - - // Traverse an objects nested properties - traverse: function(obj, fn) { // (Object, Function) - for (var k in obj) { - if (obj.hasOwnProperty(k)) { - var v = obj[k]; - fn(k, v); - if (typeof v === 'object') - Symple.traverse(v, fn); - } - } - }, - - // Generate a random string - randomString: function(n) { - return Math.random().toString(36).slice(2) //Math.random().toString(36).substring(n || 7); - }, - - // Recursively merge object properties of r into l - merge: function(l, r) { // (Object, Object) - for (var p in r) { - try { - // Property in destination object set; update its value. - //if (typeof r[p] == "object") { - if (r[p].constructor == Object) { - l[p] = merge(l[p], r[p]); - } else { - l[p] = r[p]; - } - } catch(e) { - // Property in destination object not set; - // create it and set its value. - l[p] = r[p]; - } - } - return l; - }, - - // Object extend functionality - extend: function() { - var process = function(destination, source) { - for (var key in source) { - if (hasOwnProperty.call(source, key)) { - destination[key] = source[key]; - } - } - return destination; - }; - var result = arguments[0]; - for(var i=1; i b.preference) return -1; - }); - return arr - }, - - // Returns the highest preference compatible engine - // The optional format argument further filters by engines - // which don't support the given media format. - preferredCompatibleEngine: function(format) { - var arr = this.compatibleEngines(format), engine; - engine = arr.length ? arr[0] : null; - Symple.log('symple:media: preferred engine', engine); - return engine; - }, - - // Returns the optimal video resolution for the current device - // TODO: Different aspect ratios - getOptimalVideoResolution: function() { - var w = $(window).width(); - var width = w > 800 ? - 800 : w > 640 ? - 640 : w > 480 ? - 400 : w > 320 ? - 320 : w > 240 ? - 240 : w > 160 ? - 160 : w > 128 ? - 128 : 96; - var height = width * 0.75; - return [width, height]; - }, - - buildURL: function(params) { - var query = [], url, addr = params.address; - url = addr.scheme + '://' + addr.host + ':' + addr.port + (addr.uri ? addr.uri : '/'); - for (var p in params) { - if (p == 'address') - continue; - query.push(encodeURIComponent(p) + "=" + encodeURIComponent(params[p])); - } - query.push('rand=' + Math.random()); - url += '?'; - url += query.join("&"); - return url; - - }, - - // Rescales video dimensions maintaining perspective - // TODO: Different aspect ratios - rescaleVideo: function(srcW, srcH, maxW, maxH) { - //Symple.log('Symple Player: Rescale Video: ', srcW, srcH, maxW, maxH); - var maxRatio = maxW / maxH; - var srcRatio = 1.33; //srcW / srcH; - if (srcRatio < maxRatio) { - srcH = maxH; - srcW = srcH * srcRatio; - } else { - srcW = maxW; - srcH = srcW / srcRatio; - } - return [srcW, srcH]; - }, - - // Basic checking for remote ICE style streaming candidates - // TODO: Latency checks and best candidate switching - checkCandidate: function(url, fn) { - Symple.log('symple:media: checking candidate: ', url); - - var xhr; - if (window.XMLHttpRequest) { - xhr = new XMLHttpRequest(); - } else if (window.ActiveXObject) { - xhr = new ActiveXObject("Microsoft.XMLHTTP"); - } else { - fn(url, false); - return; - } - - xhr.onreadystatechange = function() { - if (xhr.readyState == 2) { - if (fn) { - Symple.log('symple:media: candidate result: ', xhr.readyState, xhr.status); - fn(url, xhr.status == 200); - fn = null; - - // Safari on windows crashes when abort is called from inside - // the onreadystatechange callback. - setTimeout(function() { - xhr.abort(); - }, 0); - } - } - else if (xhr.readyState == 4/* && xhr.status != 0*/) { - if (fn) { - Symple.log('symple:media: candidate result: ', xhr.readyState, xhr.status); - fn(url, /*xhr.status == 200*/true); - fn = null; - } - } - }; - xhr.open('GET', url, true); - xhr.send(null); - }, -}; - -// ---------------------------------------------------------------------------- -// Symple Player -// -// Online video streaming for everyone -// Requires jQuery -// -Symple.Player = Symple.Class.extend({ - init: function(options) { - this.options = Symple.extend({ // $.extend - format: 'MJPEG', // The media format to use (MJPEG, FLV, Speex, ...) - engine: undefined, // Engine class name, can be specified or auto detected - - htmlRoot: '/javascripts/symple', - element: '.symple-player:first', - fullscreenElement: undefined, - - // Callbacks - onCommand: function(player, cmd) { }, - onStateChange: function(player, state) { }, - - // Markup - template: '\ -
\ -
\ -
\ -
\ -
\ -
\ - Play\ - Stop\ - Fullscreen\ -
\ -
' - - }, options); - - this.element = $(this.options.element); - if (!this.element.hasClass('symple-player')) { - this.element.html(this.options.template); - this.element = this.element.children('.symple-player:first'); - } - if (!this.element.length) - throw 'Player element not found'; - - this.screen = this.element.find('.symple-player-screen'); - if (!this.screen.length) - throw 'Player screen element not found'; - - // Depreciated: Screen is always 100% unless speified otherwise via CSS - // if (this.options.screenWidth) - // this.screen.width(this.options.screenWidth); - // if (this.options.screenHeight) - // this.screen.height(this.options.screenHeight); - - this.message = this.element.find('.symple-player-message') - if (!this.message.length) - throw 'Player message element not found'; - - // Try to choose the best engine if none was given - if (typeof this.options.engine == 'undefined') { - var engine = Symple.Media.preferredCompatibleEngine(this.options.format); - if (engine) - this.options.engine = engine.id; - } - - this.bindEvents(); - this.playing = false; - - // this.setState('stopped'); - // var self = this; - // $(window).resize(function() { - // self.refresh(); - // }); - }, - - setup: function() { - var id = this.options.engine; - - // Ensure the engine is configured - if (!id) - throw "Streaming engine not configured. Please set 'options.engine'"; - - // Ensure the engine exists - if (!Symple.Media.hasEngine(id)) - throw "Streaming engine not available: " + id; - if (typeof Symple.Player.Engine[id] == 'undefined') - throw "Streaming engine not found: " + id; - - // Ensure the engine is supported - if (!Symple.Media.supportsEngine(id)) - throw "Streaming engine not supported: " + id; - - // Instantiate the engine - this.engine = new Symple.Player.Engine[id](this); - this.engine.setup(); - - this.element.addClass('engine-' + id.toLowerCase()) - }, - - // - // Player Controls - // - play: function(params) { - Symple.log('symple:player: play', params) - try { - if (!this.engine) - this.setup(); - - if (this.state != 'playing' //&& - // The player may be set to loading state by the - // outside application before play is called. - //this.state != 'loading' - ) { - this.setState('loading'); - this.engine.play(params); // engine updates state to playing - } - } catch (e) { - this.setState('error'); - this.displayMessage('error', e) - throw e; - } - }, - - stop: function() { - Symple.log('symple:player: stop') - if (this.state != 'stopped') { - if (this.engine) - this.engine.stop(); // engine updates state to stopped - } - }, - - destroy: function() { - if (this.engine) - this.engine.destroy(); - this.element.remove(); - }, - - mute: function(flag) { - flag = !!flag; - Symple.log('symple:player: mute', flag); - - if (this.engine && - this.engine.mute) - this.engine.mute(flag); - this.element[flag ? 'addClass' : 'removeClass']('muted'); - }, - - setState: function(state, message) { - Symple.log('symple:player: set state', this.state, '=>', state); - if (this.state == state) - return; - - this.state = state; - this.displayStatus(null); - this.playing = state == 'playing'; - if (message) - this.displayMessage(state == 'error' ? 'error' : 'info', message); - else - this.displayMessage(null); - this.element.removeClass('state-stopped state-loading state-playing state-paused state-error'); - this.element.addClass('state-' + state); - this.options.onStateChange(this, state, message); - }, - - // - // Helpers - // - - displayStatus: function(data) { - this.element.find('.symple-player-status').html(data ? data : ''); - }, - - // Display an overlayed player message. - // Type may be one of: error, warning, info - displayMessage: function(type, message) { - Symple.log('symple:player: display message', type, message) - if (message) { - this.message.html('

' + message + '

').show(); - } - else { - this.message.html('').hide(); - } - }, - - bindEvents: function() { - var self = this; - this.element.find('.symple-player-controls a').unbind().bind('click tap', function() { - self.sendCommand(this.rel, $(this)); - return false; - }) - }, - - sendCommand: function(cmd, e) { - if (!this.options.onCommand || - !this.options.onCommand(this, cmd, e)) { - - // If there is no command callback function or the callback returns - // false then we process these default behaviours. - switch(cmd) { - case 'play': - this.play(); - break; - case 'stop': - this.stop(); - break; - case 'mute': - this.mute(true); - break; - case 'unmute': - this.mute(false); - break; - case 'fullscreen': - this.toggleFullScreen(); - break; - } - } - }, - - getButton: function(cmd) { - return this.element.find('.symple-player-controls [rel="' + cmd + '"]'); - }, - - // TODO: Toggle actual player element - toggleFullScreen: function() { - // if (!document.fullscreenElement) { - // document.documentElement.requestFullscreen(); - // } else { - // if (document.exitFullscreen) { - // document.exitFullscreen(); - // } - // } - var fullscreenElement = $(this.options.fullscreenElement)[0] || this.element[0]; - console.log(fullscreenElement) - if (Symple.runVendorMethod(document, "FullScreen") || - Symple.runVendorMethod(document, "IsFullScreen")) { - Symple.runVendorMethod(document, "CancelFullScreen"); - } - else { - Symple.runVendorMethod(fullscreenElement, "RequestFullScreen"); - } - } -}) - - -// ----------------------------------------------------------------------------- -// Player Engine Interface -// -Symple.Player.Engine = Symple.Class.extend({ - init: function(player) { - this.player = player; - this.fps = 0; - this.seq = 0; - }, - - support: function() { return true; }, - setup: function() {}, - destroy: function() {}, - play: function(params) { - this.params = params || {}; - if (!this.params.url && typeof(params.address) == 'object') - this.params.url = this.buildURL(); - }, - stop: function() {}, - pause: function(flag) {}, - mute: function(flag) {}, - // refresh: function() {}, - - setState: function(state, message) { - this.player.setState(state, message); - }, - - setError: function(error) { - Symple.log('symple:player:engine: error', error); - this.setState('error', error); - }, - - onRemoteCandidate: function(candidate) { - Symple.log('symple:player:engine: remote candidates not supported.'); - }, - - updateFPS: function() { - if (typeof this.prevTime == 'undefined') - this.prevTime = new Date().getTime(); - if (this.seq > 0) { - var now = new Date().getTime(); - this.delta = this.prevTime ? now - this.prevTime : 0; - this.fps = (1000.0 / this.delta).toFixed(3); - this.prevTime = now; - } - this.seq++; - }, - - displayFPS: function() { - this.updateFPS(); - this.player.displayStatus(this.delta + " ms (" + this.fps + " fps)"); - }, - - buildURL: function() { - if (!this.params) - throw 'Streaming parameters not set'; - if (!this.params.address) - this.params.address = this.player.options.address; - return Symple.Media.buildURL(this.params); - } -}); diff --git a/src/webrtc/samples/webrtcrecorder/client/assets/symple.player.webrtc.js b/src/webrtc/samples/webrtcrecorder/client/assets/symple.player.webrtc.js deleted file mode 100644 index 189f1fcc8..000000000 --- a/src/webrtc/samples/webrtcrecorder/client/assets/symple.player.webrtc.js +++ /dev/null @@ -1,280 +0,0 @@ -// ----------------------------------------------------------------------------- -// WebRTC Engine -// - -window.RTCPeerConnection = window.mozRTCPeerConnection || window.webkitRTCPeerConnection; -window.RTCSessionDescription = window.mozRTCSessionDescription || window.RTCSessionDescription; -window.RTCIceCandidate = window.mozRTCIceCandidate || window.RTCIceCandidate; -window.URL = window.webkitURL || window.URL; -navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia; - - -Symple.Media.registerEngine({ - id: 'WebRTC', - name: 'WebRTC Player', - formats: 'VP9, VP4, H.264, Opus', - preference: 100, - support: (function() { - return typeof RTCPeerConnection != 'undefined'; - })() -}); - - -Symple.Player.Engine.WebRTC = Symple.Player.Engine.extend({ - init: function(player) { - Symple.log('symple:webrtc: init'); - this._super(player); - - this.rtcConfig = player.options.rtcConfig || { - iceServers: [ - { url: 'stun:stun.l.google.com:19302' } - ] - } - - this.rtcOptions = player.options.rtcOptions || { - optional: [ - { DtlsSrtpKeyAgreement: true } // required for FF <=> Chrome interop - ] - } - - // Specifies that this client will be the ICE initiator, - // and will be sending the initial SDP Offer. - this.initiator = player.options.initiator; - - // The `MediaStreamConstraints` object to pass to `getUserMedia` - this.userMediaConstraints = player.options.userMediaConstraints || { - audio: true, - video: true - } - - // Reference to the active local or remote media stream - this.activeStream = null; - }, - - setup: function() { - Symple.log('symple:webrtc: setup'); - - this._createPeerConnection(); - - if (typeof(this.video) == 'undefined') { - this.video = document.createElement('video'); - this.video.autoplay = true; - this.player.screen.prepend(this.video); - } - }, - - destroy: function() { - Symple.log('symple:webrtc: destroy'); - - this.sendLocalSDP = null; - this.sendLocalCandidate = null; - this.activeStream = null; // TODO: Needs explicit close? - - if (this.video) { - this.video.src = ''; - this.video = null; - // Anything else required for video cleanup? - } - - if (this.pc) { - this.pc.close(); - this.pc = null; - // Anything else required for peer connection cleanup? - } - }, - - play: function(params) { - Symple.log('symple:webrtc: play', params); - - // If there is an active stream then play it now. - if (this.activeStream) { - this.video.src = URL.createObjectURL(this.activeStream); - this.video.play(); - this.setState('playing'); - } - - // Otherwise wait until ICE to complete before setting the 'playing' state. - else { - - // If we are the ICE `initiator` then attempt to open the local video - // device and send the SDP Offer to the peer. - if (this.initiator) { - Symple.log('symple:webrtc: initiating', this.userMediaConstraints); - var self = this; - - // TODO: Support device enumeration. - navigator.getUserMedia(this.userMediaConstraints, - function (localStream) { // success - - // Play the local video stream and create the SDP offer. - self.video.src = URL.createObjectURL(localStream); - self.pc.addStream(localStream); - self.pc.createOffer( - function(desc) { // success - Symple.log('symple:webrtc: offer', desc); - self._onLocalSDP(desc); - }, - function(err) { // error - Symple.log('symple:webrtc: offer failed', err); - }); - - // Store the active local stream - self.activeStream = localStream; - }, - function(err) { // error - self.setError('getUserMedia() failed: ' + err); - }); - } - } - }, - - stop: function() { - // NOTE: Stopping the player does not close the peer connection, - // only `destroy` does that. This enables us to resume playback - // quickly and with minimal delay. - - - if (this.video) { - this.video.src = ''; - // Do not nullify - } - - // Close peer connection - // if (this.pc) { - // this.pc.close(); - // this.pc = null; - // } - - this.setState('stopped'); - }, - - mute: function(flag) { - // Mute unless explicit false given - flag = flag === false ? false : true; - - Symple.log('symple:webrtc: mute', flag); - - if (this.video) - this.video.prop('muted', flag); - }, - - // Called when local SDP is ready to be sent to the peer. - sendLocalSDP: null, // new Function, - - // Called when a local candidate is ready to be sent to the peer. - sendLocalCandidate: null, // new Function, - - // Called when remote SDP is received from the peer. - recvRemoteSDP: function(desc) { - Symple.log('symple:webrtc: recv remote sdp', desc) - if (!desc || !desc.type || !desc.sdp) - throw 'Invalid remote SDP'; - - var self = this; - this.pc.setRemoteDescription(new RTCSessionDescription(desc), - function() { - Symple.log('symple:webrtc: sdp success'); - }, - function(message) { - console.error('symple:webrtc: sdp error', message); - self.setError('Cannot parse remote SDP offer'); - } - ); - - if (desc.type == 'offer') { - self.pc.createAnswer( - function(answer) { // success - self._onLocalSDP(answer); - }, - function() { // error - self.setError('Cannot create local SDP answer'); - }, - null // this.mediaConstraints - ); - } - }, - - // Called when remote candidate is received from the peer. - recvRemoteCandidate: function(candidate) { - Symple.log('symple:webrtc: recv remote candiate', candidate); - if (!this.pc) - throw 'The peer connection is not initialized'; // call recvRemoteSDP first - - this.pc.addIceCandidate(new RTCIceCandidate(candidate)); - }, - - // - // Private methods - // - - // Called when local SDP is ready to be sent to the peer. - _onLocalSDP: function(desc) { - try { - this.pc.setLocalDescription(desc); - this.sendLocalSDP(desc); - } - catch (e) { - Symple.log('symple:webrtc: failed to send local SDP', e); - } - }, - - // Create the RTCPeerConnection object. - _createPeerConnection: function() { - if (this.pc) - throw 'The peer connection is already initialized'; - - Symple.log('symple:webrtc: create peer connnection', this.rtcConfig, this.rtcOptions); - - var self = this; - this.pc = new RTCPeerConnection(this.rtcConfig, this.rtcOptions); - this.pc.onicecandidate = function(event) { - if (event.candidate) { - Symple.log('symple:webrtc: candidate gathered', event.candidate); - self.sendLocalCandidate(event.candidate); - } - else { - Symple.log('symple:webrtc: candidate gathering complete'); - } - }; - this.pc.onaddstream = function(event) { - Symple.log('symple:webrtc: remote stream added', URL.createObjectURL(event.stream)); - - // Set the state to playing once candidates have completed gathering. - // This is the best we can do until ICE onstatechange is implemented. - self.setState('playing'); - - self.video.src = URL.createObjectURL(event.stream); - self.video.play(); - - // Store the active stream - self.activeStream = event.stream; - }; - this.pc.onremovestream = function(event) { - Symple.log('symple:webrtc: remote stream removed', event); - self.video.stop(); - self.video.src = ''; - }; - - // NOTE: The following state events are still very unreliable. - // Hopefully when the spec is complete this will change, but until then - // we need to 'guess' the state. - // this.pc.onconnecting = function(event) { Symple.log('symple:webrtc: onconnecting:', event); }; - // this.pc.onopen = function(event) { Symple.log('symple:webrtc: onopen:', event); }; - // this.pc.onicechange = function(event) { Symple.log('symple:webrtc: onicechange :', event); }; - // this.pc.onstatechange = function(event) { Symple.log('symple:webrtc: onstatechange :', event); }; - } -}); - - -// -// Helpers - -Symple.Media.iceCandidateType = function(candidateSDP) { - if (candidateSDP.indexOf('typ relay') != -1) - return 'turn'; - if (candidateSDP.indexOf('typ srflx') != -1) - return 'stun'; - if (candidateSDP.indexOf('typ host') != -1) - return 'host'; - return 'unknown'; -} diff --git a/src/webrtc/samples/webrtcrecorder/client/index.ejs b/src/webrtc/samples/webrtcrecorder/client/index.ejs deleted file mode 100644 index 846c13cbd..000000000 --- a/src/webrtc/samples/webrtcrecorder/client/index.ejs +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - - Simple WebRTC Native Recording Demo - - - - - - - - - - - - - - - - - -
- - -
-
-
-
-
-
-
-
-
-
-
-
- Logs -
-
-

-            
-
-
-
-
- - diff --git a/src/webrtc/samples/webrtcrecorder/client/package.json b/src/webrtc/samples/webrtcrecorder/client/package.json deleted file mode 100644 index 109351f10..000000000 --- a/src/webrtc/samples/webrtcrecorder/client/package.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "name": "symple-webrtc-native-video-demo", - "title": "Symple WebRTC Native Video Demo", - "version": "0.1.0", - "scripts": { - "start": "node app.js" - }, - "dependencies": { - "symple" : "*", - "symple-client" : "*", - "symple-client-player" : "*", - "express" : "~4.13.3", - "ejs" : "~2.3.4" - } -} diff --git a/src/webrtc/samples/webrtcrecorder/client/symple.json b/src/webrtc/samples/webrtcrecorder/client/symple.json deleted file mode 100644 index 3c25528c1..000000000 --- a/src/webrtc/samples/webrtcrecorder/client/symple.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - /* The ID of the node instance */ - "nodeId" : 1, - - /* The port to listen on */ - "port" : 4500, - - /* Allow anonymous connections */ - "anonymous" : true, - - /* Session ttl in minutes */ - "sessionTtl" : 15/*,*/ - - /* Redis configuration - "redis" : { - "host" : "localhost", - "port" : 6379 - }, */ - - /* SSL configuration - "ssl" : { - "enabled" : false, - "key" : "ssl/symple.key", - "cert" : "ssl/symple.crt" - } */ -} diff --git a/src/webrtc/samples/webrtcrecorder/config.h b/src/webrtc/samples/webrtcrecorder/config.h deleted file mode 100644 index f375dd464..000000000 --- a/src/webrtc/samples/webrtcrecorder/config.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SCY_WebRTC_WebRTCRecorder_Config_H -#define SCY_WebRTC_WebRTCRecorder_Config_H - - -#include "scy/base.h" -#include "scy/av/codec.h" -#include "scy/av/format.h" - - -#define SERVER_HOST "localhost" -#define USE_SSL 0 // 1 -#if USE_SSL -#define SERVER_PORT 443 -#else -#define SERVER_PORT 4500 -#endif - - -#define OUTPUT_FILENAME "webrtcrecorder.mp4" -#define OUTPUT_FORMAT av::Format("MP4", "mp4", \ - av::VideoCodec("H.264", "libx264", 400, 300, 25, 48000, 128000, "yuv420p"), \ - av::AudioCodec("AAC", "libfdk_aac", 2, 44100, 64000, "s16")); - - -#endif diff --git a/src/webrtc/samples/webrtcrecorder/main.cpp b/src/webrtc/samples/webrtcrecorder/main.cpp deleted file mode 100644 index dfd3f9096..000000000 --- a/src/webrtc/samples/webrtcrecorder/main.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// - - -#include "scy/idler.h" -#include "scy/logger.h" -#include "signaler.h" - -#include "webrtc/base/ssladapter.h" -#include "webrtc/base/thread.h" - - -using std::endl; -using namespace scy; - - -// Test this demo with the code in the `client` directory - - -int main(int argc, char** argv) -{ - Logger::instance().add(new ConsoleChannel("debug", Level::Debug)); // LTrace - -#if USE_SSL - net::SSLManager::initNoVerifyClient(); -#endif - - // Setup WebRTC environment - rtc::LogMessage::LogToDebug(rtc::LERROR); - rtc::LogMessage::LogTimestamps(); - rtc::LogMessage::LogThreads(); - - rtc::InitializeSSL(); - - { - smpl::Client::Options options; - options.host = SERVER_HOST; - options.port = SERVER_PORT; - options.name = "Video Recorder"; - options.user = "videorecorder"; - - // NOTE: The server must enable anonymous authentication for this demo. - // options.token = ""; token based authentication - - Signaler app(options); - - // Process WebRTC threads on the main loop. - auto rtcthread = rtc::Thread::Current(); - Idler rtc([=]() { - rtcthread->ProcessMessages(1); - }); - - app.waitForShutdown(); - } - -#if USE_SSL - net::SSLManager::destroy(); -#endif - rtc::CleanupSSL(); - Logger::destroy(); - return 0; -} diff --git a/src/webrtc/samples/webrtcrecorder/signaler.cpp b/src/webrtc/samples/webrtcrecorder/signaler.cpp deleted file mode 100644 index aaf74e589..000000000 --- a/src/webrtc/samples/webrtcrecorder/signaler.cpp +++ /dev/null @@ -1,193 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// - - -#include "signaler.h" - -#include "scy/util.h" - -#include -#include - - -using std::endl; - - -namespace scy { - - -Signaler::Signaler(const smpl::Client::Options& options) - : _client(options) -{ - _client.StateChange += slot(this, &Signaler::onClientStateChange); - _client.roster().ItemAdded += slot(this, &Signaler::onPeerConnected); - _client.roster().ItemRemoved += slot(this, &Signaler::onPeerDiconnected); - _client += packetSlot(this, &Signaler::onPeerMessage); - _client.connect(); -} - - -Signaler::~Signaler() -{ -} - - -void Signaler::sendSDP(wrtc::Peer* conn, const std::string& type, const std::string& sdp) -{ - assert(type == "offer" || type == "answer"); - smpl::Message m; - json::value desc; - desc[wrtc::kSessionDescriptionTypeName] = type; - desc[wrtc::kSessionDescriptionSdpName] = sdp; - m[type] = desc; - - postMessage(m); -} - - -void Signaler::sendCandidate(wrtc::Peer* conn, const std::string& mid, int mlineindex, const std::string& sdp) -{ - smpl::Message m; - json::value desc; - desc[wrtc::kCandidateSdpMidName] = mid; - desc[wrtc::kCandidateSdpMlineIndexName] = mlineindex; - desc[wrtc::kCandidateSdpName] = sdp; - m["candidate"] = desc; - - postMessage(m); -} - - -void Signaler::onPeerConnected(smpl::Peer& peer) -{ - if (peer.id() == _client.ourID()) - return; - LDebug("Peer connected: ", peer.id()) - - if (wrtc::PeerManager::exists(peer.id())) { - LDebug("Peer already has session: ", peer.id()) - return; - } - - auto conn = new wrtc::Peer(this, &_context, peer.id(), "", wrtc::Peer::Answer); - conn->constraints().SetMandatoryReceiveVideo(true); - conn->constraints().SetMandatoryReceiveAudio(true); - conn->createConnection(); - - wrtc::PeerManager::add(peer.id(), conn); -} - - -void Signaler::onPeerMessage(smpl::Message& m) -{ - LDebug("Peer message: ", m.from().toString()) - - if (m.find("offer") != m.end()) { - recvSDP(m.from().id, m["offer"]); - } else if (m.find("answer") != m.end()) { - assert(0 && "answer not supported"); - } else if (m.find("candidate") != m.end()) { - recvCandidate(m.from().id, m["candidate"]); - } - // else assert(0 && "unknown event"); -} - - -void Signaler::onPeerDiconnected(const smpl::Peer& peer) -{ - LDebug("Peer disconnected") - - auto conn = get(peer.id()); - if (conn) { - LDebug("Closing peer connection: ", peer.id()) - conn->closeConnection(); // will be deleted via callback - } -} - - -void Signaler::onClientStateChange(void* sender, sockio::ClientState& state, const sockio::ClientState& oldState) -{ - SDebug << "Client state changed from " << oldState << " to " << state - << endl; - - switch (state.id()) { - case sockio::ClientState::Connecting: - break; - case sockio::ClientState::Connected: - break; - case sockio::ClientState::Online: - break; - case sockio::ClientState::Error: - throw std::runtime_error("Cannot connect to Symple server. " - "Did you start the demo app and the " - "Symple server is running on port 4500?"); - } -} - - -void Signaler::onAddRemoteStream(wrtc::Peer* conn, webrtc::MediaStreamInterface* stream) -{ - av::EncoderOptions options; - options.ofile = OUTPUT_FILENAME; - options.oformat = OUTPUT_FORMAT; - - _recorder.reset(new wrtc::StreamRecorder(options)); - - auto videoTracks = stream->GetVideoTracks(); - if (!videoTracks.empty()) - _recorder->setVideoTrack(videoTracks[0]); - - auto audioTracks = stream->GetAudioTracks(); - if (!audioTracks.empty()) - _recorder->setAudioTrack(audioTracks[0]); -} - - -void Signaler::onRemoveRemoteStream(wrtc::Peer* conn, webrtc::MediaStreamInterface* stream) -{ - assert(0 && "free streams"); -} - - -void Signaler::onStable(wrtc::Peer* conn) -{ -} - - -void Signaler::onClosed(wrtc::Peer* conn) -{ - _recorder.reset(); // shutdown the recorder - wrtc::PeerManager::onClosed(conn); -} - - -void Signaler::onFailure(wrtc::Peer* conn, const std::string& error) -{ - _recorder.reset(); // shutdown the recorder - wrtc::PeerManager::onFailure(conn, error); -} - - -void Signaler::postMessage(const smpl::Message& m) -{ - _ipc.push(new ipc::Action( - std::bind(&Signaler::syncMessage, this, std::placeholders::_1), - m.clone())); -} - - -void Signaler::syncMessage(const ipc::Action& action) -{ - auto m = reinterpret_cast(action.arg); - _client.send(*m); - delete m; -} - - -} // namespace scy diff --git a/src/webrtc/samples/webrtcrecorder/signaler.h b/src/webrtc/samples/webrtcrecorder/signaler.h deleted file mode 100644 index 8f7d37597..000000000 --- a/src/webrtc/samples/webrtcrecorder/signaler.h +++ /dev/null @@ -1,73 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// - - -#ifndef SCY_WebRTC_Signaler_H -#define SCY_WebRTC_Signaler_H - - -#include "config.h" -#include "scy/application.h" -#include "scy/ipc.h" -#include "scy/net/sslmanager.h" -#include "scy/net/sslsocket.h" -#include "scy/symple/client.h" -#include "scy/webrtc/peermanager.h" -#include "scy/webrtc/streamrecorder.h" - -#include -#include - - -namespace scy { - - -class Signaler : public wrtc::PeerManager, public Application -{ -public: - Signaler(const smpl::Client::Options& options); - ~Signaler(); - -protected: - - /// PeerManager interface - void sendSDP(wrtc::Peer* conn, const std::string& type, const std::string& sdp) override; - void sendCandidate(wrtc::Peer* conn, const std::string& mid, int mlineindex, const std::string& sdp) override; - void onAddRemoteStream(wrtc::Peer* conn, webrtc::MediaStreamInterface* stream) override; - void onRemoveRemoteStream(wrtc::Peer* conn, webrtc::MediaStreamInterface* stream) override; - void onStable(wrtc::Peer* conn) override; - void onClosed(wrtc::Peer* conn) override; - void onFailure(wrtc::Peer* conn, const std::string& error) override; - - void postMessage(const smpl::Message& m); - void syncMessage(const ipc::Action& action); - - void onPeerConnected(smpl::Peer& peer); - void onPeerMessage(smpl::Message& m); - void onPeerCommand(smpl::Command& c); - void onPeerDiconnected(const smpl::Peer& peer); - - void onClientStateChange(void* sender, sockio::ClientState& state, const sockio::ClientState& oldState); - -protected: - ipc::SyncQueue<> _ipc; -#if USE_SSL - smpl::SSLClient _client; -#else - smpl::TCPClient _client; -#endif - std::unique_ptr _recorder; - wrtc::PeerFactoryContext _context; -}; - - -} // namespace scy - - -#endif diff --git a/src/webrtc/samples/webrtcstreamer/CMakeLists.txt b/src/webrtc/samples/webrtcstreamer/CMakeLists.txt deleted file mode 100644 index 5c125c385..000000000 --- a/src/webrtc/samples/webrtcstreamer/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -include_dependency(WebRTC REQUIRED) -include_dependency(FFmpeg REQUIRED) - -define_sourcey_module_sample(webrtcstreamer base crypto av net http util json socketio symple webrtc) diff --git a/src/webrtc/samples/webrtcstreamer/README.md b/src/webrtc/samples/webrtcstreamer/README.md deleted file mode 100644 index fdd326de1..000000000 --- a/src/webrtc/samples/webrtcstreamer/README.md +++ /dev/null @@ -1,22 +0,0 @@ -# WebRTC Native Video Streamer - -This sample app showcases how to stream realtime video to the the browser using LibSourcey and WebRTC. Audio and video streams can be from realtime device captures or movie files encoded in any format that's supported by LibSourcey/FFmpeg. - -## Installation - -1. Compile LibSourcey with WebRTC support (`WITH_WEBRTC=ON`) and samples (`BUILD_SAMPLES_webrtc=ON`) enabled. See the main README for help: https://github.com/sourcey/libsourcey#installing-on-linux -2. Run the `webrtcstreamer` sample application from the `build` directory. -2. Install and run the Node.js client application: - -~~~ bash -cd /src/webrtc/samples/webrtcstreamer/client -npm install -node app -~~~ - -3. Finally, point your browser to: `http://localhost:4499` -4. Your should see your video and audio stream playing in the browser. - -## Hacking - -The source code is clear and concise, let it be your guide :) diff --git a/src/webrtc/samples/webrtcstreamer/client/README.md b/src/webrtc/samples/webrtcstreamer/client/README.md deleted file mode 100644 index ac7df1d1e..000000000 --- a/src/webrtc/samples/webrtcstreamer/client/README.md +++ /dev/null @@ -1,42 +0,0 @@ -# Symple WebRTC Video Chat Demo - -The Symple video chat demo is an example of how to use the Symple for instant messaging and WebRTC signaling in about 100 lines of JavaScript. External projects used are AngularJS, Bootstrap, Node.js and Express. - -See this blog post for more information about the demo: https://sourcey.com/symple-webrtc-video-chat-demo - -## What is Symple? - -Symple is a unrestrictive real-time messaging and presence protocol. - -The protocol itself is semantically similar to XMPP, except that it is much more flexible and economical due to the use of JSON instead of XML for encoding messages. - -Symple currently has client implementations in [JavaScript](https://github.com/sourcey/symple-client), [Ruby](https://github.com/sourcey/symple-client-ruby) and [C++](https://github.com/sourcey/libsourcey/tree/master/src/symple), which make it ideal for a wide range of messaging requirements, such as building real-time games and applications which run in the web browser, desktop, and mobile phone. - -## Usage - -1. Install dependencies: `npm install` -2. Fire up the server: `node app` -3. And point your browser to: `http://localhost:4500` - -## Hacking - -Some key options are specified in the main HTML file located at `index.ejs` - -**CLIENT_OPTIONS** This is the options hash for the Symple client. This is where you specify the server URL and Peer object. Note that we have disabled 'websocket' transport by default, but you will probably want to re-enable it in production. - -**WEBRTC_CONFIG** This is the PeerConnection options hash. In production you will want to specify some TURN servers so as to ensure the p2p connection succeeds in all network topologies. - -Other than that all relevant JavaScript is located in `public/js/app.js` and `public/js/helpers.js`. Enjoy! - -## Contributing - -1. Fork it -2. Create your feature branch (`git checkout -b my-new-feature`) -3. Commit your changes (`git commit -am 'Add some feature'`) -4. Push to the branch (`git push origin my-new-feature`) -5. Create new Pull Request - -## Contact - -For more information please check out the Symple homepage: https://sourcey.com/symple/ -If you have a bug or an issue then please use the Github issue tracker: https://github.com/sourcey/symple-client/issues diff --git a/src/webrtc/samples/webrtcstreamer/client/app.js b/src/webrtc/samples/webrtcstreamer/client/app.js deleted file mode 100644 index bc7f62cce..000000000 --- a/src/webrtc/samples/webrtcstreamer/client/app.js +++ /dev/null @@ -1,38 +0,0 @@ -// -/// Setup the Symple server - -var Symple = require('symple'); -var sy = new Symple(); -sy.loadConfig(__dirname + '/symple.json'); // see config.json for options -sy.init(); -console.log('Symple server listening on port ' + sy.config.port); - - -// -/// Setup the demo client web server - -var express = require('express'), - path = require('path'), - app = express(), - serverPort = parseInt(sy.config.port) - clientPort = serverPort - 1; - -app.set('port', clientPort); -app.set('view engine', 'ejs'); -app.set('views', __dirname + '/'); -app.use(express.static(__dirname + '/assets')); - -app.get('/', function (req, res) { - res.render('index', { - port: serverPort, - peer: { - user: 'demo', - name: 'Demo User', - group: 'public' - } - }); -}); - -app.listen(app.get('port'), function () { - console.log('Web server listening on port ' + app.get('port')); -}); diff --git a/src/webrtc/samples/webrtcstreamer/client/assets/main.css b/src/webrtc/samples/webrtcstreamer/client/assets/main.css deleted file mode 100644 index 3d741c645..000000000 --- a/src/webrtc/samples/webrtcstreamer/client/assets/main.css +++ /dev/null @@ -1,11 +0,0 @@ -body > .container { - padding-top: 30px; -} - -#webrtc-video .video-player { - margin-bottom: 1rem; -} - -#webrtc-video .symple-player { - min-height: 480px; -} diff --git a/src/webrtc/samples/webrtcstreamer/client/assets/main.js b/src/webrtc/samples/webrtcstreamer/client/assets/main.js deleted file mode 100644 index 8f98aa649..000000000 --- a/src/webrtc/samples/webrtcstreamer/client/assets/main.js +++ /dev/null @@ -1,116 +0,0 @@ -$(document).ready(function() { - var client, player, remotePeer; - - // - // Initialize the Symple WebRTC player - - player = new Symple.Player({ - element: '#webrtc-video .video-player', - engine: 'WebRTC', - rtcConfig: WEBRTC_CONFIG, - iceMediaConstraints: { - 'mandatory': { - 'OfferToReceiveAudio': true, - 'OfferToReceiveVideo': true - } - }, - onStateChange: function(player, state) { - player.displayStatus(state); - } - }); - - // - // Initialize the Symple client - - client = new Symple.Client(CLIENT_OPTIONS); - - client.on('announce', function(peer) { - console.log('Authentication success:', peer); - }); - - client.on('presence', function(p) { - console.log('Recv presence:', p) - }); - - client.on('message', function(m) { - // console.log('Recv message:', m) - if (remotePeer && remotePeer.id != m.from.id) { - console.log('Dropping message from unknown peer', m); - return; - } - - if (m.offer) { - try { - console.log('Reieve offer:', JSON.stringify(m.offer)) - - remotePeer = m.from; - // player.setup(); - player.play(); - player.engine.recvRemoteSDP(m.offer); - player.engine.sendLocalSDP = function(desc) { - console.log('Send answer:', JSON.stringify(desc)) - client.send({ - to: remotePeer, - type: 'message', - answer: desc - }); - } - - player.engine.sendLocalCandidate = function(cand) { - client.send({ - to: remotePeer, - type: 'message', - candidate: cand - }); - } - } - catch (e) { - console.log("Failed to create PeerConnection:", e); - } - } - - else if (m.answer) { - alert('Unexpected answer for one-way streaming'); - } - - else if (m.candidate) { - // Filter non relay candidates for testing TURN - // if (m.candidate.candidate.indexOf('typ relay') == -1) { //typ host - // console.log("Dropping Candidate:", m.candidate); - // return; - // } - - // console.log("Using Candidate:", m.candidate); - player.engine.recvRemoteCandidate(m.candidate); - } - }); - - // client.on('command', function(c) { - // console.log('Recv command:', c) - // }); - - // client.on('event', function(e) { - // console.log('Recv event:', e) - // }); - - client.on('disconnect', function() { - console.log('Disconnected from server') - }); - - client.on('error', function(error, message) { - console.log('Peer error:', error, message) - }); - - client.on('addPeer', function(peer) { - // console.log('Adding peer:', peer) - }); - - client.on('removePeer', function(peer) { - console.log('Removing peer:', peer) - if (remotePeer && remotePeer.id == peer.id) { - remotePeer = null; - } - }); - - client.connect(); -}); diff --git a/src/webrtc/samples/webrtcstreamer/client/assets/symple.client.js b/src/webrtc/samples/webrtcstreamer/client/assets/symple.client.js deleted file mode 100644 index 4cb41d078..000000000 --- a/src/webrtc/samples/webrtcstreamer/client/assets/symple.client.js +++ /dev/null @@ -1,542 +0,0 @@ -// ----------------------------------------------------------------------------- -// Symple Client -// -Symple.Client = Symple.Dispatcher.extend({ - init: function(options) { - this.options = Symple.extend({ //$.extend - url: options.url ? options.url : 'http://localhost:4000', - secure: options.url && ( - options.url.indexOf('https') == 0 || - options.url.indexOf('wss') == 0) ? true : false, - token: undefined // pre-arranged server session token - //timeout: 0 // set for connection timeout - }, options); - this._super(); - this.peer = options.peer || {}; - this.peer.rooms = options.peer.rooms || []; - this.roster = new Symple.Roster(this); - this.socket = null; - }, - - // Connects and authenticates on the server. - // If the server is down the 'error' event will fire. - connect: function() { - Symple.log('symple:client: connecting', this.options); - self = this; - if (this.socket) - throw 'The client socket is not null' - this.socket = io.connect(this.options.url, this.options); - this.socket.on('connect', function() { - Symple.log('symple:client: connected'); - self.socket.emit('announce', { - token: self.options.token || '', - user: self.peer.user || '', - name: self.peer.name || '', - type: self.peer.type || '' - }, function(res) { - Symple.log('symple:client: announced', res); - if (res.status != 200) { - self.setError('auth', res); - return; - } - self.peer = Symple.extend(self.peer, res.data); // $.extend - self.roster.add(res.data); - self.sendPresence({ probe: true }); - self.dispatch('announce', res); - self.socket.on('message', function(m) { - // Symple.log('symple:client: receive', m); - if (typeof(m) == 'object') { - switch(m.type) { - case 'message': - m = new Symple.Message(m); - break; - case 'command': - m = new Symple.Command(m); - break; - case 'event': - m = new Symple.Event(m); - break; - case 'presence': - m = new Symple.Presence(m); - if (m.data.online) - self.roster.update(m.data); - else - self.roster.remove(m.data.id); - if (m.probe) - self.sendPresence(new Symple.Presence({ - to: Symple.parseAddress(m.from).id - })); - break; - default: - o = m; - o.type = o.type || 'message'; - break; - } - - if (typeof(m.from) != 'string') { - Symple.log('symple:client: invalid sender address', m); - return; - } - - // Replace the from attribute with the full peer object. - // This will only work for peer messages, not server messages. - var rpeer = self.roster.get(m.from); - if (rpeer) - m.from = rpeer; - else - Symple.log('symple:client: got message from unknown peer', m); - - // Dispatch to the application - self.dispatch(m.type, m); - } - }); - }); - }); - this.socket.on('error', function() { - // This is triggered when any transport fails, - // so not necessarily fatal. - self.dispatch('connect'); - }); - this.socket.on('connecting', function() { - Symple.log('symple:client: connecting'); - self.dispatch('connecting'); - }); - this.socket.on('reconnecting', function() { - Symple.log('symple:client: reconnecting'); - self.dispatch('reconnecting'); - }); - this.socket.on('connect_failed', function() { - // Called when all transports fail - Symple.log('symple:client: connect failed'); - self.dispatch('connect_failed'); - self.setError('connect'); - }); - this.socket.on('disconnect', function() { - Symple.log('symple:client: disconnect'); - self.peer.online = false; - self.dispatch('disconnect'); - }); - }, - - // Disconnect from the server - disconnect: function() { - if (this.socket) - this.socket.disconnect(); - }, - - // Return the online status - online: function() { - return this.peer.online; - }, - - // Join a room - join: function(room) { - this.socket.emit('join', room); - }, - - // Leave a room - leave: function(room) { - this.socket.emit('leave', room); - }, - - // Send a message to the given peer - send: function(m, to) { - // Symple.log('symple:client: before send', m, to); - if (!this.online()) - throw 'Cannot send messages while offline'; // add to pending queue? - if (typeof(m) != 'object') - throw 'Message must be an object'; - if (typeof(m.type) != 'string') - m.type = 'message'; - if (!m.id) - m.id = Symple.randomString(8); - if (to) - m.to = to; - if (m.to && typeof(m.to) == 'object') - m.to = Symple.buildAddress(m.to); - if (m.to && typeof(m.to) != 'string') - throw 'Message `to` attribute must be an address string'; - m.from = Symple.buildAddress(this.peer); - if (m.from == m.to) - throw 'Message sender cannot match the recipient'; - - Symple.log('symple:client: sending', m); - this.socket.json.send(m); - }, - - respond: function(m) { - this.send(m, m.from); - }, - - sendMessage: function(m, to) { - this.send(m, to); - }, - - sendPresence: function(p) { - p = p || {}; - if (p.data) - p.data = Symple.merge(this.peer, p.data); - else - p.data = this.peer; - this.send(new Symple.Presence(p)); - }, - - sendCommand: function(c, to, fn, once) { - var self = this; - c = new Symple.Command(c, to); - this.send(c); - if (fn) { - this.onResponse('command', { - id: c.id - }, fn, function(res) { - if (once || ( - // 202 (Accepted) and 406 (Not acceptable) response codes - // signal that the command has not yet completed. - res.status != 202 && - res.status != 406)) { - self.clear('command', fn); - } - }); - } - }, - - // Adds a capability for our current peer - addCapability: function(name, value) { - var peer = this.peer; - if (peer) { - if (typeof value == 'undefined') - value = true - if (typeof peer.capabilities == 'undefined') - peer.capabilities = {} - peer.capabilities[name] = value; - // var idx = peer.capabilities.indexOf(name); - // if (idx == -1) { - // peer.capabilities.push(name); - // this.sendPresence(); - // } - } - }, - - // Removes a capability from our current peer - removeCapability: function(name) { - var peer = this.peer; - if (peer && typeof peer.capabilities != 'undefined' && - typeof peer.capabilities[name] != 'undefined') { - delete peer.capabilities[key]; - this.sendPresence(); - // var idx = peer.capabilities.indexOf(name) - // if (idx != -1) { - // peer.capabilities.pop(name); - // this.sendPresence(); - // } - } - }, - - // Checks if a peer has a specific capbility and returns a boolean - hasCapability: function(id, name) { - var peer = this.roster.get(id) - if (peer) { - if (typeof peer.capabilities != 'undefined' && - typeof peer.capabilities[name] != 'undefined') - return peer.capabilities[name] !== false; - if (typeof peer.data != 'undefined' && - typeof peer.data.capabilities != 'undefined' && - typeof peer.data.capabilities[name] != 'undefined') - return peer.data.capabilities[name] !== false; - } - return false; - }, - - // Checks if a peer has a specific capbility and returns the value - getCapability: function(id, name) { - var peer = this.roster.get(id) - if (peer) { - if (typeof peer.capabilities != 'undefined' && - typeof peer.capabilities[name] != 'undefined') - return peer.capabilities[name]; - if (typeof peer.data != 'undefined' && - typeof peer.data.capabilities != 'undefined' && - typeof peer.data.capabilities[name] != 'undefined') - return peer.data.capabilities[name]; - } - return undefined; - }, - - // Sets the client to an error state and disconnect - setError: function(error, message) { - Symple.log('symple:client: fatal error', error, message); - // if (this.error == error) - // return; - // this.error = error; - this.dispatch('error', error, message); - if (this.socket) - this.socket.disconnect(); - }, - - onResponse: function(event, filters, fn, after) { - if (typeof this.listeners[event] == 'undefined') - this.listeners[event] = []; - if (typeof fn != 'undefined' && fn.constructor == Function) - this.listeners[event].push({ - fn: fn, // data callback function - after: after, // after data callback function - filters: filters // event filter object for matching response - }); - }, - - clear: function(event, fn) { - Symple.log('symple:client: clearing callback', event); - if (typeof this.listeners[event] != 'undefined') { - for (var i = 0; i < this.listeners[event].length; i++) { - if (this.listeners[event][i].fn === fn && - String(this.listeners[event][i].fn) == String(fn)) { - this.listeners[event].splice(i, 1); - Symple.log('symple:client: cleared callback', event); - } - } - } - }, - - // Extended dispatch function to handle filtered message response - // callbacks first, and then standard events. - dispatch: function() { - if (!this.dispatchResponse.apply(this, arguments)) { - this._super.apply(this, arguments); - } - }, - - // Dispatch function for handling filtered message response callbacks. - dispatchResponse: function() { - var event = arguments[0]; - var data = Array.prototype.slice.call(arguments, 1); - if (typeof this.listeners[event] != 'undefined') { - for (var i = 0; i < this.listeners[event].length; i++) { - if (typeof this.listeners[event][i] == 'object' && - this.listeners[event][i].filters != 'undefined' && - Symple.match(this.listeners[event][i].filters, data[0])) { - this.listeners[event][i].fn.apply(this, data); - if (this.listeners[event][i].after != 'undefined') { - this.listeners[event][i].after.apply(this, data); - } - return true; - } - } - } - return false; - } - - // getPeers: function(fn) { - // self = this; - // this.socket.emit('peers', function(res) { - // Symple.log('Peers: ', res); - // if (typeof(res) != 'object') - // for (var peer in res) - // self.roster.update(peer); - // if (fn) - // fn(res); - // }); - // } -}); - - -// ----------------------------------------------------------------------------- -// Symple Roster -// -Symple.Roster = Symple.Manager.extend({ - init: function(client) { - this._super(); - this.client = client; - }, - - // Add a peer object to the roster - add: function(peer) { - Symple.log('symple:roster: adding', peer); - if (!peer || !peer.id || !peer.user) // || !peer.group - throw 'Cannot add invalid peer' - this._super(peer); - this.client.dispatch('addPeer', peer); - }, - - // Remove the peer matching an ID or address string: user|id - remove: function(id) { - id = Symple.parseAddress(id).id || id; - var peer = this._super(id); - Symple.log('symple:roster: removing', id, peer); - if (peer) - this.client.dispatch('removePeer', peer); - return peer; - }, - - // Get the peer matching an ID or address string: user|id - get: function(id) { - - // Handle IDs - peer = this._super(id); // id = Symple.parseIDFromAddress(id) || id; - if (peer) - return peer; - - // Handle address strings - return this.findOne(Symple.parseAddress(id)); - }, - - update: function(data) { - if (!data || !data.id) - return; - var peer = this.get(data.id); - if (peer) - for (var key in data) - peer[key] = data[key]; - else - this.add(data); - } - - // Get the peer matching an address string: user|id - // getForAddr: function(addr) { - // var o = Symple.parseAddress(addr); - // if (o && o.id) - // return this.get(o.id); - // return null; - // } -}); - - -// ----------------------------------------------------------------------------- -// Helpers -// -Symple.parseAddress = function(str) { - var addr = {}, - arr = str.split("|") - - if (arr.length > 0) // no id - addr.user = arr[0]; - if (arr.length > 1) // has id - addr.id = arr[1]; - - return addr; -} - -Symple.buildAddress = function(peer) { - return (peer.user ? (peer.user + '|') : '') + - (peer.id ? peer.id : ''); -} - - -// ----------------------------------------------------------------------------- -// Message -// -Symple.Message = function(json) { - if (typeof(json) == 'object') - this.fromJSON(json); - this.type = "message"; -} - -Symple.Message.prototype = { - fromJSON: function(json) { - for (var key in json) - this[key] = json[key]; - }, - - valid: function() { - return this['id'] - && this['from']; - } -}; - - -// ----------------------------------------------------------------------------- -// Command -// -Symple.Command = function(json) { - if (typeof(json) == 'object') - this.fromJSON(json); - this.type = "command"; -} - -Symple.Command.prototype = { - getData: function(name) { - return this['data'] ? this['data'][name] : null; - }, - - params: function() { - return this['node'].split(':'); - }, - - param: function(n) { - return this.params()[n-1]; - }, - - matches: function(xuser) { - xparams = xuser.split(':'); - - // No match if x params are greater than ours. - if (xparams.length > this.params().length) - return false; - - for (var i = 0; i < xparams.length; i++) { - - // Wildcard * matches everything until next parameter. - if (xparams[i] == "*") - continue; - if (xparams[i] != this.params()[i]) - return false; - } - - return true; - }, - - fromJSON: function(json) { - for (var key in json) - this[key] = json[key]; - }, - - valid: function() { - return this['id'] - && this['from'] - && this['node']; - } -}; - - -// ----------------------------------------------------------------------------- -// Presence -// -Symple.Presence = function(json) { - if (typeof(json) == 'object') - this.fromJSON(json); - this.type = "presence"; -} - -Symple.Presence.prototype = { - fromJSON: function(json) { - for (var key in json) - this[key] = json[key]; - }, - - valid: function() { - return this['id'] - && this['from']; - } -}; - - -// ----------------------------------------------------------------------------- -// Event -// -Symple.Event = function(json) { - if (typeof(json) == 'object') - this.fromJSON(json); - this.type = "event"; -} - -Symple.Event.prototype = { - fromJSON: function(json) { - for (var key in json) - this[key] = json[key]; - }, - - valid: function() { - return this['id'] - && this['from'] - && this.name; - } -}; diff --git a/src/webrtc/samples/webrtcstreamer/client/assets/symple.js b/src/webrtc/samples/webrtcstreamer/client/assets/symple.js deleted file mode 100644 index 26bc604c8..000000000 --- a/src/webrtc/samples/webrtcstreamer/client/assets/symple.js +++ /dev/null @@ -1,385 +0,0 @@ -// ----------------------------------------------------------------------------- -// Symple JavaScript Client -// -var Symple = { - // Version - VERSION: "0.9.0", - - // Return an array of nested objects matching - // the given key/value strings. - filterObject: function(obj, key, value) { // (Object[, String, String]) - var r = [] - for (var k in obj) { - if (obj.hasOwnProperty(k)) { - var v = obj[k]; - if ((!key || k == key) && - (!value || v == value)) { - r.push(obj) - } - else if (typeof v === 'object') { - var a = Symple.filterObject(v, key, value); - if (a) r = r.concat(a); - } - } - } - return r; - }, - - // Delete nested objects with properties - // that match the given key/value strings. - deleteNested: function(obj, key, value) { // (Object[, String, String]) - for (var k in obj) { - var v = obj[k]; - if ((!key || k == key) && - (!value || v == value)) { - delete obj[k]; - } - else if (typeof v === 'object') - Symple.deleteNested(v, key); - } - }, - - // Count nested object properties which - // match the given key/value strings. - countNested: function(obj, key, value, count) { - if (count === undefined) count = 0; - for (var k in obj) { - if (obj.hasOwnProperty(k)) { - var v = obj[k]; - if ((!key || k == key) && - (!value || v == value)) { - count++; - } - else if (typeof(v) === 'object') { - //else if (v instanceof Object) { - count = Symple.countNested(v, key, value, count); - } - } - } - return count; - }, - - // Traverse an objects nested properties - traverse: function(obj, fn) { // (Object, Function) - for (var k in obj) { - if (obj.hasOwnProperty(k)) { - var v = obj[k]; - fn(k, v); - if (typeof v === 'object') - Symple.traverse(v, fn); - } - } - }, - - // Generate a random string - randomString: function(n) { - return Math.random().toString(36).slice(2) //Math.random().toString(36).substring(n || 7); - }, - - // Recursively merge object properties of r into l - merge: function(l, r) { // (Object, Object) - for (var p in r) { - try { - // Property in destination object set; update its value. - //if (typeof r[p] == "object") { - if (r[p].constructor == Object) { - l[p] = merge(l[p], r[p]); - } else { - l[p] = r[p]; - } - } catch(e) { - // Property in destination object not set; - // create it and set its value. - l[p] = r[p]; - } - } - return l; - }, - - // Object extend functionality - extend: function() { - var process = function(destination, source) { - for (var key in source) { - if (hasOwnProperty.call(source, key)) { - destination[key] = source[key]; - } - } - return destination; - }; - var result = arguments[0]; - for(var i=1; i b.preference) return -1; - }); - return arr - }, - - // Returns the highest preference compatible engine - // The optional format argument further filters by engines - // which don't support the given media format. - preferredCompatibleEngine: function(format) { - var arr = this.compatibleEngines(format), engine; - engine = arr.length ? arr[0] : null; - Symple.log('symple:media: preferred engine', engine); - return engine; - }, - - // Returns the optimal video resolution for the current device - // TODO: Different aspect ratios - getOptimalVideoResolution: function() { - var w = $(window).width(); - var width = w > 800 ? - 800 : w > 640 ? - 640 : w > 480 ? - 400 : w > 320 ? - 320 : w > 240 ? - 240 : w > 160 ? - 160 : w > 128 ? - 128 : 96; - var height = width * 0.75; - return [width, height]; - }, - - buildURL: function(params) { - var query = [], url, addr = params.address; - url = addr.scheme + '://' + addr.host + ':' + addr.port + (addr.uri ? addr.uri : '/'); - for (var p in params) { - if (p == 'address') - continue; - query.push(encodeURIComponent(p) + "=" + encodeURIComponent(params[p])); - } - query.push('rand=' + Math.random()); - url += '?'; - url += query.join("&"); - return url; - - }, - - // Rescales video dimensions maintaining perspective - // TODO: Different aspect ratios - rescaleVideo: function(srcW, srcH, maxW, maxH) { - //Symple.log('Symple Player: Rescale Video: ', srcW, srcH, maxW, maxH); - var maxRatio = maxW / maxH; - var srcRatio = 1.33; //srcW / srcH; - if (srcRatio < maxRatio) { - srcH = maxH; - srcW = srcH * srcRatio; - } else { - srcW = maxW; - srcH = srcW / srcRatio; - } - return [srcW, srcH]; - }, - - // Basic checking for remote ICE style streaming candidates - // TODO: Latency checks and best candidate switching - checkCandidate: function(url, fn) { - Symple.log('symple:media: checking candidate: ', url); - - var xhr; - if (window.XMLHttpRequest) { - xhr = new XMLHttpRequest(); - } else if (window.ActiveXObject) { - xhr = new ActiveXObject("Microsoft.XMLHTTP"); - } else { - fn(url, false); - return; - } - - xhr.onreadystatechange = function() { - if (xhr.readyState == 2) { - if (fn) { - Symple.log('symple:media: candidate result: ', xhr.readyState, xhr.status); - fn(url, xhr.status == 200); - fn = null; - - // Safari on windows crashes when abort is called from inside - // the onreadystatechange callback. - setTimeout(function() { - xhr.abort(); - }, 0); - } - } - else if (xhr.readyState == 4/* && xhr.status != 0*/) { - if (fn) { - Symple.log('symple:media: candidate result: ', xhr.readyState, xhr.status); - fn(url, /*xhr.status == 200*/true); - fn = null; - } - } - }; - xhr.open('GET', url, true); - xhr.send(null); - }, -}; - -// ---------------------------------------------------------------------------- -// Symple Player -// -// Online video streaming for everyone -// Requires jQuery -// -Symple.Player = Symple.Class.extend({ - init: function(options) { - this.options = Symple.extend({ // $.extend - format: 'MJPEG', // The media format to use (MJPEG, FLV, Speex, ...) - engine: undefined, // Engine class name, can be specified or auto detected - - htmlRoot: '/javascripts/symple', - element: '.symple-player:first', - fullscreenElement: undefined, - - // Callbacks - onCommand: function(player, cmd) { }, - onStateChange: function(player, state) { }, - - // Markup - template: '\ -
\ -
\ -
\ -
\ -
\ -
\ - Play\ - Stop\ - Fullscreen\ -
\ -
' - - }, options); - - this.element = $(this.options.element); - if (!this.element.hasClass('symple-player')) { - this.element.html(this.options.template); - this.element = this.element.children('.symple-player:first'); - } - if (!this.element.length) - throw 'Player element not found'; - - this.screen = this.element.find('.symple-player-screen'); - if (!this.screen.length) - throw 'Player screen element not found'; - - // Depreciated: Screen is always 100% unless speified otherwise via CSS - // if (this.options.screenWidth) - // this.screen.width(this.options.screenWidth); - // if (this.options.screenHeight) - // this.screen.height(this.options.screenHeight); - - this.message = this.element.find('.symple-player-message') - if (!this.message.length) - throw 'Player message element not found'; - - // Try to choose the best engine if none was given - if (typeof this.options.engine == 'undefined') { - var engine = Symple.Media.preferredCompatibleEngine(this.options.format); - if (engine) - this.options.engine = engine.id; - } - - this.bindEvents(); - this.playing = false; - - // this.setState('stopped'); - // var self = this; - // $(window).resize(function() { - // self.refresh(); - // }); - }, - - setup: function() { - var id = this.options.engine; - - // Ensure the engine is configured - if (!id) - throw "Streaming engine not configured. Please set 'options.engine'"; - - // Ensure the engine exists - if (!Symple.Media.hasEngine(id)) - throw "Streaming engine not available: " + id; - if (typeof Symple.Player.Engine[id] == 'undefined') - throw "Streaming engine not found: " + id; - - // Ensure the engine is supported - if (!Symple.Media.supportsEngine(id)) - throw "Streaming engine not supported: " + id; - - // Instantiate the engine - this.engine = new Symple.Player.Engine[id](this); - this.engine.setup(); - - this.element.addClass('engine-' + id.toLowerCase()) - }, - - // - // Player Controls - // - play: function(params) { - Symple.log('symple:player: play', params) - try { - if (!this.engine) - this.setup(); - - if (this.state != 'playing' //&& - // The player may be set to loading state by the - // outside application before play is called. - //this.state != 'loading' - ) { - this.setState('loading'); - this.engine.play(params); // engine updates state to playing - } - } catch (e) { - this.setState('error'); - this.displayMessage('error', e) - throw e; - } - }, - - stop: function() { - Symple.log('symple:player: stop') - if (this.state != 'stopped') { - if (this.engine) - this.engine.stop(); // engine updates state to stopped - } - }, - - destroy: function() { - if (this.engine) - this.engine.destroy(); - this.element.remove(); - }, - - mute: function(flag) { - flag = !!flag; - Symple.log('symple:player: mute', flag); - - if (this.engine && - this.engine.mute) - this.engine.mute(flag); - this.element[flag ? 'addClass' : 'removeClass']('muted'); - }, - - setState: function(state, message) { - Symple.log('symple:player: set state', this.state, '=>', state); - if (this.state == state) - return; - - this.state = state; - this.displayStatus(null); - this.playing = state == 'playing'; - if (message) - this.displayMessage(state == 'error' ? 'error' : 'info', message); - else - this.displayMessage(null); - this.element.removeClass('state-stopped state-loading state-playing state-paused state-error'); - this.element.addClass('state-' + state); - this.options.onStateChange(this, state, message); - }, - - // - // Helpers - // - - displayStatus: function(data) { - this.element.find('.symple-player-status').html(data ? data : ''); - }, - - // Display an overlayed player message. - // Type may be one of: error, warning, info - displayMessage: function(type, message) { - Symple.log('symple:player: display message', type, message) - if (message) { - this.message.html('

' + message + '

').show(); - } - else { - this.message.html('').hide(); - } - }, - - bindEvents: function() { - var self = this; - this.element.find('.symple-player-controls a').unbind().bind('click tap', function() { - self.sendCommand(this.rel, $(this)); - return false; - }) - }, - - sendCommand: function(cmd, e) { - if (!this.options.onCommand || - !this.options.onCommand(this, cmd, e)) { - - // If there is no command callback function or the callback returns - // false then we process these default behaviours. - switch(cmd) { - case 'play': - this.play(); - break; - case 'stop': - this.stop(); - break; - case 'mute': - this.mute(true); - break; - case 'unmute': - this.mute(false); - break; - case 'fullscreen': - this.toggleFullScreen(); - break; - } - } - }, - - getButton: function(cmd) { - return this.element.find('.symple-player-controls [rel="' + cmd + '"]'); - }, - - // TODO: Toggle actual player element - toggleFullScreen: function() { - // if (!document.fullscreenElement) { - // document.documentElement.requestFullscreen(); - // } else { - // if (document.exitFullscreen) { - // document.exitFullscreen(); - // } - // } - var fullscreenElement = $(this.options.fullscreenElement)[0] || this.element[0]; - console.log(fullscreenElement) - if (Symple.runVendorMethod(document, "FullScreen") || - Symple.runVendorMethod(document, "IsFullScreen")) { - Symple.runVendorMethod(document, "CancelFullScreen"); - } - else { - Symple.runVendorMethod(fullscreenElement, "RequestFullScreen"); - } - } -}) - - -// ----------------------------------------------------------------------------- -// Player Engine Interface -// -Symple.Player.Engine = Symple.Class.extend({ - init: function(player) { - this.player = player; - this.fps = 0; - this.seq = 0; - }, - - support: function() { return true; }, - setup: function() {}, - destroy: function() {}, - play: function(params) { - this.params = params || {}; - if (!this.params.url && typeof(params.address) == 'object') - this.params.url = this.buildURL(); - }, - stop: function() {}, - pause: function(flag) {}, - mute: function(flag) {}, - // refresh: function() {}, - - setState: function(state, message) { - this.player.setState(state, message); - }, - - setError: function(error) { - Symple.log('symple:player:engine: error', error); - this.setState('error', error); - }, - - onRemoteCandidate: function(candidate) { - Symple.log('symple:player:engine: remote candidates not supported.'); - }, - - updateFPS: function() { - if (typeof this.prevTime == 'undefined') - this.prevTime = new Date().getTime(); - if (this.seq > 0) { - var now = new Date().getTime(); - this.delta = this.prevTime ? now - this.prevTime : 0; - this.fps = (1000.0 / this.delta).toFixed(3); - this.prevTime = now; - } - this.seq++; - }, - - displayFPS: function() { - this.updateFPS(); - this.player.displayStatus(this.delta + " ms (" + this.fps + " fps)"); - }, - - buildURL: function() { - if (!this.params) - throw 'Streaming parameters not set'; - if (!this.params.address) - this.params.address = this.player.options.address; - return Symple.Media.buildURL(this.params); - } -}); diff --git a/src/webrtc/samples/webrtcstreamer/client/assets/symple.player.webrtc.js b/src/webrtc/samples/webrtcstreamer/client/assets/symple.player.webrtc.js deleted file mode 100644 index 189f1fcc8..000000000 --- a/src/webrtc/samples/webrtcstreamer/client/assets/symple.player.webrtc.js +++ /dev/null @@ -1,280 +0,0 @@ -// ----------------------------------------------------------------------------- -// WebRTC Engine -// - -window.RTCPeerConnection = window.mozRTCPeerConnection || window.webkitRTCPeerConnection; -window.RTCSessionDescription = window.mozRTCSessionDescription || window.RTCSessionDescription; -window.RTCIceCandidate = window.mozRTCIceCandidate || window.RTCIceCandidate; -window.URL = window.webkitURL || window.URL; -navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia; - - -Symple.Media.registerEngine({ - id: 'WebRTC', - name: 'WebRTC Player', - formats: 'VP9, VP4, H.264, Opus', - preference: 100, - support: (function() { - return typeof RTCPeerConnection != 'undefined'; - })() -}); - - -Symple.Player.Engine.WebRTC = Symple.Player.Engine.extend({ - init: function(player) { - Symple.log('symple:webrtc: init'); - this._super(player); - - this.rtcConfig = player.options.rtcConfig || { - iceServers: [ - { url: 'stun:stun.l.google.com:19302' } - ] - } - - this.rtcOptions = player.options.rtcOptions || { - optional: [ - { DtlsSrtpKeyAgreement: true } // required for FF <=> Chrome interop - ] - } - - // Specifies that this client will be the ICE initiator, - // and will be sending the initial SDP Offer. - this.initiator = player.options.initiator; - - // The `MediaStreamConstraints` object to pass to `getUserMedia` - this.userMediaConstraints = player.options.userMediaConstraints || { - audio: true, - video: true - } - - // Reference to the active local or remote media stream - this.activeStream = null; - }, - - setup: function() { - Symple.log('symple:webrtc: setup'); - - this._createPeerConnection(); - - if (typeof(this.video) == 'undefined') { - this.video = document.createElement('video'); - this.video.autoplay = true; - this.player.screen.prepend(this.video); - } - }, - - destroy: function() { - Symple.log('symple:webrtc: destroy'); - - this.sendLocalSDP = null; - this.sendLocalCandidate = null; - this.activeStream = null; // TODO: Needs explicit close? - - if (this.video) { - this.video.src = ''; - this.video = null; - // Anything else required for video cleanup? - } - - if (this.pc) { - this.pc.close(); - this.pc = null; - // Anything else required for peer connection cleanup? - } - }, - - play: function(params) { - Symple.log('symple:webrtc: play', params); - - // If there is an active stream then play it now. - if (this.activeStream) { - this.video.src = URL.createObjectURL(this.activeStream); - this.video.play(); - this.setState('playing'); - } - - // Otherwise wait until ICE to complete before setting the 'playing' state. - else { - - // If we are the ICE `initiator` then attempt to open the local video - // device and send the SDP Offer to the peer. - if (this.initiator) { - Symple.log('symple:webrtc: initiating', this.userMediaConstraints); - var self = this; - - // TODO: Support device enumeration. - navigator.getUserMedia(this.userMediaConstraints, - function (localStream) { // success - - // Play the local video stream and create the SDP offer. - self.video.src = URL.createObjectURL(localStream); - self.pc.addStream(localStream); - self.pc.createOffer( - function(desc) { // success - Symple.log('symple:webrtc: offer', desc); - self._onLocalSDP(desc); - }, - function(err) { // error - Symple.log('symple:webrtc: offer failed', err); - }); - - // Store the active local stream - self.activeStream = localStream; - }, - function(err) { // error - self.setError('getUserMedia() failed: ' + err); - }); - } - } - }, - - stop: function() { - // NOTE: Stopping the player does not close the peer connection, - // only `destroy` does that. This enables us to resume playback - // quickly and with minimal delay. - - - if (this.video) { - this.video.src = ''; - // Do not nullify - } - - // Close peer connection - // if (this.pc) { - // this.pc.close(); - // this.pc = null; - // } - - this.setState('stopped'); - }, - - mute: function(flag) { - // Mute unless explicit false given - flag = flag === false ? false : true; - - Symple.log('symple:webrtc: mute', flag); - - if (this.video) - this.video.prop('muted', flag); - }, - - // Called when local SDP is ready to be sent to the peer. - sendLocalSDP: null, // new Function, - - // Called when a local candidate is ready to be sent to the peer. - sendLocalCandidate: null, // new Function, - - // Called when remote SDP is received from the peer. - recvRemoteSDP: function(desc) { - Symple.log('symple:webrtc: recv remote sdp', desc) - if (!desc || !desc.type || !desc.sdp) - throw 'Invalid remote SDP'; - - var self = this; - this.pc.setRemoteDescription(new RTCSessionDescription(desc), - function() { - Symple.log('symple:webrtc: sdp success'); - }, - function(message) { - console.error('symple:webrtc: sdp error', message); - self.setError('Cannot parse remote SDP offer'); - } - ); - - if (desc.type == 'offer') { - self.pc.createAnswer( - function(answer) { // success - self._onLocalSDP(answer); - }, - function() { // error - self.setError('Cannot create local SDP answer'); - }, - null // this.mediaConstraints - ); - } - }, - - // Called when remote candidate is received from the peer. - recvRemoteCandidate: function(candidate) { - Symple.log('symple:webrtc: recv remote candiate', candidate); - if (!this.pc) - throw 'The peer connection is not initialized'; // call recvRemoteSDP first - - this.pc.addIceCandidate(new RTCIceCandidate(candidate)); - }, - - // - // Private methods - // - - // Called when local SDP is ready to be sent to the peer. - _onLocalSDP: function(desc) { - try { - this.pc.setLocalDescription(desc); - this.sendLocalSDP(desc); - } - catch (e) { - Symple.log('symple:webrtc: failed to send local SDP', e); - } - }, - - // Create the RTCPeerConnection object. - _createPeerConnection: function() { - if (this.pc) - throw 'The peer connection is already initialized'; - - Symple.log('symple:webrtc: create peer connnection', this.rtcConfig, this.rtcOptions); - - var self = this; - this.pc = new RTCPeerConnection(this.rtcConfig, this.rtcOptions); - this.pc.onicecandidate = function(event) { - if (event.candidate) { - Symple.log('symple:webrtc: candidate gathered', event.candidate); - self.sendLocalCandidate(event.candidate); - } - else { - Symple.log('symple:webrtc: candidate gathering complete'); - } - }; - this.pc.onaddstream = function(event) { - Symple.log('symple:webrtc: remote stream added', URL.createObjectURL(event.stream)); - - // Set the state to playing once candidates have completed gathering. - // This is the best we can do until ICE onstatechange is implemented. - self.setState('playing'); - - self.video.src = URL.createObjectURL(event.stream); - self.video.play(); - - // Store the active stream - self.activeStream = event.stream; - }; - this.pc.onremovestream = function(event) { - Symple.log('symple:webrtc: remote stream removed', event); - self.video.stop(); - self.video.src = ''; - }; - - // NOTE: The following state events are still very unreliable. - // Hopefully when the spec is complete this will change, but until then - // we need to 'guess' the state. - // this.pc.onconnecting = function(event) { Symple.log('symple:webrtc: onconnecting:', event); }; - // this.pc.onopen = function(event) { Symple.log('symple:webrtc: onopen:', event); }; - // this.pc.onicechange = function(event) { Symple.log('symple:webrtc: onicechange :', event); }; - // this.pc.onstatechange = function(event) { Symple.log('symple:webrtc: onstatechange :', event); }; - } -}); - - -// -// Helpers - -Symple.Media.iceCandidateType = function(candidateSDP) { - if (candidateSDP.indexOf('typ relay') != -1) - return 'turn'; - if (candidateSDP.indexOf('typ srflx') != -1) - return 'stun'; - if (candidateSDP.indexOf('typ host') != -1) - return 'host'; - return 'unknown'; -} diff --git a/src/webrtc/samples/webrtcstreamer/client/index.ejs b/src/webrtc/samples/webrtcstreamer/client/index.ejs deleted file mode 100644 index 534489258..000000000 --- a/src/webrtc/samples/webrtcstreamer/client/index.ejs +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - - Simple WebRTC Native Video Demo - - - - - - - - - - - - - - - - - -
- - -
-
-
-
-
-
-
-
-
-
-
-
- Logs -
-
-

-            
-
-
-
-
- - diff --git a/src/webrtc/samples/webrtcstreamer/client/package.json b/src/webrtc/samples/webrtcstreamer/client/package.json deleted file mode 100644 index 53f3ace7a..000000000 --- a/src/webrtc/samples/webrtcstreamer/client/package.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "name": "symple-webrtc-native-video-demo", - "title": "Symple WebRTC Native Video Demo", - "version": "0.1.0", - "private": false, - "scripts": { - "start": "node app.js" - }, - "dependencies": { - "symple" : "*", - "express" : "~4.13.3", - "ejs" : "~2.3.4" - } -} diff --git a/src/webrtc/samples/webrtcstreamer/client/symple.json b/src/webrtc/samples/webrtcstreamer/client/symple.json deleted file mode 100644 index 3c25528c1..000000000 --- a/src/webrtc/samples/webrtcstreamer/client/symple.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - /* The ID of the node instance */ - "nodeId" : 1, - - /* The port to listen on */ - "port" : 4500, - - /* Allow anonymous connections */ - "anonymous" : true, - - /* Session ttl in minutes */ - "sessionTtl" : 15/*,*/ - - /* Redis configuration - "redis" : { - "host" : "localhost", - "port" : 6379 - }, */ - - /* SSL configuration - "ssl" : { - "enabled" : false, - "key" : "ssl/symple.key", - "cert" : "ssl/symple.crt" - } */ -} diff --git a/src/webrtc/samples/webrtcstreamer/config.h b/src/webrtc/samples/webrtcstreamer/config.h deleted file mode 100644 index 29c94ca32..000000000 --- a/src/webrtc/samples/webrtcstreamer/config.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef SCY_WebRTC_WebRTCStreamer_Config_H -#define SCY_WebRTC_WebRTCStreamer_Config_H - - -#include "scy/base.h" - -#define SERVER_HOST "localhost" -#define USE_SSL 0 // 1 -#if USE_SSL -#define SERVER_PORT 443 -#else -#define SERVER_PORT 4500 -#endif - - -#endif diff --git a/src/webrtc/samples/webrtcstreamer/main.cpp b/src/webrtc/samples/webrtcstreamer/main.cpp deleted file mode 100644 index 68ae5af57..000000000 --- a/src/webrtc/samples/webrtcstreamer/main.cpp +++ /dev/null @@ -1,101 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// - - -#include "scy/idler.h" -#include "scy/logger.h" -#include "scy/filesystem.h" -#include "signaler.h" - -#include "webrtc/base/ssladapter.h" -#include "webrtc/base/thread.h" - - -using std::endl; -using namespace scy; - - -// Sample data directory helper -std::string sampleDataDir(const std::string& file) -{ - std::string dir; - fs::addnode(dir, SCY_SOURCE_DIR); - fs::addnode(dir, "av"); - fs::addnode(dir, "samples"); - fs::addnode(dir, "data"); - if (!file.empty()) - fs::addnode(dir, file); - return dir; -} - - -int main(int argc, char** argv) -{ - Logger::instance().add(new ConsoleChannel("debug", Level::Trace)); - // Logger::instance().setWriter(new AsyncLogWriter); - -//#if USE_SSL - // net::SSLManager::initNoVerifyClient(); -//#endif - - // Setup WebRTC environment - rtc::LogMessage::LogToDebug(rtc::LS_INFO); // LS_VERBOSE, LS_INFO, LERROR - // rtc::LogMessage::LogTimestamps(); - // rtc::LogMessage::LogThreads(); - - rtc::InitializeSSL(); - - { - // Video source file - std::string sourceFile(sampleDataDir("test.mp4")); - - // Symple signalling client options - smpl::Client::Options options; - options.host = SERVER_HOST; - options.port = SERVER_PORT; - options.name = "Video Server"; - options.user = "videoserver"; - - // NOTE: The server must enable anonymous - // authentication for this test. - // options.token = ""; token based authentication - - // Parse command line args - OptionParser optparse(argc, argv, "-"); - for (auto& kv : optparse.args) { - const std::string& key = kv.first; - const std::string& value = kv.second; - LDebug("Setting option: ", key, ": ", value) - if (key == "file") { - sourceFile = value; - } - else { - LWarn("Unknown option: ", key, "=", value) - } - } - - Signaler app(options); - app.startStreaming(sourceFile, true); - - // Process WebRTC threads on the main loop. - auto rtcthread = rtc::Thread::Current(); - Idler rtc([rtcthread]() { - rtcthread->ProcessMessages(3); - }); - - app.waitForShutdown(); - } - -//#if USE_SSL - // net::SSLManager::destroy(); -//#endif - rtc::CleanupSSL(); - Logger::destroy(); - return 0; -} diff --git a/src/webrtc/samples/webrtcstreamer/signaler.cpp b/src/webrtc/samples/webrtcstreamer/signaler.cpp deleted file mode 100644 index 89716919b..000000000 --- a/src/webrtc/samples/webrtcstreamer/signaler.cpp +++ /dev/null @@ -1,219 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// - - -#include -#include - -#include "scy/webrtc/audiopacketmodule.h" -#include "scy/webrtc/multiplexmediacapturer.h" -#include "scy/webrtc/videopacketsource.h" -#include "signaler.h" - -#include "webrtc/api/mediastreamtrackproxy.h" - - -using std::endl; - - -namespace scy { - - -Signaler::Signaler(const smpl::Client::Options& options) - : _client(options) - , _capturer() - , _context(_capturer.getAudioModule()) -{ - // Setup the signalling client - _client.StateChange += slot(this, &Signaler::onClientStateChange); - _client.roster().ItemAdded += slot(this, &Signaler::onPeerConnected); - _client.roster().ItemRemoved += slot(this, &Signaler::onPeerDiconnected); - _client += packetSlot(this, &Signaler::onPeerMessage); - _client.connect(); -} - - -Signaler::~Signaler() -{ -} - - -void Signaler::startStreaming(const std::string& file, bool looping) -{ - // Open the video file - _capturer.openFile(file, looping); - // _capturer.start(); -} - - -void Signaler::sendSDP(wrtc::Peer* conn, const std::string& type, - const std::string& sdp) -{ - assert(type == "offer" || type == "answer"); - smpl::Message m; - json::value desc; - desc[wrtc::kSessionDescriptionTypeName] = type; - desc[wrtc::kSessionDescriptionSdpName] = sdp; - m[type] = desc; - - // smpl::Message m({ type, { - // { wrtc::kSessionDescriptionTypeName, type }, - // { wrtc::kSessionDescriptionSdpName, sdp} } - // }); - - postMessage(m); -} - - -void Signaler::sendCandidate(wrtc::Peer* conn, const std::string& mid, - int mlineindex, const std::string& sdp) -{ - smpl::Message m; - json::value desc; - desc[wrtc::kCandidateSdpMidName] = mid; - desc[wrtc::kCandidateSdpMlineIndexName] = mlineindex; - desc[wrtc::kCandidateSdpName] = sdp; - m["candidate"] = desc; - - // smpl::Message m({ "candidate", { - // { wrtc::kCandidateSdpMidName, mid }, - // { wrtc::kCandidateSdpMlineIndexName, mlineindex}, - // { wrtc::kCandidateSdpName, sdp} } - // }); - - postMessage(m); -} - - -void Signaler::onPeerConnected(smpl::Peer& peer) -{ - if (peer.id() == _client.ourID()) - return; - LDebug("Peer connected: ", peer.id()) - - if (wrtc::PeerManager::exists(peer.id())) { - LDebug("Peer already has session: ", peer.id()) - return; - } - - // Create the Peer Peer - auto conn = new wrtc::Peer(this, &_context, peer.id(), "", wrtc::Peer::Offer); - conn->constraints().SetMandatoryReceiveAudio(false); - conn->constraints().SetMandatoryReceiveVideo(false); - conn->constraints().SetAllowDtlsSctpDataChannels(); - - // Create the media stream and attach decoder - // output to the peer connection - _capturer.addMediaTracks(_context.factory, conn->createMediaStream()); - - // Send the Offer SDP - conn->createConnection(); - conn->createOffer(); - - wrtc::PeerManager::add(peer.id(), conn); -} - - -void Signaler::onPeerMessage(smpl::Message& m) -{ - LDebug("Peer message: ", m.from().toString()) - - if (m.find("offer") != m.end()) { - assert(0 && "offer not supported"); - } else if (m.find("answer") != m.end()) { - recvSDP(m.from().id, m["answer"]); - } else if (m.find("candidate") != m.end()) { - recvCandidate(m.from().id, m["candidate"]); - } - // else assert(0 && "unknown event"); -} - - -void Signaler::onPeerDiconnected(const smpl::Peer& peer) -{ - LDebug("Peer disconnected") - - auto conn = wrtc::PeerManager::remove(peer.id()); - if (conn) { - LDebug("Deleting peer connection: ", peer.id()) - // async delete not essential, but to be safe - // delete conn; - deleteLater(conn); - } -} - - -void Signaler::onClientStateChange(void*, sockio::ClientState& state, const sockio::ClientState& oldState) -{ - LDebug("Client state changed from ", oldState, " to ", state) - - switch (state.id()) { - case sockio::ClientState::Connecting: - break; - case sockio::ClientState::Connected: - break; - case sockio::ClientState::Online: - break; - case sockio::ClientState::Error: - throw std::runtime_error("Cannot connect to Symple server. " - "Did you start the demo app and the " - "Symple server is running on port 4500?"); - } -} - - -void Signaler::onAddRemoteStream(wrtc::Peer* conn, webrtc::MediaStreamInterface* stream) -{ - assert(0 && "not required"); -} - - -void Signaler::onRemoveRemoteStream(wrtc::Peer* conn, webrtc::MediaStreamInterface* stream) -{ - assert(0 && "not required"); -} - - -void Signaler::onStable(wrtc::Peer* conn) -{ - _capturer.start(); -} - - -void Signaler::onClosed(wrtc::Peer* conn) -{ - _capturer.stop(); - wrtc::PeerManager::onClosed(conn); -} - - -void Signaler::onFailure(wrtc::Peer* conn, const std::string& error) -{ - _capturer.stop(); - wrtc::PeerManager::onFailure(conn, error); -} - - -void Signaler::postMessage(const smpl::Message& m) -{ - _ipc.push(new ipc::Action( - std::bind(&Signaler::syncMessage, this, std::placeholders::_1), - m.clone())); -} - - -void Signaler::syncMessage(const ipc::Action& action) -{ - auto m = reinterpret_cast(action.arg); - _client.send(*m); - delete m; -} - - -} // namespace scy diff --git a/src/webrtc/samples/webrtcstreamer/signaler.h b/src/webrtc/samples/webrtcstreamer/signaler.h deleted file mode 100644 index 04e9de013..000000000 --- a/src/webrtc/samples/webrtcstreamer/signaler.h +++ /dev/null @@ -1,74 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// - - -#ifndef SCY_WebRTC_WebRTCStreamer_Signaler_H -#define SCY_WebRTC_WebRTCStreamer_Signaler_H - - -#include "scy/application.h" -#include "scy/ipc.h" -#include "scy/net/sslmanager.h" -#include "scy/net/sslsocket.h" -#include "scy/symple/client.h" -#include "scy/util.h" -#include "scy/webrtc/peermanager.h" -#include "scy/webrtc/multiplexmediacapturer.h" - -#include "config.h" - - -namespace scy { - - -class Signaler : public wrtc::PeerManager, public Application -{ -public: - Signaler(const smpl::Client::Options& options); - ~Signaler(); - - void startStreaming(const std::string& file, bool loop = true); - -protected: - - /// PeerManager interface - void sendSDP(wrtc::Peer* conn, const std::string& type, const std::string& sdp) override; - void sendCandidate(wrtc::Peer* conn, const std::string& mid, int mlineindex, const std::string& sdp) override; - void onAddRemoteStream(wrtc::Peer* conn, webrtc::MediaStreamInterface* stream) override; - void onRemoveRemoteStream(wrtc::Peer* conn, webrtc::MediaStreamInterface* stream) override; - void onStable(wrtc::Peer* conn) override; - void onClosed(wrtc::Peer* conn) override; - void onFailure(wrtc::Peer* conn, const std::string& error) override; - - void postMessage(const smpl::Message& m); - void syncMessage(const ipc::Action& action); - - void onPeerConnected(smpl::Peer& peer); - void onPeerMessage(smpl::Message& m); - void onPeerDiconnected(const smpl::Peer& peer); - - void onClientStateChange(void* sender, sockio::ClientState& state, - const sockio::ClientState& oldState); - -protected: - ipc::SyncQueue<> _ipc; -#if USE_SSL - smpl::SSLClient _client; -#else - smpl::TCPClient _client; -#endif - wrtc::MultiplexMediaCapturer _capturer; - wrtc::PeerFactoryContext _context; -}; - - -} // namespace scy - - -#endif diff --git a/src/webrtc/src/audiopacketmodule.cpp b/src/webrtc/src/audiopacketmodule.cpp deleted file mode 100644 index d2f1fa896..000000000 --- a/src/webrtc/src/audiopacketmodule.cpp +++ /dev/null @@ -1,827 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// @addtogroup webrtc -/// @{ - - -#include "scy/webrtc/audiopacketmodule.h" - -#ifdef HAVE_FFMPEG - -#include "webrtc/base/refcount.h" -#include "webrtc/base/thread.h" -#include "webrtc/base/timeutils.h" - -#include "scy/logger.h" - - -using std::endl; - - -namespace scy { -namespace wrtc { - - -// Constants correspond to 10ms of sterio audio at 44kHz. -static const uint8_t kNumberOfChannels = 2; -static const int kSamplesPerSecond = 44000; -static const size_t kNumberSamples = 440; -static const size_t kBytesPerSample = sizeof(AudioPacketModule::Sample) * kNumberOfChannels; -static const size_t kBufferBytes = kNumberSamples * kBytesPerSample; - -static const int kTimePerFrameMs = 10; -static const int kTotalDelayMs = 0; -static const int kClockDriftMs = 0; -static const uint32_t kMaxVolume = 14392; - -// Same value as src/modules/audio_device/main/source/audio_device_config.h in -// https://code.google.com/p/webrtc/ -static const int kAdmMaxIdleTimeProcess = 1000; - - -enum -{ - MSG_START_PROCESS, - MSG_RUN_PROCESS -}; - - -AudioPacketModule::AudioPacketModule() - : _lastProcessTimeMS(0) - , _audioCallback(nullptr) - , _recording(false) - , _playing(false) - , _playIsInitialized(false) - , _recIsInitialized(false) - , _currentMicLevel(kMaxVolume) - , _started(false) - , _nextFrameTime(0) - , _sendSamples(kBufferBytes) -{ -} - -AudioPacketModule::~AudioPacketModule() -{ - if (_processThread) { - _processThread->Stop(); - } -} - -rtc::scoped_refptr AudioPacketModule::Create() -{ - rtc::scoped_refptr capture_module( - new rtc::RefCountedObject()); - if (!capture_module->Initialize()) { - return nullptr; - } - return capture_module; -} - -void AudioPacketModule::onAudioCaptured(av::AudioPacket& packet) -{ - LTrace("Audio frame captured") - - // assert(_processThread->IsCurrent()); - rtc::CritScope cs(&_critCallback); - if (!_audioCallback || !_recording) { - return; - } - - // TODO: Implement planar formats - auto data = packet.data(); - _sendFifo.write((void**)&data, packet.numSamples); -} - -void AudioPacketModule::OnMessage(rtc::Message* msg) -{ - switch (msg->message_id) { - case MSG_START_PROCESS: - startProcessP(); - break; - case MSG_RUN_PROCESS: - processFrameP(); - break; - default: - // All existing messages should be caught. - // Getting here should never happen. - assert(false); - } -} - -bool AudioPacketModule::Initialize() -{ - // Allocate the send audio FIFO buffer - _sendFifo.close(); - _sendFifo.alloc("s16", kNumberOfChannels); - - _lastProcessTimeMS = rtc::TimeMillis(); - return true; -} - -bool AudioPacketModule::shouldStartProcessing() -{ - return _recording || _playing; - // return _recording; -} - -void AudioPacketModule::updateProcessing(bool start) -{ - if (start) { - if (!_processThread) { - _processThread.reset(new rtc::Thread()); - _processThread->Start(); - } - _processThread->Post(RTC_FROM_HERE, this, MSG_START_PROCESS); - } else { - if (_processThread) { - _processThread->Stop(); - _processThread.reset(nullptr); - } - _started = false; - } -} - -void AudioPacketModule::startProcessP() -{ - assert(_processThread->IsCurrent()); - if (_started) { - // Already started. - return; - } - processFrameP(); -} - -void AudioPacketModule::processFrameP() -{ - assert(_processThread->IsCurrent()); - if (!_started) { - _nextFrameTime = rtc::TimeMillis(); - _started = true; - } - - { - rtc::CritScope cs(&_crit); - // Receive and send frames every kTimePerFrameMs. - if (_playing) { - receiveFrameP(); - } - if (_recording) { - sendFrameP(); - } - } - - _nextFrameTime += kTimePerFrameMs; - const int64_t current_time = rtc::TimeMillis(); - const int64_t wait_time = (_nextFrameTime > current_time) ? _nextFrameTime - current_time : 0; - _processThread->PostDelayed(RTC_FROM_HERE, wait_time, this, MSG_RUN_PROCESS); -} - - -void AudioPacketModule::sendFrameP() -{ - assert(_processThread->IsCurrent()); - rtc::CritScope cs(&_critCallback); - LDebug("Send audio", _recording) - if (!_audioCallback) { - return; - } - - auto samples = &_sendSamples[0]; - if (!_sendFifo.read((void**)&samples, kNumberSamples)) { - LDebug("No audio frames in send buffer") - return; - } - - bool key_pressed = false; - uint32_t current_mic_level = 0; - MicrophoneVolume(¤t_mic_level); - - LTrace("Send audio") - if (_audioCallback->RecordedDataIsAvailable( - samples, kNumberSamples, kBytesPerSample, kNumberOfChannels, - kSamplesPerSecond, kTotalDelayMs, kClockDriftMs, current_mic_level, - key_pressed, current_mic_level) != 0) { - assert(false); - } - - SetMicrophoneVolume(current_mic_level); -} - -void AudioPacketModule::receiveFrameP() -{ - assert(_processThread->IsCurrent()); - assert(0 && "playout not implemented"); - - // { - // rtc::CritScope cs(&_critCallback); - // if (!_audioCallback) { - // return; - // } - // size_t nSamplesOut = 0; - // int64_t elapsed_time_ms = 0; - // int64_t ntp_time_ms = 0; - // if (_audioCallback->NeedMorePlayData(kNumberSamples, - // kBytesPerSample, - // kNumberOfChannels, - // kSamplesPerSecond, - // rec_sendFifo_, nSamplesOut, - // &elapsed_time_ms, &ntp_time_ms) != - // 0) { - // assert(false); - // } - // assert(nSamplesOut == kNumberSamples); - // } -} - -int64_t AudioPacketModule::TimeUntilNextProcess() -{ - const int64_t current_time = rtc::TimeMillis(); - if (current_time < _lastProcessTimeMS) { - // TODO: wraparound could be handled more gracefully. - return 0; - } - const int64_t elapsed_time = current_time - _lastProcessTimeMS; - if (kAdmMaxIdleTimeProcess < elapsed_time) { - return 0; - } - return kAdmMaxIdleTimeProcess - elapsed_time; -} - -void AudioPacketModule::Process() -{ - _lastProcessTimeMS = rtc::TimeMillis(); -} - -int32_t AudioPacketModule::ActiveAudioLayer(AudioLayer* /*audio_layer*/) const -{ - assert(false); - return 0; -} - -webrtc::AudioDeviceModule::ErrorCode AudioPacketModule::LastError() const -{ - assert(false); - return webrtc::AudioDeviceModule::kAdmErrNone; -} - -int32_t AudioPacketModule::RegisterEventObserver(webrtc::AudioDeviceObserver* /*event_callback*/) -{ - // Only used to report warnings and errors. This fake implementation won't - // generate any so discard this callback. - return 0; -} - -int32_t AudioPacketModule::RegisterAudioCallback(webrtc::AudioTransport* audio_callback) -{ - rtc::CritScope cs(&_critCallback); - _audioCallback = audio_callback; - return 0; -} - -int32_t AudioPacketModule::Init() -{ - // Initialize is called by the factory method. - // Safe to ignore this Init call. - return 0; -} - -int32_t AudioPacketModule::Terminate() -{ - // Clean up in the destructor. No action here, just success. - return 0; -} - -bool AudioPacketModule::Initialized() const -{ - assert(false); - return 0; -} - -int16_t AudioPacketModule::PlayoutDevices() -{ - assert(false); - return 0; -} - -int16_t AudioPacketModule::RecordingDevices() -{ - assert(false); - return 0; -} - -int32_t AudioPacketModule::PlayoutDeviceName(uint16_t /*index*/, - char /*name*/[webrtc::kAdmMaxDeviceNameSize], - char /*guid*/[webrtc::kAdmMaxGuidSize]) -{ - assert(false); - return 0; -} - -int32_t AudioPacketModule::RecordingDeviceName(uint16_t /*index*/, - char /*name*/[webrtc::kAdmMaxDeviceNameSize], - char /*guid*/[webrtc::kAdmMaxGuidSize]) -{ - assert(false); - return 0; -} - -int32_t AudioPacketModule::SetPlayoutDevice(uint16_t /*index*/) -{ - // No playout device, just playing from file. Return success. - return 0; -} - -int32_t AudioPacketModule::SetPlayoutDevice(WindowsDeviceType /*device*/) -{ - if (_playIsInitialized) { - return -1; - } - return 0; -} - -int32_t AudioPacketModule::SetRecordingDevice(uint16_t /*index*/) -{ - // No recording device, just dropping audio. Return success. - return 0; -} - -int32_t AudioPacketModule::SetRecordingDevice(WindowsDeviceType /*device*/) -{ - if (_recIsInitialized) { - return -1; - } - return 0; -} - -int32_t AudioPacketModule::PlayoutIsAvailable(bool* /*available*/) -{ - assert(false); - return 0; -} - -int32_t AudioPacketModule::InitPlayout() -{ - _playIsInitialized = true; - return 0; -} - -bool AudioPacketModule::PlayoutIsInitialized() const -{ - return _playIsInitialized; -} - -int32_t AudioPacketModule::RecordingIsAvailable(bool* /*available*/) -{ - assert(false); - return 0; -} - -int32_t AudioPacketModule::InitRecording() -{ - _recIsInitialized = true; - return 0; -} - -bool AudioPacketModule::RecordingIsInitialized() const -{ - return _recIsInitialized; -} - -int32_t AudioPacketModule::StartPlayout() -{ - LDebug("Start playout") - if (!_playIsInitialized) { - return -1; - } - { - rtc::CritScope cs(&_crit); - _playing = true; - } - bool start = true; - updateProcessing(start); - return 0; -} - -int32_t AudioPacketModule::StopPlayout() -{ - LDebug("Stop playout") - bool start = false; - { - rtc::CritScope cs(&_crit); - _playing = false; - start = shouldStartProcessing(); - } - updateProcessing(start); - return 0; -} - -bool AudioPacketModule::Playing() const -{ - rtc::CritScope cs(&_crit); - return _playing; -} - -int32_t AudioPacketModule::StartRecording() -{ - LDebug("Start recording") - if (!_recIsInitialized) { - return -1; - } - { - rtc::CritScope cs(&_crit); - _recording = true; - } - bool start = true; - updateProcessing(start); - return 0; -} - -int32_t AudioPacketModule::StopRecording() -{ - LDebug("Stop recording") - bool start = false; - { - rtc::CritScope cs(&_crit); - _recording = false; - start = shouldStartProcessing(); - } - updateProcessing(start); - return 0; -} - -bool AudioPacketModule::Recording() const -{ - rtc::CritScope cs(&_crit); - return _recording; -} - -int32_t AudioPacketModule::SetAGC(bool /*enable*/) -{ - // No AGC but not needed since audio is pregenerated. Return success. - return 0; -} - -bool AudioPacketModule::AGC() const -{ - assert(false); - return 0; -} - -int32_t AudioPacketModule::SetWaveOutVolume(uint16_t /*volume_left*/, - uint16_t /*volume_right*/) -{ - assert(false); - return 0; -} - -int32_t AudioPacketModule::WaveOutVolume(uint16_t* /*volume_left*/, - uint16_t* /*volume_right*/) const -{ - assert(false); - return 0; -} - -int32_t AudioPacketModule::InitSpeaker() -{ - // No speaker, just playing from file. Return success. - return 0; -} - -bool AudioPacketModule::SpeakerIsInitialized() const -{ - assert(false); - return 0; -} - -int32_t AudioPacketModule::InitMicrophone() -{ - // No microphone, just playing from file. Return success. - return 0; -} - -bool AudioPacketModule::MicrophoneIsInitialized() const -{ - assert(false); - return 0; -} - -int32_t AudioPacketModule::SpeakerVolumeIsAvailable(bool* /*available*/) -{ - assert(false); - return 0; -} - -int32_t AudioPacketModule::SetSpeakerVolume(uint32_t /*volume*/) -{ - assert(false); - return 0; -} - -int32_t AudioPacketModule::SpeakerVolume(uint32_t* /*volume*/) const -{ - assert(false); - return 0; -} - -int32_t AudioPacketModule::MaxSpeakerVolume(uint32_t* /*max_volume*/) const -{ - assert(false); - return 0; -} - -int32_t AudioPacketModule::MinSpeakerVolume(uint32_t* /*min_volume*/) const -{ - assert(false); - return 0; -} - -int32_t AudioPacketModule::SpeakerVolumeStepSize(uint16_t* /*step_size*/) const -{ - assert(false); - return 0; -} - -int32_t AudioPacketModule::MicrophoneVolumeIsAvailable(bool* /*available*/) -{ - assert(false); - return 0; -} - -int32_t AudioPacketModule::SetMicrophoneVolume(uint32_t volume) -{ - rtc::CritScope cs(&_crit); - _currentMicLevel = volume; - return 0; -} - -int32_t AudioPacketModule::MicrophoneVolume(uint32_t* volume) const -{ - rtc::CritScope cs(&_crit); - *volume = _currentMicLevel; - return 0; -} - -int32_t AudioPacketModule::MaxMicrophoneVolume(uint32_t* max_volume) const -{ - *max_volume = kMaxVolume; - return 0; -} - -int32_t AudioPacketModule::MinMicrophoneVolume(uint32_t* /*min_volume*/) const -{ - assert(false); - return 0; -} - -int32_t -AudioPacketModule::MicrophoneVolumeStepSize(uint16_t* /*step_size*/) const -{ - assert(false); - return 0; -} - -int32_t AudioPacketModule::SpeakerMuteIsAvailable(bool* /*available*/) -{ - assert(false); - return 0; -} - -int32_t AudioPacketModule::SetSpeakerMute(bool /*enable*/) -{ - assert(false); - return 0; -} - -int32_t AudioPacketModule::SpeakerMute(bool* /*enabled*/) const -{ - assert(false); - return 0; -} - -int32_t AudioPacketModule::MicrophoneMuteIsAvailable(bool* /*available*/) -{ - assert(false); - return 0; -} - -int32_t AudioPacketModule::SetMicrophoneMute(bool /*enable*/) -{ - assert(false); - return 0; -} - -int32_t AudioPacketModule::MicrophoneMute(bool* /*enabled*/) const -{ - assert(false); - return 0; -} - -int32_t AudioPacketModule::MicrophoneBoostIsAvailable(bool* /*available*/) -{ - assert(false); - return 0; -} - -int32_t AudioPacketModule::SetMicrophoneBoost(bool /*enable*/) -{ - assert(false); - return 0; -} - -int32_t AudioPacketModule::MicrophoneBoost(bool* /*enabled*/) const -{ - assert(false); - return 0; -} - -int32_t AudioPacketModule::StereoPlayoutIsAvailable(bool* available) const -{ - // No recording device, just dropping audio. Stereo can be dropped just - // as easily as mono. - *available = true; - return 0; -} - -int32_t AudioPacketModule::SetStereoPlayout(bool /*enable*/) -{ - // No recording device, just dropping audio. Stereo can be dropped just - // as easily as mono. - return 0; -} - -int32_t AudioPacketModule::StereoPlayout(bool* /*enabled*/) const -{ - assert(false); - return 0; -} - -int32_t AudioPacketModule::StereoRecordingIsAvailable(bool* available) const -{ - // Keep thing simple. No stereo recording. - *available = false; - return 0; -} - -int32_t AudioPacketModule::SetStereoRecording(bool enable) -{ - if (!enable) { - return 0; - } - return -1; -} - -int32_t AudioPacketModule::StereoRecording(bool* /*enabled*/) const -{ - assert(false); - return 0; -} - -int32_t AudioPacketModule::SetRecordingChannel(const ChannelType channel) -{ - if (channel != AudioDeviceModule::kChannelBoth) { - // There is no right or left in mono. I.e. kChannelBoth should be used - // for - // mono. - assert(false); - return -1; - } - return 0; -} - -int32_t AudioPacketModule::RecordingChannel(ChannelType* channel) const -{ - // Stereo recording not supported. However, WebRTC ADM returns kChannelBoth - // in that case. Do the same here. - *channel = AudioDeviceModule::kChannelBoth; - return 0; -} - -int32_t AudioPacketModule::SetPlayoutBuffer(const BufferType /*type*/, - uint16_t /*size_ms*/) -{ - assert(false); - return 0; -} - -int32_t AudioPacketModule::PlayoutBuffer(BufferType* /*type*/, - uint16_t* /*size_ms*/) const -{ - assert(false); - return 0; -} - -int32_t AudioPacketModule::PlayoutDelay(uint16_t* delay_ms) const -{ - // No delay since audio frames are dropped. - *delay_ms = 0; - return 0; -} - -int32_t AudioPacketModule::RecordingDelay(uint16_t* /*delay_ms*/) const -{ - assert(false); - return 0; -} - -int32_t AudioPacketModule::CPULoad(uint16_t* /*load*/) const -{ - assert(false); - return 0; -} - -int32_t AudioPacketModule::StartRawOutputFileRecording( - const char /*pcm_file_name_utf8*/[webrtc::kAdmMaxFileNameSize]) -{ - assert(false); - return 0; -} - -int32_t AudioPacketModule::StopRawOutputFileRecording() -{ - assert(false); - return 0; -} - -int32_t AudioPacketModule::StartRawInputFileRecording( - const char /*pcm_file_name_utf8*/[webrtc::kAdmMaxFileNameSize]) -{ - assert(false); - return 0; -} - -int32_t AudioPacketModule::StopRawInputFileRecording() -{ - assert(false); - return 0; -} - -int32_t -AudioPacketModule::SetRecordingSampleRate(const uint32_t /*samples_per_sec*/) -{ - assert(false); - return 0; -} - -int32_t -AudioPacketModule::RecordingSampleRate(uint32_t* /*samples_per_sec*/) const -{ - assert(false); - return 0; -} - -int32_t -AudioPacketModule::SetPlayoutSampleRate(const uint32_t /*samples_per_sec*/) -{ - assert(false); - return 0; -} - -int32_t -AudioPacketModule::PlayoutSampleRate(uint32_t* /*samples_per_sec*/) const -{ - assert(false); - return 0; -} - -int32_t AudioPacketModule::ResetAudioDevice() -{ - assert(false); - return 0; -} - -int32_t AudioPacketModule::SetLoudspeakerStatus(bool /*enable*/) -{ - assert(false); - return 0; -} - -int32_t AudioPacketModule::GetLoudspeakerStatus(bool* /*enabled*/) const -{ - assert(false); - return 0; -} - - -} } // namespace scy::wrtc - - -#endif // HAVE_FFMPEG - - -/// @\} - - -/* - * Copyright 2012 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ diff --git a/src/webrtc/src/fakeaudiodevicemodule.cpp b/src/webrtc/src/fakeaudiodevicemodule.cpp deleted file mode 100644 index 3207a9ffe..000000000 --- a/src/webrtc/src/fakeaudiodevicemodule.cpp +++ /dev/null @@ -1,622 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// @addtogroup webrtc -/// @{ - - -#include "scy/webrtc/fakeaudiodevicemodule.h" - -#include "webrtc/base/refcount.h" -#include "webrtc/base/thread.h" -#include "webrtc/base/timeutils.h" - -#include "scy/logger.h" - - -using std::endl; - - -namespace scy { -namespace wrtc { - - -// Same value as src/modules/audio_device/main/source/audio_device_config.h in -// https://code.google.com/p/webrtc/ -static const int kAdmMaxIdleTimeProcess = 1000; -static const uint32_t kMaxVolume = 14392; - - -FakeAudioDeviceModule::FakeAudioDeviceModule() - : _lastProcessTimeMS(0) - , _audioCallback(nullptr) - , _recording(false) - , _playing(false) - , _playIsInitialized(false) - , _recIsInitialized(false) - , _currentMicLevel(kMaxVolume) -{ -} - -FakeAudioDeviceModule::~FakeAudioDeviceModule() -{ -} - -rtc::scoped_refptr FakeAudioDeviceModule::Create() -{ - rtc::scoped_refptr capture_module( - new rtc::RefCountedObject()); - return capture_module; -} - -void FakeAudioDeviceModule::OnMessage(rtc::Message* msg) -{ -} - -int64_t FakeAudioDeviceModule::TimeUntilNextProcess() -{ - const int64_t current_time = rtc::TimeMillis(); - if (current_time < _lastProcessTimeMS) { - // TODO: wraparound could be handled more gracefully. - return 0; - } - const int64_t elapsed_time = current_time - _lastProcessTimeMS; - if (kAdmMaxIdleTimeProcess < elapsed_time) { - return 0; - } - return kAdmMaxIdleTimeProcess - elapsed_time; -} - -void FakeAudioDeviceModule::Process() -{ - _lastProcessTimeMS = rtc::TimeMillis(); -} - -int32_t FakeAudioDeviceModule::ActiveAudioLayer(AudioLayer* /*audio_layer*/) const -{ - assert(false); - return 0; -} - -webrtc::AudioDeviceModule::ErrorCode FakeAudioDeviceModule::LastError() const -{ - assert(false); - return webrtc::AudioDeviceModule::kAdmErrNone; -} - -int32_t FakeAudioDeviceModule::RegisterEventObserver(webrtc::AudioDeviceObserver* /*event_callback*/) -{ - // Only used to report warnings and errors. This fake implementation won't - // generate any so discard this callback. - return 0; -} - -int32_t FakeAudioDeviceModule::RegisterAudioCallback(webrtc::AudioTransport* audio_callback) -{ - // rtc::CritScope cs(&_critCallback); - // _audioCallback = audio_callback; - return 0; -} - -int32_t FakeAudioDeviceModule::Init() -{ - // Initialize is called by the factory method. - // Safe to ignore this Init call. - return 0; -} - -int32_t FakeAudioDeviceModule::Terminate() -{ - // Clean up in the destructor. No action here, just success. - return 0; -} - -bool FakeAudioDeviceModule::Initialized() const -{ - assert(false); - return 0; -} - -int16_t FakeAudioDeviceModule::PlayoutDevices() -{ - assert(false); - return 0; -} - -int16_t FakeAudioDeviceModule::RecordingDevices() -{ - assert(false); - return 0; -} - -int32_t FakeAudioDeviceModule::PlayoutDeviceName(uint16_t /*index*/, - char /*name*/[webrtc::kAdmMaxDeviceNameSize], - char /*guid*/[webrtc::kAdmMaxGuidSize]) -{ - assert(false); - return 0; -} - -int32_t FakeAudioDeviceModule::RecordingDeviceName(uint16_t /*index*/, - char /*name*/[webrtc::kAdmMaxDeviceNameSize], - char /*guid*/[webrtc::kAdmMaxGuidSize]) -{ - assert(false); - return 0; -} - -int32_t FakeAudioDeviceModule::SetPlayoutDevice(uint16_t /*index*/) -{ - // No playout device, just playing from file. Return success. - return 0; -} - -int32_t FakeAudioDeviceModule::SetPlayoutDevice(WindowsDeviceType /*device*/) -{ - if (_playIsInitialized) { - return -1; - } - return 0; -} - -int32_t FakeAudioDeviceModule::SetRecordingDevice(uint16_t /*index*/) -{ - // No recording device, just dropping audio. Return success. - return 0; -} - -int32_t FakeAudioDeviceModule::SetRecordingDevice(WindowsDeviceType /*device*/) -{ - if (_recIsInitialized) { - return -1; - } - return 0; -} - -int32_t FakeAudioDeviceModule::PlayoutIsAvailable(bool* /*available*/) -{ - assert(false); - return 0; -} - -int32_t FakeAudioDeviceModule::InitPlayout() -{ - _playIsInitialized = true; - return 0; -} - -bool FakeAudioDeviceModule::PlayoutIsInitialized() const -{ - return _playIsInitialized; -} - -int32_t FakeAudioDeviceModule::RecordingIsAvailable(bool* /*available*/) -{ - assert(false); - return 0; -} - -int32_t FakeAudioDeviceModule::InitRecording() -{ - _recIsInitialized = true; - return 0; -} - -bool FakeAudioDeviceModule::RecordingIsInitialized() const -{ - return _recIsInitialized; -} - -int32_t FakeAudioDeviceModule::StartPlayout() -{ - LDebug("Start playout") - if (!_playIsInitialized) { - return -1; - } - { - rtc::CritScope cs(&_crit); - _playing = true; - } - return 0; -} - -int32_t FakeAudioDeviceModule::StopPlayout() -{ - LDebug("Stop playout") - { - rtc::CritScope cs(&_crit); - _playing = false; - } - return 0; -} - -bool FakeAudioDeviceModule::Playing() const -{ - rtc::CritScope cs(&_crit); - return _playing; -} - -int32_t FakeAudioDeviceModule::StartRecording() -{ - LDebug("Start recording") - if (!_recIsInitialized) { - return -1; - } - { - rtc::CritScope cs(&_crit); - _recording = true; - } - return 0; -} - -int32_t FakeAudioDeviceModule::StopRecording() -{ - LDebug("Stop recording") - { - rtc::CritScope cs(&_crit); - _recording = false; - } - return 0; -} - -bool FakeAudioDeviceModule::Recording() const -{ - rtc::CritScope cs(&_crit); - return _recording; -} - -int32_t FakeAudioDeviceModule::SetAGC(bool /*enable*/) -{ - // No AGC but not needed since audio is pregenerated. Return success. - return 0; -} - -bool FakeAudioDeviceModule::AGC() const -{ - assert(false); - return 0; -} - -int32_t FakeAudioDeviceModule::SetWaveOutVolume(uint16_t /*volume_left*/, - uint16_t /*volume_right*/) -{ - assert(false); - return 0; -} - -int32_t FakeAudioDeviceModule::WaveOutVolume(uint16_t* /*volume_left*/, - uint16_t* /*volume_right*/) const -{ - assert(false); - return 0; -} - -int32_t FakeAudioDeviceModule::InitSpeaker() -{ - // No speaker, just playing from file. Return success. - return 0; -} - -bool FakeAudioDeviceModule::SpeakerIsInitialized() const -{ - assert(false); - return 0; -} - -int32_t FakeAudioDeviceModule::InitMicrophone() -{ - // No microphone, just playing from file. Return success. - return 0; -} - -bool FakeAudioDeviceModule::MicrophoneIsInitialized() const -{ - assert(false); - return 0; -} - -int32_t FakeAudioDeviceModule::SpeakerVolumeIsAvailable(bool* /*available*/) -{ - assert(false); - return 0; -} - -int32_t FakeAudioDeviceModule::SetSpeakerVolume(uint32_t /*volume*/) -{ - assert(false); - return 0; -} - -int32_t FakeAudioDeviceModule::SpeakerVolume(uint32_t* /*volume*/) const -{ - assert(false); - return 0; -} - -int32_t FakeAudioDeviceModule::MaxSpeakerVolume(uint32_t* /*max_volume*/) const -{ - assert(false); - return 0; -} - -int32_t FakeAudioDeviceModule::MinSpeakerVolume(uint32_t* /*min_volume*/) const -{ - assert(false); - return 0; -} - -int32_t FakeAudioDeviceModule::SpeakerVolumeStepSize(uint16_t* /*step_size*/) const -{ - assert(false); - return 0; -} - -int32_t FakeAudioDeviceModule::MicrophoneVolumeIsAvailable(bool* /*available*/) -{ - assert(false); - return 0; -} - -int32_t FakeAudioDeviceModule::SetMicrophoneVolume(uint32_t volume) -{ - rtc::CritScope cs(&_crit); - _currentMicLevel = volume; - return 0; -} - -int32_t FakeAudioDeviceModule::MicrophoneVolume(uint32_t* volume) const -{ - rtc::CritScope cs(&_crit); - *volume = _currentMicLevel; - return 0; -} - -int32_t FakeAudioDeviceModule::MaxMicrophoneVolume(uint32_t* max_volume) const -{ - *max_volume = kMaxVolume; - return 0; -} - -int32_t FakeAudioDeviceModule::MinMicrophoneVolume(uint32_t* /*min_volume*/) const -{ - assert(false); - return 0; -} - -int32_t -FakeAudioDeviceModule::MicrophoneVolumeStepSize(uint16_t* /*step_size*/) const -{ - assert(false); - return 0; -} - -int32_t FakeAudioDeviceModule::SpeakerMuteIsAvailable(bool* /*available*/) -{ - assert(false); - return 0; -} - -int32_t FakeAudioDeviceModule::SetSpeakerMute(bool /*enable*/) -{ - assert(false); - return 0; -} - -int32_t FakeAudioDeviceModule::SpeakerMute(bool* /*enabled*/) const -{ - assert(false); - return 0; -} - -int32_t FakeAudioDeviceModule::MicrophoneMuteIsAvailable(bool* /*available*/) -{ - assert(false); - return 0; -} - -int32_t FakeAudioDeviceModule::SetMicrophoneMute(bool /*enable*/) -{ - assert(false); - return 0; -} - -int32_t FakeAudioDeviceModule::MicrophoneMute(bool* /*enabled*/) const -{ - assert(false); - return 0; -} - -int32_t FakeAudioDeviceModule::MicrophoneBoostIsAvailable(bool* /*available*/) -{ - assert(false); - return 0; -} - -int32_t FakeAudioDeviceModule::SetMicrophoneBoost(bool /*enable*/) -{ - assert(false); - return 0; -} - -int32_t FakeAudioDeviceModule::MicrophoneBoost(bool* /*enabled*/) const -{ - assert(false); - return 0; -} - -int32_t FakeAudioDeviceModule::StereoPlayoutIsAvailable(bool* available) const -{ - // No recording device, just dropping audio. Stereo can be dropped just - // as easily as mono. - *available = true; - return 0; -} - -int32_t FakeAudioDeviceModule::SetStereoPlayout(bool /*enable*/) -{ - // No recording device, just dropping audio. Stereo can be dropped just - // as easily as mono. - return 0; -} - -int32_t FakeAudioDeviceModule::StereoPlayout(bool* /*enabled*/) const -{ - assert(false); - return 0; -} - -int32_t FakeAudioDeviceModule::StereoRecordingIsAvailable(bool* available) const -{ - // Keep thing simple. No stereo recording. - *available = false; - return 0; -} - -int32_t FakeAudioDeviceModule::SetStereoRecording(bool enable) -{ - if (!enable) { - return 0; - } - return -1; -} - -int32_t FakeAudioDeviceModule::StereoRecording(bool* /*enabled*/) const -{ - assert(false); - return 0; -} - -int32_t FakeAudioDeviceModule::SetRecordingChannel(const ChannelType channel) -{ - if (channel != AudioDeviceModule::kChannelBoth) { - // There is no right or left in mono. I.e. kChannelBoth should be used - // for - // mono. - assert(false); - return -1; - } - return 0; -} - -int32_t FakeAudioDeviceModule::RecordingChannel(ChannelType* channel) const -{ - // Stereo recording not supported. However, WebRTC ADM returns kChannelBoth - // in that case. Do the same here. - *channel = AudioDeviceModule::kChannelBoth; - return 0; -} - -int32_t FakeAudioDeviceModule::SetPlayoutBuffer(const BufferType /*type*/, - uint16_t /*size_ms*/) -{ - assert(false); - return 0; -} - -int32_t FakeAudioDeviceModule::PlayoutBuffer(BufferType* /*type*/, - uint16_t* /*size_ms*/) const -{ - assert(false); - return 0; -} - -int32_t FakeAudioDeviceModule::PlayoutDelay(uint16_t* delay_ms) const -{ - // No delay since audio frames are dropped. - *delay_ms = 0; - return 0; -} - -int32_t FakeAudioDeviceModule::RecordingDelay(uint16_t* /*delay_ms*/) const -{ - assert(false); - return 0; -} - -int32_t FakeAudioDeviceModule::CPULoad(uint16_t* /*load*/) const -{ - assert(false); - return 0; -} - -int32_t FakeAudioDeviceModule::StartRawOutputFileRecording( - const char /*pcm_file_name_utf8*/[webrtc::kAdmMaxFileNameSize]) -{ - assert(false); - return 0; -} - -int32_t FakeAudioDeviceModule::StopRawOutputFileRecording() -{ - assert(false); - return 0; -} - -int32_t FakeAudioDeviceModule::StartRawInputFileRecording( - const char /*pcm_file_name_utf8*/[webrtc::kAdmMaxFileNameSize]) -{ - assert(false); - return 0; -} - -int32_t FakeAudioDeviceModule::StopRawInputFileRecording() -{ - assert(false); - return 0; -} - -int32_t -FakeAudioDeviceModule::SetRecordingSampleRate(const uint32_t /*samples_per_sec*/) -{ - assert(false); - return 0; -} - -int32_t -FakeAudioDeviceModule::RecordingSampleRate(uint32_t* /*samples_per_sec*/) const -{ - assert(false); - return 0; -} - -int32_t -FakeAudioDeviceModule::SetPlayoutSampleRate(const uint32_t /*samples_per_sec*/) -{ - assert(false); - return 0; -} - -int32_t -FakeAudioDeviceModule::PlayoutSampleRate(uint32_t* /*samples_per_sec*/) const -{ - assert(false); - return 0; -} - -int32_t FakeAudioDeviceModule::ResetAudioDevice() -{ - assert(false); - return 0; -} - -int32_t FakeAudioDeviceModule::SetLoudspeakerStatus(bool /*enable*/) -{ - assert(false); - return 0; -} - -int32_t FakeAudioDeviceModule::GetLoudspeakerStatus(bool* /*enabled*/) const -{ - assert(false); - return 0; -} - - -} } // namespace scy::wrtc - - -/// @\} diff --git a/src/webrtc/src/multiplexmediacapturer.cpp b/src/webrtc/src/multiplexmediacapturer.cpp deleted file mode 100644 index f90764227..000000000 --- a/src/webrtc/src/multiplexmediacapturer.cpp +++ /dev/null @@ -1,136 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// @addtogroup webrtc -/// @{ - - -#include "scy/webrtc/multiplexmediacapturer.h" - -#ifdef HAVE_FFMPEG - -#include "scy/av/audioresampler.h" -#include "scy/av/ffmpeg.h" -#include "scy/av/realtimepacketqueue.h" -#include "scy/filesystem.h" -#include "scy/logger.h" -#include "scy/webrtc/webrtc.h" -#include "webrtc/media/engine/webrtcvideocapturerfactory.h" -#include "webrtc/modules/video_capture/video_capture_factory.h" - - -namespace scy { -namespace wrtc { - - -MultiplexMediaCapturer::MultiplexMediaCapturer() - : _videoCapture(std::make_shared()) - , _audioModule(AudioPacketModule::Create()) -{ - _stream.attachSource(_videoCapture, true); - // _stream.attach(std::make_shared>(0), 5); - // _stream.attach(std::make_shared>(0), 5); - _stream.emitter += packetSlot(_audioModule.get(), &AudioPacketModule::onAudioCaptured); -} - - -MultiplexMediaCapturer::~MultiplexMediaCapturer() -{ -} - - -void MultiplexMediaCapturer::openFile(const std::string& file, bool loop) -{ - // Open the capture file - _videoCapture->setLoopInput(loop); - _videoCapture->setRealtimePlayback(true); - _videoCapture->openFile(file); - - // Set the output settings - if (_videoCapture->audio()) { - _videoCapture->audio()->oparams.sampleFmt = "s16"; - _videoCapture->audio()->oparams.sampleRate = 44000; - _videoCapture->audio()->oparams.channels = 2; - _videoCapture->audio()->recreateResampler(); - // _videoCapture->audio()->resampler->maxNumSamples = 440; - // _videoCapture->audio()->resampler->variableOutput = false; - } - - // Convert to yuv420p for WebRTC compatability - if (_videoCapture->video()) { - _videoCapture->video()->oparams.pixelFmt = "yuv420p"; // nv12 - // _videoCapture->video()->oparams.width = capture_format.width; - // _videoCapture->video()->oparams.height = capture_format.height; - } -} - - -VideoPacketSource* MultiplexMediaCapturer::createVideoSource() -{ - assert(_videoCapture->video()); - auto oparams = _videoCapture->video()->oparams; - auto source = new VideoPacketSource(oparams.width, oparams.height, - oparams.fps, cricket::FOURCC_I420); - source->setPacketSource(&_stream.emitter); // nullified on VideoPacketSource::Stop - return source; -} - - -rtc::scoped_refptr MultiplexMediaCapturer::getAudioModule() -{ - return _audioModule; -} - - -void MultiplexMediaCapturer::addMediaTracks( - webrtc::PeerConnectionFactoryInterface* factory, - webrtc::MediaStreamInterface* stream) -{ - // This capturer is multicast, meaning it can be used as the source - // for multiple Peer objects. - // - // KLUDGE: Pixel format conversion should happen on the - // VideoPacketSource rather than on the decoder becasue different - // peers may request different optimal output video sizes. - - // Create and add the audio stream - if (_videoCapture->audio()) { - stream->AddTrack(factory->CreateAudioTrack( - kAudioLabel, factory->CreateAudioSource(nullptr))); - } - - // Create and add the video stream - if (_videoCapture->video()) { - stream->AddTrack(factory->CreateVideoTrack( - kVideoLabel, factory->CreateVideoSource(createVideoSource(), nullptr))); - } - - // Default WebRTC video stream for testing - // stream->AddTrack(factory->CreateVideoTrack( - // kVideoLabel, factory->CreateVideoSource(openVideoDefaultWebRtcCaptureDevice(), nullptr))); -} - - -void MultiplexMediaCapturer::start() -{ - _stream.start(); -} - - -void MultiplexMediaCapturer::stop() -{ - _stream.stop(); -} - - -} } // namespace scy::wrtc - - -#endif // HAVE_FFMPEG - - -/// @\} diff --git a/src/webrtc/src/peer.cpp b/src/webrtc/src/peer.cpp deleted file mode 100644 index d2a92e7fb..000000000 --- a/src/webrtc/src/peer.cpp +++ /dev/null @@ -1,343 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// @addtogroup webrtc -/// @{ - - -#include "scy/webrtc/peer.h" -#include "scy/webrtc/peermanager.h" -#include "scy/webrtc/peerfactorycontext.h" -#include "scy/logger.h" - - -using std::endl; - - -namespace scy { -namespace wrtc { - - -Peer::Peer(PeerManager* manager, - PeerFactoryContext* context, - const std::string& peerid, - const std::string& token, - Mode mode) - : _manager(manager) - , _context(context) - , _peerid(peerid) - , _token(token) - , _mode(mode) - //, _context->factory(manager->factory()) - , _peerConnection(nullptr) - , _stream(nullptr) -{ - // webrtc::PeerConnectionInterface::IceServer stun; - // stun.uri = kGoogleStunServerUri; - // _config.servers.push_back(stun); - - // _constraints.SetMandatoryReceiveAudio(true); - // _constraints.SetMandatoryReceiveVideo(true); - // _constraints.SetAllowDtlsSctpDataChannels(); -} - - -Peer::~Peer() -{ - LDebug(_peerid, ": Destroying") - // closeConnection(); - - if (_peerConnection) { - _peerConnection->Close(); - } -} - - -rtc::scoped_refptr Peer::createMediaStream() -{ - assert(_mode == Offer); - //assert(_context->factory); - assert(!_stream); - _stream = _context->factory->CreateLocalMediaStream(kStreamLabel); - return _stream; -} - - -void Peer::setPortRange(int minPort, int maxPort) -{ - assert(!_peerConnection); - - if (!_context->networkManager) { - throw std::runtime_error("Must initialize custom network manager to set port range"); - } - - if (!_context->socketFactory) { - throw std::runtime_error("Must initialize custom socket factory to set port range"); - } - - if (!_portAllocator) - _portAllocator.reset(new cricket::BasicPortAllocator( - _context->networkManager.get(), - _context->socketFactory.get())); - _portAllocator->SetPortRange(minPort, maxPort); -} - - -void Peer::createConnection() -{ - assert(_context->factory); - _peerConnection = _context->factory->CreatePeerConnection(_config, &_constraints, - std::move(_portAllocator), nullptr, this); - - if (_stream) { - if (!_peerConnection->AddStream(_stream)) { - throw std::runtime_error("Adding stream to Peer failed"); - } - } -} - - -void Peer::closeConnection() -{ - LDebug(_peerid, ": Closing") - - if (_peerConnection) { - _peerConnection->Close(); - } - else { - // Call onClosed if no connection has been - // made so callbacks are always run. - _manager->onClosed(this); - } -} - - -void Peer::createOffer() -{ - assert(_mode == Offer); - assert(_peerConnection); - - _peerConnection->CreateOffer(this, &_constraints); -} - - -void Peer::recvSDP(const std::string& type, const std::string& sdp) -{ - LDebug(_peerid, ": Receive ", type, ": ", sdp) - - webrtc::SdpParseError error; - webrtc::SessionDescriptionInterface* desc( - webrtc::CreateSessionDescription(type, sdp, &error)); - if (!desc) { - throw std::runtime_error("Can't parse remote SDP: " + error.description); - } - _peerConnection->SetRemoteDescription( - DummySetSessionDescriptionObserver::Create(), desc); - - if (type == "offer") { - assert(_mode == Answer); - _peerConnection->CreateAnswer(this, &_constraints); - } else { - assert(_mode == Offer); - } -} - - -void Peer::recvCandidate(const std::string& mid, int mlineindex, - const std::string& sdp) -{ - webrtc::SdpParseError error; - std::unique_ptr candidate( - webrtc::CreateIceCandidate(mid, mlineindex, sdp, &error)); - if (!candidate) { - throw std::runtime_error("Can't parse remote candidate: " + error.description); - } - _peerConnection->AddIceCandidate(candidate.get()); -} - - -void Peer::OnSignalingChange(webrtc::PeerConnectionInterface::SignalingState new_state) -{ - LDebug(_peerid, ": On signaling state change: ", new_state) - - switch (new_state) { - case webrtc::PeerConnectionInterface::kStable: - _manager->onStable(this); - break; - case webrtc::PeerConnectionInterface::kClosed: - _manager->onClosed(this); - break; - case webrtc::PeerConnectionInterface::kHaveLocalOffer: - case webrtc::PeerConnectionInterface::kHaveRemoteOffer: - case webrtc::PeerConnectionInterface::kHaveLocalPrAnswer: - case webrtc::PeerConnectionInterface::kHaveRemotePrAnswer: - break; - } -} - - -void Peer::OnIceConnectionChange(webrtc::PeerConnectionInterface::IceConnectionState new_state) -{ - LDebug(_peerid, ": On ICE connection change: ", new_state) -} - - -void Peer::OnIceGatheringChange(webrtc::PeerConnectionInterface::IceGatheringState new_state) -{ - LDebug(_peerid, ": On ICE gathering change: ", new_state) -} - - -void Peer::OnRenegotiationNeeded() -{ - LDebug(_peerid, ": On renegotiation needed") -} - - -void Peer::OnAddStream(rtc::scoped_refptr stream) -{ - // proxy to deprecated OnAddStream method - OnAddStream(stream.get()); -} - - -void Peer::OnRemoveStream(rtc::scoped_refptr stream) -{ - // proxy to deprecated OnRemoveStream method - OnRemoveStream(stream.get()); -} - - -void Peer::OnDataChannel(rtc::scoped_refptr stream) -{ - assert(0 && "virtual"); -} - - -void Peer::OnAddStream(webrtc::MediaStreamInterface* stream) -{ - assert(_mode == Answer); - - LDebug(_peerid, ": On add stream") - _manager->onAddRemoteStream(this, stream); -} - - -void Peer::OnRemoveStream(webrtc::MediaStreamInterface* stream) -{ - assert(_mode == Answer); - - LDebug(_peerid, ": On remove stream") - _manager->onRemoveRemoteStream(this, stream); -} - - -void Peer::OnIceCandidate(const webrtc::IceCandidateInterface* candidate) -{ - std::string sdp; - if (!candidate->ToString(&sdp)) { - LError(_peerid, ": Failed to serialize candidate") - assert(0); - return; - } - - _manager->sendCandidate(this, candidate->sdp_mid(), - candidate->sdp_mline_index(), sdp); -} - - -void Peer::OnSuccess(webrtc::SessionDescriptionInterface* desc) -{ - LDebug(_peerid, ": Set local description") - _peerConnection->SetLocalDescription( - DummySetSessionDescriptionObserver::Create(), desc); - - // Send an SDP offer to the peer - std::string sdp; - if (!desc->ToString(&sdp)) { - LError(_peerid, ": Failed to serialize local sdp") - assert(0); - return; - } - - _manager->sendSDP(this, desc->type(), sdp); -} - - -void Peer::OnFailure(const std::string& error) -{ - LError(_peerid, ": On failure: ", error) - - _manager->onFailure(this, error); -} - - -void Peer::setPeerFactory(rtc::scoped_refptr factory) -{ - assert(!_context->factory); // should not be already set via PeerManager - _context->factory = factory; -} - - -std::string Peer::peerid() const -{ - return _peerid; -} - - -std::string Peer::token() const -{ - return _token; -} - - -webrtc::FakeConstraints& Peer::constraints() -{ - return _constraints; -} - - -webrtc::PeerConnectionFactoryInterface* Peer::factory() const -{ - return _context->factory.get(); -} - - -rtc::scoped_refptr Peer::peerConnection() const -{ - return _peerConnection; -} - - -rtc::scoped_refptr Peer::stream() const -{ - return _stream; -} - - -// -// Dummy Set Peer Description Observer -// - - -void DummySetSessionDescriptionObserver::OnSuccess() -{ - LDebug("On SDP parse success") -} - - -void DummySetSessionDescriptionObserver::OnFailure(const std::string& error) -{ - LError("On SDP parse error: ", error) - assert(0); -} - - -} } // namespace scy::wrtc - - -/// @\} diff --git a/src/webrtc/src/peerfactorycontext.cpp b/src/webrtc/src/peerfactorycontext.cpp deleted file mode 100644 index ca96f86ab..000000000 --- a/src/webrtc/src/peerfactorycontext.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// @addtogroup webrtc -/// @{ - - -#include "scy/webrtc/peerfactorycontext.h" -#include "scy/webrtc/fakeaudiodevicemodule.h" -//#include "webrtc/pc/test/fakeaudiocapturemodule.h" -#include "scy/logger.h" - -#include "webrtc/api/peerconnectionfactoryproxy.h" -#include "webrtc/api/peerconnectionproxy.h" -#include "webrtc/api/audio_codecs/builtin_audio_decoder_factory.h" -#include "webrtc/modules/audio_coding/codecs/builtin_audio_encoder_factory.h" -#include "webrtc/p2p/base/basicpacketsocketfactory.h" -#include "webrtc/p2p/client/basicportallocator.h" -#include "webrtc/pc/peerconnection.h" - - -using std::endl; - - -namespace scy { -namespace wrtc { - - -PeerFactoryContext::PeerFactoryContext( - webrtc::AudioDeviceModule* default_adm, - cricket::WebRtcVideoEncoderFactory* video_encoder_factory, - cricket::WebRtcVideoDecoderFactory* video_decoder_factory, - rtc::scoped_refptr audio_encoder_factory, - rtc::scoped_refptr audio_decoder_factory) - // : audioDeviceManager(default_adm) -{ - // Setup threads - networkThread = rtc::Thread::CreateWithSocketServer(); - workerThread = rtc::Thread::Create(); - if (!networkThread->Start() || !workerThread->Start()) - throw std::runtime_error("Failed to start WebRTC threads"); - - // Create the factory - if (audio_encoder_factory || audio_decoder_factory) { - factory = webrtc::CreatePeerConnectionFactory( - networkThread.get(), workerThread.get(), rtc::Thread::Current(), - default_adm, audio_encoder_factory, audio_decoder_factory, - video_encoder_factory, video_decoder_factory); - } - else { - //if (!audioDeviceManager) - // audioDeviceManager = wrtc::FakeAudioDeviceModule::Create(); - //audioDeviceManager = FakeAudioCaptureModule::Create(); - factory = webrtc::CreatePeerConnectionFactory( - networkThread.get(), workerThread.get(), rtc::Thread::Current(), - default_adm, video_encoder_factory, video_decoder_factory); - // audioDeviceManager.get(), video_encoder_factory, video_decoder_factory); - //factory = webrtc::CreatePeerConnectionFactory(); - } - if (!factory) - throw std::runtime_error("Failed to create WebRTC factory"); -} - - -void PeerFactoryContext::initCustomNetworkManager() -{ - networkManager.reset(new rtc::BasicNetworkManager()); - socketFactory.reset(new rtc::BasicPacketSocketFactory(networkThread.get())); -} - - -} } // namespace scy::wrtc - - -/// @\} diff --git a/src/webrtc/src/peermanager.cpp b/src/webrtc/src/peermanager.cpp deleted file mode 100644 index f53b39f04..000000000 --- a/src/webrtc/src/peermanager.cpp +++ /dev/null @@ -1,149 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// @addtogroup webrtc -/// @{ - - -#include "scy/webrtc/peermanager.h" -#include "scy/memory.h" - - -using std::endl; - - -namespace scy { -namespace wrtc { - - -PeerManager::PeerManager() // (PeerFactoryContext* context) - // : _context(context) -{ -} - - -PeerManager::~PeerManager() -{ -} - - -void PeerManager::sendSDP(Peer* conn, const std::string& type, const std::string& sdp) -{ - assert(0 && "virtual"); -} - - -void PeerManager::sendCandidate(Peer* conn, const std::string& mid, int mlineindex, const std::string& sdp) -{ - assert(0 && "virtual"); -} - - -void PeerManager::recvSDP(const std::string& token, const json::value& message) -{ - auto conn = PeerManager::get(token, false); - if (!conn) { - assert(0 && "peer mismath"); - return; - } - - std::string type = message.value(kSessionDescriptionTypeName, ""); - std::string sdp = message.value(kSessionDescriptionSdpName, ""); - if (sdp.empty() || (type != "offer" && type != "answer")) { - LError("Received bad sdp: ", type, ": ", sdp) - assert(0 && "bad sdp"); - return; - } - - conn->recvSDP(type, sdp); - - LDebug("Received ", type, ": ", sdp) -} - - -void PeerManager::recvCandidate(const std::string& token, const json::value& message) -{ - auto conn = PeerManager::get(token, false); - if (!conn) { - assert(0 && "peer mismath"); - return; - } - - std::string mid = message.value(kCandidateSdpMidName, ""); - int mlineindex = message.value(kCandidateSdpMlineIndexName, -1); - std::string sdp = message.value(kCandidateSdpName, ""); - if (mlineindex == -1 || mid.empty() || sdp.empty()) { - LError("Invalid candidate format") - assert(0 && "bad candiate"); - return; - } - - LDebug("Received candidate: ", sdp) - - conn->recvCandidate(mid, mlineindex, sdp); -} - - -void PeerManager::onAddRemoteStream(Peer* conn, webrtc::MediaStreamInterface* stream) -{ - assert(0 && "virtual"); -} - - -void PeerManager::onRemoveRemoteStream(Peer* conn, webrtc::MediaStreamInterface* stream) -{ - assert(0 && "virtual"); -} - - -void PeerManager::onStable(Peer* conn) -{ -} - - -void PeerManager::onClosed(Peer* conn) -{ - LDebug("Deleting peer connection: ", conn->peerid()) - - if (remove(conn)) - deleteLater(conn); // async delete -} - - -void PeerManager::onFailure(Peer* conn, const std::string& error) -{ - LDebug("Deleting peer connection: ", conn->peerid()) - - if (remove(conn)) - deleteLater(conn); // async delete -} - - -//void PeerManager::setContext(PeerFactoryContext* context) -//{ -// assert(!_context); -// _context.reset(context); -//} - - -// PeerFactoryContext* PeerManager::context() const -// { -// return _context.get(); -// } - - -// webrtc::PeerConnectionFactoryInterface* PeerManager::factory() const -// { -// assert(_context); -// return _context->factory.get(); -// } - - -} } // namespace scy::wrtc - - -/// @\} diff --git a/src/webrtc/src/recordingpeer.cpp b/src/webrtc/src/recordingpeer.cpp deleted file mode 100644 index 8140b1195..000000000 --- a/src/webrtc/src/recordingpeer.cpp +++ /dev/null @@ -1,138 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// @addtogroup webrtc -/// @{ - - -#include "scy/webrtc/recordingpeer.h" - -#ifdef HAVE_FFMPEG - -#include "scy/logger.h" -#include "scy/webrtc/peermanager.h" -#include "scy/webrtc/videopacketsource.h" - - -using std::endl; - - -namespace scy { -namespace wrtc { - - -RecordingPeer::RecordingPeer(PeerManager* manager, - PeerFactoryContext* context, - const std::string& peerid, - const std::string& token, - const av::EncoderOptions& options) - : Peer(manager, context, peerid, token, Peer::Offer) - , _recorder(new StreamRecorder(options)) -{ - // _constraints.SetMandatoryReceiveAudio(false); - // _constraints.SetMandatoryReceiveVideo(false); - // _constraints.SetAllowDtlsSctpDataChannels(); -} - - -RecordingPeer::~RecordingPeer() -{ -} - - -// rtc::scoped_refptr RecordingPeer::createMediaStream() -// { -// assert(_mode == Offer); -// assert(_factory); -// assert(!_stream); -// // assert(!_capture); -// _stream = _factory->CreateLocalMediaStream(kStreamLabel); -// -// _capturer.openFile(_file); -// _capturer.addMediaTracks(_factory, _stream); -// -// return _stream; -// } - - -void RecordingPeer::OnAddStream(webrtc::MediaStreamInterface* stream) -{ - assert(_mode == Answer); - - LDebug(_peerid, ": On add stream") - _manager->onAddRemoteStream(this, stream); - - // Set tracks - auto videoTracks = stream->GetVideoTracks(); - if (!videoTracks.empty()) - _recorder->setVideoTrack(videoTracks[0]); - - auto audioTracks = stream->GetAudioTracks(); - if (!audioTracks.empty()) - _recorder->setAudioTrack(audioTracks[0]); -} - - -void RecordingPeer::OnRemoveStream(webrtc::MediaStreamInterface* stream) -{ - assert(_mode == Answer); - - LDebug(_peerid, ": On remove stream") - _manager->onRemoveRemoteStream(this, stream); - - assert(0 && "free streams"); -} - - -// void RecordingPeer::OnSignalingChange(webrtc::PeerConnectionInterface::SignalingState new_state) -// { -// switch(new_state) { -// case webrtc::PeerConnectionInterface::kStable: -// break; -// case webrtc::PeerConnectionInterface::kClosed: -// _recorder.reset(); // shutdown the recorder -// break; -// case webrtc::PeerConnectionInterface::kHaveLocalOffer: -// case webrtc::PeerConnectionInterface::kHaveRemoteOffer: -// break; -// case webrtc::PeerConnectionInterface::kHaveLocalPrAnswer: -// case webrtc::PeerConnectionInterface::kHaveRemotePrAnswer: -// _capture->start(); -// break; -// } -// -// Peer::OnSignalingChange(new_state); -// } - - -void RecordingPeer::OnIceConnectionChange( - webrtc::PeerConnectionInterface::IceConnectionState new_state) -{ - LDebug(_peerid, ": On ICE gathering change: ", new_state) - - switch (new_state) { - case webrtc::PeerConnectionInterface::kIceConnectionNew: - case webrtc::PeerConnectionInterface::kIceConnectionChecking: - case webrtc::PeerConnectionInterface::kIceConnectionConnected: - break; - case webrtc::PeerConnectionInterface::kIceConnectionCompleted: - break; - case webrtc::PeerConnectionInterface::kIceConnectionFailed: - case webrtc::PeerConnectionInterface::kIceConnectionDisconnected: - case webrtc::PeerConnectionInterface::kIceConnectionClosed: - case webrtc::PeerConnectionInterface::kIceConnectionMax: - break; - } - - Peer::OnIceConnectionChange(new_state); -} - - -} } // namespace scy::wrtc - - -#endif // HAVE_FFMPEG \ No newline at end of file diff --git a/src/webrtc/src/streamrecorder.cpp b/src/webrtc/src/streamrecorder.cpp deleted file mode 100644 index 2ee725c38..000000000 --- a/src/webrtc/src/streamrecorder.cpp +++ /dev/null @@ -1,150 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// @addtogroup webrtc -/// @{ - - -#include "scy/webrtc/streamrecorder.h" - -#ifdef HAVE_FFMPEG - -#include "scy/av/ffmpeg.h" -#include "scy/filesystem.h" -#include "scy/logger.h" - -#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" -#include "webrtc/media/engine/webrtcvideocapturerfactory.h" -#include "webrtc/modules/video_capture/video_capture_factory.h" - - -namespace scy { -namespace wrtc { - - -StreamRecorder::StreamRecorder(const av::EncoderOptions& options) - : _encoder(options) - , _awaitingVideo(false) - , _awaitingAudio(false) -{ - // Disable audio and video until tracks are set - _encoder.options().oformat.video.enabled = false; - _encoder.options().oformat.audio.enabled = false; -} - - -StreamRecorder::~StreamRecorder() -{ - if (_videoTrack) - _videoTrack->RemoveSink(this); - - if (_audioTrack) - _audioTrack->RemoveSink(this); -} - - -void StreamRecorder::setVideoTrack(webrtc::VideoTrackInterface* track) -{ - assert(!_videoTrack); - _videoTrack = track; - _videoTrack->AddOrUpdateSink(this, rtc::VideoSinkWants()); - _encoder.options().iformat.video.enabled = true; - _awaitingVideo = true; -} - - -void StreamRecorder::setAudioTrack(webrtc::AudioTrackInterface* track) -{ - assert(!_audioTrack); - _audioTrack = track; - _audioTrack->AddSink(this); - _encoder.options().iformat.audio.enabled = true; - _awaitingAudio = true; -} - - -void StreamRecorder::OnFrame(const webrtc::VideoFrame& yuvframe) -{ - LTrace("On video frame: ", yuvframe.width(), 'x', yuvframe.height()) - - // TODO: Recreate encoder context on input stream change - if (_awaitingVideo) { - _awaitingVideo = false; - - auto& ivideo = _encoder.options().iformat.video; - ivideo.width = yuvframe.width(); - ivideo.height = yuvframe.height(); - ivideo.pixelFmt = "yuv420p"; - ivideo.fps = 25; - - if (!_awaitingAudio) - _encoder.init(); - } - - if (_encoder.isActive()) { - // Set AVFrame->data pointers manually so we don't need to copy any data - // or convert the pixel format from YUV to some contiguous format. - auto frame = _encoder.video()->frame; - frame->data[0] = (uint8_t*)yuvframe.video_frame_buffer()->DataY(); - frame->data[1] = (uint8_t*)yuvframe.video_frame_buffer()->DataU(); - frame->data[2] = (uint8_t*)yuvframe.video_frame_buffer()->DataV(); - frame->width = yuvframe.width(); - frame->height = yuvframe.height(); - frame->pts = AV_NOPTS_VALUE; // set by encoder - - // Encode the video frame - _encoder.encodeVideo(frame); - } -} - - -void StreamRecorder::OnData(const void* audio_data, int bits_per_sample, - int sample_rate, size_t number_of_channels, - size_t number_of_frames) -{ - STrace << "On audio frame: " - << "number_of_frames=" << number_of_frames << ", " - << "number_of_channels=" << number_of_channels << ", " - << "sample_rate=" << sample_rate << ", " - << "bits_per_sample=" << bits_per_sample << std::endl; - - // FIXME: For some reason the first couple of samples come though as mono, - // so let's just skip those for now. - if (number_of_channels < 2) { - LWarn("Dropping initial mono samples") - return; - } - - // TODO: Recreate encoder context on input stream change - if (_awaitingAudio) { - _awaitingAudio = false; - - auto& iaudio = _encoder.options().iformat.audio; - iaudio.channels = number_of_channels; - iaudio.sampleRate = sample_rate; - iaudio.sampleFmt = "s16"; - - // WebRTC always sets 16 bits per sample, hence we use the s16 sample - // format. Set an assertion just incase this ever changes or varies. - assert(bits_per_sample == 16); - - if (!_awaitingVideo) - _encoder.init(); - } - - if (_encoder.isActive()) - _encoder.encodeAudio((uint8_t*)audio_data, number_of_frames); -} - - -} } // namespace scy::wrtc - - -/// @\} - - -#endif // HAVE_FFMPEG diff --git a/src/webrtc/src/util.cpp b/src/webrtc/src/util.cpp deleted file mode 100644 index 558eaf34d..000000000 --- a/src/webrtc/src/util.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// @addtogroup webrtc -/// @{ - - -#include "scy/webrtc/util.h" - - -namespace scy { -namespace wrtc { - - -std::vector getVideoCaptureDevices() -{ - std::vector deviceNames; - std::unique_ptr info( - webrtc::VideoCaptureFactory::CreateDeviceInfo()); - if (!info) { - return deviceNames; - } - int numDevicess = info->NumberOfDevices(); - assert(numDevicess > 0); - for (int i = 0; i < numDevicess; ++i) { - const uint32_t kSize = 256; - char name[kSize] = { 0 }; - char id[kSize] = { 0 }; - if (info->GetDeviceName(i, name, kSize, id, kSize) != -1) { - deviceNames.push_back(name); - } - } - return deviceNames; -} - - -// cricket::VideoCapturer* openWebRtcVideoCaptureDevice(const std::string& deviceName) -std::unique_ptr openWebRtcVideoCaptureDevice(const std::string& deviceName) -{ - cricket::WebRtcVideoDeviceCapturerFactory factory; - // std::unique_ptr capturer; - cricket::VideoCapturer* capturer = nullptr; - auto deviceNames = getVideoCaptureDevices(); - for (const auto& name : deviceNames) { - if (name == deviceName) { - return factory.Create(cricket::Device(name, 0)); - } - } - if (!capturer && !deviceNames.empty()) { - return factory.Create(cricket::Device(deviceNames[0], 0)); - } - - assert(0 && "no video devices"); - return nullptr; -} - - - -} } // namespace scy::wrtc - - -/// @\} diff --git a/src/webrtc/src/videopacketsource.cpp b/src/webrtc/src/videopacketsource.cpp deleted file mode 100644 index 49e39a3fb..000000000 --- a/src/webrtc/src/videopacketsource.cpp +++ /dev/null @@ -1,232 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// @addtogroup webrtc -/// @{ - - -#include "scy/webrtc/videopacketsource.h" - -#ifdef HAVE_FFMPEG - -#include "scy/av/ffmpeg.h" -#include "scy/av/videocontext.h" -#include "scy/av/videodecoder.h" -#include "scy/av/fpscounter.h" -#include - - -using std::endl; - -#define SCY_WebRTC_USE_DECODER_PTS 1 - - -namespace scy { -namespace wrtc { - - -VideoPacketSource::VideoPacketSource(int width, int height, int fps, uint32_t fourcc) - : _captureFormat(cricket::VideoFormat(width, height, cricket::VideoFormat::FpsToInterval(fps), fourcc)) - , _rotation(webrtc::kVideoRotation_0) - , _timestampOffset(0) - , _nextTimestamp(0) - , _source(nullptr) -{ - // Default supported formats. Use SetSupportedFormats to over write. - std::vector formats; - formats.push_back(_captureFormat); - SetSupportedFormats(formats); -} - - -VideoPacketSource::VideoPacketSource(const cricket::VideoFormat& captureFormat) - : _captureFormat(captureFormat) - , _rotation(webrtc::kVideoRotation_0) - , _timestampOffset(0) - , _nextTimestamp(0) - , _source(nullptr) -{ - // Default supported formats. Use SetSupportedFormats to over write. - std::vector formats; - formats.push_back(_captureFormat); - SetSupportedFormats(formats); - - // formats.push_back(cricket::VideoFormat(1280, 720, _fpsInterval, _codec)); - // formats.push_back(cricket::VideoFormat(640, 480, _fpsInterval, _codec)); - // formats.push_back(cricket::VideoFormat(320, 240, _fpsInterval, _codec)); - // formats.push_back(cricket::VideoFormat(160, 120, _fpsInterval, _codec)); -} - - -VideoPacketSource::~VideoPacketSource() -{ - LDebug(": Destroying") -} - - -void VideoPacketSource::setPacketSource(PacketSignal* source) -{ - assert(!_source); - // if (_source) - // _source->detach(packetSlot(this, &VideoPacketSource::onVideoCaptured)); - _source = source; -} - - -cricket::CaptureState VideoPacketSource::Start(const cricket::VideoFormat& format) -{ - LDebug("Start") - - // NOTE: The requested format must match the input format until - // we implememnt pixel format conversion and resizing inside - // this class. - RTC_CHECK(_captureFormat == format); - if (capture_state() == cricket::CS_RUNNING) { - LWarn("Start called when it's already started.") - return capture_state(); - } - - if (_source) - _source->attach(packetSlot(this, &VideoPacketSource::onVideoCaptured)); - - SetCaptureFormat(&format); - return cricket::CS_RUNNING; -} - - -void VideoPacketSource::Stop() -{ - LDebug("Stop") - if (capture_state() == cricket::CS_STOPPED) { - LWarn("Stop called when it's already stopped.") - return; - } - - if (_source) - _source->detach(packetSlot(this, &VideoPacketSource::onVideoCaptured)); - - SetCaptureFormat(nullptr); - SetCaptureState(cricket::CS_STOPPED); -} - - -void VideoPacketSource::onVideoCaptured(av::PlanarVideoPacket& packet) -{ - LTrace("On video frame: ", packet.width, 'x', packet.height) - - assert(packet.width > 0); - assert(packet.height > 0); - - int adapted_width; - int adapted_height; - int crop_width; - int crop_height; - int crop_x; - int crop_y; - int64_t timestamp; - int64_t translated_camera_time_us; - -#if SCY_WebRTC_USE_DECODER_PTS - // Set the packet timestamp. - // Since the stream may not be playing from the beginning we - // store the first packet timestamp and subtract it from - // subsequent packets. - if (!_timestampOffset) - _timestampOffset = -packet.time; - timestamp = packet.time + _timestampOffset; - - // NOTE: Initial packet time cannot be 0 for some reason. - // WebRTC sets the initial packet time to 1000 so we will do the same. - timestamp += 1000; -#else - _nextTimestamp += _captureFormat.interval; - timestamp = _nextTimestamp / rtc::kNumNanosecsPerMicrosec; -#endif - - if (!AdaptFrame(packet.width, packet.height, - timestamp, //rtc::TimeNanos() / rtc::kNumNanosecsPerMicrosec, - rtc::TimeMicros(), //0, 0, - &adapted_width, &adapted_height, - &crop_width, &crop_height, - &crop_x, &crop_y, &translated_camera_time_us)) { - LWarn("Adapt frame failed", packet.time) - return; - } - - rtc::scoped_refptr buffer = webrtc::I420Buffer::Copy( - packet.width, packet.height, - packet.buffer[0], packet.linesize[0], - packet.buffer[1], packet.linesize[1], - packet.buffer[2], packet.linesize[2]); - - OnFrame(webrtc::VideoFrame( - buffer, _rotation, - translated_camera_time_us), // timestamp - packet.width, packet.height); - -#if 0 // Old code pre f5297a0 - cricket::CapturedFrame frame; - frame.width = packet.width; - frame.height = packet.height; - frame.pixel_width = 1; - frame.pixel_height = 1; - frame.fourcc = cricket::FOURCC_NV12; - frame.data = packet.data(); - frame.data_size = packet.size(); - // frame.time_stamp = packet.time; // time in microseconds is ignored - - SignalFrameCaptured(this, &frame); -#endif -} - - -bool VideoPacketSource::IsRunning() -{ - return capture_state() == cricket::CS_RUNNING; -} - - -bool VideoPacketSource::GetPreferredFourccs(std::vector* fourccs) -{ - if (!fourccs) - return false; - - // This class does not yet support multiple pixel formats. - fourccs->push_back(_captureFormat.fourcc); - return true; -} - - -bool VideoPacketSource::GetBestCaptureFormat(const cricket::VideoFormat& desired, cricket::VideoFormat* best_format) -{ - if (!best_format) - return false; - - // Use the supported format as the best format. - // best_format->width = desired.width; - // best_format->height = desired.height; - // best_format->fourcc = _codec; - // best_format->interval = desired.interval; - - *best_format = _captureFormat; - return true; -} - - -bool VideoPacketSource::IsScreencast() const -{ - return false; -} - - -} } // namespace scy::wrtc - - -#endif // HAVE_FFMPEG - - -/// @\} diff --git a/src/webrtc/src/yuvframegenerator.cpp b/src/webrtc/src/yuvframegenerator.cpp deleted file mode 100644 index c5fc114d6..000000000 --- a/src/webrtc/src/yuvframegenerator.cpp +++ /dev/null @@ -1,364 +0,0 @@ -/// -// -// LibSourcey -// Copyright (c) 2005, Sourcey -// -// SPDX-License-Identifier: LGPL-2.1+ -// -/// @addtogroup webrtc -/// @{ - - -#include "scy/webrtc/yuvframegenerator.h" - -#include "webrtc/base/thread.h" -#include "webrtc/base/bind.h" -#include "webrtc/base/asyncinvoker.h" - -#include -#include -#include - - -namespace scy { -namespace wrtc { - - -// These values were figured out by trial and error. If you change any -// basic parameters e.g. unit-bar size or bars-x-offset, you may need to change -// background-width/background-height. -const int kBarcodeBackgroundWidth = 160; -const int kBarcodeBackgroundHeight = 100; -const int kBarsXOffset = 12; -const int kBarsYOffset = 4; -const int kUnitBarSize = 2; -const int kBarcodeNormalBarHeight = 80; -const int kBarcodeGuardBarHeight = 96; -const int kBarcodeMaxEncodableDigits = 7; - - -YuvFrameGenerator::YuvFrameGenerator(int width, int height, bool enable_barcode) -{ - width_ = width; - height_ = height; - frame_index_ = 0; - int size = width_ * height_; - int qsize = size / 4; - frame_data_size_ = size + 2 * qsize; - y_data_ = new uint8_t[size]; - u_data_ = new uint8_t[qsize]; - v_data_ = new uint8_t[qsize]; - if (enable_barcode) - { - assert(width_ >= kBarcodeBackgroundWidth); - assert(height_ >= kBarcodeBackgroundHeight); - barcode_start_x_ = 0; - barcode_start_y_ = height_ - kBarcodeBackgroundHeight; - } - else - { - barcode_start_x_ = -1; - barcode_start_y_ = -1; - } -} - - -YuvFrameGenerator::~YuvFrameGenerator() -{ - delete y_data_; - delete u_data_; - delete v_data_; -} - - -void YuvFrameGenerator::GenerateNextFrame(int32_t barcode_value) -{ - int size = width_ * height_; - int qsize = size / 4; - memset(y_data_, 0, size); - memset(u_data_, 0, qsize); - memset(v_data_, 0, qsize); - DrawLandscape(y_data_, width_, height_); - DrawGradientX(u_data_, width_ / 2, height_ / 2); - DrawGradientY(v_data_, width_ / 2, height_ / 2); - DrawMovingLineX(u_data_, width_ / 2, height_ / 2, frame_index_); - DrawMovingLineY(v_data_, width_ / 2, height_ / 2, frame_index_); - DrawBouncingCube(y_data_, width_, height_, frame_index_); - if (barcode_value >= 0) - { - assert(barcode_start_x_ != -1); - DrawBarcode(barcode_value); - } - frame_index_ = (frame_index_ + 1) & 0x0000FFFF; -} - - -void YuvFrameGenerator::CopyInterleavedData(uint8_t* frame_buffer) -{ - int size = width_ * height_; - int qsize = size / 4; - memcpy(frame_buffer, y_data_, size); - frame_buffer += size; - memcpy(frame_buffer, u_data_, qsize); - frame_buffer += qsize; - memcpy(frame_buffer, v_data_, qsize); -} - - -const uint8_t* YuvFrameGenerator::DataY() const -{ - return y_data_; -} - - -const uint8_t* YuvFrameGenerator::DataU() const -{ - return u_data_; -} - - -const uint8_t* YuvFrameGenerator::DataV() const -{ - return v_data_; -} - - -void YuvFrameGenerator::DrawLandscape(uint8_t* p, int w, int h) -{ - int x, y; - for (y = 0; y < h; y++) - { - for (x = 0; x < w; x++) - { - p[x + y * w] = x % (y + 1); - if (((x > w / 2 - (w / 32)) && (x < w / 2 + (w / 32))) - || ((y > h / 2 - (h / 32)) && (y < h / 2 + (h / 32)))) - { - p[x + y * w] = (((x + y) / 8 % 2)) ? 255 : 0; - } - } - } -} - - -void YuvFrameGenerator::DrawGradientX(uint8_t* p, int w, int h) -{ - int x, y; - for (y = 0; y < h; y++) - { - for (x = 0; x < w; x++) - { - p[x + y * w] = (x << 8) / w; - } - } -} - - -void YuvFrameGenerator::DrawGradientY(uint8_t* p, int w, int h) -{ - int x, y; - for (y = 0; y < h; y++) - { - for (x = 0; x < w; x++) - { - p[x + y * w] = (y << 8) / h; - } - } -} - - -void YuvFrameGenerator::DrawMovingLineX(uint8_t* p, int w, int h, int n) -{ - int x, y; - x = n % (w * 2); - if (x >= w) - x = w + w - x - 1; - for (y = 0; y < h; y++) - { - p[x + y * w] = 255; - } -} - - -void YuvFrameGenerator::DrawMovingLineY(uint8_t* p, int w, int h, int n) -{ - int x, y; - y = n % (h * 2); - if (y >= h) - y = h + h - y - 1; - for (x = 0; x < w; x++) - { - p[x + y * w] = 255; - } -} - - -void YuvFrameGenerator::DrawBouncingCube(uint8_t* p, int w, int h, int n) -{ - int x, y, pw, ph, px, py; - pw = w / 16; - ph = h / 16; - px = n % (w * 2); - py = n % (h * 2); - if (px >= w) - px = w + w - px - 1; - if (py >= h) - py = h + h - py - 1; - for (y = py - ph; y < py + ph; y++) - { - if (y >= 0 && y < h) - { - for (x = px - pw; x < px + pw; x++) - { - if (x >= 0 && x < w) - { - p[x + y * w] = 255; - } - } - } - } -} - - -void YuvFrameGenerator::GetBarcodeBounds(int* top, int* left, int* width, int* height) -{ - assert(barcode_start_x_ != -1); - *top = barcode_start_y_; - *left = barcode_start_x_; - *width = kBarcodeBackgroundWidth; - *height = kBarcodeBackgroundHeight; -} - - -static void ComputeBarcodeDigits(uint32_t value, std::stringstream* result) -{ - // Serialize |value| as 7-char string, padded with 0's to the left. - result->width(kBarcodeMaxEncodableDigits); - result->fill('0'); - *result << value; - // Compute check-digit and append to result. Steps described here: - // http://en.wikipedia.org/wiki/European_Article_Number#Calculation_of_checksum_digit - int sum = 0; - for (int pos = 1; pos <= kBarcodeMaxEncodableDigits; pos++) - { - char next_char; - result->get(next_char); - uint8_t digit = next_char - '0'; - sum += digit * (pos % 2 ? 3 : 1); - } - uint8_t check_digit = sum % 10; - if (check_digit != 0) - { - check_digit = 10 - check_digit; - } - *result << static_cast(check_digit); - result->seekg(0); -} - - -void YuvFrameGenerator::DrawBarcode(uint32_t value) -{ - std::stringstream value_str_stream; - ComputeBarcodeDigits(value, &value_str_stream); - // Draw white filled rectangle as background to barcode. - DrawBlockRectangle(y_data_, barcode_start_x_, barcode_start_y_, kBarcodeBackgroundWidth, - kBarcodeBackgroundHeight, width_, 255); - DrawBlockRectangle(u_data_, barcode_start_x_ / 2, barcode_start_y_ / 2, - kBarcodeBackgroundWidth / 2, kBarcodeBackgroundHeight / 2, width_ / 2, 128); - DrawBlockRectangle(v_data_, barcode_start_x_ / 2, barcode_start_y_ / 2, - kBarcodeBackgroundWidth / 2, kBarcodeBackgroundHeight / 2, width_ / 2, 128); - // Scan through chars (digits) and draw black bars. - int x = barcode_start_x_ + kBarsXOffset; - int y = barcode_start_y_ + kBarsYOffset; - int pos = 0; - x = DrawSideGuardBars(x, y, kBarcodeGuardBarHeight); - while (true) - { - char next_char; - value_str_stream.get(next_char); - if (!value_str_stream.good()) - { - break; - } - if (pos++ == 4) - { - x = DrawMiddleGuardBars(x, y, kBarcodeGuardBarHeight); - } - uint8_t digit = next_char - '0'; - x = DrawEanEncodedDigit(digit, x, y, kBarcodeNormalBarHeight, pos > 4); - } - x = DrawSideGuardBars(x, y, kBarcodeGuardBarHeight); -} - - -int YuvFrameGenerator::DrawMiddleGuardBars(int x, int y, int height) -{ - x += kUnitBarSize; - DrawBlockRectangle(y_data_, x, y, kUnitBarSize, height, width_, 0); - x += (kUnitBarSize * 2); - DrawBlockRectangle(y_data_, x, y, kUnitBarSize, height, width_, 0); - return x + (kUnitBarSize * 2); -} - - -int YuvFrameGenerator::DrawSideGuardBars(int x, int y, int height) -{ - DrawBlockRectangle(y_data_, x, y, kUnitBarSize, height, width_, 0); - x += (kUnitBarSize * 2); - DrawBlockRectangle(y_data_, x, y, kUnitBarSize, height, width_, 0); - return x + kUnitBarSize; -} - - -// For each digit: 0-9, |kEanEncodings| contains a bit-mask indicating -// which bars are black (1) and which are blank (0). These are for the L-code -// only. R-code values are bitwise negation of these. Reference: -// http://en.wikipedia.org/wiki/European_Article_Number#Binary_encoding_of_data_digits_into_EAN-13_barcode -// // NOLINT -const uint8_t kEanEncodings[] = { 13, 25, 19, 61, 35, 49, 47, 59, 55, 11 }; - -int YuvFrameGenerator::DrawEanEncodedDigit(int digit, int x, int y, int height, bool flip) -{ - uint8_t ean_encoding = kEanEncodings[digit]; - if (flip) - { - ean_encoding = ~ean_encoding; - } - uint8_t mask = 0x40; - for (int i = 6; i >= 0; i--, mask >>= 1) - { - if (ean_encoding & mask) - { - DrawBlockRectangle(y_data_, x, y, kUnitBarSize, height, width_, 0); - } - x += kUnitBarSize; - } - return x; -} - - -void YuvFrameGenerator::DrawBlockRectangle( - uint8_t* p, int x_start, int y_start, int width, int height, int pitch, uint8_t value) -{ - for (int x = x_start; x < x_start + width; x++) - { - for (int y = y_start; y < y_start + height; y++) - { - p[x + y * pitch] = value; - } - } -} - - -} } // namespace scy::wrtc - - -/* - * Copyright (c) 2010 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ diff --git a/vcpkg/portfile.cmake b/vcpkg/portfile.cmake new file mode 100644 index 000000000..283a878fb --- /dev/null +++ b/vcpkg/portfile.cmake @@ -0,0 +1,23 @@ +vcpkg_from_github( + OUT_SOURCE_PATH SOURCE_PATH + REPO sourcey/libsourcey + REF "v${VERSION}" + SHA512 0 # Update with actual hash when publishing +) + +vcpkg_cmake_configure( + SOURCE_PATH "${SOURCE_PATH}" + OPTIONS + -DBUILD_TESTS=OFF + -DBUILD_SAMPLES=OFF + -DBUILD_APPLICATIONS=OFF +) + +vcpkg_cmake_install() +vcpkg_cmake_config_fixup(CONFIG_PATH lib/cmake/LibSourcey) +vcpkg_fixup_pkgconfig() + +file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/debug/include") +file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/debug/share") + +vcpkg_install_copyright(FILE_LIST "${SOURCE_PATH}/LICENSE.md") diff --git a/vcpkg/vcpkg.json b/vcpkg/vcpkg.json new file mode 100644 index 000000000..a3d73a407 --- /dev/null +++ b/vcpkg/vcpkg.json @@ -0,0 +1,31 @@ +{ + "name": "libsourcey", + "version": "2.0.0", + "description": "C++ Networking Evolved - cross-platform modules for high-performance networked and media streaming applications", + "homepage": "https://github.com/sourcey/libsourcey", + "license": "LGPL-2.1-or-later", + "dependencies": [ + { + "name": "openssl", + "platform": "!windows" + } + ], + "default-features": [ + "core" + ], + "features": { + "core": { + "description": "Core modules (base, net, crypto, http, json)" + }, + "av": { + "description": "Audio/video module (requires FFmpeg)", + "dependencies": [ + { + "name": "ffmpeg", + "default-features": false, + "features": ["avcodec", "avformat", "avutil", "swscale"] + } + ] + } + } +} diff --git a/vendor/dshow/_mingw_dxhelper.h b/vendor/dshow/_mingw_dxhelper.h deleted file mode 100644 index 467f3aa23..000000000 --- a/vendor/dshow/_mingw_dxhelper.h +++ /dev/null @@ -1,110 +0,0 @@ -/** - * This file has no copyright assigned and is placed in the Public Domain. - * This file is part of the w64 mingw-runtime package. - * No warranty is given; refer to the file DISCLAIMER within this package. - */ - -#if defined(_MSC_VER) && !defined(_MSC_EXTENSIONS) -#define NONAMELESSUNION 1 -#endif -#if defined(NONAMELESSSTRUCT) && \ - !defined(NONAMELESSUNION) -#define NONAMELESSUNION 1 -#endif -#if defined(NONAMELESSUNION) && \ - !defined(NONAMELESSSTRUCT) -#define NONAMELESSSTRUCT 1 -#endif - -#ifndef __ANONYMOUS_DEFINED -#define __ANONYMOUS_DEFINED -#if defined(__GNUC__) || defined(__GNUG__) -#define _ANONYMOUS_UNION __extension__ -#define _ANONYMOUS_STRUCT __extension__ -#else -#define _ANONYMOUS_UNION -#define _ANONYMOUS_STRUCT -#endif -#ifndef NONAMELESSUNION -#define _UNION_NAME(x) -#define _STRUCT_NAME(x) -#else /* NONAMELESSUNION */ -#define _UNION_NAME(x) x -#define _STRUCT_NAME(x) x -#endif -#endif /* __ANONYMOUS_DEFINED */ - -#ifndef DUMMYUNIONNAME -# ifdef NONAMELESSUNION -# define DUMMYUNIONNAME u -# define DUMMYUNIONNAME1 u1 /* Wine uses this variant */ -# define DUMMYUNIONNAME2 u2 -# define DUMMYUNIONNAME3 u3 -# define DUMMYUNIONNAME4 u4 -# define DUMMYUNIONNAME5 u5 -# define DUMMYUNIONNAME6 u6 -# define DUMMYUNIONNAME7 u7 -# define DUMMYUNIONNAME8 u8 -# define DUMMYUNIONNAME9 u9 -# else /* NONAMELESSUNION */ -# define DUMMYUNIONNAME -# define DUMMYUNIONNAME1 /* Wine uses this variant */ -# define DUMMYUNIONNAME2 -# define DUMMYUNIONNAME3 -# define DUMMYUNIONNAME4 -# define DUMMYUNIONNAME5 -# define DUMMYUNIONNAME6 -# define DUMMYUNIONNAME7 -# define DUMMYUNIONNAME8 -# define DUMMYUNIONNAME9 -# endif -#endif /* DUMMYUNIONNAME */ - -#if !defined(DUMMYUNIONNAME1) /* MinGW does not define this one */ -# ifdef NONAMELESSUNION -# define DUMMYUNIONNAME1 u1 /* Wine uses this variant */ -# else -# define DUMMYUNIONNAME1 /* Wine uses this variant */ -# endif -#endif /* DUMMYUNIONNAME1 */ - -#ifndef DUMMYSTRUCTNAME -# ifdef NONAMELESSUNION -# define DUMMYSTRUCTNAME s -# define DUMMYSTRUCTNAME1 s1 /* Wine uses this variant */ -# define DUMMYSTRUCTNAME2 s2 -# define DUMMYSTRUCTNAME3 s3 -# define DUMMYSTRUCTNAME4 s4 -# define DUMMYSTRUCTNAME5 s5 -# else -# define DUMMYSTRUCTNAME -# define DUMMYSTRUCTNAME1 /* Wine uses this variant */ -# define DUMMYSTRUCTNAME2 -# define DUMMYSTRUCTNAME3 -# define DUMMYSTRUCTNAME4 -# define DUMMYSTRUCTNAME5 -# endif -#endif /* DUMMYSTRUCTNAME */ - -/* These are for compatibility with the Wine source tree */ - -#ifndef WINELIB_NAME_AW -# ifdef __MINGW_NAME_AW -# define WINELIB_NAME_AW __MINGW_NAME_AW -# else -# ifdef UNICODE -# define WINELIB_NAME_AW(func) func##W -# else -# define WINELIB_NAME_AW(func) func##A -# endif -# endif -#endif /* WINELIB_NAME_AW */ - -#ifndef DECL_WINELIB_TYPE_AW -# ifdef __MINGW_TYPEDEF_AW -# define DECL_WINELIB_TYPE_AW __MINGW_TYPEDEF_AW -# else -# define DECL_WINELIB_TYPE_AW(type) typedef WINELIB_NAME_AW(type) type; -# endif -#endif /* DECL_WINELIB_TYPE_AW */ - diff --git a/vendor/dshow/_mingw_unicode.h b/vendor/dshow/_mingw_unicode.h deleted file mode 100644 index 38334bc71..000000000 --- a/vendor/dshow/_mingw_unicode.h +++ /dev/null @@ -1,33 +0,0 @@ -/** - * This file has no copyright assigned and is placed in the Public Domain. - * This file is part of the w64 mingw-runtime package. - * No warranty is given; refer to the file DISCLAIMER.PD within this package. - */ - -#if !defined(_INC_CRT_UNICODE_MACROS) -/* _INC_CRT_UNICODE_MACROS defined based on UNICODE flag */ - -#if defined(UNICODE) -# define _INC_CRT_UNICODE_MACROS 1 -# define __MINGW_NAME_AW(func) func##W -# define __MINGW_NAME_AW_EXT(func,ext) func##W##ext -# define __MINGW_NAME_UAW(func) func##_W -# define __MINGW_NAME_UAW_EXT(func,ext) func##_W_##ext -# define __MINGW_STRING_AW(str) L##str /* same as TEXT() from winnt.h */ -# define __MINGW_PROCNAMEEXT_AW "W" -#else -# define _INC_CRT_UNICODE_MACROS 2 -# define __MINGW_NAME_AW(func) func##A -# define __MINGW_NAME_AW_EXT(func,ext) func##A##ext -# define __MINGW_NAME_UAW(func) func##_A -# define __MINGW_NAME_UAW_EXT(func,ext) func##_A_##ext -# define __MINGW_STRING_AW(str) str /* same as TEXT() from winnt.h */ -# define __MINGW_PROCNAMEEXT_AW "A" -#endif - -#define __MINGW_TYPEDEF_AW(type) \ - typedef __MINGW_NAME_AW(type) type; -#define __MINGW_TYPEDEF_UAW(type) \ - typedef __MINGW_NAME_UAW(type) type; - -#endif /* !defined(_INC_CRT_UNICODE_MACROS) */ diff --git a/vendor/dshow/amvideo.h b/vendor/dshow/amvideo.h deleted file mode 100644 index 401c10541..000000000 --- a/vendor/dshow/amvideo.h +++ /dev/null @@ -1,1290 +0,0 @@ -/*** Autogenerated by WIDL from amvideo.idl - Do not edit ***/ - -#include -#include - -#ifndef __WIDL_AMVIDEO_H -#define __WIDL_AMVIDEO_H - -/* Forward declarations */ - -#ifndef __IDirectDrawVideo_FWD_DEFINED__ -#define __IDirectDrawVideo_FWD_DEFINED__ -typedef interface IDirectDrawVideo IDirectDrawVideo; -#endif - -#ifndef __IQualProp_FWD_DEFINED__ -#define __IQualProp_FWD_DEFINED__ -typedef interface IQualProp IQualProp; -#endif - -#ifndef __IFullScreenVideo_FWD_DEFINED__ -#define __IFullScreenVideo_FWD_DEFINED__ -typedef interface IFullScreenVideo IFullScreenVideo; -#endif - -#ifndef __IFullScreenVideoEx_FWD_DEFINED__ -#define __IFullScreenVideoEx_FWD_DEFINED__ -typedef interface IFullScreenVideoEx IFullScreenVideoEx; -#endif - -#ifndef __IBaseVideoMixer_FWD_DEFINED__ -#define __IBaseVideoMixer_FWD_DEFINED__ -typedef interface IBaseVideoMixer IBaseVideoMixer; -#endif - -/* Headers for imported files */ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#if 0 -typedef void *LPDIRECTDRAW; -typedef void DDSURFACEDESC; -typedef void DDCAPS; -typedef DWORD RGBQUAD; -typedef LONGLONG REFERENCE_TIME; -typedef struct __WIDL_amvideo_generated_name_00000000 { - DWORD biSize; - LONG biWidth; - LONG biHeight; - WORD biPlanes; - WORD biBitCount; - DWORD biCompression; - DWORD biSizeImage; - LONG biXPelsPerMeter; - LONG biYPelsPerMeter; - DWORD biClrUsed; - DWORD biClrImportant; -} BITMAPINFOHEADER; -typedef struct __WIDL_amvideo_generated_name_00000000 *PBITMAPINFOHEADER; -typedef struct __WIDL_amvideo_generated_name_00000000 *LPBITMAPINFOHEADER; -#endif -#include -#define AMDDS_NONE 0x00 -#define AMDDS_DCIPS 0x01 -#define AMDDS_PS 0x02 -#define AMDDS_RGBOVR 0x04 -#define AMDDS_YUVOVR 0x08 -#define AMDDS_RGBOFF 0x10 -#define AMDDS_YUVOFF 0x20 -#define AMDDS_RGBFLP 0x40 -#define AMDDS_YUVFLP 0x80 -#define AMDDS_ALL 0xFF -#define AMDDS_DEFAULT AMDDS_ALL -#define AMDDS_YUV (AMDDS_YUVOFF | AMDDS_YUVOVR | AMDDS_YUVFLP) -#define AMDDS_RGB (AMDDS_RGBOFF | AMDDS_RGBOVR | AMDDS_RGBFLP) -#define AMDSS_PRIMARY (AMDDS_DCIPS | AMDDS_PS) -/***************************************************************************** - * IDirectDrawVideo interface - */ -#ifndef __IDirectDrawVideo_INTERFACE_DEFINED__ -#define __IDirectDrawVideo_INTERFACE_DEFINED__ - -#if defined(__cplusplus) && !defined(CINTERFACE) -interface IDirectDrawVideo : public IUnknown -{ - virtual HRESULT STDMETHODCALLTYPE GetSwitches( - DWORD *pSwitches) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetSwitches( - DWORD Switches) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetCaps( - DDCAPS *pCaps) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetEmulatedCaps( - DDCAPS *pCaps) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetSurfaceDesc( - DDSURFACEDESC *pSurfaceDesc) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetFourCCCodes( - DWORD *pCount, - DWORD *pCodes) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetDirectDraw( - LPDIRECTDRAW pDirectDraw) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetDirectDraw( - LPDIRECTDRAW *ppDirectDraw) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetSurfaceType( - DWORD *pSurfaceType) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetDefault( - ) = 0; - - virtual HRESULT STDMETHODCALLTYPE UseScanLine( - LONG UseScanLine) = 0; - - virtual HRESULT STDMETHODCALLTYPE CanUseScanLine( - LONG *UseScanLine) = 0; - - virtual HRESULT STDMETHODCALLTYPE UseOverlayStretch( - LONG UseOverlayStretch) = 0; - - virtual HRESULT STDMETHODCALLTYPE CanUseOverlayStretch( - LONG *UseOverlayStretch) = 0; - - virtual HRESULT STDMETHODCALLTYPE UseWhenFullScreen( - LONG UseWhenFullScreen) = 0; - - virtual HRESULT STDMETHODCALLTYPE WillUseFullScreen( - LONG *UseWhenFullScreen) = 0; - -}; -#else -typedef struct IDirectDrawVideoVtbl { - BEGIN_INTERFACE - - /*** IUnknown methods ***/ - HRESULT (STDMETHODCALLTYPE *QueryInterface)( - IDirectDrawVideo* This, - REFIID riid, - void **ppvObject); - - ULONG (STDMETHODCALLTYPE *AddRef)( - IDirectDrawVideo* This); - - ULONG (STDMETHODCALLTYPE *Release)( - IDirectDrawVideo* This); - - /*** IDirectDrawVideo methods ***/ - HRESULT (STDMETHODCALLTYPE *GetSwitches)( - IDirectDrawVideo* This, - DWORD *pSwitches); - - HRESULT (STDMETHODCALLTYPE *SetSwitches)( - IDirectDrawVideo* This, - DWORD Switches); - - HRESULT (STDMETHODCALLTYPE *GetCaps)( - IDirectDrawVideo* This, - DDCAPS *pCaps); - - HRESULT (STDMETHODCALLTYPE *GetEmulatedCaps)( - IDirectDrawVideo* This, - DDCAPS *pCaps); - - HRESULT (STDMETHODCALLTYPE *GetSurfaceDesc)( - IDirectDrawVideo* This, - DDSURFACEDESC *pSurfaceDesc); - - HRESULT (STDMETHODCALLTYPE *GetFourCCCodes)( - IDirectDrawVideo* This, - DWORD *pCount, - DWORD *pCodes); - - HRESULT (STDMETHODCALLTYPE *SetDirectDraw)( - IDirectDrawVideo* This, - LPDIRECTDRAW pDirectDraw); - - HRESULT (STDMETHODCALLTYPE *GetDirectDraw)( - IDirectDrawVideo* This, - LPDIRECTDRAW *ppDirectDraw); - - HRESULT (STDMETHODCALLTYPE *GetSurfaceType)( - IDirectDrawVideo* This, - DWORD *pSurfaceType); - - HRESULT (STDMETHODCALLTYPE *SetDefault)( - IDirectDrawVideo* This); - - HRESULT (STDMETHODCALLTYPE *UseScanLine)( - IDirectDrawVideo* This, - LONG UseScanLine); - - HRESULT (STDMETHODCALLTYPE *CanUseScanLine)( - IDirectDrawVideo* This, - LONG *UseScanLine); - - HRESULT (STDMETHODCALLTYPE *UseOverlayStretch)( - IDirectDrawVideo* This, - LONG UseOverlayStretch); - - HRESULT (STDMETHODCALLTYPE *CanUseOverlayStretch)( - IDirectDrawVideo* This, - LONG *UseOverlayStretch); - - HRESULT (STDMETHODCALLTYPE *UseWhenFullScreen)( - IDirectDrawVideo* This, - LONG UseWhenFullScreen); - - HRESULT (STDMETHODCALLTYPE *WillUseFullScreen)( - IDirectDrawVideo* This, - LONG *UseWhenFullScreen); - - END_INTERFACE -} IDirectDrawVideoVtbl; -interface IDirectDrawVideo { - CONST_VTBL IDirectDrawVideoVtbl* lpVtbl; -}; - -#ifdef COBJMACROS -/*** IUnknown methods ***/ -#define IDirectDrawVideo_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IDirectDrawVideo_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IDirectDrawVideo_Release(This) (This)->lpVtbl->Release(This) -/*** IDirectDrawVideo methods ***/ -#define IDirectDrawVideo_GetSwitches(This,pSwitches) (This)->lpVtbl->GetSwitches(This,pSwitches) -#define IDirectDrawVideo_SetSwitches(This,Switches) (This)->lpVtbl->SetSwitches(This,Switches) -#define IDirectDrawVideo_GetCaps(This,pCaps) (This)->lpVtbl->GetCaps(This,pCaps) -#define IDirectDrawVideo_GetEmulatedCaps(This,pCaps) (This)->lpVtbl->GetEmulatedCaps(This,pCaps) -#define IDirectDrawVideo_GetSurfaceDesc(This,pSurfaceDesc) (This)->lpVtbl->GetSurfaceDesc(This,pSurfaceDesc) -#define IDirectDrawVideo_GetFourCCCodes(This,pCount,pCodes) (This)->lpVtbl->GetFourCCCodes(This,pCount,pCodes) -#define IDirectDrawVideo_SetDirectDraw(This,pDirectDraw) (This)->lpVtbl->SetDirectDraw(This,pDirectDraw) -#define IDirectDrawVideo_GetDirectDraw(This,ppDirectDraw) (This)->lpVtbl->GetDirectDraw(This,ppDirectDraw) -#define IDirectDrawVideo_GetSurfaceType(This,pSurfaceType) (This)->lpVtbl->GetSurfaceType(This,pSurfaceType) -#define IDirectDrawVideo_SetDefault(This) (This)->lpVtbl->SetDefault(This) -#define IDirectDrawVideo_UseScanLine(This,UseScanLine) (This)->lpVtbl->UseScanLine(This,UseScanLine) -#define IDirectDrawVideo_CanUseScanLine(This,UseScanLine) (This)->lpVtbl->CanUseScanLine(This,UseScanLine) -#define IDirectDrawVideo_UseOverlayStretch(This,UseOverlayStretch) (This)->lpVtbl->UseOverlayStretch(This,UseOverlayStretch) -#define IDirectDrawVideo_CanUseOverlayStretch(This,UseOverlayStretch) (This)->lpVtbl->CanUseOverlayStretch(This,UseOverlayStretch) -#define IDirectDrawVideo_UseWhenFullScreen(This,UseWhenFullScreen) (This)->lpVtbl->UseWhenFullScreen(This,UseWhenFullScreen) -#define IDirectDrawVideo_WillUseFullScreen(This,UseWhenFullScreen) (This)->lpVtbl->WillUseFullScreen(This,UseWhenFullScreen) -#endif - -#endif - -HRESULT STDMETHODCALLTYPE IDirectDrawVideo_GetSwitches_Proxy( - IDirectDrawVideo* This, - DWORD *pSwitches); -void __RPC_STUB IDirectDrawVideo_GetSwitches_Stub( - IRpcStubBuffer* This, - IRpcChannelBuffer* pRpcChannelBuffer, - PRPC_MESSAGE pRpcMessage, - DWORD* pdwStubPhase); -HRESULT STDMETHODCALLTYPE IDirectDrawVideo_SetSwitches_Proxy( - IDirectDrawVideo* This, - DWORD Switches); -void __RPC_STUB IDirectDrawVideo_SetSwitches_Stub( - IRpcStubBuffer* This, - IRpcChannelBuffer* pRpcChannelBuffer, - PRPC_MESSAGE pRpcMessage, - DWORD* pdwStubPhase); -HRESULT STDMETHODCALLTYPE IDirectDrawVideo_GetCaps_Proxy( - IDirectDrawVideo* This, - DDCAPS *pCaps); -void __RPC_STUB IDirectDrawVideo_GetCaps_Stub( - IRpcStubBuffer* This, - IRpcChannelBuffer* pRpcChannelBuffer, - PRPC_MESSAGE pRpcMessage, - DWORD* pdwStubPhase); -HRESULT STDMETHODCALLTYPE IDirectDrawVideo_GetEmulatedCaps_Proxy( - IDirectDrawVideo* This, - DDCAPS *pCaps); -void __RPC_STUB IDirectDrawVideo_GetEmulatedCaps_Stub( - IRpcStubBuffer* This, - IRpcChannelBuffer* pRpcChannelBuffer, - PRPC_MESSAGE pRpcMessage, - DWORD* pdwStubPhase); -HRESULT STDMETHODCALLTYPE IDirectDrawVideo_GetSurfaceDesc_Proxy( - IDirectDrawVideo* This, - DDSURFACEDESC *pSurfaceDesc); -void __RPC_STUB IDirectDrawVideo_GetSurfaceDesc_Stub( - IRpcStubBuffer* This, - IRpcChannelBuffer* pRpcChannelBuffer, - PRPC_MESSAGE pRpcMessage, - DWORD* pdwStubPhase); -HRESULT STDMETHODCALLTYPE IDirectDrawVideo_GetFourCCCodes_Proxy( - IDirectDrawVideo* This, - DWORD *pCount, - DWORD *pCodes); -void __RPC_STUB IDirectDrawVideo_GetFourCCCodes_Stub( - IRpcStubBuffer* This, - IRpcChannelBuffer* pRpcChannelBuffer, - PRPC_MESSAGE pRpcMessage, - DWORD* pdwStubPhase); -HRESULT STDMETHODCALLTYPE IDirectDrawVideo_SetDirectDraw_Proxy( - IDirectDrawVideo* This, - LPDIRECTDRAW pDirectDraw); -void __RPC_STUB IDirectDrawVideo_SetDirectDraw_Stub( - IRpcStubBuffer* This, - IRpcChannelBuffer* pRpcChannelBuffer, - PRPC_MESSAGE pRpcMessage, - DWORD* pdwStubPhase); -HRESULT STDMETHODCALLTYPE IDirectDrawVideo_GetDirectDraw_Proxy( - IDirectDrawVideo* This, - LPDIRECTDRAW *ppDirectDraw); -void __RPC_STUB IDirectDrawVideo_GetDirectDraw_Stub( - IRpcStubBuffer* This, - IRpcChannelBuffer* pRpcChannelBuffer, - PRPC_MESSAGE pRpcMessage, - DWORD* pdwStubPhase); -HRESULT STDMETHODCALLTYPE IDirectDrawVideo_GetSurfaceType_Proxy( - IDirectDrawVideo* This, - DWORD *pSurfaceType); -void __RPC_STUB IDirectDrawVideo_GetSurfaceType_Stub( - IRpcStubBuffer* This, - IRpcChannelBuffer* pRpcChannelBuffer, - PRPC_MESSAGE pRpcMessage, - DWORD* pdwStubPhase); -HRESULT STDMETHODCALLTYPE IDirectDrawVideo_SetDefault_Proxy( - IDirectDrawVideo* This); -void __RPC_STUB IDirectDrawVideo_SetDefault_Stub( - IRpcStubBuffer* This, - IRpcChannelBuffer* pRpcChannelBuffer, - PRPC_MESSAGE pRpcMessage, - DWORD* pdwStubPhase); -HRESULT STDMETHODCALLTYPE IDirectDrawVideo_UseScanLine_Proxy( - IDirectDrawVideo* This, - LONG UseScanLine); -void __RPC_STUB IDirectDrawVideo_UseScanLine_Stub( - IRpcStubBuffer* This, - IRpcChannelBuffer* pRpcChannelBuffer, - PRPC_MESSAGE pRpcMessage, - DWORD* pdwStubPhase); -HRESULT STDMETHODCALLTYPE IDirectDrawVideo_CanUseScanLine_Proxy( - IDirectDrawVideo* This, - LONG *UseScanLine); -void __RPC_STUB IDirectDrawVideo_CanUseScanLine_Stub( - IRpcStubBuffer* This, - IRpcChannelBuffer* pRpcChannelBuffer, - PRPC_MESSAGE pRpcMessage, - DWORD* pdwStubPhase); -HRESULT STDMETHODCALLTYPE IDirectDrawVideo_UseOverlayStretch_Proxy( - IDirectDrawVideo* This, - LONG UseOverlayStretch); -void __RPC_STUB IDirectDrawVideo_UseOverlayStretch_Stub( - IRpcStubBuffer* This, - IRpcChannelBuffer* pRpcChannelBuffer, - PRPC_MESSAGE pRpcMessage, - DWORD* pdwStubPhase); -HRESULT STDMETHODCALLTYPE IDirectDrawVideo_CanUseOverlayStretch_Proxy( - IDirectDrawVideo* This, - LONG *UseOverlayStretch); -void __RPC_STUB IDirectDrawVideo_CanUseOverlayStretch_Stub( - IRpcStubBuffer* This, - IRpcChannelBuffer* pRpcChannelBuffer, - PRPC_MESSAGE pRpcMessage, - DWORD* pdwStubPhase); -HRESULT STDMETHODCALLTYPE IDirectDrawVideo_UseWhenFullScreen_Proxy( - IDirectDrawVideo* This, - LONG UseWhenFullScreen); -void __RPC_STUB IDirectDrawVideo_UseWhenFullScreen_Stub( - IRpcStubBuffer* This, - IRpcChannelBuffer* pRpcChannelBuffer, - PRPC_MESSAGE pRpcMessage, - DWORD* pdwStubPhase); -HRESULT STDMETHODCALLTYPE IDirectDrawVideo_WillUseFullScreen_Proxy( - IDirectDrawVideo* This, - LONG *UseWhenFullScreen); -void __RPC_STUB IDirectDrawVideo_WillUseFullScreen_Stub( - IRpcStubBuffer* This, - IRpcChannelBuffer* pRpcChannelBuffer, - PRPC_MESSAGE pRpcMessage, - DWORD* pdwStubPhase); - -#endif /* __IDirectDrawVideo_INTERFACE_DEFINED__ */ - -/***************************************************************************** - * IQualProp interface - */ -#ifndef __IQualProp_INTERFACE_DEFINED__ -#define __IQualProp_INTERFACE_DEFINED__ - -#if defined(__cplusplus) && !defined(CINTERFACE) -interface IQualProp : public IUnknown -{ - virtual HRESULT STDMETHODCALLTYPE get_FramesDroppedInRenderer( - int *pcFrames) = 0; - - virtual HRESULT STDMETHODCALLTYPE get_FramesDrawn( - int *pcFramesDrawn) = 0; - - virtual HRESULT STDMETHODCALLTYPE get_AvgFrameRate( - int *piAvgFrameRate) = 0; - - virtual HRESULT STDMETHODCALLTYPE get_Jitter( - int *iJitter) = 0; - - virtual HRESULT STDMETHODCALLTYPE get_AvgSyncOffset( - int *piAvg) = 0; - - virtual HRESULT STDMETHODCALLTYPE get_DevSyncOffset( - int *piDev) = 0; - -}; -#else -typedef struct IQualPropVtbl { - BEGIN_INTERFACE - - /*** IUnknown methods ***/ - HRESULT (STDMETHODCALLTYPE *QueryInterface)( - IQualProp* This, - REFIID riid, - void **ppvObject); - - ULONG (STDMETHODCALLTYPE *AddRef)( - IQualProp* This); - - ULONG (STDMETHODCALLTYPE *Release)( - IQualProp* This); - - /*** IQualProp methods ***/ - HRESULT (STDMETHODCALLTYPE *get_FramesDroppedInRenderer)( - IQualProp* This, - int *pcFrames); - - HRESULT (STDMETHODCALLTYPE *get_FramesDrawn)( - IQualProp* This, - int *pcFramesDrawn); - - HRESULT (STDMETHODCALLTYPE *get_AvgFrameRate)( - IQualProp* This, - int *piAvgFrameRate); - - HRESULT (STDMETHODCALLTYPE *get_Jitter)( - IQualProp* This, - int *iJitter); - - HRESULT (STDMETHODCALLTYPE *get_AvgSyncOffset)( - IQualProp* This, - int *piAvg); - - HRESULT (STDMETHODCALLTYPE *get_DevSyncOffset)( - IQualProp* This, - int *piDev); - - END_INTERFACE -} IQualPropVtbl; -interface IQualProp { - CONST_VTBL IQualPropVtbl* lpVtbl; -}; - -#ifdef COBJMACROS -/*** IUnknown methods ***/ -#define IQualProp_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IQualProp_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IQualProp_Release(This) (This)->lpVtbl->Release(This) -/*** IQualProp methods ***/ -#define IQualProp_get_FramesDroppedInRenderer(This,pcFrames) (This)->lpVtbl->get_FramesDroppedInRenderer(This,pcFrames) -#define IQualProp_get_FramesDrawn(This,pcFramesDrawn) (This)->lpVtbl->get_FramesDrawn(This,pcFramesDrawn) -#define IQualProp_get_AvgFrameRate(This,piAvgFrameRate) (This)->lpVtbl->get_AvgFrameRate(This,piAvgFrameRate) -#define IQualProp_get_Jitter(This,iJitter) (This)->lpVtbl->get_Jitter(This,iJitter) -#define IQualProp_get_AvgSyncOffset(This,piAvg) (This)->lpVtbl->get_AvgSyncOffset(This,piAvg) -#define IQualProp_get_DevSyncOffset(This,piDev) (This)->lpVtbl->get_DevSyncOffset(This,piDev) -#endif - -#endif - -HRESULT STDMETHODCALLTYPE IQualProp_get_FramesDroppedInRenderer_Proxy( - IQualProp* This, - int *pcFrames); -void __RPC_STUB IQualProp_get_FramesDroppedInRenderer_Stub( - IRpcStubBuffer* This, - IRpcChannelBuffer* pRpcChannelBuffer, - PRPC_MESSAGE pRpcMessage, - DWORD* pdwStubPhase); -HRESULT STDMETHODCALLTYPE IQualProp_get_FramesDrawn_Proxy( - IQualProp* This, - int *pcFramesDrawn); -void __RPC_STUB IQualProp_get_FramesDrawn_Stub( - IRpcStubBuffer* This, - IRpcChannelBuffer* pRpcChannelBuffer, - PRPC_MESSAGE pRpcMessage, - DWORD* pdwStubPhase); -HRESULT STDMETHODCALLTYPE IQualProp_get_AvgFrameRate_Proxy( - IQualProp* This, - int *piAvgFrameRate); -void __RPC_STUB IQualProp_get_AvgFrameRate_Stub( - IRpcStubBuffer* This, - IRpcChannelBuffer* pRpcChannelBuffer, - PRPC_MESSAGE pRpcMessage, - DWORD* pdwStubPhase); -HRESULT STDMETHODCALLTYPE IQualProp_get_Jitter_Proxy( - IQualProp* This, - int *iJitter); -void __RPC_STUB IQualProp_get_Jitter_Stub( - IRpcStubBuffer* This, - IRpcChannelBuffer* pRpcChannelBuffer, - PRPC_MESSAGE pRpcMessage, - DWORD* pdwStubPhase); -HRESULT STDMETHODCALLTYPE IQualProp_get_AvgSyncOffset_Proxy( - IQualProp* This, - int *piAvg); -void __RPC_STUB IQualProp_get_AvgSyncOffset_Stub( - IRpcStubBuffer* This, - IRpcChannelBuffer* pRpcChannelBuffer, - PRPC_MESSAGE pRpcMessage, - DWORD* pdwStubPhase); -HRESULT STDMETHODCALLTYPE IQualProp_get_DevSyncOffset_Proxy( - IQualProp* This, - int *piDev); -void __RPC_STUB IQualProp_get_DevSyncOffset_Stub( - IRpcStubBuffer* This, - IRpcChannelBuffer* pRpcChannelBuffer, - PRPC_MESSAGE pRpcMessage, - DWORD* pdwStubPhase); - -#endif /* __IQualProp_INTERFACE_DEFINED__ */ - -/***************************************************************************** - * IFullScreenVideo interface - */ -#ifndef __IFullScreenVideo_INTERFACE_DEFINED__ -#define __IFullScreenVideo_INTERFACE_DEFINED__ - -#if defined(__cplusplus) && !defined(CINTERFACE) -interface IFullScreenVideo : public IUnknown -{ - virtual HRESULT STDMETHODCALLTYPE CountModes( - LONG *pModes) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetModeInfo( - LONG Mode, - LONG *pWidth, - LONG *pHeight, - LONG *pDepth) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetCurrentMode( - LONG *pMode) = 0; - - virtual HRESULT STDMETHODCALLTYPE IsModeAvailable( - LONG Mode) = 0; - - virtual HRESULT STDMETHODCALLTYPE IsModeEnabled( - LONG Mode) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetEnabled( - LONG Mode, - LONG bEnabled) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetClipFactor( - LONG *pClipFactor) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetClipFactor( - LONG ClipFactor) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetMessageDrain( - HWND hwnd) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetMessageDrain( - HWND *hwnd) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetMonitor( - LONG Monitor) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetMonitor( - LONG *Monitor) = 0; - - virtual HRESULT STDMETHODCALLTYPE HideOnDeactivate( - LONG Hide) = 0; - - virtual HRESULT STDMETHODCALLTYPE IsHideOnDeactivate( - ) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetCaption( - BSTR strCaption) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetCaption( - BSTR *pstrCaption) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetDefault( - ) = 0; - -}; -#else -typedef struct IFullScreenVideoVtbl { - BEGIN_INTERFACE - - /*** IUnknown methods ***/ - HRESULT (STDMETHODCALLTYPE *QueryInterface)( - IFullScreenVideo* This, - REFIID riid, - void **ppvObject); - - ULONG (STDMETHODCALLTYPE *AddRef)( - IFullScreenVideo* This); - - ULONG (STDMETHODCALLTYPE *Release)( - IFullScreenVideo* This); - - /*** IFullScreenVideo methods ***/ - HRESULT (STDMETHODCALLTYPE *CountModes)( - IFullScreenVideo* This, - LONG *pModes); - - HRESULT (STDMETHODCALLTYPE *GetModeInfo)( - IFullScreenVideo* This, - LONG Mode, - LONG *pWidth, - LONG *pHeight, - LONG *pDepth); - - HRESULT (STDMETHODCALLTYPE *GetCurrentMode)( - IFullScreenVideo* This, - LONG *pMode); - - HRESULT (STDMETHODCALLTYPE *IsModeAvailable)( - IFullScreenVideo* This, - LONG Mode); - - HRESULT (STDMETHODCALLTYPE *IsModeEnabled)( - IFullScreenVideo* This, - LONG Mode); - - HRESULT (STDMETHODCALLTYPE *SetEnabled)( - IFullScreenVideo* This, - LONG Mode, - LONG bEnabled); - - HRESULT (STDMETHODCALLTYPE *GetClipFactor)( - IFullScreenVideo* This, - LONG *pClipFactor); - - HRESULT (STDMETHODCALLTYPE *SetClipFactor)( - IFullScreenVideo* This, - LONG ClipFactor); - - HRESULT (STDMETHODCALLTYPE *SetMessageDrain)( - IFullScreenVideo* This, - HWND hwnd); - - HRESULT (STDMETHODCALLTYPE *GetMessageDrain)( - IFullScreenVideo* This, - HWND *hwnd); - - HRESULT (STDMETHODCALLTYPE *SetMonitor)( - IFullScreenVideo* This, - LONG Monitor); - - HRESULT (STDMETHODCALLTYPE *GetMonitor)( - IFullScreenVideo* This, - LONG *Monitor); - - HRESULT (STDMETHODCALLTYPE *HideOnDeactivate)( - IFullScreenVideo* This, - LONG Hide); - - HRESULT (STDMETHODCALLTYPE *IsHideOnDeactivate)( - IFullScreenVideo* This); - - HRESULT (STDMETHODCALLTYPE *SetCaption)( - IFullScreenVideo* This, - BSTR strCaption); - - HRESULT (STDMETHODCALLTYPE *GetCaption)( - IFullScreenVideo* This, - BSTR *pstrCaption); - - HRESULT (STDMETHODCALLTYPE *SetDefault)( - IFullScreenVideo* This); - - END_INTERFACE -} IFullScreenVideoVtbl; -interface IFullScreenVideo { - CONST_VTBL IFullScreenVideoVtbl* lpVtbl; -}; - -#ifdef COBJMACROS -/*** IUnknown methods ***/ -#define IFullScreenVideo_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IFullScreenVideo_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IFullScreenVideo_Release(This) (This)->lpVtbl->Release(This) -/*** IFullScreenVideo methods ***/ -#define IFullScreenVideo_CountModes(This,pModes) (This)->lpVtbl->CountModes(This,pModes) -#define IFullScreenVideo_GetModeInfo(This,Mode,pWidth,pHeight,pDepth) (This)->lpVtbl->GetModeInfo(This,Mode,pWidth,pHeight,pDepth) -#define IFullScreenVideo_GetCurrentMode(This,pMode) (This)->lpVtbl->GetCurrentMode(This,pMode) -#define IFullScreenVideo_IsModeAvailable(This,Mode) (This)->lpVtbl->IsModeAvailable(This,Mode) -#define IFullScreenVideo_IsModeEnabled(This,Mode) (This)->lpVtbl->IsModeEnabled(This,Mode) -#define IFullScreenVideo_SetEnabled(This,Mode,bEnabled) (This)->lpVtbl->SetEnabled(This,Mode,bEnabled) -#define IFullScreenVideo_GetClipFactor(This,pClipFactor) (This)->lpVtbl->GetClipFactor(This,pClipFactor) -#define IFullScreenVideo_SetClipFactor(This,ClipFactor) (This)->lpVtbl->SetClipFactor(This,ClipFactor) -#define IFullScreenVideo_SetMessageDrain(This,hwnd) (This)->lpVtbl->SetMessageDrain(This,hwnd) -#define IFullScreenVideo_GetMessageDrain(This,hwnd) (This)->lpVtbl->GetMessageDrain(This,hwnd) -#define IFullScreenVideo_SetMonitor(This,Monitor) (This)->lpVtbl->SetMonitor(This,Monitor) -#define IFullScreenVideo_GetMonitor(This,Monitor) (This)->lpVtbl->GetMonitor(This,Monitor) -#define IFullScreenVideo_HideOnDeactivate(This,Hide) (This)->lpVtbl->HideOnDeactivate(This,Hide) -#define IFullScreenVideo_IsHideOnDeactivate(This) (This)->lpVtbl->IsHideOnDeactivate(This) -#define IFullScreenVideo_SetCaption(This,strCaption) (This)->lpVtbl->SetCaption(This,strCaption) -#define IFullScreenVideo_GetCaption(This,pstrCaption) (This)->lpVtbl->GetCaption(This,pstrCaption) -#define IFullScreenVideo_SetDefault(This) (This)->lpVtbl->SetDefault(This) -#endif - -#endif - -HRESULT STDMETHODCALLTYPE IFullScreenVideo_CountModes_Proxy( - IFullScreenVideo* This, - LONG *pModes); -void __RPC_STUB IFullScreenVideo_CountModes_Stub( - IRpcStubBuffer* This, - IRpcChannelBuffer* pRpcChannelBuffer, - PRPC_MESSAGE pRpcMessage, - DWORD* pdwStubPhase); -HRESULT STDMETHODCALLTYPE IFullScreenVideo_GetModeInfo_Proxy( - IFullScreenVideo* This, - LONG Mode, - LONG *pWidth, - LONG *pHeight, - LONG *pDepth); -void __RPC_STUB IFullScreenVideo_GetModeInfo_Stub( - IRpcStubBuffer* This, - IRpcChannelBuffer* pRpcChannelBuffer, - PRPC_MESSAGE pRpcMessage, - DWORD* pdwStubPhase); -HRESULT STDMETHODCALLTYPE IFullScreenVideo_GetCurrentMode_Proxy( - IFullScreenVideo* This, - LONG *pMode); -void __RPC_STUB IFullScreenVideo_GetCurrentMode_Stub( - IRpcStubBuffer* This, - IRpcChannelBuffer* pRpcChannelBuffer, - PRPC_MESSAGE pRpcMessage, - DWORD* pdwStubPhase); -HRESULT STDMETHODCALLTYPE IFullScreenVideo_IsModeAvailable_Proxy( - IFullScreenVideo* This, - LONG Mode); -void __RPC_STUB IFullScreenVideo_IsModeAvailable_Stub( - IRpcStubBuffer* This, - IRpcChannelBuffer* pRpcChannelBuffer, - PRPC_MESSAGE pRpcMessage, - DWORD* pdwStubPhase); -HRESULT STDMETHODCALLTYPE IFullScreenVideo_IsModeEnabled_Proxy( - IFullScreenVideo* This, - LONG Mode); -void __RPC_STUB IFullScreenVideo_IsModeEnabled_Stub( - IRpcStubBuffer* This, - IRpcChannelBuffer* pRpcChannelBuffer, - PRPC_MESSAGE pRpcMessage, - DWORD* pdwStubPhase); -HRESULT STDMETHODCALLTYPE IFullScreenVideo_SetEnabled_Proxy( - IFullScreenVideo* This, - LONG Mode, - LONG bEnabled); -void __RPC_STUB IFullScreenVideo_SetEnabled_Stub( - IRpcStubBuffer* This, - IRpcChannelBuffer* pRpcChannelBuffer, - PRPC_MESSAGE pRpcMessage, - DWORD* pdwStubPhase); -HRESULT STDMETHODCALLTYPE IFullScreenVideo_GetClipFactor_Proxy( - IFullScreenVideo* This, - LONG *pClipFactor); -void __RPC_STUB IFullScreenVideo_GetClipFactor_Stub( - IRpcStubBuffer* This, - IRpcChannelBuffer* pRpcChannelBuffer, - PRPC_MESSAGE pRpcMessage, - DWORD* pdwStubPhase); -HRESULT STDMETHODCALLTYPE IFullScreenVideo_SetClipFactor_Proxy( - IFullScreenVideo* This, - LONG ClipFactor); -void __RPC_STUB IFullScreenVideo_SetClipFactor_Stub( - IRpcStubBuffer* This, - IRpcChannelBuffer* pRpcChannelBuffer, - PRPC_MESSAGE pRpcMessage, - DWORD* pdwStubPhase); -HRESULT STDMETHODCALLTYPE IFullScreenVideo_SetMessageDrain_Proxy( - IFullScreenVideo* This, - HWND hwnd); -void __RPC_STUB IFullScreenVideo_SetMessageDrain_Stub( - IRpcStubBuffer* This, - IRpcChannelBuffer* pRpcChannelBuffer, - PRPC_MESSAGE pRpcMessage, - DWORD* pdwStubPhase); -HRESULT STDMETHODCALLTYPE IFullScreenVideo_GetMessageDrain_Proxy( - IFullScreenVideo* This, - HWND *hwnd); -void __RPC_STUB IFullScreenVideo_GetMessageDrain_Stub( - IRpcStubBuffer* This, - IRpcChannelBuffer* pRpcChannelBuffer, - PRPC_MESSAGE pRpcMessage, - DWORD* pdwStubPhase); -HRESULT STDMETHODCALLTYPE IFullScreenVideo_SetMonitor_Proxy( - IFullScreenVideo* This, - LONG Monitor); -void __RPC_STUB IFullScreenVideo_SetMonitor_Stub( - IRpcStubBuffer* This, - IRpcChannelBuffer* pRpcChannelBuffer, - PRPC_MESSAGE pRpcMessage, - DWORD* pdwStubPhase); -HRESULT STDMETHODCALLTYPE IFullScreenVideo_GetMonitor_Proxy( - IFullScreenVideo* This, - LONG *Monitor); -void __RPC_STUB IFullScreenVideo_GetMonitor_Stub( - IRpcStubBuffer* This, - IRpcChannelBuffer* pRpcChannelBuffer, - PRPC_MESSAGE pRpcMessage, - DWORD* pdwStubPhase); -HRESULT STDMETHODCALLTYPE IFullScreenVideo_HideOnDeactivate_Proxy( - IFullScreenVideo* This, - LONG Hide); -void __RPC_STUB IFullScreenVideo_HideOnDeactivate_Stub( - IRpcStubBuffer* This, - IRpcChannelBuffer* pRpcChannelBuffer, - PRPC_MESSAGE pRpcMessage, - DWORD* pdwStubPhase); -HRESULT STDMETHODCALLTYPE IFullScreenVideo_IsHideOnDeactivate_Proxy( - IFullScreenVideo* This); -void __RPC_STUB IFullScreenVideo_IsHideOnDeactivate_Stub( - IRpcStubBuffer* This, - IRpcChannelBuffer* pRpcChannelBuffer, - PRPC_MESSAGE pRpcMessage, - DWORD* pdwStubPhase); -HRESULT STDMETHODCALLTYPE IFullScreenVideo_SetCaption_Proxy( - IFullScreenVideo* This, - BSTR strCaption); -void __RPC_STUB IFullScreenVideo_SetCaption_Stub( - IRpcStubBuffer* This, - IRpcChannelBuffer* pRpcChannelBuffer, - PRPC_MESSAGE pRpcMessage, - DWORD* pdwStubPhase); -HRESULT STDMETHODCALLTYPE IFullScreenVideo_GetCaption_Proxy( - IFullScreenVideo* This, - BSTR *pstrCaption); -void __RPC_STUB IFullScreenVideo_GetCaption_Stub( - IRpcStubBuffer* This, - IRpcChannelBuffer* pRpcChannelBuffer, - PRPC_MESSAGE pRpcMessage, - DWORD* pdwStubPhase); -HRESULT STDMETHODCALLTYPE IFullScreenVideo_SetDefault_Proxy( - IFullScreenVideo* This); -void __RPC_STUB IFullScreenVideo_SetDefault_Stub( - IRpcStubBuffer* This, - IRpcChannelBuffer* pRpcChannelBuffer, - PRPC_MESSAGE pRpcMessage, - DWORD* pdwStubPhase); - -#endif /* __IFullScreenVideo_INTERFACE_DEFINED__ */ - -/***************************************************************************** - * IFullScreenVideoEx interface - */ -#ifndef __IFullScreenVideoEx_INTERFACE_DEFINED__ -#define __IFullScreenVideoEx_INTERFACE_DEFINED__ - -#if defined(__cplusplus) && !defined(CINTERFACE) -interface IFullScreenVideoEx : public IFullScreenVideo -{ - virtual HRESULT STDMETHODCALLTYPE SetAcceleratorTable( - HWND hwnd, - HACCEL hAccel) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetAcceleratorTable( - HWND *phwnd, - HACCEL *phAccel) = 0; - - virtual HRESULT STDMETHODCALLTYPE KeepPixelAspectRatio( - LONG KeepAspect) = 0; - - virtual HRESULT STDMETHODCALLTYPE IsKeepPixelAspectRatio( - LONG *pKeepAspect) = 0; - -}; -#else -typedef struct IFullScreenVideoExVtbl { - BEGIN_INTERFACE - - /*** IUnknown methods ***/ - HRESULT (STDMETHODCALLTYPE *QueryInterface)( - IFullScreenVideoEx* This, - REFIID riid, - void **ppvObject); - - ULONG (STDMETHODCALLTYPE *AddRef)( - IFullScreenVideoEx* This); - - ULONG (STDMETHODCALLTYPE *Release)( - IFullScreenVideoEx* This); - - /*** IFullScreenVideo methods ***/ - HRESULT (STDMETHODCALLTYPE *CountModes)( - IFullScreenVideoEx* This, - LONG *pModes); - - HRESULT (STDMETHODCALLTYPE *GetModeInfo)( - IFullScreenVideoEx* This, - LONG Mode, - LONG *pWidth, - LONG *pHeight, - LONG *pDepth); - - HRESULT (STDMETHODCALLTYPE *GetCurrentMode)( - IFullScreenVideoEx* This, - LONG *pMode); - - HRESULT (STDMETHODCALLTYPE *IsModeAvailable)( - IFullScreenVideoEx* This, - LONG Mode); - - HRESULT (STDMETHODCALLTYPE *IsModeEnabled)( - IFullScreenVideoEx* This, - LONG Mode); - - HRESULT (STDMETHODCALLTYPE *SetEnabled)( - IFullScreenVideoEx* This, - LONG Mode, - LONG bEnabled); - - HRESULT (STDMETHODCALLTYPE *GetClipFactor)( - IFullScreenVideoEx* This, - LONG *pClipFactor); - - HRESULT (STDMETHODCALLTYPE *SetClipFactor)( - IFullScreenVideoEx* This, - LONG ClipFactor); - - HRESULT (STDMETHODCALLTYPE *SetMessageDrain)( - IFullScreenVideoEx* This, - HWND hwnd); - - HRESULT (STDMETHODCALLTYPE *GetMessageDrain)( - IFullScreenVideoEx* This, - HWND *hwnd); - - HRESULT (STDMETHODCALLTYPE *SetMonitor)( - IFullScreenVideoEx* This, - LONG Monitor); - - HRESULT (STDMETHODCALLTYPE *GetMonitor)( - IFullScreenVideoEx* This, - LONG *Monitor); - - HRESULT (STDMETHODCALLTYPE *HideOnDeactivate)( - IFullScreenVideoEx* This, - LONG Hide); - - HRESULT (STDMETHODCALLTYPE *IsHideOnDeactivate)( - IFullScreenVideoEx* This); - - HRESULT (STDMETHODCALLTYPE *SetCaption)( - IFullScreenVideoEx* This, - BSTR strCaption); - - HRESULT (STDMETHODCALLTYPE *GetCaption)( - IFullScreenVideoEx* This, - BSTR *pstrCaption); - - HRESULT (STDMETHODCALLTYPE *SetDefault)( - IFullScreenVideoEx* This); - - /*** IFullScreenVideoEx methods ***/ - HRESULT (STDMETHODCALLTYPE *SetAcceleratorTable)( - IFullScreenVideoEx* This, - HWND hwnd, - HACCEL hAccel); - - HRESULT (STDMETHODCALLTYPE *GetAcceleratorTable)( - IFullScreenVideoEx* This, - HWND *phwnd, - HACCEL *phAccel); - - HRESULT (STDMETHODCALLTYPE *KeepPixelAspectRatio)( - IFullScreenVideoEx* This, - LONG KeepAspect); - - HRESULT (STDMETHODCALLTYPE *IsKeepPixelAspectRatio)( - IFullScreenVideoEx* This, - LONG *pKeepAspect); - - END_INTERFACE -} IFullScreenVideoExVtbl; -interface IFullScreenVideoEx { - CONST_VTBL IFullScreenVideoExVtbl* lpVtbl; -}; - -#ifdef COBJMACROS -/*** IUnknown methods ***/ -#define IFullScreenVideoEx_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IFullScreenVideoEx_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IFullScreenVideoEx_Release(This) (This)->lpVtbl->Release(This) -/*** IFullScreenVideo methods ***/ -#define IFullScreenVideoEx_CountModes(This,pModes) (This)->lpVtbl->CountModes(This,pModes) -#define IFullScreenVideoEx_GetModeInfo(This,Mode,pWidth,pHeight,pDepth) (This)->lpVtbl->GetModeInfo(This,Mode,pWidth,pHeight,pDepth) -#define IFullScreenVideoEx_GetCurrentMode(This,pMode) (This)->lpVtbl->GetCurrentMode(This,pMode) -#define IFullScreenVideoEx_IsModeAvailable(This,Mode) (This)->lpVtbl->IsModeAvailable(This,Mode) -#define IFullScreenVideoEx_IsModeEnabled(This,Mode) (This)->lpVtbl->IsModeEnabled(This,Mode) -#define IFullScreenVideoEx_SetEnabled(This,Mode,bEnabled) (This)->lpVtbl->SetEnabled(This,Mode,bEnabled) -#define IFullScreenVideoEx_GetClipFactor(This,pClipFactor) (This)->lpVtbl->GetClipFactor(This,pClipFactor) -#define IFullScreenVideoEx_SetClipFactor(This,ClipFactor) (This)->lpVtbl->SetClipFactor(This,ClipFactor) -#define IFullScreenVideoEx_SetMessageDrain(This,hwnd) (This)->lpVtbl->SetMessageDrain(This,hwnd) -#define IFullScreenVideoEx_GetMessageDrain(This,hwnd) (This)->lpVtbl->GetMessageDrain(This,hwnd) -#define IFullScreenVideoEx_SetMonitor(This,Monitor) (This)->lpVtbl->SetMonitor(This,Monitor) -#define IFullScreenVideoEx_GetMonitor(This,Monitor) (This)->lpVtbl->GetMonitor(This,Monitor) -#define IFullScreenVideoEx_HideOnDeactivate(This,Hide) (This)->lpVtbl->HideOnDeactivate(This,Hide) -#define IFullScreenVideoEx_IsHideOnDeactivate(This) (This)->lpVtbl->IsHideOnDeactivate(This) -#define IFullScreenVideoEx_SetCaption(This,strCaption) (This)->lpVtbl->SetCaption(This,strCaption) -#define IFullScreenVideoEx_GetCaption(This,pstrCaption) (This)->lpVtbl->GetCaption(This,pstrCaption) -#define IFullScreenVideoEx_SetDefault(This) (This)->lpVtbl->SetDefault(This) -/*** IFullScreenVideoEx methods ***/ -#define IFullScreenVideoEx_SetAcceleratorTable(This,hwnd,hAccel) (This)->lpVtbl->SetAcceleratorTable(This,hwnd,hAccel) -#define IFullScreenVideoEx_GetAcceleratorTable(This,phwnd,phAccel) (This)->lpVtbl->GetAcceleratorTable(This,phwnd,phAccel) -#define IFullScreenVideoEx_KeepPixelAspectRatio(This,KeepAspect) (This)->lpVtbl->KeepPixelAspectRatio(This,KeepAspect) -#define IFullScreenVideoEx_IsKeepPixelAspectRatio(This,pKeepAspect) (This)->lpVtbl->IsKeepPixelAspectRatio(This,pKeepAspect) -#endif - -#endif - -HRESULT STDMETHODCALLTYPE IFullScreenVideoEx_SetAcceleratorTable_Proxy( - IFullScreenVideoEx* This, - HWND hwnd, - HACCEL hAccel); -void __RPC_STUB IFullScreenVideoEx_SetAcceleratorTable_Stub( - IRpcStubBuffer* This, - IRpcChannelBuffer* pRpcChannelBuffer, - PRPC_MESSAGE pRpcMessage, - DWORD* pdwStubPhase); -HRESULT STDMETHODCALLTYPE IFullScreenVideoEx_GetAcceleratorTable_Proxy( - IFullScreenVideoEx* This, - HWND *phwnd, - HACCEL *phAccel); -void __RPC_STUB IFullScreenVideoEx_GetAcceleratorTable_Stub( - IRpcStubBuffer* This, - IRpcChannelBuffer* pRpcChannelBuffer, - PRPC_MESSAGE pRpcMessage, - DWORD* pdwStubPhase); -HRESULT STDMETHODCALLTYPE IFullScreenVideoEx_KeepPixelAspectRatio_Proxy( - IFullScreenVideoEx* This, - LONG KeepAspect); -void __RPC_STUB IFullScreenVideoEx_KeepPixelAspectRatio_Stub( - IRpcStubBuffer* This, - IRpcChannelBuffer* pRpcChannelBuffer, - PRPC_MESSAGE pRpcMessage, - DWORD* pdwStubPhase); -HRESULT STDMETHODCALLTYPE IFullScreenVideoEx_IsKeepPixelAspectRatio_Proxy( - IFullScreenVideoEx* This, - LONG *pKeepAspect); -void __RPC_STUB IFullScreenVideoEx_IsKeepPixelAspectRatio_Stub( - IRpcStubBuffer* This, - IRpcChannelBuffer* pRpcChannelBuffer, - PRPC_MESSAGE pRpcMessage, - DWORD* pdwStubPhase); - -#endif /* __IFullScreenVideoEx_INTERFACE_DEFINED__ */ - -/***************************************************************************** - * IBaseVideoMixer interface - */ -#ifndef __IBaseVideoMixer_INTERFACE_DEFINED__ -#define __IBaseVideoMixer_INTERFACE_DEFINED__ - -#if defined(__cplusplus) && !defined(CINTERFACE) -interface IBaseVideoMixer : public IUnknown -{ - virtual HRESULT STDMETHODCALLTYPE SetLeadPin( - int iPin) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetLeadPin( - int *piPin) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetInputPinCount( - int *piPinCount) = 0; - - virtual HRESULT STDMETHODCALLTYPE IsUsingClock( - int *pbValue) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetUsingClock( - int bValue) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetClockPeriod( - int *pbValue) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetClockPeriod( - int bValue) = 0; - -}; -#else -typedef struct IBaseVideoMixerVtbl { - BEGIN_INTERFACE - - /*** IUnknown methods ***/ - HRESULT (STDMETHODCALLTYPE *QueryInterface)( - IBaseVideoMixer* This, - REFIID riid, - void **ppvObject); - - ULONG (STDMETHODCALLTYPE *AddRef)( - IBaseVideoMixer* This); - - ULONG (STDMETHODCALLTYPE *Release)( - IBaseVideoMixer* This); - - /*** IBaseVideoMixer methods ***/ - HRESULT (STDMETHODCALLTYPE *SetLeadPin)( - IBaseVideoMixer* This, - int iPin); - - HRESULT (STDMETHODCALLTYPE *GetLeadPin)( - IBaseVideoMixer* This, - int *piPin); - - HRESULT (STDMETHODCALLTYPE *GetInputPinCount)( - IBaseVideoMixer* This, - int *piPinCount); - - HRESULT (STDMETHODCALLTYPE *IsUsingClock)( - IBaseVideoMixer* This, - int *pbValue); - - HRESULT (STDMETHODCALLTYPE *SetUsingClock)( - IBaseVideoMixer* This, - int bValue); - - HRESULT (STDMETHODCALLTYPE *GetClockPeriod)( - IBaseVideoMixer* This, - int *pbValue); - - HRESULT (STDMETHODCALLTYPE *SetClockPeriod)( - IBaseVideoMixer* This, - int bValue); - - END_INTERFACE -} IBaseVideoMixerVtbl; -interface IBaseVideoMixer { - CONST_VTBL IBaseVideoMixerVtbl* lpVtbl; -}; - -#ifdef COBJMACROS -/*** IUnknown methods ***/ -#define IBaseVideoMixer_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IBaseVideoMixer_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IBaseVideoMixer_Release(This) (This)->lpVtbl->Release(This) -/*** IBaseVideoMixer methods ***/ -#define IBaseVideoMixer_SetLeadPin(This,iPin) (This)->lpVtbl->SetLeadPin(This,iPin) -#define IBaseVideoMixer_GetLeadPin(This,piPin) (This)->lpVtbl->GetLeadPin(This,piPin) -#define IBaseVideoMixer_GetInputPinCount(This,piPinCount) (This)->lpVtbl->GetInputPinCount(This,piPinCount) -#define IBaseVideoMixer_IsUsingClock(This,pbValue) (This)->lpVtbl->IsUsingClock(This,pbValue) -#define IBaseVideoMixer_SetUsingClock(This,bValue) (This)->lpVtbl->SetUsingClock(This,bValue) -#define IBaseVideoMixer_GetClockPeriod(This,pbValue) (This)->lpVtbl->GetClockPeriod(This,pbValue) -#define IBaseVideoMixer_SetClockPeriod(This,bValue) (This)->lpVtbl->SetClockPeriod(This,bValue) -#endif - -#endif - -HRESULT STDMETHODCALLTYPE IBaseVideoMixer_SetLeadPin_Proxy( - IBaseVideoMixer* This, - int iPin); -void __RPC_STUB IBaseVideoMixer_SetLeadPin_Stub( - IRpcStubBuffer* This, - IRpcChannelBuffer* pRpcChannelBuffer, - PRPC_MESSAGE pRpcMessage, - DWORD* pdwStubPhase); -HRESULT STDMETHODCALLTYPE IBaseVideoMixer_GetLeadPin_Proxy( - IBaseVideoMixer* This, - int *piPin); -void __RPC_STUB IBaseVideoMixer_GetLeadPin_Stub( - IRpcStubBuffer* This, - IRpcChannelBuffer* pRpcChannelBuffer, - PRPC_MESSAGE pRpcMessage, - DWORD* pdwStubPhase); -HRESULT STDMETHODCALLTYPE IBaseVideoMixer_GetInputPinCount_Proxy( - IBaseVideoMixer* This, - int *piPinCount); -void __RPC_STUB IBaseVideoMixer_GetInputPinCount_Stub( - IRpcStubBuffer* This, - IRpcChannelBuffer* pRpcChannelBuffer, - PRPC_MESSAGE pRpcMessage, - DWORD* pdwStubPhase); -HRESULT STDMETHODCALLTYPE IBaseVideoMixer_IsUsingClock_Proxy( - IBaseVideoMixer* This, - int *pbValue); -void __RPC_STUB IBaseVideoMixer_IsUsingClock_Stub( - IRpcStubBuffer* This, - IRpcChannelBuffer* pRpcChannelBuffer, - PRPC_MESSAGE pRpcMessage, - DWORD* pdwStubPhase); -HRESULT STDMETHODCALLTYPE IBaseVideoMixer_SetUsingClock_Proxy( - IBaseVideoMixer* This, - int bValue); -void __RPC_STUB IBaseVideoMixer_SetUsingClock_Stub( - IRpcStubBuffer* This, - IRpcChannelBuffer* pRpcChannelBuffer, - PRPC_MESSAGE pRpcMessage, - DWORD* pdwStubPhase); -HRESULT STDMETHODCALLTYPE IBaseVideoMixer_GetClockPeriod_Proxy( - IBaseVideoMixer* This, - int *pbValue); -void __RPC_STUB IBaseVideoMixer_GetClockPeriod_Stub( - IRpcStubBuffer* This, - IRpcChannelBuffer* pRpcChannelBuffer, - PRPC_MESSAGE pRpcMessage, - DWORD* pdwStubPhase); -HRESULT STDMETHODCALLTYPE IBaseVideoMixer_SetClockPeriod_Proxy( - IBaseVideoMixer* This, - int bValue); -void __RPC_STUB IBaseVideoMixer_SetClockPeriod_Stub( - IRpcStubBuffer* This, - IRpcChannelBuffer* pRpcChannelBuffer, - PRPC_MESSAGE pRpcMessage, - DWORD* pdwStubPhase); - -#endif /* __IBaseVideoMixer_INTERFACE_DEFINED__ */ - -#define iPALETTE_COLORS 256 -#define iEGA_COLORS 16 -#define iMASK_COLORS 3 -#define iTRUECOLOR 16 -#define iRED 0 -#define iGREEN 1 -#define iBLUE 2 -#define iPALETTE 8 -#define iMAXBITS 8 -typedef struct tag_TRUECOLORINFO { - DWORD dwBitMasks[3]; - RGBQUAD bmiColors[256]; -} TRUECOLORINFO; -typedef struct tagVIDEOINFOHEADER { - RECT rcSource; - RECT rcTarget; - DWORD dwBitRate; - DWORD dwBitErrorRate; - REFERENCE_TIME AvgTimePerFrame; - BITMAPINFOHEADER bmiHeader; -} VIDEOINFOHEADER; -typedef struct tagVIDEOINFO { - RECT rcSource; - RECT rcTarget; - DWORD dwBitRate; - DWORD dwBitErrorRate; - REFERENCE_TIME AvgTimePerFrame; - BITMAPINFOHEADER bmiHeader; - union { - RGBQUAD bmiColors[256]; - DWORD dwBitMasks[3]; - TRUECOLORINFO TrueColorInfo; - } DUMMYUNIONNAME; -} VIDEOINFO; -typedef struct tagMPEG1VIDEOINFO { - VIDEOINFOHEADER hdr; - DWORD dwStartTimeCode; - DWORD cbSequenceHeader; - BYTE bSequenceHeader[1]; -} MPEG1VIDEOINFO; -#define MAX_SIZE_MPEG1_SEQUENCE_INFO 140 -#define MPEG1_SEQUENCE_INFO(pv) ((const BYTE *)(pv)->bSequenceHeader) -typedef struct tagAnalogVideoInfo { - RECT rcSource; - RECT rcTarget; - DWORD dwActiveWidth; - DWORD dwActiveHeight; - REFERENCE_TIME AvgTimePerFrame; -} ANALOGVIDEOINFO; -typedef enum __WIDL_amvideo_generated_name_00000001 { - AM_PROPERTY_FRAMESTEP_STEP = 0x1, - AM_PROPERTY_FRAMESTEP_CANCEL = 0x2, - AM_PROPERTY_FRAMESTEP_CANSTEP = 0x3, - AM_PROPERTY_FRAMESTEP_CANSTEPMULTIPLE = 0x4 -} AM_PROPERTY_FRAMESTEP; -typedef struct _AM_FRAMESTEP_STEP { - DWORD dwFramesToStep; -} AM_FRAMESTEP_STEP; -/* Begin additional prototypes for all interfaces */ - -ULONG __RPC_USER HWND_UserSize (ULONG *, ULONG, HWND *); -unsigned char * __RPC_USER HWND_UserMarshal (ULONG *, unsigned char *, HWND *); -unsigned char * __RPC_USER HWND_UserUnmarshal(ULONG *, unsigned char *, HWND *); -void __RPC_USER HWND_UserFree (ULONG *, HWND *); -ULONG __RPC_USER BSTR_UserSize (ULONG *, ULONG, BSTR *); -unsigned char * __RPC_USER BSTR_UserMarshal (ULONG *, unsigned char *, BSTR *); -unsigned char * __RPC_USER BSTR_UserUnmarshal(ULONG *, unsigned char *, BSTR *); -void __RPC_USER BSTR_UserFree (ULONG *, BSTR *); - -/* End additional prototypes */ - -#ifdef __cplusplus -} -#endif - -#endif /* __WIDL_AMVIDEO_H */ diff --git a/vendor/dshow/audevcod.h b/vendor/dshow/audevcod.h deleted file mode 100644 index 8d741e08b..000000000 --- a/vendor/dshow/audevcod.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef _AUDEVCOD_H -#define _AUDEVCOD_H -#if __GNUC__ >=3 -#pragma GCC system_header -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum _tagSND_DEVICE_ERROR { - SNDDEV_ERROR_Open = 1, - SNDDEV_ERROR_Close = 2, - SNDDEV_ERROR_GetCaps = 3, - SNDDEV_ERROR_PrepareHeader = 4, - SNDDEV_ERROR_UnprepareHeader = 5, - SNDDEV_ERROR_Reset = 6, - SNDDEV_ERROR_Restart = 7, - SNDDEV_ERROR_GetPosition = 8, - SNDDEV_ERROR_Write = 9, - SNDDEV_ERROR_Pause = 10, - SNDDEV_ERROR_Stop = 11, - SNDDEV_ERROR_Start = 12, - SNDDEV_ERROR_AddBuffer = 13, - SNDDEV_ERROR_Query = 14 -} SNDDEV_ERR; - -#ifdef __cplusplus -} -#endif -#endif diff --git a/vendor/dshow/bdatypes.h b/vendor/dshow/bdatypes.h deleted file mode 100644 index d42dceb2e..000000000 --- a/vendor/dshow/bdatypes.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef _BDATYPES_H -#define _BDATYPES_H -#if __GNUC__ >= 3 -#pragma GCC system_header -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/*--- DirectShow Reference - DirectShow Enumerated Types */ -typedef enum { - MEDIA_TRANSPORT_PACKET, - MEDIA_ELEMENTARY_STREAM, - MEDIA_MPEG2_PSI, - MEDIA_TRANSPORT_PAYLOAD -} MEDIA_SAMPLE_CONTENT; -/*--- DirectShow Reference - DirectShow Structures */ -typedef struct { - DWORD dwOffset; - DWORD dwPacketLength; - DWORD dwStride; -} MPEG2_TRANSPORT_STRIDE; -typedef struct { - ULONG ulPID; - MEDIA_SAMPLE_CONTENT MediaSampleContent ; -} PID_MAP; - -#ifdef __cplusplus -} -#endif -#endif diff --git a/vendor/dshow/control.h b/vendor/dshow/control.h deleted file mode 100644 index b012239e1..000000000 --- a/vendor/dshow/control.h +++ /dev/null @@ -1,1467 +0,0 @@ -/** - * This file has no copyright assigned and is placed in the Public Domain. - * This file is part of the w64 mingw-runtime package. - * No warranty is given; refer to the file DISCLAIMER.PD within this package. - */ -#ifndef __REQUIRED_RPCNDR_H_VERSION__ -#define __REQUIRED_RPCNDR_H_VERSION__ 475 -#endif - -#include "rpc.h" -#include "rpcndr.h" - -#ifndef __RPCNDR_H_VERSION__ -#error this stub requires an updated version of -#endif - -#ifndef __control_h__ -#define __control_h__ - -#ifndef __IAMCollection_FWD_DEFINED__ -#define __IAMCollection_FWD_DEFINED__ -typedef struct IAMCollection IAMCollection; -#endif - -#ifndef __IMediaControl_FWD_DEFINED__ -#define __IMediaControl_FWD_DEFINED__ -typedef struct IMediaControl IMediaControl; -#endif - -#ifndef __IMediaEvent_FWD_DEFINED__ -#define __IMediaEvent_FWD_DEFINED__ -typedef struct IMediaEvent IMediaEvent; -#endif - -#ifndef __IMediaEventEx_FWD_DEFINED__ -#define __IMediaEventEx_FWD_DEFINED__ -typedef struct IMediaEventEx IMediaEventEx; -#endif - -#ifndef __IMediaPosition_FWD_DEFINED__ -#define __IMediaPosition_FWD_DEFINED__ -typedef struct IMediaPosition IMediaPosition; -#endif - -#ifndef __IBasicAudio_FWD_DEFINED__ -#define __IBasicAudio_FWD_DEFINED__ -typedef struct IBasicAudio IBasicAudio; -#endif - -#ifndef __IVideoWindow_FWD_DEFINED__ -#define __IVideoWindow_FWD_DEFINED__ -typedef struct IVideoWindow IVideoWindow; -#endif - -#ifndef __IBasicVideo_FWD_DEFINED__ -#define __IBasicVideo_FWD_DEFINED__ -typedef struct IBasicVideo IBasicVideo; -#endif - -#ifndef __IBasicVideo2_FWD_DEFINED__ -#define __IBasicVideo2_FWD_DEFINED__ -typedef struct IBasicVideo2 IBasicVideo2; -#endif - -#ifndef __IDeferredCommand_FWD_DEFINED__ -#define __IDeferredCommand_FWD_DEFINED__ -typedef struct IDeferredCommand IDeferredCommand; -#endif - -#ifndef __IQueueCommand_FWD_DEFINED__ -#define __IQueueCommand_FWD_DEFINED__ -typedef struct IQueueCommand IQueueCommand; -#endif - -#ifndef __FilgraphManager_FWD_DEFINED__ -#define __FilgraphManager_FWD_DEFINED__ - -#ifdef __cplusplus -typedef class FilgraphManager FilgraphManager; -#else -typedef struct FilgraphManager FilgraphManager; -#endif -#endif - -#ifndef __IFilterInfo_FWD_DEFINED__ -#define __IFilterInfo_FWD_DEFINED__ -typedef struct IFilterInfo IFilterInfo; -#endif - -#ifndef __IRegFilterInfo_FWD_DEFINED__ -#define __IRegFilterInfo_FWD_DEFINED__ -typedef struct IRegFilterInfo IRegFilterInfo; -#endif - -#ifndef __IMediaTypeInfo_FWD_DEFINED__ -#define __IMediaTypeInfo_FWD_DEFINED__ -typedef struct IMediaTypeInfo IMediaTypeInfo; -#endif - -#ifndef __IPinInfo_FWD_DEFINED__ -#define __IPinInfo_FWD_DEFINED__ -typedef struct IPinInfo IPinInfo; -#endif - -#ifndef __IAMStats_FWD_DEFINED__ -#define __IAMStats_FWD_DEFINED__ -typedef struct IAMStats IAMStats; -#endif - -#ifdef __cplusplus -extern "C"{ -#endif - -#ifndef __MIDL_user_allocate_free_DEFINED__ -#define __MIDL_user_allocate_free_DEFINED__ - void *__RPC_API MIDL_user_allocate(size_t); - void __RPC_API MIDL_user_free(void *); -#endif - -#ifndef __QuartzTypeLib_LIBRARY_DEFINED__ -#define __QuartzTypeLib_LIBRARY_DEFINED__ - typedef double REFTIME; - typedef LONG_PTR OAEVENT; - typedef LONG_PTR OAHWND; - typedef long OAFilterState; - - DEFINE_GUID(LIBID_QuartzTypeLib,0x56a868b0,0x0ad4,0x11ce,0xb0,0x3a,0x00,0x20,0xaf,0x0b,0xa7,0x70); -#ifndef __IAMCollection_INTERFACE_DEFINED__ -#define __IAMCollection_INTERFACE_DEFINED__ - DEFINE_GUID(IID_IAMCollection,0x56a868b9,0x0ad4,0x11ce,0xb0,0x3a,0x00,0x20,0xaf,0x0b,0xa7,0x70); -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IAMCollection : public IDispatch { - public: - virtual HRESULT WINAPI get_Count(LONG *plCount) = 0; - virtual HRESULT WINAPI Item(long lItem,IUnknown **ppUnk) = 0; - virtual HRESULT WINAPI get__NewEnum(IUnknown **ppUnk) = 0; - }; -#else - typedef struct IAMCollectionVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IAMCollection *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IAMCollection *This); - ULONG (WINAPI *Release)(IAMCollection *This); - HRESULT (WINAPI *GetTypeInfoCount)(IAMCollection *This,UINT *pctinfo); - HRESULT (WINAPI *GetTypeInfo)(IAMCollection *This,UINT iTInfo,LCID lcid,ITypeInfo **ppTInfo); - HRESULT (WINAPI *GetIDsOfNames)(IAMCollection *This,REFIID riid,LPOLESTR *rgszNames,UINT cNames,LCID lcid,DISPID *rgDispId); - HRESULT (WINAPI *Invoke)(IAMCollection *This,DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS *pDispParams,VARIANT *pVarResult,EXCEPINFO *pExcepInfo,UINT *puArgErr); - HRESULT (WINAPI *get_Count)(IAMCollection *This,LONG *plCount); - HRESULT (WINAPI *Item)(IAMCollection *This,long lItem,IUnknown **ppUnk); - HRESULT (WINAPI *get__NewEnum)(IAMCollection *This,IUnknown **ppUnk); - END_INTERFACE - } IAMCollectionVtbl; - struct IAMCollection { - CONST_VTBL struct IAMCollectionVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IAMCollection_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IAMCollection_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IAMCollection_Release(This) (This)->lpVtbl->Release(This) -#define IAMCollection_GetTypeInfoCount(This,pctinfo) (This)->lpVtbl->GetTypeInfoCount(This,pctinfo) -#define IAMCollection_GetTypeInfo(This,iTInfo,lcid,ppTInfo) (This)->lpVtbl->GetTypeInfo(This,iTInfo,lcid,ppTInfo) -#define IAMCollection_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) (This)->lpVtbl->GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) -#define IAMCollection_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) (This)->lpVtbl->Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) -#define IAMCollection_get_Count(This,plCount) (This)->lpVtbl->get_Count(This,plCount) -#define IAMCollection_Item(This,lItem,ppUnk) (This)->lpVtbl->Item(This,lItem,ppUnk) -#define IAMCollection_get__NewEnum(This,ppUnk) (This)->lpVtbl->get__NewEnum(This,ppUnk) -#endif -#endif - HRESULT WINAPI IAMCollection_get_Count_Proxy(IAMCollection *This,LONG *plCount); - void __RPC_STUB IAMCollection_get_Count_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMCollection_Item_Proxy(IAMCollection *This,long lItem,IUnknown **ppUnk); - void __RPC_STUB IAMCollection_Item_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMCollection_get__NewEnum_Proxy(IAMCollection *This,IUnknown **ppUnk); - void __RPC_STUB IAMCollection_get__NewEnum_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IMediaControl_INTERFACE_DEFINED__ -#define __IMediaControl_INTERFACE_DEFINED__ - DEFINE_GUID(IID_IMediaControl,0x56a868b1,0x0ad4,0x11ce,0xb0,0x3a,0x00,0x20,0xaf,0x0b,0xa7,0x70); -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IMediaControl : public IDispatch { - public: - virtual HRESULT WINAPI Run(void) = 0; - virtual HRESULT WINAPI Pause(void) = 0; - virtual HRESULT WINAPI Stop(void) = 0; - virtual HRESULT WINAPI GetState(LONG msTimeout,OAFilterState *pfs) = 0; - virtual HRESULT WINAPI RenderFile(BSTR strFilename) = 0; - virtual HRESULT WINAPI AddSourceFilter(BSTR strFilename,IDispatch **ppUnk) = 0; - virtual HRESULT WINAPI get_FilterCollection(IDispatch **ppUnk) = 0; - virtual HRESULT WINAPI get_RegFilterCollection(IDispatch **ppUnk) = 0; - virtual HRESULT WINAPI StopWhenReady(void) = 0; - }; -#else - typedef struct IMediaControlVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IMediaControl *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IMediaControl *This); - ULONG (WINAPI *Release)(IMediaControl *This); - HRESULT (WINAPI *GetTypeInfoCount)(IMediaControl *This,UINT *pctinfo); - HRESULT (WINAPI *GetTypeInfo)(IMediaControl *This,UINT iTInfo,LCID lcid,ITypeInfo **ppTInfo); - HRESULT (WINAPI *GetIDsOfNames)(IMediaControl *This,REFIID riid,LPOLESTR *rgszNames,UINT cNames,LCID lcid,DISPID *rgDispId); - HRESULT (WINAPI *Invoke)(IMediaControl *This,DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS *pDispParams,VARIANT *pVarResult,EXCEPINFO *pExcepInfo,UINT *puArgErr); - HRESULT (WINAPI *Run)(IMediaControl *This); - HRESULT (WINAPI *Pause)(IMediaControl *This); - HRESULT (WINAPI *Stop)(IMediaControl *This); - HRESULT (WINAPI *GetState)(IMediaControl *This,LONG msTimeout,OAFilterState *pfs); - HRESULT (WINAPI *RenderFile)(IMediaControl *This,BSTR strFilename); - HRESULT (WINAPI *AddSourceFilter)(IMediaControl *This,BSTR strFilename,IDispatch **ppUnk); - HRESULT (WINAPI *get_FilterCollection)(IMediaControl *This,IDispatch **ppUnk); - HRESULT (WINAPI *get_RegFilterCollection)(IMediaControl *This,IDispatch **ppUnk); - HRESULT (WINAPI *StopWhenReady)(IMediaControl *This); - END_INTERFACE - } IMediaControlVtbl; - struct IMediaControl { - CONST_VTBL struct IMediaControlVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IMediaControl_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IMediaControl_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IMediaControl_Release(This) (This)->lpVtbl->Release(This) -#define IMediaControl_GetTypeInfoCount(This,pctinfo) (This)->lpVtbl->GetTypeInfoCount(This,pctinfo) -#define IMediaControl_GetTypeInfo(This,iTInfo,lcid,ppTInfo) (This)->lpVtbl->GetTypeInfo(This,iTInfo,lcid,ppTInfo) -#define IMediaControl_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) (This)->lpVtbl->GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) -#define IMediaControl_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) (This)->lpVtbl->Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) -#define IMediaControl_Run(This) (This)->lpVtbl->Run(This) -#define IMediaControl_Pause(This) (This)->lpVtbl->Pause(This) -#define IMediaControl_Stop(This) (This)->lpVtbl->Stop(This) -#define IMediaControl_GetState(This,msTimeout,pfs) (This)->lpVtbl->GetState(This,msTimeout,pfs) -#define IMediaControl_RenderFile(This,strFilename) (This)->lpVtbl->RenderFile(This,strFilename) -#define IMediaControl_AddSourceFilter(This,strFilename,ppUnk) (This)->lpVtbl->AddSourceFilter(This,strFilename,ppUnk) -#define IMediaControl_get_FilterCollection(This,ppUnk) (This)->lpVtbl->get_FilterCollection(This,ppUnk) -#define IMediaControl_get_RegFilterCollection(This,ppUnk) (This)->lpVtbl->get_RegFilterCollection(This,ppUnk) -#define IMediaControl_StopWhenReady(This) (This)->lpVtbl->StopWhenReady(This) -#endif -#endif - HRESULT WINAPI IMediaControl_Run_Proxy(IMediaControl *This); - void __RPC_STUB IMediaControl_Run_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMediaControl_Pause_Proxy(IMediaControl *This); - void __RPC_STUB IMediaControl_Pause_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMediaControl_Stop_Proxy(IMediaControl *This); - void __RPC_STUB IMediaControl_Stop_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMediaControl_GetState_Proxy(IMediaControl *This,LONG msTimeout,OAFilterState *pfs); - void __RPC_STUB IMediaControl_GetState_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMediaControl_RenderFile_Proxy(IMediaControl *This,BSTR strFilename); - void __RPC_STUB IMediaControl_RenderFile_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMediaControl_AddSourceFilter_Proxy(IMediaControl *This,BSTR strFilename,IDispatch **ppUnk); - void __RPC_STUB IMediaControl_AddSourceFilter_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMediaControl_get_FilterCollection_Proxy(IMediaControl *This,IDispatch **ppUnk); - void __RPC_STUB IMediaControl_get_FilterCollection_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMediaControl_get_RegFilterCollection_Proxy(IMediaControl *This,IDispatch **ppUnk); - void __RPC_STUB IMediaControl_get_RegFilterCollection_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMediaControl_StopWhenReady_Proxy(IMediaControl *This); - void __RPC_STUB IMediaControl_StopWhenReady_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IMediaEvent_INTERFACE_DEFINED__ -#define __IMediaEvent_INTERFACE_DEFINED__ - DEFINE_GUID(IID_IMediaEvent,0x56a868b6,0x0ad4,0x11ce,0xb0,0x3a,0x00,0x20,0xaf,0x0b,0xa7,0x70); -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IMediaEvent : public IDispatch { - public: - virtual HRESULT WINAPI GetEventHandle(OAEVENT *hEvent) = 0; - virtual HRESULT WINAPI GetEvent(long *lEventCode,LONG_PTR *lParam1,LONG_PTR *lParam2,long msTimeout) = 0; - virtual HRESULT WINAPI WaitForCompletion(long msTimeout,long *pEvCode) = 0; - virtual HRESULT WINAPI CancelDefaultHandling(long lEvCode) = 0; - virtual HRESULT WINAPI RestoreDefaultHandling(long lEvCode) = 0; - virtual HRESULT WINAPI FreeEventParams(long lEvCode,LONG_PTR lParam1,LONG_PTR lParam2) = 0; - }; -#else - typedef struct IMediaEventVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IMediaEvent *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IMediaEvent *This); - ULONG (WINAPI *Release)(IMediaEvent *This); - HRESULT (WINAPI *GetTypeInfoCount)(IMediaEvent *This,UINT *pctinfo); - HRESULT (WINAPI *GetTypeInfo)(IMediaEvent *This,UINT iTInfo,LCID lcid,ITypeInfo **ppTInfo); - HRESULT (WINAPI *GetIDsOfNames)(IMediaEvent *This,REFIID riid,LPOLESTR *rgszNames,UINT cNames,LCID lcid,DISPID *rgDispId); - HRESULT (WINAPI *Invoke)(IMediaEvent *This,DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS *pDispParams,VARIANT *pVarResult,EXCEPINFO *pExcepInfo,UINT *puArgErr); - HRESULT (WINAPI *GetEventHandle)(IMediaEvent *This,OAEVENT *hEvent); - HRESULT (WINAPI *GetEvent)(IMediaEvent *This,long *lEventCode,LONG_PTR *lParam1,LONG_PTR *lParam2,long msTimeout); - HRESULT (WINAPI *WaitForCompletion)(IMediaEvent *This,long msTimeout,long *pEvCode); - HRESULT (WINAPI *CancelDefaultHandling)(IMediaEvent *This,long lEvCode); - HRESULT (WINAPI *RestoreDefaultHandling)(IMediaEvent *This,long lEvCode); - HRESULT (WINAPI *FreeEventParams)(IMediaEvent *This,long lEvCode,LONG_PTR lParam1,LONG_PTR lParam2); - END_INTERFACE - } IMediaEventVtbl; - struct IMediaEvent { - CONST_VTBL struct IMediaEventVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IMediaEvent_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IMediaEvent_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IMediaEvent_Release(This) (This)->lpVtbl->Release(This) -#define IMediaEvent_GetTypeInfoCount(This,pctinfo) (This)->lpVtbl->GetTypeInfoCount(This,pctinfo) -#define IMediaEvent_GetTypeInfo(This,iTInfo,lcid,ppTInfo) (This)->lpVtbl->GetTypeInfo(This,iTInfo,lcid,ppTInfo) -#define IMediaEvent_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) (This)->lpVtbl->GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) -#define IMediaEvent_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) (This)->lpVtbl->Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) -#define IMediaEvent_GetEventHandle(This,hEvent) (This)->lpVtbl->GetEventHandle(This,hEvent) -#define IMediaEvent_GetEvent(This,lEventCode,lParam1,lParam2,msTimeout) (This)->lpVtbl->GetEvent(This,lEventCode,lParam1,lParam2,msTimeout) -#define IMediaEvent_WaitForCompletion(This,msTimeout,pEvCode) (This)->lpVtbl->WaitForCompletion(This,msTimeout,pEvCode) -#define IMediaEvent_CancelDefaultHandling(This,lEvCode) (This)->lpVtbl->CancelDefaultHandling(This,lEvCode) -#define IMediaEvent_RestoreDefaultHandling(This,lEvCode) (This)->lpVtbl->RestoreDefaultHandling(This,lEvCode) -#define IMediaEvent_FreeEventParams(This,lEvCode,lParam1,lParam2) (This)->lpVtbl->FreeEventParams(This,lEvCode,lParam1,lParam2) -#endif -#endif - HRESULT WINAPI IMediaEvent_GetEventHandle_Proxy(IMediaEvent *This,OAEVENT *hEvent); - void __RPC_STUB IMediaEvent_GetEventHandle_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMediaEvent_GetEvent_Proxy(IMediaEvent *This,long *lEventCode,LONG_PTR *lParam1,LONG_PTR *lParam2,long msTimeout); - void __RPC_STUB IMediaEvent_GetEvent_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMediaEvent_WaitForCompletion_Proxy(IMediaEvent *This,long msTimeout,long *pEvCode); - void __RPC_STUB IMediaEvent_WaitForCompletion_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMediaEvent_CancelDefaultHandling_Proxy(IMediaEvent *This,long lEvCode); - void __RPC_STUB IMediaEvent_CancelDefaultHandling_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMediaEvent_RestoreDefaultHandling_Proxy(IMediaEvent *This,long lEvCode); - void __RPC_STUB IMediaEvent_RestoreDefaultHandling_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMediaEvent_FreeEventParams_Proxy(IMediaEvent *This,long lEvCode,LONG_PTR lParam1,LONG_PTR lParam2); - void __RPC_STUB IMediaEvent_FreeEventParams_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IMediaEventEx_INTERFACE_DEFINED__ -#define __IMediaEventEx_INTERFACE_DEFINED__ - DEFINE_GUID(IID_IMediaEventEx,0x56a868c0,0x0ad4,0x11ce,0xb0,0x3a,0x00,0x20,0xaf,0x0b,0xa7,0x70); -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IMediaEventEx : public IMediaEvent { - public: - virtual HRESULT WINAPI SetNotifyWindow(OAHWND hwnd,long lMsg,LONG_PTR lInstanceData) = 0; - virtual HRESULT WINAPI SetNotifyFlags(long lNoNotifyFlags) = 0; - virtual HRESULT WINAPI GetNotifyFlags(long *lplNoNotifyFlags) = 0; - }; -#else - typedef struct IMediaEventExVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IMediaEventEx *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IMediaEventEx *This); - ULONG (WINAPI *Release)(IMediaEventEx *This); - HRESULT (WINAPI *GetTypeInfoCount)(IMediaEventEx *This,UINT *pctinfo); - HRESULT (WINAPI *GetTypeInfo)(IMediaEventEx *This,UINT iTInfo,LCID lcid,ITypeInfo **ppTInfo); - HRESULT (WINAPI *GetIDsOfNames)(IMediaEventEx *This,REFIID riid,LPOLESTR *rgszNames,UINT cNames,LCID lcid,DISPID *rgDispId); - HRESULT (WINAPI *Invoke)(IMediaEventEx *This,DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS *pDispParams,VARIANT *pVarResult,EXCEPINFO *pExcepInfo,UINT *puArgErr); - HRESULT (WINAPI *GetEventHandle)(IMediaEventEx *This,OAEVENT *hEvent); - HRESULT (WINAPI *GetEvent)(IMediaEventEx *This,long *lEventCode,LONG_PTR *lParam1,LONG_PTR *lParam2,long msTimeout); - HRESULT (WINAPI *WaitForCompletion)(IMediaEventEx *This,long msTimeout,long *pEvCode); - HRESULT (WINAPI *CancelDefaultHandling)(IMediaEventEx *This,long lEvCode); - HRESULT (WINAPI *RestoreDefaultHandling)(IMediaEventEx *This,long lEvCode); - HRESULT (WINAPI *FreeEventParams)(IMediaEventEx *This,long lEvCode,LONG_PTR lParam1,LONG_PTR lParam2); - HRESULT (WINAPI *SetNotifyWindow)(IMediaEventEx *This,OAHWND hwnd,long lMsg,LONG_PTR lInstanceData); - HRESULT (WINAPI *SetNotifyFlags)(IMediaEventEx *This,long lNoNotifyFlags); - HRESULT (WINAPI *GetNotifyFlags)(IMediaEventEx *This,long *lplNoNotifyFlags); - END_INTERFACE - } IMediaEventExVtbl; - struct IMediaEventEx { - CONST_VTBL struct IMediaEventExVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IMediaEventEx_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IMediaEventEx_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IMediaEventEx_Release(This) (This)->lpVtbl->Release(This) -#define IMediaEventEx_GetTypeInfoCount(This,pctinfo) (This)->lpVtbl->GetTypeInfoCount(This,pctinfo) -#define IMediaEventEx_GetTypeInfo(This,iTInfo,lcid,ppTInfo) (This)->lpVtbl->GetTypeInfo(This,iTInfo,lcid,ppTInfo) -#define IMediaEventEx_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) (This)->lpVtbl->GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) -#define IMediaEventEx_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) (This)->lpVtbl->Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) -#define IMediaEventEx_GetEventHandle(This,hEvent) (This)->lpVtbl->GetEventHandle(This,hEvent) -#define IMediaEventEx_GetEvent(This,lEventCode,lParam1,lParam2,msTimeout) (This)->lpVtbl->GetEvent(This,lEventCode,lParam1,lParam2,msTimeout) -#define IMediaEventEx_WaitForCompletion(This,msTimeout,pEvCode) (This)->lpVtbl->WaitForCompletion(This,msTimeout,pEvCode) -#define IMediaEventEx_CancelDefaultHandling(This,lEvCode) (This)->lpVtbl->CancelDefaultHandling(This,lEvCode) -#define IMediaEventEx_RestoreDefaultHandling(This,lEvCode) (This)->lpVtbl->RestoreDefaultHandling(This,lEvCode) -#define IMediaEventEx_FreeEventParams(This,lEvCode,lParam1,lParam2) (This)->lpVtbl->FreeEventParams(This,lEvCode,lParam1,lParam2) -#define IMediaEventEx_SetNotifyWindow(This,hwnd,lMsg,lInstanceData) (This)->lpVtbl->SetNotifyWindow(This,hwnd,lMsg,lInstanceData) -#define IMediaEventEx_SetNotifyFlags(This,lNoNotifyFlags) (This)->lpVtbl->SetNotifyFlags(This,lNoNotifyFlags) -#define IMediaEventEx_GetNotifyFlags(This,lplNoNotifyFlags) (This)->lpVtbl->GetNotifyFlags(This,lplNoNotifyFlags) -#endif -#endif - HRESULT WINAPI IMediaEventEx_SetNotifyWindow_Proxy(IMediaEventEx *This,OAHWND hwnd,long lMsg,LONG_PTR lInstanceData); - void __RPC_STUB IMediaEventEx_SetNotifyWindow_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMediaEventEx_SetNotifyFlags_Proxy(IMediaEventEx *This,long lNoNotifyFlags); - void __RPC_STUB IMediaEventEx_SetNotifyFlags_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMediaEventEx_GetNotifyFlags_Proxy(IMediaEventEx *This,long *lplNoNotifyFlags); - void __RPC_STUB IMediaEventEx_GetNotifyFlags_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IMediaPosition_INTERFACE_DEFINED__ -#define __IMediaPosition_INTERFACE_DEFINED__ - DEFINE_GUID(IID_IMediaPosition,0x56a868b2,0x0ad4,0x11ce,0xb0,0x3a,0x00,0x20,0xaf,0x0b,0xa7,0x70); -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IMediaPosition : public IDispatch { - public: - virtual HRESULT WINAPI get_Duration(REFTIME *plength) = 0; - virtual HRESULT WINAPI put_CurrentPosition(REFTIME llTime) = 0; - virtual HRESULT WINAPI get_CurrentPosition(REFTIME *pllTime) = 0; - virtual HRESULT WINAPI get_StopTime(REFTIME *pllTime) = 0; - virtual HRESULT WINAPI put_StopTime(REFTIME llTime) = 0; - virtual HRESULT WINAPI get_PrerollTime(REFTIME *pllTime) = 0; - virtual HRESULT WINAPI put_PrerollTime(REFTIME llTime) = 0; - virtual HRESULT WINAPI put_Rate(double dRate) = 0; - virtual HRESULT WINAPI get_Rate(double *pdRate) = 0; - virtual HRESULT WINAPI CanSeekForward(LONG *pCanSeekForward) = 0; - virtual HRESULT WINAPI CanSeekBackward(LONG *pCanSeekBackward) = 0; - }; -#else - typedef struct IMediaPositionVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IMediaPosition *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IMediaPosition *This); - ULONG (WINAPI *Release)(IMediaPosition *This); - HRESULT (WINAPI *GetTypeInfoCount)(IMediaPosition *This,UINT *pctinfo); - HRESULT (WINAPI *GetTypeInfo)(IMediaPosition *This,UINT iTInfo,LCID lcid,ITypeInfo **ppTInfo); - HRESULT (WINAPI *GetIDsOfNames)(IMediaPosition *This,REFIID riid,LPOLESTR *rgszNames,UINT cNames,LCID lcid,DISPID *rgDispId); - HRESULT (WINAPI *Invoke)(IMediaPosition *This,DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS *pDispParams,VARIANT *pVarResult,EXCEPINFO *pExcepInfo,UINT *puArgErr); - HRESULT (WINAPI *get_Duration)(IMediaPosition *This,REFTIME *plength); - HRESULT (WINAPI *put_CurrentPosition)(IMediaPosition *This,REFTIME llTime); - HRESULT (WINAPI *get_CurrentPosition)(IMediaPosition *This,REFTIME *pllTime); - HRESULT (WINAPI *get_StopTime)(IMediaPosition *This,REFTIME *pllTime); - HRESULT (WINAPI *put_StopTime)(IMediaPosition *This,REFTIME llTime); - HRESULT (WINAPI *get_PrerollTime)(IMediaPosition *This,REFTIME *pllTime); - HRESULT (WINAPI *put_PrerollTime)(IMediaPosition *This,REFTIME llTime); - HRESULT (WINAPI *put_Rate)(IMediaPosition *This,double dRate); - HRESULT (WINAPI *get_Rate)(IMediaPosition *This,double *pdRate); - HRESULT (WINAPI *CanSeekForward)(IMediaPosition *This,LONG *pCanSeekForward); - HRESULT (WINAPI *CanSeekBackward)(IMediaPosition *This,LONG *pCanSeekBackward); - END_INTERFACE - } IMediaPositionVtbl; - struct IMediaPosition { - CONST_VTBL struct IMediaPositionVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IMediaPosition_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IMediaPosition_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IMediaPosition_Release(This) (This)->lpVtbl->Release(This) -#define IMediaPosition_GetTypeInfoCount(This,pctinfo) (This)->lpVtbl->GetTypeInfoCount(This,pctinfo) -#define IMediaPosition_GetTypeInfo(This,iTInfo,lcid,ppTInfo) (This)->lpVtbl->GetTypeInfo(This,iTInfo,lcid,ppTInfo) -#define IMediaPosition_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) (This)->lpVtbl->GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) -#define IMediaPosition_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) (This)->lpVtbl->Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) -#define IMediaPosition_get_Duration(This,plength) (This)->lpVtbl->get_Duration(This,plength) -#define IMediaPosition_put_CurrentPosition(This,llTime) (This)->lpVtbl->put_CurrentPosition(This,llTime) -#define IMediaPosition_get_CurrentPosition(This,pllTime) (This)->lpVtbl->get_CurrentPosition(This,pllTime) -#define IMediaPosition_get_StopTime(This,pllTime) (This)->lpVtbl->get_StopTime(This,pllTime) -#define IMediaPosition_put_StopTime(This,llTime) (This)->lpVtbl->put_StopTime(This,llTime) -#define IMediaPosition_get_PrerollTime(This,pllTime) (This)->lpVtbl->get_PrerollTime(This,pllTime) -#define IMediaPosition_put_PrerollTime(This,llTime) (This)->lpVtbl->put_PrerollTime(This,llTime) -#define IMediaPosition_put_Rate(This,dRate) (This)->lpVtbl->put_Rate(This,dRate) -#define IMediaPosition_get_Rate(This,pdRate) (This)->lpVtbl->get_Rate(This,pdRate) -#define IMediaPosition_CanSeekForward(This,pCanSeekForward) (This)->lpVtbl->CanSeekForward(This,pCanSeekForward) -#define IMediaPosition_CanSeekBackward(This,pCanSeekBackward) (This)->lpVtbl->CanSeekBackward(This,pCanSeekBackward) -#endif -#endif - HRESULT WINAPI IMediaPosition_get_Duration_Proxy(IMediaPosition *This,REFTIME *plength); - void __RPC_STUB IMediaPosition_get_Duration_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMediaPosition_put_CurrentPosition_Proxy(IMediaPosition *This,REFTIME llTime); - void __RPC_STUB IMediaPosition_put_CurrentPosition_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMediaPosition_get_CurrentPosition_Proxy(IMediaPosition *This,REFTIME *pllTime); - void __RPC_STUB IMediaPosition_get_CurrentPosition_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMediaPosition_get_StopTime_Proxy(IMediaPosition *This,REFTIME *pllTime); - void __RPC_STUB IMediaPosition_get_StopTime_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMediaPosition_put_StopTime_Proxy(IMediaPosition *This,REFTIME llTime); - void __RPC_STUB IMediaPosition_put_StopTime_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMediaPosition_get_PrerollTime_Proxy(IMediaPosition *This,REFTIME *pllTime); - void __RPC_STUB IMediaPosition_get_PrerollTime_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMediaPosition_put_PrerollTime_Proxy(IMediaPosition *This,REFTIME llTime); - void __RPC_STUB IMediaPosition_put_PrerollTime_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMediaPosition_put_Rate_Proxy(IMediaPosition *This,double dRate); - void __RPC_STUB IMediaPosition_put_Rate_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMediaPosition_get_Rate_Proxy(IMediaPosition *This,double *pdRate); - void __RPC_STUB IMediaPosition_get_Rate_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMediaPosition_CanSeekForward_Proxy(IMediaPosition *This,LONG *pCanSeekForward); - void __RPC_STUB IMediaPosition_CanSeekForward_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMediaPosition_CanSeekBackward_Proxy(IMediaPosition *This,LONG *pCanSeekBackward); - void __RPC_STUB IMediaPosition_CanSeekBackward_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IBasicAudio_INTERFACE_DEFINED__ -#define __IBasicAudio_INTERFACE_DEFINED__ - DEFINE_GUID(IID_IBasicAudio,0x56a868b3,0x0ad4,0x11ce,0xb0,0x3a,0x00,0x20,0xaf,0x0b,0xa7,0x70); -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IBasicAudio : public IDispatch { - public: - virtual HRESULT WINAPI put_Volume(long lVolume) = 0; - virtual HRESULT WINAPI get_Volume(long *plVolume) = 0; - virtual HRESULT WINAPI put_Balance(long lBalance) = 0; - virtual HRESULT WINAPI get_Balance(long *plBalance) = 0; - }; -#else - typedef struct IBasicAudioVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IBasicAudio *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IBasicAudio *This); - ULONG (WINAPI *Release)(IBasicAudio *This); - HRESULT (WINAPI *GetTypeInfoCount)(IBasicAudio *This,UINT *pctinfo); - HRESULT (WINAPI *GetTypeInfo)(IBasicAudio *This,UINT iTInfo,LCID lcid,ITypeInfo **ppTInfo); - HRESULT (WINAPI *GetIDsOfNames)(IBasicAudio *This,REFIID riid,LPOLESTR *rgszNames,UINT cNames,LCID lcid,DISPID *rgDispId); - HRESULT (WINAPI *Invoke)(IBasicAudio *This,DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS *pDispParams,VARIANT *pVarResult,EXCEPINFO *pExcepInfo,UINT *puArgErr); - HRESULT (WINAPI *put_Volume)(IBasicAudio *This,long lVolume); - HRESULT (WINAPI *get_Volume)(IBasicAudio *This,long *plVolume); - HRESULT (WINAPI *put_Balance)(IBasicAudio *This,long lBalance); - HRESULT (WINAPI *get_Balance)(IBasicAudio *This,long *plBalance); - END_INTERFACE - } IBasicAudioVtbl; - struct IBasicAudio { - CONST_VTBL struct IBasicAudioVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IBasicAudio_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IBasicAudio_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IBasicAudio_Release(This) (This)->lpVtbl->Release(This) -#define IBasicAudio_GetTypeInfoCount(This,pctinfo) (This)->lpVtbl->GetTypeInfoCount(This,pctinfo) -#define IBasicAudio_GetTypeInfo(This,iTInfo,lcid,ppTInfo) (This)->lpVtbl->GetTypeInfo(This,iTInfo,lcid,ppTInfo) -#define IBasicAudio_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) (This)->lpVtbl->GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) -#define IBasicAudio_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) (This)->lpVtbl->Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) -#define IBasicAudio_put_Volume(This,lVolume) (This)->lpVtbl->put_Volume(This,lVolume) -#define IBasicAudio_get_Volume(This,plVolume) (This)->lpVtbl->get_Volume(This,plVolume) -#define IBasicAudio_put_Balance(This,lBalance) (This)->lpVtbl->put_Balance(This,lBalance) -#define IBasicAudio_get_Balance(This,plBalance) (This)->lpVtbl->get_Balance(This,plBalance) -#endif -#endif - HRESULT WINAPI IBasicAudio_put_Volume_Proxy(IBasicAudio *This,long lVolume); - void __RPC_STUB IBasicAudio_put_Volume_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IBasicAudio_get_Volume_Proxy(IBasicAudio *This,long *plVolume); - void __RPC_STUB IBasicAudio_get_Volume_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IBasicAudio_put_Balance_Proxy(IBasicAudio *This,long lBalance); - void __RPC_STUB IBasicAudio_put_Balance_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IBasicAudio_get_Balance_Proxy(IBasicAudio *This,long *plBalance); - void __RPC_STUB IBasicAudio_get_Balance_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IVideoWindow_INTERFACE_DEFINED__ -#define __IVideoWindow_INTERFACE_DEFINED__ - DEFINE_GUID(IID_IVideoWindow,0x56a868b4,0x0ad4,0x11ce,0xb0,0x3a,0x00,0x20,0xaf,0x0b,0xa7,0x70); -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IVideoWindow : public IDispatch { - public: - virtual HRESULT WINAPI put_Caption(BSTR strCaption) = 0; - virtual HRESULT WINAPI get_Caption(BSTR *strCaption) = 0; - virtual HRESULT WINAPI put_WindowStyle(long WindowStyle) = 0; - virtual HRESULT WINAPI get_WindowStyle(long *WindowStyle) = 0; - virtual HRESULT WINAPI put_WindowStyleEx(long WindowStyleEx) = 0; - virtual HRESULT WINAPI get_WindowStyleEx(long *WindowStyleEx) = 0; - virtual HRESULT WINAPI put_AutoShow(long AutoShow) = 0; - virtual HRESULT WINAPI get_AutoShow(long *AutoShow) = 0; - virtual HRESULT WINAPI put_WindowState(long WindowState) = 0; - virtual HRESULT WINAPI get_WindowState(long *WindowState) = 0; - virtual HRESULT WINAPI put_BackgroundPalette(long BackgroundPalette) = 0; - virtual HRESULT WINAPI get_BackgroundPalette(long *pBackgroundPalette) = 0; - virtual HRESULT WINAPI put_Visible(long Visible) = 0; - virtual HRESULT WINAPI get_Visible(long *pVisible) = 0; - virtual HRESULT WINAPI put_Left(long Left) = 0; - virtual HRESULT WINAPI get_Left(long *pLeft) = 0; - virtual HRESULT WINAPI put_Width(long Width) = 0; - virtual HRESULT WINAPI get_Width(long *pWidth) = 0; - virtual HRESULT WINAPI put_Top(long Top) = 0; - virtual HRESULT WINAPI get_Top(long *pTop) = 0; - virtual HRESULT WINAPI put_Height(long Height) = 0; - virtual HRESULT WINAPI get_Height(long *pHeight) = 0; - virtual HRESULT WINAPI put_Owner(OAHWND Owner) = 0; - virtual HRESULT WINAPI get_Owner(OAHWND *Owner) = 0; - virtual HRESULT WINAPI put_MessageDrain(OAHWND Drain) = 0; - virtual HRESULT WINAPI get_MessageDrain(OAHWND *Drain) = 0; - virtual HRESULT WINAPI get_BorderColor(long *Color) = 0; - virtual HRESULT WINAPI put_BorderColor(long Color) = 0; - virtual HRESULT WINAPI get_FullScreenMode(long *FullScreenMode) = 0; - virtual HRESULT WINAPI put_FullScreenMode(long FullScreenMode) = 0; - virtual HRESULT WINAPI SetWindowForeground(long Focus) = 0; - virtual HRESULT WINAPI NotifyOwnerMessage(OAHWND hwnd,long uMsg,LONG_PTR wParam,LONG_PTR lParam) = 0; - virtual HRESULT WINAPI SetWindowPosition(long Left,long Top,long Width,long Height) = 0; - virtual HRESULT WINAPI GetWindowPosition(long *pLeft,long *pTop,long *pWidth,long *pHeight) = 0; - virtual HRESULT WINAPI GetMinIdealImageSize(long *pWidth,long *pHeight) = 0; - virtual HRESULT WINAPI GetMaxIdealImageSize(long *pWidth,long *pHeight) = 0; - virtual HRESULT WINAPI GetRestorePosition(long *pLeft,long *pTop,long *pWidth,long *pHeight) = 0; - virtual HRESULT WINAPI HideCursor(long HideCursor) = 0; - virtual HRESULT WINAPI IsCursorHidden(long *CursorHidden) = 0; - }; -#else - typedef struct IVideoWindowVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IVideoWindow *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IVideoWindow *This); - ULONG (WINAPI *Release)(IVideoWindow *This); - HRESULT (WINAPI *GetTypeInfoCount)(IVideoWindow *This,UINT *pctinfo); - HRESULT (WINAPI *GetTypeInfo)(IVideoWindow *This,UINT iTInfo,LCID lcid,ITypeInfo **ppTInfo); - HRESULT (WINAPI *GetIDsOfNames)(IVideoWindow *This,REFIID riid,LPOLESTR *rgszNames,UINT cNames,LCID lcid,DISPID *rgDispId); - HRESULT (WINAPI *Invoke)(IVideoWindow *This,DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS *pDispParams,VARIANT *pVarResult,EXCEPINFO *pExcepInfo,UINT *puArgErr); - HRESULT (WINAPI *put_Caption)(IVideoWindow *This,BSTR strCaption); - HRESULT (WINAPI *get_Caption)(IVideoWindow *This,BSTR *strCaption); - HRESULT (WINAPI *put_WindowStyle)(IVideoWindow *This,long WindowStyle); - HRESULT (WINAPI *get_WindowStyle)(IVideoWindow *This,long *WindowStyle); - HRESULT (WINAPI *put_WindowStyleEx)(IVideoWindow *This,long WindowStyleEx); - HRESULT (WINAPI *get_WindowStyleEx)(IVideoWindow *This,long *WindowStyleEx); - HRESULT (WINAPI *put_AutoShow)(IVideoWindow *This,long AutoShow); - HRESULT (WINAPI *get_AutoShow)(IVideoWindow *This,long *AutoShow); - HRESULT (WINAPI *put_WindowState)(IVideoWindow *This,long WindowState); - HRESULT (WINAPI *get_WindowState)(IVideoWindow *This,long *WindowState); - HRESULT (WINAPI *put_BackgroundPalette)(IVideoWindow *This,long BackgroundPalette); - HRESULT (WINAPI *get_BackgroundPalette)(IVideoWindow *This,long *pBackgroundPalette); - HRESULT (WINAPI *put_Visible)(IVideoWindow *This,long Visible); - HRESULT (WINAPI *get_Visible)(IVideoWindow *This,long *pVisible); - HRESULT (WINAPI *put_Left)(IVideoWindow *This,long Left); - HRESULT (WINAPI *get_Left)(IVideoWindow *This,long *pLeft); - HRESULT (WINAPI *put_Width)(IVideoWindow *This,long Width); - HRESULT (WINAPI *get_Width)(IVideoWindow *This,long *pWidth); - HRESULT (WINAPI *put_Top)(IVideoWindow *This,long Top); - HRESULT (WINAPI *get_Top)(IVideoWindow *This,long *pTop); - HRESULT (WINAPI *put_Height)(IVideoWindow *This,long Height); - HRESULT (WINAPI *get_Height)(IVideoWindow *This,long *pHeight); - HRESULT (WINAPI *put_Owner)(IVideoWindow *This,OAHWND Owner); - HRESULT (WINAPI *get_Owner)(IVideoWindow *This,OAHWND *Owner); - HRESULT (WINAPI *put_MessageDrain)(IVideoWindow *This,OAHWND Drain); - HRESULT (WINAPI *get_MessageDrain)(IVideoWindow *This,OAHWND *Drain); - HRESULT (WINAPI *get_BorderColor)(IVideoWindow *This,long *Color); - HRESULT (WINAPI *put_BorderColor)(IVideoWindow *This,long Color); - HRESULT (WINAPI *get_FullScreenMode)(IVideoWindow *This,long *FullScreenMode); - HRESULT (WINAPI *put_FullScreenMode)(IVideoWindow *This,long FullScreenMode); - HRESULT (WINAPI *SetWindowForeground)(IVideoWindow *This,long Focus); - HRESULT (WINAPI *NotifyOwnerMessage)(IVideoWindow *This,OAHWND hwnd,long uMsg,LONG_PTR wParam,LONG_PTR lParam); - HRESULT (WINAPI *SetWindowPosition)(IVideoWindow *This,long Left,long Top,long Width,long Height); - HRESULT (WINAPI *GetWindowPosition)(IVideoWindow *This,long *pLeft,long *pTop,long *pWidth,long *pHeight); - HRESULT (WINAPI *GetMinIdealImageSize)(IVideoWindow *This,long *pWidth,long *pHeight); - HRESULT (WINAPI *GetMaxIdealImageSize)(IVideoWindow *This,long *pWidth,long *pHeight); - HRESULT (WINAPI *GetRestorePosition)(IVideoWindow *This,long *pLeft,long *pTop,long *pWidth,long *pHeight); - HRESULT (WINAPI *HideCursor)(IVideoWindow *This,long HideCursor); - HRESULT (WINAPI *IsCursorHidden)(IVideoWindow *This,long *CursorHidden); - END_INTERFACE - } IVideoWindowVtbl; - struct IVideoWindow { - CONST_VTBL struct IVideoWindowVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IVideoWindow_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IVideoWindow_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IVideoWindow_Release(This) (This)->lpVtbl->Release(This) -#define IVideoWindow_GetTypeInfoCount(This,pctinfo) (This)->lpVtbl->GetTypeInfoCount(This,pctinfo) -#define IVideoWindow_GetTypeInfo(This,iTInfo,lcid,ppTInfo) (This)->lpVtbl->GetTypeInfo(This,iTInfo,lcid,ppTInfo) -#define IVideoWindow_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) (This)->lpVtbl->GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) -#define IVideoWindow_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) (This)->lpVtbl->Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) -#define IVideoWindow_put_Caption(This,strCaption) (This)->lpVtbl->put_Caption(This,strCaption) -#define IVideoWindow_get_Caption(This,strCaption) (This)->lpVtbl->get_Caption(This,strCaption) -#define IVideoWindow_put_WindowStyle(This,WindowStyle) (This)->lpVtbl->put_WindowStyle(This,WindowStyle) -#define IVideoWindow_get_WindowStyle(This,WindowStyle) (This)->lpVtbl->get_WindowStyle(This,WindowStyle) -#define IVideoWindow_put_WindowStyleEx(This,WindowStyleEx) (This)->lpVtbl->put_WindowStyleEx(This,WindowStyleEx) -#define IVideoWindow_get_WindowStyleEx(This,WindowStyleEx) (This)->lpVtbl->get_WindowStyleEx(This,WindowStyleEx) -#define IVideoWindow_put_AutoShow(This,AutoShow) (This)->lpVtbl->put_AutoShow(This,AutoShow) -#define IVideoWindow_get_AutoShow(This,AutoShow) (This)->lpVtbl->get_AutoShow(This,AutoShow) -#define IVideoWindow_put_WindowState(This,WindowState) (This)->lpVtbl->put_WindowState(This,WindowState) -#define IVideoWindow_get_WindowState(This,WindowState) (This)->lpVtbl->get_WindowState(This,WindowState) -#define IVideoWindow_put_BackgroundPalette(This,BackgroundPalette) (This)->lpVtbl->put_BackgroundPalette(This,BackgroundPalette) -#define IVideoWindow_get_BackgroundPalette(This,pBackgroundPalette) (This)->lpVtbl->get_BackgroundPalette(This,pBackgroundPalette) -#define IVideoWindow_put_Visible(This,Visible) (This)->lpVtbl->put_Visible(This,Visible) -#define IVideoWindow_get_Visible(This,pVisible) (This)->lpVtbl->get_Visible(This,pVisible) -#define IVideoWindow_put_Left(This,Left) (This)->lpVtbl->put_Left(This,Left) -#define IVideoWindow_get_Left(This,pLeft) (This)->lpVtbl->get_Left(This,pLeft) -#define IVideoWindow_put_Width(This,Width) (This)->lpVtbl->put_Width(This,Width) -#define IVideoWindow_get_Width(This,pWidth) (This)->lpVtbl->get_Width(This,pWidth) -#define IVideoWindow_put_Top(This,Top) (This)->lpVtbl->put_Top(This,Top) -#define IVideoWindow_get_Top(This,pTop) (This)->lpVtbl->get_Top(This,pTop) -#define IVideoWindow_put_Height(This,Height) (This)->lpVtbl->put_Height(This,Height) -#define IVideoWindow_get_Height(This,pHeight) (This)->lpVtbl->get_Height(This,pHeight) -#define IVideoWindow_put_Owner(This,Owner) (This)->lpVtbl->put_Owner(This,Owner) -#define IVideoWindow_get_Owner(This,Owner) (This)->lpVtbl->get_Owner(This,Owner) -#define IVideoWindow_put_MessageDrain(This,Drain) (This)->lpVtbl->put_MessageDrain(This,Drain) -#define IVideoWindow_get_MessageDrain(This,Drain) (This)->lpVtbl->get_MessageDrain(This,Drain) -#define IVideoWindow_get_BorderColor(This,Color) (This)->lpVtbl->get_BorderColor(This,Color) -#define IVideoWindow_put_BorderColor(This,Color) (This)->lpVtbl->put_BorderColor(This,Color) -#define IVideoWindow_get_FullScreenMode(This,FullScreenMode) (This)->lpVtbl->get_FullScreenMode(This,FullScreenMode) -#define IVideoWindow_put_FullScreenMode(This,FullScreenMode) (This)->lpVtbl->put_FullScreenMode(This,FullScreenMode) -#define IVideoWindow_SetWindowForeground(This,Focus) (This)->lpVtbl->SetWindowForeground(This,Focus) -#define IVideoWindow_NotifyOwnerMessage(This,hwnd,uMsg,wParam,lParam) (This)->lpVtbl->NotifyOwnerMessage(This,hwnd,uMsg,wParam,lParam) -#define IVideoWindow_SetWindowPosition(This,Left,Top,Width,Height) (This)->lpVtbl->SetWindowPosition(This,Left,Top,Width,Height) -#define IVideoWindow_GetWindowPosition(This,pLeft,pTop,pWidth,pHeight) (This)->lpVtbl->GetWindowPosition(This,pLeft,pTop,pWidth,pHeight) -#define IVideoWindow_GetMinIdealImageSize(This,pWidth,pHeight) (This)->lpVtbl->GetMinIdealImageSize(This,pWidth,pHeight) -#define IVideoWindow_GetMaxIdealImageSize(This,pWidth,pHeight) (This)->lpVtbl->GetMaxIdealImageSize(This,pWidth,pHeight) -#define IVideoWindow_GetRestorePosition(This,pLeft,pTop,pWidth,pHeight) (This)->lpVtbl->GetRestorePosition(This,pLeft,pTop,pWidth,pHeight) -#define IVideoWindow_HideCursor(This,HideCursor) (This)->lpVtbl->HideCursor(This,HideCursor) -#define IVideoWindow_IsCursorHidden(This,CursorHidden) (This)->lpVtbl->IsCursorHidden(This,CursorHidden) -#endif -#endif - HRESULT WINAPI IVideoWindow_put_Caption_Proxy(IVideoWindow *This,BSTR strCaption); - void __RPC_STUB IVideoWindow_put_Caption_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVideoWindow_get_Caption_Proxy(IVideoWindow *This,BSTR *strCaption); - void __RPC_STUB IVideoWindow_get_Caption_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVideoWindow_put_WindowStyle_Proxy(IVideoWindow *This,long WindowStyle); - void __RPC_STUB IVideoWindow_put_WindowStyle_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVideoWindow_get_WindowStyle_Proxy(IVideoWindow *This,long *WindowStyle); - void __RPC_STUB IVideoWindow_get_WindowStyle_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVideoWindow_put_WindowStyleEx_Proxy(IVideoWindow *This,long WindowStyleEx); - void __RPC_STUB IVideoWindow_put_WindowStyleEx_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVideoWindow_get_WindowStyleEx_Proxy(IVideoWindow *This,long *WindowStyleEx); - void __RPC_STUB IVideoWindow_get_WindowStyleEx_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVideoWindow_put_AutoShow_Proxy(IVideoWindow *This,long AutoShow); - void __RPC_STUB IVideoWindow_put_AutoShow_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVideoWindow_get_AutoShow_Proxy(IVideoWindow *This,long *AutoShow); - void __RPC_STUB IVideoWindow_get_AutoShow_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVideoWindow_put_WindowState_Proxy(IVideoWindow *This,long WindowState); - void __RPC_STUB IVideoWindow_put_WindowState_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVideoWindow_get_WindowState_Proxy(IVideoWindow *This,long *WindowState); - void __RPC_STUB IVideoWindow_get_WindowState_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVideoWindow_put_BackgroundPalette_Proxy(IVideoWindow *This,long BackgroundPalette); - void __RPC_STUB IVideoWindow_put_BackgroundPalette_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVideoWindow_get_BackgroundPalette_Proxy(IVideoWindow *This,long *pBackgroundPalette); - void __RPC_STUB IVideoWindow_get_BackgroundPalette_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVideoWindow_put_Visible_Proxy(IVideoWindow *This,long Visible); - void __RPC_STUB IVideoWindow_put_Visible_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVideoWindow_get_Visible_Proxy(IVideoWindow *This,long *pVisible); - void __RPC_STUB IVideoWindow_get_Visible_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVideoWindow_put_Left_Proxy(IVideoWindow *This,long Left); - void __RPC_STUB IVideoWindow_put_Left_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVideoWindow_get_Left_Proxy(IVideoWindow *This,long *pLeft); - void __RPC_STUB IVideoWindow_get_Left_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVideoWindow_put_Width_Proxy(IVideoWindow *This,long Width); - void __RPC_STUB IVideoWindow_put_Width_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVideoWindow_get_Width_Proxy(IVideoWindow *This,long *pWidth); - void __RPC_STUB IVideoWindow_get_Width_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVideoWindow_put_Top_Proxy(IVideoWindow *This,long Top); - void __RPC_STUB IVideoWindow_put_Top_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVideoWindow_get_Top_Proxy(IVideoWindow *This,long *pTop); - void __RPC_STUB IVideoWindow_get_Top_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVideoWindow_put_Height_Proxy(IVideoWindow *This,long Height); - void __RPC_STUB IVideoWindow_put_Height_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVideoWindow_get_Height_Proxy(IVideoWindow *This,long *pHeight); - void __RPC_STUB IVideoWindow_get_Height_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVideoWindow_put_Owner_Proxy(IVideoWindow *This,OAHWND Owner); - void __RPC_STUB IVideoWindow_put_Owner_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVideoWindow_get_Owner_Proxy(IVideoWindow *This,OAHWND *Owner); - void __RPC_STUB IVideoWindow_get_Owner_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVideoWindow_put_MessageDrain_Proxy(IVideoWindow *This,OAHWND Drain); - void __RPC_STUB IVideoWindow_put_MessageDrain_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVideoWindow_get_MessageDrain_Proxy(IVideoWindow *This,OAHWND *Drain); - void __RPC_STUB IVideoWindow_get_MessageDrain_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVideoWindow_get_BorderColor_Proxy(IVideoWindow *This,long *Color); - void __RPC_STUB IVideoWindow_get_BorderColor_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVideoWindow_put_BorderColor_Proxy(IVideoWindow *This,long Color); - void __RPC_STUB IVideoWindow_put_BorderColor_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVideoWindow_get_FullScreenMode_Proxy(IVideoWindow *This,long *FullScreenMode); - void __RPC_STUB IVideoWindow_get_FullScreenMode_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVideoWindow_put_FullScreenMode_Proxy(IVideoWindow *This,long FullScreenMode); - void __RPC_STUB IVideoWindow_put_FullScreenMode_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVideoWindow_SetWindowForeground_Proxy(IVideoWindow *This,long Focus); - void __RPC_STUB IVideoWindow_SetWindowForeground_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVideoWindow_NotifyOwnerMessage_Proxy(IVideoWindow *This,OAHWND hwnd,long uMsg,LONG_PTR wParam,LONG_PTR lParam); - void __RPC_STUB IVideoWindow_NotifyOwnerMessage_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVideoWindow_SetWindowPosition_Proxy(IVideoWindow *This,long Left,long Top,long Width,long Height); - void __RPC_STUB IVideoWindow_SetWindowPosition_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVideoWindow_GetWindowPosition_Proxy(IVideoWindow *This,long *pLeft,long *pTop,long *pWidth,long *pHeight); - void __RPC_STUB IVideoWindow_GetWindowPosition_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVideoWindow_GetMinIdealImageSize_Proxy(IVideoWindow *This,long *pWidth,long *pHeight); - void __RPC_STUB IVideoWindow_GetMinIdealImageSize_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVideoWindow_GetMaxIdealImageSize_Proxy(IVideoWindow *This,long *pWidth,long *pHeight); - void __RPC_STUB IVideoWindow_GetMaxIdealImageSize_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVideoWindow_GetRestorePosition_Proxy(IVideoWindow *This,long *pLeft,long *pTop,long *pWidth,long *pHeight); - void __RPC_STUB IVideoWindow_GetRestorePosition_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVideoWindow_HideCursor_Proxy(IVideoWindow *This,long HideCursor); - void __RPC_STUB IVideoWindow_HideCursor_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVideoWindow_IsCursorHidden_Proxy(IVideoWindow *This,long *CursorHidden); - void __RPC_STUB IVideoWindow_IsCursorHidden_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IBasicVideo_INTERFACE_DEFINED__ -#define __IBasicVideo_INTERFACE_DEFINED__ - DEFINE_GUID(IID_IBasicVideo,0x56a868b5,0x0ad4,0x11ce,0xb0,0x3a,0x00,0x20,0xaf,0x0b,0xa7,0x70); -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IBasicVideo : public IDispatch { - public: - virtual HRESULT WINAPI get_AvgTimePerFrame(REFTIME *pAvgTimePerFrame) = 0; - virtual HRESULT WINAPI get_BitRate(long *pBitRate) = 0; - virtual HRESULT WINAPI get_BitErrorRate(long *pBitErrorRate) = 0; - virtual HRESULT WINAPI get_VideoWidth(long *pVideoWidth) = 0; - virtual HRESULT WINAPI get_VideoHeight(long *pVideoHeight) = 0; - virtual HRESULT WINAPI put_SourceLeft(long SourceLeft) = 0; - virtual HRESULT WINAPI get_SourceLeft(long *pSourceLeft) = 0; - virtual HRESULT WINAPI put_SourceWidth(long SourceWidth) = 0; - virtual HRESULT WINAPI get_SourceWidth(long *pSourceWidth) = 0; - virtual HRESULT WINAPI put_SourceTop(long SourceTop) = 0; - virtual HRESULT WINAPI get_SourceTop(long *pSourceTop) = 0; - virtual HRESULT WINAPI put_SourceHeight(long SourceHeight) = 0; - virtual HRESULT WINAPI get_SourceHeight(long *pSourceHeight) = 0; - virtual HRESULT WINAPI put_DestinationLeft(long DestinationLeft) = 0; - virtual HRESULT WINAPI get_DestinationLeft(long *pDestinationLeft) = 0; - virtual HRESULT WINAPI put_DestinationWidth(long DestinationWidth) = 0; - virtual HRESULT WINAPI get_DestinationWidth(long *pDestinationWidth) = 0; - virtual HRESULT WINAPI put_DestinationTop(long DestinationTop) = 0; - virtual HRESULT WINAPI get_DestinationTop(long *pDestinationTop) = 0; - virtual HRESULT WINAPI put_DestinationHeight(long DestinationHeight) = 0; - virtual HRESULT WINAPI get_DestinationHeight(long *pDestinationHeight) = 0; - virtual HRESULT WINAPI SetSourcePosition(long Left,long Top,long Width,long Height) = 0; - virtual HRESULT WINAPI GetSourcePosition(long *pLeft,long *pTop,long *pWidth,long *pHeight) = 0; - virtual HRESULT WINAPI SetDefaultSourcePosition(void) = 0; - virtual HRESULT WINAPI SetDestinationPosition(long Left,long Top,long Width,long Height) = 0; - virtual HRESULT WINAPI GetDestinationPosition(long *pLeft,long *pTop,long *pWidth,long *pHeight) = 0; - virtual HRESULT WINAPI SetDefaultDestinationPosition(void) = 0; - virtual HRESULT WINAPI GetVideoSize(long *pWidth,long *pHeight) = 0; - virtual HRESULT WINAPI GetVideoPaletteEntries(long StartIndex,long Entries,long *pRetrieved,long *pPalette) = 0; - virtual HRESULT WINAPI GetCurrentImage(long *pBufferSize,long *pDIBImage) = 0; - virtual HRESULT WINAPI IsUsingDefaultSource(void) = 0; - virtual HRESULT WINAPI IsUsingDefaultDestination(void) = 0; - }; -#else - typedef struct IBasicVideoVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IBasicVideo *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IBasicVideo *This); - ULONG (WINAPI *Release)(IBasicVideo *This); - HRESULT (WINAPI *GetTypeInfoCount)(IBasicVideo *This,UINT *pctinfo); - HRESULT (WINAPI *GetTypeInfo)(IBasicVideo *This,UINT iTInfo,LCID lcid,ITypeInfo **ppTInfo); - HRESULT (WINAPI *GetIDsOfNames)(IBasicVideo *This,REFIID riid,LPOLESTR *rgszNames,UINT cNames,LCID lcid,DISPID *rgDispId); - HRESULT (WINAPI *Invoke)(IBasicVideo *This,DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS *pDispParams,VARIANT *pVarResult,EXCEPINFO *pExcepInfo,UINT *puArgErr); - HRESULT (WINAPI *get_AvgTimePerFrame)(IBasicVideo *This,REFTIME *pAvgTimePerFrame); - HRESULT (WINAPI *get_BitRate)(IBasicVideo *This,long *pBitRate); - HRESULT (WINAPI *get_BitErrorRate)(IBasicVideo *This,long *pBitErrorRate); - HRESULT (WINAPI *get_VideoWidth)(IBasicVideo *This,long *pVideoWidth); - HRESULT (WINAPI *get_VideoHeight)(IBasicVideo *This,long *pVideoHeight); - HRESULT (WINAPI *put_SourceLeft)(IBasicVideo *This,long SourceLeft); - HRESULT (WINAPI *get_SourceLeft)(IBasicVideo *This,long *pSourceLeft); - HRESULT (WINAPI *put_SourceWidth)(IBasicVideo *This,long SourceWidth); - HRESULT (WINAPI *get_SourceWidth)(IBasicVideo *This,long *pSourceWidth); - HRESULT (WINAPI *put_SourceTop)(IBasicVideo *This,long SourceTop); - HRESULT (WINAPI *get_SourceTop)(IBasicVideo *This,long *pSourceTop); - HRESULT (WINAPI *put_SourceHeight)(IBasicVideo *This,long SourceHeight); - HRESULT (WINAPI *get_SourceHeight)(IBasicVideo *This,long *pSourceHeight); - HRESULT (WINAPI *put_DestinationLeft)(IBasicVideo *This,long DestinationLeft); - HRESULT (WINAPI *get_DestinationLeft)(IBasicVideo *This,long *pDestinationLeft); - HRESULT (WINAPI *put_DestinationWidth)(IBasicVideo *This,long DestinationWidth); - HRESULT (WINAPI *get_DestinationWidth)(IBasicVideo *This,long *pDestinationWidth); - HRESULT (WINAPI *put_DestinationTop)(IBasicVideo *This,long DestinationTop); - HRESULT (WINAPI *get_DestinationTop)(IBasicVideo *This,long *pDestinationTop); - HRESULT (WINAPI *put_DestinationHeight)(IBasicVideo *This,long DestinationHeight); - HRESULT (WINAPI *get_DestinationHeight)(IBasicVideo *This,long *pDestinationHeight); - HRESULT (WINAPI *SetSourcePosition)(IBasicVideo *This,long Left,long Top,long Width,long Height); - HRESULT (WINAPI *GetSourcePosition)(IBasicVideo *This,long *pLeft,long *pTop,long *pWidth,long *pHeight); - HRESULT (WINAPI *SetDefaultSourcePosition)(IBasicVideo *This); - HRESULT (WINAPI *SetDestinationPosition)(IBasicVideo *This,long Left,long Top,long Width,long Height); - HRESULT (WINAPI *GetDestinationPosition)(IBasicVideo *This,long *pLeft,long *pTop,long *pWidth,long *pHeight); - HRESULT (WINAPI *SetDefaultDestinationPosition)(IBasicVideo *This); - HRESULT (WINAPI *GetVideoSize)(IBasicVideo *This,long *pWidth,long *pHeight); - HRESULT (WINAPI *GetVideoPaletteEntries)(IBasicVideo *This,long StartIndex,long Entries,long *pRetrieved,long *pPalette); - HRESULT (WINAPI *GetCurrentImage)(IBasicVideo *This,long *pBufferSize,long *pDIBImage); - HRESULT (WINAPI *IsUsingDefaultSource)(IBasicVideo *This); - HRESULT (WINAPI *IsUsingDefaultDestination)(IBasicVideo *This); - END_INTERFACE - } IBasicVideoVtbl; - struct IBasicVideo { - CONST_VTBL struct IBasicVideoVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IBasicVideo_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IBasicVideo_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IBasicVideo_Release(This) (This)->lpVtbl->Release(This) -#define IBasicVideo_GetTypeInfoCount(This,pctinfo) (This)->lpVtbl->GetTypeInfoCount(This,pctinfo) -#define IBasicVideo_GetTypeInfo(This,iTInfo,lcid,ppTInfo) (This)->lpVtbl->GetTypeInfo(This,iTInfo,lcid,ppTInfo) -#define IBasicVideo_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) (This)->lpVtbl->GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) -#define IBasicVideo_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) (This)->lpVtbl->Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) -#define IBasicVideo_get_AvgTimePerFrame(This,pAvgTimePerFrame) (This)->lpVtbl->get_AvgTimePerFrame(This,pAvgTimePerFrame) -#define IBasicVideo_get_BitRate(This,pBitRate) (This)->lpVtbl->get_BitRate(This,pBitRate) -#define IBasicVideo_get_BitErrorRate(This,pBitErrorRate) (This)->lpVtbl->get_BitErrorRate(This,pBitErrorRate) -#define IBasicVideo_get_VideoWidth(This,pVideoWidth) (This)->lpVtbl->get_VideoWidth(This,pVideoWidth) -#define IBasicVideo_get_VideoHeight(This,pVideoHeight) (This)->lpVtbl->get_VideoHeight(This,pVideoHeight) -#define IBasicVideo_put_SourceLeft(This,SourceLeft) (This)->lpVtbl->put_SourceLeft(This,SourceLeft) -#define IBasicVideo_get_SourceLeft(This,pSourceLeft) (This)->lpVtbl->get_SourceLeft(This,pSourceLeft) -#define IBasicVideo_put_SourceWidth(This,SourceWidth) (This)->lpVtbl->put_SourceWidth(This,SourceWidth) -#define IBasicVideo_get_SourceWidth(This,pSourceWidth) (This)->lpVtbl->get_SourceWidth(This,pSourceWidth) -#define IBasicVideo_put_SourceTop(This,SourceTop) (This)->lpVtbl->put_SourceTop(This,SourceTop) -#define IBasicVideo_get_SourceTop(This,pSourceTop) (This)->lpVtbl->get_SourceTop(This,pSourceTop) -#define IBasicVideo_put_SourceHeight(This,SourceHeight) (This)->lpVtbl->put_SourceHeight(This,SourceHeight) -#define IBasicVideo_get_SourceHeight(This,pSourceHeight) (This)->lpVtbl->get_SourceHeight(This,pSourceHeight) -#define IBasicVideo_put_DestinationLeft(This,DestinationLeft) (This)->lpVtbl->put_DestinationLeft(This,DestinationLeft) -#define IBasicVideo_get_DestinationLeft(This,pDestinationLeft) (This)->lpVtbl->get_DestinationLeft(This,pDestinationLeft) -#define IBasicVideo_put_DestinationWidth(This,DestinationWidth) (This)->lpVtbl->put_DestinationWidth(This,DestinationWidth) -#define IBasicVideo_get_DestinationWidth(This,pDestinationWidth) (This)->lpVtbl->get_DestinationWidth(This,pDestinationWidth) -#define IBasicVideo_put_DestinationTop(This,DestinationTop) (This)->lpVtbl->put_DestinationTop(This,DestinationTop) -#define IBasicVideo_get_DestinationTop(This,pDestinationTop) (This)->lpVtbl->get_DestinationTop(This,pDestinationTop) -#define IBasicVideo_put_DestinationHeight(This,DestinationHeight) (This)->lpVtbl->put_DestinationHeight(This,DestinationHeight) -#define IBasicVideo_get_DestinationHeight(This,pDestinationHeight) (This)->lpVtbl->get_DestinationHeight(This,pDestinationHeight) -#define IBasicVideo_SetSourcePosition(This,Left,Top,Width,Height) (This)->lpVtbl->SetSourcePosition(This,Left,Top,Width,Height) -#define IBasicVideo_GetSourcePosition(This,pLeft,pTop,pWidth,pHeight) (This)->lpVtbl->GetSourcePosition(This,pLeft,pTop,pWidth,pHeight) -#define IBasicVideo_SetDefaultSourcePosition(This) (This)->lpVtbl->SetDefaultSourcePosition(This) -#define IBasicVideo_SetDestinationPosition(This,Left,Top,Width,Height) (This)->lpVtbl->SetDestinationPosition(This,Left,Top,Width,Height) -#define IBasicVideo_GetDestinationPosition(This,pLeft,pTop,pWidth,pHeight) (This)->lpVtbl->GetDestinationPosition(This,pLeft,pTop,pWidth,pHeight) -#define IBasicVideo_SetDefaultDestinationPosition(This) (This)->lpVtbl->SetDefaultDestinationPosition(This) -#define IBasicVideo_GetVideoSize(This,pWidth,pHeight) (This)->lpVtbl->GetVideoSize(This,pWidth,pHeight) -#define IBasicVideo_GetVideoPaletteEntries(This,StartIndex,Entries,pRetrieved,pPalette) (This)->lpVtbl->GetVideoPaletteEntries(This,StartIndex,Entries,pRetrieved,pPalette) -#define IBasicVideo_GetCurrentImage(This,pBufferSize,pDIBImage) (This)->lpVtbl->GetCurrentImage(This,pBufferSize,pDIBImage) -#define IBasicVideo_IsUsingDefaultSource(This) (This)->lpVtbl->IsUsingDefaultSource(This) -#define IBasicVideo_IsUsingDefaultDestination(This) (This)->lpVtbl->IsUsingDefaultDestination(This) -#endif -#endif - HRESULT WINAPI IBasicVideo_get_AvgTimePerFrame_Proxy(IBasicVideo *This,REFTIME *pAvgTimePerFrame); - void __RPC_STUB IBasicVideo_get_AvgTimePerFrame_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IBasicVideo_get_BitRate_Proxy(IBasicVideo *This,long *pBitRate); - void __RPC_STUB IBasicVideo_get_BitRate_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IBasicVideo_get_BitErrorRate_Proxy(IBasicVideo *This,long *pBitErrorRate); - void __RPC_STUB IBasicVideo_get_BitErrorRate_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IBasicVideo_get_VideoWidth_Proxy(IBasicVideo *This,long *pVideoWidth); - void __RPC_STUB IBasicVideo_get_VideoWidth_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IBasicVideo_get_VideoHeight_Proxy(IBasicVideo *This,long *pVideoHeight); - void __RPC_STUB IBasicVideo_get_VideoHeight_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IBasicVideo_put_SourceLeft_Proxy(IBasicVideo *This,long SourceLeft); - void __RPC_STUB IBasicVideo_put_SourceLeft_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IBasicVideo_get_SourceLeft_Proxy(IBasicVideo *This,long *pSourceLeft); - void __RPC_STUB IBasicVideo_get_SourceLeft_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IBasicVideo_put_SourceWidth_Proxy(IBasicVideo *This,long SourceWidth); - void __RPC_STUB IBasicVideo_put_SourceWidth_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IBasicVideo_get_SourceWidth_Proxy(IBasicVideo *This,long *pSourceWidth); - void __RPC_STUB IBasicVideo_get_SourceWidth_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IBasicVideo_put_SourceTop_Proxy(IBasicVideo *This,long SourceTop); - void __RPC_STUB IBasicVideo_put_SourceTop_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IBasicVideo_get_SourceTop_Proxy(IBasicVideo *This,long *pSourceTop); - void __RPC_STUB IBasicVideo_get_SourceTop_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IBasicVideo_put_SourceHeight_Proxy(IBasicVideo *This,long SourceHeight); - void __RPC_STUB IBasicVideo_put_SourceHeight_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IBasicVideo_get_SourceHeight_Proxy(IBasicVideo *This,long *pSourceHeight); - void __RPC_STUB IBasicVideo_get_SourceHeight_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IBasicVideo_put_DestinationLeft_Proxy(IBasicVideo *This,long DestinationLeft); - void __RPC_STUB IBasicVideo_put_DestinationLeft_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IBasicVideo_get_DestinationLeft_Proxy(IBasicVideo *This,long *pDestinationLeft); - void __RPC_STUB IBasicVideo_get_DestinationLeft_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IBasicVideo_put_DestinationWidth_Proxy(IBasicVideo *This,long DestinationWidth); - void __RPC_STUB IBasicVideo_put_DestinationWidth_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IBasicVideo_get_DestinationWidth_Proxy(IBasicVideo *This,long *pDestinationWidth); - void __RPC_STUB IBasicVideo_get_DestinationWidth_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IBasicVideo_put_DestinationTop_Proxy(IBasicVideo *This,long DestinationTop); - void __RPC_STUB IBasicVideo_put_DestinationTop_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IBasicVideo_get_DestinationTop_Proxy(IBasicVideo *This,long *pDestinationTop); - void __RPC_STUB IBasicVideo_get_DestinationTop_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IBasicVideo_put_DestinationHeight_Proxy(IBasicVideo *This,long DestinationHeight); - void __RPC_STUB IBasicVideo_put_DestinationHeight_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IBasicVideo_get_DestinationHeight_Proxy(IBasicVideo *This,long *pDestinationHeight); - void __RPC_STUB IBasicVideo_get_DestinationHeight_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IBasicVideo_SetSourcePosition_Proxy(IBasicVideo *This,long Left,long Top,long Width,long Height); - void __RPC_STUB IBasicVideo_SetSourcePosition_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IBasicVideo_GetSourcePosition_Proxy(IBasicVideo *This,long *pLeft,long *pTop,long *pWidth,long *pHeight); - void __RPC_STUB IBasicVideo_GetSourcePosition_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IBasicVideo_SetDefaultSourcePosition_Proxy(IBasicVideo *This); - void __RPC_STUB IBasicVideo_SetDefaultSourcePosition_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IBasicVideo_SetDestinationPosition_Proxy(IBasicVideo *This,long Left,long Top,long Width,long Height); - void __RPC_STUB IBasicVideo_SetDestinationPosition_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IBasicVideo_GetDestinationPosition_Proxy(IBasicVideo *This,long *pLeft,long *pTop,long *pWidth,long *pHeight); - void __RPC_STUB IBasicVideo_GetDestinationPosition_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IBasicVideo_SetDefaultDestinationPosition_Proxy(IBasicVideo *This); - void __RPC_STUB IBasicVideo_SetDefaultDestinationPosition_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IBasicVideo_GetVideoSize_Proxy(IBasicVideo *This,long *pWidth,long *pHeight); - void __RPC_STUB IBasicVideo_GetVideoSize_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IBasicVideo_GetVideoPaletteEntries_Proxy(IBasicVideo *This,long StartIndex,long Entries,long *pRetrieved,long *pPalette); - void __RPC_STUB IBasicVideo_GetVideoPaletteEntries_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IBasicVideo_GetCurrentImage_Proxy(IBasicVideo *This,long *pBufferSize,long *pDIBImage); - void __RPC_STUB IBasicVideo_GetCurrentImage_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IBasicVideo_IsUsingDefaultSource_Proxy(IBasicVideo *This); - void __RPC_STUB IBasicVideo_IsUsingDefaultSource_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IBasicVideo_IsUsingDefaultDestination_Proxy(IBasicVideo *This); - void __RPC_STUB IBasicVideo_IsUsingDefaultDestination_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IBasicVideo2_INTERFACE_DEFINED__ -#define __IBasicVideo2_INTERFACE_DEFINED__ - DEFINE_GUID(IID_IBasicVideo2,0x329bb360,0xf6ea,0x11d1,0x90,0x38,0x00,0xa0,0xc9,0x69,0x72,0x98); -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IBasicVideo2 : public IBasicVideo { - public: - virtual HRESULT WINAPI GetPreferredAspectRatio(long *plAspectX,long *plAspectY) = 0; - }; -#else - typedef struct IBasicVideo2Vtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IBasicVideo2 *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IBasicVideo2 *This); - ULONG (WINAPI *Release)(IBasicVideo2 *This); - HRESULT (WINAPI *GetTypeInfoCount)(IBasicVideo2 *This,UINT *pctinfo); - HRESULT (WINAPI *GetTypeInfo)(IBasicVideo2 *This,UINT iTInfo,LCID lcid,ITypeInfo **ppTInfo); - HRESULT (WINAPI *GetIDsOfNames)(IBasicVideo2 *This,REFIID riid,LPOLESTR *rgszNames,UINT cNames,LCID lcid,DISPID *rgDispId); - HRESULT (WINAPI *Invoke)(IBasicVideo2 *This,DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS *pDispParams,VARIANT *pVarResult,EXCEPINFO *pExcepInfo,UINT *puArgErr); - HRESULT (WINAPI *get_AvgTimePerFrame)(IBasicVideo2 *This,REFTIME *pAvgTimePerFrame); - HRESULT (WINAPI *get_BitRate)(IBasicVideo2 *This,long *pBitRate); - HRESULT (WINAPI *get_BitErrorRate)(IBasicVideo2 *This,long *pBitErrorRate); - HRESULT (WINAPI *get_VideoWidth)(IBasicVideo2 *This,long *pVideoWidth); - HRESULT (WINAPI *get_VideoHeight)(IBasicVideo2 *This,long *pVideoHeight); - HRESULT (WINAPI *put_SourceLeft)(IBasicVideo2 *This,long SourceLeft); - HRESULT (WINAPI *get_SourceLeft)(IBasicVideo2 *This,long *pSourceLeft); - HRESULT (WINAPI *put_SourceWidth)(IBasicVideo2 *This,long SourceWidth); - HRESULT (WINAPI *get_SourceWidth)(IBasicVideo2 *This,long *pSourceWidth); - HRESULT (WINAPI *put_SourceTop)(IBasicVideo2 *This,long SourceTop); - HRESULT (WINAPI *get_SourceTop)(IBasicVideo2 *This,long *pSourceTop); - HRESULT (WINAPI *put_SourceHeight)(IBasicVideo2 *This,long SourceHeight); - HRESULT (WINAPI *get_SourceHeight)(IBasicVideo2 *This,long *pSourceHeight); - HRESULT (WINAPI *put_DestinationLeft)(IBasicVideo2 *This,long DestinationLeft); - HRESULT (WINAPI *get_DestinationLeft)(IBasicVideo2 *This,long *pDestinationLeft); - HRESULT (WINAPI *put_DestinationWidth)(IBasicVideo2 *This,long DestinationWidth); - HRESULT (WINAPI *get_DestinationWidth)(IBasicVideo2 *This,long *pDestinationWidth); - HRESULT (WINAPI *put_DestinationTop)(IBasicVideo2 *This,long DestinationTop); - HRESULT (WINAPI *get_DestinationTop)(IBasicVideo2 *This,long *pDestinationTop); - HRESULT (WINAPI *put_DestinationHeight)(IBasicVideo2 *This,long DestinationHeight); - HRESULT (WINAPI *get_DestinationHeight)(IBasicVideo2 *This,long *pDestinationHeight); - HRESULT (WINAPI *SetSourcePosition)(IBasicVideo2 *This,long Left,long Top,long Width,long Height); - HRESULT (WINAPI *GetSourcePosition)(IBasicVideo2 *This,long *pLeft,long *pTop,long *pWidth,long *pHeight); - HRESULT (WINAPI *SetDefaultSourcePosition)(IBasicVideo2 *This); - HRESULT (WINAPI *SetDestinationPosition)(IBasicVideo2 *This,long Left,long Top,long Width,long Height); - HRESULT (WINAPI *GetDestinationPosition)(IBasicVideo2 *This,long *pLeft,long *pTop,long *pWidth,long *pHeight); - HRESULT (WINAPI *SetDefaultDestinationPosition)(IBasicVideo2 *This); - HRESULT (WINAPI *GetVideoSize)(IBasicVideo2 *This,long *pWidth,long *pHeight); - HRESULT (WINAPI *GetVideoPaletteEntries)(IBasicVideo2 *This,long StartIndex,long Entries,long *pRetrieved,long *pPalette); - HRESULT (WINAPI *GetCurrentImage)(IBasicVideo2 *This,long *pBufferSize,long *pDIBImage); - HRESULT (WINAPI *IsUsingDefaultSource)(IBasicVideo2 *This); - HRESULT (WINAPI *IsUsingDefaultDestination)(IBasicVideo2 *This); - HRESULT (WINAPI *GetPreferredAspectRatio)(IBasicVideo2 *This,long *plAspectX,long *plAspectY); - END_INTERFACE - } IBasicVideo2Vtbl; - struct IBasicVideo2 { - CONST_VTBL struct IBasicVideo2Vtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IBasicVideo2_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IBasicVideo2_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IBasicVideo2_Release(This) (This)->lpVtbl->Release(This) -#define IBasicVideo2_GetTypeInfoCount(This,pctinfo) (This)->lpVtbl->GetTypeInfoCount(This,pctinfo) -#define IBasicVideo2_GetTypeInfo(This,iTInfo,lcid,ppTInfo) (This)->lpVtbl->GetTypeInfo(This,iTInfo,lcid,ppTInfo) -#define IBasicVideo2_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) (This)->lpVtbl->GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) -#define IBasicVideo2_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) (This)->lpVtbl->Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) -#define IBasicVideo2_get_AvgTimePerFrame(This,pAvgTimePerFrame) (This)->lpVtbl->get_AvgTimePerFrame(This,pAvgTimePerFrame) -#define IBasicVideo2_get_BitRate(This,pBitRate) (This)->lpVtbl->get_BitRate(This,pBitRate) -#define IBasicVideo2_get_BitErrorRate(This,pBitErrorRate) (This)->lpVtbl->get_BitErrorRate(This,pBitErrorRate) -#define IBasicVideo2_get_VideoWidth(This,pVideoWidth) (This)->lpVtbl->get_VideoWidth(This,pVideoWidth) -#define IBasicVideo2_get_VideoHeight(This,pVideoHeight) (This)->lpVtbl->get_VideoHeight(This,pVideoHeight) -#define IBasicVideo2_put_SourceLeft(This,SourceLeft) (This)->lpVtbl->put_SourceLeft(This,SourceLeft) -#define IBasicVideo2_get_SourceLeft(This,pSourceLeft) (This)->lpVtbl->get_SourceLeft(This,pSourceLeft) -#define IBasicVideo2_put_SourceWidth(This,SourceWidth) (This)->lpVtbl->put_SourceWidth(This,SourceWidth) -#define IBasicVideo2_get_SourceWidth(This,pSourceWidth) (This)->lpVtbl->get_SourceWidth(This,pSourceWidth) -#define IBasicVideo2_put_SourceTop(This,SourceTop) (This)->lpVtbl->put_SourceTop(This,SourceTop) -#define IBasicVideo2_get_SourceTop(This,pSourceTop) (This)->lpVtbl->get_SourceTop(This,pSourceTop) -#define IBasicVideo2_put_SourceHeight(This,SourceHeight) (This)->lpVtbl->put_SourceHeight(This,SourceHeight) -#define IBasicVideo2_get_SourceHeight(This,pSourceHeight) (This)->lpVtbl->get_SourceHeight(This,pSourceHeight) -#define IBasicVideo2_put_DestinationLeft(This,DestinationLeft) (This)->lpVtbl->put_DestinationLeft(This,DestinationLeft) -#define IBasicVideo2_get_DestinationLeft(This,pDestinationLeft) (This)->lpVtbl->get_DestinationLeft(This,pDestinationLeft) -#define IBasicVideo2_put_DestinationWidth(This,DestinationWidth) (This)->lpVtbl->put_DestinationWidth(This,DestinationWidth) -#define IBasicVideo2_get_DestinationWidth(This,pDestinationWidth) (This)->lpVtbl->get_DestinationWidth(This,pDestinationWidth) -#define IBasicVideo2_put_DestinationTop(This,DestinationTop) (This)->lpVtbl->put_DestinationTop(This,DestinationTop) -#define IBasicVideo2_get_DestinationTop(This,pDestinationTop) (This)->lpVtbl->get_DestinationTop(This,pDestinationTop) -#define IBasicVideo2_put_DestinationHeight(This,DestinationHeight) (This)->lpVtbl->put_DestinationHeight(This,DestinationHeight) -#define IBasicVideo2_get_DestinationHeight(This,pDestinationHeight) (This)->lpVtbl->get_DestinationHeight(This,pDestinationHeight) -#define IBasicVideo2_SetSourcePosition(This,Left,Top,Width,Height) (This)->lpVtbl->SetSourcePosition(This,Left,Top,Width,Height) -#define IBasicVideo2_GetSourcePosition(This,pLeft,pTop,pWidth,pHeight) (This)->lpVtbl->GetSourcePosition(This,pLeft,pTop,pWidth,pHeight) -#define IBasicVideo2_SetDefaultSourcePosition(This) (This)->lpVtbl->SetDefaultSourcePosition(This) -#define IBasicVideo2_SetDestinationPosition(This,Left,Top,Width,Height) (This)->lpVtbl->SetDestinationPosition(This,Left,Top,Width,Height) -#define IBasicVideo2_GetDestinationPosition(This,pLeft,pTop,pWidth,pHeight) (This)->lpVtbl->GetDestinationPosition(This,pLeft,pTop,pWidth,pHeight) -#define IBasicVideo2_SetDefaultDestinationPosition(This) (This)->lpVtbl->SetDefaultDestinationPosition(This) -#define IBasicVideo2_GetVideoSize(This,pWidth,pHeight) (This)->lpVtbl->GetVideoSize(This,pWidth,pHeight) -#define IBasicVideo2_GetVideoPaletteEntries(This,StartIndex,Entries,pRetrieved,pPalette) (This)->lpVtbl->GetVideoPaletteEntries(This,StartIndex,Entries,pRetrieved,pPalette) -#define IBasicVideo2_GetCurrentImage(This,pBufferSize,pDIBImage) (This)->lpVtbl->GetCurrentImage(This,pBufferSize,pDIBImage) -#define IBasicVideo2_IsUsingDefaultSource(This) (This)->lpVtbl->IsUsingDefaultSource(This) -#define IBasicVideo2_IsUsingDefaultDestination(This) (This)->lpVtbl->IsUsingDefaultDestination(This) -#define IBasicVideo2_GetPreferredAspectRatio(This,plAspectX,plAspectY) (This)->lpVtbl->GetPreferredAspectRatio(This,plAspectX,plAspectY) -#endif -#endif - HRESULT WINAPI IBasicVideo2_GetPreferredAspectRatio_Proxy(IBasicVideo2 *This,long *plAspectX,long *plAspectY); - void __RPC_STUB IBasicVideo2_GetPreferredAspectRatio_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IDeferredCommand_INTERFACE_DEFINED__ -#define __IDeferredCommand_INTERFACE_DEFINED__ - DEFINE_GUID(IID_IDeferredCommand,0x56a868b8,0x0ad4,0x11ce,0xb0,0x3a,0x00,0x20,0xaf,0x0b,0xa7,0x70); -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IDeferredCommand : public IUnknown { - public: - virtual HRESULT WINAPI Cancel(void) = 0; - virtual HRESULT WINAPI Confidence(LONG *pConfidence) = 0; - virtual HRESULT WINAPI Postpone(REFTIME newtime) = 0; - virtual HRESULT WINAPI GetHResult(HRESULT *phrResult) = 0; - }; -#else - typedef struct IDeferredCommandVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IDeferredCommand *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IDeferredCommand *This); - ULONG (WINAPI *Release)(IDeferredCommand *This); - HRESULT (WINAPI *Cancel)(IDeferredCommand *This); - HRESULT (WINAPI *Confidence)(IDeferredCommand *This,LONG *pConfidence); - HRESULT (WINAPI *Postpone)(IDeferredCommand *This,REFTIME newtime); - HRESULT (WINAPI *GetHResult)(IDeferredCommand *This,HRESULT *phrResult); - END_INTERFACE - } IDeferredCommandVtbl; - struct IDeferredCommand { - CONST_VTBL struct IDeferredCommandVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IDeferredCommand_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IDeferredCommand_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IDeferredCommand_Release(This) (This)->lpVtbl->Release(This) -#define IDeferredCommand_Cancel(This) (This)->lpVtbl->Cancel(This) -#define IDeferredCommand_Confidence(This,pConfidence) (This)->lpVtbl->Confidence(This,pConfidence) -#define IDeferredCommand_Postpone(This,newtime) (This)->lpVtbl->Postpone(This,newtime) -#define IDeferredCommand_GetHResult(This,phrResult) (This)->lpVtbl->GetHResult(This,phrResult) -#endif -#endif - HRESULT WINAPI IDeferredCommand_Cancel_Proxy(IDeferredCommand *This); - void __RPC_STUB IDeferredCommand_Cancel_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDeferredCommand_Confidence_Proxy(IDeferredCommand *This,LONG *pConfidence); - void __RPC_STUB IDeferredCommand_Confidence_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDeferredCommand_Postpone_Proxy(IDeferredCommand *This,REFTIME newtime); - void __RPC_STUB IDeferredCommand_Postpone_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDeferredCommand_GetHResult_Proxy(IDeferredCommand *This,HRESULT *phrResult); - void __RPC_STUB IDeferredCommand_GetHResult_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IQueueCommand_INTERFACE_DEFINED__ -#define __IQueueCommand_INTERFACE_DEFINED__ - DEFINE_GUID(IID_IQueueCommand,0x56a868b7,0x0ad4,0x11ce,0xb0,0x3a,0x00,0x20,0xaf,0x0b,0xa7,0x70); -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IQueueCommand : public IUnknown { - public: - virtual HRESULT WINAPI InvokeAtStreamTime(IDeferredCommand **pCmd,REFTIME time,GUID *iid,long dispidMethod,short wFlags,long cArgs,VARIANT *pDispParams,VARIANT *pvarResult,short *puArgErr) = 0; - virtual HRESULT WINAPI InvokeAtPresentationTime(IDeferredCommand **pCmd,REFTIME time,GUID *iid,long dispidMethod,short wFlags,long cArgs,VARIANT *pDispParams,VARIANT *pvarResult,short *puArgErr) = 0; - }; -#else - typedef struct IQueueCommandVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IQueueCommand *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IQueueCommand *This); - ULONG (WINAPI *Release)(IQueueCommand *This); - HRESULT (WINAPI *InvokeAtStreamTime)(IQueueCommand *This,IDeferredCommand **pCmd,REFTIME time,GUID *iid,long dispidMethod,short wFlags,long cArgs,VARIANT *pDispParams,VARIANT *pvarResult,short *puArgErr); - HRESULT (WINAPI *InvokeAtPresentationTime)(IQueueCommand *This,IDeferredCommand **pCmd,REFTIME time,GUID *iid,long dispidMethod,short wFlags,long cArgs,VARIANT *pDispParams,VARIANT *pvarResult,short *puArgErr); - END_INTERFACE - } IQueueCommandVtbl; - struct IQueueCommand { - CONST_VTBL struct IQueueCommandVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IQueueCommand_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IQueueCommand_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IQueueCommand_Release(This) (This)->lpVtbl->Release(This) -#define IQueueCommand_InvokeAtStreamTime(This,pCmd,time,iid,dispidMethod,wFlags,cArgs,pDispParams,pvarResult,puArgErr) (This)->lpVtbl->InvokeAtStreamTime(This,pCmd,time,iid,dispidMethod,wFlags,cArgs,pDispParams,pvarResult,puArgErr) -#define IQueueCommand_InvokeAtPresentationTime(This,pCmd,time,iid,dispidMethod,wFlags,cArgs,pDispParams,pvarResult,puArgErr) (This)->lpVtbl->InvokeAtPresentationTime(This,pCmd,time,iid,dispidMethod,wFlags,cArgs,pDispParams,pvarResult,puArgErr) -#endif -#endif - HRESULT WINAPI IQueueCommand_InvokeAtStreamTime_Proxy(IQueueCommand *This,IDeferredCommand **pCmd,REFTIME time,GUID *iid,long dispidMethod,short wFlags,long cArgs,VARIANT *pDispParams,VARIANT *pvarResult,short *puArgErr); - void __RPC_STUB IQueueCommand_InvokeAtStreamTime_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IQueueCommand_InvokeAtPresentationTime_Proxy(IQueueCommand *This,IDeferredCommand **pCmd,REFTIME time,GUID *iid,long dispidMethod,short wFlags,long cArgs,VARIANT *pDispParams,VARIANT *pvarResult,short *puArgErr); - void __RPC_STUB IQueueCommand_InvokeAtPresentationTime_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - DEFINE_GUID(CLSID_FilgraphManager,0xe436ebb3,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70); -#ifdef __cplusplus - class FilgraphManager; -#endif - -#ifndef __IFilterInfo_INTERFACE_DEFINED__ -#define __IFilterInfo_INTERFACE_DEFINED__ - DEFINE_GUID(IID_IFilterInfo,0x56a868ba,0x0ad4,0x11ce,0xb0,0x3a,0x00,0x20,0xaf,0x0b,0xa7,0x70); -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IFilterInfo : public IDispatch { - public: - virtual HRESULT WINAPI FindPin(BSTR strPinID,IDispatch **ppUnk) = 0; - virtual HRESULT WINAPI get_Name(BSTR *strName) = 0; - virtual HRESULT WINAPI get_VendorInfo(BSTR *strVendorInfo) = 0; - virtual HRESULT WINAPI get_Filter(IUnknown **ppUnk) = 0; - virtual HRESULT WINAPI get_Pins(IDispatch **ppUnk) = 0; - virtual HRESULT WINAPI get_IsFileSource(LONG *pbIsSource) = 0; - virtual HRESULT WINAPI get_Filename(BSTR *pstrFilename) = 0; - virtual HRESULT WINAPI put_Filename(BSTR strFilename) = 0; - }; -#else - typedef struct IFilterInfoVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IFilterInfo *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IFilterInfo *This); - ULONG (WINAPI *Release)(IFilterInfo *This); - HRESULT (WINAPI *GetTypeInfoCount)(IFilterInfo *This,UINT *pctinfo); - HRESULT (WINAPI *GetTypeInfo)(IFilterInfo *This,UINT iTInfo,LCID lcid,ITypeInfo **ppTInfo); - HRESULT (WINAPI *GetIDsOfNames)(IFilterInfo *This,REFIID riid,LPOLESTR *rgszNames,UINT cNames,LCID lcid,DISPID *rgDispId); - HRESULT (WINAPI *Invoke)(IFilterInfo *This,DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS *pDispParams,VARIANT *pVarResult,EXCEPINFO *pExcepInfo,UINT *puArgErr); - HRESULT (WINAPI *FindPin)(IFilterInfo *This,BSTR strPinID,IDispatch **ppUnk); - HRESULT (WINAPI *get_Name)(IFilterInfo *This,BSTR *strName); - HRESULT (WINAPI *get_VendorInfo)(IFilterInfo *This,BSTR *strVendorInfo); - HRESULT (WINAPI *get_Filter)(IFilterInfo *This,IUnknown **ppUnk); - HRESULT (WINAPI *get_Pins)(IFilterInfo *This,IDispatch **ppUnk); - HRESULT (WINAPI *get_IsFileSource)(IFilterInfo *This,LONG *pbIsSource); - HRESULT (WINAPI *get_Filename)(IFilterInfo *This,BSTR *pstrFilename); - HRESULT (WINAPI *put_Filename)(IFilterInfo *This,BSTR strFilename); - END_INTERFACE - } IFilterInfoVtbl; - struct IFilterInfo { - CONST_VTBL struct IFilterInfoVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IFilterInfo_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IFilterInfo_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IFilterInfo_Release(This) (This)->lpVtbl->Release(This) -#define IFilterInfo_GetTypeInfoCount(This,pctinfo) (This)->lpVtbl->GetTypeInfoCount(This,pctinfo) -#define IFilterInfo_GetTypeInfo(This,iTInfo,lcid,ppTInfo) (This)->lpVtbl->GetTypeInfo(This,iTInfo,lcid,ppTInfo) -#define IFilterInfo_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) (This)->lpVtbl->GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) -#define IFilterInfo_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) (This)->lpVtbl->Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) -#define IFilterInfo_FindPin(This,strPinID,ppUnk) (This)->lpVtbl->FindPin(This,strPinID,ppUnk) -#define IFilterInfo_get_Name(This,strName) (This)->lpVtbl->get_Name(This,strName) -#define IFilterInfo_get_VendorInfo(This,strVendorInfo) (This)->lpVtbl->get_VendorInfo(This,strVendorInfo) -#define IFilterInfo_get_Filter(This,ppUnk) (This)->lpVtbl->get_Filter(This,ppUnk) -#define IFilterInfo_get_Pins(This,ppUnk) (This)->lpVtbl->get_Pins(This,ppUnk) -#define IFilterInfo_get_IsFileSource(This,pbIsSource) (This)->lpVtbl->get_IsFileSource(This,pbIsSource) -#define IFilterInfo_get_Filename(This,pstrFilename) (This)->lpVtbl->get_Filename(This,pstrFilename) -#define IFilterInfo_put_Filename(This,strFilename) (This)->lpVtbl->put_Filename(This,strFilename) -#endif -#endif - HRESULT WINAPI IFilterInfo_FindPin_Proxy(IFilterInfo *This,BSTR strPinID,IDispatch **ppUnk); - void __RPC_STUB IFilterInfo_FindPin_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IFilterInfo_get_Name_Proxy(IFilterInfo *This,BSTR *strName); - void __RPC_STUB IFilterInfo_get_Name_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IFilterInfo_get_VendorInfo_Proxy(IFilterInfo *This,BSTR *strVendorInfo); - void __RPC_STUB IFilterInfo_get_VendorInfo_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IFilterInfo_get_Filter_Proxy(IFilterInfo *This,IUnknown **ppUnk); - void __RPC_STUB IFilterInfo_get_Filter_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IFilterInfo_get_Pins_Proxy(IFilterInfo *This,IDispatch **ppUnk); - void __RPC_STUB IFilterInfo_get_Pins_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IFilterInfo_get_IsFileSource_Proxy(IFilterInfo *This,LONG *pbIsSource); - void __RPC_STUB IFilterInfo_get_IsFileSource_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IFilterInfo_get_Filename_Proxy(IFilterInfo *This,BSTR *pstrFilename); - void __RPC_STUB IFilterInfo_get_Filename_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IFilterInfo_put_Filename_Proxy(IFilterInfo *This,BSTR strFilename); - void __RPC_STUB IFilterInfo_put_Filename_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IRegFilterInfo_INTERFACE_DEFINED__ -#define __IRegFilterInfo_INTERFACE_DEFINED__ - DEFINE_GUID(IID_IRegFilterInfo,0x56a868bb,0x0ad4,0x11ce,0xb0,0x3a,0x00,0x20,0xaf,0x0b,0xa7,0x70); -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IRegFilterInfo : public IDispatch { - public: - virtual HRESULT WINAPI get_Name(BSTR *strName) = 0; - virtual HRESULT WINAPI Filter(IDispatch **ppUnk) = 0; - }; -#else - typedef struct IRegFilterInfoVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IRegFilterInfo *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IRegFilterInfo *This); - ULONG (WINAPI *Release)(IRegFilterInfo *This); - HRESULT (WINAPI *GetTypeInfoCount)(IRegFilterInfo *This,UINT *pctinfo); - HRESULT (WINAPI *GetTypeInfo)(IRegFilterInfo *This,UINT iTInfo,LCID lcid,ITypeInfo **ppTInfo); - HRESULT (WINAPI *GetIDsOfNames)(IRegFilterInfo *This,REFIID riid,LPOLESTR *rgszNames,UINT cNames,LCID lcid,DISPID *rgDispId); - HRESULT (WINAPI *Invoke)(IRegFilterInfo *This,DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS *pDispParams,VARIANT *pVarResult,EXCEPINFO *pExcepInfo,UINT *puArgErr); - HRESULT (WINAPI *get_Name)(IRegFilterInfo *This,BSTR *strName); - HRESULT (WINAPI *Filter)(IRegFilterInfo *This,IDispatch **ppUnk); - END_INTERFACE - } IRegFilterInfoVtbl; - struct IRegFilterInfo { - CONST_VTBL struct IRegFilterInfoVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IRegFilterInfo_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IRegFilterInfo_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IRegFilterInfo_Release(This) (This)->lpVtbl->Release(This) -#define IRegFilterInfo_GetTypeInfoCount(This,pctinfo) (This)->lpVtbl->GetTypeInfoCount(This,pctinfo) -#define IRegFilterInfo_GetTypeInfo(This,iTInfo,lcid,ppTInfo) (This)->lpVtbl->GetTypeInfo(This,iTInfo,lcid,ppTInfo) -#define IRegFilterInfo_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) (This)->lpVtbl->GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) -#define IRegFilterInfo_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) (This)->lpVtbl->Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) -#define IRegFilterInfo_get_Name(This,strName) (This)->lpVtbl->get_Name(This,strName) -#define IRegFilterInfo_Filter(This,ppUnk) (This)->lpVtbl->Filter(This,ppUnk) -#endif -#endif - HRESULT WINAPI IRegFilterInfo_get_Name_Proxy(IRegFilterInfo *This,BSTR *strName); - void __RPC_STUB IRegFilterInfo_get_Name_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IRegFilterInfo_Filter_Proxy(IRegFilterInfo *This,IDispatch **ppUnk); - void __RPC_STUB IRegFilterInfo_Filter_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IMediaTypeInfo_INTERFACE_DEFINED__ -#define __IMediaTypeInfo_INTERFACE_DEFINED__ - DEFINE_GUID(IID_IMediaTypeInfo,0x56a868bc,0x0ad4,0x11ce,0xb0,0x3a,0x00,0x20,0xaf,0x0b,0xa7,0x70); -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IMediaTypeInfo : public IDispatch { - public: - virtual HRESULT WINAPI get_Type(BSTR *strType) = 0; - virtual HRESULT WINAPI get_Subtype(BSTR *strType) = 0; - }; -#else - typedef struct IMediaTypeInfoVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IMediaTypeInfo *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IMediaTypeInfo *This); - ULONG (WINAPI *Release)(IMediaTypeInfo *This); - HRESULT (WINAPI *GetTypeInfoCount)(IMediaTypeInfo *This,UINT *pctinfo); - HRESULT (WINAPI *GetTypeInfo)(IMediaTypeInfo *This,UINT iTInfo,LCID lcid,ITypeInfo **ppTInfo); - HRESULT (WINAPI *GetIDsOfNames)(IMediaTypeInfo *This,REFIID riid,LPOLESTR *rgszNames,UINT cNames,LCID lcid,DISPID *rgDispId); - HRESULT (WINAPI *Invoke)(IMediaTypeInfo *This,DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS *pDispParams,VARIANT *pVarResult,EXCEPINFO *pExcepInfo,UINT *puArgErr); - HRESULT (WINAPI *get_Type)(IMediaTypeInfo *This,BSTR *strType); - HRESULT (WINAPI *get_Subtype)(IMediaTypeInfo *This,BSTR *strType); - END_INTERFACE - } IMediaTypeInfoVtbl; - struct IMediaTypeInfo { - CONST_VTBL struct IMediaTypeInfoVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IMediaTypeInfo_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IMediaTypeInfo_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IMediaTypeInfo_Release(This) (This)->lpVtbl->Release(This) -#define IMediaTypeInfo_GetTypeInfoCount(This,pctinfo) (This)->lpVtbl->GetTypeInfoCount(This,pctinfo) -#define IMediaTypeInfo_GetTypeInfo(This,iTInfo,lcid,ppTInfo) (This)->lpVtbl->GetTypeInfo(This,iTInfo,lcid,ppTInfo) -#define IMediaTypeInfo_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) (This)->lpVtbl->GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) -#define IMediaTypeInfo_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) (This)->lpVtbl->Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) -#define IMediaTypeInfo_get_Type(This,strType) (This)->lpVtbl->get_Type(This,strType) -#define IMediaTypeInfo_get_Subtype(This,strType) (This)->lpVtbl->get_Subtype(This,strType) -#endif -#endif - HRESULT WINAPI IMediaTypeInfo_get_Type_Proxy(IMediaTypeInfo *This,BSTR *strType); - void __RPC_STUB IMediaTypeInfo_get_Type_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMediaTypeInfo_get_Subtype_Proxy(IMediaTypeInfo *This,BSTR *strType); - void __RPC_STUB IMediaTypeInfo_get_Subtype_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IPinInfo_INTERFACE_DEFINED__ -#define __IPinInfo_INTERFACE_DEFINED__ - DEFINE_GUID(IID_IPinInfo,0x56a868bd,0x0ad4,0x11ce,0xb0,0x3a,0x00,0x20,0xaf,0x0b,0xa7,0x70); -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IPinInfo : public IDispatch { - public: - virtual HRESULT WINAPI get_Pin(IUnknown **ppUnk) = 0; - virtual HRESULT WINAPI get_ConnectedTo(IDispatch **ppUnk) = 0; - virtual HRESULT WINAPI get_ConnectionMediaType(IDispatch **ppUnk) = 0; - virtual HRESULT WINAPI get_FilterInfo(IDispatch **ppUnk) = 0; - virtual HRESULT WINAPI get_Name(BSTR *ppUnk) = 0; - virtual HRESULT WINAPI get_Direction(LONG *ppDirection) = 0; - virtual HRESULT WINAPI get_PinID(BSTR *strPinID) = 0; - virtual HRESULT WINAPI get_MediaTypes(IDispatch **ppUnk) = 0; - virtual HRESULT WINAPI Connect(IUnknown *pPin) = 0; - virtual HRESULT WINAPI ConnectDirect(IUnknown *pPin) = 0; - virtual HRESULT WINAPI ConnectWithType(IUnknown *pPin,IDispatch *pMediaType) = 0; - virtual HRESULT WINAPI Disconnect(void) = 0; - virtual HRESULT WINAPI Render(void) = 0; - }; -#else - typedef struct IPinInfoVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IPinInfo *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IPinInfo *This); - ULONG (WINAPI *Release)(IPinInfo *This); - HRESULT (WINAPI *GetTypeInfoCount)(IPinInfo *This,UINT *pctinfo); - HRESULT (WINAPI *GetTypeInfo)(IPinInfo *This,UINT iTInfo,LCID lcid,ITypeInfo **ppTInfo); - HRESULT (WINAPI *GetIDsOfNames)(IPinInfo *This,REFIID riid,LPOLESTR *rgszNames,UINT cNames,LCID lcid,DISPID *rgDispId); - HRESULT (WINAPI *Invoke)(IPinInfo *This,DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS *pDispParams,VARIANT *pVarResult,EXCEPINFO *pExcepInfo,UINT *puArgErr); - HRESULT (WINAPI *get_Pin)(IPinInfo *This,IUnknown **ppUnk); - HRESULT (WINAPI *get_ConnectedTo)(IPinInfo *This,IDispatch **ppUnk); - HRESULT (WINAPI *get_ConnectionMediaType)(IPinInfo *This,IDispatch **ppUnk); - HRESULT (WINAPI *get_FilterInfo)(IPinInfo *This,IDispatch **ppUnk); - HRESULT (WINAPI *get_Name)(IPinInfo *This,BSTR *ppUnk); - HRESULT (WINAPI *get_Direction)(IPinInfo *This,LONG *ppDirection); - HRESULT (WINAPI *get_PinID)(IPinInfo *This,BSTR *strPinID); - HRESULT (WINAPI *get_MediaTypes)(IPinInfo *This,IDispatch **ppUnk); - HRESULT (WINAPI *Connect)(IPinInfo *This,IUnknown *pPin); - HRESULT (WINAPI *ConnectDirect)(IPinInfo *This,IUnknown *pPin); - HRESULT (WINAPI *ConnectWithType)(IPinInfo *This,IUnknown *pPin,IDispatch *pMediaType); - HRESULT (WINAPI *Disconnect)(IPinInfo *This); - HRESULT (WINAPI *Render)(IPinInfo *This); - END_INTERFACE - } IPinInfoVtbl; - struct IPinInfo { - CONST_VTBL struct IPinInfoVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IPinInfo_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IPinInfo_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IPinInfo_Release(This) (This)->lpVtbl->Release(This) -#define IPinInfo_GetTypeInfoCount(This,pctinfo) (This)->lpVtbl->GetTypeInfoCount(This,pctinfo) -#define IPinInfo_GetTypeInfo(This,iTInfo,lcid,ppTInfo) (This)->lpVtbl->GetTypeInfo(This,iTInfo,lcid,ppTInfo) -#define IPinInfo_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) (This)->lpVtbl->GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) -#define IPinInfo_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) (This)->lpVtbl->Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) -#define IPinInfo_get_Pin(This,ppUnk) (This)->lpVtbl->get_Pin(This,ppUnk) -#define IPinInfo_get_ConnectedTo(This,ppUnk) (This)->lpVtbl->get_ConnectedTo(This,ppUnk) -#define IPinInfo_get_ConnectionMediaType(This,ppUnk) (This)->lpVtbl->get_ConnectionMediaType(This,ppUnk) -#define IPinInfo_get_FilterInfo(This,ppUnk) (This)->lpVtbl->get_FilterInfo(This,ppUnk) -#define IPinInfo_get_Name(This,ppUnk) (This)->lpVtbl->get_Name(This,ppUnk) -#define IPinInfo_get_Direction(This,ppDirection) (This)->lpVtbl->get_Direction(This,ppDirection) -#define IPinInfo_get_PinID(This,strPinID) (This)->lpVtbl->get_PinID(This,strPinID) -#define IPinInfo_get_MediaTypes(This,ppUnk) (This)->lpVtbl->get_MediaTypes(This,ppUnk) -#define IPinInfo_Connect(This,pPin) (This)->lpVtbl->Connect(This,pPin) -#define IPinInfo_ConnectDirect(This,pPin) (This)->lpVtbl->ConnectDirect(This,pPin) -#define IPinInfo_ConnectWithType(This,pPin,pMediaType) (This)->lpVtbl->ConnectWithType(This,pPin,pMediaType) -#define IPinInfo_Disconnect(This) (This)->lpVtbl->Disconnect(This) -#define IPinInfo_Render(This) (This)->lpVtbl->Render(This) -#endif -#endif - HRESULT WINAPI IPinInfo_get_Pin_Proxy(IPinInfo *This,IUnknown **ppUnk); - void __RPC_STUB IPinInfo_get_Pin_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IPinInfo_get_ConnectedTo_Proxy(IPinInfo *This,IDispatch **ppUnk); - void __RPC_STUB IPinInfo_get_ConnectedTo_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IPinInfo_get_ConnectionMediaType_Proxy(IPinInfo *This,IDispatch **ppUnk); - void __RPC_STUB IPinInfo_get_ConnectionMediaType_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IPinInfo_get_FilterInfo_Proxy(IPinInfo *This,IDispatch **ppUnk); - void __RPC_STUB IPinInfo_get_FilterInfo_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IPinInfo_get_Name_Proxy(IPinInfo *This,BSTR *ppUnk); - void __RPC_STUB IPinInfo_get_Name_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IPinInfo_get_Direction_Proxy(IPinInfo *This,LONG *ppDirection); - void __RPC_STUB IPinInfo_get_Direction_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IPinInfo_get_PinID_Proxy(IPinInfo *This,BSTR *strPinID); - void __RPC_STUB IPinInfo_get_PinID_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IPinInfo_get_MediaTypes_Proxy(IPinInfo *This,IDispatch **ppUnk); - void __RPC_STUB IPinInfo_get_MediaTypes_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IPinInfo_Connect_Proxy(IPinInfo *This,IUnknown *pPin); - void __RPC_STUB IPinInfo_Connect_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IPinInfo_ConnectDirect_Proxy(IPinInfo *This,IUnknown *pPin); - void __RPC_STUB IPinInfo_ConnectDirect_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IPinInfo_ConnectWithType_Proxy(IPinInfo *This,IUnknown *pPin,IDispatch *pMediaType); - void __RPC_STUB IPinInfo_ConnectWithType_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IPinInfo_Disconnect_Proxy(IPinInfo *This); - void __RPC_STUB IPinInfo_Disconnect_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IPinInfo_Render_Proxy(IPinInfo *This); - void __RPC_STUB IPinInfo_Render_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IAMStats_INTERFACE_DEFINED__ -#define __IAMStats_INTERFACE_DEFINED__ - DEFINE_GUID(IID_IAMStats,0xbc9bcf80,0xdcd2,0x11d2,0xab,0xf6,0x00,0xa0,0xc9,0x05,0xf3,0x75); -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IAMStats : public IDispatch { - public: - virtual HRESULT WINAPI Reset(void) = 0; - virtual HRESULT WINAPI get_Count(LONG *plCount) = 0; - virtual HRESULT WINAPI GetValueByIndex(long lIndex,BSTR *szName,long *lCount,double *dLast,double *dAverage,double *dStdDev,double *dMin,double *dMax) = 0; - virtual HRESULT WINAPI GetValueByName(BSTR szName,long *lIndex,long *lCount,double *dLast,double *dAverage,double *dStdDev,double *dMin,double *dMax) = 0; - virtual HRESULT WINAPI GetIndex(BSTR szName,long lCreate,long *plIndex) = 0; - virtual HRESULT WINAPI AddValue(long lIndex,double dValue) = 0; - }; -#else - typedef struct IAMStatsVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IAMStats *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IAMStats *This); - ULONG (WINAPI *Release)(IAMStats *This); - HRESULT (WINAPI *GetTypeInfoCount)(IAMStats *This,UINT *pctinfo); - HRESULT (WINAPI *GetTypeInfo)(IAMStats *This,UINT iTInfo,LCID lcid,ITypeInfo **ppTInfo); - HRESULT (WINAPI *GetIDsOfNames)(IAMStats *This,REFIID riid,LPOLESTR *rgszNames,UINT cNames,LCID lcid,DISPID *rgDispId); - HRESULT (WINAPI *Invoke)(IAMStats *This,DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS *pDispParams,VARIANT *pVarResult,EXCEPINFO *pExcepInfo,UINT *puArgErr); - HRESULT (WINAPI *Reset)(IAMStats *This); - HRESULT (WINAPI *get_Count)(IAMStats *This,LONG *plCount); - HRESULT (WINAPI *GetValueByIndex)(IAMStats *This,long lIndex,BSTR *szName,long *lCount,double *dLast,double *dAverage,double *dStdDev,double *dMin,double *dMax); - HRESULT (WINAPI *GetValueByName)(IAMStats *This,BSTR szName,long *lIndex,long *lCount,double *dLast,double *dAverage,double *dStdDev,double *dMin,double *dMax); - HRESULT (WINAPI *GetIndex)(IAMStats *This,BSTR szName,long lCreate,long *plIndex); - HRESULT (WINAPI *AddValue)(IAMStats *This,long lIndex,double dValue); - END_INTERFACE - } IAMStatsVtbl; - struct IAMStats { - CONST_VTBL struct IAMStatsVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IAMStats_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IAMStats_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IAMStats_Release(This) (This)->lpVtbl->Release(This) -#define IAMStats_GetTypeInfoCount(This,pctinfo) (This)->lpVtbl->GetTypeInfoCount(This,pctinfo) -#define IAMStats_GetTypeInfo(This,iTInfo,lcid,ppTInfo) (This)->lpVtbl->GetTypeInfo(This,iTInfo,lcid,ppTInfo) -#define IAMStats_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) (This)->lpVtbl->GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) -#define IAMStats_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) (This)->lpVtbl->Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) -#define IAMStats_Reset(This) (This)->lpVtbl->Reset(This) -#define IAMStats_get_Count(This,plCount) (This)->lpVtbl->get_Count(This,plCount) -#define IAMStats_GetValueByIndex(This,lIndex,szName,lCount,dLast,dAverage,dStdDev,dMin,dMax) (This)->lpVtbl->GetValueByIndex(This,lIndex,szName,lCount,dLast,dAverage,dStdDev,dMin,dMax) -#define IAMStats_GetValueByName(This,szName,lIndex,lCount,dLast,dAverage,dStdDev,dMin,dMax) (This)->lpVtbl->GetValueByName(This,szName,lIndex,lCount,dLast,dAverage,dStdDev,dMin,dMax) -#define IAMStats_GetIndex(This,szName,lCreate,plIndex) (This)->lpVtbl->GetIndex(This,szName,lCreate,plIndex) -#define IAMStats_AddValue(This,lIndex,dValue) (This)->lpVtbl->AddValue(This,lIndex,dValue) -#endif -#endif - - HRESULT WINAPI IAMStats_Reset_Proxy(IAMStats *This); - void __RPC_STUB IAMStats_Reset_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMStats_get_Count_Proxy(IAMStats *This,LONG *plCount); - void __RPC_STUB IAMStats_get_Count_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMStats_GetValueByIndex_Proxy(IAMStats *This,long lIndex,BSTR *szName,long *lCount,double *dLast,double *dAverage,double *dStdDev,double *dMin,double *dMax); - void __RPC_STUB IAMStats_GetValueByIndex_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMStats_GetValueByName_Proxy(IAMStats *This,BSTR szName,long *lIndex,long *lCount,double *dLast,double *dAverage,double *dStdDev,double *dMin,double *dMax); - void __RPC_STUB IAMStats_GetValueByName_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMStats_GetIndex_Proxy(IAMStats *This,BSTR szName,long lCreate,long *plIndex); - void __RPC_STUB IAMStats_GetIndex_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMStats_AddValue_Proxy(IAMStats *This,long lIndex,double dValue); - void __RPC_STUB IAMStats_AddValue_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif -#endif - -#ifdef __cplusplus -} -#endif -#endif diff --git a/vendor/dshow/ddraw.h b/vendor/dshow/ddraw.h deleted file mode 100644 index 318b1652d..000000000 --- a/vendor/dshow/ddraw.h +++ /dev/null @@ -1,2712 +0,0 @@ -/* - * Copyright (C) the Wine project - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#ifndef __DDRAW_INCLUDED__ -#define __DDRAW_INCLUDED__ - -#define COM_NO_WINDOWS_H -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif /* defined(__cplusplus) */ - -#ifndef DIRECTDRAW_VERSION -#define DIRECTDRAW_VERSION 0x0700 -#endif /* DIRECTDRAW_VERSION */ - -/***************************************************************************** - * Predeclare the interfaces - */ -#ifndef __DDRAW_GUID_DEFINED__ -DEFINE_GUID( CLSID_DirectDraw, 0xD7B70EE0,0x4340,0x11CF,0xB0,0x63,0x00,0x20,0xAF,0xC2,0xCD,0x35 ); -DEFINE_GUID( CLSID_DirectDraw7, 0x3C305196,0x50DB,0x11D3,0x9C,0xFE,0x00,0xC0,0x4F,0xD9,0x30,0xC5 ); -DEFINE_GUID( CLSID_DirectDrawClipper, 0x593817A0,0x7DB3,0x11CF,0xA2,0xDE,0x00,0xAA,0x00,0xb9,0x33,0x56 ); -DEFINE_GUID( IID_IDirectDraw, 0x6C14DB80,0xA733,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60 ); -DEFINE_GUID( IID_IDirectDraw2, 0xB3A6F3E0,0x2B43,0x11CF,0xA2,0xDE,0x00,0xAA,0x00,0xB9,0x33,0x56 ); -DEFINE_GUID( IID_IDirectDraw3, 0x618f8ad4,0x8b7a,0x11d0,0x8f,0xcc,0x0,0xc0,0x4f,0xd9,0x18,0x9d ); -DEFINE_GUID( IID_IDirectDraw4, 0x9c59509a,0x39bd,0x11d1,0x8c,0x4a,0x00,0xc0,0x4f,0xd9,0x30,0xc5 ); -DEFINE_GUID( IID_IDirectDraw7, 0x15e65ec0,0x3b9c,0x11d2,0xb9,0x2f,0x00,0x60,0x97,0x97,0xea,0x5b ); -DEFINE_GUID( IID_IDirectDrawSurface, 0x6C14DB81,0xA733,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60 ); -DEFINE_GUID( IID_IDirectDrawSurface2, 0x57805885,0x6eec,0x11cf,0x94,0x41,0xa8,0x23,0x03,0xc1,0x0e,0x27 ); -DEFINE_GUID( IID_IDirectDrawSurface3, 0xDA044E00,0x69B2,0x11D0,0xA1,0xD5,0x00,0xAA,0x00,0xB8,0xDF,0xBB ); -DEFINE_GUID( IID_IDirectDrawSurface4, 0x0B2B8630,0xAD35,0x11D0,0x8E,0xA6,0x00,0x60,0x97,0x97,0xEA,0x5B ); -DEFINE_GUID( IID_IDirectDrawSurface7, 0x06675a80,0x3b9b,0x11d2,0xb9,0x2f,0x00,0x60,0x97,0x97,0xea,0x5b ); -DEFINE_GUID( IID_IDirectDrawPalette, 0x6C14DB84,0xA733,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60 ); -DEFINE_GUID( IID_IDirectDrawClipper, 0x6C14DB85,0xA733,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60 ); -DEFINE_GUID( IID_IDirectDrawColorControl,0x4B9F0EE0,0x0D7E,0x11D0,0x9B,0x06,0x00,0xA0,0xC9,0x03,0xA3,0xB8 ); -DEFINE_GUID( IID_IDirectDrawGammaControl,0x69C11C3E,0xB46B,0x11D1,0xAD,0x7A,0x00,0xC0,0x4F,0xC2,0x9B,0x4E ); -#endif - -typedef struct IDirectDraw *LPDIRECTDRAW; -typedef struct IDirectDraw2 *LPDIRECTDRAW2; -typedef struct IDirectDraw3 *LPDIRECTDRAW3; -typedef struct IDirectDraw4 *LPDIRECTDRAW4; -typedef struct IDirectDraw7 *LPDIRECTDRAW7; -typedef struct IDirectDrawClipper *LPDIRECTDRAWCLIPPER; -typedef struct IDirectDrawPalette *LPDIRECTDRAWPALETTE; -typedef struct IDirectDrawSurface *LPDIRECTDRAWSURFACE; -typedef struct IDirectDrawSurface2 *LPDIRECTDRAWSURFACE2; -typedef struct IDirectDrawSurface3 *LPDIRECTDRAWSURFACE3; -typedef struct IDirectDrawSurface4 *LPDIRECTDRAWSURFACE4; -typedef struct IDirectDrawSurface7 *LPDIRECTDRAWSURFACE7; -typedef struct IDirectDrawColorControl *LPDIRECTDRAWCOLORCONTROL; -typedef struct IDirectDrawGammaControl *LPDIRECTDRAWGAMMACONTROL; - - -#define DDENUMRET_CANCEL 0 -#define DDENUMRET_OK 1 - -#define DD_OK S_OK -#define DD_FALSE S_FALSE - - -#define _FACDD 0x876 -#define MAKE_DDHRESULT( code ) MAKE_HRESULT( 1, _FACDD, code ) - -#define DDERR_ALREADYINITIALIZED MAKE_DDHRESULT( 5 ) -#define DDERR_CANNOTATTACHSURFACE MAKE_DDHRESULT( 10 ) -#define DDERR_CANNOTDETACHSURFACE MAKE_DDHRESULT( 20 ) -#define DDERR_CURRENTLYNOTAVAIL MAKE_DDHRESULT( 40 ) -#define DDERR_EXCEPTION MAKE_DDHRESULT( 55 ) -#define DDERR_GENERIC E_FAIL -#define DDERR_HEIGHTALIGN MAKE_DDHRESULT( 90 ) -#define DDERR_INCOMPATIBLEPRIMARY MAKE_DDHRESULT( 95 ) -#define DDERR_INVALIDCAPS MAKE_DDHRESULT( 100 ) -#define DDERR_INVALIDCLIPLIST MAKE_DDHRESULT( 110 ) -#define DDERR_INVALIDMODE MAKE_DDHRESULT( 120 ) -#define DDERR_INVALIDOBJECT MAKE_DDHRESULT( 130 ) -#define DDERR_INVALIDPARAMS E_INVALIDARG -#define DDERR_INVALIDPIXELFORMAT MAKE_DDHRESULT( 145 ) -#define DDERR_INVALIDRECT MAKE_DDHRESULT( 150 ) -#define DDERR_LOCKEDSURFACES MAKE_DDHRESULT( 160 ) -#define DDERR_NO3D MAKE_DDHRESULT( 170 ) -#define DDERR_NOALPHAHW MAKE_DDHRESULT( 180 ) -#define DDERR_NOSTEREOHARDWARE MAKE_DDHRESULT( 181 ) -#define DDERR_NOSURFACELEFT MAKE_DDHRESULT( 182 ) -#define DDERR_NOCLIPLIST MAKE_DDHRESULT( 205 ) -#define DDERR_NOCOLORCONVHW MAKE_DDHRESULT( 210 ) -#define DDERR_NOCOOPERATIVELEVELSET MAKE_DDHRESULT( 212 ) -#define DDERR_NOCOLORKEY MAKE_DDHRESULT( 215 ) -#define DDERR_NOCOLORKEYHW MAKE_DDHRESULT( 220 ) -#define DDERR_NODIRECTDRAWSUPPORT MAKE_DDHRESULT( 222 ) -#define DDERR_NOEXCLUSIVEMODE MAKE_DDHRESULT( 225 ) -#define DDERR_NOFLIPHW MAKE_DDHRESULT( 230 ) -#define DDERR_NOGDI MAKE_DDHRESULT( 240 ) -#define DDERR_NOMIRRORHW MAKE_DDHRESULT( 250 ) -#define DDERR_NOTFOUND MAKE_DDHRESULT( 255 ) -#define DDERR_NOOVERLAYHW MAKE_DDHRESULT( 260 ) -#define DDERR_OVERLAPPINGRECTS MAKE_DDHRESULT( 270 ) -#define DDERR_NORASTEROPHW MAKE_DDHRESULT( 280 ) -#define DDERR_NOROTATIONHW MAKE_DDHRESULT( 290 ) -#define DDERR_NOSTRETCHHW MAKE_DDHRESULT( 310 ) -#define DDERR_NOT4BITCOLOR MAKE_DDHRESULT( 316 ) -#define DDERR_NOT4BITCOLORINDEX MAKE_DDHRESULT( 317 ) -#define DDERR_NOT8BITCOLOR MAKE_DDHRESULT( 320 ) -#define DDERR_NOTEXTUREHW MAKE_DDHRESULT( 330 ) -#define DDERR_NOVSYNCHW MAKE_DDHRESULT( 335 ) -#define DDERR_NOZBUFFERHW MAKE_DDHRESULT( 340 ) -#define DDERR_NOZOVERLAYHW MAKE_DDHRESULT( 350 ) -#define DDERR_OUTOFCAPS MAKE_DDHRESULT( 360 ) -#define DDERR_OUTOFMEMORY E_OUTOFMEMORY -#define DDERR_OUTOFVIDEOMEMORY MAKE_DDHRESULT( 380 ) -#define DDERR_OVERLAYCANTCLIP MAKE_DDHRESULT( 382 ) -#define DDERR_OVERLAYCOLORKEYONLYONEACTIVE MAKE_DDHRESULT( 384 ) -#define DDERR_PALETTEBUSY MAKE_DDHRESULT( 387 ) -#define DDERR_COLORKEYNOTSET MAKE_DDHRESULT( 400 ) -#define DDERR_SURFACEALREADYATTACHED MAKE_DDHRESULT( 410 ) -#define DDERR_SURFACEALREADYDEPENDENT MAKE_DDHRESULT( 420 ) -#define DDERR_SURFACEBUSY MAKE_DDHRESULT( 430 ) -#define DDERR_CANTLOCKSURFACE MAKE_DDHRESULT( 435 ) -#define DDERR_SURFACEISOBSCURED MAKE_DDHRESULT( 440 ) -#define DDERR_SURFACELOST MAKE_DDHRESULT( 450 ) -#define DDERR_SURFACENOTATTACHED MAKE_DDHRESULT( 460 ) -#define DDERR_TOOBIGHEIGHT MAKE_DDHRESULT( 470 ) -#define DDERR_TOOBIGSIZE MAKE_DDHRESULT( 480 ) -#define DDERR_TOOBIGWIDTH MAKE_DDHRESULT( 490 ) -#define DDERR_UNSUPPORTED E_NOTIMPL -#define DDERR_UNSUPPORTEDFORMAT MAKE_DDHRESULT( 510 ) -#define DDERR_UNSUPPORTEDMASK MAKE_DDHRESULT( 520 ) -#define DDERR_INVALIDSTREAM MAKE_DDHRESULT( 521 ) -#define DDERR_VERTICALBLANKINPROGRESS MAKE_DDHRESULT( 537 ) -#define DDERR_WASSTILLDRAWING MAKE_DDHRESULT( 540 ) -#define DDERR_DDSCAPSCOMPLEXREQUIRED MAKE_DDHRESULT( 542 ) -#define DDERR_XALIGN MAKE_DDHRESULT( 560 ) -#define DDERR_INVALIDDIRECTDRAWGUID MAKE_DDHRESULT( 561 ) -#define DDERR_DIRECTDRAWALREADYCREATED MAKE_DDHRESULT( 562 ) -#define DDERR_NODIRECTDRAWHW MAKE_DDHRESULT( 563 ) -#define DDERR_PRIMARYSURFACEALREADYEXISTS MAKE_DDHRESULT( 564 ) -#define DDERR_NOEMULATION MAKE_DDHRESULT( 565 ) -#define DDERR_REGIONTOOSMALL MAKE_DDHRESULT( 566 ) -#define DDERR_CLIPPERISUSINGHWND MAKE_DDHRESULT( 567 ) -#define DDERR_NOCLIPPERATTACHED MAKE_DDHRESULT( 568 ) -#define DDERR_NOHWND MAKE_DDHRESULT( 569 ) -#define DDERR_HWNDSUBCLASSED MAKE_DDHRESULT( 570 ) -#define DDERR_HWNDALREADYSET MAKE_DDHRESULT( 571 ) -#define DDERR_NOPALETTEATTACHED MAKE_DDHRESULT( 572 ) -#define DDERR_NOPALETTEHW MAKE_DDHRESULT( 573 ) -#define DDERR_BLTFASTCANTCLIP MAKE_DDHRESULT( 574 ) -#define DDERR_NOBLTHW MAKE_DDHRESULT( 575 ) -#define DDERR_NODDROPSHW MAKE_DDHRESULT( 576 ) -#define DDERR_OVERLAYNOTVISIBLE MAKE_DDHRESULT( 577 ) -#define DDERR_NOOVERLAYDEST MAKE_DDHRESULT( 578 ) -#define DDERR_INVALIDPOSITION MAKE_DDHRESULT( 579 ) -#define DDERR_NOTAOVERLAYSURFACE MAKE_DDHRESULT( 580 ) -#define DDERR_EXCLUSIVEMODEALREADYSET MAKE_DDHRESULT( 581 ) -#define DDERR_NOTFLIPPABLE MAKE_DDHRESULT( 582 ) -#define DDERR_CANTDUPLICATE MAKE_DDHRESULT( 583 ) -#define DDERR_NOTLOCKED MAKE_DDHRESULT( 584 ) -#define DDERR_CANTCREATEDC MAKE_DDHRESULT( 585 ) -#define DDERR_NODC MAKE_DDHRESULT( 586 ) -#define DDERR_WRONGMODE MAKE_DDHRESULT( 587 ) -#define DDERR_IMPLICITLYCREATED MAKE_DDHRESULT( 588 ) -#define DDERR_NOTPALETTIZED MAKE_DDHRESULT( 589 ) -#define DDERR_UNSUPPORTEDMODE MAKE_DDHRESULT( 590 ) -#define DDERR_NOMIPMAPHW MAKE_DDHRESULT( 591 ) -#define DDERR_INVALIDSURFACETYPE MAKE_DDHRESULT( 592 ) -#define DDERR_NOOPTIMIZEHW MAKE_DDHRESULT( 600 ) -#define DDERR_NOTLOADED MAKE_DDHRESULT( 601 ) -#define DDERR_NOFOCUSWINDOW MAKE_DDHRESULT( 602 ) -#define DDERR_NOTONMIPMAPSUBLEVEL MAKE_DDHRESULT( 603 ) -#define DDERR_DCALREADYCREATED MAKE_DDHRESULT( 620 ) -#define DDERR_NONONLOCALVIDMEM MAKE_DDHRESULT( 630 ) -#define DDERR_CANTPAGELOCK MAKE_DDHRESULT( 640 ) -#define DDERR_CANTPAGEUNLOCK MAKE_DDHRESULT( 660 ) -#define DDERR_NOTPAGELOCKED MAKE_DDHRESULT( 680 ) -#define DDERR_MOREDATA MAKE_DDHRESULT( 690 ) -#define DDERR_EXPIRED MAKE_DDHRESULT( 691 ) -#define DDERR_TESTFINISHED MAKE_DDHRESULT( 692 ) -#define DDERR_NEWMODE MAKE_DDHRESULT( 693 ) -#define DDERR_D3DNOTINITIALIZED MAKE_DDHRESULT( 694 ) -#define DDERR_VIDEONOTACTIVE MAKE_DDHRESULT( 695 ) -#define DDERR_NOMONITORINFORMATION MAKE_DDHRESULT( 696 ) -#define DDERR_NODRIVERSUPPORT MAKE_DDHRESULT( 697 ) -#define DDERR_DEVICEDOESNTOWNSURFACE MAKE_DDHRESULT( 699 ) -#define DDERR_NOTINITIALIZED CO_E_NOTINITIALIZED - -/* dwFlags for Blt* */ -#define DDBLT_ALPHADEST 0x00000001 -#define DDBLT_ALPHADESTCONSTOVERRIDE 0x00000002 -#define DDBLT_ALPHADESTNEG 0x00000004 -#define DDBLT_ALPHADESTSURFACEOVERRIDE 0x00000008 -#define DDBLT_ALPHAEDGEBLEND 0x00000010 -#define DDBLT_ALPHASRC 0x00000020 -#define DDBLT_ALPHASRCCONSTOVERRIDE 0x00000040 -#define DDBLT_ALPHASRCNEG 0x00000080 -#define DDBLT_ALPHASRCSURFACEOVERRIDE 0x00000100 -#define DDBLT_ASYNC 0x00000200 -#define DDBLT_COLORFILL 0x00000400 -#define DDBLT_DDFX 0x00000800 -#define DDBLT_DDROPS 0x00001000 -#define DDBLT_KEYDEST 0x00002000 -#define DDBLT_KEYDESTOVERRIDE 0x00004000 -#define DDBLT_KEYSRC 0x00008000 -#define DDBLT_KEYSRCOVERRIDE 0x00010000 -#define DDBLT_ROP 0x00020000 -#define DDBLT_ROTATIONANGLE 0x00040000 -#define DDBLT_ZBUFFER 0x00080000 -#define DDBLT_ZBUFFERDESTCONSTOVERRIDE 0x00100000 -#define DDBLT_ZBUFFERDESTOVERRIDE 0x00200000 -#define DDBLT_ZBUFFERSRCCONSTOVERRIDE 0x00400000 -#define DDBLT_ZBUFFERSRCOVERRIDE 0x00800000 -#define DDBLT_WAIT 0x01000000 -#define DDBLT_DEPTHFILL 0x02000000 -#define DDBLT_DONOTWAIT 0x08000000 - -/* dwTrans for BltFast */ -#define DDBLTFAST_NOCOLORKEY 0x00000000 -#define DDBLTFAST_SRCCOLORKEY 0x00000001 -#define DDBLTFAST_DESTCOLORKEY 0x00000002 -#define DDBLTFAST_WAIT 0x00000010 -#define DDBLTFAST_DONOTWAIT 0x00000020 - -/* dwFlags for Flip */ -#define DDFLIP_WAIT 0x00000001 -#define DDFLIP_EVEN 0x00000002 /* only valid for overlay */ -#define DDFLIP_ODD 0x00000004 /* only valid for overlay */ -#define DDFLIP_NOVSYNC 0x00000008 -#define DDFLIP_STEREO 0x00000010 -#define DDFLIP_DONOTWAIT 0x00000020 -#define DDFLIP_INTERVAL2 0x02000000 -#define DDFLIP_INTERVAL3 0x03000000 -#define DDFLIP_INTERVAL4 0x04000000 - - -/* dwFlags for GetBltStatus */ -#define DDGBS_CANBLT 0x00000001 -#define DDGBS_ISBLTDONE 0x00000002 - -/* dwFlags for IDirectDrawSurface7::GetFlipStatus */ -#define DDGFS_CANFLIP 1L -#define DDGFS_ISFLIPDONE 2L - -/* dwFlags for IDirectDrawSurface7::SetPrivateData */ -#define DDSPD_IUNKNOWNPOINTER 1L -#define DDSPD_VOLATILE 2L - -/* DDSCAPS.dwCaps */ -/* reserved1, was 3d capable */ -#define DDSCAPS_RESERVED1 0x00000001 -/* surface contains alpha information */ -#define DDSCAPS_ALPHA 0x00000002 -/* this surface is a backbuffer */ -#define DDSCAPS_BACKBUFFER 0x00000004 -/* complex surface structure */ -#define DDSCAPS_COMPLEX 0x00000008 -/* part of surface flipping structure */ -#define DDSCAPS_FLIP 0x00000010 -/* this surface is the frontbuffer surface */ -#define DDSCAPS_FRONTBUFFER 0x00000020 -/* this is a plain offscreen surface */ -#define DDSCAPS_OFFSCREENPLAIN 0x00000040 -/* overlay */ -#define DDSCAPS_OVERLAY 0x00000080 -/* palette objects can be created and attached to us */ -#define DDSCAPS_PALETTE 0x00000100 -/* primary surface (the one the user looks at currently)(right eye)*/ -#define DDSCAPS_PRIMARYSURFACE 0x00000200 -/* primary surface for left eye */ -#define DDSCAPS_PRIMARYSURFACELEFT 0x00000400 -/* surface exists in systemmemory */ -#define DDSCAPS_SYSTEMMEMORY 0x00000800 -/* surface can be used as a texture */ -#define DDSCAPS_TEXTURE 0x00001000 -/* surface may be destination for 3d rendering */ -#define DDSCAPS_3DDEVICE 0x00002000 -/* surface exists in videomemory */ -#define DDSCAPS_VIDEOMEMORY 0x00004000 -/* surface changes immediately visible */ -#define DDSCAPS_VISIBLE 0x00008000 -/* write only surface */ -#define DDSCAPS_WRITEONLY 0x00010000 -/* zbuffer surface */ -#define DDSCAPS_ZBUFFER 0x00020000 -/* has its own DC */ -#define DDSCAPS_OWNDC 0x00040000 -/* surface should be able to receive live video */ -#define DDSCAPS_LIVEVIDEO 0x00080000 -/* should be able to have a hw codec decompress stuff into it */ -#define DDSCAPS_HWCODEC 0x00100000 -/* mode X (320x200 or 320x240) surface */ -#define DDSCAPS_MODEX 0x00200000 -/* one mipmap surface (1 level) */ -#define DDSCAPS_MIPMAP 0x00400000 -#define DDSCAPS_RESERVED2 0x00800000 -/* memory allocation delayed until Load() */ -#define DDSCAPS_ALLOCONLOAD 0x04000000 -/* Indicates that the surface will receive data from a video port */ -#define DDSCAPS_VIDEOPORT 0x08000000 -/* surface is in local videomemory */ -#define DDSCAPS_LOCALVIDMEM 0x10000000 -/* surface is in nonlocal videomemory */ -#define DDSCAPS_NONLOCALVIDMEM 0x20000000 -/* surface is a standard VGA mode surface (NOT ModeX) */ -#define DDSCAPS_STANDARDVGAMODE 0x40000000 -/* optimized? surface */ -#define DDSCAPS_OPTIMIZED 0x80000000 - -typedef struct _DDSCAPS { - DWORD dwCaps; /* capabilities of surface wanted */ -} DDSCAPS,*LPDDSCAPS; - -/* DDSCAPS2.dwCaps2 */ -/* indicates the surface will receive data from a video port using - deinterlacing hardware. */ -#define DDSCAPS2_HARDWAREDEINTERLACE 0x00000002 -/* indicates the surface will be locked very frequently. */ -#define DDSCAPS2_HINTDYNAMIC 0x00000004 -/* indicates surface can be re-ordered or retiled on load() */ -#define DDSCAPS2_HINTSTATIC 0x00000008 -/* indicates surface to be managed by directdraw/direct3D */ -#define DDSCAPS2_TEXTUREMANAGE 0x00000010 -/* reserved bits */ -#define DDSCAPS2_RESERVED1 0x00000020 -#define DDSCAPS2_RESERVED2 0x00000040 -/* indicates surface will never be locked again */ -#define DDSCAPS2_OPAQUE 0x00000080 -/* set at CreateSurface() time to indicate antialiasing will be used */ -#define DDSCAPS2_HINTANTIALIASING 0x00000100 -/* set at CreateSurface() time to indicate cubic environment map */ -#define DDSCAPS2_CUBEMAP 0x00000200 -/* face flags for cube maps */ -#define DDSCAPS2_CUBEMAP_POSITIVEX 0x00000400 -#define DDSCAPS2_CUBEMAP_NEGATIVEX 0x00000800 -#define DDSCAPS2_CUBEMAP_POSITIVEY 0x00001000 -#define DDSCAPS2_CUBEMAP_NEGATIVEY 0x00002000 -#define DDSCAPS2_CUBEMAP_POSITIVEZ 0x00004000 -#define DDSCAPS2_CUBEMAP_NEGATIVEZ 0x00008000 -/* specifies all faces of a cube for CreateSurface() */ -#define DDSCAPS2_CUBEMAP_ALLFACES ( DDSCAPS2_CUBEMAP_POSITIVEX |\ - DDSCAPS2_CUBEMAP_NEGATIVEX |\ - DDSCAPS2_CUBEMAP_POSITIVEY |\ - DDSCAPS2_CUBEMAP_NEGATIVEY |\ - DDSCAPS2_CUBEMAP_POSITIVEZ |\ - DDSCAPS2_CUBEMAP_NEGATIVEZ ) -/* set for mipmap sublevels on DirectX7 and later. ignored by CreateSurface() */ -#define DDSCAPS2_MIPMAPSUBLEVEL 0x00010000 -/* indicates texture surface to be managed by Direct3D *only* */ -#define DDSCAPS2_D3DTEXTUREMANAGE 0x00020000 -/* indicates managed surface that can safely be lost */ -#define DDSCAPS2_DONOTPERSIST 0x00040000 -/* indicates surface is part of a stereo flipping chain */ -#define DDSCAPS2_STEREOSURFACELEFT 0x00080000 - -typedef struct _DDSCAPS2 { - DWORD dwCaps; /* capabilities of surface wanted */ - DWORD dwCaps2; /* additional capabilities */ - DWORD dwCaps3; /* reserved capabilities */ - __extension__ union { - DWORD dwCaps4; /* low word is the depth for a volume texture */ - DWORD dwVolumeDepth; - } DUMMYUNIONNAME1; -} DDSCAPS2,*LPDDSCAPS2; - -typedef struct _DDSCAPSEX { - DWORD dwCaps2; - DWORD dwCaps3; - __extension__ union { - DWORD dwCaps4; - DWORD dwVolumeDepth; - } DUMMYUNIONNAME1; -} DDSCAPSEX,*LPDDSCAPSEX; - -#define DD_ROP_SPACE (256/32) /* space required to store ROP array */ - -typedef struct _DDCAPS_DX7 /* DirectX 7 version of caps struct */ -{ - DWORD dwSize; /* size of the DDDRIVERCAPS structure */ - DWORD dwCaps; /* driver specific capabilities */ - DWORD dwCaps2; /* more driver specific capabilities */ - DWORD dwCKeyCaps; /* color key capabilities of the surface */ - DWORD dwFXCaps; /* driver specific stretching and effects capabilities */ - DWORD dwFXAlphaCaps; /* alpha driver specific capabilities */ - DWORD dwPalCaps; /* palette capabilities */ - DWORD dwSVCaps; /* stereo vision capabilities */ - DWORD dwAlphaBltConstBitDepths; /* DDBD_2,4,8 */ - DWORD dwAlphaBltPixelBitDepths; /* DDBD_1,2,4,8 */ - DWORD dwAlphaBltSurfaceBitDepths; /* DDBD_1,2,4,8 */ - DWORD dwAlphaOverlayConstBitDepths; /* DDBD_2,4,8 */ - DWORD dwAlphaOverlayPixelBitDepths; /* DDBD_1,2,4,8 */ - DWORD dwAlphaOverlaySurfaceBitDepths; /* DDBD_1,2,4,8 */ - DWORD dwZBufferBitDepths; /* DDBD_8,16,24,32 */ - DWORD dwVidMemTotal; /* total amount of video memory */ - DWORD dwVidMemFree; /* amount of free video memory */ - DWORD dwMaxVisibleOverlays; /* maximum number of visible overlays */ - DWORD dwCurrVisibleOverlays; /* current number of visible overlays */ - DWORD dwNumFourCCCodes; /* number of four cc codes */ - DWORD dwAlignBoundarySrc; /* source rectangle alignment */ - DWORD dwAlignSizeSrc; /* source rectangle byte size */ - DWORD dwAlignBoundaryDest; /* dest rectangle alignment */ - DWORD dwAlignSizeDest; /* dest rectangle byte size */ - DWORD dwAlignStrideAlign; /* stride alignment */ - DWORD dwRops[DD_ROP_SPACE]; /* ROPs supported */ - DDSCAPS ddsOldCaps; /* old DDSCAPS - superseded for DirectX6+ */ - DWORD dwMinOverlayStretch; /* minimum overlay stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3 */ - DWORD dwMaxOverlayStretch; /* maximum overlay stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3 */ - DWORD dwMinLiveVideoStretch; /* minimum live video stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3 */ - DWORD dwMaxLiveVideoStretch; /* maximum live video stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3 */ - DWORD dwMinHwCodecStretch; /* minimum hardware codec stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3 */ - DWORD dwMaxHwCodecStretch; /* maximum hardware codec stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3 */ - DWORD dwReserved1; - DWORD dwReserved2; - DWORD dwReserved3; - DWORD dwSVBCaps; /* driver specific capabilities for System->Vmem blts */ - DWORD dwSVBCKeyCaps; /* driver color key capabilities for System->Vmem blts */ - DWORD dwSVBFXCaps; /* driver FX capabilities for System->Vmem blts */ - DWORD dwSVBRops[DD_ROP_SPACE];/* ROPs supported for System->Vmem blts */ - DWORD dwVSBCaps; /* driver specific capabilities for Vmem->System blts */ - DWORD dwVSBCKeyCaps; /* driver color key capabilities for Vmem->System blts */ - DWORD dwVSBFXCaps; /* driver FX capabilities for Vmem->System blts */ - DWORD dwVSBRops[DD_ROP_SPACE];/* ROPs supported for Vmem->System blts */ - DWORD dwSSBCaps; /* driver specific capabilities for System->System blts */ - DWORD dwSSBCKeyCaps; /* driver color key capabilities for System->System blts */ - DWORD dwSSBFXCaps; /* driver FX capabilities for System->System blts */ - DWORD dwSSBRops[DD_ROP_SPACE];/* ROPs supported for System->System blts */ - DWORD dwMaxVideoPorts; /* maximum number of usable video ports */ - DWORD dwCurrVideoPorts; /* current number of video ports used */ - DWORD dwSVBCaps2; /* more driver specific capabilities for System->Vmem blts */ - DWORD dwNLVBCaps; /* driver specific capabilities for non-local->local vidmem blts */ - DWORD dwNLVBCaps2; /* more driver specific capabilities non-local->local vidmem blts */ - DWORD dwNLVBCKeyCaps; /* driver color key capabilities for non-local->local vidmem blts */ - DWORD dwNLVBFXCaps; /* driver FX capabilities for non-local->local blts */ - DWORD dwNLVBRops[DD_ROP_SPACE]; /* ROPs supported for non-local->local blts */ - DDSCAPS2 ddsCaps; /* surface capabilities */ -} DDCAPS_DX7,*LPDDCAPS_DX7; - -typedef struct _DDCAPS_DX6 /* DirectX 6 version of caps struct */ -{ - DWORD dwSize; /* size of the DDDRIVERCAPS structure */ - DWORD dwCaps; /* driver specific capabilities */ - DWORD dwCaps2; /* more driver specific capabilities */ - DWORD dwCKeyCaps; /* color key capabilities of the surface */ - DWORD dwFXCaps; /* driver specific stretching and effects capabilities */ - DWORD dwFXAlphaCaps; /* alpha driver specific capabilities */ - DWORD dwPalCaps; /* palette capabilities */ - DWORD dwSVCaps; /* stereo vision capabilities */ - DWORD dwAlphaBltConstBitDepths; /* DDBD_2,4,8 */ - DWORD dwAlphaBltPixelBitDepths; /* DDBD_1,2,4,8 */ - DWORD dwAlphaBltSurfaceBitDepths; /* DDBD_1,2,4,8 */ - DWORD dwAlphaOverlayConstBitDepths; /* DDBD_2,4,8 */ - DWORD dwAlphaOverlayPixelBitDepths; /* DDBD_1,2,4,8 */ - DWORD dwAlphaOverlaySurfaceBitDepths; /* DDBD_1,2,4,8 */ - DWORD dwZBufferBitDepths; /* DDBD_8,16,24,32 */ - DWORD dwVidMemTotal; /* total amount of video memory */ - DWORD dwVidMemFree; /* amount of free video memory */ - DWORD dwMaxVisibleOverlays; /* maximum number of visible overlays */ - DWORD dwCurrVisibleOverlays; /* current number of visible overlays */ - DWORD dwNumFourCCCodes; /* number of four cc codes */ - DWORD dwAlignBoundarySrc; /* source rectangle alignment */ - DWORD dwAlignSizeSrc; /* source rectangle byte size */ - DWORD dwAlignBoundaryDest; /* dest rectangle alignment */ - DWORD dwAlignSizeDest; /* dest rectangle byte size */ - DWORD dwAlignStrideAlign; /* stride alignment */ - DWORD dwRops[DD_ROP_SPACE]; /* ROPs supported */ - DDSCAPS ddsOldCaps; /* old DDSCAPS - superseded for DirectX6+ */ - DWORD dwMinOverlayStretch; /* minimum overlay stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3 */ - DWORD dwMaxOverlayStretch; /* maximum overlay stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3 */ - DWORD dwMinLiveVideoStretch; /* minimum live video stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3 */ - DWORD dwMaxLiveVideoStretch; /* maximum live video stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3 */ - DWORD dwMinHwCodecStretch; /* minimum hardware codec stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3 */ - DWORD dwMaxHwCodecStretch; /* maximum hardware codec stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3 */ - DWORD dwReserved1; - DWORD dwReserved2; - DWORD dwReserved3; - DWORD dwSVBCaps; /* driver specific capabilities for System->Vmem blts */ - DWORD dwSVBCKeyCaps; /* driver color key capabilities for System->Vmem blts */ - DWORD dwSVBFXCaps; /* driver FX capabilities for System->Vmem blts */ - DWORD dwSVBRops[DD_ROP_SPACE];/* ROPs supported for System->Vmem blts */ - DWORD dwVSBCaps; /* driver specific capabilities for Vmem->System blts */ - DWORD dwVSBCKeyCaps; /* driver color key capabilities for Vmem->System blts */ - DWORD dwVSBFXCaps; /* driver FX capabilities for Vmem->System blts */ - DWORD dwVSBRops[DD_ROP_SPACE];/* ROPs supported for Vmem->System blts */ - DWORD dwSSBCaps; /* driver specific capabilities for System->System blts */ - DWORD dwSSBCKeyCaps; /* driver color key capabilities for System->System blts */ - DWORD dwSSBFXCaps; /* driver FX capabilities for System->System blts */ - DWORD dwSSBRops[DD_ROP_SPACE];/* ROPs supported for System->System blts */ - DWORD dwMaxVideoPorts; /* maximum number of usable video ports */ - DWORD dwCurrVideoPorts; /* current number of video ports used */ - DWORD dwSVBCaps2; /* more driver specific capabilities for System->Vmem blts */ - DWORD dwNLVBCaps; /* driver specific capabilities for non-local->local vidmem blts */ - DWORD dwNLVBCaps2; /* more driver specific capabilities non-local->local vidmem blts */ - DWORD dwNLVBCKeyCaps; /* driver color key capabilities for non-local->local vidmem blts */ - DWORD dwNLVBFXCaps; /* driver FX capabilities for non-local->local blts */ - DWORD dwNLVBRops[DD_ROP_SPACE]; /* ROPs supported for non-local->local blts */ - /* and one new member for DirectX 6 */ - DDSCAPS2 ddsCaps; /* surface capabilities */ -} DDCAPS_DX6,*LPDDCAPS_DX6; - -typedef struct _DDCAPS_DX5 /* DirectX5 version of caps struct */ -{ - DWORD dwSize; /* size of the DDDRIVERCAPS structure */ - DWORD dwCaps; /* driver specific capabilities */ - DWORD dwCaps2; /* more driver specific capabilities */ - DWORD dwCKeyCaps; /* color key capabilities of the surface */ - DWORD dwFXCaps; /* driver specific stretching and effects capabilities */ - DWORD dwFXAlphaCaps; /* alpha driver specific capabilities */ - DWORD dwPalCaps; /* palette capabilities */ - DWORD dwSVCaps; /* stereo vision capabilities */ - DWORD dwAlphaBltConstBitDepths; /* DDBD_2,4,8 */ - DWORD dwAlphaBltPixelBitDepths; /* DDBD_1,2,4,8 */ - DWORD dwAlphaBltSurfaceBitDepths; /* DDBD_1,2,4,8 */ - DWORD dwAlphaOverlayConstBitDepths; /* DDBD_2,4,8 */ - DWORD dwAlphaOverlayPixelBitDepths; /* DDBD_1,2,4,8 */ - DWORD dwAlphaOverlaySurfaceBitDepths; /* DDBD_1,2,4,8 */ - DWORD dwZBufferBitDepths; /* DDBD_8,16,24,32 */ - DWORD dwVidMemTotal; /* total amount of video memory */ - DWORD dwVidMemFree; /* amount of free video memory */ - DWORD dwMaxVisibleOverlays; /* maximum number of visible overlays */ - DWORD dwCurrVisibleOverlays; /* current number of visible overlays */ - DWORD dwNumFourCCCodes; /* number of four cc codes */ - DWORD dwAlignBoundarySrc; /* source rectangle alignment */ - DWORD dwAlignSizeSrc; /* source rectangle byte size */ - DWORD dwAlignBoundaryDest; /* dest rectangle alignment */ - DWORD dwAlignSizeDest; /* dest rectangle byte size */ - DWORD dwAlignStrideAlign; /* stride alignment */ - DWORD dwRops[DD_ROP_SPACE]; /* ROPs supported */ - DDSCAPS ddsCaps; /* DDSCAPS structure has all the general capabilities */ - DWORD dwMinOverlayStretch; /* minimum overlay stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3 */ - DWORD dwMaxOverlayStretch; /* maximum overlay stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3 */ - DWORD dwMinLiveVideoStretch; /* minimum live video stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3 */ - DWORD dwMaxLiveVideoStretch; /* maximum live video stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3 */ - DWORD dwMinHwCodecStretch; /* minimum hardware codec stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3 */ - DWORD dwMaxHwCodecStretch; /* maximum hardware codec stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3 */ - DWORD dwReserved1; - DWORD dwReserved2; - DWORD dwReserved3; - DWORD dwSVBCaps; /* driver specific capabilities for System->Vmem blts */ - DWORD dwSVBCKeyCaps; /* driver color key capabilities for System->Vmem blts */ - DWORD dwSVBFXCaps; /* driver FX capabilities for System->Vmem blts */ - DWORD dwSVBRops[DD_ROP_SPACE];/* ROPs supported for System->Vmem blts */ - DWORD dwVSBCaps; /* driver specific capabilities for Vmem->System blts */ - DWORD dwVSBCKeyCaps; /* driver color key capabilities for Vmem->System blts */ - DWORD dwVSBFXCaps; /* driver FX capabilities for Vmem->System blts */ - DWORD dwVSBRops[DD_ROP_SPACE];/* ROPs supported for Vmem->System blts */ - DWORD dwSSBCaps; /* driver specific capabilities for System->System blts */ - DWORD dwSSBCKeyCaps; /* driver color key capabilities for System->System blts */ - DWORD dwSSBFXCaps; /* driver FX capabilities for System->System blts */ - DWORD dwSSBRops[DD_ROP_SPACE];/* ROPs supported for System->System blts */ - /* the following are the new DirectX 5 members */ - DWORD dwMaxVideoPorts; /* maximum number of usable video ports */ - DWORD dwCurrVideoPorts; /* current number of video ports used */ - DWORD dwSVBCaps2; /* more driver specific capabilities for System->Vmem blts */ - DWORD dwNLVBCaps; /* driver specific capabilities for non-local->local vidmem blts */ - DWORD dwNLVBCaps2; /* more driver specific capabilities non-local->local vidmem blts */ - DWORD dwNLVBCKeyCaps; /* driver color key capabilities for non-local->local vidmem blts */ - DWORD dwNLVBFXCaps; /* driver FX capabilities for non-local->local blts */ - DWORD dwNLVBRops[DD_ROP_SPACE]; /* ROPs supported for non-local->local blts */ -} DDCAPS_DX5,*LPDDCAPS_DX5; - -typedef struct _DDCAPS_DX3 /* DirectX3 version of caps struct */ -{ - DWORD dwSize; /* size of the DDDRIVERCAPS structure */ - DWORD dwCaps; /* driver specific capabilities */ - DWORD dwCaps2; /* more driver specific capabilities */ - DWORD dwCKeyCaps; /* color key capabilities of the surface */ - DWORD dwFXCaps; /* driver specific stretching and effects capabilities */ - DWORD dwFXAlphaCaps; /* alpha driver specific capabilities */ - DWORD dwPalCaps; /* palette capabilities */ - DWORD dwSVCaps; /* stereo vision capabilities */ - DWORD dwAlphaBltConstBitDepths; /* DDBD_2,4,8 */ - DWORD dwAlphaBltPixelBitDepths; /* DDBD_1,2,4,8 */ - DWORD dwAlphaBltSurfaceBitDepths; /* DDBD_1,2,4,8 */ - DWORD dwAlphaOverlayConstBitDepths; /* DDBD_2,4,8 */ - DWORD dwAlphaOverlayPixelBitDepths; /* DDBD_1,2,4,8 */ - DWORD dwAlphaOverlaySurfaceBitDepths; /* DDBD_1,2,4,8 */ - DWORD dwZBufferBitDepths; /* DDBD_8,16,24,32 */ - DWORD dwVidMemTotal; /* total amount of video memory */ - DWORD dwVidMemFree; /* amount of free video memory */ - DWORD dwMaxVisibleOverlays; /* maximum number of visible overlays */ - DWORD dwCurrVisibleOverlays; /* current number of visible overlays */ - DWORD dwNumFourCCCodes; /* number of four cc codes */ - DWORD dwAlignBoundarySrc; /* source rectangle alignment */ - DWORD dwAlignSizeSrc; /* source rectangle byte size */ - DWORD dwAlignBoundaryDest; /* dest rectangle alignment */ - DWORD dwAlignSizeDest; /* dest rectangle byte size */ - DWORD dwAlignStrideAlign; /* stride alignment */ - DWORD dwRops[DD_ROP_SPACE]; /* ROPs supported */ - DDSCAPS ddsCaps; /* DDSCAPS structure has all the general capabilities */ - DWORD dwMinOverlayStretch; /* minimum overlay stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3 */ - DWORD dwMaxOverlayStretch; /* maximum overlay stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3 */ - DWORD dwMinLiveVideoStretch; /* minimum live video stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3 */ - DWORD dwMaxLiveVideoStretch; /* maximum live video stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3 */ - DWORD dwMinHwCodecStretch; /* minimum hardware codec stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3 */ - DWORD dwMaxHwCodecStretch; /* maximum hardware codec stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3 */ - DWORD dwReserved1; - DWORD dwReserved2; - DWORD dwReserved3; - DWORD dwSVBCaps; /* driver specific capabilities for System->Vmem blts */ - DWORD dwSVBCKeyCaps; /* driver color key capabilities for System->Vmem blts */ - DWORD dwSVBFXCaps; /* driver FX capabilities for System->Vmem blts */ - DWORD dwSVBRops[DD_ROP_SPACE];/* ROPs supported for System->Vmem blts */ - DWORD dwVSBCaps; /* driver specific capabilities for Vmem->System blts */ - DWORD dwVSBCKeyCaps; /* driver color key capabilities for Vmem->System blts */ - DWORD dwVSBFXCaps; /* driver FX capabilities for Vmem->System blts */ - DWORD dwVSBRops[DD_ROP_SPACE];/* ROPs supported for Vmem->System blts */ - DWORD dwSSBCaps; /* driver specific capabilities for System->System blts */ - DWORD dwSSBCKeyCaps; /* driver color key capabilities for System->System blts */ - DWORD dwSSBFXCaps; /* driver FX capabilities for System->System blts */ - DWORD dwSSBRops[DD_ROP_SPACE];/* ROPs supported for System->System blts */ - DWORD dwReserved4; - DWORD dwReserved5; - DWORD dwReserved6; -} DDCAPS_DX3,*LPDDCAPS_DX3; - -/* set caps struct according to DIRECTDRAW_VERSION */ - -#if DIRECTDRAW_VERSION <= 0x300 -typedef DDCAPS_DX3 DDCAPS; -#elif DIRECTDRAW_VERSION <= 0x500 -typedef DDCAPS_DX5 DDCAPS; -#elif DIRECTDRAW_VERSION <= 0x600 -typedef DDCAPS_DX6 DDCAPS; -#else -typedef DDCAPS_DX7 DDCAPS; -#endif - -typedef DDCAPS *LPDDCAPS; - -/* DDCAPS.dwCaps */ -#define DDCAPS_3D 0x00000001 -#define DDCAPS_ALIGNBOUNDARYDEST 0x00000002 -#define DDCAPS_ALIGNSIZEDEST 0x00000004 -#define DDCAPS_ALIGNBOUNDARYSRC 0x00000008 -#define DDCAPS_ALIGNSIZESRC 0x00000010 -#define DDCAPS_ALIGNSTRIDE 0x00000020 -#define DDCAPS_BLT 0x00000040 -#define DDCAPS_BLTQUEUE 0x00000080 -#define DDCAPS_BLTFOURCC 0x00000100 -#define DDCAPS_BLTSTRETCH 0x00000200 -#define DDCAPS_GDI 0x00000400 -#define DDCAPS_OVERLAY 0x00000800 -#define DDCAPS_OVERLAYCANTCLIP 0x00001000 -#define DDCAPS_OVERLAYFOURCC 0x00002000 -#define DDCAPS_OVERLAYSTRETCH 0x00004000 -#define DDCAPS_PALETTE 0x00008000 -#define DDCAPS_PALETTEVSYNC 0x00010000 -#define DDCAPS_READSCANLINE 0x00020000 -#define DDCAPS_STEREOVIEW 0x00040000 -#define DDCAPS_VBI 0x00080000 -#define DDCAPS_ZBLTS 0x00100000 -#define DDCAPS_ZOVERLAYS 0x00200000 -#define DDCAPS_COLORKEY 0x00400000 -#define DDCAPS_ALPHA 0x00800000 -#define DDCAPS_COLORKEYHWASSIST 0x01000000 -#define DDCAPS_NOHARDWARE 0x02000000 -#define DDCAPS_BLTCOLORFILL 0x04000000 -#define DDCAPS_BANKSWITCHED 0x08000000 -#define DDCAPS_BLTDEPTHFILL 0x10000000 -#define DDCAPS_CANCLIP 0x20000000 -#define DDCAPS_CANCLIPSTRETCHED 0x40000000 -#define DDCAPS_CANBLTSYSMEM 0x80000000 - -/* DDCAPS.dwCaps2 */ -#define DDCAPS2_CERTIFIED 0x00000001 -#define DDCAPS2_NO2DDURING3DSCENE 0x00000002 -#define DDCAPS2_VIDEOPORT 0x00000004 -#define DDCAPS2_AUTOFLIPOVERLAY 0x00000008 -#define DDCAPS2_CANBOBINTERLEAVED 0x00000010 -#define DDCAPS2_CANBOBNONINTERLEAVED 0x00000020 -#define DDCAPS2_COLORCONTROLOVERLAY 0x00000040 -#define DDCAPS2_COLORCONTROLPRIMARY 0x00000080 -#define DDCAPS2_CANDROPZ16BIT 0x00000100 -#define DDCAPS2_NONLOCALVIDMEM 0x00000200 -#define DDCAPS2_NONLOCALVIDMEMCAPS 0x00000400 -#define DDCAPS2_NOPAGELOCKREQUIRED 0x00000800 -#define DDCAPS2_WIDESURFACES 0x00001000 -#define DDCAPS2_CANFLIPODDEVEN 0x00002000 -#define DDCAPS2_CANBOBHARDWARE 0x00004000 -#define DDCAPS2_COPYFOURCC 0x00008000 -#define DDCAPS2_PRIMARYGAMMA 0x00020000 -#define DDCAPS2_CANRENDERWINDOWED 0x00080000 -#define DDCAPS2_CANCALIBRATEGAMMA 0x00100000 -#define DDCAPS2_FLIPINTERVAL 0x00200000 -#define DDCAPS2_FLIPNOVSYNC 0x00400000 -#define DDCAPS2_CANMANAGETEXTURE 0x00800000 -#define DDCAPS2_TEXMANINNONLOCALVIDMEM 0x01000000 -#define DDCAPS2_STEREO 0x02000000 -#define DDCAPS2_SYSTONONLOCAL_AS_SYSTOLOCAL 0x04000000 - - -/* Set/Get Colour Key Flags */ -#define DDCKEY_COLORSPACE 0x00000001 /* Struct is single colour space */ -#define DDCKEY_DESTBLT 0x00000002 /* To be used as dest for blt */ -#define DDCKEY_DESTOVERLAY 0x00000004 /* To be used as dest for CK overlays */ -#define DDCKEY_SRCBLT 0x00000008 /* To be used as src for blt */ -#define DDCKEY_SRCOVERLAY 0x00000010 /* To be used as src for CK overlays */ - -typedef struct _DDCOLORKEY -{ - DWORD dwColorSpaceLowValue;/* low boundary of color space that is to - * be treated as Color Key, inclusive - */ - DWORD dwColorSpaceHighValue;/* high boundary of color space that is - * to be treated as Color Key, inclusive - */ -} DDCOLORKEY,*LPDDCOLORKEY; - -/* ddCKEYCAPS bits */ -#define DDCKEYCAPS_DESTBLT 0x00000001 -#define DDCKEYCAPS_DESTBLTCLRSPACE 0x00000002 -#define DDCKEYCAPS_DESTBLTCLRSPACEYUV 0x00000004 -#define DDCKEYCAPS_DESTBLTYUV 0x00000008 -#define DDCKEYCAPS_DESTOVERLAY 0x00000010 -#define DDCKEYCAPS_DESTOVERLAYCLRSPACE 0x00000020 -#define DDCKEYCAPS_DESTOVERLAYCLRSPACEYUV 0x00000040 -#define DDCKEYCAPS_DESTOVERLAYONEACTIVE 0x00000080 -#define DDCKEYCAPS_DESTOVERLAYYUV 0x00000100 -#define DDCKEYCAPS_SRCBLT 0x00000200 -#define DDCKEYCAPS_SRCBLTCLRSPACE 0x00000400 -#define DDCKEYCAPS_SRCBLTCLRSPACEYUV 0x00000800 -#define DDCKEYCAPS_SRCBLTYUV 0x00001000 -#define DDCKEYCAPS_SRCOVERLAY 0x00002000 -#define DDCKEYCAPS_SRCOVERLAYCLRSPACE 0x00004000 -#define DDCKEYCAPS_SRCOVERLAYCLRSPACEYUV 0x00008000 -#define DDCKEYCAPS_SRCOVERLAYONEACTIVE 0x00010000 -#define DDCKEYCAPS_SRCOVERLAYYUV 0x00020000 -#define DDCKEYCAPS_NOCOSTOVERLAY 0x00040000 - -typedef struct _DDPIXELFORMAT { - DWORD dwSize; /* 0: size of structure */ - DWORD dwFlags; /* 4: pixel format flags */ - DWORD dwFourCC; /* 8: (FOURCC code) */ - __extension__ union { - DWORD dwRGBBitCount; /* C: how many bits per pixel */ - DWORD dwYUVBitCount; /* C: how many bits per pixel */ - DWORD dwZBufferBitDepth; /* C: how many bits for z buffers */ - DWORD dwAlphaBitDepth; /* C: how many bits for alpha channels*/ - DWORD dwLuminanceBitCount; - DWORD dwBumpBitCount; - } DUMMYUNIONNAME1; - __extension__ union { - DWORD dwRBitMask; /* 10: mask for red bit*/ - DWORD dwYBitMask; /* 10: mask for Y bits*/ - DWORD dwStencilBitDepth; - DWORD dwLuminanceBitMask; - DWORD dwBumpDuBitMask; - } DUMMYUNIONNAME2; - __extension__ union { - DWORD dwGBitMask; /* 14: mask for green bits*/ - DWORD dwUBitMask; /* 14: mask for U bits*/ - DWORD dwZBitMask; - DWORD dwBumpDvBitMask; - } DUMMYUNIONNAME3; - __extension__ union { - DWORD dwBBitMask; /* 18: mask for blue bits*/ - DWORD dwVBitMask; /* 18: mask for V bits*/ - DWORD dwStencilBitMask; - DWORD dwBumpLuminanceBitMask; - } DUMMYUNIONNAME4; - __extension__ union { - DWORD dwRGBAlphaBitMask; /* 1C: mask for alpha channel */ - DWORD dwYUVAlphaBitMask; /* 1C: mask for alpha channel */ - DWORD dwLuminanceAlphaBitMask; - DWORD dwRGBZBitMask; /* 1C: mask for Z channel */ - DWORD dwYUVZBitMask; /* 1C: mask for Z channel */ - } DUMMYUNIONNAME5; - /* 20: next structure */ -} DDPIXELFORMAT,*LPDDPIXELFORMAT; - -#ifndef MAKEFOURCC -#define MAKEFOURCC(ch0, ch1, ch2, ch3) \ - ((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | \ - ((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24 )) -#endif /* MAKEFOURCC */ - -/* DDCAPS.dwFXCaps */ -#define DDFXCAPS_BLTALPHA 0x00000001 -#define DDFXCAPS_OVERLAYALPHA 0x00000004 -#define DDFXCAPS_BLTARITHSTRETCHYN 0x00000010 -#define DDFXCAPS_BLTARITHSTRETCHY 0x00000020 -#define DDFXCAPS_BLTMIRRORLEFTRIGHT 0x00000040 -#define DDFXCAPS_BLTMIRRORUPDOWN 0x00000080 -#define DDFXCAPS_BLTROTATION 0x00000100 -#define DDFXCAPS_BLTROTATION90 0x00000200 -#define DDFXCAPS_BLTSHRINKX 0x00000400 -#define DDFXCAPS_BLTSHRINKXN 0x00000800 -#define DDFXCAPS_BLTSHRINKY 0x00001000 -#define DDFXCAPS_BLTSHRINKYN 0x00002000 -#define DDFXCAPS_BLTSTRETCHX 0x00004000 -#define DDFXCAPS_BLTSTRETCHXN 0x00008000 -#define DDFXCAPS_BLTSTRETCHY 0x00010000 -#define DDFXCAPS_BLTSTRETCHYN 0x00020000 -#define DDFXCAPS_OVERLAYARITHSTRETCHY 0x00040000 -#define DDFXCAPS_OVERLAYARITHSTRETCHYN 0x00000008 -#define DDFXCAPS_OVERLAYSHRINKX 0x00080000 -#define DDFXCAPS_OVERLAYSHRINKXN 0x00100000 -#define DDFXCAPS_OVERLAYSHRINKY 0x00200000 -#define DDFXCAPS_OVERLAYSHRINKYN 0x00400000 -#define DDFXCAPS_OVERLAYSTRETCHX 0x00800000 -#define DDFXCAPS_OVERLAYSTRETCHXN 0x01000000 -#define DDFXCAPS_OVERLAYSTRETCHY 0x02000000 -#define DDFXCAPS_OVERLAYSTRETCHYN 0x04000000 -#define DDFXCAPS_OVERLAYMIRRORLEFTRIGHT 0x08000000 -#define DDFXCAPS_OVERLAYMIRRORUPDOWN 0x10000000 - -#define DDFXCAPS_OVERLAYFILTER DDFXCAPS_OVERLAYARITHSTRETCHY - -/* DDCAPS.dwFXAlphaCaps */ -#define DDFXALPHACAPS_BLTALPHAEDGEBLEND 0x00000001 -#define DDFXALPHACAPS_BLTALPHAPIXELS 0x00000002 -#define DDFXALPHACAPS_BLTALPHAPIXELSNEG 0x00000004 -#define DDFXALPHACAPS_BLTALPHASURFACES 0x00000008 -#define DDFXALPHACAPS_BLTALPHASURFACESNEG 0x00000010 -#define DDFXALPHACAPS_OVERLAYALPHAEDGEBLEND 0x00000020 -#define DDFXALPHACAPS_OVERLAYALPHAPIXELS 0x00000040 -#define DDFXALPHACAPS_OVERLAYALPHAPIXELSNEG 0x00000080 -#define DDFXALPHACAPS_OVERLAYALPHASURFACES 0x00000100 -#define DDFXALPHACAPS_OVERLAYALPHASURFACESNEG 0x00000200 - -/* DDCAPS.dwPalCaps */ -#define DDPCAPS_4BIT 0x00000001 -#define DDPCAPS_8BITENTRIES 0x00000002 -#define DDPCAPS_8BIT 0x00000004 -#define DDPCAPS_INITIALIZE 0x00000008 -#define DDPCAPS_PRIMARYSURFACE 0x00000010 -#define DDPCAPS_PRIMARYSURFACELEFT 0x00000020 -#define DDPCAPS_ALLOW256 0x00000040 -#define DDPCAPS_VSYNC 0x00000080 -#define DDPCAPS_1BIT 0x00000100 -#define DDPCAPS_2BIT 0x00000200 -#define DDPCAPS_ALPHA 0x00000400 - -/* DDCAPS.dwSVCaps */ -/* the first 4 of these are now obsolete */ -#if DIRECTDRAW_VERSION >= 0x700 /* FIXME: I'm not sure when this switch occurred */ -#define DDSVCAPS_RESERVED1 0x00000001 -#define DDSVCAPS_RESERVED2 0x00000002 -#define DDSVCAPS_RESERVED3 0x00000004 -#define DDSVCAPS_RESERVED4 0x00000008 -#else -#define DDSVCAPS_ENIGMA 0x00000001 -#define DDSVCAPS_FLICKER 0x00000002 -#define DDSVCAPS_REDBLUE 0x00000004 -#define DDSVCAPS_SPLIT 0x00000008 -#endif -#define DDSVCAPS_STEREOSEQUENTIAL 0x00000010 - -/* BitDepths */ -#define DDBD_1 0x00004000 -#define DDBD_2 0x00002000 -#define DDBD_4 0x00001000 -#define DDBD_8 0x00000800 -#define DDBD_16 0x00000400 -#define DDBD_24 0x00000200 -#define DDBD_32 0x00000100 - -/* DDOVERLAYFX.dwDDFX */ -#define DDOVERFX_ARITHSTRETCHY 0x00000001 -#define DDOVERFX_MIRRORLEFTRIGHT 0x00000002 -#define DDOVERFX_MIRRORUPDOWN 0x00000004 - -/* UpdateOverlay flags */ -#define DDOVER_ALPHADEST 0x00000001 -#define DDOVER_ALPHADESTCONSTOVERRIDE 0x00000002 -#define DDOVER_ALPHADESTNEG 0x00000004 -#define DDOVER_ALPHADESTSURFACEOVERRIDE 0x00000008 -#define DDOVER_ALPHAEDGEBLEND 0x00000010 -#define DDOVER_ALPHASRC 0x00000020 -#define DDOVER_ALPHASRCCONSTOVERRIDE 0x00000040 -#define DDOVER_ALPHASRCNEG 0x00000080 -#define DDOVER_ALPHASRCSURFACEOVERRIDE 0x00000100 -#define DDOVER_HIDE 0x00000200 -#define DDOVER_KEYDEST 0x00000400 -#define DDOVER_KEYDESTOVERRIDE 0x00000800 -#define DDOVER_KEYSRC 0x00001000 -#define DDOVER_KEYSRCOVERRIDE 0x00002000 -#define DDOVER_SHOW 0x00004000 -#define DDOVER_ADDDIRTYRECT 0x00008000 -#define DDOVER_REFRESHDIRTYRECTS 0x00010000 -#define DDOVER_REFRESHALL 0x00020000 -#define DDOVER_DDFX 0x00080000 -#define DDOVER_AUTOFLIP 0x00100000 -#define DDOVER_BOB 0x00200000 -#define DDOVER_OVERRIDEBOBWEAVE 0x00400000 -#define DDOVER_INTERLEAVED 0x00800000 - -/* DDCOLORKEY.dwFlags */ -#define DDPF_ALPHAPIXELS 0x00000001 -#define DDPF_ALPHA 0x00000002 -#define DDPF_FOURCC 0x00000004 -#define DDPF_PALETTEINDEXED4 0x00000008 -#define DDPF_PALETTEINDEXEDTO8 0x00000010 -#define DDPF_PALETTEINDEXED8 0x00000020 -#define DDPF_RGB 0x00000040 -#define DDPF_COMPRESSED 0x00000080 -#define DDPF_RGBTOYUV 0x00000100 -#define DDPF_YUV 0x00000200 -#define DDPF_ZBUFFER 0x00000400 -#define DDPF_PALETTEINDEXED1 0x00000800 -#define DDPF_PALETTEINDEXED2 0x00001000 -#define DDPF_ZPIXELS 0x00002000 -#define DDPF_STENCILBUFFER 0x00004000 -#define DDPF_ALPHAPREMULT 0x00008000 -#define DDPF_LUMINANCE 0x00020000 -#define DDPF_BUMPLUMINANCE 0x00040000 -#define DDPF_BUMPDUDV 0x00080000 - -/* SetCooperativeLevel dwFlags */ -#define DDSCL_FULLSCREEN 0x00000001 -#define DDSCL_ALLOWREBOOT 0x00000002 -#define DDSCL_NOWINDOWCHANGES 0x00000004 -#define DDSCL_NORMAL 0x00000008 -#define DDSCL_EXCLUSIVE 0x00000010 -#define DDSCL_ALLOWMODEX 0x00000040 -#define DDSCL_SETFOCUSWINDOW 0x00000080 -#define DDSCL_SETDEVICEWINDOW 0x00000100 -#define DDSCL_CREATEDEVICEWINDOW 0x00000200 -#define DDSCL_MULTITHREADED 0x00000400 -#define DDSCL_FPUSETUP 0x00000800 -#define DDSCL_FPUPRESERVE 0x00001000 - - -/* DDSURFACEDESC.dwFlags */ -#define DDSD_CAPS 0x00000001 -#define DDSD_HEIGHT 0x00000002 -#define DDSD_WIDTH 0x00000004 -#define DDSD_PITCH 0x00000008 -#define DDSD_BACKBUFFERCOUNT 0x00000020 -#define DDSD_ZBUFFERBITDEPTH 0x00000040 -#define DDSD_ALPHABITDEPTH 0x00000080 -#define DDSD_LPSURFACE 0x00000800 -#define DDSD_PIXELFORMAT 0x00001000 -#define DDSD_CKDESTOVERLAY 0x00002000 -#define DDSD_CKDESTBLT 0x00004000 -#define DDSD_CKSRCOVERLAY 0x00008000 -#define DDSD_CKSRCBLT 0x00010000 -#define DDSD_MIPMAPCOUNT 0x00020000 -#define DDSD_REFRESHRATE 0x00040000 -#define DDSD_LINEARSIZE 0x00080000 -#define DDSD_TEXTURESTAGE 0x00100000 -#define DDSD_FVF 0x00200000 -#define DDSD_SRCVBHANDLE 0x00400000 -#define DDSD_DEPTH 0x00800000 -#define DDSD_ALL 0x00fff9ee - -/* EnumSurfaces flags */ -#define DDENUMSURFACES_ALL 0x00000001 -#define DDENUMSURFACES_MATCH 0x00000002 -#define DDENUMSURFACES_NOMATCH 0x00000004 -#define DDENUMSURFACES_CANBECREATED 0x00000008 -#define DDENUMSURFACES_DOESEXIST 0x00000010 - -/* SetDisplayMode flags */ -#define DDSDM_STANDARDVGAMODE 0x00000001 - -/* EnumDisplayModes flags */ -#define DDEDM_REFRESHRATES 0x00000001 -#define DDEDM_STANDARDVGAMODES 0x00000002 - -/* WaitForVerticalDisplay flags */ - -#define DDWAITVB_BLOCKBEGIN 0x00000001 -#define DDWAITVB_BLOCKBEGINEVENT 0x00000002 -#define DDWAITVB_BLOCKEND 0x00000004 - -typedef struct _DDSURFACEDESC -{ - DWORD dwSize; /* 0: size of the DDSURFACEDESC structure*/ - DWORD dwFlags; /* 4: determines what fields are valid*/ - DWORD dwHeight; /* 8: height of surface to be created*/ - DWORD dwWidth; /* C: width of input surface*/ - __extension__ union { - LONG lPitch; /* 10: distance to start of next line (return value only)*/ - DWORD dwLinearSize; - } DUMMYUNIONNAME1; - DWORD dwBackBufferCount;/* 14: number of back buffers requested*/ - __extension__ union { - DWORD dwMipMapCount;/* 18:number of mip-map levels requested*/ - DWORD dwZBufferBitDepth;/*18: depth of Z buffer requested*/ - DWORD dwRefreshRate;/* 18:refresh rate (used when display mode is described)*/ - } DUMMYUNIONNAME2; - DWORD dwAlphaBitDepth;/* 1C:depth of alpha buffer requested*/ - DWORD dwReserved; /* 20:reserved*/ - LPVOID lpSurface; /* 24:pointer to the associated surface memory*/ - DDCOLORKEY ddckCKDestOverlay;/* 28: CK for dest overlay use*/ - DDCOLORKEY ddckCKDestBlt; /* 30: CK for destination blt use*/ - DDCOLORKEY ddckCKSrcOverlay;/* 38: CK for source overlay use*/ - DDCOLORKEY ddckCKSrcBlt; /* 40: CK for source blt use*/ - DDPIXELFORMAT ddpfPixelFormat;/* 48: pixel format description of the surface*/ - DDSCAPS ddsCaps; /* 68: direct draw surface caps */ -} DDSURFACEDESC,*LPDDSURFACEDESC; - -typedef struct _DDSURFACEDESC2 -{ - DWORD dwSize; /* 0: size of the DDSURFACEDESC2 structure*/ - DWORD dwFlags; /* 4: determines what fields are valid*/ - DWORD dwHeight; /* 8: height of surface to be created*/ - DWORD dwWidth; /* C: width of input surface*/ - __extension__ union { - LONG lPitch; /*10: distance to start of next line (return value only)*/ - DWORD dwLinearSize; /*10: formless late-allocated optimized surface size */ - } DUMMYUNIONNAME1; - DWORD dwBackBufferCount;/* 14: number of back buffers requested*/ - __extension__ union { - DWORD dwMipMapCount;/* 18:number of mip-map levels requested*/ - DWORD dwRefreshRate;/* 18:refresh rate (used when display mode is described)*/ - DWORD dwSrcVBHandle;/* 18:source used in VB::Optimize */ - } DUMMYUNIONNAME2; - DWORD dwAlphaBitDepth;/* 1C:depth of alpha buffer requested*/ - DWORD dwReserved; /* 20:reserved*/ - LPVOID lpSurface; /* 24:pointer to the associated surface memory*/ - __extension__ union { - DDCOLORKEY ddckCKDestOverlay; /* 28: CK for dest overlay use*/ - DWORD dwEmptyFaceColor; /* 28: color for empty cubemap faces */ - } DUMMYUNIONNAME3; - DDCOLORKEY ddckCKDestBlt; /* 30: CK for destination blt use*/ - DDCOLORKEY ddckCKSrcOverlay;/* 38: CK for source overlay use*/ - DDCOLORKEY ddckCKSrcBlt; /* 40: CK for source blt use*/ - - __extension__ union { - DDPIXELFORMAT ddpfPixelFormat;/* 48: pixel format description of the surface*/ - DWORD dwFVF; /* 48: vertex format description of vertex buffers */ - } DUMMYUNIONNAME4; - DDSCAPS2 ddsCaps; /* 68: DDraw surface caps */ - DWORD dwTextureStage; /* 78: stage in multitexture cascade */ -} DDSURFACEDESC2,*LPDDSURFACEDESC2; - - -typedef struct _DDARGB { - BYTE blue; - BYTE green; - BYTE red; - BYTE alpha; -} DDARGB, *LPDDARGB; - -typedef struct _DDRGBA { - BYTE red; - BYTE green; - BYTE blue; - BYTE alpha; -} DDRGBA, *LPDDRGBA; - - -/* DDCOLORCONTROL.dwFlags */ -#define DDCOLOR_BRIGHTNESS 0x00000001 -#define DDCOLOR_CONTRAST 0x00000002 -#define DDCOLOR_HUE 0x00000004 -#define DDCOLOR_SATURATION 0x00000008 -#define DDCOLOR_SHARPNESS 0x00000010 -#define DDCOLOR_GAMMA 0x00000020 -#define DDCOLOR_COLORENABLE 0x00000040 - -typedef struct { - DWORD dwSize; - DWORD dwFlags; - LONG lBrightness; - LONG lContrast; - LONG lHue; - LONG lSaturation; - LONG lSharpness; - LONG lGamma; - LONG lColorEnable; - DWORD dwReserved1; -} DDCOLORCONTROL,*LPDDCOLORCONTROL; - -typedef struct { - WORD red[256]; - WORD green[256]; - WORD blue[256]; -} DDGAMMARAMP,*LPDDGAMMARAMP; - -typedef BOOL (CALLBACK *LPDDENUMCALLBACKA)(GUID *, LPSTR, LPSTR, LPVOID); -typedef BOOL (CALLBACK *LPDDENUMCALLBACKW)(GUID *, LPWSTR, LPWSTR, LPVOID); -DECL_WINELIB_TYPE_AW(LPDDENUMCALLBACK) - -typedef HRESULT (CALLBACK *LPDDENUMMODESCALLBACK)(LPDDSURFACEDESC, LPVOID); -typedef HRESULT (CALLBACK *LPDDENUMMODESCALLBACK2)(LPDDSURFACEDESC2, LPVOID); -typedef HRESULT (CALLBACK *LPDDENUMSURFACESCALLBACK)(LPDIRECTDRAWSURFACE, LPDDSURFACEDESC, LPVOID); -typedef HRESULT (CALLBACK *LPDDENUMSURFACESCALLBACK2)(LPDIRECTDRAWSURFACE4, LPDDSURFACEDESC2, LPVOID); -typedef HRESULT (CALLBACK *LPDDENUMSURFACESCALLBACK7)(LPDIRECTDRAWSURFACE7, LPDDSURFACEDESC2, LPVOID); - -typedef BOOL (CALLBACK *LPDDENUMCALLBACKEXA)(GUID *, LPSTR, LPSTR, LPVOID, HMONITOR); -typedef BOOL (CALLBACK *LPDDENUMCALLBACKEXW)(GUID *, LPWSTR, LPWSTR, LPVOID, HMONITOR); -DECL_WINELIB_TYPE_AW(LPDDENUMCALLBACKEX) - -HRESULT WINAPI DirectDrawEnumerateA(LPDDENUMCALLBACKA,LPVOID); -HRESULT WINAPI DirectDrawEnumerateW(LPDDENUMCALLBACKW,LPVOID); -#define DirectDrawEnumerate WINELIB_NAME_AW(DirectDrawEnumerate) - -HRESULT WINAPI DirectDrawEnumerateExA( LPDDENUMCALLBACKEXA lpCallback, LPVOID lpContext, DWORD dwFlags); -HRESULT WINAPI DirectDrawEnumerateExW( LPDDENUMCALLBACKEXW lpCallback, LPVOID lpContext, DWORD dwFlags); -#define DirectDrawEnumerateEx WINELIB_NAME_AW(DirectDrawEnumerateEx) - -typedef HRESULT (WINAPI * LPDIRECTDRAWENUMERATEEXA)( LPDDENUMCALLBACKEXA lpCallback, LPVOID lpContext, DWORD dwFlags); -typedef HRESULT (WINAPI * LPDIRECTDRAWENUMERATEEXW)( LPDDENUMCALLBACKEXW lpCallback, LPVOID lpContext, DWORD dwFlags); -DECL_WINELIB_TYPE_AW(LPDIRECTDRAWENUMERATEEX) - -/* flags for DirectDrawEnumerateEx */ -#define DDENUM_ATTACHEDSECONDARYDEVICES 0x00000001 -#define DDENUM_DETACHEDSECONDARYDEVICES 0x00000002 -#define DDENUM_NONDISPLAYDEVICES 0x00000004 - -/* flags for DirectDrawCreate or IDirectDraw::Initialize */ -#define DDCREATE_HARDWAREONLY 1L -#define DDCREATE_EMULATIONONLY 2L - -typedef struct _DDBLTFX -{ - DWORD dwSize; /* size of structure */ - DWORD dwDDFX; /* FX operations */ - DWORD dwROP; /* Win32 raster operations */ - DWORD dwDDROP; /* Raster operations new for DirectDraw */ - DWORD dwRotationAngle; /* Rotation angle for blt */ - DWORD dwZBufferOpCode; /* ZBuffer compares */ - DWORD dwZBufferLow; /* Low limit of Z buffer */ - DWORD dwZBufferHigh; /* High limit of Z buffer */ - DWORD dwZBufferBaseDest; /* Destination base value */ - DWORD dwZDestConstBitDepth; /* Bit depth used to specify Z constant for destination */ - __extension__ union - { - DWORD dwZDestConst; /* Constant to use as Z buffer for dest */ - LPDIRECTDRAWSURFACE lpDDSZBufferDest; /* Surface to use as Z buffer for dest */ - } DUMMYUNIONNAME1; - DWORD dwZSrcConstBitDepth; /* Bit depth used to specify Z constant for source */ - __extension__ union - { - DWORD dwZSrcConst; /* Constant to use as Z buffer for src */ - LPDIRECTDRAWSURFACE lpDDSZBufferSrc; /* Surface to use as Z buffer for src */ - } DUMMYUNIONNAME2; - DWORD dwAlphaEdgeBlendBitDepth; /* Bit depth used to specify constant for alpha edge blend */ - DWORD dwAlphaEdgeBlend; /* Alpha for edge blending */ - DWORD dwReserved; - DWORD dwAlphaDestConstBitDepth; /* Bit depth used to specify alpha constant for destination */ - __extension__ union - { - DWORD dwAlphaDestConst; /* Constant to use as Alpha Channel */ - LPDIRECTDRAWSURFACE lpDDSAlphaDest; /* Surface to use as Alpha Channel */ - } DUMMYUNIONNAME3; - DWORD dwAlphaSrcConstBitDepth; /* Bit depth used to specify alpha constant for source */ - __extension__ union - { - DWORD dwAlphaSrcConst; /* Constant to use as Alpha Channel */ - LPDIRECTDRAWSURFACE lpDDSAlphaSrc; /* Surface to use as Alpha Channel */ - } DUMMYUNIONNAME4; - __extension__ union - { - DWORD dwFillColor; /* color in RGB or Palettized */ - DWORD dwFillDepth; /* depth value for z-buffer */ - DWORD dwFillPixel; /* pixel val for RGBA or RGBZ */ - LPDIRECTDRAWSURFACE lpDDSPattern; /* Surface to use as pattern */ - } DUMMYUNIONNAME5; - DDCOLORKEY ddckDestColorkey; /* DestColorkey override */ - DDCOLORKEY ddckSrcColorkey; /* SrcColorkey override */ -} DDBLTFX,*LPDDBLTFX; - -/* dwDDFX */ -/* arithmetic stretching along y axis */ -#define DDBLTFX_ARITHSTRETCHY 0x00000001 -/* mirror on y axis */ -#define DDBLTFX_MIRRORLEFTRIGHT 0x00000002 -/* mirror on x axis */ -#define DDBLTFX_MIRRORUPDOWN 0x00000004 -/* do not tear */ -#define DDBLTFX_NOTEARING 0x00000008 -/* 180 degrees clockwise rotation */ -#define DDBLTFX_ROTATE180 0x00000010 -/* 270 degrees clockwise rotation */ -#define DDBLTFX_ROTATE270 0x00000020 -/* 90 degrees clockwise rotation */ -#define DDBLTFX_ROTATE90 0x00000040 -/* dwZBufferLow and dwZBufferHigh specify limits to the copied Z values */ -#define DDBLTFX_ZBUFFERRANGE 0x00000080 -/* add dwZBufferBaseDest to every source z value before compare */ -#define DDBLTFX_ZBUFFERBASEDEST 0x00000100 - -typedef struct _DDOVERLAYFX -{ - DWORD dwSize; /* size of structure */ - DWORD dwAlphaEdgeBlendBitDepth; /* Bit depth used to specify constant for alpha edge blend */ - DWORD dwAlphaEdgeBlend; /* Constant to use as alpha for edge blend */ - DWORD dwReserved; - DWORD dwAlphaDestConstBitDepth; /* Bit depth used to specify alpha constant for destination */ - __extension__ union - { - DWORD dwAlphaDestConst; /* Constant to use as alpha channel for dest */ - LPDIRECTDRAWSURFACE lpDDSAlphaDest; /* Surface to use as alpha channel for dest */ - } DUMMYUNIONNAME1; - DWORD dwAlphaSrcConstBitDepth; /* Bit depth used to specify alpha constant for source */ - __extension__ union - { - DWORD dwAlphaSrcConst; /* Constant to use as alpha channel for src */ - LPDIRECTDRAWSURFACE lpDDSAlphaSrc; /* Surface to use as alpha channel for src */ - } DUMMYUNIONNAME2; - DDCOLORKEY dckDestColorkey; /* DestColorkey override */ - DDCOLORKEY dckSrcColorkey; /* DestColorkey override */ - DWORD dwDDFX; /* Overlay FX */ - DWORD dwFlags; /* flags */ -} DDOVERLAYFX,*LPDDOVERLAYFX; - -typedef struct _DDBLTBATCH -{ - LPRECT lprDest; - LPDIRECTDRAWSURFACE lpDDSSrc; - LPRECT lprSrc; - DWORD dwFlags; - LPDDBLTFX lpDDBltFx; -} DDBLTBATCH,*LPDDBLTBATCH; - -#define MAX_DDDEVICEID_STRING 512 - -#define DDGDI_GETHOSTIDENTIFIER 1 - -typedef struct tagDDDEVICEIDENTIFIER { - char szDriver[MAX_DDDEVICEID_STRING]; - char szDescription[MAX_DDDEVICEID_STRING]; - LARGE_INTEGER liDriverVersion; - DWORD dwVendorId; - DWORD dwDeviceId; - DWORD dwSubSysId; - DWORD dwRevision; - GUID guidDeviceIdentifier; -} DDDEVICEIDENTIFIER, * LPDDDEVICEIDENTIFIER; - -typedef struct tagDDDEVICEIDENTIFIER2 { - char szDriver[MAX_DDDEVICEID_STRING]; /* user readable driver name */ - char szDescription[MAX_DDDEVICEID_STRING]; /* user readable description */ - LARGE_INTEGER liDriverVersion; /* driver version */ - DWORD dwVendorId; /* vendor ID, zero if unknown */ - DWORD dwDeviceId; /* chipset ID, zero if unknown */ - DWORD dwSubSysId; /* board ID, zero if unknown */ - DWORD dwRevision; /* chipset version, zero if unknown */ - GUID guidDeviceIdentifier; /* unique ID for this driver/chipset combination */ - DWORD dwWHQLLevel; /* Windows Hardware Quality Lab certification level */ -} DDDEVICEIDENTIFIER2, * LPDDDEVICEIDENTIFIER2; - -/***************************************************************************** - * IDirectDrawPalette interface - */ -#undef INTERFACE -#define INTERFACE IDirectDrawPalette -DECLARE_INTERFACE_(IDirectDrawPalette,IUnknown) -{ - /*** IUnknown methods ***/ - STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; - STDMETHOD_(ULONG,AddRef)(THIS) PURE; - STDMETHOD_(ULONG,Release)(THIS) PURE; - /*** IDirectDrawPalette methods ***/ - STDMETHOD(GetCaps)(THIS_ LPDWORD lpdwCaps) PURE; - STDMETHOD(GetEntries)(THIS_ DWORD dwFlags, DWORD dwBase, DWORD dwNumEntries, LPPALETTEENTRY lpEntries) PURE; - STDMETHOD(Initialize)(THIS_ LPDIRECTDRAW lpDD, DWORD dwFlags, LPPALETTEENTRY lpDDColorTable) PURE; - STDMETHOD(SetEntries)(THIS_ DWORD dwFlags, DWORD dwStartingEntry, DWORD dwCount, LPPALETTEENTRY lpEntries) PURE; -}; -#undef INTERFACE - -#if !defined(__cplusplus) || defined(CINTERFACE) -/*** IUnknown methods ***/ -#define IDirectDrawPalette_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) -#define IDirectDrawPalette_AddRef(p) (p)->lpVtbl->AddRef(p) -#define IDirectDrawPalette_Release(p) (p)->lpVtbl->Release(p) -/*** IDirectDrawPalette methods ***/ -#define IDirectDrawPalette_GetCaps(p,a) (p)->lpVtbl->GetCaps(p,a) -#define IDirectDrawPalette_GetEntries(p,a,b,c,d) (p)->lpVtbl->GetEntries(p,a,b,c,d) -#define IDirectDrawPalette_Initialize(p,a,b,c) (p)->lpVtbl->Initialize(p,a,b,c) -#define IDirectDrawPalette_SetEntries(p,a,b,c,d) (p)->lpVtbl->SetEntries(p,a,b,c,d) -#else -/*** IUnknown methods ***/ -#define IDirectDrawPalette_QueryInterface(p,a,b) (p)->QueryInterface(a,b) -#define IDirectDrawPalette_AddRef(p) (p)->AddRef() -#define IDirectDrawPalette_Release(p) (p)->Release() -/*** IDirectDrawPalette methods ***/ -#define IDirectDrawPalette_GetCaps(p,a) (p)->GetCaps(a) -#define IDirectDrawPalette_GetEntries(p,a,b,c,d) (p)->GetEntries(a,b,c,d) -#define IDirectDrawPalette_Initialize(p,a,b,c) (p)->Initialize(a,b,c) -#define IDirectDrawPalette_SetEntries(p,a,b,c,d) (p)->SetEntries(a,b,c,d) -#endif - - -/***************************************************************************** - * IDirectDrawClipper interface - */ -#define INTERFACE IDirectDrawClipper -DECLARE_INTERFACE_(IDirectDrawClipper,IUnknown) -{ - /*** IUnknown methods ***/ - STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; - STDMETHOD_(ULONG,AddRef)(THIS) PURE; - STDMETHOD_(ULONG,Release)(THIS) PURE; - /*** IDirectDrawClipper methods ***/ - STDMETHOD(GetClipList)(THIS_ LPRECT lpRect, LPRGNDATA lpClipList, LPDWORD lpdwSize) PURE; - STDMETHOD(GetHWnd)(THIS_ HWND *lphWnd) PURE; - STDMETHOD(Initialize)(THIS_ LPDIRECTDRAW lpDD, DWORD dwFlags) PURE; - STDMETHOD(IsClipListChanged)(THIS_ BOOL *lpbChanged) PURE; - STDMETHOD(SetClipList)(THIS_ LPRGNDATA lpClipList, DWORD dwFlags) PURE; - STDMETHOD(SetHWnd)(THIS_ DWORD dwFlags, HWND hWnd) PURE; -}; -#undef INTERFACE - -#if !defined(__cplusplus) || defined(CINTERFACE) -/*** IUnknown methods ***/ -#define IDirectDrawClipper_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) -#define IDirectDrawClipper_AddRef(p) (p)->lpVtbl->AddRef(p) -#define IDirectDrawClipper_Release(p) (p)->lpVtbl->Release(p) -/*** IDirectDrawClipper methods ***/ -#define IDirectDrawClipper_GetClipList(p,a,b,c) (p)->lpVtbl->GetClipList(p,a,b,c) -#define IDirectDrawClipper_GetHWnd(p,a) (p)->lpVtbl->GetHWnd(p,a) -#define IDirectDrawClipper_Initialize(p,a,b) (p)->lpVtbl->Initialize(p,a,b) -#define IDirectDrawClipper_IsClipListChanged(p,a) (p)->lpVtbl->IsClipListChanged(p,a) -#define IDirectDrawClipper_SetClipList(p,a,b) (p)->lpVtbl->SetClipList(p,a,b) -#define IDirectDrawClipper_SetHWnd(p,a,b) (p)->lpVtbl->SetHWnd(p,a,b) -#else -/*** IUnknown methods ***/ -#define IDirectDrawClipper_QueryInterface(p,a,b) (p)->QueryInterface(a,b) -#define IDirectDrawClipper_AddRef(p) (p)->AddRef() -#define IDirectDrawClipper_Release(p) (p)->Release() -/*** IDirectDrawClipper methods ***/ -#define IDirectDrawClipper_GetClipList(p,a,b,c) (p)->GetClipList(a,b,c) -#define IDirectDrawClipper_GetHWnd(p,a) (p)->GetHWnd(a) -#define IDirectDrawClipper_Initialize(p,a,b) (p)->Initialize(a,b) -#define IDirectDrawClipper_IsClipListChanged(p,a) (p)->IsClipListChanged(a) -#define IDirectDrawClipper_SetClipList(p,a,b) (p)->SetClipList(a,b) -#define IDirectDrawClipper_SetHWnd(p,a,b) (p)->SetHWnd(a,b) -#endif - - -/***************************************************************************** - * IDirectDraw interface - */ -#define INTERFACE IDirectDraw -DECLARE_INTERFACE_(IDirectDraw,IUnknown) -{ - /*** IUnknown methods ***/ - STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; - STDMETHOD_(ULONG,AddRef)(THIS) PURE; - STDMETHOD_(ULONG,Release)(THIS) PURE; - /*** IDirectDraw methods ***/ - STDMETHOD(Compact)(THIS) PURE; - STDMETHOD(CreateClipper)(THIS_ DWORD dwFlags, LPDIRECTDRAWCLIPPER *lplpDDClipper, IUnknown *pUnkOuter) PURE; - STDMETHOD(CreatePalette)(THIS_ DWORD dwFlags, LPPALETTEENTRY lpColorTable, LPDIRECTDRAWPALETTE *lplpDDPalette, IUnknown *pUnkOuter) PURE; - STDMETHOD(CreateSurface)(THIS_ LPDDSURFACEDESC lpDDSurfaceDesc, LPDIRECTDRAWSURFACE *lplpDDSurface, IUnknown *pUnkOuter) PURE; - STDMETHOD(DuplicateSurface)(THIS_ LPDIRECTDRAWSURFACE lpDDSurface, LPDIRECTDRAWSURFACE *lplpDupDDSurface) PURE; - STDMETHOD(EnumDisplayModes)(THIS_ DWORD dwFlags, LPDDSURFACEDESC lpDDSurfaceDesc, LPVOID lpContext, LPDDENUMMODESCALLBACK lpEnumModesCallback) PURE; - STDMETHOD(EnumSurfaces)(THIS_ DWORD dwFlags, LPDDSURFACEDESC lpDDSD, LPVOID lpContext, LPDDENUMSURFACESCALLBACK lpEnumSurfacesCallback) PURE; - STDMETHOD(FlipToGDISurface)(THIS) PURE; - STDMETHOD(GetCaps)(THIS_ LPDDCAPS lpDDDriverCaps, LPDDCAPS lpDDHELCaps) PURE; - STDMETHOD(GetDisplayMode)(THIS_ LPDDSURFACEDESC lpDDSurfaceDesc) PURE; - STDMETHOD(GetFourCCCodes)(THIS_ LPDWORD lpNumCodes, LPDWORD lpCodes) PURE; - STDMETHOD(GetGDISurface)(THIS_ LPDIRECTDRAWSURFACE *lplpGDIDDSurface) PURE; - STDMETHOD(GetMonitorFrequency)(THIS_ LPDWORD lpdwFrequency) PURE; - STDMETHOD(GetScanLine)(THIS_ LPDWORD lpdwScanLine) PURE; - STDMETHOD(GetVerticalBlankStatus)(THIS_ BOOL *lpbIsInVB) PURE; - STDMETHOD(Initialize)(THIS_ GUID *lpGUID) PURE; - STDMETHOD(RestoreDisplayMode)(THIS) PURE; - STDMETHOD(SetCooperativeLevel)(THIS_ HWND hWnd, DWORD dwFlags) PURE; - STDMETHOD(SetDisplayMode)(THIS_ DWORD dwWidth, DWORD dwHeight, DWORD dwBPP) PURE; - STDMETHOD(WaitForVerticalBlank)(THIS_ DWORD dwFlags, HANDLE hEvent) PURE; -}; -#undef INTERFACE - -#if !defined(__cplusplus) || defined(CINTERFACE) -/*** IUnknown methods ***/ -#define IDirectDraw_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) -#define IDirectDraw_AddRef(p) (p)->lpVtbl->AddRef(p) -#define IDirectDraw_Release(p) (p)->lpVtbl->Release(p) -/*** IDirectDraw methods ***/ -#define IDirectDraw_Compact(p) (p)->lpVtbl->Compact(p) -#define IDirectDraw_CreateClipper(p,a,b,c) (p)->lpVtbl->CreateClipper(p,a,b,c) -#define IDirectDraw_CreatePalette(p,a,b,c,d) (p)->lpVtbl->CreatePalette(p,a,b,c,d) -#define IDirectDraw_CreateSurface(p,a,b,c) (p)->lpVtbl->CreateSurface(p,a,b,c) -#define IDirectDraw_DuplicateSurface(p,a,b) (p)->lpVtbl->DuplicateSurface(p,a,b) -#define IDirectDraw_EnumDisplayModes(p,a,b,c,d) (p)->lpVtbl->EnumDisplayModes(p,a,b,c,d) -#define IDirectDraw_EnumSurfaces(p,a,b,c,d) (p)->lpVtbl->EnumSurfaces(p,a,b,c,d) -#define IDirectDraw_FlipToGDISurface(p) (p)->lpVtbl->FlipToGDISurface(p) -#define IDirectDraw_GetCaps(p,a,b) (p)->lpVtbl->GetCaps(p,a,b) -#define IDirectDraw_GetDisplayMode(p,a) (p)->lpVtbl->GetDisplayMode(p,a) -#define IDirectDraw_GetFourCCCodes(p,a,b) (p)->lpVtbl->GetFourCCCodes(p,a,b) -#define IDirectDraw_GetGDISurface(p,a) (p)->lpVtbl->GetGDISurface(p,a) -#define IDirectDraw_GetMonitorFrequency(p,a) (p)->lpVtbl->GetMonitorFrequency(p,a) -#define IDirectDraw_GetScanLine(p,a) (p)->lpVtbl->GetScanLine(p,a) -#define IDirectDraw_GetVerticalBlankStatus(p,a) (p)->lpVtbl->GetVerticalBlankStatus(p,a) -#define IDirectDraw_Initialize(p,a) (p)->lpVtbl->Initialize(p,a) -#define IDirectDraw_RestoreDisplayMode(p) (p)->lpVtbl->RestoreDisplayMode(p) -#define IDirectDraw_SetCooperativeLevel(p,a,b) (p)->lpVtbl->SetCooperativeLevel(p,a,b) -#define IDirectDraw_SetDisplayMode(p,a,b,c) (p)->lpVtbl->SetDisplayMode(p,a,b,c) -#define IDirectDraw_WaitForVerticalBlank(p,a,b) (p)->lpVtbl->WaitForVerticalBlank(p,a,b) -#else -/*** IUnknown methods ***/ -#define IDirectDraw_QueryInterface(p,a,b) (p)->QueryInterface(a,b) -#define IDirectDraw_AddRef(p) (p)->AddRef() -#define IDirectDraw_Release(p) (p)->Release() -/*** IDirectDraw methods ***/ -#define IDirectDraw_Compact(p) (p)->Compact() -#define IDirectDraw_CreateClipper(p,a,b,c) (p)->CreateClipper(a,b,c) -#define IDirectDraw_CreatePalette(p,a,b,c,d) (p)->CreatePalette(a,b,c,d) -#define IDirectDraw_CreateSurface(p,a,b,c) (p)->CreateSurface(a,b,c) -#define IDirectDraw_DuplicateSurface(p,a,b) (p)->DuplicateSurface(a,b) -#define IDirectDraw_EnumDisplayModes(p,a,b,c,d) (p)->EnumDisplayModes(a,b,c,d) -#define IDirectDraw_EnumSurfaces(p,a,b,c,d) (p)->EnumSurfaces(a,b,c,d) -#define IDirectDraw_FlipToGDISurface(p) (p)->FlipToGDISurface() -#define IDirectDraw_GetCaps(p,a,b) (p)->GetCaps(a,b) -#define IDirectDraw_GetDisplayMode(p,a) (p)->GetDisplayMode(a) -#define IDirectDraw_GetFourCCCodes(p,a,b) (p)->GetFourCCCodes(a,b) -#define IDirectDraw_GetGDISurface(p,a) (p)->GetGDISurface(a) -#define IDirectDraw_GetMonitorFrequency(p,a) (p)->GetMonitorFrequency(a) -#define IDirectDraw_GetScanLine(p,a) (p)->GetScanLine(a) -#define IDirectDraw_GetVerticalBlankStatus(p,a) (p)->GetVerticalBlankStatus(a) -#define IDirectDraw_Initialize(p,a) (p)->Initialize(a) -#define IDirectDraw_RestoreDisplayMode(p) (p)->RestoreDisplayMode() -#define IDirectDraw_SetCooperativeLevel(p,a,b) (p)->SetCooperativeLevel(a,b) -#define IDirectDraw_SetDisplayMode(p,a,b,c) (p)->SetDisplayMode(a,b,c) -#define IDirectDraw_WaitForVerticalBlank(p,a,b) (p)->WaitForVerticalBlank(a,b) -#endif - - -/* flags for Lock() */ -#define DDLOCK_SURFACEMEMORYPTR 0x00000000 -#define DDLOCK_WAIT 0x00000001 -#define DDLOCK_EVENT 0x00000002 -#define DDLOCK_READONLY 0x00000010 -#define DDLOCK_WRITEONLY 0x00000020 -#define DDLOCK_NOSYSLOCK 0x00000800 -#define DDLOCK_NOOVERWRITE 0x00001000 -#define DDLOCK_DISCARDCONTENTS 0x00002000 - - -/***************************************************************************** - * IDirectDraw2 interface - */ -/* Note: IDirectDraw2 cannot derive from IDirectDraw because the number of - * arguments of SetDisplayMode has changed ! - */ -#define INTERFACE IDirectDraw2 -DECLARE_INTERFACE_(IDirectDraw2,IUnknown) -{ - /*** IUnknown methods ***/ -/*00*/ STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; -/*04*/ STDMETHOD_(ULONG,AddRef)(THIS) PURE; -/*08*/ STDMETHOD_(ULONG,Release)(THIS) PURE; - /*** IDirectDraw2 methods ***/ -/*0c*/ STDMETHOD(Compact)(THIS) PURE; -/*10*/ STDMETHOD(CreateClipper)(THIS_ DWORD dwFlags, LPDIRECTDRAWCLIPPER *lplpDDClipper, IUnknown *pUnkOuter) PURE; -/*14*/ STDMETHOD(CreatePalette)(THIS_ DWORD dwFlags, LPPALETTEENTRY lpColorTable, LPDIRECTDRAWPALETTE *lplpDDPalette, IUnknown *pUnkOuter) PURE; -/*18*/ STDMETHOD(CreateSurface)(THIS_ LPDDSURFACEDESC lpDDSurfaceDesc, LPDIRECTDRAWSURFACE *lplpDDSurface, IUnknown *pUnkOuter) PURE; -/*1c*/ STDMETHOD(DuplicateSurface)(THIS_ LPDIRECTDRAWSURFACE lpDDSurface, LPDIRECTDRAWSURFACE *lplpDupDDSurface) PURE; -/*20*/ STDMETHOD(EnumDisplayModes)(THIS_ DWORD dwFlags, LPDDSURFACEDESC lpDDSurfaceDesc, LPVOID lpContext, LPDDENUMMODESCALLBACK lpEnumModesCallback) PURE; -/*24*/ STDMETHOD(EnumSurfaces)(THIS_ DWORD dwFlags, LPDDSURFACEDESC lpDDSD, LPVOID lpContext, LPDDENUMSURFACESCALLBACK lpEnumSurfacesCallback) PURE; -/*28*/ STDMETHOD(FlipToGDISurface)(THIS) PURE; -/*2c*/ STDMETHOD(GetCaps)(THIS_ LPDDCAPS lpDDDriverCaps, LPDDCAPS lpDDHELCaps) PURE; -/*30*/ STDMETHOD(GetDisplayMode)(THIS_ LPDDSURFACEDESC lpDDSurfaceDesc) PURE; -/*34*/ STDMETHOD(GetFourCCCodes)(THIS_ LPDWORD lpNumCodes, LPDWORD lpCodes) PURE; -/*38*/ STDMETHOD(GetGDISurface)(THIS_ LPDIRECTDRAWSURFACE *lplpGDIDDSurface) PURE; -/*3c*/ STDMETHOD(GetMonitorFrequency)(THIS_ LPDWORD lpdwFrequency) PURE; -/*40*/ STDMETHOD(GetScanLine)(THIS_ LPDWORD lpdwScanLine) PURE; -/*44*/ STDMETHOD(GetVerticalBlankStatus)(THIS_ BOOL *lpbIsInVB) PURE; -/*48*/ STDMETHOD(Initialize)(THIS_ GUID *lpGUID) PURE; -/*4c*/ STDMETHOD(RestoreDisplayMode)(THIS) PURE; -/*50*/ STDMETHOD(SetCooperativeLevel)(THIS_ HWND hWnd, DWORD dwFlags) PURE; -/*54*/ STDMETHOD(SetDisplayMode)(THIS_ DWORD dwWidth, DWORD dwHeight, DWORD dwBPP, DWORD dwRefreshRate, DWORD dwFlags) PURE; -/*58*/ STDMETHOD(WaitForVerticalBlank)(THIS_ DWORD dwFlags, HANDLE hEvent) PURE; - /* added in v2 */ -/*5c*/ STDMETHOD(GetAvailableVidMem)(THIS_ LPDDSCAPS lpDDCaps, LPDWORD lpdwTotal, LPDWORD lpdwFree) PURE; -}; -#undef INTERFACE - -#if !defined(__cplusplus) || defined(CINTERFACE) -/*** IUnknown methods ***/ -#define IDirectDraw2_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) -#define IDirectDraw2_AddRef(p) (p)->lpVtbl->AddRef(p) -#define IDirectDraw2_Release(p) (p)->lpVtbl->Release(p) -/*** IDirectDraw methods ***/ -#define IDirectDraw2_Compact(p) (p)->lpVtbl->Compact(p) -#define IDirectDraw2_CreateClipper(p,a,b,c) (p)->lpVtbl->CreateClipper(p,a,b,c) -#define IDirectDraw2_CreatePalette(p,a,b,c,d) (p)->lpVtbl->CreatePalette(p,a,b,c,d) -#define IDirectDraw2_CreateSurface(p,a,b,c) (p)->lpVtbl->CreateSurface(p,a,b,c) -#define IDirectDraw2_DuplicateSurface(p,a,b) (p)->lpVtbl->DuplicateSurface(p,a,b) -#define IDirectDraw2_EnumDisplayModes(p,a,b,c,d) (p)->lpVtbl->EnumDisplayModes(p,a,b,c,d) -#define IDirectDraw2_EnumSurfaces(p,a,b,c,d) (p)->lpVtbl->EnumSurfaces(p,a,b,c,d) -#define IDirectDraw2_FlipToGDISurface(p) (p)->lpVtbl->FlipToGDISurface(p) -#define IDirectDraw2_GetCaps(p,a,b) (p)->lpVtbl->GetCaps(p,a,b) -#define IDirectDraw2_GetDisplayMode(p,a) (p)->lpVtbl->GetDisplayMode(p,a) -#define IDirectDraw2_GetFourCCCodes(p,a,b) (p)->lpVtbl->GetFourCCCodes(p,a,b) -#define IDirectDraw2_GetGDISurface(p,a) (p)->lpVtbl->GetGDISurface(p,a) -#define IDirectDraw2_GetMonitorFrequency(p,a) (p)->lpVtbl->GetMonitorFrequency(p,a) -#define IDirectDraw2_GetScanLine(p,a) (p)->lpVtbl->GetScanLine(p,a) -#define IDirectDraw2_GetVerticalBlankStatus(p,a) (p)->lpVtbl->GetVerticalBlankStatus(p,a) -#define IDirectDraw2_Initialize(p,a) (p)->lpVtbl->Initialize(p,a) -#define IDirectDraw2_RestoreDisplayMode(p) (p)->lpVtbl->RestoreDisplayMode(p) -#define IDirectDraw2_SetCooperativeLevel(p,a,b) (p)->lpVtbl->SetCooperativeLevel(p,a,b) -#define IDirectDraw2_SetDisplayMode(p,a,b,c,d,e) (p)->lpVtbl->SetDisplayMode(p,a,b,c,d,e) -#define IDirectDraw2_WaitForVerticalBlank(p,a,b) (p)->lpVtbl->WaitForVerticalBlank(p,a,b) -/*** IDirectDraw2 methods ***/ -#define IDirectDraw2_GetAvailableVidMem(p,a,b,c) (p)->lpVtbl->GetAvailableVidMem(p,a,b,c) -#else -/*** IUnknown methods ***/ -#define IDirectDraw2_QueryInterface(p,a,b) (p)->QueryInterface(a,b) -#define IDirectDraw2_AddRef(p) (p)->AddRef() -#define IDirectDraw2_Release(p) (p)->Release() -/*** IDirectDraw methods ***/ -#define IDirectDraw2_Compact(p) (p)->Compact() -#define IDirectDraw2_CreateClipper(p,a,b,c) (p)->CreateClipper(a,b,c) -#define IDirectDraw2_CreatePalette(p,a,b,c,d) (p)->CreatePalette(a,b,c,d) -#define IDirectDraw2_CreateSurface(p,a,b,c) (p)->CreateSurface(a,b,c) -#define IDirectDraw2_DuplicateSurface(p,a,b) (p)->DuplicateSurface(a,b) -#define IDirectDraw2_EnumDisplayModes(p,a,b,c,d) (p)->EnumDisplayModes(a,b,c,d) -#define IDirectDraw2_EnumSurfaces(p,a,b,c,d) (p)->EnumSurfaces(a,b,c,d) -#define IDirectDraw2_FlipToGDISurface(p) (p)->FlipToGDISurface() -#define IDirectDraw2_GetCaps(p,a,b) (p)->GetCaps(a,b) -#define IDirectDraw2_GetDisplayMode(p,a) (p)->GetDisplayMode(a) -#define IDirectDraw2_GetFourCCCodes(p,a,b) (p)->GetFourCCCodes(a,b) -#define IDirectDraw2_GetGDISurface(p,a) (p)->GetGDISurface(a) -#define IDirectDraw2_GetMonitorFrequency(p,a) (p)->GetMonitorFrequency(a) -#define IDirectDraw2_GetScanLine(p,a) (p)->GetScanLine(a) -#define IDirectDraw2_GetVerticalBlankStatus(p,a) (p)->GetVerticalBlankStatus(a) -#define IDirectDraw2_Initialize(p,a) (p)->Initialize(a) -#define IDirectDraw2_RestoreDisplayMode(p) (p)->RestoreDisplayMode() -#define IDirectDraw2_SetCooperativeLevel(p,a,b) (p)->SetCooperativeLevel(a,b) -#define IDirectDraw2_SetDisplayMode(p,a,b,c,d,e) (p)->SetDisplayMode(a,b,c,d,e) -#define IDirectDraw2_WaitForVerticalBlank(p,a,b) (p)->WaitForVerticalBlank(a,b) -/*** IDirectDraw2 methods ***/ -#define IDirectDraw2_GetAvailableVidMem(p,a,b,c) (p)->GetAvailableVidMem(a,b,c) -#endif - - -/***************************************************************************** - * IDirectDraw3 interface - */ -#define INTERFACE IDirectDraw3 -DECLARE_INTERFACE_(IDirectDraw3,IUnknown) -{ - /*** IUnknown methods ***/ -/*00*/ STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; -/*04*/ STDMETHOD_(ULONG,AddRef)(THIS) PURE; -/*08*/ STDMETHOD_(ULONG,Release)(THIS) PURE; - /*** IDirectDraw2 methods ***/ -/*0c*/ STDMETHOD(Compact)(THIS) PURE; -/*10*/ STDMETHOD(CreateClipper)(THIS_ DWORD dwFlags, LPDIRECTDRAWCLIPPER *lplpDDClipper, IUnknown *pUnkOuter) PURE; -/*14*/ STDMETHOD(CreatePalette)(THIS_ DWORD dwFlags, LPPALETTEENTRY lpColorTable, LPDIRECTDRAWPALETTE *lplpDDPalette, IUnknown *pUnkOuter) PURE; -/*18*/ STDMETHOD(CreateSurface)(THIS_ LPDDSURFACEDESC lpDDSurfaceDesc, LPDIRECTDRAWSURFACE *lplpDDSurface, IUnknown *pUnkOuter) PURE; -/*1c*/ STDMETHOD(DuplicateSurface)(THIS_ LPDIRECTDRAWSURFACE lpDDSurface, LPDIRECTDRAWSURFACE *lplpDupDDSurface) PURE; -/*20*/ STDMETHOD(EnumDisplayModes)(THIS_ DWORD dwFlags, LPDDSURFACEDESC lpDDSurfaceDesc, LPVOID lpContext, LPDDENUMMODESCALLBACK lpEnumModesCallback) PURE; -/*24*/ STDMETHOD(EnumSurfaces)(THIS_ DWORD dwFlags, LPDDSURFACEDESC lpDDSD, LPVOID lpContext, LPDDENUMSURFACESCALLBACK lpEnumSurfacesCallback) PURE; -/*28*/ STDMETHOD(FlipToGDISurface)(THIS) PURE; -/*2c*/ STDMETHOD(GetCaps)(THIS_ LPDDCAPS lpDDDriverCaps, LPDDCAPS lpDDHELCaps) PURE; -/*30*/ STDMETHOD(GetDisplayMode)(THIS_ LPDDSURFACEDESC lpDDSurfaceDesc) PURE; -/*34*/ STDMETHOD(GetFourCCCodes)(THIS_ LPDWORD lpNumCodes, LPDWORD lpCodes) PURE; -/*38*/ STDMETHOD(GetGDISurface)(THIS_ LPDIRECTDRAWSURFACE *lplpGDIDDSurface) PURE; -/*3c*/ STDMETHOD(GetMonitorFrequency)(THIS_ LPDWORD lpdwFrequency) PURE; -/*40*/ STDMETHOD(GetScanLine)(THIS_ LPDWORD lpdwScanLine) PURE; -/*44*/ STDMETHOD(GetVerticalBlankStatus)(THIS_ BOOL *lpbIsInVB) PURE; -/*48*/ STDMETHOD(Initialize)(THIS_ GUID *lpGUID) PURE; -/*4c*/ STDMETHOD(RestoreDisplayMode)(THIS) PURE; -/*50*/ STDMETHOD(SetCooperativeLevel)(THIS_ HWND hWnd, DWORD dwFlags) PURE; -/*54*/ STDMETHOD(SetDisplayMode)(THIS_ DWORD dwWidth, DWORD dwHeight, DWORD dwBPP, DWORD dwRefreshRate, DWORD dwFlags) PURE; -/*58*/ STDMETHOD(WaitForVerticalBlank)(THIS_ DWORD dwFlags, HANDLE hEvent) PURE; - /* added in v2 */ -/*5c*/ STDMETHOD(GetAvailableVidMem)(THIS_ LPDDSCAPS lpDDCaps, LPDWORD lpdwTotal, LPDWORD lpdwFree) PURE; - /* added in v3 */ -/*60*/ STDMETHOD(GetSurfaceFromDC)(THIS_ HDC hdc, LPDIRECTDRAWSURFACE *pSurf) PURE; -}; -#undef INTERFACE - -#if !defined(__cplusplus) || defined(CINTERFACE) -/*** IUnknown methods ***/ -#define IDirectDraw3_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) -#define IDirectDraw3_AddRef(p) (p)->lpVtbl->AddRef(p) -#define IDirectDraw3_Release(p) (p)->lpVtbl->Release(p) -/*** IDirectDraw methods ***/ -#define IDirectDraw3_Compact(p) (p)->lpVtbl->Compact(p) -#define IDirectDraw3_CreateClipper(p,a,b,c) (p)->lpVtbl->CreateClipper(p,a,b,c) -#define IDirectDraw3_CreatePalette(p,a,b,c,d) (p)->lpVtbl->CreatePalette(p,a,b,c,d) -#define IDirectDraw3_CreateSurface(p,a,b,c) (p)->lpVtbl->CreateSurface(p,a,b,c) -#define IDirectDraw3_DuplicateSurface(p,a,b) (p)->lpVtbl->DuplicateSurface(p,a,b) -#define IDirectDraw3_EnumDisplayModes(p,a,b,c,d) (p)->lpVtbl->EnumDisplayModes(p,a,b,c,d) -#define IDirectDraw3_EnumSurfaces(p,a,b,c,d) (p)->lpVtbl->EnumSurfaces(p,a,b,c,d) -#define IDirectDraw3_FlipToGDISurface(p) (p)->lpVtbl->FlipToGDISurface(p) -#define IDirectDraw3_GetCaps(p,a,b) (p)->lpVtbl->GetCaps(p,a,b) -#define IDirectDraw3_GetDisplayMode(p,a) (p)->lpVtbl->GetDisplayMode(p,a) -#define IDirectDraw3_GetFourCCCodes(p,a,b) (p)->lpVtbl->GetFourCCCodes(p,a,b) -#define IDirectDraw3_GetGDISurface(p,a) (p)->lpVtbl->GetGDISurface(p,a) -#define IDirectDraw3_GetMonitorFrequency(p,a) (p)->lpVtbl->GetMonitorFrequency(p,a) -#define IDirectDraw3_GetScanLine(p,a) (p)->lpVtbl->GetScanLine(p,a) -#define IDirectDraw3_GetVerticalBlankStatus(p,a) (p)->lpVtbl->GetVerticalBlankStatus(p,a) -#define IDirectDraw3_Initialize(p,a) (p)->lpVtbl->Initialize(p,a) -#define IDirectDraw3_RestoreDisplayMode(p) (p)->lpVtbl->RestoreDisplayMode(p) -#define IDirectDraw3_SetCooperativeLevel(p,a,b) (p)->lpVtbl->SetCooperativeLevel(p,a,b) -#define IDirectDraw3_SetDisplayMode(p,a,b,c,d,e) (p)->lpVtbl->SetDisplayMode(p,a,b,c,d,e) -#define IDirectDraw3_WaitForVerticalBlank(p,a,b) (p)->lpVtbl->WaitForVerticalBlank(p,a,b) -/*** IDirectDraw2 methods ***/ -#define IDirectDraw3_GetAvailableVidMem(p,a,b,c) (p)->lpVtbl->GetAvailableVidMem(p,a,b,c) -/*** IDirectDraw3 methods ***/ -#define IDirectDraw3_GetSurfaceFromDC(p,a,b) (p)->lpVtbl->GetSurfaceFromDC(p,a,b) -#else -/*** IUnknown methods ***/ -#define IDirectDraw3_QueryInterface(p,a,b) (p)->QueryInterface(a,b) -#define IDirectDraw3_AddRef(p) (p)->AddRef() -#define IDirectDraw3_Release(p) (p)->Release() -/*** IDirectDraw methods ***/ -#define IDirectDraw3_Compact(p) (p)->Compact() -#define IDirectDraw3_CreateClipper(p,a,b,c) (p)->CreateClipper(a,b,c) -#define IDirectDraw3_CreatePalette(p,a,b,c,d) (p)->CreatePalette(a,b,c,d) -#define IDirectDraw3_CreateSurface(p,a,b,c) (p)->CreateSurface(a,b,c) -#define IDirectDraw3_DuplicateSurface(p,a,b) (p)->DuplicateSurface(a,b) -#define IDirectDraw3_EnumDisplayModes(p,a,b,c,d) (p)->EnumDisplayModes(a,b,c,d) -#define IDirectDraw3_EnumSurfaces(p,a,b,c,d) (p)->EnumSurfaces(a,b,c,d) -#define IDirectDraw3_FlipToGDISurface(p) (p)->FlipToGDISurface() -#define IDirectDraw3_GetCaps(p,a,b) (p)->GetCaps(a,b) -#define IDirectDraw3_GetDisplayMode(p,a) (p)->GetDisplayMode(a) -#define IDirectDraw3_GetFourCCCodes(p,a,b) (p)->GetFourCCCodes(a,b) -#define IDirectDraw3_GetGDISurface(p,a) (p)->GetGDISurface(a) -#define IDirectDraw3_GetMonitorFrequency(p,a) (p)->GetMonitorFrequency(a) -#define IDirectDraw3_GetScanLine(p,a) (p)->GetScanLine(a) -#define IDirectDraw3_GetVerticalBlankStatus(p,a) (p)->GetVerticalBlankStatus(a) -#define IDirectDraw3_Initialize(p,a) (p)->Initialize(a) -#define IDirectDraw3_RestoreDisplayMode(p) (p)->RestoreDisplayMode() -#define IDirectDraw3_SetCooperativeLevel(p,a,b) (p)->SetCooperativeLevel(a,b) -#define IDirectDraw3_SetDisplayMode(p,a,b,c,d,e) (p)->SetDisplayMode(a,b,c,d,e) -#define IDirectDraw3_WaitForVerticalBlank(p,a,b) (p)->WaitForVerticalBlank(a,b) -/*** IDirectDraw2 methods ***/ -#define IDirectDraw3_GetAvailableVidMem(p,a,b,c) (p)->GetAvailableVidMem(a,b,c) -/*** IDirectDraw3 methods ***/ -#define IDirectDraw3_GetSurfaceFromDC(p,a,b) (p)->GetSurfaceFromDC(a,b) -#endif - - -/***************************************************************************** - * IDirectDraw4 interface - */ -#define INTERFACE IDirectDraw4 -DECLARE_INTERFACE_(IDirectDraw4,IUnknown) -{ - /*** IUnknown methods ***/ -/*00*/ STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; -/*04*/ STDMETHOD_(ULONG,AddRef)(THIS) PURE; -/*08*/ STDMETHOD_(ULONG,Release)(THIS) PURE; - /*** IDirectDraw4 methods ***/ -/*0c*/ STDMETHOD(Compact)(THIS) PURE; -/*10*/ STDMETHOD(CreateClipper)(THIS_ DWORD dwFlags, LPDIRECTDRAWCLIPPER *lplpDDClipper, IUnknown *pUnkOuter) PURE; -/*14*/ STDMETHOD(CreatePalette)(THIS_ DWORD dwFlags, LPPALETTEENTRY lpColorTable, LPDIRECTDRAWPALETTE *lplpDDPalette, IUnknown *pUnkOuter) PURE; -/*18*/ STDMETHOD(CreateSurface)(THIS_ LPDDSURFACEDESC2 lpDDSurfaceDesc, LPDIRECTDRAWSURFACE4 *lplpDDSurface, IUnknown *pUnkOuter) PURE; -/*1c*/ STDMETHOD(DuplicateSurface)(THIS_ LPDIRECTDRAWSURFACE4 lpDDSurface, LPDIRECTDRAWSURFACE4 *lplpDupDDSurface) PURE; -/*20*/ STDMETHOD(EnumDisplayModes)(THIS_ DWORD dwFlags, LPDDSURFACEDESC2 lpDDSurfaceDesc, LPVOID lpContext, LPDDENUMMODESCALLBACK2 lpEnumModesCallback) PURE; -/*24*/ STDMETHOD(EnumSurfaces)(THIS_ DWORD dwFlags, LPDDSURFACEDESC2 lpDDSD, LPVOID lpContext, LPDDENUMSURFACESCALLBACK2 lpEnumSurfacesCallback) PURE; -/*28*/ STDMETHOD(FlipToGDISurface)(THIS) PURE; -/*2c*/ STDMETHOD(GetCaps)(THIS_ LPDDCAPS lpDDDriverCaps, LPDDCAPS lpDDHELCaps) PURE; -/*30*/ STDMETHOD(GetDisplayMode)(THIS_ LPDDSURFACEDESC2 lpDDSurfaceDesc) PURE; -/*34*/ STDMETHOD(GetFourCCCodes)(THIS_ LPDWORD lpNumCodes, LPDWORD lpCodes) PURE; -/*38*/ STDMETHOD(GetGDISurface)(THIS_ LPDIRECTDRAWSURFACE4 *lplpGDIDDSurface) PURE; -/*3c*/ STDMETHOD(GetMonitorFrequency)(THIS_ LPDWORD lpdwFrequency) PURE; -/*40*/ STDMETHOD(GetScanLine)(THIS_ LPDWORD lpdwScanLine) PURE; -/*44*/ STDMETHOD(GetVerticalBlankStatus)(THIS_ BOOL *lpbIsInVB) PURE; -/*48*/ STDMETHOD(Initialize)(THIS_ GUID *lpGUID) PURE; -/*4c*/ STDMETHOD(RestoreDisplayMode)(THIS) PURE; -/*50*/ STDMETHOD(SetCooperativeLevel)(THIS_ HWND hWnd, DWORD dwFlags) PURE; -/*54*/ STDMETHOD(SetDisplayMode)(THIS_ DWORD dwWidth, DWORD dwHeight, DWORD dwBPP, DWORD dwRefreshRate, DWORD dwFlags) PURE; -/*58*/ STDMETHOD(WaitForVerticalBlank)(THIS_ DWORD dwFlags, HANDLE hEvent) PURE; - /* added in v2 */ -/*5c*/ STDMETHOD(GetAvailableVidMem)(THIS_ LPDDSCAPS2 lpDDCaps, LPDWORD lpdwTotal, LPDWORD lpdwFree) PURE; - /* added in v4 */ -/*60*/ STDMETHOD(GetSurfaceFromDC)(THIS_ HDC hdc, LPDIRECTDRAWSURFACE4 *pSurf) PURE; -/*64*/ STDMETHOD(RestoreAllSurfaces)(THIS) PURE; -/*68*/ STDMETHOD(TestCooperativeLevel)(THIS) PURE; -/*6c*/ STDMETHOD(GetDeviceIdentifier)(THIS_ LPDDDEVICEIDENTIFIER pDDDI, DWORD dwFlags) PURE; -}; -#undef INTERFACE - -#if !defined(__cplusplus) || defined(CINTERFACE) -/*** IUnknown methods ***/ -#define IDirectDraw4_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) -#define IDirectDraw4_AddRef(p) (p)->lpVtbl->AddRef(p) -#define IDirectDraw4_Release(p) (p)->lpVtbl->Release(p) -/*** IDirectDraw methods ***/ -#define IDirectDraw4_Compact(p) (p)->lpVtbl->Compact(p) -#define IDirectDraw4_CreateClipper(p,a,b,c) (p)->lpVtbl->CreateClipper(p,a,b,c) -#define IDirectDraw4_CreatePalette(p,a,b,c,d) (p)->lpVtbl->CreatePalette(p,a,b,c,d) -#define IDirectDraw4_CreateSurface(p,a,b,c) (p)->lpVtbl->CreateSurface(p,a,b,c) -#define IDirectDraw4_DuplicateSurface(p,a,b) (p)->lpVtbl->DuplicateSurface(p,a,b) -#define IDirectDraw4_EnumDisplayModes(p,a,b,c,d) (p)->lpVtbl->EnumDisplayModes(p,a,b,c,d) -#define IDirectDraw4_EnumSurfaces(p,a,b,c,d) (p)->lpVtbl->EnumSurfaces(p,a,b,c,d) -#define IDirectDraw4_FlipToGDISurface(p) (p)->lpVtbl->FlipToGDISurface(p) -#define IDirectDraw4_GetCaps(p,a,b) (p)->lpVtbl->GetCaps(p,a,b) -#define IDirectDraw4_GetDisplayMode(p,a) (p)->lpVtbl->GetDisplayMode(p,a) -#define IDirectDraw4_GetFourCCCodes(p,a,b) (p)->lpVtbl->GetFourCCCodes(p,a,b) -#define IDirectDraw4_GetGDISurface(p,a) (p)->lpVtbl->GetGDISurface(p,a) -#define IDirectDraw4_GetMonitorFrequency(p,a) (p)->lpVtbl->GetMonitorFrequency(p,a) -#define IDirectDraw4_GetScanLine(p,a) (p)->lpVtbl->GetScanLine(p,a) -#define IDirectDraw4_GetVerticalBlankStatus(p,a) (p)->lpVtbl->GetVerticalBlankStatus(p,a) -#define IDirectDraw4_Initialize(p,a) (p)->lpVtbl->Initialize(p,a) -#define IDirectDraw4_RestoreDisplayMode(p) (p)->lpVtbl->RestoreDisplayMode(p) -#define IDirectDraw4_SetCooperativeLevel(p,a,b) (p)->lpVtbl->SetCooperativeLevel(p,a,b) -#define IDirectDraw4_SetDisplayMode(p,a,b,c,d,e) (p)->lpVtbl->SetDisplayMode(p,a,b,c,d,e) -#define IDirectDraw4_WaitForVerticalBlank(p,a,b) (p)->lpVtbl->WaitForVerticalBlank(p,a,b) -/*** IDirectDraw2 methods ***/ -#define IDirectDraw4_GetAvailableVidMem(p,a,b,c) (p)->lpVtbl->GetAvailableVidMem(p,a,b,c) -/*** IDirectDraw4 methods ***/ -#define IDirectDraw4_GetSurfaceFromDC(p,a,b) (p)->lpVtbl->GetSurfaceFromDC(p,a,b) -#define IDirectDraw4_RestoreAllSurfaces(p) (p)->lpVtbl->RestoreAllSurfaces(p) -#define IDirectDraw4_TestCooperativeLevel(p) (p)->lpVtbl->TestCooperativeLevel(p) -#define IDirectDraw4_GetDeviceIdentifier(p,a,b) (p)->lpVtbl->GetDeviceIdentifier(p,a,b) -#else -/*** IUnknown methods ***/ -#define IDirectDraw4_QueryInterface(p,a,b) (p)->QueryInterface(a,b) -#define IDirectDraw4_AddRef(p) (p)->AddRef() -#define IDirectDraw4_Release(p) (p)->Release() -/*** IDirectDraw methods ***/ -#define IDirectDraw4_Compact(p) (p)->Compact() -#define IDirectDraw4_CreateClipper(p,a,b,c) (p)->CreateClipper(a,b,c) -#define IDirectDraw4_CreatePalette(p,a,b,c,d) (p)->CreatePalette(a,b,c,d) -#define IDirectDraw4_CreateSurface(p,a,b,c) (p)->CreateSurface(a,b,c) -#define IDirectDraw4_DuplicateSurface(p,a,b) (p)->DuplicateSurface(a,b) -#define IDirectDraw4_EnumDisplayModes(p,a,b,c,d) (p)->EnumDisplayModes(a,b,c,d) -#define IDirectDraw4_EnumSurfaces(p,a,b,c,d) (p)->EnumSurfaces(a,b,c,d) -#define IDirectDraw4_FlipToGDISurface(p) (p)->FlipToGDISurface() -#define IDirectDraw4_GetCaps(p,a,b) (p)->GetCaps(a,b) -#define IDirectDraw4_GetDisplayMode(p,a) (p)->GetDisplayMode(a) -#define IDirectDraw4_GetFourCCCodes(p,a,b) (p)->GetFourCCCodes(a,b) -#define IDirectDraw4_GetGDISurface(p,a) (p)->GetGDISurface(a) -#define IDirectDraw4_GetMonitorFrequency(p,a) (p)->GetMonitorFrequency(a) -#define IDirectDraw4_GetScanLine(p,a) (p)->GetScanLine(a) -#define IDirectDraw4_GetVerticalBlankStatus(p,a) (p)->GetVerticalBlankStatus(a) -#define IDirectDraw4_Initialize(p,a) (p)->Initialize(a) -#define IDirectDraw4_RestoreDisplayMode(p) (p)->RestoreDisplayMode() -#define IDirectDraw4_SetCooperativeLevel(p,a,b) (p)->SetCooperativeLevel(a,b) -#define IDirectDraw4_SetDisplayMode(p,a,b,c,d,e) (p)->SetDisplayMode(a,b,c,d,e) -#define IDirectDraw4_WaitForVerticalBlank(p,a,b) (p)->WaitForVerticalBlank(a,b) -/*** IDirectDraw2 methods ***/ -#define IDirectDraw4_GetAvailableVidMem(p,a,b,c) (p)->GetAvailableVidMem(a,b,c) -/*** IDirectDraw4 methods ***/ -#define IDirectDraw4_GetSurfaceFromDC(p,a,b) (p)->GetSurfaceFromDC(a,b) -#define IDirectDraw4_RestoreAllSurfaces(pc) (p)->RestoreAllSurfaces() -#define IDirectDraw4_TestCooperativeLevel(p) (p)->TestCooperativeLevel() -#define IDirectDraw4_GetDeviceIdentifier(p,a,b) (p)->GetDeviceIdentifier(a,b) -#endif - - -/***************************************************************************** - * IDirectDraw7 interface - */ -/* Note: IDirectDraw7 cannot derive from IDirectDraw4; it is even documented - * as not interchangeable with earlier DirectDraw interfaces. - */ -#define INTERFACE IDirectDraw7 -DECLARE_INTERFACE_(IDirectDraw7,IUnknown) -{ - /*** IUnknown methods ***/ -/*00*/ STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; -/*04*/ STDMETHOD_(ULONG,AddRef)(THIS) PURE; -/*08*/ STDMETHOD_(ULONG,Release)(THIS) PURE; - /*** IDirectDraw7 methods ***/ -/*0c*/ STDMETHOD(Compact)(THIS) PURE; -/*10*/ STDMETHOD(CreateClipper)(THIS_ DWORD dwFlags, LPDIRECTDRAWCLIPPER *lplpDDClipper, IUnknown *pUnkOuter) PURE; -/*14*/ STDMETHOD(CreatePalette)(THIS_ DWORD dwFlags, LPPALETTEENTRY lpColorTable, LPDIRECTDRAWPALETTE *lplpDDPalette, IUnknown *pUnkOuter) PURE; -/*18*/ STDMETHOD(CreateSurface)(THIS_ LPDDSURFACEDESC2 lpDDSurfaceDesc, LPDIRECTDRAWSURFACE7 *lplpDDSurface, IUnknown *pUnkOuter) PURE; -/*1c*/ STDMETHOD(DuplicateSurface)(THIS_ LPDIRECTDRAWSURFACE7 lpDDSurface, LPDIRECTDRAWSURFACE7 *lplpDupDDSurface) PURE; -/*20*/ STDMETHOD(EnumDisplayModes)(THIS_ DWORD dwFlags, LPDDSURFACEDESC2 lpDDSurfaceDesc, LPVOID lpContext, LPDDENUMMODESCALLBACK2 lpEnumModesCallback) PURE; -/*24*/ STDMETHOD(EnumSurfaces)(THIS_ DWORD dwFlags, LPDDSURFACEDESC2 lpDDSD, LPVOID lpContext, LPDDENUMSURFACESCALLBACK7 lpEnumSurfacesCallback) PURE; -/*28*/ STDMETHOD(FlipToGDISurface)(THIS) PURE; -/*2c*/ STDMETHOD(GetCaps)(THIS_ LPDDCAPS lpDDDriverCaps, LPDDCAPS lpDDHELCaps) PURE; -/*30*/ STDMETHOD(GetDisplayMode)(THIS_ LPDDSURFACEDESC2 lpDDSurfaceDesc) PURE; -/*34*/ STDMETHOD(GetFourCCCodes)(THIS_ LPDWORD lpNumCodes, LPDWORD lpCodes) PURE; -/*38*/ STDMETHOD(GetGDISurface)(THIS_ LPDIRECTDRAWSURFACE7 *lplpGDIDDSurface) PURE; -/*3c*/ STDMETHOD(GetMonitorFrequency)(THIS_ LPDWORD lpdwFrequency) PURE; -/*40*/ STDMETHOD(GetScanLine)(THIS_ LPDWORD lpdwScanLine) PURE; -/*44*/ STDMETHOD(GetVerticalBlankStatus)(THIS_ BOOL *lpbIsInVB) PURE; -/*48*/ STDMETHOD(Initialize)(THIS_ GUID *lpGUID) PURE; -/*4c*/ STDMETHOD(RestoreDisplayMode)(THIS) PURE; -/*50*/ STDMETHOD(SetCooperativeLevel)(THIS_ HWND hWnd, DWORD dwFlags) PURE; -/*54*/ STDMETHOD(SetDisplayMode)(THIS_ DWORD dwWidth, DWORD dwHeight, DWORD dwBPP, DWORD dwRefreshRate, DWORD dwFlags) PURE; -/*58*/ STDMETHOD(WaitForVerticalBlank)(THIS_ DWORD dwFlags, HANDLE hEvent) PURE; - /* added in v2 */ -/*5c*/ STDMETHOD(GetAvailableVidMem)(THIS_ LPDDSCAPS2 lpDDCaps, LPDWORD lpdwTotal, LPDWORD lpdwFree) PURE; - /* added in v4 */ -/*60*/ STDMETHOD(GetSurfaceFromDC)(THIS_ HDC hdc, LPDIRECTDRAWSURFACE7 *pSurf) PURE; -/*64*/ STDMETHOD(RestoreAllSurfaces)(THIS) PURE; -/*68*/ STDMETHOD(TestCooperativeLevel)(THIS) PURE; -/*6c*/ STDMETHOD(GetDeviceIdentifier)(THIS_ LPDDDEVICEIDENTIFIER2 pDDDI, DWORD dwFlags) PURE; - /* added in v7 */ -/*70*/ STDMETHOD(StartModeTest)(THIS_ LPSIZE pModes, DWORD dwNumModes, DWORD dwFlags) PURE; -/*74*/ STDMETHOD(EvaluateMode)(THIS_ DWORD dwFlags, DWORD *pTimeout) PURE; -}; -#undef INTERFACE - -#if !defined(__cplusplus) || defined(CINTERFACE) -/*** IUnknown methods ***/ -#define IDirectDraw7_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) -#define IDirectDraw7_AddRef(p) (p)->lpVtbl->AddRef(p) -#define IDirectDraw7_Release(p) (p)->lpVtbl->Release(p) -/*** IDirectDraw methods ***/ -#define IDirectDraw7_Compact(p) (p)->lpVtbl->Compact(p) -#define IDirectDraw7_CreateClipper(p,a,b,c) (p)->lpVtbl->CreateClipper(p,a,b,c) -#define IDirectDraw7_CreatePalette(p,a,b,c,d) (p)->lpVtbl->CreatePalette(p,a,b,c,d) -#define IDirectDraw7_CreateSurface(p,a,b,c) (p)->lpVtbl->CreateSurface(p,a,b,c) -#define IDirectDraw7_DuplicateSurface(p,a,b) (p)->lpVtbl->DuplicateSurface(p,a,b) -#define IDirectDraw7_EnumDisplayModes(p,a,b,c,d) (p)->lpVtbl->EnumDisplayModes(p,a,b,c,d) -#define IDirectDraw7_EnumSurfaces(p,a,b,c,d) (p)->lpVtbl->EnumSurfaces(p,a,b,c,d) -#define IDirectDraw7_FlipToGDISurface(p) (p)->lpVtbl->FlipToGDISurface(p) -#define IDirectDraw7_GetCaps(p,a,b) (p)->lpVtbl->GetCaps(p,a,b) -#define IDirectDraw7_GetDisplayMode(p,a) (p)->lpVtbl->GetDisplayMode(p,a) -#define IDirectDraw7_GetFourCCCodes(p,a,b) (p)->lpVtbl->GetFourCCCodes(p,a,b) -#define IDirectDraw7_GetGDISurface(p,a) (p)->lpVtbl->GetGDISurface(p,a) -#define IDirectDraw7_GetMonitorFrequency(p,a) (p)->lpVtbl->GetMonitorFrequency(p,a) -#define IDirectDraw7_GetScanLine(p,a) (p)->lpVtbl->GetScanLine(p,a) -#define IDirectDraw7_GetVerticalBlankStatus(p,a) (p)->lpVtbl->GetVerticalBlankStatus(p,a) -#define IDirectDraw7_Initialize(p,a) (p)->lpVtbl->Initialize(p,a) -#define IDirectDraw7_RestoreDisplayMode(p) (p)->lpVtbl->RestoreDisplayMode(p) -#define IDirectDraw7_SetCooperativeLevel(p,a,b) (p)->lpVtbl->SetCooperativeLevel(p,a,b) -#define IDirectDraw7_SetDisplayMode(p,a,b,c,d,e) (p)->lpVtbl->SetDisplayMode(p,a,b,c,d,e) -#define IDirectDraw7_WaitForVerticalBlank(p,a,b) (p)->lpVtbl->WaitForVerticalBlank(p,a,b) -/*** added in IDirectDraw2 ***/ -#define IDirectDraw7_GetAvailableVidMem(p,a,b,c) (p)->lpVtbl->GetAvailableVidMem(p,a,b,c) -/*** added in IDirectDraw4 ***/ -#define IDirectDraw7_GetSurfaceFromDC(p,a,b) (p)->lpVtbl->GetSurfaceFromDC(p,a,b) -#define IDirectDraw7_RestoreAllSurfaces(p) (p)->lpVtbl->RestoreAllSurfaces(p) -#define IDirectDraw7_TestCooperativeLevel(p) (p)->lpVtbl->TestCooperativeLevel(p) -#define IDirectDraw7_GetDeviceIdentifier(p,a,b) (p)->lpVtbl->GetDeviceIdentifier(p,a,b) -/*** added in IDirectDraw 7 ***/ -#define IDirectDraw7_StartModeTest(p,a,b,c) (p)->lpVtbl->StartModeTest(p,a,b,c) -#define IDirectDraw7_EvaluateMode(p,a,b) (p)->lpVtbl->EvaluateMode(p,a,b) -#else -/*** IUnknown methods ***/ -#define IDirectDraw7_QueryInterface(p,a,b) (p)->QueryInterface(a,b) -#define IDirectDraw7_AddRef(p) (p)->AddRef() -#define IDirectDraw7_Release(p) (p)->Release() -/*** IDirectDraw methods ***/ -#define IDirectDraw7_Compact(p) (p)->Compact() -#define IDirectDraw7_CreateClipper(p,a,b,c) (p)->CreateClipper(a,b,c) -#define IDirectDraw7_CreatePalette(p,a,b,c,d) (p)->CreatePalette(a,b,c,d) -#define IDirectDraw7_CreateSurface(p,a,b,c) (p)->CreateSurface(a,b,c) -#define IDirectDraw7_DuplicateSurface(p,a,b) (p)->DuplicateSurface(a,b) -#define IDirectDraw7_EnumDisplayModes(p,a,b,c,d) (p)->EnumDisplayModes(a,b,c,d) -#define IDirectDraw7_EnumSurfaces(p,a,b,c,d) (p)->EnumSurfaces(a,b,c,d) -#define IDirectDraw7_FlipToGDISurface(p) (p)->FlipToGDISurface() -#define IDirectDraw7_GetCaps(p,a,b) (p)->GetCaps(a,b) -#define IDirectDraw7_GetDisplayMode(p,a) (p)->GetDisplayMode(a) -#define IDirectDraw7_GetFourCCCodes(p,a,b) (p)->GetFourCCCodes(a,b) -#define IDirectDraw7_GetGDISurface(p,a) (p)->GetGDISurface(a) -#define IDirectDraw7_GetMonitorFrequency(p,a) (p)->GetMonitorFrequency(a) -#define IDirectDraw7_GetScanLine(p,a) (p)->GetScanLine(a) -#define IDirectDraw7_GetVerticalBlankStatus(p,a) (p)->GetVerticalBlankStatus(a) -#define IDirectDraw7_Initialize(p,a) (p)->Initialize(a) -#define IDirectDraw7_RestoreDisplayMode(p) (p)->RestoreDisplayMode() -#define IDirectDraw7_SetCooperativeLevel(p,a,b) (p)->SetCooperativeLevel(a,b) -#define IDirectDraw7_SetDisplayMode(p,a,b,c,d,e) (p)->SetDisplayMode(a,b,c,d,e) -#define IDirectDraw7_WaitForVerticalBlank(p,a,b) (p)->WaitForVerticalBlank(a,b) -/*** added in IDirectDraw2 ***/ -#define IDirectDraw7_GetAvailableVidMem(p,a,b,c) (p)->GetAvailableVidMem(a,b,c) -/*** added in IDirectDraw4 ***/ -#define IDirectDraw7_GetSurfaceFromDC(p,a,b) (p)->GetSurfaceFromDC(a,b) -#define IDirectDraw7_RestoreAllSurfaces(p) (p)->RestoreAllSurfaces() -#define IDirectDraw7_TestCooperativeLevel(p) (p)->TestCooperativeLevel() -#define IDirectDraw7_GetDeviceIdentifier(p,a,b) (p)->GetDeviceIdentifier(a,b) -/*** added in IDirectDraw 7 ***/ -#define IDirectDraw7_StartModeTest(p,a,b,c) (p)->StartModeTest(a,b,c) -#define IDirectDraw7_EvaluateMode(p,a,b) (p)->EvaluateMode(a,b) -#endif - - -/***************************************************************************** - * IDirectDrawSurface interface - */ -#define INTERFACE IDirectDrawSurface -DECLARE_INTERFACE_(IDirectDrawSurface,IUnknown) -{ - /*** IUnknown methods ***/ -/*00*/ STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; -/*04*/ STDMETHOD_(ULONG,AddRef)(THIS) PURE; -/*08*/ STDMETHOD_(ULONG,Release)(THIS) PURE; - /*** IDirectDrawSurface methods ***/ -/*0c*/ STDMETHOD(AddAttachedSurface)(THIS_ LPDIRECTDRAWSURFACE lpDDSAttachedSurface) PURE; -/*10*/ STDMETHOD(AddOverlayDirtyRect)(THIS_ LPRECT lpRect) PURE; -/*14*/ STDMETHOD(Blt)(THIS_ LPRECT lpDestRect, LPDIRECTDRAWSURFACE lpDDSrcSurface, LPRECT lpSrcRect, DWORD dwFlags, LPDDBLTFX lpDDBltFx) PURE; -/*18*/ STDMETHOD(BltBatch)(THIS_ LPDDBLTBATCH lpDDBltBatch, DWORD dwCount, DWORD dwFlags) PURE; -/*1c*/ STDMETHOD(BltFast)(THIS_ DWORD dwX, DWORD dwY, LPDIRECTDRAWSURFACE lpDDSrcSurface, LPRECT lpSrcRect, DWORD dwTrans) PURE; -/*20*/ STDMETHOD(DeleteAttachedSurface)(THIS_ DWORD dwFlags, LPDIRECTDRAWSURFACE lpDDSAttachedSurface) PURE; -/*24*/ STDMETHOD(EnumAttachedSurfaces)(THIS_ LPVOID lpContext, LPDDENUMSURFACESCALLBACK lpEnumSurfacesCallback) PURE; -/*28*/ STDMETHOD(EnumOverlayZOrders)(THIS_ DWORD dwFlags, LPVOID lpContext, LPDDENUMSURFACESCALLBACK lpfnCallback) PURE; -/*2c*/ STDMETHOD(Flip)(THIS_ LPDIRECTDRAWSURFACE lpDDSurfaceTargetOverride, DWORD dwFlags) PURE; -/*30*/ STDMETHOD(GetAttachedSurface)(THIS_ LPDDSCAPS lpDDSCaps, LPDIRECTDRAWSURFACE *lplpDDAttachedSurface) PURE; -/*34*/ STDMETHOD(GetBltStatus)(THIS_ DWORD dwFlags) PURE; -/*38*/ STDMETHOD(GetCaps)(THIS_ LPDDSCAPS lpDDSCaps) PURE; -/*3c*/ STDMETHOD(GetClipper)(THIS_ LPDIRECTDRAWCLIPPER *lplpDDClipper) PURE; -/*40*/ STDMETHOD(GetColorKey)(THIS_ DWORD dwFlags, LPDDCOLORKEY lpDDColorKey) PURE; -/*44*/ STDMETHOD(GetDC)(THIS_ HDC *lphDC) PURE; -/*48*/ STDMETHOD(GetFlipStatus)(THIS_ DWORD dwFlags) PURE; -/*4c*/ STDMETHOD(GetOverlayPosition)(THIS_ LPLONG lplX, LPLONG lplY) PURE; -/*50*/ STDMETHOD(GetPalette)(THIS_ LPDIRECTDRAWPALETTE *lplpDDPalette) PURE; -/*54*/ STDMETHOD(GetPixelFormat)(THIS_ LPDDPIXELFORMAT lpDDPixelFormat) PURE; -/*58*/ STDMETHOD(GetSurfaceDesc)(THIS_ LPDDSURFACEDESC lpDDSurfaceDesc) PURE; -/*5c*/ STDMETHOD(Initialize)(THIS_ LPDIRECTDRAW lpDD, LPDDSURFACEDESC lpDDSurfaceDesc) PURE; -/*60*/ STDMETHOD(IsLost)(THIS) PURE; -/*64*/ STDMETHOD(Lock)(THIS_ LPRECT lpDestRect, LPDDSURFACEDESC lpDDSurfaceDesc, DWORD dwFlags, HANDLE hEvent) PURE; -/*68*/ STDMETHOD(ReleaseDC)(THIS_ HDC hDC) PURE; -/*6c*/ STDMETHOD(Restore)(THIS) PURE; -/*70*/ STDMETHOD(SetClipper)(THIS_ LPDIRECTDRAWCLIPPER lpDDClipper) PURE; -/*74*/ STDMETHOD(SetColorKey)(THIS_ DWORD dwFlags, LPDDCOLORKEY lpDDColorKey) PURE; -/*78*/ STDMETHOD(SetOverlayPosition)(THIS_ LONG lX, LONG lY) PURE; -/*7c*/ STDMETHOD(SetPalette)(THIS_ LPDIRECTDRAWPALETTE lpDDPalette) PURE; -/*80*/ STDMETHOD(Unlock)(THIS_ LPVOID lpSurfaceData) PURE; -/*84*/ STDMETHOD(UpdateOverlay)(THIS_ LPRECT lpSrcRect, LPDIRECTDRAWSURFACE lpDDDestSurface, LPRECT lpDestRect, DWORD dwFlags, LPDDOVERLAYFX lpDDOverlayFx) PURE; -/*88*/ STDMETHOD(UpdateOverlayDisplay)(THIS_ DWORD dwFlags) PURE; -/*8c*/ STDMETHOD(UpdateOverlayZOrder)(THIS_ DWORD dwFlags, LPDIRECTDRAWSURFACE lpDDSReference) PURE; -}; -#undef INTERFACE - -#if !defined(__cplusplus) || defined(CINTERFACE) -/*** IUnknown methods ***/ -#define IDirectDrawSurface_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) -#define IDirectDrawSurface_AddRef(p) (p)->lpVtbl->AddRef(p) -#define IDirectDrawSurface_Release(p) (p)->lpVtbl->Release(p) -/*** IDirectDrawSurface methods ***/ -#define IDirectDrawSurface_AddAttachedSurface(p,a) (p)->lpVtbl->AddAttachedSurface(p,a) -#define IDirectDrawSurface_AddOverlayDirtyRect(p,a) (p)->lpVtbl->AddOverlayDirtyRect(p,a) -#define IDirectDrawSurface_Blt(p,a,b,c,d,e) (p)->lpVtbl->Blt(p,a,b,c,d,e) -#define IDirectDrawSurface_BltBatch(p,a,b,c) (p)->lpVtbl->BltBatch(p,a,b,c) -#define IDirectDrawSurface_BltFast(p,a,b,c,d,e) (p)->lpVtbl->BltFast(p,a,b,c,d,e) -#define IDirectDrawSurface_DeleteAttachedSurface(p,a,b) (p)->lpVtbl->DeleteAttachedSurface(p,a,b) -#define IDirectDrawSurface_EnumAttachedSurfaces(p,a,b) (p)->lpVtbl->EnumAttachedSurfaces(p,a,b) -#define IDirectDrawSurface_EnumOverlayZOrders(p,a,b,c) (p)->lpVtbl->EnumOverlayZOrders(p,a,b,c) -#define IDirectDrawSurface_Flip(p,a,b) (p)->lpVtbl->Flip(p,a,b) -#define IDirectDrawSurface_GetAttachedSurface(p,a,b) (p)->lpVtbl->GetAttachedSurface(p,a,b) -#define IDirectDrawSurface_GetBltStatus(p,a) (p)->lpVtbl->GetBltStatus(p,a) -#define IDirectDrawSurface_GetCaps(p,a) (p)->lpVtbl->GetCaps(p,a) -#define IDirectDrawSurface_GetClipper(p,a) (p)->lpVtbl->GetClipper(p,a) -#define IDirectDrawSurface_GetColorKey(p,a,b) (p)->lpVtbl->GetColorKey(p,a,b) -#define IDirectDrawSurface_GetDC(p,a) (p)->lpVtbl->GetDC(p,a) -#define IDirectDrawSurface_GetFlipStatus(p,a) (p)->lpVtbl->GetFlipStatus(p,a) -#define IDirectDrawSurface_GetOverlayPosition(p,a,b) (p)->lpVtbl->GetOverlayPosition(p,a,b) -#define IDirectDrawSurface_GetPalette(p,a) (p)->lpVtbl->GetPalette(p,a) -#define IDirectDrawSurface_GetPixelFormat(p,a) (p)->lpVtbl->GetPixelFormat(p,a) -#define IDirectDrawSurface_GetSurfaceDesc(p,a) (p)->lpVtbl->GetSurfaceDesc(p,a) -#define IDirectDrawSurface_Initialize(p,a,b) (p)->lpVtbl->Initialize(p,a,b) -#define IDirectDrawSurface_IsLost(p) (p)->lpVtbl->IsLost(p) -#define IDirectDrawSurface_Lock(p,a,b,c,d) (p)->lpVtbl->Lock(p,a,b,c,d) -#define IDirectDrawSurface_ReleaseDC(p,a) (p)->lpVtbl->ReleaseDC(p,a) -#define IDirectDrawSurface_Restore(p) (p)->lpVtbl->Restore(p) -#define IDirectDrawSurface_SetClipper(p,a) (p)->lpVtbl->SetClipper(p,a) -#define IDirectDrawSurface_SetColorKey(p,a,b) (p)->lpVtbl->SetColorKey(p,a,b) -#define IDirectDrawSurface_SetOverlayPosition(p,a,b) (p)->lpVtbl->SetOverlayPosition(p,a,b) -#define IDirectDrawSurface_SetPalette(p,a) (p)->lpVtbl->SetPalette(p,a) -#define IDirectDrawSurface_Unlock(p,a) (p)->lpVtbl->Unlock(p,a) -#define IDirectDrawSurface_UpdateOverlay(p,a,b,c,d,e) (p)->lpVtbl->UpdateOverlay(p,a,b,c,d,e) -#define IDirectDrawSurface_UpdateOverlayDisplay(p,a) (p)->lpVtbl->UpdateOverlayDisplay(p,a) -#define IDirectDrawSurface_UpdateOverlayZOrder(p,a,b) (p)->lpVtbl->UpdateOverlayZOrder(p,a,b) -#else -/*** IUnknown methods ***/ -#define IDirectDrawSurface_QueryInterface(p,a,b) (p)->QueryInterface(a,b) -#define IDirectDrawSurface_AddRef(p) (p)->AddRef() -#define IDirectDrawSurface_Release(p) (p)->Release() -/*** IDirectDrawSurface methods ***/ -#define IDirectDrawSurface_AddAttachedSurface(p,a) (p)->AddAttachedSurface(a) -#define IDirectDrawSurface_AddOverlayDirtyRect(p,a) (p)->AddOverlayDirtyRect(a) -#define IDirectDrawSurface_Blt(p,a,b,c,d,e) (p)->Blt(a,b,c,d,e) -#define IDirectDrawSurface_BltBatch(p,a,b,c) (p)->BltBatch(a,b,c) -#define IDirectDrawSurface_BltFast(p,a,b,c,d,e) (p)->BltFast(a,b,c,d,e) -#define IDirectDrawSurface_DeleteAttachedSurface(p,a,b) (p)->DeleteAttachedSurface(a,b) -#define IDirectDrawSurface_EnumAttachedSurfaces(p,a,b) (p)->EnumAttachedSurfaces(a,b) -#define IDirectDrawSurface_EnumOverlayZOrders(p,a,b,c) (p)->EnumOverlayZOrders(a,b,c) -#define IDirectDrawSurface_Flip(p,a,b) (p)->Flip(a,b) -#define IDirectDrawSurface_GetAttachedSurface(p,a,b) (p)->GetAttachedSurface(a,b) -#define IDirectDrawSurface_GetBltStatus(p,a) (p)->GetBltStatus(a) -#define IDirectDrawSurface_GetCaps(p,a) (p)->GetCaps(a) -#define IDirectDrawSurface_GetClipper(p,a) (p)->GetClipper(a) -#define IDirectDrawSurface_GetColorKey(p,a,b) (p)->GetColorKey(a,b) -#define IDirectDrawSurface_GetDC(p,a) (p)->GetDC(a) -#define IDirectDrawSurface_GetFlipStatus(p,a) (p)->GetFlipStatus(a) -#define IDirectDrawSurface_GetOverlayPosition(p,a,b) (p)->GetOverlayPosition(a,b) -#define IDirectDrawSurface_GetPalette(p,a) (p)->GetPalette(a) -#define IDirectDrawSurface_GetPixelFormat(p,a) (p)->GetPixelFormat(a) -#define IDirectDrawSurface_GetSurfaceDesc(p,a) (p)->GetSurfaceDesc(a) -#define IDirectDrawSurface_Initialize(p,a,b) (p)->Initialize(a,b) -#define IDirectDrawSurface_IsLost(p) (p)->IsLost() -#define IDirectDrawSurface_Lock(p,a,b,c,d) (p)->Lock(a,b,c,d) -#define IDirectDrawSurface_ReleaseDC(p,a) (p)->ReleaseDC(a) -#define IDirectDrawSurface_Restore(p) (p)->Restore() -#define IDirectDrawSurface_SetClipper(p,a) (p)->SetClipper(a) -#define IDirectDrawSurface_SetColorKey(p,a,b) (p)->SetColorKey(a,b) -#define IDirectDrawSurface_SetOverlayPosition(p,a,b) (p)->SetOverlayPosition(a,b) -#define IDirectDrawSurface_SetPalette(p,a) (p)->SetPalette(a) -#define IDirectDrawSurface_Unlock(p,a) (p)->Unlock(a) -#define IDirectDrawSurface_UpdateOverlay(p,a,b,c,d,e) (p)->UpdateOverlay(a,b,c,d,e) -#define IDirectDrawSurface_UpdateOverlayDisplay(p,a) (p)->UpdateOverlayDisplay(a) -#define IDirectDrawSurface_UpdateOverlayZOrder(p,a,b) (p)->UpdateOverlayZOrder(a,b) -#endif - - -/***************************************************************************** - * IDirectDrawSurface2 interface - */ -/* Cannot inherit from IDirectDrawSurface because the LPDIRECTDRAWSURFACE parameters - * have been converted to LPDIRECTDRAWSURFACE2. - */ -#define INTERFACE IDirectDrawSurface2 -DECLARE_INTERFACE_(IDirectDrawSurface2,IUnknown) -{ - /*** IUnknown methods ***/ - STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; - STDMETHOD_(ULONG,AddRef)(THIS) PURE; - STDMETHOD_(ULONG,Release)(THIS) PURE; - /*** IDirectDrawSurface2 methods ***/ - STDMETHOD(AddAttachedSurface)(THIS_ LPDIRECTDRAWSURFACE2 lpDDSAttachedSurface) PURE; - STDMETHOD(AddOverlayDirtyRect)(THIS_ LPRECT lpRect) PURE; - STDMETHOD(Blt)(THIS_ LPRECT lpDestRect, LPDIRECTDRAWSURFACE2 lpDDSrcSurface, LPRECT lpSrcRect, DWORD dwFlags, LPDDBLTFX lpDDBltFx) PURE; - STDMETHOD(BltBatch)(THIS_ LPDDBLTBATCH lpDDBltBatch, DWORD dwCount, DWORD dwFlags) PURE; - STDMETHOD(BltFast)(THIS_ DWORD dwX, DWORD dwY, LPDIRECTDRAWSURFACE2 lpDDSrcSurface, LPRECT lpSrcRect, DWORD dwTrans) PURE; - STDMETHOD(DeleteAttachedSurface)(THIS_ DWORD dwFlags, LPDIRECTDRAWSURFACE2 lpDDSAttachedSurface) PURE; - STDMETHOD(EnumAttachedSurfaces)(THIS_ LPVOID lpContext, LPDDENUMSURFACESCALLBACK lpEnumSurfacesCallback) PURE; - STDMETHOD(EnumOverlayZOrders)(THIS_ DWORD dwFlags, LPVOID lpContext, LPDDENUMSURFACESCALLBACK lpfnCallback) PURE; - STDMETHOD(Flip)(THIS_ LPDIRECTDRAWSURFACE2 lpDDSurfaceTargetOverride, DWORD dwFlags) PURE; - STDMETHOD(GetAttachedSurface)(THIS_ LPDDSCAPS lpDDSCaps, LPDIRECTDRAWSURFACE2 *lplpDDAttachedSurface) PURE; - STDMETHOD(GetBltStatus)(THIS_ DWORD dwFlags) PURE; - STDMETHOD(GetCaps)(THIS_ LPDDSCAPS lpDDSCaps) PURE; - STDMETHOD(GetClipper)(THIS_ LPDIRECTDRAWCLIPPER *lplpDDClipper) PURE; - STDMETHOD(GetColorKey)(THIS_ DWORD dwFlags, LPDDCOLORKEY lpDDColorKey) PURE; - STDMETHOD(GetDC)(THIS_ HDC *lphDC) PURE; - STDMETHOD(GetFlipStatus)(THIS_ DWORD dwFlags) PURE; - STDMETHOD(GetOverlayPosition)(THIS_ LPLONG lplX, LPLONG lplY) PURE; - STDMETHOD(GetPalette)(THIS_ LPDIRECTDRAWPALETTE *lplpDDPalette) PURE; - STDMETHOD(GetPixelFormat)(THIS_ LPDDPIXELFORMAT lpDDPixelFormat) PURE; - STDMETHOD(GetSurfaceDesc)(THIS_ LPDDSURFACEDESC lpDDSurfaceDesc) PURE; - STDMETHOD(Initialize)(THIS_ LPDIRECTDRAW lpDD, LPDDSURFACEDESC lpDDSurfaceDesc) PURE; - STDMETHOD(IsLost)(THIS) PURE; - STDMETHOD(Lock)(THIS_ LPRECT lpDestRect, LPDDSURFACEDESC lpDDSurfaceDesc, DWORD dwFlags, HANDLE hEvent) PURE; - STDMETHOD(ReleaseDC)(THIS_ HDC hDC) PURE; - STDMETHOD(Restore)(THIS) PURE; - STDMETHOD(SetClipper)(THIS_ LPDIRECTDRAWCLIPPER lpDDClipper) PURE; - STDMETHOD(SetColorKey)(THIS_ DWORD dwFlags, LPDDCOLORKEY lpDDColorKey) PURE; - STDMETHOD(SetOverlayPosition)(THIS_ LONG lX, LONG lY) PURE; - STDMETHOD(SetPalette)(THIS_ LPDIRECTDRAWPALETTE lpDDPalette) PURE; - STDMETHOD(Unlock)(THIS_ LPVOID lpSurfaceData) PURE; - STDMETHOD(UpdateOverlay)(THIS_ LPRECT lpSrcRect, LPDIRECTDRAWSURFACE2 lpDDDestSurface, LPRECT lpDestRect, DWORD dwFlags, LPDDOVERLAYFX lpDDOverlayFx) PURE; - STDMETHOD(UpdateOverlayDisplay)(THIS_ DWORD dwFlags) PURE; - STDMETHOD(UpdateOverlayZOrder)(THIS_ DWORD dwFlags, LPDIRECTDRAWSURFACE2 lpDDSReference) PURE; - /* added in v2 */ - STDMETHOD(GetDDInterface)(THIS_ LPVOID *lplpDD) PURE; - STDMETHOD(PageLock)(THIS_ DWORD dwFlags) PURE; - STDMETHOD(PageUnlock)(THIS_ DWORD dwFlags) PURE; -}; -#undef INTERFACE - -#if !defined(__cplusplus) || defined(CINTERFACE) -/*** IUnknown methods ***/ -#define IDirectDrawSurface2_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) -#define IDirectDrawSurface2_AddRef(p) (p)->lpVtbl->AddRef(p) -#define IDirectDrawSurface2_Release(p) (p)->lpVtbl->Release(p) -/*** IDirectDrawSurface methods (almost) ***/ -#define IDirectDrawSurface2_AddAttachedSurface(p,a) (p)->lpVtbl->AddAttachedSurface(p,a) -#define IDirectDrawSurface2_AddOverlayDirtyRect(p,a) (p)->lpVtbl->AddOverlayDirtyRect(p,a) -#define IDirectDrawSurface2_Blt(p,a,b,c,d,e) (p)->lpVtbl->Blt(p,a,b,c,d,e) -#define IDirectDrawSurface2_BltBatch(p,a,b,c) (p)->lpVtbl->BltBatch(p,a,b,c) -#define IDirectDrawSurface2_BltFast(p,a,b,c,d,e) (p)->lpVtbl->BltFast(p,a,b,c,d,e) -#define IDirectDrawSurface2_DeleteAttachedSurface(p,a,b) (p)->lpVtbl->DeleteAttachedSurface(p,a,b) -#define IDirectDrawSurface2_EnumAttachedSurfaces(p,a,b) (p)->lpVtbl->EnumAttachedSurfaces(p,a,b) -#define IDirectDrawSurface2_EnumOverlayZOrders(p,a,b,c) (p)->lpVtbl->EnumOverlayZOrders(p,a,b,c) -#define IDirectDrawSurface2_Flip(p,a,b) (p)->lpVtbl->Flip(p,a,b) -#define IDirectDrawSurface2_GetAttachedSurface(p,a,b) (p)->lpVtbl->GetAttachedSurface(p,a,b) -#define IDirectDrawSurface2_GetBltStatus(p,a) (p)->lpVtbl->GetBltStatus(p,a) -#define IDirectDrawSurface2_GetCaps(p,a) (p)->lpVtbl->GetCaps(p,a) -#define IDirectDrawSurface2_GetClipper(p,a) (p)->lpVtbl->GetClipper(p,a) -#define IDirectDrawSurface2_GetColorKey(p,a,b) (p)->lpVtbl->GetColorKey(p,a,b) -#define IDirectDrawSurface2_GetDC(p,a) (p)->lpVtbl->GetDC(p,a) -#define IDirectDrawSurface2_GetFlipStatus(p,a) (p)->lpVtbl->GetFlipStatus(p,a) -#define IDirectDrawSurface2_GetOverlayPosition(p,a,b) (p)->lpVtbl->GetOverlayPosition(p,a,b) -#define IDirectDrawSurface2_GetPalette(p,a) (p)->lpVtbl->GetPalette(p,a) -#define IDirectDrawSurface2_GetPixelFormat(p,a) (p)->lpVtbl->GetPixelFormat(p,a) -#define IDirectDrawSurface2_GetSurfaceDesc(p,a) (p)->lpVtbl->GetSurfaceDesc(p,a) -#define IDirectDrawSurface2_Initialize(p,a,b) (p)->lpVtbl->Initialize(p,a,b) -#define IDirectDrawSurface2_IsLost(p) (p)->lpVtbl->IsLost(p) -#define IDirectDrawSurface2_Lock(p,a,b,c,d) (p)->lpVtbl->Lock(p,a,b,c,d) -#define IDirectDrawSurface2_ReleaseDC(p,a) (p)->lpVtbl->ReleaseDC(p,a) -#define IDirectDrawSurface2_Restore(p) (p)->lpVtbl->Restore(p) -#define IDirectDrawSurface2_SetClipper(p,a) (p)->lpVtbl->SetClipper(p,a) -#define IDirectDrawSurface2_SetColorKey(p,a,b) (p)->lpVtbl->SetColorKey(p,a,b) -#define IDirectDrawSurface2_SetOverlayPosition(p,a,b) (p)->lpVtbl->SetOverlayPosition(p,a,b) -#define IDirectDrawSurface2_SetPalette(p,a) (p)->lpVtbl->SetPalette(p,a) -#define IDirectDrawSurface2_Unlock(p,a) (p)->lpVtbl->Unlock(p,a) -#define IDirectDrawSurface2_UpdateOverlay(p,a,b,c,d,e) (p)->lpVtbl->UpdateOverlay(p,a,b,c,d,e) -#define IDirectDrawSurface2_UpdateOverlayDisplay(p,a) (p)->lpVtbl->UpdateOverlayDisplay(p,a) -#define IDirectDrawSurface2_UpdateOverlayZOrder(p,a,b) (p)->lpVtbl->UpdateOverlayZOrder(p,a,b) -/*** IDirectDrawSurface2 methods ***/ -#define IDirectDrawSurface2_GetDDInterface(p,a) (p)->lpVtbl->GetDDInterface(p,a) -#define IDirectDrawSurface2_PageLock(p,a) (p)->lpVtbl->PageLock(p,a) -#define IDirectDrawSurface2_PageUnlock(p,a) (p)->lpVtbl->PageUnlock(p,a) -#else -/*** IUnknown methods ***/ -#define IDirectDrawSurface2_QueryInterface(p,a,b) (p)->QueryInterface(a,b) -#define IDirectDrawSurface2_AddRef(p) (p)->AddRef() -#define IDirectDrawSurface2_Release(p) (p)->Release() -/*** IDirectDrawSurface methods (almost) ***/ -#define IDirectDrawSurface2_AddAttachedSurface(p,a) (p)->AddAttachedSurface(a) -#define IDirectDrawSurface2_AddOverlayDirtyRect(p,a) (p)->AddOverlayDirtyRect(a) -#define IDirectDrawSurface2_Blt(p,a,b,c,d,e) (p)->Blt(a,b,c,d,e) -#define IDirectDrawSurface2_BltBatch(p,a,b,c) (p)->BltBatch(a,b,c) -#define IDirectDrawSurface2_BltFast(p,a,b,c,d,e) (p)->BltFast(a,b,c,d,e) -#define IDirectDrawSurface2_DeleteAttachedSurface(p,a,b) (p)->DeleteAttachedSurface(a,b) -#define IDirectDrawSurface2_EnumAttachedSurfaces(p,a,b) (p)->EnumAttachedSurfaces(a,b) -#define IDirectDrawSurface2_EnumOverlayZOrders(p,a,b,c) (p)->EnumOverlayZOrders(a,b,c) -#define IDirectDrawSurface2_Flip(p,a,b) (p)->Flip(a,b) -#define IDirectDrawSurface2_GetAttachedSurface(p,a,b) (p)->GetAttachedSurface(a,b) -#define IDirectDrawSurface2_GetBltStatus(p,a) (p)->GetBltStatus(a) -#define IDirectDrawSurface2_GetCaps(p,a) (p)->GetCaps(a) -#define IDirectDrawSurface2_GetClipper(p,a) (p)->GetClipper(a) -#define IDirectDrawSurface2_GetColorKey(p,a,b) (p)->GetColorKey(a,b) -#define IDirectDrawSurface2_GetDC(p,a) (p)->GetDC(a) -#define IDirectDrawSurface2_GetFlipStatus(p,a) (p)->GetFlipStatus(a) -#define IDirectDrawSurface2_GetOverlayPosition(p,a,b) (p)->GetOverlayPosition(a,b) -#define IDirectDrawSurface2_GetPalette(p,a) (p)->GetPalette(a) -#define IDirectDrawSurface2_GetPixelFormat(p,a) (p)->GetPixelFormat(a) -#define IDirectDrawSurface2_GetSurfaceDesc(p,a) (p)->GetSurfaceDesc(a) -#define IDirectDrawSurface2_Initialize(p,a,b) (p)->Initialize(a,b) -#define IDirectDrawSurface2_IsLost(p) (p)->IsLost() -#define IDirectDrawSurface2_Lock(p,a,b,c,d) (p)->Lock(a,b,c,d) -#define IDirectDrawSurface2_ReleaseDC(p,a) (p)->ReleaseDC(a) -#define IDirectDrawSurface2_Restore(p) (p)->Restore() -#define IDirectDrawSurface2_SetClipper(p,a) (p)->SetClipper(a) -#define IDirectDrawSurface2_SetColorKey(p,a,b) (p)->SetColorKey(a,b) -#define IDirectDrawSurface2_SetOverlayPosition(p,a,b) (p)->SetOverlayPosition(a,b) -#define IDirectDrawSurface2_SetPalette(p,a) (p)->SetPalette(a) -#define IDirectDrawSurface2_Unlock(p,a) (p)->Unlock(a) -#define IDirectDrawSurface2_UpdateOverlay(p,a,b,c,d,e) (p)->UpdateOverlay(a,b,c,d,e) -#define IDirectDrawSurface2_UpdateOverlayDisplay(p,a) (p)->UpdateOverlayDisplay(a) -#define IDirectDrawSurface2_UpdateOverlayZOrder(p,a,b) (p)->UpdateOverlayZOrder(a,b) -/*** IDirectDrawSurface2 methods ***/ -#define IDirectDrawSurface2_GetDDInterface(p,a) (p)->GetDDInterface(a) -#define IDirectDrawSurface2_PageLock(p,a) (p)->PageLock(a) -#define IDirectDrawSurface2_PageUnlock(p,a) (p)->PageUnlock(a) -#endif - - -/***************************************************************************** - * IDirectDrawSurface3 interface - */ -/* Cannot inherit from IDirectDrawSurface2 because the LPDIRECTDRAWSURFACE2 parameters - * have been converted to LPDIRECTDRAWSURFACE3. - */ -#define INTERFACE IDirectDrawSurface3 -DECLARE_INTERFACE_(IDirectDrawSurface3,IUnknown) -{ - /*** IUnknown methods ***/ - STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; - STDMETHOD_(ULONG,AddRef)(THIS) PURE; - STDMETHOD_(ULONG,Release)(THIS) PURE; - /*** IDirectDrawSurface3 methods ***/ - STDMETHOD(AddAttachedSurface)(THIS_ LPDIRECTDRAWSURFACE3 lpDDSAttachedSurface) PURE; - STDMETHOD(AddOverlayDirtyRect)(THIS_ LPRECT lpRect) PURE; - STDMETHOD(Blt)(THIS_ LPRECT lpDestRect, LPDIRECTDRAWSURFACE3 lpDDSrcSurface, LPRECT lpSrcRect, DWORD dwFlags, LPDDBLTFX lpDDBltFx) PURE; - STDMETHOD(BltBatch)(THIS_ LPDDBLTBATCH lpDDBltBatch, DWORD dwCount, DWORD dwFlags) PURE; - STDMETHOD(BltFast)(THIS_ DWORD dwX, DWORD dwY, LPDIRECTDRAWSURFACE3 lpDDSrcSurface, LPRECT lpSrcRect, DWORD dwTrans) PURE; - STDMETHOD(DeleteAttachedSurface)(THIS_ DWORD dwFlags, LPDIRECTDRAWSURFACE3 lpDDSAttachedSurface) PURE; - STDMETHOD(EnumAttachedSurfaces)(THIS_ LPVOID lpContext, LPDDENUMSURFACESCALLBACK lpEnumSurfacesCallback) PURE; - STDMETHOD(EnumOverlayZOrders)(THIS_ DWORD dwFlags, LPVOID lpContext, LPDDENUMSURFACESCALLBACK lpfnCallback) PURE; - STDMETHOD(Flip)(THIS_ LPDIRECTDRAWSURFACE3 lpDDSurfaceTargetOverride, DWORD dwFlags) PURE; - STDMETHOD(GetAttachedSurface)(THIS_ LPDDSCAPS lpDDSCaps, LPDIRECTDRAWSURFACE3 *lplpDDAttachedSurface) PURE; - STDMETHOD(GetBltStatus)(THIS_ DWORD dwFlags) PURE; - STDMETHOD(GetCaps)(THIS_ LPDDSCAPS lpDDSCaps) PURE; - STDMETHOD(GetClipper)(THIS_ LPDIRECTDRAWCLIPPER *lplpDDClipper) PURE; - STDMETHOD(GetColorKey)(THIS_ DWORD dwFlags, LPDDCOLORKEY lpDDColorKey) PURE; - STDMETHOD(GetDC)(THIS_ HDC *lphDC) PURE; - STDMETHOD(GetFlipStatus)(THIS_ DWORD dwFlags) PURE; - STDMETHOD(GetOverlayPosition)(THIS_ LPLONG lplX, LPLONG lplY) PURE; - STDMETHOD(GetPalette)(THIS_ LPDIRECTDRAWPALETTE *lplpDDPalette) PURE; - STDMETHOD(GetPixelFormat)(THIS_ LPDDPIXELFORMAT lpDDPixelFormat) PURE; - STDMETHOD(GetSurfaceDesc)(THIS_ LPDDSURFACEDESC lpDDSurfaceDesc) PURE; - STDMETHOD(Initialize)(THIS_ LPDIRECTDRAW lpDD, LPDDSURFACEDESC lpDDSurfaceDesc) PURE; - STDMETHOD(IsLost)(THIS) PURE; - STDMETHOD(Lock)(THIS_ LPRECT lpDestRect, LPDDSURFACEDESC lpDDSurfaceDesc, DWORD dwFlags, HANDLE hEvent) PURE; - STDMETHOD(ReleaseDC)(THIS_ HDC hDC) PURE; - STDMETHOD(Restore)(THIS) PURE; - STDMETHOD(SetClipper)(THIS_ LPDIRECTDRAWCLIPPER lpDDClipper) PURE; - STDMETHOD(SetColorKey)(THIS_ DWORD dwFlags, LPDDCOLORKEY lpDDColorKey) PURE; - STDMETHOD(SetOverlayPosition)(THIS_ LONG lX, LONG lY) PURE; - STDMETHOD(SetPalette)(THIS_ LPDIRECTDRAWPALETTE lpDDPalette) PURE; - STDMETHOD(Unlock)(THIS_ LPVOID lpSurfaceData) PURE; - STDMETHOD(UpdateOverlay)(THIS_ LPRECT lpSrcRect, LPDIRECTDRAWSURFACE3 lpDDDestSurface, LPRECT lpDestRect, DWORD dwFlags, LPDDOVERLAYFX lpDDOverlayFx) PURE; - STDMETHOD(UpdateOverlayDisplay)(THIS_ DWORD dwFlags) PURE; - STDMETHOD(UpdateOverlayZOrder)(THIS_ DWORD dwFlags, LPDIRECTDRAWSURFACE3 lpDDSReference) PURE; - /* added in v2 */ - STDMETHOD(GetDDInterface)(THIS_ LPVOID *lplpDD) PURE; - STDMETHOD(PageLock)(THIS_ DWORD dwFlags) PURE; - STDMETHOD(PageUnlock)(THIS_ DWORD dwFlags) PURE; - /* added in v3 */ - STDMETHOD(SetSurfaceDesc)(THIS_ LPDDSURFACEDESC lpDDSD, DWORD dwFlags) PURE; -}; -#undef INTERFACE - -#if !defined(__cplusplus) || defined(CINTERFACE) -/*** IUnknown methods ***/ -#define IDirectDrawSurface3_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) -#define IDirectDrawSurface3_AddRef(p) (p)->lpVtbl->AddRef(p) -#define IDirectDrawSurface3_Release(p) (p)->lpVtbl->Release(p) -/*** IDirectDrawSurface methods (almost) ***/ -#define IDirectDrawSurface3_AddAttachedSurface(p,a) (p)->lpVtbl->AddAttachedSurface(p,a) -#define IDirectDrawSurface3_AddOverlayDirtyRect(p,a) (p)->lpVtbl->AddOverlayDirtyRect(p,a) -#define IDirectDrawSurface3_Blt(p,a,b,c,d,e) (p)->lpVtbl->Blt(p,a,b,c,d,e) -#define IDirectDrawSurface3_BltBatch(p,a,b,c) (p)->lpVtbl->BltBatch(p,a,b,c) -#define IDirectDrawSurface3_BltFast(p,a,b,c,d,e) (p)->lpVtbl->BltFast(p,a,b,c,d,e) -#define IDirectDrawSurface3_DeleteAttachedSurface(p,a,b) (p)->lpVtbl->DeleteAttachedSurface(p,a,b) -#define IDirectDrawSurface3_EnumAttachedSurfaces(p,a,b) (p)->lpVtbl->EnumAttachedSurfaces(p,a,b) -#define IDirectDrawSurface3_EnumOverlayZOrders(p,a,b,c) (p)->lpVtbl->EnumOverlayZOrders(p,a,b,c) -#define IDirectDrawSurface3_Flip(p,a,b) (p)->lpVtbl->Flip(p,a,b) -#define IDirectDrawSurface3_GetAttachedSurface(p,a,b) (p)->lpVtbl->GetAttachedSurface(p,a,b) -#define IDirectDrawSurface3_GetBltStatus(p,a) (p)->lpVtbl->GetBltStatus(p,a) -#define IDirectDrawSurface3_GetCaps(p,a) (p)->lpVtbl->GetCaps(p,a) -#define IDirectDrawSurface3_GetClipper(p,a) (p)->lpVtbl->GetClipper(p,a) -#define IDirectDrawSurface3_GetColorKey(p,a,b) (p)->lpVtbl->GetColorKey(p,a,b) -#define IDirectDrawSurface3_GetDC(p,a) (p)->lpVtbl->GetDC(p,a) -#define IDirectDrawSurface3_GetFlipStatus(p,a) (p)->lpVtbl->GetFlipStatus(p,a) -#define IDirectDrawSurface3_GetOverlayPosition(p,a,b) (p)->lpVtbl->GetOverlayPosition(p,a,b) -#define IDirectDrawSurface3_GetPalette(p,a) (p)->lpVtbl->GetPalette(p,a) -#define IDirectDrawSurface3_GetPixelFormat(p,a) (p)->lpVtbl->GetPixelFormat(p,a) -#define IDirectDrawSurface3_GetSurfaceDesc(p,a) (p)->lpVtbl->GetSurfaceDesc(p,a) -#define IDirectDrawSurface3_Initialize(p,a,b) (p)->lpVtbl->Initialize(p,a,b) -#define IDirectDrawSurface3_IsLost(p) (p)->lpVtbl->IsLost(p) -#define IDirectDrawSurface3_Lock(p,a,b,c,d) (p)->lpVtbl->Lock(p,a,b,c,d) -#define IDirectDrawSurface3_ReleaseDC(p,a) (p)->lpVtbl->ReleaseDC(p,a) -#define IDirectDrawSurface3_Restore(p) (p)->lpVtbl->Restore(p) -#define IDirectDrawSurface3_SetClipper(p,a) (p)->lpVtbl->SetClipper(p,a) -#define IDirectDrawSurface3_SetColorKey(p,a,b) (p)->lpVtbl->SetColorKey(p,a,b) -#define IDirectDrawSurface3_SetOverlayPosition(p,a,b) (p)->lpVtbl->SetOverlayPosition(p,a,b) -#define IDirectDrawSurface3_SetPalette(p,a) (p)->lpVtbl->SetPalette(p,a) -#define IDirectDrawSurface3_Unlock(p,a) (p)->lpVtbl->Unlock(p,a) -#define IDirectDrawSurface3_UpdateOverlay(p,a,b,c,d,e) (p)->lpVtbl->UpdateOverlay(p,a,b,c,d,e) -#define IDirectDrawSurface3_UpdateOverlayDisplay(p,a) (p)->lpVtbl->UpdateOverlayDisplay(p,a) -#define IDirectDrawSurface3_UpdateOverlayZOrder(p,a,b) (p)->lpVtbl->UpdateOverlayZOrder(p,a,b) -/*** IDirectDrawSurface2 methods ***/ -#define IDirectDrawSurface3_GetDDInterface(p,a) (p)->lpVtbl->GetDDInterface(p,a) -#define IDirectDrawSurface3_PageLock(p,a) (p)->lpVtbl->PageLock(p,a) -#define IDirectDrawSurface3_PageUnlock(p,a) (p)->lpVtbl->PageUnlock(p,a) -/*** IDirectDrawSurface3 methods ***/ -#define IDirectDrawSurface3_SetSurfaceDesc(p,a,b) (p)->lpVtbl->SetSurfaceDesc(p,a,b) -#else -/*** IUnknown methods ***/ -#define IDirectDrawSurface3_QueryInterface(p,a,b) (p)->QueryInterface(a,b) -#define IDirectDrawSurface3_AddRef(p) (p)->AddRef() -#define IDirectDrawSurface3_Release(p) (p)->Release() -/*** IDirectDrawSurface methods (almost) ***/ -#define IDirectDrawSurface3_AddAttachedSurface(p,a) (p)->AddAttachedSurface(a) -#define IDirectDrawSurface3_AddOverlayDirtyRect(p,a) (p)->AddOverlayDirtyRect(a) -#define IDirectDrawSurface3_Blt(p,a,b,c,d,e) (p)->Blt(a,b,c,d,e) -#define IDirectDrawSurface3_BltBatch(p,a,b,c) (p)->BltBatch(a,b,c) -#define IDirectDrawSurface3_BltFast(p,a,b,c,d,e) (p)->BltFast(a,b,c,d,e) -#define IDirectDrawSurface3_DeleteAttachedSurface(p,a,b) (p)->DeleteAttachedSurface(a,b) -#define IDirectDrawSurface3_EnumAttachedSurfaces(p,a,b) (p)->EnumAttachedSurfaces(a,b) -#define IDirectDrawSurface3_EnumOverlayZOrders(p,a,b,c) (p)->EnumOverlayZOrders(a,b,c) -#define IDirectDrawSurface3_Flip(p,a,b) (p)->Flip(a,b) -#define IDirectDrawSurface3_GetAttachedSurface(p,a,b) (p)->GetAttachedSurface(a,b) -#define IDirectDrawSurface3_GetBltStatus(p,a) (p)->GetBltStatus(a) -#define IDirectDrawSurface3_GetCaps(p,a) (p)->GetCaps(a) -#define IDirectDrawSurface3_GetClipper(p,a) (p)->GetClipper(a) -#define IDirectDrawSurface3_GetColorKey(p,a,b) (p)->GetColorKey(a,b) -#define IDirectDrawSurface3_GetDC(p,a) (p)->GetDC(a) -#define IDirectDrawSurface3_GetFlipStatus(p,a) (p)->GetFlipStatus(a) -#define IDirectDrawSurface3_GetOverlayPosition(p,a,b) (p)->GetOverlayPosition(a,b) -#define IDirectDrawSurface3_GetPalette(p,a) (p)->GetPalette(a) -#define IDirectDrawSurface3_GetPixelFormat(p,a) (p)->GetPixelFormat(a) -#define IDirectDrawSurface3_GetSurfaceDesc(p,a) (p)->GetSurfaceDesc(a) -#define IDirectDrawSurface3_Initialize(p,a,b) (p)->Initialize(a,b) -#define IDirectDrawSurface3_IsLost(p) (p)->IsLost() -#define IDirectDrawSurface3_Lock(p,a,b,c,d) (p)->Lock(a,b,c,d) -#define IDirectDrawSurface3_ReleaseDC(p,a) (p)->ReleaseDC(a) -#define IDirectDrawSurface3_Restore(p) (p)->Restore() -#define IDirectDrawSurface3_SetClipper(p,a) (p)->SetClipper(a) -#define IDirectDrawSurface3_SetColorKey(p,a,b) (p)->SetColorKey(a,b) -#define IDirectDrawSurface3_SetOverlayPosition(p,a,b) (p)->SetOverlayPosition(a,b) -#define IDirectDrawSurface3_SetPalette(p,a) (p)->SetPalette(a) -#define IDirectDrawSurface3_Unlock(p,a) (p)->Unlock(a) -#define IDirectDrawSurface3_UpdateOverlay(p,a,b,c,d,e) (p)->UpdateOverlay(a,b,c,d,e) -#define IDirectDrawSurface3_UpdateOverlayDisplay(p,a) (p)->UpdateOverlayDisplay(a) -#define IDirectDrawSurface3_UpdateOverlayZOrder(p,a,b) (p)->UpdateOverlayZOrder(a,b) -/*** IDirectDrawSurface2 methods ***/ -#define IDirectDrawSurface3_GetDDInterface(p,a) (p)->GetDDInterface(a) -#define IDirectDrawSurface3_PageLock(p,a) (p)->PageLock(a) -#define IDirectDrawSurface3_PageUnlock(p,a) (p)->PageUnlock(a) -/*** IDirectDrawSurface3 methods ***/ -#define IDirectDrawSurface3_SetSurfaceDesc(p,a,b) (p)->SetSurfaceDesc(a,b) -#endif - - -/***************************************************************************** - * IDirectDrawSurface4 interface - */ -/* Cannot inherit from IDirectDrawSurface2 because DDSCAPS changed to DDSCAPS2. - */ -#define INTERFACE IDirectDrawSurface4 -DECLARE_INTERFACE_(IDirectDrawSurface4,IUnknown) -{ - /*** IUnknown methods ***/ - STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; - STDMETHOD_(ULONG,AddRef)(THIS) PURE; - STDMETHOD_(ULONG,Release)(THIS) PURE; - /*** IDirectDrawSurface4 methods ***/ - STDMETHOD(AddAttachedSurface)(THIS_ LPDIRECTDRAWSURFACE4 lpDDSAttachedSurface) PURE; - STDMETHOD(AddOverlayDirtyRect)(THIS_ LPRECT lpRect) PURE; - STDMETHOD(Blt)(THIS_ LPRECT lpDestRect, LPDIRECTDRAWSURFACE4 lpDDSrcSurface, LPRECT lpSrcRect, DWORD dwFlags, LPDDBLTFX lpDDBltFx) PURE; - STDMETHOD(BltBatch)(THIS_ LPDDBLTBATCH lpDDBltBatch, DWORD dwCount, DWORD dwFlags) PURE; - STDMETHOD(BltFast)(THIS_ DWORD dwX, DWORD dwY, LPDIRECTDRAWSURFACE4 lpDDSrcSurface, LPRECT lpSrcRect, DWORD dwTrans) PURE; - STDMETHOD(DeleteAttachedSurface)(THIS_ DWORD dwFlags, LPDIRECTDRAWSURFACE4 lpDDSAttachedSurface) PURE; - STDMETHOD(EnumAttachedSurfaces)(THIS_ LPVOID lpContext, LPDDENUMSURFACESCALLBACK2 lpEnumSurfacesCallback) PURE; - STDMETHOD(EnumOverlayZOrders)(THIS_ DWORD dwFlags, LPVOID lpContext, LPDDENUMSURFACESCALLBACK2 lpfnCallback) PURE; - STDMETHOD(Flip)(THIS_ LPDIRECTDRAWSURFACE4 lpDDSurfaceTargetOverride, DWORD dwFlags) PURE; - STDMETHOD(GetAttachedSurface)(THIS_ LPDDSCAPS2 lpDDSCaps, LPDIRECTDRAWSURFACE4 *lplpDDAttachedSurface) PURE; - STDMETHOD(GetBltStatus)(THIS_ DWORD dwFlags) PURE; - STDMETHOD(GetCaps)(THIS_ LPDDSCAPS2 lpDDSCaps) PURE; - STDMETHOD(GetClipper)(THIS_ LPDIRECTDRAWCLIPPER *lplpDDClipper) PURE; - STDMETHOD(GetColorKey)(THIS_ DWORD dwFlags, LPDDCOLORKEY lpDDColorKey) PURE; - STDMETHOD(GetDC)(THIS_ HDC *lphDC) PURE; - STDMETHOD(GetFlipStatus)(THIS_ DWORD dwFlags) PURE; - STDMETHOD(GetOverlayPosition)(THIS_ LPLONG lplX, LPLONG lplY) PURE; - STDMETHOD(GetPalette)(THIS_ LPDIRECTDRAWPALETTE *lplpDDPalette) PURE; - STDMETHOD(GetPixelFormat)(THIS_ LPDDPIXELFORMAT lpDDPixelFormat) PURE; - STDMETHOD(GetSurfaceDesc)(THIS_ LPDDSURFACEDESC2 lpDDSurfaceDesc) PURE; - STDMETHOD(Initialize)(THIS_ LPDIRECTDRAW lpDD, LPDDSURFACEDESC2 lpDDSurfaceDesc) PURE; - STDMETHOD(IsLost)(THIS) PURE; - STDMETHOD(Lock)(THIS_ LPRECT lpDestRect, LPDDSURFACEDESC2 lpDDSurfaceDesc, DWORD dwFlags, HANDLE hEvent) PURE; - STDMETHOD(ReleaseDC)(THIS_ HDC hDC) PURE; - STDMETHOD(Restore)(THIS) PURE; - STDMETHOD(SetClipper)(THIS_ LPDIRECTDRAWCLIPPER lpDDClipper) PURE; - STDMETHOD(SetColorKey)(THIS_ DWORD dwFlags, LPDDCOLORKEY lpDDColorKey) PURE; - STDMETHOD(SetOverlayPosition)(THIS_ LONG lX, LONG lY) PURE; - STDMETHOD(SetPalette)(THIS_ LPDIRECTDRAWPALETTE lpDDPalette) PURE; - STDMETHOD(Unlock)(THIS_ LPRECT lpSurfaceData) PURE; - STDMETHOD(UpdateOverlay)(THIS_ LPRECT lpSrcRect, LPDIRECTDRAWSURFACE4 lpDDDestSurface, LPRECT lpDestRect, DWORD dwFlags, LPDDOVERLAYFX lpDDOverlayFx) PURE; - STDMETHOD(UpdateOverlayDisplay)(THIS_ DWORD dwFlags) PURE; - STDMETHOD(UpdateOverlayZOrder)(THIS_ DWORD dwFlags, LPDIRECTDRAWSURFACE4 lpDDSReference) PURE; - /* added in v2 */ - STDMETHOD(GetDDInterface)(THIS_ LPVOID *lplpDD) PURE; - STDMETHOD(PageLock)(THIS_ DWORD dwFlags) PURE; - STDMETHOD(PageUnlock)(THIS_ DWORD dwFlags) PURE; - /* added in v3 */ - STDMETHOD(SetSurfaceDesc)(THIS_ LPDDSURFACEDESC2 lpDDSD, DWORD dwFlags) PURE; - /* added in v4 */ - STDMETHOD(SetPrivateData)(THIS_ REFGUID tag, LPVOID pData, DWORD cbSize, DWORD dwFlags) PURE; - STDMETHOD(GetPrivateData)(THIS_ REFGUID tag, LPVOID pBuffer, LPDWORD pcbBufferSize) PURE; - STDMETHOD(FreePrivateData)(THIS_ REFGUID tag) PURE; - STDMETHOD(GetUniquenessValue)(THIS_ LPDWORD pValue) PURE; - STDMETHOD(ChangeUniquenessValue)(THIS) PURE; -}; -#undef INTERFACE - -#if !defined(__cplusplus) || defined(CINTERFACE) -/*** IUnknown methods ***/ -#define IDirectDrawSurface4_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) -#define IDirectDrawSurface4_AddRef(p) (p)->lpVtbl->AddRef(p) -#define IDirectDrawSurface4_Release(p) (p)->lpVtbl->Release(p) -/*** IDirectDrawSurface (almost) methods ***/ -#define IDirectDrawSurface4_AddAttachedSurface(p,a) (p)->lpVtbl->AddAttachedSurface(p,a) -#define IDirectDrawSurface4_AddOverlayDirtyRect(p,a) (p)->lpVtbl->AddOverlayDirtyRect(p,a) -#define IDirectDrawSurface4_Blt(p,a,b,c,d,e) (p)->lpVtbl->Blt(p,a,b,c,d,e) -#define IDirectDrawSurface4_BltBatch(p,a,b,c) (p)->lpVtbl->BltBatch(p,a,b,c) -#define IDirectDrawSurface4_BltFast(p,a,b,c,d,e) (p)->lpVtbl->BltFast(p,a,b,c,d,e) -#define IDirectDrawSurface4_DeleteAttachedSurface(p,a,b) (p)->lpVtbl->DeleteAttachedSurface(p,a,b) -#define IDirectDrawSurface4_EnumAttachedSurfaces(p,a,b) (p)->lpVtbl->EnumAttachedSurfaces(p,a,b) -#define IDirectDrawSurface4_EnumOverlayZOrders(p,a,b,c) (p)->lpVtbl->EnumOverlayZOrders(p,a,b,c) -#define IDirectDrawSurface4_Flip(p,a,b) (p)->lpVtbl->Flip(p,a,b) -#define IDirectDrawSurface4_GetAttachedSurface(p,a,b) (p)->lpVtbl->GetAttachedSurface(p,a,b) -#define IDirectDrawSurface4_GetBltStatus(p,a) (p)->lpVtbl->GetBltStatus(p,a) -#define IDirectDrawSurface4_GetCaps(p,a) (p)->lpVtbl->GetCaps(p,a) -#define IDirectDrawSurface4_GetClipper(p,a) (p)->lpVtbl->GetClipper(p,a) -#define IDirectDrawSurface4_GetColorKey(p,a,b) (p)->lpVtbl->GetColorKey(p,a,b) -#define IDirectDrawSurface4_GetDC(p,a) (p)->lpVtbl->GetDC(p,a) -#define IDirectDrawSurface4_GetFlipStatus(p,a) (p)->lpVtbl->GetFlipStatus(p,a) -#define IDirectDrawSurface4_GetOverlayPosition(p,a,b) (p)->lpVtbl->GetOverlayPosition(p,a,b) -#define IDirectDrawSurface4_GetPalette(p,a) (p)->lpVtbl->GetPalette(p,a) -#define IDirectDrawSurface4_GetPixelFormat(p,a) (p)->lpVtbl->GetPixelFormat(p,a) -#define IDirectDrawSurface4_GetSurfaceDesc(p,a) (p)->lpVtbl->GetSurfaceDesc(p,a) -#define IDirectDrawSurface4_Initialize(p,a,b) (p)->lpVtbl->Initialize(p,a,b) -#define IDirectDrawSurface4_IsLost(p) (p)->lpVtbl->IsLost(p) -#define IDirectDrawSurface4_Lock(p,a,b,c,d) (p)->lpVtbl->Lock(p,a,b,c,d) -#define IDirectDrawSurface4_ReleaseDC(p,a) (p)->lpVtbl->ReleaseDC(p,a) -#define IDirectDrawSurface4_Restore(p) (p)->lpVtbl->Restore(p) -#define IDirectDrawSurface4_SetClipper(p,a) (p)->lpVtbl->SetClipper(p,a) -#define IDirectDrawSurface4_SetColorKey(p,a,b) (p)->lpVtbl->SetColorKey(p,a,b) -#define IDirectDrawSurface4_SetOverlayPosition(p,a,b) (p)->lpVtbl->SetOverlayPosition(p,a,b) -#define IDirectDrawSurface4_SetPalette(p,a) (p)->lpVtbl->SetPalette(p,a) -#define IDirectDrawSurface4_Unlock(p,a) (p)->lpVtbl->Unlock(p,a) -#define IDirectDrawSurface4_UpdateOverlay(p,a,b,c,d,e) (p)->lpVtbl->UpdateOverlay(p,a,b,c,d,e) -#define IDirectDrawSurface4_UpdateOverlayDisplay(p,a) (p)->lpVtbl->UpdateOverlayDisplay(p,a) -#define IDirectDrawSurface4_UpdateOverlayZOrder(p,a,b) (p)->lpVtbl->UpdateOverlayZOrder(p,a,b) -/*** IDirectDrawSurface2 methods ***/ -#define IDirectDrawSurface4_GetDDInterface(p,a) (p)->lpVtbl->GetDDInterface(p,a) -#define IDirectDrawSurface4_PageLock(p,a) (p)->lpVtbl->PageLock(p,a) -#define IDirectDrawSurface4_PageUnlock(p,a) (p)->lpVtbl->PageUnlock(p,a) -/*** IDirectDrawSurface3 methods ***/ -#define IDirectDrawSurface4_SetSurfaceDesc(p,a,b) (p)->lpVtbl->SetSurfaceDesc(p,a,b) -/*** IDirectDrawSurface4 methods ***/ -#define IDirectDrawSurface4_SetPrivateData(p,a,b,c,d) (p)->lpVtbl->SetPrivateData(p,a,b,c,d) -#define IDirectDrawSurface4_GetPrivateData(p,a,b,c) (p)->lpVtbl->GetPrivateData(p,a,b,c) -#define IDirectDrawSurface4_FreePrivateData(p,a) (p)->lpVtbl->FreePrivateData(p,a) -#define IDirectDrawSurface4_GetUniquenessValue(p,a) (p)->lpVtbl->GetUniquenessValue(p,a) -#define IDirectDrawSurface4_ChangeUniquenessValue(p) (p)->lpVtbl->ChangeUniquenessValue(p) -#else -/*** IUnknown methods ***/ -#define IDirectDrawSurface4_QueryInterface(p,a,b) (p)->QueryInterface(a,b) -#define IDirectDrawSurface4_AddRef(p) (p)->AddRef() -#define IDirectDrawSurface4_Release(p) (p)->Release() -/*** IDirectDrawSurface (almost) methods ***/ -#define IDirectDrawSurface4_AddAttachedSurface(p,a) (p)->AddAttachedSurface(a) -#define IDirectDrawSurface4_AddOverlayDirtyRect(p,a) (p)->AddOverlayDirtyRect(a) -#define IDirectDrawSurface4_Blt(p,a,b,c,d,e) (p)->Blt(a,b,c,d,e) -#define IDirectDrawSurface4_BltBatch(p,a,b,c) (p)->BltBatch(a,b,c) -#define IDirectDrawSurface4_BltFast(p,a,b,c,d,e) (p)->BltFast(a,b,c,d,e) -#define IDirectDrawSurface4_DeleteAttachedSurface(p,a,b) (p)->DeleteAttachedSurface(a,b) -#define IDirectDrawSurface4_EnumAttachedSurfaces(p,a,b) (p)->EnumAttachedSurfaces(a,b) -#define IDirectDrawSurface4_EnumOverlayZOrders(p,a,b,c) (p)->EnumOverlayZOrders(a,b,c) -#define IDirectDrawSurface4_Flip(p,a,b) (p)->Flip(a,b) -#define IDirectDrawSurface4_GetAttachedSurface(p,a,b) (p)->GetAttachedSurface(a,b) -#define IDirectDrawSurface4_GetBltStatus(p,a) (p)->GetBltStatus(a) -#define IDirectDrawSurface4_GetCaps(p,a) (p)->GetCaps(a) -#define IDirectDrawSurface4_GetClipper(p,a) (p)->GetClipper(a) -#define IDirectDrawSurface4_GetColorKey(p,a,b) (p)->GetColorKey(a,b) -#define IDirectDrawSurface4_GetDC(p,a) (p)->GetDC(a) -#define IDirectDrawSurface4_GetFlipStatus(p,a) (p)->GetFlipStatus(a) -#define IDirectDrawSurface4_GetOverlayPosition(p,a,b) (p)->GetOverlayPosition(a,b) -#define IDirectDrawSurface4_GetPalette(p,a) (p)->GetPalette(a) -#define IDirectDrawSurface4_GetPixelFormat(p,a) (p)->GetPixelFormat(a) -#define IDirectDrawSurface4_GetSurfaceDesc(p,a) (p)->GetSurfaceDesc(a) -#define IDirectDrawSurface4_Initialize(p,a,b) (p)->Initialize(a,b) -#define IDirectDrawSurface4_IsLost(p) (p)->IsLost() -#define IDirectDrawSurface4_Lock(p,a,b,c,d) (p)->Lock(a,b,c,d) -#define IDirectDrawSurface4_ReleaseDC(p,a) (p)->ReleaseDC(a) -#define IDirectDrawSurface4_Restore(p) (p)->Restore() -#define IDirectDrawSurface4_SetClipper(p,a) (p)->SetClipper(a) -#define IDirectDrawSurface4_SetColorKey(p,a,b) (p)->SetColorKey(a,b) -#define IDirectDrawSurface4_SetOverlayPosition(p,a,b) (p)->SetOverlayPosition(a,b) -#define IDirectDrawSurface4_SetPalette(p,a) (p)->SetPalette(a) -#define IDirectDrawSurface4_Unlock(p,a) (p)->Unlock(a) -#define IDirectDrawSurface4_UpdateOverlay(p,a,b,c,d,e) (p)->UpdateOverlay(a,b,c,d,e) -#define IDirectDrawSurface4_UpdateOverlayDisplay(p,a) (p)->UpdateOverlayDisplay(a) -#define IDirectDrawSurface4_UpdateOverlayZOrder(p,a,b) (p)->UpdateOverlayZOrder(a,b) -/*** IDirectDrawSurface2 methods ***/ -#define IDirectDrawSurface4_GetDDInterface(p,a) (p)->GetDDInterface(a) -#define IDirectDrawSurface4_PageLock(p,a) (p)->PageLock(a) -#define IDirectDrawSurface4_PageUnlock(p,a) (p)->PageUnlock(a) -/*** IDirectDrawSurface3 methods ***/ -#define IDirectDrawSurface4_SetSurfaceDesc(p,a,b) (p)->SetSurfaceDesc(a,b) -/*** IDirectDrawSurface4 methods ***/ -#define IDirectDrawSurface4_SetPrivateData(p,a,b,c,d) (p)->SetPrivateData(a,b,c,d) -#define IDirectDrawSurface4_GetPrivateData(p,a,b,c) (p)->GetPrivateData(a,b,c) -#define IDirectDrawSurface4_FreePrivateData(p,a) (p)->FreePrivateData(a) -#define IDirectDrawSurface4_GetUniquenessValue(p,a) (p)->GetUniquenessValue(a) -#define IDirectDrawSurface4_ChangeUniquenessValue(p) (p)->ChangeUniquenessValue() -#endif - - -/***************************************************************************** - * IDirectDrawSurface7 interface - */ -#define INTERFACE IDirectDrawSurface7 -DECLARE_INTERFACE_(IDirectDrawSurface7,IUnknown) -{ - /*** IUnknown methods ***/ - STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; - STDMETHOD_(ULONG,AddRef)(THIS) PURE; - STDMETHOD_(ULONG,Release)(THIS) PURE; - /*** IDirectDrawSurface7 methods ***/ - STDMETHOD(AddAttachedSurface)(THIS_ LPDIRECTDRAWSURFACE7 lpDDSAttachedSurface) PURE; - STDMETHOD(AddOverlayDirtyRect)(THIS_ LPRECT lpRect) PURE; - STDMETHOD(Blt)(THIS_ LPRECT lpDestRect, LPDIRECTDRAWSURFACE7 lpDDSrcSurface, LPRECT lpSrcRect, DWORD dwFlags, LPDDBLTFX lpDDBltFx) PURE; - STDMETHOD(BltBatch)(THIS_ LPDDBLTBATCH lpDDBltBatch, DWORD dwCount, DWORD dwFlags) PURE; - STDMETHOD(BltFast)(THIS_ DWORD dwX, DWORD dwY, LPDIRECTDRAWSURFACE7 lpDDSrcSurface, LPRECT lpSrcRect, DWORD dwTrans) PURE; - STDMETHOD(DeleteAttachedSurface)(THIS_ DWORD dwFlags, LPDIRECTDRAWSURFACE7 lpDDSAttachedSurface) PURE; - STDMETHOD(EnumAttachedSurfaces)(THIS_ LPVOID lpContext, LPDDENUMSURFACESCALLBACK7 lpEnumSurfacesCallback) PURE; - STDMETHOD(EnumOverlayZOrders)(THIS_ DWORD dwFlags, LPVOID lpContext, LPDDENUMSURFACESCALLBACK7 lpfnCallback) PURE; - STDMETHOD(Flip)(THIS_ LPDIRECTDRAWSURFACE7 lpDDSurfaceTargetOverride, DWORD dwFlags) PURE; - STDMETHOD(GetAttachedSurface)(THIS_ LPDDSCAPS2 lpDDSCaps, LPDIRECTDRAWSURFACE7 *lplpDDAttachedSurface) PURE; - STDMETHOD(GetBltStatus)(THIS_ DWORD dwFlags) PURE; - STDMETHOD(GetCaps)(THIS_ LPDDSCAPS2 lpDDSCaps) PURE; - STDMETHOD(GetClipper)(THIS_ LPDIRECTDRAWCLIPPER *lplpDDClipper) PURE; - STDMETHOD(GetColorKey)(THIS_ DWORD dwFlags, LPDDCOLORKEY lpDDColorKey) PURE; - STDMETHOD(GetDC)(THIS_ HDC *lphDC) PURE; - STDMETHOD(GetFlipStatus)(THIS_ DWORD dwFlags) PURE; - STDMETHOD(GetOverlayPosition)(THIS_ LPLONG lplX, LPLONG lplY) PURE; - STDMETHOD(GetPalette)(THIS_ LPDIRECTDRAWPALETTE *lplpDDPalette) PURE; - STDMETHOD(GetPixelFormat)(THIS_ LPDDPIXELFORMAT lpDDPixelFormat) PURE; - STDMETHOD(GetSurfaceDesc)(THIS_ LPDDSURFACEDESC2 lpDDSurfaceDesc) PURE; - STDMETHOD(Initialize)(THIS_ LPDIRECTDRAW lpDD, LPDDSURFACEDESC2 lpDDSurfaceDesc) PURE; - STDMETHOD(IsLost)(THIS) PURE; - STDMETHOD(Lock)(THIS_ LPRECT lpDestRect, LPDDSURFACEDESC2 lpDDSurfaceDesc, DWORD dwFlags, HANDLE hEvent) PURE; - STDMETHOD(ReleaseDC)(THIS_ HDC hDC) PURE; - STDMETHOD(Restore)(THIS) PURE; - STDMETHOD(SetClipper)(THIS_ LPDIRECTDRAWCLIPPER lpDDClipper) PURE; - STDMETHOD(SetColorKey)(THIS_ DWORD dwFlags, LPDDCOLORKEY lpDDColorKey) PURE; - STDMETHOD(SetOverlayPosition)(THIS_ LONG lX, LONG lY) PURE; - STDMETHOD(SetPalette)(THIS_ LPDIRECTDRAWPALETTE lpDDPalette) PURE; - STDMETHOD(Unlock)(THIS_ LPRECT lpSurfaceData) PURE; - STDMETHOD(UpdateOverlay)(THIS_ LPRECT lpSrcRect, LPDIRECTDRAWSURFACE7 lpDDDestSurface, LPRECT lpDestRect, DWORD dwFlags, LPDDOVERLAYFX lpDDOverlayFx) PURE; - STDMETHOD(UpdateOverlayDisplay)(THIS_ DWORD dwFlags) PURE; - STDMETHOD(UpdateOverlayZOrder)(THIS_ DWORD dwFlags, LPDIRECTDRAWSURFACE7 lpDDSReference) PURE; - /* added in v2 */ - STDMETHOD(GetDDInterface)(THIS_ LPVOID *lplpDD) PURE; - STDMETHOD(PageLock)(THIS_ DWORD dwFlags) PURE; - STDMETHOD(PageUnlock)(THIS_ DWORD dwFlags) PURE; - /* added in v3 */ - STDMETHOD(SetSurfaceDesc)(THIS_ LPDDSURFACEDESC2 lpDDSD, DWORD dwFlags) PURE; - /* added in v4 */ - STDMETHOD(SetPrivateData)(THIS_ REFGUID tag, LPVOID pData, DWORD cbSize, DWORD dwFlags) PURE; - STDMETHOD(GetPrivateData)(THIS_ REFGUID tag, LPVOID pBuffer, LPDWORD pcbBufferSize) PURE; - STDMETHOD(FreePrivateData)(THIS_ REFGUID tag) PURE; - STDMETHOD(GetUniquenessValue)(THIS_ LPDWORD pValue) PURE; - STDMETHOD(ChangeUniquenessValue)(THIS) PURE; - /* added in v7 */ - STDMETHOD(SetPriority)(THIS_ DWORD prio) PURE; - STDMETHOD(GetPriority)(THIS_ LPDWORD prio) PURE; - STDMETHOD(SetLOD)(THIS_ DWORD lod) PURE; - STDMETHOD(GetLOD)(THIS_ LPDWORD lod) PURE; -}; -#undef INTERFACE - -#if !defined(__cplusplus) || defined(CINTERFACE) -/*** IUnknown methods ***/ -#define IDirectDrawSurface7_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) -#define IDirectDrawSurface7_AddRef(p) (p)->lpVtbl->AddRef(p) -#define IDirectDrawSurface7_Release(p) (p)->lpVtbl->Release(p) -/*** IDirectDrawSurface (almost) methods ***/ -#define IDirectDrawSurface7_AddAttachedSurface(p,a) (p)->lpVtbl->AddAttachedSurface(p,a) -#define IDirectDrawSurface7_AddOverlayDirtyRect(p,a) (p)->lpVtbl->AddOverlayDirtyRect(p,a) -#define IDirectDrawSurface7_Blt(p,a,b,c,d,e) (p)->lpVtbl->Blt(p,a,b,c,d,e) -#define IDirectDrawSurface7_BltBatch(p,a,b,c) (p)->lpVtbl->BltBatch(p,a,b,c) -#define IDirectDrawSurface7_BltFast(p,a,b,c,d,e) (p)->lpVtbl->BltFast(p,a,b,c,d,e) -#define IDirectDrawSurface7_DeleteAttachedSurface(p,a,b) (p)->lpVtbl->DeleteAttachedSurface(p,a,b) -#define IDirectDrawSurface7_EnumAttachedSurfaces(p,a,b) (p)->lpVtbl->EnumAttachedSurfaces(p,a,b) -#define IDirectDrawSurface7_EnumOverlayZOrders(p,a,b,c) (p)->lpVtbl->EnumOverlayZOrders(p,a,b,c) -#define IDirectDrawSurface7_Flip(p,a,b) (p)->lpVtbl->Flip(p,a,b) -#define IDirectDrawSurface7_GetAttachedSurface(p,a,b) (p)->lpVtbl->GetAttachedSurface(p,a,b) -#define IDirectDrawSurface7_GetBltStatus(p,a) (p)->lpVtbl->GetBltStatus(p,a) -#define IDirectDrawSurface7_GetCaps(p,a) (p)->lpVtbl->GetCaps(p,a) -#define IDirectDrawSurface7_GetClipper(p,a) (p)->lpVtbl->GetClipper(p,a) -#define IDirectDrawSurface7_GetColorKey(p,a,b) (p)->lpVtbl->GetColorKey(p,a,b) -#define IDirectDrawSurface7_GetDC(p,a) (p)->lpVtbl->GetDC(p,a) -#define IDirectDrawSurface7_GetFlipStatus(p,a) (p)->lpVtbl->GetFlipStatus(p,a) -#define IDirectDrawSurface7_GetOverlayPosition(p,a,b) (p)->lpVtbl->GetOverlayPosition(p,a,b) -#define IDirectDrawSurface7_GetPalette(p,a) (p)->lpVtbl->GetPalette(p,a) -#define IDirectDrawSurface7_GetPixelFormat(p,a) (p)->lpVtbl->GetPixelFormat(p,a) -#define IDirectDrawSurface7_GetSurfaceDesc(p,a) (p)->lpVtbl->GetSurfaceDesc(p,a) -#define IDirectDrawSurface7_Initialize(p,a,b) (p)->lpVtbl->Initialize(p,a,b) -#define IDirectDrawSurface7_IsLost(p) (p)->lpVtbl->IsLost(p) -#define IDirectDrawSurface7_Lock(p,a,b,c,d) (p)->lpVtbl->Lock(p,a,b,c,d) -#define IDirectDrawSurface7_ReleaseDC(p,a) (p)->lpVtbl->ReleaseDC(p,a) -#define IDirectDrawSurface7_Restore(p) (p)->lpVtbl->Restore(p) -#define IDirectDrawSurface7_SetClipper(p,a) (p)->lpVtbl->SetClipper(p,a) -#define IDirectDrawSurface7_SetColorKey(p,a,b) (p)->lpVtbl->SetColorKey(p,a,b) -#define IDirectDrawSurface7_SetOverlayPosition(p,a,b) (p)->lpVtbl->SetOverlayPosition(p,a,b) -#define IDirectDrawSurface7_SetPalette(p,a) (p)->lpVtbl->SetPalette(p,a) -#define IDirectDrawSurface7_Unlock(p,a) (p)->lpVtbl->Unlock(p,a) -#define IDirectDrawSurface7_UpdateOverlay(p,a,b,c,d,e) (p)->lpVtbl->UpdateOverlay(p,a,b,c,d,e) -#define IDirectDrawSurface7_UpdateOverlayDisplay(p,a) (p)->lpVtbl->UpdateOverlayDisplay(p,a) -#define IDirectDrawSurface7_UpdateOverlayZOrder(p,a,b) (p)->lpVtbl->UpdateOverlayZOrder(p,a,b) -/*** IDirectDrawSurface2 methods ***/ -#define IDirectDrawSurface7_GetDDInterface(p,a) (p)->lpVtbl->GetDDInterface(p,a) -#define IDirectDrawSurface7_PageLock(p,a) (p)->lpVtbl->PageLock(p,a) -#define IDirectDrawSurface7_PageUnlock(p,a) (p)->lpVtbl->PageUnlock(p,a) -/*** IDirectDrawSurface3 methods ***/ -#define IDirectDrawSurface7_SetSurfaceDesc(p,a,b) (p)->lpVtbl->SetSurfaceDesc(p,a,b) -/*** IDirectDrawSurface4 methods ***/ -#define IDirectDrawSurface7_SetPrivateData(p,a,b,c,d) (p)->lpVtbl->SetPrivateData(p,a,b,c,d) -#define IDirectDrawSurface7_GetPrivateData(p,a,b,c) (p)->lpVtbl->GetPrivateData(p,a,b,c) -#define IDirectDrawSurface7_FreePrivateData(p,a) (p)->lpVtbl->FreePrivateData(p,a) -#define IDirectDrawSurface7_GetUniquenessValue(p,a) (p)->lpVtbl->GetUniquenessValue(p,a) -#define IDirectDrawSurface7_ChangeUniquenessValue(p) (p)->lpVtbl->ChangeUniquenessValue(p) -/*** IDirectDrawSurface7 methods ***/ -#define IDirectDrawSurface7_SetPriority(p,a) (p)->lpVtbl->SetPriority(p,a) -#define IDirectDrawSurface7_GetPriority(p,a) (p)->lpVtbl->GetPriority(p,a) -#define IDirectDrawSurface7_SetLOD(p,a) (p)->lpVtbl->SetLOD(p,a) -#define IDirectDrawSurface7_GetLOD(p,a) (p)->lpVtbl->GetLOD(p,a) -#else -/*** IUnknown methods ***/ -#define IDirectDrawSurface7_QueryInterface(p,a,b) (p)->QueryInterface(a,b) -#define IDirectDrawSurface7_AddRef(p) (p)->AddRef() -#define IDirectDrawSurface7_Release(p) (p)->Release() -/*** IDirectDrawSurface (almost) methods ***/ -#define IDirectDrawSurface7_AddAttachedSurface(p,a) (p)->AddAttachedSurface(a) -#define IDirectDrawSurface7_AddOverlayDirtyRect(p,a) (p)->AddOverlayDirtyRect(a) -#define IDirectDrawSurface7_Blt(p,a,b,c,d,e) (p)->Blt(a,b,c,d,e) -#define IDirectDrawSurface7_BltBatch(p,a,b,c) (p)->BltBatch(a,b,c) -#define IDirectDrawSurface7_BltFast(p,a,b,c,d,e) (p)->BltFast(a,b,c,d,e) -#define IDirectDrawSurface7_DeleteAttachedSurface(p,a,b) (p)->DeleteAttachedSurface(a,b) -#define IDirectDrawSurface7_EnumAttachedSurfaces(p,a,b) (p)->EnumAttachedSurfaces(a,b) -#define IDirectDrawSurface7_EnumOverlayZOrders(p,a,b,c) (p)->EnumOverlayZOrders(a,b,c) -#define IDirectDrawSurface7_Flip(p,a,b) (p)->Flip(a,b) -#define IDirectDrawSurface7_GetAttachedSurface(p,a,b) (p)->GetAttachedSurface(a,b) -#define IDirectDrawSurface7_GetBltStatus(p,a) (p)->GetBltStatus(a) -#define IDirectDrawSurface7_GetCaps(p,a) (p)->GetCaps(a) -#define IDirectDrawSurface7_GetClipper(p,a) (p)->GetClipper(a) -#define IDirectDrawSurface7_GetColorKey(p,a,b) (p)->GetColorKey(a,b) -#define IDirectDrawSurface7_GetDC(p,a) (p)->GetDC(a) -#define IDirectDrawSurface7_GetFlipStatus(p,a) (p)->GetFlipStatus(a) -#define IDirectDrawSurface7_GetOverlayPosition(p,a,b) (p)->GetOverlayPosition(a,b) -#define IDirectDrawSurface7_GetPalette(p,a) (p)->GetPalette(a) -#define IDirectDrawSurface7_GetPixelFormat(p,a) (p)->GetPixelFormat(a) -#define IDirectDrawSurface7_GetSurfaceDesc(p,a) (p)->GetSurfaceDesc(a) -#define IDirectDrawSurface7_Initialize(p,a,b) (p)->Initialize(a,b) -#define IDirectDrawSurface7_IsLost(p) (p)->IsLost() -#define IDirectDrawSurface7_Lock(p,a,b,c,d) (p)->Lock(a,b,c,d) -#define IDirectDrawSurface7_ReleaseDC(p,a) (p)->ReleaseDC(a) -#define IDirectDrawSurface7_Restore(p) (p)->Restore() -#define IDirectDrawSurface7_SetClipper(p,a) (p)->SetClipper(a) -#define IDirectDrawSurface7_SetColorKey(p,a,b) (p)->SetColorKey(a,b) -#define IDirectDrawSurface7_SetOverlayPosition(p,a,b) (p)->SetOverlayPosition(a,b) -#define IDirectDrawSurface7_SetPalette(p,a) (p)->SetPalette(a) -#define IDirectDrawSurface7_Unlock(p,a) (p)->Unlock(a) -#define IDirectDrawSurface7_UpdateOverlay(p,a,b,c,d,e) (p)->UpdateOverlay(a,b,c,d,e) -#define IDirectDrawSurface7_UpdateOverlayDisplay(p,a) (p)->UpdateOverlayDisplay(a) -#define IDirectDrawSurface7_UpdateOverlayZOrder(p,a,b) (p)->UpdateOverlayZOrder(a,b) -/*** IDirectDrawSurface2 methods ***/ -#define IDirectDrawSurface7_GetDDInterface(p,a) (p)->GetDDInterface(a) -#define IDirectDrawSurface7_PageLock(p,a) (p)->PageLock(a) -#define IDirectDrawSurface7_PageUnlock(p,a) (p)->PageUnlock(a) -/*** IDirectDrawSurface3 methods ***/ -#define IDirectDrawSurface7_SetSurfaceDesc(p,a,b) (p)->SetSurfaceDesc(a,b) -/*** IDirectDrawSurface4 methods ***/ -#define IDirectDrawSurface7_SetPrivateData(p,a,b,c,d) (p)->SetPrivateData(a,b,c,d) -#define IDirectDrawSurface7_GetPrivateData(p,a,b,c) (p)->GetPrivateData(a,b,c) -#define IDirectDrawSurface7_FreePrivateData(p,a) (p)->FreePrivateData(a) -#define IDirectDrawSurface7_GetUniquenessValue(p,a) (p)->GetUniquenessValue(a) -#define IDirectDrawSurface7_ChangeUniquenessValue(p) (p)->ChangeUniquenessValue() -/*** IDirectDrawSurface7 methods ***/ -#define IDirectDrawSurface7_SetPriority(p,a) (p)->SetPriority(a) -#define IDirectDrawSurface7_GetPriority(p,a) (p)->GetPriority(a) -#define IDirectDrawSurface7_SetLOD(p,a) (p)->SetLOD(a) -#define IDirectDrawSurface7_GetLOD(p,a) (p)->GetLOD(a) -#endif - -/***************************************************************************** - * IDirectDrawColorControl interface - */ -#define INTERFACE IDirectDrawColorControl -DECLARE_INTERFACE_(IDirectDrawColorControl,IUnknown) -{ - /*** IUnknown methods ***/ - STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; - STDMETHOD_(ULONG,AddRef)(THIS) PURE; - STDMETHOD_(ULONG,Release)(THIS) PURE; - /*** IDirectDrawColorControl methods ***/ - STDMETHOD(GetColorControls)(THIS_ LPDDCOLORCONTROL lpColorControl) PURE; - STDMETHOD(SetColorControls)(THIS_ LPDDCOLORCONTROL lpColorControl) PURE; -}; -#undef INTERFACE - -#if !defined(__cplusplus) || defined(CINTERFACE) -/*** IUnknown methods ***/ -#define IDirectDrawColorControl_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) -#define IDirectDrawColorControl_AddRef(p) (p)->lpVtbl->AddRef(p) -#define IDirectDrawColorControl_Release(p) (p)->lpVtbl->Release(p) -/*** IDirectDrawColorControl methods ***/ -#define IDirectDrawColorControl_GetColorControls(p,a) (p)->lpVtbl->GetColorControls(p,a) -#define IDirectDrawColorControl_SetColorControls(p,a) (p)->lpVtbl->SetColorControls(p,a) -#else -/*** IUnknown methods ***/ -#define IDirectDrawColorControl_QueryInterface(p,a,b) (p)->QueryInterface(a,b) -#define IDirectDrawColorControl_AddRef(p) (p)->AddRef() -#define IDirectDrawColorControl_Release(p) (p)->Release() -/*** IDirectDrawColorControl methods ***/ -#define IDirectDrawColorControl_GetColorControls(p,a) (p)->GetColorControls(a) -#define IDirectDrawColorControl_SetColorControls(p,a) (p)->SetColorControls(a) -#endif - -/***************************************************************************** - * IDirectDrawGammaControl interface - */ -#define INTERFACE IDirectDrawGammaControl -DECLARE_INTERFACE_(IDirectDrawGammaControl,IUnknown) -{ - /*** IUnknown methods ***/ - STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; - STDMETHOD_(ULONG,AddRef)(THIS) PURE; - STDMETHOD_(ULONG,Release)(THIS) PURE; - /*** IDirectDrawGammaControl methods ***/ - STDMETHOD(GetGammaRamp)(THIS_ DWORD dwFlags, LPDDGAMMARAMP lpGammaRamp) PURE; - STDMETHOD(SetGammaRamp)(THIS_ DWORD dwFlags, LPDDGAMMARAMP lpGammaRamp) PURE; -}; -#undef INTERFACE - -#if !defined(__cplusplus) || defined(CINTERFACE) -/*** IUnknown methods ***/ -#define IDirectDrawGammaControl_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) -#define IDirectDrawGammaControl_AddRef(p) (p)->lpVtbl->AddRef(p) -#define IDirectDrawGammaControl_Release(p) (p)->lpVtbl->Release(p) -/*** IDirectDrawGammaControl methods ***/ -#define IDirectDrawGammaControl_GetGammaRamp(p,a,b) (p)->lpVtbl->GetGammaRamp(p,a,b) -#define IDirectDrawGammaControl_SetGammaRamp(p,a,b) (p)->lpVtbl->SetGammaRamp(p,a,b) -#else -/*** IUnknown methods ***/ -#define IDirectDrawGammaControl_QueryInterface(p,a,b) (p)->QueryInterface(a,b) -#define IDirectDrawGammaControl_AddRef(p) (p)->AddRef() -#define IDirectDrawGammaControl_Release(p) (p)->Release() -/*** IDirectDrawGammaControl methods ***/ -#define IDirectDrawGammaControl_GetGammaRamp(p,a,b) (p)->GetGammaRamp(a,b) -#define IDirectDrawGammaControl_SetGammaRamp(p,a,b) (p)->SetGammaRamp(a,b) -#endif - - -HRESULT WINAPI DirectDrawCreate(GUID*,LPDIRECTDRAW*,IUnknown*); -HRESULT WINAPI DirectDrawCreateEx(GUID*,LPVOID*,REFIID,IUnknown*); -HRESULT WINAPI DirectDrawCreateClipper(DWORD,LPDIRECTDRAWCLIPPER*,IUnknown*); - -#ifdef __cplusplus -} /* extern "C" */ -#endif /* defined(__cplusplus) */ - -#endif /* __DDRAW_INCLUDED__ */ diff --git a/vendor/dshow/dshow.h b/vendor/dshow/dshow.h deleted file mode 100644 index 2587b2fa7..000000000 --- a/vendor/dshow/dshow.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2002 Alexandre Julliard - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#ifndef __DSHOW_INCLUDED__ -#define __DSHOW_INCLUDED__ - -#define AM_NOVTABLE - -#ifndef __WINESRC__ -# include -# include -#else -# include -# include -# include -#endif -#include -#include -#include -/* FIXME: #include */ - -#ifndef NUMELMS -#define NUMELMS(array) (sizeof(array)/sizeof((array)[0])) -#endif - -#include -#include -#ifdef DSHOW_USE_AMAUDIO -/* FIXME: #include */ -#endif -#include -#include -#include -#include -/* FIXME: #include */ -#include -/* FIXME: #include */ - -#ifndef OATRUE -#define OATRUE (-1) -#endif -#ifndef OAFALSE -#define OAFALSE (0) -#endif - -#endif /* __DSHOW_INCLUDED__ */ diff --git a/vendor/dshow/dsound.h b/vendor/dshow/dsound.h deleted file mode 100644 index 7230e8f91..000000000 --- a/vendor/dshow/dsound.h +++ /dev/null @@ -1,1199 +0,0 @@ -#include -#undef INTERFACE -/* - * Copyright (C) the Wine project - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#ifndef __DSOUND_INCLUDED__ -#define __DSOUND_INCLUDED__ - -#ifndef DIRECTSOUND_VERSION -#define DIRECTSOUND_VERSION 0x0900 -#endif - -#define COM_NO_WINDOWS_H -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif /* defined(__cplusplus) */ - -#ifndef DX_SHARED_DEFINES - -typedef float D3DVALUE, *LPD3DVALUE; - -#ifndef D3DCOLOR_DEFINED -typedef DWORD D3DCOLOR, *LPD3DCOLOR; -#define D3DCOLOR_DEFINED -#endif - -#ifndef D3DVECTOR_DEFINED -typedef struct _D3DVECTOR { - float x; - float y; - float z; -} D3DVECTOR; -#define D3DVECTOR_DEFINED -#endif - -#ifndef LPD3DVECTOR_DEFINED -typedef D3DVECTOR *LPD3DVECTOR; -#define LPD3DVECTOR_DEFINED -#endif - -#define DX_SHARED_DEFINES -#endif /* DX_SHARED_DEFINES */ - -/***************************************************************************** - * Predeclare the interfaces - */ -DEFINE_GUID(CLSID_DirectSound, 0x47d4d946, 0x62e8, 0x11cf, 0x93, 0xbc, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00); -DEFINE_GUID(CLSID_DirectSound8, 0x3901cc3f, 0x84b5, 0x4fa4, 0xba, 0x35, 0xaa, 0x81, 0x72, 0xb8, 0xa0, 0x9b); -DEFINE_GUID(CLSID_DirectSoundCapture, 0xb0210780, 0x89cd, 0x11d0, 0xaf, 0x08, 0x00, 0xa0, 0xc9, 0x25, 0xcd, 0x16); -DEFINE_GUID(CLSID_DirectSoundCapture8, 0xe4bcac13, 0x7f99, 0x4908, 0x9a, 0x8e, 0x74, 0xe3, 0xbf, 0x24, 0xb6, 0xe1); -DEFINE_GUID(CLSID_DirectSoundFullDuplex,0xfea4300c, 0x7959, 0x4147, 0xb2, 0x6a, 0x23, 0x77, 0xb9, 0xe7, 0xa9, 0x1d); - -DEFINE_GUID(IID_IDirectSound, 0x279AFA83,0x4981,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60); -typedef struct IDirectSound *LPDIRECTSOUND,**LPLPDIRECTSOUND; - -DEFINE_GUID(IID_IDirectSound8, 0xC50A7E93,0xF395,0x4834,0x9E,0xF6,0x7F,0xA9,0x9D,0xE5,0x09,0x66); -typedef struct IDirectSound8 *LPDIRECTSOUND8,**LPLPDIRECTSOUND8; - -DEFINE_GUID(IID_IDirectSoundBuffer, 0x279AFA85,0x4981,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60); -typedef struct IDirectSoundBuffer *LPDIRECTSOUNDBUFFER,**LPLPDIRECTSOUNDBUFFER; - -DEFINE_GUID(IID_IDirectSoundBuffer8, 0x6825A449,0x7524,0x4D82,0x92,0x0F,0x50,0xE3,0x6A,0xB3,0xAB,0x1E); -typedef struct IDirectSoundBuffer8 *LPDIRECTSOUNDBUFFER8,**LPLPDIRECTSOUNDBUFFER8; - -DEFINE_GUID(IID_IDirectSoundNotify, 0xB0210783,0x89cd,0x11d0,0xAF,0x08,0x00,0xA0,0xC9,0x25,0xCD,0x16); -typedef struct IDirectSoundNotify *LPDIRECTSOUNDNOTIFY,**LPLPDIRECTSOUNDNOTIFY; -#define IID_IDirectSoundNotify8 IID_IDirectSoundNotify - -DEFINE_GUID(IID_IDirectSound3DListener, 0x279AFA84,0x4981,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60); -typedef struct IDirectSound3DListener *LPDIRECTSOUND3DLISTENER,**LPLPDIRECTSOUND3DLISTENER; - -DEFINE_GUID(IID_IDirectSound3DBuffer, 0x279AFA86,0x4981,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60); -typedef struct IDirectSound3DBuffer *LPDIRECTSOUND3DBUFFER,**LPLPDIRECTSOUND3DBUFFER; - -DEFINE_GUID(IID_IDirectSoundCapture, 0xB0210781,0x89CD,0x11D0,0xAF,0x08,0x00,0xA0,0xC9,0x25,0xCD,0x16); -typedef struct IDirectSoundCapture *LPDIRECTSOUNDCAPTURE,**LPLPDIRECTSOUNDCAPTURE; -#define IID_IDirectSoundCapture8 IID_IDirectSoundCapture -typedef struct IDirectSoundCapture IDirectSoundCapture8,*LPDIRECTSOUNDCAPTURE8,**LPLPDIRECTSOUNDCAPTURE8; - -DEFINE_GUID(IID_IDirectSoundCaptureBuffer,0xB0210782,0x89CD,0x11D0,0xAF,0x08,0x00,0xA0,0xC9,0x25,0xCD,0x16); -typedef struct IDirectSoundCaptureBuffer *LPDIRECTSOUNDCAPTUREBUFFER,**LPLPDIRECTSOUNDCAPTUREBUFFER; - -DEFINE_GUID(IID_IDirectSoundCaptureBuffer8,0x00990DF4,0x0DBB,0x4872,0x83,0x3E,0x6D,0x30,0x3E,0x80,0xAE,0xB6); -typedef struct IDirectSoundCaptureBuffer8 *LPDIRECTSOUNDCAPTUREBUFFER8,**LPLPDIRECTSOUNDCAPTUREBUFFER8; - -DEFINE_GUID(IID_IDirectSoundFullDuplex, 0xEDCB4C7A,0xDAAB,0x4216,0xA4,0x2E,0x6C,0x50,0x59,0x6D,0xDC,0x1D); -typedef struct IDirectSoundFullDuplex *LPDIRECTSOUNDFULLDUPLEX,**LPLPDIRECTSOUNDFULLDUPLEX; -#define IID_IDirectSoundFullDuplex8 IID_IDirectSoundFullDuplex - -DEFINE_GUID(DSDEVID_DefaultPlayback, 0xDEF00000,0x9C6D,0x47Ed,0xAA,0xF1,0x4D,0xDA,0x8F,0x2B,0x5C,0x03); -DEFINE_GUID(DSDEVID_DefaultCapture, 0xDEF00001,0x9C6D,0x47Ed,0xAA,0xF1,0x4D,0xDA,0x8F,0x2B,0x5C,0x03); -DEFINE_GUID(DSDEVID_DefaultVoicePlayback,0xDEF00002,0x9C6D,0x47Ed,0xAA,0xF1,0x4D,0xDA,0x8F,0x2B,0x5C,0x03); -DEFINE_GUID(DSDEVID_DefaultVoiceCapture, 0xDEF00003,0x9C6D,0x47ED,0xAA,0xF1,0x4D,0xDA,0x8F,0x2B,0x5C,0x03); - -DEFINE_GUID(DSDEVID_WinePlayback, 0x40316A1D,0x605B,0xD611,0x87,0xC6,0x00,0x80,0xAD,0x00,0x02,0xFE); - -#define _FACDS 0x878 -#define MAKE_DSHRESULT(code) MAKE_HRESULT(1,_FACDS,code) - -#define DS_OK 0 -#define DS_NO_VIRTUALIZATION MAKE_HRESULT(0, _FACDS, 10) -#define DS_INCOMPLETE MAKE_HRESULT(0, _FACDS, 20) -#define DSERR_ALLOCATED MAKE_DSHRESULT(10) -#define DSERR_CONTROLUNAVAIL MAKE_DSHRESULT(30) -#define DSERR_INVALIDPARAM E_INVALIDARG -#define DSERR_INVALIDCALL MAKE_DSHRESULT(50) -#define DSERR_GENERIC E_FAIL -#define DSERR_PRIOLEVELNEEDED MAKE_DSHRESULT(70) -#define DSERR_OUTOFMEMORY E_OUTOFMEMORY -#define DSERR_BADFORMAT MAKE_DSHRESULT(100) -#define DSERR_UNSUPPORTED E_NOTIMPL -#define DSERR_NODRIVER MAKE_DSHRESULT(120) -#define DSERR_ALREADYINITIALIZED MAKE_DSHRESULT(130) -#define DSERR_NOAGGREGATION CLASS_E_NOAGGREGATION -#define DSERR_BUFFERLOST MAKE_DSHRESULT(150) -#define DSERR_OTHERAPPHASPRIO MAKE_DSHRESULT(160) -#define DSERR_UNINITIALIZED MAKE_DSHRESULT(170) -#define DSERR_NOINTERFACE E_NOINTERFACE -#define DSERR_ACCESSDENIED E_ACCESSDENIED -#define DSERR_BUFFERTOOSMALL MAKE_DSHRESULT(180) -#define DSERR_DS8_REQUIRED MAKE_DSHRESULT(190) -#define DSERR_SENDLOOP MAKE_DSHRESULT(200) -#define DSERR_BADSENDBUFFERGUID MAKE_DSHRESULT(210) -#define DSERR_FXUNAVAILABLE MAKE_DSHRESULT(220) -#define DSERR_OBJECTNOTFOUND MAKE_DSHRESULT(4449) - -#define DSCAPS_PRIMARYMONO 0x00000001 -#define DSCAPS_PRIMARYSTEREO 0x00000002 -#define DSCAPS_PRIMARY8BIT 0x00000004 -#define DSCAPS_PRIMARY16BIT 0x00000008 -#define DSCAPS_CONTINUOUSRATE 0x00000010 -#define DSCAPS_EMULDRIVER 0x00000020 -#define DSCAPS_CERTIFIED 0x00000040 -#define DSCAPS_SECONDARYMONO 0x00000100 -#define DSCAPS_SECONDARYSTEREO 0x00000200 -#define DSCAPS_SECONDARY8BIT 0x00000400 -#define DSCAPS_SECONDARY16BIT 0x00000800 - -#define DSSCL_NORMAL 1 -#define DSSCL_PRIORITY 2 -#define DSSCL_EXCLUSIVE 3 -#define DSSCL_WRITEPRIMARY 4 - -typedef struct _DSCAPS -{ - DWORD dwSize; - DWORD dwFlags; - DWORD dwMinSecondarySampleRate; - DWORD dwMaxSecondarySampleRate; - DWORD dwPrimaryBuffers; - DWORD dwMaxHwMixingAllBuffers; - DWORD dwMaxHwMixingStaticBuffers; - DWORD dwMaxHwMixingStreamingBuffers; - DWORD dwFreeHwMixingAllBuffers; - DWORD dwFreeHwMixingStaticBuffers; - DWORD dwFreeHwMixingStreamingBuffers; - DWORD dwMaxHw3DAllBuffers; - DWORD dwMaxHw3DStaticBuffers; - DWORD dwMaxHw3DStreamingBuffers; - DWORD dwFreeHw3DAllBuffers; - DWORD dwFreeHw3DStaticBuffers; - DWORD dwFreeHw3DStreamingBuffers; - DWORD dwTotalHwMemBytes; - DWORD dwFreeHwMemBytes; - DWORD dwMaxContigFreeHwMemBytes; - DWORD dwUnlockTransferRateHwBuffers; - DWORD dwPlayCpuOverheadSwBuffers; - DWORD dwReserved1; - DWORD dwReserved2; -} DSCAPS,*LPDSCAPS; -typedef const DSCAPS *LPCDSCAPS; - -#define DSBPLAY_LOOPING 0x00000001 -#define DSBPLAY_LOCHARDWARE 0x00000002 -#define DSBPLAY_LOCSOFTWARE 0x00000004 -#define DSBPLAY_TERMINATEBY_TIME 0x00000008 -#define DSBPLAY_TERMINATEBY_DISTANCE 0x000000010 -#define DSBPLAY_TERMINATEBY_PRIORITY 0x000000020 - -#define DSBSTATUS_PLAYING 0x00000001 -#define DSBSTATUS_BUFFERLOST 0x00000002 -#define DSBSTATUS_LOOPING 0x00000004 -#define DSBSTATUS_LOCHARDWARE 0x00000008 -#define DSBSTATUS_LOCSOFTWARE 0x00000010 -#define DSBSTATUS_TERMINATED 0x00000020 - -#define DSBLOCK_FROMWRITECURSOR 0x00000001 -#define DSBLOCK_ENTIREBUFFER 0x00000002 - -#define DSBCAPS_PRIMARYBUFFER 0x00000001 -#define DSBCAPS_STATIC 0x00000002 -#define DSBCAPS_LOCHARDWARE 0x00000004 -#define DSBCAPS_LOCSOFTWARE 0x00000008 -#define DSBCAPS_CTRL3D 0x00000010 -#define DSBCAPS_CTRLFREQUENCY 0x00000020 -#define DSBCAPS_CTRLPAN 0x00000040 -#define DSBCAPS_CTRLVOLUME 0x00000080 -#define DSBCAPS_CTRLDEFAULT 0x000000E0 /* Pan + volume + frequency. */ -#define DSBCAPS_CTRLPOSITIONNOTIFY 0x00000100 -#define DSBCAPS_CTRLFX 0x00000200 -#define DSBCAPS_CTRLALL 0x000001F0 /* All control capabilities */ -#define DSBCAPS_STICKYFOCUS 0x00004000 -#define DSBCAPS_GLOBALFOCUS 0x00008000 -#define DSBCAPS_GETCURRENTPOSITION2 0x00010000 /* More accurate play cursor under emulation*/ -#define DSBCAPS_MUTE3DATMAXDISTANCE 0x00020000 -#define DSBCAPS_LOCDEFER 0x00040000 - -#define DSBSIZE_MIN 4 -#define DSBSIZE_MAX 0xFFFFFFF -#define DSBPAN_LEFT -10000 -#define DSBPAN_CENTER 0 -#define DSBPAN_RIGHT 10000 -#define DSBVOLUME_MAX 0 -#define DSBVOLUME_MIN -10000 -#define DSBFREQUENCY_MIN 100 -#define DSBFREQUENCY_MAX 200000 -#define DSBFREQUENCY_ORIGINAL 0 - -#define DSBNOTIFICATIONS_MAX 100000U - -typedef struct _DSBCAPS -{ - DWORD dwSize; - DWORD dwFlags; - DWORD dwBufferBytes; - DWORD dwUnlockTransferRate; - DWORD dwPlayCpuOverhead; -} DSBCAPS,*LPDSBCAPS; -typedef const DSBCAPS *LPCDSBCAPS; - -#define DSSCL_NORMAL 1 -#define DSSCL_PRIORITY 2 -#define DSSCL_EXCLUSIVE 3 -#define DSSCL_WRITEPRIMARY 4 - -typedef struct _DSEFFECTDESC -{ - DWORD dwSize; - DWORD dwFlags; - GUID guidDSFXClass; - DWORD_PTR dwReserved1; - DWORD_PTR dwReserved2; -} DSEFFECTDESC,*LPDSEFFECTDESC; -typedef const DSEFFECTDESC *LPCDSEFFECTDESC; - -#define DSFX_LOCHARDWARE 0x00000001 -#define DSFX_LOCSOFTWARE 0x00000002 - -enum -{ - DSFXR_PRESENT, - DSFXR_LOCHARDWARE, - DSFXR_LOCSOFTWARE, - DSFXR_UNALLOCATED, - DSFXR_FAILED, - DSFXR_UNKNOWN, - DSFXR_SENDLOOP -}; - -typedef struct _DSBUFFERDESC1 -{ - DWORD dwSize; - DWORD dwFlags; - DWORD dwBufferBytes; - DWORD dwReserved; - LPWAVEFORMATEX lpwfxFormat; -} DSBUFFERDESC1,*LPDSBUFFERDESC1; -typedef const DSBUFFERDESC1 *LPCDSBUFFERDESC1; - -typedef struct _DSBUFFERDESC -{ - DWORD dwSize; - DWORD dwFlags; - DWORD dwBufferBytes; - DWORD dwReserved; - LPWAVEFORMATEX lpwfxFormat; - GUID guid3DAlgorithm; -} DSBUFFERDESC,*LPDSBUFFERDESC; -typedef const DSBUFFERDESC *LPCDSBUFFERDESC; - -typedef struct _DSBPOSITIONNOTIFY -{ - DWORD dwOffset; - HANDLE hEventNotify; -} DSBPOSITIONNOTIFY,*LPDSBPOSITIONNOTIFY; -typedef const DSBPOSITIONNOTIFY *LPCDSBPOSITIONNOTIFY; - -#define DSSPEAKER_HEADPHONE 1 -#define DSSPEAKER_MONO 2 -#define DSSPEAKER_QUAD 3 -#define DSSPEAKER_STEREO 4 -#define DSSPEAKER_SURROUND 5 -#define DSSPEAKER_5POINT1 6 -#define DSSPEAKER_7POINT1 7 - -#define DSSPEAKER_GEOMETRY_MIN 0x00000005 /* 5 degrees */ -#define DSSPEAKER_GEOMETRY_NARROW 0x0000000A /* 10 degrees */ -#define DSSPEAKER_GEOMETRY_WIDE 0x00000014 /* 20 degrees */ -#define DSSPEAKER_GEOMETRY_MAX 0x000000B4 /* 180 degrees */ - -#define DSSPEAKER_COMBINED(c, g) ((DWORD)(((BYTE)(c)) | ((DWORD)((BYTE)(g))) << 16)) -#define DSSPEAKER_CONFIG(a) ((BYTE)(a)) -#define DSSPEAKER_GEOMETRY(a) ((BYTE)(((DWORD)(a) >> 16) & 0x00FF)) - -#define DS_CERTIFIED 0x00000000 -#define DS_UNCERTIFIED 0x00000001 - -typedef struct _DSCEFFECTDESC -{ - DWORD dwSize; - DWORD dwFlags; - GUID guidDSCFXClass; - GUID guidDSCFXInstance; - DWORD dwReserved1; - DWORD dwReserved2; -} DSCEFFECTDESC, *LPDSCEFFECTDESC; -typedef const DSCEFFECTDESC *LPCDSCEFFECTDESC; - -#define DSCFX_LOCHARDWARE 0x00000001 -#define DSCFX_LOCSOFTWARE 0x00000002 - -#define DSCFXR_LOCHARDWARE 0x00000010 -#define DSCFXR_LOCSOFTWARE 0x00000020 - -typedef struct _DSCBUFFERDESC1 -{ - DWORD dwSize; - DWORD dwFlags; - DWORD dwBufferBytes; - DWORD dwReserved; - LPWAVEFORMATEX lpwfxFormat; -} DSCBUFFERDESC1, *LPDSCBUFFERDESC1; - -typedef struct _DSCBUFFERDESC -{ - DWORD dwSize; - DWORD dwFlags; - DWORD dwBufferBytes; - DWORD dwReserved; - LPWAVEFORMATEX lpwfxFormat; - DWORD dwFXCount; - LPDSCEFFECTDESC lpDSCFXDesc; -} DSCBUFFERDESC, *LPDSCBUFFERDESC; -typedef const DSCBUFFERDESC *LPCDSCBUFFERDESC; - -typedef struct _DSCCAPS -{ - DWORD dwSize; - DWORD dwFlags; - DWORD dwFormats; - DWORD dwChannels; -} DSCCAPS, *LPDSCCAPS; -typedef const DSCCAPS *LPCDSCCAPS; - -typedef struct _DSCBCAPS -{ - DWORD dwSize; - DWORD dwFlags; - DWORD dwBufferBytes; - DWORD dwReserved; -} DSCBCAPS, *LPDSCBCAPS; -typedef const DSCBCAPS *LPCDSCBCAPS; - -#define DSCCAPS_EMULDRIVER DSCAPS_EMULDRIVER -#define DSCCAPS_CERTIFIED DSCAPS_CERTIFIED -#define DSCCAPS_MULTIPLECAPTURE 0x00000001 - -#define DSCBCAPS_WAVEMAPPED 0x80000000 -#define DSCBCAPS_CTRLFX 0x00000200 - -#define DSCBLOCK_ENTIREBUFFER 0x00000001 -#define DSCBSTART_LOOPING 0x00000001 -#define DSCBPN_OFFSET_STOP 0xffffffff - -#define DSCBSTATUS_CAPTURING 0x00000001 -#define DSCBSTATUS_LOOPING 0x00000002 - -#ifndef __LPCGUID_DEFINED__ -#define __LPCGUID_DEFINED__ -typedef const GUID *LPCGUID; -#endif - -typedef WINBOOL (CALLBACK *LPDSENUMCALLBACKW)(LPGUID,LPCWSTR,LPCWSTR,LPVOID); -typedef WINBOOL (CALLBACK *LPDSENUMCALLBACKA)(LPGUID,LPCSTR,LPCSTR,LPVOID); -__MINGW_TYPEDEF_AW(LPDSENUMCALLBACK) - -extern HRESULT WINAPI DirectSoundCreate(LPCGUID lpGUID,LPDIRECTSOUND *ppDS,LPUNKNOWN pUnkOuter); -extern HRESULT WINAPI DirectSoundEnumerateA(LPDSENUMCALLBACKA, LPVOID); -extern HRESULT WINAPI DirectSoundEnumerateW(LPDSENUMCALLBACKW, LPVOID); -#define DirectSoundEnumerate __MINGW_NAME_AW(DirectSoundEnumerate) -extern HRESULT WINAPI DirectSoundCaptureCreate(LPCGUID lpGUID, LPDIRECTSOUNDCAPTURE *ppDSC, LPUNKNOWN pUnkOuter); -extern HRESULT WINAPI DirectSoundCaptureEnumerateA(LPDSENUMCALLBACKA, LPVOID); -extern HRESULT WINAPI DirectSoundCaptureEnumerateW(LPDSENUMCALLBACKW, LPVOID); -#define DirectSoundCaptureEnumerate __MINGW_NAME_AW(DirectSoundCaptureEnumerate) - -extern HRESULT WINAPI DirectSoundCreate8(LPCGUID lpGUID,LPDIRECTSOUND8 *ppDS8,LPUNKNOWN pUnkOuter); -extern HRESULT WINAPI DirectSoundCaptureCreate8(LPCGUID lpGUID, LPDIRECTSOUNDCAPTURE8 *ppDSC8, LPUNKNOWN pUnkOuter); -extern HRESULT WINAPI DirectSoundFullDuplexCreate(LPCGUID pcGuidCaptureDevice, LPCGUID pcGuidRenderDevice, - LPCDSCBUFFERDESC pcDSCBufferDesc, LPCDSBUFFERDESC pcDSBufferDesc, HWND hWnd, DWORD dwLevel, - LPDIRECTSOUNDFULLDUPLEX *ppDSFD, LPDIRECTSOUNDCAPTUREBUFFER8 *ppDSCBuffer8, LPDIRECTSOUNDBUFFER8 *ppDSBuffer8, LPUNKNOWN pUnkOuter); -#define DirectSoundFullDuplexCreate8 DirectSoundFullDuplexCreate -extern HRESULT WINAPI GetDeviceID(LPCGUID lpGuidSrc, LPGUID lpGuidDest); - - -/***************************************************************************** - * IDirectSound interface - */ -#define INTERFACE IDirectSound -DECLARE_INTERFACE_(IDirectSound,IUnknown) -{ - /*** IUnknown methods ***/ - STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; - STDMETHOD_(ULONG,AddRef)(THIS) PURE; - STDMETHOD_(ULONG,Release)(THIS) PURE; - /*** IDirectSound methods ***/ - STDMETHOD(CreateSoundBuffer)(THIS_ LPCDSBUFFERDESC lpcDSBufferDesc, LPLPDIRECTSOUNDBUFFER lplpDirectSoundBuffer, IUnknown *pUnkOuter) PURE; - STDMETHOD(GetCaps)(THIS_ LPDSCAPS lpDSCaps) PURE; - STDMETHOD(DuplicateSoundBuffer)(THIS_ LPDIRECTSOUNDBUFFER lpDsbOriginal, LPLPDIRECTSOUNDBUFFER lplpDsbDuplicate) PURE; - STDMETHOD(SetCooperativeLevel)(THIS_ HWND hwnd, DWORD dwLevel) PURE; - STDMETHOD(Compact)(THIS) PURE; - STDMETHOD(GetSpeakerConfig)(THIS_ LPDWORD lpdwSpeakerConfig) PURE; - STDMETHOD(SetSpeakerConfig)(THIS_ DWORD dwSpeakerConfig) PURE; - STDMETHOD(Initialize)(THIS_ LPCGUID lpcGuid) PURE; -}; -#undef INTERFACE - -#if !defined(__cplusplus) || defined(CINTERFACE) -/*** IUnknown methods ***/ -#define IDirectSound_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) -#define IDirectSound_AddRef(p) (p)->lpVtbl->AddRef(p) -#define IDirectSound_Release(p) (p)->lpVtbl->Release(p) -/*** IDirectSound methods ***/ -#define IDirectSound_CreateSoundBuffer(p,a,b,c) (p)->lpVtbl->CreateSoundBuffer(p,a,b,c) -#define IDirectSound_GetCaps(p,a) (p)->lpVtbl->GetCaps(p,a) -#define IDirectSound_DuplicateSoundBuffer(p,a,b) (p)->lpVtbl->DuplicateSoundBuffer(p,a,b) -#define IDirectSound_SetCooperativeLevel(p,a,b) (p)->lpVtbl->SetCooperativeLevel(p,a,b) -#define IDirectSound_Compact(p) (p)->lpVtbl->Compact(p) -#define IDirectSound_GetSpeakerConfig(p,a) (p)->lpVtbl->GetSpeakerConfig(p,a) -#define IDirectSound_SetSpeakerConfig(p,a) (p)->lpVtbl->SetSpeakerConfig(p,a) -#define IDirectSound_Initialize(p,a) (p)->lpVtbl->Initialize(p,a) -#else -/*** IUnknown methods ***/ -#define IDirectSound_QueryInterface(p,a,b) (p)->QueryInterface(a,b) -#define IDirectSound_AddRef(p) (p)->AddRef() -#define IDirectSound_Release(p) (p)->Release() -/*** IDirectSound methods ***/ -#define IDirectSound_CreateSoundBuffer(p,a,b,c) (p)->CreateSoundBuffer(a,b,c) -#define IDirectSound_GetCaps(p,a) (p)->GetCaps(a) -#define IDirectSound_DuplicateSoundBuffer(p,a,b) (p)->DuplicateSoundBuffer(a,b) -#define IDirectSound_SetCooperativeLevel(p,a,b) (p)->SetCooperativeLevel(a,b) -#define IDirectSound_Compact(p) (p)->Compact() -#define IDirectSound_GetSpeakerConfig(p,a) (p)->GetSpeakerConfig(a) -#define IDirectSound_SetSpeakerConfig(p,a) (p)->SetSpeakerConfig(a) -#define IDirectSound_Initialize(p,a) (p)->Initialize(a) -#endif - - -/***************************************************************************** - * IDirectSound8 interface - */ -#define INTERFACE IDirectSound8 -DECLARE_INTERFACE_(IDirectSound8,IUnknown) -{ - /*** IUnknown methods ***/ - STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; - STDMETHOD_(ULONG,AddRef)(THIS) PURE; - STDMETHOD_(ULONG,Release)(THIS) PURE; - /*** IDirectSound8 methods ***/ - STDMETHOD(CreateSoundBuffer)(THIS_ LPCDSBUFFERDESC lpcDSBufferDesc, LPLPDIRECTSOUNDBUFFER lplpDirectSoundBuffer, IUnknown *pUnkOuter) PURE; - STDMETHOD(GetCaps)(THIS_ LPDSCAPS lpDSCaps) PURE; - STDMETHOD(DuplicateSoundBuffer)(THIS_ LPDIRECTSOUNDBUFFER lpDsbOriginal, LPLPDIRECTSOUNDBUFFER lplpDsbDuplicate) PURE; - STDMETHOD(SetCooperativeLevel)(THIS_ HWND hwnd, DWORD dwLevel) PURE; - STDMETHOD(Compact)(THIS) PURE; - STDMETHOD(GetSpeakerConfig)(THIS_ LPDWORD lpdwSpeakerConfig) PURE; - STDMETHOD(SetSpeakerConfig)(THIS_ DWORD dwSpeakerConfig) PURE; - STDMETHOD(Initialize)(THIS_ LPCGUID lpcGuid) PURE; - STDMETHOD(VerifyCertification)(THIS_ LPDWORD pdwCertified) PURE; -}; -#undef INTERFACE - -#if !defined(__cplusplus) || defined(CINTERFACE) -/*** IUnknown methods ***/ -#define IDirectSound8_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) -#define IDirectSound8_AddRef(p) (p)->lpVtbl->AddRef(p) -#define IDirectSound8_Release(p) (p)->lpVtbl->Release(p) -/*** IDirectSound methods ***/ -#define IDirectSound8_CreateSoundBuffer(p,a,b,c) (p)->lpVtbl->CreateSoundBuffer(p,a,b,c) -#define IDirectSound8_GetCaps(p,a) (p)->lpVtbl->GetCaps(p,a) -#define IDirectSound8_DuplicateSoundBuffer(p,a,b) (p)->lpVtbl->DuplicateSoundBuffer(p,a,b) -#define IDirectSound8_SetCooperativeLevel(p,a,b) (p)->lpVtbl->SetCooperativeLevel(p,a,b) -#define IDirectSound8_Compact(p) (p)->lpVtbl->Compact(p) -#define IDirectSound8_GetSpeakerConfig(p,a) (p)->lpVtbl->GetSpeakerConfig(p,a) -#define IDirectSound8_SetSpeakerConfig(p,a) (p)->lpVtbl->SetSpeakerConfig(p,a) -#define IDirectSound8_Initialize(p,a) (p)->lpVtbl->Initialize(p,a) -/*** IDirectSound8 methods ***/ -#define IDirectSound8_VerifyCertification(p,a) (p)->lpVtbl->VerifyCertification(p,a) -#else -/*** IUnknown methods ***/ -#define IDirectSound8_QueryInterface(p,a,b) (p)->QueryInterface(a,b) -#define IDirectSound8_AddRef(p) (p)->AddRef() -#define IDirectSound8_Release(p) (p)->Release() -/*** IDirectSound methods ***/ -#define IDirectSound8_CreateSoundBuffer(p,a,b,c) (p)->CreateSoundBuffer(a,b,c) -#define IDirectSound8_GetCaps(p,a) (p)->GetCaps(a) -#define IDirectSound8_DuplicateSoundBuffer(p,a,b) (p)->DuplicateSoundBuffer(a,b) -#define IDirectSound8_SetCooperativeLevel(p,a,b) (p)->SetCooperativeLevel(a,b) -#define IDirectSound8_Compact(p) (p)->Compact() -#define IDirectSound8_GetSpeakerConfig(p,a) (p)->GetSpeakerConfig(a) -#define IDirectSound8_SetSpeakerConfig(p,a) (p)->SetSpeakerConfig(a) -#define IDirectSound8_Initialize(p,a) (p)->Initialize(a) -/*** IDirectSound8 methods ***/ -#define IDirectSound8_VerifyCertification(p,a) (p)->VerifyCertification(a) -#endif - - -/***************************************************************************** - * IDirectSoundBuffer interface - */ -#define INTERFACE IDirectSoundBuffer -DECLARE_INTERFACE_(IDirectSoundBuffer,IUnknown) -{ - /*** IUnknown methods ***/ - STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; - STDMETHOD_(ULONG,AddRef)(THIS) PURE; - STDMETHOD_(ULONG,Release)(THIS) PURE; - /*** IDirectSoundBuffer methods ***/ - STDMETHOD(GetCaps)(THIS_ LPDSBCAPS lpDSBufferCaps) PURE; - STDMETHOD(GetCurrentPosition)(THIS_ LPDWORD lpdwCurrentPlayCursor, LPDWORD lpdwCurrentWriteCursor) PURE; - STDMETHOD(GetFormat)(THIS_ LPWAVEFORMATEX lpwfxFormat, DWORD dwSizeAllocated, LPDWORD lpdwSizeWritten) PURE; - STDMETHOD(GetVolume)(THIS_ LPLONG lplVolume) PURE; - STDMETHOD(GetPan)(THIS_ LPLONG lplpan) PURE; - STDMETHOD(GetFrequency)(THIS_ LPDWORD lpdwFrequency) PURE; - STDMETHOD(GetStatus)(THIS_ LPDWORD lpdwStatus) PURE; - STDMETHOD(Initialize)(THIS_ LPDIRECTSOUND lpDirectSound, LPCDSBUFFERDESC lpcDSBufferDesc) PURE; - STDMETHOD(Lock)(THIS_ DWORD dwOffset, DWORD dwBytes, LPVOID *ppvAudioPtr1, LPDWORD pdwAudioBytes1, LPVOID *ppvAudioPtr2, LPDWORD pdwAudioBytes2, DWORD dwFlags) PURE; - STDMETHOD(Play)(THIS_ DWORD dwReserved1, DWORD dwReserved2, DWORD dwFlags) PURE; - STDMETHOD(SetCurrentPosition)(THIS_ DWORD dwNewPosition) PURE; - STDMETHOD(SetFormat)(THIS_ LPCWAVEFORMATEX lpcfxFormat) PURE; - STDMETHOD(SetVolume)(THIS_ LONG lVolume) PURE; - STDMETHOD(SetPan)(THIS_ LONG lPan) PURE; - STDMETHOD(SetFrequency)(THIS_ DWORD dwFrequency) PURE; - STDMETHOD(Stop)(THIS) PURE; - STDMETHOD(Unlock)(THIS_ LPVOID pvAudioPtr1, DWORD dwAudioBytes1, LPVOID pvAudioPtr2, DWORD dwAudioPtr2) PURE; - STDMETHOD(Restore)(THIS) PURE; -}; -#undef INTERFACE - -#if !defined(__cplusplus) || defined(CINTERFACE) -/*** IUnknown methods ***/ -#define IDirectSoundBuffer_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) -#define IDirectSoundBuffer_AddRef(p) (p)->lpVtbl->AddRef(p) -#define IDirectSoundBuffer_Release(p) (p)->lpVtbl->Release(p) -/*** IDirectSoundBuffer methods ***/ -#define IDirectSoundBuffer_GetCaps(p,a) (p)->lpVtbl->GetCaps(p,a) -#define IDirectSoundBuffer_GetCurrentPosition(p,a,b) (p)->lpVtbl->GetCurrentPosition(p,a,b) -#define IDirectSoundBuffer_GetFormat(p,a,b,c) (p)->lpVtbl->GetFormat(p,a,b,c) -#define IDirectSoundBuffer_GetVolume(p,a) (p)->lpVtbl->GetVolume(p,a) -#define IDirectSoundBuffer_GetPan(p,a) (p)->lpVtbl->GetPan(p,a) -#define IDirectSoundBuffer_GetFrequency(p,a) (p)->lpVtbl->GetFrequency(p,a) -#define IDirectSoundBuffer_GetStatus(p,a) (p)->lpVtbl->GetStatus(p,a) -#define IDirectSoundBuffer_Initialize(p,a,b) (p)->lpVtbl->Initialize(p,a,b) -#define IDirectSoundBuffer_Lock(p,a,b,c,d,e,f,g) (p)->lpVtbl->Lock(p,a,b,c,d,e,f,g) -#define IDirectSoundBuffer_Play(p,a,b,c) (p)->lpVtbl->Play(p,a,b,c) -#define IDirectSoundBuffer_SetCurrentPosition(p,a) (p)->lpVtbl->SetCurrentPosition(p,a) -#define IDirectSoundBuffer_SetFormat(p,a) (p)->lpVtbl->SetFormat(p,a) -#define IDirectSoundBuffer_SetVolume(p,a) (p)->lpVtbl->SetVolume(p,a) -#define IDirectSoundBuffer_SetPan(p,a) (p)->lpVtbl->SetPan(p,a) -#define IDirectSoundBuffer_SetFrequency(p,a) (p)->lpVtbl->SetFrequency(p,a) -#define IDirectSoundBuffer_Stop(p) (p)->lpVtbl->Stop(p) -#define IDirectSoundBuffer_Unlock(p,a,b,c,d) (p)->lpVtbl->Unlock(p,a,b,c,d) -#define IDirectSoundBuffer_Restore(p) (p)->lpVtbl->Restore(p) -#else -/*** IUnknown methods ***/ -#define IDirectSoundBuffer_QueryInterface(p,a,b) (p)->QueryInterface(a,b) -#define IDirectSoundBuffer_AddRef(p) (p)->AddRef() -#define IDirectSoundBuffer_Release(p) (p)->Release() -/*** IDirectSoundBuffer methods ***/ -#define IDirectSoundBuffer_GetCaps(p,a) (p)->GetCaps(a) -#define IDirectSoundBuffer_GetCurrentPosition(p,a,b) (p)->GetCurrentPosition(a,b) -#define IDirectSoundBuffer_GetFormat(p,a,b,c) (p)->GetFormat(a,b,c) -#define IDirectSoundBuffer_GetVolume(p,a) (p)->GetVolume(a) -#define IDirectSoundBuffer_GetPan(p,a) (p)->GetPan(a) -#define IDirectSoundBuffer_GetFrequency(p,a) (p)->GetFrequency(a) -#define IDirectSoundBuffer_GetStatus(p,a) (p)->GetStatus(a) -#define IDirectSoundBuffer_Initialize(p,a,b) (p)->Initialize(a,b) -#define IDirectSoundBuffer_Lock(p,a,b,c,d,e,f,g) (p)->Lock(a,b,c,d,e,f,g) -#define IDirectSoundBuffer_Play(p,a,b,c) (p)->Play(a,b,c) -#define IDirectSoundBuffer_SetCurrentPosition(p,a) (p)->SetCurrentPosition(a) -#define IDirectSoundBuffer_SetFormat(p,a) (p)->SetFormat(a) -#define IDirectSoundBuffer_SetVolume(p,a) (p)->SetVolume(a) -#define IDirectSoundBuffer_SetPan(p,a) (p)->SetPan(a) -#define IDirectSoundBuffer_SetFrequency(p,a) (p)->SetFrequency(a) -#define IDirectSoundBuffer_Stop(p) (p)->Stop() -#define IDirectSoundBuffer_Unlock(p,a,b,c,d) (p)->Unlock(a,b,c,d) -#define IDirectSoundBuffer_Restore(p) (p)->Restore() -#endif - - -/***************************************************************************** - * IDirectSoundBuffer8 interface - */ -#define INTERFACE IDirectSoundBuffer8 -DECLARE_INTERFACE_(IDirectSoundBuffer8,IUnknown) -{ - /*** IUnknown methods ***/ - STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; - STDMETHOD_(ULONG,AddRef)(THIS) PURE; - STDMETHOD_(ULONG,Release)(THIS) PURE; - /*** IDirectSoundBuffer8 methods ***/ - STDMETHOD(GetCaps)(THIS_ LPDSBCAPS lpDSBufferCaps) PURE; - STDMETHOD(GetCurrentPosition)(THIS_ LPDWORD lpdwCurrentPlayCursor, LPDWORD lpdwCurrentWriteCursor) PURE; - STDMETHOD(GetFormat)(THIS_ LPWAVEFORMATEX lpwfxFormat, DWORD dwSizeAllocated, LPDWORD lpdwSizeWritten) PURE; - STDMETHOD(GetVolume)(THIS_ LPLONG lplVolume) PURE; - STDMETHOD(GetPan)(THIS_ LPLONG lplpan) PURE; - STDMETHOD(GetFrequency)(THIS_ LPDWORD lpdwFrequency) PURE; - STDMETHOD(GetStatus)(THIS_ LPDWORD lpdwStatus) PURE; - STDMETHOD(Initialize)(THIS_ LPDIRECTSOUND lpDirectSound, LPCDSBUFFERDESC lpcDSBufferDesc) PURE; - STDMETHOD(Lock)(THIS_ DWORD dwOffset, DWORD dwBytes, LPVOID *ppvAudioPtr1, LPDWORD pdwAudioBytes1, LPVOID *ppvAudioPtr2, LPDWORD pdwAudioBytes2, DWORD dwFlags) PURE; - STDMETHOD(Play)(THIS_ DWORD dwReserved1, DWORD dwReserved2, DWORD dwFlags) PURE; - STDMETHOD(SetCurrentPosition)(THIS_ DWORD dwNewPosition) PURE; - STDMETHOD(SetFormat)(THIS_ LPCWAVEFORMATEX lpcfxFormat) PURE; - STDMETHOD(SetVolume)(THIS_ LONG lVolume) PURE; - STDMETHOD(SetPan)(THIS_ LONG lPan) PURE; - STDMETHOD(SetFrequency)(THIS_ DWORD dwFrequency) PURE; - STDMETHOD(Stop)(THIS) PURE; - STDMETHOD(Unlock)(THIS_ LPVOID pvAudioPtr1, DWORD dwAudioBytes1, LPVOID pvAudioPtr2, DWORD dwAudioPtr2) PURE; - STDMETHOD(Restore)(THIS) PURE; - STDMETHOD(SetFX)(THIS_ DWORD dwEffectsCount, LPDSEFFECTDESC pDSFXDesc, LPDWORD pdwResultCodes) PURE; - STDMETHOD(AcquireResources)(THIS_ DWORD dwFlags, DWORD dwEffectsCount, LPDWORD pdwResultCodes) PURE; - STDMETHOD(GetObjectInPath)(THIS_ REFGUID rguidObject, DWORD dwIndex, REFGUID rguidInterface, LPVOID *ppObject) PURE; -}; -#undef INTERFACE - -#if !defined(__cplusplus) || defined(CINTERFACE) -/*** IUnknown methods ***/ -#define IDirectSoundBuffer8_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) -#define IDirectSoundBuffer8_AddRef(p) (p)->lpVtbl->AddRef(p) -#define IDirectSoundBuffer8_Release(p) (p)->lpVtbl->Release(p) -/*** IDirectSoundBuffer methods ***/ -#define IDirectSoundBuffer8_GetCaps(p,a) (p)->lpVtbl->GetCaps(p,a) -#define IDirectSoundBuffer8_GetCurrentPosition(p,a,b) (p)->lpVtbl->GetCurrentPosition(p,a,b) -#define IDirectSoundBuffer8_GetFormat(p,a,b,c) (p)->lpVtbl->GetFormat(p,a,b,c) -#define IDirectSoundBuffer8_GetVolume(p,a) (p)->lpVtbl->GetVolume(p,a) -#define IDirectSoundBuffer8_GetPan(p,a) (p)->lpVtbl->GetPan(p,a) -#define IDirectSoundBuffer8_GetFrequency(p,a) (p)->lpVtbl->GetFrequency(p,a) -#define IDirectSoundBuffer8_GetStatus(p,a) (p)->lpVtbl->GetStatus(p,a) -#define IDirectSoundBuffer8_Initialize(p,a,b) (p)->lpVtbl->Initialize(p,a,b) -#define IDirectSoundBuffer8_Lock(p,a,b,c,d,e,f,g) (p)->lpVtbl->Lock(p,a,b,c,d,e,f,g) -#define IDirectSoundBuffer8_Play(p,a,b,c) (p)->lpVtbl->Play(p,a,b,c) -#define IDirectSoundBuffer8_SetCurrentPosition(p,a) (p)->lpVtbl->SetCurrentPosition(p,a) -#define IDirectSoundBuffer8_SetFormat(p,a) (p)->lpVtbl->SetFormat(p,a) -#define IDirectSoundBuffer8_SetVolume(p,a) (p)->lpVtbl->SetVolume(p,a) -#define IDirectSoundBuffer8_SetPan(p,a) (p)->lpVtbl->SetPan(p,a) -#define IDirectSoundBuffer8_SetFrequency(p,a) (p)->lpVtbl->SetFrequency(p,a) -#define IDirectSoundBuffer8_Stop(p) (p)->lpVtbl->Stop(p) -#define IDirectSoundBuffer8_Unlock(p,a,b,c,d) (p)->lpVtbl->Unlock(p,a,b,c,d) -#define IDirectSoundBuffer8_Restore(p) (p)->lpVtbl->Restore(p) -/*** IDirectSoundBuffer8 methods ***/ -#define IDirectSoundBuffer8_SetFX(p,a,b,c) (p)->lpVtbl->SetFX(p,a,b,c) -#define IDirectSoundBuffer8_AcquireResources(p,a,b,c) (p)->lpVtbl->AcquireResources(p,a,b,c) -#define IDirectSoundBuffer8_GetObjectInPath(p,a,b,c,d) (p)->lpVtbl->GetObjectInPath(p,a,b,c,d) -#else -/*** IUnknown methods ***/ -#define IDirectSoundBuffer8_QueryInterface(p,a,b) (p)->QueryInterface(a,b) -#define IDirectSoundBuffer8_AddRef(p) (p)->AddRef() -#define IDirectSoundBuffer8_Release(p) (p)->Release() -/*** IDirectSoundBuffer methods ***/ -#define IDirectSoundBuffer8_GetCaps(p,a) (p)->GetCaps(a) -#define IDirectSoundBuffer8_GetCurrentPosition(p,a,b) (p)->GetCurrentPosition(a,b) -#define IDirectSoundBuffer8_GetFormat(p,a,b,c) (p)->GetFormat(a,b,c) -#define IDirectSoundBuffer8_GetVolume(p,a) (p)->GetVolume(a) -#define IDirectSoundBuffer8_GetPan(p,a) (p)->GetPan(a) -#define IDirectSoundBuffer8_GetFrequency(p,a) (p)->GetFrequency(a) -#define IDirectSoundBuffer8_GetStatus(p,a) (p)->GetStatus(a) -#define IDirectSoundBuffer8_Initialize(p,a,b) (p)->Initialize(a,b) -#define IDirectSoundBuffer8_Lock(p,a,b,c,d,e,f,g) (p)->Lock(a,b,c,d,e,f,g) -#define IDirectSoundBuffer8_Play(p,a,b,c) (p)->Play(a,b,c) -#define IDirectSoundBuffer8_SetCurrentPosition(p,a) (p)->SetCurrentPosition(a) -#define IDirectSoundBuffer8_SetFormat(p,a) (p)->SetFormat(a) -#define IDirectSoundBuffer8_SetVolume(p,a) (p)->SetVolume(a) -#define IDirectSoundBuffer8_SetPan(p,a) (p)->SetPan(a) -#define IDirectSoundBuffer8_SetFrequency(p,a) (p)->SetFrequency(a) -#define IDirectSoundBuffer8_Stop(p) (p)->Stop() -#define IDirectSoundBuffer8_Unlock(p,a,b,c,d) (p)->Unlock(a,b,c,d) -#define IDirectSoundBuffer8_Restore(p) (p)->Restore() -/*** IDirectSoundBuffer8 methods ***/ -#define IDirectSoundBuffer8_SetFX(p,a,b,c) (p)->SetFX(a,b,c) -#define IDirectSoundBuffer8_AcquireResources(p,a,b,c) (p)->AcquireResources(a,b,c) -#define IDirectSoundBuffer8_GetObjectInPath(p,a,b,c,d) (p)->GetObjectInPath(a,b,c,d) -#endif - - -/***************************************************************************** - * IDirectSoundCapture interface - */ -#define INTERFACE IDirectSoundCapture -DECLARE_INTERFACE_(IDirectSoundCapture,IUnknown) -{ - /*** IUnknown methods ***/ - STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; - STDMETHOD_(ULONG,AddRef)(THIS) PURE; - STDMETHOD_(ULONG,Release)(THIS) PURE; - /*** IDirectSoundCapture methods ***/ - STDMETHOD(CreateCaptureBuffer)(THIS_ LPCDSCBUFFERDESC lpcDSCBufferDesc,LPDIRECTSOUNDCAPTUREBUFFER *lplpDSCaptureBuffer, LPUNKNOWN pUnk) PURE; - STDMETHOD(GetCaps)(THIS_ LPDSCCAPS lpDSCCaps) PURE; - STDMETHOD(Initialize)(THIS_ LPCGUID lpcGUID) PURE; -}; -#undef INTERFACE - -#if !defined(__cplusplus) || defined(CINTERFACE) -/*** IUnknown methods ***/ -#define IDirectSoundCapture_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) -#define IDirectSoundCapture_AddRef(p) (p)->lpVtbl->AddRef(p) -#define IDirectSoundCapture_Release(p) (p)->lpVtbl->Release(p) -/*** IDirectSoundCapture methods ***/ -#define IDirectSoundCapture_CreateCaptureBuffer(p,a,b,c) (p)->lpVtbl->CreateCaptureBuffer(p,a,b,c) -#define IDirectSoundCapture_GetCaps(p,a) (p)->lpVtbl->GetCaps(p,a) -#define IDirectSoundCapture_Initialize(p,a) (p)->lpVtbl->Initialize(p,a) -#else -/*** IUnknown methods ***/ -#define IDirectSoundCapture_QueryInterface(p,a,b) (p)->QueryInterface(a,b) -#define IDirectSoundCapture_AddRef(p) (p)->AddRef() -#define IDirectSoundCapture_Release(p) (p)->Release() -/*** IDirectSoundCapture methods ***/ -#define IDirectSoundCapture_CreateCaptureBuffer(p,a,b,c) (p)->CreateCaptureBuffer(a,b,c) -#define IDirectSoundCapture_GetCaps(p,a) (p)->GetCaps(a) -#define IDirectSoundCapture_Initialize(p,a) (p)->Initialize(a) -#endif - -/***************************************************************************** - * IDirectSoundCaptureBuffer interface - */ -#define INTERFACE IDirectSoundCaptureBuffer -DECLARE_INTERFACE_(IDirectSoundCaptureBuffer,IUnknown) -{ - /*** IUnknown methods ***/ - STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; - STDMETHOD_(ULONG,AddRef)(THIS) PURE; - STDMETHOD_(ULONG,Release)(THIS) PURE; - /*** IDirectSoundCaptureBuffer methods ***/ - STDMETHOD(GetCaps)(THIS_ LPDSCBCAPS lpDSCBCaps) PURE; - STDMETHOD(GetCurrentPosition)(THIS_ LPDWORD lpdwCapturePosition,LPDWORD lpdwReadPosition) PURE; - STDMETHOD(GetFormat)(THIS_ LPWAVEFORMATEX lpwfxFormat, DWORD dwSizeAllocated, LPDWORD lpdwSizeWritten) PURE; - STDMETHOD(GetStatus)(THIS_ LPDWORD lpdwStatus) PURE; - STDMETHOD(Initialize)(THIS_ LPDIRECTSOUNDCAPTURE lpDSC, LPCDSCBUFFERDESC lpcDSCBDesc) PURE; - STDMETHOD(Lock)(THIS_ DWORD dwReadCusor, DWORD dwReadBytes, LPVOID *lplpvAudioPtr1, LPDWORD lpdwAudioBytes1, LPVOID *lplpvAudioPtr2, LPDWORD lpdwAudioBytes2, DWORD dwFlags) PURE; - STDMETHOD(Start)(THIS_ DWORD dwFlags) PURE; - STDMETHOD(Stop)(THIS) PURE; - STDMETHOD(Unlock)(THIS_ LPVOID lpvAudioPtr1, DWORD dwAudioBytes1, LPVOID lpvAudioPtr2, DWORD dwAudioBytes2) PURE; -}; -#undef INTERFACE - -#if !defined(__cplusplus) || defined(CINTERFACE) -/*** IUnknown methods ***/ -#define IDirectSoundCaptureBuffer_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) -#define IDirectSoundCaptureBuffer_AddRef(p) (p)->lpVtbl->AddRef(p) -#define IDirectSoundCaptureBuffer_Release(p) (p)->lpVtbl->Release(p) -/*** IDirectSoundCaptureBuffer methods ***/ -#define IDirectSoundCaptureBuffer_GetCaps(p,a) (p)->lpVtbl->GetCaps(p,a) -#define IDirectSoundCaptureBuffer_GetCurrentPosition(p,a,b) (p)->lpVtbl->GetCurrentPosition(p,a,b) -#define IDirectSoundCaptureBuffer_GetFormat(p,a,b,c) (p)->lpVtbl->GetFormat(p,a,b,c) -#define IDirectSoundCaptureBuffer_GetStatus(p,a) (p)->lpVtbl->GetStatus(p,a) -#define IDirectSoundCaptureBuffer_Initialize(p,a,b) (p)->lpVtbl->Initialize(p,a,b) -#define IDirectSoundCaptureBuffer_Lock(p,a,b,c,d,e,f,g) (p)->lpVtbl->Lock(p,a,b,c,d,e,f,g) -#define IDirectSoundCaptureBuffer_Start(p,a) (p)->lpVtbl->Start(p,a) -#define IDirectSoundCaptureBuffer_Stop(p) (p)->lpVtbl->Stop(p) -#define IDirectSoundCaptureBuffer_Unlock(p,a,b,c,d) (p)->lpVtbl->Unlock(p,a,b,c,d) -#else -/*** IUnknown methods ***/ -#define IDirectSoundCaptureBuffer_QueryInterface(p,a,b) (p)->QueryInterface(a,b) -#define IDirectSoundCaptureBuffer_AddRef(p) (p)->AddRef() -#define IDirectSoundCaptureBuffer_Release(p) (p)->Release() -/*** IDirectSoundCaptureBuffer methods ***/ -#define IDirectSoundCaptureBuffer_GetCaps(p,a) (p)->GetCaps(a) -#define IDirectSoundCaptureBuffer_GetCurrentPosition(p,a,b) (p)->GetCurrentPosition(a,b) -#define IDirectSoundCaptureBuffer_GetFormat(p,a,b,c) (p)->GetFormat(a,b,c) -#define IDirectSoundCaptureBuffer_GetStatus(p,a) (p)->GetStatus(a) -#define IDirectSoundCaptureBuffer_Initialize(p,a,b) (p)->Initialize(a,b) -#define IDirectSoundCaptureBuffer_Lock(p,a,b,c,d,e,f,g) (p)->Lock(a,b,c,d,e,f,g) -#define IDirectSoundCaptureBuffer_Start(p,a) (p)->Start(a) -#define IDirectSoundCaptureBuffer_Stop(p) (p)->Stop() -#define IDirectSoundCaptureBuffer_Unlock(p,a,b,c,d) (p)->Unlock(a,b,c,d) -#endif - -/***************************************************************************** - * IDirectSoundCaptureBuffer8 interface - */ -#define INTERFACE IDirectSoundCaptureBuffer8 -DECLARE_INTERFACE_(IDirectSoundCaptureBuffer8,IDirectSoundCaptureBuffer) -{ - /*** IUnknown methods ***/ - STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; - STDMETHOD_(ULONG,AddRef)(THIS) PURE; - STDMETHOD_(ULONG,Release)(THIS) PURE; - /*** IDirectSoundCaptureBuffer methods ***/ - STDMETHOD(GetCaps)(THIS_ LPDSCBCAPS lpDSCBCaps) PURE; - STDMETHOD(GetCurrentPosition)(THIS_ LPDWORD lpdwCapturePosition,LPDWORD lpdwReadPosition) PURE; - STDMETHOD(GetFormat)(THIS_ LPWAVEFORMATEX lpwfxFormat, DWORD dwSizeAllocated, LPDWORD lpdwSizeWritten) PURE; - STDMETHOD(GetStatus)(THIS_ LPDWORD lpdwStatus) PURE; - STDMETHOD(Initialize)(THIS_ LPDIRECTSOUNDCAPTURE lpDSC, LPCDSCBUFFERDESC lpcDSCBDesc) PURE; - STDMETHOD(Lock)(THIS_ DWORD dwReadCusor, DWORD dwReadBytes, LPVOID *lplpvAudioPtr1, LPDWORD lpdwAudioBytes1, LPVOID *lplpvAudioPtr2, LPDWORD lpdwAudioBytes2, DWORD dwFlags) PURE; - STDMETHOD(Start)(THIS_ DWORD dwFlags) PURE; - STDMETHOD(Stop)(THIS) PURE; - STDMETHOD(Unlock)(THIS_ LPVOID lpvAudioPtr1, DWORD dwAudioBytes1, LPVOID lpvAudioPtr2, DWORD dwAudioBytes2) PURE; - /*** IDirectSoundCaptureBuffer8 methods ***/ - STDMETHOD(GetObjectInPath)(THIS_ REFGUID rguidObject, DWORD dwIndex, REFGUID rguidInterface, LPVOID *ppObject) PURE; - STDMETHOD(GetFXStatus)(THIS_ DWORD dwFXCount, LPDWORD pdwFXStatus) PURE; -}; -#undef INTERFACE - -#if !defined(__cplusplus) || defined(CINTERFACE) -/*** IUnknown methods ***/ -#define IDirectSoundCaptureBuffer8_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) -#define IDirectSoundCaptureBuffer8_AddRef(p) (p)->lpVtbl->AddRef(p) -#define IDirectSoundCaptureBuffer8_Release(p) (p)->lpVtbl->Release(p) -/*** IDirectSoundCaptureBuffer methods ***/ -#define IDirectSoundCaptureBuffer8_GetCaps(p,a) (p)->lpVtbl->GetCaps(p,a) -#define IDirectSoundCaptureBuffer8_GetCurrentPosition(p,a,b) (p)->lpVtbl->GetCurrentPosition(p,a,b) -#define IDirectSoundCaptureBuffer8_GetFormat(p,a,b,c) (p)->lpVtbl->GetFormat(p,a,b,c) -#define IDirectSoundCaptureBuffer8_GetStatus(p,a) (p)->lpVtbl->GetStatus(p,a) -#define IDirectSoundCaptureBuffer8_Initialize(p,a,b) (p)->lpVtbl->Initialize(p,a,b) -#define IDirectSoundCaptureBuffer8_Lock(p,a,b,c,d,e,f,g) (p)->lpVtbl->Lock(p,a,b,c,d,e,f,g) -#define IDirectSoundCaptureBuffer8_Start(p,a) (p)->lpVtbl->Start(p,a) -#define IDirectSoundCaptureBuffer8_Stop(p) (p)->lpVtbl->Stop(p) -#define IDirectSoundCaptureBuffer8_Unlock(p,a,b,c,d) (p)->lpVtbl->Unlock(p,a,b,c,d) -/*** IDirectSoundCaptureBuffer8 methods ***/ -#define IDirectSoundCaptureBuffer8_GetObjectInPath(p,a,b,c,d) (p)->lpVtbl->GetObjectInPath(p,a,b,c,d) -#define IDirectSoundCaptureBuffer8_GetFXStatus(p,a,b) (p)->lpVtbl->GetFXStatus(p,a,b) -#else -/*** IUnknown methods ***/ -#define IDirectSoundCaptureBuffer8_QueryInterface(p,a,b) (p)->QueryInterface(a,b) -#define IDirectSoundCaptureBuffer8_AddRef(p) (p)->AddRef() -#define IDirectSoundCaptureBuffer8_Release(p) (p)->Release() -/*** IDirectSoundCaptureBuffer methods ***/ -#define IDirectSoundCaptureBuffer8_GetCaps(p,a) (p)->GetCaps(a) -#define IDirectSoundCaptureBuffer8_GetCurrentPosition(p,a,b) (p)->GetCurrentPosition(a,b) -#define IDirectSoundCaptureBuffer8_GetFormat(p,a,b,c) (p)->GetFormat(a,b,c) -#define IDirectSoundCaptureBuffer8_GetStatus(p,a) (p)->GetStatus(a) -#define IDirectSoundCaptureBuffer8_Initialize(p,a,b) (p)->Initialize(a,b) -#define IDirectSoundCaptureBuffer8_Lock(p,a,b,c,d,e,f,g) (p)->Lock(a,b,c,d,e,f,g) -#define IDirectSoundCaptureBuffer8_Start(p,a) (p)->Start(a) -#define IDirectSoundCaptureBuffer8_Stop(p) (p)->Stop() -#define IDirectSoundCaptureBuffer8_Unlock(p,a,b,c,d) (p)->Unlock(a,b,c,d) -/*** IDirectSoundCaptureBuffer8 methods ***/ -#define IDirectSoundCaptureBuffer8_GetObjectInPath(p,a,b,c,d) (p)->GetObjectInPath(a,b,c,d) -#define IDirectSoundCaptureBuffer8_GetFXStatus(p,a,b) (p)->GetFXStatus(a,b) -#endif - -/***************************************************************************** - * IDirectSoundNotify interface - */ -#define WINE_NOBUFFER 0x80000000 - -#define DSBPN_OFFSETSTOP -1 - -#define INTERFACE IDirectSoundNotify -DECLARE_INTERFACE_(IDirectSoundNotify,IUnknown) -{ - /*** IUnknown methods ***/ - STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; - STDMETHOD_(ULONG,AddRef)(THIS) PURE; - STDMETHOD_(ULONG,Release)(THIS) PURE; - /*** IDirectSoundNotify methods ***/ - STDMETHOD(SetNotificationPositions)(THIS_ DWORD cPositionNotifies, LPCDSBPOSITIONNOTIFY lpcPositionNotifies) PURE; -}; -#undef INTERFACE - -#if !defined(__cplusplus) || defined(CINTERFACE) -/*** IUnknown methods ***/ -#define IDirectSoundNotify_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) -#define IDirectSoundNotify_AddRef(p) (p)->lpVtbl->AddRef(p) -#define IDirectSoundNotify_Release(p) (p)->lpVtbl->Release(p) -/*** IDirectSoundNotify methods ***/ -#define IDirectSoundNotify_SetNotificationPositions(p,a,b) (p)->lpVtbl->SetNotificationPositions(p,a,b) -#else -/*** IUnknown methods ***/ -#define IDirectSoundNotify_QueryInterface(p,a,b) (p)->QueryInterface(a,b) -#define IDirectSoundNotify_AddRef(p) (p)->AddRef() -#define IDirectSoundNotify_Release(p) (p)->Release() -/*** IDirectSoundNotify methods ***/ -#define IDirectSoundNotify_SetNotificationPositions(p,a,b) (p)->SetNotificationPositions(a,b) -#endif - - -/***************************************************************************** - * IDirectSound3DListener interface - */ -#define DS3DMODE_NORMAL 0x00000000 -#define DS3DMODE_HEADRELATIVE 0x00000001 -#define DS3DMODE_DISABLE 0x00000002 - -#define DS3D_IMMEDIATE 0x00000000 -#define DS3D_DEFERRED 0x00000001 - -#define DS3D_MINDISTANCEFACTOR FLT_MIN -#define DS3D_MAXDISTANCEFACTOR FLT_MAX -#define DS3D_DEFAULTDISTANCEFACTOR 1.0f - -#define DS3D_MINROLLOFFFACTOR 0.0f -#define DS3D_MAXROLLOFFFACTOR 10.0f -#define DS3D_DEFAULTROLLOFFFACTOR 1.0f - -#define DS3D_MINDOPPLERFACTOR 0.0f -#define DS3D_MAXDOPPLERFACTOR 10.0f -#define DS3D_DEFAULTDOPPLERFACTOR 1.0f - -#define DS3D_DEFAULTMINDISTANCE 1.0f -#define DS3D_DEFAULTMAXDISTANCE 1000000000.0f - -#define DS3D_MINCONEANGLE 0 -#define DS3D_MAXCONEANGLE 360 -#define DS3D_DEFAULTCONEANGLE 360 - -#define DS3D_DEFAULTCONEOUTSIDEVOLUME DSBVOLUME_MAX - -typedef struct _DS3DLISTENER { - DWORD dwSize; - D3DVECTOR vPosition; - D3DVECTOR vVelocity; - D3DVECTOR vOrientFront; - D3DVECTOR vOrientTop; - D3DVALUE flDistanceFactor; - D3DVALUE flRolloffFactor; - D3DVALUE flDopplerFactor; -} DS3DLISTENER, *LPDS3DLISTENER; - -typedef const DS3DLISTENER *LPCDS3DLISTENER; - -#define INTERFACE IDirectSound3DListener -DECLARE_INTERFACE_(IDirectSound3DListener,IUnknown) -{ - /*** IUnknown methods ***/ - STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; - STDMETHOD_(ULONG,AddRef)(THIS) PURE; - STDMETHOD_(ULONG,Release)(THIS) PURE; - /*** IDirectSound3DListener methods ***/ - STDMETHOD(GetAllParameters)(THIS_ LPDS3DLISTENER lpListener) PURE; - STDMETHOD(GetDistanceFactor)(THIS_ LPD3DVALUE lpflDistanceFactor) PURE; - STDMETHOD(GetDopplerFactor)(THIS_ LPD3DVALUE lpflDopplerFactor) PURE; - STDMETHOD(GetOrientation)(THIS_ LPD3DVECTOR lpvOrientFront, LPD3DVECTOR lpvOrientTop) PURE; - STDMETHOD(GetPosition)(THIS_ LPD3DVECTOR lpvPosition) PURE; - STDMETHOD(GetRolloffFactor)(THIS_ LPD3DVALUE lpflRolloffFactor) PURE; - STDMETHOD(GetVelocity)(THIS_ LPD3DVECTOR lpvVelocity) PURE; - STDMETHOD(SetAllParameters)(THIS_ LPCDS3DLISTENER lpcListener, DWORD dwApply) PURE; - STDMETHOD(SetDistanceFactor)(THIS_ D3DVALUE flDistanceFactor, DWORD dwApply) PURE; - STDMETHOD(SetDopplerFactor)(THIS_ D3DVALUE flDopplerFactor, DWORD dwApply) PURE; - STDMETHOD(SetOrientation)(THIS_ D3DVALUE xFront, D3DVALUE yFront, D3DVALUE zFront, D3DVALUE xTop, D3DVALUE yTop, D3DVALUE zTop, DWORD dwApply) PURE; - STDMETHOD(SetPosition)(THIS_ D3DVALUE x, D3DVALUE y, D3DVALUE z, DWORD dwApply) PURE; - STDMETHOD(SetRolloffFactor)(THIS_ D3DVALUE flRolloffFactor, DWORD dwApply) PURE; - STDMETHOD(SetVelocity)(THIS_ D3DVALUE x, D3DVALUE y, D3DVALUE z, DWORD dwApply) PURE; - STDMETHOD(CommitDeferredSettings)(THIS) PURE; -}; -#undef INTERFACE - -#if !defined(__cplusplus) || defined(CINTERFACE) -/*** IUnknown methods ***/ -#define IDirectSound3DListener_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) -#define IDirectSound3DListener_AddRef(p) (p)->lpVtbl->AddRef(p) -#define IDirectSound3DListener_Release(p) (p)->lpVtbl->Release(p) -/*** IDirectSound3DListener methods ***/ -#define IDirectSound3DListener_GetAllParameters(p,a) (p)->lpVtbl->GetAllParameters(p,a) -#define IDirectSound3DListener_GetDistanceFactor(p,a) (p)->lpVtbl->GetDistanceFactor(p,a) -#define IDirectSound3DListener_GetDopplerFactor(p,a) (p)->lpVtbl->GetDopplerFactor(p,a) -#define IDirectSound3DListener_GetOrientation(p,a,b) (p)->lpVtbl->GetOrientation(p,a,b) -#define IDirectSound3DListener_GetPosition(p,a) (p)->lpVtbl->GetPosition(p,a) -#define IDirectSound3DListener_GetRolloffFactor(p,a) (p)->lpVtbl->GetRolloffFactor(p,a) -#define IDirectSound3DListener_GetVelocity(p,a) (p)->lpVtbl->GetVelocity(p,a) -#define IDirectSound3DListener_SetAllParameters(p,a,b) (p)->lpVtbl->SetAllParameters(p,a,b) -#define IDirectSound3DListener_SetDistanceFactor(p,a,b) (p)->lpVtbl->SetDistanceFactor(p,a,b) -#define IDirectSound3DListener_SetDopplerFactor(p,a,b) (p)->lpVtbl->SetDopplerFactor(p,a,b) -#define IDirectSound3DListener_SetOrientation(p,a,b,c,d,e,f,g) (p)->lpVtbl->SetOrientation(p,a,b,c,d,e,f,g) -#define IDirectSound3DListener_SetPosition(p,a,b,c,d) (p)->lpVtbl->SetPosition(p,a,b,c,d) -#define IDirectSound3DListener_SetRolloffFactor(p,a,b) (p)->lpVtbl->SetRolloffFactor(p,a,b) -#define IDirectSound3DListener_SetVelocity(p,a,b,c,d) (p)->lpVtbl->SetVelocity(p,a,b,c,d) -#define IDirectSound3DListener_CommitDeferredSettings(p) (p)->lpVtbl->CommitDeferredSettings(p) -#else -/*** IUnknown methods ***/ -#define IDirectSound3DListener_QueryInterface(p,a,b) (p)->QueryInterface(a,b) -#define IDirectSound3DListener_AddRef(p) (p)->AddRef() -#define IDirectSound3DListener_Release(p) (p)->Release() -/*** IDirectSound3DListener methods ***/ -#define IDirectSound3DListener_GetAllParameters(p,a) (p)->GetAllParameters(a) -#define IDirectSound3DListener_GetDistanceFactor(p,a) (p)->GetDistanceFactor(a) -#define IDirectSound3DListener_GetDopplerFactor(p,a) (p)->GetDopplerFactor(a) -#define IDirectSound3DListener_GetOrientation(p,a,b) (p)->GetOrientation(a,b) -#define IDirectSound3DListener_GetPosition(p,a) (p)->GetPosition(a) -#define IDirectSound3DListener_GetRolloffFactor(p,a) (p)->GetRolloffFactor(a) -#define IDirectSound3DListener_GetVelocity(p,a) (p)->GetVelocity(a) -#define IDirectSound3DListener_SetAllParameters(p,a,b) (p)->SetAllParameters(a,b) -#define IDirectSound3DListener_SetDistanceFactor(p,a,b) (p)->SetDistanceFactor(a,b) -#define IDirectSound3DListener_SetDopplerFactor(p,a,b) (p)->SetDopplerFactor(a,b) -#define IDirectSound3DListener_SetOrientation(p,a,b,c,d,e,f,g) (p)->SetOrientation(a,b,c,d,e,f,g) -#define IDirectSound3DListener_SetPosition(p,a,b,c,d) (p)->SetPosition(a,b,c,d) -#define IDirectSound3DListener_SetRolloffFactor(p,a,b) (p)->SetRolloffFactor(a,b) -#define IDirectSound3DListener_SetVelocity(p,a,b,c,d) (p)->SetVelocity(a,b,c,d) -#define IDirectSound3DListener_CommitDeferredSettings(p) (p)->CommitDeferredSettings() -#endif - - -/***************************************************************************** - * IDirectSound3DBuffer interface - */ -typedef struct _DS3DBUFFER { - DWORD dwSize; - D3DVECTOR vPosition; - D3DVECTOR vVelocity; - DWORD dwInsideConeAngle; - DWORD dwOutsideConeAngle; - D3DVECTOR vConeOrientation; - LONG lConeOutsideVolume; - D3DVALUE flMinDistance; - D3DVALUE flMaxDistance; - DWORD dwMode; -} DS3DBUFFER, *LPDS3DBUFFER; - -typedef const DS3DBUFFER *LPCDS3DBUFFER; - -#define INTERFACE IDirectSound3DBuffer -DECLARE_INTERFACE_(IDirectSound3DBuffer,IUnknown) -{ - /*** IUnknown methods ***/ - STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; - STDMETHOD_(ULONG,AddRef)(THIS) PURE; - STDMETHOD_(ULONG,Release)(THIS) PURE; - /*** IDirectSound3DBuffer methods ***/ - STDMETHOD(GetAllParameters)(THIS_ LPDS3DBUFFER lpDs3dBuffer) PURE; - STDMETHOD(GetConeAngles)(THIS_ LPDWORD lpdwInsideConeAngle, LPDWORD lpdwOutsideConeAngle) PURE; - STDMETHOD(GetConeOrientation)(THIS_ LPD3DVECTOR lpvOrientation) PURE; - STDMETHOD(GetConeOutsideVolume)(THIS_ LPLONG lplConeOutsideVolume) PURE; - STDMETHOD(GetMaxDistance)(THIS_ LPD3DVALUE lpflMaxDistance) PURE; - STDMETHOD(GetMinDistance)(THIS_ LPD3DVALUE lpflMinDistance) PURE; - STDMETHOD(GetMode)(THIS_ LPDWORD lpwdMode) PURE; - STDMETHOD(GetPosition)(THIS_ LPD3DVECTOR lpvPosition) PURE; - STDMETHOD(GetVelocity)(THIS_ LPD3DVECTOR lpvVelocity) PURE; - STDMETHOD(SetAllParameters)(THIS_ LPCDS3DBUFFER lpcDs3dBuffer, DWORD dwApply) PURE; - STDMETHOD(SetConeAngles)(THIS_ DWORD dwInsideConeAngle, DWORD dwOutsideConeAngle, DWORD dwApply) PURE; - STDMETHOD(SetConeOrientation)(THIS_ D3DVALUE x, D3DVALUE y, D3DVALUE z, DWORD dwApply) PURE; - STDMETHOD(SetConeOutsideVolume)(THIS_ LONG lConeOutsideVolume, DWORD dwApply) PURE; - STDMETHOD(SetMaxDistance)(THIS_ D3DVALUE flMaxDistance, DWORD dwApply) PURE; - STDMETHOD(SetMinDistance)(THIS_ D3DVALUE flMinDistance, DWORD dwApply) PURE; - STDMETHOD(SetMode)(THIS_ DWORD dwMode, DWORD dwApply) PURE; - STDMETHOD(SetPosition)(THIS_ D3DVALUE x, D3DVALUE y, D3DVALUE z, DWORD dwApply) PURE; - STDMETHOD(SetVelocity)(THIS_ D3DVALUE x, D3DVALUE y, D3DVALUE z, DWORD dwApply) PURE; -}; -#undef INTERFACE - -#if !defined(__cplusplus) || defined(CINTERFACE) -/*** IUnknown methods ***/ -#define IDirectSound3DBuffer_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) -#define IDirectSound3DBuffer_AddRef(p) (p)->lpVtbl->AddRef(p) -#define IDirectSound3DBuffer_Release(p) (p)->lpVtbl->Release(p) -/*** IDirectSound3DBuffer methods ***/ -#define IDirectSound3DBuffer_GetAllParameters(p,a) (p)->lpVtbl->GetAllParameters(p,a) -#define IDirectSound3DBuffer_GetConeAngles(p,a,b) (p)->lpVtbl->GetConeAngles(p,a,b) -#define IDirectSound3DBuffer_GetConeOrientation(p,a) (p)->lpVtbl->GetConeOrientation(p,a) -#define IDirectSound3DBuffer_GetConeOutsideVolume(p,a) (p)->lpVtbl->GetConeOutsideVolume(p,a) -#define IDirectSound3DBuffer_GetMaxDistance(p,a) (p)->lpVtbl->GetMaxDistance(p,a) -#define IDirectSound3DBuffer_GetMinDistance(p,a) (p)->lpVtbl->GetMinDistance(p,a) -#define IDirectSound3DBuffer_GetMode(p,a) (p)->lpVtbl->GetMode(p,a) -#define IDirectSound3DBuffer_GetPosition(p,a) (p)->lpVtbl->GetPosition(p,a) -#define IDirectSound3DBuffer_GetVelocity(p,a) (p)->lpVtbl->GetVelocity(p,a) -#define IDirectSound3DBuffer_SetAllParameters(p,a,b) (p)->lpVtbl->SetAllParameters(p,a,b) -#define IDirectSound3DBuffer_SetConeAngles(p,a,b,c) (p)->lpVtbl->SetConeAngles(p,a,b,c) -#define IDirectSound3DBuffer_SetConeOrientation(p,a,b,c,d) (p)->lpVtbl->SetConeOrientation(p,a,b,c,d) -#define IDirectSound3DBuffer_SetConeOutsideVolume(p,a,b) (p)->lpVtbl->SetConeOutsideVolume(p,a,b) -#define IDirectSound3DBuffer_SetMaxDistance(p,a,b) (p)->lpVtbl->SetMaxDistance(p,a,b) -#define IDirectSound3DBuffer_SetMinDistance(p,a,b) (p)->lpVtbl->SetMinDistance(p,a,b) -#define IDirectSound3DBuffer_SetMode(p,a,b) (p)->lpVtbl->SetMode(p,a,b) -#define IDirectSound3DBuffer_SetPosition(p,a,b,c,d) (p)->lpVtbl->SetPosition(p,a,b,c,d) -#define IDirectSound3DBuffer_SetVelocity(p,a,b,c,d) (p)->lpVtbl->SetVelocity(p,a,b,c,d) -#else -/*** IUnknown methods ***/ -#define IDirectSound3DBuffer_QueryInterface(p,a,b) (p)->QueryInterface(a,b) -#define IDirectSound3DBuffer_AddRef(p) (p)->AddRef() -#define IDirectSound3DBuffer_Release(p) (p)->Release() -/*** IDirectSound3DBuffer methods ***/ -#define IDirectSound3DBuffer_GetAllParameters(p,a) (p)->GetAllParameters(a) -#define IDirectSound3DBuffer_GetConeAngles(p,a,b) (p)->GetConeAngles(a,b) -#define IDirectSound3DBuffer_GetConeOrientation(p,a) (p)->GetConeOrientation(a) -#define IDirectSound3DBuffer_GetConeOutsideVolume(p,a) (p)->GetConeOutsideVolume(a) -#define IDirectSound3DBuffer_GetMaxDistance(p,a) (p)->GetMaxDistance(a) -#define IDirectSound3DBuffer_GetMinDistance(p,a) (p)->GetMinDistance(a) -#define IDirectSound3DBuffer_GetMode(p,a) (p)->GetMode(a) -#define IDirectSound3DBuffer_GetPosition(p,a) (p)->GetPosition(a) -#define IDirectSound3DBuffer_GetVelocity(p,a) (p)->GetVelocity(a) -#define IDirectSound3DBuffer_SetAllParameters(p,a,b) (p)->SetAllParameters(a,b) -#define IDirectSound3DBuffer_SetConeAngles(p,a,b,c) (p)->SetConeAngles(a,b,c) -#define IDirectSound3DBuffer_SetConeOrientation(p,a,b,c,d) (p)->SetConeOrientation(a,b,c,d) -#define IDirectSound3DBuffer_SetConeOutsideVolume(p,a,b) (p)->SetConeOutsideVolume(a,b) -#define IDirectSound3DBuffer_SetMaxDistance(p,a,b) (p)->SetMaxDistance(a,b) -#define IDirectSound3DBuffer_SetMinDistance(p,a,b) (p)->SetMinDistance(a,b) -#define IDirectSound3DBuffer_SetMode(p,a,b) (p)->SetMode(a,b) -#define IDirectSound3DBuffer_SetPosition(p,a,b,c,d) (p)->SetPosition(a,b,c,d) -#define IDirectSound3DBuffer_SetVelocity(p,a,b,c,d) (p)->SetVelocity(a,b,c,d) -#endif - -/***************************************************************************** - * IKsPropertySet interface - */ -#ifndef _IKsPropertySet_ -#define _IKsPropertySet_ - -typedef struct IKsPropertySet *LPKSPROPERTYSET; - -DEFINE_GUID(IID_IKsPropertySet,0x31EFAC30,0x515C,0x11D0,0xA9,0xAA,0x00,0xAA,0x00,0x61,0xBE,0x93); - -#define KSPROPERTY_SUPPORT_GET 1 -#define KSPROPERTY_SUPPORT_SET 2 - -#define INTERFACE IKsPropertySet -DECLARE_INTERFACE_(IKsPropertySet,IUnknown) -{ - /*** IUnknown methods ***/ - STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; - STDMETHOD_(ULONG,AddRef)(THIS) PURE; - STDMETHOD_(ULONG,Release)(THIS) PURE; - /*** IKsPropertySet methods ***/ - STDMETHOD(Get)(THIS_ REFGUID rgid,ULONG x1,LPVOID p1,ULONG x2,LPVOID p2,ULONG x3,ULONG *px4) PURE; - STDMETHOD(Set)(THIS_ REFGUID rgid,ULONG x1,LPVOID p1,ULONG x2,LPVOID p2,ULONG x3) PURE; - STDMETHOD(QuerySupport)(THIS_ REFGUID rgid,ULONG x1,ULONG *px2) PURE; -}; -#undef INTERFACE - -#if !defined(__cplusplus) || defined(CINTERFACE) -/*** IUnknown methods ***/ -#define IKsPropertySet_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) -#define IKsPropertySet_AddRef(p) (p)->lpVtbl->AddRef(p) -#define IKsPropertySet_Release(p) (p)->lpVtbl->Release(p) -/*** IKsPropertySet methods ***/ -#define IKsPropertySet_Get(p,a,b,c,d,e,f,g) (p)->lpVtbl->Get(p,a,b,c,d,e,f,g) -#define IKsPropertySet_Set(p,a,b,c,d,e,f) (p)->lpVtbl->Set(p,a,b,c,d,e,f) -#define IKsPropertySet_QuerySupport(p,a,b,c) (p)->lpVtbl->QuerySupport(p,a,b,c) -#else -/*** IUnknown methods ***/ -#define IKsPropertySet_QueryInterface(p,a,b) (p)->QueryInterface(a,b) -#define IKsPropertySet_AddRef(p) (p)->AddRef() -#define IKsPropertySet_Release(p) (p)->Release() -/*** IKsPropertySet methods ***/ -#define IKsPropertySet_Get(p,a,b,c,d,e,f,g) (p)->Get(a,b,c,d,e,f,g) -#define IKsPropertySet_Set(p,a,b,c,d,e,f) (p)->Set(a,b,c,d,e,f) -#define IKsPropertySet_QuerySupport(p,a,b,c) (p)->QuerySupport(a,b,c) -#endif - -#endif /* _IKsPropertySet_ */ - -/***************************************************************************** - * IDirectSoundFullDuplex interface - */ -#define INTERFACE IDirectSoundFullDuplex -DECLARE_INTERFACE_(IDirectSoundFullDuplex,IUnknown) -{ - /*** IUnknown methods ***/ - STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; - STDMETHOD_(ULONG,AddRef)(THIS) PURE; - STDMETHOD_(ULONG,Release)(THIS) PURE; - /*** IDirectSoundFullDuplex methods ***/ - STDMETHOD(Initialize)(THIS_ LPCGUID pCaptureGuid,LPCGUID pRendererGuid,LPCDSCBUFFERDESC lpDscBufferDesc,LPCDSBUFFERDESC lpDsBufferDesc,HWND hWnd,DWORD dwLevel,LPLPDIRECTSOUNDCAPTUREBUFFER8 lplpDirectSoundCaptureBuffer8,LPLPDIRECTSOUNDBUFFER8 lplpDirectSoundBuffer8) PURE; -}; -#undef INTERFACE - -#if !defined(__cplusplus) || defined(CINTERFACE) -/*** IUnknown methods ***/ -#define IDirectSoundFullDuplex_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) -#define IDirectSoundFullDuplex_AddRef(p) (p)->lpVtbl->AddRef(p) -#define IDirectSoundFullDuplex_Release(p) (p)->lpVtbl->Release(p) -/*** IDirectSoundFullDuplex methods ***/ -#define IDirectSoundFullDuplex_Initialize(p,a,b,c,d,e,f,g,h) (p)->lpVtbl->Initialize(p,a,b,c,d,e,f,g,h) -#else -/*** IUnknown methods ***/ -#define IDirectSoundFullDuplex_QueryInterface(p,a,b) (p)->QueryInterface(a,b) -#define IDirectSoundFullDuplex_AddRef(p) (p)->AddRef() -#define IDirectSoundFullDuplex_Release(p) (p)->Release() -/*** IDirectSoundFullDuplex methods ***/ -#define IDirectSoundFullDuplex_Initialize(p,a,b,c,d,e,f,g,h) (p)->Initialize(a,b,c,d,e,f,g,h) -#endif - -#ifdef __cplusplus -} /* extern "C" */ -#endif /* defined(__cplusplus) */ - -#endif /* __DSOUND_INCLUDED__ */ diff --git a/vendor/dshow/dvdmedia.h b/vendor/dshow/dvdmedia.h deleted file mode 100644 index 3dcab4d63..000000000 --- a/vendor/dshow/dvdmedia.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2008 Maarten Lankhorst - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#ifndef __DVDMEDIA_H__ -#define __DVDMEDIA_H__ - -#define AMCONTROL_USED 0x00000001 -#define AMCONTROL_PAD_TO_4x3 0x00000002 -#define AMCONTROL_PAD_TO_16x9 0x00000004 - -enum AM_MPEG2Level { - AM_MPEG2Level_Low = 1, - AM_MPEG2Level_Main, - AM_MPEG2Level_High1440, - AM_MPEG2Level_High -}; -enum AM_MPEG2Profile { - AM_MPEG2Profile_Simple = 1, - AM_MPEG2Profile_Main, - AM_MPEG2Profile_SNRScalable, - AM_MPEG2Profile_SpatiallyScalable, - AM_MPEG2Profile_High -}; -typedef enum { - AM_RATE_ChangeRate = 1, - AM_RATE_FullDataRateMax = 2, - AM_RATE_ReverseDecode = 3, - AM_RATE_DecoderPosition = 4, - AM_RATE_DecoderVersion = 5 -} AM_PROPERTY_DVD_RATE_CHANGE; - -typedef struct tagVIDEOINFOHEADER2 { - RECT rcSource; - RECT rcTarget; - DWORD dwBitRate; - DWORD dwBitErrorRate; - REFERENCE_TIME AvgTimePerFrame; - DWORD dwInterlaceFlags; - DWORD dwCopyProtectFlags; - DWORD dwPictAspectRatioX; - DWORD dwPictAspectRatioY; - union { - DWORD dwControlFlags; - DWORD dwReserved1; - } DUMMYUNIONNAME; - DWORD dwReserved2; - BITMAPINFOHEADER bmiHeader; -} VIDEOINFOHEADER2; - -typedef struct tagMPEG2VIDEOINFO { - VIDEOINFOHEADER2 hdr; - DWORD dwStartTimeCode; - DWORD cbSequenceHeader; - DWORD dwProfile; - DWORD dwLevel; - DWORD dwFlags; - DWORD dwSequenceHeader[1]; -} MPEG2VIDEOINFO; - -#endif /* __DVDMEDIA_H__ */ diff --git a/vendor/dshow/errors.h b/vendor/dshow/errors.h deleted file mode 100644 index 75818991a..000000000 --- a/vendor/dshow/errors.h +++ /dev/null @@ -1,169 +0,0 @@ -#ifndef _ERRORS_H -#define _ERRORS_H -#if __GNUC__ >=3 -#pragma GCC system_header -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/*--- DirectShow Reference - Constants and GUIDs - Error and Success Codes */ -#define VFW_S_NO_MORE_ITEMS 0x00040103 -#define VFW_S_DUPLICATE_NAME 0x0004022D -#define VFW_S_STATE_INTERMEDIATE 0x00040237 -#define VFW_S_PARTIAL_RENDER 0x00040242 -#define VFW_S_SOME_DATA_IGNORED 0x00040245 -#define VFW_S_CONNECTIONS_DEFERRED 0x00040246 -#define VFW_S_RESOURCE_NOT_NEEDED 0x00040250 -#define VFW_S_MEDIA_TYPE_IGNORED 0x00040254 -#define VFW_S_VIDEO_NOT_RENDERED 0x00040257 -#define VFW_S_AUDIO_NOT_RENDERED 0x00040258 -#define VFW_S_RPZA 0x0004025A -#define VFW_S_ESTIMATED 0x00040260 -#define VFW_S_RESERVED 0x00040263 -#define VFW_S_STREAM_OFF 0x00040267 -#define VFW_S_CANT_CUE 0x00040268 -#define VFW_S_NOPREVIEWPIN 0x0004027E -#define VFW_S_DVD_NON_ONE_SEQUENTIAL 0x00040280 -#define VFW_S_DVD_CHANNEL_CONTENTS_NOT_AVAILABLE 0x0004028C -#define VFW_S_DVD_NOT_ACCURATE 0x0004028D -#define VFW_E_INVALIDMEDIATYPE 0x80040200 -#define VFW_E_INVALIDSUBTYPE 0x80040201 -#define VFW_E_NEED_OWNER 0x80040202 -#define VFW_E_ENUM_OUT_OF_SYNC 0x80040203 -#define VFW_E_ALREADY_CONNECTED 0x80040204 -#define VFW_E_FILTER_ACTIVE 0x80040205 -#define VFW_E_NO_TYPES 0x80040206 -#define VFW_E_NO_ACCEPTABLE_TYPES 0x80040207 -#define VFW_E_INVALID_DIRECTION 0x80040208 -#define VFW_E_NOT_CONNECTED 0x80040209 -#define VFW_E_NO_ALLOCATOR 0x8004020A -#define VFW_E_RUNTIME_ERROR 0x8004020B -#define VFW_E_BUFFER_NOTSET 0x8004020C -#define VFW_E_BUFFER_OVERFLOW 0x8004020D -#define VFW_E_BADALIGN 0x8004020E -#define VFW_E_ALREADY_COMMITTED 0x8004020F -#define VFW_E_BUFFERS_OUTSTANDING 0x80040210 -#define VFW_E_NOT_COMMITTED 0x80040211 -#define VFW_E_SIZENOTSET 0x80040212 -#define VFW_E_NO_CLOCK 0x80040213 -#define VFW_E_NO_SINK 0x80040214 -#define VFW_E_NO_INTERFACE 0x80040215 -#define VFW_E_NOT_FOUND 0x80040216 -#define VFW_E_CANNOT_CONNECT 0x80040217 -#define VFW_E_CANNOT_RENDER 0x80040218 -#define VFW_E_CHANGING_FORMAT 0x80040219 -#define VFW_E_NO_COLOR_KEY_SET 0x8004021A -#define VFW_E_NOT_OVERLAY_CONNECTION 0x8004021B -#define VFW_E_NOT_SAMPLE_CONNECTION 0x8004021C -#define VFW_E_PALETTE_SET 0x8004021D -#define VFW_E_COLOR_KEY_SET 0x8004021E -#define VFW_E_NO_COLOR_KEY_FOUND 0x8004021F -#define VFW_E_NO_PALETTE_AVAILABLE 0x80040220 -#define VFW_E_NO_DISPLAY_PALETTE 0x80040221 -#define VFW_E_TOO_MANY_COLORS 0x80040222 -#define VFW_E_STATE_CHANGED 0x80040223 -#define VFW_E_NOT_STOPPED 0x80040224 -#define VFW_E_NOT_PAUSED 0x80040225 -#define VFW_E_NOT_RUNNING 0x80040226 -#define VFW_E_WRONG_STATE 0x80040227 -#define VFW_E_START_TIME_AFTER_END 0x80040228 -#define VFW_E_INVALID_RECT 0x80040229 -#define VFW_E_TYPE_NOT_ACCEPTED 0x8004022A -#define VFW_E_SAMPLE_REJECTED 0x8004022B -#define VFW_E_SAMPLE_REJECTED_EOS 0x8004022C -#define VFW_E_DUPLICATE_NAME 0x8004022D -#define VFW_E_TIMEOUT 0x8004022E -#define VFW_E_INVALID_FILE_FORMAT 0x8004022F -#define VFW_E_ENUM_OUT_OF_RANGE 0x80040230 -#define VFW_E_CIRCULAR_GRAPH 0x80040231 -#define VFW_E_NOT_ALLOWED_TO_SAVE 0x80040232 -#define VFW_E_TIME_ALREADY_PASSED 0x80040233 -#define VFW_E_ALREADY_CANCELLED 0x80040234 -#define VFW_E_CORRUPT_GRAPH_FILE 0x80040235 -#define VFW_E_ADVISE_ALREADY_SET 0x80040236 -#define VFW_E_NO_MODEX_AVAILABLE 0x80040238 -#define VFW_E_NO_ADVISE_SET 0x80040239 -#define VFW_E_NO_FULLSCREEN 0x8004023A -#define VFW_E_IN_FULLSCREEN_MODE 0x8004023B -#define VFW_E_UNKNOWN_FILE_TYPE 0x80040240 -#define VFW_E_CANNOT_LOAD_SOURCE_FILTER 0x80040241 -#define VFW_E_FILE_TOO_SHORT 0x80040243 -#define VFW_E_INVALID_FILE_VERSION 0x80040244 -#define VFW_E_INVALID_CLSID 0x80040247 -#define VFW_E_INVALID_MEDIA_TYPE 0x80040248 -#define VFW_E_SAMPLE_TIME_NOT_SET 0x80040249 -#define VFW_E_MEDIA_TIME_NOT_SET 0x80040251 -#define VFW_E_NO_TIME_FORMAT_SET 0x80040252 -#define VFW_E_MONO_AUDIO_HW 0x80040253 -#define VFW_E_NO_DECOMPRESSOR 0x80040255 -#define VFW_E_NO_AUDIO_HARDWARE 0x80040256 -#define VFW_E_RPZA 0x80040259 -#define VFW_E_PROCESSOR_NOT_SUITABLE 0x8004025B -#define VFW_E_UNSUPPORTED_AUDIO 0x8004025C -#define VFW_E_UNSUPPORTED_VIDEO 0x8004025D -#define VFW_E_MPEG_NOT_CONSTRAINED 0x8004025E -#define VFW_E_NOT_IN_GRAPH 0x8004025F -#define VFW_E_NO_TIME_FORMAT 0x80040261 -#define VFW_E_READ_ONLY 0x80040262 -#define VFW_E_BUFFER_UNDERFLOW 0x80040264 -#define VFW_E_UNSUPPORTED_STREAM 0x80040265 -#define VFW_E_NO_TRANSPORT 0x80040266 -#define VFW_E_BAD_VIDEOCD 0x80040269 -#define VFW_S_NO_STOP_TIME 0x80040270 -#define VFW_E_OUT_OF_VIDEO_MEMORY 0x80040271 -#define VFW_E_VP_NEGOTIATION_FAILED 0x80040272 -#define VFW_E_DDRAW_CAPS_NOT_SUITABLE 0x80040273 -#define VFW_E_NO_VP_HARDWARE 0x80040274 -#define VFW_E_NO_CAPTURE_HARDWARE 0x80040275 -#define VFW_E_DVD_OPERATION_INHIBITED 0x80040276 -#define VFW_E_DVD_INVALIDDOMAIN 0x80040277 -#define VFW_E_DVD_NO_BUTTON 0x80040278 -#define VFW_E_DVD_GRAPHNOTREADY 0x80040279 -#define VFW_E_DVD_RENDERFAIL 0x8004027A -#define VFW_E_DVD_DECNOTENOUGH 0x8004027B -#define VFW_E_DDRAW_VERSION_NOT_SUITABLE 0x8004027C -#define VFW_E_COPYPROT_FAILED 0x8004027D -#define VFW_E_TIME_EXPIRED 0x8004027F -#define VFW_E_DVD_WRONG_SPEED 0x80040281 -#define VFW_E_DVD_MENU_DOES_NOT_EXIST 0x80040282 -#define VFW_E_DVD_CMD_CANCELLED 0x80040283 -#define VFW_E_DVD_STATE_WRONG_VERSION 0x80040284 -#define VFW_E_DVD_STATE_CORRUPT 0x80040285 -#define VFW_E_DVD_STATE_WRONG_DISC 0x80040286 -#define VFW_E_DVD_INCOMPATIBLE_REGION 0x80040287 -#define VFW_E_DVD_NO_ATTRIBUTES 0x80040288 -#define VFW_E_DVD_NO_GOUP_PGC 0x80040289 -#define VFW_E_DVD_LOW_PARENTAL_LEVEL 0x8004028A -#define VFW_E_DVD_NOT_IN_KARAOKE_MODE 0x8004028B -#define VFW_E_FRAME_STEP_UNSUPPORTED 0x8004028E -#define VFW_E_DVD_STREAM_DISABLED 0x8004028F -#define VFW_E_DVD_TITLE_UNKNOWN 0x80040290 -#define VFW_E_DVD_INVALID_DISC 0x80040291 -#define VFW_E_DVD_NO_RESUME_INFORMATION 0x80040292 -#define VFW_E_PIN_ALREADY_BLOCKED_ON_THIS_THREAD 0x80040293 -#define VFW_E_PIN_ALREADY_BLOCKED 0x80040294 -#define VFW_E_CERTIFICATION_FAILURE 0x80040295 -#define VFW_E_VMR_NOT_IN_MIXER_MODE 0x80040296 -#define VFW_E_VMR_NO_AP_SUPPLIED 0x80040297 -#define VFW_E_VMR_NO_DEINTERLACE_HW 0x80040298 -#define VFW_E_VMR_NO_PROCAMP_HW 0x80040299 -#define VFW_E_DVD_VMR9_INCOMPATIBLEDEC 0x8004029A -#define VFW_E_NO_COPP_HW 0x8004029B -#define VFW_E_BAD_KEY 0x800403F2 -/*--- DirectShow Reference - Functions */ -#define MAX_ERROR_TEXT_LEN 160 -/*--- DirectShow Reference - Functions */ -DWORD WINAPI AMGetErrorTextA(HRESULT,CHAR*,DWORD); -DWORD WINAPI AMGetErrorTextW(HRESULT,WCHAR*,DWORD); -#ifdef UNICODE -#define AMGetErrorText AMGetErrorTextW -#else -#define AMGetErrorText AMGetErrorTextA -#endif - -#ifdef __cplusplus -} -#endif -#endif diff --git a/vendor/dshow/evcode.h b/vendor/dshow/evcode.h deleted file mode 100644 index 11426e455..000000000 --- a/vendor/dshow/evcode.h +++ /dev/null @@ -1,68 +0,0 @@ -#ifndef _EVCODE_H -#define _EVCODE_H -#if __GNUC__ >=3 -#pragma GCC system_header -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/*--- DirectShow Reference - Constants and GUIDs - Event Notification Codes */ -#define EC_ACTIVATE 0x0013 -#define EC_BUFFERING_DATA 0x0011 -#define EC_BUILT 0x0300 -#define EC_CLOCK_CHANGED 0x000D -#define EC_CLOCK_UNSET 0x0051 -#define EC_CODECAPI_EVENT 0x0057 -#define EC_COMPLETE 0x0001 -#define EC_DEVICE_LOST 0x001F -#define EC_DISPLAY_CHANGED 0x0016 -#define EC_END_OF_SEGMENT 0x001C -#define EC_ERROR_STILLPLAYING 0x0008 -#define EC_ERRORABORT 0x0003 -#define EC_EXTDEVICE_MODE_CHANGE 0x0031 -#define EC_FULLSCREEN_LOST 0x0012 -#define EC_GRAPH_CHANGED 0x0050 -#define EC_LENGTH_CHANGED 0x001E -#define EC_NEED_RESTART 0x0014 -#define EC_NOTIFY_WINDOW 0x0019 -#define EC_OLE_EVENT 0x0018 -#define EC_OPENING_FILE 0x0010 -#define EC_PALETTE_CHANGED 0x0009 -#define EC_PAUSED 0x000E -#define EC_PREPROCESS_COMPLETE 0x0056 -#define EC_QUALITY_CHANGE 0x000B -#define EC_REPAINT 0x0005 -#define EC_SEGMENT_STARTED 0x001D -#define EC_SHUTTING_DOWN 0x000C -#define EC_SNDDEV_IN_ERROR 0x0200 -#define EC_SNDDEV_OUT_ERROR 0x0201 -#define EC_STARVATION 0x0017 -#define EC_STATE_CHANGE 0x0032 -#define EC_STEP_COMPLETE 0x0024 -#define EC_STREAM_CONTROL_STARTED 0x001B -#define EC_STREAM_CONTROL_STOPPED 0x001A -#define EC_STREAM_ERROR_STILLPLAYING 0x0007 -#define EC_STREAM_ERROR_STOPPED 0x0006 -#define EC_TIMECODE_AVAILABLE 0x0030 -#define EC_UNBUILT 0x0301 -#define EC_USERABORT 0x0002 -#define EC_VIDEO_SIZE_CHANGED 0x000A -#define EC_VMR_RENDERDEVICE_SET 0x0053 -#define EC_VMR_SURFACE_FLIPPED 0x0054 -#define EC_VMR_RECONNECTION_FAILED 0x0055 -#define EC_WINDOW_DESTROYED 0x0015 -#define EC_WMT_EVENT 0x0252 -#define EC_WMT_INDEX_EVENT 0x0251 -#define EC_USER 0x8000 -/*--- DirectShow Reference - DirectShow Structures */ -typedef struct { - HRESULT hrStatus; - void *pData; -} AM_WMT_EVENT_DATA; - -#ifdef __cplusplus -} -#endif -#endif diff --git a/vendor/dshow/ksuuids.h b/vendor/dshow/ksuuids.h deleted file mode 100644 index 2eba88427..000000000 --- a/vendor/dshow/ksuuids.h +++ /dev/null @@ -1,191 +0,0 @@ -/** - * This file has no copyright assigned and is placed in the Public Domain. - * This file is part of the w64 mingw-runtime package. - * No warranty is given; refer to the file DISCLAIMER.PD within this package. - */ - -OUR_GUID_ENTRY(MEDIATYPE_MPEG2_PACK, - 0x36523B13,0x8EE5,0x11d1,0x8C,0xA3,0x00,0x60,0xB0,0x57,0x66,0x4A) - -OUR_GUID_ENTRY(MEDIATYPE_MPEG2_PES, - 0xe06d8020,0xdb46,0x11cf,0xb4,0xd1,0x00,0x80,0x5f,0x6c,0xbb,0xea) - -OUR_GUID_ENTRY(MEDIASUBTYPE_MPEG2_WMDRM_TRANSPORT, - 0x18BEC4EA,0x4676,0x450e,0xB4,0x78,0x0C,0xD8,0x4C,0x54,0xB3,0x27) - -OUR_GUID_ENTRY(MEDIASUBTYPE_MPEG2_VIDEO, - 0xe06d8026,0xdb46,0x11cf,0xb4,0xd1,0x00,0x80,0x5f,0x6c,0xbb,0xea) - -OUR_GUID_ENTRY(FORMAT_MPEG2_VIDEO, - 0xe06d80e3,0xdb46,0x11cf,0xb4,0xd1,0x00,0x80,0x5f,0x6c,0xbb,0xea) - -OUR_GUID_ENTRY(FORMAT_VIDEOINFO2, - 0xf72a76A0L,0xeb0a,0x11d0,0xac,0xe4,0x0,0x0,0xc0,0xcc,0x16,0xba) - -OUR_GUID_ENTRY(MEDIASUBTYPE_MPEG2_PROGRAM, - 0xe06d8022,0xdb46,0x11cf,0xb4,0xd1,0x00,0x80,0x05f,0x6c,0xbb,0xea) - -OUR_GUID_ENTRY(MEDIASUBTYPE_MPEG2_TRANSPORT, - 0xe06d8023,0xdb46,0x11cf,0xb4,0xd1,0x00,0x80,0x05f,0x6c,0xbb,0xea) - -OUR_GUID_ENTRY(MEDIASUBTYPE_MPEG2_AUDIO, - 0xe06d802b,0xdb46,0x11cf,0xb4,0xd1,0x00,0x80,0x05f,0x6c,0xbb,0xea) - -OUR_GUID_ENTRY(MEDIASUBTYPE_DOLBY_AC3, - 0xe06d802c,0xdb46,0x11cf,0xb4,0xd1,0x00,0x80,0x05f,0x6c,0xbb,0xea) - -OUR_GUID_ENTRY(MEDIASUBTYPE_DVD_SUBPICTURE, - 0xe06d802d,0xdb46,0x11cf,0xb4,0xd1,0x00,0x80,0x05f,0x6c,0xbb,0xea) - -OUR_GUID_ENTRY(MEDIASUBTYPE_DVD_LPCM_AUDIO, - 0xe06d8032,0xdb46,0x11cf,0xb4,0xd1,0x00,0x80,0x05f,0x6c,0xbb,0xea) - -OUR_GUID_ENTRY(MEDIATYPE_DVD_ENCRYPTED_PACK, - 0xed0b916a,0x044d,0x11d1,0xaa,0x78,0x00,0xc0,0x04f,0xc3,0x1d,0x60) - -OUR_GUID_ENTRY(MEDIATYPE_DVD_NAVIGATION, - 0xe06d802e,0xdb46,0x11cf,0xb4,0xd1,0x00,0x80,0x05f,0x6c,0xbb,0xea) - -OUR_GUID_ENTRY(MEDIASUBTYPE_DVD_NAVIGATION_PCI, - 0xe06d802f,0xdb46,0x11cf,0xb4,0xd1,0x00,0x80,0x05f,0x6c,0xbb,0xea) - -OUR_GUID_ENTRY(MEDIASUBTYPE_DVD_NAVIGATION_DSI, - 0xe06d8030,0xdb46,0x11cf,0xb4,0xd1,0x00,0x80,0x05f,0x6c,0xbb,0xea) - -OUR_GUID_ENTRY(MEDIASUBTYPE_DVD_NAVIGATION_PROVIDER, - 0xe06d8031,0xdb46,0x11cf,0xb4,0xd1,0x00,0x80,0x05f,0x6c,0xbb,0xea) - -OUR_GUID_ENTRY(FORMAT_MPEG2Video, - 0xe06d80e3,0xdb46,0x11cf,0xb4,0xd1,0x00,0x80,0x05f,0x6c,0xbb,0xea) - -OUR_GUID_ENTRY(FORMAT_DolbyAC3, - 0xe06d80e4,0xdb46,0x11cf,0xb4,0xd1,0x00,0x80,0x05f,0x6c,0xbb,0xea) - -OUR_GUID_ENTRY(FORMAT_MPEG2Audio, - 0xe06d80e5,0xdb46,0x11cf,0xb4,0xd1,0x00,0x80,0x05f,0x6c,0xbb,0xea) - -OUR_GUID_ENTRY(FORMAT_DVD_LPCMAudio, - 0xe06d80e6,0xdb46,0x11cf,0xb4,0xd1,0x00,0x80,0x05f,0x6c,0xbb,0xea) - -OUR_GUID_ENTRY(AM_KSPROPSETID_AC3, - 0xBFABE720,0x6E1F,0x11D0,0xBC,0xF2,0x44,0x45,0x53,0x54,0x00,0x00) - -OUR_GUID_ENTRY(AM_KSPROPSETID_DvdSubPic, - 0xac390460,0x43af,0x11d0,0xbd,0x6a,0x00,0x35,0x05,0xc1,0x03,0xa9) - -OUR_GUID_ENTRY(AM_KSPROPSETID_CopyProt, - 0x0E8A0A40,0x6AEF,0x11D0,0x9E,0xD0,0x00,0xA0,0x24,0xCA,0x19,0xB3) - -OUR_GUID_ENTRY(AM_KSPROPSETID_TSRateChange, - 0xa503c5c0,0x1d1d,0x11d1,0xad,0x80,0x44,0x45,0x53,0x54,0x0,0x0) - -OUR_GUID_ENTRY(AM_KSPROPSETID_MPEG4_MediaType_Attributes, - 0xff6c4bfa,0x7a9,0x4c7b,0xa2,0x37,0x67,0x2f,0x9d,0x68,0x6,0x5f) - -OUR_GUID_ENTRY(AM_KSCATEGORY_CAPTURE, - 0x65E8773DL,0x8F56,0x11D0,0xA3,0xB9,0x00,0xA0,0xC9,0x22,0x31,0x96) - -OUR_GUID_ENTRY(AM_KSCATEGORY_RENDER, - 0x65E8773EL,0x8F56,0x11D0,0xA3,0xB9,0x00,0xA0,0xC9,0x22,0x31,0x96) - -OUR_GUID_ENTRY(AM_KSCATEGORY_DATACOMPRESSOR, - 0x1E84C900L,0x7E70,0x11D0,0xA5,0xD6,0x28,0xDB,0x04,0xC1,0x00,0x00) - -OUR_GUID_ENTRY(AM_KSCATEGORY_AUDIO, - 0x6994AD04L,0x93EF,0x11D0,0xA3,0xCC,0x00,0xA0,0xC9,0x22,0x31,0x96) - -OUR_GUID_ENTRY(AM_KSCATEGORY_VIDEO, - 0x6994AD05L,0x93EF,0x11D0,0xA3,0xCC,0x00,0xA0,0xC9,0x22,0x31,0x96) - -OUR_GUID_ENTRY(AM_KSCATEGORY_TVTUNER, - 0xa799a800L,0xa46d,0x11d0,0xa1,0x8c,0x00,0xa0,0x24,0x01,0xdc,0xd4) - -OUR_GUID_ENTRY(AM_KSCATEGORY_CROSSBAR, - 0xa799a801L,0xa46d,0x11d0,0xa1,0x8c,0x00,0xa0,0x24,0x01,0xdc,0xd4) - -OUR_GUID_ENTRY(AM_KSCATEGORY_TVAUDIO, - 0xa799a802L,0xa46d,0x11d0,0xa1,0x8c,0x00,0xa0,0x24,0x01,0xdc,0xd4) - -OUR_GUID_ENTRY(AM_KSCATEGORY_VBICODEC, - 0x07dad660L,0x22f1,0x11d1,0xa9,0xf4,0x00,0xc0,0x4f,0xbb,0xde,0x8f) - -OUR_GUID_ENTRY(AM_KSCATEGORY_SPLITTER, - 0x0A4252A0L,0x7E70,0x11D0,0xA5,0xD6,0x28,0xDB,0x04,0xC1,0x00,0x00) - -OUR_GUID_ENTRY(IID_IKsInterfaceHandler, - 0xD3ABC7E0L,0x9A61,0x11D0,0xA4,0x0D,0x00,0xA0,0xC9,0x22,0x31,0x96) - -OUR_GUID_ENTRY(IID_IKsDataTypeHandler, - 0x5FFBAA02L,0x49A3,0x11D0,0x9F,0x36,0x00,0xAA,0x00,0xA2,0x16,0xA1) - -OUR_GUID_ENTRY(IID_IKsPin, - 0xb61178d1L,0xa2d9,0x11cf,0x9e,0x53,0x00,0xaa,0x00,0xa2,0x16,0xa1) - -OUR_GUID_ENTRY(IID_IKsControl, - 0x28F54685L,0x06FD,0x11D2,0xB2,0x7A,0x00,0xA0,0xC9,0x22,0x31,0x96) - -OUR_GUID_ENTRY(IID_IKsPinFactory, - 0xCD5EBE6BL,0x8B6E,0x11D1,0x8A,0xE0,0x00,0xA0,0xC9,0x22,0x31,0x96) - -OUR_GUID_ENTRY(AM_INTERFACESETID_Standard, - 0x1A8766A0L,0x62CE,0x11CF,0xA5,0xD6,0x28,0xDB,0x04,0xC1,0x00,0x00) - -#if ( (NTDDI_VERSION >= NTDDI_WINXPSP2) && (NTDDI_VERSION < NTDDI_WS03) ) || (NTDDI_VERSION >= NTDDI_WS03SP1) -OUR_GUID_ENTRY(MEDIATYPE_MPEG2_SECTIONS, - 0x455f176c,0x4b06,0x47ce,0x9a,0xef,0x8c,0xae,0xf7,0x3d,0xf7,0xb5) - -OUR_GUID_ENTRY(MEDIASUBTYPE_MPEG2_VERSIONED_TABLES, - 0x1ed988b0,0x3ffc,0x4523,0x87,0x25,0x34,0x7b,0xee,0xc1,0xa8,0xa0) - -OUR_GUID_ENTRY(MEDIASUBTYPE_ATSC_SI, - 0xb3c7397c,0xd303,0x414d,0xb3,0x3c,0x4e,0xd2,0xc9,0xd2,0x97,0x33) - -OUR_GUID_ENTRY(MEDIASUBTYPE_DVB_SI, - 0xe9dd31a3,0x221d,0x4adb,0x85,0x32,0x9a,0xf3,0x9,0xc1,0xa4,0x8) - -OUR_GUID_ENTRY(MEDIASUBTYPE_ISDB_SI, - 0xe89ad298,0x3601,0x4b06,0xaa,0xec,0x9d,0xde,0xed,0xcc,0x5b,0xd0) - -OUR_GUID_ENTRY(MEDIASUBTYPE_TIF_SI, - 0xec232eb2,0xcb96,0x4191,0xb2,0x26,0xe,0xa1,0x29,0xf3,0x82,0x50) - -OUR_GUID_ENTRY(MEDIASUBTYPE_MPEG2DATA, - 0xc892e55b,0x252d,0x42b5,0xa3,0x16,0xd9,0x97,0xe7,0xa5,0xd9,0x95) -#endif -/* ( (NTDDI_VERSION >= NTDDI_WINXPSP2) && (NTDDI_VERSION < NTDDI_WS03) ) || - (NTDDI_VERSION >= NTDDI_WS03SP1) */ - -#if (NTDDI_VERSION >= NTDDI_WINXP) -OUR_GUID_ENTRY(MEDIASUBTYPE_MPEG2_TRANSPORT_STRIDE, - 0x138aa9a4,0x1ee2,0x4c5b,0x98,0x8e,0x19,0xab,0xfd,0xbc,0x8a,0x11) - -OUR_GUID_ENTRY(MEDIASUBTYPE_MPEG2_UDCR_TRANSPORT, - 0x18BEC4EA,0x4676,0x450e,0xB4,0x78,0x0C,0xD8,0x4C,0x54,0xB3,0x27) - -OUR_GUID_ENTRY(MEDIASUBTYPE_MPEG2_PBDA_TRANSPORT_RAW, - 0x0d7aed42,0xcb9a,0x11db,0x97,0x5,0x0,0x50,0x56,0xc0,0x0,0x8) - -OUR_GUID_ENTRY(MEDIASUBTYPE_MPEG2_PBDA_TRANSPORT_PROCESSED, - 0xaf748dd4,0xd80,0x11db,0x97,0x5,0x0,0x50,0x56,0xc0,0x0,0x8) - -OUR_GUID_ENTRY(MEDIASUBTYPE_DTS, - 0xe06d8033,0xdb46,0x11cf,0xb4,0xd1,0x00,0x80,0x05f,0x6c,0xbb,0xea) - -OUR_GUID_ENTRY(MEDIASUBTYPE_SDDS, - 0xe06d8034,0xdb46,0x11cf,0xb4,0xd1,0x00,0x80,0x05f,0x6c,0xbb,0xea) - -OUR_GUID_ENTRY(AM_KSPROPSETID_DVD_RateChange, - 0x3577eb09,0x9582,0x477f,0xb2,0x9c,0xb0,0xc4,0x52,0xa4,0xff,0x9a) - -OUR_GUID_ENTRY(AM_KSPROPSETID_DvdKaraoke, - 0xae4720ae,0xaa71,0x42d8,0xb8,0x2a,0xff,0xfd,0xf5,0x8b,0x76,0xfd) - -OUR_GUID_ENTRY(AM_KSPROPSETID_FrameStep, - 0xc830acbd,0xab07,0x492f,0x88,0x52,0x45,0xb6,0x98,0x7c,0x29,0x79) -#endif /* NTDDI_VERSION >= NTDDI_WINXP */ - -#if (NTDDI_VERSION >= NTDDI_WS03SP1) -OUR_GUID_ENTRY(AM_KSCATEGORY_VBICODEC_MI, - 0x9c24a977,0x951,0x451a,0x80,0x6,0xe,0x49,0xbd,0x28,0xcd,0x5f) -#endif /* NTDDI_VERSION >= NTDDI_WS03SP1 */ - diff --git a/vendor/dshow/strmif.h b/vendor/dshow/strmif.h deleted file mode 100644 index 9fa927d25..000000000 --- a/vendor/dshow/strmif.h +++ /dev/null @@ -1,9392 +0,0 @@ -/** - * This file has no copyright assigned and is placed in the Public Domain. - * This file is part of the w64 mingw-runtime package. - * No warranty is given; refer to the file DISCLAIMER.PD within this package. - */ -#ifndef __REQUIRED_RPCNDR_H_VERSION__ -#define __REQUIRED_RPCNDR_H_VERSION__ 475 -#endif - -#include "rpc.h" -#include "rpcndr.h" - -#ifndef __RPCNDR_H_VERSION__ -#error This stub requires an updated version of -#endif - -#ifndef COM_NO_WINDOWS_H -#include "windows.h" -#include "ole2.h" -#endif - -#ifndef __strmif_h__ -#define __strmif_h__ - -#ifndef __ICreateDevEnum_FWD_DEFINED__ -#define __ICreateDevEnum_FWD_DEFINED__ -typedef struct ICreateDevEnum ICreateDevEnum; -#endif - -#ifndef __IPin_FWD_DEFINED__ -#define __IPin_FWD_DEFINED__ -typedef struct IPin IPin; -#endif - -#ifndef __IEnumPins_FWD_DEFINED__ -#define __IEnumPins_FWD_DEFINED__ -typedef struct IEnumPins IEnumPins; -#endif - -#ifndef __IEnumMediaTypes_FWD_DEFINED__ -#define __IEnumMediaTypes_FWD_DEFINED__ -typedef struct IEnumMediaTypes IEnumMediaTypes; -#endif - -#ifndef __IFilterGraph_FWD_DEFINED__ -#define __IFilterGraph_FWD_DEFINED__ -typedef struct IFilterGraph IFilterGraph; -#endif - -#ifndef __IEnumFilters_FWD_DEFINED__ -#define __IEnumFilters_FWD_DEFINED__ -typedef struct IEnumFilters IEnumFilters; -#endif - -#ifndef __IMediaFilter_FWD_DEFINED__ -#define __IMediaFilter_FWD_DEFINED__ -typedef struct IMediaFilter IMediaFilter; -#endif - -#ifndef __IBaseFilter_FWD_DEFINED__ -#define __IBaseFilter_FWD_DEFINED__ -typedef struct IBaseFilter IBaseFilter; -#endif - -#ifndef __IReferenceClock_FWD_DEFINED__ -#define __IReferenceClock_FWD_DEFINED__ -typedef struct IReferenceClock IReferenceClock; -#endif - -#ifndef __IReferenceClock2_FWD_DEFINED__ -#define __IReferenceClock2_FWD_DEFINED__ -typedef struct IReferenceClock2 IReferenceClock2; -#endif - -#ifndef __IMediaSample_FWD_DEFINED__ -#define __IMediaSample_FWD_DEFINED__ -typedef struct IMediaSample IMediaSample; -#endif - -#ifndef __IMediaSample2_FWD_DEFINED__ -#define __IMediaSample2_FWD_DEFINED__ -typedef struct IMediaSample2 IMediaSample2; -#endif - -#ifndef __IMemAllocator_FWD_DEFINED__ -#define __IMemAllocator_FWD_DEFINED__ -typedef struct IMemAllocator IMemAllocator; -#endif - -#ifndef __IMemAllocatorCallbackTemp_FWD_DEFINED__ -#define __IMemAllocatorCallbackTemp_FWD_DEFINED__ -typedef struct IMemAllocatorCallbackTemp IMemAllocatorCallbackTemp; -#endif - -#ifndef __IMemAllocatorNotifyCallbackTemp_FWD_DEFINED__ -#define __IMemAllocatorNotifyCallbackTemp_FWD_DEFINED__ -typedef struct IMemAllocatorNotifyCallbackTemp IMemAllocatorNotifyCallbackTemp; -#endif - -#ifndef __IMemInputPin_FWD_DEFINED__ -#define __IMemInputPin_FWD_DEFINED__ -typedef struct IMemInputPin IMemInputPin; -#endif - -#ifndef __IAMovieSetup_FWD_DEFINED__ -#define __IAMovieSetup_FWD_DEFINED__ -typedef struct IAMovieSetup IAMovieSetup; -#endif - -#ifndef __IMediaSeeking_FWD_DEFINED__ -#define __IMediaSeeking_FWD_DEFINED__ -typedef struct IMediaSeeking IMediaSeeking; -#endif - -#ifndef __IEnumRegFilters_FWD_DEFINED__ -#define __IEnumRegFilters_FWD_DEFINED__ -typedef struct IEnumRegFilters IEnumRegFilters; -#endif - -#ifndef __IFilterMapper_FWD_DEFINED__ -#define __IFilterMapper_FWD_DEFINED__ -typedef struct IFilterMapper IFilterMapper; -#endif - -#ifndef __IFilterMapper2_FWD_DEFINED__ -#define __IFilterMapper2_FWD_DEFINED__ -typedef struct IFilterMapper2 IFilterMapper2; -#endif - -#ifndef __IFilterMapper3_FWD_DEFINED__ -#define __IFilterMapper3_FWD_DEFINED__ -typedef struct IFilterMapper3 IFilterMapper3; -#endif - -#ifndef __IQualityControl_FWD_DEFINED__ -#define __IQualityControl_FWD_DEFINED__ -typedef struct IQualityControl IQualityControl; -#endif - -#ifndef __IOverlayNotify_FWD_DEFINED__ -#define __IOverlayNotify_FWD_DEFINED__ -typedef struct IOverlayNotify IOverlayNotify; -#endif - -#ifndef __IOverlayNotify2_FWD_DEFINED__ -#define __IOverlayNotify2_FWD_DEFINED__ -typedef struct IOverlayNotify2 IOverlayNotify2; -#endif - -#ifndef __IOverlay_FWD_DEFINED__ -#define __IOverlay_FWD_DEFINED__ -typedef struct IOverlay IOverlay; -#endif - -#ifndef __IMediaEventSink_FWD_DEFINED__ -#define __IMediaEventSink_FWD_DEFINED__ -typedef struct IMediaEventSink IMediaEventSink; -#endif - -#ifndef __IFileSourceFilter_FWD_DEFINED__ -#define __IFileSourceFilter_FWD_DEFINED__ -typedef struct IFileSourceFilter IFileSourceFilter; -#endif - -#ifndef __IFileSinkFilter_FWD_DEFINED__ -#define __IFileSinkFilter_FWD_DEFINED__ -typedef struct IFileSinkFilter IFileSinkFilter; -#endif - -#ifndef __IFileSinkFilter2_FWD_DEFINED__ -#define __IFileSinkFilter2_FWD_DEFINED__ -typedef struct IFileSinkFilter2 IFileSinkFilter2; -#endif - -#ifndef __IGraphBuilder_FWD_DEFINED__ -#define __IGraphBuilder_FWD_DEFINED__ -typedef struct IGraphBuilder IGraphBuilder; -#endif - -#ifndef __ICaptureGraphBuilder_FWD_DEFINED__ -#define __ICaptureGraphBuilder_FWD_DEFINED__ -typedef struct ICaptureGraphBuilder ICaptureGraphBuilder; -#endif - -#ifndef __IAMCopyCaptureFileProgress_FWD_DEFINED__ -#define __IAMCopyCaptureFileProgress_FWD_DEFINED__ -typedef struct IAMCopyCaptureFileProgress IAMCopyCaptureFileProgress; -#endif - -#ifndef __ICaptureGraphBuilder2_FWD_DEFINED__ -#define __ICaptureGraphBuilder2_FWD_DEFINED__ -typedef struct ICaptureGraphBuilder2 ICaptureGraphBuilder2; -#endif - -#ifndef __IFilterGraph2_FWD_DEFINED__ -#define __IFilterGraph2_FWD_DEFINED__ -typedef struct IFilterGraph2 IFilterGraph2; -#endif - -#ifndef __IStreamBuilder_FWD_DEFINED__ -#define __IStreamBuilder_FWD_DEFINED__ -typedef struct IStreamBuilder IStreamBuilder; -#endif - -#ifndef __IAsyncReader_FWD_DEFINED__ -#define __IAsyncReader_FWD_DEFINED__ -typedef struct IAsyncReader IAsyncReader; -#endif - -#ifndef __IGraphVersion_FWD_DEFINED__ -#define __IGraphVersion_FWD_DEFINED__ -typedef struct IGraphVersion IGraphVersion; -#endif - -#ifndef __IResourceConsumer_FWD_DEFINED__ -#define __IResourceConsumer_FWD_DEFINED__ -typedef struct IResourceConsumer IResourceConsumer; -#endif - -#ifndef __IResourceManager_FWD_DEFINED__ -#define __IResourceManager_FWD_DEFINED__ -typedef struct IResourceManager IResourceManager; -#endif - -#ifndef __IDistributorNotify_FWD_DEFINED__ -#define __IDistributorNotify_FWD_DEFINED__ -typedef struct IDistributorNotify IDistributorNotify; -#endif - -#ifndef __IAMStreamControl_FWD_DEFINED__ -#define __IAMStreamControl_FWD_DEFINED__ -typedef struct IAMStreamControl IAMStreamControl; -#endif - -#ifndef __ISeekingPassThru_FWD_DEFINED__ -#define __ISeekingPassThru_FWD_DEFINED__ -typedef struct ISeekingPassThru ISeekingPassThru; -#endif - -#ifndef __IAMStreamConfig_FWD_DEFINED__ -#define __IAMStreamConfig_FWD_DEFINED__ -typedef struct IAMStreamConfig IAMStreamConfig; -#endif - -#ifndef __IConfigInterleaving_FWD_DEFINED__ -#define __IConfigInterleaving_FWD_DEFINED__ -typedef struct IConfigInterleaving IConfigInterleaving; -#endif - -#ifndef __IConfigAviMux_FWD_DEFINED__ -#define __IConfigAviMux_FWD_DEFINED__ -typedef struct IConfigAviMux IConfigAviMux; -#endif - -#ifndef __IAMVideoCompression_FWD_DEFINED__ -#define __IAMVideoCompression_FWD_DEFINED__ -typedef struct IAMVideoCompression IAMVideoCompression; -#endif - -#ifndef __IAMVfwCaptureDialogs_FWD_DEFINED__ -#define __IAMVfwCaptureDialogs_FWD_DEFINED__ -typedef struct IAMVfwCaptureDialogs IAMVfwCaptureDialogs; -#endif - -#ifndef __IAMVfwCompressDialogs_FWD_DEFINED__ -#define __IAMVfwCompressDialogs_FWD_DEFINED__ -typedef struct IAMVfwCompressDialogs IAMVfwCompressDialogs; -#endif - -#ifndef __IAMDroppedFrames_FWD_DEFINED__ -#define __IAMDroppedFrames_FWD_DEFINED__ -typedef struct IAMDroppedFrames IAMDroppedFrames; -#endif - -#ifndef __IAMAudioInputMixer_FWD_DEFINED__ -#define __IAMAudioInputMixer_FWD_DEFINED__ -typedef struct IAMAudioInputMixer IAMAudioInputMixer; -#endif - -#ifndef __IAMBufferNegotiation_FWD_DEFINED__ -#define __IAMBufferNegotiation_FWD_DEFINED__ -typedef struct IAMBufferNegotiation IAMBufferNegotiation; -#endif - -#ifndef __IAMAnalogVideoDecoder_FWD_DEFINED__ -#define __IAMAnalogVideoDecoder_FWD_DEFINED__ -typedef struct IAMAnalogVideoDecoder IAMAnalogVideoDecoder; -#endif - -#ifndef __IAMVideoProcAmp_FWD_DEFINED__ -#define __IAMVideoProcAmp_FWD_DEFINED__ -typedef struct IAMVideoProcAmp IAMVideoProcAmp; -#endif - -#ifndef __IAMCameraControl_FWD_DEFINED__ -#define __IAMCameraControl_FWD_DEFINED__ -typedef struct IAMCameraControl IAMCameraControl; -#endif - -#ifndef __IAMVideoControl_FWD_DEFINED__ -#define __IAMVideoControl_FWD_DEFINED__ -typedef struct IAMVideoControl IAMVideoControl; -#endif - -#ifndef __IAMCrossbar_FWD_DEFINED__ -#define __IAMCrossbar_FWD_DEFINED__ -typedef struct IAMCrossbar IAMCrossbar; -#endif - -#ifndef __IAMTuner_FWD_DEFINED__ -#define __IAMTuner_FWD_DEFINED__ -typedef struct IAMTuner IAMTuner; -#endif - -#ifndef __IAMTunerNotification_FWD_DEFINED__ -#define __IAMTunerNotification_FWD_DEFINED__ -typedef struct IAMTunerNotification IAMTunerNotification; -#endif - -#ifndef __IAMTVTuner_FWD_DEFINED__ -#define __IAMTVTuner_FWD_DEFINED__ -typedef struct IAMTVTuner IAMTVTuner; -#endif - -#ifndef __IBPCSatelliteTuner_FWD_DEFINED__ -#define __IBPCSatelliteTuner_FWD_DEFINED__ -typedef struct IBPCSatelliteTuner IBPCSatelliteTuner; -#endif - -#ifndef __IAMTVAudio_FWD_DEFINED__ -#define __IAMTVAudio_FWD_DEFINED__ -typedef struct IAMTVAudio IAMTVAudio; -#endif - -#ifndef __IAMTVAudioNotification_FWD_DEFINED__ -#define __IAMTVAudioNotification_FWD_DEFINED__ -typedef struct IAMTVAudioNotification IAMTVAudioNotification; -#endif - -#ifndef __IAMAnalogVideoEncoder_FWD_DEFINED__ -#define __IAMAnalogVideoEncoder_FWD_DEFINED__ -typedef struct IAMAnalogVideoEncoder IAMAnalogVideoEncoder; -#endif - -#ifndef __IKsPropertySet_FWD_DEFINED__ -#define __IKsPropertySet_FWD_DEFINED__ -typedef struct IKsPropertySet IKsPropertySet; -#endif - -#ifndef __IMediaPropertyBag_FWD_DEFINED__ -#define __IMediaPropertyBag_FWD_DEFINED__ -typedef struct IMediaPropertyBag IMediaPropertyBag; -#endif - -#ifndef __IPersistMediaPropertyBag_FWD_DEFINED__ -#define __IPersistMediaPropertyBag_FWD_DEFINED__ -typedef struct IPersistMediaPropertyBag IPersistMediaPropertyBag; -#endif - -#ifndef __IAMPhysicalPinInfo_FWD_DEFINED__ -#define __IAMPhysicalPinInfo_FWD_DEFINED__ -typedef struct IAMPhysicalPinInfo IAMPhysicalPinInfo; -#endif - -#ifndef __IAMExtDevice_FWD_DEFINED__ -#define __IAMExtDevice_FWD_DEFINED__ -typedef struct IAMExtDevice IAMExtDevice; -#endif - -#ifndef __IAMExtTransport_FWD_DEFINED__ -#define __IAMExtTransport_FWD_DEFINED__ -typedef struct IAMExtTransport IAMExtTransport; -#endif - -#ifndef __IAMTimecodeReader_FWD_DEFINED__ -#define __IAMTimecodeReader_FWD_DEFINED__ -typedef struct IAMTimecodeReader IAMTimecodeReader; -#endif - -#ifndef __IAMTimecodeGenerator_FWD_DEFINED__ -#define __IAMTimecodeGenerator_FWD_DEFINED__ -typedef struct IAMTimecodeGenerator IAMTimecodeGenerator; -#endif - -#ifndef __IAMTimecodeDisplay_FWD_DEFINED__ -#define __IAMTimecodeDisplay_FWD_DEFINED__ -typedef struct IAMTimecodeDisplay IAMTimecodeDisplay; -#endif - -#ifndef __IAMDevMemoryAllocator_FWD_DEFINED__ -#define __IAMDevMemoryAllocator_FWD_DEFINED__ -typedef struct IAMDevMemoryAllocator IAMDevMemoryAllocator; -#endif - -#ifndef __IAMDevMemoryControl_FWD_DEFINED__ -#define __IAMDevMemoryControl_FWD_DEFINED__ -typedef struct IAMDevMemoryControl IAMDevMemoryControl; -#endif - -#ifndef __IAMStreamSelect_FWD_DEFINED__ -#define __IAMStreamSelect_FWD_DEFINED__ -typedef struct IAMStreamSelect IAMStreamSelect; -#endif - -#ifndef __IAMResourceControl_FWD_DEFINED__ -#define __IAMResourceControl_FWD_DEFINED__ -typedef struct IAMResourceControl IAMResourceControl; -#endif - -#ifndef __IAMClockAdjust_FWD_DEFINED__ -#define __IAMClockAdjust_FWD_DEFINED__ -typedef struct IAMClockAdjust IAMClockAdjust; -#endif - -#ifndef __IAMFilterMiscFlags_FWD_DEFINED__ -#define __IAMFilterMiscFlags_FWD_DEFINED__ -typedef struct IAMFilterMiscFlags IAMFilterMiscFlags; -#endif - -#ifndef __IDrawVideoImage_FWD_DEFINED__ -#define __IDrawVideoImage_FWD_DEFINED__ -typedef struct IDrawVideoImage IDrawVideoImage; -#endif - -#ifndef __IDecimateVideoImage_FWD_DEFINED__ -#define __IDecimateVideoImage_FWD_DEFINED__ -typedef struct IDecimateVideoImage IDecimateVideoImage; -#endif - -#ifndef __IAMVideoDecimationProperties_FWD_DEFINED__ -#define __IAMVideoDecimationProperties_FWD_DEFINED__ -typedef struct IAMVideoDecimationProperties IAMVideoDecimationProperties; -#endif - -#ifndef __IVideoFrameStep_FWD_DEFINED__ -#define __IVideoFrameStep_FWD_DEFINED__ -typedef struct IVideoFrameStep IVideoFrameStep; -#endif - -#ifndef __IAMLatency_FWD_DEFINED__ -#define __IAMLatency_FWD_DEFINED__ -typedef struct IAMLatency IAMLatency; -#endif - -#ifndef __IAMPushSource_FWD_DEFINED__ -#define __IAMPushSource_FWD_DEFINED__ -typedef struct IAMPushSource IAMPushSource; -#endif - -#ifndef __IAMDeviceRemoval_FWD_DEFINED__ -#define __IAMDeviceRemoval_FWD_DEFINED__ -typedef struct IAMDeviceRemoval IAMDeviceRemoval; -#endif - -#ifndef __IDVEnc_FWD_DEFINED__ -#define __IDVEnc_FWD_DEFINED__ -typedef struct IDVEnc IDVEnc; -#endif - -#ifndef __IIPDVDec_FWD_DEFINED__ -#define __IIPDVDec_FWD_DEFINED__ -typedef struct IIPDVDec IIPDVDec; -#endif - -#ifndef __IDVRGB219_FWD_DEFINED__ -#define __IDVRGB219_FWD_DEFINED__ -typedef struct IDVRGB219 IDVRGB219; -#endif - -#ifndef __IDVSplitter_FWD_DEFINED__ -#define __IDVSplitter_FWD_DEFINED__ -typedef struct IDVSplitter IDVSplitter; -#endif - -#ifndef __IAMAudioRendererStats_FWD_DEFINED__ -#define __IAMAudioRendererStats_FWD_DEFINED__ -typedef struct IAMAudioRendererStats IAMAudioRendererStats; -#endif - -#ifndef __IAMGraphStreams_FWD_DEFINED__ -#define __IAMGraphStreams_FWD_DEFINED__ -typedef struct IAMGraphStreams IAMGraphStreams; -#endif - -#ifndef __IAMOverlayFX_FWD_DEFINED__ -#define __IAMOverlayFX_FWD_DEFINED__ -typedef struct IAMOverlayFX IAMOverlayFX; -#endif - -#ifndef __IAMOpenProgress_FWD_DEFINED__ -#define __IAMOpenProgress_FWD_DEFINED__ -typedef struct IAMOpenProgress IAMOpenProgress; -#endif - -#ifndef __IMpeg2Demultiplexer_FWD_DEFINED__ -#define __IMpeg2Demultiplexer_FWD_DEFINED__ -typedef struct IMpeg2Demultiplexer IMpeg2Demultiplexer; -#endif - -#ifndef __IEnumStreamIdMap_FWD_DEFINED__ -#define __IEnumStreamIdMap_FWD_DEFINED__ -typedef struct IEnumStreamIdMap IEnumStreamIdMap; -#endif - -#ifndef __IMPEG2StreamIdMap_FWD_DEFINED__ -#define __IMPEG2StreamIdMap_FWD_DEFINED__ -typedef struct IMPEG2StreamIdMap IMPEG2StreamIdMap; -#endif - -#ifndef __IRegisterServiceProvider_FWD_DEFINED__ -#define __IRegisterServiceProvider_FWD_DEFINED__ -typedef struct IRegisterServiceProvider IRegisterServiceProvider; -#endif - -#ifndef __IAMClockSlave_FWD_DEFINED__ -#define __IAMClockSlave_FWD_DEFINED__ -typedef struct IAMClockSlave IAMClockSlave; -#endif - -#ifndef __IAMGraphBuilderCallback_FWD_DEFINED__ -#define __IAMGraphBuilderCallback_FWD_DEFINED__ -typedef struct IAMGraphBuilderCallback IAMGraphBuilderCallback; -#endif - -#ifndef __ICodecAPI_FWD_DEFINED__ -#define __ICodecAPI_FWD_DEFINED__ -typedef struct ICodecAPI ICodecAPI; -#endif - -#ifndef __IGetCapabilitiesKey_FWD_DEFINED__ -#define __IGetCapabilitiesKey_FWD_DEFINED__ -typedef struct IGetCapabilitiesKey IGetCapabilitiesKey; -#endif - -#ifndef __IEncoderAPI_FWD_DEFINED__ -#define __IEncoderAPI_FWD_DEFINED__ -typedef struct IEncoderAPI IEncoderAPI; -#endif - -#ifndef __IVideoEncoder_FWD_DEFINED__ -#define __IVideoEncoder_FWD_DEFINED__ -typedef struct IVideoEncoder IVideoEncoder; -#endif - -#ifndef __IAMDecoderCaps_FWD_DEFINED__ -#define __IAMDecoderCaps_FWD_DEFINED__ -typedef struct IAMDecoderCaps IAMDecoderCaps; -#endif - -#ifndef __IAMCertifiedOutputProtection_FWD_DEFINED__ -#define __IAMCertifiedOutputProtection_FWD_DEFINED__ -typedef struct IAMCertifiedOutputProtection IAMCertifiedOutputProtection; -#endif - -#ifndef __IDvdControl_FWD_DEFINED__ -#define __IDvdControl_FWD_DEFINED__ -typedef struct IDvdControl IDvdControl; -#endif - -#ifndef __IDvdInfo_FWD_DEFINED__ -#define __IDvdInfo_FWD_DEFINED__ -typedef struct IDvdInfo IDvdInfo; -#endif - -#ifndef __IDvdCmd_FWD_DEFINED__ -#define __IDvdCmd_FWD_DEFINED__ -typedef struct IDvdCmd IDvdCmd; -#endif - -#ifndef __IDvdState_FWD_DEFINED__ -#define __IDvdState_FWD_DEFINED__ -typedef struct IDvdState IDvdState; -#endif - -#ifndef __IDvdControl2_FWD_DEFINED__ -#define __IDvdControl2_FWD_DEFINED__ -typedef struct IDvdControl2 IDvdControl2; -#endif - -#ifndef __IDvdInfo2_FWD_DEFINED__ -#define __IDvdInfo2_FWD_DEFINED__ -typedef struct IDvdInfo2 IDvdInfo2; -#endif - -#ifndef __IDvdGraphBuilder_FWD_DEFINED__ -#define __IDvdGraphBuilder_FWD_DEFINED__ -typedef struct IDvdGraphBuilder IDvdGraphBuilder; -#endif - -#ifndef __IDDrawExclModeVideo_FWD_DEFINED__ -#define __IDDrawExclModeVideo_FWD_DEFINED__ -typedef struct IDDrawExclModeVideo IDDrawExclModeVideo; -#endif - -#ifndef __IDDrawExclModeVideoCallback_FWD_DEFINED__ -#define __IDDrawExclModeVideoCallback_FWD_DEFINED__ -typedef struct IDDrawExclModeVideoCallback IDDrawExclModeVideoCallback; -#endif - -#ifndef __IPinConnection_FWD_DEFINED__ -#define __IPinConnection_FWD_DEFINED__ -typedef struct IPinConnection IPinConnection; -#endif - -#ifndef __IPinFlowControl_FWD_DEFINED__ -#define __IPinFlowControl_FWD_DEFINED__ -typedef struct IPinFlowControl IPinFlowControl; -#endif - -#ifndef __IGraphConfig_FWD_DEFINED__ -#define __IGraphConfig_FWD_DEFINED__ -typedef struct IGraphConfig IGraphConfig; -#endif - -#ifndef __IGraphConfigCallback_FWD_DEFINED__ -#define __IGraphConfigCallback_FWD_DEFINED__ -typedef struct IGraphConfigCallback IGraphConfigCallback; -#endif - -#ifndef __IFilterChain_FWD_DEFINED__ -#define __IFilterChain_FWD_DEFINED__ -typedef struct IFilterChain IFilterChain; -#endif - -#ifndef __IVMRImagePresenter_FWD_DEFINED__ -#define __IVMRImagePresenter_FWD_DEFINED__ -typedef struct IVMRImagePresenter IVMRImagePresenter; -#endif - -#ifndef __IVMRSurfaceAllocator_FWD_DEFINED__ -#define __IVMRSurfaceAllocator_FWD_DEFINED__ -typedef struct IVMRSurfaceAllocator IVMRSurfaceAllocator; -#endif - -#ifndef __IVMRSurfaceAllocatorNotify_FWD_DEFINED__ -#define __IVMRSurfaceAllocatorNotify_FWD_DEFINED__ -typedef struct IVMRSurfaceAllocatorNotify IVMRSurfaceAllocatorNotify; -#endif - -#ifndef __IVMRWindowlessControl_FWD_DEFINED__ -#define __IVMRWindowlessControl_FWD_DEFINED__ -typedef struct IVMRWindowlessControl IVMRWindowlessControl; -#endif - -#ifndef __IVMRMixerControl_FWD_DEFINED__ -#define __IVMRMixerControl_FWD_DEFINED__ -typedef struct IVMRMixerControl IVMRMixerControl; -#endif - -#ifndef __IVMRMonitorConfig_FWD_DEFINED__ -#define __IVMRMonitorConfig_FWD_DEFINED__ -typedef struct IVMRMonitorConfig IVMRMonitorConfig; -#endif - -#ifndef __IVMRFilterConfig_FWD_DEFINED__ -#define __IVMRFilterConfig_FWD_DEFINED__ -typedef struct IVMRFilterConfig IVMRFilterConfig; -#endif - -#ifndef __IVMRAspectRatioControl_FWD_DEFINED__ -#define __IVMRAspectRatioControl_FWD_DEFINED__ -typedef struct IVMRAspectRatioControl IVMRAspectRatioControl; -#endif - -#ifndef __IVMRDeinterlaceControl_FWD_DEFINED__ -#define __IVMRDeinterlaceControl_FWD_DEFINED__ -typedef struct IVMRDeinterlaceControl IVMRDeinterlaceControl; -#endif - -#ifndef __IVMRMixerBitmap_FWD_DEFINED__ -#define __IVMRMixerBitmap_FWD_DEFINED__ -typedef struct IVMRMixerBitmap IVMRMixerBitmap; -#endif - -#ifndef __IVMRImageCompositor_FWD_DEFINED__ -#define __IVMRImageCompositor_FWD_DEFINED__ -typedef struct IVMRImageCompositor IVMRImageCompositor; -#endif - -#ifndef __IVMRVideoStreamControl_FWD_DEFINED__ -#define __IVMRVideoStreamControl_FWD_DEFINED__ -typedef struct IVMRVideoStreamControl IVMRVideoStreamControl; -#endif - -#ifndef __IVMRSurface_FWD_DEFINED__ -#define __IVMRSurface_FWD_DEFINED__ -typedef struct IVMRSurface IVMRSurface; -#endif - -#ifndef __IVMRImagePresenterConfig_FWD_DEFINED__ -#define __IVMRImagePresenterConfig_FWD_DEFINED__ -typedef struct IVMRImagePresenterConfig IVMRImagePresenterConfig; -#endif - -#ifndef __IVMRImagePresenterExclModeConfig_FWD_DEFINED__ -#define __IVMRImagePresenterExclModeConfig_FWD_DEFINED__ -typedef struct IVMRImagePresenterExclModeConfig IVMRImagePresenterExclModeConfig; -#endif - -#ifndef __IVPManager_FWD_DEFINED__ -#define __IVPManager_FWD_DEFINED__ -typedef struct IVPManager IVPManager; -#endif - -#include "unknwn.h" -#include "objidl.h" -#include "oaidl.h" -#include "ocidl.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef __MIDL_user_allocate_free_DEFINED__ -#define __MIDL_user_allocate_free_DEFINED__ - void *__RPC_API MIDL_user_allocate(size_t); - void __RPC_API MIDL_user_free(void *); -#endif - -#define CDEF_CLASS_DEFAULT 0x0001 -#define CDEF_BYPASS_CLASS_MANAGER 0x0002 -#define CDEF_MERIT_ABOVE_DO_NOT_USE 0x0008 -#define CDEF_DEVMON_CMGR_DEVICE 0x0010 -#define CDEF_DEVMON_DMO 0x0020 -#define CDEF_DEVMON_PNP_DEVICE 0x0040 -#define CDEF_DEVMON_FILTER 0x0080 -#define CDEF_DEVMON_SELECTIVE_MASK 0x00f0 - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0000_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0000_v0_0_s_ifspec; -#ifndef __ICreateDevEnum_INTERFACE_DEFINED__ -#define __ICreateDevEnum_INTERFACE_DEFINED__ - EXTERN_C const IID IID_ICreateDevEnum; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct ICreateDevEnum : public IUnknown { - public: - virtual HRESULT WINAPI CreateClassEnumerator(REFCLSID clsidDeviceClass,IEnumMoniker **ppEnumMoniker,DWORD dwFlags) = 0; - }; -#else - typedef struct ICreateDevEnumVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(ICreateDevEnum *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(ICreateDevEnum *This); - ULONG (WINAPI *Release)(ICreateDevEnum *This); - HRESULT (WINAPI *CreateClassEnumerator)(ICreateDevEnum *This,REFCLSID clsidDeviceClass,IEnumMoniker **ppEnumMoniker,DWORD dwFlags); - END_INTERFACE - } ICreateDevEnumVtbl; - struct ICreateDevEnum { - CONST_VTBL struct ICreateDevEnumVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define ICreateDevEnum_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define ICreateDevEnum_AddRef(This) (This)->lpVtbl->AddRef(This) -#define ICreateDevEnum_Release(This) (This)->lpVtbl->Release(This) -#define ICreateDevEnum_CreateClassEnumerator(This,clsidDeviceClass,ppEnumMoniker,dwFlags) (This)->lpVtbl->CreateClassEnumerator(This,clsidDeviceClass,ppEnumMoniker,dwFlags) -#endif -#endif - HRESULT WINAPI ICreateDevEnum_CreateClassEnumerator_Proxy(ICreateDevEnum *This,REFCLSID clsidDeviceClass,IEnumMoniker **ppEnumMoniker,DWORD dwFlags); - void __RPC_STUB ICreateDevEnum_CreateClassEnumerator_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#define CHARS_IN_GUID 39 - typedef struct _AMMediaType { - GUID majortype; - GUID subtype; - WINBOOL bFixedSizeSamples; - WINBOOL bTemporalCompression; - ULONG lSampleSize; - GUID formattype; - IUnknown *pUnk; - ULONG cbFormat; - BYTE *pbFormat; - } AM_MEDIA_TYPE; - - typedef enum _PinDirection { - PINDIR_INPUT = 0,PINDIR_OUTPUT = PINDIR_INPUT + 1 - } PIN_DIRECTION; - -#define MAX_PIN_NAME 128 -#define MAX_FILTER_NAME 128 - -#ifndef __REFERENCE_TIME_DEFINED -#define __REFERENCE_TIME_DEFINED -typedef LONGLONG REFERENCE_TIME; -#endif /*__REFERENCE_TIME_DEFINED*/ - - typedef double REFTIME; - typedef DWORD_PTR HSEMAPHORE; - typedef DWORD_PTR HEVENT; - - typedef struct _AllocatorProperties { - long cBuffers; - long cbBuffer; - long cbAlign; - long cbPrefix; - } ALLOCATOR_PROPERTIES; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0117_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0117_v0_0_s_ifspec; -#ifndef __IPin_INTERFACE_DEFINED__ -#define __IPin_INTERFACE_DEFINED__ - typedef struct _PinInfo { - IBaseFilter *pFilter; - PIN_DIRECTION dir; - WCHAR achName[128]; - } PIN_INFO; - - EXTERN_C const IID IID_IPin; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IPin : public IUnknown { - public: - virtual HRESULT WINAPI Connect(IPin *pReceivePin,const AM_MEDIA_TYPE *pmt) = 0; - virtual HRESULT WINAPI ReceiveConnection(IPin *pConnector,const AM_MEDIA_TYPE *pmt) = 0; - virtual HRESULT WINAPI Disconnect(void) = 0; - virtual HRESULT WINAPI ConnectedTo(IPin **pPin) = 0; - virtual HRESULT WINAPI ConnectionMediaType(AM_MEDIA_TYPE *pmt) = 0; - virtual HRESULT WINAPI QueryPinInfo(PIN_INFO *pInfo) = 0; - virtual HRESULT WINAPI QueryDirection(PIN_DIRECTION *pPinDir) = 0; - virtual HRESULT WINAPI QueryId(LPWSTR *Id) = 0; - virtual HRESULT WINAPI QueryAccept(const AM_MEDIA_TYPE *pmt) = 0; - virtual HRESULT WINAPI EnumMediaTypes(IEnumMediaTypes **ppEnum) = 0; - virtual HRESULT WINAPI QueryInternalConnections(IPin **apPin,ULONG *nPin) = 0; - virtual HRESULT WINAPI EndOfStream(void) = 0; - virtual HRESULT WINAPI BeginFlush(void) = 0; - virtual HRESULT WINAPI EndFlush(void) = 0; - virtual HRESULT WINAPI NewSegment(REFERENCE_TIME tStart,REFERENCE_TIME tStop,double dRate) = 0; - }; -#else - typedef struct IPinVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IPin *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IPin *This); - ULONG (WINAPI *Release)(IPin *This); - HRESULT (WINAPI *Connect)(IPin *This,IPin *pReceivePin,const AM_MEDIA_TYPE *pmt); - HRESULT (WINAPI *ReceiveConnection)(IPin *This,IPin *pConnector,const AM_MEDIA_TYPE *pmt); - HRESULT (WINAPI *Disconnect)(IPin *This); - HRESULT (WINAPI *ConnectedTo)(IPin *This,IPin **pPin); - HRESULT (WINAPI *ConnectionMediaType)(IPin *This,AM_MEDIA_TYPE *pmt); - HRESULT (WINAPI *QueryPinInfo)(IPin *This,PIN_INFO *pInfo); - HRESULT (WINAPI *QueryDirection)(IPin *This,PIN_DIRECTION *pPinDir); - HRESULT (WINAPI *QueryId)(IPin *This,LPWSTR *Id); - HRESULT (WINAPI *QueryAccept)(IPin *This,const AM_MEDIA_TYPE *pmt); - HRESULT (WINAPI *EnumMediaTypes)(IPin *This,IEnumMediaTypes **ppEnum); - HRESULT (WINAPI *QueryInternalConnections)(IPin *This,IPin **apPin,ULONG *nPin); - HRESULT (WINAPI *EndOfStream)(IPin *This); - HRESULT (WINAPI *BeginFlush)(IPin *This); - HRESULT (WINAPI *EndFlush)(IPin *This); - HRESULT (WINAPI *NewSegment)(IPin *This,REFERENCE_TIME tStart,REFERENCE_TIME tStop,double dRate); - END_INTERFACE - } IPinVtbl; - struct IPin { - CONST_VTBL struct IPinVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IPin_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IPin_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IPin_Release(This) (This)->lpVtbl->Release(This) -#define IPin_Connect(This,pReceivePin,pmt) (This)->lpVtbl->Connect(This,pReceivePin,pmt) -#define IPin_ReceiveConnection(This,pConnector,pmt) (This)->lpVtbl->ReceiveConnection(This,pConnector,pmt) -#define IPin_Disconnect(This) (This)->lpVtbl->Disconnect(This) -#define IPin_ConnectedTo(This,pPin) (This)->lpVtbl->ConnectedTo(This,pPin) -#define IPin_ConnectionMediaType(This,pmt) (This)->lpVtbl->ConnectionMediaType(This,pmt) -#define IPin_QueryPinInfo(This,pInfo) (This)->lpVtbl->QueryPinInfo(This,pInfo) -#define IPin_QueryDirection(This,pPinDir) (This)->lpVtbl->QueryDirection(This,pPinDir) -#define IPin_QueryId(This,Id) (This)->lpVtbl->QueryId(This,Id) -#define IPin_QueryAccept(This,pmt) (This)->lpVtbl->QueryAccept(This,pmt) -#define IPin_EnumMediaTypes(This,ppEnum) (This)->lpVtbl->EnumMediaTypes(This,ppEnum) -#define IPin_QueryInternalConnections(This,apPin,nPin) (This)->lpVtbl->QueryInternalConnections(This,apPin,nPin) -#define IPin_EndOfStream(This) (This)->lpVtbl->EndOfStream(This) -#define IPin_BeginFlush(This) (This)->lpVtbl->BeginFlush(This) -#define IPin_EndFlush(This) (This)->lpVtbl->EndFlush(This) -#define IPin_NewSegment(This,tStart,tStop,dRate) (This)->lpVtbl->NewSegment(This,tStart,tStop,dRate) -#endif -#endif - HRESULT WINAPI IPin_Connect_Proxy(IPin *This,IPin *pReceivePin,const AM_MEDIA_TYPE *pmt); - void __RPC_STUB IPin_Connect_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IPin_ReceiveConnection_Proxy(IPin *This,IPin *pConnector,const AM_MEDIA_TYPE *pmt); - void __RPC_STUB IPin_ReceiveConnection_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IPin_Disconnect_Proxy(IPin *This); - void __RPC_STUB IPin_Disconnect_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IPin_ConnectedTo_Proxy(IPin *This,IPin **pPin); - void __RPC_STUB IPin_ConnectedTo_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IPin_ConnectionMediaType_Proxy(IPin *This,AM_MEDIA_TYPE *pmt); - void __RPC_STUB IPin_ConnectionMediaType_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IPin_QueryPinInfo_Proxy(IPin *This,PIN_INFO *pInfo); - void __RPC_STUB IPin_QueryPinInfo_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IPin_QueryDirection_Proxy(IPin *This,PIN_DIRECTION *pPinDir); - void __RPC_STUB IPin_QueryDirection_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IPin_QueryId_Proxy(IPin *This,LPWSTR *Id); - void __RPC_STUB IPin_QueryId_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IPin_QueryAccept_Proxy(IPin *This,const AM_MEDIA_TYPE *pmt); - void __RPC_STUB IPin_QueryAccept_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IPin_EnumMediaTypes_Proxy(IPin *This,IEnumMediaTypes **ppEnum); - void __RPC_STUB IPin_EnumMediaTypes_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IPin_QueryInternalConnections_Proxy(IPin *This,IPin **apPin,ULONG *nPin); - void __RPC_STUB IPin_QueryInternalConnections_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IPin_EndOfStream_Proxy(IPin *This); - void __RPC_STUB IPin_EndOfStream_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IPin_BeginFlush_Proxy(IPin *This); - void __RPC_STUB IPin_BeginFlush_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IPin_EndFlush_Proxy(IPin *This); - void __RPC_STUB IPin_EndFlush_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IPin_NewSegment_Proxy(IPin *This,REFERENCE_TIME tStart,REFERENCE_TIME tStop,double dRate); - void __RPC_STUB IPin_NewSegment_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - typedef IPin *PPIN; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0118_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0118_v0_0_s_ifspec; -#ifndef __IEnumPins_INTERFACE_DEFINED__ -#define __IEnumPins_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IEnumPins; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IEnumPins : public IUnknown { - public: - virtual HRESULT WINAPI Next(ULONG cPins,IPin **ppPins,ULONG *pcFetched) = 0; - virtual HRESULT WINAPI Skip(ULONG cPins) = 0; - virtual HRESULT WINAPI Reset(void) = 0; - virtual HRESULT WINAPI Clone(IEnumPins **ppEnum) = 0; - }; -#else - typedef struct IEnumPinsVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IEnumPins *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IEnumPins *This); - ULONG (WINAPI *Release)(IEnumPins *This); - HRESULT (WINAPI *Next)(IEnumPins *This,ULONG cPins,IPin **ppPins,ULONG *pcFetched); - HRESULT (WINAPI *Skip)(IEnumPins *This,ULONG cPins); - HRESULT (WINAPI *Reset)(IEnumPins *This); - HRESULT (WINAPI *Clone)(IEnumPins *This,IEnumPins **ppEnum); - END_INTERFACE - } IEnumPinsVtbl; - struct IEnumPins { - CONST_VTBL struct IEnumPinsVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IEnumPins_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IEnumPins_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IEnumPins_Release(This) (This)->lpVtbl->Release(This) -#define IEnumPins_Next(This,cPins,ppPins,pcFetched) (This)->lpVtbl->Next(This,cPins,ppPins,pcFetched) -#define IEnumPins_Skip(This,cPins) (This)->lpVtbl->Skip(This,cPins) -#define IEnumPins_Reset(This) (This)->lpVtbl->Reset(This) -#define IEnumPins_Clone(This,ppEnum) (This)->lpVtbl->Clone(This,ppEnum) -#endif -#endif - HRESULT WINAPI IEnumPins_Next_Proxy(IEnumPins *This,ULONG cPins,IPin **ppPins,ULONG *pcFetched); - void __RPC_STUB IEnumPins_Next_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IEnumPins_Skip_Proxy(IEnumPins *This,ULONG cPins); - void __RPC_STUB IEnumPins_Skip_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IEnumPins_Reset_Proxy(IEnumPins *This); - void __RPC_STUB IEnumPins_Reset_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IEnumPins_Clone_Proxy(IEnumPins *This,IEnumPins **ppEnum); - void __RPC_STUB IEnumPins_Clone_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - typedef IEnumPins *PENUMPINS; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0119_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0119_v0_0_s_ifspec; -#ifndef __IEnumMediaTypes_INTERFACE_DEFINED__ -#define __IEnumMediaTypes_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IEnumMediaTypes; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IEnumMediaTypes : public IUnknown { - public: - virtual HRESULT WINAPI Next(ULONG cMediaTypes,AM_MEDIA_TYPE **ppMediaTypes,ULONG *pcFetched) = 0; - virtual HRESULT WINAPI Skip(ULONG cMediaTypes) = 0; - virtual HRESULT WINAPI Reset(void) = 0; - virtual HRESULT WINAPI Clone(IEnumMediaTypes **ppEnum) = 0; - }; -#else - typedef struct IEnumMediaTypesVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IEnumMediaTypes *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IEnumMediaTypes *This); - ULONG (WINAPI *Release)(IEnumMediaTypes *This); - HRESULT (WINAPI *Next)(IEnumMediaTypes *This,ULONG cMediaTypes,AM_MEDIA_TYPE **ppMediaTypes,ULONG *pcFetched); - HRESULT (WINAPI *Skip)(IEnumMediaTypes *This,ULONG cMediaTypes); - HRESULT (WINAPI *Reset)(IEnumMediaTypes *This); - HRESULT (WINAPI *Clone)(IEnumMediaTypes *This,IEnumMediaTypes **ppEnum); - END_INTERFACE - } IEnumMediaTypesVtbl; - struct IEnumMediaTypes { - CONST_VTBL struct IEnumMediaTypesVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IEnumMediaTypes_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IEnumMediaTypes_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IEnumMediaTypes_Release(This) (This)->lpVtbl->Release(This) -#define IEnumMediaTypes_Next(This,cMediaTypes,ppMediaTypes,pcFetched) (This)->lpVtbl->Next(This,cMediaTypes,ppMediaTypes,pcFetched) -#define IEnumMediaTypes_Skip(This,cMediaTypes) (This)->lpVtbl->Skip(This,cMediaTypes) -#define IEnumMediaTypes_Reset(This) (This)->lpVtbl->Reset(This) -#define IEnumMediaTypes_Clone(This,ppEnum) (This)->lpVtbl->Clone(This,ppEnum) -#endif -#endif - HRESULT WINAPI IEnumMediaTypes_Next_Proxy(IEnumMediaTypes *This,ULONG cMediaTypes,AM_MEDIA_TYPE **ppMediaTypes,ULONG *pcFetched); - void __RPC_STUB IEnumMediaTypes_Next_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IEnumMediaTypes_Skip_Proxy(IEnumMediaTypes *This,ULONG cMediaTypes); - void __RPC_STUB IEnumMediaTypes_Skip_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IEnumMediaTypes_Reset_Proxy(IEnumMediaTypes *This); - void __RPC_STUB IEnumMediaTypes_Reset_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IEnumMediaTypes_Clone_Proxy(IEnumMediaTypes *This,IEnumMediaTypes **ppEnum); - void __RPC_STUB IEnumMediaTypes_Clone_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - typedef IEnumMediaTypes *PENUMMEDIATYPES; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0120_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0120_v0_0_s_ifspec; -#ifndef __IFilterGraph_INTERFACE_DEFINED__ -#define __IFilterGraph_INTERFACE_DEFINED__ - - EXTERN_C const IID IID_IFilterGraph; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IFilterGraph : public IUnknown { - public: - virtual HRESULT WINAPI AddFilter(IBaseFilter *pFilter,LPCWSTR pName) = 0; - virtual HRESULT WINAPI RemoveFilter(IBaseFilter *pFilter) = 0; - virtual HRESULT WINAPI EnumFilters(IEnumFilters **ppEnum) = 0; - virtual HRESULT WINAPI FindFilterByName(LPCWSTR pName,IBaseFilter **ppFilter) = 0; - virtual HRESULT WINAPI ConnectDirect(IPin *ppinOut,IPin *ppinIn,const AM_MEDIA_TYPE *pmt) = 0; - virtual HRESULT WINAPI Reconnect(IPin *ppin) = 0; - virtual HRESULT WINAPI Disconnect(IPin *ppin) = 0; - virtual HRESULT WINAPI SetDefaultSyncSource(void) = 0; - }; -#else - typedef struct IFilterGraphVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IFilterGraph *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IFilterGraph *This); - ULONG (WINAPI *Release)(IFilterGraph *This); - HRESULT (WINAPI *AddFilter)(IFilterGraph *This,IBaseFilter *pFilter,LPCWSTR pName); - HRESULT (WINAPI *RemoveFilter)(IFilterGraph *This,IBaseFilter *pFilter); - HRESULT (WINAPI *EnumFilters)(IFilterGraph *This,IEnumFilters **ppEnum); - HRESULT (WINAPI *FindFilterByName)(IFilterGraph *This,LPCWSTR pName,IBaseFilter **ppFilter); - HRESULT (WINAPI *ConnectDirect)(IFilterGraph *This,IPin *ppinOut,IPin *ppinIn,const AM_MEDIA_TYPE *pmt); - HRESULT (WINAPI *Reconnect)(IFilterGraph *This,IPin *ppin); - HRESULT (WINAPI *Disconnect)(IFilterGraph *This,IPin *ppin); - HRESULT (WINAPI *SetDefaultSyncSource)(IFilterGraph *This); - END_INTERFACE - } IFilterGraphVtbl; - struct IFilterGraph { - CONST_VTBL struct IFilterGraphVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IFilterGraph_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IFilterGraph_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IFilterGraph_Release(This) (This)->lpVtbl->Release(This) -#define IFilterGraph_AddFilter(This,pFilter,pName) (This)->lpVtbl->AddFilter(This,pFilter,pName) -#define IFilterGraph_RemoveFilter(This,pFilter) (This)->lpVtbl->RemoveFilter(This,pFilter) -#define IFilterGraph_EnumFilters(This,ppEnum) (This)->lpVtbl->EnumFilters(This,ppEnum) -#define IFilterGraph_FindFilterByName(This,pName,ppFilter) (This)->lpVtbl->FindFilterByName(This,pName,ppFilter) -#define IFilterGraph_ConnectDirect(This,ppinOut,ppinIn,pmt) (This)->lpVtbl->ConnectDirect(This,ppinOut,ppinIn,pmt) -#define IFilterGraph_Reconnect(This,ppin) (This)->lpVtbl->Reconnect(This,ppin) -#define IFilterGraph_Disconnect(This,ppin) (This)->lpVtbl->Disconnect(This,ppin) -#define IFilterGraph_SetDefaultSyncSource(This) (This)->lpVtbl->SetDefaultSyncSource(This) -#endif -#endif - HRESULT WINAPI IFilterGraph_AddFilter_Proxy(IFilterGraph *This,IBaseFilter *pFilter,LPCWSTR pName); - void __RPC_STUB IFilterGraph_AddFilter_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IFilterGraph_RemoveFilter_Proxy(IFilterGraph *This,IBaseFilter *pFilter); - void __RPC_STUB IFilterGraph_RemoveFilter_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IFilterGraph_EnumFilters_Proxy(IFilterGraph *This,IEnumFilters **ppEnum); - void __RPC_STUB IFilterGraph_EnumFilters_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IFilterGraph_FindFilterByName_Proxy(IFilterGraph *This,LPCWSTR pName,IBaseFilter **ppFilter); - void __RPC_STUB IFilterGraph_FindFilterByName_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IFilterGraph_ConnectDirect_Proxy(IFilterGraph *This,IPin *ppinOut,IPin *ppinIn,const AM_MEDIA_TYPE *pmt); - void __RPC_STUB IFilterGraph_ConnectDirect_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IFilterGraph_Reconnect_Proxy(IFilterGraph *This,IPin *ppin); - void __RPC_STUB IFilterGraph_Reconnect_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IFilterGraph_Disconnect_Proxy(IFilterGraph *This,IPin *ppin); - void __RPC_STUB IFilterGraph_Disconnect_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IFilterGraph_SetDefaultSyncSource_Proxy(IFilterGraph *This); - void __RPC_STUB IFilterGraph_SetDefaultSyncSource_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - typedef IFilterGraph *PFILTERGRAPH; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0121_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0121_v0_0_s_ifspec; -#ifndef __IEnumFilters_INTERFACE_DEFINED__ -#define __IEnumFilters_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IEnumFilters; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IEnumFilters : public IUnknown { - public: - virtual HRESULT WINAPI Next(ULONG cFilters,IBaseFilter **ppFilter,ULONG *pcFetched) = 0; - virtual HRESULT WINAPI Skip(ULONG cFilters) = 0; - virtual HRESULT WINAPI Reset(void) = 0; - virtual HRESULT WINAPI Clone(IEnumFilters **ppEnum) = 0; - }; -#else - typedef struct IEnumFiltersVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IEnumFilters *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IEnumFilters *This); - ULONG (WINAPI *Release)(IEnumFilters *This); - HRESULT (WINAPI *Next)(IEnumFilters *This,ULONG cFilters,IBaseFilter **ppFilter,ULONG *pcFetched); - HRESULT (WINAPI *Skip)(IEnumFilters *This,ULONG cFilters); - HRESULT (WINAPI *Reset)(IEnumFilters *This); - HRESULT (WINAPI *Clone)(IEnumFilters *This,IEnumFilters **ppEnum); - END_INTERFACE - } IEnumFiltersVtbl; - struct IEnumFilters { - CONST_VTBL struct IEnumFiltersVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IEnumFilters_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IEnumFilters_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IEnumFilters_Release(This) (This)->lpVtbl->Release(This) -#define IEnumFilters_Next(This,cFilters,ppFilter,pcFetched) (This)->lpVtbl->Next(This,cFilters,ppFilter,pcFetched) -#define IEnumFilters_Skip(This,cFilters) (This)->lpVtbl->Skip(This,cFilters) -#define IEnumFilters_Reset(This) (This)->lpVtbl->Reset(This) -#define IEnumFilters_Clone(This,ppEnum) (This)->lpVtbl->Clone(This,ppEnum) -#endif -#endif - HRESULT WINAPI IEnumFilters_Next_Proxy(IEnumFilters *This,ULONG cFilters,IBaseFilter **ppFilter,ULONG *pcFetched); - void __RPC_STUB IEnumFilters_Next_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IEnumFilters_Skip_Proxy(IEnumFilters *This,ULONG cFilters); - void __RPC_STUB IEnumFilters_Skip_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IEnumFilters_Reset_Proxy(IEnumFilters *This); - void __RPC_STUB IEnumFilters_Reset_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IEnumFilters_Clone_Proxy(IEnumFilters *This,IEnumFilters **ppEnum); - void __RPC_STUB IEnumFilters_Clone_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - typedef IEnumFilters *PENUMFILTERS; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0122_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0122_v0_0_s_ifspec; -#ifndef __IMediaFilter_INTERFACE_DEFINED__ -#define __IMediaFilter_INTERFACE_DEFINED__ - typedef enum _FilterState { - State_Stopped = 0,State_Paused,State_Running - } FILTER_STATE; - - EXTERN_C const IID IID_IMediaFilter; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IMediaFilter : public IPersist { - public: - virtual HRESULT WINAPI Stop(void) = 0; - virtual HRESULT WINAPI Pause(void) = 0; - virtual HRESULT WINAPI Run(REFERENCE_TIME tStart) = 0; - virtual HRESULT WINAPI GetState(DWORD dwMilliSecsTimeout,FILTER_STATE *State) = 0; - virtual HRESULT WINAPI SetSyncSource(IReferenceClock *pClock) = 0; - virtual HRESULT WINAPI GetSyncSource(IReferenceClock **pClock) = 0; - }; -#else - typedef struct IMediaFilterVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IMediaFilter *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IMediaFilter *This); - ULONG (WINAPI *Release)(IMediaFilter *This); - HRESULT (WINAPI *GetClassID)(IMediaFilter *This,CLSID *pClassID); - HRESULT (WINAPI *Stop)(IMediaFilter *This); - HRESULT (WINAPI *Pause)(IMediaFilter *This); - HRESULT (WINAPI *Run)(IMediaFilter *This,REFERENCE_TIME tStart); - HRESULT (WINAPI *GetState)(IMediaFilter *This,DWORD dwMilliSecsTimeout,FILTER_STATE *State); - HRESULT (WINAPI *SetSyncSource)(IMediaFilter *This,IReferenceClock *pClock); - HRESULT (WINAPI *GetSyncSource)(IMediaFilter *This,IReferenceClock **pClock); - END_INTERFACE - } IMediaFilterVtbl; - struct IMediaFilter { - CONST_VTBL struct IMediaFilterVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IMediaFilter_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IMediaFilter_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IMediaFilter_Release(This) (This)->lpVtbl->Release(This) -#define IMediaFilter_GetClassID(This,pClassID) (This)->lpVtbl->GetClassID(This,pClassID) -#define IMediaFilter_Stop(This) (This)->lpVtbl->Stop(This) -#define IMediaFilter_Pause(This) (This)->lpVtbl->Pause(This) -#define IMediaFilter_Run(This,tStart) (This)->lpVtbl->Run(This,tStart) -#define IMediaFilter_GetState(This,dwMilliSecsTimeout,State) (This)->lpVtbl->GetState(This,dwMilliSecsTimeout,State) -#define IMediaFilter_SetSyncSource(This,pClock) (This)->lpVtbl->SetSyncSource(This,pClock) -#define IMediaFilter_GetSyncSource(This,pClock) (This)->lpVtbl->GetSyncSource(This,pClock) -#endif -#endif - HRESULT WINAPI IMediaFilter_Stop_Proxy(IMediaFilter *This); - void __RPC_STUB IMediaFilter_Stop_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMediaFilter_Pause_Proxy(IMediaFilter *This); - void __RPC_STUB IMediaFilter_Pause_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMediaFilter_Run_Proxy(IMediaFilter *This,REFERENCE_TIME tStart); - void __RPC_STUB IMediaFilter_Run_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMediaFilter_GetState_Proxy(IMediaFilter *This,DWORD dwMilliSecsTimeout,FILTER_STATE *State); - void __RPC_STUB IMediaFilter_GetState_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMediaFilter_SetSyncSource_Proxy(IMediaFilter *This,IReferenceClock *pClock); - void __RPC_STUB IMediaFilter_SetSyncSource_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMediaFilter_GetSyncSource_Proxy(IMediaFilter *This,IReferenceClock **pClock); - void __RPC_STUB IMediaFilter_GetSyncSource_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - typedef IMediaFilter *PMEDIAFILTER; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0123_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0123_v0_0_s_ifspec; -#ifndef __IBaseFilter_INTERFACE_DEFINED__ -#define __IBaseFilter_INTERFACE_DEFINED__ - - typedef struct _FilterInfo { - WCHAR achName[128]; - IFilterGraph *pGraph; - } FILTER_INFO; - - EXTERN_C const IID IID_IBaseFilter; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IBaseFilter : public IMediaFilter { - public: - virtual HRESULT WINAPI EnumPins(IEnumPins **ppEnum) = 0; - virtual HRESULT WINAPI FindPin(LPCWSTR Id,IPin **ppPin) = 0; - virtual HRESULT WINAPI QueryFilterInfo(FILTER_INFO *pInfo) = 0; - virtual HRESULT WINAPI JoinFilterGraph(IFilterGraph *pGraph,LPCWSTR pName) = 0; - virtual HRESULT WINAPI QueryVendorInfo(LPWSTR *pVendorInfo) = 0; - }; -#else - typedef struct IBaseFilterVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IBaseFilter *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IBaseFilter *This); - ULONG (WINAPI *Release)(IBaseFilter *This); - HRESULT (WINAPI *GetClassID)(IBaseFilter *This,CLSID *pClassID); - HRESULT (WINAPI *Stop)(IBaseFilter *This); - HRESULT (WINAPI *Pause)(IBaseFilter *This); - HRESULT (WINAPI *Run)(IBaseFilter *This,REFERENCE_TIME tStart); - HRESULT (WINAPI *GetState)(IBaseFilter *This,DWORD dwMilliSecsTimeout,FILTER_STATE *State); - HRESULT (WINAPI *SetSyncSource)(IBaseFilter *This,IReferenceClock *pClock); - HRESULT (WINAPI *GetSyncSource)(IBaseFilter *This,IReferenceClock **pClock); - HRESULT (WINAPI *EnumPins)(IBaseFilter *This,IEnumPins **ppEnum); - HRESULT (WINAPI *FindPin)(IBaseFilter *This,LPCWSTR Id,IPin **ppPin); - HRESULT (WINAPI *QueryFilterInfo)(IBaseFilter *This,FILTER_INFO *pInfo); - HRESULT (WINAPI *JoinFilterGraph)(IBaseFilter *This,IFilterGraph *pGraph,LPCWSTR pName); - HRESULT (WINAPI *QueryVendorInfo)(IBaseFilter *This,LPWSTR *pVendorInfo); - END_INTERFACE - } IBaseFilterVtbl; - struct IBaseFilter { - CONST_VTBL struct IBaseFilterVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IBaseFilter_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IBaseFilter_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IBaseFilter_Release(This) (This)->lpVtbl->Release(This) -#define IBaseFilter_GetClassID(This,pClassID) (This)->lpVtbl->GetClassID(This,pClassID) -#define IBaseFilter_Stop(This) (This)->lpVtbl->Stop(This) -#define IBaseFilter_Pause(This) (This)->lpVtbl->Pause(This) -#define IBaseFilter_Run(This,tStart) (This)->lpVtbl->Run(This,tStart) -#define IBaseFilter_GetState(This,dwMilliSecsTimeout,State) (This)->lpVtbl->GetState(This,dwMilliSecsTimeout,State) -#define IBaseFilter_SetSyncSource(This,pClock) (This)->lpVtbl->SetSyncSource(This,pClock) -#define IBaseFilter_GetSyncSource(This,pClock) (This)->lpVtbl->GetSyncSource(This,pClock) -#define IBaseFilter_EnumPins(This,ppEnum) (This)->lpVtbl->EnumPins(This,ppEnum) -#define IBaseFilter_FindPin(This,Id,ppPin) (This)->lpVtbl->FindPin(This,Id,ppPin) -#define IBaseFilter_QueryFilterInfo(This,pInfo) (This)->lpVtbl->QueryFilterInfo(This,pInfo) -#define IBaseFilter_JoinFilterGraph(This,pGraph,pName) (This)->lpVtbl->JoinFilterGraph(This,pGraph,pName) -#define IBaseFilter_QueryVendorInfo(This,pVendorInfo) (This)->lpVtbl->QueryVendorInfo(This,pVendorInfo) -#endif -#endif - HRESULT WINAPI IBaseFilter_EnumPins_Proxy(IBaseFilter *This,IEnumPins **ppEnum); - void __RPC_STUB IBaseFilter_EnumPins_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IBaseFilter_FindPin_Proxy(IBaseFilter *This,LPCWSTR Id,IPin **ppPin); - void __RPC_STUB IBaseFilter_FindPin_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IBaseFilter_QueryFilterInfo_Proxy(IBaseFilter *This,FILTER_INFO *pInfo); - void __RPC_STUB IBaseFilter_QueryFilterInfo_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IBaseFilter_JoinFilterGraph_Proxy(IBaseFilter *This,IFilterGraph *pGraph,LPCWSTR pName); - void __RPC_STUB IBaseFilter_JoinFilterGraph_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IBaseFilter_QueryVendorInfo_Proxy(IBaseFilter *This,LPWSTR *pVendorInfo); - void __RPC_STUB IBaseFilter_QueryVendorInfo_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - typedef IBaseFilter *PFILTER; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0124_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0124_v0_0_s_ifspec; -#ifndef __IReferenceClock_INTERFACE_DEFINED__ -#define __IReferenceClock_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IReferenceClock; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IReferenceClock : public IUnknown { - public: - virtual HRESULT WINAPI GetTime(REFERENCE_TIME *pTime) = 0; - virtual HRESULT WINAPI AdviseTime(REFERENCE_TIME baseTime,REFERENCE_TIME streamTime,HEVENT hEvent,DWORD_PTR *pdwAdviseCookie) = 0; - virtual HRESULT WINAPI AdvisePeriodic(REFERENCE_TIME startTime,REFERENCE_TIME periodTime,HSEMAPHORE hSemaphore,DWORD_PTR *pdwAdviseCookie) = 0; - virtual HRESULT WINAPI Unadvise(DWORD_PTR dwAdviseCookie) = 0; - }; -#else - typedef struct IReferenceClockVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IReferenceClock *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IReferenceClock *This); - ULONG (WINAPI *Release)(IReferenceClock *This); - HRESULT (WINAPI *GetTime)(IReferenceClock *This,REFERENCE_TIME *pTime); - HRESULT (WINAPI *AdviseTime)(IReferenceClock *This,REFERENCE_TIME baseTime,REFERENCE_TIME streamTime,HEVENT hEvent,DWORD_PTR *pdwAdviseCookie); - HRESULT (WINAPI *AdvisePeriodic)(IReferenceClock *This,REFERENCE_TIME startTime,REFERENCE_TIME periodTime,HSEMAPHORE hSemaphore,DWORD_PTR *pdwAdviseCookie); - HRESULT (WINAPI *Unadvise)(IReferenceClock *This,DWORD_PTR dwAdviseCookie); - END_INTERFACE - } IReferenceClockVtbl; - struct IReferenceClock { - CONST_VTBL struct IReferenceClockVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IReferenceClock_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IReferenceClock_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IReferenceClock_Release(This) (This)->lpVtbl->Release(This) -#define IReferenceClock_GetTime(This,pTime) (This)->lpVtbl->GetTime(This,pTime) -#define IReferenceClock_AdviseTime(This,baseTime,streamTime,hEvent,pdwAdviseCookie) (This)->lpVtbl->AdviseTime(This,baseTime,streamTime,hEvent,pdwAdviseCookie) -#define IReferenceClock_AdvisePeriodic(This,startTime,periodTime,hSemaphore,pdwAdviseCookie) (This)->lpVtbl->AdvisePeriodic(This,startTime,periodTime,hSemaphore,pdwAdviseCookie) -#define IReferenceClock_Unadvise(This,dwAdviseCookie) (This)->lpVtbl->Unadvise(This,dwAdviseCookie) -#endif -#endif - HRESULT WINAPI IReferenceClock_GetTime_Proxy(IReferenceClock *This,REFERENCE_TIME *pTime); - void __RPC_STUB IReferenceClock_GetTime_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IReferenceClock_AdviseTime_Proxy(IReferenceClock *This,REFERENCE_TIME baseTime,REFERENCE_TIME streamTime,HEVENT hEvent,DWORD_PTR *pdwAdviseCookie); - void __RPC_STUB IReferenceClock_AdviseTime_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IReferenceClock_AdvisePeriodic_Proxy(IReferenceClock *This,REFERENCE_TIME startTime,REFERENCE_TIME periodTime,HSEMAPHORE hSemaphore,DWORD_PTR *pdwAdviseCookie); - void __RPC_STUB IReferenceClock_AdvisePeriodic_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IReferenceClock_Unadvise_Proxy(IReferenceClock *This,DWORD_PTR dwAdviseCookie); - void __RPC_STUB IReferenceClock_Unadvise_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - typedef IReferenceClock *PREFERENCECLOCK; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0125_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0125_v0_0_s_ifspec; -#ifndef __IReferenceClock2_INTERFACE_DEFINED__ -#define __IReferenceClock2_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IReferenceClock2; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IReferenceClock2 : public IReferenceClock { - }; -#else - typedef struct IReferenceClock2Vtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IReferenceClock2 *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IReferenceClock2 *This); - ULONG (WINAPI *Release)(IReferenceClock2 *This); - HRESULT (WINAPI *GetTime)(IReferenceClock2 *This,REFERENCE_TIME *pTime); - HRESULT (WINAPI *AdviseTime)(IReferenceClock2 *This,REFERENCE_TIME baseTime,REFERENCE_TIME streamTime,HEVENT hEvent,DWORD_PTR *pdwAdviseCookie); - HRESULT (WINAPI *AdvisePeriodic)(IReferenceClock2 *This,REFERENCE_TIME startTime,REFERENCE_TIME periodTime,HSEMAPHORE hSemaphore,DWORD_PTR *pdwAdviseCookie); - HRESULT (WINAPI *Unadvise)(IReferenceClock2 *This,DWORD_PTR dwAdviseCookie); - END_INTERFACE - } IReferenceClock2Vtbl; - struct IReferenceClock2 { - CONST_VTBL struct IReferenceClock2Vtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IReferenceClock2_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IReferenceClock2_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IReferenceClock2_Release(This) (This)->lpVtbl->Release(This) -#define IReferenceClock2_GetTime(This,pTime) (This)->lpVtbl->GetTime(This,pTime) -#define IReferenceClock2_AdviseTime(This,baseTime,streamTime,hEvent,pdwAdviseCookie) (This)->lpVtbl->AdviseTime(This,baseTime,streamTime,hEvent,pdwAdviseCookie) -#define IReferenceClock2_AdvisePeriodic(This,startTime,periodTime,hSemaphore,pdwAdviseCookie) (This)->lpVtbl->AdvisePeriodic(This,startTime,periodTime,hSemaphore,pdwAdviseCookie) -#define IReferenceClock2_Unadvise(This,dwAdviseCookie) (This)->lpVtbl->Unadvise(This,dwAdviseCookie) -#endif -#endif -#endif - - typedef IReferenceClock2 *PREFERENCECLOCK2; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0126_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0126_v0_0_s_ifspec; -#ifndef __IMediaSample_INTERFACE_DEFINED__ -#define __IMediaSample_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IMediaSample; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IMediaSample : public IUnknown { - public: - virtual HRESULT WINAPI GetPointer(BYTE **ppBuffer) = 0; - virtual long WINAPI GetSize(void) = 0; - virtual HRESULT WINAPI GetTime(REFERENCE_TIME *pTimeStart,REFERENCE_TIME *pTimeEnd) = 0; - virtual HRESULT WINAPI SetTime(REFERENCE_TIME *pTimeStart,REFERENCE_TIME *pTimeEnd) = 0; - virtual HRESULT WINAPI IsSyncPoint(void) = 0; - virtual HRESULT WINAPI SetSyncPoint(WINBOOL bIsSyncPoint) = 0; - virtual HRESULT WINAPI IsPreroll(void) = 0; - virtual HRESULT WINAPI SetPreroll(WINBOOL bIsPreroll) = 0; - virtual long WINAPI GetActualDataLength(void) = 0; - virtual HRESULT WINAPI SetActualDataLength(long __MIDL_0010) = 0; - virtual HRESULT WINAPI GetMediaType(AM_MEDIA_TYPE **ppMediaType) = 0; - virtual HRESULT WINAPI SetMediaType(AM_MEDIA_TYPE *pMediaType) = 0; - virtual HRESULT WINAPI IsDiscontinuity(void) = 0; - virtual HRESULT WINAPI SetDiscontinuity(WINBOOL bDiscontinuity) = 0; - virtual HRESULT WINAPI GetMediaTime(LONGLONG *pTimeStart,LONGLONG *pTimeEnd) = 0; - virtual HRESULT WINAPI SetMediaTime(LONGLONG *pTimeStart,LONGLONG *pTimeEnd) = 0; - }; -#else - typedef struct IMediaSampleVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IMediaSample *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IMediaSample *This); - ULONG (WINAPI *Release)(IMediaSample *This); - HRESULT (WINAPI *GetPointer)(IMediaSample *This,BYTE **ppBuffer); - long (WINAPI *GetSize)(IMediaSample *This); - HRESULT (WINAPI *GetTime)(IMediaSample *This,REFERENCE_TIME *pTimeStart,REFERENCE_TIME *pTimeEnd); - HRESULT (WINAPI *SetTime)(IMediaSample *This,REFERENCE_TIME *pTimeStart,REFERENCE_TIME *pTimeEnd); - HRESULT (WINAPI *IsSyncPoint)(IMediaSample *This); - HRESULT (WINAPI *SetSyncPoint)(IMediaSample *This,WINBOOL bIsSyncPoint); - HRESULT (WINAPI *IsPreroll)(IMediaSample *This); - HRESULT (WINAPI *SetPreroll)(IMediaSample *This,WINBOOL bIsPreroll); - long (WINAPI *GetActualDataLength)(IMediaSample *This); - HRESULT (WINAPI *SetActualDataLength)(IMediaSample *This,long __MIDL_0010); - HRESULT (WINAPI *GetMediaType)(IMediaSample *This,AM_MEDIA_TYPE **ppMediaType); - HRESULT (WINAPI *SetMediaType)(IMediaSample *This,AM_MEDIA_TYPE *pMediaType); - HRESULT (WINAPI *IsDiscontinuity)(IMediaSample *This); - HRESULT (WINAPI *SetDiscontinuity)(IMediaSample *This,WINBOOL bDiscontinuity); - HRESULT (WINAPI *GetMediaTime)(IMediaSample *This,LONGLONG *pTimeStart,LONGLONG *pTimeEnd); - HRESULT (WINAPI *SetMediaTime)(IMediaSample *This,LONGLONG *pTimeStart,LONGLONG *pTimeEnd); - END_INTERFACE - } IMediaSampleVtbl; - struct IMediaSample { - CONST_VTBL struct IMediaSampleVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IMediaSample_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IMediaSample_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IMediaSample_Release(This) (This)->lpVtbl->Release(This) -#define IMediaSample_GetPointer(This,ppBuffer) (This)->lpVtbl->GetPointer(This,ppBuffer) -#define IMediaSample_GetSize(This) (This)->lpVtbl->GetSize(This) -#define IMediaSample_GetTime(This,pTimeStart,pTimeEnd) (This)->lpVtbl->GetTime(This,pTimeStart,pTimeEnd) -#define IMediaSample_SetTime(This,pTimeStart,pTimeEnd) (This)->lpVtbl->SetTime(This,pTimeStart,pTimeEnd) -#define IMediaSample_IsSyncPoint(This) (This)->lpVtbl->IsSyncPoint(This) -#define IMediaSample_SetSyncPoint(This,bIsSyncPoint) (This)->lpVtbl->SetSyncPoint(This,bIsSyncPoint) -#define IMediaSample_IsPreroll(This) (This)->lpVtbl->IsPreroll(This) -#define IMediaSample_SetPreroll(This,bIsPreroll) (This)->lpVtbl->SetPreroll(This,bIsPreroll) -#define IMediaSample_GetActualDataLength(This) (This)->lpVtbl->GetActualDataLength(This) -#define IMediaSample_SetActualDataLength(This,__MIDL_0010) (This)->lpVtbl->SetActualDataLength(This,__MIDL_0010) -#define IMediaSample_GetMediaType(This,ppMediaType) (This)->lpVtbl->GetMediaType(This,ppMediaType) -#define IMediaSample_SetMediaType(This,pMediaType) (This)->lpVtbl->SetMediaType(This,pMediaType) -#define IMediaSample_IsDiscontinuity(This) (This)->lpVtbl->IsDiscontinuity(This) -#define IMediaSample_SetDiscontinuity(This,bDiscontinuity) (This)->lpVtbl->SetDiscontinuity(This,bDiscontinuity) -#define IMediaSample_GetMediaTime(This,pTimeStart,pTimeEnd) (This)->lpVtbl->GetMediaTime(This,pTimeStart,pTimeEnd) -#define IMediaSample_SetMediaTime(This,pTimeStart,pTimeEnd) (This)->lpVtbl->SetMediaTime(This,pTimeStart,pTimeEnd) -#endif -#endif - HRESULT WINAPI IMediaSample_GetPointer_Proxy(IMediaSample *This,BYTE **ppBuffer); - void __RPC_STUB IMediaSample_GetPointer_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - long WINAPI IMediaSample_GetSize_Proxy(IMediaSample *This); - void __RPC_STUB IMediaSample_GetSize_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMediaSample_GetTime_Proxy(IMediaSample *This,REFERENCE_TIME *pTimeStart,REFERENCE_TIME *pTimeEnd); - void __RPC_STUB IMediaSample_GetTime_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMediaSample_SetTime_Proxy(IMediaSample *This,REFERENCE_TIME *pTimeStart,REFERENCE_TIME *pTimeEnd); - void __RPC_STUB IMediaSample_SetTime_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMediaSample_IsSyncPoint_Proxy(IMediaSample *This); - void __RPC_STUB IMediaSample_IsSyncPoint_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMediaSample_SetSyncPoint_Proxy(IMediaSample *This,WINBOOL bIsSyncPoint); - void __RPC_STUB IMediaSample_SetSyncPoint_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMediaSample_IsPreroll_Proxy(IMediaSample *This); - void __RPC_STUB IMediaSample_IsPreroll_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMediaSample_SetPreroll_Proxy(IMediaSample *This,WINBOOL bIsPreroll); - void __RPC_STUB IMediaSample_SetPreroll_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - long WINAPI IMediaSample_GetActualDataLength_Proxy(IMediaSample *This); - void __RPC_STUB IMediaSample_GetActualDataLength_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMediaSample_SetActualDataLength_Proxy(IMediaSample *This,long __MIDL_0010); - void __RPC_STUB IMediaSample_SetActualDataLength_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMediaSample_GetMediaType_Proxy(IMediaSample *This,AM_MEDIA_TYPE **ppMediaType); - void __RPC_STUB IMediaSample_GetMediaType_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMediaSample_SetMediaType_Proxy(IMediaSample *This,AM_MEDIA_TYPE *pMediaType); - void __RPC_STUB IMediaSample_SetMediaType_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMediaSample_IsDiscontinuity_Proxy(IMediaSample *This); - void __RPC_STUB IMediaSample_IsDiscontinuity_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMediaSample_SetDiscontinuity_Proxy(IMediaSample *This,WINBOOL bDiscontinuity); - void __RPC_STUB IMediaSample_SetDiscontinuity_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMediaSample_GetMediaTime_Proxy(IMediaSample *This,LONGLONG *pTimeStart,LONGLONG *pTimeEnd); - void __RPC_STUB IMediaSample_GetMediaTime_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMediaSample_SetMediaTime_Proxy(IMediaSample *This,LONGLONG *pTimeStart,LONGLONG *pTimeEnd); - void __RPC_STUB IMediaSample_SetMediaTime_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - typedef IMediaSample *PMEDIASAMPLE; - - enum tagAM_SAMPLE_PROPERTY_FLAGS { - AM_SAMPLE_SPLICEPOINT = 0x1,AM_SAMPLE_PREROLL = 0x2,AM_SAMPLE_DATADISCONTINUITY = 0x4,AM_SAMPLE_TYPECHANGED = 0x8,AM_SAMPLE_TIMEVALID = 0x10, - AM_SAMPLE_TIMEDISCONTINUITY = 0x40,AM_SAMPLE_FLUSH_ON_PAUSE = 0x80,AM_SAMPLE_STOPVALID = 0x100,AM_SAMPLE_ENDOFSTREAM = 0x200,AM_STREAM_MEDIA = 0, - AM_STREAM_CONTROL = 1 - }; - typedef struct tagAM_SAMPLE2_PROPERTIES { - DWORD cbData; - DWORD dwTypeSpecificFlags; - DWORD dwSampleFlags; - LONG lActual; - REFERENCE_TIME tStart; - REFERENCE_TIME tStop; - DWORD dwStreamId; - AM_MEDIA_TYPE *pMediaType; - BYTE *pbBuffer; - LONG cbBuffer; - } AM_SAMPLE2_PROPERTIES; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0127_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0127_v0_0_s_ifspec; -#ifndef __IMediaSample2_INTERFACE_DEFINED__ -#define __IMediaSample2_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IMediaSample2; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IMediaSample2 : public IMediaSample { - public: - virtual HRESULT WINAPI GetProperties(DWORD cbProperties,BYTE *pbProperties) = 0; - virtual HRESULT WINAPI SetProperties(DWORD cbProperties,const BYTE *pbProperties) = 0; - }; -#else - typedef struct IMediaSample2Vtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IMediaSample2 *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IMediaSample2 *This); - ULONG (WINAPI *Release)(IMediaSample2 *This); - HRESULT (WINAPI *GetPointer)(IMediaSample2 *This,BYTE **ppBuffer); - long (WINAPI *GetSize)(IMediaSample2 *This); - HRESULT (WINAPI *GetTime)(IMediaSample2 *This,REFERENCE_TIME *pTimeStart,REFERENCE_TIME *pTimeEnd); - HRESULT (WINAPI *SetTime)(IMediaSample2 *This,REFERENCE_TIME *pTimeStart,REFERENCE_TIME *pTimeEnd); - HRESULT (WINAPI *IsSyncPoint)(IMediaSample2 *This); - HRESULT (WINAPI *SetSyncPoint)(IMediaSample2 *This,WINBOOL bIsSyncPoint); - HRESULT (WINAPI *IsPreroll)(IMediaSample2 *This); - HRESULT (WINAPI *SetPreroll)(IMediaSample2 *This,WINBOOL bIsPreroll); - long (WINAPI *GetActualDataLength)(IMediaSample2 *This); - HRESULT (WINAPI *SetActualDataLength)(IMediaSample2 *This,long __MIDL_0010); - HRESULT (WINAPI *GetMediaType)(IMediaSample2 *This,AM_MEDIA_TYPE **ppMediaType); - HRESULT (WINAPI *SetMediaType)(IMediaSample2 *This,AM_MEDIA_TYPE *pMediaType); - HRESULT (WINAPI *IsDiscontinuity)(IMediaSample2 *This); - HRESULT (WINAPI *SetDiscontinuity)(IMediaSample2 *This,WINBOOL bDiscontinuity); - HRESULT (WINAPI *GetMediaTime)(IMediaSample2 *This,LONGLONG *pTimeStart,LONGLONG *pTimeEnd); - HRESULT (WINAPI *SetMediaTime)(IMediaSample2 *This,LONGLONG *pTimeStart,LONGLONG *pTimeEnd); - HRESULT (WINAPI *GetProperties)(IMediaSample2 *This,DWORD cbProperties,BYTE *pbProperties); - HRESULT (WINAPI *SetProperties)(IMediaSample2 *This,DWORD cbProperties,const BYTE *pbProperties); - END_INTERFACE - } IMediaSample2Vtbl; - struct IMediaSample2 { - CONST_VTBL struct IMediaSample2Vtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IMediaSample2_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IMediaSample2_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IMediaSample2_Release(This) (This)->lpVtbl->Release(This) -#define IMediaSample2_GetPointer(This,ppBuffer) (This)->lpVtbl->GetPointer(This,ppBuffer) -#define IMediaSample2_GetSize(This) (This)->lpVtbl->GetSize(This) -#define IMediaSample2_GetTime(This,pTimeStart,pTimeEnd) (This)->lpVtbl->GetTime(This,pTimeStart,pTimeEnd) -#define IMediaSample2_SetTime(This,pTimeStart,pTimeEnd) (This)->lpVtbl->SetTime(This,pTimeStart,pTimeEnd) -#define IMediaSample2_IsSyncPoint(This) (This)->lpVtbl->IsSyncPoint(This) -#define IMediaSample2_SetSyncPoint(This,bIsSyncPoint) (This)->lpVtbl->SetSyncPoint(This,bIsSyncPoint) -#define IMediaSample2_IsPreroll(This) (This)->lpVtbl->IsPreroll(This) -#define IMediaSample2_SetPreroll(This,bIsPreroll) (This)->lpVtbl->SetPreroll(This,bIsPreroll) -#define IMediaSample2_GetActualDataLength(This) (This)->lpVtbl->GetActualDataLength(This) -#define IMediaSample2_SetActualDataLength(This,__MIDL_0010) (This)->lpVtbl->SetActualDataLength(This,__MIDL_0010) -#define IMediaSample2_GetMediaType(This,ppMediaType) (This)->lpVtbl->GetMediaType(This,ppMediaType) -#define IMediaSample2_SetMediaType(This,pMediaType) (This)->lpVtbl->SetMediaType(This,pMediaType) -#define IMediaSample2_IsDiscontinuity(This) (This)->lpVtbl->IsDiscontinuity(This) -#define IMediaSample2_SetDiscontinuity(This,bDiscontinuity) (This)->lpVtbl->SetDiscontinuity(This,bDiscontinuity) -#define IMediaSample2_GetMediaTime(This,pTimeStart,pTimeEnd) (This)->lpVtbl->GetMediaTime(This,pTimeStart,pTimeEnd) -#define IMediaSample2_SetMediaTime(This,pTimeStart,pTimeEnd) (This)->lpVtbl->SetMediaTime(This,pTimeStart,pTimeEnd) -#define IMediaSample2_GetProperties(This,cbProperties,pbProperties) (This)->lpVtbl->GetProperties(This,cbProperties,pbProperties) -#define IMediaSample2_SetProperties(This,cbProperties,pbProperties) (This)->lpVtbl->SetProperties(This,cbProperties,pbProperties) -#endif -#endif - HRESULT WINAPI IMediaSample2_GetProperties_Proxy(IMediaSample2 *This,DWORD cbProperties,BYTE *pbProperties); - void __RPC_STUB IMediaSample2_GetProperties_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMediaSample2_SetProperties_Proxy(IMediaSample2 *This,DWORD cbProperties,const BYTE *pbProperties); - void __RPC_STUB IMediaSample2_SetProperties_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - typedef IMediaSample2 *PMEDIASAMPLE2; - -#define AM_GBF_PREVFRAMESKIPPED 1 -#define AM_GBF_NOTASYNCPOINT 2 -#define AM_GBF_NOWAIT 4 -#define AM_GBF_NODDSURFACELOCK 8 - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0128_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0128_v0_0_s_ifspec; -#ifndef __IMemAllocator_INTERFACE_DEFINED__ -#define __IMemAllocator_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IMemAllocator; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IMemAllocator : public IUnknown { - public: - virtual HRESULT WINAPI SetProperties(ALLOCATOR_PROPERTIES *pRequest,ALLOCATOR_PROPERTIES *pActual) = 0; - virtual HRESULT WINAPI GetProperties(ALLOCATOR_PROPERTIES *pProps) = 0; - virtual HRESULT WINAPI Commit(void) = 0; - virtual HRESULT WINAPI Decommit(void) = 0; - virtual HRESULT WINAPI GetBuffer(IMediaSample **ppBuffer,REFERENCE_TIME *pStartTime,REFERENCE_TIME *pEndTime,DWORD dwFlags) = 0; - virtual HRESULT WINAPI ReleaseBuffer(IMediaSample *pBuffer) = 0; - }; -#else - typedef struct IMemAllocatorVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IMemAllocator *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IMemAllocator *This); - ULONG (WINAPI *Release)(IMemAllocator *This); - HRESULT (WINAPI *SetProperties)(IMemAllocator *This,ALLOCATOR_PROPERTIES *pRequest,ALLOCATOR_PROPERTIES *pActual); - HRESULT (WINAPI *GetProperties)(IMemAllocator *This,ALLOCATOR_PROPERTIES *pProps); - HRESULT (WINAPI *Commit)(IMemAllocator *This); - HRESULT (WINAPI *Decommit)(IMemAllocator *This); - HRESULT (WINAPI *GetBuffer)(IMemAllocator *This,IMediaSample **ppBuffer,REFERENCE_TIME *pStartTime,REFERENCE_TIME *pEndTime,DWORD dwFlags); - HRESULT (WINAPI *ReleaseBuffer)(IMemAllocator *This,IMediaSample *pBuffer); - END_INTERFACE - } IMemAllocatorVtbl; - struct IMemAllocator { - CONST_VTBL struct IMemAllocatorVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IMemAllocator_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IMemAllocator_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IMemAllocator_Release(This) (This)->lpVtbl->Release(This) -#define IMemAllocator_SetProperties(This,pRequest,pActual) (This)->lpVtbl->SetProperties(This,pRequest,pActual) -#define IMemAllocator_GetProperties(This,pProps) (This)->lpVtbl->GetProperties(This,pProps) -#define IMemAllocator_Commit(This) (This)->lpVtbl->Commit(This) -#define IMemAllocator_Decommit(This) (This)->lpVtbl->Decommit(This) -#define IMemAllocator_GetBuffer(This,ppBuffer,pStartTime,pEndTime,dwFlags) (This)->lpVtbl->GetBuffer(This,ppBuffer,pStartTime,pEndTime,dwFlags) -#define IMemAllocator_ReleaseBuffer(This,pBuffer) (This)->lpVtbl->ReleaseBuffer(This,pBuffer) -#endif -#endif - HRESULT WINAPI IMemAllocator_SetProperties_Proxy(IMemAllocator *This,ALLOCATOR_PROPERTIES *pRequest,ALLOCATOR_PROPERTIES *pActual); - void __RPC_STUB IMemAllocator_SetProperties_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMemAllocator_GetProperties_Proxy(IMemAllocator *This,ALLOCATOR_PROPERTIES *pProps); - void __RPC_STUB IMemAllocator_GetProperties_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMemAllocator_Commit_Proxy(IMemAllocator *This); - void __RPC_STUB IMemAllocator_Commit_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMemAllocator_Decommit_Proxy(IMemAllocator *This); - void __RPC_STUB IMemAllocator_Decommit_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMemAllocator_GetBuffer_Proxy(IMemAllocator *This,IMediaSample **ppBuffer,REFERENCE_TIME *pStartTime,REFERENCE_TIME *pEndTime,DWORD dwFlags); - void __RPC_STUB IMemAllocator_GetBuffer_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMemAllocator_ReleaseBuffer_Proxy(IMemAllocator *This,IMediaSample *pBuffer); - void __RPC_STUB IMemAllocator_ReleaseBuffer_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - typedef IMemAllocator *PMEMALLOCATOR; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0129_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0129_v0_0_s_ifspec; -#ifndef __IMemAllocatorCallbackTemp_INTERFACE_DEFINED__ -#define __IMemAllocatorCallbackTemp_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IMemAllocatorCallbackTemp; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IMemAllocatorCallbackTemp : public IMemAllocator { - public: - virtual HRESULT WINAPI SetNotify(IMemAllocatorNotifyCallbackTemp *pNotify) = 0; - virtual HRESULT WINAPI GetFreeCount(LONG *plBuffersFree) = 0; - }; -#else - typedef struct IMemAllocatorCallbackTempVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IMemAllocatorCallbackTemp *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IMemAllocatorCallbackTemp *This); - ULONG (WINAPI *Release)(IMemAllocatorCallbackTemp *This); - HRESULT (WINAPI *SetProperties)(IMemAllocatorCallbackTemp *This,ALLOCATOR_PROPERTIES *pRequest,ALLOCATOR_PROPERTIES *pActual); - HRESULT (WINAPI *GetProperties)(IMemAllocatorCallbackTemp *This,ALLOCATOR_PROPERTIES *pProps); - HRESULT (WINAPI *Commit)(IMemAllocatorCallbackTemp *This); - HRESULT (WINAPI *Decommit)(IMemAllocatorCallbackTemp *This); - HRESULT (WINAPI *GetBuffer)(IMemAllocatorCallbackTemp *This,IMediaSample **ppBuffer,REFERENCE_TIME *pStartTime,REFERENCE_TIME *pEndTime,DWORD dwFlags); - HRESULT (WINAPI *ReleaseBuffer)(IMemAllocatorCallbackTemp *This,IMediaSample *pBuffer); - HRESULT (WINAPI *SetNotify)(IMemAllocatorCallbackTemp *This,IMemAllocatorNotifyCallbackTemp *pNotify); - HRESULT (WINAPI *GetFreeCount)(IMemAllocatorCallbackTemp *This,LONG *plBuffersFree); - END_INTERFACE - } IMemAllocatorCallbackTempVtbl; - struct IMemAllocatorCallbackTemp { - CONST_VTBL struct IMemAllocatorCallbackTempVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IMemAllocatorCallbackTemp_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IMemAllocatorCallbackTemp_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IMemAllocatorCallbackTemp_Release(This) (This)->lpVtbl->Release(This) -#define IMemAllocatorCallbackTemp_SetProperties(This,pRequest,pActual) (This)->lpVtbl->SetProperties(This,pRequest,pActual) -#define IMemAllocatorCallbackTemp_GetProperties(This,pProps) (This)->lpVtbl->GetProperties(This,pProps) -#define IMemAllocatorCallbackTemp_Commit(This) (This)->lpVtbl->Commit(This) -#define IMemAllocatorCallbackTemp_Decommit(This) (This)->lpVtbl->Decommit(This) -#define IMemAllocatorCallbackTemp_GetBuffer(This,ppBuffer,pStartTime,pEndTime,dwFlags) (This)->lpVtbl->GetBuffer(This,ppBuffer,pStartTime,pEndTime,dwFlags) -#define IMemAllocatorCallbackTemp_ReleaseBuffer(This,pBuffer) (This)->lpVtbl->ReleaseBuffer(This,pBuffer) -#define IMemAllocatorCallbackTemp_SetNotify(This,pNotify) (This)->lpVtbl->SetNotify(This,pNotify) -#define IMemAllocatorCallbackTemp_GetFreeCount(This,plBuffersFree) (This)->lpVtbl->GetFreeCount(This,plBuffersFree) -#endif -#endif - HRESULT WINAPI IMemAllocatorCallbackTemp_SetNotify_Proxy(IMemAllocatorCallbackTemp *This,IMemAllocatorNotifyCallbackTemp *pNotify); - void __RPC_STUB IMemAllocatorCallbackTemp_SetNotify_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMemAllocatorCallbackTemp_GetFreeCount_Proxy(IMemAllocatorCallbackTemp *This,LONG *plBuffersFree); - void __RPC_STUB IMemAllocatorCallbackTemp_GetFreeCount_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IMemAllocatorNotifyCallbackTemp_INTERFACE_DEFINED__ -#define __IMemAllocatorNotifyCallbackTemp_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IMemAllocatorNotifyCallbackTemp; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IMemAllocatorNotifyCallbackTemp : public IUnknown { - public: - virtual HRESULT WINAPI NotifyRelease(void) = 0; - }; -#else - typedef struct IMemAllocatorNotifyCallbackTempVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IMemAllocatorNotifyCallbackTemp *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IMemAllocatorNotifyCallbackTemp *This); - ULONG (WINAPI *Release)(IMemAllocatorNotifyCallbackTemp *This); - HRESULT (WINAPI *NotifyRelease)(IMemAllocatorNotifyCallbackTemp *This); - END_INTERFACE - } IMemAllocatorNotifyCallbackTempVtbl; - struct IMemAllocatorNotifyCallbackTemp { - CONST_VTBL struct IMemAllocatorNotifyCallbackTempVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IMemAllocatorNotifyCallbackTemp_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IMemAllocatorNotifyCallbackTemp_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IMemAllocatorNotifyCallbackTemp_Release(This) (This)->lpVtbl->Release(This) -#define IMemAllocatorNotifyCallbackTemp_NotifyRelease(This) (This)->lpVtbl->NotifyRelease(This) -#endif -#endif - HRESULT WINAPI IMemAllocatorNotifyCallbackTemp_NotifyRelease_Proxy(IMemAllocatorNotifyCallbackTemp *This); - void __RPC_STUB IMemAllocatorNotifyCallbackTemp_NotifyRelease_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IMemInputPin_INTERFACE_DEFINED__ -#define __IMemInputPin_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IMemInputPin; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IMemInputPin : public IUnknown { - public: - virtual HRESULT WINAPI GetAllocator(IMemAllocator **ppAllocator) = 0; - virtual HRESULT WINAPI NotifyAllocator(IMemAllocator *pAllocator,WINBOOL bReadOnly) = 0; - virtual HRESULT WINAPI GetAllocatorRequirements(ALLOCATOR_PROPERTIES *pProps) = 0; - virtual HRESULT WINAPI Receive(IMediaSample *pSample) = 0; - virtual HRESULT WINAPI ReceiveMultiple(IMediaSample **pSamples,long nSamples,long *nSamplesProcessed) = 0; - virtual HRESULT WINAPI ReceiveCanBlock(void) = 0; - }; -#else - typedef struct IMemInputPinVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IMemInputPin *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IMemInputPin *This); - ULONG (WINAPI *Release)(IMemInputPin *This); - HRESULT (WINAPI *GetAllocator)(IMemInputPin *This,IMemAllocator **ppAllocator); - HRESULT (WINAPI *NotifyAllocator)(IMemInputPin *This,IMemAllocator *pAllocator,WINBOOL bReadOnly); - HRESULT (WINAPI *GetAllocatorRequirements)(IMemInputPin *This,ALLOCATOR_PROPERTIES *pProps); - HRESULT (WINAPI *Receive)(IMemInputPin *This,IMediaSample *pSample); - HRESULT (WINAPI *ReceiveMultiple)(IMemInputPin *This,IMediaSample **pSamples,long nSamples,long *nSamplesProcessed); - HRESULT (WINAPI *ReceiveCanBlock)(IMemInputPin *This); - END_INTERFACE - } IMemInputPinVtbl; - struct IMemInputPin { - CONST_VTBL struct IMemInputPinVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IMemInputPin_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IMemInputPin_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IMemInputPin_Release(This) (This)->lpVtbl->Release(This) -#define IMemInputPin_GetAllocator(This,ppAllocator) (This)->lpVtbl->GetAllocator(This,ppAllocator) -#define IMemInputPin_NotifyAllocator(This,pAllocator,bReadOnly) (This)->lpVtbl->NotifyAllocator(This,pAllocator,bReadOnly) -#define IMemInputPin_GetAllocatorRequirements(This,pProps) (This)->lpVtbl->GetAllocatorRequirements(This,pProps) -#define IMemInputPin_Receive(This,pSample) (This)->lpVtbl->Receive(This,pSample) -#define IMemInputPin_ReceiveMultiple(This,pSamples,nSamples,nSamplesProcessed) (This)->lpVtbl->ReceiveMultiple(This,pSamples,nSamples,nSamplesProcessed) -#define IMemInputPin_ReceiveCanBlock(This) (This)->lpVtbl->ReceiveCanBlock(This) -#endif -#endif - HRESULT WINAPI IMemInputPin_GetAllocator_Proxy(IMemInputPin *This,IMemAllocator **ppAllocator); - void __RPC_STUB IMemInputPin_GetAllocator_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMemInputPin_NotifyAllocator_Proxy(IMemInputPin *This,IMemAllocator *pAllocator,WINBOOL bReadOnly); - void __RPC_STUB IMemInputPin_NotifyAllocator_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMemInputPin_GetAllocatorRequirements_Proxy(IMemInputPin *This,ALLOCATOR_PROPERTIES *pProps); - void __RPC_STUB IMemInputPin_GetAllocatorRequirements_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMemInputPin_Receive_Proxy(IMemInputPin *This,IMediaSample *pSample); - void __RPC_STUB IMemInputPin_Receive_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMemInputPin_ReceiveMultiple_Proxy(IMemInputPin *This,IMediaSample **pSamples,long nSamples,long *nSamplesProcessed); - void __RPC_STUB IMemInputPin_ReceiveMultiple_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMemInputPin_ReceiveCanBlock_Proxy(IMemInputPin *This); - void __RPC_STUB IMemInputPin_ReceiveCanBlock_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - typedef IMemInputPin *PMEMINPUTPIN; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0132_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0132_v0_0_s_ifspec; -#ifndef __IAMovieSetup_INTERFACE_DEFINED__ -#define __IAMovieSetup_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IAMovieSetup; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IAMovieSetup : public IUnknown { - public: - virtual HRESULT WINAPI Register(void) = 0; - virtual HRESULT WINAPI Unregister(void) = 0; - }; -#else - typedef struct IAMovieSetupVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IAMovieSetup *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IAMovieSetup *This); - ULONG (WINAPI *Release)(IAMovieSetup *This); - HRESULT (WINAPI *Register)(IAMovieSetup *This); - HRESULT (WINAPI *Unregister)(IAMovieSetup *This); - END_INTERFACE - } IAMovieSetupVtbl; - struct IAMovieSetup { - CONST_VTBL struct IAMovieSetupVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IAMovieSetup_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IAMovieSetup_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IAMovieSetup_Release(This) (This)->lpVtbl->Release(This) -#define IAMovieSetup_Register(This) (This)->lpVtbl->Register(This) -#define IAMovieSetup_Unregister(This) (This)->lpVtbl->Unregister(This) -#endif -#endif - HRESULT WINAPI IAMovieSetup_Register_Proxy(IAMovieSetup *This); - void __RPC_STUB IAMovieSetup_Register_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMovieSetup_Unregister_Proxy(IAMovieSetup *This); - void __RPC_STUB IAMovieSetup_Unregister_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - typedef IAMovieSetup *PAMOVIESETUP; - - typedef enum AM_SEEKING_SeekingFlags { - AM_SEEKING_NoPositioning = 0,AM_SEEKING_AbsolutePositioning = 0x1,AM_SEEKING_RelativePositioning = 0x2,AM_SEEKING_IncrementalPositioning = 0x3, - AM_SEEKING_PositioningBitsMask = 0x3,AM_SEEKING_SeekToKeyFrame = 0x4,AM_SEEKING_ReturnTime = 0x8,AM_SEEKING_Segment = 0x10,AM_SEEKING_NoFlush = 0x20 - } AM_SEEKING_SEEKING_FLAGS; - - typedef enum AM_SEEKING_SeekingCapabilities { - AM_SEEKING_CanSeekAbsolute = 0x1,AM_SEEKING_CanSeekForwards = 0x2,AM_SEEKING_CanSeekBackwards = 0x4,AM_SEEKING_CanGetCurrentPos = 0x8, - AM_SEEKING_CanGetStopPos = 0x10,AM_SEEKING_CanGetDuration = 0x20,AM_SEEKING_CanPlayBackwards = 0x40,AM_SEEKING_CanDoSegments = 0x80, - AM_SEEKING_Source = 0x100 - } AM_SEEKING_SEEKING_CAPABILITIES; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0133_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0133_v0_0_s_ifspec; -#ifndef __IMediaSeeking_INTERFACE_DEFINED__ -#define __IMediaSeeking_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IMediaSeeking; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IMediaSeeking : public IUnknown { - public: - virtual HRESULT WINAPI GetCapabilities(DWORD *pCapabilities) = 0; - virtual HRESULT WINAPI CheckCapabilities(DWORD *pCapabilities) = 0; - virtual HRESULT WINAPI IsFormatSupported(const GUID *pFormat) = 0; - virtual HRESULT WINAPI QueryPreferredFormat(GUID *pFormat) = 0; - virtual HRESULT WINAPI GetTimeFormat(GUID *pFormat) = 0; - virtual HRESULT WINAPI IsUsingTimeFormat(const GUID *pFormat) = 0; - virtual HRESULT WINAPI SetTimeFormat(const GUID *pFormat) = 0; - virtual HRESULT WINAPI GetDuration(LONGLONG *pDuration) = 0; - virtual HRESULT WINAPI GetStopPosition(LONGLONG *pStop) = 0; - virtual HRESULT WINAPI GetCurrentPosition(LONGLONG *pCurrent) = 0; - virtual HRESULT WINAPI ConvertTimeFormat(LONGLONG *pTarget,const GUID *pTargetFormat,LONGLONG Source,const GUID *pSourceFormat) = 0; - virtual HRESULT WINAPI SetPositions(LONGLONG *pCurrent,DWORD dwCurrentFlags,LONGLONG *pStop,DWORD dwStopFlags) = 0; - virtual HRESULT WINAPI GetPositions(LONGLONG *pCurrent,LONGLONG *pStop) = 0; - virtual HRESULT WINAPI GetAvailable(LONGLONG *pEarliest,LONGLONG *pLatest) = 0; - virtual HRESULT WINAPI SetRate(double dRate) = 0; - virtual HRESULT WINAPI GetRate(double *pdRate) = 0; - virtual HRESULT WINAPI GetPreroll(LONGLONG *pllPreroll) = 0; - }; -#else - typedef struct IMediaSeekingVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IMediaSeeking *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IMediaSeeking *This); - ULONG (WINAPI *Release)(IMediaSeeking *This); - HRESULT (WINAPI *GetCapabilities)(IMediaSeeking *This,DWORD *pCapabilities); - HRESULT (WINAPI *CheckCapabilities)(IMediaSeeking *This,DWORD *pCapabilities); - HRESULT (WINAPI *IsFormatSupported)(IMediaSeeking *This,const GUID *pFormat); - HRESULT (WINAPI *QueryPreferredFormat)(IMediaSeeking *This,GUID *pFormat); - HRESULT (WINAPI *GetTimeFormat)(IMediaSeeking *This,GUID *pFormat); - HRESULT (WINAPI *IsUsingTimeFormat)(IMediaSeeking *This,const GUID *pFormat); - HRESULT (WINAPI *SetTimeFormat)(IMediaSeeking *This,const GUID *pFormat); - HRESULT (WINAPI *GetDuration)(IMediaSeeking *This,LONGLONG *pDuration); - HRESULT (WINAPI *GetStopPosition)(IMediaSeeking *This,LONGLONG *pStop); - HRESULT (WINAPI *GetCurrentPosition)(IMediaSeeking *This,LONGLONG *pCurrent); - HRESULT (WINAPI *ConvertTimeFormat)(IMediaSeeking *This,LONGLONG *pTarget,const GUID *pTargetFormat,LONGLONG Source,const GUID *pSourceFormat); - HRESULT (WINAPI *SetPositions)(IMediaSeeking *This,LONGLONG *pCurrent,DWORD dwCurrentFlags,LONGLONG *pStop,DWORD dwStopFlags); - HRESULT (WINAPI *GetPositions)(IMediaSeeking *This,LONGLONG *pCurrent,LONGLONG *pStop); - HRESULT (WINAPI *GetAvailable)(IMediaSeeking *This,LONGLONG *pEarliest,LONGLONG *pLatest); - HRESULT (WINAPI *SetRate)(IMediaSeeking *This,double dRate); - HRESULT (WINAPI *GetRate)(IMediaSeeking *This,double *pdRate); - HRESULT (WINAPI *GetPreroll)(IMediaSeeking *This,LONGLONG *pllPreroll); - END_INTERFACE - } IMediaSeekingVtbl; - struct IMediaSeeking { - CONST_VTBL struct IMediaSeekingVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IMediaSeeking_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IMediaSeeking_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IMediaSeeking_Release(This) (This)->lpVtbl->Release(This) -#define IMediaSeeking_GetCapabilities(This,pCapabilities) (This)->lpVtbl->GetCapabilities(This,pCapabilities) -#define IMediaSeeking_CheckCapabilities(This,pCapabilities) (This)->lpVtbl->CheckCapabilities(This,pCapabilities) -#define IMediaSeeking_IsFormatSupported(This,pFormat) (This)->lpVtbl->IsFormatSupported(This,pFormat) -#define IMediaSeeking_QueryPreferredFormat(This,pFormat) (This)->lpVtbl->QueryPreferredFormat(This,pFormat) -#define IMediaSeeking_GetTimeFormat(This,pFormat) (This)->lpVtbl->GetTimeFormat(This,pFormat) -#define IMediaSeeking_IsUsingTimeFormat(This,pFormat) (This)->lpVtbl->IsUsingTimeFormat(This,pFormat) -#define IMediaSeeking_SetTimeFormat(This,pFormat) (This)->lpVtbl->SetTimeFormat(This,pFormat) -#define IMediaSeeking_GetDuration(This,pDuration) (This)->lpVtbl->GetDuration(This,pDuration) -#define IMediaSeeking_GetStopPosition(This,pStop) (This)->lpVtbl->GetStopPosition(This,pStop) -#define IMediaSeeking_GetCurrentPosition(This,pCurrent) (This)->lpVtbl->GetCurrentPosition(This,pCurrent) -#define IMediaSeeking_ConvertTimeFormat(This,pTarget,pTargetFormat,Source,pSourceFormat) (This)->lpVtbl->ConvertTimeFormat(This,pTarget,pTargetFormat,Source,pSourceFormat) -#define IMediaSeeking_SetPositions(This,pCurrent,dwCurrentFlags,pStop,dwStopFlags) (This)->lpVtbl->SetPositions(This,pCurrent,dwCurrentFlags,pStop,dwStopFlags) -#define IMediaSeeking_GetPositions(This,pCurrent,pStop) (This)->lpVtbl->GetPositions(This,pCurrent,pStop) -#define IMediaSeeking_GetAvailable(This,pEarliest,pLatest) (This)->lpVtbl->GetAvailable(This,pEarliest,pLatest) -#define IMediaSeeking_SetRate(This,dRate) (This)->lpVtbl->SetRate(This,dRate) -#define IMediaSeeking_GetRate(This,pdRate) (This)->lpVtbl->GetRate(This,pdRate) -#define IMediaSeeking_GetPreroll(This,pllPreroll) (This)->lpVtbl->GetPreroll(This,pllPreroll) -#endif -#endif - HRESULT WINAPI IMediaSeeking_GetCapabilities_Proxy(IMediaSeeking *This,DWORD *pCapabilities); - void __RPC_STUB IMediaSeeking_GetCapabilities_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMediaSeeking_CheckCapabilities_Proxy(IMediaSeeking *This,DWORD *pCapabilities); - void __RPC_STUB IMediaSeeking_CheckCapabilities_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMediaSeeking_IsFormatSupported_Proxy(IMediaSeeking *This,const GUID *pFormat); - void __RPC_STUB IMediaSeeking_IsFormatSupported_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMediaSeeking_QueryPreferredFormat_Proxy(IMediaSeeking *This,GUID *pFormat); - void __RPC_STUB IMediaSeeking_QueryPreferredFormat_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMediaSeeking_GetTimeFormat_Proxy(IMediaSeeking *This,GUID *pFormat); - void __RPC_STUB IMediaSeeking_GetTimeFormat_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMediaSeeking_IsUsingTimeFormat_Proxy(IMediaSeeking *This,const GUID *pFormat); - void __RPC_STUB IMediaSeeking_IsUsingTimeFormat_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMediaSeeking_SetTimeFormat_Proxy(IMediaSeeking *This,const GUID *pFormat); - void __RPC_STUB IMediaSeeking_SetTimeFormat_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMediaSeeking_GetDuration_Proxy(IMediaSeeking *This,LONGLONG *pDuration); - void __RPC_STUB IMediaSeeking_GetDuration_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMediaSeeking_GetStopPosition_Proxy(IMediaSeeking *This,LONGLONG *pStop); - void __RPC_STUB IMediaSeeking_GetStopPosition_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMediaSeeking_GetCurrentPosition_Proxy(IMediaSeeking *This,LONGLONG *pCurrent); - void __RPC_STUB IMediaSeeking_GetCurrentPosition_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMediaSeeking_ConvertTimeFormat_Proxy(IMediaSeeking *This,LONGLONG *pTarget,const GUID *pTargetFormat,LONGLONG Source,const GUID *pSourceFormat); - void __RPC_STUB IMediaSeeking_ConvertTimeFormat_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMediaSeeking_SetPositions_Proxy(IMediaSeeking *This,LONGLONG *pCurrent,DWORD dwCurrentFlags,LONGLONG *pStop,DWORD dwStopFlags); - void __RPC_STUB IMediaSeeking_SetPositions_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMediaSeeking_GetPositions_Proxy(IMediaSeeking *This,LONGLONG *pCurrent,LONGLONG *pStop); - void __RPC_STUB IMediaSeeking_GetPositions_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMediaSeeking_GetAvailable_Proxy(IMediaSeeking *This,LONGLONG *pEarliest,LONGLONG *pLatest); - void __RPC_STUB IMediaSeeking_GetAvailable_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMediaSeeking_SetRate_Proxy(IMediaSeeking *This,double dRate); - void __RPC_STUB IMediaSeeking_SetRate_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMediaSeeking_GetRate_Proxy(IMediaSeeking *This,double *pdRate); - void __RPC_STUB IMediaSeeking_GetRate_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMediaSeeking_GetPreroll_Proxy(IMediaSeeking *This,LONGLONG *pllPreroll); - void __RPC_STUB IMediaSeeking_GetPreroll_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - typedef IMediaSeeking *PMEDIASEEKING; - - enum tagAM_MEDIAEVENT_FLAGS { - AM_MEDIAEVENT_NONOTIFY = 0x01 - }; - - typedef struct __MIDL___MIDL_itf_strmif_0134_0001 { - CLSID Clsid; - LPWSTR Name; - } REGFILTER; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0134_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0134_v0_0_s_ifspec; -#ifndef __IEnumRegFilters_INTERFACE_DEFINED__ -#define __IEnumRegFilters_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IEnumRegFilters; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IEnumRegFilters : public IUnknown { - public: - virtual HRESULT WINAPI Next(ULONG cFilters,REGFILTER **apRegFilter,ULONG *pcFetched) = 0; - virtual HRESULT WINAPI Skip(ULONG cFilters) = 0; - virtual HRESULT WINAPI Reset(void) = 0; - virtual HRESULT WINAPI Clone(IEnumRegFilters **ppEnum) = 0; - }; -#else - typedef struct IEnumRegFiltersVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IEnumRegFilters *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IEnumRegFilters *This); - ULONG (WINAPI *Release)(IEnumRegFilters *This); - HRESULT (WINAPI *Next)(IEnumRegFilters *This,ULONG cFilters,REGFILTER **apRegFilter,ULONG *pcFetched); - HRESULT (WINAPI *Skip)(IEnumRegFilters *This,ULONG cFilters); - HRESULT (WINAPI *Reset)(IEnumRegFilters *This); - HRESULT (WINAPI *Clone)(IEnumRegFilters *This,IEnumRegFilters **ppEnum); - END_INTERFACE - } IEnumRegFiltersVtbl; - struct IEnumRegFilters { - CONST_VTBL struct IEnumRegFiltersVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IEnumRegFilters_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IEnumRegFilters_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IEnumRegFilters_Release(This) (This)->lpVtbl->Release(This) -#define IEnumRegFilters_Next(This,cFilters,apRegFilter,pcFetched) (This)->lpVtbl->Next(This,cFilters,apRegFilter,pcFetched) -#define IEnumRegFilters_Skip(This,cFilters) (This)->lpVtbl->Skip(This,cFilters) -#define IEnumRegFilters_Reset(This) (This)->lpVtbl->Reset(This) -#define IEnumRegFilters_Clone(This,ppEnum) (This)->lpVtbl->Clone(This,ppEnum) -#endif -#endif - HRESULT WINAPI IEnumRegFilters_Next_Proxy(IEnumRegFilters *This,ULONG cFilters,REGFILTER **apRegFilter,ULONG *pcFetched); - void __RPC_STUB IEnumRegFilters_Next_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IEnumRegFilters_Skip_Proxy(IEnumRegFilters *This,ULONG cFilters); - void __RPC_STUB IEnumRegFilters_Skip_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IEnumRegFilters_Reset_Proxy(IEnumRegFilters *This); - void __RPC_STUB IEnumRegFilters_Reset_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IEnumRegFilters_Clone_Proxy(IEnumRegFilters *This,IEnumRegFilters **ppEnum); - void __RPC_STUB IEnumRegFilters_Clone_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - typedef IEnumRegFilters *PENUMREGFILTERS; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0136_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0136_v0_0_s_ifspec; -#ifndef __IFilterMapper_INTERFACE_DEFINED__ -#define __IFilterMapper_INTERFACE_DEFINED__ - enum __MIDL_IFilterMapper_0001 { - MERIT_PREFERRED = 0x800000,MERIT_NORMAL = 0x600000,MERIT_UNLIKELY = 0x400000,MERIT_DO_NOT_USE = 0x200000,MERIT_SW_COMPRESSOR = 0x100000, - MERIT_HW_COMPRESSOR = 0x100050 - }; - EXTERN_C const IID IID_IFilterMapper; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IFilterMapper : public IUnknown { - public: - virtual HRESULT WINAPI RegisterFilter(CLSID clsid,LPCWSTR Name,DWORD dwMerit) = 0; - virtual HRESULT WINAPI RegisterFilterInstance(CLSID clsid,LPCWSTR Name,CLSID *MRId) = 0; - virtual HRESULT WINAPI RegisterPin(CLSID Filter,LPCWSTR Name,WINBOOL bRendered,WINBOOL bOutput,WINBOOL bZero,WINBOOL bMany,CLSID ConnectsToFilter,LPCWSTR ConnectsToPin) = 0; - virtual HRESULT WINAPI RegisterPinType(CLSID clsFilter,LPCWSTR strName,CLSID clsMajorType,CLSID clsSubType) = 0; - virtual HRESULT WINAPI UnregisterFilter(CLSID Filter) = 0; - virtual HRESULT WINAPI UnregisterFilterInstance(CLSID MRId) = 0; - virtual HRESULT WINAPI UnregisterPin(CLSID Filter,LPCWSTR Name) = 0; - virtual HRESULT WINAPI EnumMatchingFilters(IEnumRegFilters **ppEnum,DWORD dwMerit,WINBOOL bInputNeeded,CLSID clsInMaj,CLSID clsInSub,WINBOOL bRender,WINBOOL bOututNeeded,CLSID clsOutMaj,CLSID clsOutSub) = 0; - }; -#else - typedef struct IFilterMapperVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IFilterMapper *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IFilterMapper *This); - ULONG (WINAPI *Release)(IFilterMapper *This); - HRESULT (WINAPI *RegisterFilter)(IFilterMapper *This,CLSID clsid,LPCWSTR Name,DWORD dwMerit); - HRESULT (WINAPI *RegisterFilterInstance)(IFilterMapper *This,CLSID clsid,LPCWSTR Name,CLSID *MRId); - HRESULT (WINAPI *RegisterPin)(IFilterMapper *This,CLSID Filter,LPCWSTR Name,WINBOOL bRendered,WINBOOL bOutput,WINBOOL bZero,WINBOOL bMany,CLSID ConnectsToFilter,LPCWSTR ConnectsToPin); - HRESULT (WINAPI *RegisterPinType)(IFilterMapper *This,CLSID clsFilter,LPCWSTR strName,CLSID clsMajorType,CLSID clsSubType); - HRESULT (WINAPI *UnregisterFilter)(IFilterMapper *This,CLSID Filter); - HRESULT (WINAPI *UnregisterFilterInstance)(IFilterMapper *This,CLSID MRId); - HRESULT (WINAPI *UnregisterPin)(IFilterMapper *This,CLSID Filter,LPCWSTR Name); - HRESULT (WINAPI *EnumMatchingFilters)(IFilterMapper *This,IEnumRegFilters **ppEnum,DWORD dwMerit,WINBOOL bInputNeeded,CLSID clsInMaj,CLSID clsInSub,WINBOOL bRender,WINBOOL bOututNeeded,CLSID clsOutMaj,CLSID clsOutSub); - END_INTERFACE - } IFilterMapperVtbl; - struct IFilterMapper { - CONST_VTBL struct IFilterMapperVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IFilterMapper_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IFilterMapper_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IFilterMapper_Release(This) (This)->lpVtbl->Release(This) -#define IFilterMapper_RegisterFilter(This,clsid,Name,dwMerit) (This)->lpVtbl->RegisterFilter(This,clsid,Name,dwMerit) -#define IFilterMapper_RegisterFilterInstance(This,clsid,Name,MRId) (This)->lpVtbl->RegisterFilterInstance(This,clsid,Name,MRId) -#define IFilterMapper_RegisterPin(This,Filter,Name,bRendered,bOutput,bZero,bMany,ConnectsToFilter,ConnectsToPin) (This)->lpVtbl->RegisterPin(This,Filter,Name,bRendered,bOutput,bZero,bMany,ConnectsToFilter,ConnectsToPin) -#define IFilterMapper_RegisterPinType(This,clsFilter,strName,clsMajorType,clsSubType) (This)->lpVtbl->RegisterPinType(This,clsFilter,strName,clsMajorType,clsSubType) -#define IFilterMapper_UnregisterFilter(This,Filter) (This)->lpVtbl->UnregisterFilter(This,Filter) -#define IFilterMapper_UnregisterFilterInstance(This,MRId) (This)->lpVtbl->UnregisterFilterInstance(This,MRId) -#define IFilterMapper_UnregisterPin(This,Filter,Name) (This)->lpVtbl->UnregisterPin(This,Filter,Name) -#define IFilterMapper_EnumMatchingFilters(This,ppEnum,dwMerit,bInputNeeded,clsInMaj,clsInSub,bRender,bOututNeeded,clsOutMaj,clsOutSub) (This)->lpVtbl->EnumMatchingFilters(This,ppEnum,dwMerit,bInputNeeded,clsInMaj,clsInSub,bRender,bOututNeeded,clsOutMaj,clsOutSub) -#endif -#endif - HRESULT WINAPI IFilterMapper_RegisterFilter_Proxy(IFilterMapper *This,CLSID clsid,LPCWSTR Name,DWORD dwMerit); - void __RPC_STUB IFilterMapper_RegisterFilter_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IFilterMapper_RegisterFilterInstance_Proxy(IFilterMapper *This,CLSID clsid,LPCWSTR Name,CLSID *MRId); - void __RPC_STUB IFilterMapper_RegisterFilterInstance_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IFilterMapper_RegisterPin_Proxy(IFilterMapper *This,CLSID Filter,LPCWSTR Name,WINBOOL bRendered,WINBOOL bOutput,WINBOOL bZero,WINBOOL bMany,CLSID ConnectsToFilter,LPCWSTR ConnectsToPin); - void __RPC_STUB IFilterMapper_RegisterPin_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IFilterMapper_RegisterPinType_Proxy(IFilterMapper *This,CLSID clsFilter,LPCWSTR strName,CLSID clsMajorType,CLSID clsSubType); - void __RPC_STUB IFilterMapper_RegisterPinType_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IFilterMapper_UnregisterFilter_Proxy(IFilterMapper *This,CLSID Filter); - void __RPC_STUB IFilterMapper_UnregisterFilter_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IFilterMapper_UnregisterFilterInstance_Proxy(IFilterMapper *This,CLSID MRId); - void __RPC_STUB IFilterMapper_UnregisterFilterInstance_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IFilterMapper_UnregisterPin_Proxy(IFilterMapper *This,CLSID Filter,LPCWSTR Name); - void __RPC_STUB IFilterMapper_UnregisterPin_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IFilterMapper_EnumMatchingFilters_Proxy(IFilterMapper *This,IEnumRegFilters **ppEnum,DWORD dwMerit,WINBOOL bInputNeeded,CLSID clsInMaj,CLSID clsInSub,WINBOOL bRender,WINBOOL bOututNeeded,CLSID clsOutMaj,CLSID clsOutSub); - void __RPC_STUB IFilterMapper_EnumMatchingFilters_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - typedef struct __MIDL___MIDL_itf_strmif_0138_0001 { - const CLSID *clsMajorType; - const CLSID *clsMinorType; - } REGPINTYPES; - - typedef struct __MIDL___MIDL_itf_strmif_0138_0002 { - LPWSTR strName; - WINBOOL bRendered; - WINBOOL bOutput; - WINBOOL bZero; - WINBOOL bMany; - const CLSID *clsConnectsToFilter; - const WCHAR *strConnectsToPin; - UINT nMediaTypes; - const REGPINTYPES *lpMediaType; - } REGFILTERPINS; - - typedef struct __MIDL___MIDL_itf_strmif_0138_0003 { - CLSID clsMedium; - DWORD dw1; - DWORD dw2; - } REGPINMEDIUM; - - enum __MIDL___MIDL_itf_strmif_0138_0004 { - REG_PINFLAG_B_ZERO = 0x1,REG_PINFLAG_B_RENDERER = 0x2,REG_PINFLAG_B_MANY = 0x4,REG_PINFLAG_B_OUTPUT = 0x8 - }; - typedef struct __MIDL___MIDL_itf_strmif_0138_0005 { - DWORD dwFlags; - UINT cInstances; - UINT nMediaTypes; - const REGPINTYPES *lpMediaType; - UINT nMediums; - const REGPINMEDIUM *lpMedium; - const CLSID *clsPinCategory; - } REGFILTERPINS2; - - typedef struct __MIDL___MIDL_itf_strmif_0138_0006 { - DWORD dwVersion; - DWORD dwMerit; - union { - struct { - ULONG cPins; - const REGFILTERPINS *rgPins; - }; - struct { - ULONG cPins2; - const REGFILTERPINS2 *rgPins2; - }; - }; - } REGFILTER2; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0138_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0138_v0_0_s_ifspec; -#ifndef __IFilterMapper2_INTERFACE_DEFINED__ -#define __IFilterMapper2_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IFilterMapper2; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IFilterMapper2 : public IUnknown { - public: - virtual HRESULT WINAPI CreateCategory(REFCLSID clsidCategory,DWORD dwCategoryMerit,LPCWSTR Description) = 0; - virtual HRESULT WINAPI UnregisterFilter(const CLSID *pclsidCategory,const OLECHAR *szInstance,REFCLSID Filter) = 0; - virtual HRESULT WINAPI RegisterFilter(REFCLSID clsidFilter,LPCWSTR Name,IMoniker **ppMoniker,const CLSID *pclsidCategory,const OLECHAR *szInstance,const REGFILTER2 *prf2) = 0; - virtual HRESULT WINAPI EnumMatchingFilters(IEnumMoniker **ppEnum,DWORD dwFlags,WINBOOL bExactMatch,DWORD dwMerit,WINBOOL bInputNeeded,DWORD cInputTypes,const GUID *pInputTypes,const REGPINMEDIUM *pMedIn,const CLSID *pPinCategoryIn,WINBOOL bRender,WINBOOL bOutputNeeded,DWORD cOutputTypes,const GUID *pOutputTypes,const REGPINMEDIUM *pMedOut,const CLSID *pPinCategoryOut) = 0; - }; -#else - typedef struct IFilterMapper2Vtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IFilterMapper2 *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IFilterMapper2 *This); - ULONG (WINAPI *Release)(IFilterMapper2 *This); - HRESULT (WINAPI *CreateCategory)(IFilterMapper2 *This,REFCLSID clsidCategory,DWORD dwCategoryMerit,LPCWSTR Description); - HRESULT (WINAPI *UnregisterFilter)(IFilterMapper2 *This,const CLSID *pclsidCategory,const OLECHAR *szInstance,REFCLSID Filter); - HRESULT (WINAPI *RegisterFilter)(IFilterMapper2 *This,REFCLSID clsidFilter,LPCWSTR Name,IMoniker **ppMoniker,const CLSID *pclsidCategory,const OLECHAR *szInstance,const REGFILTER2 *prf2); - HRESULT (WINAPI *EnumMatchingFilters)(IFilterMapper2 *This,IEnumMoniker **ppEnum,DWORD dwFlags,WINBOOL bExactMatch,DWORD dwMerit,WINBOOL bInputNeeded,DWORD cInputTypes,const GUID *pInputTypes,const REGPINMEDIUM *pMedIn,const CLSID *pPinCategoryIn,WINBOOL bRender,WINBOOL bOutputNeeded,DWORD cOutputTypes,const GUID *pOutputTypes,const REGPINMEDIUM *pMedOut,const CLSID *pPinCategoryOut); - END_INTERFACE - } IFilterMapper2Vtbl; - struct IFilterMapper2 { - CONST_VTBL struct IFilterMapper2Vtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IFilterMapper2_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IFilterMapper2_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IFilterMapper2_Release(This) (This)->lpVtbl->Release(This) -#define IFilterMapper2_CreateCategory(This,clsidCategory,dwCategoryMerit,Description) (This)->lpVtbl->CreateCategory(This,clsidCategory,dwCategoryMerit,Description) -#define IFilterMapper2_UnregisterFilter(This,pclsidCategory,szInstance,Filter) (This)->lpVtbl->UnregisterFilter(This,pclsidCategory,szInstance,Filter) -#define IFilterMapper2_RegisterFilter(This,clsidFilter,Name,ppMoniker,pclsidCategory,szInstance,prf2) (This)->lpVtbl->RegisterFilter(This,clsidFilter,Name,ppMoniker,pclsidCategory,szInstance,prf2) -#define IFilterMapper2_EnumMatchingFilters(This,ppEnum,dwFlags,bExactMatch,dwMerit,bInputNeeded,cInputTypes,pInputTypes,pMedIn,pPinCategoryIn,bRender,bOutputNeeded,cOutputTypes,pOutputTypes,pMedOut,pPinCategoryOut) (This)->lpVtbl->EnumMatchingFilters(This,ppEnum,dwFlags,bExactMatch,dwMerit,bInputNeeded,cInputTypes,pInputTypes,pMedIn,pPinCategoryIn,bRender,bOutputNeeded,cOutputTypes,pOutputTypes,pMedOut,pPinCategoryOut) -#endif -#endif - HRESULT WINAPI IFilterMapper2_CreateCategory_Proxy(IFilterMapper2 *This,REFCLSID clsidCategory,DWORD dwCategoryMerit,LPCWSTR Description); - void __RPC_STUB IFilterMapper2_CreateCategory_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IFilterMapper2_UnregisterFilter_Proxy(IFilterMapper2 *This,const CLSID *pclsidCategory,const OLECHAR *szInstance,REFCLSID Filter); - void __RPC_STUB IFilterMapper2_UnregisterFilter_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IFilterMapper2_RegisterFilter_Proxy(IFilterMapper2 *This,REFCLSID clsidFilter,LPCWSTR Name,IMoniker **ppMoniker,const CLSID *pclsidCategory,const OLECHAR *szInstance,const REGFILTER2 *prf2); - void __RPC_STUB IFilterMapper2_RegisterFilter_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IFilterMapper2_EnumMatchingFilters_Proxy(IFilterMapper2 *This,IEnumMoniker **ppEnum,DWORD dwFlags,WINBOOL bExactMatch,DWORD dwMerit,WINBOOL bInputNeeded,DWORD cInputTypes,const GUID *pInputTypes,const REGPINMEDIUM *pMedIn,const CLSID *pPinCategoryIn,WINBOOL bRender,WINBOOL bOutputNeeded,DWORD cOutputTypes,const GUID *pOutputTypes,const REGPINMEDIUM *pMedOut,const CLSID *pPinCategoryOut); - void __RPC_STUB IFilterMapper2_EnumMatchingFilters_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IFilterMapper3_INTERFACE_DEFINED__ -#define __IFilterMapper3_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IFilterMapper3; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IFilterMapper3 : public IFilterMapper2 { - public: - virtual HRESULT WINAPI GetICreateDevEnum(ICreateDevEnum **ppEnum) = 0; - }; -#else - typedef struct IFilterMapper3Vtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IFilterMapper3 *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IFilterMapper3 *This); - ULONG (WINAPI *Release)(IFilterMapper3 *This); - HRESULT (WINAPI *CreateCategory)(IFilterMapper3 *This,REFCLSID clsidCategory,DWORD dwCategoryMerit,LPCWSTR Description); - HRESULT (WINAPI *UnregisterFilter)(IFilterMapper3 *This,const CLSID *pclsidCategory,const OLECHAR *szInstance,REFCLSID Filter); - HRESULT (WINAPI *RegisterFilter)(IFilterMapper3 *This,REFCLSID clsidFilter,LPCWSTR Name,IMoniker **ppMoniker,const CLSID *pclsidCategory,const OLECHAR *szInstance,const REGFILTER2 *prf2); - HRESULT (WINAPI *EnumMatchingFilters)(IFilterMapper3 *This,IEnumMoniker **ppEnum,DWORD dwFlags,WINBOOL bExactMatch,DWORD dwMerit,WINBOOL bInputNeeded,DWORD cInputTypes,const GUID *pInputTypes,const REGPINMEDIUM *pMedIn,const CLSID *pPinCategoryIn,WINBOOL bRender,WINBOOL bOutputNeeded,DWORD cOutputTypes,const GUID *pOutputTypes,const REGPINMEDIUM *pMedOut,const CLSID *pPinCategoryOut); - HRESULT (WINAPI *GetICreateDevEnum)(IFilterMapper3 *This,ICreateDevEnum **ppEnum); - END_INTERFACE - } IFilterMapper3Vtbl; - struct IFilterMapper3 { - CONST_VTBL struct IFilterMapper3Vtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IFilterMapper3_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IFilterMapper3_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IFilterMapper3_Release(This) (This)->lpVtbl->Release(This) -#define IFilterMapper3_CreateCategory(This,clsidCategory,dwCategoryMerit,Description) (This)->lpVtbl->CreateCategory(This,clsidCategory,dwCategoryMerit,Description) -#define IFilterMapper3_UnregisterFilter(This,pclsidCategory,szInstance,Filter) (This)->lpVtbl->UnregisterFilter(This,pclsidCategory,szInstance,Filter) -#define IFilterMapper3_RegisterFilter(This,clsidFilter,Name,ppMoniker,pclsidCategory,szInstance,prf2) (This)->lpVtbl->RegisterFilter(This,clsidFilter,Name,ppMoniker,pclsidCategory,szInstance,prf2) -#define IFilterMapper3_EnumMatchingFilters(This,ppEnum,dwFlags,bExactMatch,dwMerit,bInputNeeded,cInputTypes,pInputTypes,pMedIn,pPinCategoryIn,bRender,bOutputNeeded,cOutputTypes,pOutputTypes,pMedOut,pPinCategoryOut) (This)->lpVtbl->EnumMatchingFilters(This,ppEnum,dwFlags,bExactMatch,dwMerit,bInputNeeded,cInputTypes,pInputTypes,pMedIn,pPinCategoryIn,bRender,bOutputNeeded,cOutputTypes,pOutputTypes,pMedOut,pPinCategoryOut) -#define IFilterMapper3_GetICreateDevEnum(This,ppEnum) (This)->lpVtbl->GetICreateDevEnum(This,ppEnum) -#endif -#endif - HRESULT WINAPI IFilterMapper3_GetICreateDevEnum_Proxy(IFilterMapper3 *This,ICreateDevEnum **ppEnum); - void __RPC_STUB IFilterMapper3_GetICreateDevEnum_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - typedef enum tagQualityMessageType { - Famine = 0,Flood = Famine + 1 - } QualityMessageType; - - typedef struct tagQuality { - QualityMessageType Type; - long Proportion; - REFERENCE_TIME Late; - REFERENCE_TIME TimeStamp; - } Quality; - - typedef IQualityControl *PQUALITYCONTROL; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0141_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0141_v0_0_s_ifspec; -#ifndef __IQualityControl_INTERFACE_DEFINED__ -#define __IQualityControl_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IQualityControl; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IQualityControl : public IUnknown { - public: - virtual HRESULT WINAPI Notify(IBaseFilter *pSelf,Quality q) = 0; - virtual HRESULT WINAPI SetSink(IQualityControl *piqc) = 0; - }; -#else - typedef struct IQualityControlVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IQualityControl *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IQualityControl *This); - ULONG (WINAPI *Release)(IQualityControl *This); - HRESULT (WINAPI *Notify)(IQualityControl *This,IBaseFilter *pSelf,Quality q); - HRESULT (WINAPI *SetSink)(IQualityControl *This,IQualityControl *piqc); - END_INTERFACE - } IQualityControlVtbl; - struct IQualityControl { - CONST_VTBL struct IQualityControlVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IQualityControl_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IQualityControl_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IQualityControl_Release(This) (This)->lpVtbl->Release(This) -#define IQualityControl_Notify(This,pSelf,q) (This)->lpVtbl->Notify(This,pSelf,q) -#define IQualityControl_SetSink(This,piqc) (This)->lpVtbl->SetSink(This,piqc) -#endif -#endif - HRESULT WINAPI IQualityControl_Notify_Proxy(IQualityControl *This,IBaseFilter *pSelf,Quality q); - void __RPC_STUB IQualityControl_Notify_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IQualityControl_SetSink_Proxy(IQualityControl *This,IQualityControl *piqc); - void __RPC_STUB IQualityControl_SetSink_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - enum __MIDL___MIDL_itf_strmif_0142_0001 { - CK_NOCOLORKEY = 0,CK_INDEX = 0x1,CK_RGB = 0x2 - }; - typedef struct tagCOLORKEY { - DWORD KeyType; - DWORD PaletteIndex; - COLORREF LowColorValue; - COLORREF HighColorValue; - } COLORKEY; - - enum __MIDL___MIDL_itf_strmif_0142_0002 { - ADVISE_NONE = 0,ADVISE_CLIPPING = 0x1,ADVISE_PALETTE = 0x2,ADVISE_COLORKEY = 0x4,ADVISE_POSITION = 0x8,ADVISE_DISPLAY_CHANGE = 0x10 - }; -#define ADVISE_ALL (ADVISE_CLIPPING | ADVISE_PALETTE | ADVISE_COLORKEY | ADVISE_POSITION) -#define ADVISE_ALL2 (ADVISE_ALL | ADVISE_DISPLAY_CHANGE) - -#ifndef _WINGDI_ - typedef struct _RGNDATAHEADER { - DWORD dwSize; - DWORD iType; - DWORD nCount; - DWORD nRgnSize; - RECT rcBound; - } RGNDATAHEADER; - - typedef struct _RGNDATA { - RGNDATAHEADER rdh; - char Buffer[1]; - } RGNDATA; -#endif - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0142_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0142_v0_0_s_ifspec; -#ifndef __IOverlayNotify_INTERFACE_DEFINED__ -#define __IOverlayNotify_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IOverlayNotify; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IOverlayNotify : public IUnknown { - public: - virtual HRESULT WINAPI OnPaletteChange(DWORD dwColors,const PALETTEENTRY *pPalette) = 0; - virtual HRESULT WINAPI OnClipChange(const RECT *pSourceRect,const RECT *pDestinationRect,const RGNDATA *pRgnData) = 0; - virtual HRESULT WINAPI OnColorKeyChange(const COLORKEY *pColorKey) = 0; - virtual HRESULT WINAPI OnPositionChange(const RECT *pSourceRect,const RECT *pDestinationRect) = 0; - }; -#else - typedef struct IOverlayNotifyVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IOverlayNotify *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IOverlayNotify *This); - ULONG (WINAPI *Release)(IOverlayNotify *This); - HRESULT (WINAPI *OnPaletteChange)(IOverlayNotify *This,DWORD dwColors,const PALETTEENTRY *pPalette); - HRESULT (WINAPI *OnClipChange)(IOverlayNotify *This,const RECT *pSourceRect,const RECT *pDestinationRect,const RGNDATA *pRgnData); - HRESULT (WINAPI *OnColorKeyChange)(IOverlayNotify *This,const COLORKEY *pColorKey); - HRESULT (WINAPI *OnPositionChange)(IOverlayNotify *This,const RECT *pSourceRect,const RECT *pDestinationRect); - END_INTERFACE - } IOverlayNotifyVtbl; - struct IOverlayNotify { - CONST_VTBL struct IOverlayNotifyVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IOverlayNotify_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IOverlayNotify_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IOverlayNotify_Release(This) (This)->lpVtbl->Release(This) -#define IOverlayNotify_OnPaletteChange(This,dwColors,pPalette) (This)->lpVtbl->OnPaletteChange(This,dwColors,pPalette) -#define IOverlayNotify_OnClipChange(This,pSourceRect,pDestinationRect,pRgnData) (This)->lpVtbl->OnClipChange(This,pSourceRect,pDestinationRect,pRgnData) -#define IOverlayNotify_OnColorKeyChange(This,pColorKey) (This)->lpVtbl->OnColorKeyChange(This,pColorKey) -#define IOverlayNotify_OnPositionChange(This,pSourceRect,pDestinationRect) (This)->lpVtbl->OnPositionChange(This,pSourceRect,pDestinationRect) -#endif -#endif - HRESULT WINAPI IOverlayNotify_OnPaletteChange_Proxy(IOverlayNotify *This,DWORD dwColors,const PALETTEENTRY *pPalette); - void __RPC_STUB IOverlayNotify_OnPaletteChange_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IOverlayNotify_OnClipChange_Proxy(IOverlayNotify *This,const RECT *pSourceRect,const RECT *pDestinationRect,const RGNDATA *pRgnData); - void __RPC_STUB IOverlayNotify_OnClipChange_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IOverlayNotify_OnColorKeyChange_Proxy(IOverlayNotify *This,const COLORKEY *pColorKey); - void __RPC_STUB IOverlayNotify_OnColorKeyChange_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IOverlayNotify_OnPositionChange_Proxy(IOverlayNotify *This,const RECT *pSourceRect,const RECT *pDestinationRect); - void __RPC_STUB IOverlayNotify_OnPositionChange_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - typedef IOverlayNotify *POVERLAYNOTIFY; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0143_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0143_v0_0_s_ifspec; -#ifndef __IOverlayNotify2_INTERFACE_DEFINED__ -#define __IOverlayNotify2_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IOverlayNotify2; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IOverlayNotify2 : public IOverlayNotify { - public: - virtual HRESULT WINAPI OnDisplayChange(HMONITOR hMonitor) = 0; - }; -#else - typedef struct IOverlayNotify2Vtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IOverlayNotify2 *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IOverlayNotify2 *This); - ULONG (WINAPI *Release)(IOverlayNotify2 *This); - HRESULT (WINAPI *OnPaletteChange)(IOverlayNotify2 *This,DWORD dwColors,const PALETTEENTRY *pPalette); - HRESULT (WINAPI *OnClipChange)(IOverlayNotify2 *This,const RECT *pSourceRect,const RECT *pDestinationRect,const RGNDATA *pRgnData); - HRESULT (WINAPI *OnColorKeyChange)(IOverlayNotify2 *This,const COLORKEY *pColorKey); - HRESULT (WINAPI *OnPositionChange)(IOverlayNotify2 *This,const RECT *pSourceRect,const RECT *pDestinationRect); - HRESULT (WINAPI *OnDisplayChange)(IOverlayNotify2 *This,HMONITOR hMonitor); - END_INTERFACE - } IOverlayNotify2Vtbl; - struct IOverlayNotify2 { - CONST_VTBL struct IOverlayNotify2Vtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IOverlayNotify2_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IOverlayNotify2_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IOverlayNotify2_Release(This) (This)->lpVtbl->Release(This) -#define IOverlayNotify2_OnPaletteChange(This,dwColors,pPalette) (This)->lpVtbl->OnPaletteChange(This,dwColors,pPalette) -#define IOverlayNotify2_OnClipChange(This,pSourceRect,pDestinationRect,pRgnData) (This)->lpVtbl->OnClipChange(This,pSourceRect,pDestinationRect,pRgnData) -#define IOverlayNotify2_OnColorKeyChange(This,pColorKey) (This)->lpVtbl->OnColorKeyChange(This,pColorKey) -#define IOverlayNotify2_OnPositionChange(This,pSourceRect,pDestinationRect) (This)->lpVtbl->OnPositionChange(This,pSourceRect,pDestinationRect) -#define IOverlayNotify2_OnDisplayChange(This,hMonitor) (This)->lpVtbl->OnDisplayChange(This,hMonitor) -#endif -#endif - HRESULT WINAPI IOverlayNotify2_OnDisplayChange_Proxy(IOverlayNotify2 *This,HMONITOR hMonitor); - void __RPC_STUB IOverlayNotify2_OnDisplayChange_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - typedef IOverlayNotify2 *POVERLAYNOTIFY2; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0144_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0144_v0_0_s_ifspec; -#ifndef __IOverlay_INTERFACE_DEFINED__ -#define __IOverlay_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IOverlay; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IOverlay : public IUnknown { - public: - virtual HRESULT WINAPI GetPalette(DWORD *pdwColors,PALETTEENTRY **ppPalette) = 0; - virtual HRESULT WINAPI SetPalette(DWORD dwColors,PALETTEENTRY *pPalette) = 0; - virtual HRESULT WINAPI GetDefaultColorKey(COLORKEY *pColorKey) = 0; - virtual HRESULT WINAPI GetColorKey(COLORKEY *pColorKey) = 0; - virtual HRESULT WINAPI SetColorKey(COLORKEY *pColorKey) = 0; - virtual HRESULT WINAPI GetWindowHandle(HWND *pHwnd) = 0; - virtual HRESULT WINAPI GetClipList(RECT *pSourceRect,RECT *pDestinationRect,RGNDATA **ppRgnData) = 0; - virtual HRESULT WINAPI GetVideoPosition(RECT *pSourceRect,RECT *pDestinationRect) = 0; - virtual HRESULT WINAPI Advise(IOverlayNotify *pOverlayNotify,DWORD dwInterests) = 0; - virtual HRESULT WINAPI Unadvise(void) = 0; - }; -#else - typedef struct IOverlayVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IOverlay *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IOverlay *This); - ULONG (WINAPI *Release)(IOverlay *This); - HRESULT (WINAPI *GetPalette)(IOverlay *This,DWORD *pdwColors,PALETTEENTRY **ppPalette); - HRESULT (WINAPI *SetPalette)(IOverlay *This,DWORD dwColors,PALETTEENTRY *pPalette); - HRESULT (WINAPI *GetDefaultColorKey)(IOverlay *This,COLORKEY *pColorKey); - HRESULT (WINAPI *GetColorKey)(IOverlay *This,COLORKEY *pColorKey); - HRESULT (WINAPI *SetColorKey)(IOverlay *This,COLORKEY *pColorKey); - HRESULT (WINAPI *GetWindowHandle)(IOverlay *This,HWND *pHwnd); - HRESULT (WINAPI *GetClipList)(IOverlay *This,RECT *pSourceRect,RECT *pDestinationRect,RGNDATA **ppRgnData); - HRESULT (WINAPI *GetVideoPosition)(IOverlay *This,RECT *pSourceRect,RECT *pDestinationRect); - HRESULT (WINAPI *Advise)(IOverlay *This,IOverlayNotify *pOverlayNotify,DWORD dwInterests); - HRESULT (WINAPI *Unadvise)(IOverlay *This); - END_INTERFACE - } IOverlayVtbl; - struct IOverlay { - CONST_VTBL struct IOverlayVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IOverlay_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IOverlay_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IOverlay_Release(This) (This)->lpVtbl->Release(This) -#define IOverlay_GetPalette(This,pdwColors,ppPalette) (This)->lpVtbl->GetPalette(This,pdwColors,ppPalette) -#define IOverlay_SetPalette(This,dwColors,pPalette) (This)->lpVtbl->SetPalette(This,dwColors,pPalette) -#define IOverlay_GetDefaultColorKey(This,pColorKey) (This)->lpVtbl->GetDefaultColorKey(This,pColorKey) -#define IOverlay_GetColorKey(This,pColorKey) (This)->lpVtbl->GetColorKey(This,pColorKey) -#define IOverlay_SetColorKey(This,pColorKey) (This)->lpVtbl->SetColorKey(This,pColorKey) -#define IOverlay_GetWindowHandle(This,pHwnd) (This)->lpVtbl->GetWindowHandle(This,pHwnd) -#define IOverlay_GetClipList(This,pSourceRect,pDestinationRect,ppRgnData) (This)->lpVtbl->GetClipList(This,pSourceRect,pDestinationRect,ppRgnData) -#define IOverlay_GetVideoPosition(This,pSourceRect,pDestinationRect) (This)->lpVtbl->GetVideoPosition(This,pSourceRect,pDestinationRect) -#define IOverlay_Advise(This,pOverlayNotify,dwInterests) (This)->lpVtbl->Advise(This,pOverlayNotify,dwInterests) -#define IOverlay_Unadvise(This) (This)->lpVtbl->Unadvise(This) -#endif -#endif - HRESULT WINAPI IOverlay_GetPalette_Proxy(IOverlay *This,DWORD *pdwColors,PALETTEENTRY **ppPalette); - void __RPC_STUB IOverlay_GetPalette_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IOverlay_SetPalette_Proxy(IOverlay *This,DWORD dwColors,PALETTEENTRY *pPalette); - void __RPC_STUB IOverlay_SetPalette_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IOverlay_GetDefaultColorKey_Proxy(IOverlay *This,COLORKEY *pColorKey); - void __RPC_STUB IOverlay_GetDefaultColorKey_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IOverlay_GetColorKey_Proxy(IOverlay *This,COLORKEY *pColorKey); - void __RPC_STUB IOverlay_GetColorKey_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IOverlay_SetColorKey_Proxy(IOverlay *This,COLORKEY *pColorKey); - void __RPC_STUB IOverlay_SetColorKey_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IOverlay_GetWindowHandle_Proxy(IOverlay *This,HWND *pHwnd); - void __RPC_STUB IOverlay_GetWindowHandle_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IOverlay_GetClipList_Proxy(IOverlay *This,RECT *pSourceRect,RECT *pDestinationRect,RGNDATA **ppRgnData); - void __RPC_STUB IOverlay_GetClipList_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IOverlay_GetVideoPosition_Proxy(IOverlay *This,RECT *pSourceRect,RECT *pDestinationRect); - void __RPC_STUB IOverlay_GetVideoPosition_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IOverlay_Advise_Proxy(IOverlay *This,IOverlayNotify *pOverlayNotify,DWORD dwInterests); - void __RPC_STUB IOverlay_Advise_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IOverlay_Unadvise_Proxy(IOverlay *This); - void __RPC_STUB IOverlay_Unadvise_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - typedef IOverlay *POVERLAY; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0145_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0145_v0_0_s_ifspec; -#ifndef __IMediaEventSink_INTERFACE_DEFINED__ -#define __IMediaEventSink_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IMediaEventSink; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IMediaEventSink : public IUnknown { - public: - virtual HRESULT WINAPI Notify(long EventCode,LONG_PTR EventParam1,LONG_PTR EventParam2) = 0; - }; -#else - typedef struct IMediaEventSinkVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IMediaEventSink *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IMediaEventSink *This); - ULONG (WINAPI *Release)(IMediaEventSink *This); - HRESULT (WINAPI *Notify)(IMediaEventSink *This,long EventCode,LONG_PTR EventParam1,LONG_PTR EventParam2); - END_INTERFACE - } IMediaEventSinkVtbl; - struct IMediaEventSink { - CONST_VTBL struct IMediaEventSinkVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IMediaEventSink_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IMediaEventSink_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IMediaEventSink_Release(This) (This)->lpVtbl->Release(This) -#define IMediaEventSink_Notify(This,EventCode,EventParam1,EventParam2) (This)->lpVtbl->Notify(This,EventCode,EventParam1,EventParam2) -#endif -#endif - HRESULT WINAPI IMediaEventSink_Notify_Proxy(IMediaEventSink *This,long EventCode,LONG_PTR EventParam1,LONG_PTR EventParam2); - void __RPC_STUB IMediaEventSink_Notify_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - typedef IMediaEventSink *PMEDIAEVENTSINK; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0146_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0146_v0_0_s_ifspec; -#ifndef __IFileSourceFilter_INTERFACE_DEFINED__ -#define __IFileSourceFilter_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IFileSourceFilter; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IFileSourceFilter : public IUnknown { - public: - virtual HRESULT WINAPI Load(LPCOLESTR pszFileName,const AM_MEDIA_TYPE *pmt) = 0; - virtual HRESULT WINAPI GetCurFile(LPOLESTR *ppszFileName,AM_MEDIA_TYPE *pmt) = 0; - }; -#else - typedef struct IFileSourceFilterVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IFileSourceFilter *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IFileSourceFilter *This); - ULONG (WINAPI *Release)(IFileSourceFilter *This); - HRESULT (WINAPI *Load)(IFileSourceFilter *This,LPCOLESTR pszFileName,const AM_MEDIA_TYPE *pmt); - HRESULT (WINAPI *GetCurFile)(IFileSourceFilter *This,LPOLESTR *ppszFileName,AM_MEDIA_TYPE *pmt); - END_INTERFACE - } IFileSourceFilterVtbl; - struct IFileSourceFilter { - CONST_VTBL struct IFileSourceFilterVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IFileSourceFilter_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IFileSourceFilter_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IFileSourceFilter_Release(This) (This)->lpVtbl->Release(This) -#define IFileSourceFilter_Load(This,pszFileName,pmt) (This)->lpVtbl->Load(This,pszFileName,pmt) -#define IFileSourceFilter_GetCurFile(This,ppszFileName,pmt) (This)->lpVtbl->GetCurFile(This,ppszFileName,pmt) -#endif -#endif - HRESULT WINAPI IFileSourceFilter_Load_Proxy(IFileSourceFilter *This,LPCOLESTR pszFileName,const AM_MEDIA_TYPE *pmt); - void __RPC_STUB IFileSourceFilter_Load_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IFileSourceFilter_GetCurFile_Proxy(IFileSourceFilter *This,LPOLESTR *ppszFileName,AM_MEDIA_TYPE *pmt); - void __RPC_STUB IFileSourceFilter_GetCurFile_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - typedef IFileSourceFilter *PFILTERFILESOURCE; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0147_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0147_v0_0_s_ifspec; -#ifndef __IFileSinkFilter_INTERFACE_DEFINED__ -#define __IFileSinkFilter_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IFileSinkFilter; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IFileSinkFilter : public IUnknown { - public: - virtual HRESULT WINAPI SetFileName(LPCOLESTR pszFileName,const AM_MEDIA_TYPE *pmt) = 0; - virtual HRESULT WINAPI GetCurFile(LPOLESTR *ppszFileName,AM_MEDIA_TYPE *pmt) = 0; - }; -#else - typedef struct IFileSinkFilterVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IFileSinkFilter *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IFileSinkFilter *This); - ULONG (WINAPI *Release)(IFileSinkFilter *This); - HRESULT (WINAPI *SetFileName)(IFileSinkFilter *This,LPCOLESTR pszFileName,const AM_MEDIA_TYPE *pmt); - HRESULT (WINAPI *GetCurFile)(IFileSinkFilter *This,LPOLESTR *ppszFileName,AM_MEDIA_TYPE *pmt); - END_INTERFACE - } IFileSinkFilterVtbl; - struct IFileSinkFilter { - CONST_VTBL struct IFileSinkFilterVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IFileSinkFilter_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IFileSinkFilter_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IFileSinkFilter_Release(This) (This)->lpVtbl->Release(This) -#define IFileSinkFilter_SetFileName(This,pszFileName,pmt) (This)->lpVtbl->SetFileName(This,pszFileName,pmt) -#define IFileSinkFilter_GetCurFile(This,ppszFileName,pmt) (This)->lpVtbl->GetCurFile(This,ppszFileName,pmt) -#endif -#endif - HRESULT WINAPI IFileSinkFilter_SetFileName_Proxy(IFileSinkFilter *This,LPCOLESTR pszFileName,const AM_MEDIA_TYPE *pmt); - void __RPC_STUB IFileSinkFilter_SetFileName_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IFileSinkFilter_GetCurFile_Proxy(IFileSinkFilter *This,LPOLESTR *ppszFileName,AM_MEDIA_TYPE *pmt); - void __RPC_STUB IFileSinkFilter_GetCurFile_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - typedef IFileSinkFilter *PFILTERFILESINK; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0148_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0148_v0_0_s_ifspec; -#ifndef __IFileSinkFilter2_INTERFACE_DEFINED__ -#define __IFileSinkFilter2_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IFileSinkFilter2; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IFileSinkFilter2 : public IFileSinkFilter { - public: - virtual HRESULT WINAPI SetMode(DWORD dwFlags) = 0; - virtual HRESULT WINAPI GetMode(DWORD *pdwFlags) = 0; - }; -#else - typedef struct IFileSinkFilter2Vtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IFileSinkFilter2 *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IFileSinkFilter2 *This); - ULONG (WINAPI *Release)(IFileSinkFilter2 *This); - HRESULT (WINAPI *SetFileName)(IFileSinkFilter2 *This,LPCOLESTR pszFileName,const AM_MEDIA_TYPE *pmt); - HRESULT (WINAPI *GetCurFile)(IFileSinkFilter2 *This,LPOLESTR *ppszFileName,AM_MEDIA_TYPE *pmt); - HRESULT (WINAPI *SetMode)(IFileSinkFilter2 *This,DWORD dwFlags); - HRESULT (WINAPI *GetMode)(IFileSinkFilter2 *This,DWORD *pdwFlags); - END_INTERFACE - } IFileSinkFilter2Vtbl; - struct IFileSinkFilter2 { - CONST_VTBL struct IFileSinkFilter2Vtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IFileSinkFilter2_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IFileSinkFilter2_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IFileSinkFilter2_Release(This) (This)->lpVtbl->Release(This) -#define IFileSinkFilter2_SetFileName(This,pszFileName,pmt) (This)->lpVtbl->SetFileName(This,pszFileName,pmt) -#define IFileSinkFilter2_GetCurFile(This,ppszFileName,pmt) (This)->lpVtbl->GetCurFile(This,ppszFileName,pmt) -#define IFileSinkFilter2_SetMode(This,dwFlags) (This)->lpVtbl->SetMode(This,dwFlags) -#define IFileSinkFilter2_GetMode(This,pdwFlags) (This)->lpVtbl->GetMode(This,pdwFlags) -#endif -#endif - HRESULT WINAPI IFileSinkFilter2_SetMode_Proxy(IFileSinkFilter2 *This,DWORD dwFlags); - void __RPC_STUB IFileSinkFilter2_SetMode_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IFileSinkFilter2_GetMode_Proxy(IFileSinkFilter2 *This,DWORD *pdwFlags); - void __RPC_STUB IFileSinkFilter2_GetMode_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - typedef IFileSinkFilter2 *PFILESINKFILTER2; - - typedef enum __MIDL___MIDL_itf_strmif_0149_0001 { - AM_FILE_OVERWRITE = 0x1 - } AM_FILESINK_FLAGS; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0149_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0149_v0_0_s_ifspec; -#ifndef __IGraphBuilder_INTERFACE_DEFINED__ -#define __IGraphBuilder_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IGraphBuilder; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IGraphBuilder : public IFilterGraph { - public: - virtual HRESULT WINAPI Connect(IPin *ppinOut,IPin *ppinIn) = 0; - virtual HRESULT WINAPI Render(IPin *ppinOut) = 0; - virtual HRESULT WINAPI RenderFile(LPCWSTR lpcwstrFile,LPCWSTR lpcwstrPlayList) = 0; - virtual HRESULT WINAPI AddSourceFilter(LPCWSTR lpcwstrFileName,LPCWSTR lpcwstrFilterName,IBaseFilter **ppFilter) = 0; - virtual HRESULT WINAPI SetLogFile(DWORD_PTR hFile) = 0; - virtual HRESULT WINAPI Abort(void) = 0; - virtual HRESULT WINAPI ShouldOperationContinue(void) = 0; - }; -#else - typedef struct IGraphBuilderVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IGraphBuilder *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IGraphBuilder *This); - ULONG (WINAPI *Release)(IGraphBuilder *This); - HRESULT (WINAPI *AddFilter)(IGraphBuilder *This,IBaseFilter *pFilter,LPCWSTR pName); - HRESULT (WINAPI *RemoveFilter)(IGraphBuilder *This,IBaseFilter *pFilter); - HRESULT (WINAPI *EnumFilters)(IGraphBuilder *This,IEnumFilters **ppEnum); - HRESULT (WINAPI *FindFilterByName)(IGraphBuilder *This,LPCWSTR pName,IBaseFilter **ppFilter); - HRESULT (WINAPI *ConnectDirect)(IGraphBuilder *This,IPin *ppinOut,IPin *ppinIn,const AM_MEDIA_TYPE *pmt); - HRESULT (WINAPI *Reconnect)(IGraphBuilder *This,IPin *ppin); - HRESULT (WINAPI *Disconnect)(IGraphBuilder *This,IPin *ppin); - HRESULT (WINAPI *SetDefaultSyncSource)(IGraphBuilder *This); - HRESULT (WINAPI *Connect)(IGraphBuilder *This,IPin *ppinOut,IPin *ppinIn); - HRESULT (WINAPI *Render)(IGraphBuilder *This,IPin *ppinOut); - HRESULT (WINAPI *RenderFile)(IGraphBuilder *This,LPCWSTR lpcwstrFile,LPCWSTR lpcwstrPlayList); - HRESULT (WINAPI *AddSourceFilter)(IGraphBuilder *This,LPCWSTR lpcwstrFileName,LPCWSTR lpcwstrFilterName,IBaseFilter **ppFilter); - HRESULT (WINAPI *SetLogFile)(IGraphBuilder *This,DWORD_PTR hFile); - HRESULT (WINAPI *Abort)(IGraphBuilder *This); - HRESULT (WINAPI *ShouldOperationContinue)(IGraphBuilder *This); - END_INTERFACE - } IGraphBuilderVtbl; - struct IGraphBuilder { - CONST_VTBL struct IGraphBuilderVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IGraphBuilder_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IGraphBuilder_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IGraphBuilder_Release(This) (This)->lpVtbl->Release(This) -#define IGraphBuilder_AddFilter(This,pFilter,pName) (This)->lpVtbl->AddFilter(This,pFilter,pName) -#define IGraphBuilder_RemoveFilter(This,pFilter) (This)->lpVtbl->RemoveFilter(This,pFilter) -#define IGraphBuilder_EnumFilters(This,ppEnum) (This)->lpVtbl->EnumFilters(This,ppEnum) -#define IGraphBuilder_FindFilterByName(This,pName,ppFilter) (This)->lpVtbl->FindFilterByName(This,pName,ppFilter) -#define IGraphBuilder_ConnectDirect(This,ppinOut,ppinIn,pmt) (This)->lpVtbl->ConnectDirect(This,ppinOut,ppinIn,pmt) -#define IGraphBuilder_Reconnect(This,ppin) (This)->lpVtbl->Reconnect(This,ppin) -#define IGraphBuilder_Disconnect(This,ppin) (This)->lpVtbl->Disconnect(This,ppin) -#define IGraphBuilder_SetDefaultSyncSource(This) (This)->lpVtbl->SetDefaultSyncSource(This) -#define IGraphBuilder_Connect(This,ppinOut,ppinIn) (This)->lpVtbl->Connect(This,ppinOut,ppinIn) -#define IGraphBuilder_Render(This,ppinOut) (This)->lpVtbl->Render(This,ppinOut) -#define IGraphBuilder_RenderFile(This,lpcwstrFile,lpcwstrPlayList) (This)->lpVtbl->RenderFile(This,lpcwstrFile,lpcwstrPlayList) -#define IGraphBuilder_AddSourceFilter(This,lpcwstrFileName,lpcwstrFilterName,ppFilter) (This)->lpVtbl->AddSourceFilter(This,lpcwstrFileName,lpcwstrFilterName,ppFilter) -#define IGraphBuilder_SetLogFile(This,hFile) (This)->lpVtbl->SetLogFile(This,hFile) -#define IGraphBuilder_Abort(This) (This)->lpVtbl->Abort(This) -#define IGraphBuilder_ShouldOperationContinue(This) (This)->lpVtbl->ShouldOperationContinue(This) -#endif -#endif - HRESULT WINAPI IGraphBuilder_Connect_Proxy(IGraphBuilder *This,IPin *ppinOut,IPin *ppinIn); - void __RPC_STUB IGraphBuilder_Connect_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IGraphBuilder_Render_Proxy(IGraphBuilder *This,IPin *ppinOut); - void __RPC_STUB IGraphBuilder_Render_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IGraphBuilder_RenderFile_Proxy(IGraphBuilder *This,LPCWSTR lpcwstrFile,LPCWSTR lpcwstrPlayList); - void __RPC_STUB IGraphBuilder_RenderFile_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IGraphBuilder_AddSourceFilter_Proxy(IGraphBuilder *This,LPCWSTR lpcwstrFileName,LPCWSTR lpcwstrFilterName,IBaseFilter **ppFilter); - void __RPC_STUB IGraphBuilder_AddSourceFilter_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IGraphBuilder_SetLogFile_Proxy(IGraphBuilder *This,DWORD_PTR hFile); - void __RPC_STUB IGraphBuilder_SetLogFile_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IGraphBuilder_Abort_Proxy(IGraphBuilder *This); - void __RPC_STUB IGraphBuilder_Abort_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IGraphBuilder_ShouldOperationContinue_Proxy(IGraphBuilder *This); - void __RPC_STUB IGraphBuilder_ShouldOperationContinue_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __ICaptureGraphBuilder_INTERFACE_DEFINED__ -#define __ICaptureGraphBuilder_INTERFACE_DEFINED__ - EXTERN_C const IID IID_ICaptureGraphBuilder; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct ICaptureGraphBuilder : public IUnknown { - public: - virtual HRESULT WINAPI SetFiltergraph(IGraphBuilder *pfg) = 0; - virtual HRESULT WINAPI GetFiltergraph(IGraphBuilder **ppfg) = 0; - virtual HRESULT WINAPI SetOutputFileName(const GUID *pType,LPCOLESTR lpstrFile,IBaseFilter **ppf,IFileSinkFilter **ppSink) = 0; - virtual HRESULT WINAPI FindInterface(const GUID *pCategory,IBaseFilter *pf,REFIID riid,void **ppint) = 0; - virtual HRESULT WINAPI RenderStream(const GUID *pCategory,IUnknown *pSource,IBaseFilter *pfCompressor,IBaseFilter *pfRenderer) = 0; - virtual HRESULT WINAPI ControlStream(const GUID *pCategory,IBaseFilter *pFilter,REFERENCE_TIME *pstart,REFERENCE_TIME *pstop,WORD wStartCookie,WORD wStopCookie) = 0; - virtual HRESULT WINAPI AllocCapFile(LPCOLESTR lpstr,DWORDLONG dwlSize) = 0; - virtual HRESULT WINAPI CopyCaptureFile(LPOLESTR lpwstrOld,LPOLESTR lpwstrNew,int fAllowEscAbort,IAMCopyCaptureFileProgress *pCallback) = 0; - }; -#else - typedef struct ICaptureGraphBuilderVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(ICaptureGraphBuilder *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(ICaptureGraphBuilder *This); - ULONG (WINAPI *Release)(ICaptureGraphBuilder *This); - HRESULT (WINAPI *SetFiltergraph)(ICaptureGraphBuilder *This,IGraphBuilder *pfg); - HRESULT (WINAPI *GetFiltergraph)(ICaptureGraphBuilder *This,IGraphBuilder **ppfg); - HRESULT (WINAPI *SetOutputFileName)(ICaptureGraphBuilder *This,const GUID *pType,LPCOLESTR lpstrFile,IBaseFilter **ppf,IFileSinkFilter **ppSink); - HRESULT (WINAPI *FindInterface)(ICaptureGraphBuilder *This,const GUID *pCategory,IBaseFilter *pf,REFIID riid,void **ppint); - HRESULT (WINAPI *RenderStream)(ICaptureGraphBuilder *This,const GUID *pCategory,IUnknown *pSource,IBaseFilter *pfCompressor,IBaseFilter *pfRenderer); - HRESULT (WINAPI *ControlStream)(ICaptureGraphBuilder *This,const GUID *pCategory,IBaseFilter *pFilter,REFERENCE_TIME *pstart,REFERENCE_TIME *pstop,WORD wStartCookie,WORD wStopCookie); - HRESULT (WINAPI *AllocCapFile)(ICaptureGraphBuilder *This,LPCOLESTR lpstr,DWORDLONG dwlSize); - HRESULT (WINAPI *CopyCaptureFile)(ICaptureGraphBuilder *This,LPOLESTR lpwstrOld,LPOLESTR lpwstrNew,int fAllowEscAbort,IAMCopyCaptureFileProgress *pCallback); - END_INTERFACE - } ICaptureGraphBuilderVtbl; - struct ICaptureGraphBuilder { - CONST_VTBL struct ICaptureGraphBuilderVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define ICaptureGraphBuilder_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define ICaptureGraphBuilder_AddRef(This) (This)->lpVtbl->AddRef(This) -#define ICaptureGraphBuilder_Release(This) (This)->lpVtbl->Release(This) -#define ICaptureGraphBuilder_SetFiltergraph(This,pfg) (This)->lpVtbl->SetFiltergraph(This,pfg) -#define ICaptureGraphBuilder_GetFiltergraph(This,ppfg) (This)->lpVtbl->GetFiltergraph(This,ppfg) -#define ICaptureGraphBuilder_SetOutputFileName(This,pType,lpstrFile,ppf,ppSink) (This)->lpVtbl->SetOutputFileName(This,pType,lpstrFile,ppf,ppSink) -#define ICaptureGraphBuilder_FindInterface(This,pCategory,pf,riid,ppint) (This)->lpVtbl->FindInterface(This,pCategory,pf,riid,ppint) -#define ICaptureGraphBuilder_RenderStream(This,pCategory,pSource,pfCompressor,pfRenderer) (This)->lpVtbl->RenderStream(This,pCategory,pSource,pfCompressor,pfRenderer) -#define ICaptureGraphBuilder_ControlStream(This,pCategory,pFilter,pstart,pstop,wStartCookie,wStopCookie) (This)->lpVtbl->ControlStream(This,pCategory,pFilter,pstart,pstop,wStartCookie,wStopCookie) -#define ICaptureGraphBuilder_AllocCapFile(This,lpstr,dwlSize) (This)->lpVtbl->AllocCapFile(This,lpstr,dwlSize) -#define ICaptureGraphBuilder_CopyCaptureFile(This,lpwstrOld,lpwstrNew,fAllowEscAbort,pCallback) (This)->lpVtbl->CopyCaptureFile(This,lpwstrOld,lpwstrNew,fAllowEscAbort,pCallback) -#endif -#endif - HRESULT WINAPI ICaptureGraphBuilder_SetFiltergraph_Proxy(ICaptureGraphBuilder *This,IGraphBuilder *pfg); - void __RPC_STUB ICaptureGraphBuilder_SetFiltergraph_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI ICaptureGraphBuilder_GetFiltergraph_Proxy(ICaptureGraphBuilder *This,IGraphBuilder **ppfg); - void __RPC_STUB ICaptureGraphBuilder_GetFiltergraph_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI ICaptureGraphBuilder_SetOutputFileName_Proxy(ICaptureGraphBuilder *This,const GUID *pType,LPCOLESTR lpstrFile,IBaseFilter **ppf,IFileSinkFilter **ppSink); - void __RPC_STUB ICaptureGraphBuilder_SetOutputFileName_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI ICaptureGraphBuilder_RemoteFindInterface_Proxy(ICaptureGraphBuilder *This,const GUID *pCategory,IBaseFilter *pf,REFIID riid,IUnknown **ppint); - void __RPC_STUB ICaptureGraphBuilder_RemoteFindInterface_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI ICaptureGraphBuilder_RenderStream_Proxy(ICaptureGraphBuilder *This,const GUID *pCategory,IUnknown *pSource,IBaseFilter *pfCompressor,IBaseFilter *pfRenderer); - void __RPC_STUB ICaptureGraphBuilder_RenderStream_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI ICaptureGraphBuilder_ControlStream_Proxy(ICaptureGraphBuilder *This,const GUID *pCategory,IBaseFilter *pFilter,REFERENCE_TIME *pstart,REFERENCE_TIME *pstop,WORD wStartCookie,WORD wStopCookie); - void __RPC_STUB ICaptureGraphBuilder_ControlStream_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI ICaptureGraphBuilder_AllocCapFile_Proxy(ICaptureGraphBuilder *This,LPCOLESTR lpstr,DWORDLONG dwlSize); - void __RPC_STUB ICaptureGraphBuilder_AllocCapFile_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI ICaptureGraphBuilder_CopyCaptureFile_Proxy(ICaptureGraphBuilder *This,LPOLESTR lpwstrOld,LPOLESTR lpwstrNew,int fAllowEscAbort,IAMCopyCaptureFileProgress *pCallback); - void __RPC_STUB ICaptureGraphBuilder_CopyCaptureFile_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IAMCopyCaptureFileProgress_INTERFACE_DEFINED__ -#define __IAMCopyCaptureFileProgress_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IAMCopyCaptureFileProgress; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IAMCopyCaptureFileProgress : public IUnknown { - public: - virtual HRESULT WINAPI Progress(int iProgress) = 0; - }; -#else - typedef struct IAMCopyCaptureFileProgressVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IAMCopyCaptureFileProgress *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IAMCopyCaptureFileProgress *This); - ULONG (WINAPI *Release)(IAMCopyCaptureFileProgress *This); - HRESULT (WINAPI *Progress)(IAMCopyCaptureFileProgress *This,int iProgress); - END_INTERFACE - } IAMCopyCaptureFileProgressVtbl; - struct IAMCopyCaptureFileProgress { - CONST_VTBL struct IAMCopyCaptureFileProgressVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IAMCopyCaptureFileProgress_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IAMCopyCaptureFileProgress_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IAMCopyCaptureFileProgress_Release(This) (This)->lpVtbl->Release(This) -#define IAMCopyCaptureFileProgress_Progress(This,iProgress) (This)->lpVtbl->Progress(This,iProgress) -#endif -#endif - HRESULT WINAPI IAMCopyCaptureFileProgress_Progress_Proxy(IAMCopyCaptureFileProgress *This,int iProgress); - void __RPC_STUB IAMCopyCaptureFileProgress_Progress_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __ICaptureGraphBuilder2_INTERFACE_DEFINED__ -#define __ICaptureGraphBuilder2_INTERFACE_DEFINED__ - EXTERN_C const IID IID_ICaptureGraphBuilder2; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct ICaptureGraphBuilder2 : public IUnknown { - public: - virtual HRESULT WINAPI SetFiltergraph(IGraphBuilder *pfg) = 0; - virtual HRESULT WINAPI GetFiltergraph(IGraphBuilder **ppfg) = 0; - virtual HRESULT WINAPI SetOutputFileName(const GUID *pType,LPCOLESTR lpstrFile,IBaseFilter **ppf,IFileSinkFilter **ppSink) = 0; - virtual HRESULT WINAPI FindInterface(const GUID *pCategory,const GUID *pType,IBaseFilter *pf,REFIID riid,void **ppint) = 0; - virtual HRESULT WINAPI RenderStream(const GUID *pCategory,const GUID *pType,IUnknown *pSource,IBaseFilter *pfCompressor,IBaseFilter *pfRenderer) = 0; - virtual HRESULT WINAPI ControlStream(const GUID *pCategory,const GUID *pType,IBaseFilter *pFilter,REFERENCE_TIME *pstart,REFERENCE_TIME *pstop,WORD wStartCookie,WORD wStopCookie) = 0; - virtual HRESULT WINAPI AllocCapFile(LPCOLESTR lpstr,DWORDLONG dwlSize) = 0; - virtual HRESULT WINAPI CopyCaptureFile(LPOLESTR lpwstrOld,LPOLESTR lpwstrNew,int fAllowEscAbort,IAMCopyCaptureFileProgress *pCallback) = 0; - virtual HRESULT WINAPI FindPin(IUnknown *pSource,PIN_DIRECTION pindir,const GUID *pCategory,const GUID *pType,WINBOOL fUnconnected,int num,IPin **ppPin) = 0; - }; -#else - typedef struct ICaptureGraphBuilder2Vtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(ICaptureGraphBuilder2 *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(ICaptureGraphBuilder2 *This); - ULONG (WINAPI *Release)(ICaptureGraphBuilder2 *This); - HRESULT (WINAPI *SetFiltergraph)(ICaptureGraphBuilder2 *This,IGraphBuilder *pfg); - HRESULT (WINAPI *GetFiltergraph)(ICaptureGraphBuilder2 *This,IGraphBuilder **ppfg); - HRESULT (WINAPI *SetOutputFileName)(ICaptureGraphBuilder2 *This,const GUID *pType,LPCOLESTR lpstrFile,IBaseFilter **ppf,IFileSinkFilter **ppSink); - HRESULT (WINAPI *FindInterface)(ICaptureGraphBuilder2 *This,const GUID *pCategory,const GUID *pType,IBaseFilter *pf,REFIID riid,void **ppint); - HRESULT (WINAPI *RenderStream)(ICaptureGraphBuilder2 *This,const GUID *pCategory,const GUID *pType,IUnknown *pSource,IBaseFilter *pfCompressor,IBaseFilter *pfRenderer); - HRESULT (WINAPI *ControlStream)(ICaptureGraphBuilder2 *This,const GUID *pCategory,const GUID *pType,IBaseFilter *pFilter,REFERENCE_TIME *pstart,REFERENCE_TIME *pstop,WORD wStartCookie,WORD wStopCookie); - HRESULT (WINAPI *AllocCapFile)(ICaptureGraphBuilder2 *This,LPCOLESTR lpstr,DWORDLONG dwlSize); - HRESULT (WINAPI *CopyCaptureFile)(ICaptureGraphBuilder2 *This,LPOLESTR lpwstrOld,LPOLESTR lpwstrNew,int fAllowEscAbort,IAMCopyCaptureFileProgress *pCallback); - HRESULT (WINAPI *FindPin)(ICaptureGraphBuilder2 *This,IUnknown *pSource,PIN_DIRECTION pindir,const GUID *pCategory,const GUID *pType,WINBOOL fUnconnected,int num,IPin **ppPin); - END_INTERFACE - } ICaptureGraphBuilder2Vtbl; - struct ICaptureGraphBuilder2 { - CONST_VTBL struct ICaptureGraphBuilder2Vtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define ICaptureGraphBuilder2_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define ICaptureGraphBuilder2_AddRef(This) (This)->lpVtbl->AddRef(This) -#define ICaptureGraphBuilder2_Release(This) (This)->lpVtbl->Release(This) -#define ICaptureGraphBuilder2_SetFiltergraph(This,pfg) (This)->lpVtbl->SetFiltergraph(This,pfg) -#define ICaptureGraphBuilder2_GetFiltergraph(This,ppfg) (This)->lpVtbl->GetFiltergraph(This,ppfg) -#define ICaptureGraphBuilder2_SetOutputFileName(This,pType,lpstrFile,ppf,ppSink) (This)->lpVtbl->SetOutputFileName(This,pType,lpstrFile,ppf,ppSink) -#define ICaptureGraphBuilder2_FindInterface(This,pCategory,pType,pf,riid,ppint) (This)->lpVtbl->FindInterface(This,pCategory,pType,pf,riid,ppint) -#define ICaptureGraphBuilder2_RenderStream(This,pCategory,pType,pSource,pfCompressor,pfRenderer) (This)->lpVtbl->RenderStream(This,pCategory,pType,pSource,pfCompressor,pfRenderer) -#define ICaptureGraphBuilder2_ControlStream(This,pCategory,pType,pFilter,pstart,pstop,wStartCookie,wStopCookie) (This)->lpVtbl->ControlStream(This,pCategory,pType,pFilter,pstart,pstop,wStartCookie,wStopCookie) -#define ICaptureGraphBuilder2_AllocCapFile(This,lpstr,dwlSize) (This)->lpVtbl->AllocCapFile(This,lpstr,dwlSize) -#define ICaptureGraphBuilder2_CopyCaptureFile(This,lpwstrOld,lpwstrNew,fAllowEscAbort,pCallback) (This)->lpVtbl->CopyCaptureFile(This,lpwstrOld,lpwstrNew,fAllowEscAbort,pCallback) -#define ICaptureGraphBuilder2_FindPin(This,pSource,pindir,pCategory,pType,fUnconnected,num,ppPin) (This)->lpVtbl->FindPin(This,pSource,pindir,pCategory,pType,fUnconnected,num,ppPin) -#endif -#endif - HRESULT WINAPI ICaptureGraphBuilder2_SetFiltergraph_Proxy(ICaptureGraphBuilder2 *This,IGraphBuilder *pfg); - void __RPC_STUB ICaptureGraphBuilder2_SetFiltergraph_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI ICaptureGraphBuilder2_GetFiltergraph_Proxy(ICaptureGraphBuilder2 *This,IGraphBuilder **ppfg); - void __RPC_STUB ICaptureGraphBuilder2_GetFiltergraph_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI ICaptureGraphBuilder2_SetOutputFileName_Proxy(ICaptureGraphBuilder2 *This,const GUID *pType,LPCOLESTR lpstrFile,IBaseFilter **ppf,IFileSinkFilter **ppSink); - void __RPC_STUB ICaptureGraphBuilder2_SetOutputFileName_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI ICaptureGraphBuilder2_RemoteFindInterface_Proxy(ICaptureGraphBuilder2 *This,const GUID *pCategory,const GUID *pType,IBaseFilter *pf,REFIID riid,IUnknown **ppint); - void __RPC_STUB ICaptureGraphBuilder2_RemoteFindInterface_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI ICaptureGraphBuilder2_RenderStream_Proxy(ICaptureGraphBuilder2 *This,const GUID *pCategory,const GUID *pType,IUnknown *pSource,IBaseFilter *pfCompressor,IBaseFilter *pfRenderer); - void __RPC_STUB ICaptureGraphBuilder2_RenderStream_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI ICaptureGraphBuilder2_ControlStream_Proxy(ICaptureGraphBuilder2 *This,const GUID *pCategory,const GUID *pType,IBaseFilter *pFilter,REFERENCE_TIME *pstart,REFERENCE_TIME *pstop,WORD wStartCookie,WORD wStopCookie); - void __RPC_STUB ICaptureGraphBuilder2_ControlStream_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI ICaptureGraphBuilder2_AllocCapFile_Proxy(ICaptureGraphBuilder2 *This,LPCOLESTR lpstr,DWORDLONG dwlSize); - void __RPC_STUB ICaptureGraphBuilder2_AllocCapFile_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI ICaptureGraphBuilder2_CopyCaptureFile_Proxy(ICaptureGraphBuilder2 *This,LPOLESTR lpwstrOld,LPOLESTR lpwstrNew,int fAllowEscAbort,IAMCopyCaptureFileProgress *pCallback); - void __RPC_STUB ICaptureGraphBuilder2_CopyCaptureFile_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI ICaptureGraphBuilder2_FindPin_Proxy(ICaptureGraphBuilder2 *This,IUnknown *pSource,PIN_DIRECTION pindir,const GUID *pCategory,const GUID *pType,WINBOOL fUnconnected,int num,IPin **ppPin); - void __RPC_STUB ICaptureGraphBuilder2_FindPin_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - enum _AM_RENSDEREXFLAGS { - AM_RENDEREX_RENDERTOEXISTINGRENDERERS = 0x1 - }; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0153_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0153_v0_0_s_ifspec; -#ifndef __IFilterGraph2_INTERFACE_DEFINED__ -#define __IFilterGraph2_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IFilterGraph2; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IFilterGraph2 : public IGraphBuilder { - public: - virtual HRESULT WINAPI AddSourceFilterForMoniker(IMoniker *pMoniker,IBindCtx *pCtx,LPCWSTR lpcwstrFilterName,IBaseFilter **ppFilter) = 0; - virtual HRESULT WINAPI ReconnectEx(IPin *ppin,const AM_MEDIA_TYPE *pmt) = 0; - virtual HRESULT WINAPI RenderEx(IPin *pPinOut,DWORD dwFlags,DWORD *pvContext) = 0; - }; -#else - typedef struct IFilterGraph2Vtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IFilterGraph2 *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IFilterGraph2 *This); - ULONG (WINAPI *Release)(IFilterGraph2 *This); - HRESULT (WINAPI *AddFilter)(IFilterGraph2 *This,IBaseFilter *pFilter,LPCWSTR pName); - HRESULT (WINAPI *RemoveFilter)(IFilterGraph2 *This,IBaseFilter *pFilter); - HRESULT (WINAPI *EnumFilters)(IFilterGraph2 *This,IEnumFilters **ppEnum); - HRESULT (WINAPI *FindFilterByName)(IFilterGraph2 *This,LPCWSTR pName,IBaseFilter **ppFilter); - HRESULT (WINAPI *ConnectDirect)(IFilterGraph2 *This,IPin *ppinOut,IPin *ppinIn,const AM_MEDIA_TYPE *pmt); - HRESULT (WINAPI *Reconnect)(IFilterGraph2 *This,IPin *ppin); - HRESULT (WINAPI *Disconnect)(IFilterGraph2 *This,IPin *ppin); - HRESULT (WINAPI *SetDefaultSyncSource)(IFilterGraph2 *This); - HRESULT (WINAPI *Connect)(IFilterGraph2 *This,IPin *ppinOut,IPin *ppinIn); - HRESULT (WINAPI *Render)(IFilterGraph2 *This,IPin *ppinOut); - HRESULT (WINAPI *RenderFile)(IFilterGraph2 *This,LPCWSTR lpcwstrFile,LPCWSTR lpcwstrPlayList); - HRESULT (WINAPI *AddSourceFilter)(IFilterGraph2 *This,LPCWSTR lpcwstrFileName,LPCWSTR lpcwstrFilterName,IBaseFilter **ppFilter); - HRESULT (WINAPI *SetLogFile)(IFilterGraph2 *This,DWORD_PTR hFile); - HRESULT (WINAPI *Abort)(IFilterGraph2 *This); - HRESULT (WINAPI *ShouldOperationContinue)(IFilterGraph2 *This); - HRESULT (WINAPI *AddSourceFilterForMoniker)(IFilterGraph2 *This,IMoniker *pMoniker,IBindCtx *pCtx,LPCWSTR lpcwstrFilterName,IBaseFilter **ppFilter); - HRESULT (WINAPI *ReconnectEx)(IFilterGraph2 *This,IPin *ppin,const AM_MEDIA_TYPE *pmt); - HRESULT (WINAPI *RenderEx)(IFilterGraph2 *This,IPin *pPinOut,DWORD dwFlags,DWORD *pvContext); - END_INTERFACE - } IFilterGraph2Vtbl; - struct IFilterGraph2 { - CONST_VTBL struct IFilterGraph2Vtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IFilterGraph2_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IFilterGraph2_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IFilterGraph2_Release(This) (This)->lpVtbl->Release(This) -#define IFilterGraph2_AddFilter(This,pFilter,pName) (This)->lpVtbl->AddFilter(This,pFilter,pName) -#define IFilterGraph2_RemoveFilter(This,pFilter) (This)->lpVtbl->RemoveFilter(This,pFilter) -#define IFilterGraph2_EnumFilters(This,ppEnum) (This)->lpVtbl->EnumFilters(This,ppEnum) -#define IFilterGraph2_FindFilterByName(This,pName,ppFilter) (This)->lpVtbl->FindFilterByName(This,pName,ppFilter) -#define IFilterGraph2_ConnectDirect(This,ppinOut,ppinIn,pmt) (This)->lpVtbl->ConnectDirect(This,ppinOut,ppinIn,pmt) -#define IFilterGraph2_Reconnect(This,ppin) (This)->lpVtbl->Reconnect(This,ppin) -#define IFilterGraph2_Disconnect(This,ppin) (This)->lpVtbl->Disconnect(This,ppin) -#define IFilterGraph2_SetDefaultSyncSource(This) (This)->lpVtbl->SetDefaultSyncSource(This) -#define IFilterGraph2_Connect(This,ppinOut,ppinIn) (This)->lpVtbl->Connect(This,ppinOut,ppinIn) -#define IFilterGraph2_Render(This,ppinOut) (This)->lpVtbl->Render(This,ppinOut) -#define IFilterGraph2_RenderFile(This,lpcwstrFile,lpcwstrPlayList) (This)->lpVtbl->RenderFile(This,lpcwstrFile,lpcwstrPlayList) -#define IFilterGraph2_AddSourceFilter(This,lpcwstrFileName,lpcwstrFilterName,ppFilter) (This)->lpVtbl->AddSourceFilter(This,lpcwstrFileName,lpcwstrFilterName,ppFilter) -#define IFilterGraph2_SetLogFile(This,hFile) (This)->lpVtbl->SetLogFile(This,hFile) -#define IFilterGraph2_Abort(This) (This)->lpVtbl->Abort(This) -#define IFilterGraph2_ShouldOperationContinue(This) (This)->lpVtbl->ShouldOperationContinue(This) -#define IFilterGraph2_AddSourceFilterForMoniker(This,pMoniker,pCtx,lpcwstrFilterName,ppFilter) (This)->lpVtbl->AddSourceFilterForMoniker(This,pMoniker,pCtx,lpcwstrFilterName,ppFilter) -#define IFilterGraph2_ReconnectEx(This,ppin,pmt) (This)->lpVtbl->ReconnectEx(This,ppin,pmt) -#define IFilterGraph2_RenderEx(This,pPinOut,dwFlags,pvContext) (This)->lpVtbl->RenderEx(This,pPinOut,dwFlags,pvContext) -#endif -#endif - HRESULT WINAPI IFilterGraph2_AddSourceFilterForMoniker_Proxy(IFilterGraph2 *This,IMoniker *pMoniker,IBindCtx *pCtx,LPCWSTR lpcwstrFilterName,IBaseFilter **ppFilter); - void __RPC_STUB IFilterGraph2_AddSourceFilterForMoniker_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IFilterGraph2_ReconnectEx_Proxy(IFilterGraph2 *This,IPin *ppin,const AM_MEDIA_TYPE *pmt); - void __RPC_STUB IFilterGraph2_ReconnectEx_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IFilterGraph2_RenderEx_Proxy(IFilterGraph2 *This,IPin *pPinOut,DWORD dwFlags,DWORD *pvContext); - void __RPC_STUB IFilterGraph2_RenderEx_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IStreamBuilder_INTERFACE_DEFINED__ -#define __IStreamBuilder_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IStreamBuilder; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IStreamBuilder : public IUnknown { - public: - virtual HRESULT WINAPI Render(IPin *ppinOut,IGraphBuilder *pGraph) = 0; - virtual HRESULT WINAPI Backout(IPin *ppinOut,IGraphBuilder *pGraph) = 0; - }; -#else - typedef struct IStreamBuilderVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IStreamBuilder *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IStreamBuilder *This); - ULONG (WINAPI *Release)(IStreamBuilder *This); - HRESULT (WINAPI *Render)(IStreamBuilder *This,IPin *ppinOut,IGraphBuilder *pGraph); - HRESULT (WINAPI *Backout)(IStreamBuilder *This,IPin *ppinOut,IGraphBuilder *pGraph); - END_INTERFACE - } IStreamBuilderVtbl; - struct IStreamBuilder { - CONST_VTBL struct IStreamBuilderVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IStreamBuilder_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IStreamBuilder_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IStreamBuilder_Release(This) (This)->lpVtbl->Release(This) -#define IStreamBuilder_Render(This,ppinOut,pGraph) (This)->lpVtbl->Render(This,ppinOut,pGraph) -#define IStreamBuilder_Backout(This,ppinOut,pGraph) (This)->lpVtbl->Backout(This,ppinOut,pGraph) -#endif -#endif - HRESULT WINAPI IStreamBuilder_Render_Proxy(IStreamBuilder *This,IPin *ppinOut,IGraphBuilder *pGraph); - void __RPC_STUB IStreamBuilder_Render_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IStreamBuilder_Backout_Proxy(IStreamBuilder *This,IPin *ppinOut,IGraphBuilder *pGraph); - void __RPC_STUB IStreamBuilder_Backout_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IAsyncReader_INTERFACE_DEFINED__ -#define __IAsyncReader_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IAsyncReader; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IAsyncReader : public IUnknown { - public: - virtual HRESULT WINAPI RequestAllocator(IMemAllocator *pPreferred,ALLOCATOR_PROPERTIES *pProps,IMemAllocator **ppActual) = 0; - virtual HRESULT WINAPI Request(IMediaSample *pSample,DWORD_PTR dwUser) = 0; - virtual HRESULT WINAPI WaitForNext(DWORD dwTimeout,IMediaSample **ppSample,DWORD_PTR *pdwUser) = 0; - virtual HRESULT WINAPI SyncReadAligned(IMediaSample *pSample) = 0; - virtual HRESULT WINAPI SyncRead(LONGLONG llPosition,LONG lLength,BYTE *pBuffer) = 0; - virtual HRESULT WINAPI Length(LONGLONG *pTotal,LONGLONG *pAvailable) = 0; - virtual HRESULT WINAPI BeginFlush(void) = 0; - virtual HRESULT WINAPI EndFlush(void) = 0; - }; -#else - typedef struct IAsyncReaderVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IAsyncReader *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IAsyncReader *This); - ULONG (WINAPI *Release)(IAsyncReader *This); - HRESULT (WINAPI *RequestAllocator)(IAsyncReader *This,IMemAllocator *pPreferred,ALLOCATOR_PROPERTIES *pProps,IMemAllocator **ppActual); - HRESULT (WINAPI *Request)(IAsyncReader *This,IMediaSample *pSample,DWORD_PTR dwUser); - HRESULT (WINAPI *WaitForNext)(IAsyncReader *This,DWORD dwTimeout,IMediaSample **ppSample,DWORD_PTR *pdwUser); - HRESULT (WINAPI *SyncReadAligned)(IAsyncReader *This,IMediaSample *pSample); - HRESULT (WINAPI *SyncRead)(IAsyncReader *This,LONGLONG llPosition,LONG lLength,BYTE *pBuffer); - HRESULT (WINAPI *Length)(IAsyncReader *This,LONGLONG *pTotal,LONGLONG *pAvailable); - HRESULT (WINAPI *BeginFlush)(IAsyncReader *This); - HRESULT (WINAPI *EndFlush)(IAsyncReader *This); - END_INTERFACE - } IAsyncReaderVtbl; - struct IAsyncReader { - CONST_VTBL struct IAsyncReaderVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IAsyncReader_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IAsyncReader_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IAsyncReader_Release(This) (This)->lpVtbl->Release(This) -#define IAsyncReader_RequestAllocator(This,pPreferred,pProps,ppActual) (This)->lpVtbl->RequestAllocator(This,pPreferred,pProps,ppActual) -#define IAsyncReader_Request(This,pSample,dwUser) (This)->lpVtbl->Request(This,pSample,dwUser) -#define IAsyncReader_WaitForNext(This,dwTimeout,ppSample,pdwUser) (This)->lpVtbl->WaitForNext(This,dwTimeout,ppSample,pdwUser) -#define IAsyncReader_SyncReadAligned(This,pSample) (This)->lpVtbl->SyncReadAligned(This,pSample) -#define IAsyncReader_SyncRead(This,llPosition,lLength,pBuffer) (This)->lpVtbl->SyncRead(This,llPosition,lLength,pBuffer) -#define IAsyncReader_Length(This,pTotal,pAvailable) (This)->lpVtbl->Length(This,pTotal,pAvailable) -#define IAsyncReader_BeginFlush(This) (This)->lpVtbl->BeginFlush(This) -#define IAsyncReader_EndFlush(This) (This)->lpVtbl->EndFlush(This) -#endif -#endif - HRESULT WINAPI IAsyncReader_RequestAllocator_Proxy(IAsyncReader *This,IMemAllocator *pPreferred,ALLOCATOR_PROPERTIES *pProps,IMemAllocator **ppActual); - void __RPC_STUB IAsyncReader_RequestAllocator_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAsyncReader_Request_Proxy(IAsyncReader *This,IMediaSample *pSample,DWORD_PTR dwUser); - void __RPC_STUB IAsyncReader_Request_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAsyncReader_WaitForNext_Proxy(IAsyncReader *This,DWORD dwTimeout,IMediaSample **ppSample,DWORD_PTR *pdwUser); - void __RPC_STUB IAsyncReader_WaitForNext_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAsyncReader_SyncReadAligned_Proxy(IAsyncReader *This,IMediaSample *pSample); - void __RPC_STUB IAsyncReader_SyncReadAligned_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAsyncReader_SyncRead_Proxy(IAsyncReader *This,LONGLONG llPosition,LONG lLength,BYTE *pBuffer); - void __RPC_STUB IAsyncReader_SyncRead_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAsyncReader_Length_Proxy(IAsyncReader *This,LONGLONG *pTotal,LONGLONG *pAvailable); - void __RPC_STUB IAsyncReader_Length_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAsyncReader_BeginFlush_Proxy(IAsyncReader *This); - void __RPC_STUB IAsyncReader_BeginFlush_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAsyncReader_EndFlush_Proxy(IAsyncReader *This); - void __RPC_STUB IAsyncReader_EndFlush_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IGraphVersion_INTERFACE_DEFINED__ -#define __IGraphVersion_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IGraphVersion; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IGraphVersion : public IUnknown { - public: - virtual HRESULT WINAPI QueryVersion(LONG *pVersion) = 0; - }; -#else - typedef struct IGraphVersionVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IGraphVersion *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IGraphVersion *This); - ULONG (WINAPI *Release)(IGraphVersion *This); - HRESULT (WINAPI *QueryVersion)(IGraphVersion *This,LONG *pVersion); - END_INTERFACE - } IGraphVersionVtbl; - struct IGraphVersion { - CONST_VTBL struct IGraphVersionVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IGraphVersion_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IGraphVersion_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IGraphVersion_Release(This) (This)->lpVtbl->Release(This) -#define IGraphVersion_QueryVersion(This,pVersion) (This)->lpVtbl->QueryVersion(This,pVersion) -#endif -#endif - HRESULT WINAPI IGraphVersion_QueryVersion_Proxy(IGraphVersion *This,LONG *pVersion); - void __RPC_STUB IGraphVersion_QueryVersion_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IResourceConsumer_INTERFACE_DEFINED__ -#define __IResourceConsumer_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IResourceConsumer; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IResourceConsumer : public IUnknown { - public: - virtual HRESULT WINAPI AcquireResource(LONG idResource) = 0; - virtual HRESULT WINAPI ReleaseResource(LONG idResource) = 0; - }; -#else - typedef struct IResourceConsumerVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IResourceConsumer *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IResourceConsumer *This); - ULONG (WINAPI *Release)(IResourceConsumer *This); - HRESULT (WINAPI *AcquireResource)(IResourceConsumer *This,LONG idResource); - HRESULT (WINAPI *ReleaseResource)(IResourceConsumer *This,LONG idResource); - END_INTERFACE - } IResourceConsumerVtbl; - struct IResourceConsumer { - CONST_VTBL struct IResourceConsumerVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IResourceConsumer_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IResourceConsumer_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IResourceConsumer_Release(This) (This)->lpVtbl->Release(This) -#define IResourceConsumer_AcquireResource(This,idResource) (This)->lpVtbl->AcquireResource(This,idResource) -#define IResourceConsumer_ReleaseResource(This,idResource) (This)->lpVtbl->ReleaseResource(This,idResource) -#endif -#endif - HRESULT WINAPI IResourceConsumer_AcquireResource_Proxy(IResourceConsumer *This,LONG idResource); - void __RPC_STUB IResourceConsumer_AcquireResource_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IResourceConsumer_ReleaseResource_Proxy(IResourceConsumer *This,LONG idResource); - void __RPC_STUB IResourceConsumer_ReleaseResource_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IResourceManager_INTERFACE_DEFINED__ -#define __IResourceManager_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IResourceManager; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IResourceManager : public IUnknown { - public: - virtual HRESULT WINAPI Register(LPCWSTR pName,LONG cResource,LONG *plToken) = 0; - virtual HRESULT WINAPI RegisterGroup(LPCWSTR pName,LONG cResource,LONG *palTokens,LONG *plToken) = 0; - virtual HRESULT WINAPI RequestResource(LONG idResource,IUnknown *pFocusObject,IResourceConsumer *pConsumer) = 0; - virtual HRESULT WINAPI NotifyAcquire(LONG idResource,IResourceConsumer *pConsumer,HRESULT hr) = 0; - virtual HRESULT WINAPI NotifyRelease(LONG idResource,IResourceConsumer *pConsumer,WINBOOL bStillWant) = 0; - virtual HRESULT WINAPI CancelRequest(LONG idResource,IResourceConsumer *pConsumer) = 0; - virtual HRESULT WINAPI SetFocus(IUnknown *pFocusObject) = 0; - virtual HRESULT WINAPI ReleaseFocus(IUnknown *pFocusObject) = 0; - }; -#else - typedef struct IResourceManagerVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IResourceManager *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IResourceManager *This); - ULONG (WINAPI *Release)(IResourceManager *This); - HRESULT (WINAPI *Register)(IResourceManager *This,LPCWSTR pName,LONG cResource,LONG *plToken); - HRESULT (WINAPI *RegisterGroup)(IResourceManager *This,LPCWSTR pName,LONG cResource,LONG *palTokens,LONG *plToken); - HRESULT (WINAPI *RequestResource)(IResourceManager *This,LONG idResource,IUnknown *pFocusObject,IResourceConsumer *pConsumer); - HRESULT (WINAPI *NotifyAcquire)(IResourceManager *This,LONG idResource,IResourceConsumer *pConsumer,HRESULT hr); - HRESULT (WINAPI *NotifyRelease)(IResourceManager *This,LONG idResource,IResourceConsumer *pConsumer,WINBOOL bStillWant); - HRESULT (WINAPI *CancelRequest)(IResourceManager *This,LONG idResource,IResourceConsumer *pConsumer); - HRESULT (WINAPI *SetFocus)(IResourceManager *This,IUnknown *pFocusObject); - HRESULT (WINAPI *ReleaseFocus)(IResourceManager *This,IUnknown *pFocusObject); - END_INTERFACE - } IResourceManagerVtbl; - struct IResourceManager { - CONST_VTBL struct IResourceManagerVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IResourceManager_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IResourceManager_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IResourceManager_Release(This) (This)->lpVtbl->Release(This) -#define IResourceManager_Register(This,pName,cResource,plToken) (This)->lpVtbl->Register(This,pName,cResource,plToken) -#define IResourceManager_RegisterGroup(This,pName,cResource,palTokens,plToken) (This)->lpVtbl->RegisterGroup(This,pName,cResource,palTokens,plToken) -#define IResourceManager_RequestResource(This,idResource,pFocusObject,pConsumer) (This)->lpVtbl->RequestResource(This,idResource,pFocusObject,pConsumer) -#define IResourceManager_NotifyAcquire(This,idResource,pConsumer,hr) (This)->lpVtbl->NotifyAcquire(This,idResource,pConsumer,hr) -#define IResourceManager_NotifyRelease(This,idResource,pConsumer,bStillWant) (This)->lpVtbl->NotifyRelease(This,idResource,pConsumer,bStillWant) -#define IResourceManager_CancelRequest(This,idResource,pConsumer) (This)->lpVtbl->CancelRequest(This,idResource,pConsumer) -#define IResourceManager_SetFocus(This,pFocusObject) (This)->lpVtbl->SetFocus(This,pFocusObject) -#define IResourceManager_ReleaseFocus(This,pFocusObject) (This)->lpVtbl->ReleaseFocus(This,pFocusObject) -#endif -#endif - HRESULT WINAPI IResourceManager_Register_Proxy(IResourceManager *This,LPCWSTR pName,LONG cResource,LONG *plToken); - void __RPC_STUB IResourceManager_Register_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IResourceManager_RegisterGroup_Proxy(IResourceManager *This,LPCWSTR pName,LONG cResource,LONG *palTokens,LONG *plToken); - void __RPC_STUB IResourceManager_RegisterGroup_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IResourceManager_RequestResource_Proxy(IResourceManager *This,LONG idResource,IUnknown *pFocusObject,IResourceConsumer *pConsumer); - void __RPC_STUB IResourceManager_RequestResource_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IResourceManager_NotifyAcquire_Proxy(IResourceManager *This,LONG idResource,IResourceConsumer *pConsumer,HRESULT hr); - void __RPC_STUB IResourceManager_NotifyAcquire_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IResourceManager_NotifyRelease_Proxy(IResourceManager *This,LONG idResource,IResourceConsumer *pConsumer,WINBOOL bStillWant); - void __RPC_STUB IResourceManager_NotifyRelease_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IResourceManager_CancelRequest_Proxy(IResourceManager *This,LONG idResource,IResourceConsumer *pConsumer); - void __RPC_STUB IResourceManager_CancelRequest_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IResourceManager_SetFocus_Proxy(IResourceManager *This,IUnknown *pFocusObject); - void __RPC_STUB IResourceManager_SetFocus_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IResourceManager_ReleaseFocus_Proxy(IResourceManager *This,IUnknown *pFocusObject); - void __RPC_STUB IResourceManager_ReleaseFocus_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IDistributorNotify_INTERFACE_DEFINED__ -#define __IDistributorNotify_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IDistributorNotify; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IDistributorNotify : public IUnknown { - public: - virtual HRESULT WINAPI Stop(void) = 0; - virtual HRESULT WINAPI Pause(void) = 0; - virtual HRESULT WINAPI Run(REFERENCE_TIME tStart) = 0; - virtual HRESULT WINAPI SetSyncSource(IReferenceClock *pClock) = 0; - virtual HRESULT WINAPI NotifyGraphChange(void) = 0; - }; -#else - typedef struct IDistributorNotifyVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IDistributorNotify *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IDistributorNotify *This); - ULONG (WINAPI *Release)(IDistributorNotify *This); - HRESULT (WINAPI *Stop)(IDistributorNotify *This); - HRESULT (WINAPI *Pause)(IDistributorNotify *This); - HRESULT (WINAPI *Run)(IDistributorNotify *This,REFERENCE_TIME tStart); - HRESULT (WINAPI *SetSyncSource)(IDistributorNotify *This,IReferenceClock *pClock); - HRESULT (WINAPI *NotifyGraphChange)(IDistributorNotify *This); - END_INTERFACE - } IDistributorNotifyVtbl; - struct IDistributorNotify { - CONST_VTBL struct IDistributorNotifyVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IDistributorNotify_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IDistributorNotify_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IDistributorNotify_Release(This) (This)->lpVtbl->Release(This) -#define IDistributorNotify_Stop(This) (This)->lpVtbl->Stop(This) -#define IDistributorNotify_Pause(This) (This)->lpVtbl->Pause(This) -#define IDistributorNotify_Run(This,tStart) (This)->lpVtbl->Run(This,tStart) -#define IDistributorNotify_SetSyncSource(This,pClock) (This)->lpVtbl->SetSyncSource(This,pClock) -#define IDistributorNotify_NotifyGraphChange(This) (This)->lpVtbl->NotifyGraphChange(This) -#endif -#endif - HRESULT WINAPI IDistributorNotify_Stop_Proxy(IDistributorNotify *This); - void __RPC_STUB IDistributorNotify_Stop_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDistributorNotify_Pause_Proxy(IDistributorNotify *This); - void __RPC_STUB IDistributorNotify_Pause_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDistributorNotify_Run_Proxy(IDistributorNotify *This,REFERENCE_TIME tStart); - void __RPC_STUB IDistributorNotify_Run_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDistributorNotify_SetSyncSource_Proxy(IDistributorNotify *This,IReferenceClock *pClock); - void __RPC_STUB IDistributorNotify_SetSyncSource_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDistributorNotify_NotifyGraphChange_Proxy(IDistributorNotify *This); - void __RPC_STUB IDistributorNotify_NotifyGraphChange_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - typedef enum __MIDL___MIDL_itf_strmif_0160_0001 { - AM_STREAM_INFO_START_DEFINED = 0x1,AM_STREAM_INFO_STOP_DEFINED = 0x2,AM_STREAM_INFO_DISCARDING = 0x4,AM_STREAM_INFO_STOP_SEND_EXTRA = 0x10 - } AM_STREAM_INFO_FLAGS; - - typedef struct __MIDL___MIDL_itf_strmif_0160_0002 { - REFERENCE_TIME tStart; - REFERENCE_TIME tStop; - DWORD dwStartCookie; - DWORD dwStopCookie; - DWORD dwFlags; - } AM_STREAM_INFO; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0160_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0160_v0_0_s_ifspec; -#ifndef __IAMStreamControl_INTERFACE_DEFINED__ -#define __IAMStreamControl_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IAMStreamControl; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IAMStreamControl : public IUnknown { - public: - virtual HRESULT WINAPI StartAt(const REFERENCE_TIME *ptStart,DWORD dwCookie) = 0; - virtual HRESULT WINAPI StopAt(const REFERENCE_TIME *ptStop,WINBOOL bSendExtra,DWORD dwCookie) = 0; - virtual HRESULT WINAPI GetInfo(AM_STREAM_INFO *pInfo) = 0; - }; -#else - typedef struct IAMStreamControlVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IAMStreamControl *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IAMStreamControl *This); - ULONG (WINAPI *Release)(IAMStreamControl *This); - HRESULT (WINAPI *StartAt)(IAMStreamControl *This,const REFERENCE_TIME *ptStart,DWORD dwCookie); - HRESULT (WINAPI *StopAt)(IAMStreamControl *This,const REFERENCE_TIME *ptStop,WINBOOL bSendExtra,DWORD dwCookie); - HRESULT (WINAPI *GetInfo)(IAMStreamControl *This,AM_STREAM_INFO *pInfo); - END_INTERFACE - } IAMStreamControlVtbl; - struct IAMStreamControl { - CONST_VTBL struct IAMStreamControlVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IAMStreamControl_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IAMStreamControl_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IAMStreamControl_Release(This) (This)->lpVtbl->Release(This) -#define IAMStreamControl_StartAt(This,ptStart,dwCookie) (This)->lpVtbl->StartAt(This,ptStart,dwCookie) -#define IAMStreamControl_StopAt(This,ptStop,bSendExtra,dwCookie) (This)->lpVtbl->StopAt(This,ptStop,bSendExtra,dwCookie) -#define IAMStreamControl_GetInfo(This,pInfo) (This)->lpVtbl->GetInfo(This,pInfo) -#endif -#endif - HRESULT WINAPI IAMStreamControl_StartAt_Proxy(IAMStreamControl *This,const REFERENCE_TIME *ptStart,DWORD dwCookie); - void __RPC_STUB IAMStreamControl_StartAt_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMStreamControl_StopAt_Proxy(IAMStreamControl *This,const REFERENCE_TIME *ptStop,WINBOOL bSendExtra,DWORD dwCookie); - void __RPC_STUB IAMStreamControl_StopAt_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMStreamControl_GetInfo_Proxy(IAMStreamControl *This,AM_STREAM_INFO *pInfo); - void __RPC_STUB IAMStreamControl_GetInfo_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __ISeekingPassThru_INTERFACE_DEFINED__ -#define __ISeekingPassThru_INTERFACE_DEFINED__ - EXTERN_C const IID IID_ISeekingPassThru; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct ISeekingPassThru : public IUnknown { - public: - virtual HRESULT WINAPI Init(WINBOOL bSupportRendering,IPin *pPin) = 0; - }; -#else - typedef struct ISeekingPassThruVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(ISeekingPassThru *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(ISeekingPassThru *This); - ULONG (WINAPI *Release)(ISeekingPassThru *This); - HRESULT (WINAPI *Init)(ISeekingPassThru *This,WINBOOL bSupportRendering,IPin *pPin); - END_INTERFACE - } ISeekingPassThruVtbl; - struct ISeekingPassThru { - CONST_VTBL struct ISeekingPassThruVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define ISeekingPassThru_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define ISeekingPassThru_AddRef(This) (This)->lpVtbl->AddRef(This) -#define ISeekingPassThru_Release(This) (This)->lpVtbl->Release(This) -#define ISeekingPassThru_Init(This,bSupportRendering,pPin) (This)->lpVtbl->Init(This,bSupportRendering,pPin) -#endif -#endif - HRESULT WINAPI ISeekingPassThru_Init_Proxy(ISeekingPassThru *This,WINBOOL bSupportRendering,IPin *pPin); - void __RPC_STUB ISeekingPassThru_Init_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IAMStreamConfig_INTERFACE_DEFINED__ -#define __IAMStreamConfig_INTERFACE_DEFINED__ - typedef struct _VIDEO_STREAM_CONFIG_CAPS { - GUID guid; - ULONG VideoStandard; - SIZE InputSize; - SIZE MinCroppingSize; - SIZE MaxCroppingSize; - int CropGranularityX; - int CropGranularityY; - int CropAlignX; - int CropAlignY; - SIZE MinOutputSize; - SIZE MaxOutputSize; - int OutputGranularityX; - int OutputGranularityY; - int StretchTapsX; - int StretchTapsY; - int ShrinkTapsX; - int ShrinkTapsY; - LONGLONG MinFrameInterval; - LONGLONG MaxFrameInterval; - LONG MinBitsPerSecond; - LONG MaxBitsPerSecond; - } VIDEO_STREAM_CONFIG_CAPS; - - typedef struct _AUDIO_STREAM_CONFIG_CAPS { - GUID guid; - ULONG MinimumChannels; - ULONG MaximumChannels; - ULONG ChannelsGranularity; - ULONG MinimumBitsPerSample; - ULONG MaximumBitsPerSample; - ULONG BitsPerSampleGranularity; - ULONG MinimumSampleFrequency; - ULONG MaximumSampleFrequency; - ULONG SampleFrequencyGranularity; - } AUDIO_STREAM_CONFIG_CAPS; - - EXTERN_C const IID IID_IAMStreamConfig; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IAMStreamConfig : public IUnknown { - public: - virtual HRESULT WINAPI SetFormat(AM_MEDIA_TYPE *pmt) = 0; - virtual HRESULT WINAPI GetFormat(AM_MEDIA_TYPE **ppmt) = 0; - virtual HRESULT WINAPI GetNumberOfCapabilities(int *piCount,int *piSize) = 0; - virtual HRESULT WINAPI GetStreamCaps(int iIndex,AM_MEDIA_TYPE **ppmt,BYTE *pSCC) = 0; - }; -#else - typedef struct IAMStreamConfigVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IAMStreamConfig *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IAMStreamConfig *This); - ULONG (WINAPI *Release)(IAMStreamConfig *This); - HRESULT (WINAPI *SetFormat)(IAMStreamConfig *This,AM_MEDIA_TYPE *pmt); - HRESULT (WINAPI *GetFormat)(IAMStreamConfig *This,AM_MEDIA_TYPE **ppmt); - HRESULT (WINAPI *GetNumberOfCapabilities)(IAMStreamConfig *This,int *piCount,int *piSize); - HRESULT (WINAPI *GetStreamCaps)(IAMStreamConfig *This,int iIndex,AM_MEDIA_TYPE **ppmt,BYTE *pSCC); - END_INTERFACE - } IAMStreamConfigVtbl; - struct IAMStreamConfig { - CONST_VTBL struct IAMStreamConfigVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IAMStreamConfig_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IAMStreamConfig_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IAMStreamConfig_Release(This) (This)->lpVtbl->Release(This) -#define IAMStreamConfig_SetFormat(This,pmt) (This)->lpVtbl->SetFormat(This,pmt) -#define IAMStreamConfig_GetFormat(This,ppmt) (This)->lpVtbl->GetFormat(This,ppmt) -#define IAMStreamConfig_GetNumberOfCapabilities(This,piCount,piSize) (This)->lpVtbl->GetNumberOfCapabilities(This,piCount,piSize) -#define IAMStreamConfig_GetStreamCaps(This,iIndex,ppmt,pSCC) (This)->lpVtbl->GetStreamCaps(This,iIndex,ppmt,pSCC) -#endif -#endif - HRESULT WINAPI IAMStreamConfig_SetFormat_Proxy(IAMStreamConfig *This,AM_MEDIA_TYPE *pmt); - void __RPC_STUB IAMStreamConfig_SetFormat_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMStreamConfig_GetFormat_Proxy(IAMStreamConfig *This,AM_MEDIA_TYPE **ppmt); - void __RPC_STUB IAMStreamConfig_GetFormat_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMStreamConfig_GetNumberOfCapabilities_Proxy(IAMStreamConfig *This,int *piCount,int *piSize); - void __RPC_STUB IAMStreamConfig_GetNumberOfCapabilities_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMStreamConfig_GetStreamCaps_Proxy(IAMStreamConfig *This,int iIndex,AM_MEDIA_TYPE **ppmt,BYTE *pSCC); - void __RPC_STUB IAMStreamConfig_GetStreamCaps_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IConfigInterleaving_INTERFACE_DEFINED__ -#define __IConfigInterleaving_INTERFACE_DEFINED__ - typedef enum __MIDL_IConfigInterleaving_0001 { - INTERLEAVE_NONE = 0, - INTERLEAVE_CAPTURE,INTERLEAVE_FULL,INTERLEAVE_NONE_BUFFERED - } InterleavingMode; - - EXTERN_C const IID IID_IConfigInterleaving; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IConfigInterleaving : public IUnknown { - public: - virtual HRESULT WINAPI put_Mode(InterleavingMode mode) = 0; - virtual HRESULT WINAPI get_Mode(InterleavingMode *pMode) = 0; - virtual HRESULT WINAPI put_Interleaving(const REFERENCE_TIME *prtInterleave,const REFERENCE_TIME *prtPreroll) = 0; - virtual HRESULT WINAPI get_Interleaving(REFERENCE_TIME *prtInterleave,REFERENCE_TIME *prtPreroll) = 0; - }; -#else - typedef struct IConfigInterleavingVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IConfigInterleaving *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IConfigInterleaving *This); - ULONG (WINAPI *Release)(IConfigInterleaving *This); - HRESULT (WINAPI *put_Mode)(IConfigInterleaving *This,InterleavingMode mode); - HRESULT (WINAPI *get_Mode)(IConfigInterleaving *This,InterleavingMode *pMode); - HRESULT (WINAPI *put_Interleaving)(IConfigInterleaving *This,const REFERENCE_TIME *prtInterleave,const REFERENCE_TIME *prtPreroll); - HRESULT (WINAPI *get_Interleaving)(IConfigInterleaving *This,REFERENCE_TIME *prtInterleave,REFERENCE_TIME *prtPreroll); - END_INTERFACE - } IConfigInterleavingVtbl; - struct IConfigInterleaving { - CONST_VTBL struct IConfigInterleavingVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IConfigInterleaving_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IConfigInterleaving_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IConfigInterleaving_Release(This) (This)->lpVtbl->Release(This) -#define IConfigInterleaving_put_Mode(This,mode) (This)->lpVtbl->put_Mode(This,mode) -#define IConfigInterleaving_get_Mode(This,pMode) (This)->lpVtbl->get_Mode(This,pMode) -#define IConfigInterleaving_put_Interleaving(This,prtInterleave,prtPreroll) (This)->lpVtbl->put_Interleaving(This,prtInterleave,prtPreroll) -#define IConfigInterleaving_get_Interleaving(This,prtInterleave,prtPreroll) (This)->lpVtbl->get_Interleaving(This,prtInterleave,prtPreroll) -#endif -#endif - HRESULT WINAPI IConfigInterleaving_put_Mode_Proxy(IConfigInterleaving *This,InterleavingMode mode); - void __RPC_STUB IConfigInterleaving_put_Mode_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IConfigInterleaving_get_Mode_Proxy(IConfigInterleaving *This,InterleavingMode *pMode); - void __RPC_STUB IConfigInterleaving_get_Mode_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IConfigInterleaving_put_Interleaving_Proxy(IConfigInterleaving *This,const REFERENCE_TIME *prtInterleave,const REFERENCE_TIME *prtPreroll); - void __RPC_STUB IConfigInterleaving_put_Interleaving_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IConfigInterleaving_get_Interleaving_Proxy(IConfigInterleaving *This,REFERENCE_TIME *prtInterleave,REFERENCE_TIME *prtPreroll); - void __RPC_STUB IConfigInterleaving_get_Interleaving_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IConfigAviMux_INTERFACE_DEFINED__ -#define __IConfigAviMux_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IConfigAviMux; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IConfigAviMux : public IUnknown { - public: - virtual HRESULT WINAPI SetMasterStream(LONG iStream) = 0; - virtual HRESULT WINAPI GetMasterStream(LONG *pStream) = 0; - virtual HRESULT WINAPI SetOutputCompatibilityIndex(WINBOOL fOldIndex) = 0; - virtual HRESULT WINAPI GetOutputCompatibilityIndex(WINBOOL *pfOldIndex) = 0; - }; -#else - typedef struct IConfigAviMuxVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IConfigAviMux *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IConfigAviMux *This); - ULONG (WINAPI *Release)(IConfigAviMux *This); - HRESULT (WINAPI *SetMasterStream)(IConfigAviMux *This,LONG iStream); - HRESULT (WINAPI *GetMasterStream)(IConfigAviMux *This,LONG *pStream); - HRESULT (WINAPI *SetOutputCompatibilityIndex)(IConfigAviMux *This,WINBOOL fOldIndex); - HRESULT (WINAPI *GetOutputCompatibilityIndex)(IConfigAviMux *This,WINBOOL *pfOldIndex); - END_INTERFACE - } IConfigAviMuxVtbl; - struct IConfigAviMux { - CONST_VTBL struct IConfigAviMuxVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IConfigAviMux_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IConfigAviMux_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IConfigAviMux_Release(This) (This)->lpVtbl->Release(This) -#define IConfigAviMux_SetMasterStream(This,iStream) (This)->lpVtbl->SetMasterStream(This,iStream) -#define IConfigAviMux_GetMasterStream(This,pStream) (This)->lpVtbl->GetMasterStream(This,pStream) -#define IConfigAviMux_SetOutputCompatibilityIndex(This,fOldIndex) (This)->lpVtbl->SetOutputCompatibilityIndex(This,fOldIndex) -#define IConfigAviMux_GetOutputCompatibilityIndex(This,pfOldIndex) (This)->lpVtbl->GetOutputCompatibilityIndex(This,pfOldIndex) -#endif -#endif - HRESULT WINAPI IConfigAviMux_SetMasterStream_Proxy(IConfigAviMux *This,LONG iStream); - void __RPC_STUB IConfigAviMux_SetMasterStream_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IConfigAviMux_GetMasterStream_Proxy(IConfigAviMux *This,LONG *pStream); - void __RPC_STUB IConfigAviMux_GetMasterStream_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IConfigAviMux_SetOutputCompatibilityIndex_Proxy(IConfigAviMux *This,WINBOOL fOldIndex); - void __RPC_STUB IConfigAviMux_SetOutputCompatibilityIndex_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IConfigAviMux_GetOutputCompatibilityIndex_Proxy(IConfigAviMux *This,WINBOOL *pfOldIndex); - void __RPC_STUB IConfigAviMux_GetOutputCompatibilityIndex_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - typedef enum __MIDL___MIDL_itf_strmif_0167_0001 { - CompressionCaps_CanQuality = 0x1,CompressionCaps_CanCrunch = 0x2,CompressionCaps_CanKeyFrame = 0x4,CompressionCaps_CanBFrame = 0x8, - CompressionCaps_CanWindow = 0x10 - } CompressionCaps; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0167_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0167_v0_0_s_ifspec; -#ifndef __IAMVideoCompression_INTERFACE_DEFINED__ -#define __IAMVideoCompression_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IAMVideoCompression; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IAMVideoCompression : public IUnknown { - public: - virtual HRESULT WINAPI put_KeyFrameRate(long KeyFrameRate) = 0; - virtual HRESULT WINAPI get_KeyFrameRate(long *pKeyFrameRate) = 0; - virtual HRESULT WINAPI put_PFramesPerKeyFrame(long PFramesPerKeyFrame) = 0; - virtual HRESULT WINAPI get_PFramesPerKeyFrame(long *pPFramesPerKeyFrame) = 0; - virtual HRESULT WINAPI put_Quality(double Quality) = 0; - virtual HRESULT WINAPI get_Quality(double *pQuality) = 0; - virtual HRESULT WINAPI put_WindowSize(DWORDLONG WindowSize) = 0; - virtual HRESULT WINAPI get_WindowSize(DWORDLONG *pWindowSize) = 0; - virtual HRESULT WINAPI GetInfo(WCHAR *pszVersion,int *pcbVersion,LPWSTR pszDescription,int *pcbDescription,long *pDefaultKeyFrameRate,long *pDefaultPFramesPerKey,double *pDefaultQuality,long *pCapabilities) = 0; - virtual HRESULT WINAPI OverrideKeyFrame(long FrameNumber) = 0; - virtual HRESULT WINAPI OverrideFrameSize(long FrameNumber,long Size) = 0; - }; -#else - typedef struct IAMVideoCompressionVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IAMVideoCompression *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IAMVideoCompression *This); - ULONG (WINAPI *Release)(IAMVideoCompression *This); - HRESULT (WINAPI *put_KeyFrameRate)(IAMVideoCompression *This,long KeyFrameRate); - HRESULT (WINAPI *get_KeyFrameRate)(IAMVideoCompression *This,long *pKeyFrameRate); - HRESULT (WINAPI *put_PFramesPerKeyFrame)(IAMVideoCompression *This,long PFramesPerKeyFrame); - HRESULT (WINAPI *get_PFramesPerKeyFrame)(IAMVideoCompression *This,long *pPFramesPerKeyFrame); - HRESULT (WINAPI *put_Quality)(IAMVideoCompression *This,double Quality); - HRESULT (WINAPI *get_Quality)(IAMVideoCompression *This,double *pQuality); - HRESULT (WINAPI *put_WindowSize)(IAMVideoCompression *This,DWORDLONG WindowSize); - HRESULT (WINAPI *get_WindowSize)(IAMVideoCompression *This,DWORDLONG *pWindowSize); - HRESULT (WINAPI *GetInfo)(IAMVideoCompression *This,WCHAR *pszVersion,int *pcbVersion,LPWSTR pszDescription,int *pcbDescription,long *pDefaultKeyFrameRate,long *pDefaultPFramesPerKey,double *pDefaultQuality,long *pCapabilities); - HRESULT (WINAPI *OverrideKeyFrame)(IAMVideoCompression *This,long FrameNumber); - HRESULT (WINAPI *OverrideFrameSize)(IAMVideoCompression *This,long FrameNumber,long Size); - END_INTERFACE - } IAMVideoCompressionVtbl; - struct IAMVideoCompression { - CONST_VTBL struct IAMVideoCompressionVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IAMVideoCompression_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IAMVideoCompression_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IAMVideoCompression_Release(This) (This)->lpVtbl->Release(This) -#define IAMVideoCompression_put_KeyFrameRate(This,KeyFrameRate) (This)->lpVtbl->put_KeyFrameRate(This,KeyFrameRate) -#define IAMVideoCompression_get_KeyFrameRate(This,pKeyFrameRate) (This)->lpVtbl->get_KeyFrameRate(This,pKeyFrameRate) -#define IAMVideoCompression_put_PFramesPerKeyFrame(This,PFramesPerKeyFrame) (This)->lpVtbl->put_PFramesPerKeyFrame(This,PFramesPerKeyFrame) -#define IAMVideoCompression_get_PFramesPerKeyFrame(This,pPFramesPerKeyFrame) (This)->lpVtbl->get_PFramesPerKeyFrame(This,pPFramesPerKeyFrame) -#define IAMVideoCompression_put_Quality(This,Quality) (This)->lpVtbl->put_Quality(This,Quality) -#define IAMVideoCompression_get_Quality(This,pQuality) (This)->lpVtbl->get_Quality(This,pQuality) -#define IAMVideoCompression_put_WindowSize(This,WindowSize) (This)->lpVtbl->put_WindowSize(This,WindowSize) -#define IAMVideoCompression_get_WindowSize(This,pWindowSize) (This)->lpVtbl->get_WindowSize(This,pWindowSize) -#define IAMVideoCompression_GetInfo(This,pszVersion,pcbVersion,pszDescription,pcbDescription,pDefaultKeyFrameRate,pDefaultPFramesPerKey,pDefaultQuality,pCapabilities) (This)->lpVtbl->GetInfo(This,pszVersion,pcbVersion,pszDescription,pcbDescription,pDefaultKeyFrameRate,pDefaultPFramesPerKey,pDefaultQuality,pCapabilities) -#define IAMVideoCompression_OverrideKeyFrame(This,FrameNumber) (This)->lpVtbl->OverrideKeyFrame(This,FrameNumber) -#define IAMVideoCompression_OverrideFrameSize(This,FrameNumber,Size) (This)->lpVtbl->OverrideFrameSize(This,FrameNumber,Size) -#endif -#endif - HRESULT WINAPI IAMVideoCompression_put_KeyFrameRate_Proxy(IAMVideoCompression *This,long KeyFrameRate); - void __RPC_STUB IAMVideoCompression_put_KeyFrameRate_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMVideoCompression_get_KeyFrameRate_Proxy(IAMVideoCompression *This,long *pKeyFrameRate); - void __RPC_STUB IAMVideoCompression_get_KeyFrameRate_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMVideoCompression_put_PFramesPerKeyFrame_Proxy(IAMVideoCompression *This,long PFramesPerKeyFrame); - void __RPC_STUB IAMVideoCompression_put_PFramesPerKeyFrame_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMVideoCompression_get_PFramesPerKeyFrame_Proxy(IAMVideoCompression *This,long *pPFramesPerKeyFrame); - void __RPC_STUB IAMVideoCompression_get_PFramesPerKeyFrame_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMVideoCompression_put_Quality_Proxy(IAMVideoCompression *This,double Quality); - void __RPC_STUB IAMVideoCompression_put_Quality_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMVideoCompression_get_Quality_Proxy(IAMVideoCompression *This,double *pQuality); - void __RPC_STUB IAMVideoCompression_get_Quality_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMVideoCompression_put_WindowSize_Proxy(IAMVideoCompression *This,DWORDLONG WindowSize); - void __RPC_STUB IAMVideoCompression_put_WindowSize_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMVideoCompression_get_WindowSize_Proxy(IAMVideoCompression *This,DWORDLONG *pWindowSize); - void __RPC_STUB IAMVideoCompression_get_WindowSize_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMVideoCompression_GetInfo_Proxy(IAMVideoCompression *This,WCHAR *pszVersion,int *pcbVersion,LPWSTR pszDescription,int *pcbDescription,long *pDefaultKeyFrameRate,long *pDefaultPFramesPerKey,double *pDefaultQuality,long *pCapabilities); - void __RPC_STUB IAMVideoCompression_GetInfo_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMVideoCompression_OverrideKeyFrame_Proxy(IAMVideoCompression *This,long FrameNumber); - void __RPC_STUB IAMVideoCompression_OverrideKeyFrame_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMVideoCompression_OverrideFrameSize_Proxy(IAMVideoCompression *This,long FrameNumber,long Size); - void __RPC_STUB IAMVideoCompression_OverrideFrameSize_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - typedef enum __MIDL___MIDL_itf_strmif_0168_0001 { - VfwCaptureDialog_Source = 0x1,VfwCaptureDialog_Format = 0x2,VfwCaptureDialog_Display = 0x4 - } VfwCaptureDialogs; - - typedef enum __MIDL___MIDL_itf_strmif_0168_0002 { - VfwCompressDialog_Config = 0x1,VfwCompressDialog_About = 0x2,VfwCompressDialog_QueryConfig = 0x4,VfwCompressDialog_QueryAbout = 0x8 - } VfwCompressDialogs; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0168_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0168_v0_0_s_ifspec; -#ifndef __IAMVfwCaptureDialogs_INTERFACE_DEFINED__ -#define __IAMVfwCaptureDialogs_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IAMVfwCaptureDialogs; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IAMVfwCaptureDialogs : public IUnknown { - public: - virtual HRESULT WINAPI HasDialog(int iDialog) = 0; - virtual HRESULT WINAPI ShowDialog(int iDialog,HWND hwnd) = 0; - virtual HRESULT WINAPI SendDriverMessage(int iDialog,int uMsg,long dw1,long dw2) = 0; - }; -#else - typedef struct IAMVfwCaptureDialogsVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IAMVfwCaptureDialogs *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IAMVfwCaptureDialogs *This); - ULONG (WINAPI *Release)(IAMVfwCaptureDialogs *This); - HRESULT (WINAPI *HasDialog)(IAMVfwCaptureDialogs *This,int iDialog); - HRESULT (WINAPI *ShowDialog)(IAMVfwCaptureDialogs *This,int iDialog,HWND hwnd); - HRESULT (WINAPI *SendDriverMessage)(IAMVfwCaptureDialogs *This,int iDialog,int uMsg,long dw1,long dw2); - END_INTERFACE - } IAMVfwCaptureDialogsVtbl; - struct IAMVfwCaptureDialogs { - CONST_VTBL struct IAMVfwCaptureDialogsVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IAMVfwCaptureDialogs_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IAMVfwCaptureDialogs_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IAMVfwCaptureDialogs_Release(This) (This)->lpVtbl->Release(This) -#define IAMVfwCaptureDialogs_HasDialog(This,iDialog) (This)->lpVtbl->HasDialog(This,iDialog) -#define IAMVfwCaptureDialogs_ShowDialog(This,iDialog,hwnd) (This)->lpVtbl->ShowDialog(This,iDialog,hwnd) -#define IAMVfwCaptureDialogs_SendDriverMessage(This,iDialog,uMsg,dw1,dw2) (This)->lpVtbl->SendDriverMessage(This,iDialog,uMsg,dw1,dw2) -#endif -#endif - HRESULT WINAPI IAMVfwCaptureDialogs_HasDialog_Proxy(IAMVfwCaptureDialogs *This,int iDialog); - void __RPC_STUB IAMVfwCaptureDialogs_HasDialog_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMVfwCaptureDialogs_ShowDialog_Proxy(IAMVfwCaptureDialogs *This,int iDialog,HWND hwnd); - void __RPC_STUB IAMVfwCaptureDialogs_ShowDialog_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMVfwCaptureDialogs_SendDriverMessage_Proxy(IAMVfwCaptureDialogs *This,int iDialog,int uMsg,long dw1,long dw2); - void __RPC_STUB IAMVfwCaptureDialogs_SendDriverMessage_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IAMVfwCompressDialogs_INTERFACE_DEFINED__ -#define __IAMVfwCompressDialogs_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IAMVfwCompressDialogs; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IAMVfwCompressDialogs : public IUnknown { - public: - virtual HRESULT WINAPI ShowDialog(int iDialog,HWND hwnd) = 0; - virtual HRESULT WINAPI GetState(LPVOID pState,int *pcbState) = 0; - virtual HRESULT WINAPI SetState(LPVOID pState,int cbState) = 0; - virtual HRESULT WINAPI SendDriverMessage(int uMsg,long dw1,long dw2) = 0; - }; -#else - typedef struct IAMVfwCompressDialogsVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IAMVfwCompressDialogs *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IAMVfwCompressDialogs *This); - ULONG (WINAPI *Release)(IAMVfwCompressDialogs *This); - HRESULT (WINAPI *ShowDialog)(IAMVfwCompressDialogs *This,int iDialog,HWND hwnd); - HRESULT (WINAPI *GetState)(IAMVfwCompressDialogs *This,LPVOID pState,int *pcbState); - HRESULT (WINAPI *SetState)(IAMVfwCompressDialogs *This,LPVOID pState,int cbState); - HRESULT (WINAPI *SendDriverMessage)(IAMVfwCompressDialogs *This,int uMsg,long dw1,long dw2); - END_INTERFACE - } IAMVfwCompressDialogsVtbl; - struct IAMVfwCompressDialogs { - CONST_VTBL struct IAMVfwCompressDialogsVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IAMVfwCompressDialogs_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IAMVfwCompressDialogs_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IAMVfwCompressDialogs_Release(This) (This)->lpVtbl->Release(This) -#define IAMVfwCompressDialogs_ShowDialog(This,iDialog,hwnd) (This)->lpVtbl->ShowDialog(This,iDialog,hwnd) -#define IAMVfwCompressDialogs_GetState(This,pState,pcbState) (This)->lpVtbl->GetState(This,pState,pcbState) -#define IAMVfwCompressDialogs_SetState(This,pState,cbState) (This)->lpVtbl->SetState(This,pState,cbState) -#define IAMVfwCompressDialogs_SendDriverMessage(This,uMsg,dw1,dw2) (This)->lpVtbl->SendDriverMessage(This,uMsg,dw1,dw2) -#endif -#endif - HRESULT WINAPI IAMVfwCompressDialogs_ShowDialog_Proxy(IAMVfwCompressDialogs *This,int iDialog,HWND hwnd); - void __RPC_STUB IAMVfwCompressDialogs_ShowDialog_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMVfwCompressDialogs_GetState_Proxy(IAMVfwCompressDialogs *This,LPVOID pState,int *pcbState); - void __RPC_STUB IAMVfwCompressDialogs_GetState_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMVfwCompressDialogs_SetState_Proxy(IAMVfwCompressDialogs *This,LPVOID pState,int cbState); - void __RPC_STUB IAMVfwCompressDialogs_SetState_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMVfwCompressDialogs_SendDriverMessage_Proxy(IAMVfwCompressDialogs *This,int uMsg,long dw1,long dw2); - void __RPC_STUB IAMVfwCompressDialogs_SendDriverMessage_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IAMDroppedFrames_INTERFACE_DEFINED__ -#define __IAMDroppedFrames_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IAMDroppedFrames; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IAMDroppedFrames : public IUnknown { - public: - virtual HRESULT WINAPI GetNumDropped(long *plDropped) = 0; - virtual HRESULT WINAPI GetNumNotDropped(long *plNotDropped) = 0; - virtual HRESULT WINAPI GetDroppedInfo(long lSize,long *plArray,long *plNumCopied) = 0; - virtual HRESULT WINAPI GetAverageFrameSize(long *plAverageSize) = 0; - }; -#else - typedef struct IAMDroppedFramesVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IAMDroppedFrames *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IAMDroppedFrames *This); - ULONG (WINAPI *Release)(IAMDroppedFrames *This); - HRESULT (WINAPI *GetNumDropped)(IAMDroppedFrames *This,long *plDropped); - HRESULT (WINAPI *GetNumNotDropped)(IAMDroppedFrames *This,long *plNotDropped); - HRESULT (WINAPI *GetDroppedInfo)(IAMDroppedFrames *This,long lSize,long *plArray,long *plNumCopied); - HRESULT (WINAPI *GetAverageFrameSize)(IAMDroppedFrames *This,long *plAverageSize); - END_INTERFACE - } IAMDroppedFramesVtbl; - struct IAMDroppedFrames { - CONST_VTBL struct IAMDroppedFramesVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IAMDroppedFrames_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IAMDroppedFrames_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IAMDroppedFrames_Release(This) (This)->lpVtbl->Release(This) -#define IAMDroppedFrames_GetNumDropped(This,plDropped) (This)->lpVtbl->GetNumDropped(This,plDropped) -#define IAMDroppedFrames_GetNumNotDropped(This,plNotDropped) (This)->lpVtbl->GetNumNotDropped(This,plNotDropped) -#define IAMDroppedFrames_GetDroppedInfo(This,lSize,plArray,plNumCopied) (This)->lpVtbl->GetDroppedInfo(This,lSize,plArray,plNumCopied) -#define IAMDroppedFrames_GetAverageFrameSize(This,plAverageSize) (This)->lpVtbl->GetAverageFrameSize(This,plAverageSize) -#endif -#endif - HRESULT WINAPI IAMDroppedFrames_GetNumDropped_Proxy(IAMDroppedFrames *This,long *plDropped); - void __RPC_STUB IAMDroppedFrames_GetNumDropped_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMDroppedFrames_GetNumNotDropped_Proxy(IAMDroppedFrames *This,long *plNotDropped); - void __RPC_STUB IAMDroppedFrames_GetNumNotDropped_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMDroppedFrames_GetDroppedInfo_Proxy(IAMDroppedFrames *This,long lSize,long *plArray,long *plNumCopied); - void __RPC_STUB IAMDroppedFrames_GetDroppedInfo_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMDroppedFrames_GetAverageFrameSize_Proxy(IAMDroppedFrames *This,long *plAverageSize); - void __RPC_STUB IAMDroppedFrames_GetAverageFrameSize_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#define AMF_AUTOMATICGAIN -1.0 - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0171_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0171_v0_0_s_ifspec; -#ifndef __IAMAudioInputMixer_INTERFACE_DEFINED__ -#define __IAMAudioInputMixer_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IAMAudioInputMixer; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IAMAudioInputMixer : public IUnknown { - public: - virtual HRESULT WINAPI put_Enable(WINBOOL fEnable) = 0; - virtual HRESULT WINAPI get_Enable(WINBOOL *pfEnable) = 0; - virtual HRESULT WINAPI put_Mono(WINBOOL fMono) = 0; - virtual HRESULT WINAPI get_Mono(WINBOOL *pfMono) = 0; - virtual HRESULT WINAPI put_MixLevel(double Level) = 0; - virtual HRESULT WINAPI get_MixLevel(double *pLevel) = 0; - virtual HRESULT WINAPI put_Pan(double Pan) = 0; - virtual HRESULT WINAPI get_Pan(double *pPan) = 0; - virtual HRESULT WINAPI put_Loudness(WINBOOL fLoudness) = 0; - virtual HRESULT WINAPI get_Loudness(WINBOOL *pfLoudness) = 0; - virtual HRESULT WINAPI put_Treble(double Treble) = 0; - virtual HRESULT WINAPI get_Treble(double *pTreble) = 0; - virtual HRESULT WINAPI get_TrebleRange(double *pRange) = 0; - virtual HRESULT WINAPI put_Bass(double Bass) = 0; - virtual HRESULT WINAPI get_Bass(double *pBass) = 0; - virtual HRESULT WINAPI get_BassRange(double *pRange) = 0; - }; -#else - typedef struct IAMAudioInputMixerVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IAMAudioInputMixer *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IAMAudioInputMixer *This); - ULONG (WINAPI *Release)(IAMAudioInputMixer *This); - HRESULT (WINAPI *put_Enable)(IAMAudioInputMixer *This,WINBOOL fEnable); - HRESULT (WINAPI *get_Enable)(IAMAudioInputMixer *This,WINBOOL *pfEnable); - HRESULT (WINAPI *put_Mono)(IAMAudioInputMixer *This,WINBOOL fMono); - HRESULT (WINAPI *get_Mono)(IAMAudioInputMixer *This,WINBOOL *pfMono); - HRESULT (WINAPI *put_MixLevel)(IAMAudioInputMixer *This,double Level); - HRESULT (WINAPI *get_MixLevel)(IAMAudioInputMixer *This,double *pLevel); - HRESULT (WINAPI *put_Pan)(IAMAudioInputMixer *This,double Pan); - HRESULT (WINAPI *get_Pan)(IAMAudioInputMixer *This,double *pPan); - HRESULT (WINAPI *put_Loudness)(IAMAudioInputMixer *This,WINBOOL fLoudness); - HRESULT (WINAPI *get_Loudness)(IAMAudioInputMixer *This,WINBOOL *pfLoudness); - HRESULT (WINAPI *put_Treble)(IAMAudioInputMixer *This,double Treble); - HRESULT (WINAPI *get_Treble)(IAMAudioInputMixer *This,double *pTreble); - HRESULT (WINAPI *get_TrebleRange)(IAMAudioInputMixer *This,double *pRange); - HRESULT (WINAPI *put_Bass)(IAMAudioInputMixer *This,double Bass); - HRESULT (WINAPI *get_Bass)(IAMAudioInputMixer *This,double *pBass); - HRESULT (WINAPI *get_BassRange)(IAMAudioInputMixer *This,double *pRange); - END_INTERFACE - } IAMAudioInputMixerVtbl; - struct IAMAudioInputMixer { - CONST_VTBL struct IAMAudioInputMixerVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IAMAudioInputMixer_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IAMAudioInputMixer_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IAMAudioInputMixer_Release(This) (This)->lpVtbl->Release(This) -#define IAMAudioInputMixer_put_Enable(This,fEnable) (This)->lpVtbl->put_Enable(This,fEnable) -#define IAMAudioInputMixer_get_Enable(This,pfEnable) (This)->lpVtbl->get_Enable(This,pfEnable) -#define IAMAudioInputMixer_put_Mono(This,fMono) (This)->lpVtbl->put_Mono(This,fMono) -#define IAMAudioInputMixer_get_Mono(This,pfMono) (This)->lpVtbl->get_Mono(This,pfMono) -#define IAMAudioInputMixer_put_MixLevel(This,Level) (This)->lpVtbl->put_MixLevel(This,Level) -#define IAMAudioInputMixer_get_MixLevel(This,pLevel) (This)->lpVtbl->get_MixLevel(This,pLevel) -#define IAMAudioInputMixer_put_Pan(This,Pan) (This)->lpVtbl->put_Pan(This,Pan) -#define IAMAudioInputMixer_get_Pan(This,pPan) (This)->lpVtbl->get_Pan(This,pPan) -#define IAMAudioInputMixer_put_Loudness(This,fLoudness) (This)->lpVtbl->put_Loudness(This,fLoudness) -#define IAMAudioInputMixer_get_Loudness(This,pfLoudness) (This)->lpVtbl->get_Loudness(This,pfLoudness) -#define IAMAudioInputMixer_put_Treble(This,Treble) (This)->lpVtbl->put_Treble(This,Treble) -#define IAMAudioInputMixer_get_Treble(This,pTreble) (This)->lpVtbl->get_Treble(This,pTreble) -#define IAMAudioInputMixer_get_TrebleRange(This,pRange) (This)->lpVtbl->get_TrebleRange(This,pRange) -#define IAMAudioInputMixer_put_Bass(This,Bass) (This)->lpVtbl->put_Bass(This,Bass) -#define IAMAudioInputMixer_get_Bass(This,pBass) (This)->lpVtbl->get_Bass(This,pBass) -#define IAMAudioInputMixer_get_BassRange(This,pRange) (This)->lpVtbl->get_BassRange(This,pRange) -#endif -#endif - HRESULT WINAPI IAMAudioInputMixer_put_Enable_Proxy(IAMAudioInputMixer *This,WINBOOL fEnable); - void __RPC_STUB IAMAudioInputMixer_put_Enable_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMAudioInputMixer_get_Enable_Proxy(IAMAudioInputMixer *This,WINBOOL *pfEnable); - void __RPC_STUB IAMAudioInputMixer_get_Enable_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMAudioInputMixer_put_Mono_Proxy(IAMAudioInputMixer *This,WINBOOL fMono); - void __RPC_STUB IAMAudioInputMixer_put_Mono_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMAudioInputMixer_get_Mono_Proxy(IAMAudioInputMixer *This,WINBOOL *pfMono); - void __RPC_STUB IAMAudioInputMixer_get_Mono_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMAudioInputMixer_put_MixLevel_Proxy(IAMAudioInputMixer *This,double Level); - void __RPC_STUB IAMAudioInputMixer_put_MixLevel_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMAudioInputMixer_get_MixLevel_Proxy(IAMAudioInputMixer *This,double *pLevel); - void __RPC_STUB IAMAudioInputMixer_get_MixLevel_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMAudioInputMixer_put_Pan_Proxy(IAMAudioInputMixer *This,double Pan); - void __RPC_STUB IAMAudioInputMixer_put_Pan_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMAudioInputMixer_get_Pan_Proxy(IAMAudioInputMixer *This,double *pPan); - void __RPC_STUB IAMAudioInputMixer_get_Pan_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMAudioInputMixer_put_Loudness_Proxy(IAMAudioInputMixer *This,WINBOOL fLoudness); - void __RPC_STUB IAMAudioInputMixer_put_Loudness_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMAudioInputMixer_get_Loudness_Proxy(IAMAudioInputMixer *This,WINBOOL *pfLoudness); - void __RPC_STUB IAMAudioInputMixer_get_Loudness_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMAudioInputMixer_put_Treble_Proxy(IAMAudioInputMixer *This,double Treble); - void __RPC_STUB IAMAudioInputMixer_put_Treble_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMAudioInputMixer_get_Treble_Proxy(IAMAudioInputMixer *This,double *pTreble); - void __RPC_STUB IAMAudioInputMixer_get_Treble_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMAudioInputMixer_get_TrebleRange_Proxy(IAMAudioInputMixer *This,double *pRange); - void __RPC_STUB IAMAudioInputMixer_get_TrebleRange_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMAudioInputMixer_put_Bass_Proxy(IAMAudioInputMixer *This,double Bass); - void __RPC_STUB IAMAudioInputMixer_put_Bass_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMAudioInputMixer_get_Bass_Proxy(IAMAudioInputMixer *This,double *pBass); - void __RPC_STUB IAMAudioInputMixer_get_Bass_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMAudioInputMixer_get_BassRange_Proxy(IAMAudioInputMixer *This,double *pRange); - void __RPC_STUB IAMAudioInputMixer_get_BassRange_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IAMBufferNegotiation_INTERFACE_DEFINED__ -#define __IAMBufferNegotiation_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IAMBufferNegotiation; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IAMBufferNegotiation : public IUnknown { - public: - virtual HRESULT WINAPI SuggestAllocatorProperties(const ALLOCATOR_PROPERTIES *pprop) = 0; - virtual HRESULT WINAPI GetAllocatorProperties(ALLOCATOR_PROPERTIES *pprop) = 0; - }; -#else - typedef struct IAMBufferNegotiationVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IAMBufferNegotiation *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IAMBufferNegotiation *This); - ULONG (WINAPI *Release)(IAMBufferNegotiation *This); - HRESULT (WINAPI *SuggestAllocatorProperties)(IAMBufferNegotiation *This,const ALLOCATOR_PROPERTIES *pprop); - HRESULT (WINAPI *GetAllocatorProperties)(IAMBufferNegotiation *This,ALLOCATOR_PROPERTIES *pprop); - END_INTERFACE - } IAMBufferNegotiationVtbl; - struct IAMBufferNegotiation { - CONST_VTBL struct IAMBufferNegotiationVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IAMBufferNegotiation_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IAMBufferNegotiation_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IAMBufferNegotiation_Release(This) (This)->lpVtbl->Release(This) -#define IAMBufferNegotiation_SuggestAllocatorProperties(This,pprop) (This)->lpVtbl->SuggestAllocatorProperties(This,pprop) -#define IAMBufferNegotiation_GetAllocatorProperties(This,pprop) (This)->lpVtbl->GetAllocatorProperties(This,pprop) -#endif -#endif - HRESULT WINAPI IAMBufferNegotiation_SuggestAllocatorProperties_Proxy(IAMBufferNegotiation *This,const ALLOCATOR_PROPERTIES *pprop); - void __RPC_STUB IAMBufferNegotiation_SuggestAllocatorProperties_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMBufferNegotiation_GetAllocatorProperties_Proxy(IAMBufferNegotiation *This,ALLOCATOR_PROPERTIES *pprop); - void __RPC_STUB IAMBufferNegotiation_GetAllocatorProperties_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - typedef enum tagAnalogVideoStandard { - AnalogVideo_None = 0,AnalogVideo_NTSC_M = 0x1,AnalogVideo_NTSC_M_J = 0x2,AnalogVideo_NTSC_433 = 0x4,AnalogVideo_PAL_B = 0x10, - AnalogVideo_PAL_D = 0x20,AnalogVideo_PAL_G = 0x40,AnalogVideo_PAL_H = 0x80,AnalogVideo_PAL_I = 0x100,AnalogVideo_PAL_M = 0x200, - AnalogVideo_PAL_N = 0x400,AnalogVideo_PAL_60 = 0x800,AnalogVideo_SECAM_B = 0x1000,AnalogVideo_SECAM_D = 0x2000,AnalogVideo_SECAM_G = 0x4000, - AnalogVideo_SECAM_H = 0x8000,AnalogVideo_SECAM_K = 0x10000,AnalogVideo_SECAM_K1 = 0x20000,AnalogVideo_SECAM_L = 0x40000,AnalogVideo_SECAM_L1 = 0x80000, - AnalogVideo_PAL_N_COMBO = 0x100000,AnalogVideoMask_MCE_NTSC = AnalogVideo_NTSC_M | AnalogVideo_NTSC_M_J | AnalogVideo_NTSC_433 | AnalogVideo_PAL_M | AnalogVideo_PAL_N | AnalogVideo_PAL_60 | AnalogVideo_PAL_N_COMBO,AnalogVideoMask_MCE_PAL = AnalogVideo_PAL_B | AnalogVideo_PAL_D | AnalogVideo_PAL_G | AnalogVideo_PAL_H | AnalogVideo_PAL_I,AnalogVideoMask_MCE_SECAM = AnalogVideo_SECAM_B | AnalogVideo_SECAM_D | AnalogVideo_SECAM_G | AnalogVideo_SECAM_H | AnalogVideo_SECAM_K | AnalogVideo_SECAM_K1 | AnalogVideo_SECAM_L | AnalogVideo_SECAM_L1 - } AnalogVideoStandard; - - typedef enum tagTunerInputType { - TunerInputCable = 0,TunerInputAntenna = TunerInputCable + 1 - } TunerInputType; - -#define AnalogVideo_NTSC_Mask 0x00000007 -#define AnalogVideo_PAL_Mask 0x00100FF0 -#define AnalogVideo_SECAM_Mask 0x000FF000 - - typedef enum __MIDL___MIDL_itf_strmif_0173_0001 { - VideoCopyProtectionMacrovisionBasic = 0,VideoCopyProtectionMacrovisionCBI = VideoCopyProtectionMacrovisionBasic + 1 - } VideoCopyProtectionType; - - typedef enum tagPhysicalConnectorType { - PhysConn_Video_Tuner = 1, - PhysConn_Video_Composite,PhysConn_Video_SVideo,PhysConn_Video_RGB, - PhysConn_Video_YRYBY,PhysConn_Video_SerialDigital,PhysConn_Video_ParallelDigital, - PhysConn_Video_SCSI,PhysConn_Video_AUX,PhysConn_Video_1394,PhysConn_Video_USB, - PhysConn_Video_VideoDecoder,PhysConn_Video_VideoEncoder,PhysConn_Video_SCART,PhysConn_Video_Black, - PhysConn_Audio_Tuner = 0x1000,PhysConn_Audio_Line = 0x1001,PhysConn_Audio_Mic = 0x1002, - PhysConn_Audio_AESDigital = 0x1003,PhysConn_Audio_SPDIFDigital = 0x1004, - PhysConn_Audio_SCSI = 0x1005,PhysConn_Audio_AUX = 0x1006,PhysConn_Audio_1394 = 0x1007, - PhysConn_Audio_USB = 0x1008,PhysConn_Audio_AudioDecoder = 0x1009 - } PhysicalConnectorType; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0173_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0173_v0_0_s_ifspec; -#ifndef __IAMAnalogVideoDecoder_INTERFACE_DEFINED__ -#define __IAMAnalogVideoDecoder_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IAMAnalogVideoDecoder; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IAMAnalogVideoDecoder : public IUnknown { - public: - virtual HRESULT WINAPI get_AvailableTVFormats(long *lAnalogVideoStandard) = 0; - virtual HRESULT WINAPI put_TVFormat(long lAnalogVideoStandard) = 0; - virtual HRESULT WINAPI get_TVFormat(long *plAnalogVideoStandard) = 0; - virtual HRESULT WINAPI get_HorizontalLocked(long *plLocked) = 0; - virtual HRESULT WINAPI put_VCRHorizontalLocking(long lVCRHorizontalLocking) = 0; - virtual HRESULT WINAPI get_VCRHorizontalLocking(long *plVCRHorizontalLocking) = 0; - virtual HRESULT WINAPI get_NumberOfLines(long *plNumberOfLines) = 0; - virtual HRESULT WINAPI put_OutputEnable(long lOutputEnable) = 0; - virtual HRESULT WINAPI get_OutputEnable(long *plOutputEnable) = 0; - }; -#else - typedef struct IAMAnalogVideoDecoderVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IAMAnalogVideoDecoder *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IAMAnalogVideoDecoder *This); - ULONG (WINAPI *Release)(IAMAnalogVideoDecoder *This); - HRESULT (WINAPI *get_AvailableTVFormats)(IAMAnalogVideoDecoder *This,long *lAnalogVideoStandard); - HRESULT (WINAPI *put_TVFormat)(IAMAnalogVideoDecoder *This,long lAnalogVideoStandard); - HRESULT (WINAPI *get_TVFormat)(IAMAnalogVideoDecoder *This,long *plAnalogVideoStandard); - HRESULT (WINAPI *get_HorizontalLocked)(IAMAnalogVideoDecoder *This,long *plLocked); - HRESULT (WINAPI *put_VCRHorizontalLocking)(IAMAnalogVideoDecoder *This,long lVCRHorizontalLocking); - HRESULT (WINAPI *get_VCRHorizontalLocking)(IAMAnalogVideoDecoder *This,long *plVCRHorizontalLocking); - HRESULT (WINAPI *get_NumberOfLines)(IAMAnalogVideoDecoder *This,long *plNumberOfLines); - HRESULT (WINAPI *put_OutputEnable)(IAMAnalogVideoDecoder *This,long lOutputEnable); - HRESULT (WINAPI *get_OutputEnable)(IAMAnalogVideoDecoder *This,long *plOutputEnable); - END_INTERFACE - } IAMAnalogVideoDecoderVtbl; - struct IAMAnalogVideoDecoder { - CONST_VTBL struct IAMAnalogVideoDecoderVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IAMAnalogVideoDecoder_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IAMAnalogVideoDecoder_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IAMAnalogVideoDecoder_Release(This) (This)->lpVtbl->Release(This) -#define IAMAnalogVideoDecoder_get_AvailableTVFormats(This,lAnalogVideoStandard) (This)->lpVtbl->get_AvailableTVFormats(This,lAnalogVideoStandard) -#define IAMAnalogVideoDecoder_put_TVFormat(This,lAnalogVideoStandard) (This)->lpVtbl->put_TVFormat(This,lAnalogVideoStandard) -#define IAMAnalogVideoDecoder_get_TVFormat(This,plAnalogVideoStandard) (This)->lpVtbl->get_TVFormat(This,plAnalogVideoStandard) -#define IAMAnalogVideoDecoder_get_HorizontalLocked(This,plLocked) (This)->lpVtbl->get_HorizontalLocked(This,plLocked) -#define IAMAnalogVideoDecoder_put_VCRHorizontalLocking(This,lVCRHorizontalLocking) (This)->lpVtbl->put_VCRHorizontalLocking(This,lVCRHorizontalLocking) -#define IAMAnalogVideoDecoder_get_VCRHorizontalLocking(This,plVCRHorizontalLocking) (This)->lpVtbl->get_VCRHorizontalLocking(This,plVCRHorizontalLocking) -#define IAMAnalogVideoDecoder_get_NumberOfLines(This,plNumberOfLines) (This)->lpVtbl->get_NumberOfLines(This,plNumberOfLines) -#define IAMAnalogVideoDecoder_put_OutputEnable(This,lOutputEnable) (This)->lpVtbl->put_OutputEnable(This,lOutputEnable) -#define IAMAnalogVideoDecoder_get_OutputEnable(This,plOutputEnable) (This)->lpVtbl->get_OutputEnable(This,plOutputEnable) -#endif -#endif - HRESULT WINAPI IAMAnalogVideoDecoder_get_AvailableTVFormats_Proxy(IAMAnalogVideoDecoder *This,long *lAnalogVideoStandard); - void __RPC_STUB IAMAnalogVideoDecoder_get_AvailableTVFormats_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMAnalogVideoDecoder_put_TVFormat_Proxy(IAMAnalogVideoDecoder *This,long lAnalogVideoStandard); - void __RPC_STUB IAMAnalogVideoDecoder_put_TVFormat_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMAnalogVideoDecoder_get_TVFormat_Proxy(IAMAnalogVideoDecoder *This,long *plAnalogVideoStandard); - void __RPC_STUB IAMAnalogVideoDecoder_get_TVFormat_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMAnalogVideoDecoder_get_HorizontalLocked_Proxy(IAMAnalogVideoDecoder *This,long *plLocked); - void __RPC_STUB IAMAnalogVideoDecoder_get_HorizontalLocked_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMAnalogVideoDecoder_put_VCRHorizontalLocking_Proxy(IAMAnalogVideoDecoder *This,long lVCRHorizontalLocking); - void __RPC_STUB IAMAnalogVideoDecoder_put_VCRHorizontalLocking_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMAnalogVideoDecoder_get_VCRHorizontalLocking_Proxy(IAMAnalogVideoDecoder *This,long *plVCRHorizontalLocking); - void __RPC_STUB IAMAnalogVideoDecoder_get_VCRHorizontalLocking_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMAnalogVideoDecoder_get_NumberOfLines_Proxy(IAMAnalogVideoDecoder *This,long *plNumberOfLines); - void __RPC_STUB IAMAnalogVideoDecoder_get_NumberOfLines_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMAnalogVideoDecoder_put_OutputEnable_Proxy(IAMAnalogVideoDecoder *This,long lOutputEnable); - void __RPC_STUB IAMAnalogVideoDecoder_put_OutputEnable_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMAnalogVideoDecoder_get_OutputEnable_Proxy(IAMAnalogVideoDecoder *This,long *plOutputEnable); - void __RPC_STUB IAMAnalogVideoDecoder_get_OutputEnable_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - typedef enum tagVideoProcAmpProperty { - VideoProcAmp_Brightness = 0, - VideoProcAmp_Contrast,VideoProcAmp_Hue,VideoProcAmp_Saturation,VideoProcAmp_Sharpness, - VideoProcAmp_Gamma,VideoProcAmp_ColorEnable,VideoProcAmp_WhiteBalance, - VideoProcAmp_BacklightCompensation,VideoProcAmp_Gain - } VideoProcAmpProperty; - - typedef enum tagVideoProcAmpFlags { - VideoProcAmp_Flags_Auto = 0x1,VideoProcAmp_Flags_Manual = 0x2 - } VideoProcAmpFlags; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0174_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0174_v0_0_s_ifspec; -#ifndef __IAMVideoProcAmp_INTERFACE_DEFINED__ -#define __IAMVideoProcAmp_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IAMVideoProcAmp; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IAMVideoProcAmp : public IUnknown { - public: - virtual HRESULT WINAPI GetRange(long Property,long *pMin,long *pMax,long *pSteppingDelta,long *pDefault,long *pCapsFlags) = 0; - virtual HRESULT WINAPI Set(long Property,long lValue,long Flags) = 0; - virtual HRESULT WINAPI Get(long Property,long *lValue,long *Flags) = 0; - }; -#else - typedef struct IAMVideoProcAmpVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IAMVideoProcAmp *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IAMVideoProcAmp *This); - ULONG (WINAPI *Release)(IAMVideoProcAmp *This); - HRESULT (WINAPI *GetRange)(IAMVideoProcAmp *This,long Property,long *pMin,long *pMax,long *pSteppingDelta,long *pDefault,long *pCapsFlags); - HRESULT (WINAPI *Set)(IAMVideoProcAmp *This,long Property,long lValue,long Flags); - HRESULT (WINAPI *Get)(IAMVideoProcAmp *This,long Property,long *lValue,long *Flags); - END_INTERFACE - } IAMVideoProcAmpVtbl; - struct IAMVideoProcAmp { - CONST_VTBL struct IAMVideoProcAmpVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IAMVideoProcAmp_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IAMVideoProcAmp_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IAMVideoProcAmp_Release(This) (This)->lpVtbl->Release(This) -#define IAMVideoProcAmp_GetRange(This,Property,pMin,pMax,pSteppingDelta,pDefault,pCapsFlags) (This)->lpVtbl->GetRange(This,Property,pMin,pMax,pSteppingDelta,pDefault,pCapsFlags) -#define IAMVideoProcAmp_Set(This,Property,lValue,Flags) (This)->lpVtbl->Set(This,Property,lValue,Flags) -#define IAMVideoProcAmp_Get(This,Property,lValue,Flags) (This)->lpVtbl->Get(This,Property,lValue,Flags) -#endif -#endif - HRESULT WINAPI IAMVideoProcAmp_GetRange_Proxy(IAMVideoProcAmp *This,long Property,long *pMin,long *pMax,long *pSteppingDelta,long *pDefault,long *pCapsFlags); - void __RPC_STUB IAMVideoProcAmp_GetRange_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMVideoProcAmp_Set_Proxy(IAMVideoProcAmp *This,long Property,long lValue,long Flags); - void __RPC_STUB IAMVideoProcAmp_Set_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMVideoProcAmp_Get_Proxy(IAMVideoProcAmp *This,long Property,long *lValue,long *Flags); - void __RPC_STUB IAMVideoProcAmp_Get_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - typedef enum tagCameraControlProperty { - CameraControl_Pan = 0, - CameraControl_Tilt,CameraControl_Roll,CameraControl_Zoom,CameraControl_Exposure, - CameraControl_Iris,CameraControl_Focus - } CameraControlProperty; - - typedef enum tagCameraControlFlags { - CameraControl_Flags_Auto = 0x1,CameraControl_Flags_Manual = 0x2 - } CameraControlFlags; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0175_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0175_v0_0_s_ifspec; -#ifndef __IAMCameraControl_INTERFACE_DEFINED__ -#define __IAMCameraControl_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IAMCameraControl; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IAMCameraControl : public IUnknown { - public: - virtual HRESULT WINAPI GetRange(long Property,long *pMin,long *pMax,long *pSteppingDelta,long *pDefault,long *pCapsFlags) = 0; - virtual HRESULT WINAPI Set(long Property,long lValue,long Flags) = 0; - virtual HRESULT WINAPI Get(long Property,long *lValue,long *Flags) = 0; - }; -#else - typedef struct IAMCameraControlVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IAMCameraControl *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IAMCameraControl *This); - ULONG (WINAPI *Release)(IAMCameraControl *This); - HRESULT (WINAPI *GetRange)(IAMCameraControl *This,long Property,long *pMin,long *pMax,long *pSteppingDelta,long *pDefault,long *pCapsFlags); - HRESULT (WINAPI *Set)(IAMCameraControl *This,long Property,long lValue,long Flags); - HRESULT (WINAPI *Get)(IAMCameraControl *This,long Property,long *lValue,long *Flags); - END_INTERFACE - } IAMCameraControlVtbl; - struct IAMCameraControl { - CONST_VTBL struct IAMCameraControlVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IAMCameraControl_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IAMCameraControl_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IAMCameraControl_Release(This) (This)->lpVtbl->Release(This) -#define IAMCameraControl_GetRange(This,Property,pMin,pMax,pSteppingDelta,pDefault,pCapsFlags) (This)->lpVtbl->GetRange(This,Property,pMin,pMax,pSteppingDelta,pDefault,pCapsFlags) -#define IAMCameraControl_Set(This,Property,lValue,Flags) (This)->lpVtbl->Set(This,Property,lValue,Flags) -#define IAMCameraControl_Get(This,Property,lValue,Flags) (This)->lpVtbl->Get(This,Property,lValue,Flags) -#endif -#endif - HRESULT WINAPI IAMCameraControl_GetRange_Proxy(IAMCameraControl *This,long Property,long *pMin,long *pMax,long *pSteppingDelta,long *pDefault,long *pCapsFlags); - void __RPC_STUB IAMCameraControl_GetRange_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMCameraControl_Set_Proxy(IAMCameraControl *This,long Property,long lValue,long Flags); - void __RPC_STUB IAMCameraControl_Set_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMCameraControl_Get_Proxy(IAMCameraControl *This,long Property,long *lValue,long *Flags); - void __RPC_STUB IAMCameraControl_Get_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - typedef enum tagVideoControlFlags { - VideoControlFlag_FlipHorizontal = 0x1,VideoControlFlag_FlipVertical = 0x2,VideoControlFlag_ExternalTriggerEnable = 0x4,VideoControlFlag_Trigger = 0x8 - } VideoControlFlags; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0176_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0176_v0_0_s_ifspec; -#ifndef __IAMVideoControl_INTERFACE_DEFINED__ -#define __IAMVideoControl_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IAMVideoControl; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IAMVideoControl : public IUnknown { - public: - virtual HRESULT WINAPI GetCaps(IPin *pPin,long *pCapsFlags) = 0; - virtual HRESULT WINAPI SetMode(IPin *pPin,long Mode) = 0; - virtual HRESULT WINAPI GetMode(IPin *pPin,long *Mode) = 0; - virtual HRESULT WINAPI GetCurrentActualFrameRate(IPin *pPin,LONGLONG *ActualFrameRate) = 0; - virtual HRESULT WINAPI GetMaxAvailableFrameRate(IPin *pPin,long iIndex,SIZE Dimensions,LONGLONG *MaxAvailableFrameRate) = 0; - virtual HRESULT WINAPI GetFrameRateList(IPin *pPin,long iIndex,SIZE Dimensions,long *ListSize,LONGLONG **FrameRates) = 0; - }; -#else - typedef struct IAMVideoControlVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IAMVideoControl *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IAMVideoControl *This); - ULONG (WINAPI *Release)(IAMVideoControl *This); - HRESULT (WINAPI *GetCaps)(IAMVideoControl *This,IPin *pPin,long *pCapsFlags); - HRESULT (WINAPI *SetMode)(IAMVideoControl *This,IPin *pPin,long Mode); - HRESULT (WINAPI *GetMode)(IAMVideoControl *This,IPin *pPin,long *Mode); - HRESULT (WINAPI *GetCurrentActualFrameRate)(IAMVideoControl *This,IPin *pPin,LONGLONG *ActualFrameRate); - HRESULT (WINAPI *GetMaxAvailableFrameRate)(IAMVideoControl *This,IPin *pPin,long iIndex,SIZE Dimensions,LONGLONG *MaxAvailableFrameRate); - HRESULT (WINAPI *GetFrameRateList)(IAMVideoControl *This,IPin *pPin,long iIndex,SIZE Dimensions,long *ListSize,LONGLONG **FrameRates); - END_INTERFACE - } IAMVideoControlVtbl; - struct IAMVideoControl { - CONST_VTBL struct IAMVideoControlVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IAMVideoControl_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IAMVideoControl_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IAMVideoControl_Release(This) (This)->lpVtbl->Release(This) -#define IAMVideoControl_GetCaps(This,pPin,pCapsFlags) (This)->lpVtbl->GetCaps(This,pPin,pCapsFlags) -#define IAMVideoControl_SetMode(This,pPin,Mode) (This)->lpVtbl->SetMode(This,pPin,Mode) -#define IAMVideoControl_GetMode(This,pPin,Mode) (This)->lpVtbl->GetMode(This,pPin,Mode) -#define IAMVideoControl_GetCurrentActualFrameRate(This,pPin,ActualFrameRate) (This)->lpVtbl->GetCurrentActualFrameRate(This,pPin,ActualFrameRate) -#define IAMVideoControl_GetMaxAvailableFrameRate(This,pPin,iIndex,Dimensions,MaxAvailableFrameRate) (This)->lpVtbl->GetMaxAvailableFrameRate(This,pPin,iIndex,Dimensions,MaxAvailableFrameRate) -#define IAMVideoControl_GetFrameRateList(This,pPin,iIndex,Dimensions,ListSize,FrameRates) (This)->lpVtbl->GetFrameRateList(This,pPin,iIndex,Dimensions,ListSize,FrameRates) -#endif -#endif - HRESULT WINAPI IAMVideoControl_GetCaps_Proxy(IAMVideoControl *This,IPin *pPin,long *pCapsFlags); - void __RPC_STUB IAMVideoControl_GetCaps_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMVideoControl_SetMode_Proxy(IAMVideoControl *This,IPin *pPin,long Mode); - void __RPC_STUB IAMVideoControl_SetMode_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMVideoControl_GetMode_Proxy(IAMVideoControl *This,IPin *pPin,long *Mode); - void __RPC_STUB IAMVideoControl_GetMode_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMVideoControl_GetCurrentActualFrameRate_Proxy(IAMVideoControl *This,IPin *pPin,LONGLONG *ActualFrameRate); - void __RPC_STUB IAMVideoControl_GetCurrentActualFrameRate_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMVideoControl_GetMaxAvailableFrameRate_Proxy(IAMVideoControl *This,IPin *pPin,long iIndex,SIZE Dimensions,LONGLONG *MaxAvailableFrameRate); - void __RPC_STUB IAMVideoControl_GetMaxAvailableFrameRate_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMVideoControl_GetFrameRateList_Proxy(IAMVideoControl *This,IPin *pPin,long iIndex,SIZE Dimensions,long *ListSize,LONGLONG **FrameRates); - void __RPC_STUB IAMVideoControl_GetFrameRateList_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IAMCrossbar_INTERFACE_DEFINED__ -#define __IAMCrossbar_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IAMCrossbar; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IAMCrossbar : public IUnknown { - public: - virtual HRESULT WINAPI get_PinCounts(long *OutputPinCount,long *InputPinCount) = 0; - virtual HRESULT WINAPI CanRoute(long OutputPinIndex,long InputPinIndex) = 0; - virtual HRESULT WINAPI Route(long OutputPinIndex,long InputPinIndex) = 0; - virtual HRESULT WINAPI get_IsRoutedTo(long OutputPinIndex,long *InputPinIndex) = 0; - virtual HRESULT WINAPI get_CrossbarPinInfo(WINBOOL IsInputPin,long PinIndex,long *PinIndexRelated,long *PhysicalType) = 0; - }; -#else - typedef struct IAMCrossbarVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IAMCrossbar *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IAMCrossbar *This); - ULONG (WINAPI *Release)(IAMCrossbar *This); - HRESULT (WINAPI *get_PinCounts)(IAMCrossbar *This,long *OutputPinCount,long *InputPinCount); - HRESULT (WINAPI *CanRoute)(IAMCrossbar *This,long OutputPinIndex,long InputPinIndex); - HRESULT (WINAPI *Route)(IAMCrossbar *This,long OutputPinIndex,long InputPinIndex); - HRESULT (WINAPI *get_IsRoutedTo)(IAMCrossbar *This,long OutputPinIndex,long *InputPinIndex); - HRESULT (WINAPI *get_CrossbarPinInfo)(IAMCrossbar *This,WINBOOL IsInputPin,long PinIndex,long *PinIndexRelated,long *PhysicalType); - END_INTERFACE - } IAMCrossbarVtbl; - struct IAMCrossbar { - CONST_VTBL struct IAMCrossbarVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IAMCrossbar_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IAMCrossbar_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IAMCrossbar_Release(This) (This)->lpVtbl->Release(This) -#define IAMCrossbar_get_PinCounts(This,OutputPinCount,InputPinCount) (This)->lpVtbl->get_PinCounts(This,OutputPinCount,InputPinCount) -#define IAMCrossbar_CanRoute(This,OutputPinIndex,InputPinIndex) (This)->lpVtbl->CanRoute(This,OutputPinIndex,InputPinIndex) -#define IAMCrossbar_Route(This,OutputPinIndex,InputPinIndex) (This)->lpVtbl->Route(This,OutputPinIndex,InputPinIndex) -#define IAMCrossbar_get_IsRoutedTo(This,OutputPinIndex,InputPinIndex) (This)->lpVtbl->get_IsRoutedTo(This,OutputPinIndex,InputPinIndex) -#define IAMCrossbar_get_CrossbarPinInfo(This,IsInputPin,PinIndex,PinIndexRelated,PhysicalType) (This)->lpVtbl->get_CrossbarPinInfo(This,IsInputPin,PinIndex,PinIndexRelated,PhysicalType) -#endif -#endif - HRESULT WINAPI IAMCrossbar_get_PinCounts_Proxy(IAMCrossbar *This,long *OutputPinCount,long *InputPinCount); - void __RPC_STUB IAMCrossbar_get_PinCounts_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMCrossbar_CanRoute_Proxy(IAMCrossbar *This,long OutputPinIndex,long InputPinIndex); - void __RPC_STUB IAMCrossbar_CanRoute_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMCrossbar_Route_Proxy(IAMCrossbar *This,long OutputPinIndex,long InputPinIndex); - void __RPC_STUB IAMCrossbar_Route_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMCrossbar_get_IsRoutedTo_Proxy(IAMCrossbar *This,long OutputPinIndex,long *InputPinIndex); - void __RPC_STUB IAMCrossbar_get_IsRoutedTo_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMCrossbar_get_CrossbarPinInfo_Proxy(IAMCrossbar *This,WINBOOL IsInputPin,long PinIndex,long *PinIndexRelated,long *PhysicalType); - void __RPC_STUB IAMCrossbar_get_CrossbarPinInfo_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - typedef enum tagAMTunerSubChannel { - AMTUNER_SUBCHAN_NO_TUNE = -2,AMTUNER_SUBCHAN_DEFAULT = -1 - } AMTunerSubChannel; - - typedef enum tagAMTunerSignalStrength { - AMTUNER_HASNOSIGNALSTRENGTH = -1,AMTUNER_NOSIGNAL = 0,AMTUNER_SIGNALPRESENT = 1 - } AMTunerSignalStrength; - - typedef enum tagAMTunerModeType { - AMTUNER_MODE_DEFAULT = 0,AMTUNER_MODE_TV = 0x1,AMTUNER_MODE_FM_RADIO = 0x2,AMTUNER_MODE_AM_RADIO = 0x4,AMTUNER_MODE_DSS = 0x8 - } AMTunerModeType; - - typedef enum tagAMTunerEventType { - AMTUNER_EVENT_CHANGED = 0x1 - } AMTunerEventType; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0178_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0178_v0_0_s_ifspec; -#ifndef __IAMTuner_INTERFACE_DEFINED__ -#define __IAMTuner_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IAMTuner; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IAMTuner : public IUnknown { - public: - virtual HRESULT WINAPI put_Channel(long lChannel,long lVideoSubChannel,long lAudioSubChannel) = 0; - virtual HRESULT WINAPI get_Channel(long *plChannel,long *plVideoSubChannel,long *plAudioSubChannel) = 0; - virtual HRESULT WINAPI ChannelMinMax(long *lChannelMin,long *lChannelMax) = 0; - virtual HRESULT WINAPI put_CountryCode(long lCountryCode) = 0; - virtual HRESULT WINAPI get_CountryCode(long *plCountryCode) = 0; - virtual HRESULT WINAPI put_TuningSpace(long lTuningSpace) = 0; - virtual HRESULT WINAPI get_TuningSpace(long *plTuningSpace) = 0; - virtual HRESULT WINAPI Logon(HANDLE hCurrentUser) = 0; - virtual HRESULT WINAPI Logout(void) = 0; - virtual HRESULT WINAPI SignalPresent(long *plSignalStrength) = 0; - virtual HRESULT WINAPI put_Mode(AMTunerModeType lMode) = 0; - virtual HRESULT WINAPI get_Mode(AMTunerModeType *plMode) = 0; - virtual HRESULT WINAPI GetAvailableModes(long *plModes) = 0; - virtual HRESULT WINAPI RegisterNotificationCallBack(IAMTunerNotification *pNotify,long lEvents) = 0; - virtual HRESULT WINAPI UnRegisterNotificationCallBack(IAMTunerNotification *pNotify) = 0; - }; -#else - typedef struct IAMTunerVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IAMTuner *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IAMTuner *This); - ULONG (WINAPI *Release)(IAMTuner *This); - HRESULT (WINAPI *put_Channel)(IAMTuner *This,long lChannel,long lVideoSubChannel,long lAudioSubChannel); - HRESULT (WINAPI *get_Channel)(IAMTuner *This,long *plChannel,long *plVideoSubChannel,long *plAudioSubChannel); - HRESULT (WINAPI *ChannelMinMax)(IAMTuner *This,long *lChannelMin,long *lChannelMax); - HRESULT (WINAPI *put_CountryCode)(IAMTuner *This,long lCountryCode); - HRESULT (WINAPI *get_CountryCode)(IAMTuner *This,long *plCountryCode); - HRESULT (WINAPI *put_TuningSpace)(IAMTuner *This,long lTuningSpace); - HRESULT (WINAPI *get_TuningSpace)(IAMTuner *This,long *plTuningSpace); - HRESULT (WINAPI *Logon)(IAMTuner *This,HANDLE hCurrentUser); - HRESULT (WINAPI *Logout)(IAMTuner *This); - HRESULT (WINAPI *SignalPresent)(IAMTuner *This,long *plSignalStrength); - HRESULT (WINAPI *put_Mode)(IAMTuner *This,AMTunerModeType lMode); - HRESULT (WINAPI *get_Mode)(IAMTuner *This,AMTunerModeType *plMode); - HRESULT (WINAPI *GetAvailableModes)(IAMTuner *This,long *plModes); - HRESULT (WINAPI *RegisterNotificationCallBack)(IAMTuner *This,IAMTunerNotification *pNotify,long lEvents); - HRESULT (WINAPI *UnRegisterNotificationCallBack)(IAMTuner *This,IAMTunerNotification *pNotify); - END_INTERFACE - } IAMTunerVtbl; - struct IAMTuner { - CONST_VTBL struct IAMTunerVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IAMTuner_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IAMTuner_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IAMTuner_Release(This) (This)->lpVtbl->Release(This) -#define IAMTuner_put_Channel(This,lChannel,lVideoSubChannel,lAudioSubChannel) (This)->lpVtbl->put_Channel(This,lChannel,lVideoSubChannel,lAudioSubChannel) -#define IAMTuner_get_Channel(This,plChannel,plVideoSubChannel,plAudioSubChannel) (This)->lpVtbl->get_Channel(This,plChannel,plVideoSubChannel,plAudioSubChannel) -#define IAMTuner_ChannelMinMax(This,lChannelMin,lChannelMax) (This)->lpVtbl->ChannelMinMax(This,lChannelMin,lChannelMax) -#define IAMTuner_put_CountryCode(This,lCountryCode) (This)->lpVtbl->put_CountryCode(This,lCountryCode) -#define IAMTuner_get_CountryCode(This,plCountryCode) (This)->lpVtbl->get_CountryCode(This,plCountryCode) -#define IAMTuner_put_TuningSpace(This,lTuningSpace) (This)->lpVtbl->put_TuningSpace(This,lTuningSpace) -#define IAMTuner_get_TuningSpace(This,plTuningSpace) (This)->lpVtbl->get_TuningSpace(This,plTuningSpace) -#define IAMTuner_Logon(This,hCurrentUser) (This)->lpVtbl->Logon(This,hCurrentUser) -#define IAMTuner_Logout(This) (This)->lpVtbl->Logout(This) -#define IAMTuner_SignalPresent(This,plSignalStrength) (This)->lpVtbl->SignalPresent(This,plSignalStrength) -#define IAMTuner_put_Mode(This,lMode) (This)->lpVtbl->put_Mode(This,lMode) -#define IAMTuner_get_Mode(This,plMode) (This)->lpVtbl->get_Mode(This,plMode) -#define IAMTuner_GetAvailableModes(This,plModes) (This)->lpVtbl->GetAvailableModes(This,plModes) -#define IAMTuner_RegisterNotificationCallBack(This,pNotify,lEvents) (This)->lpVtbl->RegisterNotificationCallBack(This,pNotify,lEvents) -#define IAMTuner_UnRegisterNotificationCallBack(This,pNotify) (This)->lpVtbl->UnRegisterNotificationCallBack(This,pNotify) -#endif -#endif - HRESULT WINAPI IAMTuner_put_Channel_Proxy(IAMTuner *This,long lChannel,long lVideoSubChannel,long lAudioSubChannel); - void __RPC_STUB IAMTuner_put_Channel_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMTuner_get_Channel_Proxy(IAMTuner *This,long *plChannel,long *plVideoSubChannel,long *plAudioSubChannel); - void __RPC_STUB IAMTuner_get_Channel_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMTuner_ChannelMinMax_Proxy(IAMTuner *This,long *lChannelMin,long *lChannelMax); - void __RPC_STUB IAMTuner_ChannelMinMax_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMTuner_put_CountryCode_Proxy(IAMTuner *This,long lCountryCode); - void __RPC_STUB IAMTuner_put_CountryCode_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMTuner_get_CountryCode_Proxy(IAMTuner *This,long *plCountryCode); - void __RPC_STUB IAMTuner_get_CountryCode_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMTuner_put_TuningSpace_Proxy(IAMTuner *This,long lTuningSpace); - void __RPC_STUB IAMTuner_put_TuningSpace_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMTuner_get_TuningSpace_Proxy(IAMTuner *This,long *plTuningSpace); - void __RPC_STUB IAMTuner_get_TuningSpace_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMTuner_Logon_Proxy(IAMTuner *This,HANDLE hCurrentUser); - void __RPC_STUB IAMTuner_Logon_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMTuner_Logout_Proxy(IAMTuner *This); - void __RPC_STUB IAMTuner_Logout_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMTuner_SignalPresent_Proxy(IAMTuner *This,long *plSignalStrength); - void __RPC_STUB IAMTuner_SignalPresent_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMTuner_put_Mode_Proxy(IAMTuner *This,AMTunerModeType lMode); - void __RPC_STUB IAMTuner_put_Mode_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMTuner_get_Mode_Proxy(IAMTuner *This,AMTunerModeType *plMode); - void __RPC_STUB IAMTuner_get_Mode_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMTuner_GetAvailableModes_Proxy(IAMTuner *This,long *plModes); - void __RPC_STUB IAMTuner_GetAvailableModes_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMTuner_RegisterNotificationCallBack_Proxy(IAMTuner *This,IAMTunerNotification *pNotify,long lEvents); - void __RPC_STUB IAMTuner_RegisterNotificationCallBack_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMTuner_UnRegisterNotificationCallBack_Proxy(IAMTuner *This,IAMTunerNotification *pNotify); - void __RPC_STUB IAMTuner_UnRegisterNotificationCallBack_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IAMTunerNotification_INTERFACE_DEFINED__ -#define __IAMTunerNotification_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IAMTunerNotification; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IAMTunerNotification : public IUnknown { - public: - virtual HRESULT WINAPI OnEvent(AMTunerEventType Event) = 0; - }; -#else - typedef struct IAMTunerNotificationVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IAMTunerNotification *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IAMTunerNotification *This); - ULONG (WINAPI *Release)(IAMTunerNotification *This); - HRESULT (WINAPI *OnEvent)(IAMTunerNotification *This,AMTunerEventType Event); - END_INTERFACE - } IAMTunerNotificationVtbl; - struct IAMTunerNotification { - CONST_VTBL struct IAMTunerNotificationVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IAMTunerNotification_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IAMTunerNotification_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IAMTunerNotification_Release(This) (This)->lpVtbl->Release(This) -#define IAMTunerNotification_OnEvent(This,Event) (This)->lpVtbl->OnEvent(This,Event) -#endif -#endif - HRESULT WINAPI IAMTunerNotification_OnEvent_Proxy(IAMTunerNotification *This,AMTunerEventType Event); - void __RPC_STUB IAMTunerNotification_OnEvent_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IAMTVTuner_INTERFACE_DEFINED__ -#define __IAMTVTuner_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IAMTVTuner; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IAMTVTuner : public IAMTuner { - public: - virtual HRESULT WINAPI get_AvailableTVFormats(long *lAnalogVideoStandard) = 0; - virtual HRESULT WINAPI get_TVFormat(long *plAnalogVideoStandard) = 0; - virtual HRESULT WINAPI AutoTune(long lChannel,long *plFoundSignal) = 0; - virtual HRESULT WINAPI StoreAutoTune(void) = 0; - virtual HRESULT WINAPI get_NumInputConnections(long *plNumInputConnections) = 0; - virtual HRESULT WINAPI put_InputType(long lIndex,TunerInputType InputType) = 0; - virtual HRESULT WINAPI get_InputType(long lIndex,TunerInputType *pInputType) = 0; - virtual HRESULT WINAPI put_ConnectInput(long lIndex) = 0; - virtual HRESULT WINAPI get_ConnectInput(long *plIndex) = 0; - virtual HRESULT WINAPI get_VideoFrequency(long *lFreq) = 0; - virtual HRESULT WINAPI get_AudioFrequency(long *lFreq) = 0; - }; -#else - typedef struct IAMTVTunerVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IAMTVTuner *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IAMTVTuner *This); - ULONG (WINAPI *Release)(IAMTVTuner *This); - HRESULT (WINAPI *put_Channel)(IAMTVTuner *This,long lChannel,long lVideoSubChannel,long lAudioSubChannel); - HRESULT (WINAPI *get_Channel)(IAMTVTuner *This,long *plChannel,long *plVideoSubChannel,long *plAudioSubChannel); - HRESULT (WINAPI *ChannelMinMax)(IAMTVTuner *This,long *lChannelMin,long *lChannelMax); - HRESULT (WINAPI *put_CountryCode)(IAMTVTuner *This,long lCountryCode); - HRESULT (WINAPI *get_CountryCode)(IAMTVTuner *This,long *plCountryCode); - HRESULT (WINAPI *put_TuningSpace)(IAMTVTuner *This,long lTuningSpace); - HRESULT (WINAPI *get_TuningSpace)(IAMTVTuner *This,long *plTuningSpace); - HRESULT (WINAPI *Logon)(IAMTVTuner *This,HANDLE hCurrentUser); - HRESULT (WINAPI *Logout)(IAMTVTuner *This); - HRESULT (WINAPI *SignalPresent)(IAMTVTuner *This,long *plSignalStrength); - HRESULT (WINAPI *put_Mode)(IAMTVTuner *This,AMTunerModeType lMode); - HRESULT (WINAPI *get_Mode)(IAMTVTuner *This,AMTunerModeType *plMode); - HRESULT (WINAPI *GetAvailableModes)(IAMTVTuner *This,long *plModes); - HRESULT (WINAPI *RegisterNotificationCallBack)(IAMTVTuner *This,IAMTunerNotification *pNotify,long lEvents); - HRESULT (WINAPI *UnRegisterNotificationCallBack)(IAMTVTuner *This,IAMTunerNotification *pNotify); - HRESULT (WINAPI *get_AvailableTVFormats)(IAMTVTuner *This,long *lAnalogVideoStandard); - HRESULT (WINAPI *get_TVFormat)(IAMTVTuner *This,long *plAnalogVideoStandard); - HRESULT (WINAPI *AutoTune)(IAMTVTuner *This,long lChannel,long *plFoundSignal); - HRESULT (WINAPI *StoreAutoTune)(IAMTVTuner *This); - HRESULT (WINAPI *get_NumInputConnections)(IAMTVTuner *This,long *plNumInputConnections); - HRESULT (WINAPI *put_InputType)(IAMTVTuner *This,long lIndex,TunerInputType InputType); - HRESULT (WINAPI *get_InputType)(IAMTVTuner *This,long lIndex,TunerInputType *pInputType); - HRESULT (WINAPI *put_ConnectInput)(IAMTVTuner *This,long lIndex); - HRESULT (WINAPI *get_ConnectInput)(IAMTVTuner *This,long *plIndex); - HRESULT (WINAPI *get_VideoFrequency)(IAMTVTuner *This,long *lFreq); - HRESULT (WINAPI *get_AudioFrequency)(IAMTVTuner *This,long *lFreq); - END_INTERFACE - } IAMTVTunerVtbl; - struct IAMTVTuner { - CONST_VTBL struct IAMTVTunerVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IAMTVTuner_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IAMTVTuner_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IAMTVTuner_Release(This) (This)->lpVtbl->Release(This) -#define IAMTVTuner_put_Channel(This,lChannel,lVideoSubChannel,lAudioSubChannel) (This)->lpVtbl->put_Channel(This,lChannel,lVideoSubChannel,lAudioSubChannel) -#define IAMTVTuner_get_Channel(This,plChannel,plVideoSubChannel,plAudioSubChannel) (This)->lpVtbl->get_Channel(This,plChannel,plVideoSubChannel,plAudioSubChannel) -#define IAMTVTuner_ChannelMinMax(This,lChannelMin,lChannelMax) (This)->lpVtbl->ChannelMinMax(This,lChannelMin,lChannelMax) -#define IAMTVTuner_put_CountryCode(This,lCountryCode) (This)->lpVtbl->put_CountryCode(This,lCountryCode) -#define IAMTVTuner_get_CountryCode(This,plCountryCode) (This)->lpVtbl->get_CountryCode(This,plCountryCode) -#define IAMTVTuner_put_TuningSpace(This,lTuningSpace) (This)->lpVtbl->put_TuningSpace(This,lTuningSpace) -#define IAMTVTuner_get_TuningSpace(This,plTuningSpace) (This)->lpVtbl->get_TuningSpace(This,plTuningSpace) -#define IAMTVTuner_Logon(This,hCurrentUser) (This)->lpVtbl->Logon(This,hCurrentUser) -#define IAMTVTuner_Logout(This) (This)->lpVtbl->Logout(This) -#define IAMTVTuner_SignalPresent(This,plSignalStrength) (This)->lpVtbl->SignalPresent(This,plSignalStrength) -#define IAMTVTuner_put_Mode(This,lMode) (This)->lpVtbl->put_Mode(This,lMode) -#define IAMTVTuner_get_Mode(This,plMode) (This)->lpVtbl->get_Mode(This,plMode) -#define IAMTVTuner_GetAvailableModes(This,plModes) (This)->lpVtbl->GetAvailableModes(This,plModes) -#define IAMTVTuner_RegisterNotificationCallBack(This,pNotify,lEvents) (This)->lpVtbl->RegisterNotificationCallBack(This,pNotify,lEvents) -#define IAMTVTuner_UnRegisterNotificationCallBack(This,pNotify) (This)->lpVtbl->UnRegisterNotificationCallBack(This,pNotify) -#define IAMTVTuner_get_AvailableTVFormats(This,lAnalogVideoStandard) (This)->lpVtbl->get_AvailableTVFormats(This,lAnalogVideoStandard) -#define IAMTVTuner_get_TVFormat(This,plAnalogVideoStandard) (This)->lpVtbl->get_TVFormat(This,plAnalogVideoStandard) -#define IAMTVTuner_AutoTune(This,lChannel,plFoundSignal) (This)->lpVtbl->AutoTune(This,lChannel,plFoundSignal) -#define IAMTVTuner_StoreAutoTune(This) (This)->lpVtbl->StoreAutoTune(This) -#define IAMTVTuner_get_NumInputConnections(This,plNumInputConnections) (This)->lpVtbl->get_NumInputConnections(This,plNumInputConnections) -#define IAMTVTuner_put_InputType(This,lIndex,InputType) (This)->lpVtbl->put_InputType(This,lIndex,InputType) -#define IAMTVTuner_get_InputType(This,lIndex,pInputType) (This)->lpVtbl->get_InputType(This,lIndex,pInputType) -#define IAMTVTuner_put_ConnectInput(This,lIndex) (This)->lpVtbl->put_ConnectInput(This,lIndex) -#define IAMTVTuner_get_ConnectInput(This,plIndex) (This)->lpVtbl->get_ConnectInput(This,plIndex) -#define IAMTVTuner_get_VideoFrequency(This,lFreq) (This)->lpVtbl->get_VideoFrequency(This,lFreq) -#define IAMTVTuner_get_AudioFrequency(This,lFreq) (This)->lpVtbl->get_AudioFrequency(This,lFreq) -#endif -#endif - HRESULT WINAPI IAMTVTuner_get_AvailableTVFormats_Proxy(IAMTVTuner *This,long *lAnalogVideoStandard); - void __RPC_STUB IAMTVTuner_get_AvailableTVFormats_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMTVTuner_get_TVFormat_Proxy(IAMTVTuner *This,long *plAnalogVideoStandard); - void __RPC_STUB IAMTVTuner_get_TVFormat_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMTVTuner_AutoTune_Proxy(IAMTVTuner *This,long lChannel,long *plFoundSignal); - void __RPC_STUB IAMTVTuner_AutoTune_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMTVTuner_StoreAutoTune_Proxy(IAMTVTuner *This); - void __RPC_STUB IAMTVTuner_StoreAutoTune_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMTVTuner_get_NumInputConnections_Proxy(IAMTVTuner *This,long *plNumInputConnections); - void __RPC_STUB IAMTVTuner_get_NumInputConnections_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMTVTuner_put_InputType_Proxy(IAMTVTuner *This,long lIndex,TunerInputType InputType); - void __RPC_STUB IAMTVTuner_put_InputType_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMTVTuner_get_InputType_Proxy(IAMTVTuner *This,long lIndex,TunerInputType *pInputType); - void __RPC_STUB IAMTVTuner_get_InputType_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMTVTuner_put_ConnectInput_Proxy(IAMTVTuner *This,long lIndex); - void __RPC_STUB IAMTVTuner_put_ConnectInput_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMTVTuner_get_ConnectInput_Proxy(IAMTVTuner *This,long *plIndex); - void __RPC_STUB IAMTVTuner_get_ConnectInput_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMTVTuner_get_VideoFrequency_Proxy(IAMTVTuner *This,long *lFreq); - void __RPC_STUB IAMTVTuner_get_VideoFrequency_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMTVTuner_get_AudioFrequency_Proxy(IAMTVTuner *This,long *lFreq); - void __RPC_STUB IAMTVTuner_get_AudioFrequency_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IBPCSatelliteTuner_INTERFACE_DEFINED__ -#define __IBPCSatelliteTuner_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IBPCSatelliteTuner; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IBPCSatelliteTuner : public IAMTuner { - public: - virtual HRESULT WINAPI get_DefaultSubChannelTypes(long *plDefaultVideoType,long *plDefaultAudioType) = 0; - virtual HRESULT WINAPI put_DefaultSubChannelTypes(long lDefaultVideoType,long lDefaultAudioType) = 0; - virtual HRESULT WINAPI IsTapingPermitted(void) = 0; - }; -#else - typedef struct IBPCSatelliteTunerVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IBPCSatelliteTuner *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IBPCSatelliteTuner *This); - ULONG (WINAPI *Release)(IBPCSatelliteTuner *This); - HRESULT (WINAPI *put_Channel)(IBPCSatelliteTuner *This,long lChannel,long lVideoSubChannel,long lAudioSubChannel); - HRESULT (WINAPI *get_Channel)(IBPCSatelliteTuner *This,long *plChannel,long *plVideoSubChannel,long *plAudioSubChannel); - HRESULT (WINAPI *ChannelMinMax)(IBPCSatelliteTuner *This,long *lChannelMin,long *lChannelMax); - HRESULT (WINAPI *put_CountryCode)(IBPCSatelliteTuner *This,long lCountryCode); - HRESULT (WINAPI *get_CountryCode)(IBPCSatelliteTuner *This,long *plCountryCode); - HRESULT (WINAPI *put_TuningSpace)(IBPCSatelliteTuner *This,long lTuningSpace); - HRESULT (WINAPI *get_TuningSpace)(IBPCSatelliteTuner *This,long *plTuningSpace); - HRESULT (WINAPI *Logon)(IBPCSatelliteTuner *This,HANDLE hCurrentUser); - HRESULT (WINAPI *Logout)(IBPCSatelliteTuner *This); - HRESULT (WINAPI *SignalPresent)(IBPCSatelliteTuner *This,long *plSignalStrength); - HRESULT (WINAPI *put_Mode)(IBPCSatelliteTuner *This,AMTunerModeType lMode); - HRESULT (WINAPI *get_Mode)(IBPCSatelliteTuner *This,AMTunerModeType *plMode); - HRESULT (WINAPI *GetAvailableModes)(IBPCSatelliteTuner *This,long *plModes); - HRESULT (WINAPI *RegisterNotificationCallBack)(IBPCSatelliteTuner *This,IAMTunerNotification *pNotify,long lEvents); - HRESULT (WINAPI *UnRegisterNotificationCallBack)(IBPCSatelliteTuner *This,IAMTunerNotification *pNotify); - HRESULT (WINAPI *get_DefaultSubChannelTypes)(IBPCSatelliteTuner *This,long *plDefaultVideoType,long *plDefaultAudioType); - HRESULT (WINAPI *put_DefaultSubChannelTypes)(IBPCSatelliteTuner *This,long lDefaultVideoType,long lDefaultAudioType); - HRESULT (WINAPI *IsTapingPermitted)(IBPCSatelliteTuner *This); - END_INTERFACE - } IBPCSatelliteTunerVtbl; - struct IBPCSatelliteTuner { - CONST_VTBL struct IBPCSatelliteTunerVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IBPCSatelliteTuner_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IBPCSatelliteTuner_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IBPCSatelliteTuner_Release(This) (This)->lpVtbl->Release(This) -#define IBPCSatelliteTuner_put_Channel(This,lChannel,lVideoSubChannel,lAudioSubChannel) (This)->lpVtbl->put_Channel(This,lChannel,lVideoSubChannel,lAudioSubChannel) -#define IBPCSatelliteTuner_get_Channel(This,plChannel,plVideoSubChannel,plAudioSubChannel) (This)->lpVtbl->get_Channel(This,plChannel,plVideoSubChannel,plAudioSubChannel) -#define IBPCSatelliteTuner_ChannelMinMax(This,lChannelMin,lChannelMax) (This)->lpVtbl->ChannelMinMax(This,lChannelMin,lChannelMax) -#define IBPCSatelliteTuner_put_CountryCode(This,lCountryCode) (This)->lpVtbl->put_CountryCode(This,lCountryCode) -#define IBPCSatelliteTuner_get_CountryCode(This,plCountryCode) (This)->lpVtbl->get_CountryCode(This,plCountryCode) -#define IBPCSatelliteTuner_put_TuningSpace(This,lTuningSpace) (This)->lpVtbl->put_TuningSpace(This,lTuningSpace) -#define IBPCSatelliteTuner_get_TuningSpace(This,plTuningSpace) (This)->lpVtbl->get_TuningSpace(This,plTuningSpace) -#define IBPCSatelliteTuner_Logon(This,hCurrentUser) (This)->lpVtbl->Logon(This,hCurrentUser) -#define IBPCSatelliteTuner_Logout(This) (This)->lpVtbl->Logout(This) -#define IBPCSatelliteTuner_SignalPresent(This,plSignalStrength) (This)->lpVtbl->SignalPresent(This,plSignalStrength) -#define IBPCSatelliteTuner_put_Mode(This,lMode) (This)->lpVtbl->put_Mode(This,lMode) -#define IBPCSatelliteTuner_get_Mode(This,plMode) (This)->lpVtbl->get_Mode(This,plMode) -#define IBPCSatelliteTuner_GetAvailableModes(This,plModes) (This)->lpVtbl->GetAvailableModes(This,plModes) -#define IBPCSatelliteTuner_RegisterNotificationCallBack(This,pNotify,lEvents) (This)->lpVtbl->RegisterNotificationCallBack(This,pNotify,lEvents) -#define IBPCSatelliteTuner_UnRegisterNotificationCallBack(This,pNotify) (This)->lpVtbl->UnRegisterNotificationCallBack(This,pNotify) -#define IBPCSatelliteTuner_get_DefaultSubChannelTypes(This,plDefaultVideoType,plDefaultAudioType) (This)->lpVtbl->get_DefaultSubChannelTypes(This,plDefaultVideoType,plDefaultAudioType) -#define IBPCSatelliteTuner_put_DefaultSubChannelTypes(This,lDefaultVideoType,lDefaultAudioType) (This)->lpVtbl->put_DefaultSubChannelTypes(This,lDefaultVideoType,lDefaultAudioType) -#define IBPCSatelliteTuner_IsTapingPermitted(This) (This)->lpVtbl->IsTapingPermitted(This) -#endif -#endif - HRESULT WINAPI IBPCSatelliteTuner_get_DefaultSubChannelTypes_Proxy(IBPCSatelliteTuner *This,long *plDefaultVideoType,long *plDefaultAudioType); - void __RPC_STUB IBPCSatelliteTuner_get_DefaultSubChannelTypes_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IBPCSatelliteTuner_put_DefaultSubChannelTypes_Proxy(IBPCSatelliteTuner *This,long lDefaultVideoType,long lDefaultAudioType); - void __RPC_STUB IBPCSatelliteTuner_put_DefaultSubChannelTypes_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IBPCSatelliteTuner_IsTapingPermitted_Proxy(IBPCSatelliteTuner *This); - void __RPC_STUB IBPCSatelliteTuner_IsTapingPermitted_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - typedef enum tagTVAudioMode { - AMTVAUDIO_MODE_MONO = 0x1,AMTVAUDIO_MODE_STEREO = 0x2,AMTVAUDIO_MODE_LANG_A = 0x10,AMTVAUDIO_MODE_LANG_B = 0x20,AMTVAUDIO_MODE_LANG_C = 0x40 - } TVAudioMode; - - typedef enum tagAMTVAudioEventType { - AMTVAUDIO_EVENT_CHANGED = 0x1 - } AMTVAudioEventType; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0182_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0182_v0_0_s_ifspec; -#ifndef __IAMTVAudio_INTERFACE_DEFINED__ -#define __IAMTVAudio_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IAMTVAudio; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IAMTVAudio : public IUnknown { - public: - virtual HRESULT WINAPI GetHardwareSupportedTVAudioModes(long *plModes) = 0; - virtual HRESULT WINAPI GetAvailableTVAudioModes(long *plModes) = 0; - virtual HRESULT WINAPI get_TVAudioMode(long *plMode) = 0; - virtual HRESULT WINAPI put_TVAudioMode(long lMode) = 0; - virtual HRESULT WINAPI RegisterNotificationCallBack(IAMTunerNotification *pNotify,long lEvents) = 0; - virtual HRESULT WINAPI UnRegisterNotificationCallBack(IAMTunerNotification *pNotify) = 0; - }; -#else - typedef struct IAMTVAudioVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IAMTVAudio *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IAMTVAudio *This); - ULONG (WINAPI *Release)(IAMTVAudio *This); - HRESULT (WINAPI *GetHardwareSupportedTVAudioModes)(IAMTVAudio *This,long *plModes); - HRESULT (WINAPI *GetAvailableTVAudioModes)(IAMTVAudio *This,long *plModes); - HRESULT (WINAPI *get_TVAudioMode)(IAMTVAudio *This,long *plMode); - HRESULT (WINAPI *put_TVAudioMode)(IAMTVAudio *This,long lMode); - HRESULT (WINAPI *RegisterNotificationCallBack)(IAMTVAudio *This,IAMTunerNotification *pNotify,long lEvents); - HRESULT (WINAPI *UnRegisterNotificationCallBack)(IAMTVAudio *This,IAMTunerNotification *pNotify); - END_INTERFACE - } IAMTVAudioVtbl; - struct IAMTVAudio { - CONST_VTBL struct IAMTVAudioVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IAMTVAudio_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IAMTVAudio_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IAMTVAudio_Release(This) (This)->lpVtbl->Release(This) -#define IAMTVAudio_GetHardwareSupportedTVAudioModes(This,plModes) (This)->lpVtbl->GetHardwareSupportedTVAudioModes(This,plModes) -#define IAMTVAudio_GetAvailableTVAudioModes(This,plModes) (This)->lpVtbl->GetAvailableTVAudioModes(This,plModes) -#define IAMTVAudio_get_TVAudioMode(This,plMode) (This)->lpVtbl->get_TVAudioMode(This,plMode) -#define IAMTVAudio_put_TVAudioMode(This,lMode) (This)->lpVtbl->put_TVAudioMode(This,lMode) -#define IAMTVAudio_RegisterNotificationCallBack(This,pNotify,lEvents) (This)->lpVtbl->RegisterNotificationCallBack(This,pNotify,lEvents) -#define IAMTVAudio_UnRegisterNotificationCallBack(This,pNotify) (This)->lpVtbl->UnRegisterNotificationCallBack(This,pNotify) -#endif -#endif - HRESULT WINAPI IAMTVAudio_GetHardwareSupportedTVAudioModes_Proxy(IAMTVAudio *This,long *plModes); - void __RPC_STUB IAMTVAudio_GetHardwareSupportedTVAudioModes_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMTVAudio_GetAvailableTVAudioModes_Proxy(IAMTVAudio *This,long *plModes); - void __RPC_STUB IAMTVAudio_GetAvailableTVAudioModes_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMTVAudio_get_TVAudioMode_Proxy(IAMTVAudio *This,long *plMode); - void __RPC_STUB IAMTVAudio_get_TVAudioMode_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMTVAudio_put_TVAudioMode_Proxy(IAMTVAudio *This,long lMode); - void __RPC_STUB IAMTVAudio_put_TVAudioMode_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMTVAudio_RegisterNotificationCallBack_Proxy(IAMTVAudio *This,IAMTunerNotification *pNotify,long lEvents); - void __RPC_STUB IAMTVAudio_RegisterNotificationCallBack_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMTVAudio_UnRegisterNotificationCallBack_Proxy(IAMTVAudio *This,IAMTunerNotification *pNotify); - void __RPC_STUB IAMTVAudio_UnRegisterNotificationCallBack_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IAMTVAudioNotification_INTERFACE_DEFINED__ -#define __IAMTVAudioNotification_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IAMTVAudioNotification; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IAMTVAudioNotification : public IUnknown { - public: - virtual HRESULT WINAPI OnEvent(AMTVAudioEventType Event) = 0; - }; -#else - typedef struct IAMTVAudioNotificationVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IAMTVAudioNotification *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IAMTVAudioNotification *This); - ULONG (WINAPI *Release)(IAMTVAudioNotification *This); - HRESULT (WINAPI *OnEvent)(IAMTVAudioNotification *This,AMTVAudioEventType Event); - END_INTERFACE - } IAMTVAudioNotificationVtbl; - struct IAMTVAudioNotification { - CONST_VTBL struct IAMTVAudioNotificationVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IAMTVAudioNotification_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IAMTVAudioNotification_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IAMTVAudioNotification_Release(This) (This)->lpVtbl->Release(This) -#define IAMTVAudioNotification_OnEvent(This,Event) (This)->lpVtbl->OnEvent(This,Event) -#endif -#endif - HRESULT WINAPI IAMTVAudioNotification_OnEvent_Proxy(IAMTVAudioNotification *This,AMTVAudioEventType Event); - void __RPC_STUB IAMTVAudioNotification_OnEvent_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IAMAnalogVideoEncoder_INTERFACE_DEFINED__ -#define __IAMAnalogVideoEncoder_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IAMAnalogVideoEncoder; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IAMAnalogVideoEncoder : public IUnknown { - public: - virtual HRESULT WINAPI get_AvailableTVFormats(long *lAnalogVideoStandard) = 0; - virtual HRESULT WINAPI put_TVFormat(long lAnalogVideoStandard) = 0; - virtual HRESULT WINAPI get_TVFormat(long *plAnalogVideoStandard) = 0; - virtual HRESULT WINAPI put_CopyProtection(long lVideoCopyProtection) = 0; - virtual HRESULT WINAPI get_CopyProtection(long *lVideoCopyProtection) = 0; - virtual HRESULT WINAPI put_CCEnable(long lCCEnable) = 0; - virtual HRESULT WINAPI get_CCEnable(long *lCCEnable) = 0; - }; -#else - typedef struct IAMAnalogVideoEncoderVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IAMAnalogVideoEncoder *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IAMAnalogVideoEncoder *This); - ULONG (WINAPI *Release)(IAMAnalogVideoEncoder *This); - HRESULT (WINAPI *get_AvailableTVFormats)(IAMAnalogVideoEncoder *This,long *lAnalogVideoStandard); - HRESULT (WINAPI *put_TVFormat)(IAMAnalogVideoEncoder *This,long lAnalogVideoStandard); - HRESULT (WINAPI *get_TVFormat)(IAMAnalogVideoEncoder *This,long *plAnalogVideoStandard); - HRESULT (WINAPI *put_CopyProtection)(IAMAnalogVideoEncoder *This,long lVideoCopyProtection); - HRESULT (WINAPI *get_CopyProtection)(IAMAnalogVideoEncoder *This,long *lVideoCopyProtection); - HRESULT (WINAPI *put_CCEnable)(IAMAnalogVideoEncoder *This,long lCCEnable); - HRESULT (WINAPI *get_CCEnable)(IAMAnalogVideoEncoder *This,long *lCCEnable); - END_INTERFACE - } IAMAnalogVideoEncoderVtbl; - struct IAMAnalogVideoEncoder { - CONST_VTBL struct IAMAnalogVideoEncoderVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IAMAnalogVideoEncoder_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IAMAnalogVideoEncoder_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IAMAnalogVideoEncoder_Release(This) (This)->lpVtbl->Release(This) -#define IAMAnalogVideoEncoder_get_AvailableTVFormats(This,lAnalogVideoStandard) (This)->lpVtbl->get_AvailableTVFormats(This,lAnalogVideoStandard) -#define IAMAnalogVideoEncoder_put_TVFormat(This,lAnalogVideoStandard) (This)->lpVtbl->put_TVFormat(This,lAnalogVideoStandard) -#define IAMAnalogVideoEncoder_get_TVFormat(This,plAnalogVideoStandard) (This)->lpVtbl->get_TVFormat(This,plAnalogVideoStandard) -#define IAMAnalogVideoEncoder_put_CopyProtection(This,lVideoCopyProtection) (This)->lpVtbl->put_CopyProtection(This,lVideoCopyProtection) -#define IAMAnalogVideoEncoder_get_CopyProtection(This,lVideoCopyProtection) (This)->lpVtbl->get_CopyProtection(This,lVideoCopyProtection) -#define IAMAnalogVideoEncoder_put_CCEnable(This,lCCEnable) (This)->lpVtbl->put_CCEnable(This,lCCEnable) -#define IAMAnalogVideoEncoder_get_CCEnable(This,lCCEnable) (This)->lpVtbl->get_CCEnable(This,lCCEnable) -#endif -#endif - HRESULT WINAPI IAMAnalogVideoEncoder_get_AvailableTVFormats_Proxy(IAMAnalogVideoEncoder *This,long *lAnalogVideoStandard); - void __RPC_STUB IAMAnalogVideoEncoder_get_AvailableTVFormats_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMAnalogVideoEncoder_put_TVFormat_Proxy(IAMAnalogVideoEncoder *This,long lAnalogVideoStandard); - void __RPC_STUB IAMAnalogVideoEncoder_put_TVFormat_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMAnalogVideoEncoder_get_TVFormat_Proxy(IAMAnalogVideoEncoder *This,long *plAnalogVideoStandard); - void __RPC_STUB IAMAnalogVideoEncoder_get_TVFormat_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMAnalogVideoEncoder_put_CopyProtection_Proxy(IAMAnalogVideoEncoder *This,long lVideoCopyProtection); - void __RPC_STUB IAMAnalogVideoEncoder_put_CopyProtection_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMAnalogVideoEncoder_get_CopyProtection_Proxy(IAMAnalogVideoEncoder *This,long *lVideoCopyProtection); - void __RPC_STUB IAMAnalogVideoEncoder_get_CopyProtection_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMAnalogVideoEncoder_put_CCEnable_Proxy(IAMAnalogVideoEncoder *This,long lCCEnable); - void __RPC_STUB IAMAnalogVideoEncoder_put_CCEnable_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMAnalogVideoEncoder_get_CCEnable_Proxy(IAMAnalogVideoEncoder *This,long *lCCEnable); - void __RPC_STUB IAMAnalogVideoEncoder_get_CCEnable_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - typedef enum __MIDL___MIDL_itf_strmif_0185_0001 { - AMPROPERTY_PIN_CATEGORY = 0,AMPROPERTY_PIN_MEDIUM = AMPROPERTY_PIN_CATEGORY + 1 - } AMPROPERTY_PIN; - -#ifndef _IKsPropertySet_ -#define _IKsPropertySet_ -#define KSPROPERTY_SUPPORT_GET 1 -#define KSPROPERTY_SUPPORT_SET 2 - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0185_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0185_v0_0_s_ifspec; -#ifndef __IKsPropertySet_INTERFACE_DEFINED__ -#define __IKsPropertySet_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IKsPropertySet; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IKsPropertySet : public IUnknown { - public: - virtual HRESULT WINAPI Set(REFGUID guidPropSet,DWORD dwPropID,LPVOID pInstanceData,DWORD cbInstanceData,LPVOID pPropData,DWORD cbPropData) = 0; - virtual HRESULT WINAPI Get(REFGUID guidPropSet,DWORD dwPropID,LPVOID pInstanceData,DWORD cbInstanceData,LPVOID pPropData,DWORD cbPropData,DWORD *pcbReturned) = 0; - virtual HRESULT WINAPI QuerySupported(REFGUID guidPropSet,DWORD dwPropID,DWORD *pTypeSupport) = 0; - }; -#else - typedef struct IKsPropertySetVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IKsPropertySet *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IKsPropertySet *This); - ULONG (WINAPI *Release)(IKsPropertySet *This); - HRESULT (WINAPI *Set)(IKsPropertySet *This,REFGUID guidPropSet,DWORD dwPropID,LPVOID pInstanceData,DWORD cbInstanceData,LPVOID pPropData,DWORD cbPropData); - HRESULT (WINAPI *Get)(IKsPropertySet *This,REFGUID guidPropSet,DWORD dwPropID,LPVOID pInstanceData,DWORD cbInstanceData,LPVOID pPropData,DWORD cbPropData,DWORD *pcbReturned); - HRESULT (WINAPI *QuerySupported)(IKsPropertySet *This,REFGUID guidPropSet,DWORD dwPropID,DWORD *pTypeSupport); - END_INTERFACE - } IKsPropertySetVtbl; - struct IKsPropertySet { - CONST_VTBL struct IKsPropertySetVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IKsPropertySet_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IKsPropertySet_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IKsPropertySet_Release(This) (This)->lpVtbl->Release(This) -#define IKsPropertySet_Set(This,guidPropSet,dwPropID,pInstanceData,cbInstanceData,pPropData,cbPropData) (This)->lpVtbl->Set(This,guidPropSet,dwPropID,pInstanceData,cbInstanceData,pPropData,cbPropData) -#define IKsPropertySet_Get(This,guidPropSet,dwPropID,pInstanceData,cbInstanceData,pPropData,cbPropData,pcbReturned) (This)->lpVtbl->Get(This,guidPropSet,dwPropID,pInstanceData,cbInstanceData,pPropData,cbPropData,pcbReturned) -#define IKsPropertySet_QuerySupported(This,guidPropSet,dwPropID,pTypeSupport) (This)->lpVtbl->QuerySupported(This,guidPropSet,dwPropID,pTypeSupport) -#endif -#endif - HRESULT WINAPI IKsPropertySet_RemoteSet_Proxy(IKsPropertySet *This,REFGUID guidPropSet,DWORD dwPropID,byte *pInstanceData,DWORD cbInstanceData,byte *pPropData,DWORD cbPropData); - void __RPC_STUB IKsPropertySet_RemoteSet_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IKsPropertySet_RemoteGet_Proxy(IKsPropertySet *This,REFGUID guidPropSet,DWORD dwPropID,byte *pInstanceData,DWORD cbInstanceData,byte *pPropData,DWORD cbPropData,DWORD *pcbReturned); - void __RPC_STUB IKsPropertySet_RemoteGet_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IKsPropertySet_QuerySupported_Proxy(IKsPropertySet *This,REFGUID guidPropSet,DWORD dwPropID,DWORD *pTypeSupport); - void __RPC_STUB IKsPropertySet_QuerySupported_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif -#endif - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0186_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0186_v0_0_s_ifspec; -#ifndef __IMediaPropertyBag_INTERFACE_DEFINED__ -#define __IMediaPropertyBag_INTERFACE_DEFINED__ - typedef IMediaPropertyBag *LPMEDIAPROPERTYBAG; - - EXTERN_C const IID IID_IMediaPropertyBag; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IMediaPropertyBag : public IPropertyBag { - public: - virtual HRESULT WINAPI EnumProperty(ULONG iProperty,VARIANT *pvarPropertyName,VARIANT *pvarPropertyValue) = 0; - }; -#else - typedef struct IMediaPropertyBagVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IMediaPropertyBag *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IMediaPropertyBag *This); - ULONG (WINAPI *Release)(IMediaPropertyBag *This); - HRESULT (WINAPI *Read)(IMediaPropertyBag *This,LPCOLESTR pszPropName,VARIANT *pVar,IErrorLog *pErrorLog); - HRESULT (WINAPI *Write)(IMediaPropertyBag *This,LPCOLESTR pszPropName,VARIANT *pVar); - HRESULT (WINAPI *EnumProperty)(IMediaPropertyBag *This,ULONG iProperty,VARIANT *pvarPropertyName,VARIANT *pvarPropertyValue); - END_INTERFACE - } IMediaPropertyBagVtbl; - struct IMediaPropertyBag { - CONST_VTBL struct IMediaPropertyBagVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IMediaPropertyBag_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IMediaPropertyBag_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IMediaPropertyBag_Release(This) (This)->lpVtbl->Release(This) -#define IMediaPropertyBag_Read(This,pszPropName,pVar,pErrorLog) (This)->lpVtbl->Read(This,pszPropName,pVar,pErrorLog) -#define IMediaPropertyBag_Write(This,pszPropName,pVar) (This)->lpVtbl->Write(This,pszPropName,pVar) -#define IMediaPropertyBag_EnumProperty(This,iProperty,pvarPropertyName,pvarPropertyValue) (This)->lpVtbl->EnumProperty(This,iProperty,pvarPropertyName,pvarPropertyValue) -#endif -#endif - HRESULT WINAPI IMediaPropertyBag_EnumProperty_Proxy(IMediaPropertyBag *This,ULONG iProperty,VARIANT *pvarPropertyName,VARIANT *pvarPropertyValue); - void __RPC_STUB IMediaPropertyBag_EnumProperty_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IPersistMediaPropertyBag_INTERFACE_DEFINED__ -#define __IPersistMediaPropertyBag_INTERFACE_DEFINED__ - typedef IPersistMediaPropertyBag *LPPERSISTMEDIAPROPERTYBAG; - - EXTERN_C const IID IID_IPersistMediaPropertyBag; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IPersistMediaPropertyBag : public IPersist { - public: - virtual HRESULT WINAPI InitNew(void) = 0; - virtual HRESULT WINAPI Load(IMediaPropertyBag *pPropBag,IErrorLog *pErrorLog) = 0; - virtual HRESULT WINAPI Save(IMediaPropertyBag *pPropBag,WINBOOL fClearDirty,WINBOOL fSaveAllProperties) = 0; - }; -#else - typedef struct IPersistMediaPropertyBagVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IPersistMediaPropertyBag *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IPersistMediaPropertyBag *This); - ULONG (WINAPI *Release)(IPersistMediaPropertyBag *This); - HRESULT (WINAPI *GetClassID)(IPersistMediaPropertyBag *This,CLSID *pClassID); - HRESULT (WINAPI *InitNew)(IPersistMediaPropertyBag *This); - HRESULT (WINAPI *Load)(IPersistMediaPropertyBag *This,IMediaPropertyBag *pPropBag,IErrorLog *pErrorLog); - HRESULT (WINAPI *Save)(IPersistMediaPropertyBag *This,IMediaPropertyBag *pPropBag,WINBOOL fClearDirty,WINBOOL fSaveAllProperties); - END_INTERFACE - } IPersistMediaPropertyBagVtbl; - struct IPersistMediaPropertyBag { - CONST_VTBL struct IPersistMediaPropertyBagVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IPersistMediaPropertyBag_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IPersistMediaPropertyBag_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IPersistMediaPropertyBag_Release(This) (This)->lpVtbl->Release(This) -#define IPersistMediaPropertyBag_GetClassID(This,pClassID) (This)->lpVtbl->GetClassID(This,pClassID) -#define IPersistMediaPropertyBag_InitNew(This) (This)->lpVtbl->InitNew(This) -#define IPersistMediaPropertyBag_Load(This,pPropBag,pErrorLog) (This)->lpVtbl->Load(This,pPropBag,pErrorLog) -#define IPersistMediaPropertyBag_Save(This,pPropBag,fClearDirty,fSaveAllProperties) (This)->lpVtbl->Save(This,pPropBag,fClearDirty,fSaveAllProperties) -#endif -#endif - HRESULT WINAPI IPersistMediaPropertyBag_InitNew_Proxy(IPersistMediaPropertyBag *This); - void __RPC_STUB IPersistMediaPropertyBag_InitNew_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IPersistMediaPropertyBag_Load_Proxy(IPersistMediaPropertyBag *This,IMediaPropertyBag *pPropBag,IErrorLog *pErrorLog); - void __RPC_STUB IPersistMediaPropertyBag_Load_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IPersistMediaPropertyBag_Save_Proxy(IPersistMediaPropertyBag *This,IMediaPropertyBag *pPropBag,WINBOOL fClearDirty,WINBOOL fSaveAllProperties); - void __RPC_STUB IPersistMediaPropertyBag_Save_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IAMPhysicalPinInfo_INTERFACE_DEFINED__ -#define __IAMPhysicalPinInfo_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IAMPhysicalPinInfo; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IAMPhysicalPinInfo : public IUnknown { - public: - virtual HRESULT WINAPI GetPhysicalType(long *pType,LPOLESTR *ppszType) = 0; - }; -#else - typedef struct IAMPhysicalPinInfoVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IAMPhysicalPinInfo *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IAMPhysicalPinInfo *This); - ULONG (WINAPI *Release)(IAMPhysicalPinInfo *This); - HRESULT (WINAPI *GetPhysicalType)(IAMPhysicalPinInfo *This,long *pType,LPOLESTR *ppszType); - END_INTERFACE - } IAMPhysicalPinInfoVtbl; - struct IAMPhysicalPinInfo { - CONST_VTBL struct IAMPhysicalPinInfoVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IAMPhysicalPinInfo_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IAMPhysicalPinInfo_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IAMPhysicalPinInfo_Release(This) (This)->lpVtbl->Release(This) -#define IAMPhysicalPinInfo_GetPhysicalType(This,pType,ppszType) (This)->lpVtbl->GetPhysicalType(This,pType,ppszType) -#endif -#endif - HRESULT WINAPI IAMPhysicalPinInfo_GetPhysicalType_Proxy(IAMPhysicalPinInfo *This,long *pType,LPOLESTR *ppszType); - void __RPC_STUB IAMPhysicalPinInfo_GetPhysicalType_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - typedef IAMPhysicalPinInfo *PAMPHYSICALPININFO; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0338_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0338_v0_0_s_ifspec; -#ifndef __IAMExtDevice_INTERFACE_DEFINED__ -#define __IAMExtDevice_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IAMExtDevice; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IAMExtDevice : public IUnknown { - public: - virtual HRESULT WINAPI GetCapability(long Capability,long *pValue,double *pdblValue) = 0; - virtual HRESULT WINAPI get_ExternalDeviceID(LPOLESTR *ppszData) = 0; - virtual HRESULT WINAPI get_ExternalDeviceVersion(LPOLESTR *ppszData) = 0; - virtual HRESULT WINAPI put_DevicePower(long PowerMode) = 0; - virtual HRESULT WINAPI get_DevicePower(long *pPowerMode) = 0; - virtual HRESULT WINAPI Calibrate(HEVENT hEvent,long Mode,long *pStatus) = 0; - virtual HRESULT WINAPI put_DevicePort(long DevicePort) = 0; - virtual HRESULT WINAPI get_DevicePort(long *pDevicePort) = 0; - }; -#else - typedef struct IAMExtDeviceVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IAMExtDevice *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IAMExtDevice *This); - ULONG (WINAPI *Release)(IAMExtDevice *This); - HRESULT (WINAPI *GetCapability)(IAMExtDevice *This,long Capability,long *pValue,double *pdblValue); - HRESULT (WINAPI *get_ExternalDeviceID)(IAMExtDevice *This,LPOLESTR *ppszData); - HRESULT (WINAPI *get_ExternalDeviceVersion)(IAMExtDevice *This,LPOLESTR *ppszData); - HRESULT (WINAPI *put_DevicePower)(IAMExtDevice *This,long PowerMode); - HRESULT (WINAPI *get_DevicePower)(IAMExtDevice *This,long *pPowerMode); - HRESULT (WINAPI *Calibrate)(IAMExtDevice *This,HEVENT hEvent,long Mode,long *pStatus); - HRESULT (WINAPI *put_DevicePort)(IAMExtDevice *This,long DevicePort); - HRESULT (WINAPI *get_DevicePort)(IAMExtDevice *This,long *pDevicePort); - END_INTERFACE - } IAMExtDeviceVtbl; - struct IAMExtDevice { - CONST_VTBL struct IAMExtDeviceVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IAMExtDevice_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IAMExtDevice_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IAMExtDevice_Release(This) (This)->lpVtbl->Release(This) -#define IAMExtDevice_GetCapability(This,Capability,pValue,pdblValue) (This)->lpVtbl->GetCapability(This,Capability,pValue,pdblValue) -#define IAMExtDevice_get_ExternalDeviceID(This,ppszData) (This)->lpVtbl->get_ExternalDeviceID(This,ppszData) -#define IAMExtDevice_get_ExternalDeviceVersion(This,ppszData) (This)->lpVtbl->get_ExternalDeviceVersion(This,ppszData) -#define IAMExtDevice_put_DevicePower(This,PowerMode) (This)->lpVtbl->put_DevicePower(This,PowerMode) -#define IAMExtDevice_get_DevicePower(This,pPowerMode) (This)->lpVtbl->get_DevicePower(This,pPowerMode) -#define IAMExtDevice_Calibrate(This,hEvent,Mode,pStatus) (This)->lpVtbl->Calibrate(This,hEvent,Mode,pStatus) -#define IAMExtDevice_put_DevicePort(This,DevicePort) (This)->lpVtbl->put_DevicePort(This,DevicePort) -#define IAMExtDevice_get_DevicePort(This,pDevicePort) (This)->lpVtbl->get_DevicePort(This,pDevicePort) -#endif -#endif - HRESULT WINAPI IAMExtDevice_GetCapability_Proxy(IAMExtDevice *This,long Capability,long *pValue,double *pdblValue); - void __RPC_STUB IAMExtDevice_GetCapability_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMExtDevice_get_ExternalDeviceID_Proxy(IAMExtDevice *This,LPOLESTR *ppszData); - void __RPC_STUB IAMExtDevice_get_ExternalDeviceID_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMExtDevice_get_ExternalDeviceVersion_Proxy(IAMExtDevice *This,LPOLESTR *ppszData); - void __RPC_STUB IAMExtDevice_get_ExternalDeviceVersion_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMExtDevice_put_DevicePower_Proxy(IAMExtDevice *This,long PowerMode); - void __RPC_STUB IAMExtDevice_put_DevicePower_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMExtDevice_get_DevicePower_Proxy(IAMExtDevice *This,long *pPowerMode); - void __RPC_STUB IAMExtDevice_get_DevicePower_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMExtDevice_Calibrate_Proxy(IAMExtDevice *This,HEVENT hEvent,long Mode,long *pStatus); - void __RPC_STUB IAMExtDevice_Calibrate_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMExtDevice_put_DevicePort_Proxy(IAMExtDevice *This,long DevicePort); - void __RPC_STUB IAMExtDevice_put_DevicePort_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMExtDevice_get_DevicePort_Proxy(IAMExtDevice *This,long *pDevicePort); - void __RPC_STUB IAMExtDevice_get_DevicePort_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - typedef IAMExtDevice *PEXTDEVICE; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0339_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0339_v0_0_s_ifspec; -#ifndef __IAMExtTransport_INTERFACE_DEFINED__ -#define __IAMExtTransport_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IAMExtTransport; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IAMExtTransport : public IUnknown { - public: - virtual HRESULT WINAPI GetCapability(long Capability,long *pValue,double *pdblValue) = 0; - virtual HRESULT WINAPI put_MediaState(long State) = 0; - virtual HRESULT WINAPI get_MediaState(long *pState) = 0; - virtual HRESULT WINAPI put_LocalControl(long State) = 0; - virtual HRESULT WINAPI get_LocalControl(long *pState) = 0; - virtual HRESULT WINAPI GetStatus(long StatusItem,long *pValue) = 0; - virtual HRESULT WINAPI GetTransportBasicParameters(long Param,long *pValue,LPOLESTR *ppszData) = 0; - virtual HRESULT WINAPI SetTransportBasicParameters(long Param,long Value,LPCOLESTR pszData) = 0; - virtual HRESULT WINAPI GetTransportVideoParameters(long Param,long *pValue) = 0; - virtual HRESULT WINAPI SetTransportVideoParameters(long Param,long Value) = 0; - virtual HRESULT WINAPI GetTransportAudioParameters(long Param,long *pValue) = 0; - virtual HRESULT WINAPI SetTransportAudioParameters(long Param,long Value) = 0; - virtual HRESULT WINAPI put_Mode(long Mode) = 0; - virtual HRESULT WINAPI get_Mode(long *pMode) = 0; - virtual HRESULT WINAPI put_Rate(double dblRate) = 0; - virtual HRESULT WINAPI get_Rate(double *pdblRate) = 0; - virtual HRESULT WINAPI GetChase(long *pEnabled,long *pOffset,HEVENT *phEvent) = 0; - virtual HRESULT WINAPI SetChase(long Enable,long Offset,HEVENT hEvent) = 0; - virtual HRESULT WINAPI GetBump(long *pSpeed,long *pDuration) = 0; - virtual HRESULT WINAPI SetBump(long Speed,long Duration) = 0; - virtual HRESULT WINAPI get_AntiClogControl(long *pEnabled) = 0; - virtual HRESULT WINAPI put_AntiClogControl(long Enable) = 0; - virtual HRESULT WINAPI GetEditPropertySet(long EditID,long *pState) = 0; - virtual HRESULT WINAPI SetEditPropertySet(long *pEditID,long State) = 0; - virtual HRESULT WINAPI GetEditProperty(long EditID,long Param,long *pValue) = 0; - virtual HRESULT WINAPI SetEditProperty(long EditID,long Param,long Value) = 0; - virtual HRESULT WINAPI get_EditStart(long *pValue) = 0; - virtual HRESULT WINAPI put_EditStart(long Value) = 0; - }; -#else - typedef struct IAMExtTransportVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IAMExtTransport *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IAMExtTransport *This); - ULONG (WINAPI *Release)(IAMExtTransport *This); - HRESULT (WINAPI *GetCapability)(IAMExtTransport *This,long Capability,long *pValue,double *pdblValue); - HRESULT (WINAPI *put_MediaState)(IAMExtTransport *This,long State); - HRESULT (WINAPI *get_MediaState)(IAMExtTransport *This,long *pState); - HRESULT (WINAPI *put_LocalControl)(IAMExtTransport *This,long State); - HRESULT (WINAPI *get_LocalControl)(IAMExtTransport *This,long *pState); - HRESULT (WINAPI *GetStatus)(IAMExtTransport *This,long StatusItem,long *pValue); - HRESULT (WINAPI *GetTransportBasicParameters)(IAMExtTransport *This,long Param,long *pValue,LPOLESTR *ppszData); - HRESULT (WINAPI *SetTransportBasicParameters)(IAMExtTransport *This,long Param,long Value,LPCOLESTR pszData); - HRESULT (WINAPI *GetTransportVideoParameters)(IAMExtTransport *This,long Param,long *pValue); - HRESULT (WINAPI *SetTransportVideoParameters)(IAMExtTransport *This,long Param,long Value); - HRESULT (WINAPI *GetTransportAudioParameters)(IAMExtTransport *This,long Param,long *pValue); - HRESULT (WINAPI *SetTransportAudioParameters)(IAMExtTransport *This,long Param,long Value); - HRESULT (WINAPI *put_Mode)(IAMExtTransport *This,long Mode); - HRESULT (WINAPI *get_Mode)(IAMExtTransport *This,long *pMode); - HRESULT (WINAPI *put_Rate)(IAMExtTransport *This,double dblRate); - HRESULT (WINAPI *get_Rate)(IAMExtTransport *This,double *pdblRate); - HRESULT (WINAPI *GetChase)(IAMExtTransport *This,long *pEnabled,long *pOffset,HEVENT *phEvent); - HRESULT (WINAPI *SetChase)(IAMExtTransport *This,long Enable,long Offset,HEVENT hEvent); - HRESULT (WINAPI *GetBump)(IAMExtTransport *This,long *pSpeed,long *pDuration); - HRESULT (WINAPI *SetBump)(IAMExtTransport *This,long Speed,long Duration); - HRESULT (WINAPI *get_AntiClogControl)(IAMExtTransport *This,long *pEnabled); - HRESULT (WINAPI *put_AntiClogControl)(IAMExtTransport *This,long Enable); - HRESULT (WINAPI *GetEditPropertySet)(IAMExtTransport *This,long EditID,long *pState); - HRESULT (WINAPI *SetEditPropertySet)(IAMExtTransport *This,long *pEditID,long State); - HRESULT (WINAPI *GetEditProperty)(IAMExtTransport *This,long EditID,long Param,long *pValue); - HRESULT (WINAPI *SetEditProperty)(IAMExtTransport *This,long EditID,long Param,long Value); - HRESULT (WINAPI *get_EditStart)(IAMExtTransport *This,long *pValue); - HRESULT (WINAPI *put_EditStart)(IAMExtTransport *This,long Value); - END_INTERFACE - } IAMExtTransportVtbl; - struct IAMExtTransport { - CONST_VTBL struct IAMExtTransportVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IAMExtTransport_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IAMExtTransport_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IAMExtTransport_Release(This) (This)->lpVtbl->Release(This) -#define IAMExtTransport_GetCapability(This,Capability,pValue,pdblValue) (This)->lpVtbl->GetCapability(This,Capability,pValue,pdblValue) -#define IAMExtTransport_put_MediaState(This,State) (This)->lpVtbl->put_MediaState(This,State) -#define IAMExtTransport_get_MediaState(This,pState) (This)->lpVtbl->get_MediaState(This,pState) -#define IAMExtTransport_put_LocalControl(This,State) (This)->lpVtbl->put_LocalControl(This,State) -#define IAMExtTransport_get_LocalControl(This,pState) (This)->lpVtbl->get_LocalControl(This,pState) -#define IAMExtTransport_GetStatus(This,StatusItem,pValue) (This)->lpVtbl->GetStatus(This,StatusItem,pValue) -#define IAMExtTransport_GetTransportBasicParameters(This,Param,pValue,ppszData) (This)->lpVtbl->GetTransportBasicParameters(This,Param,pValue,ppszData) -#define IAMExtTransport_SetTransportBasicParameters(This,Param,Value,pszData) (This)->lpVtbl->SetTransportBasicParameters(This,Param,Value,pszData) -#define IAMExtTransport_GetTransportVideoParameters(This,Param,pValue) (This)->lpVtbl->GetTransportVideoParameters(This,Param,pValue) -#define IAMExtTransport_SetTransportVideoParameters(This,Param,Value) (This)->lpVtbl->SetTransportVideoParameters(This,Param,Value) -#define IAMExtTransport_GetTransportAudioParameters(This,Param,pValue) (This)->lpVtbl->GetTransportAudioParameters(This,Param,pValue) -#define IAMExtTransport_SetTransportAudioParameters(This,Param,Value) (This)->lpVtbl->SetTransportAudioParameters(This,Param,Value) -#define IAMExtTransport_put_Mode(This,Mode) (This)->lpVtbl->put_Mode(This,Mode) -#define IAMExtTransport_get_Mode(This,pMode) (This)->lpVtbl->get_Mode(This,pMode) -#define IAMExtTransport_put_Rate(This,dblRate) (This)->lpVtbl->put_Rate(This,dblRate) -#define IAMExtTransport_get_Rate(This,pdblRate) (This)->lpVtbl->get_Rate(This,pdblRate) -#define IAMExtTransport_GetChase(This,pEnabled,pOffset,phEvent) (This)->lpVtbl->GetChase(This,pEnabled,pOffset,phEvent) -#define IAMExtTransport_SetChase(This,Enable,Offset,hEvent) (This)->lpVtbl->SetChase(This,Enable,Offset,hEvent) -#define IAMExtTransport_GetBump(This,pSpeed,pDuration) (This)->lpVtbl->GetBump(This,pSpeed,pDuration) -#define IAMExtTransport_SetBump(This,Speed,Duration) (This)->lpVtbl->SetBump(This,Speed,Duration) -#define IAMExtTransport_get_AntiClogControl(This,pEnabled) (This)->lpVtbl->get_AntiClogControl(This,pEnabled) -#define IAMExtTransport_put_AntiClogControl(This,Enable) (This)->lpVtbl->put_AntiClogControl(This,Enable) -#define IAMExtTransport_GetEditPropertySet(This,EditID,pState) (This)->lpVtbl->GetEditPropertySet(This,EditID,pState) -#define IAMExtTransport_SetEditPropertySet(This,pEditID,State) (This)->lpVtbl->SetEditPropertySet(This,pEditID,State) -#define IAMExtTransport_GetEditProperty(This,EditID,Param,pValue) (This)->lpVtbl->GetEditProperty(This,EditID,Param,pValue) -#define IAMExtTransport_SetEditProperty(This,EditID,Param,Value) (This)->lpVtbl->SetEditProperty(This,EditID,Param,Value) -#define IAMExtTransport_get_EditStart(This,pValue) (This)->lpVtbl->get_EditStart(This,pValue) -#define IAMExtTransport_put_EditStart(This,Value) (This)->lpVtbl->put_EditStart(This,Value) -#endif -#endif - HRESULT WINAPI IAMExtTransport_GetCapability_Proxy(IAMExtTransport *This,long Capability,long *pValue,double *pdblValue); - void __RPC_STUB IAMExtTransport_GetCapability_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMExtTransport_put_MediaState_Proxy(IAMExtTransport *This,long State); - void __RPC_STUB IAMExtTransport_put_MediaState_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMExtTransport_get_MediaState_Proxy(IAMExtTransport *This,long *pState); - void __RPC_STUB IAMExtTransport_get_MediaState_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMExtTransport_put_LocalControl_Proxy(IAMExtTransport *This,long State); - void __RPC_STUB IAMExtTransport_put_LocalControl_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMExtTransport_get_LocalControl_Proxy(IAMExtTransport *This,long *pState); - void __RPC_STUB IAMExtTransport_get_LocalControl_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMExtTransport_GetStatus_Proxy(IAMExtTransport *This,long StatusItem,long *pValue); - void __RPC_STUB IAMExtTransport_GetStatus_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMExtTransport_GetTransportBasicParameters_Proxy(IAMExtTransport *This,long Param,long *pValue,LPOLESTR *ppszData); - void __RPC_STUB IAMExtTransport_GetTransportBasicParameters_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMExtTransport_SetTransportBasicParameters_Proxy(IAMExtTransport *This,long Param,long Value,LPCOLESTR pszData); - void __RPC_STUB IAMExtTransport_SetTransportBasicParameters_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMExtTransport_GetTransportVideoParameters_Proxy(IAMExtTransport *This,long Param,long *pValue); - void __RPC_STUB IAMExtTransport_GetTransportVideoParameters_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMExtTransport_SetTransportVideoParameters_Proxy(IAMExtTransport *This,long Param,long Value); - void __RPC_STUB IAMExtTransport_SetTransportVideoParameters_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMExtTransport_GetTransportAudioParameters_Proxy(IAMExtTransport *This,long Param,long *pValue); - void __RPC_STUB IAMExtTransport_GetTransportAudioParameters_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMExtTransport_SetTransportAudioParameters_Proxy(IAMExtTransport *This,long Param,long Value); - void __RPC_STUB IAMExtTransport_SetTransportAudioParameters_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMExtTransport_put_Mode_Proxy(IAMExtTransport *This,long Mode); - void __RPC_STUB IAMExtTransport_put_Mode_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMExtTransport_get_Mode_Proxy(IAMExtTransport *This,long *pMode); - void __RPC_STUB IAMExtTransport_get_Mode_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMExtTransport_put_Rate_Proxy(IAMExtTransport *This,double dblRate); - void __RPC_STUB IAMExtTransport_put_Rate_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMExtTransport_get_Rate_Proxy(IAMExtTransport *This,double *pdblRate); - void __RPC_STUB IAMExtTransport_get_Rate_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMExtTransport_GetChase_Proxy(IAMExtTransport *This,long *pEnabled,long *pOffset,HEVENT *phEvent); - void __RPC_STUB IAMExtTransport_GetChase_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMExtTransport_SetChase_Proxy(IAMExtTransport *This,long Enable,long Offset,HEVENT hEvent); - void __RPC_STUB IAMExtTransport_SetChase_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMExtTransport_GetBump_Proxy(IAMExtTransport *This,long *pSpeed,long *pDuration); - void __RPC_STUB IAMExtTransport_GetBump_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMExtTransport_SetBump_Proxy(IAMExtTransport *This,long Speed,long Duration); - void __RPC_STUB IAMExtTransport_SetBump_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMExtTransport_get_AntiClogControl_Proxy(IAMExtTransport *This,long *pEnabled); - void __RPC_STUB IAMExtTransport_get_AntiClogControl_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMExtTransport_put_AntiClogControl_Proxy(IAMExtTransport *This,long Enable); - void __RPC_STUB IAMExtTransport_put_AntiClogControl_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMExtTransport_GetEditPropertySet_Proxy(IAMExtTransport *This,long EditID,long *pState); - void __RPC_STUB IAMExtTransport_GetEditPropertySet_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMExtTransport_SetEditPropertySet_Proxy(IAMExtTransport *This,long *pEditID,long State); - void __RPC_STUB IAMExtTransport_SetEditPropertySet_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMExtTransport_GetEditProperty_Proxy(IAMExtTransport *This,long EditID,long Param,long *pValue); - void __RPC_STUB IAMExtTransport_GetEditProperty_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMExtTransport_SetEditProperty_Proxy(IAMExtTransport *This,long EditID,long Param,long Value); - void __RPC_STUB IAMExtTransport_SetEditProperty_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMExtTransport_get_EditStart_Proxy(IAMExtTransport *This,long *pValue); - void __RPC_STUB IAMExtTransport_get_EditStart_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMExtTransport_put_EditStart_Proxy(IAMExtTransport *This,long Value); - void __RPC_STUB IAMExtTransport_put_EditStart_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - typedef IAMExtTransport *PIAMEXTTRANSPORT; - -#ifndef TIMECODE_DEFINED -#define TIMECODE_DEFINED - typedef union _timecode { - struct { - WORD wFrameRate; - WORD wFrameFract; - DWORD dwFrames; - }; - DWORDLONG qw; - } TIMECODE; -#endif - - typedef TIMECODE *PTIMECODE; - - typedef struct tagTIMECODE_SAMPLE { - LONGLONG qwTick; - TIMECODE timecode; - DWORD dwUser; - DWORD dwFlags; - } TIMECODE_SAMPLE; - - typedef TIMECODE_SAMPLE *PTIMECODE_SAMPLE; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0340_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0340_v0_0_s_ifspec; -#ifndef __IAMTimecodeReader_INTERFACE_DEFINED__ -#define __IAMTimecodeReader_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IAMTimecodeReader; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IAMTimecodeReader : public IUnknown { - public: - virtual HRESULT WINAPI GetTCRMode(long Param,long *pValue) = 0; - virtual HRESULT WINAPI SetTCRMode(long Param,long Value) = 0; - virtual HRESULT WINAPI put_VITCLine(long Line) = 0; - virtual HRESULT WINAPI get_VITCLine(long *pLine) = 0; - virtual HRESULT WINAPI GetTimecode(PTIMECODE_SAMPLE pTimecodeSample) = 0; - }; -#else - typedef struct IAMTimecodeReaderVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IAMTimecodeReader *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IAMTimecodeReader *This); - ULONG (WINAPI *Release)(IAMTimecodeReader *This); - HRESULT (WINAPI *GetTCRMode)(IAMTimecodeReader *This,long Param,long *pValue); - HRESULT (WINAPI *SetTCRMode)(IAMTimecodeReader *This,long Param,long Value); - HRESULT (WINAPI *put_VITCLine)(IAMTimecodeReader *This,long Line); - HRESULT (WINAPI *get_VITCLine)(IAMTimecodeReader *This,long *pLine); - HRESULT (WINAPI *GetTimecode)(IAMTimecodeReader *This,PTIMECODE_SAMPLE pTimecodeSample); - END_INTERFACE - } IAMTimecodeReaderVtbl; - struct IAMTimecodeReader { - CONST_VTBL struct IAMTimecodeReaderVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IAMTimecodeReader_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IAMTimecodeReader_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IAMTimecodeReader_Release(This) (This)->lpVtbl->Release(This) -#define IAMTimecodeReader_GetTCRMode(This,Param,pValue) (This)->lpVtbl->GetTCRMode(This,Param,pValue) -#define IAMTimecodeReader_SetTCRMode(This,Param,Value) (This)->lpVtbl->SetTCRMode(This,Param,Value) -#define IAMTimecodeReader_put_VITCLine(This,Line) (This)->lpVtbl->put_VITCLine(This,Line) -#define IAMTimecodeReader_get_VITCLine(This,pLine) (This)->lpVtbl->get_VITCLine(This,pLine) -#define IAMTimecodeReader_GetTimecode(This,pTimecodeSample) (This)->lpVtbl->GetTimecode(This,pTimecodeSample) -#endif -#endif - HRESULT WINAPI IAMTimecodeReader_GetTCRMode_Proxy(IAMTimecodeReader *This,long Param,long *pValue); - void __RPC_STUB IAMTimecodeReader_GetTCRMode_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMTimecodeReader_SetTCRMode_Proxy(IAMTimecodeReader *This,long Param,long Value); - void __RPC_STUB IAMTimecodeReader_SetTCRMode_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMTimecodeReader_put_VITCLine_Proxy(IAMTimecodeReader *This,long Line); - void __RPC_STUB IAMTimecodeReader_put_VITCLine_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMTimecodeReader_get_VITCLine_Proxy(IAMTimecodeReader *This,long *pLine); - void __RPC_STUB IAMTimecodeReader_get_VITCLine_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMTimecodeReader_GetTimecode_Proxy(IAMTimecodeReader *This,PTIMECODE_SAMPLE pTimecodeSample); - void __RPC_STUB IAMTimecodeReader_GetTimecode_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - typedef IAMTimecodeReader *PIAMTIMECODEREADER; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0341_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0341_v0_0_s_ifspec; -#ifndef __IAMTimecodeGenerator_INTERFACE_DEFINED__ -#define __IAMTimecodeGenerator_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IAMTimecodeGenerator; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IAMTimecodeGenerator : public IUnknown { - public: - virtual HRESULT WINAPI GetTCGMode(long Param,long *pValue) = 0; - virtual HRESULT WINAPI SetTCGMode(long Param,long Value) = 0; - virtual HRESULT WINAPI put_VITCLine(long Line) = 0; - virtual HRESULT WINAPI get_VITCLine(long *pLine) = 0; - virtual HRESULT WINAPI SetTimecode(PTIMECODE_SAMPLE pTimecodeSample) = 0; - virtual HRESULT WINAPI GetTimecode(PTIMECODE_SAMPLE pTimecodeSample) = 0; - }; -#else - typedef struct IAMTimecodeGeneratorVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IAMTimecodeGenerator *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IAMTimecodeGenerator *This); - ULONG (WINAPI *Release)(IAMTimecodeGenerator *This); - HRESULT (WINAPI *GetTCGMode)(IAMTimecodeGenerator *This,long Param,long *pValue); - HRESULT (WINAPI *SetTCGMode)(IAMTimecodeGenerator *This,long Param,long Value); - HRESULT (WINAPI *put_VITCLine)(IAMTimecodeGenerator *This,long Line); - HRESULT (WINAPI *get_VITCLine)(IAMTimecodeGenerator *This,long *pLine); - HRESULT (WINAPI *SetTimecode)(IAMTimecodeGenerator *This,PTIMECODE_SAMPLE pTimecodeSample); - HRESULT (WINAPI *GetTimecode)(IAMTimecodeGenerator *This,PTIMECODE_SAMPLE pTimecodeSample); - END_INTERFACE - } IAMTimecodeGeneratorVtbl; - struct IAMTimecodeGenerator { - CONST_VTBL struct IAMTimecodeGeneratorVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IAMTimecodeGenerator_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IAMTimecodeGenerator_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IAMTimecodeGenerator_Release(This) (This)->lpVtbl->Release(This) -#define IAMTimecodeGenerator_GetTCGMode(This,Param,pValue) (This)->lpVtbl->GetTCGMode(This,Param,pValue) -#define IAMTimecodeGenerator_SetTCGMode(This,Param,Value) (This)->lpVtbl->SetTCGMode(This,Param,Value) -#define IAMTimecodeGenerator_put_VITCLine(This,Line) (This)->lpVtbl->put_VITCLine(This,Line) -#define IAMTimecodeGenerator_get_VITCLine(This,pLine) (This)->lpVtbl->get_VITCLine(This,pLine) -#define IAMTimecodeGenerator_SetTimecode(This,pTimecodeSample) (This)->lpVtbl->SetTimecode(This,pTimecodeSample) -#define IAMTimecodeGenerator_GetTimecode(This,pTimecodeSample) (This)->lpVtbl->GetTimecode(This,pTimecodeSample) -#endif -#endif - HRESULT WINAPI IAMTimecodeGenerator_GetTCGMode_Proxy(IAMTimecodeGenerator *This,long Param,long *pValue); - void __RPC_STUB IAMTimecodeGenerator_GetTCGMode_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMTimecodeGenerator_SetTCGMode_Proxy(IAMTimecodeGenerator *This,long Param,long Value); - void __RPC_STUB IAMTimecodeGenerator_SetTCGMode_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMTimecodeGenerator_put_VITCLine_Proxy(IAMTimecodeGenerator *This,long Line); - void __RPC_STUB IAMTimecodeGenerator_put_VITCLine_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMTimecodeGenerator_get_VITCLine_Proxy(IAMTimecodeGenerator *This,long *pLine); - void __RPC_STUB IAMTimecodeGenerator_get_VITCLine_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMTimecodeGenerator_SetTimecode_Proxy(IAMTimecodeGenerator *This,PTIMECODE_SAMPLE pTimecodeSample); - void __RPC_STUB IAMTimecodeGenerator_SetTimecode_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMTimecodeGenerator_GetTimecode_Proxy(IAMTimecodeGenerator *This,PTIMECODE_SAMPLE pTimecodeSample); - void __RPC_STUB IAMTimecodeGenerator_GetTimecode_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - typedef IAMTimecodeGenerator *PIAMTIMECODEGENERATOR; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0342_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0342_v0_0_s_ifspec; -#ifndef __IAMTimecodeDisplay_INTERFACE_DEFINED__ -#define __IAMTimecodeDisplay_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IAMTimecodeDisplay; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IAMTimecodeDisplay : public IUnknown { - public: - virtual HRESULT WINAPI GetTCDisplayEnable(long *pState) = 0; - virtual HRESULT WINAPI SetTCDisplayEnable(long State) = 0; - virtual HRESULT WINAPI GetTCDisplay(long Param,long *pValue) = 0; - virtual HRESULT WINAPI SetTCDisplay(long Param,long Value) = 0; - }; -#else - typedef struct IAMTimecodeDisplayVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IAMTimecodeDisplay *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IAMTimecodeDisplay *This); - ULONG (WINAPI *Release)(IAMTimecodeDisplay *This); - HRESULT (WINAPI *GetTCDisplayEnable)(IAMTimecodeDisplay *This,long *pState); - HRESULT (WINAPI *SetTCDisplayEnable)(IAMTimecodeDisplay *This,long State); - HRESULT (WINAPI *GetTCDisplay)(IAMTimecodeDisplay *This,long Param,long *pValue); - HRESULT (WINAPI *SetTCDisplay)(IAMTimecodeDisplay *This,long Param,long Value); - END_INTERFACE - } IAMTimecodeDisplayVtbl; - struct IAMTimecodeDisplay { - CONST_VTBL struct IAMTimecodeDisplayVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IAMTimecodeDisplay_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IAMTimecodeDisplay_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IAMTimecodeDisplay_Release(This) (This)->lpVtbl->Release(This) -#define IAMTimecodeDisplay_GetTCDisplayEnable(This,pState) (This)->lpVtbl->GetTCDisplayEnable(This,pState) -#define IAMTimecodeDisplay_SetTCDisplayEnable(This,State) (This)->lpVtbl->SetTCDisplayEnable(This,State) -#define IAMTimecodeDisplay_GetTCDisplay(This,Param,pValue) (This)->lpVtbl->GetTCDisplay(This,Param,pValue) -#define IAMTimecodeDisplay_SetTCDisplay(This,Param,Value) (This)->lpVtbl->SetTCDisplay(This,Param,Value) -#endif -#endif - HRESULT WINAPI IAMTimecodeDisplay_GetTCDisplayEnable_Proxy(IAMTimecodeDisplay *This,long *pState); - void __RPC_STUB IAMTimecodeDisplay_GetTCDisplayEnable_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMTimecodeDisplay_SetTCDisplayEnable_Proxy(IAMTimecodeDisplay *This,long State); - void __RPC_STUB IAMTimecodeDisplay_SetTCDisplayEnable_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMTimecodeDisplay_GetTCDisplay_Proxy(IAMTimecodeDisplay *This,long Param,long *pValue); - void __RPC_STUB IAMTimecodeDisplay_GetTCDisplay_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMTimecodeDisplay_SetTCDisplay_Proxy(IAMTimecodeDisplay *This,long Param,long Value); - void __RPC_STUB IAMTimecodeDisplay_SetTCDisplay_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - typedef IAMTimecodeDisplay *PIAMTIMECODEDISPLAY; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0343_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0343_v0_0_s_ifspec; -#ifndef __IAMDevMemoryAllocator_INTERFACE_DEFINED__ -#define __IAMDevMemoryAllocator_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IAMDevMemoryAllocator; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IAMDevMemoryAllocator : public IUnknown { - public: - virtual HRESULT WINAPI GetInfo(DWORD *pdwcbTotalFree,DWORD *pdwcbLargestFree,DWORD *pdwcbTotalMemory,DWORD *pdwcbMinimumChunk) = 0; - virtual HRESULT WINAPI CheckMemory(const BYTE *pBuffer) = 0; - virtual HRESULT WINAPI Alloc(BYTE **ppBuffer,DWORD *pdwcbBuffer) = 0; - virtual HRESULT WINAPI Free(BYTE *pBuffer) = 0; - virtual HRESULT WINAPI GetDevMemoryObject(IUnknown **ppUnkInnner,IUnknown *pUnkOuter) = 0; - }; -#else - typedef struct IAMDevMemoryAllocatorVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IAMDevMemoryAllocator *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IAMDevMemoryAllocator *This); - ULONG (WINAPI *Release)(IAMDevMemoryAllocator *This); - HRESULT (WINAPI *GetInfo)(IAMDevMemoryAllocator *This,DWORD *pdwcbTotalFree,DWORD *pdwcbLargestFree,DWORD *pdwcbTotalMemory,DWORD *pdwcbMinimumChunk); - HRESULT (WINAPI *CheckMemory)(IAMDevMemoryAllocator *This,const BYTE *pBuffer); - HRESULT (WINAPI *Alloc)(IAMDevMemoryAllocator *This,BYTE **ppBuffer,DWORD *pdwcbBuffer); - HRESULT (WINAPI *Free)(IAMDevMemoryAllocator *This,BYTE *pBuffer); - HRESULT (WINAPI *GetDevMemoryObject)(IAMDevMemoryAllocator *This,IUnknown **ppUnkInnner,IUnknown *pUnkOuter); - END_INTERFACE - } IAMDevMemoryAllocatorVtbl; - struct IAMDevMemoryAllocator { - CONST_VTBL struct IAMDevMemoryAllocatorVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IAMDevMemoryAllocator_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IAMDevMemoryAllocator_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IAMDevMemoryAllocator_Release(This) (This)->lpVtbl->Release(This) -#define IAMDevMemoryAllocator_GetInfo(This,pdwcbTotalFree,pdwcbLargestFree,pdwcbTotalMemory,pdwcbMinimumChunk) (This)->lpVtbl->GetInfo(This,pdwcbTotalFree,pdwcbLargestFree,pdwcbTotalMemory,pdwcbMinimumChunk) -#define IAMDevMemoryAllocator_CheckMemory(This,pBuffer) (This)->lpVtbl->CheckMemory(This,pBuffer) -#define IAMDevMemoryAllocator_Alloc(This,ppBuffer,pdwcbBuffer) (This)->lpVtbl->Alloc(This,ppBuffer,pdwcbBuffer) -#define IAMDevMemoryAllocator_Free(This,pBuffer) (This)->lpVtbl->Free(This,pBuffer) -#define IAMDevMemoryAllocator_GetDevMemoryObject(This,ppUnkInnner,pUnkOuter) (This)->lpVtbl->GetDevMemoryObject(This,ppUnkInnner,pUnkOuter) -#endif -#endif - HRESULT WINAPI IAMDevMemoryAllocator_GetInfo_Proxy(IAMDevMemoryAllocator *This,DWORD *pdwcbTotalFree,DWORD *pdwcbLargestFree,DWORD *pdwcbTotalMemory,DWORD *pdwcbMinimumChunk); - void __RPC_STUB IAMDevMemoryAllocator_GetInfo_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMDevMemoryAllocator_CheckMemory_Proxy(IAMDevMemoryAllocator *This,const BYTE *pBuffer); - void __RPC_STUB IAMDevMemoryAllocator_CheckMemory_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMDevMemoryAllocator_Alloc_Proxy(IAMDevMemoryAllocator *This,BYTE **ppBuffer,DWORD *pdwcbBuffer); - void __RPC_STUB IAMDevMemoryAllocator_Alloc_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMDevMemoryAllocator_Free_Proxy(IAMDevMemoryAllocator *This,BYTE *pBuffer); - void __RPC_STUB IAMDevMemoryAllocator_Free_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMDevMemoryAllocator_GetDevMemoryObject_Proxy(IAMDevMemoryAllocator *This,IUnknown **ppUnkInnner,IUnknown *pUnkOuter); - void __RPC_STUB IAMDevMemoryAllocator_GetDevMemoryObject_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - typedef IAMDevMemoryAllocator *PAMDEVMEMORYALLOCATOR; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0344_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0344_v0_0_s_ifspec; -#ifndef __IAMDevMemoryControl_INTERFACE_DEFINED__ -#define __IAMDevMemoryControl_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IAMDevMemoryControl; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IAMDevMemoryControl : public IUnknown { - public: - virtual HRESULT WINAPI QueryWriteSync(void) = 0; - virtual HRESULT WINAPI WriteSync(void) = 0; - virtual HRESULT WINAPI GetDevId(DWORD *pdwDevId) = 0; - }; -#else - typedef struct IAMDevMemoryControlVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IAMDevMemoryControl *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IAMDevMemoryControl *This); - ULONG (WINAPI *Release)(IAMDevMemoryControl *This); - HRESULT (WINAPI *QueryWriteSync)(IAMDevMemoryControl *This); - HRESULT (WINAPI *WriteSync)(IAMDevMemoryControl *This); - HRESULT (WINAPI *GetDevId)(IAMDevMemoryControl *This,DWORD *pdwDevId); - END_INTERFACE - } IAMDevMemoryControlVtbl; - struct IAMDevMemoryControl { - CONST_VTBL struct IAMDevMemoryControlVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IAMDevMemoryControl_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IAMDevMemoryControl_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IAMDevMemoryControl_Release(This) (This)->lpVtbl->Release(This) -#define IAMDevMemoryControl_QueryWriteSync(This) (This)->lpVtbl->QueryWriteSync(This) -#define IAMDevMemoryControl_WriteSync(This) (This)->lpVtbl->WriteSync(This) -#define IAMDevMemoryControl_GetDevId(This,pdwDevId) (This)->lpVtbl->GetDevId(This,pdwDevId) -#endif -#endif - HRESULT WINAPI IAMDevMemoryControl_QueryWriteSync_Proxy(IAMDevMemoryControl *This); - void __RPC_STUB IAMDevMemoryControl_QueryWriteSync_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMDevMemoryControl_WriteSync_Proxy(IAMDevMemoryControl *This); - void __RPC_STUB IAMDevMemoryControl_WriteSync_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMDevMemoryControl_GetDevId_Proxy(IAMDevMemoryControl *This,DWORD *pdwDevId); - void __RPC_STUB IAMDevMemoryControl_GetDevId_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - typedef IAMDevMemoryControl *PAMDEVMEMORYCONTROL; - - enum _AMSTREAMSELECTINFOFLAGS { - AMSTREAMSELECTINFO_ENABLED = 0x1,AMSTREAMSELECTINFO_EXCLUSIVE = 0x2 - }; - - enum _AMSTREAMSELECTENABLEFLAGS { - AMSTREAMSELECTENABLE_ENABLE = 0x1,AMSTREAMSELECTENABLE_ENABLEALL = 0x2 - }; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0345_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0345_v0_0_s_ifspec; -#ifndef __IAMStreamSelect_INTERFACE_DEFINED__ -#define __IAMStreamSelect_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IAMStreamSelect; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IAMStreamSelect : public IUnknown { - public: - virtual HRESULT WINAPI Count(DWORD *pcStreams) = 0; - virtual HRESULT WINAPI Info(long lIndex,AM_MEDIA_TYPE **ppmt,DWORD *pdwFlags,LCID *plcid,DWORD *pdwGroup,WCHAR **ppszName,IUnknown **ppObject,IUnknown **ppUnk) = 0; - virtual HRESULT WINAPI Enable(long lIndex,DWORD dwFlags) = 0; - }; -#else - typedef struct IAMStreamSelectVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IAMStreamSelect *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IAMStreamSelect *This); - ULONG (WINAPI *Release)(IAMStreamSelect *This); - HRESULT (WINAPI *Count)(IAMStreamSelect *This,DWORD *pcStreams); - HRESULT (WINAPI *Info)(IAMStreamSelect *This,long lIndex,AM_MEDIA_TYPE **ppmt,DWORD *pdwFlags,LCID *plcid,DWORD *pdwGroup,WCHAR **ppszName,IUnknown **ppObject,IUnknown **ppUnk); - HRESULT (WINAPI *Enable)(IAMStreamSelect *This,long lIndex,DWORD dwFlags); - END_INTERFACE - } IAMStreamSelectVtbl; - struct IAMStreamSelect { - CONST_VTBL struct IAMStreamSelectVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IAMStreamSelect_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IAMStreamSelect_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IAMStreamSelect_Release(This) (This)->lpVtbl->Release(This) -#define IAMStreamSelect_Count(This,pcStreams) (This)->lpVtbl->Count(This,pcStreams) -#define IAMStreamSelect_Info(This,lIndex,ppmt,pdwFlags,plcid,pdwGroup,ppszName,ppObject,ppUnk) (This)->lpVtbl->Info(This,lIndex,ppmt,pdwFlags,plcid,pdwGroup,ppszName,ppObject,ppUnk) -#define IAMStreamSelect_Enable(This,lIndex,dwFlags) (This)->lpVtbl->Enable(This,lIndex,dwFlags) -#endif -#endif - HRESULT WINAPI IAMStreamSelect_Count_Proxy(IAMStreamSelect *This,DWORD *pcStreams); - void __RPC_STUB IAMStreamSelect_Count_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMStreamSelect_Info_Proxy(IAMStreamSelect *This,long lIndex,AM_MEDIA_TYPE **ppmt,DWORD *pdwFlags,LCID *plcid,DWORD *pdwGroup,WCHAR **ppszName,IUnknown **ppObject,IUnknown **ppUnk); - void __RPC_STUB IAMStreamSelect_Info_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMStreamSelect_Enable_Proxy(IAMStreamSelect *This,long lIndex,DWORD dwFlags); - void __RPC_STUB IAMStreamSelect_Enable_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - typedef IAMStreamSelect *PAMSTREAMSELECT; - - enum _AMRESCTL_RESERVEFLAGS { - AMRESCTL_RESERVEFLAGS_RESERVE = 0,AMRESCTL_RESERVEFLAGS_UNRESERVE = 0x1 - }; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0346_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0346_v0_0_s_ifspec; -#ifndef __IAMResourceControl_INTERFACE_DEFINED__ -#define __IAMResourceControl_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IAMResourceControl; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IAMResourceControl : public IUnknown { - public: - virtual HRESULT WINAPI Reserve(DWORD dwFlags,PVOID pvReserved) = 0; - }; -#else - typedef struct IAMResourceControlVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IAMResourceControl *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IAMResourceControl *This); - ULONG (WINAPI *Release)(IAMResourceControl *This); - HRESULT (WINAPI *Reserve)(IAMResourceControl *This,DWORD dwFlags,PVOID pvReserved); - END_INTERFACE - } IAMResourceControlVtbl; - struct IAMResourceControl { - CONST_VTBL struct IAMResourceControlVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IAMResourceControl_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IAMResourceControl_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IAMResourceControl_Release(This) (This)->lpVtbl->Release(This) -#define IAMResourceControl_Reserve(This,dwFlags,pvReserved) (This)->lpVtbl->Reserve(This,dwFlags,pvReserved) -#endif -#endif - HRESULT WINAPI IAMResourceControl_Reserve_Proxy(IAMResourceControl *This,DWORD dwFlags,PVOID pvReserved); - void __RPC_STUB IAMResourceControl_Reserve_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IAMClockAdjust_INTERFACE_DEFINED__ -#define __IAMClockAdjust_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IAMClockAdjust; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IAMClockAdjust : public IUnknown { - public: - virtual HRESULT WINAPI SetClockDelta(REFERENCE_TIME rtDelta) = 0; - }; -#else - typedef struct IAMClockAdjustVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IAMClockAdjust *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IAMClockAdjust *This); - ULONG (WINAPI *Release)(IAMClockAdjust *This); - HRESULT (WINAPI *SetClockDelta)(IAMClockAdjust *This,REFERENCE_TIME rtDelta); - END_INTERFACE - } IAMClockAdjustVtbl; - struct IAMClockAdjust { - CONST_VTBL struct IAMClockAdjustVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IAMClockAdjust_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IAMClockAdjust_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IAMClockAdjust_Release(This) (This)->lpVtbl->Release(This) -#define IAMClockAdjust_SetClockDelta(This,rtDelta) (This)->lpVtbl->SetClockDelta(This,rtDelta) -#endif -#endif - HRESULT WINAPI IAMClockAdjust_SetClockDelta_Proxy(IAMClockAdjust *This,REFERENCE_TIME rtDelta); - void __RPC_STUB IAMClockAdjust_SetClockDelta_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - enum _AM_FILTER_MISC_FLAGS { - AM_FILTER_MISC_FLAGS_IS_RENDERER = 0x1,AM_FILTER_MISC_FLAGS_IS_SOURCE = 0x2 - }; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0348_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0348_v0_0_s_ifspec; -#ifndef __IAMFilterMiscFlags_INTERFACE_DEFINED__ -#define __IAMFilterMiscFlags_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IAMFilterMiscFlags; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IAMFilterMiscFlags : public IUnknown { - public: - virtual ULONG WINAPI GetMiscFlags(void) = 0; - }; -#else - typedef struct IAMFilterMiscFlagsVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IAMFilterMiscFlags *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IAMFilterMiscFlags *This); - ULONG (WINAPI *Release)(IAMFilterMiscFlags *This); - ULONG (WINAPI *GetMiscFlags)(IAMFilterMiscFlags *This); - END_INTERFACE - } IAMFilterMiscFlagsVtbl; - struct IAMFilterMiscFlags { - CONST_VTBL struct IAMFilterMiscFlagsVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IAMFilterMiscFlags_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IAMFilterMiscFlags_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IAMFilterMiscFlags_Release(This) (This)->lpVtbl->Release(This) -#define IAMFilterMiscFlags_GetMiscFlags(This) (This)->lpVtbl->GetMiscFlags(This) -#endif -#endif - ULONG WINAPI IAMFilterMiscFlags_GetMiscFlags_Proxy(IAMFilterMiscFlags *This); - void __RPC_STUB IAMFilterMiscFlags_GetMiscFlags_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IDrawVideoImage_INTERFACE_DEFINED__ -#define __IDrawVideoImage_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IDrawVideoImage; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IDrawVideoImage : public IUnknown { - public: - virtual HRESULT WINAPI DrawVideoImageBegin(void) = 0; - virtual HRESULT WINAPI DrawVideoImageEnd(void) = 0; - virtual HRESULT WINAPI DrawVideoImageDraw(HDC hdc,LPRECT lprcSrc,LPRECT lprcDst) = 0; - }; -#else - typedef struct IDrawVideoImageVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IDrawVideoImage *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IDrawVideoImage *This); - ULONG (WINAPI *Release)(IDrawVideoImage *This); - HRESULT (WINAPI *DrawVideoImageBegin)(IDrawVideoImage *This); - HRESULT (WINAPI *DrawVideoImageEnd)(IDrawVideoImage *This); - HRESULT (WINAPI *DrawVideoImageDraw)(IDrawVideoImage *This,HDC hdc,LPRECT lprcSrc,LPRECT lprcDst); - END_INTERFACE - } IDrawVideoImageVtbl; - struct IDrawVideoImage { - CONST_VTBL struct IDrawVideoImageVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IDrawVideoImage_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IDrawVideoImage_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IDrawVideoImage_Release(This) (This)->lpVtbl->Release(This) -#define IDrawVideoImage_DrawVideoImageBegin(This) (This)->lpVtbl->DrawVideoImageBegin(This) -#define IDrawVideoImage_DrawVideoImageEnd(This) (This)->lpVtbl->DrawVideoImageEnd(This) -#define IDrawVideoImage_DrawVideoImageDraw(This,hdc,lprcSrc,lprcDst) (This)->lpVtbl->DrawVideoImageDraw(This,hdc,lprcSrc,lprcDst) -#endif -#endif - HRESULT WINAPI IDrawVideoImage_DrawVideoImageBegin_Proxy(IDrawVideoImage *This); - void __RPC_STUB IDrawVideoImage_DrawVideoImageBegin_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDrawVideoImage_DrawVideoImageEnd_Proxy(IDrawVideoImage *This); - void __RPC_STUB IDrawVideoImage_DrawVideoImageEnd_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDrawVideoImage_DrawVideoImageDraw_Proxy(IDrawVideoImage *This,HDC hdc,LPRECT lprcSrc,LPRECT lprcDst); - void __RPC_STUB IDrawVideoImage_DrawVideoImageDraw_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IDecimateVideoImage_INTERFACE_DEFINED__ -#define __IDecimateVideoImage_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IDecimateVideoImage; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IDecimateVideoImage : public IUnknown { - public: - virtual HRESULT WINAPI SetDecimationImageSize(long lWidth,long lHeight) = 0; - virtual HRESULT WINAPI ResetDecimationImageSize(void) = 0; - }; -#else - typedef struct IDecimateVideoImageVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IDecimateVideoImage *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IDecimateVideoImage *This); - ULONG (WINAPI *Release)(IDecimateVideoImage *This); - HRESULT (WINAPI *SetDecimationImageSize)(IDecimateVideoImage *This,long lWidth,long lHeight); - HRESULT (WINAPI *ResetDecimationImageSize)(IDecimateVideoImage *This); - END_INTERFACE - } IDecimateVideoImageVtbl; - struct IDecimateVideoImage { - CONST_VTBL struct IDecimateVideoImageVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IDecimateVideoImage_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IDecimateVideoImage_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IDecimateVideoImage_Release(This) (This)->lpVtbl->Release(This) -#define IDecimateVideoImage_SetDecimationImageSize(This,lWidth,lHeight) (This)->lpVtbl->SetDecimationImageSize(This,lWidth,lHeight) -#define IDecimateVideoImage_ResetDecimationImageSize(This) (This)->lpVtbl->ResetDecimationImageSize(This) -#endif -#endif - HRESULT WINAPI IDecimateVideoImage_SetDecimationImageSize_Proxy(IDecimateVideoImage *This,long lWidth,long lHeight); - void __RPC_STUB IDecimateVideoImage_SetDecimationImageSize_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDecimateVideoImage_ResetDecimationImageSize_Proxy(IDecimateVideoImage *This); - void __RPC_STUB IDecimateVideoImage_ResetDecimationImageSize_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - typedef enum _DECIMATION_USAGE { - DECIMATION_LEGACY = 0, - DECIMATION_USE_DECODER_ONLY,DECIMATION_USE_VIDEOPORT_ONLY,DECIMATION_USE_OVERLAY_ONLY, - DECIMATION_DEFAULT - } DECIMATION_USAGE; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0351_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0351_v0_0_s_ifspec; -#ifndef __IAMVideoDecimationProperties_INTERFACE_DEFINED__ -#define __IAMVideoDecimationProperties_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IAMVideoDecimationProperties; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IAMVideoDecimationProperties : public IUnknown { - public: - virtual HRESULT WINAPI QueryDecimationUsage(DECIMATION_USAGE *lpUsage) = 0; - virtual HRESULT WINAPI SetDecimationUsage(DECIMATION_USAGE Usage) = 0; - }; -#else - typedef struct IAMVideoDecimationPropertiesVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IAMVideoDecimationProperties *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IAMVideoDecimationProperties *This); - ULONG (WINAPI *Release)(IAMVideoDecimationProperties *This); - HRESULT (WINAPI *QueryDecimationUsage)(IAMVideoDecimationProperties *This,DECIMATION_USAGE *lpUsage); - HRESULT (WINAPI *SetDecimationUsage)(IAMVideoDecimationProperties *This,DECIMATION_USAGE Usage); - END_INTERFACE - } IAMVideoDecimationPropertiesVtbl; - struct IAMVideoDecimationProperties { - CONST_VTBL struct IAMVideoDecimationPropertiesVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IAMVideoDecimationProperties_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IAMVideoDecimationProperties_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IAMVideoDecimationProperties_Release(This) (This)->lpVtbl->Release(This) -#define IAMVideoDecimationProperties_QueryDecimationUsage(This,lpUsage) (This)->lpVtbl->QueryDecimationUsage(This,lpUsage) -#define IAMVideoDecimationProperties_SetDecimationUsage(This,Usage) (This)->lpVtbl->SetDecimationUsage(This,Usage) -#endif -#endif - HRESULT WINAPI IAMVideoDecimationProperties_QueryDecimationUsage_Proxy(IAMVideoDecimationProperties *This,DECIMATION_USAGE *lpUsage); - void __RPC_STUB IAMVideoDecimationProperties_QueryDecimationUsage_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMVideoDecimationProperties_SetDecimationUsage_Proxy(IAMVideoDecimationProperties *This,DECIMATION_USAGE Usage); - void __RPC_STUB IAMVideoDecimationProperties_SetDecimationUsage_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IVideoFrameStep_INTERFACE_DEFINED__ -#define __IVideoFrameStep_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IVideoFrameStep; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IVideoFrameStep : public IUnknown { - public: - virtual HRESULT WINAPI Step(DWORD dwFrames,IUnknown *pStepObject) = 0; - virtual HRESULT WINAPI CanStep(long bMultiple,IUnknown *pStepObject) = 0; - virtual HRESULT WINAPI CancelStep(void) = 0; - }; -#else - typedef struct IVideoFrameStepVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IVideoFrameStep *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IVideoFrameStep *This); - ULONG (WINAPI *Release)(IVideoFrameStep *This); - HRESULT (WINAPI *Step)(IVideoFrameStep *This,DWORD dwFrames,IUnknown *pStepObject); - HRESULT (WINAPI *CanStep)(IVideoFrameStep *This,long bMultiple,IUnknown *pStepObject); - HRESULT (WINAPI *CancelStep)(IVideoFrameStep *This); - END_INTERFACE - } IVideoFrameStepVtbl; - struct IVideoFrameStep { - CONST_VTBL struct IVideoFrameStepVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IVideoFrameStep_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IVideoFrameStep_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IVideoFrameStep_Release(This) (This)->lpVtbl->Release(This) -#define IVideoFrameStep_Step(This,dwFrames,pStepObject) (This)->lpVtbl->Step(This,dwFrames,pStepObject) -#define IVideoFrameStep_CanStep(This,bMultiple,pStepObject) (This)->lpVtbl->CanStep(This,bMultiple,pStepObject) -#define IVideoFrameStep_CancelStep(This) (This)->lpVtbl->CancelStep(This) -#endif -#endif - HRESULT WINAPI IVideoFrameStep_Step_Proxy(IVideoFrameStep *This,DWORD dwFrames,IUnknown *pStepObject); - void __RPC_STUB IVideoFrameStep_Step_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVideoFrameStep_CanStep_Proxy(IVideoFrameStep *This,long bMultiple,IUnknown *pStepObject); - void __RPC_STUB IVideoFrameStep_CanStep_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVideoFrameStep_CancelStep_Proxy(IVideoFrameStep *This); - void __RPC_STUB IVideoFrameStep_CancelStep_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - enum _AM_PUSHSOURCE_FLAGS { - AM_PUSHSOURCECAPS_INTERNAL_RM = 0x1,AM_PUSHSOURCECAPS_NOT_LIVE = 0x2,AM_PUSHSOURCECAPS_PRIVATE_CLOCK = 0x4, - AM_PUSHSOURCEREQS_USE_STREAM_CLOCK = 0x10000,AM_PUSHSOURCEREQS_USE_CLOCK_CHAIN = 0x20000 - }; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0353_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0353_v0_0_s_ifspec; -#ifndef __IAMLatency_INTERFACE_DEFINED__ -#define __IAMLatency_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IAMLatency; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IAMLatency : public IUnknown { - public: - virtual HRESULT WINAPI GetLatency(REFERENCE_TIME *prtLatency) = 0; - }; -#else - typedef struct IAMLatencyVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IAMLatency *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IAMLatency *This); - ULONG (WINAPI *Release)(IAMLatency *This); - HRESULT (WINAPI *GetLatency)(IAMLatency *This,REFERENCE_TIME *prtLatency); - END_INTERFACE - } IAMLatencyVtbl; - struct IAMLatency { - CONST_VTBL struct IAMLatencyVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IAMLatency_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IAMLatency_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IAMLatency_Release(This) (This)->lpVtbl->Release(This) -#define IAMLatency_GetLatency(This,prtLatency) (This)->lpVtbl->GetLatency(This,prtLatency) -#endif -#endif - HRESULT WINAPI IAMLatency_GetLatency_Proxy(IAMLatency *This,REFERENCE_TIME *prtLatency); - void __RPC_STUB IAMLatency_GetLatency_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IAMPushSource_INTERFACE_DEFINED__ -#define __IAMPushSource_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IAMPushSource; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IAMPushSource : public IAMLatency { - public: - virtual HRESULT WINAPI GetPushSourceFlags(ULONG *pFlags) = 0; - virtual HRESULT WINAPI SetPushSourceFlags(ULONG Flags) = 0; - virtual HRESULT WINAPI SetStreamOffset(REFERENCE_TIME rtOffset) = 0; - virtual HRESULT WINAPI GetStreamOffset(REFERENCE_TIME *prtOffset) = 0; - virtual HRESULT WINAPI GetMaxStreamOffset(REFERENCE_TIME *prtMaxOffset) = 0; - virtual HRESULT WINAPI SetMaxStreamOffset(REFERENCE_TIME rtMaxOffset) = 0; - }; -#else - typedef struct IAMPushSourceVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IAMPushSource *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IAMPushSource *This); - ULONG (WINAPI *Release)(IAMPushSource *This); - HRESULT (WINAPI *GetLatency)(IAMPushSource *This,REFERENCE_TIME *prtLatency); - HRESULT (WINAPI *GetPushSourceFlags)(IAMPushSource *This,ULONG *pFlags); - HRESULT (WINAPI *SetPushSourceFlags)(IAMPushSource *This,ULONG Flags); - HRESULT (WINAPI *SetStreamOffset)(IAMPushSource *This,REFERENCE_TIME rtOffset); - HRESULT (WINAPI *GetStreamOffset)(IAMPushSource *This,REFERENCE_TIME *prtOffset); - HRESULT (WINAPI *GetMaxStreamOffset)(IAMPushSource *This,REFERENCE_TIME *prtMaxOffset); - HRESULT (WINAPI *SetMaxStreamOffset)(IAMPushSource *This,REFERENCE_TIME rtMaxOffset); - END_INTERFACE - } IAMPushSourceVtbl; - struct IAMPushSource { - CONST_VTBL struct IAMPushSourceVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IAMPushSource_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IAMPushSource_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IAMPushSource_Release(This) (This)->lpVtbl->Release(This) -#define IAMPushSource_GetLatency(This,prtLatency) (This)->lpVtbl->GetLatency(This,prtLatency) -#define IAMPushSource_GetPushSourceFlags(This,pFlags) (This)->lpVtbl->GetPushSourceFlags(This,pFlags) -#define IAMPushSource_SetPushSourceFlags(This,Flags) (This)->lpVtbl->SetPushSourceFlags(This,Flags) -#define IAMPushSource_SetStreamOffset(This,rtOffset) (This)->lpVtbl->SetStreamOffset(This,rtOffset) -#define IAMPushSource_GetStreamOffset(This,prtOffset) (This)->lpVtbl->GetStreamOffset(This,prtOffset) -#define IAMPushSource_GetMaxStreamOffset(This,prtMaxOffset) (This)->lpVtbl->GetMaxStreamOffset(This,prtMaxOffset) -#define IAMPushSource_SetMaxStreamOffset(This,rtMaxOffset) (This)->lpVtbl->SetMaxStreamOffset(This,rtMaxOffset) -#endif -#endif - HRESULT WINAPI IAMPushSource_GetPushSourceFlags_Proxy(IAMPushSource *This,ULONG *pFlags); - void __RPC_STUB IAMPushSource_GetPushSourceFlags_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMPushSource_SetPushSourceFlags_Proxy(IAMPushSource *This,ULONG Flags); - void __RPC_STUB IAMPushSource_SetPushSourceFlags_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMPushSource_SetStreamOffset_Proxy(IAMPushSource *This,REFERENCE_TIME rtOffset); - void __RPC_STUB IAMPushSource_SetStreamOffset_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMPushSource_GetStreamOffset_Proxy(IAMPushSource *This,REFERENCE_TIME *prtOffset); - void __RPC_STUB IAMPushSource_GetStreamOffset_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMPushSource_GetMaxStreamOffset_Proxy(IAMPushSource *This,REFERENCE_TIME *prtMaxOffset); - void __RPC_STUB IAMPushSource_GetMaxStreamOffset_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMPushSource_SetMaxStreamOffset_Proxy(IAMPushSource *This,REFERENCE_TIME rtMaxOffset); - void __RPC_STUB IAMPushSource_SetMaxStreamOffset_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IAMDeviceRemoval_INTERFACE_DEFINED__ -#define __IAMDeviceRemoval_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IAMDeviceRemoval; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IAMDeviceRemoval : public IUnknown { - public: - virtual HRESULT WINAPI DeviceInfo(CLSID *pclsidInterfaceClass,WCHAR **pwszSymbolicLink) = 0; - virtual HRESULT WINAPI Reassociate(void) = 0; - virtual HRESULT WINAPI Disassociate(void) = 0; - }; -#else - typedef struct IAMDeviceRemovalVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IAMDeviceRemoval *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IAMDeviceRemoval *This); - ULONG (WINAPI *Release)(IAMDeviceRemoval *This); - HRESULT (WINAPI *DeviceInfo)(IAMDeviceRemoval *This,CLSID *pclsidInterfaceClass,WCHAR **pwszSymbolicLink); - HRESULT (WINAPI *Reassociate)(IAMDeviceRemoval *This); - HRESULT (WINAPI *Disassociate)(IAMDeviceRemoval *This); - END_INTERFACE - } IAMDeviceRemovalVtbl; - struct IAMDeviceRemoval { - CONST_VTBL struct IAMDeviceRemovalVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IAMDeviceRemoval_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IAMDeviceRemoval_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IAMDeviceRemoval_Release(This) (This)->lpVtbl->Release(This) -#define IAMDeviceRemoval_DeviceInfo(This,pclsidInterfaceClass,pwszSymbolicLink) (This)->lpVtbl->DeviceInfo(This,pclsidInterfaceClass,pwszSymbolicLink) -#define IAMDeviceRemoval_Reassociate(This) (This)->lpVtbl->Reassociate(This) -#define IAMDeviceRemoval_Disassociate(This) (This)->lpVtbl->Disassociate(This) -#endif -#endif - HRESULT WINAPI IAMDeviceRemoval_DeviceInfo_Proxy(IAMDeviceRemoval *This,CLSID *pclsidInterfaceClass,WCHAR **pwszSymbolicLink); - void __RPC_STUB IAMDeviceRemoval_DeviceInfo_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMDeviceRemoval_Reassociate_Proxy(IAMDeviceRemoval *This); - void __RPC_STUB IAMDeviceRemoval_Reassociate_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMDeviceRemoval_Disassociate_Proxy(IAMDeviceRemoval *This); - void __RPC_STUB IAMDeviceRemoval_Disassociate_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - typedef struct __MIDL___MIDL_itf_strmif_0355_0001 { - DWORD dwDVAAuxSrc; - DWORD dwDVAAuxCtl; - DWORD dwDVAAuxSrc1; - DWORD dwDVAAuxCtl1; - DWORD dwDVVAuxSrc; - DWORD dwDVVAuxCtl; - DWORD dwDVReserved[2]; - } DVINFO; - - typedef struct __MIDL___MIDL_itf_strmif_0355_0001 *PDVINFO; - - enum _DVENCODERRESOLUTION { - DVENCODERRESOLUTION_720x480 = 2012,DVENCODERRESOLUTION_360x240 = 2013,DVENCODERRESOLUTION_180x120 = 2014,DVENCODERRESOLUTION_88x60 = 2015 - }; - - enum _DVENCODERVIDEOFORMAT { - DVENCODERVIDEOFORMAT_NTSC = 2000,DVENCODERVIDEOFORMAT_PAL = 2001 - }; - - enum _DVENCODERFORMAT { - DVENCODERFORMAT_DVSD = 2007,DVENCODERFORMAT_DVHD = 2008,DVENCODERFORMAT_DVSL = 2009 - }; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0355_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0355_v0_0_s_ifspec; -#ifndef __IDVEnc_INTERFACE_DEFINED__ -#define __IDVEnc_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IDVEnc; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IDVEnc : public IUnknown { - public: - virtual HRESULT WINAPI get_IFormatResolution(int *VideoFormat,int *DVFormat,int *Resolution,BYTE fDVInfo,DVINFO *sDVInfo) = 0; - virtual HRESULT WINAPI put_IFormatResolution(int VideoFormat,int DVFormat,int Resolution,BYTE fDVInfo,DVINFO *sDVInfo) = 0; - }; -#else - typedef struct IDVEncVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IDVEnc *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IDVEnc *This); - ULONG (WINAPI *Release)(IDVEnc *This); - HRESULT (WINAPI *get_IFormatResolution)(IDVEnc *This,int *VideoFormat,int *DVFormat,int *Resolution,BYTE fDVInfo,DVINFO *sDVInfo); - HRESULT (WINAPI *put_IFormatResolution)(IDVEnc *This,int VideoFormat,int DVFormat,int Resolution,BYTE fDVInfo,DVINFO *sDVInfo); - END_INTERFACE - } IDVEncVtbl; - struct IDVEnc { - CONST_VTBL struct IDVEncVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IDVEnc_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IDVEnc_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IDVEnc_Release(This) (This)->lpVtbl->Release(This) -#define IDVEnc_get_IFormatResolution(This,VideoFormat,DVFormat,Resolution,fDVInfo,sDVInfo) (This)->lpVtbl->get_IFormatResolution(This,VideoFormat,DVFormat,Resolution,fDVInfo,sDVInfo) -#define IDVEnc_put_IFormatResolution(This,VideoFormat,DVFormat,Resolution,fDVInfo,sDVInfo) (This)->lpVtbl->put_IFormatResolution(This,VideoFormat,DVFormat,Resolution,fDVInfo,sDVInfo) -#endif -#endif - HRESULT WINAPI IDVEnc_get_IFormatResolution_Proxy(IDVEnc *This,int *VideoFormat,int *DVFormat,int *Resolution,BYTE fDVInfo,DVINFO *sDVInfo); - void __RPC_STUB IDVEnc_get_IFormatResolution_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDVEnc_put_IFormatResolution_Proxy(IDVEnc *This,int VideoFormat,int DVFormat,int Resolution,BYTE fDVInfo,DVINFO *sDVInfo); - void __RPC_STUB IDVEnc_put_IFormatResolution_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - enum _DVDECODERRESOLUTION { - DVDECODERRESOLUTION_720x480 = 1000,DVDECODERRESOLUTION_360x240 = 1001,DVDECODERRESOLUTION_180x120 = 1002,DVDECODERRESOLUTION_88x60 = 1003 - }; - - enum _DVRESOLUTION { - DVRESOLUTION_FULL = 1000,DVRESOLUTION_HALF = 1001,DVRESOLUTION_QUARTER = 1002,DVRESOLUTION_DC = 1003 - }; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0356_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0356_v0_0_s_ifspec; -#ifndef __IIPDVDec_INTERFACE_DEFINED__ -#define __IIPDVDec_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IIPDVDec; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IIPDVDec : public IUnknown { - public: - virtual HRESULT WINAPI get_IPDisplay(int *displayPix) = 0; - virtual HRESULT WINAPI put_IPDisplay(int displayPix) = 0; - }; -#else - typedef struct IIPDVDecVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IIPDVDec *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IIPDVDec *This); - ULONG (WINAPI *Release)(IIPDVDec *This); - HRESULT (WINAPI *get_IPDisplay)(IIPDVDec *This,int *displayPix); - HRESULT (WINAPI *put_IPDisplay)(IIPDVDec *This,int displayPix); - END_INTERFACE - } IIPDVDecVtbl; - struct IIPDVDec { - CONST_VTBL struct IIPDVDecVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IIPDVDec_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IIPDVDec_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IIPDVDec_Release(This) (This)->lpVtbl->Release(This) -#define IIPDVDec_get_IPDisplay(This,displayPix) (This)->lpVtbl->get_IPDisplay(This,displayPix) -#define IIPDVDec_put_IPDisplay(This,displayPix) (This)->lpVtbl->put_IPDisplay(This,displayPix) -#endif -#endif - HRESULT WINAPI IIPDVDec_get_IPDisplay_Proxy(IIPDVDec *This,int *displayPix); - void __RPC_STUB IIPDVDec_get_IPDisplay_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IIPDVDec_put_IPDisplay_Proxy(IIPDVDec *This,int displayPix); - void __RPC_STUB IIPDVDec_put_IPDisplay_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IDVRGB219_INTERFACE_DEFINED__ -#define __IDVRGB219_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IDVRGB219; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IDVRGB219 : public IUnknown { - public: - virtual HRESULT WINAPI SetRGB219(WINBOOL bState) = 0; - }; -#else - typedef struct IDVRGB219Vtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IDVRGB219 *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IDVRGB219 *This); - ULONG (WINAPI *Release)(IDVRGB219 *This); - HRESULT (WINAPI *SetRGB219)(IDVRGB219 *This,WINBOOL bState); - END_INTERFACE - } IDVRGB219Vtbl; - struct IDVRGB219 { - CONST_VTBL struct IDVRGB219Vtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IDVRGB219_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IDVRGB219_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IDVRGB219_Release(This) (This)->lpVtbl->Release(This) -#define IDVRGB219_SetRGB219(This,bState) (This)->lpVtbl->SetRGB219(This,bState) -#endif -#endif - HRESULT WINAPI IDVRGB219_SetRGB219_Proxy(IDVRGB219 *This,WINBOOL bState); - void __RPC_STUB IDVRGB219_SetRGB219_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IDVSplitter_INTERFACE_DEFINED__ -#define __IDVSplitter_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IDVSplitter; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IDVSplitter : public IUnknown { - public: - virtual HRESULT WINAPI DiscardAlternateVideoFrames(int nDiscard) = 0; - }; -#else - typedef struct IDVSplitterVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IDVSplitter *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IDVSplitter *This); - ULONG (WINAPI *Release)(IDVSplitter *This); - HRESULT (WINAPI *DiscardAlternateVideoFrames)(IDVSplitter *This,int nDiscard); - END_INTERFACE - } IDVSplitterVtbl; - struct IDVSplitter { - CONST_VTBL struct IDVSplitterVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IDVSplitter_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IDVSplitter_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IDVSplitter_Release(This) (This)->lpVtbl->Release(This) -#define IDVSplitter_DiscardAlternateVideoFrames(This,nDiscard) (This)->lpVtbl->DiscardAlternateVideoFrames(This,nDiscard) -#endif -#endif - HRESULT WINAPI IDVSplitter_DiscardAlternateVideoFrames_Proxy(IDVSplitter *This,int nDiscard); - void __RPC_STUB IDVSplitter_DiscardAlternateVideoFrames_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - enum _AM_AUDIO_RENDERER_STAT_PARAM { - AM_AUDREND_STAT_PARAM_BREAK_COUNT = 1, - AM_AUDREND_STAT_PARAM_SLAVE_MODE,AM_AUDREND_STAT_PARAM_SILENCE_DUR, - AM_AUDREND_STAT_PARAM_LAST_BUFFER_DUR,AM_AUDREND_STAT_PARAM_DISCONTINUITIES, - AM_AUDREND_STAT_PARAM_SLAVE_RATE,AM_AUDREND_STAT_PARAM_SLAVE_DROPWRITE_DUR, - AM_AUDREND_STAT_PARAM_SLAVE_HIGHLOWERROR,AM_AUDREND_STAT_PARAM_SLAVE_LASTHIGHLOWERROR, - AM_AUDREND_STAT_PARAM_SLAVE_ACCUMERROR,AM_AUDREND_STAT_PARAM_BUFFERFULLNESS, - AM_AUDREND_STAT_PARAM_JITTER - }; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0359_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0359_v0_0_s_ifspec; -#ifndef __IAMAudioRendererStats_INTERFACE_DEFINED__ -#define __IAMAudioRendererStats_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IAMAudioRendererStats; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IAMAudioRendererStats : public IUnknown { - public: - virtual HRESULT WINAPI GetStatParam(DWORD dwParam,DWORD *pdwParam1,DWORD *pdwParam2) = 0; - }; -#else - typedef struct IAMAudioRendererStatsVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IAMAudioRendererStats *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IAMAudioRendererStats *This); - ULONG (WINAPI *Release)(IAMAudioRendererStats *This); - HRESULT (WINAPI *GetStatParam)(IAMAudioRendererStats *This,DWORD dwParam,DWORD *pdwParam1,DWORD *pdwParam2); - END_INTERFACE - } IAMAudioRendererStatsVtbl; - struct IAMAudioRendererStats { - CONST_VTBL struct IAMAudioRendererStatsVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IAMAudioRendererStats_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IAMAudioRendererStats_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IAMAudioRendererStats_Release(This) (This)->lpVtbl->Release(This) -#define IAMAudioRendererStats_GetStatParam(This,dwParam,pdwParam1,pdwParam2) (This)->lpVtbl->GetStatParam(This,dwParam,pdwParam1,pdwParam2) -#endif -#endif - HRESULT WINAPI IAMAudioRendererStats_GetStatParam_Proxy(IAMAudioRendererStats *This,DWORD dwParam,DWORD *pdwParam1,DWORD *pdwParam2); - void __RPC_STUB IAMAudioRendererStats_GetStatParam_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - enum _AM_INTF_SEARCH_FLAGS { - AM_INTF_SEARCH_INPUT_PIN = 0x1,AM_INTF_SEARCH_OUTPUT_PIN = 0x2,AM_INTF_SEARCH_FILTER = 0x4 - }; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0361_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0361_v0_0_s_ifspec; -#ifndef __IAMGraphStreams_INTERFACE_DEFINED__ -#define __IAMGraphStreams_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IAMGraphStreams; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IAMGraphStreams : public IUnknown { - public: - virtual HRESULT WINAPI FindUpstreamInterface(IPin *pPin,REFIID riid,void **ppvInterface,DWORD dwFlags) = 0; - virtual HRESULT WINAPI SyncUsingStreamOffset(WINBOOL bUseStreamOffset) = 0; - virtual HRESULT WINAPI SetMaxGraphLatency(REFERENCE_TIME rtMaxGraphLatency) = 0; - }; -#else - typedef struct IAMGraphStreamsVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IAMGraphStreams *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IAMGraphStreams *This); - ULONG (WINAPI *Release)(IAMGraphStreams *This); - HRESULT (WINAPI *FindUpstreamInterface)(IAMGraphStreams *This,IPin *pPin,REFIID riid,void **ppvInterface,DWORD dwFlags); - HRESULT (WINAPI *SyncUsingStreamOffset)(IAMGraphStreams *This,WINBOOL bUseStreamOffset); - HRESULT (WINAPI *SetMaxGraphLatency)(IAMGraphStreams *This,REFERENCE_TIME rtMaxGraphLatency); - END_INTERFACE - } IAMGraphStreamsVtbl; - struct IAMGraphStreams { - CONST_VTBL struct IAMGraphStreamsVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IAMGraphStreams_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IAMGraphStreams_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IAMGraphStreams_Release(This) (This)->lpVtbl->Release(This) -#define IAMGraphStreams_FindUpstreamInterface(This,pPin,riid,ppvInterface,dwFlags) (This)->lpVtbl->FindUpstreamInterface(This,pPin,riid,ppvInterface,dwFlags) -#define IAMGraphStreams_SyncUsingStreamOffset(This,bUseStreamOffset) (This)->lpVtbl->SyncUsingStreamOffset(This,bUseStreamOffset) -#define IAMGraphStreams_SetMaxGraphLatency(This,rtMaxGraphLatency) (This)->lpVtbl->SetMaxGraphLatency(This,rtMaxGraphLatency) -#endif -#endif - HRESULT WINAPI IAMGraphStreams_FindUpstreamInterface_Proxy(IAMGraphStreams *This,IPin *pPin,REFIID riid,void **ppvInterface,DWORD dwFlags); - void __RPC_STUB IAMGraphStreams_FindUpstreamInterface_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMGraphStreams_SyncUsingStreamOffset_Proxy(IAMGraphStreams *This,WINBOOL bUseStreamOffset); - void __RPC_STUB IAMGraphStreams_SyncUsingStreamOffset_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMGraphStreams_SetMaxGraphLatency_Proxy(IAMGraphStreams *This,REFERENCE_TIME rtMaxGraphLatency); - void __RPC_STUB IAMGraphStreams_SetMaxGraphLatency_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - enum AMOVERLAYFX { - AMOVERFX_NOFX = 0,AMOVERFX_MIRRORLEFTRIGHT = 0x2,AMOVERFX_MIRRORUPDOWN = 0x4,AMOVERFX_DEINTERLACE = 0x8 - }; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0362_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0362_v0_0_s_ifspec; -#ifndef __IAMOverlayFX_INTERFACE_DEFINED__ -#define __IAMOverlayFX_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IAMOverlayFX; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IAMOverlayFX : public IUnknown { - public: - virtual HRESULT WINAPI QueryOverlayFXCaps(DWORD *lpdwOverlayFXCaps) = 0; - virtual HRESULT WINAPI SetOverlayFX(DWORD dwOverlayFX) = 0; - virtual HRESULT WINAPI GetOverlayFX(DWORD *lpdwOverlayFX) = 0; - }; -#else - typedef struct IAMOverlayFXVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IAMOverlayFX *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IAMOverlayFX *This); - ULONG (WINAPI *Release)(IAMOverlayFX *This); - HRESULT (WINAPI *QueryOverlayFXCaps)(IAMOverlayFX *This,DWORD *lpdwOverlayFXCaps); - HRESULT (WINAPI *SetOverlayFX)(IAMOverlayFX *This,DWORD dwOverlayFX); - HRESULT (WINAPI *GetOverlayFX)(IAMOverlayFX *This,DWORD *lpdwOverlayFX); - END_INTERFACE - } IAMOverlayFXVtbl; - struct IAMOverlayFX { - CONST_VTBL struct IAMOverlayFXVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IAMOverlayFX_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IAMOverlayFX_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IAMOverlayFX_Release(This) (This)->lpVtbl->Release(This) -#define IAMOverlayFX_QueryOverlayFXCaps(This,lpdwOverlayFXCaps) (This)->lpVtbl->QueryOverlayFXCaps(This,lpdwOverlayFXCaps) -#define IAMOverlayFX_SetOverlayFX(This,dwOverlayFX) (This)->lpVtbl->SetOverlayFX(This,dwOverlayFX) -#define IAMOverlayFX_GetOverlayFX(This,lpdwOverlayFX) (This)->lpVtbl->GetOverlayFX(This,lpdwOverlayFX) -#endif -#endif - HRESULT WINAPI IAMOverlayFX_QueryOverlayFXCaps_Proxy(IAMOverlayFX *This,DWORD *lpdwOverlayFXCaps); - void __RPC_STUB IAMOverlayFX_QueryOverlayFXCaps_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMOverlayFX_SetOverlayFX_Proxy(IAMOverlayFX *This,DWORD dwOverlayFX); - void __RPC_STUB IAMOverlayFX_SetOverlayFX_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMOverlayFX_GetOverlayFX_Proxy(IAMOverlayFX *This,DWORD *lpdwOverlayFX); - void __RPC_STUB IAMOverlayFX_GetOverlayFX_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IAMOpenProgress_INTERFACE_DEFINED__ -#define __IAMOpenProgress_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IAMOpenProgress; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IAMOpenProgress : public IUnknown { - public: - virtual HRESULT WINAPI QueryProgress(LONGLONG *pllTotal,LONGLONG *pllCurrent) = 0; - virtual HRESULT WINAPI AbortOperation(void) = 0; - }; -#else - typedef struct IAMOpenProgressVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IAMOpenProgress *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IAMOpenProgress *This); - ULONG (WINAPI *Release)(IAMOpenProgress *This); - HRESULT (WINAPI *QueryProgress)(IAMOpenProgress *This,LONGLONG *pllTotal,LONGLONG *pllCurrent); - HRESULT (WINAPI *AbortOperation)(IAMOpenProgress *This); - END_INTERFACE - } IAMOpenProgressVtbl; - struct IAMOpenProgress { - CONST_VTBL struct IAMOpenProgressVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IAMOpenProgress_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IAMOpenProgress_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IAMOpenProgress_Release(This) (This)->lpVtbl->Release(This) -#define IAMOpenProgress_QueryProgress(This,pllTotal,pllCurrent) (This)->lpVtbl->QueryProgress(This,pllTotal,pllCurrent) -#define IAMOpenProgress_AbortOperation(This) (This)->lpVtbl->AbortOperation(This) -#endif -#endif - HRESULT WINAPI IAMOpenProgress_QueryProgress_Proxy(IAMOpenProgress *This,LONGLONG *pllTotal,LONGLONG *pllCurrent); - void __RPC_STUB IAMOpenProgress_QueryProgress_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMOpenProgress_AbortOperation_Proxy(IAMOpenProgress *This); - void __RPC_STUB IAMOpenProgress_AbortOperation_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IMpeg2Demultiplexer_INTERFACE_DEFINED__ -#define __IMpeg2Demultiplexer_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IMpeg2Demultiplexer; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IMpeg2Demultiplexer : public IUnknown { - public: - virtual HRESULT WINAPI CreateOutputPin(AM_MEDIA_TYPE *pMediaType,LPWSTR pszPinName,IPin **ppIPin) = 0; - virtual HRESULT WINAPI SetOutputPinMediaType(LPWSTR pszPinName,AM_MEDIA_TYPE *pMediaType) = 0; - virtual HRESULT WINAPI DeleteOutputPin(LPWSTR pszPinName) = 0; - }; -#else - typedef struct IMpeg2DemultiplexerVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IMpeg2Demultiplexer *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IMpeg2Demultiplexer *This); - ULONG (WINAPI *Release)(IMpeg2Demultiplexer *This); - HRESULT (WINAPI *CreateOutputPin)(IMpeg2Demultiplexer *This,AM_MEDIA_TYPE *pMediaType,LPWSTR pszPinName,IPin **ppIPin); - HRESULT (WINAPI *SetOutputPinMediaType)(IMpeg2Demultiplexer *This,LPWSTR pszPinName,AM_MEDIA_TYPE *pMediaType); - HRESULT (WINAPI *DeleteOutputPin)(IMpeg2Demultiplexer *This,LPWSTR pszPinName); - END_INTERFACE - } IMpeg2DemultiplexerVtbl; - struct IMpeg2Demultiplexer { - CONST_VTBL struct IMpeg2DemultiplexerVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IMpeg2Demultiplexer_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IMpeg2Demultiplexer_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IMpeg2Demultiplexer_Release(This) (This)->lpVtbl->Release(This) -#define IMpeg2Demultiplexer_CreateOutputPin(This,pMediaType,pszPinName,ppIPin) (This)->lpVtbl->CreateOutputPin(This,pMediaType,pszPinName,ppIPin) -#define IMpeg2Demultiplexer_SetOutputPinMediaType(This,pszPinName,pMediaType) (This)->lpVtbl->SetOutputPinMediaType(This,pszPinName,pMediaType) -#define IMpeg2Demultiplexer_DeleteOutputPin(This,pszPinName) (This)->lpVtbl->DeleteOutputPin(This,pszPinName) -#endif -#endif - HRESULT WINAPI IMpeg2Demultiplexer_CreateOutputPin_Proxy(IMpeg2Demultiplexer *This,AM_MEDIA_TYPE *pMediaType,LPWSTR pszPinName,IPin **ppIPin); - void __RPC_STUB IMpeg2Demultiplexer_CreateOutputPin_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMpeg2Demultiplexer_SetOutputPinMediaType_Proxy(IMpeg2Demultiplexer *This,LPWSTR pszPinName,AM_MEDIA_TYPE *pMediaType); - void __RPC_STUB IMpeg2Demultiplexer_SetOutputPinMediaType_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMpeg2Demultiplexer_DeleteOutputPin_Proxy(IMpeg2Demultiplexer *This,LPWSTR pszPinName); - void __RPC_STUB IMpeg2Demultiplexer_DeleteOutputPin_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#define MPEG2_PROGRAM_STREAM_MAP 0x00000000 -#define MPEG2_PROGRAM_ELEMENTARY_STREAM 0x00000001 -#define MPEG2_PROGRAM_DIRECTORY_PES_PACKET 0x00000002 -#define MPEG2_PROGRAM_PACK_HEADER 0x00000003 -#define MPEG2_PROGRAM_PES_STREAM 0x00000004 -#define MPEG2_PROGRAM_SYSTEM_HEADER 0x00000005 -#define SUBSTREAM_FILTER_VAL_NONE 0x10000000 - - typedef struct __MIDL___MIDL_itf_strmif_0365_0001 { - ULONG stream_id; - DWORD dwMediaSampleContent; - ULONG ulSubstreamFilterValue; - int iDataOffset; - } STREAM_ID_MAP; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0365_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0365_v0_0_s_ifspec; -#ifndef __IEnumStreamIdMap_INTERFACE_DEFINED__ -#define __IEnumStreamIdMap_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IEnumStreamIdMap; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IEnumStreamIdMap : public IUnknown { - public: - virtual HRESULT WINAPI Next(ULONG cRequest,STREAM_ID_MAP *pStreamIdMap,ULONG *pcReceived) = 0; - virtual HRESULT WINAPI Skip(ULONG cRecords) = 0; - virtual HRESULT WINAPI Reset(void) = 0; - virtual HRESULT WINAPI Clone(IEnumStreamIdMap **ppIEnumStreamIdMap) = 0; - }; -#else - typedef struct IEnumStreamIdMapVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IEnumStreamIdMap *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IEnumStreamIdMap *This); - ULONG (WINAPI *Release)(IEnumStreamIdMap *This); - HRESULT (WINAPI *Next)(IEnumStreamIdMap *This,ULONG cRequest,STREAM_ID_MAP *pStreamIdMap,ULONG *pcReceived); - HRESULT (WINAPI *Skip)(IEnumStreamIdMap *This,ULONG cRecords); - HRESULT (WINAPI *Reset)(IEnumStreamIdMap *This); - HRESULT (WINAPI *Clone)(IEnumStreamIdMap *This,IEnumStreamIdMap **ppIEnumStreamIdMap); - END_INTERFACE - } IEnumStreamIdMapVtbl; - struct IEnumStreamIdMap { - CONST_VTBL struct IEnumStreamIdMapVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IEnumStreamIdMap_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IEnumStreamIdMap_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IEnumStreamIdMap_Release(This) (This)->lpVtbl->Release(This) -#define IEnumStreamIdMap_Next(This,cRequest,pStreamIdMap,pcReceived) (This)->lpVtbl->Next(This,cRequest,pStreamIdMap,pcReceived) -#define IEnumStreamIdMap_Skip(This,cRecords) (This)->lpVtbl->Skip(This,cRecords) -#define IEnumStreamIdMap_Reset(This) (This)->lpVtbl->Reset(This) -#define IEnumStreamIdMap_Clone(This,ppIEnumStreamIdMap) (This)->lpVtbl->Clone(This,ppIEnumStreamIdMap) -#endif -#endif - HRESULT WINAPI IEnumStreamIdMap_Next_Proxy(IEnumStreamIdMap *This,ULONG cRequest,STREAM_ID_MAP *pStreamIdMap,ULONG *pcReceived); - void __RPC_STUB IEnumStreamIdMap_Next_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IEnumStreamIdMap_Skip_Proxy(IEnumStreamIdMap *This,ULONG cRecords); - void __RPC_STUB IEnumStreamIdMap_Skip_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IEnumStreamIdMap_Reset_Proxy(IEnumStreamIdMap *This); - void __RPC_STUB IEnumStreamIdMap_Reset_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IEnumStreamIdMap_Clone_Proxy(IEnumStreamIdMap *This,IEnumStreamIdMap **ppIEnumStreamIdMap); - void __RPC_STUB IEnumStreamIdMap_Clone_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IMPEG2StreamIdMap_INTERFACE_DEFINED__ -#define __IMPEG2StreamIdMap_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IMPEG2StreamIdMap; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IMPEG2StreamIdMap : public IUnknown { - public: - virtual HRESULT WINAPI MapStreamId(ULONG ulStreamId,DWORD MediaSampleContent,ULONG ulSubstreamFilterValue,int iDataOffset) = 0; - virtual HRESULT WINAPI UnmapStreamId(ULONG culStreamId,ULONG *pulStreamId) = 0; - virtual HRESULT WINAPI EnumStreamIdMap(IEnumStreamIdMap **ppIEnumStreamIdMap) = 0; - }; -#else - typedef struct IMPEG2StreamIdMapVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IMPEG2StreamIdMap *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IMPEG2StreamIdMap *This); - ULONG (WINAPI *Release)(IMPEG2StreamIdMap *This); - HRESULT (WINAPI *MapStreamId)(IMPEG2StreamIdMap *This,ULONG ulStreamId,DWORD MediaSampleContent,ULONG ulSubstreamFilterValue,int iDataOffset); - HRESULT (WINAPI *UnmapStreamId)(IMPEG2StreamIdMap *This,ULONG culStreamId,ULONG *pulStreamId); - HRESULT (WINAPI *EnumStreamIdMap)(IMPEG2StreamIdMap *This,IEnumStreamIdMap **ppIEnumStreamIdMap); - END_INTERFACE - } IMPEG2StreamIdMapVtbl; - struct IMPEG2StreamIdMap { - CONST_VTBL struct IMPEG2StreamIdMapVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IMPEG2StreamIdMap_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IMPEG2StreamIdMap_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IMPEG2StreamIdMap_Release(This) (This)->lpVtbl->Release(This) -#define IMPEG2StreamIdMap_MapStreamId(This,ulStreamId,MediaSampleContent,ulSubstreamFilterValue,iDataOffset) (This)->lpVtbl->MapStreamId(This,ulStreamId,MediaSampleContent,ulSubstreamFilterValue,iDataOffset) -#define IMPEG2StreamIdMap_UnmapStreamId(This,culStreamId,pulStreamId) (This)->lpVtbl->UnmapStreamId(This,culStreamId,pulStreamId) -#define IMPEG2StreamIdMap_EnumStreamIdMap(This,ppIEnumStreamIdMap) (This)->lpVtbl->EnumStreamIdMap(This,ppIEnumStreamIdMap) -#endif -#endif - HRESULT WINAPI IMPEG2StreamIdMap_MapStreamId_Proxy(IMPEG2StreamIdMap *This,ULONG ulStreamId,DWORD MediaSampleContent,ULONG ulSubstreamFilterValue,int iDataOffset); - void __RPC_STUB IMPEG2StreamIdMap_MapStreamId_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMPEG2StreamIdMap_UnmapStreamId_Proxy(IMPEG2StreamIdMap *This,ULONG culStreamId,ULONG *pulStreamId); - void __RPC_STUB IMPEG2StreamIdMap_UnmapStreamId_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IMPEG2StreamIdMap_EnumStreamIdMap_Proxy(IMPEG2StreamIdMap *This,IEnumStreamIdMap **ppIEnumStreamIdMap); - void __RPC_STUB IMPEG2StreamIdMap_EnumStreamIdMap_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IRegisterServiceProvider_INTERFACE_DEFINED__ -#define __IRegisterServiceProvider_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IRegisterServiceProvider; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IRegisterServiceProvider : public IUnknown { - public: - virtual HRESULT WINAPI RegisterService(REFGUID guidService,IUnknown *pUnkObject) = 0; - }; -#else - typedef struct IRegisterServiceProviderVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IRegisterServiceProvider *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IRegisterServiceProvider *This); - ULONG (WINAPI *Release)(IRegisterServiceProvider *This); - HRESULT (WINAPI *RegisterService)(IRegisterServiceProvider *This,REFGUID guidService,IUnknown *pUnkObject); - END_INTERFACE - } IRegisterServiceProviderVtbl; - struct IRegisterServiceProvider { - CONST_VTBL struct IRegisterServiceProviderVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IRegisterServiceProvider_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IRegisterServiceProvider_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IRegisterServiceProvider_Release(This) (This)->lpVtbl->Release(This) -#define IRegisterServiceProvider_RegisterService(This,guidService,pUnkObject) (This)->lpVtbl->RegisterService(This,guidService,pUnkObject) -#endif -#endif - HRESULT WINAPI IRegisterServiceProvider_RegisterService_Proxy(IRegisterServiceProvider *This,REFGUID guidService,IUnknown *pUnkObject); - void __RPC_STUB IRegisterServiceProvider_RegisterService_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IAMClockSlave_INTERFACE_DEFINED__ -#define __IAMClockSlave_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IAMClockSlave; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IAMClockSlave : public IUnknown { - public: - virtual HRESULT WINAPI SetErrorTolerance(DWORD dwTolerance) = 0; - virtual HRESULT WINAPI GetErrorTolerance(DWORD *pdwTolerance) = 0; - }; -#else - typedef struct IAMClockSlaveVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IAMClockSlave *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IAMClockSlave *This); - ULONG (WINAPI *Release)(IAMClockSlave *This); - HRESULT (WINAPI *SetErrorTolerance)(IAMClockSlave *This,DWORD dwTolerance); - HRESULT (WINAPI *GetErrorTolerance)(IAMClockSlave *This,DWORD *pdwTolerance); - END_INTERFACE - } IAMClockSlaveVtbl; - struct IAMClockSlave { - CONST_VTBL struct IAMClockSlaveVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IAMClockSlave_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IAMClockSlave_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IAMClockSlave_Release(This) (This)->lpVtbl->Release(This) -#define IAMClockSlave_SetErrorTolerance(This,dwTolerance) (This)->lpVtbl->SetErrorTolerance(This,dwTolerance) -#define IAMClockSlave_GetErrorTolerance(This,pdwTolerance) (This)->lpVtbl->GetErrorTolerance(This,pdwTolerance) -#endif -#endif - HRESULT WINAPI IAMClockSlave_SetErrorTolerance_Proxy(IAMClockSlave *This,DWORD dwTolerance); - void __RPC_STUB IAMClockSlave_SetErrorTolerance_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMClockSlave_GetErrorTolerance_Proxy(IAMClockSlave *This,DWORD *pdwTolerance); - void __RPC_STUB IAMClockSlave_GetErrorTolerance_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IAMGraphBuilderCallback_INTERFACE_DEFINED__ -#define __IAMGraphBuilderCallback_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IAMGraphBuilderCallback; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IAMGraphBuilderCallback : public IUnknown { - public: - virtual HRESULT WINAPI SelectedFilter(IMoniker *pMon) = 0; - virtual HRESULT WINAPI CreatedFilter(IBaseFilter *pFil) = 0; - }; -#else - typedef struct IAMGraphBuilderCallbackVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IAMGraphBuilderCallback *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IAMGraphBuilderCallback *This); - ULONG (WINAPI *Release)(IAMGraphBuilderCallback *This); - HRESULT (WINAPI *SelectedFilter)(IAMGraphBuilderCallback *This,IMoniker *pMon); - HRESULT (WINAPI *CreatedFilter)(IAMGraphBuilderCallback *This,IBaseFilter *pFil); - END_INTERFACE - } IAMGraphBuilderCallbackVtbl; - struct IAMGraphBuilderCallback { - CONST_VTBL struct IAMGraphBuilderCallbackVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IAMGraphBuilderCallback_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IAMGraphBuilderCallback_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IAMGraphBuilderCallback_Release(This) (This)->lpVtbl->Release(This) -#define IAMGraphBuilderCallback_SelectedFilter(This,pMon) (This)->lpVtbl->SelectedFilter(This,pMon) -#define IAMGraphBuilderCallback_CreatedFilter(This,pFil) (This)->lpVtbl->CreatedFilter(This,pFil) -#endif -#endif - HRESULT WINAPI IAMGraphBuilderCallback_SelectedFilter_Proxy(IAMGraphBuilderCallback *This,IMoniker *pMon); - void __RPC_STUB IAMGraphBuilderCallback_SelectedFilter_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMGraphBuilderCallback_CreatedFilter_Proxy(IAMGraphBuilderCallback *This,IBaseFilter *pFil); - void __RPC_STUB IAMGraphBuilderCallback_CreatedFilter_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifdef __cplusplus -#ifndef _IAMFilterGraphCallback_ -#define _IAMFilterGraphCallback_ - //EXTERN_GUID(IID_IAMFilterGraphCallback,0x56a868fd,0x0ad4,0x11ce,0xb0,0xa3,0x0,0x20,0xaf,0x0b,0xa7,0x70); - struct IAMFilterGraphCallback : public IUnknown { - virtual HRESULT UnableToRender(IPin *pPin) = 0; - }; -#endif -#endif - struct CodecAPIEventData { - GUID guid; - DWORD dataLength; - DWORD reserved[3]; - }; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0370_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0370_v0_0_s_ifspec; -#ifndef __ICodecAPI_INTERFACE_DEFINED__ -#define __ICodecAPI_INTERFACE_DEFINED__ - EXTERN_C const IID IID_ICodecAPI; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct ICodecAPI : public IUnknown { - public: - virtual HRESULT WINAPI IsSupported(const GUID *Api) = 0; - virtual HRESULT WINAPI IsModifiable(const GUID *Api) = 0; - virtual HRESULT WINAPI GetParameterRange(const GUID *Api,VARIANT *ValueMin,VARIANT *ValueMax,VARIANT *SteppingDelta) = 0; - virtual HRESULT WINAPI GetParameterValues(const GUID *Api,VARIANT **Values,ULONG *ValuesCount) = 0; - virtual HRESULT WINAPI GetDefaultValue(const GUID *Api,VARIANT *Value) = 0; - virtual HRESULT WINAPI GetValue(const GUID *Api,VARIANT *Value) = 0; - virtual HRESULT WINAPI SetValue(const GUID *Api,VARIANT *Value) = 0; - virtual HRESULT WINAPI RegisterForEvent(const GUID *Api,LONG_PTR userData) = 0; - virtual HRESULT WINAPI UnregisterForEvent(const GUID *Api) = 0; - virtual HRESULT WINAPI SetAllDefaults(void) = 0; - virtual HRESULT WINAPI SetValueWithNotify(const GUID *Api,VARIANT *Value,GUID **ChangedParam,ULONG *ChangedParamCount) = 0; - virtual HRESULT WINAPI SetAllDefaultsWithNotify(GUID **ChangedParam,ULONG *ChangedParamCount) = 0; - virtual HRESULT WINAPI GetAllSettings(IStream *__MIDL_0016) = 0; - virtual HRESULT WINAPI SetAllSettings(IStream *__MIDL_0017) = 0; - virtual HRESULT WINAPI SetAllSettingsWithNotify(IStream *__MIDL_0018,GUID **ChangedParam,ULONG *ChangedParamCount) = 0; - }; -#else - typedef struct ICodecAPIVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(ICodecAPI *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(ICodecAPI *This); - ULONG (WINAPI *Release)(ICodecAPI *This); - HRESULT (WINAPI *IsSupported)(ICodecAPI *This,const GUID *Api); - HRESULT (WINAPI *IsModifiable)(ICodecAPI *This,const GUID *Api); - HRESULT (WINAPI *GetParameterRange)(ICodecAPI *This,const GUID *Api,VARIANT *ValueMin,VARIANT *ValueMax,VARIANT *SteppingDelta); - HRESULT (WINAPI *GetParameterValues)(ICodecAPI *This,const GUID *Api,VARIANT **Values,ULONG *ValuesCount); - HRESULT (WINAPI *GetDefaultValue)(ICodecAPI *This,const GUID *Api,VARIANT *Value); - HRESULT (WINAPI *GetValue)(ICodecAPI *This,const GUID *Api,VARIANT *Value); - HRESULT (WINAPI *SetValue)(ICodecAPI *This,const GUID *Api,VARIANT *Value); - HRESULT (WINAPI *RegisterForEvent)(ICodecAPI *This,const GUID *Api,LONG_PTR userData); - HRESULT (WINAPI *UnregisterForEvent)(ICodecAPI *This,const GUID *Api); - HRESULT (WINAPI *SetAllDefaults)(ICodecAPI *This); - HRESULT (WINAPI *SetValueWithNotify)(ICodecAPI *This,const GUID *Api,VARIANT *Value,GUID **ChangedParam,ULONG *ChangedParamCount); - HRESULT (WINAPI *SetAllDefaultsWithNotify)(ICodecAPI *This,GUID **ChangedParam,ULONG *ChangedParamCount); - HRESULT (WINAPI *GetAllSettings)(ICodecAPI *This,IStream *__MIDL_0016); - HRESULT (WINAPI *SetAllSettings)(ICodecAPI *This,IStream *__MIDL_0017); - HRESULT (WINAPI *SetAllSettingsWithNotify)(ICodecAPI *This,IStream *__MIDL_0018,GUID **ChangedParam,ULONG *ChangedParamCount); - END_INTERFACE - } ICodecAPIVtbl; - struct ICodecAPI { - CONST_VTBL struct ICodecAPIVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define ICodecAPI_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define ICodecAPI_AddRef(This) (This)->lpVtbl->AddRef(This) -#define ICodecAPI_Release(This) (This)->lpVtbl->Release(This) -#define ICodecAPI_IsSupported(This,Api) (This)->lpVtbl->IsSupported(This,Api) -#define ICodecAPI_IsModifiable(This,Api) (This)->lpVtbl->IsModifiable(This,Api) -#define ICodecAPI_GetParameterRange(This,Api,ValueMin,ValueMax,SteppingDelta) (This)->lpVtbl->GetParameterRange(This,Api,ValueMin,ValueMax,SteppingDelta) -#define ICodecAPI_GetParameterValues(This,Api,Values,ValuesCount) (This)->lpVtbl->GetParameterValues(This,Api,Values,ValuesCount) -#define ICodecAPI_GetDefaultValue(This,Api,Value) (This)->lpVtbl->GetDefaultValue(This,Api,Value) -#define ICodecAPI_GetValue(This,Api,Value) (This)->lpVtbl->GetValue(This,Api,Value) -#define ICodecAPI_SetValue(This,Api,Value) (This)->lpVtbl->SetValue(This,Api,Value) -#define ICodecAPI_RegisterForEvent(This,Api,userData) (This)->lpVtbl->RegisterForEvent(This,Api,userData) -#define ICodecAPI_UnregisterForEvent(This,Api) (This)->lpVtbl->UnregisterForEvent(This,Api) -#define ICodecAPI_SetAllDefaults(This) (This)->lpVtbl->SetAllDefaults(This) -#define ICodecAPI_SetValueWithNotify(This,Api,Value,ChangedParam,ChangedParamCount) (This)->lpVtbl->SetValueWithNotify(This,Api,Value,ChangedParam,ChangedParamCount) -#define ICodecAPI_SetAllDefaultsWithNotify(This,ChangedParam,ChangedParamCount) (This)->lpVtbl->SetAllDefaultsWithNotify(This,ChangedParam,ChangedParamCount) -#define ICodecAPI_GetAllSettings(This,__MIDL_0016) (This)->lpVtbl->GetAllSettings(This,__MIDL_0016) -#define ICodecAPI_SetAllSettings(This,__MIDL_0017) (This)->lpVtbl->SetAllSettings(This,__MIDL_0017) -#define ICodecAPI_SetAllSettingsWithNotify(This,__MIDL_0018,ChangedParam,ChangedParamCount) (This)->lpVtbl->SetAllSettingsWithNotify(This,__MIDL_0018,ChangedParam,ChangedParamCount) -#endif -#endif - HRESULT WINAPI ICodecAPI_IsSupported_Proxy(ICodecAPI *This,const GUID *Api); - void __RPC_STUB ICodecAPI_IsSupported_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI ICodecAPI_IsModifiable_Proxy(ICodecAPI *This,const GUID *Api); - void __RPC_STUB ICodecAPI_IsModifiable_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI ICodecAPI_GetParameterRange_Proxy(ICodecAPI *This,const GUID *Api,VARIANT *ValueMin,VARIANT *ValueMax,VARIANT *SteppingDelta); - void __RPC_STUB ICodecAPI_GetParameterRange_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI ICodecAPI_GetParameterValues_Proxy(ICodecAPI *This,const GUID *Api,VARIANT **Values,ULONG *ValuesCount); - void __RPC_STUB ICodecAPI_GetParameterValues_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI ICodecAPI_GetDefaultValue_Proxy(ICodecAPI *This,const GUID *Api,VARIANT *Value); - void __RPC_STUB ICodecAPI_GetDefaultValue_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI ICodecAPI_GetValue_Proxy(ICodecAPI *This,const GUID *Api,VARIANT *Value); - void __RPC_STUB ICodecAPI_GetValue_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI ICodecAPI_SetValue_Proxy(ICodecAPI *This,const GUID *Api,VARIANT *Value); - void __RPC_STUB ICodecAPI_SetValue_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI ICodecAPI_RegisterForEvent_Proxy(ICodecAPI *This,const GUID *Api,LONG_PTR userData); - void __RPC_STUB ICodecAPI_RegisterForEvent_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI ICodecAPI_UnregisterForEvent_Proxy(ICodecAPI *This,const GUID *Api); - void __RPC_STUB ICodecAPI_UnregisterForEvent_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI ICodecAPI_SetAllDefaults_Proxy(ICodecAPI *This); - void __RPC_STUB ICodecAPI_SetAllDefaults_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI ICodecAPI_SetValueWithNotify_Proxy(ICodecAPI *This,const GUID *Api,VARIANT *Value,GUID **ChangedParam,ULONG *ChangedParamCount); - void __RPC_STUB ICodecAPI_SetValueWithNotify_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI ICodecAPI_SetAllDefaultsWithNotify_Proxy(ICodecAPI *This,GUID **ChangedParam,ULONG *ChangedParamCount); - void __RPC_STUB ICodecAPI_SetAllDefaultsWithNotify_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI ICodecAPI_GetAllSettings_Proxy(ICodecAPI *This,IStream *__MIDL_0016); - void __RPC_STUB ICodecAPI_GetAllSettings_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI ICodecAPI_SetAllSettings_Proxy(ICodecAPI *This,IStream *__MIDL_0017); - void __RPC_STUB ICodecAPI_SetAllSettings_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI ICodecAPI_SetAllSettingsWithNotify_Proxy(ICodecAPI *This,IStream *__MIDL_0018,GUID **ChangedParam,ULONG *ChangedParamCount); - void __RPC_STUB ICodecAPI_SetAllSettingsWithNotify_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IGetCapabilitiesKey_INTERFACE_DEFINED__ -#define __IGetCapabilitiesKey_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IGetCapabilitiesKey; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IGetCapabilitiesKey : public IUnknown { - public: - virtual HRESULT WINAPI GetCapabilitiesKey(HKEY *pHKey) = 0; - }; -#else - typedef struct IGetCapabilitiesKeyVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IGetCapabilitiesKey *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IGetCapabilitiesKey *This); - ULONG (WINAPI *Release)(IGetCapabilitiesKey *This); - HRESULT (WINAPI *GetCapabilitiesKey)(IGetCapabilitiesKey *This,HKEY *pHKey); - END_INTERFACE - } IGetCapabilitiesKeyVtbl; - struct IGetCapabilitiesKey { - CONST_VTBL struct IGetCapabilitiesKeyVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IGetCapabilitiesKey_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IGetCapabilitiesKey_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IGetCapabilitiesKey_Release(This) (This)->lpVtbl->Release(This) -#define IGetCapabilitiesKey_GetCapabilitiesKey(This,pHKey) (This)->lpVtbl->GetCapabilitiesKey(This,pHKey) -#endif -#endif - HRESULT WINAPI IGetCapabilitiesKey_GetCapabilitiesKey_Proxy(IGetCapabilitiesKey *This,HKEY *pHKey); - void __RPC_STUB IGetCapabilitiesKey_GetCapabilitiesKey_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IEncoderAPI_INTERFACE_DEFINED__ -#define __IEncoderAPI_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IEncoderAPI; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IEncoderAPI : public IUnknown { - public: - virtual HRESULT WINAPI IsSupported(const GUID *Api) = 0; - virtual HRESULT WINAPI IsAvailable(const GUID *Api) = 0; - virtual HRESULT WINAPI GetParameterRange(const GUID *Api,VARIANT *ValueMin,VARIANT *ValueMax,VARIANT *SteppingDelta) = 0; - virtual HRESULT WINAPI GetParameterValues(const GUID *Api,VARIANT **Values,ULONG *ValuesCount) = 0; - virtual HRESULT WINAPI GetDefaultValue(const GUID *Api,VARIANT *Value) = 0; - virtual HRESULT WINAPI GetValue(const GUID *Api,VARIANT *Value) = 0; - virtual HRESULT WINAPI SetValue(const GUID *Api,VARIANT *Value) = 0; - }; -#else - typedef struct IEncoderAPIVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IEncoderAPI *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IEncoderAPI *This); - ULONG (WINAPI *Release)(IEncoderAPI *This); - HRESULT (WINAPI *IsSupported)(IEncoderAPI *This,const GUID *Api); - HRESULT (WINAPI *IsAvailable)(IEncoderAPI *This,const GUID *Api); - HRESULT (WINAPI *GetParameterRange)(IEncoderAPI *This,const GUID *Api,VARIANT *ValueMin,VARIANT *ValueMax,VARIANT *SteppingDelta); - HRESULT (WINAPI *GetParameterValues)(IEncoderAPI *This,const GUID *Api,VARIANT **Values,ULONG *ValuesCount); - HRESULT (WINAPI *GetDefaultValue)(IEncoderAPI *This,const GUID *Api,VARIANT *Value); - HRESULT (WINAPI *GetValue)(IEncoderAPI *This,const GUID *Api,VARIANT *Value); - HRESULT (WINAPI *SetValue)(IEncoderAPI *This,const GUID *Api,VARIANT *Value); - END_INTERFACE - } IEncoderAPIVtbl; - struct IEncoderAPI { - CONST_VTBL struct IEncoderAPIVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IEncoderAPI_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IEncoderAPI_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IEncoderAPI_Release(This) (This)->lpVtbl->Release(This) -#define IEncoderAPI_IsSupported(This,Api) (This)->lpVtbl->IsSupported(This,Api) -#define IEncoderAPI_IsAvailable(This,Api) (This)->lpVtbl->IsAvailable(This,Api) -#define IEncoderAPI_GetParameterRange(This,Api,ValueMin,ValueMax,SteppingDelta) (This)->lpVtbl->GetParameterRange(This,Api,ValueMin,ValueMax,SteppingDelta) -#define IEncoderAPI_GetParameterValues(This,Api,Values,ValuesCount) (This)->lpVtbl->GetParameterValues(This,Api,Values,ValuesCount) -#define IEncoderAPI_GetDefaultValue(This,Api,Value) (This)->lpVtbl->GetDefaultValue(This,Api,Value) -#define IEncoderAPI_GetValue(This,Api,Value) (This)->lpVtbl->GetValue(This,Api,Value) -#define IEncoderAPI_SetValue(This,Api,Value) (This)->lpVtbl->SetValue(This,Api,Value) -#endif -#endif - HRESULT WINAPI IEncoderAPI_IsSupported_Proxy(IEncoderAPI *This,const GUID *Api); - void __RPC_STUB IEncoderAPI_IsSupported_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IEncoderAPI_IsAvailable_Proxy(IEncoderAPI *This,const GUID *Api); - void __RPC_STUB IEncoderAPI_IsAvailable_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IEncoderAPI_GetParameterRange_Proxy(IEncoderAPI *This,const GUID *Api,VARIANT *ValueMin,VARIANT *ValueMax,VARIANT *SteppingDelta); - void __RPC_STUB IEncoderAPI_GetParameterRange_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IEncoderAPI_GetParameterValues_Proxy(IEncoderAPI *This,const GUID *Api,VARIANT **Values,ULONG *ValuesCount); - void __RPC_STUB IEncoderAPI_GetParameterValues_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IEncoderAPI_GetDefaultValue_Proxy(IEncoderAPI *This,const GUID *Api,VARIANT *Value); - void __RPC_STUB IEncoderAPI_GetDefaultValue_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IEncoderAPI_GetValue_Proxy(IEncoderAPI *This,const GUID *Api,VARIANT *Value); - void __RPC_STUB IEncoderAPI_GetValue_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IEncoderAPI_SetValue_Proxy(IEncoderAPI *This,const GUID *Api,VARIANT *Value); - void __RPC_STUB IEncoderAPI_SetValue_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IVideoEncoder_INTERFACE_DEFINED__ -#define __IVideoEncoder_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IVideoEncoder; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IVideoEncoder : public IEncoderAPI { - public: - }; -#else - typedef struct IVideoEncoderVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IVideoEncoder *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IVideoEncoder *This); - ULONG (WINAPI *Release)(IVideoEncoder *This); - HRESULT (WINAPI *IsSupported)(IVideoEncoder *This,const GUID *Api); - HRESULT (WINAPI *IsAvailable)(IVideoEncoder *This,const GUID *Api); - HRESULT (WINAPI *GetParameterRange)(IVideoEncoder *This,const GUID *Api,VARIANT *ValueMin,VARIANT *ValueMax,VARIANT *SteppingDelta); - HRESULT (WINAPI *GetParameterValues)(IVideoEncoder *This,const GUID *Api,VARIANT **Values,ULONG *ValuesCount); - HRESULT (WINAPI *GetDefaultValue)(IVideoEncoder *This,const GUID *Api,VARIANT *Value); - HRESULT (WINAPI *GetValue)(IVideoEncoder *This,const GUID *Api,VARIANT *Value); - HRESULT (WINAPI *SetValue)(IVideoEncoder *This,const GUID *Api,VARIANT *Value); - END_INTERFACE - } IVideoEncoderVtbl; - struct IVideoEncoder { - CONST_VTBL struct IVideoEncoderVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IVideoEncoder_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IVideoEncoder_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IVideoEncoder_Release(This) (This)->lpVtbl->Release(This) -#define IVideoEncoder_IsSupported(This,Api) (This)->lpVtbl->IsSupported(This,Api) -#define IVideoEncoder_IsAvailable(This,Api) (This)->lpVtbl->IsAvailable(This,Api) -#define IVideoEncoder_GetParameterRange(This,Api,ValueMin,ValueMax,SteppingDelta) (This)->lpVtbl->GetParameterRange(This,Api,ValueMin,ValueMax,SteppingDelta) -#define IVideoEncoder_GetParameterValues(This,Api,Values,ValuesCount) (This)->lpVtbl->GetParameterValues(This,Api,Values,ValuesCount) -#define IVideoEncoder_GetDefaultValue(This,Api,Value) (This)->lpVtbl->GetDefaultValue(This,Api,Value) -#define IVideoEncoder_GetValue(This,Api,Value) (This)->lpVtbl->GetValue(This,Api,Value) -#define IVideoEncoder_SetValue(This,Api,Value) (This)->lpVtbl->SetValue(This,Api,Value) -#endif -#endif -#endif - -#ifndef __ENCODER_API_DEFINES__ -#define __ENCODER_API_DEFINES__ - typedef enum __MIDL___MIDL_itf_strmif_0374_0001 { - ConstantBitRate = 0, - VariableBitRateAverage,VariableBitRatePeak - } VIDEOENCODER_BITRATE_MODE; -#endif -#define AM_GETDECODERCAP_QUERY_VMR_SUPPORT 0x00000001 -#define VMR_NOTSUPPORTED 0x00000000 -#define VMR_SUPPORTED 0x00000001 -#define AM_QUERY_DECODER_VMR_SUPPORT 0x00000001 -#define AM_QUERY_DECODER_DXVA_1_SUPPORT 0x00000002 -#define AM_QUERY_DECODER_DVD_SUPPORT 0x00000003 -#define AM_QUERY_DECODER_ATSC_SD_SUPPORT 0x00000004 -#define AM_QUERY_DECODER_ATSC_HD_SUPPORT 0x00000005 -#define AM_GETDECODERCAP_QUERY_VMR9_SUPPORT 0x00000006 -#define DECODER_CAP_NOTSUPPORTED 0x00000000 -#define DECODER_CAP_SUPPORTED 0x00000001 - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0374_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0374_v0_0_s_ifspec; -#ifndef __IAMDecoderCaps_INTERFACE_DEFINED__ -#define __IAMDecoderCaps_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IAMDecoderCaps; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IAMDecoderCaps : public IUnknown { - public: - virtual HRESULT WINAPI GetDecoderCaps(DWORD dwCapIndex,DWORD *lpdwCap) = 0; - }; -#else - typedef struct IAMDecoderCapsVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IAMDecoderCaps *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IAMDecoderCaps *This); - ULONG (WINAPI *Release)(IAMDecoderCaps *This); - HRESULT (WINAPI *GetDecoderCaps)(IAMDecoderCaps *This,DWORD dwCapIndex,DWORD *lpdwCap); - END_INTERFACE - } IAMDecoderCapsVtbl; - struct IAMDecoderCaps { - CONST_VTBL struct IAMDecoderCapsVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IAMDecoderCaps_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IAMDecoderCaps_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IAMDecoderCaps_Release(This) (This)->lpVtbl->Release(This) -#define IAMDecoderCaps_GetDecoderCaps(This,dwCapIndex,lpdwCap) (This)->lpVtbl->GetDecoderCaps(This,dwCapIndex,lpdwCap) -#endif -#endif - HRESULT WINAPI IAMDecoderCaps_GetDecoderCaps_Proxy(IAMDecoderCaps *This,DWORD dwCapIndex,DWORD *lpdwCap); - void __RPC_STUB IAMDecoderCaps_GetDecoderCaps_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - typedef struct _AMCOPPSignature { - BYTE Signature[256]; - } AMCOPPSignature; - - typedef struct _AMCOPPCommand { - GUID macKDI; - GUID guidCommandID; - DWORD dwSequence; - DWORD cbSizeData; - BYTE CommandData[4056]; - } AMCOPPCommand; - - typedef struct _AMCOPPCommand *LPAMCOPPCommand; - - typedef struct _AMCOPPStatusInput { - GUID rApp; - GUID guidStatusRequestID; - DWORD dwSequence; - DWORD cbSizeData; - BYTE StatusData[4056]; - } AMCOPPStatusInput; - - typedef struct _AMCOPPStatusInput *LPAMCOPPStatusInput; - - typedef struct _AMCOPPStatusOutput { - GUID macKDI; - DWORD cbSizeData; - BYTE COPPStatus[4076]; - } AMCOPPStatusOutput; - - typedef struct _AMCOPPStatusOutput *LPAMCOPPStatusOutput; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0375_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0375_v0_0_s_ifspec; -#ifndef __IAMCertifiedOutputProtection_INTERFACE_DEFINED__ -#define __IAMCertifiedOutputProtection_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IAMCertifiedOutputProtection; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IAMCertifiedOutputProtection : public IUnknown { - public: - virtual HRESULT WINAPI KeyExchange(GUID *pRandom,BYTE **VarLenCertGH,DWORD *pdwLengthCertGH) = 0; - virtual HRESULT WINAPI SessionSequenceStart(AMCOPPSignature *pSig) = 0; - virtual HRESULT WINAPI ProtectionCommand(const AMCOPPCommand *cmd) = 0; - virtual HRESULT WINAPI ProtectionStatus(const AMCOPPStatusInput *pStatusInput,AMCOPPStatusOutput *pStatusOutput) = 0; - }; -#else - typedef struct IAMCertifiedOutputProtectionVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IAMCertifiedOutputProtection *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IAMCertifiedOutputProtection *This); - ULONG (WINAPI *Release)(IAMCertifiedOutputProtection *This); - HRESULT (WINAPI *KeyExchange)(IAMCertifiedOutputProtection *This,GUID *pRandom,BYTE **VarLenCertGH,DWORD *pdwLengthCertGH); - HRESULT (WINAPI *SessionSequenceStart)(IAMCertifiedOutputProtection *This,AMCOPPSignature *pSig); - HRESULT (WINAPI *ProtectionCommand)(IAMCertifiedOutputProtection *This,const AMCOPPCommand *cmd); - HRESULT (WINAPI *ProtectionStatus)(IAMCertifiedOutputProtection *This,const AMCOPPStatusInput *pStatusInput,AMCOPPStatusOutput *pStatusOutput); - END_INTERFACE - } IAMCertifiedOutputProtectionVtbl; - struct IAMCertifiedOutputProtection { - CONST_VTBL struct IAMCertifiedOutputProtectionVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IAMCertifiedOutputProtection_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IAMCertifiedOutputProtection_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IAMCertifiedOutputProtection_Release(This) (This)->lpVtbl->Release(This) -#define IAMCertifiedOutputProtection_KeyExchange(This,pRandom,VarLenCertGH,pdwLengthCertGH) (This)->lpVtbl->KeyExchange(This,pRandom,VarLenCertGH,pdwLengthCertGH) -#define IAMCertifiedOutputProtection_SessionSequenceStart(This,pSig) (This)->lpVtbl->SessionSequenceStart(This,pSig) -#define IAMCertifiedOutputProtection_ProtectionCommand(This,cmd) (This)->lpVtbl->ProtectionCommand(This,cmd) -#define IAMCertifiedOutputProtection_ProtectionStatus(This,pStatusInput,pStatusOutput) (This)->lpVtbl->ProtectionStatus(This,pStatusInput,pStatusOutput) -#endif -#endif - HRESULT WINAPI IAMCertifiedOutputProtection_KeyExchange_Proxy(IAMCertifiedOutputProtection *This,GUID *pRandom,BYTE **VarLenCertGH,DWORD *pdwLengthCertGH); - void __RPC_STUB IAMCertifiedOutputProtection_KeyExchange_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMCertifiedOutputProtection_SessionSequenceStart_Proxy(IAMCertifiedOutputProtection *This,AMCOPPSignature *pSig); - void __RPC_STUB IAMCertifiedOutputProtection_SessionSequenceStart_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMCertifiedOutputProtection_ProtectionCommand_Proxy(IAMCertifiedOutputProtection *This,const AMCOPPCommand *cmd); - void __RPC_STUB IAMCertifiedOutputProtection_ProtectionCommand_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IAMCertifiedOutputProtection_ProtectionStatus_Proxy(IAMCertifiedOutputProtection *This,const AMCOPPStatusInput *pStatusInput,AMCOPPStatusOutput *pStatusOutput); - void __RPC_STUB IAMCertifiedOutputProtection_ProtectionStatus_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#include - - typedef enum tagDVD_DOMAIN { - DVD_DOMAIN_FirstPlay = 1, - DVD_DOMAIN_VideoManagerMenu,DVD_DOMAIN_VideoTitleSetMenu,DVD_DOMAIN_Title, - DVD_DOMAIN_Stop - } DVD_DOMAIN; - - typedef enum tagDVD_MENU_ID { - DVD_MENU_Title = 2,DVD_MENU_Root = 3,DVD_MENU_Subpicture = 4,DVD_MENU_Audio = 5, - DVD_MENU_Angle = 6,DVD_MENU_Chapter = 7 - } DVD_MENU_ID; - - typedef enum tagDVD_DISC_SIDE { - DVD_SIDE_A = 1,DVD_SIDE_B = 2 - } DVD_DISC_SIDE; - - typedef enum tagDVD_PREFERRED_DISPLAY_MODE { - DISPLAY_CONTENT_DEFAULT = 0,DISPLAY_16x9 = 1,DISPLAY_4x3_PANSCAN_PREFERRED = 2,DISPLAY_4x3_LETTERBOX_PREFERRED = 3 - } DVD_PREFERRED_DISPLAY_MODE; - - typedef WORD DVD_REGISTER; - typedef DVD_REGISTER GPRMARRAY[16]; - typedef DVD_REGISTER SPRMARRAY[24]; - - typedef struct tagDVD_ATR { - ULONG ulCAT; - BYTE pbATRI[768]; - } DVD_ATR; - - typedef BYTE DVD_VideoATR[2]; - typedef BYTE DVD_AudioATR[8]; - typedef BYTE DVD_SubpictureATR[6]; - - typedef enum tagDVD_FRAMERATE { - DVD_FPS_25 = 1,DVD_FPS_30NonDrop = 3 - } DVD_FRAMERATE; - - typedef struct tagDVD_TIMECODE { - ULONG Hours1 :4; - ULONG Hours10 :4; - ULONG Minutes1 :4; - ULONG Minutes10:4; - ULONG Seconds1 :4; - ULONG Seconds10:4; - ULONG Frames1 :4; - ULONG Frames10 :2; - ULONG FrameRateCode: 2; - } DVD_TIMECODE; - - typedef enum tagDVD_TIMECODE_FLAGS { - DVD_TC_FLAG_25fps = 0x1,DVD_TC_FLAG_30fps = 0x2,DVD_TC_FLAG_DropFrame = 0x4,DVD_TC_FLAG_Interpolated = 0x8 - } DVD_TIMECODE_FLAGS; - - typedef struct tagDVD_HMSF_TIMECODE { - BYTE bHours; - BYTE bMinutes; - BYTE bSeconds; - BYTE bFrames; - } DVD_HMSF_TIMECODE; - - typedef struct tagDVD_PLAYBACK_LOCATION2 { - ULONG TitleNum; - ULONG ChapterNum; - DVD_HMSF_TIMECODE TimeCode; - ULONG TimeCodeFlags; - } DVD_PLAYBACK_LOCATION2; - - typedef struct tagDVD_PLAYBACK_LOCATION { - ULONG TitleNum; - ULONG ChapterNum; - ULONG TimeCode; - } DVD_PLAYBACK_LOCATION; - - typedef DWORD VALID_UOP_SOMTHING_OR_OTHER; - - typedef enum __MIDL___MIDL_itf_strmif_0376_0001 { - UOP_FLAG_Play_Title_Or_AtTime = 0x1,UOP_FLAG_Play_Chapter = 0x2,UOP_FLAG_Play_Title = 0x4,UOP_FLAG_Stop = 0x8,UOP_FLAG_ReturnFromSubMenu = 0x10, - UOP_FLAG_Play_Chapter_Or_AtTime = 0x20,UOP_FLAG_PlayPrev_Or_Replay_Chapter = 0x40,UOP_FLAG_PlayNext_Chapter = 0x80,UOP_FLAG_Play_Forwards = 0x100, - UOP_FLAG_Play_Backwards = 0x200,UOP_FLAG_ShowMenu_Title = 0x400,UOP_FLAG_ShowMenu_Root = 0x800,UOP_FLAG_ShowMenu_SubPic = 0x1000, - UOP_FLAG_ShowMenu_Audio = 0x2000,UOP_FLAG_ShowMenu_Angle = 0x4000,UOP_FLAG_ShowMenu_Chapter = 0x8000,UOP_FLAG_Resume = 0x10000, - UOP_FLAG_Select_Or_Activate_Button = 0x20000,UOP_FLAG_Still_Off = 0x40000,UOP_FLAG_Pause_On = 0x80000,UOP_FLAG_Select_Audio_Stream = 0x100000, - UOP_FLAG_Select_SubPic_Stream = 0x200000,UOP_FLAG_Select_Angle = 0x400000,UOP_FLAG_Select_Karaoke_Audio_Presentation_Mode = 0x800000, - UOP_FLAG_Select_Video_Mode_Preference = 0x1000000 - } VALID_UOP_FLAG; - - typedef enum __MIDL___MIDL_itf_strmif_0376_0002 { - DVD_CMD_FLAG_None = 0,DVD_CMD_FLAG_Flush = 0x1,DVD_CMD_FLAG_SendEvents = 0x2,DVD_CMD_FLAG_Block = 0x4,DVD_CMD_FLAG_StartWhenRendered = 0x8, - DVD_CMD_FLAG_EndAfterRendered = 0x10 - } DVD_CMD_FLAGS; - - typedef enum __MIDL___MIDL_itf_strmif_0376_0003 { - DVD_ResetOnStop = 1,DVD_NotifyParentalLevelChange = 2,DVD_HMSF_TimeCodeEvents = 3,DVD_AudioDuringFFwdRew = 4 - } DVD_OPTION_FLAG; - - typedef enum __MIDL___MIDL_itf_strmif_0376_0004 { - DVD_Relative_Upper = 1,DVD_Relative_Lower = 2,DVD_Relative_Left = 3,DVD_Relative_Right = 4 - } DVD_RELATIVE_BUTTON; - - typedef enum tagDVD_PARENTAL_LEVEL { - DVD_PARENTAL_LEVEL_8 = 0x8000,DVD_PARENTAL_LEVEL_7 = 0x4000,DVD_PARENTAL_LEVEL_6 = 0x2000,DVD_PARENTAL_LEVEL_5 = 0x1000, - DVD_PARENTAL_LEVEL_4 = 0x800,DVD_PARENTAL_LEVEL_3 = 0x400,DVD_PARENTAL_LEVEL_2 = 0x200,DVD_PARENTAL_LEVEL_1 = 0x100 - } DVD_PARENTAL_LEVEL; - - typedef enum tagDVD_AUDIO_LANG_EXT { - DVD_AUD_EXT_NotSpecified = 0,DVD_AUD_EXT_Captions = 1,DVD_AUD_EXT_VisuallyImpaired = 2,DVD_AUD_EXT_DirectorComments1 = 3, - DVD_AUD_EXT_DirectorComments2 = 4 - } DVD_AUDIO_LANG_EXT; - - typedef enum tagDVD_SUBPICTURE_LANG_EXT { - DVD_SP_EXT_NotSpecified = 0,DVD_SP_EXT_Caption_Normal = 1,DVD_SP_EXT_Caption_Big = 2,DVD_SP_EXT_Caption_Children = 3,DVD_SP_EXT_CC_Normal = 5, - DVD_SP_EXT_CC_Big = 6,DVD_SP_EXT_CC_Children = 7,DVD_SP_EXT_Forced = 9,DVD_SP_EXT_DirectorComments_Normal = 13,DVD_SP_EXT_DirectorComments_Big = 14, - DVD_SP_EXT_DirectorComments_Children = 15 - } DVD_SUBPICTURE_LANG_EXT; - - typedef enum tagDVD_AUDIO_APPMODE { - DVD_AudioMode_None = 0,DVD_AudioMode_Karaoke = 1,DVD_AudioMode_Surround = 2,DVD_AudioMode_Other = 3 - } DVD_AUDIO_APPMODE; - - typedef enum tagDVD_AUDIO_FORMAT { - DVD_AudioFormat_AC3 = 0,DVD_AudioFormat_MPEG1 = 1,DVD_AudioFormat_MPEG1_DRC = 2,DVD_AudioFormat_MPEG2 = 3,DVD_AudioFormat_MPEG2_DRC = 4, - DVD_AudioFormat_LPCM = 5,DVD_AudioFormat_DTS = 6,DVD_AudioFormat_SDDS = 7,DVD_AudioFormat_Other = 8 - } DVD_AUDIO_FORMAT; - - typedef enum tagDVD_KARAOKE_DOWNMIX { - DVD_Mix_0to0 = 0x1,DVD_Mix_1to0 = 0x2,DVD_Mix_2to0 = 0x4,DVD_Mix_3to0 = 0x8,DVD_Mix_4to0 = 0x10,DVD_Mix_Lto0 = 0x20,DVD_Mix_Rto0 = 0x40, - DVD_Mix_0to1 = 0x100,DVD_Mix_1to1 = 0x200,DVD_Mix_2to1 = 0x400,DVD_Mix_3to1 = 0x800,DVD_Mix_4to1 = 0x1000,DVD_Mix_Lto1 = 0x2000, - DVD_Mix_Rto1 = 0x4000 - } DVD_KARAOKE_DOWNMIX; - - typedef struct tagDVD_AudioAttributes { - DVD_AUDIO_APPMODE AppMode; - BYTE AppModeData; - DVD_AUDIO_FORMAT AudioFormat; - LCID Language; - DVD_AUDIO_LANG_EXT LanguageExtension; - WINBOOL fHasMultichannelInfo; - DWORD dwFrequency; - BYTE bQuantization; - BYTE bNumberOfChannels; - DWORD dwReserved[2]; - } DVD_AudioAttributes; - - typedef struct tagDVD_MUA_MixingInfo { - WINBOOL fMixTo0; - WINBOOL fMixTo1; - WINBOOL fMix0InPhase; - WINBOOL fMix1InPhase; - DWORD dwSpeakerPosition; - } DVD_MUA_MixingInfo; - - typedef struct tagDVD_MUA_Coeff { - double log2_alpha; - double log2_beta; - } DVD_MUA_Coeff; - - typedef struct tagDVD_MultichannelAudioAttributes { - DVD_MUA_MixingInfo Info[8]; - DVD_MUA_Coeff Coeff[8]; - } DVD_MultichannelAudioAttributes; - - typedef enum tagDVD_KARAOKE_CONTENTS { - DVD_Karaoke_GuideVocal1 = 0x1,DVD_Karaoke_GuideVocal2 = 0x2,DVD_Karaoke_GuideMelody1 = 0x4,DVD_Karaoke_GuideMelody2 = 0x8, - DVD_Karaoke_GuideMelodyA = 0x10,DVD_Karaoke_GuideMelodyB = 0x20,DVD_Karaoke_SoundEffectA = 0x40,DVD_Karaoke_SoundEffectB = 0x80 - } DVD_KARAOKE_CONTENTS; - - typedef enum tagDVD_KARAOKE_ASSIGNMENT { - DVD_Assignment_reserved0 = 0,DVD_Assignment_reserved1 = 1,DVD_Assignment_LR = 2,DVD_Assignment_LRM = 3,DVD_Assignment_LR1 = 4, - DVD_Assignment_LRM1 = 5,DVD_Assignment_LR12 = 6,DVD_Assignment_LRM12 = 7 - } DVD_KARAOKE_ASSIGNMENT; - - typedef struct tagDVD_KaraokeAttributes { - BYTE bVersion; - WINBOOL fMasterOfCeremoniesInGuideVocal1; - WINBOOL fDuet; - DVD_KARAOKE_ASSIGNMENT ChannelAssignment; - WORD wChannelContents[8]; - } DVD_KaraokeAttributes; - - typedef enum tagDVD_VIDEO_COMPRESSION { - DVD_VideoCompression_Other = 0,DVD_VideoCompression_MPEG1 = 1,DVD_VideoCompression_MPEG2 = 2 - } DVD_VIDEO_COMPRESSION; - - typedef struct tagDVD_VideoAttributes { - WINBOOL fPanscanPermitted; - WINBOOL fLetterboxPermitted; - ULONG ulAspectX; - ULONG ulAspectY; - ULONG ulFrameRate; - ULONG ulFrameHeight; - DVD_VIDEO_COMPRESSION Compression; - WINBOOL fLine21Field1InGOP; - WINBOOL fLine21Field2InGOP; - ULONG ulSourceResolutionX; - ULONG ulSourceResolutionY; - WINBOOL fIsSourceLetterboxed; - WINBOOL fIsFilmMode; - } DVD_VideoAttributes; - - typedef enum tagDVD_SUBPICTURE_TYPE { - DVD_SPType_NotSpecified = 0,DVD_SPType_Language = 1,DVD_SPType_Other = 2 - } DVD_SUBPICTURE_TYPE; - - typedef enum tagDVD_SUBPICTURE_CODING { - DVD_SPCoding_RunLength = 0,DVD_SPCoding_Extended = 1,DVD_SPCoding_Other = 2 - } DVD_SUBPICTURE_CODING; - - typedef struct tagDVD_SubpictureAttributes { - DVD_SUBPICTURE_TYPE Type; - DVD_SUBPICTURE_CODING CodingMode; - LCID Language; - DVD_SUBPICTURE_LANG_EXT LanguageExtension; - } DVD_SubpictureAttributes; - - typedef enum tagDVD_TITLE_APPMODE { - DVD_AppMode_Not_Specified = 0,DVD_AppMode_Karaoke = 1,DVD_AppMode_Other = 3 - } DVD_TITLE_APPMODE; - - typedef struct tagDVD_TitleMainAttributes { - DVD_TITLE_APPMODE AppMode; - DVD_VideoAttributes VideoAttributes; - ULONG ulNumberOfAudioStreams; - DVD_AudioAttributes AudioAttributes[8]; - DVD_MultichannelAudioAttributes MultichannelAudioAttributes[8]; - ULONG ulNumberOfSubpictureStreams; - DVD_SubpictureAttributes SubpictureAttributes[32]; - } DVD_TitleAttributes; - - typedef struct tagDVD_MenuAttributes { - WINBOOL fCompatibleRegion[8]; - DVD_VideoAttributes VideoAttributes; - WINBOOL fAudioPresent; - DVD_AudioAttributes AudioAttributes; - WINBOOL fSubpicturePresent; - DVD_SubpictureAttributes SubpictureAttributes; - } DVD_MenuAttributes; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0376_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0376_v0_0_s_ifspec; -#ifndef __IDvdControl_INTERFACE_DEFINED__ -#define __IDvdControl_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IDvdControl; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IDvdControl : public IUnknown { - public: - virtual HRESULT WINAPI TitlePlay(ULONG ulTitle) = 0; - virtual HRESULT WINAPI ChapterPlay(ULONG ulTitle,ULONG ulChapter) = 0; - virtual HRESULT WINAPI TimePlay(ULONG ulTitle,ULONG bcdTime) = 0; - virtual HRESULT WINAPI StopForResume(void) = 0; - virtual HRESULT WINAPI GoUp(void) = 0; - virtual HRESULT WINAPI TimeSearch(ULONG bcdTime) = 0; - virtual HRESULT WINAPI ChapterSearch(ULONG ulChapter) = 0; - virtual HRESULT WINAPI PrevPGSearch(void) = 0; - virtual HRESULT WINAPI TopPGSearch(void) = 0; - virtual HRESULT WINAPI NextPGSearch(void) = 0; - virtual HRESULT WINAPI ForwardScan(double dwSpeed) = 0; - virtual HRESULT WINAPI BackwardScan(double dwSpeed) = 0; - virtual HRESULT WINAPI MenuCall(DVD_MENU_ID MenuID) = 0; - virtual HRESULT WINAPI Resume(void) = 0; - virtual HRESULT WINAPI UpperButtonSelect(void) = 0; - virtual HRESULT WINAPI LowerButtonSelect(void) = 0; - virtual HRESULT WINAPI LeftButtonSelect(void) = 0; - virtual HRESULT WINAPI RightButtonSelect(void) = 0; - virtual HRESULT WINAPI ButtonActivate(void) = 0; - virtual HRESULT WINAPI ButtonSelectAndActivate(ULONG ulButton) = 0; - virtual HRESULT WINAPI StillOff(void) = 0; - virtual HRESULT WINAPI PauseOn(void) = 0; - virtual HRESULT WINAPI PauseOff(void) = 0; - virtual HRESULT WINAPI MenuLanguageSelect(LCID Language) = 0; - virtual HRESULT WINAPI AudioStreamChange(ULONG ulAudio) = 0; - virtual HRESULT WINAPI SubpictureStreamChange(ULONG ulSubPicture,WINBOOL bDisplay) = 0; - virtual HRESULT WINAPI AngleChange(ULONG ulAngle) = 0; - virtual HRESULT WINAPI ParentalLevelSelect(ULONG ulParentalLevel) = 0; - virtual HRESULT WINAPI ParentalCountrySelect(WORD wCountry) = 0; - virtual HRESULT WINAPI KaraokeAudioPresentationModeChange(ULONG ulMode) = 0; - virtual HRESULT WINAPI VideoModePreferrence(ULONG ulPreferredDisplayMode) = 0; - virtual HRESULT WINAPI SetRoot(LPCWSTR pszPath) = 0; - virtual HRESULT WINAPI MouseActivate(POINT point) = 0; - virtual HRESULT WINAPI MouseSelect(POINT point) = 0; - virtual HRESULT WINAPI ChapterPlayAutoStop(ULONG ulTitle,ULONG ulChapter,ULONG ulChaptersToPlay) = 0; - }; -#else - typedef struct IDvdControlVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IDvdControl *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IDvdControl *This); - ULONG (WINAPI *Release)(IDvdControl *This); - HRESULT (WINAPI *TitlePlay)(IDvdControl *This,ULONG ulTitle); - HRESULT (WINAPI *ChapterPlay)(IDvdControl *This,ULONG ulTitle,ULONG ulChapter); - HRESULT (WINAPI *TimePlay)(IDvdControl *This,ULONG ulTitle,ULONG bcdTime); - HRESULT (WINAPI *StopForResume)(IDvdControl *This); - HRESULT (WINAPI *GoUp)(IDvdControl *This); - HRESULT (WINAPI *TimeSearch)(IDvdControl *This,ULONG bcdTime); - HRESULT (WINAPI *ChapterSearch)(IDvdControl *This,ULONG ulChapter); - HRESULT (WINAPI *PrevPGSearch)(IDvdControl *This); - HRESULT (WINAPI *TopPGSearch)(IDvdControl *This); - HRESULT (WINAPI *NextPGSearch)(IDvdControl *This); - HRESULT (WINAPI *ForwardScan)(IDvdControl *This,double dwSpeed); - HRESULT (WINAPI *BackwardScan)(IDvdControl *This,double dwSpeed); - HRESULT (WINAPI *MenuCall)(IDvdControl *This,DVD_MENU_ID MenuID); - HRESULT (WINAPI *Resume)(IDvdControl *This); - HRESULT (WINAPI *UpperButtonSelect)(IDvdControl *This); - HRESULT (WINAPI *LowerButtonSelect)(IDvdControl *This); - HRESULT (WINAPI *LeftButtonSelect)(IDvdControl *This); - HRESULT (WINAPI *RightButtonSelect)(IDvdControl *This); - HRESULT (WINAPI *ButtonActivate)(IDvdControl *This); - HRESULT (WINAPI *ButtonSelectAndActivate)(IDvdControl *This,ULONG ulButton); - HRESULT (WINAPI *StillOff)(IDvdControl *This); - HRESULT (WINAPI *PauseOn)(IDvdControl *This); - HRESULT (WINAPI *PauseOff)(IDvdControl *This); - HRESULT (WINAPI *MenuLanguageSelect)(IDvdControl *This,LCID Language); - HRESULT (WINAPI *AudioStreamChange)(IDvdControl *This,ULONG ulAudio); - HRESULT (WINAPI *SubpictureStreamChange)(IDvdControl *This,ULONG ulSubPicture,WINBOOL bDisplay); - HRESULT (WINAPI *AngleChange)(IDvdControl *This,ULONG ulAngle); - HRESULT (WINAPI *ParentalLevelSelect)(IDvdControl *This,ULONG ulParentalLevel); - HRESULT (WINAPI *ParentalCountrySelect)(IDvdControl *This,WORD wCountry); - HRESULT (WINAPI *KaraokeAudioPresentationModeChange)(IDvdControl *This,ULONG ulMode); - HRESULT (WINAPI *VideoModePreferrence)(IDvdControl *This,ULONG ulPreferredDisplayMode); - HRESULT (WINAPI *SetRoot)(IDvdControl *This,LPCWSTR pszPath); - HRESULT (WINAPI *MouseActivate)(IDvdControl *This,POINT point); - HRESULT (WINAPI *MouseSelect)(IDvdControl *This,POINT point); - HRESULT (WINAPI *ChapterPlayAutoStop)(IDvdControl *This,ULONG ulTitle,ULONG ulChapter,ULONG ulChaptersToPlay); - END_INTERFACE - } IDvdControlVtbl; - struct IDvdControl { - CONST_VTBL struct IDvdControlVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IDvdControl_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IDvdControl_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IDvdControl_Release(This) (This)->lpVtbl->Release(This) -#define IDvdControl_TitlePlay(This,ulTitle) (This)->lpVtbl->TitlePlay(This,ulTitle) -#define IDvdControl_ChapterPlay(This,ulTitle,ulChapter) (This)->lpVtbl->ChapterPlay(This,ulTitle,ulChapter) -#define IDvdControl_TimePlay(This,ulTitle,bcdTime) (This)->lpVtbl->TimePlay(This,ulTitle,bcdTime) -#define IDvdControl_StopForResume(This) (This)->lpVtbl->StopForResume(This) -#define IDvdControl_GoUp(This) (This)->lpVtbl->GoUp(This) -#define IDvdControl_TimeSearch(This,bcdTime) (This)->lpVtbl->TimeSearch(This,bcdTime) -#define IDvdControl_ChapterSearch(This,ulChapter) (This)->lpVtbl->ChapterSearch(This,ulChapter) -#define IDvdControl_PrevPGSearch(This) (This)->lpVtbl->PrevPGSearch(This) -#define IDvdControl_TopPGSearch(This) (This)->lpVtbl->TopPGSearch(This) -#define IDvdControl_NextPGSearch(This) (This)->lpVtbl->NextPGSearch(This) -#define IDvdControl_ForwardScan(This,dwSpeed) (This)->lpVtbl->ForwardScan(This,dwSpeed) -#define IDvdControl_BackwardScan(This,dwSpeed) (This)->lpVtbl->BackwardScan(This,dwSpeed) -#define IDvdControl_MenuCall(This,MenuID) (This)->lpVtbl->MenuCall(This,MenuID) -#define IDvdControl_Resume(This) (This)->lpVtbl->Resume(This) -#define IDvdControl_UpperButtonSelect(This) (This)->lpVtbl->UpperButtonSelect(This) -#define IDvdControl_LowerButtonSelect(This) (This)->lpVtbl->LowerButtonSelect(This) -#define IDvdControl_LeftButtonSelect(This) (This)->lpVtbl->LeftButtonSelect(This) -#define IDvdControl_RightButtonSelect(This) (This)->lpVtbl->RightButtonSelect(This) -#define IDvdControl_ButtonActivate(This) (This)->lpVtbl->ButtonActivate(This) -#define IDvdControl_ButtonSelectAndActivate(This,ulButton) (This)->lpVtbl->ButtonSelectAndActivate(This,ulButton) -#define IDvdControl_StillOff(This) (This)->lpVtbl->StillOff(This) -#define IDvdControl_PauseOn(This) (This)->lpVtbl->PauseOn(This) -#define IDvdControl_PauseOff(This) (This)->lpVtbl->PauseOff(This) -#define IDvdControl_MenuLanguageSelect(This,Language) (This)->lpVtbl->MenuLanguageSelect(This,Language) -#define IDvdControl_AudioStreamChange(This,ulAudio) (This)->lpVtbl->AudioStreamChange(This,ulAudio) -#define IDvdControl_SubpictureStreamChange(This,ulSubPicture,bDisplay) (This)->lpVtbl->SubpictureStreamChange(This,ulSubPicture,bDisplay) -#define IDvdControl_AngleChange(This,ulAngle) (This)->lpVtbl->AngleChange(This,ulAngle) -#define IDvdControl_ParentalLevelSelect(This,ulParentalLevel) (This)->lpVtbl->ParentalLevelSelect(This,ulParentalLevel) -#define IDvdControl_ParentalCountrySelect(This,wCountry) (This)->lpVtbl->ParentalCountrySelect(This,wCountry) -#define IDvdControl_KaraokeAudioPresentationModeChange(This,ulMode) (This)->lpVtbl->KaraokeAudioPresentationModeChange(This,ulMode) -#define IDvdControl_VideoModePreferrence(This,ulPreferredDisplayMode) (This)->lpVtbl->VideoModePreferrence(This,ulPreferredDisplayMode) -#define IDvdControl_SetRoot(This,pszPath) (This)->lpVtbl->SetRoot(This,pszPath) -#define IDvdControl_MouseActivate(This,point) (This)->lpVtbl->MouseActivate(This,point) -#define IDvdControl_MouseSelect(This,point) (This)->lpVtbl->MouseSelect(This,point) -#define IDvdControl_ChapterPlayAutoStop(This,ulTitle,ulChapter,ulChaptersToPlay) (This)->lpVtbl->ChapterPlayAutoStop(This,ulTitle,ulChapter,ulChaptersToPlay) -#endif -#endif - HRESULT WINAPI IDvdControl_TitlePlay_Proxy(IDvdControl *This,ULONG ulTitle); - void __RPC_STUB IDvdControl_TitlePlay_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl_ChapterPlay_Proxy(IDvdControl *This,ULONG ulTitle,ULONG ulChapter); - void __RPC_STUB IDvdControl_ChapterPlay_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl_TimePlay_Proxy(IDvdControl *This,ULONG ulTitle,ULONG bcdTime); - void __RPC_STUB IDvdControl_TimePlay_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl_StopForResume_Proxy(IDvdControl *This); - void __RPC_STUB IDvdControl_StopForResume_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl_GoUp_Proxy(IDvdControl *This); - void __RPC_STUB IDvdControl_GoUp_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl_TimeSearch_Proxy(IDvdControl *This,ULONG bcdTime); - void __RPC_STUB IDvdControl_TimeSearch_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl_ChapterSearch_Proxy(IDvdControl *This,ULONG ulChapter); - void __RPC_STUB IDvdControl_ChapterSearch_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl_PrevPGSearch_Proxy(IDvdControl *This); - void __RPC_STUB IDvdControl_PrevPGSearch_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl_TopPGSearch_Proxy(IDvdControl *This); - void __RPC_STUB IDvdControl_TopPGSearch_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl_NextPGSearch_Proxy(IDvdControl *This); - void __RPC_STUB IDvdControl_NextPGSearch_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl_ForwardScan_Proxy(IDvdControl *This,double dwSpeed); - void __RPC_STUB IDvdControl_ForwardScan_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl_BackwardScan_Proxy(IDvdControl *This,double dwSpeed); - void __RPC_STUB IDvdControl_BackwardScan_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl_MenuCall_Proxy(IDvdControl *This,DVD_MENU_ID MenuID); - void __RPC_STUB IDvdControl_MenuCall_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl_Resume_Proxy(IDvdControl *This); - void __RPC_STUB IDvdControl_Resume_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl_UpperButtonSelect_Proxy(IDvdControl *This); - void __RPC_STUB IDvdControl_UpperButtonSelect_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl_LowerButtonSelect_Proxy(IDvdControl *This); - void __RPC_STUB IDvdControl_LowerButtonSelect_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl_LeftButtonSelect_Proxy(IDvdControl *This); - void __RPC_STUB IDvdControl_LeftButtonSelect_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl_RightButtonSelect_Proxy(IDvdControl *This); - void __RPC_STUB IDvdControl_RightButtonSelect_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl_ButtonActivate_Proxy(IDvdControl *This); - void __RPC_STUB IDvdControl_ButtonActivate_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl_ButtonSelectAndActivate_Proxy(IDvdControl *This,ULONG ulButton); - void __RPC_STUB IDvdControl_ButtonSelectAndActivate_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl_StillOff_Proxy(IDvdControl *This); - void __RPC_STUB IDvdControl_StillOff_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl_PauseOn_Proxy(IDvdControl *This); - void __RPC_STUB IDvdControl_PauseOn_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl_PauseOff_Proxy(IDvdControl *This); - void __RPC_STUB IDvdControl_PauseOff_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl_MenuLanguageSelect_Proxy(IDvdControl *This,LCID Language); - void __RPC_STUB IDvdControl_MenuLanguageSelect_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl_AudioStreamChange_Proxy(IDvdControl *This,ULONG ulAudio); - void __RPC_STUB IDvdControl_AudioStreamChange_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl_SubpictureStreamChange_Proxy(IDvdControl *This,ULONG ulSubPicture,WINBOOL bDisplay); - void __RPC_STUB IDvdControl_SubpictureStreamChange_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl_AngleChange_Proxy(IDvdControl *This,ULONG ulAngle); - void __RPC_STUB IDvdControl_AngleChange_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl_ParentalLevelSelect_Proxy(IDvdControl *This,ULONG ulParentalLevel); - void __RPC_STUB IDvdControl_ParentalLevelSelect_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl_ParentalCountrySelect_Proxy(IDvdControl *This,WORD wCountry); - void __RPC_STUB IDvdControl_ParentalCountrySelect_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl_KaraokeAudioPresentationModeChange_Proxy(IDvdControl *This,ULONG ulMode); - void __RPC_STUB IDvdControl_KaraokeAudioPresentationModeChange_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl_VideoModePreferrence_Proxy(IDvdControl *This,ULONG ulPreferredDisplayMode); - void __RPC_STUB IDvdControl_VideoModePreferrence_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl_SetRoot_Proxy(IDvdControl *This,LPCWSTR pszPath); - void __RPC_STUB IDvdControl_SetRoot_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl_MouseActivate_Proxy(IDvdControl *This,POINT point); - void __RPC_STUB IDvdControl_MouseActivate_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl_MouseSelect_Proxy(IDvdControl *This,POINT point); - void __RPC_STUB IDvdControl_MouseSelect_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl_ChapterPlayAutoStop_Proxy(IDvdControl *This,ULONG ulTitle,ULONG ulChapter,ULONG ulChaptersToPlay); - void __RPC_STUB IDvdControl_ChapterPlayAutoStop_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IDvdInfo_INTERFACE_DEFINED__ -#define __IDvdInfo_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IDvdInfo; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IDvdInfo : public IUnknown { - public: - virtual HRESULT WINAPI GetCurrentDomain(DVD_DOMAIN *pDomain) = 0; - virtual HRESULT WINAPI GetCurrentLocation(DVD_PLAYBACK_LOCATION *pLocation) = 0; - virtual HRESULT WINAPI GetTotalTitleTime(ULONG *pulTotalTime) = 0; - virtual HRESULT WINAPI GetCurrentButton(ULONG *pulButtonsAvailable,ULONG *pulCurrentButton) = 0; - virtual HRESULT WINAPI GetCurrentAngle(ULONG *pulAnglesAvailable,ULONG *pulCurrentAngle) = 0; - virtual HRESULT WINAPI GetCurrentAudio(ULONG *pulStreamsAvailable,ULONG *pulCurrentStream) = 0; - virtual HRESULT WINAPI GetCurrentSubpicture(ULONG *pulStreamsAvailable,ULONG *pulCurrentStream,WINBOOL *pIsDisabled) = 0; - virtual HRESULT WINAPI GetCurrentUOPS(VALID_UOP_SOMTHING_OR_OTHER *pUOP) = 0; - virtual HRESULT WINAPI GetAllSPRMs(SPRMARRAY *pRegisterArray) = 0; - virtual HRESULT WINAPI GetAllGPRMs(GPRMARRAY *pRegisterArray) = 0; - virtual HRESULT WINAPI GetAudioLanguage(ULONG ulStream,LCID *pLanguage) = 0; - virtual HRESULT WINAPI GetSubpictureLanguage(ULONG ulStream,LCID *pLanguage) = 0; - virtual HRESULT WINAPI GetTitleAttributes(ULONG ulTitle,DVD_ATR *pATR) = 0; - virtual HRESULT WINAPI GetVMGAttributes(DVD_ATR *pATR) = 0; - virtual HRESULT WINAPI GetCurrentVideoAttributes(DVD_VideoATR *pATR) = 0; - virtual HRESULT WINAPI GetCurrentAudioAttributes(DVD_AudioATR *pATR) = 0; - virtual HRESULT WINAPI GetCurrentSubpictureAttributes(DVD_SubpictureATR *pATR) = 0; - virtual HRESULT WINAPI GetCurrentVolumeInfo(ULONG *pulNumOfVol,ULONG *pulThisVolNum,DVD_DISC_SIDE *pSide,ULONG *pulNumOfTitles) = 0; - virtual HRESULT WINAPI GetDVDTextInfo(BYTE *pTextManager,ULONG ulBufSize,ULONG *pulActualSize) = 0; - virtual HRESULT WINAPI GetPlayerParentalLevel(ULONG *pulParentalLevel,ULONG *pulCountryCode) = 0; - virtual HRESULT WINAPI GetNumberOfChapters(ULONG ulTitle,ULONG *pulNumberOfChapters) = 0; - virtual HRESULT WINAPI GetTitleParentalLevels(ULONG ulTitle,ULONG *pulParentalLevels) = 0; - virtual HRESULT WINAPI GetRoot(LPSTR pRoot,ULONG ulBufSize,ULONG *pulActualSize) = 0; - }; -#else - typedef struct IDvdInfoVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IDvdInfo *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IDvdInfo *This); - ULONG (WINAPI *Release)(IDvdInfo *This); - HRESULT (WINAPI *GetCurrentDomain)(IDvdInfo *This,DVD_DOMAIN *pDomain); - HRESULT (WINAPI *GetCurrentLocation)(IDvdInfo *This,DVD_PLAYBACK_LOCATION *pLocation); - HRESULT (WINAPI *GetTotalTitleTime)(IDvdInfo *This,ULONG *pulTotalTime); - HRESULT (WINAPI *GetCurrentButton)(IDvdInfo *This,ULONG *pulButtonsAvailable,ULONG *pulCurrentButton); - HRESULT (WINAPI *GetCurrentAngle)(IDvdInfo *This,ULONG *pulAnglesAvailable,ULONG *pulCurrentAngle); - HRESULT (WINAPI *GetCurrentAudio)(IDvdInfo *This,ULONG *pulStreamsAvailable,ULONG *pulCurrentStream); - HRESULT (WINAPI *GetCurrentSubpicture)(IDvdInfo *This,ULONG *pulStreamsAvailable,ULONG *pulCurrentStream,WINBOOL *pIsDisabled); - HRESULT (WINAPI *GetCurrentUOPS)(IDvdInfo *This,VALID_UOP_SOMTHING_OR_OTHER *pUOP); - HRESULT (WINAPI *GetAllSPRMs)(IDvdInfo *This,SPRMARRAY *pRegisterArray); - HRESULT (WINAPI *GetAllGPRMs)(IDvdInfo *This,GPRMARRAY *pRegisterArray); - HRESULT (WINAPI *GetAudioLanguage)(IDvdInfo *This,ULONG ulStream,LCID *pLanguage); - HRESULT (WINAPI *GetSubpictureLanguage)(IDvdInfo *This,ULONG ulStream,LCID *pLanguage); - HRESULT (WINAPI *GetTitleAttributes)(IDvdInfo *This,ULONG ulTitle,DVD_ATR *pATR); - HRESULT (WINAPI *GetVMGAttributes)(IDvdInfo *This,DVD_ATR *pATR); - HRESULT (WINAPI *GetCurrentVideoAttributes)(IDvdInfo *This,DVD_VideoATR *pATR); - HRESULT (WINAPI *GetCurrentAudioAttributes)(IDvdInfo *This,DVD_AudioATR *pATR); - HRESULT (WINAPI *GetCurrentSubpictureAttributes)(IDvdInfo *This,DVD_SubpictureATR *pATR); - HRESULT (WINAPI *GetCurrentVolumeInfo)(IDvdInfo *This,ULONG *pulNumOfVol,ULONG *pulThisVolNum,DVD_DISC_SIDE *pSide,ULONG *pulNumOfTitles); - HRESULT (WINAPI *GetDVDTextInfo)(IDvdInfo *This,BYTE *pTextManager,ULONG ulBufSize,ULONG *pulActualSize); - HRESULT (WINAPI *GetPlayerParentalLevel)(IDvdInfo *This,ULONG *pulParentalLevel,ULONG *pulCountryCode); - HRESULT (WINAPI *GetNumberOfChapters)(IDvdInfo *This,ULONG ulTitle,ULONG *pulNumberOfChapters); - HRESULT (WINAPI *GetTitleParentalLevels)(IDvdInfo *This,ULONG ulTitle,ULONG *pulParentalLevels); - HRESULT (WINAPI *GetRoot)(IDvdInfo *This,LPSTR pRoot,ULONG ulBufSize,ULONG *pulActualSize); - END_INTERFACE - } IDvdInfoVtbl; - struct IDvdInfo { - CONST_VTBL struct IDvdInfoVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IDvdInfo_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IDvdInfo_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IDvdInfo_Release(This) (This)->lpVtbl->Release(This) -#define IDvdInfo_GetCurrentDomain(This,pDomain) (This)->lpVtbl->GetCurrentDomain(This,pDomain) -#define IDvdInfo_GetCurrentLocation(This,pLocation) (This)->lpVtbl->GetCurrentLocation(This,pLocation) -#define IDvdInfo_GetTotalTitleTime(This,pulTotalTime) (This)->lpVtbl->GetTotalTitleTime(This,pulTotalTime) -#define IDvdInfo_GetCurrentButton(This,pulButtonsAvailable,pulCurrentButton) (This)->lpVtbl->GetCurrentButton(This,pulButtonsAvailable,pulCurrentButton) -#define IDvdInfo_GetCurrentAngle(This,pulAnglesAvailable,pulCurrentAngle) (This)->lpVtbl->GetCurrentAngle(This,pulAnglesAvailable,pulCurrentAngle) -#define IDvdInfo_GetCurrentAudio(This,pulStreamsAvailable,pulCurrentStream) (This)->lpVtbl->GetCurrentAudio(This,pulStreamsAvailable,pulCurrentStream) -#define IDvdInfo_GetCurrentSubpicture(This,pulStreamsAvailable,pulCurrentStream,pIsDisabled) (This)->lpVtbl->GetCurrentSubpicture(This,pulStreamsAvailable,pulCurrentStream,pIsDisabled) -#define IDvdInfo_GetCurrentUOPS(This,pUOP) (This)->lpVtbl->GetCurrentUOPS(This,pUOP) -#define IDvdInfo_GetAllSPRMs(This,pRegisterArray) (This)->lpVtbl->GetAllSPRMs(This,pRegisterArray) -#define IDvdInfo_GetAllGPRMs(This,pRegisterArray) (This)->lpVtbl->GetAllGPRMs(This,pRegisterArray) -#define IDvdInfo_GetAudioLanguage(This,ulStream,pLanguage) (This)->lpVtbl->GetAudioLanguage(This,ulStream,pLanguage) -#define IDvdInfo_GetSubpictureLanguage(This,ulStream,pLanguage) (This)->lpVtbl->GetSubpictureLanguage(This,ulStream,pLanguage) -#define IDvdInfo_GetTitleAttributes(This,ulTitle,pATR) (This)->lpVtbl->GetTitleAttributes(This,ulTitle,pATR) -#define IDvdInfo_GetVMGAttributes(This,pATR) (This)->lpVtbl->GetVMGAttributes(This,pATR) -#define IDvdInfo_GetCurrentVideoAttributes(This,pATR) (This)->lpVtbl->GetCurrentVideoAttributes(This,pATR) -#define IDvdInfo_GetCurrentAudioAttributes(This,pATR) (This)->lpVtbl->GetCurrentAudioAttributes(This,pATR) -#define IDvdInfo_GetCurrentSubpictureAttributes(This,pATR) (This)->lpVtbl->GetCurrentSubpictureAttributes(This,pATR) -#define IDvdInfo_GetCurrentVolumeInfo(This,pulNumOfVol,pulThisVolNum,pSide,pulNumOfTitles) (This)->lpVtbl->GetCurrentVolumeInfo(This,pulNumOfVol,pulThisVolNum,pSide,pulNumOfTitles) -#define IDvdInfo_GetDVDTextInfo(This,pTextManager,ulBufSize,pulActualSize) (This)->lpVtbl->GetDVDTextInfo(This,pTextManager,ulBufSize,pulActualSize) -#define IDvdInfo_GetPlayerParentalLevel(This,pulParentalLevel,pulCountryCode) (This)->lpVtbl->GetPlayerParentalLevel(This,pulParentalLevel,pulCountryCode) -#define IDvdInfo_GetNumberOfChapters(This,ulTitle,pulNumberOfChapters) (This)->lpVtbl->GetNumberOfChapters(This,ulTitle,pulNumberOfChapters) -#define IDvdInfo_GetTitleParentalLevels(This,ulTitle,pulParentalLevels) (This)->lpVtbl->GetTitleParentalLevels(This,ulTitle,pulParentalLevels) -#define IDvdInfo_GetRoot(This,pRoot,ulBufSize,pulActualSize) (This)->lpVtbl->GetRoot(This,pRoot,ulBufSize,pulActualSize) -#endif -#endif - HRESULT WINAPI IDvdInfo_GetCurrentDomain_Proxy(IDvdInfo *This,DVD_DOMAIN *pDomain); - void __RPC_STUB IDvdInfo_GetCurrentDomain_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdInfo_GetCurrentLocation_Proxy(IDvdInfo *This,DVD_PLAYBACK_LOCATION *pLocation); - void __RPC_STUB IDvdInfo_GetCurrentLocation_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdInfo_GetTotalTitleTime_Proxy(IDvdInfo *This,ULONG *pulTotalTime); - void __RPC_STUB IDvdInfo_GetTotalTitleTime_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdInfo_GetCurrentButton_Proxy(IDvdInfo *This,ULONG *pulButtonsAvailable,ULONG *pulCurrentButton); - void __RPC_STUB IDvdInfo_GetCurrentButton_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdInfo_GetCurrentAngle_Proxy(IDvdInfo *This,ULONG *pulAnglesAvailable,ULONG *pulCurrentAngle); - void __RPC_STUB IDvdInfo_GetCurrentAngle_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdInfo_GetCurrentAudio_Proxy(IDvdInfo *This,ULONG *pulStreamsAvailable,ULONG *pulCurrentStream); - void __RPC_STUB IDvdInfo_GetCurrentAudio_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdInfo_GetCurrentSubpicture_Proxy(IDvdInfo *This,ULONG *pulStreamsAvailable,ULONG *pulCurrentStream,WINBOOL *pIsDisabled); - void __RPC_STUB IDvdInfo_GetCurrentSubpicture_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdInfo_GetCurrentUOPS_Proxy(IDvdInfo *This,VALID_UOP_SOMTHING_OR_OTHER *pUOP); - void __RPC_STUB IDvdInfo_GetCurrentUOPS_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdInfo_GetAllSPRMs_Proxy(IDvdInfo *This,SPRMARRAY *pRegisterArray); - void __RPC_STUB IDvdInfo_GetAllSPRMs_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdInfo_GetAllGPRMs_Proxy(IDvdInfo *This,GPRMARRAY *pRegisterArray); - void __RPC_STUB IDvdInfo_GetAllGPRMs_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdInfo_GetAudioLanguage_Proxy(IDvdInfo *This,ULONG ulStream,LCID *pLanguage); - void __RPC_STUB IDvdInfo_GetAudioLanguage_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdInfo_GetSubpictureLanguage_Proxy(IDvdInfo *This,ULONG ulStream,LCID *pLanguage); - void __RPC_STUB IDvdInfo_GetSubpictureLanguage_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdInfo_GetTitleAttributes_Proxy(IDvdInfo *This,ULONG ulTitle,DVD_ATR *pATR); - void __RPC_STUB IDvdInfo_GetTitleAttributes_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdInfo_GetVMGAttributes_Proxy(IDvdInfo *This,DVD_ATR *pATR); - void __RPC_STUB IDvdInfo_GetVMGAttributes_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdInfo_GetCurrentVideoAttributes_Proxy(IDvdInfo *This,DVD_VideoATR *pATR); - void __RPC_STUB IDvdInfo_GetCurrentVideoAttributes_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdInfo_GetCurrentAudioAttributes_Proxy(IDvdInfo *This,DVD_AudioATR *pATR); - void __RPC_STUB IDvdInfo_GetCurrentAudioAttributes_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdInfo_GetCurrentSubpictureAttributes_Proxy(IDvdInfo *This,DVD_SubpictureATR *pATR); - void __RPC_STUB IDvdInfo_GetCurrentSubpictureAttributes_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdInfo_GetCurrentVolumeInfo_Proxy(IDvdInfo *This,ULONG *pulNumOfVol,ULONG *pulThisVolNum,DVD_DISC_SIDE *pSide,ULONG *pulNumOfTitles); - void __RPC_STUB IDvdInfo_GetCurrentVolumeInfo_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdInfo_GetDVDTextInfo_Proxy(IDvdInfo *This,BYTE *pTextManager,ULONG ulBufSize,ULONG *pulActualSize); - void __RPC_STUB IDvdInfo_GetDVDTextInfo_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdInfo_GetPlayerParentalLevel_Proxy(IDvdInfo *This,ULONG *pulParentalLevel,ULONG *pulCountryCode); - void __RPC_STUB IDvdInfo_GetPlayerParentalLevel_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdInfo_GetNumberOfChapters_Proxy(IDvdInfo *This,ULONG ulTitle,ULONG *pulNumberOfChapters); - void __RPC_STUB IDvdInfo_GetNumberOfChapters_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdInfo_GetTitleParentalLevels_Proxy(IDvdInfo *This,ULONG ulTitle,ULONG *pulParentalLevels); - void __RPC_STUB IDvdInfo_GetTitleParentalLevels_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdInfo_GetRoot_Proxy(IDvdInfo *This,LPSTR pRoot,ULONG ulBufSize,ULONG *pulActualSize); - void __RPC_STUB IDvdInfo_GetRoot_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IDvdCmd_INTERFACE_DEFINED__ -#define __IDvdCmd_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IDvdCmd; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IDvdCmd : public IUnknown { - public: - virtual HRESULT WINAPI WaitForStart(void) = 0; - virtual HRESULT WINAPI WaitForEnd(void) = 0; - }; -#else - typedef struct IDvdCmdVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IDvdCmd *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IDvdCmd *This); - ULONG (WINAPI *Release)(IDvdCmd *This); - HRESULT (WINAPI *WaitForStart)(IDvdCmd *This); - HRESULT (WINAPI *WaitForEnd)(IDvdCmd *This); - END_INTERFACE - } IDvdCmdVtbl; - struct IDvdCmd { - CONST_VTBL struct IDvdCmdVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IDvdCmd_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IDvdCmd_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IDvdCmd_Release(This) (This)->lpVtbl->Release(This) -#define IDvdCmd_WaitForStart(This) (This)->lpVtbl->WaitForStart(This) -#define IDvdCmd_WaitForEnd(This) (This)->lpVtbl->WaitForEnd(This) -#endif -#endif - HRESULT WINAPI IDvdCmd_WaitForStart_Proxy(IDvdCmd *This); - void __RPC_STUB IDvdCmd_WaitForStart_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdCmd_WaitForEnd_Proxy(IDvdCmd *This); - void __RPC_STUB IDvdCmd_WaitForEnd_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IDvdState_INTERFACE_DEFINED__ -#define __IDvdState_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IDvdState; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IDvdState : public IUnknown { - public: - virtual HRESULT WINAPI GetDiscID(ULONGLONG *pullUniqueID) = 0; - virtual HRESULT WINAPI GetParentalLevel(ULONG *pulParentalLevel) = 0; - }; -#else - typedef struct IDvdStateVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IDvdState *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IDvdState *This); - ULONG (WINAPI *Release)(IDvdState *This); - HRESULT (WINAPI *GetDiscID)(IDvdState *This,ULONGLONG *pullUniqueID); - HRESULT (WINAPI *GetParentalLevel)(IDvdState *This,ULONG *pulParentalLevel); - END_INTERFACE - } IDvdStateVtbl; - struct IDvdState { - CONST_VTBL struct IDvdStateVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IDvdState_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IDvdState_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IDvdState_Release(This) (This)->lpVtbl->Release(This) -#define IDvdState_GetDiscID(This,pullUniqueID) (This)->lpVtbl->GetDiscID(This,pullUniqueID) -#define IDvdState_GetParentalLevel(This,pulParentalLevel) (This)->lpVtbl->GetParentalLevel(This,pulParentalLevel) -#endif -#endif - HRESULT WINAPI IDvdState_GetDiscID_Proxy(IDvdState *This,ULONGLONG *pullUniqueID); - void __RPC_STUB IDvdState_GetDiscID_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdState_GetParentalLevel_Proxy(IDvdState *This,ULONG *pulParentalLevel); - void __RPC_STUB IDvdState_GetParentalLevel_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IDvdControl2_INTERFACE_DEFINED__ -#define __IDvdControl2_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IDvdControl2; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IDvdControl2 : public IUnknown { - public: - virtual HRESULT WINAPI PlayTitle(ULONG ulTitle,DWORD dwFlags,IDvdCmd **ppCmd) = 0; - virtual HRESULT WINAPI PlayChapterInTitle(ULONG ulTitle,ULONG ulChapter,DWORD dwFlags,IDvdCmd **ppCmd) = 0; - virtual HRESULT WINAPI PlayAtTimeInTitle(ULONG ulTitle,DVD_HMSF_TIMECODE *pStartTime,DWORD dwFlags,IDvdCmd **ppCmd) = 0; - virtual HRESULT WINAPI Stop(void) = 0; - virtual HRESULT WINAPI ReturnFromSubmenu(DWORD dwFlags,IDvdCmd **ppCmd) = 0; - virtual HRESULT WINAPI PlayAtTime(DVD_HMSF_TIMECODE *pTime,DWORD dwFlags,IDvdCmd **ppCmd) = 0; - virtual HRESULT WINAPI PlayChapter(ULONG ulChapter,DWORD dwFlags,IDvdCmd **ppCmd) = 0; - virtual HRESULT WINAPI PlayPrevChapter(DWORD dwFlags,IDvdCmd **ppCmd) = 0; - virtual HRESULT WINAPI ReplayChapter(DWORD dwFlags,IDvdCmd **ppCmd) = 0; - virtual HRESULT WINAPI PlayNextChapter(DWORD dwFlags,IDvdCmd **ppCmd) = 0; - virtual HRESULT WINAPI PlayForwards(double dSpeed,DWORD dwFlags,IDvdCmd **ppCmd) = 0; - virtual HRESULT WINAPI PlayBackwards(double dSpeed,DWORD dwFlags,IDvdCmd **ppCmd) = 0; - virtual HRESULT WINAPI ShowMenu(DVD_MENU_ID MenuID,DWORD dwFlags,IDvdCmd **ppCmd) = 0; - virtual HRESULT WINAPI Resume(DWORD dwFlags,IDvdCmd **ppCmd) = 0; - virtual HRESULT WINAPI SelectRelativeButton(DVD_RELATIVE_BUTTON buttonDir) = 0; - virtual HRESULT WINAPI ActivateButton(void) = 0; - virtual HRESULT WINAPI SelectButton(ULONG ulButton) = 0; - virtual HRESULT WINAPI SelectAndActivateButton(ULONG ulButton) = 0; - virtual HRESULT WINAPI StillOff(void) = 0; - virtual HRESULT WINAPI Pause(WINBOOL bState) = 0; - virtual HRESULT WINAPI SelectAudioStream(ULONG ulAudio,DWORD dwFlags,IDvdCmd **ppCmd) = 0; - virtual HRESULT WINAPI SelectSubpictureStream(ULONG ulSubPicture,DWORD dwFlags,IDvdCmd **ppCmd) = 0; - virtual HRESULT WINAPI SetSubpictureState(WINBOOL bState,DWORD dwFlags,IDvdCmd **ppCmd) = 0; - virtual HRESULT WINAPI SelectAngle(ULONG ulAngle,DWORD dwFlags,IDvdCmd **ppCmd) = 0; - virtual HRESULT WINAPI SelectParentalLevel(ULONG ulParentalLevel) = 0; - virtual HRESULT WINAPI SelectParentalCountry(BYTE bCountry[2]) = 0; - virtual HRESULT WINAPI SelectKaraokeAudioPresentationMode(ULONG ulMode) = 0; - virtual HRESULT WINAPI SelectVideoModePreference(ULONG ulPreferredDisplayMode) = 0; - virtual HRESULT WINAPI SetDVDDirectory(LPCWSTR pszwPath) = 0; - virtual HRESULT WINAPI ActivateAtPosition(POINT point) = 0; - virtual HRESULT WINAPI SelectAtPosition(POINT point) = 0; - virtual HRESULT WINAPI PlayChaptersAutoStop(ULONG ulTitle,ULONG ulChapter,ULONG ulChaptersToPlay,DWORD dwFlags,IDvdCmd **ppCmd) = 0; - virtual HRESULT WINAPI AcceptParentalLevelChange(WINBOOL bAccept) = 0; - virtual HRESULT WINAPI SetOption(DVD_OPTION_FLAG flag,WINBOOL fState) = 0; - virtual HRESULT WINAPI SetState(IDvdState *pState,DWORD dwFlags,IDvdCmd **ppCmd) = 0; - virtual HRESULT WINAPI PlayPeriodInTitleAutoStop(ULONG ulTitle,DVD_HMSF_TIMECODE *pStartTime,DVD_HMSF_TIMECODE *pEndTime,DWORD dwFlags,IDvdCmd **ppCmd) = 0; - virtual HRESULT WINAPI SetGPRM(ULONG ulIndex,WORD wValue,DWORD dwFlags,IDvdCmd **ppCmd) = 0; - virtual HRESULT WINAPI SelectDefaultMenuLanguage(LCID Language) = 0; - virtual HRESULT WINAPI SelectDefaultAudioLanguage(LCID Language,DVD_AUDIO_LANG_EXT audioExtension) = 0; - virtual HRESULT WINAPI SelectDefaultSubpictureLanguage(LCID Language,DVD_SUBPICTURE_LANG_EXT subpictureExtension) = 0; - }; -#else - typedef struct IDvdControl2Vtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IDvdControl2 *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IDvdControl2 *This); - ULONG (WINAPI *Release)(IDvdControl2 *This); - HRESULT (WINAPI *PlayTitle)(IDvdControl2 *This,ULONG ulTitle,DWORD dwFlags,IDvdCmd **ppCmd); - HRESULT (WINAPI *PlayChapterInTitle)(IDvdControl2 *This,ULONG ulTitle,ULONG ulChapter,DWORD dwFlags,IDvdCmd **ppCmd); - HRESULT (WINAPI *PlayAtTimeInTitle)(IDvdControl2 *This,ULONG ulTitle,DVD_HMSF_TIMECODE *pStartTime,DWORD dwFlags,IDvdCmd **ppCmd); - HRESULT (WINAPI *Stop)(IDvdControl2 *This); - HRESULT (WINAPI *ReturnFromSubmenu)(IDvdControl2 *This,DWORD dwFlags,IDvdCmd **ppCmd); - HRESULT (WINAPI *PlayAtTime)(IDvdControl2 *This,DVD_HMSF_TIMECODE *pTime,DWORD dwFlags,IDvdCmd **ppCmd); - HRESULT (WINAPI *PlayChapter)(IDvdControl2 *This,ULONG ulChapter,DWORD dwFlags,IDvdCmd **ppCmd); - HRESULT (WINAPI *PlayPrevChapter)(IDvdControl2 *This,DWORD dwFlags,IDvdCmd **ppCmd); - HRESULT (WINAPI *ReplayChapter)(IDvdControl2 *This,DWORD dwFlags,IDvdCmd **ppCmd); - HRESULT (WINAPI *PlayNextChapter)(IDvdControl2 *This,DWORD dwFlags,IDvdCmd **ppCmd); - HRESULT (WINAPI *PlayForwards)(IDvdControl2 *This,double dSpeed,DWORD dwFlags,IDvdCmd **ppCmd); - HRESULT (WINAPI *PlayBackwards)(IDvdControl2 *This,double dSpeed,DWORD dwFlags,IDvdCmd **ppCmd); - HRESULT (WINAPI *ShowMenu)(IDvdControl2 *This,DVD_MENU_ID MenuID,DWORD dwFlags,IDvdCmd **ppCmd); - HRESULT (WINAPI *Resume)(IDvdControl2 *This,DWORD dwFlags,IDvdCmd **ppCmd); - HRESULT (WINAPI *SelectRelativeButton)(IDvdControl2 *This,DVD_RELATIVE_BUTTON buttonDir); - HRESULT (WINAPI *ActivateButton)(IDvdControl2 *This); - HRESULT (WINAPI *SelectButton)(IDvdControl2 *This,ULONG ulButton); - HRESULT (WINAPI *SelectAndActivateButton)(IDvdControl2 *This,ULONG ulButton); - HRESULT (WINAPI *StillOff)(IDvdControl2 *This); - HRESULT (WINAPI *Pause)(IDvdControl2 *This,WINBOOL bState); - HRESULT (WINAPI *SelectAudioStream)(IDvdControl2 *This,ULONG ulAudio,DWORD dwFlags,IDvdCmd **ppCmd); - HRESULT (WINAPI *SelectSubpictureStream)(IDvdControl2 *This,ULONG ulSubPicture,DWORD dwFlags,IDvdCmd **ppCmd); - HRESULT (WINAPI *SetSubpictureState)(IDvdControl2 *This,WINBOOL bState,DWORD dwFlags,IDvdCmd **ppCmd); - HRESULT (WINAPI *SelectAngle)(IDvdControl2 *This,ULONG ulAngle,DWORD dwFlags,IDvdCmd **ppCmd); - HRESULT (WINAPI *SelectParentalLevel)(IDvdControl2 *This,ULONG ulParentalLevel); - HRESULT (WINAPI *SelectParentalCountry)(IDvdControl2 *This,BYTE bCountry[2]); - HRESULT (WINAPI *SelectKaraokeAudioPresentationMode)(IDvdControl2 *This,ULONG ulMode); - HRESULT (WINAPI *SelectVideoModePreference)(IDvdControl2 *This,ULONG ulPreferredDisplayMode); - HRESULT (WINAPI *SetDVDDirectory)(IDvdControl2 *This,LPCWSTR pszwPath); - HRESULT (WINAPI *ActivateAtPosition)(IDvdControl2 *This,POINT point); - HRESULT (WINAPI *SelectAtPosition)(IDvdControl2 *This,POINT point); - HRESULT (WINAPI *PlayChaptersAutoStop)(IDvdControl2 *This,ULONG ulTitle,ULONG ulChapter,ULONG ulChaptersToPlay,DWORD dwFlags,IDvdCmd **ppCmd); - HRESULT (WINAPI *AcceptParentalLevelChange)(IDvdControl2 *This,WINBOOL bAccept); - HRESULT (WINAPI *SetOption)(IDvdControl2 *This,DVD_OPTION_FLAG flag,WINBOOL fState); - HRESULT (WINAPI *SetState)(IDvdControl2 *This,IDvdState *pState,DWORD dwFlags,IDvdCmd **ppCmd); - HRESULT (WINAPI *PlayPeriodInTitleAutoStop)(IDvdControl2 *This,ULONG ulTitle,DVD_HMSF_TIMECODE *pStartTime,DVD_HMSF_TIMECODE *pEndTime,DWORD dwFlags,IDvdCmd **ppCmd); - HRESULT (WINAPI *SetGPRM)(IDvdControl2 *This,ULONG ulIndex,WORD wValue,DWORD dwFlags,IDvdCmd **ppCmd); - HRESULT (WINAPI *SelectDefaultMenuLanguage)(IDvdControl2 *This,LCID Language); - HRESULT (WINAPI *SelectDefaultAudioLanguage)(IDvdControl2 *This,LCID Language,DVD_AUDIO_LANG_EXT audioExtension); - HRESULT (WINAPI *SelectDefaultSubpictureLanguage)(IDvdControl2 *This,LCID Language,DVD_SUBPICTURE_LANG_EXT subpictureExtension); - END_INTERFACE - } IDvdControl2Vtbl; - struct IDvdControl2 { - CONST_VTBL struct IDvdControl2Vtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IDvdControl2_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IDvdControl2_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IDvdControl2_Release(This) (This)->lpVtbl->Release(This) -#define IDvdControl2_PlayTitle(This,ulTitle,dwFlags,ppCmd) (This)->lpVtbl->PlayTitle(This,ulTitle,dwFlags,ppCmd) -#define IDvdControl2_PlayChapterInTitle(This,ulTitle,ulChapter,dwFlags,ppCmd) (This)->lpVtbl->PlayChapterInTitle(This,ulTitle,ulChapter,dwFlags,ppCmd) -#define IDvdControl2_PlayAtTimeInTitle(This,ulTitle,pStartTime,dwFlags,ppCmd) (This)->lpVtbl->PlayAtTimeInTitle(This,ulTitle,pStartTime,dwFlags,ppCmd) -#define IDvdControl2_Stop(This) (This)->lpVtbl->Stop(This) -#define IDvdControl2_ReturnFromSubmenu(This,dwFlags,ppCmd) (This)->lpVtbl->ReturnFromSubmenu(This,dwFlags,ppCmd) -#define IDvdControl2_PlayAtTime(This,pTime,dwFlags,ppCmd) (This)->lpVtbl->PlayAtTime(This,pTime,dwFlags,ppCmd) -#define IDvdControl2_PlayChapter(This,ulChapter,dwFlags,ppCmd) (This)->lpVtbl->PlayChapter(This,ulChapter,dwFlags,ppCmd) -#define IDvdControl2_PlayPrevChapter(This,dwFlags,ppCmd) (This)->lpVtbl->PlayPrevChapter(This,dwFlags,ppCmd) -#define IDvdControl2_ReplayChapter(This,dwFlags,ppCmd) (This)->lpVtbl->ReplayChapter(This,dwFlags,ppCmd) -#define IDvdControl2_PlayNextChapter(This,dwFlags,ppCmd) (This)->lpVtbl->PlayNextChapter(This,dwFlags,ppCmd) -#define IDvdControl2_PlayForwards(This,dSpeed,dwFlags,ppCmd) (This)->lpVtbl->PlayForwards(This,dSpeed,dwFlags,ppCmd) -#define IDvdControl2_PlayBackwards(This,dSpeed,dwFlags,ppCmd) (This)->lpVtbl->PlayBackwards(This,dSpeed,dwFlags,ppCmd) -#define IDvdControl2_ShowMenu(This,MenuID,dwFlags,ppCmd) (This)->lpVtbl->ShowMenu(This,MenuID,dwFlags,ppCmd) -#define IDvdControl2_Resume(This,dwFlags,ppCmd) (This)->lpVtbl->Resume(This,dwFlags,ppCmd) -#define IDvdControl2_SelectRelativeButton(This,buttonDir) (This)->lpVtbl->SelectRelativeButton(This,buttonDir) -#define IDvdControl2_ActivateButton(This) (This)->lpVtbl->ActivateButton(This) -#define IDvdControl2_SelectButton(This,ulButton) (This)->lpVtbl->SelectButton(This,ulButton) -#define IDvdControl2_SelectAndActivateButton(This,ulButton) (This)->lpVtbl->SelectAndActivateButton(This,ulButton) -#define IDvdControl2_StillOff(This) (This)->lpVtbl->StillOff(This) -#define IDvdControl2_Pause(This,bState) (This)->lpVtbl->Pause(This,bState) -#define IDvdControl2_SelectAudioStream(This,ulAudio,dwFlags,ppCmd) (This)->lpVtbl->SelectAudioStream(This,ulAudio,dwFlags,ppCmd) -#define IDvdControl2_SelectSubpictureStream(This,ulSubPicture,dwFlags,ppCmd) (This)->lpVtbl->SelectSubpictureStream(This,ulSubPicture,dwFlags,ppCmd) -#define IDvdControl2_SetSubpictureState(This,bState,dwFlags,ppCmd) (This)->lpVtbl->SetSubpictureState(This,bState,dwFlags,ppCmd) -#define IDvdControl2_SelectAngle(This,ulAngle,dwFlags,ppCmd) (This)->lpVtbl->SelectAngle(This,ulAngle,dwFlags,ppCmd) -#define IDvdControl2_SelectParentalLevel(This,ulParentalLevel) (This)->lpVtbl->SelectParentalLevel(This,ulParentalLevel) -#define IDvdControl2_SelectParentalCountry(This,bCountry) (This)->lpVtbl->SelectParentalCountry(This,bCountry) -#define IDvdControl2_SelectKaraokeAudioPresentationMode(This,ulMode) (This)->lpVtbl->SelectKaraokeAudioPresentationMode(This,ulMode) -#define IDvdControl2_SelectVideoModePreference(This,ulPreferredDisplayMode) (This)->lpVtbl->SelectVideoModePreference(This,ulPreferredDisplayMode) -#define IDvdControl2_SetDVDDirectory(This,pszwPath) (This)->lpVtbl->SetDVDDirectory(This,pszwPath) -#define IDvdControl2_ActivateAtPosition(This,point) (This)->lpVtbl->ActivateAtPosition(This,point) -#define IDvdControl2_SelectAtPosition(This,point) (This)->lpVtbl->SelectAtPosition(This,point) -#define IDvdControl2_PlayChaptersAutoStop(This,ulTitle,ulChapter,ulChaptersToPlay,dwFlags,ppCmd) (This)->lpVtbl->PlayChaptersAutoStop(This,ulTitle,ulChapter,ulChaptersToPlay,dwFlags,ppCmd) -#define IDvdControl2_AcceptParentalLevelChange(This,bAccept) (This)->lpVtbl->AcceptParentalLevelChange(This,bAccept) -#define IDvdControl2_SetOption(This,flag,fState) (This)->lpVtbl->SetOption(This,flag,fState) -#define IDvdControl2_SetState(This,pState,dwFlags,ppCmd) (This)->lpVtbl->SetState(This,pState,dwFlags,ppCmd) -#define IDvdControl2_PlayPeriodInTitleAutoStop(This,ulTitle,pStartTime,pEndTime,dwFlags,ppCmd) (This)->lpVtbl->PlayPeriodInTitleAutoStop(This,ulTitle,pStartTime,pEndTime,dwFlags,ppCmd) -#define IDvdControl2_SetGPRM(This,ulIndex,wValue,dwFlags,ppCmd) (This)->lpVtbl->SetGPRM(This,ulIndex,wValue,dwFlags,ppCmd) -#define IDvdControl2_SelectDefaultMenuLanguage(This,Language) (This)->lpVtbl->SelectDefaultMenuLanguage(This,Language) -#define IDvdControl2_SelectDefaultAudioLanguage(This,Language,audioExtension) (This)->lpVtbl->SelectDefaultAudioLanguage(This,Language,audioExtension) -#define IDvdControl2_SelectDefaultSubpictureLanguage(This,Language,subpictureExtension) (This)->lpVtbl->SelectDefaultSubpictureLanguage(This,Language,subpictureExtension) -#endif -#endif - HRESULT WINAPI IDvdControl2_PlayTitle_Proxy(IDvdControl2 *This,ULONG ulTitle,DWORD dwFlags,IDvdCmd **ppCmd); - void __RPC_STUB IDvdControl2_PlayTitle_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl2_PlayChapterInTitle_Proxy(IDvdControl2 *This,ULONG ulTitle,ULONG ulChapter,DWORD dwFlags,IDvdCmd **ppCmd); - void __RPC_STUB IDvdControl2_PlayChapterInTitle_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl2_PlayAtTimeInTitle_Proxy(IDvdControl2 *This,ULONG ulTitle,DVD_HMSF_TIMECODE *pStartTime,DWORD dwFlags,IDvdCmd **ppCmd); - void __RPC_STUB IDvdControl2_PlayAtTimeInTitle_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl2_Stop_Proxy(IDvdControl2 *This); - void __RPC_STUB IDvdControl2_Stop_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl2_ReturnFromSubmenu_Proxy(IDvdControl2 *This,DWORD dwFlags,IDvdCmd **ppCmd); - void __RPC_STUB IDvdControl2_ReturnFromSubmenu_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl2_PlayAtTime_Proxy(IDvdControl2 *This,DVD_HMSF_TIMECODE *pTime,DWORD dwFlags,IDvdCmd **ppCmd); - void __RPC_STUB IDvdControl2_PlayAtTime_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl2_PlayChapter_Proxy(IDvdControl2 *This,ULONG ulChapter,DWORD dwFlags,IDvdCmd **ppCmd); - void __RPC_STUB IDvdControl2_PlayChapter_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl2_PlayPrevChapter_Proxy(IDvdControl2 *This,DWORD dwFlags,IDvdCmd **ppCmd); - void __RPC_STUB IDvdControl2_PlayPrevChapter_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl2_ReplayChapter_Proxy(IDvdControl2 *This,DWORD dwFlags,IDvdCmd **ppCmd); - void __RPC_STUB IDvdControl2_ReplayChapter_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl2_PlayNextChapter_Proxy(IDvdControl2 *This,DWORD dwFlags,IDvdCmd **ppCmd); - void __RPC_STUB IDvdControl2_PlayNextChapter_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl2_PlayForwards_Proxy(IDvdControl2 *This,double dSpeed,DWORD dwFlags,IDvdCmd **ppCmd); - void __RPC_STUB IDvdControl2_PlayForwards_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl2_PlayBackwards_Proxy(IDvdControl2 *This,double dSpeed,DWORD dwFlags,IDvdCmd **ppCmd); - void __RPC_STUB IDvdControl2_PlayBackwards_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl2_ShowMenu_Proxy(IDvdControl2 *This,DVD_MENU_ID MenuID,DWORD dwFlags,IDvdCmd **ppCmd); - void __RPC_STUB IDvdControl2_ShowMenu_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl2_Resume_Proxy(IDvdControl2 *This,DWORD dwFlags,IDvdCmd **ppCmd); - void __RPC_STUB IDvdControl2_Resume_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl2_SelectRelativeButton_Proxy(IDvdControl2 *This,DVD_RELATIVE_BUTTON buttonDir); - void __RPC_STUB IDvdControl2_SelectRelativeButton_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl2_ActivateButton_Proxy(IDvdControl2 *This); - void __RPC_STUB IDvdControl2_ActivateButton_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl2_SelectButton_Proxy(IDvdControl2 *This,ULONG ulButton); - void __RPC_STUB IDvdControl2_SelectButton_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl2_SelectAndActivateButton_Proxy(IDvdControl2 *This,ULONG ulButton); - void __RPC_STUB IDvdControl2_SelectAndActivateButton_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl2_StillOff_Proxy(IDvdControl2 *This); - void __RPC_STUB IDvdControl2_StillOff_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl2_Pause_Proxy(IDvdControl2 *This,WINBOOL bState); - void __RPC_STUB IDvdControl2_Pause_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl2_SelectAudioStream_Proxy(IDvdControl2 *This,ULONG ulAudio,DWORD dwFlags,IDvdCmd **ppCmd); - void __RPC_STUB IDvdControl2_SelectAudioStream_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl2_SelectSubpictureStream_Proxy(IDvdControl2 *This,ULONG ulSubPicture,DWORD dwFlags,IDvdCmd **ppCmd); - void __RPC_STUB IDvdControl2_SelectSubpictureStream_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl2_SetSubpictureState_Proxy(IDvdControl2 *This,WINBOOL bState,DWORD dwFlags,IDvdCmd **ppCmd); - void __RPC_STUB IDvdControl2_SetSubpictureState_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl2_SelectAngle_Proxy(IDvdControl2 *This,ULONG ulAngle,DWORD dwFlags,IDvdCmd **ppCmd); - void __RPC_STUB IDvdControl2_SelectAngle_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl2_SelectParentalLevel_Proxy(IDvdControl2 *This,ULONG ulParentalLevel); - void __RPC_STUB IDvdControl2_SelectParentalLevel_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl2_SelectParentalCountry_Proxy(IDvdControl2 *This,BYTE bCountry[2]); - void __RPC_STUB IDvdControl2_SelectParentalCountry_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl2_SelectKaraokeAudioPresentationMode_Proxy(IDvdControl2 *This,ULONG ulMode); - void __RPC_STUB IDvdControl2_SelectKaraokeAudioPresentationMode_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl2_SelectVideoModePreference_Proxy(IDvdControl2 *This,ULONG ulPreferredDisplayMode); - void __RPC_STUB IDvdControl2_SelectVideoModePreference_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl2_SetDVDDirectory_Proxy(IDvdControl2 *This,LPCWSTR pszwPath); - void __RPC_STUB IDvdControl2_SetDVDDirectory_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl2_ActivateAtPosition_Proxy(IDvdControl2 *This,POINT point); - void __RPC_STUB IDvdControl2_ActivateAtPosition_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl2_SelectAtPosition_Proxy(IDvdControl2 *This,POINT point); - void __RPC_STUB IDvdControl2_SelectAtPosition_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl2_PlayChaptersAutoStop_Proxy(IDvdControl2 *This,ULONG ulTitle,ULONG ulChapter,ULONG ulChaptersToPlay,DWORD dwFlags,IDvdCmd **ppCmd); - void __RPC_STUB IDvdControl2_PlayChaptersAutoStop_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl2_AcceptParentalLevelChange_Proxy(IDvdControl2 *This,WINBOOL bAccept); - void __RPC_STUB IDvdControl2_AcceptParentalLevelChange_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl2_SetOption_Proxy(IDvdControl2 *This,DVD_OPTION_FLAG flag,WINBOOL fState); - void __RPC_STUB IDvdControl2_SetOption_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl2_SetState_Proxy(IDvdControl2 *This,IDvdState *pState,DWORD dwFlags,IDvdCmd **ppCmd); - void __RPC_STUB IDvdControl2_SetState_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl2_PlayPeriodInTitleAutoStop_Proxy(IDvdControl2 *This,ULONG ulTitle,DVD_HMSF_TIMECODE *pStartTime,DVD_HMSF_TIMECODE *pEndTime,DWORD dwFlags,IDvdCmd **ppCmd); - void __RPC_STUB IDvdControl2_PlayPeriodInTitleAutoStop_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl2_SetGPRM_Proxy(IDvdControl2 *This,ULONG ulIndex,WORD wValue,DWORD dwFlags,IDvdCmd **ppCmd); - void __RPC_STUB IDvdControl2_SetGPRM_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl2_SelectDefaultMenuLanguage_Proxy(IDvdControl2 *This,LCID Language); - void __RPC_STUB IDvdControl2_SelectDefaultMenuLanguage_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl2_SelectDefaultAudioLanguage_Proxy(IDvdControl2 *This,LCID Language,DVD_AUDIO_LANG_EXT audioExtension); - void __RPC_STUB IDvdControl2_SelectDefaultAudioLanguage_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdControl2_SelectDefaultSubpictureLanguage_Proxy(IDvdControl2 *This,LCID Language,DVD_SUBPICTURE_LANG_EXT subpictureExtension); - void __RPC_STUB IDvdControl2_SelectDefaultSubpictureLanguage_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - enum DVD_TextStringType { - DVD_Struct_Volume = 0x1,DVD_Struct_Title = 0x2,DVD_Struct_ParentalID = 0x3,DVD_Struct_PartOfTitle = 0x4,DVD_Struct_Cell = 0x5, - DVD_Stream_Audio = 0x10,DVD_Stream_Subpicture = 0x11,DVD_Stream_Angle = 0x12,DVD_Channel_Audio = 0x20,DVD_General_Name = 0x30, - DVD_General_Comments = 0x31,DVD_Title_Series = 0x38,DVD_Title_Movie = 0x39,DVD_Title_Video = 0x3a,DVD_Title_Album = 0x3b,DVD_Title_Song = 0x3c, - DVD_Title_Other = 0x3f,DVD_Title_Sub_Series = 0x40,DVD_Title_Sub_Movie = 0x41,DVD_Title_Sub_Video = 0x42,DVD_Title_Sub_Album = 0x43, - DVD_Title_Sub_Song = 0x44,DVD_Title_Sub_Other = 0x47,DVD_Title_Orig_Series = 0x48,DVD_Title_Orig_Movie = 0x49,DVD_Title_Orig_Video = 0x4a, - DVD_Title_Orig_Album = 0x4b,DVD_Title_Orig_Song = 0x4c,DVD_Title_Orig_Other = 0x4f,DVD_Other_Scene = 0x50,DVD_Other_Cut = 0x51,DVD_Other_Take = 0x52 - }; - - enum DVD_TextCharSet { - DVD_CharSet_Unicode = 0,DVD_CharSet_ISO646 = 1,DVD_CharSet_JIS_Roman_Kanji = 2,DVD_CharSet_ISO8859_1 = 3, - DVD_CharSet_ShiftJIS_Kanji_Roman_Katakana = 4 - }; -#define DVD_TITLE_MENU 0x000 -#define DVD_STREAM_DATA_CURRENT 0x800 -#define DVD_STREAM_DATA_VMGM 0x400 -#define DVD_STREAM_DATA_VTSM 0x401 -#define DVD_DEFAULT_AUDIO_STREAM 0x0f - - typedef struct tagDVD_DECODER_CAPS { - DWORD dwSize; - DWORD dwAudioCaps; - double dFwdMaxRateVideo; - double dFwdMaxRateAudio; - double dFwdMaxRateSP; - double dBwdMaxRateVideo; - double dBwdMaxRateAudio; - double dBwdMaxRateSP; - DWORD dwRes1; - DWORD dwRes2; - DWORD dwRes3; - DWORD dwRes4; - } DVD_DECODER_CAPS; - -#define DVD_AUDIO_CAPS_AC3 0x00000001 -#define DVD_AUDIO_CAPS_MPEG2 0x00000002 -#define DVD_AUDIO_CAPS_LPCM 0x00000004 -#define DVD_AUDIO_CAPS_DTS 0x00000008 -#define DVD_AUDIO_CAPS_SDDS 0x00000010 - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0387_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0387_v0_0_s_ifspec; -#ifndef __IDvdInfo2_INTERFACE_DEFINED__ -#define __IDvdInfo2_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IDvdInfo2; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IDvdInfo2 : public IUnknown { - public: - virtual HRESULT WINAPI GetCurrentDomain(DVD_DOMAIN *pDomain) = 0; - virtual HRESULT WINAPI GetCurrentLocation(DVD_PLAYBACK_LOCATION2 *pLocation) = 0; - virtual HRESULT WINAPI GetTotalTitleTime(DVD_HMSF_TIMECODE *pTotalTime,ULONG *ulTimeCodeFlags) = 0; - virtual HRESULT WINAPI GetCurrentButton(ULONG *pulButtonsAvailable,ULONG *pulCurrentButton) = 0; - virtual HRESULT WINAPI GetCurrentAngle(ULONG *pulAnglesAvailable,ULONG *pulCurrentAngle) = 0; - virtual HRESULT WINAPI GetCurrentAudio(ULONG *pulStreamsAvailable,ULONG *pulCurrentStream) = 0; - virtual HRESULT WINAPI GetCurrentSubpicture(ULONG *pulStreamsAvailable,ULONG *pulCurrentStream,WINBOOL *pbIsDisabled) = 0; - virtual HRESULT WINAPI GetCurrentUOPS(ULONG *pulUOPs) = 0; - virtual HRESULT WINAPI GetAllSPRMs(SPRMARRAY *pRegisterArray) = 0; - virtual HRESULT WINAPI GetAllGPRMs(GPRMARRAY *pRegisterArray) = 0; - virtual HRESULT WINAPI GetAudioLanguage(ULONG ulStream,LCID *pLanguage) = 0; - virtual HRESULT WINAPI GetSubpictureLanguage(ULONG ulStream,LCID *pLanguage) = 0; - virtual HRESULT WINAPI GetTitleAttributes(ULONG ulTitle,DVD_MenuAttributes *pMenu,DVD_TitleAttributes *pTitle) = 0; - virtual HRESULT WINAPI GetVMGAttributes(DVD_MenuAttributes *pATR) = 0; - virtual HRESULT WINAPI GetCurrentVideoAttributes(DVD_VideoAttributes *pATR) = 0; - virtual HRESULT WINAPI GetAudioAttributes(ULONG ulStream,DVD_AudioAttributes *pATR) = 0; - virtual HRESULT WINAPI GetKaraokeAttributes(ULONG ulStream,DVD_KaraokeAttributes *pAttributes) = 0; - virtual HRESULT WINAPI GetSubpictureAttributes(ULONG ulStream,DVD_SubpictureAttributes *pATR) = 0; - virtual HRESULT WINAPI GetDVDVolumeInfo(ULONG *pulNumOfVolumes,ULONG *pulVolume,DVD_DISC_SIDE *pSide,ULONG *pulNumOfTitles) = 0; - virtual HRESULT WINAPI GetDVDTextNumberOfLanguages(ULONG *pulNumOfLangs) = 0; - virtual HRESULT WINAPI GetDVDTextLanguageInfo(ULONG ulLangIndex,ULONG *pulNumOfStrings,LCID *pLangCode,enum DVD_TextCharSet *pbCharacterSet) = 0; - virtual HRESULT WINAPI GetDVDTextStringAsNative(ULONG ulLangIndex,ULONG ulStringIndex,BYTE *pbBuffer,ULONG ulMaxBufferSize,ULONG *pulActualSize,enum DVD_TextStringType *pType) = 0; - virtual HRESULT WINAPI GetDVDTextStringAsUnicode(ULONG ulLangIndex,ULONG ulStringIndex,WCHAR *pchwBuffer,ULONG ulMaxBufferSize,ULONG *pulActualSize,enum DVD_TextStringType *pType) = 0; - virtual HRESULT WINAPI GetPlayerParentalLevel(ULONG *pulParentalLevel,BYTE pbCountryCode[2]) = 0; - virtual HRESULT WINAPI GetNumberOfChapters(ULONG ulTitle,ULONG *pulNumOfChapters) = 0; - virtual HRESULT WINAPI GetTitleParentalLevels(ULONG ulTitle,ULONG *pulParentalLevels) = 0; - virtual HRESULT WINAPI GetDVDDirectory(LPWSTR pszwPath,ULONG ulMaxSize,ULONG *pulActualSize) = 0; - virtual HRESULT WINAPI IsAudioStreamEnabled(ULONG ulStreamNum,WINBOOL *pbEnabled) = 0; - virtual HRESULT WINAPI GetDiscID(LPCWSTR pszwPath,ULONGLONG *pullDiscID) = 0; - virtual HRESULT WINAPI GetState(IDvdState **pStateData) = 0; - virtual HRESULT WINAPI GetMenuLanguages(LCID *pLanguages,ULONG ulMaxLanguages,ULONG *pulActualLanguages) = 0; - virtual HRESULT WINAPI GetButtonAtPosition(POINT point,ULONG *pulButtonIndex) = 0; - virtual HRESULT WINAPI GetCmdFromEvent(LONG_PTR lParam1,IDvdCmd **pCmdObj) = 0; - virtual HRESULT WINAPI GetDefaultMenuLanguage(LCID *pLanguage) = 0; - virtual HRESULT WINAPI GetDefaultAudioLanguage(LCID *pLanguage,DVD_AUDIO_LANG_EXT *pAudioExtension) = 0; - virtual HRESULT WINAPI GetDefaultSubpictureLanguage(LCID *pLanguage,DVD_SUBPICTURE_LANG_EXT *pSubpictureExtension) = 0; - virtual HRESULT WINAPI GetDecoderCaps(DVD_DECODER_CAPS *pCaps) = 0; - virtual HRESULT WINAPI GetButtonRect(ULONG ulButton,RECT *pRect) = 0; - virtual HRESULT WINAPI IsSubpictureStreamEnabled(ULONG ulStreamNum,WINBOOL *pbEnabled) = 0; - }; -#else - typedef struct IDvdInfo2Vtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IDvdInfo2 *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IDvdInfo2 *This); - ULONG (WINAPI *Release)(IDvdInfo2 *This); - HRESULT (WINAPI *GetCurrentDomain)(IDvdInfo2 *This,DVD_DOMAIN *pDomain); - HRESULT (WINAPI *GetCurrentLocation)(IDvdInfo2 *This,DVD_PLAYBACK_LOCATION2 *pLocation); - HRESULT (WINAPI *GetTotalTitleTime)(IDvdInfo2 *This,DVD_HMSF_TIMECODE *pTotalTime,ULONG *ulTimeCodeFlags); - HRESULT (WINAPI *GetCurrentButton)(IDvdInfo2 *This,ULONG *pulButtonsAvailable,ULONG *pulCurrentButton); - HRESULT (WINAPI *GetCurrentAngle)(IDvdInfo2 *This,ULONG *pulAnglesAvailable,ULONG *pulCurrentAngle); - HRESULT (WINAPI *GetCurrentAudio)(IDvdInfo2 *This,ULONG *pulStreamsAvailable,ULONG *pulCurrentStream); - HRESULT (WINAPI *GetCurrentSubpicture)(IDvdInfo2 *This,ULONG *pulStreamsAvailable,ULONG *pulCurrentStream,WINBOOL *pbIsDisabled); - HRESULT (WINAPI *GetCurrentUOPS)(IDvdInfo2 *This,ULONG *pulUOPs); - HRESULT (WINAPI *GetAllSPRMs)(IDvdInfo2 *This,SPRMARRAY *pRegisterArray); - HRESULT (WINAPI *GetAllGPRMs)(IDvdInfo2 *This,GPRMARRAY *pRegisterArray); - HRESULT (WINAPI *GetAudioLanguage)(IDvdInfo2 *This,ULONG ulStream,LCID *pLanguage); - HRESULT (WINAPI *GetSubpictureLanguage)(IDvdInfo2 *This,ULONG ulStream,LCID *pLanguage); - HRESULT (WINAPI *GetTitleAttributes)(IDvdInfo2 *This,ULONG ulTitle,DVD_MenuAttributes *pMenu,DVD_TitleAttributes *pTitle); - HRESULT (WINAPI *GetVMGAttributes)(IDvdInfo2 *This,DVD_MenuAttributes *pATR); - HRESULT (WINAPI *GetCurrentVideoAttributes)(IDvdInfo2 *This,DVD_VideoAttributes *pATR); - HRESULT (WINAPI *GetAudioAttributes)(IDvdInfo2 *This,ULONG ulStream,DVD_AudioAttributes *pATR); - HRESULT (WINAPI *GetKaraokeAttributes)(IDvdInfo2 *This,ULONG ulStream,DVD_KaraokeAttributes *pAttributes); - HRESULT (WINAPI *GetSubpictureAttributes)(IDvdInfo2 *This,ULONG ulStream,DVD_SubpictureAttributes *pATR); - HRESULT (WINAPI *GetDVDVolumeInfo)(IDvdInfo2 *This,ULONG *pulNumOfVolumes,ULONG *pulVolume,DVD_DISC_SIDE *pSide,ULONG *pulNumOfTitles); - HRESULT (WINAPI *GetDVDTextNumberOfLanguages)(IDvdInfo2 *This,ULONG *pulNumOfLangs); - HRESULT (WINAPI *GetDVDTextLanguageInfo)(IDvdInfo2 *This,ULONG ulLangIndex,ULONG *pulNumOfStrings,LCID *pLangCode,enum DVD_TextCharSet *pbCharacterSet); - HRESULT (WINAPI *GetDVDTextStringAsNative)(IDvdInfo2 *This,ULONG ulLangIndex,ULONG ulStringIndex,BYTE *pbBuffer,ULONG ulMaxBufferSize,ULONG *pulActualSize,enum DVD_TextStringType *pType); - HRESULT (WINAPI *GetDVDTextStringAsUnicode)(IDvdInfo2 *This,ULONG ulLangIndex,ULONG ulStringIndex,WCHAR *pchwBuffer,ULONG ulMaxBufferSize,ULONG *pulActualSize,enum DVD_TextStringType *pType); - HRESULT (WINAPI *GetPlayerParentalLevel)(IDvdInfo2 *This,ULONG *pulParentalLevel,BYTE pbCountryCode[2]); - HRESULT (WINAPI *GetNumberOfChapters)(IDvdInfo2 *This,ULONG ulTitle,ULONG *pulNumOfChapters); - HRESULT (WINAPI *GetTitleParentalLevels)(IDvdInfo2 *This,ULONG ulTitle,ULONG *pulParentalLevels); - HRESULT (WINAPI *GetDVDDirectory)(IDvdInfo2 *This,LPWSTR pszwPath,ULONG ulMaxSize,ULONG *pulActualSize); - HRESULT (WINAPI *IsAudioStreamEnabled)(IDvdInfo2 *This,ULONG ulStreamNum,WINBOOL *pbEnabled); - HRESULT (WINAPI *GetDiscID)(IDvdInfo2 *This,LPCWSTR pszwPath,ULONGLONG *pullDiscID); - HRESULT (WINAPI *GetState)(IDvdInfo2 *This,IDvdState **pStateData); - HRESULT (WINAPI *GetMenuLanguages)(IDvdInfo2 *This,LCID *pLanguages,ULONG ulMaxLanguages,ULONG *pulActualLanguages); - HRESULT (WINAPI *GetButtonAtPosition)(IDvdInfo2 *This,POINT point,ULONG *pulButtonIndex); - HRESULT (WINAPI *GetCmdFromEvent)(IDvdInfo2 *This,LONG_PTR lParam1,IDvdCmd **pCmdObj); - HRESULT (WINAPI *GetDefaultMenuLanguage)(IDvdInfo2 *This,LCID *pLanguage); - HRESULT (WINAPI *GetDefaultAudioLanguage)(IDvdInfo2 *This,LCID *pLanguage,DVD_AUDIO_LANG_EXT *pAudioExtension); - HRESULT (WINAPI *GetDefaultSubpictureLanguage)(IDvdInfo2 *This,LCID *pLanguage,DVD_SUBPICTURE_LANG_EXT *pSubpictureExtension); - HRESULT (WINAPI *GetDecoderCaps)(IDvdInfo2 *This,DVD_DECODER_CAPS *pCaps); - HRESULT (WINAPI *GetButtonRect)(IDvdInfo2 *This,ULONG ulButton,RECT *pRect); - HRESULT (WINAPI *IsSubpictureStreamEnabled)(IDvdInfo2 *This,ULONG ulStreamNum,WINBOOL *pbEnabled); - END_INTERFACE - } IDvdInfo2Vtbl; - struct IDvdInfo2 { - CONST_VTBL struct IDvdInfo2Vtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IDvdInfo2_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IDvdInfo2_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IDvdInfo2_Release(This) (This)->lpVtbl->Release(This) -#define IDvdInfo2_GetCurrentDomain(This,pDomain) (This)->lpVtbl->GetCurrentDomain(This,pDomain) -#define IDvdInfo2_GetCurrentLocation(This,pLocation) (This)->lpVtbl->GetCurrentLocation(This,pLocation) -#define IDvdInfo2_GetTotalTitleTime(This,pTotalTime,ulTimeCodeFlags) (This)->lpVtbl->GetTotalTitleTime(This,pTotalTime,ulTimeCodeFlags) -#define IDvdInfo2_GetCurrentButton(This,pulButtonsAvailable,pulCurrentButton) (This)->lpVtbl->GetCurrentButton(This,pulButtonsAvailable,pulCurrentButton) -#define IDvdInfo2_GetCurrentAngle(This,pulAnglesAvailable,pulCurrentAngle) (This)->lpVtbl->GetCurrentAngle(This,pulAnglesAvailable,pulCurrentAngle) -#define IDvdInfo2_GetCurrentAudio(This,pulStreamsAvailable,pulCurrentStream) (This)->lpVtbl->GetCurrentAudio(This,pulStreamsAvailable,pulCurrentStream) -#define IDvdInfo2_GetCurrentSubpicture(This,pulStreamsAvailable,pulCurrentStream,pbIsDisabled) (This)->lpVtbl->GetCurrentSubpicture(This,pulStreamsAvailable,pulCurrentStream,pbIsDisabled) -#define IDvdInfo2_GetCurrentUOPS(This,pulUOPs) (This)->lpVtbl->GetCurrentUOPS(This,pulUOPs) -#define IDvdInfo2_GetAllSPRMs(This,pRegisterArray) (This)->lpVtbl->GetAllSPRMs(This,pRegisterArray) -#define IDvdInfo2_GetAllGPRMs(This,pRegisterArray) (This)->lpVtbl->GetAllGPRMs(This,pRegisterArray) -#define IDvdInfo2_GetAudioLanguage(This,ulStream,pLanguage) (This)->lpVtbl->GetAudioLanguage(This,ulStream,pLanguage) -#define IDvdInfo2_GetSubpictureLanguage(This,ulStream,pLanguage) (This)->lpVtbl->GetSubpictureLanguage(This,ulStream,pLanguage) -#define IDvdInfo2_GetTitleAttributes(This,ulTitle,pMenu,pTitle) (This)->lpVtbl->GetTitleAttributes(This,ulTitle,pMenu,pTitle) -#define IDvdInfo2_GetVMGAttributes(This,pATR) (This)->lpVtbl->GetVMGAttributes(This,pATR) -#define IDvdInfo2_GetCurrentVideoAttributes(This,pATR) (This)->lpVtbl->GetCurrentVideoAttributes(This,pATR) -#define IDvdInfo2_GetAudioAttributes(This,ulStream,pATR) (This)->lpVtbl->GetAudioAttributes(This,ulStream,pATR) -#define IDvdInfo2_GetKaraokeAttributes(This,ulStream,pAttributes) (This)->lpVtbl->GetKaraokeAttributes(This,ulStream,pAttributes) -#define IDvdInfo2_GetSubpictureAttributes(This,ulStream,pATR) (This)->lpVtbl->GetSubpictureAttributes(This,ulStream,pATR) -#define IDvdInfo2_GetDVDVolumeInfo(This,pulNumOfVolumes,pulVolume,pSide,pulNumOfTitles) (This)->lpVtbl->GetDVDVolumeInfo(This,pulNumOfVolumes,pulVolume,pSide,pulNumOfTitles) -#define IDvdInfo2_GetDVDTextNumberOfLanguages(This,pulNumOfLangs) (This)->lpVtbl->GetDVDTextNumberOfLanguages(This,pulNumOfLangs) -#define IDvdInfo2_GetDVDTextLanguageInfo(This,ulLangIndex,pulNumOfStrings,pLangCode,pbCharacterSet) (This)->lpVtbl->GetDVDTextLanguageInfo(This,ulLangIndex,pulNumOfStrings,pLangCode,pbCharacterSet) -#define IDvdInfo2_GetDVDTextStringAsNative(This,ulLangIndex,ulStringIndex,pbBuffer,ulMaxBufferSize,pulActualSize,pType) (This)->lpVtbl->GetDVDTextStringAsNative(This,ulLangIndex,ulStringIndex,pbBuffer,ulMaxBufferSize,pulActualSize,pType) -#define IDvdInfo2_GetDVDTextStringAsUnicode(This,ulLangIndex,ulStringIndex,pchwBuffer,ulMaxBufferSize,pulActualSize,pType) (This)->lpVtbl->GetDVDTextStringAsUnicode(This,ulLangIndex,ulStringIndex,pchwBuffer,ulMaxBufferSize,pulActualSize,pType) -#define IDvdInfo2_GetPlayerParentalLevel(This,pulParentalLevel,pbCountryCode) (This)->lpVtbl->GetPlayerParentalLevel(This,pulParentalLevel,pbCountryCode) -#define IDvdInfo2_GetNumberOfChapters(This,ulTitle,pulNumOfChapters) (This)->lpVtbl->GetNumberOfChapters(This,ulTitle,pulNumOfChapters) -#define IDvdInfo2_GetTitleParentalLevels(This,ulTitle,pulParentalLevels) (This)->lpVtbl->GetTitleParentalLevels(This,ulTitle,pulParentalLevels) -#define IDvdInfo2_GetDVDDirectory(This,pszwPath,ulMaxSize,pulActualSize) (This)->lpVtbl->GetDVDDirectory(This,pszwPath,ulMaxSize,pulActualSize) -#define IDvdInfo2_IsAudioStreamEnabled(This,ulStreamNum,pbEnabled) (This)->lpVtbl->IsAudioStreamEnabled(This,ulStreamNum,pbEnabled) -#define IDvdInfo2_GetDiscID(This,pszwPath,pullDiscID) (This)->lpVtbl->GetDiscID(This,pszwPath,pullDiscID) -#define IDvdInfo2_GetState(This,pStateData) (This)->lpVtbl->GetState(This,pStateData) -#define IDvdInfo2_GetMenuLanguages(This,pLanguages,ulMaxLanguages,pulActualLanguages) (This)->lpVtbl->GetMenuLanguages(This,pLanguages,ulMaxLanguages,pulActualLanguages) -#define IDvdInfo2_GetButtonAtPosition(This,point,pulButtonIndex) (This)->lpVtbl->GetButtonAtPosition(This,point,pulButtonIndex) -#define IDvdInfo2_GetCmdFromEvent(This,lParam1,pCmdObj) (This)->lpVtbl->GetCmdFromEvent(This,lParam1,pCmdObj) -#define IDvdInfo2_GetDefaultMenuLanguage(This,pLanguage) (This)->lpVtbl->GetDefaultMenuLanguage(This,pLanguage) -#define IDvdInfo2_GetDefaultAudioLanguage(This,pLanguage,pAudioExtension) (This)->lpVtbl->GetDefaultAudioLanguage(This,pLanguage,pAudioExtension) -#define IDvdInfo2_GetDefaultSubpictureLanguage(This,pLanguage,pSubpictureExtension) (This)->lpVtbl->GetDefaultSubpictureLanguage(This,pLanguage,pSubpictureExtension) -#define IDvdInfo2_GetDecoderCaps(This,pCaps) (This)->lpVtbl->GetDecoderCaps(This,pCaps) -#define IDvdInfo2_GetButtonRect(This,ulButton,pRect) (This)->lpVtbl->GetButtonRect(This,ulButton,pRect) -#define IDvdInfo2_IsSubpictureStreamEnabled(This,ulStreamNum,pbEnabled) (This)->lpVtbl->IsSubpictureStreamEnabled(This,ulStreamNum,pbEnabled) -#endif -#endif - HRESULT WINAPI IDvdInfo2_GetCurrentDomain_Proxy(IDvdInfo2 *This,DVD_DOMAIN *pDomain); - void __RPC_STUB IDvdInfo2_GetCurrentDomain_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdInfo2_GetCurrentLocation_Proxy(IDvdInfo2 *This,DVD_PLAYBACK_LOCATION2 *pLocation); - void __RPC_STUB IDvdInfo2_GetCurrentLocation_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdInfo2_GetTotalTitleTime_Proxy(IDvdInfo2 *This,DVD_HMSF_TIMECODE *pTotalTime,ULONG *ulTimeCodeFlags); - void __RPC_STUB IDvdInfo2_GetTotalTitleTime_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdInfo2_GetCurrentButton_Proxy(IDvdInfo2 *This,ULONG *pulButtonsAvailable,ULONG *pulCurrentButton); - void __RPC_STUB IDvdInfo2_GetCurrentButton_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdInfo2_GetCurrentAngle_Proxy(IDvdInfo2 *This,ULONG *pulAnglesAvailable,ULONG *pulCurrentAngle); - void __RPC_STUB IDvdInfo2_GetCurrentAngle_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdInfo2_GetCurrentAudio_Proxy(IDvdInfo2 *This,ULONG *pulStreamsAvailable,ULONG *pulCurrentStream); - void __RPC_STUB IDvdInfo2_GetCurrentAudio_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdInfo2_GetCurrentSubpicture_Proxy(IDvdInfo2 *This,ULONG *pulStreamsAvailable,ULONG *pulCurrentStream,WINBOOL *pbIsDisabled); - void __RPC_STUB IDvdInfo2_GetCurrentSubpicture_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdInfo2_GetCurrentUOPS_Proxy(IDvdInfo2 *This,ULONG *pulUOPs); - void __RPC_STUB IDvdInfo2_GetCurrentUOPS_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdInfo2_GetAllSPRMs_Proxy(IDvdInfo2 *This,SPRMARRAY *pRegisterArray); - void __RPC_STUB IDvdInfo2_GetAllSPRMs_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdInfo2_GetAllGPRMs_Proxy(IDvdInfo2 *This,GPRMARRAY *pRegisterArray); - void __RPC_STUB IDvdInfo2_GetAllGPRMs_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdInfo2_GetAudioLanguage_Proxy(IDvdInfo2 *This,ULONG ulStream,LCID *pLanguage); - void __RPC_STUB IDvdInfo2_GetAudioLanguage_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdInfo2_GetSubpictureLanguage_Proxy(IDvdInfo2 *This,ULONG ulStream,LCID *pLanguage); - void __RPC_STUB IDvdInfo2_GetSubpictureLanguage_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdInfo2_GetTitleAttributes_Proxy(IDvdInfo2 *This,ULONG ulTitle,DVD_MenuAttributes *pMenu,DVD_TitleAttributes *pTitle); - void __RPC_STUB IDvdInfo2_GetTitleAttributes_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdInfo2_GetVMGAttributes_Proxy(IDvdInfo2 *This,DVD_MenuAttributes *pATR); - void __RPC_STUB IDvdInfo2_GetVMGAttributes_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdInfo2_GetCurrentVideoAttributes_Proxy(IDvdInfo2 *This,DVD_VideoAttributes *pATR); - void __RPC_STUB IDvdInfo2_GetCurrentVideoAttributes_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdInfo2_GetAudioAttributes_Proxy(IDvdInfo2 *This,ULONG ulStream,DVD_AudioAttributes *pATR); - void __RPC_STUB IDvdInfo2_GetAudioAttributes_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdInfo2_GetKaraokeAttributes_Proxy(IDvdInfo2 *This,ULONG ulStream,DVD_KaraokeAttributes *pAttributes); - void __RPC_STUB IDvdInfo2_GetKaraokeAttributes_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdInfo2_GetSubpictureAttributes_Proxy(IDvdInfo2 *This,ULONG ulStream,DVD_SubpictureAttributes *pATR); - void __RPC_STUB IDvdInfo2_GetSubpictureAttributes_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdInfo2_GetDVDVolumeInfo_Proxy(IDvdInfo2 *This,ULONG *pulNumOfVolumes,ULONG *pulVolume,DVD_DISC_SIDE *pSide,ULONG *pulNumOfTitles); - void __RPC_STUB IDvdInfo2_GetDVDVolumeInfo_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdInfo2_GetDVDTextNumberOfLanguages_Proxy(IDvdInfo2 *This,ULONG *pulNumOfLangs); - void __RPC_STUB IDvdInfo2_GetDVDTextNumberOfLanguages_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdInfo2_GetDVDTextLanguageInfo_Proxy(IDvdInfo2 *This,ULONG ulLangIndex,ULONG *pulNumOfStrings,LCID *pLangCode,enum DVD_TextCharSet *pbCharacterSet); - void __RPC_STUB IDvdInfo2_GetDVDTextLanguageInfo_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdInfo2_GetDVDTextStringAsNative_Proxy(IDvdInfo2 *This,ULONG ulLangIndex,ULONG ulStringIndex,BYTE *pbBuffer,ULONG ulMaxBufferSize,ULONG *pulActualSize,enum DVD_TextStringType *pType); - void __RPC_STUB IDvdInfo2_GetDVDTextStringAsNative_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdInfo2_GetDVDTextStringAsUnicode_Proxy(IDvdInfo2 *This,ULONG ulLangIndex,ULONG ulStringIndex,WCHAR *pchwBuffer,ULONG ulMaxBufferSize,ULONG *pulActualSize,enum DVD_TextStringType *pType); - void __RPC_STUB IDvdInfo2_GetDVDTextStringAsUnicode_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdInfo2_GetPlayerParentalLevel_Proxy(IDvdInfo2 *This,ULONG *pulParentalLevel,BYTE pbCountryCode[2]); - void __RPC_STUB IDvdInfo2_GetPlayerParentalLevel_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdInfo2_GetNumberOfChapters_Proxy(IDvdInfo2 *This,ULONG ulTitle,ULONG *pulNumOfChapters); - void __RPC_STUB IDvdInfo2_GetNumberOfChapters_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdInfo2_GetTitleParentalLevels_Proxy(IDvdInfo2 *This,ULONG ulTitle,ULONG *pulParentalLevels); - void __RPC_STUB IDvdInfo2_GetTitleParentalLevels_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdInfo2_GetDVDDirectory_Proxy(IDvdInfo2 *This,LPWSTR pszwPath,ULONG ulMaxSize,ULONG *pulActualSize); - void __RPC_STUB IDvdInfo2_GetDVDDirectory_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdInfo2_IsAudioStreamEnabled_Proxy(IDvdInfo2 *This,ULONG ulStreamNum,WINBOOL *pbEnabled); - void __RPC_STUB IDvdInfo2_IsAudioStreamEnabled_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdInfo2_GetDiscID_Proxy(IDvdInfo2 *This,LPCWSTR pszwPath,ULONGLONG *pullDiscID); - void __RPC_STUB IDvdInfo2_GetDiscID_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdInfo2_GetState_Proxy(IDvdInfo2 *This,IDvdState **pStateData); - void __RPC_STUB IDvdInfo2_GetState_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdInfo2_GetMenuLanguages_Proxy(IDvdInfo2 *This,LCID *pLanguages,ULONG ulMaxLanguages,ULONG *pulActualLanguages); - void __RPC_STUB IDvdInfo2_GetMenuLanguages_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdInfo2_GetButtonAtPosition_Proxy(IDvdInfo2 *This,POINT point,ULONG *pulButtonIndex); - void __RPC_STUB IDvdInfo2_GetButtonAtPosition_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdInfo2_GetCmdFromEvent_Proxy(IDvdInfo2 *This,LONG_PTR lParam1,IDvdCmd **pCmdObj); - void __RPC_STUB IDvdInfo2_GetCmdFromEvent_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdInfo2_GetDefaultMenuLanguage_Proxy(IDvdInfo2 *This,LCID *pLanguage); - void __RPC_STUB IDvdInfo2_GetDefaultMenuLanguage_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdInfo2_GetDefaultAudioLanguage_Proxy(IDvdInfo2 *This,LCID *pLanguage,DVD_AUDIO_LANG_EXT *pAudioExtension); - void __RPC_STUB IDvdInfo2_GetDefaultAudioLanguage_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdInfo2_GetDefaultSubpictureLanguage_Proxy(IDvdInfo2 *This,LCID *pLanguage,DVD_SUBPICTURE_LANG_EXT *pSubpictureExtension); - void __RPC_STUB IDvdInfo2_GetDefaultSubpictureLanguage_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdInfo2_GetDecoderCaps_Proxy(IDvdInfo2 *This,DVD_DECODER_CAPS *pCaps); - void __RPC_STUB IDvdInfo2_GetDecoderCaps_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdInfo2_GetButtonRect_Proxy(IDvdInfo2 *This,ULONG ulButton,RECT *pRect); - void __RPC_STUB IDvdInfo2_GetButtonRect_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdInfo2_IsSubpictureStreamEnabled_Proxy(IDvdInfo2 *This,ULONG ulStreamNum,WINBOOL *pbEnabled); - void __RPC_STUB IDvdInfo2_IsSubpictureStreamEnabled_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - typedef enum _AM_DVD_GRAPH_FLAGS { - AM_DVD_HWDEC_PREFER = 0x1,AM_DVD_HWDEC_ONLY = 0x2,AM_DVD_SWDEC_PREFER = 0x4,AM_DVD_SWDEC_ONLY = 0x8,AM_DVD_NOVPE = 0x100, - AM_DVD_VMR9_ONLY = 0x800 - } AM_DVD_GRAPH_FLAGS; - - typedef enum _AM_DVD_STREAM_FLAGS { - AM_DVD_STREAM_VIDEO = 0x1,AM_DVD_STREAM_AUDIO = 0x2,AM_DVD_STREAM_SUBPIC = 0x4 - } AM_DVD_STREAM_FLAGS; - - typedef struct __MIDL___MIDL_itf_strmif_0389_0001 { - HRESULT hrVPEStatus; - WINBOOL bDvdVolInvalid; - WINBOOL bDvdVolUnknown; - WINBOOL bNoLine21In; - WINBOOL bNoLine21Out; - int iNumStreams; - int iNumStreamsFailed; - DWORD dwFailedStreamsFlag; - } AM_DVD_RENDERSTATUS; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0389_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0389_v0_0_s_ifspec; -#ifndef __IDvdGraphBuilder_INTERFACE_DEFINED__ -#define __IDvdGraphBuilder_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IDvdGraphBuilder; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IDvdGraphBuilder : public IUnknown { - public: - virtual HRESULT WINAPI GetFiltergraph(IGraphBuilder **ppGB) = 0; - virtual HRESULT WINAPI GetDvdInterface(REFIID riid,void **ppvIF) = 0; - virtual HRESULT WINAPI RenderDvdVideoVolume(LPCWSTR lpcwszPathName,DWORD dwFlags,AM_DVD_RENDERSTATUS *pStatus) = 0; - }; -#else - typedef struct IDvdGraphBuilderVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IDvdGraphBuilder *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IDvdGraphBuilder *This); - ULONG (WINAPI *Release)(IDvdGraphBuilder *This); - HRESULT (WINAPI *GetFiltergraph)(IDvdGraphBuilder *This,IGraphBuilder **ppGB); - HRESULT (WINAPI *GetDvdInterface)(IDvdGraphBuilder *This,REFIID riid,void **ppvIF); - HRESULT (WINAPI *RenderDvdVideoVolume)(IDvdGraphBuilder *This,LPCWSTR lpcwszPathName,DWORD dwFlags,AM_DVD_RENDERSTATUS *pStatus); - END_INTERFACE - } IDvdGraphBuilderVtbl; - struct IDvdGraphBuilder { - CONST_VTBL struct IDvdGraphBuilderVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IDvdGraphBuilder_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IDvdGraphBuilder_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IDvdGraphBuilder_Release(This) (This)->lpVtbl->Release(This) -#define IDvdGraphBuilder_GetFiltergraph(This,ppGB) (This)->lpVtbl->GetFiltergraph(This,ppGB) -#define IDvdGraphBuilder_GetDvdInterface(This,riid,ppvIF) (This)->lpVtbl->GetDvdInterface(This,riid,ppvIF) -#define IDvdGraphBuilder_RenderDvdVideoVolume(This,lpcwszPathName,dwFlags,pStatus) (This)->lpVtbl->RenderDvdVideoVolume(This,lpcwszPathName,dwFlags,pStatus) -#endif -#endif - HRESULT WINAPI IDvdGraphBuilder_GetFiltergraph_Proxy(IDvdGraphBuilder *This,IGraphBuilder **ppGB); - void __RPC_STUB IDvdGraphBuilder_GetFiltergraph_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdGraphBuilder_GetDvdInterface_Proxy(IDvdGraphBuilder *This,REFIID riid,void **ppvIF); - void __RPC_STUB IDvdGraphBuilder_GetDvdInterface_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDvdGraphBuilder_RenderDvdVideoVolume_Proxy(IDvdGraphBuilder *This,LPCWSTR lpcwszPathName,DWORD dwFlags,AM_DVD_RENDERSTATUS *pStatus); - void __RPC_STUB IDvdGraphBuilder_RenderDvdVideoVolume_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IDDrawExclModeVideo_INTERFACE_DEFINED__ -#define __IDDrawExclModeVideo_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IDDrawExclModeVideo; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IDDrawExclModeVideo : public IUnknown { - public: - virtual HRESULT WINAPI SetDDrawObject(IDirectDraw *pDDrawObject) = 0; - virtual HRESULT WINAPI GetDDrawObject(IDirectDraw **ppDDrawObject,WINBOOL *pbUsingExternal) = 0; - virtual HRESULT WINAPI SetDDrawSurface(IDirectDrawSurface *pDDrawSurface) = 0; - virtual HRESULT WINAPI GetDDrawSurface(IDirectDrawSurface **ppDDrawSurface,WINBOOL *pbUsingExternal) = 0; - virtual HRESULT WINAPI SetDrawParameters(const RECT *prcSource,const RECT *prcTarget) = 0; - virtual HRESULT WINAPI GetNativeVideoProps(DWORD *pdwVideoWidth,DWORD *pdwVideoHeight,DWORD *pdwPictAspectRatioX,DWORD *pdwPictAspectRatioY) = 0; - virtual HRESULT WINAPI SetCallbackInterface(IDDrawExclModeVideoCallback *pCallback,DWORD dwFlags) = 0; - }; -#else - typedef struct IDDrawExclModeVideoVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IDDrawExclModeVideo *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IDDrawExclModeVideo *This); - ULONG (WINAPI *Release)(IDDrawExclModeVideo *This); - HRESULT (WINAPI *SetDDrawObject)(IDDrawExclModeVideo *This,IDirectDraw *pDDrawObject); - HRESULT (WINAPI *GetDDrawObject)(IDDrawExclModeVideo *This,IDirectDraw **ppDDrawObject,WINBOOL *pbUsingExternal); - HRESULT (WINAPI *SetDDrawSurface)(IDDrawExclModeVideo *This,IDirectDrawSurface *pDDrawSurface); - HRESULT (WINAPI *GetDDrawSurface)(IDDrawExclModeVideo *This,IDirectDrawSurface **ppDDrawSurface,WINBOOL *pbUsingExternal); - HRESULT (WINAPI *SetDrawParameters)(IDDrawExclModeVideo *This,const RECT *prcSource,const RECT *prcTarget); - HRESULT (WINAPI *GetNativeVideoProps)(IDDrawExclModeVideo *This,DWORD *pdwVideoWidth,DWORD *pdwVideoHeight,DWORD *pdwPictAspectRatioX,DWORD *pdwPictAspectRatioY); - HRESULT (WINAPI *SetCallbackInterface)(IDDrawExclModeVideo *This,IDDrawExclModeVideoCallback *pCallback,DWORD dwFlags); - END_INTERFACE - } IDDrawExclModeVideoVtbl; - struct IDDrawExclModeVideo { - CONST_VTBL struct IDDrawExclModeVideoVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IDDrawExclModeVideo_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IDDrawExclModeVideo_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IDDrawExclModeVideo_Release(This) (This)->lpVtbl->Release(This) -#define IDDrawExclModeVideo_SetDDrawObject(This,pDDrawObject) (This)->lpVtbl->SetDDrawObject(This,pDDrawObject) -#define IDDrawExclModeVideo_GetDDrawObject(This,ppDDrawObject,pbUsingExternal) (This)->lpVtbl->GetDDrawObject(This,ppDDrawObject,pbUsingExternal) -#define IDDrawExclModeVideo_SetDDrawSurface(This,pDDrawSurface) (This)->lpVtbl->SetDDrawSurface(This,pDDrawSurface) -#define IDDrawExclModeVideo_GetDDrawSurface(This,ppDDrawSurface,pbUsingExternal) (This)->lpVtbl->GetDDrawSurface(This,ppDDrawSurface,pbUsingExternal) -#define IDDrawExclModeVideo_SetDrawParameters(This,prcSource,prcTarget) (This)->lpVtbl->SetDrawParameters(This,prcSource,prcTarget) -#define IDDrawExclModeVideo_GetNativeVideoProps(This,pdwVideoWidth,pdwVideoHeight,pdwPictAspectRatioX,pdwPictAspectRatioY) (This)->lpVtbl->GetNativeVideoProps(This,pdwVideoWidth,pdwVideoHeight,pdwPictAspectRatioX,pdwPictAspectRatioY) -#define IDDrawExclModeVideo_SetCallbackInterface(This,pCallback,dwFlags) (This)->lpVtbl->SetCallbackInterface(This,pCallback,dwFlags) -#endif -#endif - HRESULT WINAPI IDDrawExclModeVideo_SetDDrawObject_Proxy(IDDrawExclModeVideo *This,IDirectDraw *pDDrawObject); - void __RPC_STUB IDDrawExclModeVideo_SetDDrawObject_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDDrawExclModeVideo_GetDDrawObject_Proxy(IDDrawExclModeVideo *This,IDirectDraw **ppDDrawObject,WINBOOL *pbUsingExternal); - void __RPC_STUB IDDrawExclModeVideo_GetDDrawObject_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDDrawExclModeVideo_SetDDrawSurface_Proxy(IDDrawExclModeVideo *This,IDirectDrawSurface *pDDrawSurface); - void __RPC_STUB IDDrawExclModeVideo_SetDDrawSurface_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDDrawExclModeVideo_GetDDrawSurface_Proxy(IDDrawExclModeVideo *This,IDirectDrawSurface **ppDDrawSurface,WINBOOL *pbUsingExternal); - void __RPC_STUB IDDrawExclModeVideo_GetDDrawSurface_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDDrawExclModeVideo_SetDrawParameters_Proxy(IDDrawExclModeVideo *This,const RECT *prcSource,const RECT *prcTarget); - void __RPC_STUB IDDrawExclModeVideo_SetDrawParameters_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDDrawExclModeVideo_GetNativeVideoProps_Proxy(IDDrawExclModeVideo *This,DWORD *pdwVideoWidth,DWORD *pdwVideoHeight,DWORD *pdwPictAspectRatioX,DWORD *pdwPictAspectRatioY); - void __RPC_STUB IDDrawExclModeVideo_GetNativeVideoProps_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDDrawExclModeVideo_SetCallbackInterface_Proxy(IDDrawExclModeVideo *This,IDDrawExclModeVideoCallback *pCallback,DWORD dwFlags); - void __RPC_STUB IDDrawExclModeVideo_SetCallbackInterface_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - enum _AM_OVERLAY_NOTIFY_FLAGS { - AM_OVERLAY_NOTIFY_VISIBLE_CHANGE = 0x1,AM_OVERLAY_NOTIFY_SOURCE_CHANGE = 0x2,AM_OVERLAY_NOTIFY_DEST_CHANGE = 0x4 - }; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0391_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0391_v0_0_s_ifspec; -#ifndef __IDDrawExclModeVideoCallback_INTERFACE_DEFINED__ -#define __IDDrawExclModeVideoCallback_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IDDrawExclModeVideoCallback; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IDDrawExclModeVideoCallback : public IUnknown { - public: - virtual HRESULT WINAPI OnUpdateOverlay(WINBOOL bBefore,DWORD dwFlags,WINBOOL bOldVisible,const RECT *prcOldSrc,const RECT *prcOldDest,WINBOOL bNewVisible,const RECT *prcNewSrc,const RECT *prcNewDest) = 0; - virtual HRESULT WINAPI OnUpdateColorKey(const COLORKEY *pKey,DWORD dwColor) = 0; - virtual HRESULT WINAPI OnUpdateSize(DWORD dwWidth,DWORD dwHeight,DWORD dwARWidth,DWORD dwARHeight) = 0; - }; -#else - typedef struct IDDrawExclModeVideoCallbackVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IDDrawExclModeVideoCallback *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IDDrawExclModeVideoCallback *This); - ULONG (WINAPI *Release)(IDDrawExclModeVideoCallback *This); - HRESULT (WINAPI *OnUpdateOverlay)(IDDrawExclModeVideoCallback *This,WINBOOL bBefore,DWORD dwFlags,WINBOOL bOldVisible,const RECT *prcOldSrc,const RECT *prcOldDest,WINBOOL bNewVisible,const RECT *prcNewSrc,const RECT *prcNewDest); - HRESULT (WINAPI *OnUpdateColorKey)(IDDrawExclModeVideoCallback *This,const COLORKEY *pKey,DWORD dwColor); - HRESULT (WINAPI *OnUpdateSize)(IDDrawExclModeVideoCallback *This,DWORD dwWidth,DWORD dwHeight,DWORD dwARWidth,DWORD dwARHeight); - END_INTERFACE - } IDDrawExclModeVideoCallbackVtbl; - struct IDDrawExclModeVideoCallback { - CONST_VTBL struct IDDrawExclModeVideoCallbackVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IDDrawExclModeVideoCallback_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IDDrawExclModeVideoCallback_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IDDrawExclModeVideoCallback_Release(This) (This)->lpVtbl->Release(This) -#define IDDrawExclModeVideoCallback_OnUpdateOverlay(This,bBefore,dwFlags,bOldVisible,prcOldSrc,prcOldDest,bNewVisible,prcNewSrc,prcNewDest) (This)->lpVtbl->OnUpdateOverlay(This,bBefore,dwFlags,bOldVisible,prcOldSrc,prcOldDest,bNewVisible,prcNewSrc,prcNewDest) -#define IDDrawExclModeVideoCallback_OnUpdateColorKey(This,pKey,dwColor) (This)->lpVtbl->OnUpdateColorKey(This,pKey,dwColor) -#define IDDrawExclModeVideoCallback_OnUpdateSize(This,dwWidth,dwHeight,dwARWidth,dwARHeight) (This)->lpVtbl->OnUpdateSize(This,dwWidth,dwHeight,dwARWidth,dwARHeight) -#endif -#endif - HRESULT WINAPI IDDrawExclModeVideoCallback_OnUpdateOverlay_Proxy(IDDrawExclModeVideoCallback *This,WINBOOL bBefore,DWORD dwFlags,WINBOOL bOldVisible,const RECT *prcOldSrc,const RECT *prcOldDest,WINBOOL bNewVisible,const RECT *prcNewSrc,const RECT *prcNewDest); - void __RPC_STUB IDDrawExclModeVideoCallback_OnUpdateOverlay_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDDrawExclModeVideoCallback_OnUpdateColorKey_Proxy(IDDrawExclModeVideoCallback *This,const COLORKEY *pKey,DWORD dwColor); - void __RPC_STUB IDDrawExclModeVideoCallback_OnUpdateColorKey_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IDDrawExclModeVideoCallback_OnUpdateSize_Proxy(IDDrawExclModeVideoCallback *This,DWORD dwWidth,DWORD dwHeight,DWORD dwARWidth,DWORD dwARHeight); - void __RPC_STUB IDDrawExclModeVideoCallback_OnUpdateSize_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0392_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0392_v0_0_s_ifspec; -#ifndef __IPinConnection_INTERFACE_DEFINED__ -#define __IPinConnection_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IPinConnection; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IPinConnection : public IUnknown { - public: - virtual HRESULT WINAPI DynamicQueryAccept(const AM_MEDIA_TYPE *pmt) = 0; - virtual HRESULT WINAPI NotifyEndOfStream(HANDLE hNotifyEvent) = 0; - virtual HRESULT WINAPI IsEndPin(void) = 0; - virtual HRESULT WINAPI DynamicDisconnect(void) = 0; - }; -#else - typedef struct IPinConnectionVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IPinConnection *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IPinConnection *This); - ULONG (WINAPI *Release)(IPinConnection *This); - HRESULT (WINAPI *DynamicQueryAccept)(IPinConnection *This,const AM_MEDIA_TYPE *pmt); - HRESULT (WINAPI *NotifyEndOfStream)(IPinConnection *This,HANDLE hNotifyEvent); - HRESULT (WINAPI *IsEndPin)(IPinConnection *This); - HRESULT (WINAPI *DynamicDisconnect)(IPinConnection *This); - END_INTERFACE - } IPinConnectionVtbl; - struct IPinConnection { - CONST_VTBL struct IPinConnectionVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IPinConnection_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IPinConnection_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IPinConnection_Release(This) (This)->lpVtbl->Release(This) -#define IPinConnection_DynamicQueryAccept(This,pmt) (This)->lpVtbl->DynamicQueryAccept(This,pmt) -#define IPinConnection_NotifyEndOfStream(This,hNotifyEvent) (This)->lpVtbl->NotifyEndOfStream(This,hNotifyEvent) -#define IPinConnection_IsEndPin(This) (This)->lpVtbl->IsEndPin(This) -#define IPinConnection_DynamicDisconnect(This) (This)->lpVtbl->DynamicDisconnect(This) -#endif -#endif - HRESULT WINAPI IPinConnection_DynamicQueryAccept_Proxy(IPinConnection *This,const AM_MEDIA_TYPE *pmt); - void __RPC_STUB IPinConnection_DynamicQueryAccept_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IPinConnection_NotifyEndOfStream_Proxy(IPinConnection *This,HANDLE hNotifyEvent); - void __RPC_STUB IPinConnection_NotifyEndOfStream_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IPinConnection_IsEndPin_Proxy(IPinConnection *This); - void __RPC_STUB IPinConnection_IsEndPin_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IPinConnection_DynamicDisconnect_Proxy(IPinConnection *This); - void __RPC_STUB IPinConnection_DynamicDisconnect_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IPinFlowControl_INTERFACE_DEFINED__ -#define __IPinFlowControl_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IPinFlowControl; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IPinFlowControl : public IUnknown { - public: - virtual HRESULT WINAPI Block(DWORD dwBlockFlags,HANDLE hEvent) = 0; - }; -#else - typedef struct IPinFlowControlVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IPinFlowControl *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IPinFlowControl *This); - ULONG (WINAPI *Release)(IPinFlowControl *This); - HRESULT (WINAPI *Block)(IPinFlowControl *This,DWORD dwBlockFlags,HANDLE hEvent); - END_INTERFACE - } IPinFlowControlVtbl; - struct IPinFlowControl { - CONST_VTBL struct IPinFlowControlVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IPinFlowControl_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IPinFlowControl_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IPinFlowControl_Release(This) (This)->lpVtbl->Release(This) -#define IPinFlowControl_Block(This,dwBlockFlags,hEvent) (This)->lpVtbl->Block(This,dwBlockFlags,hEvent) -#endif -#endif - HRESULT WINAPI IPinFlowControl_Block_Proxy(IPinFlowControl *This,DWORD dwBlockFlags,HANDLE hEvent); - void __RPC_STUB IPinFlowControl_Block_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - enum _AM_PIN_FLOW_CONTROL_BLOCK_FLAGS { - AM_PIN_FLOW_CONTROL_BLOCK = 0x1 - }; - typedef enum _AM_GRAPH_CONFIG_RECONNECT_FLAGS { - AM_GRAPH_CONFIG_RECONNECT_DIRECTCONNECT = 0x1,AM_GRAPH_CONFIG_RECONNECT_CACHE_REMOVED_FILTERS = 0x2, - AM_GRAPH_CONFIG_RECONNECT_USE_ONLY_CACHED_FILTERS = 0x4 - } AM_GRAPH_CONFIG_RECONNECT_FLAGS; - - enum _REM_FILTER_FLAGS { - REMFILTERF_LEAVECONNECTED = 0x1 - }; - - typedef enum _AM_FILTER_FLAGS { - AM_FILTER_FLAGS_REMOVABLE = 0x1 - } AM_FILTER_FLAGS; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0394_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0394_v0_0_s_ifspec; -#ifndef __IGraphConfig_INTERFACE_DEFINED__ -#define __IGraphConfig_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IGraphConfig; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IGraphConfig : public IUnknown { - public: - virtual HRESULT WINAPI Reconnect(IPin *pOutputPin,IPin *pInputPin,const AM_MEDIA_TYPE *pmtFirstConnection,IBaseFilter *pUsingFilter,HANDLE hAbortEvent,DWORD dwFlags) = 0; - virtual HRESULT WINAPI Reconfigure(IGraphConfigCallback *pCallback,PVOID pvContext,DWORD dwFlags,HANDLE hAbortEvent) = 0; - virtual HRESULT WINAPI AddFilterToCache(IBaseFilter *pFilter) = 0; - virtual HRESULT WINAPI EnumCacheFilter(IEnumFilters **pEnum) = 0; - virtual HRESULT WINAPI RemoveFilterFromCache(IBaseFilter *pFilter) = 0; - virtual HRESULT WINAPI GetStartTime(REFERENCE_TIME *prtStart) = 0; - virtual HRESULT WINAPI PushThroughData(IPin *pOutputPin,IPinConnection *pConnection,HANDLE hEventAbort) = 0; - virtual HRESULT WINAPI SetFilterFlags(IBaseFilter *pFilter,DWORD dwFlags) = 0; - virtual HRESULT WINAPI GetFilterFlags(IBaseFilter *pFilter,DWORD *pdwFlags) = 0; - virtual HRESULT WINAPI RemoveFilterEx(IBaseFilter *pFilter,DWORD Flags) = 0; - }; -#else - typedef struct IGraphConfigVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IGraphConfig *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IGraphConfig *This); - ULONG (WINAPI *Release)(IGraphConfig *This); - HRESULT (WINAPI *Reconnect)(IGraphConfig *This,IPin *pOutputPin,IPin *pInputPin,const AM_MEDIA_TYPE *pmtFirstConnection,IBaseFilter *pUsingFilter,HANDLE hAbortEvent,DWORD dwFlags); - HRESULT (WINAPI *Reconfigure)(IGraphConfig *This,IGraphConfigCallback *pCallback,PVOID pvContext,DWORD dwFlags,HANDLE hAbortEvent); - HRESULT (WINAPI *AddFilterToCache)(IGraphConfig *This,IBaseFilter *pFilter); - HRESULT (WINAPI *EnumCacheFilter)(IGraphConfig *This,IEnumFilters **pEnum); - HRESULT (WINAPI *RemoveFilterFromCache)(IGraphConfig *This,IBaseFilter *pFilter); - HRESULT (WINAPI *GetStartTime)(IGraphConfig *This,REFERENCE_TIME *prtStart); - HRESULT (WINAPI *PushThroughData)(IGraphConfig *This,IPin *pOutputPin,IPinConnection *pConnection,HANDLE hEventAbort); - HRESULT (WINAPI *SetFilterFlags)(IGraphConfig *This,IBaseFilter *pFilter,DWORD dwFlags); - HRESULT (WINAPI *GetFilterFlags)(IGraphConfig *This,IBaseFilter *pFilter,DWORD *pdwFlags); - HRESULT (WINAPI *RemoveFilterEx)(IGraphConfig *This,IBaseFilter *pFilter,DWORD Flags); - END_INTERFACE - } IGraphConfigVtbl; - struct IGraphConfig { - CONST_VTBL struct IGraphConfigVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IGraphConfig_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IGraphConfig_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IGraphConfig_Release(This) (This)->lpVtbl->Release(This) -#define IGraphConfig_Reconnect(This,pOutputPin,pInputPin,pmtFirstConnection,pUsingFilter,hAbortEvent,dwFlags) (This)->lpVtbl->Reconnect(This,pOutputPin,pInputPin,pmtFirstConnection,pUsingFilter,hAbortEvent,dwFlags) -#define IGraphConfig_Reconfigure(This,pCallback,pvContext,dwFlags,hAbortEvent) (This)->lpVtbl->Reconfigure(This,pCallback,pvContext,dwFlags,hAbortEvent) -#define IGraphConfig_AddFilterToCache(This,pFilter) (This)->lpVtbl->AddFilterToCache(This,pFilter) -#define IGraphConfig_EnumCacheFilter(This,pEnum) (This)->lpVtbl->EnumCacheFilter(This,pEnum) -#define IGraphConfig_RemoveFilterFromCache(This,pFilter) (This)->lpVtbl->RemoveFilterFromCache(This,pFilter) -#define IGraphConfig_GetStartTime(This,prtStart) (This)->lpVtbl->GetStartTime(This,prtStart) -#define IGraphConfig_PushThroughData(This,pOutputPin,pConnection,hEventAbort) (This)->lpVtbl->PushThroughData(This,pOutputPin,pConnection,hEventAbort) -#define IGraphConfig_SetFilterFlags(This,pFilter,dwFlags) (This)->lpVtbl->SetFilterFlags(This,pFilter,dwFlags) -#define IGraphConfig_GetFilterFlags(This,pFilter,pdwFlags) (This)->lpVtbl->GetFilterFlags(This,pFilter,pdwFlags) -#define IGraphConfig_RemoveFilterEx(This,pFilter,Flags) (This)->lpVtbl->RemoveFilterEx(This,pFilter,Flags) -#endif -#endif - HRESULT WINAPI IGraphConfig_Reconnect_Proxy(IGraphConfig *This,IPin *pOutputPin,IPin *pInputPin,const AM_MEDIA_TYPE *pmtFirstConnection,IBaseFilter *pUsingFilter,HANDLE hAbortEvent,DWORD dwFlags); - void __RPC_STUB IGraphConfig_Reconnect_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IGraphConfig_Reconfigure_Proxy(IGraphConfig *This,IGraphConfigCallback *pCallback,PVOID pvContext,DWORD dwFlags,HANDLE hAbortEvent); - void __RPC_STUB IGraphConfig_Reconfigure_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IGraphConfig_AddFilterToCache_Proxy(IGraphConfig *This,IBaseFilter *pFilter); - void __RPC_STUB IGraphConfig_AddFilterToCache_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IGraphConfig_EnumCacheFilter_Proxy(IGraphConfig *This,IEnumFilters **pEnum); - void __RPC_STUB IGraphConfig_EnumCacheFilter_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IGraphConfig_RemoveFilterFromCache_Proxy(IGraphConfig *This,IBaseFilter *pFilter); - void __RPC_STUB IGraphConfig_RemoveFilterFromCache_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IGraphConfig_GetStartTime_Proxy(IGraphConfig *This,REFERENCE_TIME *prtStart); - void __RPC_STUB IGraphConfig_GetStartTime_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IGraphConfig_PushThroughData_Proxy(IGraphConfig *This,IPin *pOutputPin,IPinConnection *pConnection,HANDLE hEventAbort); - void __RPC_STUB IGraphConfig_PushThroughData_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IGraphConfig_SetFilterFlags_Proxy(IGraphConfig *This,IBaseFilter *pFilter,DWORD dwFlags); - void __RPC_STUB IGraphConfig_SetFilterFlags_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IGraphConfig_GetFilterFlags_Proxy(IGraphConfig *This,IBaseFilter *pFilter,DWORD *pdwFlags); - void __RPC_STUB IGraphConfig_GetFilterFlags_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IGraphConfig_RemoveFilterEx_Proxy(IGraphConfig *This,IBaseFilter *pFilter,DWORD Flags); - void __RPC_STUB IGraphConfig_RemoveFilterEx_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IGraphConfigCallback_INTERFACE_DEFINED__ -#define __IGraphConfigCallback_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IGraphConfigCallback; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IGraphConfigCallback : public IUnknown { - public: - virtual HRESULT WINAPI Reconfigure(PVOID pvContext,DWORD dwFlags) = 0; - }; -#else - typedef struct IGraphConfigCallbackVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IGraphConfigCallback *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IGraphConfigCallback *This); - ULONG (WINAPI *Release)(IGraphConfigCallback *This); - HRESULT (WINAPI *Reconfigure)(IGraphConfigCallback *This,PVOID pvContext,DWORD dwFlags); - END_INTERFACE - } IGraphConfigCallbackVtbl; - struct IGraphConfigCallback { - CONST_VTBL struct IGraphConfigCallbackVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IGraphConfigCallback_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IGraphConfigCallback_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IGraphConfigCallback_Release(This) (This)->lpVtbl->Release(This) -#define IGraphConfigCallback_Reconfigure(This,pvContext,dwFlags) (This)->lpVtbl->Reconfigure(This,pvContext,dwFlags) -#endif -#endif - HRESULT WINAPI IGraphConfigCallback_Reconfigure_Proxy(IGraphConfigCallback *This,PVOID pvContext,DWORD dwFlags); - void __RPC_STUB IGraphConfigCallback_Reconfigure_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IFilterChain_INTERFACE_DEFINED__ -#define __IFilterChain_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IFilterChain; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IFilterChain : public IUnknown { - public: - virtual HRESULT WINAPI StartChain(IBaseFilter *pStartFilter,IBaseFilter *pEndFilter) = 0; - virtual HRESULT WINAPI PauseChain(IBaseFilter *pStartFilter,IBaseFilter *pEndFilter) = 0; - virtual HRESULT WINAPI StopChain(IBaseFilter *pStartFilter,IBaseFilter *pEndFilter) = 0; - virtual HRESULT WINAPI RemoveChain(IBaseFilter *pStartFilter,IBaseFilter *pEndFilter) = 0; - }; -#else - typedef struct IFilterChainVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IFilterChain *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IFilterChain *This); - ULONG (WINAPI *Release)(IFilterChain *This); - HRESULT (WINAPI *StartChain)(IFilterChain *This,IBaseFilter *pStartFilter,IBaseFilter *pEndFilter); - HRESULT (WINAPI *PauseChain)(IFilterChain *This,IBaseFilter *pStartFilter,IBaseFilter *pEndFilter); - HRESULT (WINAPI *StopChain)(IFilterChain *This,IBaseFilter *pStartFilter,IBaseFilter *pEndFilter); - HRESULT (WINAPI *RemoveChain)(IFilterChain *This,IBaseFilter *pStartFilter,IBaseFilter *pEndFilter); - END_INTERFACE - } IFilterChainVtbl; - struct IFilterChain { - CONST_VTBL struct IFilterChainVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IFilterChain_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IFilterChain_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IFilterChain_Release(This) (This)->lpVtbl->Release(This) -#define IFilterChain_StartChain(This,pStartFilter,pEndFilter) (This)->lpVtbl->StartChain(This,pStartFilter,pEndFilter) -#define IFilterChain_PauseChain(This,pStartFilter,pEndFilter) (This)->lpVtbl->PauseChain(This,pStartFilter,pEndFilter) -#define IFilterChain_StopChain(This,pStartFilter,pEndFilter) (This)->lpVtbl->StopChain(This,pStartFilter,pEndFilter) -#define IFilterChain_RemoveChain(This,pStartFilter,pEndFilter) (This)->lpVtbl->RemoveChain(This,pStartFilter,pEndFilter) -#endif -#endif - HRESULT WINAPI IFilterChain_StartChain_Proxy(IFilterChain *This,IBaseFilter *pStartFilter,IBaseFilter *pEndFilter); - void __RPC_STUB IFilterChain_StartChain_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IFilterChain_PauseChain_Proxy(IFilterChain *This,IBaseFilter *pStartFilter,IBaseFilter *pEndFilter); - void __RPC_STUB IFilterChain_PauseChain_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IFilterChain_StopChain_Proxy(IFilterChain *This,IBaseFilter *pStartFilter,IBaseFilter *pEndFilter); - void __RPC_STUB IFilterChain_StopChain_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IFilterChain_RemoveChain_Proxy(IFilterChain *This,IBaseFilter *pStartFilter,IBaseFilter *pEndFilter); - void __RPC_STUB IFilterChain_RemoveChain_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifdef MINGW_HAS_DDRAW_H -#include -#endif - - typedef enum __MIDL___MIDL_itf_strmif_0397_0002 { - VMRSample_SyncPoint = 0x1,VMRSample_Preroll = 0x2,VMRSample_Discontinuity = 0x4,VMRSample_TimeValid = 0x8,VMRSample_SrcDstRectsValid = 0x10 - } VMRPresentationFlags; - - typedef struct tagVMRPRESENTATIONINFO { - DWORD dwFlags; - LPDIRECTDRAWSURFACE7 lpSurf; - REFERENCE_TIME rtStart; - REFERENCE_TIME rtEnd; - SIZE szAspectRatio; - RECT rcSrc; - RECT rcDst; - DWORD dwTypeSpecificFlags; - DWORD dwInterlaceFlags; - } VMRPRESENTATIONINFO; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0397_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0397_v0_0_s_ifspec; -#ifndef __IVMRImagePresenter_INTERFACE_DEFINED__ -#define __IVMRImagePresenter_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IVMRImagePresenter; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IVMRImagePresenter : public IUnknown { - public: - virtual HRESULT WINAPI StartPresenting(DWORD_PTR dwUserID) = 0; - virtual HRESULT WINAPI StopPresenting(DWORD_PTR dwUserID) = 0; - virtual HRESULT WINAPI PresentImage(DWORD_PTR dwUserID,VMRPRESENTATIONINFO *lpPresInfo) = 0; - }; -#else - typedef struct IVMRImagePresenterVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IVMRImagePresenter *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IVMRImagePresenter *This); - ULONG (WINAPI *Release)(IVMRImagePresenter *This); - HRESULT (WINAPI *StartPresenting)(IVMRImagePresenter *This,DWORD_PTR dwUserID); - HRESULT (WINAPI *StopPresenting)(IVMRImagePresenter *This,DWORD_PTR dwUserID); - HRESULT (WINAPI *PresentImage)(IVMRImagePresenter *This,DWORD_PTR dwUserID,VMRPRESENTATIONINFO *lpPresInfo); - END_INTERFACE - } IVMRImagePresenterVtbl; - struct IVMRImagePresenter { - CONST_VTBL struct IVMRImagePresenterVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IVMRImagePresenter_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IVMRImagePresenter_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IVMRImagePresenter_Release(This) (This)->lpVtbl->Release(This) -#define IVMRImagePresenter_StartPresenting(This,dwUserID) (This)->lpVtbl->StartPresenting(This,dwUserID) -#define IVMRImagePresenter_StopPresenting(This,dwUserID) (This)->lpVtbl->StopPresenting(This,dwUserID) -#define IVMRImagePresenter_PresentImage(This,dwUserID,lpPresInfo) (This)->lpVtbl->PresentImage(This,dwUserID,lpPresInfo) -#endif -#endif - HRESULT WINAPI IVMRImagePresenter_StartPresenting_Proxy(IVMRImagePresenter *This,DWORD_PTR dwUserID); - void __RPC_STUB IVMRImagePresenter_StartPresenting_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRImagePresenter_StopPresenting_Proxy(IVMRImagePresenter *This,DWORD_PTR dwUserID); - void __RPC_STUB IVMRImagePresenter_StopPresenting_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRImagePresenter_PresentImage_Proxy(IVMRImagePresenter *This,DWORD_PTR dwUserID,VMRPRESENTATIONINFO *lpPresInfo); - void __RPC_STUB IVMRImagePresenter_PresentImage_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - typedef enum __MIDL___MIDL_itf_strmif_0398_0001 { - AMAP_PIXELFORMAT_VALID = 0x1,AMAP_3D_TARGET = 0x2,AMAP_ALLOW_SYSMEM = 0x4,AMAP_FORCE_SYSMEM = 0x8,AMAP_DIRECTED_FLIP = 0x10,AMAP_DXVA_TARGET = 0x20 - } VMRSurfaceAllocationFlags; - - typedef struct tagVMRALLOCATIONINFO { - DWORD dwFlags; - LPBITMAPINFOHEADER lpHdr; - LPDDPIXELFORMAT lpPixFmt; - SIZE szAspectRatio; - DWORD dwMinBuffers; - DWORD dwMaxBuffers; - DWORD dwInterlaceFlags; - SIZE szNativeSize; - } VMRALLOCATIONINFO; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0398_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0398_v0_0_s_ifspec; -#ifndef __IVMRSurfaceAllocator_INTERFACE_DEFINED__ -#define __IVMRSurfaceAllocator_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IVMRSurfaceAllocator; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IVMRSurfaceAllocator : public IUnknown { - public: - virtual HRESULT WINAPI AllocateSurface(DWORD_PTR dwUserID,VMRALLOCATIONINFO *lpAllocInfo,DWORD *lpdwActualBuffers,LPDIRECTDRAWSURFACE7 *lplpSurface) = 0; - virtual HRESULT WINAPI FreeSurface(DWORD_PTR dwID) = 0; - virtual HRESULT WINAPI PrepareSurface(DWORD_PTR dwUserID,LPDIRECTDRAWSURFACE7 lpSurface,DWORD dwSurfaceFlags) = 0; - virtual HRESULT WINAPI AdviseNotify(IVMRSurfaceAllocatorNotify *lpIVMRSurfAllocNotify) = 0; - }; -#else - typedef struct IVMRSurfaceAllocatorVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IVMRSurfaceAllocator *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IVMRSurfaceAllocator *This); - ULONG (WINAPI *Release)(IVMRSurfaceAllocator *This); - HRESULT (WINAPI *AllocateSurface)(IVMRSurfaceAllocator *This,DWORD_PTR dwUserID,VMRALLOCATIONINFO *lpAllocInfo,DWORD *lpdwActualBuffers,LPDIRECTDRAWSURFACE7 *lplpSurface); - HRESULT (WINAPI *FreeSurface)(IVMRSurfaceAllocator *This,DWORD_PTR dwID); - HRESULT (WINAPI *PrepareSurface)(IVMRSurfaceAllocator *This,DWORD_PTR dwUserID,LPDIRECTDRAWSURFACE7 lpSurface,DWORD dwSurfaceFlags); - HRESULT (WINAPI *AdviseNotify)(IVMRSurfaceAllocator *This,IVMRSurfaceAllocatorNotify *lpIVMRSurfAllocNotify); - END_INTERFACE - } IVMRSurfaceAllocatorVtbl; - struct IVMRSurfaceAllocator { - CONST_VTBL struct IVMRSurfaceAllocatorVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IVMRSurfaceAllocator_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IVMRSurfaceAllocator_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IVMRSurfaceAllocator_Release(This) (This)->lpVtbl->Release(This) -#define IVMRSurfaceAllocator_AllocateSurface(This,dwUserID,lpAllocInfo,lpdwActualBuffers,lplpSurface) (This)->lpVtbl->AllocateSurface(This,dwUserID,lpAllocInfo,lpdwActualBuffers,lplpSurface) -#define IVMRSurfaceAllocator_FreeSurface(This,dwID) (This)->lpVtbl->FreeSurface(This,dwID) -#define IVMRSurfaceAllocator_PrepareSurface(This,dwUserID,lpSurface,dwSurfaceFlags) (This)->lpVtbl->PrepareSurface(This,dwUserID,lpSurface,dwSurfaceFlags) -#define IVMRSurfaceAllocator_AdviseNotify(This,lpIVMRSurfAllocNotify) (This)->lpVtbl->AdviseNotify(This,lpIVMRSurfAllocNotify) -#endif -#endif - HRESULT WINAPI IVMRSurfaceAllocator_AllocateSurface_Proxy(IVMRSurfaceAllocator *This,DWORD_PTR dwUserID,VMRALLOCATIONINFO *lpAllocInfo,DWORD *lpdwActualBuffers,LPDIRECTDRAWSURFACE7 *lplpSurface); - void __RPC_STUB IVMRSurfaceAllocator_AllocateSurface_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRSurfaceAllocator_FreeSurface_Proxy(IVMRSurfaceAllocator *This,DWORD_PTR dwID); - void __RPC_STUB IVMRSurfaceAllocator_FreeSurface_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRSurfaceAllocator_PrepareSurface_Proxy(IVMRSurfaceAllocator *This,DWORD_PTR dwUserID,LPDIRECTDRAWSURFACE7 lpSurface,DWORD dwSurfaceFlags); - void __RPC_STUB IVMRSurfaceAllocator_PrepareSurface_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRSurfaceAllocator_AdviseNotify_Proxy(IVMRSurfaceAllocator *This,IVMRSurfaceAllocatorNotify *lpIVMRSurfAllocNotify); - void __RPC_STUB IVMRSurfaceAllocator_AdviseNotify_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IVMRSurfaceAllocatorNotify_INTERFACE_DEFINED__ -#define __IVMRSurfaceAllocatorNotify_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IVMRSurfaceAllocatorNotify; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IVMRSurfaceAllocatorNotify : public IUnknown { - public: - virtual HRESULT WINAPI AdviseSurfaceAllocator(DWORD_PTR dwUserID,IVMRSurfaceAllocator *lpIVRMSurfaceAllocator) = 0; - virtual HRESULT WINAPI SetDDrawDevice(LPDIRECTDRAW7 lpDDrawDevice,HMONITOR hMonitor) = 0; - virtual HRESULT WINAPI ChangeDDrawDevice(LPDIRECTDRAW7 lpDDrawDevice,HMONITOR hMonitor) = 0; - virtual HRESULT WINAPI RestoreDDrawSurfaces(void) = 0; - virtual HRESULT WINAPI NotifyEvent(LONG EventCode,LONG_PTR Param1,LONG_PTR Param2) = 0; - virtual HRESULT WINAPI SetBorderColor(COLORREF clrBorder) = 0; - }; -#else - typedef struct IVMRSurfaceAllocatorNotifyVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IVMRSurfaceAllocatorNotify *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IVMRSurfaceAllocatorNotify *This); - ULONG (WINAPI *Release)(IVMRSurfaceAllocatorNotify *This); - HRESULT (WINAPI *AdviseSurfaceAllocator)(IVMRSurfaceAllocatorNotify *This,DWORD_PTR dwUserID,IVMRSurfaceAllocator *lpIVRMSurfaceAllocator); - HRESULT (WINAPI *SetDDrawDevice)(IVMRSurfaceAllocatorNotify *This,LPDIRECTDRAW7 lpDDrawDevice,HMONITOR hMonitor); - HRESULT (WINAPI *ChangeDDrawDevice)(IVMRSurfaceAllocatorNotify *This,LPDIRECTDRAW7 lpDDrawDevice,HMONITOR hMonitor); - HRESULT (WINAPI *RestoreDDrawSurfaces)(IVMRSurfaceAllocatorNotify *This); - HRESULT (WINAPI *NotifyEvent)(IVMRSurfaceAllocatorNotify *This,LONG EventCode,LONG_PTR Param1,LONG_PTR Param2); - HRESULT (WINAPI *SetBorderColor)(IVMRSurfaceAllocatorNotify *This,COLORREF clrBorder); - END_INTERFACE - } IVMRSurfaceAllocatorNotifyVtbl; - struct IVMRSurfaceAllocatorNotify { - CONST_VTBL struct IVMRSurfaceAllocatorNotifyVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IVMRSurfaceAllocatorNotify_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IVMRSurfaceAllocatorNotify_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IVMRSurfaceAllocatorNotify_Release(This) (This)->lpVtbl->Release(This) -#define IVMRSurfaceAllocatorNotify_AdviseSurfaceAllocator(This,dwUserID,lpIVRMSurfaceAllocator) (This)->lpVtbl->AdviseSurfaceAllocator(This,dwUserID,lpIVRMSurfaceAllocator) -#define IVMRSurfaceAllocatorNotify_SetDDrawDevice(This,lpDDrawDevice,hMonitor) (This)->lpVtbl->SetDDrawDevice(This,lpDDrawDevice,hMonitor) -#define IVMRSurfaceAllocatorNotify_ChangeDDrawDevice(This,lpDDrawDevice,hMonitor) (This)->lpVtbl->ChangeDDrawDevice(This,lpDDrawDevice,hMonitor) -#define IVMRSurfaceAllocatorNotify_RestoreDDrawSurfaces(This) (This)->lpVtbl->RestoreDDrawSurfaces(This) -#define IVMRSurfaceAllocatorNotify_NotifyEvent(This,EventCode,Param1,Param2) (This)->lpVtbl->NotifyEvent(This,EventCode,Param1,Param2) -#define IVMRSurfaceAllocatorNotify_SetBorderColor(This,clrBorder) (This)->lpVtbl->SetBorderColor(This,clrBorder) -#endif -#endif - HRESULT WINAPI IVMRSurfaceAllocatorNotify_AdviseSurfaceAllocator_Proxy(IVMRSurfaceAllocatorNotify *This,DWORD_PTR dwUserID,IVMRSurfaceAllocator *lpIVRMSurfaceAllocator); - void __RPC_STUB IVMRSurfaceAllocatorNotify_AdviseSurfaceAllocator_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRSurfaceAllocatorNotify_SetDDrawDevice_Proxy(IVMRSurfaceAllocatorNotify *This,LPDIRECTDRAW7 lpDDrawDevice,HMONITOR hMonitor); - void __RPC_STUB IVMRSurfaceAllocatorNotify_SetDDrawDevice_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRSurfaceAllocatorNotify_ChangeDDrawDevice_Proxy(IVMRSurfaceAllocatorNotify *This,LPDIRECTDRAW7 lpDDrawDevice,HMONITOR hMonitor); - void __RPC_STUB IVMRSurfaceAllocatorNotify_ChangeDDrawDevice_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRSurfaceAllocatorNotify_RestoreDDrawSurfaces_Proxy(IVMRSurfaceAllocatorNotify *This); - void __RPC_STUB IVMRSurfaceAllocatorNotify_RestoreDDrawSurfaces_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRSurfaceAllocatorNotify_NotifyEvent_Proxy(IVMRSurfaceAllocatorNotify *This,LONG EventCode,LONG_PTR Param1,LONG_PTR Param2); - void __RPC_STUB IVMRSurfaceAllocatorNotify_NotifyEvent_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRSurfaceAllocatorNotify_SetBorderColor_Proxy(IVMRSurfaceAllocatorNotify *This,COLORREF clrBorder); - void __RPC_STUB IVMRSurfaceAllocatorNotify_SetBorderColor_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - typedef enum __MIDL___MIDL_itf_strmif_0400_0001 { - VMR_ARMODE_NONE = 0,VMR_ARMODE_LETTER_BOX = VMR_ARMODE_NONE + 1 - } VMR_ASPECT_RATIO_MODE; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0400_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0400_v0_0_s_ifspec; -#ifndef __IVMRWindowlessControl_INTERFACE_DEFINED__ -#define __IVMRWindowlessControl_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IVMRWindowlessControl; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IVMRWindowlessControl : public IUnknown { - public: - virtual HRESULT WINAPI GetNativeVideoSize(LONG *lpWidth,LONG *lpHeight,LONG *lpARWidth,LONG *lpARHeight) = 0; - virtual HRESULT WINAPI GetMinIdealVideoSize(LONG *lpWidth,LONG *lpHeight) = 0; - virtual HRESULT WINAPI GetMaxIdealVideoSize(LONG *lpWidth,LONG *lpHeight) = 0; - virtual HRESULT WINAPI SetVideoPosition(const LPRECT lpSRCRect,const LPRECT lpDSTRect) = 0; - virtual HRESULT WINAPI GetVideoPosition(LPRECT lpSRCRect,LPRECT lpDSTRect) = 0; - virtual HRESULT WINAPI GetAspectRatioMode(DWORD *lpAspectRatioMode) = 0; - virtual HRESULT WINAPI SetAspectRatioMode(DWORD AspectRatioMode) = 0; - virtual HRESULT WINAPI SetVideoClippingWindow(HWND hwnd) = 0; - virtual HRESULT WINAPI RepaintVideo(HWND hwnd,HDC hdc) = 0; - virtual HRESULT WINAPI DisplayModeChanged(void) = 0; - virtual HRESULT WINAPI GetCurrentImage(BYTE **lpDib) = 0; - virtual HRESULT WINAPI SetBorderColor(COLORREF Clr) = 0; - virtual HRESULT WINAPI GetBorderColor(COLORREF *lpClr) = 0; - virtual HRESULT WINAPI SetColorKey(COLORREF Clr) = 0; - virtual HRESULT WINAPI GetColorKey(COLORREF *lpClr) = 0; - }; -#else - typedef struct IVMRWindowlessControlVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IVMRWindowlessControl *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IVMRWindowlessControl *This); - ULONG (WINAPI *Release)(IVMRWindowlessControl *This); - HRESULT (WINAPI *GetNativeVideoSize)(IVMRWindowlessControl *This,LONG *lpWidth,LONG *lpHeight,LONG *lpARWidth,LONG *lpARHeight); - HRESULT (WINAPI *GetMinIdealVideoSize)(IVMRWindowlessControl *This,LONG *lpWidth,LONG *lpHeight); - HRESULT (WINAPI *GetMaxIdealVideoSize)(IVMRWindowlessControl *This,LONG *lpWidth,LONG *lpHeight); - HRESULT (WINAPI *SetVideoPosition)(IVMRWindowlessControl *This,const LPRECT lpSRCRect,const LPRECT lpDSTRect); - HRESULT (WINAPI *GetVideoPosition)(IVMRWindowlessControl *This,LPRECT lpSRCRect,LPRECT lpDSTRect); - HRESULT (WINAPI *GetAspectRatioMode)(IVMRWindowlessControl *This,DWORD *lpAspectRatioMode); - HRESULT (WINAPI *SetAspectRatioMode)(IVMRWindowlessControl *This,DWORD AspectRatioMode); - HRESULT (WINAPI *SetVideoClippingWindow)(IVMRWindowlessControl *This,HWND hwnd); - HRESULT (WINAPI *RepaintVideo)(IVMRWindowlessControl *This,HWND hwnd,HDC hdc); - HRESULT (WINAPI *DisplayModeChanged)(IVMRWindowlessControl *This); - HRESULT (WINAPI *GetCurrentImage)(IVMRWindowlessControl *This,BYTE **lpDib); - HRESULT (WINAPI *SetBorderColor)(IVMRWindowlessControl *This,COLORREF Clr); - HRESULT (WINAPI *GetBorderColor)(IVMRWindowlessControl *This,COLORREF *lpClr); - HRESULT (WINAPI *SetColorKey)(IVMRWindowlessControl *This,COLORREF Clr); - HRESULT (WINAPI *GetColorKey)(IVMRWindowlessControl *This,COLORREF *lpClr); - END_INTERFACE - } IVMRWindowlessControlVtbl; - struct IVMRWindowlessControl { - CONST_VTBL struct IVMRWindowlessControlVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IVMRWindowlessControl_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IVMRWindowlessControl_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IVMRWindowlessControl_Release(This) (This)->lpVtbl->Release(This) -#define IVMRWindowlessControl_GetNativeVideoSize(This,lpWidth,lpHeight,lpARWidth,lpARHeight) (This)->lpVtbl->GetNativeVideoSize(This,lpWidth,lpHeight,lpARWidth,lpARHeight) -#define IVMRWindowlessControl_GetMinIdealVideoSize(This,lpWidth,lpHeight) (This)->lpVtbl->GetMinIdealVideoSize(This,lpWidth,lpHeight) -#define IVMRWindowlessControl_GetMaxIdealVideoSize(This,lpWidth,lpHeight) (This)->lpVtbl->GetMaxIdealVideoSize(This,lpWidth,lpHeight) -#define IVMRWindowlessControl_SetVideoPosition(This,lpSRCRect,lpDSTRect) (This)->lpVtbl->SetVideoPosition(This,lpSRCRect,lpDSTRect) -#define IVMRWindowlessControl_GetVideoPosition(This,lpSRCRect,lpDSTRect) (This)->lpVtbl->GetVideoPosition(This,lpSRCRect,lpDSTRect) -#define IVMRWindowlessControl_GetAspectRatioMode(This,lpAspectRatioMode) (This)->lpVtbl->GetAspectRatioMode(This,lpAspectRatioMode) -#define IVMRWindowlessControl_SetAspectRatioMode(This,AspectRatioMode) (This)->lpVtbl->SetAspectRatioMode(This,AspectRatioMode) -#define IVMRWindowlessControl_SetVideoClippingWindow(This,hwnd) (This)->lpVtbl->SetVideoClippingWindow(This,hwnd) -#define IVMRWindowlessControl_RepaintVideo(This,hwnd,hdc) (This)->lpVtbl->RepaintVideo(This,hwnd,hdc) -#define IVMRWindowlessControl_DisplayModeChanged(This) (This)->lpVtbl->DisplayModeChanged(This) -#define IVMRWindowlessControl_GetCurrentImage(This,lpDib) (This)->lpVtbl->GetCurrentImage(This,lpDib) -#define IVMRWindowlessControl_SetBorderColor(This,Clr) (This)->lpVtbl->SetBorderColor(This,Clr) -#define IVMRWindowlessControl_GetBorderColor(This,lpClr) (This)->lpVtbl->GetBorderColor(This,lpClr) -#define IVMRWindowlessControl_SetColorKey(This,Clr) (This)->lpVtbl->SetColorKey(This,Clr) -#define IVMRWindowlessControl_GetColorKey(This,lpClr) (This)->lpVtbl->GetColorKey(This,lpClr) -#endif -#endif - HRESULT WINAPI IVMRWindowlessControl_GetNativeVideoSize_Proxy(IVMRWindowlessControl *This,LONG *lpWidth,LONG *lpHeight,LONG *lpARWidth,LONG *lpARHeight); - void __RPC_STUB IVMRWindowlessControl_GetNativeVideoSize_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRWindowlessControl_GetMinIdealVideoSize_Proxy(IVMRWindowlessControl *This,LONG *lpWidth,LONG *lpHeight); - void __RPC_STUB IVMRWindowlessControl_GetMinIdealVideoSize_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRWindowlessControl_GetMaxIdealVideoSize_Proxy(IVMRWindowlessControl *This,LONG *lpWidth,LONG *lpHeight); - void __RPC_STUB IVMRWindowlessControl_GetMaxIdealVideoSize_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRWindowlessControl_SetVideoPosition_Proxy(IVMRWindowlessControl *This,const LPRECT lpSRCRect,const LPRECT lpDSTRect); - void __RPC_STUB IVMRWindowlessControl_SetVideoPosition_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRWindowlessControl_GetVideoPosition_Proxy(IVMRWindowlessControl *This,LPRECT lpSRCRect,LPRECT lpDSTRect); - void __RPC_STUB IVMRWindowlessControl_GetVideoPosition_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRWindowlessControl_GetAspectRatioMode_Proxy(IVMRWindowlessControl *This,DWORD *lpAspectRatioMode); - void __RPC_STUB IVMRWindowlessControl_GetAspectRatioMode_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRWindowlessControl_SetAspectRatioMode_Proxy(IVMRWindowlessControl *This,DWORD AspectRatioMode); - void __RPC_STUB IVMRWindowlessControl_SetAspectRatioMode_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRWindowlessControl_SetVideoClippingWindow_Proxy(IVMRWindowlessControl *This,HWND hwnd); - void __RPC_STUB IVMRWindowlessControl_SetVideoClippingWindow_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRWindowlessControl_RepaintVideo_Proxy(IVMRWindowlessControl *This,HWND hwnd,HDC hdc); - void __RPC_STUB IVMRWindowlessControl_RepaintVideo_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRWindowlessControl_DisplayModeChanged_Proxy(IVMRWindowlessControl *This); - void __RPC_STUB IVMRWindowlessControl_DisplayModeChanged_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRWindowlessControl_GetCurrentImage_Proxy(IVMRWindowlessControl *This,BYTE **lpDib); - void __RPC_STUB IVMRWindowlessControl_GetCurrentImage_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRWindowlessControl_SetBorderColor_Proxy(IVMRWindowlessControl *This,COLORREF Clr); - void __RPC_STUB IVMRWindowlessControl_SetBorderColor_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRWindowlessControl_GetBorderColor_Proxy(IVMRWindowlessControl *This,COLORREF *lpClr); - void __RPC_STUB IVMRWindowlessControl_GetBorderColor_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRWindowlessControl_SetColorKey_Proxy(IVMRWindowlessControl *This,COLORREF Clr); - void __RPC_STUB IVMRWindowlessControl_SetColorKey_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRWindowlessControl_GetColorKey_Proxy(IVMRWindowlessControl *This,COLORREF *lpClr); - void __RPC_STUB IVMRWindowlessControl_GetColorKey_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - typedef enum __MIDL___MIDL_itf_strmif_0401_0001 { - MixerPref_NoDecimation = 0x1,MixerPref_DecimateOutput = 0x2,MixerPref_ARAdjustXorY = 0x4,MixerPref_DecimationReserved = 0x8, - MixerPref_DecimateMask = 0xf,MixerPref_BiLinearFiltering = 0x10,MixerPref_PointFiltering = 0x20,MixerPref_FilteringMask = 0xf0, - MixerPref_RenderTargetRGB = 0x100,MixerPref_RenderTargetYUV = 0x1000,MixerPref_RenderTargetYUV420 = 0x200,MixerPref_RenderTargetYUV422 = 0x400, - MixerPref_RenderTargetYUV444 = 0x800,MixerPref_RenderTargetReserved = 0xe000,MixerPref_RenderTargetMask = 0xff00, - MixerPref_DynamicSwitchToBOB = 0x10000,MixerPref_DynamicDecimateBy2 = 0x20000,MixerPref_DynamicReserved = 0xc0000, - MixerPref_DynamicMask = 0xf0000 - } VMRMixerPrefs; - - typedef struct _NORMALIZEDRECT { - float left; - float top; - float right; - float bottom; - } NORMALIZEDRECT; - - typedef struct _NORMALIZEDRECT *PNORMALIZEDRECT; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0401_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0401_v0_0_s_ifspec; -#ifndef __IVMRMixerControl_INTERFACE_DEFINED__ -#define __IVMRMixerControl_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IVMRMixerControl; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IVMRMixerControl : public IUnknown { - public: - virtual HRESULT WINAPI SetAlpha(DWORD dwStreamID,float Alpha) = 0; - virtual HRESULT WINAPI GetAlpha(DWORD dwStreamID,float *pAlpha) = 0; - virtual HRESULT WINAPI SetZOrder(DWORD dwStreamID,DWORD dwZ) = 0; - virtual HRESULT WINAPI GetZOrder(DWORD dwStreamID,DWORD *pZ) = 0; - virtual HRESULT WINAPI SetOutputRect(DWORD dwStreamID,const NORMALIZEDRECT *pRect) = 0; - virtual HRESULT WINAPI GetOutputRect(DWORD dwStreamID,NORMALIZEDRECT *pRect) = 0; - virtual HRESULT WINAPI SetBackgroundClr(COLORREF ClrBkg) = 0; - virtual HRESULT WINAPI GetBackgroundClr(COLORREF *lpClrBkg) = 0; - virtual HRESULT WINAPI SetMixingPrefs(DWORD dwMixerPrefs) = 0; - virtual HRESULT WINAPI GetMixingPrefs(DWORD *pdwMixerPrefs) = 0; - }; -#else - typedef struct IVMRMixerControlVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IVMRMixerControl *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IVMRMixerControl *This); - ULONG (WINAPI *Release)(IVMRMixerControl *This); - HRESULT (WINAPI *SetAlpha)(IVMRMixerControl *This,DWORD dwStreamID,float Alpha); - HRESULT (WINAPI *GetAlpha)(IVMRMixerControl *This,DWORD dwStreamID,float *pAlpha); - HRESULT (WINAPI *SetZOrder)(IVMRMixerControl *This,DWORD dwStreamID,DWORD dwZ); - HRESULT (WINAPI *GetZOrder)(IVMRMixerControl *This,DWORD dwStreamID,DWORD *pZ); - HRESULT (WINAPI *SetOutputRect)(IVMRMixerControl *This,DWORD dwStreamID,const NORMALIZEDRECT *pRect); - HRESULT (WINAPI *GetOutputRect)(IVMRMixerControl *This,DWORD dwStreamID,NORMALIZEDRECT *pRect); - HRESULT (WINAPI *SetBackgroundClr)(IVMRMixerControl *This,COLORREF ClrBkg); - HRESULT (WINAPI *GetBackgroundClr)(IVMRMixerControl *This,COLORREF *lpClrBkg); - HRESULT (WINAPI *SetMixingPrefs)(IVMRMixerControl *This,DWORD dwMixerPrefs); - HRESULT (WINAPI *GetMixingPrefs)(IVMRMixerControl *This,DWORD *pdwMixerPrefs); - END_INTERFACE - } IVMRMixerControlVtbl; - struct IVMRMixerControl { - CONST_VTBL struct IVMRMixerControlVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IVMRMixerControl_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IVMRMixerControl_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IVMRMixerControl_Release(This) (This)->lpVtbl->Release(This) -#define IVMRMixerControl_SetAlpha(This,dwStreamID,Alpha) (This)->lpVtbl->SetAlpha(This,dwStreamID,Alpha) -#define IVMRMixerControl_GetAlpha(This,dwStreamID,pAlpha) (This)->lpVtbl->GetAlpha(This,dwStreamID,pAlpha) -#define IVMRMixerControl_SetZOrder(This,dwStreamID,dwZ) (This)->lpVtbl->SetZOrder(This,dwStreamID,dwZ) -#define IVMRMixerControl_GetZOrder(This,dwStreamID,pZ) (This)->lpVtbl->GetZOrder(This,dwStreamID,pZ) -#define IVMRMixerControl_SetOutputRect(This,dwStreamID,pRect) (This)->lpVtbl->SetOutputRect(This,dwStreamID,pRect) -#define IVMRMixerControl_GetOutputRect(This,dwStreamID,pRect) (This)->lpVtbl->GetOutputRect(This,dwStreamID,pRect) -#define IVMRMixerControl_SetBackgroundClr(This,ClrBkg) (This)->lpVtbl->SetBackgroundClr(This,ClrBkg) -#define IVMRMixerControl_GetBackgroundClr(This,lpClrBkg) (This)->lpVtbl->GetBackgroundClr(This,lpClrBkg) -#define IVMRMixerControl_SetMixingPrefs(This,dwMixerPrefs) (This)->lpVtbl->SetMixingPrefs(This,dwMixerPrefs) -#define IVMRMixerControl_GetMixingPrefs(This,pdwMixerPrefs) (This)->lpVtbl->GetMixingPrefs(This,pdwMixerPrefs) -#endif -#endif - HRESULT WINAPI IVMRMixerControl_SetAlpha_Proxy(IVMRMixerControl *This,DWORD dwStreamID,float Alpha); - void __RPC_STUB IVMRMixerControl_SetAlpha_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRMixerControl_GetAlpha_Proxy(IVMRMixerControl *This,DWORD dwStreamID,float *pAlpha); - void __RPC_STUB IVMRMixerControl_GetAlpha_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRMixerControl_SetZOrder_Proxy(IVMRMixerControl *This,DWORD dwStreamID,DWORD dwZ); - void __RPC_STUB IVMRMixerControl_SetZOrder_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRMixerControl_GetZOrder_Proxy(IVMRMixerControl *This,DWORD dwStreamID,DWORD *pZ); - void __RPC_STUB IVMRMixerControl_GetZOrder_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRMixerControl_SetOutputRect_Proxy(IVMRMixerControl *This,DWORD dwStreamID,const NORMALIZEDRECT *pRect); - void __RPC_STUB IVMRMixerControl_SetOutputRect_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRMixerControl_GetOutputRect_Proxy(IVMRMixerControl *This,DWORD dwStreamID,NORMALIZEDRECT *pRect); - void __RPC_STUB IVMRMixerControl_GetOutputRect_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRMixerControl_SetBackgroundClr_Proxy(IVMRMixerControl *This,COLORREF ClrBkg); - void __RPC_STUB IVMRMixerControl_SetBackgroundClr_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRMixerControl_GetBackgroundClr_Proxy(IVMRMixerControl *This,COLORREF *lpClrBkg); - void __RPC_STUB IVMRMixerControl_GetBackgroundClr_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRMixerControl_SetMixingPrefs_Proxy(IVMRMixerControl *This,DWORD dwMixerPrefs); - void __RPC_STUB IVMRMixerControl_SetMixingPrefs_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRMixerControl_GetMixingPrefs_Proxy(IVMRMixerControl *This,DWORD *pdwMixerPrefs); - - void __RPC_STUB IVMRMixerControl_GetMixingPrefs_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifdef __cplusplus - typedef struct tagVMRGUID { - ::GUID *pGUID; - ::GUID GUID; - } VMRGUID; -#else - typedef struct tagVMRGUID { - GUID *pGUID; - GUID GUID; - } VMRGUID; -#endif - - typedef struct tagVMRMONITORINFO { - VMRGUID guid; - RECT rcMonitor; - HMONITOR hMon; - DWORD dwFlags; - wchar_t szDevice[32]; - wchar_t szDescription[256]; - LARGE_INTEGER liDriverVersion; - DWORD dwVendorId; - DWORD dwDeviceId; - DWORD dwSubSysId; - DWORD dwRevision; - } VMRMONITORINFO; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0402_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0402_v0_0_s_ifspec; -#ifndef __IVMRMonitorConfig_INTERFACE_DEFINED__ -#define __IVMRMonitorConfig_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IVMRMonitorConfig; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IVMRMonitorConfig : public IUnknown { - public: - virtual HRESULT WINAPI SetMonitor(const VMRGUID *pGUID) = 0; - virtual HRESULT WINAPI GetMonitor(VMRGUID *pGUID) = 0; - virtual HRESULT WINAPI SetDefaultMonitor(const VMRGUID *pGUID) = 0; - virtual HRESULT WINAPI GetDefaultMonitor(VMRGUID *pGUID) = 0; - virtual HRESULT WINAPI GetAvailableMonitors(VMRMONITORINFO *pInfo,DWORD dwMaxInfoArraySize,DWORD *pdwNumDevices) = 0; - }; -#else - typedef struct IVMRMonitorConfigVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IVMRMonitorConfig *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IVMRMonitorConfig *This); - ULONG (WINAPI *Release)(IVMRMonitorConfig *This); - HRESULT (WINAPI *SetMonitor)(IVMRMonitorConfig *This,const VMRGUID *pGUID); - HRESULT (WINAPI *GetMonitor)(IVMRMonitorConfig *This,VMRGUID *pGUID); - HRESULT (WINAPI *SetDefaultMonitor)(IVMRMonitorConfig *This,const VMRGUID *pGUID); - HRESULT (WINAPI *GetDefaultMonitor)(IVMRMonitorConfig *This,VMRGUID *pGUID); - HRESULT (WINAPI *GetAvailableMonitors)(IVMRMonitorConfig *This,VMRMONITORINFO *pInfo,DWORD dwMaxInfoArraySize,DWORD *pdwNumDevices); - END_INTERFACE - } IVMRMonitorConfigVtbl; - struct IVMRMonitorConfig { - CONST_VTBL struct IVMRMonitorConfigVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IVMRMonitorConfig_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IVMRMonitorConfig_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IVMRMonitorConfig_Release(This) (This)->lpVtbl->Release(This) -#define IVMRMonitorConfig_SetMonitor(This,pGUID) (This)->lpVtbl->SetMonitor(This,pGUID) -#define IVMRMonitorConfig_GetMonitor(This,pGUID) (This)->lpVtbl->GetMonitor(This,pGUID) -#define IVMRMonitorConfig_SetDefaultMonitor(This,pGUID) (This)->lpVtbl->SetDefaultMonitor(This,pGUID) -#define IVMRMonitorConfig_GetDefaultMonitor(This,pGUID) (This)->lpVtbl->GetDefaultMonitor(This,pGUID) -#define IVMRMonitorConfig_GetAvailableMonitors(This,pInfo,dwMaxInfoArraySize,pdwNumDevices) (This)->lpVtbl->GetAvailableMonitors(This,pInfo,dwMaxInfoArraySize,pdwNumDevices) -#endif -#endif - HRESULT WINAPI IVMRMonitorConfig_SetMonitor_Proxy(IVMRMonitorConfig *This,const VMRGUID *pGUID); - void __RPC_STUB IVMRMonitorConfig_SetMonitor_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRMonitorConfig_GetMonitor_Proxy(IVMRMonitorConfig *This,VMRGUID *pGUID); - void __RPC_STUB IVMRMonitorConfig_GetMonitor_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRMonitorConfig_SetDefaultMonitor_Proxy(IVMRMonitorConfig *This,const VMRGUID *pGUID); - void __RPC_STUB IVMRMonitorConfig_SetDefaultMonitor_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRMonitorConfig_GetDefaultMonitor_Proxy(IVMRMonitorConfig *This,VMRGUID *pGUID); - void __RPC_STUB IVMRMonitorConfig_GetDefaultMonitor_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRMonitorConfig_GetAvailableMonitors_Proxy(IVMRMonitorConfig *This,VMRMONITORINFO *pInfo,DWORD dwMaxInfoArraySize,DWORD *pdwNumDevices); - void __RPC_STUB IVMRMonitorConfig_GetAvailableMonitors_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - typedef enum __MIDL___MIDL_itf_strmif_0403_0001 { - RenderPrefs_RestrictToInitialMonitor = 0,RenderPrefs_ForceOffscreen = 0x1,RenderPrefs_ForceOverlays = 0x2,RenderPrefs_AllowOverlays = 0, - RenderPrefs_AllowOffscreen = 0,RenderPrefs_DoNotRenderColorKeyAndBorder = 0x8,RenderPrefs_Reserved = 0x10,RenderPrefs_PreferAGPMemWhenMixing = 0x20, - RenderPrefs_Mask = 0x3f - } VMRRenderPrefs; - - typedef enum __MIDL___MIDL_itf_strmif_0403_0002 { - VMRMode_Windowed = 0x1,VMRMode_Windowless = 0x2,VMRMode_Renderless = 0x4,VMRMode_Mask = 0x7 - } VMRMode; - - enum __MIDL___MIDL_itf_strmif_0403_0003 { - MAX_NUMBER_OF_STREAMS = 16 - }; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0403_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0403_v0_0_s_ifspec; -#ifndef __IVMRFilterConfig_INTERFACE_DEFINED__ -#define __IVMRFilterConfig_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IVMRFilterConfig; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IVMRFilterConfig : public IUnknown { - public: - virtual HRESULT WINAPI SetImageCompositor(IVMRImageCompositor *lpVMRImgCompositor) = 0; - virtual HRESULT WINAPI SetNumberOfStreams(DWORD dwMaxStreams) = 0; - virtual HRESULT WINAPI GetNumberOfStreams(DWORD *pdwMaxStreams) = 0; - virtual HRESULT WINAPI SetRenderingPrefs(DWORD dwRenderFlags) = 0; - virtual HRESULT WINAPI GetRenderingPrefs(DWORD *pdwRenderFlags) = 0; - virtual HRESULT WINAPI SetRenderingMode(DWORD Mode) = 0; - virtual HRESULT WINAPI GetRenderingMode(DWORD *pMode) = 0; - }; -#else - typedef struct IVMRFilterConfigVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IVMRFilterConfig *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IVMRFilterConfig *This); - ULONG (WINAPI *Release)(IVMRFilterConfig *This); - HRESULT (WINAPI *SetImageCompositor)(IVMRFilterConfig *This,IVMRImageCompositor *lpVMRImgCompositor); - HRESULT (WINAPI *SetNumberOfStreams)(IVMRFilterConfig *This,DWORD dwMaxStreams); - HRESULT (WINAPI *GetNumberOfStreams)(IVMRFilterConfig *This,DWORD *pdwMaxStreams); - HRESULT (WINAPI *SetRenderingPrefs)(IVMRFilterConfig *This,DWORD dwRenderFlags); - HRESULT (WINAPI *GetRenderingPrefs)(IVMRFilterConfig *This,DWORD *pdwRenderFlags); - HRESULT (WINAPI *SetRenderingMode)(IVMRFilterConfig *This,DWORD Mode); - HRESULT (WINAPI *GetRenderingMode)(IVMRFilterConfig *This,DWORD *pMode); - END_INTERFACE - } IVMRFilterConfigVtbl; - struct IVMRFilterConfig { - CONST_VTBL struct IVMRFilterConfigVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IVMRFilterConfig_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IVMRFilterConfig_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IVMRFilterConfig_Release(This) (This)->lpVtbl->Release(This) -#define IVMRFilterConfig_SetImageCompositor(This,lpVMRImgCompositor) (This)->lpVtbl->SetImageCompositor(This,lpVMRImgCompositor) -#define IVMRFilterConfig_SetNumberOfStreams(This,dwMaxStreams) (This)->lpVtbl->SetNumberOfStreams(This,dwMaxStreams) -#define IVMRFilterConfig_GetNumberOfStreams(This,pdwMaxStreams) (This)->lpVtbl->GetNumberOfStreams(This,pdwMaxStreams) -#define IVMRFilterConfig_SetRenderingPrefs(This,dwRenderFlags) (This)->lpVtbl->SetRenderingPrefs(This,dwRenderFlags) -#define IVMRFilterConfig_GetRenderingPrefs(This,pdwRenderFlags) (This)->lpVtbl->GetRenderingPrefs(This,pdwRenderFlags) -#define IVMRFilterConfig_SetRenderingMode(This,Mode) (This)->lpVtbl->SetRenderingMode(This,Mode) -#define IVMRFilterConfig_GetRenderingMode(This,pMode) (This)->lpVtbl->GetRenderingMode(This,pMode) -#endif -#endif - HRESULT WINAPI IVMRFilterConfig_SetImageCompositor_Proxy(IVMRFilterConfig *This,IVMRImageCompositor *lpVMRImgCompositor); - void __RPC_STUB IVMRFilterConfig_SetImageCompositor_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRFilterConfig_SetNumberOfStreams_Proxy(IVMRFilterConfig *This,DWORD dwMaxStreams); - void __RPC_STUB IVMRFilterConfig_SetNumberOfStreams_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRFilterConfig_GetNumberOfStreams_Proxy(IVMRFilterConfig *This,DWORD *pdwMaxStreams); - void __RPC_STUB IVMRFilterConfig_GetNumberOfStreams_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRFilterConfig_SetRenderingPrefs_Proxy(IVMRFilterConfig *This,DWORD dwRenderFlags); - void __RPC_STUB IVMRFilterConfig_SetRenderingPrefs_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRFilterConfig_GetRenderingPrefs_Proxy(IVMRFilterConfig *This,DWORD *pdwRenderFlags); - void __RPC_STUB IVMRFilterConfig_GetRenderingPrefs_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRFilterConfig_SetRenderingMode_Proxy(IVMRFilterConfig *This,DWORD Mode); - void __RPC_STUB IVMRFilterConfig_SetRenderingMode_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRFilterConfig_GetRenderingMode_Proxy(IVMRFilterConfig *This,DWORD *pMode); - void __RPC_STUB IVMRFilterConfig_GetRenderingMode_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IVMRAspectRatioControl_INTERFACE_DEFINED__ -#define __IVMRAspectRatioControl_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IVMRAspectRatioControl; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IVMRAspectRatioControl : public IUnknown { - public: - virtual HRESULT WINAPI GetAspectRatioMode(LPDWORD lpdwARMode) = 0; - virtual HRESULT WINAPI SetAspectRatioMode(DWORD dwARMode) = 0; - }; -#else - typedef struct IVMRAspectRatioControlVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IVMRAspectRatioControl *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IVMRAspectRatioControl *This); - ULONG (WINAPI *Release)(IVMRAspectRatioControl *This); - HRESULT (WINAPI *GetAspectRatioMode)(IVMRAspectRatioControl *This,LPDWORD lpdwARMode); - HRESULT (WINAPI *SetAspectRatioMode)(IVMRAspectRatioControl *This,DWORD dwARMode); - END_INTERFACE - } IVMRAspectRatioControlVtbl; - struct IVMRAspectRatioControl { - CONST_VTBL struct IVMRAspectRatioControlVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IVMRAspectRatioControl_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IVMRAspectRatioControl_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IVMRAspectRatioControl_Release(This) (This)->lpVtbl->Release(This) -#define IVMRAspectRatioControl_GetAspectRatioMode(This,lpdwARMode) (This)->lpVtbl->GetAspectRatioMode(This,lpdwARMode) -#define IVMRAspectRatioControl_SetAspectRatioMode(This,dwARMode) (This)->lpVtbl->SetAspectRatioMode(This,dwARMode) -#endif -#endif - HRESULT WINAPI IVMRAspectRatioControl_GetAspectRatioMode_Proxy(IVMRAspectRatioControl *This,LPDWORD lpdwARMode); - void __RPC_STUB IVMRAspectRatioControl_GetAspectRatioMode_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRAspectRatioControl_SetAspectRatioMode_Proxy(IVMRAspectRatioControl *This,DWORD dwARMode); - void __RPC_STUB IVMRAspectRatioControl_SetAspectRatioMode_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - typedef enum __MIDL___MIDL_itf_strmif_0405_0001 { - DeinterlacePref_NextBest = 0x1,DeinterlacePref_BOB = 0x2,DeinterlacePref_Weave = 0x4,DeinterlacePref_Mask = 0x7 - } VMRDeinterlacePrefs; - - typedef enum __MIDL___MIDL_itf_strmif_0405_0002 { - DeinterlaceTech_Unknown = 0,DeinterlaceTech_BOBLineReplicate = 0x1,DeinterlaceTech_BOBVerticalStretch = 0x2,DeinterlaceTech_MedianFiltering = 0x4, - DeinterlaceTech_EdgeFiltering = 0x10,DeinterlaceTech_FieldAdaptive = 0x20,DeinterlaceTech_PixelAdaptive = 0x40, - DeinterlaceTech_MotionVectorSteered = 0x80 - } VMRDeinterlaceTech; - - typedef struct _VMRFrequency { - DWORD dwNumerator; - DWORD dwDenominator; - } VMRFrequency; - - typedef struct _VMRVideoDesc { - DWORD dwSize; - DWORD dwSampleWidth; - DWORD dwSampleHeight; - WINBOOL SingleFieldPerSample; - DWORD dwFourCC; - VMRFrequency InputSampleFreq; - VMRFrequency OutputFrameFreq; - } VMRVideoDesc; - - typedef struct _VMRDeinterlaceCaps { - DWORD dwSize; - DWORD dwNumPreviousOutputFrames; - DWORD dwNumForwardRefSamples; - DWORD dwNumBackwardRefSamples; - VMRDeinterlaceTech DeinterlaceTechnology; - } VMRDeinterlaceCaps; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0405_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0405_v0_0_s_ifspec; -#ifndef __IVMRDeinterlaceControl_INTERFACE_DEFINED__ -#define __IVMRDeinterlaceControl_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IVMRDeinterlaceControl; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IVMRDeinterlaceControl : public IUnknown { - public: - virtual HRESULT WINAPI GetNumberOfDeinterlaceModes(VMRVideoDesc *lpVideoDescription,LPDWORD lpdwNumDeinterlaceModes,LPGUID lpDeinterlaceModes) = 0; - virtual HRESULT WINAPI GetDeinterlaceModeCaps(LPGUID lpDeinterlaceMode,VMRVideoDesc *lpVideoDescription,VMRDeinterlaceCaps *lpDeinterlaceCaps) = 0; - virtual HRESULT WINAPI GetDeinterlaceMode(DWORD dwStreamID,LPGUID lpDeinterlaceMode) = 0; - virtual HRESULT WINAPI SetDeinterlaceMode(DWORD dwStreamID,LPGUID lpDeinterlaceMode) = 0; - virtual HRESULT WINAPI GetDeinterlacePrefs(LPDWORD lpdwDeinterlacePrefs) = 0; - virtual HRESULT WINAPI SetDeinterlacePrefs(DWORD dwDeinterlacePrefs) = 0; - virtual HRESULT WINAPI GetActualDeinterlaceMode(DWORD dwStreamID,LPGUID lpDeinterlaceMode) = 0; - }; -#else - typedef struct IVMRDeinterlaceControlVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IVMRDeinterlaceControl *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IVMRDeinterlaceControl *This); - ULONG (WINAPI *Release)(IVMRDeinterlaceControl *This); - HRESULT (WINAPI *GetNumberOfDeinterlaceModes)(IVMRDeinterlaceControl *This,VMRVideoDesc *lpVideoDescription,LPDWORD lpdwNumDeinterlaceModes,LPGUID lpDeinterlaceModes); - HRESULT (WINAPI *GetDeinterlaceModeCaps)(IVMRDeinterlaceControl *This,LPGUID lpDeinterlaceMode,VMRVideoDesc *lpVideoDescription,VMRDeinterlaceCaps *lpDeinterlaceCaps); - HRESULT (WINAPI *GetDeinterlaceMode)(IVMRDeinterlaceControl *This,DWORD dwStreamID,LPGUID lpDeinterlaceMode); - HRESULT (WINAPI *SetDeinterlaceMode)(IVMRDeinterlaceControl *This,DWORD dwStreamID,LPGUID lpDeinterlaceMode); - HRESULT (WINAPI *GetDeinterlacePrefs)(IVMRDeinterlaceControl *This,LPDWORD lpdwDeinterlacePrefs); - HRESULT (WINAPI *SetDeinterlacePrefs)(IVMRDeinterlaceControl *This,DWORD dwDeinterlacePrefs); - HRESULT (WINAPI *GetActualDeinterlaceMode)(IVMRDeinterlaceControl *This,DWORD dwStreamID,LPGUID lpDeinterlaceMode); - END_INTERFACE - } IVMRDeinterlaceControlVtbl; - struct IVMRDeinterlaceControl { - CONST_VTBL struct IVMRDeinterlaceControlVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IVMRDeinterlaceControl_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IVMRDeinterlaceControl_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IVMRDeinterlaceControl_Release(This) (This)->lpVtbl->Release(This) -#define IVMRDeinterlaceControl_GetNumberOfDeinterlaceModes(This,lpVideoDescription,lpdwNumDeinterlaceModes,lpDeinterlaceModes) (This)->lpVtbl->GetNumberOfDeinterlaceModes(This,lpVideoDescription,lpdwNumDeinterlaceModes,lpDeinterlaceModes) -#define IVMRDeinterlaceControl_GetDeinterlaceModeCaps(This,lpDeinterlaceMode,lpVideoDescription,lpDeinterlaceCaps) (This)->lpVtbl->GetDeinterlaceModeCaps(This,lpDeinterlaceMode,lpVideoDescription,lpDeinterlaceCaps) -#define IVMRDeinterlaceControl_GetDeinterlaceMode(This,dwStreamID,lpDeinterlaceMode) (This)->lpVtbl->GetDeinterlaceMode(This,dwStreamID,lpDeinterlaceMode) -#define IVMRDeinterlaceControl_SetDeinterlaceMode(This,dwStreamID,lpDeinterlaceMode) (This)->lpVtbl->SetDeinterlaceMode(This,dwStreamID,lpDeinterlaceMode) -#define IVMRDeinterlaceControl_GetDeinterlacePrefs(This,lpdwDeinterlacePrefs) (This)->lpVtbl->GetDeinterlacePrefs(This,lpdwDeinterlacePrefs) -#define IVMRDeinterlaceControl_SetDeinterlacePrefs(This,dwDeinterlacePrefs) (This)->lpVtbl->SetDeinterlacePrefs(This,dwDeinterlacePrefs) -#define IVMRDeinterlaceControl_GetActualDeinterlaceMode(This,dwStreamID,lpDeinterlaceMode) (This)->lpVtbl->GetActualDeinterlaceMode(This,dwStreamID,lpDeinterlaceMode) -#endif -#endif - HRESULT WINAPI IVMRDeinterlaceControl_GetNumberOfDeinterlaceModes_Proxy(IVMRDeinterlaceControl *This,VMRVideoDesc *lpVideoDescription,LPDWORD lpdwNumDeinterlaceModes,LPGUID lpDeinterlaceModes); - void __RPC_STUB IVMRDeinterlaceControl_GetNumberOfDeinterlaceModes_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRDeinterlaceControl_GetDeinterlaceModeCaps_Proxy(IVMRDeinterlaceControl *This,LPGUID lpDeinterlaceMode,VMRVideoDesc *lpVideoDescription,VMRDeinterlaceCaps *lpDeinterlaceCaps); - void __RPC_STUB IVMRDeinterlaceControl_GetDeinterlaceModeCaps_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRDeinterlaceControl_GetDeinterlaceMode_Proxy(IVMRDeinterlaceControl *This,DWORD dwStreamID,LPGUID lpDeinterlaceMode); - void __RPC_STUB IVMRDeinterlaceControl_GetDeinterlaceMode_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRDeinterlaceControl_SetDeinterlaceMode_Proxy(IVMRDeinterlaceControl *This,DWORD dwStreamID,LPGUID lpDeinterlaceMode); - void __RPC_STUB IVMRDeinterlaceControl_SetDeinterlaceMode_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRDeinterlaceControl_GetDeinterlacePrefs_Proxy(IVMRDeinterlaceControl *This,LPDWORD lpdwDeinterlacePrefs); - void __RPC_STUB IVMRDeinterlaceControl_GetDeinterlacePrefs_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRDeinterlaceControl_SetDeinterlacePrefs_Proxy(IVMRDeinterlaceControl *This,DWORD dwDeinterlacePrefs); - void __RPC_STUB IVMRDeinterlaceControl_SetDeinterlacePrefs_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRDeinterlaceControl_GetActualDeinterlaceMode_Proxy(IVMRDeinterlaceControl *This,DWORD dwStreamID,LPGUID lpDeinterlaceMode); - void __RPC_STUB IVMRDeinterlaceControl_GetActualDeinterlaceMode_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - typedef struct _VMRALPHABITMAP { - DWORD dwFlags; - HDC hdc; - LPDIRECTDRAWSURFACE7 pDDS; - RECT rSrc; - NORMALIZEDRECT rDest; - FLOAT fAlpha; - COLORREF clrSrcKey; - } VMRALPHABITMAP; - - typedef struct _VMRALPHABITMAP *PVMRALPHABITMAP; - -#define VMRBITMAP_DISABLE 0x00000001 -#define VMRBITMAP_HDC 0x00000002 -#define VMRBITMAP_ENTIREDDS 0x00000004 -#define VMRBITMAP_SRCCOLORKEY 0x00000008 -#define VMRBITMAP_SRCRECT 0x00000010 - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0406_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0406_v0_0_s_ifspec; -#ifndef __IVMRMixerBitmap_INTERFACE_DEFINED__ -#define __IVMRMixerBitmap_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IVMRMixerBitmap; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IVMRMixerBitmap : public IUnknown { - public: - virtual HRESULT WINAPI SetAlphaBitmap(const VMRALPHABITMAP *pBmpParms) = 0; - virtual HRESULT WINAPI UpdateAlphaBitmapParameters(PVMRALPHABITMAP pBmpParms) = 0; - virtual HRESULT WINAPI GetAlphaBitmapParameters(PVMRALPHABITMAP pBmpParms) = 0; - }; -#else - typedef struct IVMRMixerBitmapVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IVMRMixerBitmap *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IVMRMixerBitmap *This); - ULONG (WINAPI *Release)(IVMRMixerBitmap *This); - HRESULT (WINAPI *SetAlphaBitmap)(IVMRMixerBitmap *This,const VMRALPHABITMAP *pBmpParms); - HRESULT (WINAPI *UpdateAlphaBitmapParameters)(IVMRMixerBitmap *This,PVMRALPHABITMAP pBmpParms); - HRESULT (WINAPI *GetAlphaBitmapParameters)(IVMRMixerBitmap *This,PVMRALPHABITMAP pBmpParms); - END_INTERFACE - } IVMRMixerBitmapVtbl; - struct IVMRMixerBitmap { - CONST_VTBL struct IVMRMixerBitmapVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IVMRMixerBitmap_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IVMRMixerBitmap_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IVMRMixerBitmap_Release(This) (This)->lpVtbl->Release(This) -#define IVMRMixerBitmap_SetAlphaBitmap(This,pBmpParms) (This)->lpVtbl->SetAlphaBitmap(This,pBmpParms) -#define IVMRMixerBitmap_UpdateAlphaBitmapParameters(This,pBmpParms) (This)->lpVtbl->UpdateAlphaBitmapParameters(This,pBmpParms) -#define IVMRMixerBitmap_GetAlphaBitmapParameters(This,pBmpParms) (This)->lpVtbl->GetAlphaBitmapParameters(This,pBmpParms) -#endif -#endif - HRESULT WINAPI IVMRMixerBitmap_SetAlphaBitmap_Proxy(IVMRMixerBitmap *This,const VMRALPHABITMAP *pBmpParms); - void __RPC_STUB IVMRMixerBitmap_SetAlphaBitmap_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRMixerBitmap_UpdateAlphaBitmapParameters_Proxy(IVMRMixerBitmap *This,PVMRALPHABITMAP pBmpParms); - void __RPC_STUB IVMRMixerBitmap_UpdateAlphaBitmapParameters_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRMixerBitmap_GetAlphaBitmapParameters_Proxy(IVMRMixerBitmap *This,PVMRALPHABITMAP pBmpParms); - void __RPC_STUB IVMRMixerBitmap_GetAlphaBitmapParameters_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - typedef struct _VMRVIDEOSTREAMINFO { - LPDIRECTDRAWSURFACE7 pddsVideoSurface; - DWORD dwWidth; - DWORD dwHeight; - DWORD dwStrmID; - FLOAT fAlpha; - DDCOLORKEY ddClrKey; - NORMALIZEDRECT rNormal; - } VMRVIDEOSTREAMINFO; - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0407_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0407_v0_0_s_ifspec; -#ifndef __IVMRImageCompositor_INTERFACE_DEFINED__ -#define __IVMRImageCompositor_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IVMRImageCompositor; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IVMRImageCompositor : public IUnknown { - public: - virtual HRESULT WINAPI InitCompositionTarget(IUnknown *pD3DDevice,LPDIRECTDRAWSURFACE7 pddsRenderTarget) = 0; - virtual HRESULT WINAPI TermCompositionTarget(IUnknown *pD3DDevice,LPDIRECTDRAWSURFACE7 pddsRenderTarget) = 0; - virtual HRESULT WINAPI SetStreamMediaType(DWORD dwStrmID,AM_MEDIA_TYPE *pmt,WINBOOL fTexture) = 0; - virtual HRESULT WINAPI CompositeImage(IUnknown *pD3DDevice,LPDIRECTDRAWSURFACE7 pddsRenderTarget,AM_MEDIA_TYPE *pmtRenderTarget,REFERENCE_TIME rtStart,REFERENCE_TIME rtEnd,DWORD dwClrBkGnd,VMRVIDEOSTREAMINFO *pVideoStreamInfo,UINT cStreams) = 0; - }; -#else - typedef struct IVMRImageCompositorVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IVMRImageCompositor *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IVMRImageCompositor *This); - ULONG (WINAPI *Release)(IVMRImageCompositor *This); - HRESULT (WINAPI *InitCompositionTarget)(IVMRImageCompositor *This,IUnknown *pD3DDevice,LPDIRECTDRAWSURFACE7 pddsRenderTarget); - HRESULT (WINAPI *TermCompositionTarget)(IVMRImageCompositor *This,IUnknown *pD3DDevice,LPDIRECTDRAWSURFACE7 pddsRenderTarget); - HRESULT (WINAPI *SetStreamMediaType)(IVMRImageCompositor *This,DWORD dwStrmID,AM_MEDIA_TYPE *pmt,WINBOOL fTexture); - HRESULT (WINAPI *CompositeImage)(IVMRImageCompositor *This,IUnknown *pD3DDevice,LPDIRECTDRAWSURFACE7 pddsRenderTarget,AM_MEDIA_TYPE *pmtRenderTarget,REFERENCE_TIME rtStart,REFERENCE_TIME rtEnd,DWORD dwClrBkGnd,VMRVIDEOSTREAMINFO *pVideoStreamInfo,UINT cStreams); - END_INTERFACE - } IVMRImageCompositorVtbl; - struct IVMRImageCompositor { - CONST_VTBL struct IVMRImageCompositorVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IVMRImageCompositor_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IVMRImageCompositor_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IVMRImageCompositor_Release(This) (This)->lpVtbl->Release(This) -#define IVMRImageCompositor_InitCompositionTarget(This,pD3DDevice,pddsRenderTarget) (This)->lpVtbl->InitCompositionTarget(This,pD3DDevice,pddsRenderTarget) -#define IVMRImageCompositor_TermCompositionTarget(This,pD3DDevice,pddsRenderTarget) (This)->lpVtbl->TermCompositionTarget(This,pD3DDevice,pddsRenderTarget) -#define IVMRImageCompositor_SetStreamMediaType(This,dwStrmID,pmt,fTexture) (This)->lpVtbl->SetStreamMediaType(This,dwStrmID,pmt,fTexture) -#define IVMRImageCompositor_CompositeImage(This,pD3DDevice,pddsRenderTarget,pmtRenderTarget,rtStart,rtEnd,dwClrBkGnd,pVideoStreamInfo,cStreams) (This)->lpVtbl->CompositeImage(This,pD3DDevice,pddsRenderTarget,pmtRenderTarget,rtStart,rtEnd,dwClrBkGnd,pVideoStreamInfo,cStreams) -#endif -#endif - HRESULT WINAPI IVMRImageCompositor_InitCompositionTarget_Proxy(IVMRImageCompositor *This,IUnknown *pD3DDevice,LPDIRECTDRAWSURFACE7 pddsRenderTarget); - void __RPC_STUB IVMRImageCompositor_InitCompositionTarget_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRImageCompositor_TermCompositionTarget_Proxy(IVMRImageCompositor *This,IUnknown *pD3DDevice,LPDIRECTDRAWSURFACE7 pddsRenderTarget); - void __RPC_STUB IVMRImageCompositor_TermCompositionTarget_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRImageCompositor_SetStreamMediaType_Proxy(IVMRImageCompositor *This,DWORD dwStrmID,AM_MEDIA_TYPE *pmt,WINBOOL fTexture); - void __RPC_STUB IVMRImageCompositor_SetStreamMediaType_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRImageCompositor_CompositeImage_Proxy(IVMRImageCompositor *This,IUnknown *pD3DDevice,LPDIRECTDRAWSURFACE7 pddsRenderTarget,AM_MEDIA_TYPE *pmtRenderTarget,REFERENCE_TIME rtStart,REFERENCE_TIME rtEnd,DWORD dwClrBkGnd,VMRVIDEOSTREAMINFO *pVideoStreamInfo,UINT cStreams); - void __RPC_STUB IVMRImageCompositor_CompositeImage_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IVMRVideoStreamControl_INTERFACE_DEFINED__ -#define __IVMRVideoStreamControl_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IVMRVideoStreamControl; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IVMRVideoStreamControl : public IUnknown { - public: - virtual HRESULT WINAPI SetColorKey(LPDDCOLORKEY lpClrKey) = 0; - virtual HRESULT WINAPI GetColorKey(LPDDCOLORKEY lpClrKey) = 0; - virtual HRESULT WINAPI SetStreamActiveState(WINBOOL fActive) = 0; - virtual HRESULT WINAPI GetStreamActiveState(WINBOOL *lpfActive) = 0; - }; -#else - typedef struct IVMRVideoStreamControlVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IVMRVideoStreamControl *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IVMRVideoStreamControl *This); - ULONG (WINAPI *Release)(IVMRVideoStreamControl *This); - HRESULT (WINAPI *SetColorKey)(IVMRVideoStreamControl *This,LPDDCOLORKEY lpClrKey); - HRESULT (WINAPI *GetColorKey)(IVMRVideoStreamControl *This,LPDDCOLORKEY lpClrKey); - HRESULT (WINAPI *SetStreamActiveState)(IVMRVideoStreamControl *This,WINBOOL fActive); - HRESULT (WINAPI *GetStreamActiveState)(IVMRVideoStreamControl *This,WINBOOL *lpfActive); - END_INTERFACE - } IVMRVideoStreamControlVtbl; - struct IVMRVideoStreamControl { - CONST_VTBL struct IVMRVideoStreamControlVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IVMRVideoStreamControl_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IVMRVideoStreamControl_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IVMRVideoStreamControl_Release(This) (This)->lpVtbl->Release(This) -#define IVMRVideoStreamControl_SetColorKey(This,lpClrKey) (This)->lpVtbl->SetColorKey(This,lpClrKey) -#define IVMRVideoStreamControl_GetColorKey(This,lpClrKey) (This)->lpVtbl->GetColorKey(This,lpClrKey) -#define IVMRVideoStreamControl_SetStreamActiveState(This,fActive) (This)->lpVtbl->SetStreamActiveState(This,fActive) -#define IVMRVideoStreamControl_GetStreamActiveState(This,lpfActive) (This)->lpVtbl->GetStreamActiveState(This,lpfActive) -#endif -#endif - HRESULT WINAPI IVMRVideoStreamControl_SetColorKey_Proxy(IVMRVideoStreamControl *This,LPDDCOLORKEY lpClrKey); - void __RPC_STUB IVMRVideoStreamControl_SetColorKey_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRVideoStreamControl_GetColorKey_Proxy(IVMRVideoStreamControl *This,LPDDCOLORKEY lpClrKey); - void __RPC_STUB IVMRVideoStreamControl_GetColorKey_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRVideoStreamControl_SetStreamActiveState_Proxy(IVMRVideoStreamControl *This,WINBOOL fActive); - void __RPC_STUB IVMRVideoStreamControl_SetStreamActiveState_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRVideoStreamControl_GetStreamActiveState_Proxy(IVMRVideoStreamControl *This,WINBOOL *lpfActive); - void __RPC_STUB IVMRVideoStreamControl_GetStreamActiveState_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IVMRSurface_INTERFACE_DEFINED__ -#define __IVMRSurface_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IVMRSurface; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IVMRSurface : public IUnknown { - public: - virtual HRESULT WINAPI IsSurfaceLocked(void) = 0; - virtual HRESULT WINAPI LockSurface(BYTE **lpSurface) = 0; - virtual HRESULT WINAPI UnlockSurface(void) = 0; - virtual HRESULT WINAPI GetSurface(LPDIRECTDRAWSURFACE7 *lplpSurface) = 0; - }; -#else - typedef struct IVMRSurfaceVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IVMRSurface *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IVMRSurface *This); - ULONG (WINAPI *Release)(IVMRSurface *This); - HRESULT (WINAPI *IsSurfaceLocked)(IVMRSurface *This); - HRESULT (WINAPI *LockSurface)(IVMRSurface *This,BYTE **lpSurface); - HRESULT (WINAPI *UnlockSurface)(IVMRSurface *This); - HRESULT (WINAPI *GetSurface)(IVMRSurface *This,LPDIRECTDRAWSURFACE7 *lplpSurface); - END_INTERFACE - } IVMRSurfaceVtbl; - struct IVMRSurface { - CONST_VTBL struct IVMRSurfaceVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IVMRSurface_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IVMRSurface_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IVMRSurface_Release(This) (This)->lpVtbl->Release(This) -#define IVMRSurface_IsSurfaceLocked(This) (This)->lpVtbl->IsSurfaceLocked(This) -#define IVMRSurface_LockSurface(This,lpSurface) (This)->lpVtbl->LockSurface(This,lpSurface) -#define IVMRSurface_UnlockSurface(This) (This)->lpVtbl->UnlockSurface(This) -#define IVMRSurface_GetSurface(This,lplpSurface) (This)->lpVtbl->GetSurface(This,lplpSurface) -#endif -#endif - HRESULT WINAPI IVMRSurface_IsSurfaceLocked_Proxy(IVMRSurface *This); - void __RPC_STUB IVMRSurface_IsSurfaceLocked_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRSurface_LockSurface_Proxy(IVMRSurface *This,BYTE **lpSurface); - void __RPC_STUB IVMRSurface_LockSurface_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRSurface_UnlockSurface_Proxy(IVMRSurface *This); - void __RPC_STUB IVMRSurface_UnlockSurface_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRSurface_GetSurface_Proxy(IVMRSurface *This,LPDIRECTDRAWSURFACE7 *lplpSurface); - void __RPC_STUB IVMRSurface_GetSurface_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IVMRImagePresenterConfig_INTERFACE_DEFINED__ -#define __IVMRImagePresenterConfig_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IVMRImagePresenterConfig; - -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IVMRImagePresenterConfig : public IUnknown { - public: - virtual HRESULT WINAPI SetRenderingPrefs(DWORD dwRenderFlags) = 0; - virtual HRESULT WINAPI GetRenderingPrefs(DWORD *dwRenderFlags) = 0; - }; -#else - typedef struct IVMRImagePresenterConfigVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IVMRImagePresenterConfig *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IVMRImagePresenterConfig *This); - ULONG (WINAPI *Release)(IVMRImagePresenterConfig *This); - HRESULT (WINAPI *SetRenderingPrefs)(IVMRImagePresenterConfig *This,DWORD dwRenderFlags); - HRESULT (WINAPI *GetRenderingPrefs)(IVMRImagePresenterConfig *This,DWORD *dwRenderFlags); - END_INTERFACE - } IVMRImagePresenterConfigVtbl; - struct IVMRImagePresenterConfig { - CONST_VTBL struct IVMRImagePresenterConfigVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IVMRImagePresenterConfig_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IVMRImagePresenterConfig_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IVMRImagePresenterConfig_Release(This) (This)->lpVtbl->Release(This) -#define IVMRImagePresenterConfig_SetRenderingPrefs(This,dwRenderFlags) (This)->lpVtbl->SetRenderingPrefs(This,dwRenderFlags) -#define IVMRImagePresenterConfig_GetRenderingPrefs(This,dwRenderFlags) (This)->lpVtbl->GetRenderingPrefs(This,dwRenderFlags) -#endif -#endif - HRESULT WINAPI IVMRImagePresenterConfig_SetRenderingPrefs_Proxy(IVMRImagePresenterConfig *This,DWORD dwRenderFlags); - void __RPC_STUB IVMRImagePresenterConfig_SetRenderingPrefs_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRImagePresenterConfig_GetRenderingPrefs_Proxy(IVMRImagePresenterConfig *This,DWORD *dwRenderFlags); - void __RPC_STUB IVMRImagePresenterConfig_GetRenderingPrefs_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IVMRImagePresenterExclModeConfig_INTERFACE_DEFINED__ -#define __IVMRImagePresenterExclModeConfig_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IVMRImagePresenterExclModeConfig; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IVMRImagePresenterExclModeConfig : public IVMRImagePresenterConfig { - public: - virtual HRESULT WINAPI SetXlcModeDDObjAndPrimarySurface(LPDIRECTDRAW7 lpDDObj,LPDIRECTDRAWSURFACE7 lpPrimarySurf) = 0; - virtual HRESULT WINAPI GetXlcModeDDObjAndPrimarySurface(LPDIRECTDRAW7 *lpDDObj,LPDIRECTDRAWSURFACE7 *lpPrimarySurf) = 0; - }; -#else - typedef struct IVMRImagePresenterExclModeConfigVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IVMRImagePresenterExclModeConfig *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IVMRImagePresenterExclModeConfig *This); - ULONG (WINAPI *Release)(IVMRImagePresenterExclModeConfig *This); - HRESULT (WINAPI *SetRenderingPrefs)(IVMRImagePresenterExclModeConfig *This,DWORD dwRenderFlags); - HRESULT (WINAPI *GetRenderingPrefs)(IVMRImagePresenterExclModeConfig *This,DWORD *dwRenderFlags); - HRESULT (WINAPI *SetXlcModeDDObjAndPrimarySurface)(IVMRImagePresenterExclModeConfig *This,LPDIRECTDRAW7 lpDDObj,LPDIRECTDRAWSURFACE7 lpPrimarySurf); - HRESULT (WINAPI *GetXlcModeDDObjAndPrimarySurface)(IVMRImagePresenterExclModeConfig *This,LPDIRECTDRAW7 *lpDDObj,LPDIRECTDRAWSURFACE7 *lpPrimarySurf); - END_INTERFACE - } IVMRImagePresenterExclModeConfigVtbl; - struct IVMRImagePresenterExclModeConfig { - CONST_VTBL struct IVMRImagePresenterExclModeConfigVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IVMRImagePresenterExclModeConfig_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IVMRImagePresenterExclModeConfig_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IVMRImagePresenterExclModeConfig_Release(This) (This)->lpVtbl->Release(This) -#define IVMRImagePresenterExclModeConfig_SetRenderingPrefs(This,dwRenderFlags) (This)->lpVtbl->SetRenderingPrefs(This,dwRenderFlags) -#define IVMRImagePresenterExclModeConfig_GetRenderingPrefs(This,dwRenderFlags) (This)->lpVtbl->GetRenderingPrefs(This,dwRenderFlags) -#define IVMRImagePresenterExclModeConfig_SetXlcModeDDObjAndPrimarySurface(This,lpDDObj,lpPrimarySurf) (This)->lpVtbl->SetXlcModeDDObjAndPrimarySurface(This,lpDDObj,lpPrimarySurf) -#define IVMRImagePresenterExclModeConfig_GetXlcModeDDObjAndPrimarySurface(This,lpDDObj,lpPrimarySurf) (This)->lpVtbl->GetXlcModeDDObjAndPrimarySurface(This,lpDDObj,lpPrimarySurf) -#endif -#endif - HRESULT WINAPI IVMRImagePresenterExclModeConfig_SetXlcModeDDObjAndPrimarySurface_Proxy(IVMRImagePresenterExclModeConfig *This,LPDIRECTDRAW7 lpDDObj,LPDIRECTDRAWSURFACE7 lpPrimarySurf); - void __RPC_STUB IVMRImagePresenterExclModeConfig_SetXlcModeDDObjAndPrimarySurface_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVMRImagePresenterExclModeConfig_GetXlcModeDDObjAndPrimarySurface_Proxy(IVMRImagePresenterExclModeConfig *This,LPDIRECTDRAW7 *lpDDObj,LPDIRECTDRAWSURFACE7 *lpPrimarySurf); - void __RPC_STUB IVMRImagePresenterExclModeConfig_GetXlcModeDDObjAndPrimarySurface_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - -#ifndef __IVPManager_INTERFACE_DEFINED__ -#define __IVPManager_INTERFACE_DEFINED__ - EXTERN_C const IID IID_IVPManager; -#if defined(__cplusplus) && !defined(CINTERFACE) - struct IVPManager : public IUnknown { - public: - virtual HRESULT WINAPI SetVideoPortIndex(DWORD dwVideoPortIndex) = 0; - virtual HRESULT WINAPI GetVideoPortIndex(DWORD *pdwVideoPortIndex) = 0; - }; -#else - typedef struct IVPManagerVtbl { - BEGIN_INTERFACE - HRESULT (WINAPI *QueryInterface)(IVPManager *This,REFIID riid,void **ppvObject); - ULONG (WINAPI *AddRef)(IVPManager *This); - ULONG (WINAPI *Release)(IVPManager *This); - HRESULT (WINAPI *SetVideoPortIndex)(IVPManager *This,DWORD dwVideoPortIndex); - HRESULT (WINAPI *GetVideoPortIndex)(IVPManager *This,DWORD *pdwVideoPortIndex); - END_INTERFACE - } IVPManagerVtbl; - struct IVPManager { - CONST_VTBL struct IVPManagerVtbl *lpVtbl; - }; -#ifdef COBJMACROS -#define IVPManager_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) -#define IVPManager_AddRef(This) (This)->lpVtbl->AddRef(This) -#define IVPManager_Release(This) (This)->lpVtbl->Release(This) -#define IVPManager_SetVideoPortIndex(This,dwVideoPortIndex) (This)->lpVtbl->SetVideoPortIndex(This,dwVideoPortIndex) -#define IVPManager_GetVideoPortIndex(This,pdwVideoPortIndex) (This)->lpVtbl->GetVideoPortIndex(This,pdwVideoPortIndex) -#endif -#endif - HRESULT WINAPI IVPManager_SetVideoPortIndex_Proxy(IVPManager *This,DWORD dwVideoPortIndex); - void __RPC_STUB IVPManager_SetVideoPortIndex_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); - HRESULT WINAPI IVPManager_GetVideoPortIndex_Proxy(IVPManager *This,DWORD *pdwVideoPortIndex); - void __RPC_STUB IVPManager_GetVideoPortIndex_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase); -#endif - - extern RPC_IF_HANDLE __MIDL_itf_strmif_0413_v0_0_c_ifspec; - extern RPC_IF_HANDLE __MIDL_itf_strmif_0413_v0_0_s_ifspec; - - unsigned long __RPC_API VARIANT_UserSize(unsigned long *,unsigned long,VARIANT *); - unsigned char *__RPC_API VARIANT_UserMarshal(unsigned long *,unsigned char *,VARIANT *); - unsigned char *__RPC_API VARIANT_UserUnmarshal(unsigned long *,unsigned char *,VARIANT *); - void __RPC_API VARIANT_UserFree(unsigned long *,VARIANT *); - - HRESULT WINAPI ICaptureGraphBuilder_FindInterface_Proxy(ICaptureGraphBuilder *This,const GUID *pCategory,IBaseFilter *pf,REFIID riid,void **ppint); - HRESULT WINAPI ICaptureGraphBuilder_FindInterface_Stub(ICaptureGraphBuilder *This,const GUID *pCategory,IBaseFilter *pf,REFIID riid,IUnknown **ppint); - HRESULT WINAPI ICaptureGraphBuilder2_FindInterface_Proxy(ICaptureGraphBuilder2 *This,const GUID *pCategory,const GUID *pType,IBaseFilter *pf,REFIID riid,void **ppint); - HRESULT WINAPI ICaptureGraphBuilder2_FindInterface_Stub(ICaptureGraphBuilder2 *This,const GUID *pCategory,const GUID *pType,IBaseFilter *pf,REFIID riid,IUnknown **ppint); - HRESULT WINAPI IKsPropertySet_Set_Proxy(IKsPropertySet *This,REFGUID guidPropSet,DWORD dwPropID,LPVOID pInstanceData,DWORD cbInstanceData,LPVOID pPropData,DWORD cbPropData); - HRESULT WINAPI IKsPropertySet_Set_Stub(IKsPropertySet *This,REFGUID guidPropSet,DWORD dwPropID,byte *pInstanceData,DWORD cbInstanceData,byte *pPropData,DWORD cbPropData); - HRESULT WINAPI IKsPropertySet_Get_Proxy(IKsPropertySet *This,REFGUID guidPropSet,DWORD dwPropID,LPVOID pInstanceData,DWORD cbInstanceData,LPVOID pPropData,DWORD cbPropData,DWORD *pcbReturned); - HRESULT WINAPI IKsPropertySet_Get_Stub(IKsPropertySet *This,REFGUID guidPropSet,DWORD dwPropID,byte *pInstanceData,DWORD cbInstanceData,byte *pPropData,DWORD cbPropData,DWORD *pcbReturned); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/vendor/dshow/uuids.h b/vendor/dshow/uuids.h deleted file mode 100644 index 53cdefdad..000000000 --- a/vendor/dshow/uuids.h +++ /dev/null @@ -1,368 +0,0 @@ -/** - * This file has no copyright assigned and is placed in the Public Domain. - * This file is part of the w64 mingw-runtime package. - * No warranty is given; refer to the file DISCLAIMER.PD within this package. - */ -#ifndef OUR_GUID_ENTRY -#define OUR_GUID_ENTRY(name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) DEFINE_GUID(name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8); -#endif - -#define MEDIATYPE_NULL GUID_NULL -#define MEDIASUBTYPE_NULL GUID_NULL - -OUR_GUID_ENTRY(MEDIASUBTYPE_None,0xe436eb8e,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70) -OUR_GUID_ENTRY(MEDIATYPE_Video,0x73646976,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIATYPE_Audio,0x73647561,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIATYPE_Text,0x73747874,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIATYPE_Midi,0x7364696D,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIATYPE_Stream,0xe436eb83,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70) -OUR_GUID_ENTRY(MEDIATYPE_Interleaved,0x73766169,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIATYPE_File,0x656c6966,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIATYPE_ScriptCommand,0x73636d64,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIATYPE_AUXLine21Data,0x670aea80,0x3a82,0x11d0,0xb7,0x9b,0x0,0xaa,0x0,0x37,0x67,0xa7) -OUR_GUID_ENTRY(MEDIATYPE_VBI,0xf72a76e1,0xeb0a,0x11d0,0xac,0xe4,0x00,0x00,0xc0,0xcc,0x16,0xba) -OUR_GUID_ENTRY(MEDIATYPE_Timecode,0x482dee3,0x7817,0x11cf,0x8a,0x3,0x0,0xaa,0x0,0x6e,0xcb,0x65) -OUR_GUID_ENTRY(MEDIATYPE_LMRT,0x74726c6d,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIATYPE_URL_STREAM,0x736c7275,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIASUBTYPE_CLPL,0x4C504C43,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIASUBTYPE_YUYV,0x56595559,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIASUBTYPE_IYUV,0x56555949,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIASUBTYPE_YVU9,0x39555659,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIASUBTYPE_Y411,0x31313459,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIASUBTYPE_Y41P,0x50313459,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIASUBTYPE_YUY2,0x32595559,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIASUBTYPE_YVYU,0x55595659,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIASUBTYPE_UYVY,0x59565955,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIASUBTYPE_Y211,0x31313259,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIASUBTYPE_CLJR,0x524a4c43,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIASUBTYPE_IF09,0x39304649,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIASUBTYPE_CPLA,0x414c5043,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIASUBTYPE_MJPG,0x47504A4D,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIASUBTYPE_TVMJ,0x4A4D5654,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIASUBTYPE_WAKE,0x454B4157,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIASUBTYPE_CFCC,0x43434643,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIASUBTYPE_IJPG,0x47504A49,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIASUBTYPE_Plum,0x6D756C50,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIASUBTYPE_DVCS,0x53435644,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIASUBTYPE_DVSD,0x44535644,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIASUBTYPE_MDVF,0x4656444D,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIASUBTYPE_RGB1,0xe436eb78,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70) -OUR_GUID_ENTRY(MEDIASUBTYPE_RGB4,0xe436eb79,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70) -OUR_GUID_ENTRY(MEDIASUBTYPE_RGB8,0xe436eb7a,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70) -OUR_GUID_ENTRY(MEDIASUBTYPE_RGB565,0xe436eb7b,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70) -OUR_GUID_ENTRY(MEDIASUBTYPE_RGB555,0xe436eb7c,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70) -OUR_GUID_ENTRY(MEDIASUBTYPE_RGB24,0xe436eb7d,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70) -OUR_GUID_ENTRY(MEDIASUBTYPE_RGB32,0xe436eb7e,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70) -OUR_GUID_ENTRY(MEDIASUBTYPE_ARGB1555,0x297c55af,0xe209,0x4cb3,0xb7,0x57,0xc7,0x6d,0x6b,0x9c,0x88,0xa8) -OUR_GUID_ENTRY(MEDIASUBTYPE_ARGB4444,0x6e6415e6,0x5c24,0x425f,0x93,0xcd,0x80,0x10,0x2b,0x3d,0x1c,0xca) -OUR_GUID_ENTRY(MEDIASUBTYPE_ARGB32,0x773c9ac0,0x3274,0x11d0,0xb7,0x24,0x0,0xaa,0x0,0x6c,0x1a,0x1) -OUR_GUID_ENTRY(MEDIASUBTYPE_A2R10G10B10,0x2f8bb76d,0xb644,0x4550,0xac,0xf3,0xd3,0x0c,0xaa,0x65,0xd5,0xc5) -OUR_GUID_ENTRY(MEDIASUBTYPE_A2B10G10R10,0x576f7893,0xbdf6,0x48c4,0x87,0x5f,0xae,0x7b,0x81,0x83,0x45,0x67) -OUR_GUID_ENTRY(MEDIASUBTYPE_AYUV,0x56555941,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIASUBTYPE_AI44,0x34344941,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIASUBTYPE_IA44,0x34344149,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIASUBTYPE_RGB32_D3D_DX7_RT,0x32335237,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIASUBTYPE_RGB16_D3D_DX7_RT,0x36315237,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIASUBTYPE_ARGB32_D3D_DX7_RT,0x38384137,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIASUBTYPE_ARGB4444_D3D_DX7_RT,0x34344137,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIASUBTYPE_ARGB1555_D3D_DX7_RT,0x35314137,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIASUBTYPE_RGB32_D3D_DX9_RT,0x32335239,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIASUBTYPE_RGB16_D3D_DX9_RT,0x36315239,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIASUBTYPE_ARGB32_D3D_DX9_RT,0x38384139,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIASUBTYPE_ARGB4444_D3D_DX9_RT,0x34344139,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIASUBTYPE_ARGB1555_D3D_DX9_RT,0x35314139,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) - -#define MEDIASUBTYPE_HASALPHA(mt) (((mt).subtype==MEDIASUBTYPE_ARGB4444) || ((mt).subtype==MEDIASUBTYPE_ARGB32) || ((mt).subtype==MEDIASUBTYPE_AYUV) || ((mt).subtype==MEDIASUBTYPE_AI44) || ((mt).subtype==MEDIASUBTYPE_IA44) || ((mt).subtype==MEDIASUBTYPE_ARGB1555) || ((mt).subtype==MEDIASUBTYPE_ARGB32_D3D_DX7_RT) || ((mt).subtype==MEDIASUBTYPE_ARGB4444_D3D_DX7_RT) || ((mt).subtype==MEDIASUBTYPE_ARGB1555_D3D_DX7_RT) || ((mt).subtype==MEDIASUBTYPE_ARGB32_D3D_DX9_RT) || ((mt).subtype==MEDIASUBTYPE_ARGB4444_D3D_DX9_RT) || ((mt).subtype==MEDIASUBTYPE_ARGB1555_D3D_DX9_RT)) -#define MEDIASUBTYPE_HASALPHA7(mt) (((mt).subtype==MEDIASUBTYPE_ARGB32_D3D_DX7_RT) || ((mt).subtype==MEDIASUBTYPE_ARGB4444_D3D_DX7_RT) || ((mt).subtype==MEDIASUBTYPE_ARGB1555_D3D_DX7_RT)) -#define MEDIASUBTYPE_D3D_DX7_RT(mt) (((mt).subtype==MEDIASUBTYPE_ARGB32_D3D_DX7_RT) || ((mt).subtype==MEDIASUBTYPE_ARGB4444_D3D_DX7_RT) || ((mt).subtype==MEDIASUBTYPE_ARGB1555_D3D_DX7_RT) || ((mt).subtype==MEDIASUBTYPE_RGB32_D3D_DX7_RT) || ((mt).subtype==MEDIASUBTYPE_RGB16_D3D_DX7_RT)) -#define MEDIASUBTYPE_HASALPHA9(mt) (((mt).subtype==MEDIASUBTYPE_ARGB32_D3D_DX9_RT) || ((mt).subtype==MEDIASUBTYPE_ARGB4444_D3D_DX9_RT) || ((mt).subtype==MEDIASUBTYPE_ARGB1555_D3D_DX9_RT)) -#define MEDIASUBTYPE_D3D_DX9_RT(mt) (((mt).subtype==MEDIASUBTYPE_ARGB32_D3D_DX9_RT) || ((mt).subtype==MEDIASUBTYPE_ARGB4444_D3D_DX9_RT) || ((mt).subtype==MEDIASUBTYPE_ARGB1555_D3D_DX9_RT) || ((mt).subtype==MEDIASUBTYPE_RGB32_D3D_DX9_RT) || ((mt).subtype==MEDIASUBTYPE_RGB16_D3D_DX9_RT)) - -OUR_GUID_ENTRY(MEDIASUBTYPE_YV12,0x32315659,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIASUBTYPE_NV12,0x3231564E,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIASUBTYPE_IMC1,0x31434D49,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIASUBTYPE_IMC2,0x32434D49,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIASUBTYPE_IMC3,0x33434D49,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIASUBTYPE_IMC4,0x34434D49,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIASUBTYPE_S340,0x30343353,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIASUBTYPE_S342,0x32343353,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIASUBTYPE_Overlay,0xe436eb7f,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70) -OUR_GUID_ENTRY(MEDIASUBTYPE_MPEG1Packet,0xe436eb80,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70) -OUR_GUID_ENTRY(MEDIASUBTYPE_MPEG1Payload,0xe436eb81,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70) -OUR_GUID_ENTRY(MEDIASUBTYPE_MPEG1AudioPayload,0x00000050,0x0000,0x0010,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71) -OUR_GUID_ENTRY(MEDIATYPE_MPEG1SystemStream,0xe436eb82,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70) -OUR_GUID_ENTRY(MEDIASUBTYPE_MPEG1System,0xe436eb84,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70) -OUR_GUID_ENTRY(MEDIASUBTYPE_MPEG1VideoCD,0xe436eb85,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70) -OUR_GUID_ENTRY(MEDIASUBTYPE_MPEG1Video,0xe436eb86,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70) -OUR_GUID_ENTRY(MEDIASUBTYPE_MPEG1Audio,0xe436eb87,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70) -OUR_GUID_ENTRY(MEDIASUBTYPE_Avi,0xe436eb88,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70) -OUR_GUID_ENTRY(MEDIASUBTYPE_Asf,0x3db80f90,0x9412,0x11d1,0xad,0xed,0x0,0x0,0xf8,0x75,0x4b,0x99) -OUR_GUID_ENTRY(MEDIASUBTYPE_QTMovie,0xe436eb89,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70) -OUR_GUID_ENTRY(MEDIASUBTYPE_QTRpza,0x617a7072,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIASUBTYPE_QTSmc,0x20636d73,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIASUBTYPE_QTRle,0x20656c72,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIASUBTYPE_QTJpeg,0x6765706a,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIASUBTYPE_PCMAudio_Obsolete,0xe436eb8a,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70) -OUR_GUID_ENTRY(MEDIASUBTYPE_PCM,0x00000001,0x0000,0x0010,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71) -OUR_GUID_ENTRY(MEDIASUBTYPE_WAVE,0xe436eb8b,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70) -OUR_GUID_ENTRY(MEDIASUBTYPE_AU,0xe436eb8c,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70) -OUR_GUID_ENTRY(MEDIASUBTYPE_AIFF,0xe436eb8d,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70) -OUR_GUID_ENTRY(MEDIASUBTYPE_dvsd,0x64737664,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIASUBTYPE_dvhd,0x64687664,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIASUBTYPE_dvsl,0x6c737664,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIASUBTYPE_dv25,0x35327664,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIASUBTYPE_dv50,0x30357664,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIASUBTYPE_dvh1,0x31687664,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIASUBTYPE_Line21_BytePair,0x6e8d4a22,0x310c,0x11d0,0xb7,0x9a,0x0,0xaa,0x0,0x37,0x67,0xa7) -OUR_GUID_ENTRY(MEDIASUBTYPE_Line21_GOPPacket,0x6e8d4a23,0x310c,0x11d0,0xb7,0x9a,0x0,0xaa,0x0,0x37,0x67,0xa7) -OUR_GUID_ENTRY(MEDIASUBTYPE_Line21_VBIRawData,0x6e8d4a24,0x310c,0x11d0,0xb7,0x9a,0x0,0xaa,0x0,0x37,0x67,0xa7) -OUR_GUID_ENTRY(MEDIASUBTYPE_TELETEXT,0xf72a76e3,0xeb0a,0x11d0,0xac,0xe4,0x00,0x00,0xc0,0xcc,0x16,0xba) -OUR_GUID_ENTRY(MEDIASUBTYPE_WSS,0x2791D576,0x8E7A,0x466F,0x9E,0x90,0x5D,0x3F,0x30,0x83,0x73,0x8B) -OUR_GUID_ENTRY(MEDIASUBTYPE_VPS,0xa1b3f620,0x9792,0x4d8d,0x81,0xa4,0x86,0xaf,0x25,0x77,0x20,0x90) -OUR_GUID_ENTRY(MEDIASUBTYPE_DRM_Audio,0x00000009,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIASUBTYPE_IEEE_FLOAT,0x00000003,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIASUBTYPE_DOLBY_AC3_SPDIF,0x00000092,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIASUBTYPE_RAW_SPORT,0x00000240,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIASUBTYPE_SPDIF_TAG_241h,0x00000241,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71) -OUR_GUID_ENTRY(MEDIASUBTYPE_DssVideo,0xa0af4f81,0xe163,0x11d0,0xba,0xd9,0x0,0x60,0x97,0x44,0x11,0x1a) -OUR_GUID_ENTRY(MEDIASUBTYPE_DssAudio,0xa0af4f82,0xe163,0x11d0,0xba,0xd9,0x0,0x60,0x97,0x44,0x11,0x1a) -OUR_GUID_ENTRY(MEDIASUBTYPE_VPVideo,0x5a9b6a40,0x1a22,0x11d1,0xba,0xd9,0x0,0x60,0x97,0x44,0x11,0x1a) -OUR_GUID_ENTRY(MEDIASUBTYPE_VPVBI,0x5a9b6a41,0x1a22,0x11d1,0xba,0xd9,0x0,0x60,0x97,0x44,0x11,0x1a) -OUR_GUID_ENTRY(CLSID_CaptureGraphBuilder,0xBF87B6E0,0x8C27,0x11d0,0xB3,0xF0,0x0,0xAA,0x00,0x37,0x61,0xC5) -OUR_GUID_ENTRY(CLSID_CaptureGraphBuilder2,0xBF87B6E1,0x8C27,0x11d0,0xB3,0xF0,0x0,0xAA,0x00,0x37,0x61,0xC5) -OUR_GUID_ENTRY(CLSID_ProtoFilterGraph,0xe436ebb0,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70) -OUR_GUID_ENTRY(CLSID_SystemClock,0xe436ebb1,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70) -OUR_GUID_ENTRY(CLSID_FilterMapper,0xe436ebb2,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70) -OUR_GUID_ENTRY(CLSID_FilterGraph,0xe436ebb3,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70) -OUR_GUID_ENTRY(CLSID_FilterGraphNoThread,0xe436ebb8,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70) -OUR_GUID_ENTRY(CLSID_MPEG1Doc,0xe4bbd160,0x4269,0x11ce,0x83,0x8d,0x0,0xaa,0x0,0x55,0x59,0x5a) -OUR_GUID_ENTRY(CLSID_FileSource,0x701722e0,0x8ae3,0x11ce,0xa8,0x5c,0x00,0xaa,0x00,0x2f,0xea,0xb5) -OUR_GUID_ENTRY(CLSID_MPEG1PacketPlayer,0x26c25940,0x4ca9,0x11ce,0xa8,0x28,0x0,0xaa,0x0,0x2f,0xea,0xb5) -OUR_GUID_ENTRY(CLSID_MPEG1Splitter,0x336475d0,0x942a,0x11ce,0xa8,0x70,0x00,0xaa,0x00,0x2f,0xea,0xb5) -OUR_GUID_ENTRY(CLSID_CMpegVideoCodec,0xfeb50740,0x7bef,0x11ce,0x9b,0xd9,0x0,0x0,0xe2,0x2,0x59,0x9c) -OUR_GUID_ENTRY(CLSID_CMpegAudioCodec,0x4a2286e0,0x7bef,0x11ce,0x9b,0xd9,0x0,0x0,0xe2,0x2,0x59,0x9c) -OUR_GUID_ENTRY(CLSID_TextRender,0xe30629d3,0x27e5,0x11ce,0x87,0x5d,0x0,0x60,0x8c,0xb7,0x80,0x66) -OUR_GUID_ENTRY(CLSID_InfTee,0xf8388a40,0xd5bb,0x11d0,0xbe,0x5a,0x0,0x80,0xc7,0x6,0x56,0x8e) -OUR_GUID_ENTRY(CLSID_AviSplitter,0x1b544c20,0xfd0b,0x11ce,0x8c,0x63,0x0,0xaa,0x00,0x44,0xb5,0x1e) -OUR_GUID_ENTRY(CLSID_AviReader,0x1b544c21,0xfd0b,0x11ce,0x8c,0x63,0x0,0xaa,0x00,0x44,0xb5,0x1e) -OUR_GUID_ENTRY(CLSID_VfwCapture,0x1b544c22,0xfd0b,0x11ce,0x8c,0x63,0x0,0xaa,0x00,0x44,0xb5,0x1e) -OUR_GUID_ENTRY(CLSID_CaptureProperties,0x1B544c22,0xFD0B,0x11ce,0x8C,0x63,0x00,0xAA,0x00,0x44,0xB5,0x1F) -OUR_GUID_ENTRY(CLSID_FGControl,0xe436ebb4,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70) -OUR_GUID_ENTRY(CLSID_MOVReader,0x44584800,0xf8ee,0x11ce,0xb2,0xd4,0x00,0xdd,0x1,0x10,0x1b,0x85) -OUR_GUID_ENTRY(CLSID_QuickTimeParser,0xd51bd5a0,0x7548,0x11cf,0xa5,0x20,0x0,0x80,0xc7,0x7e,0xf5,0x8a) -OUR_GUID_ENTRY(CLSID_QTDec,0xfdfe9681,0x74a3,0x11d0,0xaf,0xa7,0x0,0xaa,0x0,0xb6,0x7a,0x42) -OUR_GUID_ENTRY(CLSID_AVIDoc,0xd3588ab0,0x0781,0x11ce,0xb0,0x3a,0x00,0x20,0xaf,0xb,0xa7,0x70) -OUR_GUID_ENTRY(CLSID_VideoRenderer,0x70e102b0,0x5556,0x11ce,0x97,0xc0,0x00,0xaa,0x00,0x55,0x59,0x5a) -OUR_GUID_ENTRY(CLSID_Colour,0x1643e180,0x90f5,0x11ce,0x97,0xd5,0x00,0xaa,0x00,0x55,0x59,0x5a) -OUR_GUID_ENTRY(CLSID_Dither,0x1da08500,0x9edc,0x11cf,0xbc,0x10,0x00,0xaa,0x00,0xac,0x74,0xf6) -OUR_GUID_ENTRY(CLSID_ModexRenderer,0x7167665,0x5011,0x11cf,0xbf,0x33,0x0,0xaa,0x0,0x55,0x59,0x5a) -OUR_GUID_ENTRY(CLSID_AudioRender,0xe30629d1,0x27e5,0x11ce,0x87,0x5d,0x0,0x60,0x8c,0xb7,0x80,0x66) -OUR_GUID_ENTRY(CLSID_AudioProperties,0x05589faf,0xc356,0x11ce,0xbf,0x01,0x0,0xaa,0x0,0x55,0x59,0x5a) -OUR_GUID_ENTRY(CLSID_DSoundRender,0x79376820,0x07D0,0x11CF,0xA2,0x4D,0x0,0x20,0xAF,0xD7,0x97,0x67) -OUR_GUID_ENTRY(CLSID_AudioRecord,0xe30629d2,0x27e5,0x11ce,0x87,0x5d,0x0,0x60,0x8c,0xb7,0x80,0x66) -OUR_GUID_ENTRY(CLSID_AudioInputMixerProperties,0x2ca8ca52,0x3c3f,0x11d2,0xb7,0x3d,0x0,0xc0,0x4f,0xb6,0xbd,0x3d) -OUR_GUID_ENTRY(CLSID_AVIDec,0xcf49d4e0,0x1115,0x11ce,0xb0,0x3a,0x0,0x20,0xaf,0xb,0xa7,0x70) -OUR_GUID_ENTRY(CLSID_AVIDraw,0xa888df60,0x1e90,0x11cf,0xac,0x98,0x0,0xaa,0x0,0x4c,0xf,0xa9) -OUR_GUID_ENTRY(CLSID_ACMWrapper,0x6a08cf80,0x0e18,0x11cf,0xa2,0x4d,0x0,0x20,0xaf,0xd7,0x97,0x67) -OUR_GUID_ENTRY(CLSID_AsyncReader,0xe436ebb5,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70) -OUR_GUID_ENTRY(CLSID_URLReader,0xe436ebb6,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70) -OUR_GUID_ENTRY(CLSID_PersistMonikerPID,0xe436ebb7,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70) -OUR_GUID_ENTRY(CLSID_AVICo,0xd76e2820,0x1563,0x11cf,0xac,0x98,0x0,0xaa,0x0,0x4c,0xf,0xa9) -OUR_GUID_ENTRY(CLSID_FileWriter,0x8596e5f0,0xda5,0x11d0,0xbd,0x21,0x0,0xa0,0xc9,0x11,0xce,0x86) -OUR_GUID_ENTRY(CLSID_AviDest,0xe2510970,0xf137,0x11ce,0x8b,0x67,0x0,0xaa,0x0,0xa3,0xf1,0xa6) -OUR_GUID_ENTRY(CLSID_AviMuxProptyPage,0xc647b5c0,0x157c,0x11d0,0xbd,0x23,0x0,0xa0,0xc9,0x11,0xce,0x86) -OUR_GUID_ENTRY(CLSID_AviMuxProptyPage1,0xa9ae910,0x85c0,0x11d0,0xbd,0x42,0x0,0xa0,0xc9,0x11,0xce,0x86) -OUR_GUID_ENTRY(CLSID_AVIMIDIRender,0x07b65360,0xc445,0x11ce,0xaf,0xde,0x00,0xaa,0x00,0x6c,0x14,0xf4) -OUR_GUID_ENTRY(CLSID_WMAsfReader,0x187463a0,0x5bb7,0x11d3,0xac,0xbe,0x0,0x80,0xc7,0x5e,0x24,0x6e) -OUR_GUID_ENTRY(CLSID_WMAsfWriter,0x7c23220e,0x55bb,0x11d3,0x8b,0x16,0x0,0xc0,0x4f,0xb6,0xbd,0x3d) -OUR_GUID_ENTRY(CLSID_MPEG2Demultiplexer,0xafb6c280,0x2c41,0x11d3,0x8a,0x60,0x00,0x00,0xf8,0x1e,0x0e,0x4a) -OUR_GUID_ENTRY(CLSID_MMSPLITTER,0x3ae86b20,0x7be8,0x11d1,0xab,0xe6,0x00,0xa0,0xc9,0x05,0xf3,0x75) -OUR_GUID_ENTRY(CLSID_StreamBufferSink,0x2db47ae5,0xcf39,0x43c2,0xb4,0xd6,0xc,0xd8,0xd9,0x9,0x46,0xf4) -OUR_GUID_ENTRY(CLSID_StreamBufferSource,0xc9f5fe02,0xf851,0x4eb5,0x99,0xee,0xad,0x60,0x2a,0xf1,0xe6,0x19) -OUR_GUID_ENTRY(CLSID_StreamBufferConfig,0xfa8a68b2,0xc864,0x4ba2,0xad,0x53,0xd3,0x87,0x6a,0x87,0x49,0x4b) -OUR_GUID_ENTRY(CLSID_Mpeg2VideoStreamAnalyzer,0x6cfad761,0x735d,0x4aa5,0x8a,0xfc,0xaf,0x91,0xa7,0xd6,0x1e,0xba) -OUR_GUID_ENTRY(CLSID_StreamBufferRecordingAttributes,0xccaa63ac,0x1057,0x4778,0xae,0x92,0x12,0x6,0xab,0x9a,0xce,0xe6) -OUR_GUID_ENTRY(CLSID_StreamBufferComposeRecording,0xd682c4ba,0xa90a,0x42fe,0xb9,0xe1,0x3,0x10,0x98,0x49,0xc4,0x23) -OUR_GUID_ENTRY(CLSID_DVVideoCodec,0xb1b77c00,0xc3e4,0x11cf,0xaf,0x79,0x0,0xaa,0x0,0xb6,0x7a,0x42) -OUR_GUID_ENTRY(CLSID_DVVideoEnc,0x13aa3650,0xbb6f,0x11d0,0xaf,0xb9,0x0,0xaa,0x0,0xb6,0x7a,0x42) -OUR_GUID_ENTRY(CLSID_DVSplitter,0x4eb31670,0x9fc6,0x11cf,0xaf,0x6e,0x0,0xaa,0x0,0xb6,0x7a,0x42) -OUR_GUID_ENTRY(CLSID_DVMux,0x129d7e40,0xc10d,0x11d0,0xaf,0xb9,0x0,0xaa,0x0,0xb6,0x7a,0x42) -OUR_GUID_ENTRY(CLSID_SeekingPassThru,0x60af76c,0x68dd,0x11d0,0x8f,0xc1,0x0,0xc0,0x4f,0xd9,0x18,0x9d) -OUR_GUID_ENTRY(CLSID_Line21Decoder,0x6e8d4a20,0x310c,0x11d0,0xb7,0x9a,0x0,0xaa,0x0,0x37,0x67,0xa7) -OUR_GUID_ENTRY(CLSID_Line21Decoder2,0xe4206432,0x01a1,0x4bee,0xb3,0xe1,0x37,0x02,0xc8,0xed,0xc5,0x74) -OUR_GUID_ENTRY(CLSID_OverlayMixer,0xcd8743a1,0x3736,0x11d0,0x9e,0x69,0x0,0xc0,0x4f,0xd7,0xc1,0x5b) -OUR_GUID_ENTRY(CLSID_VBISurfaces,0x814b9800,0x1c88,0x11d1,0xba,0xd9,0x0,0x60,0x97,0x44,0x11,0x1a) -OUR_GUID_ENTRY(CLSID_WSTDecoder,0x70bc06e0,0x5666,0x11d3,0xa1,0x84,0x0,0x10,0x5a,0xef,0x9f,0x33) -OUR_GUID_ENTRY(CLSID_MjpegDec,0x301056d0,0x6dff,0x11d2,0x9e,0xeb,0x0,0x60,0x8,0x3,0x9e,0x37) -OUR_GUID_ENTRY(CLSID_MJPGEnc,0xb80ab0a0,0x7416,0x11d2,0x9e,0xeb,0x0,0x60,0x8,0x3,0x9e,0x37) -OUR_GUID_ENTRY(CLSID_SystemDeviceEnum,0x62BE5D10,0x60EB,0x11d0,0xBD,0x3B,0x00,0xA0,0xC9,0x11,0xCE,0x86) -OUR_GUID_ENTRY(CLSID_CDeviceMoniker,0x4315D437,0x5B8C,0x11d0,0xBD,0x3B,0x00,0xA0,0xC9,0x11,0xCE,0x86) -OUR_GUID_ENTRY(CLSID_VideoInputDeviceCategory,0x860BB310,0x5D01,0x11d0,0xBD,0x3B,0x00,0xA0,0xC9,0x11,0xCE,0x86) -OUR_GUID_ENTRY(CLSID_CVidCapClassManager,0x860BB310,0x5D01,0x11d0,0xBD,0x3B,0x00,0xA0,0xC9,0x11,0xCE,0x86) -OUR_GUID_ENTRY(CLSID_LegacyAmFilterCategory,0x083863F1,0x70DE,0x11d0,0xBD,0x40,0x00,0xA0,0xC9,0x11,0xCE,0x86) -OUR_GUID_ENTRY(CLSID_CQzFilterClassManager,0x083863F1,0x70DE,0x11d0,0xBD,0x40,0x00,0xA0,0xC9,0x11,0xCE,0x86) -OUR_GUID_ENTRY(CLSID_VideoCompressorCategory,0x33d9a760,0x90c8,0x11d0,0xbd,0x43,0x0,0xa0,0xc9,0x11,0xce,0x86) -OUR_GUID_ENTRY(CLSID_CIcmCoClassManager,0x33d9a760,0x90c8,0x11d0,0xbd,0x43,0x0,0xa0,0xc9,0x11,0xce,0x86) -OUR_GUID_ENTRY(CLSID_AudioCompressorCategory,0x33d9a761,0x90c8,0x11d0,0xbd,0x43,0x0,0xa0,0xc9,0x11,0xce,0x86) -OUR_GUID_ENTRY(CLSID_CAcmCoClassManager,0x33d9a761,0x90c8,0x11d0,0xbd,0x43,0x0,0xa0,0xc9,0x11,0xce,0x86) -OUR_GUID_ENTRY(CLSID_AudioInputDeviceCategory,0x33d9a762,0x90c8,0x11d0,0xbd,0x43,0x0,0xa0,0xc9,0x11,0xce,0x86) -OUR_GUID_ENTRY(CLSID_CWaveinClassManager,0x33d9a762,0x90c8,0x11d0,0xbd,0x43,0x0,0xa0,0xc9,0x11,0xce,0x86) -OUR_GUID_ENTRY(CLSID_AudioRendererCategory,0xe0f158e1,0xcb04,0x11d0,0xbd,0x4e,0x0,0xa0,0xc9,0x11,0xce,0x86) -OUR_GUID_ENTRY(CLSID_CWaveOutClassManager,0xe0f158e1,0xcb04,0x11d0,0xbd,0x4e,0x0,0xa0,0xc9,0x11,0xce,0x86) -OUR_GUID_ENTRY(CLSID_MidiRendererCategory,0x4EfE2452,0x168A,0x11d1,0xBC,0x76,0x0,0xc0,0x4F,0xB9,0x45,0x3B) -OUR_GUID_ENTRY(CLSID_CMidiOutClassManager,0x4EfE2452,0x168A,0x11d1,0xBC,0x76,0x0,0xc0,0x4F,0xB9,0x45,0x3B) -OUR_GUID_ENTRY(CLSID_TransmitCategory,0xcc7bfb41,0xf175,0x11d1,0xa3,0x92,0x0,0xe0,0x29,0x1f,0x39,0x59) -OUR_GUID_ENTRY(CLSID_DeviceControlCategory,0xcc7bfb46,0xf175,0x11d1,0xa3,0x92,0x0,0xe0,0x29,0x1f,0x39,0x59) -OUR_GUID_ENTRY(CLSID_ActiveMovieCategories,0xda4e3da0,0xd07d,0x11d0,0xbd,0x50,0x0,0xa0,0xc9,0x11,0xce,0x86) -OUR_GUID_ENTRY(CLSID_DVDHWDecodersCategory,0x2721AE20,0x7E70,0x11D0,0xA5,0xD6,0x28,0xDB,0x04,0xC1,0x00,0x00) -OUR_GUID_ENTRY(CLSID_MediaEncoderCategory,0x7D22E920,0x5CA9,0x4787,0x8C,0x2B,0xA6,0x77,0x9B,0xD1,0x17,0x81) -OUR_GUID_ENTRY(CLSID_MediaMultiplexerCategory,0x236C9559,0xADCE,0x4736,0xBF,0x72,0xBA,0xB3,0x4E,0x39,0x21,0x96) -OUR_GUID_ENTRY(CLSID_FilterMapper2,0xcda42200,0xbd88,0x11d0,0xbd,0x4e,0x0,0xa0,0xc9,0x11,0xce,0x86) -OUR_GUID_ENTRY(CLSID_MemoryAllocator,0x1e651cc0,0xb199,0x11d0,0x82,0x12,0x00,0xc0,0x4f,0xc3,0x2c,0x45) -OUR_GUID_ENTRY(CLSID_MediaPropertyBag,0xcdbd8d00,0xc193,0x11d0,0xbd,0x4e,0x0,0xa0,0xc9,0x11,0xce,0x86) -OUR_GUID_ENTRY(CLSID_DvdGraphBuilder,0xFCC152B7,0xF372,0x11d0,0x8E,0x00,0x00,0xC0,0x4F,0xD7,0xC0,0x8B) -OUR_GUID_ENTRY(CLSID_DVDNavigator,0x9b8c4620,0x2c1a,0x11d0,0x84,0x93,0x0,0xa0,0x24,0x38,0xad,0x48) -OUR_GUID_ENTRY(CLSID_DVDState,0xf963c5cf,0xa659,0x4a93,0x96,0x38,0xca,0xf3,0xcd,0x27,0x7d,0x13) -OUR_GUID_ENTRY(CLSID_SmartTee,0xcc58e280,0x8aa1,0x11d1,0xb3,0xf1,0x0,0xaa,0x0,0x37,0x61,0xc5) -OUR_GUID_ENTRY(FORMAT_None,0x0F6417D6,0xc318,0x11d0,0xa4,0x3f,0x00,0xa0,0xc9,0x22,0x31,0x96) -OUR_GUID_ENTRY(FORMAT_VideoInfo,0x05589f80,0xc356,0x11ce,0xbf,0x01,0x00,0xaa,0x00,0x55,0x59,0x5a) -OUR_GUID_ENTRY(FORMAT_VideoInfo2,0xf72a76A0,0xeb0a,0x11d0,0xac,0xe4,0x00,0x00,0xc0,0xcc,0x16,0xba) -OUR_GUID_ENTRY(FORMAT_WaveFormatEx,0x05589f81,0xc356,0x11ce,0xbf,0x01,0x00,0xaa,0x00,0x55,0x59,0x5a) -OUR_GUID_ENTRY(FORMAT_MPEGVideo,0x05589f82,0xc356,0x11ce,0xbf,0x01,0x00,0xaa,0x00,0x55,0x59,0x5a) -OUR_GUID_ENTRY(FORMAT_MPEGStreams,0x05589f83,0xc356,0x11ce,0xbf,0x01,0x00,0xaa,0x00,0x55,0x59,0x5a) -OUR_GUID_ENTRY(FORMAT_DvInfo,0x05589f84,0xc356,0x11ce,0xbf,0x01,0x00,0xaa,0x00,0x55,0x59,0x5a) -OUR_GUID_ENTRY(CLSID_DirectDrawProperties,0x944d4c00,0xdd52,0x11ce,0xbf,0x0e,0x00,0xaa,0x00,0x55,0x59,0x5a) -OUR_GUID_ENTRY(CLSID_PerformanceProperties,0x59ce6880,0xacf8,0x11cf,0xb5,0x6e,0x00,0x80,0xc7,0xc4,0xb6,0x8a) -OUR_GUID_ENTRY(CLSID_QualityProperties,0x418afb70,0xf8b8,0x11ce,0xaa,0xc6,0x00,0x20,0xaf,0x0b,0x99,0xa3) -OUR_GUID_ENTRY(IID_IBaseVideoMixer,0x61ded640,0xe912,0x11ce,0xa0,0x99,0x00,0xaa,0x00,0x47,0x9a,0x58) -OUR_GUID_ENTRY(IID_IDirectDrawVideo,0x36d39eb0,0xdd75,0x11ce,0xbf,0x0e,0x00,0xaa,0x00,0x55,0x59,0x5a) -OUR_GUID_ENTRY(IID_IQualProp,0x1bd0ecb0,0xf8e2,0x11ce,0xaa,0xc6,0x00,0x20,0xaf,0x0b,0x99,0xa3) -OUR_GUID_ENTRY(CLSID_VPObject,0xce292861,0xfc88,0x11d0,0x9e,0x69,0x0,0xc0,0x4f,0xd7,0xc1,0x5b) -OUR_GUID_ENTRY(IID_IVPObject,0xce292862,0xfc88,0x11d0,0x9e,0x69,0x0,0xc0,0x4f,0xd7,0xc1,0x5b) -OUR_GUID_ENTRY(IID_IVPControl,0x25df12c1,0x3de0,0x11d1,0x9e,0x69,0x0,0xc0,0x4f,0xd7,0xc1,0x5b) -OUR_GUID_ENTRY(CLSID_VPVBIObject,0x814b9801,0x1c88,0x11d1,0xba,0xd9,0x0,0x60,0x97,0x44,0x11,0x1a) -OUR_GUID_ENTRY(IID_IVPVBIObject,0x814b9802,0x1c88,0x11d1,0xba,0xd9,0x0,0x60,0x97,0x44,0x11,0x1a) -OUR_GUID_ENTRY(IID_IVPConfig,0xbc29a660,0x30e3,0x11d0,0x9e,0x69,0x0,0xc0,0x4f,0xd7,0xc1,0x5b) -OUR_GUID_ENTRY(IID_IVPNotify,0xc76794a1,0xd6c5,0x11d0,0x9e,0x69,0x0,0xc0,0x4f,0xd7,0xc1,0x5b) -OUR_GUID_ENTRY(IID_IVPNotify2,0xebf47183,0x8764,0x11d1,0x9e,0x69,0x0,0xc0,0x4f,0xd7,0xc1,0x5b) -OUR_GUID_ENTRY(IID_IVPVBIConfig,0xec529b00,0x1a1f,0x11d1,0xba,0xd9,0x0,0x60,0x97,0x44,0x11,0x1a) -OUR_GUID_ENTRY(IID_IVPVBINotify,0xec529b01,0x1a1f,0x11d1,0xba,0xd9,0x0,0x60,0x97,0x44,0x11,0x1a) -OUR_GUID_ENTRY(IID_IMixerPinConfig,0x593cdde1,0x759,0x11d1,0x9e,0x69,0x0,0xc0,0x4f,0xd7,0xc1,0x5b) -OUR_GUID_ENTRY(IID_IMixerPinConfig2,0xebf47182,0x8764,0x11d1,0x9e,0x69,0x0,0xc0,0x4f,0xd7,0xc1,0x5b) -#ifndef __DDRAW_INCLUDED__ -OUR_GUID_ENTRY(CLSID_DirectDraw,0xD7B70EE0,0x4340,0x11CF,0xB0,0x63,0x00,0x20,0xAF,0xC2,0xCD,0x35) -OUR_GUID_ENTRY(CLSID_DirectDrawClipper,0x593817A0,0x7DB3,0x11CF,0xA2,0xDE,0x00,0xAA,0x00,0xb9,0x33,0x56) -OUR_GUID_ENTRY(IID_IDirectDraw,0x6C14DB80,0xA733,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60) -OUR_GUID_ENTRY(IID_IDirectDraw2,0xB3A6F3E0,0x2B43,0x11CF,0xA2,0xDE,0x00,0xAA,0x00,0xB9,0x33,0x56) -OUR_GUID_ENTRY(IID_IDirectDrawSurface,0x6C14DB81,0xA733,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60) -OUR_GUID_ENTRY(IID_IDirectDrawSurface2,0x57805885,0x6eec,0x11cf,0x94,0x41,0xa8,0x23,0x03,0xc1,0x0e,0x27) -OUR_GUID_ENTRY(IID_IDirectDrawSurface3,0xDA044E00,0x69B2,0x11D0,0xA1,0xD5,0x00,0xAA,0x00,0xB8,0xDF,0xBB) -OUR_GUID_ENTRY(IID_IDirectDrawSurface4,0x0B2B8630,0xAD35,0x11D0,0x8E,0xA6,0x00,0x60,0x97,0x97,0xEA,0x5B) -OUR_GUID_ENTRY(IID_IDirectDrawSurface7,0x06675a80,0x3b9b,0x11d2,0xb9,0x2f,0x00,0x60,0x97,0x97,0xea,0x5b) -OUR_GUID_ENTRY(IID_IDirectDrawPalette,0x6C14DB84,0xA733,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60) -OUR_GUID_ENTRY(IID_IDirectDrawClipper,0x6C14DB85,0xA733,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60) -OUR_GUID_ENTRY(IID_IDirectDrawColorControl,0x4B9F0EE0,0x0D7E,0x11D0,0x9B,0x06,0x00,0xA0,0xC9,0x03,0xA3,0xB8) -#endif -#ifndef __DVP_INCLUDED__ -OUR_GUID_ENTRY(IID_IDDVideoPortContainer,0x6C142760,0xA733,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60) -#endif -#ifndef __DDKM_INCLUDED__ -OUR_GUID_ENTRY(IID_IDirectDrawKernel,0x8D56C120,0x6A08,0x11D0,0x9B,0x06,0x00,0xA0,0xC9,0x03,0xA3,0xB8) -OUR_GUID_ENTRY(IID_IDirectDrawSurfaceKernel,0x60755DA0,0x6A40,0x11D0,0x9B,0x06,0x00,0xA0,0xC9,0x03,0xA3,0xB8) -#endif -OUR_GUID_ENTRY(CLSID_ModexProperties,0x0618aa30,0x6bc4,0x11cf,0xbf,0x36,0x00,0xaa,0x00,0x55,0x59,0x5a) -OUR_GUID_ENTRY(IID_IFullScreenVideo,0xdd1d7110,0x7836,0x11cf,0xbf,0x47,0x00,0xaa,0x00,0x55,0x59,0x5a) -OUR_GUID_ENTRY(IID_IFullScreenVideoEx,0x53479470,0xf1dd,0x11cf,0xbc,0x42,0x00,0xaa,0x00,0xac,0x74,0xf6) -OUR_GUID_ENTRY(CLSID_DVDecPropertiesPage,0x101193c0,0xbfe,0x11d0,0xaf,0x91,0x0,0xaa,0x0,0xb6,0x7a,0x42) -OUR_GUID_ENTRY(CLSID_DVEncPropertiesPage,0x4150f050,0xbb6f,0x11d0,0xaf,0xb9,0x0,0xaa,0x0,0xb6,0x7a,0x42) -OUR_GUID_ENTRY(CLSID_DVMuxPropertyPage,0x4db880e0,0xc10d,0x11d0,0xaf,0xb9,0x0,0xaa,0x0,0xb6,0x7a,0x42) -OUR_GUID_ENTRY(IID_IAMDirectSound,0x546f4260,0xd53e,0x11cf,0xb3,0xf0,0x0,0xaa,0x0,0x37,0x61,0xc5) -OUR_GUID_ENTRY(IID_IMpegAudioDecoder,0xb45dd570,0x3c77,0x11d1,0xab,0xe1,0x00,0xa0,0xc9,0x05,0xf3,0x75) -OUR_GUID_ENTRY(IID_IAMLine21Decoder,0x6e8d4a21,0x310c,0x11d0,0xb7,0x9a,0x0,0xaa,0x0,0x37,0x67,0xa7) -OUR_GUID_ENTRY(IID_IAMWstDecoder,0xc056de21,0x75c2,0x11d3,0xa1,0x84,0x0,0x10,0x5a,0xef,0x9f,0x33) -OUR_GUID_ENTRY(CLSID_WstDecoderPropertyPage,0x4e27f80,0x91e4,0x11d3,0xa1,0x84,0x0,0x10,0x5a,0xef,0x9f,0x33) -OUR_GUID_ENTRY(FORMAT_AnalogVideo,0x482dde0,0x7817,0x11cf,0x8a,0x3,0x0,0xaa,0x0,0x6e,0xcb,0x65) -OUR_GUID_ENTRY(MEDIATYPE_AnalogVideo,0x482dde1,0x7817,0x11cf,0x8a,0x3,0x0,0xaa,0x0,0x6e,0xcb,0x65) -OUR_GUID_ENTRY(MEDIASUBTYPE_AnalogVideo_NTSC_M,0x482dde2,0x7817,0x11cf,0x8a,0x3,0x0,0xaa,0x0,0x6e,0xcb,0x65) -OUR_GUID_ENTRY(MEDIASUBTYPE_AnalogVideo_PAL_B,0x482dde5,0x7817,0x11cf,0x8a,0x3,0x0,0xaa,0x0,0x6e,0xcb,0x65) -OUR_GUID_ENTRY(MEDIASUBTYPE_AnalogVideo_PAL_D,0x482dde6,0x7817,0x11cf,0x8a,0x3,0x0,0xaa,0x0,0x6e,0xcb,0x65) -OUR_GUID_ENTRY(MEDIASUBTYPE_AnalogVideo_PAL_G,0x482dde7,0x7817,0x11cf,0x8a,0x3,0x0,0xaa,0x0,0x6e,0xcb,0x65) -OUR_GUID_ENTRY(MEDIASUBTYPE_AnalogVideo_PAL_H,0x482dde8,0x7817,0x11cf,0x8a,0x3,0x0,0xaa,0x0,0x6e,0xcb,0x65) -OUR_GUID_ENTRY(MEDIASUBTYPE_AnalogVideo_PAL_I,0x482dde9,0x7817,0x11cf,0x8a,0x3,0x0,0xaa,0x0,0x6e,0xcb,0x65) -OUR_GUID_ENTRY(MEDIASUBTYPE_AnalogVideo_PAL_M,0x482ddea,0x7817,0x11cf,0x8a,0x3,0x0,0xaa,0x0,0x6e,0xcb,0x65) -OUR_GUID_ENTRY(MEDIASUBTYPE_AnalogVideo_PAL_N,0x482ddeb,0x7817,0x11cf,0x8a,0x3,0x0,0xaa,0x0,0x6e,0xcb,0x65) -OUR_GUID_ENTRY(MEDIASUBTYPE_AnalogVideo_PAL_N_COMBO,0x482ddec,0x7817,0x11cf,0x8a,0x3,0x0,0xaa,0x0,0x6e,0xcb,0x65) -OUR_GUID_ENTRY(MEDIASUBTYPE_AnalogVideo_SECAM_B,0x482ddf0,0x7817,0x11cf,0x8a,0x3,0x0,0xaa,0x0,0x6e,0xcb,0x65) -OUR_GUID_ENTRY(MEDIASUBTYPE_AnalogVideo_SECAM_D,0x482ddf1,0x7817,0x11cf,0x8a,0x3,0x0,0xaa,0x0,0x6e,0xcb,0x65) -OUR_GUID_ENTRY(MEDIASUBTYPE_AnalogVideo_SECAM_G,0x482ddf2,0x7817,0x11cf,0x8a,0x3,0x0,0xaa,0x0,0x6e,0xcb,0x65) -OUR_GUID_ENTRY(MEDIASUBTYPE_AnalogVideo_SECAM_H,0x482ddf3,0x7817,0x11cf,0x8a,0x3,0x0,0xaa,0x0,0x6e,0xcb,0x65) -OUR_GUID_ENTRY(MEDIASUBTYPE_AnalogVideo_SECAM_K,0x482ddf4,0x7817,0x11cf,0x8a,0x3,0x0,0xaa,0x0,0x6e,0xcb,0x65) -OUR_GUID_ENTRY(MEDIASUBTYPE_AnalogVideo_SECAM_K1,0x482ddf5,0x7817,0x11cf,0x8a,0x3,0x0,0xaa,0x0,0x6e,0xcb,0x65) -OUR_GUID_ENTRY(MEDIASUBTYPE_AnalogVideo_SECAM_L,0x482ddf6,0x7817,0x11cf,0x8a,0x3,0x0,0xaa,0x0,0x6e,0xcb,0x65) -OUR_GUID_ENTRY(MEDIATYPE_AnalogAudio,0x482dee1,0x7817,0x11cf,0x8a,0x3,0x0,0xaa,0x0,0x6e,0xcb,0x65) - -#include "dshow/ksuuids.h" - -OUR_GUID_ENTRY(TIME_FORMAT_NONE,0L,0,0,0,0,0,0,0,0,0,0) -OUR_GUID_ENTRY(TIME_FORMAT_FRAME,0x7b785570,0x8c82,0x11cf,0xbc,0xc,0x0,0xaa,0x0,0xac,0x74,0xf6) -OUR_GUID_ENTRY(TIME_FORMAT_BYTE,0x7b785571,0x8c82,0x11cf,0xbc,0xc,0x0,0xaa,0x0,0xac,0x74,0xf6) -OUR_GUID_ENTRY(TIME_FORMAT_SAMPLE,0x7b785572,0x8c82,0x11cf,0xbc,0xc,0x0,0xaa,0x0,0xac,0x74,0xf6) -OUR_GUID_ENTRY(TIME_FORMAT_FIELD,0x7b785573,0x8c82,0x11cf,0xbc,0xc,0x0,0xaa,0x0,0xac,0x74,0xf6) -OUR_GUID_ENTRY(TIME_FORMAT_MEDIA_TIME,0x7b785574,0x8c82,0x11cf,0xbc,0xc,0x0,0xaa,0x0,0xac,0x74,0xf6) -OUR_GUID_ENTRY(AMPROPSETID_Pin,0x9b00f101,0x1567,0x11d1,0xb3,0xf1,0x0,0xaa,0x0,0x37,0x61,0xc5) -OUR_GUID_ENTRY(PIN_CATEGORY_CAPTURE,0xfb6c4281,0x0353,0x11d1,0x90,0x5f,0x00,0x00,0xc0,0xcc,0x16,0xba) -OUR_GUID_ENTRY(PIN_CATEGORY_PREVIEW,0xfb6c4282,0x0353,0x11d1,0x90,0x5f,0x00,0x00,0xc0,0xcc,0x16,0xba) -OUR_GUID_ENTRY(PIN_CATEGORY_ANALOGVIDEOIN,0xfb6c4283,0x0353,0x11d1,0x90,0x5f,0x00,0x00,0xc0,0xcc,0x16,0xba) -OUR_GUID_ENTRY(PIN_CATEGORY_VBI,0xfb6c4284,0x0353,0x11d1,0x90,0x5f,0x00,0x00,0xc0,0xcc,0x16,0xba) -OUR_GUID_ENTRY(PIN_CATEGORY_VIDEOPORT,0xfb6c4285,0x0353,0x11d1,0x90,0x5f,0x00,0x00,0xc0,0xcc,0x16,0xba) -OUR_GUID_ENTRY(PIN_CATEGORY_NABTS,0xfb6c4286,0x0353,0x11d1,0x90,0x5f,0x00,0x00,0xc0,0xcc,0x16,0xba) -OUR_GUID_ENTRY(PIN_CATEGORY_EDS,0xfb6c4287,0x0353,0x11d1,0x90,0x5f,0x00,0x00,0xc0,0xcc,0x16,0xba) -OUR_GUID_ENTRY(PIN_CATEGORY_TELETEXT,0xfb6c4288,0x0353,0x11d1,0x90,0x5f,0x00,0x00,0xc0,0xcc,0x16,0xba) -OUR_GUID_ENTRY(PIN_CATEGORY_CC,0xfb6c4289,0x0353,0x11d1,0x90,0x5f,0x00,0x00,0xc0,0xcc,0x16,0xba) -OUR_GUID_ENTRY(PIN_CATEGORY_STILL,0xfb6c428a,0x0353,0x11d1,0x90,0x5f,0x00,0x00,0xc0,0xcc,0x16,0xba) -OUR_GUID_ENTRY(PIN_CATEGORY_TIMECODE,0xfb6c428b,0x0353,0x11d1,0x90,0x5f,0x00,0x00,0xc0,0xcc,0x16,0xba) -OUR_GUID_ENTRY(PIN_CATEGORY_VIDEOPORT_VBI,0xfb6c428c,0x0353,0x11d1,0x90,0x5f,0x00,0x00,0xc0,0xcc,0x16,0xba) -OUR_GUID_ENTRY(LOOK_UPSTREAM_ONLY,0xac798be0,0x98e3,0x11d1,0xb3,0xf1,0x0,0xaa,0x0,0x37,0x61,0xc5) -OUR_GUID_ENTRY(LOOK_DOWNSTREAM_ONLY,0xac798be1,0x98e3,0x11d1,0xb3,0xf1,0x0,0xaa,0x0,0x37,0x61,0xc5) -OUR_GUID_ENTRY(CLSID_TVTunerFilterPropertyPage,0x266eee41,0x6c63,0x11cf,0x8a,0x3,0x0,0xaa,0x0,0x6e,0xcb,0x65) -OUR_GUID_ENTRY(CLSID_CrossbarFilterPropertyPage,0x71f96461,0x78f3,0x11d0,0xa1,0x8c,0x0,0xa0,0xc9,0x11,0x89,0x56) -OUR_GUID_ENTRY(CLSID_TVAudioFilterPropertyPage,0x71f96463,0x78f3,0x11d0,0xa1,0x8c,0x0,0xa0,0xc9,0x11,0x89,0x56) -OUR_GUID_ENTRY(CLSID_VideoProcAmpPropertyPage,0x71f96464,0x78f3,0x11d0,0xa1,0x8c,0x0,0xa0,0xc9,0x11,0x89,0x56) -OUR_GUID_ENTRY(CLSID_CameraControlPropertyPage,0x71f96465,0x78f3,0x11d0,0xa1,0x8c,0x0,0xa0,0xc9,0x11,0x89,0x56) -OUR_GUID_ENTRY(CLSID_AnalogVideoDecoderPropertyPage,0x71f96466,0x78f3,0x11d0,0xa1,0x8c,0x0,0xa0,0xc9,0x11,0x89,0x56) -OUR_GUID_ENTRY(CLSID_VideoStreamConfigPropertyPage,0x71f96467,0x78f3,0x11d0,0xa1,0x8c,0x0,0xa0,0xc9,0x11,0x89,0x56) -OUR_GUID_ENTRY(CLSID_AudioRendererAdvancedProperties,0x37e92a92,0xd9aa,0x11d2,0xbf,0x84,0x8e,0xf2,0xb1,0x55,0x5a,0xed) -OUR_GUID_ENTRY(CLSID_VideoMixingRenderer,0xB87BEB7B,0x8D29,0x423f,0xAE,0x4D,0x65,0x82,0xC1,0x01,0x75,0xAC) -OUR_GUID_ENTRY(CLSID_VideoRendererDefault,0x6BC1CFFA,0x8FC1,0x4261,0xAC,0x22,0xCF,0xB4,0xCC,0x38,0xDB,0x50) -OUR_GUID_ENTRY(CLSID_AllocPresenter,0x99d54f63,0x1a69,0x41ae,0xaa,0x4d,0xc9,0x76,0xeb,0x3f,0x07,0x13) -OUR_GUID_ENTRY(CLSID_AllocPresenterDDXclMode,0x4444ac9e,0x242e,0x471b,0xa3,0xc7,0x45,0xdc,0xd4,0x63,0x52,0xbc) -OUR_GUID_ENTRY(CLSID_VideoPortManager,0x6f26a6cd,0x967b,0x47fd,0x87,0x4a,0x7a,0xed,0x2c,0x9d,0x25,0xa2) -OUR_GUID_ENTRY(CLSID_VideoMixingRenderer9,0x51b4abf3,0x748f,0x4e3b,0xa2,0x76,0xc8,0x28,0x33,0x0e,0x92,0x6a) -OUR_GUID_ENTRY(CLSID_ATSCNetworkProvider,0x0dad2fdd,0x5fd7,0x11d3,0x8f,0x50,0x00,0xc0,0x4f,0x79,0x71,0xe2) -OUR_GUID_ENTRY(CLSID_ATSCNetworkPropertyPage,0xe3444d16,0x5ac4,0x4386,0x88,0xdf,0x13,0xfd,0x23,0x0e,0x1d,0xda) -OUR_GUID_ENTRY(CLSID_DVBSNetworkProvider,0xfa4b375a,0x45b4,0x4d45,0x84,0x40,0x26,0x39,0x57,0xb1,0x16,0x23) -OUR_GUID_ENTRY(CLSID_DVBTNetworkProvider,0x216c62df,0x6d7f,0x4e9a,0x85,0x71,0x5,0xf1,0x4e,0xdb,0x76,0x6a) -OUR_GUID_ENTRY(CLSID_DVBCNetworkProvider,0xdc0c0fe7,0x485,0x4266,0xb9,0x3f,0x68,0xfb,0xf8,0xe,0xd8,0x34) -OUR_GUID_ENTRY(CLSID_DShowTVEFilter,0x05500280,0xFAA5,0x4DF9,0x82,0x46,0xBF,0xC2,0x3A,0xC5,0xCE,0xA8) -OUR_GUID_ENTRY(CLSID_TVEFilterTuneProperties,0x05500281,0xFAA5,0x4DF9,0x82,0x46,0xBF,0xC2,0x3A,0xC5,0xCE,0xA8) -OUR_GUID_ENTRY(CLSID_TVEFilterCCProperties,0x05500282,0xFAA5,0x4DF9,0x82,0x46,0xBF,0xC2,0x3A,0xC5,0xCE,0xA8) -OUR_GUID_ENTRY(CLSID_TVEFilterStatsProperties,0x05500283,0xFAA5,0x4DF9,0x82,0x46,0xBF,0xC2,0x3A,0xC5,0xCE,0xA8) -OUR_GUID_ENTRY(CLSID_IVideoEncoderProxy,0xb43c4eec,0x8c32,0x4791,0x91,0x2,0x50,0x8a,0xda,0x5e,0xe8,0xe7) -OUR_GUID_ENTRY(CLSID_ICodecAPIProxy,0x7ff0997a,0x1999,0x4286,0xa7,0x3c,0x62,0x2b,0x88,0x14,0xe7,0xeb) -OUR_GUID_ENTRY(CLSID_IVideoEncoderCodecAPIProxy,0xb05dabd9,0x56e5,0x4fdc,0xaf,0xa4,0x8a,0x47,0xe9,0x1f,0x1c,0x9c) - -#ifndef __ENCODER_API_GUIDS__ -#define __ENCODER_API_GUIDS__ -OUR_GUID_ENTRY(ENCAPIPARAM_BITRATE,0x49cc4c43,0xca83,0x4ad4,0xa9,0xaf,0xf3,0x69,0x6a,0xf6,0x66,0xdf) -OUR_GUID_ENTRY(ENCAPIPARAM_PEAK_BITRATE,0x703f16a9,0x3d48,0x44a1,0xb0,0x77,0x1,0x8d,0xff,0x91,0x5d,0x19) -OUR_GUID_ENTRY(ENCAPIPARAM_BITRATE_MODE,0xee5fb25c,0xc713,0x40d1,0x9d,0x58,0xc0,0xd7,0x24,0x1e,0x25,0xf) -OUR_GUID_ENTRY(CODECAPI_CHANGELISTS,0x62b12acf,0xf6b0,0x47d9,0x94,0x56,0x96,0xf2,0x2c,0x4e,0x0b,0x9d) -OUR_GUID_ENTRY(CODECAPI_VIDEO_ENCODER,0x7112e8e1,0x3d03,0x47ef,0x8e,0x60,0x03,0xf1,0xcf,0x53,0x73,0x01) -OUR_GUID_ENTRY(CODECAPI_AUDIO_ENCODER,0xb9d19a3e,0xf897,0x429c,0xbc,0x46,0x81,0x38,0xb7,0x27,0x2b,0x2d) -OUR_GUID_ENTRY(CODECAPI_SETALLDEFAULTS,0x6c5e6a7c,0xacf8,0x4f55,0xa9,0x99,0x1a,0x62,0x81,0x09,0x05,0x1b) -OUR_GUID_ENTRY(CODECAPI_ALLSETTINGS,0x6a577e92,0x83e1,0x4113,0xad,0xc2,0x4f,0xce,0xc3,0x2f,0x83,0xa1) -OUR_GUID_ENTRY(CODECAPI_SUPPORTSEVENTS,0x0581af97,0x7693,0x4dbd,0x9d,0xca,0x3f,0x9e,0xbd,0x65,0x85,0xa1) -OUR_GUID_ENTRY(CODECAPI_CURRENTCHANGELIST,0x1cb14e83,0x7d72,0x4657,0x83,0xfd,0x47,0xa2,0xc5,0xb9,0xd1,0x3d) -#endif - -#undef OUR_GUID_ENTRY diff --git a/vendor/http_parser/.gitignore b/vendor/http_parser/.gitignore deleted file mode 100644 index c122e76fb..000000000 --- a/vendor/http_parser/.gitignore +++ /dev/null @@ -1,30 +0,0 @@ -/out/ -core -tags -*.o -test -test_g -test_fast -bench -url_parser -parsertrace -parsertrace_g -*.mk -*.Makefile -*.so.* -*.exe.* -*.exe -*.a - - -# Visual Studio uglies -*.suo -*.sln -*.vcxproj -*.vcxproj.filters -*.vcxproj.user -*.opensdf -*.ncrunchsolution* -*.sdf -*.vsp -*.psess diff --git a/vendor/http_parser/.mailmap b/vendor/http_parser/.mailmap deleted file mode 100644 index 278d14126..000000000 --- a/vendor/http_parser/.mailmap +++ /dev/null @@ -1,8 +0,0 @@ -# update AUTHORS with: -# git log --all --reverse --format='%aN <%aE>' | perl -ne 'BEGIN{print "# Authors ordered by first contribution.\n"} print unless $h{$_}; $h{$_} = 1' > AUTHORS -Ryan Dahl -Salman Haq -Simon Zimmermann -Thomas LE ROUX LE ROUX Thomas -Thomas LE ROUX Thomas LE ROUX -Fedor Indutny diff --git a/vendor/http_parser/.travis.yml b/vendor/http_parser/.travis.yml deleted file mode 100644 index 4b038e6e6..000000000 --- a/vendor/http_parser/.travis.yml +++ /dev/null @@ -1,13 +0,0 @@ -language: c - -compiler: - - clang - - gcc - -script: - - "make" - -notifications: - email: false - irc: - - "irc.freenode.net#node-ci" diff --git a/vendor/http_parser/AUTHORS b/vendor/http_parser/AUTHORS deleted file mode 100644 index 5323b685c..000000000 --- a/vendor/http_parser/AUTHORS +++ /dev/null @@ -1,68 +0,0 @@ -# Authors ordered by first contribution. -Ryan Dahl -Jeremy Hinegardner -Sergey Shepelev -Joe Damato -tomika -Phoenix Sol -Cliff Frey -Ewen Cheslack-Postava -Santiago Gala -Tim Becker -Jeff Terrace -Ben Noordhuis -Nathan Rajlich -Mark Nottingham -Aman Gupta -Tim Becker -Sean Cunningham -Peter Griess -Salman Haq -Cliff Frey -Jon Kolb -Fouad Mardini -Paul Querna -Felix Geisendörfer -koichik -Andre Caron -Ivo Raisr -James McLaughlin -David Gwynne -Thomas LE ROUX -Randy Rizun -Andre Louis Caron -Simon Zimmermann -Erik Dubbelboer -Martell Malone -Bertrand Paquet -BogDan Vatra -Peter Faiman -Corey Richardson -Tóth Tamás -Cam Swords -Chris Dickinson -Uli Köhler -Charlie Somerville -Patrik Stutz -Fedor Indutny -runner -Alexis Campailla -David Wragg -Vinnie Falco -Alex Butum -Rex Feng -Alex Kocharin -Mark Koopman -Helge Heß -Alexis La Goutte -George Miroshnykov -Maciej Małecki -Marc O'Morain -Jeff Pinner -Timothy J Fontaine -Akagi201 -Romain Giraud -Jay Satiro -Arne Steen -Kjell Schubert -Olivier Mengué diff --git a/vendor/http_parser/CMakeLists.txt b/vendor/http_parser/CMakeLists.txt deleted file mode 100644 index 962bd2cf7..000000000 --- a/vendor/http_parser/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -#include_directories("${CMAKE_CURRENT_SOURCE_DIR}") - -set(http_parser_SOURCE_FILES http_parser.c) -set(http_parser_HEADER_FILES http_parser.h) - -define_sourcey_dependency(http_parser) diff --git a/vendor/http_parser/LICENSE-MIT b/vendor/http_parser/LICENSE-MIT deleted file mode 100644 index 58010b388..000000000 --- a/vendor/http_parser/LICENSE-MIT +++ /dev/null @@ -1,23 +0,0 @@ -http_parser.c is based on src/http/ngx_http_parse.c from NGINX copyright -Igor Sysoev. - -Additional changes are licensed under the same terms as NGINX and -copyright Joyent, Inc. and other Node contributors. All rights reserved. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to -deal in the Software without restriction, including without limitation the -rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -sell copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -IN THE SOFTWARE. diff --git a/vendor/http_parser/Makefile b/vendor/http_parser/Makefile deleted file mode 100644 index 970bdc426..000000000 --- a/vendor/http_parser/Makefile +++ /dev/null @@ -1,149 +0,0 @@ -# Copyright Joyent, Inc. and other Node contributors. All rights reserved. -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to -# deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -PLATFORM ?= $(shell sh -c 'uname -s | tr "[A-Z]" "[a-z]"') -HELPER ?= -BINEXT ?= -ifeq (darwin,$(PLATFORM)) -SONAME ?= libhttp_parser.2.6.2.dylib -SOEXT ?= dylib -else ifeq (wine,$(PLATFORM)) -CC = winegcc -BINEXT = .exe.so -HELPER = wine -else -SONAME ?= libhttp_parser.so.2.6.2 -SOEXT ?= so -endif - -CC?=gcc -AR?=ar - -CPPFLAGS ?= -LDFLAGS ?= - -CPPFLAGS += -I. -CPPFLAGS_DEBUG = $(CPPFLAGS) -DHTTP_PARSER_STRICT=1 -CPPFLAGS_DEBUG += $(CPPFLAGS_DEBUG_EXTRA) -CPPFLAGS_FAST = $(CPPFLAGS) -DHTTP_PARSER_STRICT=0 -CPPFLAGS_FAST += $(CPPFLAGS_FAST_EXTRA) -CPPFLAGS_BENCH = $(CPPFLAGS_FAST) - -CFLAGS += -Wall -Wextra -Werror -CFLAGS_DEBUG = $(CFLAGS) -O0 -g $(CFLAGS_DEBUG_EXTRA) -CFLAGS_FAST = $(CFLAGS) -O3 $(CFLAGS_FAST_EXTRA) -CFLAGS_BENCH = $(CFLAGS_FAST) -Wno-unused-parameter -CFLAGS_LIB = $(CFLAGS_FAST) -fPIC - -LDFLAGS_LIB = $(LDFLAGS) -shared - -INSTALL ?= install -PREFIX ?= $(DESTDIR)/usr/local -LIBDIR = $(PREFIX)/lib -INCLUDEDIR = $(PREFIX)/include - -ifneq (darwin,$(PLATFORM)) -# TODO(bnoordhuis) The native SunOS linker expects -h rather than -soname... -LDFLAGS_LIB += -Wl,-soname=$(SONAME) -endif - -test: test_g test_fast - $(HELPER) ./test_g$(BINEXT) - $(HELPER) ./test_fast$(BINEXT) - -test_g: http_parser_g.o test_g.o - $(CC) $(CFLAGS_DEBUG) $(LDFLAGS) http_parser_g.o test_g.o -o $@ - -test_g.o: test.c http_parser.h Makefile - $(CC) $(CPPFLAGS_DEBUG) $(CFLAGS_DEBUG) -c test.c -o $@ - -http_parser_g.o: http_parser.c http_parser.h Makefile - $(CC) $(CPPFLAGS_DEBUG) $(CFLAGS_DEBUG) -c http_parser.c -o $@ - -test_fast: http_parser.o test.o http_parser.h - $(CC) $(CFLAGS_FAST) $(LDFLAGS) http_parser.o test.o -o $@ - -test.o: test.c http_parser.h Makefile - $(CC) $(CPPFLAGS_FAST) $(CFLAGS_FAST) -c test.c -o $@ - -bench: http_parser.o bench.o - $(CC) $(CFLAGS_BENCH) $(LDFLAGS) http_parser.o bench.o -o $@ - -bench.o: bench.c http_parser.h Makefile - $(CC) $(CPPFLAGS_BENCH) $(CFLAGS_BENCH) -c bench.c -o $@ - -http_parser.o: http_parser.c http_parser.h Makefile - $(CC) $(CPPFLAGS_FAST) $(CFLAGS_FAST) -c http_parser.c - -test-run-timed: test_fast - while(true) do time $(HELPER) ./test_fast$(BINEXT) > /dev/null; done - -test-valgrind: test_g - valgrind ./test_g - -libhttp_parser.o: http_parser.c http_parser.h Makefile - $(CC) $(CPPFLAGS_FAST) $(CFLAGS_LIB) -c http_parser.c -o libhttp_parser.o - -library: libhttp_parser.o - $(CC) $(LDFLAGS_LIB) -o $(SONAME) $< - -package: http_parser.o - $(AR) rcs libhttp_parser.a http_parser.o - -url_parser: http_parser.o contrib/url_parser.c - $(CC) $(CPPFLAGS_FAST) $(CFLAGS_FAST) $^ -o $@ - -url_parser_g: http_parser_g.o contrib/url_parser.c - $(CC) $(CPPFLAGS_DEBUG) $(CFLAGS_DEBUG) $^ -o $@ - -parsertrace: http_parser.o contrib/parsertrace.c - $(CC) $(CPPFLAGS_FAST) $(CFLAGS_FAST) $^ -o parsertrace$(BINEXT) - -parsertrace_g: http_parser_g.o contrib/parsertrace.c - $(CC) $(CPPFLAGS_DEBUG) $(CFLAGS_DEBUG) $^ -o parsertrace_g$(BINEXT) - -tags: http_parser.c http_parser.h test.c - ctags $^ - -install: library - $(INSTALL) -D http_parser.h $(INCLUDEDIR)/http_parser.h - $(INSTALL) -D $(SONAME) $(LIBDIR)/$(SONAME) - ln -s $(LIBDIR)/$(SONAME) $(LIBDIR)/libhttp_parser.$(SOEXT) - -install-strip: library - $(INSTALL) -D http_parser.h $(INCLUDEDIR)/http_parser.h - $(INSTALL) -D -s $(SONAME) $(LIBDIR)/$(SONAME) - ln -s $(LIBDIR)/$(SONAME) $(LIBDIR)/libhttp_parser.$(SOEXT) - -uninstall: - rm $(INCLUDEDIR)/http_parser.h - rm $(LIBDIR)/$(SONAME) - rm $(LIBDIR)/libhttp_parser.so - -clean: - rm -f *.o *.a tags test test_fast test_g \ - http_parser.tar libhttp_parser.so.* \ - url_parser url_parser_g parsertrace parsertrace_g \ - *.exe *.exe.so - -contrib/url_parser.c: http_parser.h -contrib/parsertrace.c: http_parser.h - -.PHONY: clean package test-run test-run-timed test-valgrind install install-strip uninstall diff --git a/vendor/http_parser/README.md b/vendor/http_parser/README.md deleted file mode 100644 index eedd7f8c9..000000000 --- a/vendor/http_parser/README.md +++ /dev/null @@ -1,246 +0,0 @@ -HTTP Parser -=========== - -[![Build Status](https://api.travis-ci.org/nodejs/http-parser.svg?branch=master)](https://travis-ci.org/nodejs/http-parser) - -This is a parser for HTTP messages written in C. It parses both requests and -responses. The parser is designed to be used in performance HTTP -applications. It does not make any syscalls nor allocations, it does not -buffer data, it can be interrupted at anytime. Depending on your -architecture, it only requires about 40 bytes of data per message -stream (in a web server that is per connection). - -Features: - - * No dependencies - * Handles persistent streams (keep-alive). - * Decodes chunked encoding. - * Upgrade support - * Defends against buffer overflow attacks. - -The parser extracts the following information from HTTP messages: - - * Header fields and values - * Content-Length - * Request method - * Response status code - * Transfer-Encoding - * HTTP version - * Request URL - * Message body - - -Usage ------ - -One `http_parser` object is used per TCP connection. Initialize the struct -using `http_parser_init()` and set the callbacks. That might look something -like this for a request parser: -```c -http_parser_settings settings; -settings.on_url = my_url_callback; -settings.on_header_field = my_header_field_callback; -/* ... */ - -http_parser *parser = malloc(sizeof(http_parser)); -http_parser_init(parser, HTTP_REQUEST); -parser->data = my_socket; -``` - -When data is received on the socket execute the parser and check for errors. - -```c -size_t len = 80*1024, nparsed; -char buf[len]; -ssize_t recved; - -recved = recv(fd, buf, len, 0); - -if (recved < 0) { - /* Handle error. */ -} - -/* Start up / continue the parser. - * Note we pass recved==0 to signal that EOF has been received. - */ -nparsed = http_parser_execute(parser, &settings, buf, recved); - -if (parser->upgrade) { - /* handle new protocol */ -} else if (nparsed != recved) { - /* Handle error. Usually just close the connection. */ -} -``` - -HTTP needs to know where the end of the stream is. For example, sometimes -servers send responses without Content-Length and expect the client to -consume input (for the body) until EOF. To tell http_parser about EOF, give -`0` as the fourth parameter to `http_parser_execute()`. Callbacks and errors -can still be encountered during an EOF, so one must still be prepared -to receive them. - -Scalar valued message information such as `status_code`, `method`, and the -HTTP version are stored in the parser structure. This data is only -temporally stored in `http_parser` and gets reset on each new message. If -this information is needed later, copy it out of the structure during the -`headers_complete` callback. - -The parser decodes the transfer-encoding for both requests and responses -transparently. That is, a chunked encoding is decoded before being sent to -the on_body callback. - - -The Special Problem of Upgrade ------------------------------- - -HTTP supports upgrading the connection to a different protocol. An -increasingly common example of this is the WebSocket protocol which sends -a request like - - GET /demo HTTP/1.1 - Upgrade: WebSocket - Connection: Upgrade - Host: example.com - Origin: http://example.com - WebSocket-Protocol: sample - -followed by non-HTTP data. - -(See [RFC6455](https://tools.ietf.org/html/rfc6455) for more information the -WebSocket protocol.) - -To support this, the parser will treat this as a normal HTTP message without a -body, issuing both on_headers_complete and on_message_complete callbacks. However -http_parser_execute() will stop parsing at the end of the headers and return. - -The user is expected to check if `parser->upgrade` has been set to 1 after -`http_parser_execute()` returns. Non-HTTP data begins at the buffer supplied -offset by the return value of `http_parser_execute()`. - - -Callbacks ---------- - -During the `http_parser_execute()` call, the callbacks set in -`http_parser_settings` will be executed. The parser maintains state and -never looks behind, so buffering the data is not necessary. If you need to -save certain data for later usage, you can do that from the callbacks. - -There are two types of callbacks: - -* notification `typedef int (*http_cb) (http_parser*);` - Callbacks: on_message_begin, on_headers_complete, on_message_complete. -* data `typedef int (*http_data_cb) (http_parser*, const char *at, size_t length);` - Callbacks: (requests only) on_url, - (common) on_header_field, on_header_value, on_body; - -Callbacks must return 0 on success. Returning a non-zero value indicates -error to the parser, making it exit immediately. - -For cases where it is necessary to pass local information to/from a callback, -the `http_parser` object's `data` field can be used. -An example of such a case is when using threads to handle a socket connection, -parse a request, and then give a response over that socket. By instantiation -of a thread-local struct containing relevant data (e.g. accepted socket, -allocated memory for callbacks to write into, etc), a parser's callbacks are -able to communicate data between the scope of the thread and the scope of the -callback in a threadsafe manner. This allows http-parser to be used in -multi-threaded contexts. - -Example: -``` - typedef struct { - socket_t sock; - void* buffer; - int buf_len; - } custom_data_t; - - -int my_url_callback(http_parser* parser, const char *at, size_t length) { - /* access to thread local custom_data_t struct. - Use this access save parsed data for later use into thread local - buffer, or communicate over socket - */ - parser->data; - ... - return 0; -} - -... - -void http_parser_thread(socket_t sock) { - int nparsed = 0; - /* allocate memory for user data */ - custom_data_t *my_data = malloc(sizeof(custom_data_t)); - - /* some information for use by callbacks. - * achieves thread -> callback information flow */ - my_data->sock = sock; - - /* instantiate a thread-local parser */ - http_parser *parser = malloc(sizeof(http_parser)); - http_parser_init(parser, HTTP_REQUEST); /* initialise parser */ - /* this custom data reference is accessible through the reference to the - parser supplied to callback functions */ - parser->data = my_data; - - http_parser_settings settings; / * set up callbacks */ - settings.on_url = my_url_callback; - - /* execute parser */ - nparsed = http_parser_execute(parser, &settings, buf, recved); - - ... - /* parsed information copied from callback. - can now perform action on data copied into thread-local memory from callbacks. - achieves callback -> thread information flow */ - my_data->buffer; - ... -} - -``` - -In case you parse HTTP message in chunks (i.e. `read()` request line -from socket, parse, read half headers, parse, etc) your data callbacks -may be called more than once. Http-parser guarantees that data pointer is only -valid for the lifetime of callback. You can also `read()` into a heap allocated -buffer to avoid copying memory around if this fits your application. - -Reading headers may be a tricky task if you read/parse headers partially. -Basically, you need to remember whether last header callback was field or value -and apply the following logic: - - (on_header_field and on_header_value shortened to on_h_*) - ------------------------ ------------ -------------------------------------------- - | State (prev. callback) | Callback | Description/action | - ------------------------ ------------ -------------------------------------------- - | nothing (first call) | on_h_field | Allocate new buffer and copy callback data | - | | | into it | - ------------------------ ------------ -------------------------------------------- - | value | on_h_field | New header started. | - | | | Copy current name,value buffers to headers | - | | | list and allocate new buffer for new name | - ------------------------ ------------ -------------------------------------------- - | field | on_h_field | Previous name continues. Reallocate name | - | | | buffer and append callback data to it | - ------------------------ ------------ -------------------------------------------- - | field | on_h_value | Value for current header started. Allocate | - | | | new buffer and copy callback data to it | - ------------------------ ------------ -------------------------------------------- - | value | on_h_value | Value continues. Reallocate value buffer | - | | | and append callback data to it | - ------------------------ ------------ -------------------------------------------- - - -Parsing URLs ------------- - -A simplistic zero-copy URL parser is provided as `http_parser_parse_url()`. -Users of this library may wish to use it to parse URLs constructed from -consecutive `on_url` callbacks. - -See examples of reading in headers: - -* [partial example](http://gist.github.com/155877) in C -* [from http-parser tests](http://github.com/joyent/http-parser/blob/37a0ff8/test.c#L403) in C -* [from Node library](http://github.com/joyent/node/blob/842eaf4/src/http.js#L284) in Javascript diff --git a/vendor/http_parser/bench.c b/vendor/http_parser/bench.c deleted file mode 100644 index 5b452fa1c..000000000 --- a/vendor/http_parser/bench.c +++ /dev/null @@ -1,111 +0,0 @@ -/* Copyright Fedor Indutny. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ -#include "http_parser.h" -#include -#include -#include -#include - -static const char data[] = - "POST /joyent/http-parser HTTP/1.1\r\n" - "Host: github.com\r\n" - "DNT: 1\r\n" - "Accept-Encoding: gzip, deflate, sdch\r\n" - "Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4\r\n" - "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) " - "AppleWebKit/537.36 (KHTML, like Gecko) " - "Chrome/39.0.2171.65 Safari/537.36\r\n" - "Accept: text/html,application/xhtml+xml,application/xml;q=0.9," - "image/webp,*/*;q=0.8\r\n" - "Referer: https://github.com/joyent/http-parser\r\n" - "Connection: keep-alive\r\n" - "Transfer-Encoding: chunked\r\n" - "Cache-Control: max-age=0\r\n\r\nb\r\nhello world\r\n0\r\n\r\n"; -static const size_t data_len = sizeof(data) - 1; - -static int on_info(http_parser* p) { - return 0; -} - - -static int on_data(http_parser* p, const char *at, size_t length) { - return 0; -} - -static http_parser_settings settings = { - .on_message_begin = on_info, - .on_headers_complete = on_info, - .on_message_complete = on_info, - .on_header_field = on_data, - .on_header_value = on_data, - .on_url = on_data, - .on_status = on_data, - .on_body = on_data -}; - -int bench(int iter_count, int silent) { - struct http_parser parser; - int i; - int err; - struct timeval start; - struct timeval end; - float rps; - - if (!silent) { - err = gettimeofday(&start, NULL); - assert(err == 0); - } - - for (i = 0; i < iter_count; i++) { - size_t parsed; - http_parser_init(&parser, HTTP_REQUEST); - - parsed = http_parser_execute(&parser, &settings, data, data_len); - assert(parsed == data_len); - } - - if (!silent) { - err = gettimeofday(&end, NULL); - assert(err == 0); - - fprintf(stdout, "Benchmark result:\n"); - - rps = (float) (end.tv_sec - start.tv_sec) + - (end.tv_usec - start.tv_usec) * 1e-6f; - fprintf(stdout, "Took %f seconds to run\n", rps); - - rps = (float) iter_count / rps; - fprintf(stdout, "%f req/sec\n", rps); - fflush(stdout); - } - - return 0; -} - -int main(int argc, char** argv) { - if (argc == 2 && strcmp(argv[1], "infinite") == 0) { - for (;;) - bench(5000000, 1); - return 0; - } else { - return bench(5000000, 0); - } -} diff --git a/vendor/http_parser/contrib/parsertrace.c b/vendor/http_parser/contrib/parsertrace.c deleted file mode 100644 index e7153680f..000000000 --- a/vendor/http_parser/contrib/parsertrace.c +++ /dev/null @@ -1,160 +0,0 @@ -/* Based on src/http/ngx_http_parse.c from NGINX copyright Igor Sysoev - * - * Additional changes are licensed under the same terms as NGINX and - * copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -/* Dump what the parser finds to stdout as it happen */ - -#include "http_parser.h" -#include -#include -#include - -int on_message_begin(http_parser* _) { - (void)_; - printf("\n***MESSAGE BEGIN***\n\n"); - return 0; -} - -int on_headers_complete(http_parser* _) { - (void)_; - printf("\n***HEADERS COMPLETE***\n\n"); - return 0; -} - -int on_message_complete(http_parser* _) { - (void)_; - printf("\n***MESSAGE COMPLETE***\n\n"); - return 0; -} - -int on_url(http_parser* _, const char* at, size_t length) { - (void)_; - printf("Url: %.*s\n", (int)length, at); - return 0; -} - -int on_header_field(http_parser* _, const char* at, size_t length) { - (void)_; - printf("Header field: %.*s\n", (int)length, at); - return 0; -} - -int on_header_value(http_parser* _, const char* at, size_t length) { - (void)_; - printf("Header value: %.*s\n", (int)length, at); - return 0; -} - -int on_body(http_parser* _, const char* at, size_t length) { - (void)_; - printf("Body: %.*s\n", (int)length, at); - return 0; -} - -void usage(const char* name) { - fprintf(stderr, - "Usage: %s $type $filename\n" - " type: -x, where x is one of {r,b,q}\n" - " parses file as a Response, reQuest, or Both\n", - name); - exit(EXIT_FAILURE); -} - -int main(int argc, char* argv[]) { - enum http_parser_type file_type; - - if (argc != 3) { - usage(argv[0]); - } - - char* type = argv[1]; - if (type[0] != '-') { - usage(argv[0]); - } - - switch (type[1]) { - /* in the case of "-", type[1] will be NUL */ - case 'r': - file_type = HTTP_RESPONSE; - break; - case 'q': - file_type = HTTP_REQUEST; - break; - case 'b': - file_type = HTTP_BOTH; - break; - default: - usage(argv[0]); - } - - char* filename = argv[2]; - FILE* file = fopen(filename, "r"); - if (file == NULL) { - perror("fopen"); - goto fail; - } - - fseek(file, 0, SEEK_END); - long file_length = ftell(file); - if (file_length == -1) { - perror("ftell"); - goto fail; - } - fseek(file, 0, SEEK_SET); - - char* data = malloc(file_length); - if (fread(data, 1, file_length, file) != (size_t)file_length) { - fprintf(stderr, "couldn't read entire file\n"); - free(data); - goto fail; - } - - http_parser_settings settings; - memset(&settings, 0, sizeof(settings)); - settings.on_message_begin = on_message_begin; - settings.on_url = on_url; - settings.on_header_field = on_header_field; - settings.on_header_value = on_header_value; - settings.on_headers_complete = on_headers_complete; - settings.on_body = on_body; - settings.on_message_complete = on_message_complete; - - http_parser parser; - http_parser_init(&parser, file_type); - size_t nparsed = http_parser_execute(&parser, &settings, data, file_length); - free(data); - - if (nparsed != (size_t)file_length) { - fprintf(stderr, - "Error: %s (%s)\n", - http_errno_description(HTTP_PARSER_ERRNO(&parser)), - http_errno_name(HTTP_PARSER_ERRNO(&parser))); - goto fail; - } - - return EXIT_SUCCESS; - -fail: - fclose(file); - return EXIT_FAILURE; -} diff --git a/vendor/http_parser/contrib/url_parser.c b/vendor/http_parser/contrib/url_parser.c deleted file mode 100644 index f235bed9e..000000000 --- a/vendor/http_parser/contrib/url_parser.c +++ /dev/null @@ -1,47 +0,0 @@ -#include "http_parser.h" -#include -#include - -void -dump_url (const char *url, const struct http_parser_url *u) -{ - unsigned int i; - - printf("\tfield_set: 0x%x, port: %u\n", u->field_set, u->port); - for (i = 0; i < UF_MAX; i++) { - if ((u->field_set & (1 << i)) == 0) { - printf("\tfield_data[%u]: unset\n", i); - continue; - } - - printf("\tfield_data[%u]: off: %u, len: %u, part: %.*s\n", - i, - u->field_data[i].off, - u->field_data[i].len, - u->field_data[i].len, - url + u->field_data[i].off); - } -} - -int main(int argc, char ** argv) { - struct http_parser_url u; - int len, connect, result; - - if (argc != 3) { - printf("Syntax : %s connect|get url\n", argv[0]); - return 1; - } - len = strlen(argv[2]); - connect = strcmp("connect", argv[1]) == 0 ? 1 : 0; - printf("Parsing %s, connect %d\n", argv[2], connect); - - http_parser_url_init(&u); - result = http_parser_parse_url(argv[2], len, connect, &u); - if (result != 0) { - printf("Parse error : %d\n", result); - return result; - } - printf("Parse ok, result : \n"); - dump_url(argv[2], &u); - return 0; -} diff --git a/vendor/http_parser/http_parser.c b/vendor/http_parser/http_parser.c deleted file mode 100644 index d51a2e7bc..000000000 --- a/vendor/http_parser/http_parser.c +++ /dev/null @@ -1,2465 +0,0 @@ -/* Based on src/http/ngx_http_parse.c from NGINX copyright Igor Sysoev - * - * Additional changes are licensed under the same terms as NGINX and - * copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ -#include "http_parser.h" -#include -#include -#include -#include -#include -#include - -#ifndef ULLONG_MAX -# define ULLONG_MAX ((uint64_t) -1) /* 2^64-1 */ -#endif - -#ifndef MIN -# define MIN(a,b) ((a) < (b) ? (a) : (b)) -#endif - -#ifndef ARRAY_SIZE -# define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) -#endif - -#ifndef BIT_AT -# define BIT_AT(a, i) \ - (!!((unsigned int) (a)[(unsigned int) (i) >> 3] & \ - (1 << ((unsigned int) (i) & 7)))) -#endif - -#ifndef ELEM_AT -# define ELEM_AT(a, i, v) ((unsigned int) (i) < ARRAY_SIZE(a) ? (a)[(i)] : (v)) -#endif - -#define SET_ERRNO(e) \ -do { \ - parser->http_errno = (e); \ -} while(0) - -#define CURRENT_STATE() p_state -#define UPDATE_STATE(V) p_state = (enum state) (V); -#define RETURN(V) \ -do { \ - parser->state = CURRENT_STATE(); \ - return (V); \ -} while (0); -#define REEXECUTE() \ - goto reexecute; \ - - -#ifdef __GNUC__ -# define LIKELY(X) __builtin_expect(!!(X), 1) -# define UNLIKELY(X) __builtin_expect(!!(X), 0) -#else -# define LIKELY(X) (X) -# define UNLIKELY(X) (X) -#endif - - -/* Run the notify callback FOR, returning ER if it fails */ -#define CALLBACK_NOTIFY_(FOR, ER) \ -do { \ - assert(HTTP_PARSER_ERRNO(parser) == HPE_OK); \ - \ - if (LIKELY(settings->on_##FOR)) { \ - parser->state = CURRENT_STATE(); \ - if (UNLIKELY(0 != settings->on_##FOR(parser))) { \ - SET_ERRNO(HPE_CB_##FOR); \ - } \ - UPDATE_STATE(parser->state); \ - \ - /* We either errored above or got paused; get out */ \ - if (UNLIKELY(HTTP_PARSER_ERRNO(parser) != HPE_OK)) { \ - return (ER); \ - } \ - } \ -} while (0) - -/* Run the notify callback FOR and consume the current byte */ -#define CALLBACK_NOTIFY(FOR) CALLBACK_NOTIFY_(FOR, p - data + 1) - -/* Run the notify callback FOR and don't consume the current byte */ -#define CALLBACK_NOTIFY_NOADVANCE(FOR) CALLBACK_NOTIFY_(FOR, p - data) - -/* Run data callback FOR with LEN bytes, returning ER if it fails */ -#define CALLBACK_DATA_(FOR, LEN, ER) \ -do { \ - assert(HTTP_PARSER_ERRNO(parser) == HPE_OK); \ - \ - if (FOR##_mark) { \ - if (LIKELY(settings->on_##FOR)) { \ - parser->state = CURRENT_STATE(); \ - if (UNLIKELY(0 != \ - settings->on_##FOR(parser, FOR##_mark, (LEN)))) { \ - SET_ERRNO(HPE_CB_##FOR); \ - } \ - UPDATE_STATE(parser->state); \ - \ - /* We either errored above or got paused; get out */ \ - if (UNLIKELY(HTTP_PARSER_ERRNO(parser) != HPE_OK)) { \ - return (ER); \ - } \ - } \ - FOR##_mark = NULL; \ - } \ -} while (0) - -/* Run the data callback FOR and consume the current byte */ -#define CALLBACK_DATA(FOR) \ - CALLBACK_DATA_(FOR, p - FOR##_mark, p - data + 1) - -/* Run the data callback FOR and don't consume the current byte */ -#define CALLBACK_DATA_NOADVANCE(FOR) \ - CALLBACK_DATA_(FOR, p - FOR##_mark, p - data) - -/* Set the mark FOR; non-destructive if mark is already set */ -#define MARK(FOR) \ -do { \ - if (!FOR##_mark) { \ - FOR##_mark = p; \ - } \ -} while (0) - -/* Don't allow the total size of the HTTP headers (including the status - * line) to exceed HTTP_MAX_HEADER_SIZE. This check is here to protect - * embedders against denial-of-service attacks where the attacker feeds - * us a never-ending header that the embedder keeps buffering. - * - * This check is arguably the responsibility of embedders but we're doing - * it on the embedder's behalf because most won't bother and this way we - * make the web a little safer. HTTP_MAX_HEADER_SIZE is still far bigger - * than any reasonable request or response so this should never affect - * day-to-day operation. - */ -#define COUNT_HEADER_SIZE(V) \ -do { \ - parser->nread += (V); \ - if (UNLIKELY(parser->nread > (HTTP_MAX_HEADER_SIZE))) { \ - SET_ERRNO(HPE_HEADER_OVERFLOW); \ - goto error; \ - } \ -} while (0) - - -#define PROXY_CONNECTION "proxy-connection" -#define CONNECTION "connection" -#define CONTENT_LENGTH "content-length" -#define TRANSFER_ENCODING "transfer-encoding" -#define UPGRADE "upgrade" -#define CHUNKED "chunked" -#define KEEP_ALIVE "keep-alive" -#define CLOSE "close" - - -static const char *method_strings[] = - { -#define XX(num, name, string) #string, - HTTP_METHOD_MAP(XX) -#undef XX - }; - - -/* Tokens as defined by rfc 2616. Also lowercases them. - * token = 1* - * separators = "(" | ")" | "<" | ">" | "@" - * | "," | ";" | ":" | "\" | <"> - * | "/" | "[" | "]" | "?" | "=" - * | "{" | "}" | SP | HT - */ -static const char tokens[256] = { -/* 0 nul 1 soh 2 stx 3 etx 4 eot 5 enq 6 ack 7 bel */ - 0, 0, 0, 0, 0, 0, 0, 0, -/* 8 bs 9 ht 10 nl 11 vt 12 np 13 cr 14 so 15 si */ - 0, 0, 0, 0, 0, 0, 0, 0, -/* 16 dle 17 dc1 18 dc2 19 dc3 20 dc4 21 nak 22 syn 23 etb */ - 0, 0, 0, 0, 0, 0, 0, 0, -/* 24 can 25 em 26 sub 27 esc 28 fs 29 gs 30 rs 31 us */ - 0, 0, 0, 0, 0, 0, 0, 0, -/* 32 sp 33 ! 34 " 35 # 36 $ 37 % 38 & 39 ' */ - 0, '!', 0, '#', '$', '%', '&', '\'', -/* 40 ( 41 ) 42 * 43 + 44 , 45 - 46 . 47 / */ - 0, 0, '*', '+', 0, '-', '.', 0, -/* 48 0 49 1 50 2 51 3 52 4 53 5 54 6 55 7 */ - '0', '1', '2', '3', '4', '5', '6', '7', -/* 56 8 57 9 58 : 59 ; 60 < 61 = 62 > 63 ? */ - '8', '9', 0, 0, 0, 0, 0, 0, -/* 64 @ 65 A 66 B 67 C 68 D 69 E 70 F 71 G */ - 0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', -/* 72 H 73 I 74 J 75 K 76 L 77 M 78 N 79 O */ - 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', -/* 80 P 81 Q 82 R 83 S 84 T 85 U 86 V 87 W */ - 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', -/* 88 X 89 Y 90 Z 91 [ 92 \ 93 ] 94 ^ 95 _ */ - 'x', 'y', 'z', 0, 0, 0, '^', '_', -/* 96 ` 97 a 98 b 99 c 100 d 101 e 102 f 103 g */ - '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', -/* 104 h 105 i 106 j 107 k 108 l 109 m 110 n 111 o */ - 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', -/* 112 p 113 q 114 r 115 s 116 t 117 u 118 v 119 w */ - 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', -/* 120 x 121 y 122 z 123 { 124 | 125 } 126 ~ 127 del */ - 'x', 'y', 'z', 0, '|', 0, '~', 0 }; - - -static const int8_t unhex[256] = - {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 - ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 - ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 - , 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1 - ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1 - ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 - ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1 - ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 - }; - - -#if HTTP_PARSER_STRICT -# define T(v) 0 -#else -# define T(v) v -#endif - - -static const uint8_t normal_url_char[32] = { -/* 0 nul 1 soh 2 stx 3 etx 4 eot 5 enq 6 ack 7 bel */ - 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0, -/* 8 bs 9 ht 10 nl 11 vt 12 np 13 cr 14 so 15 si */ - 0 | T(2) | 0 | 0 | T(16) | 0 | 0 | 0, -/* 16 dle 17 dc1 18 dc2 19 dc3 20 dc4 21 nak 22 syn 23 etb */ - 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0, -/* 24 can 25 em 26 sub 27 esc 28 fs 29 gs 30 rs 31 us */ - 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0, -/* 32 sp 33 ! 34 " 35 # 36 $ 37 % 38 & 39 ' */ - 0 | 2 | 4 | 0 | 16 | 32 | 64 | 128, -/* 40 ( 41 ) 42 * 43 + 44 , 45 - 46 . 47 / */ - 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, -/* 48 0 49 1 50 2 51 3 52 4 53 5 54 6 55 7 */ - 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, -/* 56 8 57 9 58 : 59 ; 60 < 61 = 62 > 63 ? */ - 1 | 2 | 4 | 8 | 16 | 32 | 64 | 0, -/* 64 @ 65 A 66 B 67 C 68 D 69 E 70 F 71 G */ - 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, -/* 72 H 73 I 74 J 75 K 76 L 77 M 78 N 79 O */ - 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, -/* 80 P 81 Q 82 R 83 S 84 T 85 U 86 V 87 W */ - 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, -/* 88 X 89 Y 90 Z 91 [ 92 \ 93 ] 94 ^ 95 _ */ - 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, -/* 96 ` 97 a 98 b 99 c 100 d 101 e 102 f 103 g */ - 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, -/* 104 h 105 i 106 j 107 k 108 l 109 m 110 n 111 o */ - 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, -/* 112 p 113 q 114 r 115 s 116 t 117 u 118 v 119 w */ - 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, -/* 120 x 121 y 122 z 123 { 124 | 125 } 126 ~ 127 del */ - 1 | 2 | 4 | 8 | 16 | 32 | 64 | 0, }; - -#undef T - -enum state - { s_dead = 1 /* important that this is > 0 */ - - , s_start_req_or_res - , s_res_or_resp_H - , s_start_res - , s_res_H - , s_res_HT - , s_res_HTT - , s_res_HTTP - , s_res_first_http_major - , s_res_http_major - , s_res_first_http_minor - , s_res_http_minor - , s_res_first_status_code - , s_res_status_code - , s_res_status_start - , s_res_status - , s_res_line_almost_done - - , s_start_req - - , s_req_method - , s_req_spaces_before_url - , s_req_schema - , s_req_schema_slash - , s_req_schema_slash_slash - , s_req_server_start - , s_req_server - , s_req_server_with_at - , s_req_path - , s_req_query_string_start - , s_req_query_string - , s_req_fragment_start - , s_req_fragment - , s_req_http_start - , s_req_http_H - , s_req_http_HT - , s_req_http_HTT - , s_req_http_HTTP - , s_req_first_http_major - , s_req_http_major - , s_req_first_http_minor - , s_req_http_minor - , s_req_line_almost_done - - , s_header_field_start - , s_header_field - , s_header_value_discard_ws - , s_header_value_discard_ws_almost_done - , s_header_value_discard_lws - , s_header_value_start - , s_header_value - , s_header_value_lws - - , s_header_almost_done - - , s_chunk_size_start - , s_chunk_size - , s_chunk_parameters - , s_chunk_size_almost_done - - , s_headers_almost_done - , s_headers_done - - /* Important: 's_headers_done' must be the last 'header' state. All - * states beyond this must be 'body' states. It is used for overflow - * checking. See the PARSING_HEADER() macro. - */ - - , s_chunk_data - , s_chunk_data_almost_done - , s_chunk_data_done - - , s_body_identity - , s_body_identity_eof - - , s_message_done - }; - - -#define PARSING_HEADER(state) (state <= s_headers_done) - - -enum header_states - { h_general = 0 - , h_C - , h_CO - , h_CON - - , h_matching_connection - , h_matching_proxy_connection - , h_matching_content_length - , h_matching_transfer_encoding - , h_matching_upgrade - - , h_connection - , h_content_length - , h_transfer_encoding - , h_upgrade - - , h_matching_transfer_encoding_chunked - , h_matching_connection_token_start - , h_matching_connection_keep_alive - , h_matching_connection_close - , h_matching_connection_upgrade - , h_matching_connection_token - - , h_transfer_encoding_chunked - , h_connection_keep_alive - , h_connection_close - , h_connection_upgrade - }; - -enum http_host_state - { - s_http_host_dead = 1 - , s_http_userinfo_start - , s_http_userinfo - , s_http_host_start - , s_http_host_v6_start - , s_http_host - , s_http_host_v6 - , s_http_host_v6_end - , s_http_host_v6_zone_start - , s_http_host_v6_zone - , s_http_host_port_start - , s_http_host_port -}; - -/* Macros for character classes; depends on strict-mode */ -#define CR '\r' -#define LF '\n' -#define LOWER(c) (unsigned char)(c | 0x20) -#define IS_ALPHA(c) (LOWER(c) >= 'a' && LOWER(c) <= 'z') -#define IS_NUM(c) ((c) >= '0' && (c) <= '9') -#define IS_ALPHANUM(c) (IS_ALPHA(c) || IS_NUM(c)) -#define IS_HEX(c) (IS_NUM(c) || (LOWER(c) >= 'a' && LOWER(c) <= 'f')) -#define IS_MARK(c) ((c) == '-' || (c) == '_' || (c) == '.' || \ - (c) == '!' || (c) == '~' || (c) == '*' || (c) == '\'' || (c) == '(' || \ - (c) == ')') -#define IS_USERINFO_CHAR(c) (IS_ALPHANUM(c) || IS_MARK(c) || (c) == '%' || \ - (c) == ';' || (c) == ':' || (c) == '&' || (c) == '=' || (c) == '+' || \ - (c) == '$' || (c) == ',') - -#define STRICT_TOKEN(c) (tokens[(unsigned char)c]) - -#if HTTP_PARSER_STRICT -#define TOKEN(c) (tokens[(unsigned char)c]) -#define IS_URL_CHAR(c) (BIT_AT(normal_url_char, (unsigned char)c)) -#define IS_HOST_CHAR(c) (IS_ALPHANUM(c) || (c) == '.' || (c) == '-') -#else -#define TOKEN(c) ((c == ' ') ? ' ' : tokens[(unsigned char)c]) -#define IS_URL_CHAR(c) \ - (BIT_AT(normal_url_char, (unsigned char)c) || ((c) & 0x80)) -#define IS_HOST_CHAR(c) \ - (IS_ALPHANUM(c) || (c) == '.' || (c) == '-' || (c) == '_') -#endif - -/** - * Verify that a char is a valid visible (printable) US-ASCII - * character or %x80-FF - **/ -#define IS_HEADER_CHAR(ch) \ - (ch == CR || ch == LF || ch == 9 || ((unsigned char)ch > 31 && ch != 127)) - -#define start_state (parser->type == HTTP_REQUEST ? s_start_req : s_start_res) - - -#if HTTP_PARSER_STRICT -# define STRICT_CHECK(cond) \ -do { \ - if (cond) { \ - SET_ERRNO(HPE_STRICT); \ - goto error; \ - } \ -} while (0) -# define NEW_MESSAGE() (http_should_keep_alive(parser) ? start_state : s_dead) -#else -# define STRICT_CHECK(cond) -# define NEW_MESSAGE() start_state -#endif - - -/* Map errno values to strings for human-readable output */ -#define HTTP_STRERROR_GEN(n, s) { "HPE_" #n, s }, -static struct { - const char *name; - const char *description; -} http_strerror_tab[] = { - HTTP_ERRNO_MAP(HTTP_STRERROR_GEN) -}; -#undef HTTP_STRERROR_GEN - -int http_message_needs_eof(const http_parser *parser); - -/* Our URL parser. - * - * This is designed to be shared by http_parser_execute() for URL validation, - * hence it has a state transition + byte-for-byte interface. In addition, it - * is meant to be embedded in http_parser_parse_url(), which does the dirty - * work of turning state transitions URL components for its API. - * - * This function should only be invoked with non-space characters. It is - * assumed that the caller cares about (and can detect) the transition between - * URL and non-URL states by looking for these. - */ -static enum state -parse_url_char(enum state s, const char ch) -{ - if (ch == ' ' || ch == '\r' || ch == '\n') { - return s_dead; - } - -#if HTTP_PARSER_STRICT - if (ch == '\t' || ch == '\f') { - return s_dead; - } -#endif - - switch (s) { - case s_req_spaces_before_url: - /* Proxied requests are followed by scheme of an absolute URI (alpha). - * All methods except CONNECT are followed by '/' or '*'. - */ - - if (ch == '/' || ch == '*') { - return s_req_path; - } - - if (IS_ALPHA(ch)) { - return s_req_schema; - } - - break; - - case s_req_schema: - if (IS_ALPHA(ch)) { - return s; - } - - if (ch == ':') { - return s_req_schema_slash; - } - - break; - - case s_req_schema_slash: - if (ch == '/') { - return s_req_schema_slash_slash; - } - - break; - - case s_req_schema_slash_slash: - if (ch == '/') { - return s_req_server_start; - } - - break; - - case s_req_server_with_at: - if (ch == '@') { - return s_dead; - } - - /* FALLTHROUGH */ - case s_req_server_start: - case s_req_server: - if (ch == '/') { - return s_req_path; - } - - if (ch == '?') { - return s_req_query_string_start; - } - - if (ch == '@') { - return s_req_server_with_at; - } - - if (IS_USERINFO_CHAR(ch) || ch == '[' || ch == ']') { - return s_req_server; - } - - break; - - case s_req_path: - if (IS_URL_CHAR(ch)) { - return s; - } - - switch (ch) { - case '?': - return s_req_query_string_start; - - case '#': - return s_req_fragment_start; - } - - break; - - case s_req_query_string_start: - case s_req_query_string: - if (IS_URL_CHAR(ch)) { - return s_req_query_string; - } - - switch (ch) { - case '?': - /* allow extra '?' in query string */ - return s_req_query_string; - - case '#': - return s_req_fragment_start; - } - - break; - - case s_req_fragment_start: - if (IS_URL_CHAR(ch)) { - return s_req_fragment; - } - - switch (ch) { - case '?': - return s_req_fragment; - - case '#': - return s; - } - - break; - - case s_req_fragment: - if (IS_URL_CHAR(ch)) { - return s; - } - - switch (ch) { - case '?': - case '#': - return s; - } - - break; - - default: - break; - } - - /* We should never fall out of the switch above unless there's an error */ - return s_dead; -} - -size_t http_parser_execute (http_parser *parser, - const http_parser_settings *settings, - const char *data, - size_t len) -{ - char c, ch; - int8_t unhex_val; - const char *p = data; - const char *header_field_mark = 0; - const char *header_value_mark = 0; - const char *url_mark = 0; - const char *body_mark = 0; - const char *status_mark = 0; - enum state p_state = (enum state) parser->state; - const unsigned int lenient = parser->lenient_http_headers; - - /* We're in an error state. Don't bother doing anything. */ - if (HTTP_PARSER_ERRNO(parser) != HPE_OK) { - return 0; - } - - if (len == 0) { - switch (CURRENT_STATE()) { - case s_body_identity_eof: - /* Use of CALLBACK_NOTIFY() here would erroneously return 1 byte read if - * we got paused. - */ - CALLBACK_NOTIFY_NOADVANCE(message_complete); - return 0; - - case s_dead: - case s_start_req_or_res: - case s_start_res: - case s_start_req: - return 0; - - default: - SET_ERRNO(HPE_INVALID_EOF_STATE); - return 1; - } - } - - - if (CURRENT_STATE() == s_header_field) - header_field_mark = data; - if (CURRENT_STATE() == s_header_value) - header_value_mark = data; - switch (CURRENT_STATE()) { - case s_req_path: - case s_req_schema: - case s_req_schema_slash: - case s_req_schema_slash_slash: - case s_req_server_start: - case s_req_server: - case s_req_server_with_at: - case s_req_query_string_start: - case s_req_query_string: - case s_req_fragment_start: - case s_req_fragment: - url_mark = data; - break; - case s_res_status: - status_mark = data; - break; - default: - break; - } - - for (p=data; p != data + len; p++) { - ch = *p; - - if (PARSING_HEADER(CURRENT_STATE())) - COUNT_HEADER_SIZE(1); - -reexecute: - switch (CURRENT_STATE()) { - - case s_dead: - /* this state is used after a 'Connection: close' message - * the parser will error out if it reads another message - */ - if (LIKELY(ch == CR || ch == LF)) - break; - - SET_ERRNO(HPE_CLOSED_CONNECTION); - goto error; - - case s_start_req_or_res: - { - if (ch == CR || ch == LF) - break; - parser->flags = 0; - parser->content_length = ULLONG_MAX; - - if (ch == 'H') { - UPDATE_STATE(s_res_or_resp_H); - - CALLBACK_NOTIFY(message_begin); - } else { - parser->type = HTTP_REQUEST; - UPDATE_STATE(s_start_req); - REEXECUTE(); - } - - break; - } - - case s_res_or_resp_H: - if (ch == 'T') { - parser->type = HTTP_RESPONSE; - UPDATE_STATE(s_res_HT); - } else { - if (UNLIKELY(ch != 'E')) { - SET_ERRNO(HPE_INVALID_CONSTANT); - goto error; - } - - parser->type = HTTP_REQUEST; - parser->method = HTTP_HEAD; - parser->index = 2; - UPDATE_STATE(s_req_method); - } - break; - - case s_start_res: - { - parser->flags = 0; - parser->content_length = ULLONG_MAX; - - switch (ch) { - case 'H': - UPDATE_STATE(s_res_H); - break; - - case CR: - case LF: - break; - - default: - SET_ERRNO(HPE_INVALID_CONSTANT); - goto error; - } - - CALLBACK_NOTIFY(message_begin); - break; - } - - case s_res_H: - STRICT_CHECK(ch != 'T'); - UPDATE_STATE(s_res_HT); - break; - - case s_res_HT: - STRICT_CHECK(ch != 'T'); - UPDATE_STATE(s_res_HTT); - break; - - case s_res_HTT: - STRICT_CHECK(ch != 'P'); - UPDATE_STATE(s_res_HTTP); - break; - - case s_res_HTTP: - STRICT_CHECK(ch != '/'); - UPDATE_STATE(s_res_first_http_major); - break; - - case s_res_first_http_major: - if (UNLIKELY(ch < '0' || ch > '9')) { - SET_ERRNO(HPE_INVALID_VERSION); - goto error; - } - - parser->http_major = ch - '0'; - UPDATE_STATE(s_res_http_major); - break; - - /* major HTTP version or dot */ - case s_res_http_major: - { - if (ch == '.') { - UPDATE_STATE(s_res_first_http_minor); - break; - } - - if (!IS_NUM(ch)) { - SET_ERRNO(HPE_INVALID_VERSION); - goto error; - } - - parser->http_major *= 10; - parser->http_major += ch - '0'; - - if (UNLIKELY(parser->http_major > 999)) { - SET_ERRNO(HPE_INVALID_VERSION); - goto error; - } - - break; - } - - /* first digit of minor HTTP version */ - case s_res_first_http_minor: - if (UNLIKELY(!IS_NUM(ch))) { - SET_ERRNO(HPE_INVALID_VERSION); - goto error; - } - - parser->http_minor = ch - '0'; - UPDATE_STATE(s_res_http_minor); - break; - - /* minor HTTP version or end of request line */ - case s_res_http_minor: - { - if (ch == ' ') { - UPDATE_STATE(s_res_first_status_code); - break; - } - - if (UNLIKELY(!IS_NUM(ch))) { - SET_ERRNO(HPE_INVALID_VERSION); - goto error; - } - - parser->http_minor *= 10; - parser->http_minor += ch - '0'; - - if (UNLIKELY(parser->http_minor > 999)) { - SET_ERRNO(HPE_INVALID_VERSION); - goto error; - } - - break; - } - - case s_res_first_status_code: - { - if (!IS_NUM(ch)) { - if (ch == ' ') { - break; - } - - SET_ERRNO(HPE_INVALID_STATUS); - goto error; - } - parser->status_code = ch - '0'; - UPDATE_STATE(s_res_status_code); - break; - } - - case s_res_status_code: - { - if (!IS_NUM(ch)) { - switch (ch) { - case ' ': - UPDATE_STATE(s_res_status_start); - break; - case CR: - UPDATE_STATE(s_res_line_almost_done); - break; - case LF: - UPDATE_STATE(s_header_field_start); - break; - default: - SET_ERRNO(HPE_INVALID_STATUS); - goto error; - } - break; - } - - parser->status_code *= 10; - parser->status_code += ch - '0'; - - if (UNLIKELY(parser->status_code > 999)) { - SET_ERRNO(HPE_INVALID_STATUS); - goto error; - } - - break; - } - - case s_res_status_start: - { - if (ch == CR) { - UPDATE_STATE(s_res_line_almost_done); - break; - } - - if (ch == LF) { - UPDATE_STATE(s_header_field_start); - break; - } - - MARK(status); - UPDATE_STATE(s_res_status); - parser->index = 0; - break; - } - - case s_res_status: - if (ch == CR) { - UPDATE_STATE(s_res_line_almost_done); - CALLBACK_DATA(status); - break; - } - - if (ch == LF) { - UPDATE_STATE(s_header_field_start); - CALLBACK_DATA(status); - break; - } - - break; - - case s_res_line_almost_done: - STRICT_CHECK(ch != LF); - UPDATE_STATE(s_header_field_start); - break; - - case s_start_req: - { - if (ch == CR || ch == LF) - break; - parser->flags = 0; - parser->content_length = ULLONG_MAX; - - if (UNLIKELY(!IS_ALPHA(ch))) { - SET_ERRNO(HPE_INVALID_METHOD); - goto error; - } - - parser->method = (enum http_method) 0; - parser->index = 1; - switch (ch) { - case 'A': parser->method = HTTP_ACL; break; - case 'B': parser->method = HTTP_BIND; break; - case 'C': parser->method = HTTP_CONNECT; /* or COPY, CHECKOUT */ break; - case 'D': parser->method = HTTP_DELETE; break; - case 'G': parser->method = HTTP_GET; break; - case 'H': parser->method = HTTP_HEAD; break; - case 'L': parser->method = HTTP_LOCK; /* or LINK */ break; - case 'M': parser->method = HTTP_MKCOL; /* or MOVE, MKACTIVITY, MERGE, M-SEARCH, MKCALENDAR */ break; - case 'N': parser->method = HTTP_NOTIFY; break; - case 'O': parser->method = HTTP_OPTIONS; break; - case 'P': parser->method = HTTP_POST; - /* or PROPFIND|PROPPATCH|PUT|PATCH|PURGE */ - break; - case 'R': parser->method = HTTP_REPORT; /* or REBIND */ break; - case 'S': parser->method = HTTP_SUBSCRIBE; /* or SEARCH */ break; - case 'T': parser->method = HTTP_TRACE; break; - case 'U': parser->method = HTTP_UNLOCK; /* or UNSUBSCRIBE, UNBIND, UNLINK */ break; - default: - SET_ERRNO(HPE_INVALID_METHOD); - goto error; - } - UPDATE_STATE(s_req_method); - - CALLBACK_NOTIFY(message_begin); - - break; - } - - case s_req_method: - { - const char *matcher; - if (UNLIKELY(ch == '\0')) { - SET_ERRNO(HPE_INVALID_METHOD); - goto error; - } - - matcher = method_strings[parser->method]; - if (ch == ' ' && matcher[parser->index] == '\0') { - UPDATE_STATE(s_req_spaces_before_url); - } else if (ch == matcher[parser->index]) { - ; /* nada */ - } else if (IS_ALPHA(ch)) { - - switch (parser->method << 16 | parser->index << 8 | ch) { -#define XX(meth, pos, ch, new_meth) \ - case (HTTP_##meth << 16 | pos << 8 | ch): \ - parser->method = HTTP_##new_meth; break; - - XX(POST, 1, 'U', PUT) - XX(POST, 1, 'A', PATCH) - XX(CONNECT, 1, 'H', CHECKOUT) - XX(CONNECT, 2, 'P', COPY) - XX(MKCOL, 1, 'O', MOVE) - XX(MKCOL, 1, 'E', MERGE) - XX(MKCOL, 2, 'A', MKACTIVITY) - XX(MKCOL, 3, 'A', MKCALENDAR) - XX(SUBSCRIBE, 1, 'E', SEARCH) - XX(REPORT, 2, 'B', REBIND) - XX(POST, 1, 'R', PROPFIND) - XX(PROPFIND, 4, 'P', PROPPATCH) - XX(PUT, 2, 'R', PURGE) - XX(LOCK, 1, 'I', LINK) - XX(UNLOCK, 2, 'S', UNSUBSCRIBE) - XX(UNLOCK, 2, 'B', UNBIND) - XX(UNLOCK, 3, 'I', UNLINK) -#undef XX - - default: - SET_ERRNO(HPE_INVALID_METHOD); - goto error; - } - } else if (ch == '-' && - parser->index == 1 && - parser->method == HTTP_MKCOL) { - parser->method = HTTP_MSEARCH; - } else { - SET_ERRNO(HPE_INVALID_METHOD); - goto error; - } - - ++parser->index; - break; - } - - case s_req_spaces_before_url: - { - if (ch == ' ') break; - - MARK(url); - if (parser->method == HTTP_CONNECT) { - UPDATE_STATE(s_req_server_start); - } - - UPDATE_STATE(parse_url_char(CURRENT_STATE(), ch)); - if (UNLIKELY(CURRENT_STATE() == s_dead)) { - SET_ERRNO(HPE_INVALID_URL); - goto error; - } - - break; - } - - case s_req_schema: - case s_req_schema_slash: - case s_req_schema_slash_slash: - case s_req_server_start: - { - switch (ch) { - /* No whitespace allowed here */ - case ' ': - case CR: - case LF: - SET_ERRNO(HPE_INVALID_URL); - goto error; - default: - UPDATE_STATE(parse_url_char(CURRENT_STATE(), ch)); - if (UNLIKELY(CURRENT_STATE() == s_dead)) { - SET_ERRNO(HPE_INVALID_URL); - goto error; - } - } - - break; - } - - case s_req_server: - case s_req_server_with_at: - case s_req_path: - case s_req_query_string_start: - case s_req_query_string: - case s_req_fragment_start: - case s_req_fragment: - { - switch (ch) { - case ' ': - UPDATE_STATE(s_req_http_start); - CALLBACK_DATA(url); - break; - case CR: - case LF: - parser->http_major = 0; - parser->http_minor = 9; - UPDATE_STATE((ch == CR) ? - s_req_line_almost_done : - s_header_field_start); - CALLBACK_DATA(url); - break; - default: - UPDATE_STATE(parse_url_char(CURRENT_STATE(), ch)); - if (UNLIKELY(CURRENT_STATE() == s_dead)) { - SET_ERRNO(HPE_INVALID_URL); - goto error; - } - } - break; - } - - case s_req_http_start: - switch (ch) { - case 'H': - UPDATE_STATE(s_req_http_H); - break; - case ' ': - break; - default: - SET_ERRNO(HPE_INVALID_CONSTANT); - goto error; - } - break; - - case s_req_http_H: - STRICT_CHECK(ch != 'T'); - UPDATE_STATE(s_req_http_HT); - break; - - case s_req_http_HT: - STRICT_CHECK(ch != 'T'); - UPDATE_STATE(s_req_http_HTT); - break; - - case s_req_http_HTT: - STRICT_CHECK(ch != 'P'); - UPDATE_STATE(s_req_http_HTTP); - break; - - case s_req_http_HTTP: - STRICT_CHECK(ch != '/'); - UPDATE_STATE(s_req_first_http_major); - break; - - /* first digit of major HTTP version */ - case s_req_first_http_major: - if (UNLIKELY(ch < '1' || ch > '9')) { - SET_ERRNO(HPE_INVALID_VERSION); - goto error; - } - - parser->http_major = ch - '0'; - UPDATE_STATE(s_req_http_major); - break; - - /* major HTTP version or dot */ - case s_req_http_major: - { - if (ch == '.') { - UPDATE_STATE(s_req_first_http_minor); - break; - } - - if (UNLIKELY(!IS_NUM(ch))) { - SET_ERRNO(HPE_INVALID_VERSION); - goto error; - } - - parser->http_major *= 10; - parser->http_major += ch - '0'; - - if (UNLIKELY(parser->http_major > 999)) { - SET_ERRNO(HPE_INVALID_VERSION); - goto error; - } - - break; - } - - /* first digit of minor HTTP version */ - case s_req_first_http_minor: - if (UNLIKELY(!IS_NUM(ch))) { - SET_ERRNO(HPE_INVALID_VERSION); - goto error; - } - - parser->http_minor = ch - '0'; - UPDATE_STATE(s_req_http_minor); - break; - - /* minor HTTP version or end of request line */ - case s_req_http_minor: - { - if (ch == CR) { - UPDATE_STATE(s_req_line_almost_done); - break; - } - - if (ch == LF) { - UPDATE_STATE(s_header_field_start); - break; - } - - /* XXX allow spaces after digit? */ - - if (UNLIKELY(!IS_NUM(ch))) { - SET_ERRNO(HPE_INVALID_VERSION); - goto error; - } - - parser->http_minor *= 10; - parser->http_minor += ch - '0'; - - if (UNLIKELY(parser->http_minor > 999)) { - SET_ERRNO(HPE_INVALID_VERSION); - goto error; - } - - break; - } - - /* end of request line */ - case s_req_line_almost_done: - { - if (UNLIKELY(ch != LF)) { - SET_ERRNO(HPE_LF_EXPECTED); - goto error; - } - - UPDATE_STATE(s_header_field_start); - break; - } - - case s_header_field_start: - { - if (ch == CR) { - UPDATE_STATE(s_headers_almost_done); - break; - } - - if (ch == LF) { - /* they might be just sending \n instead of \r\n so this would be - * the second \n to denote the end of headers*/ - UPDATE_STATE(s_headers_almost_done); - REEXECUTE(); - } - - c = TOKEN(ch); - - if (UNLIKELY(!c)) { - SET_ERRNO(HPE_INVALID_HEADER_TOKEN); - goto error; - } - - MARK(header_field); - - parser->index = 0; - UPDATE_STATE(s_header_field); - - switch (c) { - case 'c': - parser->header_state = h_C; - break; - - case 'p': - parser->header_state = h_matching_proxy_connection; - break; - - case 't': - parser->header_state = h_matching_transfer_encoding; - break; - - case 'u': - parser->header_state = h_matching_upgrade; - break; - - default: - parser->header_state = h_general; - break; - } - break; - } - - case s_header_field: - { - const char* start = p; - for (; p != data + len; p++) { - ch = *p; - c = TOKEN(ch); - - if (!c) - break; - - switch (parser->header_state) { - case h_general: - break; - - case h_C: - parser->index++; - parser->header_state = (c == 'o' ? h_CO : h_general); - break; - - case h_CO: - parser->index++; - parser->header_state = (c == 'n' ? h_CON : h_general); - break; - - case h_CON: - parser->index++; - switch (c) { - case 'n': - parser->header_state = h_matching_connection; - break; - case 't': - parser->header_state = h_matching_content_length; - break; - default: - parser->header_state = h_general; - break; - } - break; - - /* connection */ - - case h_matching_connection: - parser->index++; - if (parser->index > sizeof(CONNECTION)-1 - || c != CONNECTION[parser->index]) { - parser->header_state = h_general; - } else if (parser->index == sizeof(CONNECTION)-2) { - parser->header_state = h_connection; - } - break; - - /* proxy-connection */ - - case h_matching_proxy_connection: - parser->index++; - if (parser->index > sizeof(PROXY_CONNECTION)-1 - || c != PROXY_CONNECTION[parser->index]) { - parser->header_state = h_general; - } else if (parser->index == sizeof(PROXY_CONNECTION)-2) { - parser->header_state = h_connection; - } - break; - - /* content-length */ - - case h_matching_content_length: - parser->index++; - if (parser->index > sizeof(CONTENT_LENGTH)-1 - || c != CONTENT_LENGTH[parser->index]) { - parser->header_state = h_general; - } else if (parser->index == sizeof(CONTENT_LENGTH)-2) { - if (parser->flags & F_CONTENTLENGTH) { - SET_ERRNO(HPE_UNEXPECTED_CONTENT_LENGTH); - goto error; - } - parser->header_state = h_content_length; - parser->flags |= F_CONTENTLENGTH; - } - break; - - /* transfer-encoding */ - - case h_matching_transfer_encoding: - parser->index++; - if (parser->index > sizeof(TRANSFER_ENCODING)-1 - || c != TRANSFER_ENCODING[parser->index]) { - parser->header_state = h_general; - } else if (parser->index == sizeof(TRANSFER_ENCODING)-2) { - parser->header_state = h_transfer_encoding; - } - break; - - /* upgrade */ - - case h_matching_upgrade: - parser->index++; - if (parser->index > sizeof(UPGRADE)-1 - || c != UPGRADE[parser->index]) { - parser->header_state = h_general; - } else if (parser->index == sizeof(UPGRADE)-2) { - parser->header_state = h_upgrade; - } - break; - - case h_connection: - case h_content_length: - case h_transfer_encoding: - case h_upgrade: - if (ch != ' ') parser->header_state = h_general; - break; - - default: - assert(0 && "Unknown header_state"); - break; - } - } - - COUNT_HEADER_SIZE(p - start); - - if (p == data + len) { - --p; - break; - } - - if (ch == ':') { - UPDATE_STATE(s_header_value_discard_ws); - CALLBACK_DATA(header_field); - break; - } - - SET_ERRNO(HPE_INVALID_HEADER_TOKEN); - goto error; - } - - case s_header_value_discard_ws: - if (ch == ' ' || ch == '\t') break; - - if (ch == CR) { - UPDATE_STATE(s_header_value_discard_ws_almost_done); - break; - } - - if (ch == LF) { - UPDATE_STATE(s_header_value_discard_lws); - break; - } - - /* FALLTHROUGH */ - - case s_header_value_start: - { - MARK(header_value); - - UPDATE_STATE(s_header_value); - parser->index = 0; - - c = LOWER(ch); - - switch (parser->header_state) { - case h_upgrade: - parser->flags |= F_UPGRADE; - parser->header_state = h_general; - break; - - case h_transfer_encoding: - /* looking for 'Transfer-Encoding: chunked' */ - if ('c' == c) { - parser->header_state = h_matching_transfer_encoding_chunked; - } else { - parser->header_state = h_general; - } - break; - - case h_content_length: - if (UNLIKELY(!IS_NUM(ch))) { - SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); - goto error; - } - - parser->content_length = ch - '0'; - break; - - case h_connection: - /* looking for 'Connection: keep-alive' */ - if (c == 'k') { - parser->header_state = h_matching_connection_keep_alive; - /* looking for 'Connection: close' */ - } else if (c == 'c') { - parser->header_state = h_matching_connection_close; - } else if (c == 'u') { - parser->header_state = h_matching_connection_upgrade; - } else { - parser->header_state = h_matching_connection_token; - } - break; - - /* Multi-value `Connection` header */ - case h_matching_connection_token_start: - break; - - default: - parser->header_state = h_general; - break; - } - break; - } - - case s_header_value: - { - const char* start = p; - enum header_states h_state = (enum header_states) parser->header_state; - for (; p != data + len; p++) { - ch = *p; - if (ch == CR) { - UPDATE_STATE(s_header_almost_done); - parser->header_state = h_state; - CALLBACK_DATA(header_value); - break; - } - - if (ch == LF) { - UPDATE_STATE(s_header_almost_done); - COUNT_HEADER_SIZE(p - start); - parser->header_state = h_state; - CALLBACK_DATA_NOADVANCE(header_value); - REEXECUTE(); - } - - if (!lenient && !IS_HEADER_CHAR(ch)) { - SET_ERRNO(HPE_INVALID_HEADER_TOKEN); - goto error; - } - - c = LOWER(ch); - - switch (h_state) { - case h_general: - { - const char* p_cr; - const char* p_lf; - size_t limit = data + len - p; - - limit = MIN(limit, HTTP_MAX_HEADER_SIZE); - - p_cr = (const char*) memchr(p, CR, limit); - p_lf = (const char*) memchr(p, LF, limit); - if (p_cr != NULL) { - if (p_lf != NULL && p_cr >= p_lf) - p = p_lf; - else - p = p_cr; - } else if (UNLIKELY(p_lf != NULL)) { - p = p_lf; - } else { - p = data + len; - } - --p; - - break; - } - - case h_connection: - case h_transfer_encoding: - assert(0 && "Shouldn't get here."); - break; - - case h_content_length: - { - uint64_t t; - - if (ch == ' ') break; - - if (UNLIKELY(!IS_NUM(ch))) { - SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); - parser->header_state = h_state; - goto error; - } - - t = parser->content_length; - t *= 10; - t += ch - '0'; - - /* Overflow? Test against a conservative limit for simplicity. */ - if (UNLIKELY((ULLONG_MAX - 10) / 10 < parser->content_length)) { - SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); - parser->header_state = h_state; - goto error; - } - - parser->content_length = t; - break; - } - - /* Transfer-Encoding: chunked */ - case h_matching_transfer_encoding_chunked: - parser->index++; - if (parser->index > sizeof(CHUNKED)-1 - || c != CHUNKED[parser->index]) { - h_state = h_general; - } else if (parser->index == sizeof(CHUNKED)-2) { - h_state = h_transfer_encoding_chunked; - } - break; - - case h_matching_connection_token_start: - /* looking for 'Connection: keep-alive' */ - if (c == 'k') { - h_state = h_matching_connection_keep_alive; - /* looking for 'Connection: close' */ - } else if (c == 'c') { - h_state = h_matching_connection_close; - } else if (c == 'u') { - h_state = h_matching_connection_upgrade; - } else if (STRICT_TOKEN(c)) { - h_state = h_matching_connection_token; - } else if (c == ' ' || c == '\t') { - /* Skip lws */ - } else { - h_state = h_general; - } - break; - - /* looking for 'Connection: keep-alive' */ - case h_matching_connection_keep_alive: - parser->index++; - if (parser->index > sizeof(KEEP_ALIVE)-1 - || c != KEEP_ALIVE[parser->index]) { - h_state = h_matching_connection_token; - } else if (parser->index == sizeof(KEEP_ALIVE)-2) { - h_state = h_connection_keep_alive; - } - break; - - /* looking for 'Connection: close' */ - case h_matching_connection_close: - parser->index++; - if (parser->index > sizeof(CLOSE)-1 || c != CLOSE[parser->index]) { - h_state = h_matching_connection_token; - } else if (parser->index == sizeof(CLOSE)-2) { - h_state = h_connection_close; - } - break; - - /* looking for 'Connection: upgrade' */ - case h_matching_connection_upgrade: - parser->index++; - if (parser->index > sizeof(UPGRADE) - 1 || - c != UPGRADE[parser->index]) { - h_state = h_matching_connection_token; - } else if (parser->index == sizeof(UPGRADE)-2) { - h_state = h_connection_upgrade; - } - break; - - case h_matching_connection_token: - if (ch == ',') { - h_state = h_matching_connection_token_start; - parser->index = 0; - } - break; - - case h_transfer_encoding_chunked: - if (ch != ' ') h_state = h_general; - break; - - case h_connection_keep_alive: - case h_connection_close: - case h_connection_upgrade: - if (ch == ',') { - if (h_state == h_connection_keep_alive) { - parser->flags |= F_CONNECTION_KEEP_ALIVE; - } else if (h_state == h_connection_close) { - parser->flags |= F_CONNECTION_CLOSE; - } else if (h_state == h_connection_upgrade) { - parser->flags |= F_CONNECTION_UPGRADE; - } - h_state = h_matching_connection_token_start; - parser->index = 0; - } else if (ch != ' ') { - h_state = h_matching_connection_token; - } - break; - - default: - UPDATE_STATE(s_header_value); - h_state = h_general; - break; - } - } - parser->header_state = h_state; - - COUNT_HEADER_SIZE(p - start); - - if (p == data + len) - --p; - break; - } - - case s_header_almost_done: - { - if (UNLIKELY(ch != LF)) { - SET_ERRNO(HPE_LF_EXPECTED); - goto error; - } - - UPDATE_STATE(s_header_value_lws); - break; - } - - case s_header_value_lws: - { - if (ch == ' ' || ch == '\t') { - UPDATE_STATE(s_header_value_start); - REEXECUTE(); - } - - /* finished the header */ - switch (parser->header_state) { - case h_connection_keep_alive: - parser->flags |= F_CONNECTION_KEEP_ALIVE; - break; - case h_connection_close: - parser->flags |= F_CONNECTION_CLOSE; - break; - case h_transfer_encoding_chunked: - parser->flags |= F_CHUNKED; - break; - case h_connection_upgrade: - parser->flags |= F_CONNECTION_UPGRADE; - break; - default: - break; - } - - UPDATE_STATE(s_header_field_start); - REEXECUTE(); - } - - case s_header_value_discard_ws_almost_done: - { - STRICT_CHECK(ch != LF); - UPDATE_STATE(s_header_value_discard_lws); - break; - } - - case s_header_value_discard_lws: - { - if (ch == ' ' || ch == '\t') { - UPDATE_STATE(s_header_value_discard_ws); - break; - } else { - switch (parser->header_state) { - case h_connection_keep_alive: - parser->flags |= F_CONNECTION_KEEP_ALIVE; - break; - case h_connection_close: - parser->flags |= F_CONNECTION_CLOSE; - break; - case h_connection_upgrade: - parser->flags |= F_CONNECTION_UPGRADE; - break; - case h_transfer_encoding_chunked: - parser->flags |= F_CHUNKED; - break; - default: - break; - } - - /* header value was empty */ - MARK(header_value); - UPDATE_STATE(s_header_field_start); - CALLBACK_DATA_NOADVANCE(header_value); - REEXECUTE(); - } - } - - case s_headers_almost_done: - { - STRICT_CHECK(ch != LF); - - if (parser->flags & F_TRAILING) { - /* End of a chunked request */ - UPDATE_STATE(s_message_done); - CALLBACK_NOTIFY_NOADVANCE(chunk_complete); - REEXECUTE(); - } - - /* Cannot use chunked encoding and a content-length header together - per the HTTP specification. */ - if ((parser->flags & F_CHUNKED) && - (parser->flags & F_CONTENTLENGTH)) { - SET_ERRNO(HPE_UNEXPECTED_CONTENT_LENGTH); - goto error; - } - - UPDATE_STATE(s_headers_done); - - /* Set this here so that on_headers_complete() callbacks can see it */ - parser->upgrade = - ((parser->flags & (F_UPGRADE | F_CONNECTION_UPGRADE)) == - (F_UPGRADE | F_CONNECTION_UPGRADE) || - parser->method == HTTP_CONNECT); - - /* Here we call the headers_complete callback. This is somewhat - * different than other callbacks because if the user returns 1, we - * will interpret that as saying that this message has no body. This - * is needed for the annoying case of recieving a response to a HEAD - * request. - * - * We'd like to use CALLBACK_NOTIFY_NOADVANCE() here but we cannot, so - * we have to simulate it by handling a change in errno below. - */ - if (settings->on_headers_complete) { - switch (settings->on_headers_complete(parser)) { - case 0: - break; - - case 1: - parser->flags |= F_SKIPBODY; - break; - - default: - SET_ERRNO(HPE_CB_headers_complete); - RETURN(p - data); /* Error */ - } - } - - if (HTTP_PARSER_ERRNO(parser) != HPE_OK) { - RETURN(p - data); - } - - REEXECUTE(); - } - - case s_headers_done: - { - int hasBody; - STRICT_CHECK(ch != LF); - - parser->nread = 0; - - hasBody = parser->flags & F_CHUNKED || - (parser->content_length > 0 && parser->content_length != ULLONG_MAX); - if (parser->upgrade && (parser->method == HTTP_CONNECT || - (parser->flags & F_SKIPBODY) || !hasBody)) { - /* Exit, the rest of the message is in a different protocol. */ - UPDATE_STATE(NEW_MESSAGE()); - CALLBACK_NOTIFY(message_complete); - RETURN((p - data) + 1); - } - - if (parser->flags & F_SKIPBODY) { - UPDATE_STATE(NEW_MESSAGE()); - CALLBACK_NOTIFY(message_complete); - } else if (parser->flags & F_CHUNKED) { - /* chunked encoding - ignore Content-Length header */ - UPDATE_STATE(s_chunk_size_start); - } else { - if (parser->content_length == 0) { - /* Content-Length header given but zero: Content-Length: 0\r\n */ - UPDATE_STATE(NEW_MESSAGE()); - CALLBACK_NOTIFY(message_complete); - } else if (parser->content_length != ULLONG_MAX) { - /* Content-Length header given and non-zero */ - UPDATE_STATE(s_body_identity); - } else { - if (!http_message_needs_eof(parser)) { - /* Assume content-length 0 - read the next */ - UPDATE_STATE(NEW_MESSAGE()); - CALLBACK_NOTIFY(message_complete); - } else { - /* Read body until EOF */ - UPDATE_STATE(s_body_identity_eof); - } - } - } - - break; - } - - case s_body_identity: - { - uint64_t to_read = MIN(parser->content_length, - (uint64_t) ((data + len) - p)); - - assert(parser->content_length != 0 - && parser->content_length != ULLONG_MAX); - - /* The difference between advancing content_length and p is because - * the latter will automaticaly advance on the next loop iteration. - * Further, if content_length ends up at 0, we want to see the last - * byte again for our message complete callback. - */ - MARK(body); - parser->content_length -= to_read; - p += to_read - 1; - - if (parser->content_length == 0) { - UPDATE_STATE(s_message_done); - - /* Mimic CALLBACK_DATA_NOADVANCE() but with one extra byte. - * - * The alternative to doing this is to wait for the next byte to - * trigger the data callback, just as in every other case. The - * problem with this is that this makes it difficult for the test - * harness to distinguish between complete-on-EOF and - * complete-on-length. It's not clear that this distinction is - * important for applications, but let's keep it for now. - */ - CALLBACK_DATA_(body, p - body_mark + 1, p - data); - REEXECUTE(); - } - - break; - } - - /* read until EOF */ - case s_body_identity_eof: - MARK(body); - p = data + len - 1; - - break; - - case s_message_done: - UPDATE_STATE(NEW_MESSAGE()); - CALLBACK_NOTIFY(message_complete); - if (parser->upgrade) { - /* Exit, the rest of the message is in a different protocol. */ - RETURN((p - data) + 1); - } - break; - - case s_chunk_size_start: - { - assert(parser->nread == 1); - assert(parser->flags & F_CHUNKED); - - unhex_val = unhex[(unsigned char)ch]; - if (UNLIKELY(unhex_val == -1)) { - SET_ERRNO(HPE_INVALID_CHUNK_SIZE); - goto error; - } - - parser->content_length = unhex_val; - UPDATE_STATE(s_chunk_size); - break; - } - - case s_chunk_size: - { - uint64_t t; - - assert(parser->flags & F_CHUNKED); - - if (ch == CR) { - UPDATE_STATE(s_chunk_size_almost_done); - break; - } - - unhex_val = unhex[(unsigned char)ch]; - - if (unhex_val == -1) { - if (ch == ';' || ch == ' ') { - UPDATE_STATE(s_chunk_parameters); - break; - } - - SET_ERRNO(HPE_INVALID_CHUNK_SIZE); - goto error; - } - - t = parser->content_length; - t *= 16; - t += unhex_val; - - /* Overflow? Test against a conservative limit for simplicity. */ - if (UNLIKELY((ULLONG_MAX - 16) / 16 < parser->content_length)) { - SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); - goto error; - } - - parser->content_length = t; - break; - } - - case s_chunk_parameters: - { - assert(parser->flags & F_CHUNKED); - /* just ignore this shit. TODO check for overflow */ - if (ch == CR) { - UPDATE_STATE(s_chunk_size_almost_done); - break; - } - break; - } - - case s_chunk_size_almost_done: - { - assert(parser->flags & F_CHUNKED); - STRICT_CHECK(ch != LF); - - parser->nread = 0; - - if (parser->content_length == 0) { - parser->flags |= F_TRAILING; - UPDATE_STATE(s_header_field_start); - } else { - UPDATE_STATE(s_chunk_data); - } - CALLBACK_NOTIFY(chunk_header); - break; - } - - case s_chunk_data: - { - uint64_t to_read = MIN(parser->content_length, - (uint64_t) ((data + len) - p)); - - assert(parser->flags & F_CHUNKED); - assert(parser->content_length != 0 - && parser->content_length != ULLONG_MAX); - - /* See the explanation in s_body_identity for why the content - * length and data pointers are managed this way. - */ - MARK(body); - parser->content_length -= to_read; - p += to_read - 1; - - if (parser->content_length == 0) { - UPDATE_STATE(s_chunk_data_almost_done); - } - - break; - } - - case s_chunk_data_almost_done: - assert(parser->flags & F_CHUNKED); - assert(parser->content_length == 0); - STRICT_CHECK(ch != CR); - UPDATE_STATE(s_chunk_data_done); - CALLBACK_DATA(body); - break; - - case s_chunk_data_done: - assert(parser->flags & F_CHUNKED); - STRICT_CHECK(ch != LF); - parser->nread = 0; - UPDATE_STATE(s_chunk_size_start); - CALLBACK_NOTIFY(chunk_complete); - break; - - default: - assert(0 && "unhandled state"); - SET_ERRNO(HPE_INVALID_INTERNAL_STATE); - goto error; - } - } - - /* Run callbacks for any marks that we have leftover after we ran our of - * bytes. There should be at most one of these set, so it's OK to invoke - * them in series (unset marks will not result in callbacks). - * - * We use the NOADVANCE() variety of callbacks here because 'p' has already - * overflowed 'data' and this allows us to correct for the off-by-one that - * we'd otherwise have (since CALLBACK_DATA() is meant to be run with a 'p' - * value that's in-bounds). - */ - - assert(((header_field_mark ? 1 : 0) + - (header_value_mark ? 1 : 0) + - (url_mark ? 1 : 0) + - (body_mark ? 1 : 0) + - (status_mark ? 1 : 0)) <= 1); - - CALLBACK_DATA_NOADVANCE(header_field); - CALLBACK_DATA_NOADVANCE(header_value); - CALLBACK_DATA_NOADVANCE(url); - CALLBACK_DATA_NOADVANCE(body); - CALLBACK_DATA_NOADVANCE(status); - - RETURN(len); - -error: - if (HTTP_PARSER_ERRNO(parser) == HPE_OK) { - SET_ERRNO(HPE_UNKNOWN); - } - - RETURN(p - data); -} - - -/* Does the parser need to see an EOF to find the end of the message? */ -int -http_message_needs_eof (const http_parser *parser) -{ - if (parser->type == HTTP_REQUEST) { - return 0; - } - - /* See RFC 2616 section 4.4 */ - if (parser->status_code / 100 == 1 || /* 1xx e.g. Continue */ - parser->status_code == 204 || /* No Content */ - parser->status_code == 304 || /* Not Modified */ - parser->flags & F_SKIPBODY) { /* response to a HEAD request */ - return 0; - } - - if ((parser->flags & F_CHUNKED) || parser->content_length != ULLONG_MAX) { - return 0; - } - - return 1; -} - - -int -http_should_keep_alive (const http_parser *parser) -{ - if (parser->http_major > 0 && parser->http_minor > 0) { - /* HTTP/1.1 */ - if (parser->flags & F_CONNECTION_CLOSE) { - return 0; - } - } else { - /* HTTP/1.0 or earlier */ - if (!(parser->flags & F_CONNECTION_KEEP_ALIVE)) { - return 0; - } - } - - return !http_message_needs_eof(parser); -} - - -const char * -http_method_str (enum http_method m) -{ - return ELEM_AT(method_strings, m, ""); -} - - -void -http_parser_init (http_parser *parser, enum http_parser_type t) -{ - void *data = parser->data; /* preserve application data */ - memset(parser, 0, sizeof(*parser)); - parser->data = data; - parser->type = t; - parser->state = (t == HTTP_REQUEST ? s_start_req : (t == HTTP_RESPONSE ? s_start_res : s_start_req_or_res)); - parser->http_errno = HPE_OK; -} - -void -http_parser_settings_init(http_parser_settings *settings) -{ - memset(settings, 0, sizeof(*settings)); -} - -const char * -http_errno_name(enum http_errno err) { - assert(((size_t) err) < ARRAY_SIZE(http_strerror_tab)); - return http_strerror_tab[err].name; -} - -const char * -http_errno_description(enum http_errno err) { - assert(((size_t) err) < ARRAY_SIZE(http_strerror_tab)); - return http_strerror_tab[err].description; -} - -static enum http_host_state -http_parse_host_char(enum http_host_state s, const char ch) { - switch(s) { - case s_http_userinfo: - case s_http_userinfo_start: - if (ch == '@') { - return s_http_host_start; - } - - if (IS_USERINFO_CHAR(ch)) { - return s_http_userinfo; - } - break; - - case s_http_host_start: - if (ch == '[') { - return s_http_host_v6_start; - } - - if (IS_HOST_CHAR(ch)) { - return s_http_host; - } - - break; - - case s_http_host: - if (IS_HOST_CHAR(ch)) { - return s_http_host; - } - - /* FALLTHROUGH */ - case s_http_host_v6_end: - if (ch == ':') { - return s_http_host_port_start; - } - - break; - - case s_http_host_v6: - if (ch == ']') { - return s_http_host_v6_end; - } - - /* FALLTHROUGH */ - case s_http_host_v6_start: - if (IS_HEX(ch) || ch == ':' || ch == '.') { - return s_http_host_v6; - } - - if (s == s_http_host_v6 && ch == '%') { - return s_http_host_v6_zone_start; - } - break; - - case s_http_host_v6_zone: - if (ch == ']') { - return s_http_host_v6_end; - } - - /* FALLTHROUGH */ - case s_http_host_v6_zone_start: - /* RFC 6874 Zone ID consists of 1*( unreserved / pct-encoded) */ - if (IS_ALPHANUM(ch) || ch == '%' || ch == '.' || ch == '-' || ch == '_' || - ch == '~') { - return s_http_host_v6_zone; - } - break; - - case s_http_host_port: - case s_http_host_port_start: - if (IS_NUM(ch)) { - return s_http_host_port; - } - - break; - - default: - break; - } - return s_http_host_dead; -} - -static int -http_parse_host(const char * buf, struct http_parser_url *u, int found_at) { - assert(u->field_set & (1 << UF_HOST)); - enum http_host_state s; - - const char *p; - size_t buflen = u->field_data[UF_HOST].off + u->field_data[UF_HOST].len; - - u->field_data[UF_HOST].len = 0; - - s = found_at ? s_http_userinfo_start : s_http_host_start; - - for (p = buf + u->field_data[UF_HOST].off; p < buf + buflen; p++) { - enum http_host_state new_s = http_parse_host_char(s, *p); - - if (new_s == s_http_host_dead) { - return 1; - } - - switch(new_s) { - case s_http_host: - if (s != s_http_host) { - u->field_data[UF_HOST].off = p - buf; - } - u->field_data[UF_HOST].len++; - break; - - case s_http_host_v6: - if (s != s_http_host_v6) { - u->field_data[UF_HOST].off = p - buf; - } - u->field_data[UF_HOST].len++; - break; - - case s_http_host_v6_zone_start: - case s_http_host_v6_zone: - u->field_data[UF_HOST].len++; - break; - - case s_http_host_port: - if (s != s_http_host_port) { - u->field_data[UF_PORT].off = p - buf; - u->field_data[UF_PORT].len = 0; - u->field_set |= (1 << UF_PORT); - } - u->field_data[UF_PORT].len++; - break; - - case s_http_userinfo: - if (s != s_http_userinfo) { - u->field_data[UF_USERINFO].off = p - buf ; - u->field_data[UF_USERINFO].len = 0; - u->field_set |= (1 << UF_USERINFO); - } - u->field_data[UF_USERINFO].len++; - break; - - default: - break; - } - s = new_s; - } - - /* Make sure we don't end somewhere unexpected */ - switch (s) { - case s_http_host_start: - case s_http_host_v6_start: - case s_http_host_v6: - case s_http_host_v6_zone_start: - case s_http_host_v6_zone: - case s_http_host_port_start: - case s_http_userinfo: - case s_http_userinfo_start: - return 1; - default: - break; - } - - return 0; -} - -void -http_parser_url_init(struct http_parser_url *u) { - memset(u, 0, sizeof(*u)); -} - -int -http_parser_parse_url(const char *buf, size_t buflen, int is_connect, - struct http_parser_url *u) -{ - enum state s; - const char *p; - enum http_parser_url_fields uf, old_uf; - int found_at = 0; - - u->port = u->field_set = 0; - s = is_connect ? s_req_server_start : s_req_spaces_before_url; - old_uf = UF_MAX; - - for (p = buf; p < buf + buflen; p++) { - s = parse_url_char(s, *p); - - /* Figure out the next field that we're operating on */ - switch (s) { - case s_dead: - return 1; - - /* Skip delimeters */ - case s_req_schema_slash: - case s_req_schema_slash_slash: - case s_req_server_start: - case s_req_query_string_start: - case s_req_fragment_start: - continue; - - case s_req_schema: - uf = UF_SCHEMA; - break; - - case s_req_server_with_at: - found_at = 1; - - /* FALLTROUGH */ - case s_req_server: - uf = UF_HOST; - break; - - case s_req_path: - uf = UF_PATH; - break; - - case s_req_query_string: - uf = UF_QUERY; - break; - - case s_req_fragment: - uf = UF_FRAGMENT; - break; - - default: - assert(!"Unexpected state"); - return 1; - } - - /* Nothing's changed; soldier on */ - if (uf == old_uf) { - u->field_data[uf].len++; - continue; - } - - u->field_data[uf].off = p - buf; - u->field_data[uf].len = 1; - - u->field_set |= (1 << uf); - old_uf = uf; - } - - /* host must be present if there is a schema */ - /* parsing http:///toto will fail */ - if ((u->field_set & (1 << UF_SCHEMA)) && - (u->field_set & (1 << UF_HOST)) == 0) { - return 1; - } - - if (u->field_set & (1 << UF_HOST)) { - if (http_parse_host(buf, u, found_at) != 0) { - return 1; - } - } - - /* CONNECT requests can only contain "hostname:port" */ - if (is_connect && u->field_set != ((1 << UF_HOST)|(1 << UF_PORT))) { - return 1; - } - - if (u->field_set & (1 << UF_PORT)) { - /* Don't bother with endp; we've already validated the string */ - unsigned long v = strtoul(buf + u->field_data[UF_PORT].off, NULL, 10); - - /* Ports have a max value of 2^16 */ - if (v > 0xffff) { - return 1; - } - - u->port = (uint16_t) v; - } - - return 0; -} - -void -http_parser_pause(http_parser *parser, int paused) { - /* Users should only be pausing/unpausing a parser that is not in an error - * state. In non-debug builds, there's not much that we can do about this - * other than ignore it. - */ - if (HTTP_PARSER_ERRNO(parser) == HPE_OK || - HTTP_PARSER_ERRNO(parser) == HPE_PAUSED) { - SET_ERRNO((paused) ? HPE_PAUSED : HPE_OK); - } else { - assert(0 && "Attempting to pause parser in error state"); - } -} - -int -http_body_is_final(const struct http_parser *parser) { - return parser->state == s_message_done; -} - -unsigned long -http_parser_version(void) { - return HTTP_PARSER_VERSION_MAJOR * 0x10000 | - HTTP_PARSER_VERSION_MINOR * 0x00100 | - HTTP_PARSER_VERSION_PATCH * 0x00001; -} diff --git a/vendor/http_parser/http_parser.gyp b/vendor/http_parser/http_parser.gyp deleted file mode 100644 index ef34ecaea..000000000 --- a/vendor/http_parser/http_parser.gyp +++ /dev/null @@ -1,111 +0,0 @@ -# This file is used with the GYP meta build system. -# http://code.google.com/p/gyp/ -# To build try this: -# svn co http://gyp.googlecode.com/svn/trunk gyp -# ./gyp/gyp -f make --depth=`pwd` http_parser.gyp -# ./out/Debug/test -{ - 'target_defaults': { - 'default_configuration': 'Debug', - 'configurations': { - # TODO: hoist these out and put them somewhere common, because - # RuntimeLibrary MUST MATCH across the entire project - 'Debug': { - 'defines': [ 'DEBUG', '_DEBUG' ], - 'cflags': [ '-Wall', '-Wextra', '-O0', '-g', '-ftrapv' ], - 'msvs_settings': { - 'VCCLCompilerTool': { - 'RuntimeLibrary': 1, # static debug - }, - }, - }, - 'Release': { - 'defines': [ 'NDEBUG' ], - 'cflags': [ '-Wall', '-Wextra', '-O3' ], - 'msvs_settings': { - 'VCCLCompilerTool': { - 'RuntimeLibrary': 0, # static release - }, - }, - } - }, - 'msvs_settings': { - 'VCCLCompilerTool': { - }, - 'VCLibrarianTool': { - }, - 'VCLinkerTool': { - 'GenerateDebugInformation': 'true', - }, - }, - 'conditions': [ - ['OS == "win"', { - 'defines': [ - 'WIN32' - ], - }] - ], - }, - - 'targets': [ - { - 'target_name': 'http_parser', - 'type': 'static_library', - 'include_dirs': [ '.' ], - 'direct_dependent_settings': { - 'defines': [ 'HTTP_PARSER_STRICT=0' ], - 'include_dirs': [ '.' ], - }, - 'defines': [ 'HTTP_PARSER_STRICT=0' ], - 'sources': [ './http_parser.c', ], - 'conditions': [ - ['OS=="win"', { - 'msvs_settings': { - 'VCCLCompilerTool': { - # Compile as C++. http_parser.c is actually C99, but C++ is - # close enough in this case. - 'CompileAs': 2, - }, - }, - }] - ], - }, - - { - 'target_name': 'http_parser_strict', - 'type': 'static_library', - 'include_dirs': [ '.' ], - 'direct_dependent_settings': { - 'defines': [ 'HTTP_PARSER_STRICT=1' ], - 'include_dirs': [ '.' ], - }, - 'defines': [ 'HTTP_PARSER_STRICT=1' ], - 'sources': [ './http_parser.c', ], - 'conditions': [ - ['OS=="win"', { - 'msvs_settings': { - 'VCCLCompilerTool': { - # Compile as C++. http_parser.c is actually C99, but C++ is - # close enough in this case. - 'CompileAs': 2, - }, - }, - }] - ], - }, - - { - 'target_name': 'test-nonstrict', - 'type': 'executable', - 'dependencies': [ 'http_parser' ], - 'sources': [ 'test.c' ] - }, - - { - 'target_name': 'test-strict', - 'type': 'executable', - 'dependencies': [ 'http_parser_strict' ], - 'sources': [ 'test.c' ] - } - ] -} diff --git a/vendor/http_parser/http_parser.h b/vendor/http_parser/http_parser.h deleted file mode 100644 index 0cee4cc85..000000000 --- a/vendor/http_parser/http_parser.h +++ /dev/null @@ -1,357 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ -#ifndef http_parser_h -#define http_parser_h -#ifdef __cplusplus -extern "C" { -#endif - -/* Also update SONAME in the Makefile whenever you change these. */ -#define HTTP_PARSER_VERSION_MAJOR 2 -#define HTTP_PARSER_VERSION_MINOR 6 -#define HTTP_PARSER_VERSION_PATCH 2 - -#include -#if defined(_WIN32) && !defined(__MINGW32__) && \ - (!defined(_MSC_VER) || _MSC_VER<1600) && !defined(__WINE__) -#include -#include -typedef __int8 int8_t; -typedef unsigned __int8 uint8_t; -typedef __int16 int16_t; -typedef unsigned __int16 uint16_t; -typedef __int32 int32_t; -typedef unsigned __int32 uint32_t; -typedef __int64 int64_t; -typedef unsigned __int64 uint64_t; -#else -#include -#endif - -/* Compile with -DHTTP_PARSER_STRICT=0 to make less checks, but run - * faster - */ -#ifndef HTTP_PARSER_STRICT -# define HTTP_PARSER_STRICT 1 -#endif - -/* Maximium header size allowed. If the macro is not defined - * before including this header then the default is used. To - * change the maximum header size, define the macro in the build - * environment (e.g. -DHTTP_MAX_HEADER_SIZE=). To remove - * the effective limit on the size of the header, define the macro - * to a very large number (e.g. -DHTTP_MAX_HEADER_SIZE=0x7fffffff) - */ -#ifndef HTTP_MAX_HEADER_SIZE -# define HTTP_MAX_HEADER_SIZE (80*1024) -#endif - -typedef struct http_parser http_parser; -typedef struct http_parser_settings http_parser_settings; - - -/* Callbacks should return non-zero to indicate an error. The parser will - * then halt execution. - * - * The one exception is on_headers_complete. In a HTTP_RESPONSE parser - * returning '1' from on_headers_complete will tell the parser that it - * should not expect a body. This is used when receiving a response to a - * HEAD request which may contain 'Content-Length' or 'Transfer-Encoding: - * chunked' headers that indicate the presence of a body. - * - * http_data_cb does not return data chunks. It will be called arbitrarily - * many times for each string. E.G. you might get 10 callbacks for "on_url" - * each providing just a few characters more data. - */ -typedef int (*http_data_cb) (http_parser*, const char *at, size_t length); -typedef int (*http_cb) (http_parser*); - - -/* Request Methods */ -#define HTTP_METHOD_MAP(XX) \ - XX(0, DELETE, DELETE) \ - XX(1, GET, GET) \ - XX(2, HEAD, HEAD) \ - XX(3, POST, POST) \ - XX(4, PUT, PUT) \ - /* pathological */ \ - XX(5, CONNECT, CONNECT) \ - XX(6, OPTIONS, OPTIONS) \ - XX(7, TRACE, TRACE) \ - /* WebDAV */ \ - XX(8, COPY, COPY) \ - XX(9, LOCK, LOCK) \ - XX(10, MKCOL, MKCOL) \ - XX(11, MOVE, MOVE) \ - XX(12, PROPFIND, PROPFIND) \ - XX(13, PROPPATCH, PROPPATCH) \ - XX(14, SEARCH, SEARCH) \ - XX(15, UNLOCK, UNLOCK) \ - XX(16, BIND, BIND) \ - XX(17, REBIND, REBIND) \ - XX(18, UNBIND, UNBIND) \ - XX(19, ACL, ACL) \ - /* subversion */ \ - XX(20, REPORT, REPORT) \ - XX(21, MKACTIVITY, MKACTIVITY) \ - XX(22, CHECKOUT, CHECKOUT) \ - XX(23, MERGE, MERGE) \ - /* upnp */ \ - XX(24, MSEARCH, M-SEARCH) \ - XX(25, NOTIFY, NOTIFY) \ - XX(26, SUBSCRIBE, SUBSCRIBE) \ - XX(27, UNSUBSCRIBE, UNSUBSCRIBE) \ - /* RFC-5789 */ \ - XX(28, PATCH, PATCH) \ - XX(29, PURGE, PURGE) \ - /* CalDAV */ \ - XX(30, MKCALENDAR, MKCALENDAR) \ - /* RFC-2068, section 19.6.1.2 */ \ - XX(31, LINK, LINK) \ - XX(32, UNLINK, UNLINK) \ - -enum http_method - { -#define XX(num, name, string) HTTP_##name = num, - HTTP_METHOD_MAP(XX) -#undef XX - }; - - -enum http_parser_type { HTTP_REQUEST, HTTP_RESPONSE, HTTP_BOTH }; - - -/* Flag values for http_parser.flags field */ -enum flags - { F_CHUNKED = 1 << 0 - , F_CONNECTION_KEEP_ALIVE = 1 << 1 - , F_CONNECTION_CLOSE = 1 << 2 - , F_CONNECTION_UPGRADE = 1 << 3 - , F_TRAILING = 1 << 4 - , F_UPGRADE = 1 << 5 - , F_SKIPBODY = 1 << 6 - , F_CONTENTLENGTH = 1 << 7 - }; - - -/* Map for errno-related constants - * - * The provided argument should be a macro that takes 2 arguments. - */ -#define HTTP_ERRNO_MAP(XX) \ - /* No error */ \ - XX(OK, "success") \ - \ - /* Callback-related errors */ \ - XX(CB_message_begin, "the on_message_begin callback failed") \ - XX(CB_url, "the on_url callback failed") \ - XX(CB_header_field, "the on_header_field callback failed") \ - XX(CB_header_value, "the on_header_value callback failed") \ - XX(CB_headers_complete, "the on_headers_complete callback failed") \ - XX(CB_body, "the on_body callback failed") \ - XX(CB_message_complete, "the on_message_complete callback failed") \ - XX(CB_status, "the on_status callback failed") \ - XX(CB_chunk_header, "the on_chunk_header callback failed") \ - XX(CB_chunk_complete, "the on_chunk_complete callback failed") \ - \ - /* Parsing-related errors */ \ - XX(INVALID_EOF_STATE, "stream ended at an unexpected time") \ - XX(HEADER_OVERFLOW, \ - "too many header bytes seen; overflow detected") \ - XX(CLOSED_CONNECTION, \ - "data received after completed connection: close message") \ - XX(INVALID_VERSION, "invalid HTTP version") \ - XX(INVALID_STATUS, "invalid HTTP status code") \ - XX(INVALID_METHOD, "invalid HTTP method") \ - XX(INVALID_URL, "invalid URL") \ - XX(INVALID_HOST, "invalid host") \ - XX(INVALID_PORT, "invalid port") \ - XX(INVALID_PATH, "invalid path") \ - XX(INVALID_QUERY_STRING, "invalid query string") \ - XX(INVALID_FRAGMENT, "invalid fragment") \ - XX(LF_EXPECTED, "LF character expected") \ - XX(INVALID_HEADER_TOKEN, "invalid character in header") \ - XX(INVALID_CONTENT_LENGTH, \ - "invalid character in content-length header") \ - XX(UNEXPECTED_CONTENT_LENGTH, \ - "unexpected content-length header") \ - XX(INVALID_CHUNK_SIZE, \ - "invalid character in chunk size header") \ - XX(INVALID_CONSTANT, "invalid constant string") \ - XX(INVALID_INTERNAL_STATE, "encountered unexpected internal state")\ - XX(STRICT, "strict mode assertion failed") \ - XX(PAUSED, "parser is paused") \ - XX(UNKNOWN, "an unknown error occurred") - - -/* Define HPE_* values for each errno value above */ -#define HTTP_ERRNO_GEN(n, s) HPE_##n, -enum http_errno { - HTTP_ERRNO_MAP(HTTP_ERRNO_GEN) -}; -#undef HTTP_ERRNO_GEN - - -/* Get an http_errno value from an http_parser */ -#define HTTP_PARSER_ERRNO(p) ((enum http_errno) (p)->http_errno) - - -struct http_parser { - /** PRIVATE **/ - unsigned int type : 2; /* enum http_parser_type */ - unsigned int flags : 8; /* F_* values from 'flags' enum; semi-public */ - unsigned int state : 7; /* enum state from http_parser.c */ - unsigned int header_state : 7; /* enum header_state from http_parser.c */ - unsigned int index : 7; /* index into current matcher */ - unsigned int lenient_http_headers : 1; - - uint32_t nread; /* # bytes read in various scenarios */ - uint64_t content_length; /* # bytes in body (0 if no Content-Length header) */ - - /** READ-ONLY **/ - unsigned short http_major; - unsigned short http_minor; - unsigned int status_code : 16; /* responses only */ - unsigned int method : 8; /* requests only */ - unsigned int http_errno : 7; - - /* 1 = Upgrade header was present and the parser has exited because of that. - * 0 = No upgrade header present. - * Should be checked when http_parser_execute() returns in addition to - * error checking. - */ - unsigned int upgrade : 1; - - /** PUBLIC **/ - void *data; /* A pointer to get hook to the "connection" or "socket" object */ -}; - - -struct http_parser_settings { - http_cb on_message_begin; - http_data_cb on_url; - http_data_cb on_status; - http_data_cb on_header_field; - http_data_cb on_header_value; - http_cb on_headers_complete; - http_data_cb on_body; - http_cb on_message_complete; - /* When on_chunk_header is called, the current chunk length is stored - * in parser->content_length. - */ - http_cb on_chunk_header; - http_cb on_chunk_complete; -}; - - -enum http_parser_url_fields - { UF_SCHEMA = 0 - , UF_HOST = 1 - , UF_PORT = 2 - , UF_PATH = 3 - , UF_QUERY = 4 - , UF_FRAGMENT = 5 - , UF_USERINFO = 6 - , UF_MAX = 7 - }; - - -/* Result structure for http_parser_parse_url(). - * - * Callers should index into field_data[] with UF_* values iff field_set - * has the relevant (1 << UF_*) bit set. As a courtesy to clients (and - * because we probably have padding left over), we convert any port to - * a uint16_t. - */ -struct http_parser_url { - uint16_t field_set; /* Bitmask of (1 << UF_*) values */ - uint16_t port; /* Converted UF_PORT string */ - - struct { - uint16_t off; /* Offset into buffer in which field starts */ - uint16_t len; /* Length of run in buffer */ - } field_data[UF_MAX]; -}; - - -/* Returns the library version. Bits 16-23 contain the major version number, - * bits 8-15 the minor version number and bits 0-7 the patch level. - * Usage example: - * - * unsigned long version = http_parser_version(); - * unsigned major = (version >> 16) & 255; - * unsigned minor = (version >> 8) & 255; - * unsigned patch = version & 255; - * printf("http_parser v%u.%u.%u\n", major, minor, patch); - */ -unsigned long http_parser_version(void); - -void http_parser_init(http_parser *parser, enum http_parser_type type); - - -/* Initialize http_parser_settings members to 0 - */ -void http_parser_settings_init(http_parser_settings *settings); - - -/* Executes the parser. Returns number of parsed bytes. Sets - * `parser->http_errno` on error. */ -size_t http_parser_execute(http_parser *parser, - const http_parser_settings *settings, - const char *data, - size_t len); - - -/* If http_should_keep_alive() in the on_headers_complete or - * on_message_complete callback returns 0, then this should be - * the last message on the connection. - * If you are the server, respond with the "Connection: close" header. - * If you are the client, close the connection. - */ -int http_should_keep_alive(const http_parser *parser); - -/* Returns a string version of the HTTP method. */ -const char *http_method_str(enum http_method m); - -/* Return a string name of the given error */ -const char *http_errno_name(enum http_errno err); - -/* Return a string description of the given error */ -const char *http_errno_description(enum http_errno err); - -/* Initialize all http_parser_url members to 0 */ -void http_parser_url_init(struct http_parser_url *u); - -/* Parse a URL; return nonzero on failure */ -int http_parser_parse_url(const char *buf, size_t buflen, - int is_connect, - struct http_parser_url *u); - -/* Pause or un-pause the parser; a nonzero value pauses */ -void http_parser_pause(http_parser *parser, int paused); - -/* Checks if this is the final chunk of the body. */ -int http_body_is_final(const http_parser *parser); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/vendor/http_parser/test.c b/vendor/http_parser/test.c deleted file mode 100644 index 7b01dc346..000000000 --- a/vendor/http_parser/test.c +++ /dev/null @@ -1,4132 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ -#include "http_parser.h" -#include -#include -#include -#include /* rand */ -#include -#include - -#if defined(__APPLE__) -# undef strlcat -# undef strlncpy -# undef strlcpy -#endif /* defined(__APPLE__) */ - -#undef TRUE -#define TRUE 1 -#undef FALSE -#define FALSE 0 - -#define MAX_HEADERS 13 -#define MAX_ELEMENT_SIZE 2048 -#define MAX_CHUNKS 16 - -#define MIN(a,b) ((a) < (b) ? (a) : (b)) - -static http_parser *parser; - -struct message { - const char *name; // for debugging purposes - const char *raw; - enum http_parser_type type; - enum http_method method; - int status_code; - char response_status[MAX_ELEMENT_SIZE]; - char request_path[MAX_ELEMENT_SIZE]; - char request_url[MAX_ELEMENT_SIZE]; - char fragment[MAX_ELEMENT_SIZE]; - char query_string[MAX_ELEMENT_SIZE]; - char body[MAX_ELEMENT_SIZE]; - size_t body_size; - const char *host; - const char *userinfo; - uint16_t port; - int num_headers; - enum { NONE=0, FIELD, VALUE } last_header_element; - char headers [MAX_HEADERS][2][MAX_ELEMENT_SIZE]; - int should_keep_alive; - - int num_chunks; - int num_chunks_complete; - int chunk_lengths[MAX_CHUNKS]; - - const char *upgrade; // upgraded body - - unsigned short http_major; - unsigned short http_minor; - - int message_begin_cb_called; - int headers_complete_cb_called; - int message_complete_cb_called; - int message_complete_on_eof; - int body_is_final; -}; - -static int currently_parsing_eof; - -static struct message messages[5]; -static int num_messages; -static http_parser_settings *current_pause_parser; - -/* * R E Q U E S T S * */ -const struct message requests[] = -#define CURL_GET 0 -{ {.name= "curl get" - ,.type= HTTP_REQUEST - ,.raw= "GET /test HTTP/1.1\r\n" - "User-Agent: curl/7.18.0 (i486-pc-linux-gnu) libcurl/7.18.0 OpenSSL/0.9.8g zlib/1.2.3.3 libidn/1.1\r\n" - "Host: 0.0.0.0=5000\r\n" - "Accept: */*\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_GET - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/test" - ,.request_url= "/test" - ,.num_headers= 3 - ,.headers= - { { "User-Agent", "curl/7.18.0 (i486-pc-linux-gnu) libcurl/7.18.0 OpenSSL/0.9.8g zlib/1.2.3.3 libidn/1.1" } - , { "Host", "0.0.0.0=5000" } - , { "Accept", "*/*" } - } - ,.body= "" - } - -#define FIREFOX_GET 1 -, {.name= "firefox get" - ,.type= HTTP_REQUEST - ,.raw= "GET /favicon.ico HTTP/1.1\r\n" - "Host: 0.0.0.0=5000\r\n" - "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9) Gecko/2008061015 Firefox/3.0\r\n" - "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n" - "Accept-Language: en-us,en;q=0.5\r\n" - "Accept-Encoding: gzip,deflate\r\n" - "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n" - "Keep-Alive: 300\r\n" - "Connection: keep-alive\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_GET - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/favicon.ico" - ,.request_url= "/favicon.ico" - ,.num_headers= 8 - ,.headers= - { { "Host", "0.0.0.0=5000" } - , { "User-Agent", "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9) Gecko/2008061015 Firefox/3.0" } - , { "Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" } - , { "Accept-Language", "en-us,en;q=0.5" } - , { "Accept-Encoding", "gzip,deflate" } - , { "Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.7" } - , { "Keep-Alive", "300" } - , { "Connection", "keep-alive" } - } - ,.body= "" - } - -#define DUMBFUCK 2 -, {.name= "dumbfuck" - ,.type= HTTP_REQUEST - ,.raw= "GET /dumbfuck HTTP/1.1\r\n" - "aaaaaaaaaaaaa:++++++++++\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_GET - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/dumbfuck" - ,.request_url= "/dumbfuck" - ,.num_headers= 1 - ,.headers= - { { "aaaaaaaaaaaaa", "++++++++++" } - } - ,.body= "" - } - -#define FRAGMENT_IN_URI 3 -, {.name= "fragment in url" - ,.type= HTTP_REQUEST - ,.raw= "GET /forums/1/topics/2375?page=1#posts-17408 HTTP/1.1\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_GET - ,.query_string= "page=1" - ,.fragment= "posts-17408" - ,.request_path= "/forums/1/topics/2375" - /* XXX request url does include fragment? */ - ,.request_url= "/forums/1/topics/2375?page=1#posts-17408" - ,.num_headers= 0 - ,.body= "" - } - -#define GET_NO_HEADERS_NO_BODY 4 -, {.name= "get no headers no body" - ,.type= HTTP_REQUEST - ,.raw= "GET /get_no_headers_no_body/world HTTP/1.1\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE /* would need Connection: close */ - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_GET - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/get_no_headers_no_body/world" - ,.request_url= "/get_no_headers_no_body/world" - ,.num_headers= 0 - ,.body= "" - } - -#define GET_ONE_HEADER_NO_BODY 5 -, {.name= "get one header no body" - ,.type= HTTP_REQUEST - ,.raw= "GET /get_one_header_no_body HTTP/1.1\r\n" - "Accept: */*\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE /* would need Connection: close */ - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_GET - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/get_one_header_no_body" - ,.request_url= "/get_one_header_no_body" - ,.num_headers= 1 - ,.headers= - { { "Accept" , "*/*" } - } - ,.body= "" - } - -#define GET_FUNKY_CONTENT_LENGTH 6 -, {.name= "get funky content length body hello" - ,.type= HTTP_REQUEST - ,.raw= "GET /get_funky_content_length_body_hello HTTP/1.0\r\n" - "conTENT-Length: 5\r\n" - "\r\n" - "HELLO" - ,.should_keep_alive= FALSE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 0 - ,.method= HTTP_GET - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/get_funky_content_length_body_hello" - ,.request_url= "/get_funky_content_length_body_hello" - ,.num_headers= 1 - ,.headers= - { { "conTENT-Length" , "5" } - } - ,.body= "HELLO" - } - -#define POST_IDENTITY_BODY_WORLD 7 -, {.name= "post identity body world" - ,.type= HTTP_REQUEST - ,.raw= "POST /post_identity_body_world?q=search#hey HTTP/1.1\r\n" - "Accept: */*\r\n" - "Transfer-Encoding: identity\r\n" - "Content-Length: 5\r\n" - "\r\n" - "World" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_POST - ,.query_string= "q=search" - ,.fragment= "hey" - ,.request_path= "/post_identity_body_world" - ,.request_url= "/post_identity_body_world?q=search#hey" - ,.num_headers= 3 - ,.headers= - { { "Accept", "*/*" } - , { "Transfer-Encoding", "identity" } - , { "Content-Length", "5" } - } - ,.body= "World" - } - -#define POST_CHUNKED_ALL_YOUR_BASE 8 -, {.name= "post - chunked body: all your base are belong to us" - ,.type= HTTP_REQUEST - ,.raw= "POST /post_chunked_all_your_base HTTP/1.1\r\n" - "Transfer-Encoding: chunked\r\n" - "\r\n" - "1e\r\nall your base are belong to us\r\n" - "0\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_POST - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/post_chunked_all_your_base" - ,.request_url= "/post_chunked_all_your_base" - ,.num_headers= 1 - ,.headers= - { { "Transfer-Encoding" , "chunked" } - } - ,.body= "all your base are belong to us" - ,.num_chunks_complete= 2 - ,.chunk_lengths= { 0x1e } - } - -#define TWO_CHUNKS_MULT_ZERO_END 9 -, {.name= "two chunks ; triple zero ending" - ,.type= HTTP_REQUEST - ,.raw= "POST /two_chunks_mult_zero_end HTTP/1.1\r\n" - "Transfer-Encoding: chunked\r\n" - "\r\n" - "5\r\nhello\r\n" - "6\r\n world\r\n" - "000\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_POST - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/two_chunks_mult_zero_end" - ,.request_url= "/two_chunks_mult_zero_end" - ,.num_headers= 1 - ,.headers= - { { "Transfer-Encoding", "chunked" } - } - ,.body= "hello world" - ,.num_chunks_complete= 3 - ,.chunk_lengths= { 5, 6 } - } - -#define CHUNKED_W_TRAILING_HEADERS 10 -, {.name= "chunked with trailing headers. blech." - ,.type= HTTP_REQUEST - ,.raw= "POST /chunked_w_trailing_headers HTTP/1.1\r\n" - "Transfer-Encoding: chunked\r\n" - "\r\n" - "5\r\nhello\r\n" - "6\r\n world\r\n" - "0\r\n" - "Vary: *\r\n" - "Content-Type: text/plain\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_POST - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/chunked_w_trailing_headers" - ,.request_url= "/chunked_w_trailing_headers" - ,.num_headers= 3 - ,.headers= - { { "Transfer-Encoding", "chunked" } - , { "Vary", "*" } - , { "Content-Type", "text/plain" } - } - ,.body= "hello world" - ,.num_chunks_complete= 3 - ,.chunk_lengths= { 5, 6 } - } - -#define CHUNKED_W_BULLSHIT_AFTER_LENGTH 11 -, {.name= "with bullshit after the length" - ,.type= HTTP_REQUEST - ,.raw= "POST /chunked_w_bullshit_after_length HTTP/1.1\r\n" - "Transfer-Encoding: chunked\r\n" - "\r\n" - "5; ihatew3;whatthefuck=aretheseparametersfor\r\nhello\r\n" - "6; blahblah; blah\r\n world\r\n" - "0\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_POST - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/chunked_w_bullshit_after_length" - ,.request_url= "/chunked_w_bullshit_after_length" - ,.num_headers= 1 - ,.headers= - { { "Transfer-Encoding", "chunked" } - } - ,.body= "hello world" - ,.num_chunks_complete= 3 - ,.chunk_lengths= { 5, 6 } - } - -#define WITH_QUOTES 12 -, {.name= "with quotes" - ,.type= HTTP_REQUEST - ,.raw= "GET /with_\"stupid\"_quotes?foo=\"bar\" HTTP/1.1\r\n\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_GET - ,.query_string= "foo=\"bar\"" - ,.fragment= "" - ,.request_path= "/with_\"stupid\"_quotes" - ,.request_url= "/with_\"stupid\"_quotes?foo=\"bar\"" - ,.num_headers= 0 - ,.headers= { } - ,.body= "" - } - -#define APACHEBENCH_GET 13 -/* The server receiving this request SHOULD NOT wait for EOF - * to know that content-length == 0. - * How to represent this in a unit test? message_complete_on_eof - * Compare with NO_CONTENT_LENGTH_RESPONSE. - */ -, {.name = "apachebench get" - ,.type= HTTP_REQUEST - ,.raw= "GET /test HTTP/1.0\r\n" - "Host: 0.0.0.0:5000\r\n" - "User-Agent: ApacheBench/2.3\r\n" - "Accept: */*\r\n\r\n" - ,.should_keep_alive= FALSE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 0 - ,.method= HTTP_GET - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/test" - ,.request_url= "/test" - ,.num_headers= 3 - ,.headers= { { "Host", "0.0.0.0:5000" } - , { "User-Agent", "ApacheBench/2.3" } - , { "Accept", "*/*" } - } - ,.body= "" - } - -#define QUERY_URL_WITH_QUESTION_MARK_GET 14 -/* Some clients include '?' characters in query strings. - */ -, {.name = "query url with question mark" - ,.type= HTTP_REQUEST - ,.raw= "GET /test.cgi?foo=bar?baz HTTP/1.1\r\n\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_GET - ,.query_string= "foo=bar?baz" - ,.fragment= "" - ,.request_path= "/test.cgi" - ,.request_url= "/test.cgi?foo=bar?baz" - ,.num_headers= 0 - ,.headers= {} - ,.body= "" - } - -#define PREFIX_NEWLINE_GET 15 -/* Some clients, especially after a POST in a keep-alive connection, - * will send an extra CRLF before the next request - */ -, {.name = "newline prefix get" - ,.type= HTTP_REQUEST - ,.raw= "\r\nGET /test HTTP/1.1\r\n\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_GET - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/test" - ,.request_url= "/test" - ,.num_headers= 0 - ,.headers= { } - ,.body= "" - } - -#define UPGRADE_REQUEST 16 -, {.name = "upgrade request" - ,.type= HTTP_REQUEST - ,.raw= "GET /demo HTTP/1.1\r\n" - "Host: example.com\r\n" - "Connection: Upgrade\r\n" - "Sec-WebSocket-Key2: 12998 5 Y3 1 .P00\r\n" - "Sec-WebSocket-Protocol: sample\r\n" - "Upgrade: WebSocket\r\n" - "Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5\r\n" - "Origin: http://example.com\r\n" - "\r\n" - "Hot diggity dogg" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_GET - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/demo" - ,.request_url= "/demo" - ,.num_headers= 7 - ,.upgrade="Hot diggity dogg" - ,.headers= { { "Host", "example.com" } - , { "Connection", "Upgrade" } - , { "Sec-WebSocket-Key2", "12998 5 Y3 1 .P00" } - , { "Sec-WebSocket-Protocol", "sample" } - , { "Upgrade", "WebSocket" } - , { "Sec-WebSocket-Key1", "4 @1 46546xW%0l 1 5" } - , { "Origin", "http://example.com" } - } - ,.body= "" - } - -#define CONNECT_REQUEST 17 -, {.name = "connect request" - ,.type= HTTP_REQUEST - ,.raw= "CONNECT 0-home0.netscape.com:443 HTTP/1.0\r\n" - "User-agent: Mozilla/1.1N\r\n" - "Proxy-authorization: basic aGVsbG86d29ybGQ=\r\n" - "\r\n" - "some data\r\n" - "and yet even more data" - ,.should_keep_alive= FALSE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 0 - ,.method= HTTP_CONNECT - ,.query_string= "" - ,.fragment= "" - ,.request_path= "" - ,.request_url= "0-home0.netscape.com:443" - ,.num_headers= 2 - ,.upgrade="some data\r\nand yet even more data" - ,.headers= { { "User-agent", "Mozilla/1.1N" } - , { "Proxy-authorization", "basic aGVsbG86d29ybGQ=" } - } - ,.body= "" - } - -#define REPORT_REQ 18 -, {.name= "report request" - ,.type= HTTP_REQUEST - ,.raw= "REPORT /test HTTP/1.1\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_REPORT - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/test" - ,.request_url= "/test" - ,.num_headers= 0 - ,.headers= {} - ,.body= "" - } - -#define NO_HTTP_VERSION 19 -, {.name= "request with no http version" - ,.type= HTTP_REQUEST - ,.raw= "GET /\r\n" - "\r\n" - ,.should_keep_alive= FALSE - ,.message_complete_on_eof= FALSE - ,.http_major= 0 - ,.http_minor= 9 - ,.method= HTTP_GET - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/" - ,.request_url= "/" - ,.num_headers= 0 - ,.headers= {} - ,.body= "" - } - -#define MSEARCH_REQ 20 -, {.name= "m-search request" - ,.type= HTTP_REQUEST - ,.raw= "M-SEARCH * HTTP/1.1\r\n" - "HOST: 239.255.255.250:1900\r\n" - "MAN: \"ssdp:discover\"\r\n" - "ST: \"ssdp:all\"\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_MSEARCH - ,.query_string= "" - ,.fragment= "" - ,.request_path= "*" - ,.request_url= "*" - ,.num_headers= 3 - ,.headers= { { "HOST", "239.255.255.250:1900" } - , { "MAN", "\"ssdp:discover\"" } - , { "ST", "\"ssdp:all\"" } - } - ,.body= "" - } - -#define LINE_FOLDING_IN_HEADER 21 -, {.name= "line folding in header value" - ,.type= HTTP_REQUEST - ,.raw= "GET / HTTP/1.1\r\n" - "Line1: abc\r\n" - "\tdef\r\n" - " ghi\r\n" - "\t\tjkl\r\n" - " mno \r\n" - "\t \tqrs\r\n" - "Line2: \t line2\t\r\n" - "Line3:\r\n" - " line3\r\n" - "Line4: \r\n" - " \r\n" - "Connection:\r\n" - " close\r\n" - "\r\n" - ,.should_keep_alive= FALSE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_GET - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/" - ,.request_url= "/" - ,.num_headers= 5 - ,.headers= { { "Line1", "abc\tdef ghi\t\tjkl mno \t \tqrs" } - , { "Line2", "line2\t" } - , { "Line3", "line3" } - , { "Line4", "" } - , { "Connection", "close" }, - } - ,.body= "" - } - - -#define QUERY_TERMINATED_HOST 22 -, {.name= "host terminated by a query string" - ,.type= HTTP_REQUEST - ,.raw= "GET http://hypnotoad.org?hail=all HTTP/1.1\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_GET - ,.query_string= "hail=all" - ,.fragment= "" - ,.request_path= "" - ,.request_url= "http://hypnotoad.org?hail=all" - ,.host= "hypnotoad.org" - ,.num_headers= 0 - ,.headers= { } - ,.body= "" - } - -#define QUERY_TERMINATED_HOSTPORT 23 -, {.name= "host:port terminated by a query string" - ,.type= HTTP_REQUEST - ,.raw= "GET http://hypnotoad.org:1234?hail=all HTTP/1.1\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_GET - ,.query_string= "hail=all" - ,.fragment= "" - ,.request_path= "" - ,.request_url= "http://hypnotoad.org:1234?hail=all" - ,.host= "hypnotoad.org" - ,.port= 1234 - ,.num_headers= 0 - ,.headers= { } - ,.body= "" - } - -#define SPACE_TERMINATED_HOSTPORT 24 -, {.name= "host:port terminated by a space" - ,.type= HTTP_REQUEST - ,.raw= "GET http://hypnotoad.org:1234 HTTP/1.1\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_GET - ,.query_string= "" - ,.fragment= "" - ,.request_path= "" - ,.request_url= "http://hypnotoad.org:1234" - ,.host= "hypnotoad.org" - ,.port= 1234 - ,.num_headers= 0 - ,.headers= { } - ,.body= "" - } - -#define PATCH_REQ 25 -, {.name = "PATCH request" - ,.type= HTTP_REQUEST - ,.raw= "PATCH /file.txt HTTP/1.1\r\n" - "Host: www.example.com\r\n" - "Content-Type: application/example\r\n" - "If-Match: \"e0023aa4e\"\r\n" - "Content-Length: 10\r\n" - "\r\n" - "cccccccccc" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_PATCH - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/file.txt" - ,.request_url= "/file.txt" - ,.num_headers= 4 - ,.headers= { { "Host", "www.example.com" } - , { "Content-Type", "application/example" } - , { "If-Match", "\"e0023aa4e\"" } - , { "Content-Length", "10" } - } - ,.body= "cccccccccc" - } - -#define CONNECT_CAPS_REQUEST 26 -, {.name = "connect caps request" - ,.type= HTTP_REQUEST - ,.raw= "CONNECT HOME0.NETSCAPE.COM:443 HTTP/1.0\r\n" - "User-agent: Mozilla/1.1N\r\n" - "Proxy-authorization: basic aGVsbG86d29ybGQ=\r\n" - "\r\n" - ,.should_keep_alive= FALSE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 0 - ,.method= HTTP_CONNECT - ,.query_string= "" - ,.fragment= "" - ,.request_path= "" - ,.request_url= "HOME0.NETSCAPE.COM:443" - ,.num_headers= 2 - ,.upgrade="" - ,.headers= { { "User-agent", "Mozilla/1.1N" } - , { "Proxy-authorization", "basic aGVsbG86d29ybGQ=" } - } - ,.body= "" - } - -#if !HTTP_PARSER_STRICT -#define UTF8_PATH_REQ 27 -, {.name= "utf-8 path request" - ,.type= HTTP_REQUEST - ,.raw= "GET /δ¶/δt/pope?q=1#narf HTTP/1.1\r\n" - "Host: github.com\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_GET - ,.query_string= "q=1" - ,.fragment= "narf" - ,.request_path= "/δ¶/δt/pope" - ,.request_url= "/δ¶/δt/pope?q=1#narf" - ,.num_headers= 1 - ,.headers= { {"Host", "github.com" } - } - ,.body= "" - } - -#define HOSTNAME_UNDERSCORE 28 -, {.name = "hostname underscore" - ,.type= HTTP_REQUEST - ,.raw= "CONNECT home_0.netscape.com:443 HTTP/1.0\r\n" - "User-agent: Mozilla/1.1N\r\n" - "Proxy-authorization: basic aGVsbG86d29ybGQ=\r\n" - "\r\n" - ,.should_keep_alive= FALSE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 0 - ,.method= HTTP_CONNECT - ,.query_string= "" - ,.fragment= "" - ,.request_path= "" - ,.request_url= "home_0.netscape.com:443" - ,.num_headers= 2 - ,.upgrade="" - ,.headers= { { "User-agent", "Mozilla/1.1N" } - , { "Proxy-authorization", "basic aGVsbG86d29ybGQ=" } - } - ,.body= "" - } -#endif /* !HTTP_PARSER_STRICT */ - -/* see https://github.com/ry/http-parser/issues/47 */ -#define EAT_TRAILING_CRLF_NO_CONNECTION_CLOSE 29 -, {.name = "eat CRLF between requests, no \"Connection: close\" header" - ,.raw= "POST / HTTP/1.1\r\n" - "Host: www.example.com\r\n" - "Content-Type: application/x-www-form-urlencoded\r\n" - "Content-Length: 4\r\n" - "\r\n" - "q=42\r\n" /* note the trailing CRLF */ - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_POST - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/" - ,.request_url= "/" - ,.num_headers= 3 - ,.upgrade= 0 - ,.headers= { { "Host", "www.example.com" } - , { "Content-Type", "application/x-www-form-urlencoded" } - , { "Content-Length", "4" } - } - ,.body= "q=42" - } - -/* see https://github.com/ry/http-parser/issues/47 */ -#define EAT_TRAILING_CRLF_WITH_CONNECTION_CLOSE 30 -, {.name = "eat CRLF between requests even if \"Connection: close\" is set" - ,.raw= "POST / HTTP/1.1\r\n" - "Host: www.example.com\r\n" - "Content-Type: application/x-www-form-urlencoded\r\n" - "Content-Length: 4\r\n" - "Connection: close\r\n" - "\r\n" - "q=42\r\n" /* note the trailing CRLF */ - ,.should_keep_alive= FALSE - ,.message_complete_on_eof= FALSE /* input buffer isn't empty when on_message_complete is called */ - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_POST - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/" - ,.request_url= "/" - ,.num_headers= 4 - ,.upgrade= 0 - ,.headers= { { "Host", "www.example.com" } - , { "Content-Type", "application/x-www-form-urlencoded" } - , { "Content-Length", "4" } - , { "Connection", "close" } - } - ,.body= "q=42" - } - -#define PURGE_REQ 31 -, {.name = "PURGE request" - ,.type= HTTP_REQUEST - ,.raw= "PURGE /file.txt HTTP/1.1\r\n" - "Host: www.example.com\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_PURGE - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/file.txt" - ,.request_url= "/file.txt" - ,.num_headers= 1 - ,.headers= { { "Host", "www.example.com" } } - ,.body= "" - } - -#define SEARCH_REQ 32 -, {.name = "SEARCH request" - ,.type= HTTP_REQUEST - ,.raw= "SEARCH / HTTP/1.1\r\n" - "Host: www.example.com\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_SEARCH - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/" - ,.request_url= "/" - ,.num_headers= 1 - ,.headers= { { "Host", "www.example.com" } } - ,.body= "" - } - -#define PROXY_WITH_BASIC_AUTH 33 -, {.name= "host:port and basic_auth" - ,.type= HTTP_REQUEST - ,.raw= "GET http://a%12:b!&*$@hypnotoad.org:1234/toto HTTP/1.1\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_GET - ,.fragment= "" - ,.request_path= "/toto" - ,.request_url= "http://a%12:b!&*$@hypnotoad.org:1234/toto" - ,.host= "hypnotoad.org" - ,.userinfo= "a%12:b!&*$" - ,.port= 1234 - ,.num_headers= 0 - ,.headers= { } - ,.body= "" - } - -#define LINE_FOLDING_IN_HEADER_WITH_LF 34 -, {.name= "line folding in header value" - ,.type= HTTP_REQUEST - ,.raw= "GET / HTTP/1.1\n" - "Line1: abc\n" - "\tdef\n" - " ghi\n" - "\t\tjkl\n" - " mno \n" - "\t \tqrs\n" - "Line2: \t line2\t\n" - "Line3:\n" - " line3\n" - "Line4: \n" - " \n" - "Connection:\n" - " close\n" - "\n" - ,.should_keep_alive= FALSE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_GET - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/" - ,.request_url= "/" - ,.num_headers= 5 - ,.headers= { { "Line1", "abc\tdef ghi\t\tjkl mno \t \tqrs" } - , { "Line2", "line2\t" } - , { "Line3", "line3" } - , { "Line4", "" } - , { "Connection", "close" }, - } - ,.body= "" - } - -#define CONNECTION_MULTI 35 -, {.name = "multiple connection header values with folding" - ,.type= HTTP_REQUEST - ,.raw= "GET /demo HTTP/1.1\r\n" - "Host: example.com\r\n" - "Connection: Something,\r\n" - " Upgrade, ,Keep-Alive\r\n" - "Sec-WebSocket-Key2: 12998 5 Y3 1 .P00\r\n" - "Sec-WebSocket-Protocol: sample\r\n" - "Upgrade: WebSocket\r\n" - "Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5\r\n" - "Origin: http://example.com\r\n" - "\r\n" - "Hot diggity dogg" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_GET - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/demo" - ,.request_url= "/demo" - ,.num_headers= 7 - ,.upgrade="Hot diggity dogg" - ,.headers= { { "Host", "example.com" } - , { "Connection", "Something, Upgrade, ,Keep-Alive" } - , { "Sec-WebSocket-Key2", "12998 5 Y3 1 .P00" } - , { "Sec-WebSocket-Protocol", "sample" } - , { "Upgrade", "WebSocket" } - , { "Sec-WebSocket-Key1", "4 @1 46546xW%0l 1 5" } - , { "Origin", "http://example.com" } - } - ,.body= "" - } - -#define CONNECTION_MULTI_LWS 36 -, {.name = "multiple connection header values with folding and lws" - ,.type= HTTP_REQUEST - ,.raw= "GET /demo HTTP/1.1\r\n" - "Connection: keep-alive, upgrade\r\n" - "Upgrade: WebSocket\r\n" - "\r\n" - "Hot diggity dogg" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_GET - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/demo" - ,.request_url= "/demo" - ,.num_headers= 2 - ,.upgrade="Hot diggity dogg" - ,.headers= { { "Connection", "keep-alive, upgrade" } - , { "Upgrade", "WebSocket" } - } - ,.body= "" - } - -#define CONNECTION_MULTI_LWS_CRLF 37 -, {.name = "multiple connection header values with folding and lws" - ,.type= HTTP_REQUEST - ,.raw= "GET /demo HTTP/1.1\r\n" - "Connection: keep-alive, \r\n upgrade\r\n" - "Upgrade: WebSocket\r\n" - "\r\n" - "Hot diggity dogg" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_GET - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/demo" - ,.request_url= "/demo" - ,.num_headers= 2 - ,.upgrade="Hot diggity dogg" - ,.headers= { { "Connection", "keep-alive, upgrade" } - , { "Upgrade", "WebSocket" } - } - ,.body= "" - } - -#define UPGRADE_POST_REQUEST 38 -, {.name = "upgrade post request" - ,.type= HTTP_REQUEST - ,.raw= "POST /demo HTTP/1.1\r\n" - "Host: example.com\r\n" - "Connection: Upgrade\r\n" - "Upgrade: HTTP/2.0\r\n" - "Content-Length: 15\r\n" - "\r\n" - "sweet post body" - "Hot diggity dogg" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_POST - ,.request_path= "/demo" - ,.request_url= "/demo" - ,.num_headers= 4 - ,.upgrade="Hot diggity dogg" - ,.headers= { { "Host", "example.com" } - , { "Connection", "Upgrade" } - , { "Upgrade", "HTTP/2.0" } - , { "Content-Length", "15" } - } - ,.body= "sweet post body" - } - -#define CONNECT_WITH_BODY_REQUEST 39 -, {.name = "connect with body request" - ,.type= HTTP_REQUEST - ,.raw= "CONNECT foo.bar.com:443 HTTP/1.0\r\n" - "User-agent: Mozilla/1.1N\r\n" - "Proxy-authorization: basic aGVsbG86d29ybGQ=\r\n" - "Content-Length: 10\r\n" - "\r\n" - "blarfcicle" - ,.should_keep_alive= FALSE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 0 - ,.method= HTTP_CONNECT - ,.request_url= "foo.bar.com:443" - ,.num_headers= 3 - ,.upgrade="blarfcicle" - ,.headers= { { "User-agent", "Mozilla/1.1N" } - , { "Proxy-authorization", "basic aGVsbG86d29ybGQ=" } - , { "Content-Length", "10" } - } - ,.body= "" - } - -/* Examples from the Internet draft for LINK/UNLINK methods: - * https://tools.ietf.org/id/draft-snell-link-method-01.html#rfc.section.5 - */ - -#define LINK_REQUEST 40 -, {.name = "link request" - ,.type= HTTP_REQUEST - ,.raw= "LINK /images/my_dog.jpg HTTP/1.1\r\n" - "Host: example.com\r\n" - "Link: ; rel=\"tag\"\r\n" - "Link: ; rel=\"tag\"\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_LINK - ,.request_path= "/images/my_dog.jpg" - ,.request_url= "/images/my_dog.jpg" - ,.query_string= "" - ,.fragment= "" - ,.num_headers= 3 - ,.headers= { { "Host", "example.com" } - , { "Link", "; rel=\"tag\"" } - , { "Link", "; rel=\"tag\"" } - } - ,.body= "" - } - -#define UNLINK_REQUEST 41 -, {.name = "link request" - ,.type= HTTP_REQUEST - ,.raw= "UNLINK /images/my_dog.jpg HTTP/1.1\r\n" - "Host: example.com\r\n" - "Link: ; rel=\"tag\"\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_UNLINK - ,.request_path= "/images/my_dog.jpg" - ,.request_url= "/images/my_dog.jpg" - ,.query_string= "" - ,.fragment= "" - ,.num_headers= 2 - ,.headers= { { "Host", "example.com" } - , { "Link", "; rel=\"tag\"" } - } - ,.body= "" - } - -, {.name= NULL } /* sentinel */ -}; - -/* * R E S P O N S E S * */ -const struct message responses[] = -#define GOOGLE_301 0 -{ {.name= "google 301" - ,.type= HTTP_RESPONSE - ,.raw= "HTTP/1.1 301 Moved Permanently\r\n" - "Location: http://www.google.com/\r\n" - "Content-Type: text/html; charset=UTF-8\r\n" - "Date: Sun, 26 Apr 2009 11:11:49 GMT\r\n" - "Expires: Tue, 26 May 2009 11:11:49 GMT\r\n" - "X-$PrototypeBI-Version: 1.6.0.3\r\n" /* $ char in header field */ - "Cache-Control: public, max-age=2592000\r\n" - "Server: gws\r\n" - "Content-Length: 219 \r\n" - "\r\n" - "\n" - "301 Moved\n" - "

301 Moved

\n" - "The document has moved\n" - "here.\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.status_code= 301 - ,.response_status= "Moved Permanently" - ,.num_headers= 8 - ,.headers= - { { "Location", "http://www.google.com/" } - , { "Content-Type", "text/html; charset=UTF-8" } - , { "Date", "Sun, 26 Apr 2009 11:11:49 GMT" } - , { "Expires", "Tue, 26 May 2009 11:11:49 GMT" } - , { "X-$PrototypeBI-Version", "1.6.0.3" } - , { "Cache-Control", "public, max-age=2592000" } - , { "Server", "gws" } - , { "Content-Length", "219 " } - } - ,.body= "\n" - "301 Moved\n" - "

301 Moved

\n" - "The document has moved\n" - "here.\r\n" - "\r\n" - } - -#define NO_CONTENT_LENGTH_RESPONSE 1 -/* The client should wait for the server's EOF. That is, when content-length - * is not specified, and "Connection: close", the end of body is specified - * by the EOF. - * Compare with APACHEBENCH_GET - */ -, {.name= "no content-length response" - ,.type= HTTP_RESPONSE - ,.raw= "HTTP/1.1 200 OK\r\n" - "Date: Tue, 04 Aug 2009 07:59:32 GMT\r\n" - "Server: Apache\r\n" - "X-Powered-By: Servlet/2.5 JSP/2.1\r\n" - "Content-Type: text/xml; charset=utf-8\r\n" - "Connection: close\r\n" - "\r\n" - "\n" - "\n" - " \n" - " \n" - " SOAP-ENV:Client\n" - " Client Error\n" - " \n" - " \n" - "" - ,.should_keep_alive= FALSE - ,.message_complete_on_eof= TRUE - ,.http_major= 1 - ,.http_minor= 1 - ,.status_code= 200 - ,.response_status= "OK" - ,.num_headers= 5 - ,.headers= - { { "Date", "Tue, 04 Aug 2009 07:59:32 GMT" } - , { "Server", "Apache" } - , { "X-Powered-By", "Servlet/2.5 JSP/2.1" } - , { "Content-Type", "text/xml; charset=utf-8" } - , { "Connection", "close" } - } - ,.body= "\n" - "\n" - " \n" - " \n" - " SOAP-ENV:Client\n" - " Client Error\n" - " \n" - " \n" - "" - } - -#define NO_HEADERS_NO_BODY_404 2 -, {.name= "404 no headers no body" - ,.type= HTTP_RESPONSE - ,.raw= "HTTP/1.1 404 Not Found\r\n\r\n" - ,.should_keep_alive= FALSE - ,.message_complete_on_eof= TRUE - ,.http_major= 1 - ,.http_minor= 1 - ,.status_code= 404 - ,.response_status= "Not Found" - ,.num_headers= 0 - ,.headers= {} - ,.body_size= 0 - ,.body= "" - } - -#define NO_REASON_PHRASE 3 -, {.name= "301 no response phrase" - ,.type= HTTP_RESPONSE - ,.raw= "HTTP/1.1 301\r\n\r\n" - ,.should_keep_alive = FALSE - ,.message_complete_on_eof= TRUE - ,.http_major= 1 - ,.http_minor= 1 - ,.status_code= 301 - ,.response_status= "" - ,.num_headers= 0 - ,.headers= {} - ,.body= "" - } - -#define TRAILING_SPACE_ON_CHUNKED_BODY 4 -, {.name="200 trailing space on chunked body" - ,.type= HTTP_RESPONSE - ,.raw= "HTTP/1.1 200 OK\r\n" - "Content-Type: text/plain\r\n" - "Transfer-Encoding: chunked\r\n" - "\r\n" - "25 \r\n" - "This is the data in the first chunk\r\n" - "\r\n" - "1C\r\n" - "and this is the second one\r\n" - "\r\n" - "0 \r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.status_code= 200 - ,.response_status= "OK" - ,.num_headers= 2 - ,.headers= - { {"Content-Type", "text/plain" } - , {"Transfer-Encoding", "chunked" } - } - ,.body_size = 37+28 - ,.body = - "This is the data in the first chunk\r\n" - "and this is the second one\r\n" - ,.num_chunks_complete= 3 - ,.chunk_lengths= { 0x25, 0x1c } - } - -#define NO_CARRIAGE_RET 5 -, {.name="no carriage ret" - ,.type= HTTP_RESPONSE - ,.raw= "HTTP/1.1 200 OK\n" - "Content-Type: text/html; charset=utf-8\n" - "Connection: close\n" - "\n" - "these headers are from http://news.ycombinator.com/" - ,.should_keep_alive= FALSE - ,.message_complete_on_eof= TRUE - ,.http_major= 1 - ,.http_minor= 1 - ,.status_code= 200 - ,.response_status= "OK" - ,.num_headers= 2 - ,.headers= - { {"Content-Type", "text/html; charset=utf-8" } - , {"Connection", "close" } - } - ,.body= "these headers are from http://news.ycombinator.com/" - } - -#define PROXY_CONNECTION 6 -, {.name="proxy connection" - ,.type= HTTP_RESPONSE - ,.raw= "HTTP/1.1 200 OK\r\n" - "Content-Type: text/html; charset=UTF-8\r\n" - "Content-Length: 11\r\n" - "Proxy-Connection: close\r\n" - "Date: Thu, 31 Dec 2009 20:55:48 +0000\r\n" - "\r\n" - "hello world" - ,.should_keep_alive= FALSE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.status_code= 200 - ,.response_status= "OK" - ,.num_headers= 4 - ,.headers= - { {"Content-Type", "text/html; charset=UTF-8" } - , {"Content-Length", "11" } - , {"Proxy-Connection", "close" } - , {"Date", "Thu, 31 Dec 2009 20:55:48 +0000"} - } - ,.body= "hello world" - } - -#define UNDERSTORE_HEADER_KEY 7 - // shown by - // curl -o /dev/null -v "http://ad.doubleclick.net/pfadx/DARTSHELLCONFIGXML;dcmt=text/xml;" -, {.name="underscore header key" - ,.type= HTTP_RESPONSE - ,.raw= "HTTP/1.1 200 OK\r\n" - "Server: DCLK-AdSvr\r\n" - "Content-Type: text/xml\r\n" - "Content-Length: 0\r\n" - "DCLK_imp: v7;x;114750856;0-0;0;17820020;0/0;21603567/21621457/1;;~okv=;dcmt=text/xml;;~cs=o\r\n\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.status_code= 200 - ,.response_status= "OK" - ,.num_headers= 4 - ,.headers= - { {"Server", "DCLK-AdSvr" } - , {"Content-Type", "text/xml" } - , {"Content-Length", "0" } - , {"DCLK_imp", "v7;x;114750856;0-0;0;17820020;0/0;21603567/21621457/1;;~okv=;dcmt=text/xml;;~cs=o" } - } - ,.body= "" - } - -#define BONJOUR_MADAME_FR 8 -/* The client should not merge two headers fields when the first one doesn't - * have a value. - */ -, {.name= "bonjourmadame.fr" - ,.type= HTTP_RESPONSE - ,.raw= "HTTP/1.0 301 Moved Permanently\r\n" - "Date: Thu, 03 Jun 2010 09:56:32 GMT\r\n" - "Server: Apache/2.2.3 (Red Hat)\r\n" - "Cache-Control: public\r\n" - "Pragma: \r\n" - "Location: http://www.bonjourmadame.fr/\r\n" - "Vary: Accept-Encoding\r\n" - "Content-Length: 0\r\n" - "Content-Type: text/html; charset=UTF-8\r\n" - "Connection: keep-alive\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 0 - ,.status_code= 301 - ,.response_status= "Moved Permanently" - ,.num_headers= 9 - ,.headers= - { { "Date", "Thu, 03 Jun 2010 09:56:32 GMT" } - , { "Server", "Apache/2.2.3 (Red Hat)" } - , { "Cache-Control", "public" } - , { "Pragma", "" } - , { "Location", "http://www.bonjourmadame.fr/" } - , { "Vary", "Accept-Encoding" } - , { "Content-Length", "0" } - , { "Content-Type", "text/html; charset=UTF-8" } - , { "Connection", "keep-alive" } - } - ,.body= "" - } - -#define RES_FIELD_UNDERSCORE 9 -/* Should handle spaces in header fields */ -, {.name= "field underscore" - ,.type= HTTP_RESPONSE - ,.raw= "HTTP/1.1 200 OK\r\n" - "Date: Tue, 28 Sep 2010 01:14:13 GMT\r\n" - "Server: Apache\r\n" - "Cache-Control: no-cache, must-revalidate\r\n" - "Expires: Mon, 26 Jul 1997 05:00:00 GMT\r\n" - ".et-Cookie: PlaxoCS=1274804622353690521; path=/; domain=.plaxo.com\r\n" - "Vary: Accept-Encoding\r\n" - "_eep-Alive: timeout=45\r\n" /* semantic value ignored */ - "_onnection: Keep-Alive\r\n" /* semantic value ignored */ - "Transfer-Encoding: chunked\r\n" - "Content-Type: text/html\r\n" - "Connection: close\r\n" - "\r\n" - "0\r\n\r\n" - ,.should_keep_alive= FALSE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.status_code= 200 - ,.response_status= "OK" - ,.num_headers= 11 - ,.headers= - { { "Date", "Tue, 28 Sep 2010 01:14:13 GMT" } - , { "Server", "Apache" } - , { "Cache-Control", "no-cache, must-revalidate" } - , { "Expires", "Mon, 26 Jul 1997 05:00:00 GMT" } - , { ".et-Cookie", "PlaxoCS=1274804622353690521; path=/; domain=.plaxo.com" } - , { "Vary", "Accept-Encoding" } - , { "_eep-Alive", "timeout=45" } - , { "_onnection", "Keep-Alive" } - , { "Transfer-Encoding", "chunked" } - , { "Content-Type", "text/html" } - , { "Connection", "close" } - } - ,.body= "" - ,.num_chunks_complete= 1 - ,.chunk_lengths= {} - } - -#define NON_ASCII_IN_STATUS_LINE 10 -/* Should handle non-ASCII in status line */ -, {.name= "non-ASCII in status line" - ,.type= HTTP_RESPONSE - ,.raw= "HTTP/1.1 500 Oriëntatieprobleem\r\n" - "Date: Fri, 5 Nov 2010 23:07:12 GMT+2\r\n" - "Content-Length: 0\r\n" - "Connection: close\r\n" - "\r\n" - ,.should_keep_alive= FALSE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.status_code= 500 - ,.response_status= "Oriëntatieprobleem" - ,.num_headers= 3 - ,.headers= - { { "Date", "Fri, 5 Nov 2010 23:07:12 GMT+2" } - , { "Content-Length", "0" } - , { "Connection", "close" } - } - ,.body= "" - } - -#define HTTP_VERSION_0_9 11 -/* Should handle HTTP/0.9 */ -, {.name= "http version 0.9" - ,.type= HTTP_RESPONSE - ,.raw= "HTTP/0.9 200 OK\r\n" - "\r\n" - ,.should_keep_alive= FALSE - ,.message_complete_on_eof= TRUE - ,.http_major= 0 - ,.http_minor= 9 - ,.status_code= 200 - ,.response_status= "OK" - ,.num_headers= 0 - ,.headers= - {} - ,.body= "" - } - -#define NO_CONTENT_LENGTH_NO_TRANSFER_ENCODING_RESPONSE 12 -/* The client should wait for the server's EOF. That is, when neither - * content-length nor transfer-encoding is specified, the end of body - * is specified by the EOF. - */ -, {.name= "neither content-length nor transfer-encoding response" - ,.type= HTTP_RESPONSE - ,.raw= "HTTP/1.1 200 OK\r\n" - "Content-Type: text/plain\r\n" - "\r\n" - "hello world" - ,.should_keep_alive= FALSE - ,.message_complete_on_eof= TRUE - ,.http_major= 1 - ,.http_minor= 1 - ,.status_code= 200 - ,.response_status= "OK" - ,.num_headers= 1 - ,.headers= - { { "Content-Type", "text/plain" } - } - ,.body= "hello world" - } - -#define NO_BODY_HTTP10_KA_200 13 -, {.name= "HTTP/1.0 with keep-alive and EOF-terminated 200 status" - ,.type= HTTP_RESPONSE - ,.raw= "HTTP/1.0 200 OK\r\n" - "Connection: keep-alive\r\n" - "\r\n" - ,.should_keep_alive= FALSE - ,.message_complete_on_eof= TRUE - ,.http_major= 1 - ,.http_minor= 0 - ,.status_code= 200 - ,.response_status= "OK" - ,.num_headers= 1 - ,.headers= - { { "Connection", "keep-alive" } - } - ,.body_size= 0 - ,.body= "" - } - -#define NO_BODY_HTTP10_KA_204 14 -, {.name= "HTTP/1.0 with keep-alive and a 204 status" - ,.type= HTTP_RESPONSE - ,.raw= "HTTP/1.0 204 No content\r\n" - "Connection: keep-alive\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 0 - ,.status_code= 204 - ,.response_status= "No content" - ,.num_headers= 1 - ,.headers= - { { "Connection", "keep-alive" } - } - ,.body_size= 0 - ,.body= "" - } - -#define NO_BODY_HTTP11_KA_200 15 -, {.name= "HTTP/1.1 with an EOF-terminated 200 status" - ,.type= HTTP_RESPONSE - ,.raw= "HTTP/1.1 200 OK\r\n" - "\r\n" - ,.should_keep_alive= FALSE - ,.message_complete_on_eof= TRUE - ,.http_major= 1 - ,.http_minor= 1 - ,.status_code= 200 - ,.response_status= "OK" - ,.num_headers= 0 - ,.headers={} - ,.body_size= 0 - ,.body= "" - } - -#define NO_BODY_HTTP11_KA_204 16 -, {.name= "HTTP/1.1 with a 204 status" - ,.type= HTTP_RESPONSE - ,.raw= "HTTP/1.1 204 No content\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.status_code= 204 - ,.response_status= "No content" - ,.num_headers= 0 - ,.headers={} - ,.body_size= 0 - ,.body= "" - } - -#define NO_BODY_HTTP11_NOKA_204 17 -, {.name= "HTTP/1.1 with a 204 status and keep-alive disabled" - ,.type= HTTP_RESPONSE - ,.raw= "HTTP/1.1 204 No content\r\n" - "Connection: close\r\n" - "\r\n" - ,.should_keep_alive= FALSE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.status_code= 204 - ,.response_status= "No content" - ,.num_headers= 1 - ,.headers= - { { "Connection", "close" } - } - ,.body_size= 0 - ,.body= "" - } - -#define NO_BODY_HTTP11_KA_CHUNKED_200 18 -, {.name= "HTTP/1.1 with chunked endocing and a 200 response" - ,.type= HTTP_RESPONSE - ,.raw= "HTTP/1.1 200 OK\r\n" - "Transfer-Encoding: chunked\r\n" - "\r\n" - "0\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.status_code= 200 - ,.response_status= "OK" - ,.num_headers= 1 - ,.headers= - { { "Transfer-Encoding", "chunked" } - } - ,.body_size= 0 - ,.body= "" - ,.num_chunks_complete= 1 - } - -#if !HTTP_PARSER_STRICT -#define SPACE_IN_FIELD_RES 19 -/* Should handle spaces in header fields */ -, {.name= "field space" - ,.type= HTTP_RESPONSE - ,.raw= "HTTP/1.1 200 OK\r\n" - "Server: Microsoft-IIS/6.0\r\n" - "X-Powered-By: ASP.NET\r\n" - "en-US Content-Type: text/xml\r\n" /* this is the problem */ - "Content-Type: text/xml\r\n" - "Content-Length: 16\r\n" - "Date: Fri, 23 Jul 2010 18:45:38 GMT\r\n" - "Connection: keep-alive\r\n" - "\r\n" - "hello" /* fake body */ - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.status_code= 200 - ,.response_status= "OK" - ,.num_headers= 7 - ,.headers= - { { "Server", "Microsoft-IIS/6.0" } - , { "X-Powered-By", "ASP.NET" } - , { "en-US Content-Type", "text/xml" } - , { "Content-Type", "text/xml" } - , { "Content-Length", "16" } - , { "Date", "Fri, 23 Jul 2010 18:45:38 GMT" } - , { "Connection", "keep-alive" } - } - ,.body= "hello" - } -#endif /* !HTTP_PARSER_STRICT */ - -#define AMAZON_COM 20 -, {.name= "amazon.com" - ,.type= HTTP_RESPONSE - ,.raw= "HTTP/1.1 301 MovedPermanently\r\n" - "Date: Wed, 15 May 2013 17:06:33 GMT\r\n" - "Server: Server\r\n" - "x-amz-id-1: 0GPHKXSJQ826RK7GZEB2\r\n" - "p3p: policyref=\"http://www.amazon.com/w3c/p3p.xml\",CP=\"CAO DSP LAW CUR ADM IVAo IVDo CONo OTPo OUR DELi PUBi OTRi BUS PHY ONL UNI PUR FIN COM NAV INT DEM CNT STA HEA PRE LOC GOV OTC \"\r\n" - "x-amz-id-2: STN69VZxIFSz9YJLbz1GDbxpbjG6Qjmmq5E3DxRhOUw+Et0p4hr7c/Q8qNcx4oAD\r\n" - "Location: http://www.amazon.com/Dan-Brown/e/B000AP9DSU/ref=s9_pop_gw_al1?_encoding=UTF8&refinementId=618073011&pf_rd_m=ATVPDKIKX0DER&pf_rd_s=center-2&pf_rd_r=0SHYY5BZXN3KR20BNFAY&pf_rd_t=101&pf_rd_p=1263340922&pf_rd_i=507846\r\n" - "Vary: Accept-Encoding,User-Agent\r\n" - "Content-Type: text/html; charset=ISO-8859-1\r\n" - "Transfer-Encoding: chunked\r\n" - "\r\n" - "1\r\n" - "\n\r\n" - "0\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.status_code= 301 - ,.response_status= "MovedPermanently" - ,.num_headers= 9 - ,.headers= { { "Date", "Wed, 15 May 2013 17:06:33 GMT" } - , { "Server", "Server" } - , { "x-amz-id-1", "0GPHKXSJQ826RK7GZEB2" } - , { "p3p", "policyref=\"http://www.amazon.com/w3c/p3p.xml\",CP=\"CAO DSP LAW CUR ADM IVAo IVDo CONo OTPo OUR DELi PUBi OTRi BUS PHY ONL UNI PUR FIN COM NAV INT DEM CNT STA HEA PRE LOC GOV OTC \"" } - , { "x-amz-id-2", "STN69VZxIFSz9YJLbz1GDbxpbjG6Qjmmq5E3DxRhOUw+Et0p4hr7c/Q8qNcx4oAD" } - , { "Location", "http://www.amazon.com/Dan-Brown/e/B000AP9DSU/ref=s9_pop_gw_al1?_encoding=UTF8&refinementId=618073011&pf_rd_m=ATVPDKIKX0DER&pf_rd_s=center-2&pf_rd_r=0SHYY5BZXN3KR20BNFAY&pf_rd_t=101&pf_rd_p=1263340922&pf_rd_i=507846" } - , { "Vary", "Accept-Encoding,User-Agent" } - , { "Content-Type", "text/html; charset=ISO-8859-1" } - , { "Transfer-Encoding", "chunked" } - } - ,.body= "\n" - ,.num_chunks_complete= 2 - ,.chunk_lengths= { 1 } - } - -#define EMPTY_REASON_PHRASE_AFTER_SPACE 20 -, {.name= "empty reason phrase after space" - ,.type= HTTP_RESPONSE - ,.raw= "HTTP/1.1 200 \r\n" - "\r\n" - ,.should_keep_alive= FALSE - ,.message_complete_on_eof= TRUE - ,.http_major= 1 - ,.http_minor= 1 - ,.status_code= 200 - ,.response_status= "" - ,.num_headers= 0 - ,.headers= {} - ,.body= "" - } - -, {.name= NULL } /* sentinel */ -}; - -/* strnlen() is a POSIX.2008 addition. Can't rely on it being available so - * define it ourselves. - */ -size_t -strnlen(const char *s, size_t maxlen) -{ - const char *p; - - p = memchr(s, '\0', maxlen); - if (p == NULL) - return maxlen; - - return p - s; -} - -size_t -strlncat(char *dst, size_t len, const char *src, size_t n) -{ - size_t slen; - size_t dlen; - size_t rlen; - size_t ncpy; - - slen = strnlen(src, n); - dlen = strnlen(dst, len); - - if (dlen < len) { - rlen = len - dlen; - ncpy = slen < rlen ? slen : (rlen - 1); - memcpy(dst + dlen, src, ncpy); - dst[dlen + ncpy] = '\0'; - } - - assert(len > slen + dlen); - return slen + dlen; -} - -size_t -strlcat(char *dst, const char *src, size_t len) -{ - return strlncat(dst, len, src, (size_t) -1); -} - -size_t -strlncpy(char *dst, size_t len, const char *src, size_t n) -{ - size_t slen; - size_t ncpy; - - slen = strnlen(src, n); - - if (len > 0) { - ncpy = slen < len ? slen : (len - 1); - memcpy(dst, src, ncpy); - dst[ncpy] = '\0'; - } - - assert(len > slen); - return slen; -} - -size_t -strlcpy(char *dst, const char *src, size_t len) -{ - return strlncpy(dst, len, src, (size_t) -1); -} - -int -request_url_cb (http_parser *p, const char *buf, size_t len) -{ - assert(p == parser); - strlncat(messages[num_messages].request_url, - sizeof(messages[num_messages].request_url), - buf, - len); - return 0; -} - -int -header_field_cb (http_parser *p, const char *buf, size_t len) -{ - assert(p == parser); - struct message *m = &messages[num_messages]; - - if (m->last_header_element != FIELD) - m->num_headers++; - - strlncat(m->headers[m->num_headers-1][0], - sizeof(m->headers[m->num_headers-1][0]), - buf, - len); - - m->last_header_element = FIELD; - - return 0; -} - -int -header_value_cb (http_parser *p, const char *buf, size_t len) -{ - assert(p == parser); - struct message *m = &messages[num_messages]; - - strlncat(m->headers[m->num_headers-1][1], - sizeof(m->headers[m->num_headers-1][1]), - buf, - len); - - m->last_header_element = VALUE; - - return 0; -} - -void -check_body_is_final (const http_parser *p) -{ - if (messages[num_messages].body_is_final) { - fprintf(stderr, "\n\n *** Error http_body_is_final() should return 1 " - "on last on_body callback call " - "but it doesn't! ***\n\n"); - assert(0); - abort(); - } - messages[num_messages].body_is_final = http_body_is_final(p); -} - -int -body_cb (http_parser *p, const char *buf, size_t len) -{ - assert(p == parser); - strlncat(messages[num_messages].body, - sizeof(messages[num_messages].body), - buf, - len); - messages[num_messages].body_size += len; - check_body_is_final(p); - // printf("body_cb: '%s'\n", requests[num_messages].body); - return 0; -} - -int -count_body_cb (http_parser *p, const char *buf, size_t len) -{ - assert(p == parser); - assert(buf); - messages[num_messages].body_size += len; - check_body_is_final(p); - return 0; -} - -int -message_begin_cb (http_parser *p) -{ - assert(p == parser); - messages[num_messages].message_begin_cb_called = TRUE; - return 0; -} - -int -headers_complete_cb (http_parser *p) -{ - assert(p == parser); - messages[num_messages].method = parser->method; - messages[num_messages].status_code = parser->status_code; - messages[num_messages].http_major = parser->http_major; - messages[num_messages].http_minor = parser->http_minor; - messages[num_messages].headers_complete_cb_called = TRUE; - messages[num_messages].should_keep_alive = http_should_keep_alive(parser); - return 0; -} - -int -message_complete_cb (http_parser *p) -{ - assert(p == parser); - if (messages[num_messages].should_keep_alive != http_should_keep_alive(parser)) - { - fprintf(stderr, "\n\n *** Error http_should_keep_alive() should have same " - "value in both on_message_complete and on_headers_complete " - "but it doesn't! ***\n\n"); - assert(0); - abort(); - } - - if (messages[num_messages].body_size && - http_body_is_final(p) && - !messages[num_messages].body_is_final) - { - fprintf(stderr, "\n\n *** Error http_body_is_final() should return 1 " - "on last on_body callback call " - "but it doesn't! ***\n\n"); - assert(0); - abort(); - } - - messages[num_messages].message_complete_cb_called = TRUE; - - messages[num_messages].message_complete_on_eof = currently_parsing_eof; - - num_messages++; - return 0; -} - -int -response_status_cb (http_parser *p, const char *buf, size_t len) -{ - assert(p == parser); - strlncat(messages[num_messages].response_status, - sizeof(messages[num_messages].response_status), - buf, - len); - return 0; -} - -int -chunk_header_cb (http_parser *p) -{ - assert(p == parser); - int chunk_idx = messages[num_messages].num_chunks; - messages[num_messages].num_chunks++; - if (chunk_idx < MAX_CHUNKS) { - messages[num_messages].chunk_lengths[chunk_idx] = p->content_length; - } - - return 0; -} - -int -chunk_complete_cb (http_parser *p) -{ - assert(p == parser); - - /* Here we want to verify that each chunk_header_cb is matched by a - * chunk_complete_cb, so not only should the total number of calls to - * both callbacks be the same, but they also should be interleaved - * properly */ - assert(messages[num_messages].num_chunks == - messages[num_messages].num_chunks_complete + 1); - - messages[num_messages].num_chunks_complete++; - return 0; -} - -/* These dontcall_* callbacks exist so that we can verify that when we're - * paused, no additional callbacks are invoked */ -int -dontcall_message_begin_cb (http_parser *p) -{ - if (p) { } // gcc - fprintf(stderr, "\n\n*** on_message_begin() called on paused parser ***\n\n"); - abort(); -} - -int -dontcall_header_field_cb (http_parser *p, const char *buf, size_t len) -{ - if (p || buf || len) { } // gcc - fprintf(stderr, "\n\n*** on_header_field() called on paused parser ***\n\n"); - abort(); -} - -int -dontcall_header_value_cb (http_parser *p, const char *buf, size_t len) -{ - if (p || buf || len) { } // gcc - fprintf(stderr, "\n\n*** on_header_value() called on paused parser ***\n\n"); - abort(); -} - -int -dontcall_request_url_cb (http_parser *p, const char *buf, size_t len) -{ - if (p || buf || len) { } // gcc - fprintf(stderr, "\n\n*** on_request_url() called on paused parser ***\n\n"); - abort(); -} - -int -dontcall_body_cb (http_parser *p, const char *buf, size_t len) -{ - if (p || buf || len) { } // gcc - fprintf(stderr, "\n\n*** on_body_cb() called on paused parser ***\n\n"); - abort(); -} - -int -dontcall_headers_complete_cb (http_parser *p) -{ - if (p) { } // gcc - fprintf(stderr, "\n\n*** on_headers_complete() called on paused " - "parser ***\n\n"); - abort(); -} - -int -dontcall_message_complete_cb (http_parser *p) -{ - if (p) { } // gcc - fprintf(stderr, "\n\n*** on_message_complete() called on paused " - "parser ***\n\n"); - abort(); -} - -int -dontcall_response_status_cb (http_parser *p, const char *buf, size_t len) -{ - if (p || buf || len) { } // gcc - fprintf(stderr, "\n\n*** on_status() called on paused parser ***\n\n"); - abort(); -} - -int -dontcall_chunk_header_cb (http_parser *p) -{ - if (p) { } // gcc - fprintf(stderr, "\n\n*** on_chunk_header() called on paused parser ***\n\n"); - exit(1); -} - -int -dontcall_chunk_complete_cb (http_parser *p) -{ - if (p) { } // gcc - fprintf(stderr, "\n\n*** on_chunk_complete() " - "called on paused parser ***\n\n"); - exit(1); -} - -static http_parser_settings settings_dontcall = - {.on_message_begin = dontcall_message_begin_cb - ,.on_header_field = dontcall_header_field_cb - ,.on_header_value = dontcall_header_value_cb - ,.on_url = dontcall_request_url_cb - ,.on_status = dontcall_response_status_cb - ,.on_body = dontcall_body_cb - ,.on_headers_complete = dontcall_headers_complete_cb - ,.on_message_complete = dontcall_message_complete_cb - ,.on_chunk_header = dontcall_chunk_header_cb - ,.on_chunk_complete = dontcall_chunk_complete_cb - }; - -/* These pause_* callbacks always pause the parser and just invoke the regular - * callback that tracks content. Before returning, we overwrite the parser - * settings to point to the _dontcall variety so that we can verify that - * the pause actually did, you know, pause. */ -int -pause_message_begin_cb (http_parser *p) -{ - http_parser_pause(p, 1); - *current_pause_parser = settings_dontcall; - return message_begin_cb(p); -} - -int -pause_header_field_cb (http_parser *p, const char *buf, size_t len) -{ - http_parser_pause(p, 1); - *current_pause_parser = settings_dontcall; - return header_field_cb(p, buf, len); -} - -int -pause_header_value_cb (http_parser *p, const char *buf, size_t len) -{ - http_parser_pause(p, 1); - *current_pause_parser = settings_dontcall; - return header_value_cb(p, buf, len); -} - -int -pause_request_url_cb (http_parser *p, const char *buf, size_t len) -{ - http_parser_pause(p, 1); - *current_pause_parser = settings_dontcall; - return request_url_cb(p, buf, len); -} - -int -pause_body_cb (http_parser *p, const char *buf, size_t len) -{ - http_parser_pause(p, 1); - *current_pause_parser = settings_dontcall; - return body_cb(p, buf, len); -} - -int -pause_headers_complete_cb (http_parser *p) -{ - http_parser_pause(p, 1); - *current_pause_parser = settings_dontcall; - return headers_complete_cb(p); -} - -int -pause_message_complete_cb (http_parser *p) -{ - http_parser_pause(p, 1); - *current_pause_parser = settings_dontcall; - return message_complete_cb(p); -} - -int -pause_response_status_cb (http_parser *p, const char *buf, size_t len) -{ - http_parser_pause(p, 1); - *current_pause_parser = settings_dontcall; - return response_status_cb(p, buf, len); -} - -int -pause_chunk_header_cb (http_parser *p) -{ - http_parser_pause(p, 1); - *current_pause_parser = settings_dontcall; - return chunk_header_cb(p); -} - -int -pause_chunk_complete_cb (http_parser *p) -{ - http_parser_pause(p, 1); - *current_pause_parser = settings_dontcall; - return chunk_complete_cb(p); -} - -static http_parser_settings settings_pause = - {.on_message_begin = pause_message_begin_cb - ,.on_header_field = pause_header_field_cb - ,.on_header_value = pause_header_value_cb - ,.on_url = pause_request_url_cb - ,.on_status = pause_response_status_cb - ,.on_body = pause_body_cb - ,.on_headers_complete = pause_headers_complete_cb - ,.on_message_complete = pause_message_complete_cb - ,.on_chunk_header = pause_chunk_header_cb - ,.on_chunk_complete = pause_chunk_complete_cb - }; - -static http_parser_settings settings = - {.on_message_begin = message_begin_cb - ,.on_header_field = header_field_cb - ,.on_header_value = header_value_cb - ,.on_url = request_url_cb - ,.on_status = response_status_cb - ,.on_body = body_cb - ,.on_headers_complete = headers_complete_cb - ,.on_message_complete = message_complete_cb - ,.on_chunk_header = chunk_header_cb - ,.on_chunk_complete = chunk_complete_cb - }; - -static http_parser_settings settings_count_body = - {.on_message_begin = message_begin_cb - ,.on_header_field = header_field_cb - ,.on_header_value = header_value_cb - ,.on_url = request_url_cb - ,.on_status = response_status_cb - ,.on_body = count_body_cb - ,.on_headers_complete = headers_complete_cb - ,.on_message_complete = message_complete_cb - ,.on_chunk_header = chunk_header_cb - ,.on_chunk_complete = chunk_complete_cb - }; - -static http_parser_settings settings_null = - {.on_message_begin = 0 - ,.on_header_field = 0 - ,.on_header_value = 0 - ,.on_url = 0 - ,.on_status = 0 - ,.on_body = 0 - ,.on_headers_complete = 0 - ,.on_message_complete = 0 - ,.on_chunk_header = 0 - ,.on_chunk_complete = 0 - }; - -void -parser_init (enum http_parser_type type) -{ - num_messages = 0; - - assert(parser == NULL); - - parser = malloc(sizeof(http_parser)); - - http_parser_init(parser, type); - - memset(&messages, 0, sizeof messages); - -} - -void -parser_free () -{ - assert(parser); - free(parser); - parser = NULL; -} - -size_t parse (const char *buf, size_t len) -{ - size_t nparsed; - currently_parsing_eof = (len == 0); - nparsed = http_parser_execute(parser, &settings, buf, len); - return nparsed; -} - -size_t parse_count_body (const char *buf, size_t len) -{ - size_t nparsed; - currently_parsing_eof = (len == 0); - nparsed = http_parser_execute(parser, &settings_count_body, buf, len); - return nparsed; -} - -size_t parse_pause (const char *buf, size_t len) -{ - size_t nparsed; - http_parser_settings s = settings_pause; - - currently_parsing_eof = (len == 0); - current_pause_parser = &s; - nparsed = http_parser_execute(parser, current_pause_parser, buf, len); - return nparsed; -} - -static inline int -check_str_eq (const struct message *m, - const char *prop, - const char *expected, - const char *found) { - if ((expected == NULL) != (found == NULL)) { - printf("\n*** Error: %s in '%s' ***\n\n", prop, m->name); - printf("expected %s\n", (expected == NULL) ? "NULL" : expected); - printf(" found %s\n", (found == NULL) ? "NULL" : found); - return 0; - } - if (expected != NULL && 0 != strcmp(expected, found)) { - printf("\n*** Error: %s in '%s' ***\n\n", prop, m->name); - printf("expected '%s'\n", expected); - printf(" found '%s'\n", found); - return 0; - } - return 1; -} - -static inline int -check_num_eq (const struct message *m, - const char *prop, - int expected, - int found) { - if (expected != found) { - printf("\n*** Error: %s in '%s' ***\n\n", prop, m->name); - printf("expected %d\n", expected); - printf(" found %d\n", found); - return 0; - } - return 1; -} - -#define MESSAGE_CHECK_STR_EQ(expected, found, prop) \ - if (!check_str_eq(expected, #prop, expected->prop, found->prop)) return 0 - -#define MESSAGE_CHECK_NUM_EQ(expected, found, prop) \ - if (!check_num_eq(expected, #prop, expected->prop, found->prop)) return 0 - -#define MESSAGE_CHECK_URL_EQ(u, expected, found, prop, fn) \ -do { \ - char ubuf[256]; \ - \ - if ((u)->field_set & (1 << (fn))) { \ - memcpy(ubuf, (found)->request_url + (u)->field_data[(fn)].off, \ - (u)->field_data[(fn)].len); \ - ubuf[(u)->field_data[(fn)].len] = '\0'; \ - } else { \ - ubuf[0] = '\0'; \ - } \ - \ - check_str_eq(expected, #prop, expected->prop, ubuf); \ -} while(0) - -int -message_eq (int index, const struct message *expected) -{ - int i; - struct message *m = &messages[index]; - - MESSAGE_CHECK_NUM_EQ(expected, m, http_major); - MESSAGE_CHECK_NUM_EQ(expected, m, http_minor); - - if (expected->type == HTTP_REQUEST) { - MESSAGE_CHECK_NUM_EQ(expected, m, method); - } else { - MESSAGE_CHECK_NUM_EQ(expected, m, status_code); - MESSAGE_CHECK_STR_EQ(expected, m, response_status); - } - - MESSAGE_CHECK_NUM_EQ(expected, m, should_keep_alive); - MESSAGE_CHECK_NUM_EQ(expected, m, message_complete_on_eof); - - assert(m->message_begin_cb_called); - assert(m->headers_complete_cb_called); - assert(m->message_complete_cb_called); - - - MESSAGE_CHECK_STR_EQ(expected, m, request_url); - - /* Check URL components; we can't do this w/ CONNECT since it doesn't - * send us a well-formed URL. - */ - if (*m->request_url && m->method != HTTP_CONNECT) { - struct http_parser_url u; - - if (http_parser_parse_url(m->request_url, strlen(m->request_url), 0, &u)) { - fprintf(stderr, "\n\n*** failed to parse URL %s ***\n\n", - m->request_url); - abort(); - } - - if (expected->host) { - MESSAGE_CHECK_URL_EQ(&u, expected, m, host, UF_HOST); - } - - if (expected->userinfo) { - MESSAGE_CHECK_URL_EQ(&u, expected, m, userinfo, UF_USERINFO); - } - - m->port = (u.field_set & (1 << UF_PORT)) ? - u.port : 0; - - MESSAGE_CHECK_URL_EQ(&u, expected, m, query_string, UF_QUERY); - MESSAGE_CHECK_URL_EQ(&u, expected, m, fragment, UF_FRAGMENT); - MESSAGE_CHECK_URL_EQ(&u, expected, m, request_path, UF_PATH); - MESSAGE_CHECK_NUM_EQ(expected, m, port); - } - - if (expected->body_size) { - MESSAGE_CHECK_NUM_EQ(expected, m, body_size); - } else { - MESSAGE_CHECK_STR_EQ(expected, m, body); - } - - assert(m->num_chunks == m->num_chunks_complete); - MESSAGE_CHECK_NUM_EQ(expected, m, num_chunks_complete); - for (i = 0; i < m->num_chunks && i < MAX_CHUNKS; i++) { - MESSAGE_CHECK_NUM_EQ(expected, m, chunk_lengths[i]); - } - - MESSAGE_CHECK_NUM_EQ(expected, m, num_headers); - - int r; - for (i = 0; i < m->num_headers; i++) { - r = check_str_eq(expected, "header field", expected->headers[i][0], m->headers[i][0]); - if (!r) return 0; - r = check_str_eq(expected, "header value", expected->headers[i][1], m->headers[i][1]); - if (!r) return 0; - } - - MESSAGE_CHECK_STR_EQ(expected, m, upgrade); - - return 1; -} - -/* Given a sequence of varargs messages, return the number of them that the - * parser should successfully parse, taking into account that upgraded - * messages prevent all subsequent messages from being parsed. - */ -size_t -count_parsed_messages(const size_t nmsgs, ...) { - size_t i; - va_list ap; - - va_start(ap, nmsgs); - - for (i = 0; i < nmsgs; i++) { - struct message *m = va_arg(ap, struct message *); - - if (m->upgrade) { - va_end(ap); - return i + 1; - } - } - - va_end(ap); - return nmsgs; -} - -/* Given a sequence of bytes and the number of these that we were able to - * parse, verify that upgrade bodies are correct. - */ -void -upgrade_message_fix(char *body, const size_t nread, const size_t nmsgs, ...) { - va_list ap; - size_t i; - size_t off = 0; - - va_start(ap, nmsgs); - - for (i = 0; i < nmsgs; i++) { - struct message *m = va_arg(ap, struct message *); - - off += strlen(m->raw); - - if (m->upgrade) { - off -= strlen(m->upgrade); - - /* Check the portion of the response after its specified upgrade */ - if (!check_str_eq(m, "upgrade", body + off, body + nread)) { - abort(); - } - - /* Fix up the response so that message_eq() will verify the beginning - * of the upgrade */ - *(body + nread + strlen(m->upgrade)) = '\0'; - messages[num_messages -1 ].upgrade = body + nread; - - va_end(ap); - return; - } - } - - va_end(ap); - printf("\n\n*** Error: expected a message with upgrade ***\n"); - - abort(); -} - -static void -print_error (const char *raw, size_t error_location) -{ - fprintf(stderr, "\n*** %s ***\n\n", - http_errno_description(HTTP_PARSER_ERRNO(parser))); - - int this_line = 0, char_len = 0; - size_t i, j, len = strlen(raw), error_location_line = 0; - for (i = 0; i < len; i++) { - if (i == error_location) this_line = 1; - switch (raw[i]) { - case '\r': - char_len = 2; - fprintf(stderr, "\\r"); - break; - - case '\n': - fprintf(stderr, "\\n\n"); - - if (this_line) goto print; - - error_location_line = 0; - continue; - - default: - char_len = 1; - fputc(raw[i], stderr); - break; - } - if (!this_line) error_location_line += char_len; - } - - fprintf(stderr, "[eof]\n"); - - print: - for (j = 0; j < error_location_line; j++) { - fputc(' ', stderr); - } - fprintf(stderr, "^\n\nerror location: %u\n", (unsigned int)error_location); -} - -void -test_preserve_data (void) -{ - char my_data[] = "application-specific data"; - http_parser parser; - parser.data = my_data; - http_parser_init(&parser, HTTP_REQUEST); - if (parser.data != my_data) { - printf("\n*** parser.data not preserved accross http_parser_init ***\n\n"); - abort(); - } -} - -struct url_test { - const char *name; - const char *url; - int is_connect; - struct http_parser_url u; - int rv; -}; - -const struct url_test url_tests[] = -{ {.name="proxy request" - ,.url="http://hostname/" - ,.is_connect=0 - ,.u= - {.field_set=(1 << UF_SCHEMA) | (1 << UF_HOST) | (1 << UF_PATH) - ,.port=0 - ,.field_data= - {{ 0, 4 } /* UF_SCHEMA */ - ,{ 7, 8 } /* UF_HOST */ - ,{ 0, 0 } /* UF_PORT */ - ,{ 15, 1 } /* UF_PATH */ - ,{ 0, 0 } /* UF_QUERY */ - ,{ 0, 0 } /* UF_FRAGMENT */ - ,{ 0, 0 } /* UF_USERINFO */ - } - } - ,.rv=0 - } - -, {.name="proxy request with port" - ,.url="http://hostname:444/" - ,.is_connect=0 - ,.u= - {.field_set=(1 << UF_SCHEMA) | (1 << UF_HOST) | (1 << UF_PORT) | (1 << UF_PATH) - ,.port=444 - ,.field_data= - {{ 0, 4 } /* UF_SCHEMA */ - ,{ 7, 8 } /* UF_HOST */ - ,{ 16, 3 } /* UF_PORT */ - ,{ 19, 1 } /* UF_PATH */ - ,{ 0, 0 } /* UF_QUERY */ - ,{ 0, 0 } /* UF_FRAGMENT */ - ,{ 0, 0 } /* UF_USERINFO */ - } - } - ,.rv=0 - } - -, {.name="CONNECT request" - ,.url="hostname:443" - ,.is_connect=1 - ,.u= - {.field_set=(1 << UF_HOST) | (1 << UF_PORT) - ,.port=443 - ,.field_data= - {{ 0, 0 } /* UF_SCHEMA */ - ,{ 0, 8 } /* UF_HOST */ - ,{ 9, 3 } /* UF_PORT */ - ,{ 0, 0 } /* UF_PATH */ - ,{ 0, 0 } /* UF_QUERY */ - ,{ 0, 0 } /* UF_FRAGMENT */ - ,{ 0, 0 } /* UF_USERINFO */ - } - } - ,.rv=0 - } - -, {.name="CONNECT request but not connect" - ,.url="hostname:443" - ,.is_connect=0 - ,.rv=1 - } - -, {.name="proxy ipv6 request" - ,.url="http://[1:2::3:4]/" - ,.is_connect=0 - ,.u= - {.field_set=(1 << UF_SCHEMA) | (1 << UF_HOST) | (1 << UF_PATH) - ,.port=0 - ,.field_data= - {{ 0, 4 } /* UF_SCHEMA */ - ,{ 8, 8 } /* UF_HOST */ - ,{ 0, 0 } /* UF_PORT */ - ,{ 17, 1 } /* UF_PATH */ - ,{ 0, 0 } /* UF_QUERY */ - ,{ 0, 0 } /* UF_FRAGMENT */ - ,{ 0, 0 } /* UF_USERINFO */ - } - } - ,.rv=0 - } - -, {.name="proxy ipv6 request with port" - ,.url="http://[1:2::3:4]:67/" - ,.is_connect=0 - ,.u= - {.field_set=(1 << UF_SCHEMA) | (1 << UF_HOST) | (1 << UF_PORT) | (1 << UF_PATH) - ,.port=67 - ,.field_data= - {{ 0, 4 } /* UF_SCHEMA */ - ,{ 8, 8 } /* UF_HOST */ - ,{ 18, 2 } /* UF_PORT */ - ,{ 20, 1 } /* UF_PATH */ - ,{ 0, 0 } /* UF_QUERY */ - ,{ 0, 0 } /* UF_FRAGMENT */ - ,{ 0, 0 } /* UF_USERINFO */ - } - } - ,.rv=0 - } - -, {.name="CONNECT ipv6 address" - ,.url="[1:2::3:4]:443" - ,.is_connect=1 - ,.u= - {.field_set=(1 << UF_HOST) | (1 << UF_PORT) - ,.port=443 - ,.field_data= - {{ 0, 0 } /* UF_SCHEMA */ - ,{ 1, 8 } /* UF_HOST */ - ,{ 11, 3 } /* UF_PORT */ - ,{ 0, 0 } /* UF_PATH */ - ,{ 0, 0 } /* UF_QUERY */ - ,{ 0, 0 } /* UF_FRAGMENT */ - ,{ 0, 0 } /* UF_USERINFO */ - } - } - ,.rv=0 - } - -, {.name="ipv4 in ipv6 address" - ,.url="http://[2001:0000:0000:0000:0000:0000:1.9.1.1]/" - ,.is_connect=0 - ,.u= - {.field_set=(1 << UF_SCHEMA) | (1 << UF_HOST) | (1 << UF_PATH) - ,.port=0 - ,.field_data= - {{ 0, 4 } /* UF_SCHEMA */ - ,{ 8, 37 } /* UF_HOST */ - ,{ 0, 0 } /* UF_PORT */ - ,{ 46, 1 } /* UF_PATH */ - ,{ 0, 0 } /* UF_QUERY */ - ,{ 0, 0 } /* UF_FRAGMENT */ - ,{ 0, 0 } /* UF_USERINFO */ - } - } - ,.rv=0 - } - -, {.name="extra ? in query string" - ,.url="http://a.tbcdn.cn/p/fp/2010c/??fp-header-min.css,fp-base-min.css," - "fp-channel-min.css,fp-product-min.css,fp-mall-min.css,fp-category-min.css," - "fp-sub-min.css,fp-gdp4p-min.css,fp-css3-min.css,fp-misc-min.css?t=20101022.css" - ,.is_connect=0 - ,.u= - {.field_set=(1<field_set, u->port); - for (i = 0; i < UF_MAX; i++) { - if ((u->field_set & (1 << i)) == 0) { - printf("\tfield_data[%u]: unset\n", i); - continue; - } - - printf("\tfield_data[%u]: off: %u len: %u part: \"%.*s\n\"", - i, - u->field_data[i].off, - u->field_data[i].len, - u->field_data[i].len, - url + u->field_data[i].off); - } -} - -void -test_parse_url (void) -{ - struct http_parser_url u; - const struct url_test *test; - unsigned int i; - int rv; - - for (i = 0; i < (sizeof(url_tests) / sizeof(url_tests[0])); i++) { - test = &url_tests[i]; - memset(&u, 0, sizeof(u)); - - rv = http_parser_parse_url(test->url, - strlen(test->url), - test->is_connect, - &u); - - if (test->rv == 0) { - if (rv != 0) { - printf("\n*** http_parser_parse_url(\"%s\") \"%s\" test failed, " - "unexpected rv %d ***\n\n", test->url, test->name, rv); - abort(); - } - - if (memcmp(&u, &test->u, sizeof(u)) != 0) { - printf("\n*** http_parser_parse_url(\"%s\") \"%s\" failed ***\n", - test->url, test->name); - - printf("target http_parser_url:\n"); - dump_url(test->url, &test->u); - printf("result http_parser_url:\n"); - dump_url(test->url, &u); - - abort(); - } - } else { - /* test->rv != 0 */ - if (rv == 0) { - printf("\n*** http_parser_parse_url(\"%s\") \"%s\" test failed, " - "unexpected rv %d ***\n\n", test->url, test->name, rv); - abort(); - } - } - } -} - -void -test_method_str (void) -{ - assert(0 == strcmp("GET", http_method_str(HTTP_GET))); - assert(0 == strcmp("", http_method_str(1337))); -} - -void -test_message (const struct message *message) -{ - size_t raw_len = strlen(message->raw); - size_t msg1len; - for (msg1len = 0; msg1len < raw_len; msg1len++) { - parser_init(message->type); - - size_t read; - const char *msg1 = message->raw; - const char *msg2 = msg1 + msg1len; - size_t msg2len = raw_len - msg1len; - - if (msg1len) { - read = parse(msg1, msg1len); - - if (message->upgrade && parser->upgrade && num_messages > 0) { - messages[num_messages - 1].upgrade = msg1 + read; - goto test; - } - - if (read != msg1len) { - print_error(msg1, read); - abort(); - } - } - - - read = parse(msg2, msg2len); - - if (message->upgrade && parser->upgrade) { - messages[num_messages - 1].upgrade = msg2 + read; - goto test; - } - - if (read != msg2len) { - print_error(msg2, read); - abort(); - } - - read = parse(NULL, 0); - - if (read != 0) { - print_error(message->raw, read); - abort(); - } - - test: - - if (num_messages != 1) { - printf("\n*** num_messages != 1 after testing '%s' ***\n\n", message->name); - abort(); - } - - if(!message_eq(0, message)) abort(); - - parser_free(); - } -} - -void -test_message_count_body (const struct message *message) -{ - parser_init(message->type); - - size_t read; - size_t l = strlen(message->raw); - size_t i, toread; - size_t chunk = 4024; - - for (i = 0; i < l; i+= chunk) { - toread = MIN(l-i, chunk); - read = parse_count_body(message->raw + i, toread); - if (read != toread) { - print_error(message->raw, read); - abort(); - } - } - - - read = parse_count_body(NULL, 0); - if (read != 0) { - print_error(message->raw, read); - abort(); - } - - if (num_messages != 1) { - printf("\n*** num_messages != 1 after testing '%s' ***\n\n", message->name); - abort(); - } - - if(!message_eq(0, message)) abort(); - - parser_free(); -} - -void -test_simple (const char *buf, enum http_errno err_expected) -{ - parser_init(HTTP_REQUEST); - - enum http_errno err; - - parse(buf, strlen(buf)); - err = HTTP_PARSER_ERRNO(parser); - parse(NULL, 0); - - parser_free(); - - /* In strict mode, allow us to pass with an unexpected HPE_STRICT as - * long as the caller isn't expecting success. - */ -#if HTTP_PARSER_STRICT - if (err_expected != err && err_expected != HPE_OK && err != HPE_STRICT) { -#else - if (err_expected != err) { -#endif - fprintf(stderr, "\n*** test_simple expected %s, but saw %s ***\n\n%s\n", - http_errno_name(err_expected), http_errno_name(err), buf); - abort(); - } -} - -void -test_invalid_header_content (int req, const char* str) -{ - http_parser parser; - http_parser_init(&parser, req ? HTTP_REQUEST : HTTP_RESPONSE); - size_t parsed; - const char *buf; - buf = req ? - "GET / HTTP/1.1\r\n" : - "HTTP/1.1 200 OK\r\n"; - parsed = http_parser_execute(&parser, &settings_null, buf, strlen(buf)); - assert(parsed == strlen(buf)); - - buf = str; - size_t buflen = strlen(buf); - - parsed = http_parser_execute(&parser, &settings_null, buf, buflen); - if (parsed != buflen) { - assert(HTTP_PARSER_ERRNO(&parser) == HPE_INVALID_HEADER_TOKEN); - return; - } - - fprintf(stderr, - "\n*** Error expected but none in invalid header content test ***\n"); - abort(); -} - -void -test_invalid_header_field_content_error (int req) -{ - test_invalid_header_content(req, "Foo: F\01ailure"); - test_invalid_header_content(req, "Foo: B\02ar"); -} - -void -test_invalid_header_field (int req, const char* str) -{ - http_parser parser; - http_parser_init(&parser, req ? HTTP_REQUEST : HTTP_RESPONSE); - size_t parsed; - const char *buf; - buf = req ? - "GET / HTTP/1.1\r\n" : - "HTTP/1.1 200 OK\r\n"; - parsed = http_parser_execute(&parser, &settings_null, buf, strlen(buf)); - assert(parsed == strlen(buf)); - - buf = str; - size_t buflen = strlen(buf); - - parsed = http_parser_execute(&parser, &settings_null, buf, buflen); - if (parsed != buflen) { - assert(HTTP_PARSER_ERRNO(&parser) == HPE_INVALID_HEADER_TOKEN); - return; - } - - fprintf(stderr, - "\n*** Error expected but none in invalid header token test ***\n"); - abort(); -} - -void -test_invalid_header_field_token_error (int req) -{ - test_invalid_header_field(req, "Fo@: Failure"); - test_invalid_header_field(req, "Foo\01\test: Bar"); -} - -void -test_double_content_length_error (int req) -{ - http_parser parser; - http_parser_init(&parser, req ? HTTP_REQUEST : HTTP_RESPONSE); - size_t parsed; - const char *buf; - buf = req ? - "GET / HTTP/1.1\r\n" : - "HTTP/1.1 200 OK\r\n"; - parsed = http_parser_execute(&parser, &settings_null, buf, strlen(buf)); - assert(parsed == strlen(buf)); - - buf = "Content-Length: 0\r\nContent-Length: 1\r\n\r\n"; - size_t buflen = strlen(buf); - - parsed = http_parser_execute(&parser, &settings_null, buf, buflen); - if (parsed != buflen) { - assert(HTTP_PARSER_ERRNO(&parser) == HPE_UNEXPECTED_CONTENT_LENGTH); - return; - } - - fprintf(stderr, - "\n*** Error expected but none in double content-length test ***\n"); - abort(); -} - -void -test_chunked_content_length_error (int req) -{ - http_parser parser; - http_parser_init(&parser, req ? HTTP_REQUEST : HTTP_RESPONSE); - size_t parsed; - const char *buf; - buf = req ? - "GET / HTTP/1.1\r\n" : - "HTTP/1.1 200 OK\r\n"; - parsed = http_parser_execute(&parser, &settings_null, buf, strlen(buf)); - assert(parsed == strlen(buf)); - - buf = "Transfer-Encoding: chunked\r\nContent-Length: 1\r\n\r\n"; - size_t buflen = strlen(buf); - - parsed = http_parser_execute(&parser, &settings_null, buf, buflen); - if (parsed != buflen) { - assert(HTTP_PARSER_ERRNO(&parser) == HPE_UNEXPECTED_CONTENT_LENGTH); - return; - } - - fprintf(stderr, - "\n*** Error expected but none in chunked content-length test ***\n"); - abort(); -} - -void -test_header_cr_no_lf_error (int req) -{ - http_parser parser; - http_parser_init(&parser, req ? HTTP_REQUEST : HTTP_RESPONSE); - size_t parsed; - const char *buf; - buf = req ? - "GET / HTTP/1.1\r\n" : - "HTTP/1.1 200 OK\r\n"; - parsed = http_parser_execute(&parser, &settings_null, buf, strlen(buf)); - assert(parsed == strlen(buf)); - - buf = "Foo: 1\rBar: 1\r\n\r\n"; - size_t buflen = strlen(buf); - - parsed = http_parser_execute(&parser, &settings_null, buf, buflen); - if (parsed != buflen) { - assert(HTTP_PARSER_ERRNO(&parser) == HPE_LF_EXPECTED); - return; - } - - fprintf(stderr, - "\n*** Error expected but none in header whitespace test ***\n"); - abort(); -} - -void -test_header_overflow_error (int req) -{ - http_parser parser; - http_parser_init(&parser, req ? HTTP_REQUEST : HTTP_RESPONSE); - size_t parsed; - const char *buf; - buf = req ? "GET / HTTP/1.1\r\n" : "HTTP/1.0 200 OK\r\n"; - parsed = http_parser_execute(&parser, &settings_null, buf, strlen(buf)); - assert(parsed == strlen(buf)); - - buf = "header-key: header-value\r\n"; - size_t buflen = strlen(buf); - - int i; - for (i = 0; i < 10000; i++) { - parsed = http_parser_execute(&parser, &settings_null, buf, buflen); - if (parsed != buflen) { - //fprintf(stderr, "error found on iter %d\n", i); - assert(HTTP_PARSER_ERRNO(&parser) == HPE_HEADER_OVERFLOW); - return; - } - } - - fprintf(stderr, "\n*** Error expected but none in header overflow test ***\n"); - abort(); -} - - -void -test_header_nread_value () -{ - http_parser parser; - http_parser_init(&parser, HTTP_REQUEST); - size_t parsed; - const char *buf; - buf = "GET / HTTP/1.1\r\nheader: value\nhdr: value\r\n"; - parsed = http_parser_execute(&parser, &settings_null, buf, strlen(buf)); - assert(parsed == strlen(buf)); - - assert(parser.nread == strlen(buf)); -} - - -static void -test_content_length_overflow (const char *buf, size_t buflen, int expect_ok) -{ - http_parser parser; - http_parser_init(&parser, HTTP_RESPONSE); - http_parser_execute(&parser, &settings_null, buf, buflen); - - if (expect_ok) - assert(HTTP_PARSER_ERRNO(&parser) == HPE_OK); - else - assert(HTTP_PARSER_ERRNO(&parser) == HPE_INVALID_CONTENT_LENGTH); -} - -void -test_header_content_length_overflow_error (void) -{ -#define X(size) \ - "HTTP/1.1 200 OK\r\n" \ - "Content-Length: " #size "\r\n" \ - "\r\n" - const char a[] = X(1844674407370955160); /* 2^64 / 10 - 1 */ - const char b[] = X(18446744073709551615); /* 2^64-1 */ - const char c[] = X(18446744073709551616); /* 2^64 */ -#undef X - test_content_length_overflow(a, sizeof(a) - 1, 1); /* expect ok */ - test_content_length_overflow(b, sizeof(b) - 1, 0); /* expect failure */ - test_content_length_overflow(c, sizeof(c) - 1, 0); /* expect failure */ -} - -void -test_chunk_content_length_overflow_error (void) -{ -#define X(size) \ - "HTTP/1.1 200 OK\r\n" \ - "Transfer-Encoding: chunked\r\n" \ - "\r\n" \ - #size "\r\n" \ - "..." - const char a[] = X(FFFFFFFFFFFFFFE); /* 2^64 / 16 - 1 */ - const char b[] = X(FFFFFFFFFFFFFFFF); /* 2^64-1 */ - const char c[] = X(10000000000000000); /* 2^64 */ -#undef X - test_content_length_overflow(a, sizeof(a) - 1, 1); /* expect ok */ - test_content_length_overflow(b, sizeof(b) - 1, 0); /* expect failure */ - test_content_length_overflow(c, sizeof(c) - 1, 0); /* expect failure */ -} - -void -test_no_overflow_long_body (int req, size_t length) -{ - http_parser parser; - http_parser_init(&parser, req ? HTTP_REQUEST : HTTP_RESPONSE); - size_t parsed; - size_t i; - char buf1[3000]; - size_t buf1len = sprintf(buf1, "%s\r\nConnection: Keep-Alive\r\nContent-Length: %lu\r\n\r\n", - req ? "POST / HTTP/1.0" : "HTTP/1.0 200 OK", (unsigned long)length); - parsed = http_parser_execute(&parser, &settings_null, buf1, buf1len); - if (parsed != buf1len) - goto err; - - for (i = 0; i < length; i++) { - char foo = 'a'; - parsed = http_parser_execute(&parser, &settings_null, &foo, 1); - if (parsed != 1) - goto err; - } - - parsed = http_parser_execute(&parser, &settings_null, buf1, buf1len); - if (parsed != buf1len) goto err; - return; - - err: - fprintf(stderr, - "\n*** error in test_no_overflow_long_body %s of length %lu ***\n", - req ? "REQUEST" : "RESPONSE", - (unsigned long)length); - abort(); -} - -void -test_multiple3 (const struct message *r1, const struct message *r2, const struct message *r3) -{ - int message_count = count_parsed_messages(3, r1, r2, r3); - - char total[ strlen(r1->raw) - + strlen(r2->raw) - + strlen(r3->raw) - + 1 - ]; - total[0] = '\0'; - - strcat(total, r1->raw); - strcat(total, r2->raw); - strcat(total, r3->raw); - - parser_init(r1->type); - - size_t read; - - read = parse(total, strlen(total)); - - if (parser->upgrade) { - upgrade_message_fix(total, read, 3, r1, r2, r3); - goto test; - } - - if (read != strlen(total)) { - print_error(total, read); - abort(); - } - - read = parse(NULL, 0); - - if (read != 0) { - print_error(total, read); - abort(); - } - -test: - - if (message_count != num_messages) { - fprintf(stderr, "\n\n*** Parser didn't see 3 messages only %d *** \n", num_messages); - abort(); - } - - if (!message_eq(0, r1)) abort(); - if (message_count > 1 && !message_eq(1, r2)) abort(); - if (message_count > 2 && !message_eq(2, r3)) abort(); - - parser_free(); -} - -/* SCAN through every possible breaking to make sure the - * parser can handle getting the content in any chunks that - * might come from the socket - */ -void -test_scan (const struct message *r1, const struct message *r2, const struct message *r3) -{ - char total[80*1024] = "\0"; - char buf1[80*1024] = "\0"; - char buf2[80*1024] = "\0"; - char buf3[80*1024] = "\0"; - - strcat(total, r1->raw); - strcat(total, r2->raw); - strcat(total, r3->raw); - - size_t read; - - int total_len = strlen(total); - - int total_ops = 2 * (total_len - 1) * (total_len - 2) / 2; - int ops = 0 ; - - size_t buf1_len, buf2_len, buf3_len; - int message_count = count_parsed_messages(3, r1, r2, r3); - - int i,j,type_both; - for (type_both = 0; type_both < 2; type_both ++ ) { - for (j = 2; j < total_len; j ++ ) { - for (i = 1; i < j; i ++ ) { - - if (ops % 1000 == 0) { - printf("\b\b\b\b%3.0f%%", 100 * (float)ops /(float)total_ops); - fflush(stdout); - } - ops += 1; - - parser_init(type_both ? HTTP_BOTH : r1->type); - - buf1_len = i; - strlncpy(buf1, sizeof(buf1), total, buf1_len); - buf1[buf1_len] = 0; - - buf2_len = j - i; - strlncpy(buf2, sizeof(buf1), total+i, buf2_len); - buf2[buf2_len] = 0; - - buf3_len = total_len - j; - strlncpy(buf3, sizeof(buf1), total+j, buf3_len); - buf3[buf3_len] = 0; - - read = parse(buf1, buf1_len); - - if (parser->upgrade) goto test; - - if (read != buf1_len) { - print_error(buf1, read); - goto error; - } - - read += parse(buf2, buf2_len); - - if (parser->upgrade) goto test; - - if (read != buf1_len + buf2_len) { - print_error(buf2, read); - goto error; - } - - read += parse(buf3, buf3_len); - - if (parser->upgrade) goto test; - - if (read != buf1_len + buf2_len + buf3_len) { - print_error(buf3, read); - goto error; - } - - parse(NULL, 0); - -test: - if (parser->upgrade) { - upgrade_message_fix(total, read, 3, r1, r2, r3); - } - - if (message_count != num_messages) { - fprintf(stderr, "\n\nParser didn't see %d messages only %d\n", - message_count, num_messages); - goto error; - } - - if (!message_eq(0, r1)) { - fprintf(stderr, "\n\nError matching messages[0] in test_scan.\n"); - goto error; - } - - if (message_count > 1 && !message_eq(1, r2)) { - fprintf(stderr, "\n\nError matching messages[1] in test_scan.\n"); - goto error; - } - - if (message_count > 2 && !message_eq(2, r3)) { - fprintf(stderr, "\n\nError matching messages[2] in test_scan.\n"); - goto error; - } - - parser_free(); - } - } - } - puts("\b\b\b\b100%"); - return; - - error: - fprintf(stderr, "i=%d j=%d\n", i, j); - fprintf(stderr, "buf1 (%u) %s\n\n", (unsigned int)buf1_len, buf1); - fprintf(stderr, "buf2 (%u) %s\n\n", (unsigned int)buf2_len , buf2); - fprintf(stderr, "buf3 (%u) %s\n", (unsigned int)buf3_len, buf3); - abort(); -} - -// user required to free the result -// string terminated by \0 -char * -create_large_chunked_message (int body_size_in_kb, const char* headers) -{ - int i; - size_t wrote = 0; - size_t headers_len = strlen(headers); - size_t bufsize = headers_len + (5+1024+2)*body_size_in_kb + 6; - char * buf = malloc(bufsize); - - memcpy(buf, headers, headers_len); - wrote += headers_len; - - for (i = 0; i < body_size_in_kb; i++) { - // write 1kb chunk into the body. - memcpy(buf + wrote, "400\r\n", 5); - wrote += 5; - memset(buf + wrote, 'C', 1024); - wrote += 1024; - strcpy(buf + wrote, "\r\n"); - wrote += 2; - } - - memcpy(buf + wrote, "0\r\n\r\n", 6); - wrote += 6; - assert(wrote == bufsize); - - return buf; -} - -/* Verify that we can pause parsing at any of the bytes in the - * message and still get the result that we're expecting. */ -void -test_message_pause (const struct message *msg) -{ - char *buf = (char*) msg->raw; - size_t buflen = strlen(msg->raw); - size_t nread; - - parser_init(msg->type); - - do { - nread = parse_pause(buf, buflen); - - // We can only set the upgrade buffer once we've gotten our message - // completion callback. - if (messages[0].message_complete_cb_called && - msg->upgrade && - parser->upgrade) { - messages[0].upgrade = buf + nread; - goto test; - } - - if (nread < buflen) { - - // Not much do to if we failed a strict-mode check - if (HTTP_PARSER_ERRNO(parser) == HPE_STRICT) { - parser_free(); - return; - } - - assert (HTTP_PARSER_ERRNO(parser) == HPE_PAUSED); - } - - buf += nread; - buflen -= nread; - http_parser_pause(parser, 0); - } while (buflen > 0); - - nread = parse_pause(NULL, 0); - assert (nread == 0); - -test: - if (num_messages != 1) { - printf("\n*** num_messages != 1 after testing '%s' ***\n\n", msg->name); - abort(); - } - - if(!message_eq(0, msg)) abort(); - - parser_free(); -} - -int -main (void) -{ - parser = NULL; - int i, j, k; - int request_count; - int response_count; - unsigned long version; - unsigned major; - unsigned minor; - unsigned patch; - - version = http_parser_version(); - major = (version >> 16) & 255; - minor = (version >> 8) & 255; - patch = version & 255; - printf("http_parser v%u.%u.%u (0x%06lx)\n", major, minor, patch, version); - - printf("sizeof(http_parser) = %u\n", (unsigned int)sizeof(http_parser)); - - for (request_count = 0; requests[request_count].name; request_count++); - for (response_count = 0; responses[response_count].name; response_count++); - - //// API - test_preserve_data(); - test_parse_url(); - test_method_str(); - - //// NREAD - test_header_nread_value(); - - //// OVERFLOW CONDITIONS - - test_header_overflow_error(HTTP_REQUEST); - test_no_overflow_long_body(HTTP_REQUEST, 1000); - test_no_overflow_long_body(HTTP_REQUEST, 100000); - - test_header_overflow_error(HTTP_RESPONSE); - test_no_overflow_long_body(HTTP_RESPONSE, 1000); - test_no_overflow_long_body(HTTP_RESPONSE, 100000); - - test_header_content_length_overflow_error(); - test_chunk_content_length_overflow_error(); - - //// HEADER FIELD CONDITIONS - test_double_content_length_error(HTTP_REQUEST); - test_chunked_content_length_error(HTTP_REQUEST); - test_header_cr_no_lf_error(HTTP_REQUEST); - test_invalid_header_field_token_error(HTTP_REQUEST); - test_invalid_header_field_content_error(HTTP_REQUEST); - test_double_content_length_error(HTTP_RESPONSE); - test_chunked_content_length_error(HTTP_RESPONSE); - test_header_cr_no_lf_error(HTTP_RESPONSE); - test_invalid_header_field_token_error(HTTP_RESPONSE); - test_invalid_header_field_content_error(HTTP_RESPONSE); - - //// RESPONSES - - for (i = 0; i < response_count; i++) { - test_message(&responses[i]); - } - - for (i = 0; i < response_count; i++) { - test_message_pause(&responses[i]); - } - - for (i = 0; i < response_count; i++) { - if (!responses[i].should_keep_alive) continue; - for (j = 0; j < response_count; j++) { - if (!responses[j].should_keep_alive) continue; - for (k = 0; k < response_count; k++) { - test_multiple3(&responses[i], &responses[j], &responses[k]); - } - } - } - - test_message_count_body(&responses[NO_HEADERS_NO_BODY_404]); - test_message_count_body(&responses[TRAILING_SPACE_ON_CHUNKED_BODY]); - - // test very large chunked response - { - char * msg = create_large_chunked_message(31337, - "HTTP/1.0 200 OK\r\n" - "Transfer-Encoding: chunked\r\n" - "Content-Type: text/plain\r\n" - "\r\n"); - struct message large_chunked = - {.name= "large chunked" - ,.type= HTTP_RESPONSE - ,.raw= msg - ,.should_keep_alive= FALSE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 0 - ,.status_code= 200 - ,.response_status= "OK" - ,.num_headers= 2 - ,.headers= - { { "Transfer-Encoding", "chunked" } - , { "Content-Type", "text/plain" } - } - ,.body_size= 31337*1024 - ,.num_chunks_complete= 31338 - }; - for (i = 0; i < MAX_CHUNKS; i++) { - large_chunked.chunk_lengths[i] = 1024; - } - test_message_count_body(&large_chunked); - free(msg); - } - - - - printf("response scan 1/2 "); - test_scan( &responses[TRAILING_SPACE_ON_CHUNKED_BODY] - , &responses[NO_BODY_HTTP10_KA_204] - , &responses[NO_REASON_PHRASE] - ); - - printf("response scan 2/2 "); - test_scan( &responses[BONJOUR_MADAME_FR] - , &responses[UNDERSTORE_HEADER_KEY] - , &responses[NO_CARRIAGE_RET] - ); - - puts("responses okay"); - - - /// REQUESTS - - test_simple("GET / HTP/1.1\r\n\r\n", HPE_INVALID_VERSION); - - // Extended characters - see nodejs/test/parallel/test-http-headers-obstext.js - test_simple("GET / HTTP/1.1\r\n" - "Test: Düsseldorf\r\n", - HPE_OK); - - // Well-formed but incomplete - test_simple("GET / HTTP/1.1\r\n" - "Content-Type: text/plain\r\n" - "Content-Length: 6\r\n" - "\r\n" - "fooba", - HPE_OK); - - static const char *all_methods[] = { - "DELETE", - "GET", - "HEAD", - "POST", - "PUT", - //"CONNECT", //CONNECT can't be tested like other methods, it's a tunnel - "OPTIONS", - "TRACE", - "COPY", - "LOCK", - "MKCOL", - "MOVE", - "PROPFIND", - "PROPPATCH", - "SEARCH", - "UNLOCK", - "BIND", - "REBIND", - "UNBIND", - "ACL", - "REPORT", - "MKACTIVITY", - "CHECKOUT", - "MERGE", - "M-SEARCH", - "NOTIFY", - "SUBSCRIBE", - "UNSUBSCRIBE", - "PATCH", - "PURGE", - "MKCALENDAR", - "LINK", - "UNLINK", - 0 }; - const char **this_method; - for (this_method = all_methods; *this_method; this_method++) { - char buf[200]; - sprintf(buf, "%s / HTTP/1.1\r\n\r\n", *this_method); - test_simple(buf, HPE_OK); - } - - static const char *bad_methods[] = { - "ASDF", - "C******", - "COLA", - "GEM", - "GETA", - "M****", - "MKCOLA", - "PROPPATCHA", - "PUN", - "PX", - "SA", - "hello world", - 0 }; - for (this_method = bad_methods; *this_method; this_method++) { - char buf[200]; - sprintf(buf, "%s / HTTP/1.1\r\n\r\n", *this_method); - test_simple(buf, HPE_INVALID_METHOD); - } - - // illegal header field name line folding - test_simple("GET / HTTP/1.1\r\n" - "name\r\n" - " : value\r\n" - "\r\n", - HPE_INVALID_HEADER_TOKEN); - - const char *dumbfuck2 = - "GET / HTTP/1.1\r\n" - "X-SSL-Bullshit: -----BEGIN CERTIFICATE-----\r\n" - "\tMIIFbTCCBFWgAwIBAgICH4cwDQYJKoZIhvcNAQEFBQAwcDELMAkGA1UEBhMCVUsx\r\n" - "\tETAPBgNVBAoTCGVTY2llbmNlMRIwEAYDVQQLEwlBdXRob3JpdHkxCzAJBgNVBAMT\r\n" - "\tAkNBMS0wKwYJKoZIhvcNAQkBFh5jYS1vcGVyYXRvckBncmlkLXN1cHBvcnQuYWMu\r\n" - "\tdWswHhcNMDYwNzI3MTQxMzI4WhcNMDcwNzI3MTQxMzI4WjBbMQswCQYDVQQGEwJV\r\n" - "\tSzERMA8GA1UEChMIZVNjaWVuY2UxEzARBgNVBAsTCk1hbmNoZXN0ZXIxCzAJBgNV\r\n" - "\tBAcTmrsogriqMWLAk1DMRcwFQYDVQQDEw5taWNoYWVsIHBhcmQYJKoZIhvcNAQEB\r\n" - "\tBQADggEPADCCAQoCggEBANPEQBgl1IaKdSS1TbhF3hEXSl72G9J+WC/1R64fAcEF\r\n" - "\tW51rEyFYiIeZGx/BVzwXbeBoNUK41OK65sxGuflMo5gLflbwJtHBRIEKAfVVp3YR\r\n" - "\tgW7cMA/s/XKgL1GEC7rQw8lIZT8RApukCGqOVHSi/F1SiFlPDxuDfmdiNzL31+sL\r\n" - "\t0iwHDdNkGjy5pyBSB8Y79dsSJtCW/iaLB0/n8Sj7HgvvZJ7x0fr+RQjYOUUfrePP\r\n" - "\tu2MSpFyf+9BbC/aXgaZuiCvSR+8Snv3xApQY+fULK/xY8h8Ua51iXoQ5jrgu2SqR\r\n" - "\twgA7BUi3G8LFzMBl8FRCDYGUDy7M6QaHXx1ZWIPWNKsCAwEAAaOCAiQwggIgMAwG\r\n" - "\tA1UdEwEB/wQCMAAwEQYJYIZIAYb4QgHTTPAQDAgWgMA4GA1UdDwEB/wQEAwID6DAs\r\n" - "\tBglghkgBhvhCAQ0EHxYdVUsgZS1TY2llbmNlIFVzZXIgQ2VydGlmaWNhdGUwHQYD\r\n" - "\tVR0OBBYEFDTt/sf9PeMaZDHkUIldrDYMNTBZMIGaBgNVHSMEgZIwgY+AFAI4qxGj\r\n" - "\tloCLDdMVKwiljjDastqooXSkcjBwMQswCQYDVQQGEwJVSzERMA8GA1UEChMIZVNj\r\n" - "\taWVuY2UxEjAQBgNVBAsTCUF1dGhvcml0eTELMAkGA1UEAxMCQ0ExLTArBgkqhkiG\r\n" - "\t9w0BCQEWHmNhLW9wZXJhdG9yQGdyaWQtc3VwcG9ydC5hYy51a4IBADApBgNVHRIE\r\n" - "\tIjAggR5jYS1vcGVyYXRvckBncmlkLXN1cHBvcnQuYWMudWswGQYDVR0gBBIwEDAO\r\n" - "\tBgwrBgEEAdkvAQEBAQYwPQYJYIZIAYb4QgEEBDAWLmh0dHA6Ly9jYS5ncmlkLXN1\r\n" - "\tcHBvcnQuYWMudmT4sopwqlBWsvcHViL2NybC9jYWNybC5jcmwwPQYJYIZIAYb4QgEDBDAWLmh0\r\n" - "\tdHA6Ly9jYS5ncmlkLXN1cHBvcnQuYWMudWsvcHViL2NybC9jYWNybC5jcmwwPwYD\r\n" - "\tVR0fBDgwNjA0oDKgMIYuaHR0cDovL2NhLmdyaWQt5hYy51ay9wdWIv\r\n" - "\tY3JsL2NhY3JsLmNybDANBgkqhkiG9w0BAQUFAAOCAQEAS/U4iiooBENGW/Hwmmd3\r\n" - "\tXCy6Zrt08YjKCzGNjorT98g8uGsqYjSxv/hmi0qlnlHs+k/3Iobc3LjS5AMYr5L8\r\n" - "\tUO7OSkgFFlLHQyC9JzPfmLCAugvzEbyv4Olnsr8hbxF1MbKZoQxUZtMVu29wjfXk\r\n" - "\thTeApBv7eaKCWpSp7MCbvgzm74izKhu3vlDk9w6qVrxePfGgpKPqfHiOoGhFnbTK\r\n" - "\twTC6o2xq5y0qZ03JonF7OJspEd3I5zKY3E+ov7/ZhW6DqT8UFvsAdjvQbXyhV8Eu\r\n" - "\tYhixw1aKEPzNjNowuIseVogKOLXxWI5vAi5HgXdS0/ES5gDGsABo4fqovUKlgop3\r\n" - "\tRA==\r\n" - "\t-----END CERTIFICATE-----\r\n" - "\r\n"; - test_simple(dumbfuck2, HPE_OK); - - const char *corrupted_connection = - "GET / HTTP/1.1\r\n" - "Host: www.example.com\r\n" - "Connection\r\033\065\325eep-Alive\r\n" - "Accept-Encoding: gzip\r\n" - "\r\n"; - test_simple(corrupted_connection, HPE_INVALID_HEADER_TOKEN); - - const char *corrupted_header_name = - "GET / HTTP/1.1\r\n" - "Host: www.example.com\r\n" - "X-Some-Header\r\033\065\325eep-Alive\r\n" - "Accept-Encoding: gzip\r\n" - "\r\n"; - test_simple(corrupted_header_name, HPE_INVALID_HEADER_TOKEN); - -#if 0 - // NOTE(Wed Nov 18 11:57:27 CET 2009) this seems okay. we just read body - // until EOF. - // - // no content-length - // error if there is a body without content length - const char *bad_get_no_headers_no_body = "GET /bad_get_no_headers_no_body/world HTTP/1.1\r\n" - "Accept: */*\r\n" - "\r\n" - "HELLO"; - test_simple(bad_get_no_headers_no_body, 0); -#endif - /* TODO sending junk and large headers gets rejected */ - - - /* check to make sure our predefined requests are okay */ - for (i = 0; requests[i].name; i++) { - test_message(&requests[i]); - } - - for (i = 0; i < request_count; i++) { - test_message_pause(&requests[i]); - } - - for (i = 0; i < request_count; i++) { - if (!requests[i].should_keep_alive) continue; - for (j = 0; j < request_count; j++) { - if (!requests[j].should_keep_alive) continue; - for (k = 0; k < request_count; k++) { - test_multiple3(&requests[i], &requests[j], &requests[k]); - } - } - } - - printf("request scan 1/4 "); - test_scan( &requests[GET_NO_HEADERS_NO_BODY] - , &requests[GET_ONE_HEADER_NO_BODY] - , &requests[GET_NO_HEADERS_NO_BODY] - ); - - printf("request scan 2/4 "); - test_scan( &requests[POST_CHUNKED_ALL_YOUR_BASE] - , &requests[POST_IDENTITY_BODY_WORLD] - , &requests[GET_FUNKY_CONTENT_LENGTH] - ); - - printf("request scan 3/4 "); - test_scan( &requests[TWO_CHUNKS_MULT_ZERO_END] - , &requests[CHUNKED_W_TRAILING_HEADERS] - , &requests[CHUNKED_W_BULLSHIT_AFTER_LENGTH] - ); - - printf("request scan 4/4 "); - test_scan( &requests[QUERY_URL_WITH_QUESTION_MARK_GET] - , &requests[PREFIX_NEWLINE_GET ] - , &requests[CONNECT_REQUEST] - ); - - puts("requests okay"); - - return 0; -} diff --git a/vendor/json/CMakeLists.txt b/vendor/json/CMakeLists.txt deleted file mode 100644 index d7c4e174b..000000000 --- a/vendor/json/CMakeLists.txt +++ /dev/null @@ -1,60 +0,0 @@ -# Just install the header, nothing more -install(FILES "${LibSourcey_VENDOR_SOURCE_DIR}/json/src/json.hpp" DESTINATION ${LibSourcey_VENDOR_INSTALL_DIR}/include) - -# cmake_minimum_required(VERSION 3.0) -# -# # define the project -# project(nlohmann_json VERSION 2.1.1 LANGUAGES CXX) -# -# enable_testing() -# -# option(BuildTests "Build the unit tests" ON) -# -# # define project variables -# set(JSON_TARGET_NAME ${PROJECT_NAME}) -# set(JSON_PACKAGE_NAME ${JSON_TARGET_NAME}) -# set(JSON_TARGETS_FILENAME "${JSON_PACKAGE_NAME}Targets.cmake") -# set(JSON_CONFIG_FILENAME "${JSON_PACKAGE_NAME}Config.cmake") -# set(JSON_CONFIGVERSION_FILENAME "${JSON_PACKAGE_NAME}ConfigVersion.cmake") -# set(JSON_CONFIG_DESTINATION "cmake") -# set(JSON_INCLUDE_DESTINATION "${LibSourcey_VENDOR_INSTALL_DIR}/include") -# -# set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") -# -# # create and configure the library target -# add_library(${JSON_TARGET_NAME} INTERFACE) -# target_include_directories(${JSON_TARGET_NAME} INTERFACE -# $ -# $) -# -# # create and configure the unit test target -# if(BuildTests) -# add_subdirectory(test) -# endif() -# -# # generate a config and config version file for the package -# include(CMakePackageConfigHelpers) -# configure_package_config_file("cmake/config.cmake.in" -# "${CMAKE_CURRENT_BINARY_DIR}/${JSON_CONFIG_FILENAME}" -# INSTALL_DESTINATION ${JSON_CONFIG_DESTINATION} -# PATH_VARS JSON_INCLUDE_DESTINATION) -# write_basic_package_version_file("${CMAKE_CURRENT_BINARY_DIR}/${JSON_CONFIGVERSION_FILENAME}" -# VERSION ${PROJECT_VERSION} -# COMPATIBILITY SameMajorVersion) -# -# # export the library target and store build directory in package registry -# export(TARGETS ${JSON_TARGET_NAME} -# FILE "${CMAKE_CURRENT_BINARY_DIR}/${JSON_TARGETS_FILENAME}") -# export(PACKAGE ${JSON_PACKAGE_NAME}) -# -# # install library target and config files -# install(TARGETS ${JSON_TARGET_NAME} -# EXPORT ${JSON_PACKAGE_NAME}) -# install(FILES "src/json.hpp" -# DESTINATION ${JSON_INCLUDE_DESTINATION}) -# install(EXPORT ${JSON_PACKAGE_NAME} -# FILE ${JSON_TARGETS_FILENAME} -# DESTINATION ${JSON_CONFIG_DESTINATION}) -# install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${JSON_CONFIG_FILENAME}" -# "${CMAKE_CURRENT_BINARY_DIR}/${JSON_CONFIGVERSION_FILENAME}" -# DESTINATION ${JSON_CONFIG_DESTINATION}) diff --git a/vendor/json/ChangeLog.md b/vendor/json/ChangeLog.md deleted file mode 100644 index 76244c5da..000000000 --- a/vendor/json/ChangeLog.md +++ /dev/null @@ -1,488 +0,0 @@ -# Change Log -All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). - -## [v2.1.1](https://github.com/nlohmann/json/releases/tag/v2.1.1) (2017-02-25) -[Full Changelog](https://github.com/nlohmann/json/compare/v2.1.0...v2.1.1) - -- warning in the library [\#472](https://github.com/nlohmann/json/issues/472) -- How to create an array of Objects? [\#470](https://github.com/nlohmann/json/issues/470) -- \[Bug?\] Cannot get int pointer, but int64\_t works [\#468](https://github.com/nlohmann/json/issues/468) -- Illegal indirection [\#467](https://github.com/nlohmann/json/issues/467) -- in vs can't find linkageId [\#466](https://github.com/nlohmann/json/issues/466) -- Roundtrip error while parsing "1000000000000000010E5" [\#465](https://github.com/nlohmann/json/issues/465) -- C4996 error and warning with Visual Studio [\#463](https://github.com/nlohmann/json/issues/463) -- Support startIndex for from\_cbor/from\_msgpack [\#462](https://github.com/nlohmann/json/issues/462) -- question: monospace font used in feature slideshow? [\#460](https://github.com/nlohmann/json/issues/460) -- Object.keys\(\) [\#459](https://github.com/nlohmann/json/issues/459) -- Use “, “ as delimiter for json-objects. [\#457](https://github.com/nlohmann/json/issues/457) -- Enum -\> string during serialization and vice versa [\#455](https://github.com/nlohmann/json/issues/455) -- doubles are printed as integers [\#454](https://github.com/nlohmann/json/issues/454) -- Warnings with Visual Studio c++ \(VS2015 Update 3\) [\#453](https://github.com/nlohmann/json/issues/453) -- Heap-buffer-overflow \(OSS-Fuzz issue 585\) [\#452](https://github.com/nlohmann/json/issues/452) -- use of undeclared identifier 'UINT8\_MAX' [\#451](https://github.com/nlohmann/json/issues/451) -- Question on the lifetime managment of objects at the lower levels [\#449](https://github.com/nlohmann/json/issues/449) -- Json should not be constructible with 'json\*' [\#448](https://github.com/nlohmann/json/issues/448) -- Move value\_t to namespace scope [\#447](https://github.com/nlohmann/json/issues/447) -- Typo in README.md [\#446](https://github.com/nlohmann/json/issues/446) -- make check compilation is unneccesarily slow [\#445](https://github.com/nlohmann/json/issues/445) -- Problem in dump\(\) in json.h caused by ss.imbue [\#444](https://github.com/nlohmann/json/issues/444) -- I want to create Windows Application in Visual Studio 2015 c++, and i have a problem [\#443](https://github.com/nlohmann/json/issues/443) -- Implicit conversion issues [\#442](https://github.com/nlohmann/json/issues/442) -- Parsing of floats locale dependent [\#302](https://github.com/nlohmann/json/issues/302) - -- Speedup CI builds using cotire [\#461](https://github.com/nlohmann/json/pull/461) ([tusharpm](https://github.com/tusharpm)) -- TurpentineDistillery feature/locale independent str to num [\#450](https://github.com/nlohmann/json/pull/450) ([nlohmann](https://github.com/nlohmann)) -- README: adjust boost::optional example [\#439](https://github.com/nlohmann/json/pull/439) ([jaredgrubb](https://github.com/jaredgrubb)) -- fix \#414 - comparing to 0 literal [\#415](https://github.com/nlohmann/json/pull/415) ([stanmihai4](https://github.com/stanmihai4)) - -## [v2.1.0](https://github.com/nlohmann/json/releases/tag/v2.1.0) (2017-01-28) -[Full Changelog](https://github.com/nlohmann/json/compare/v2.0.10...v2.1.0) - -- Parsing multiple JSON objects from a string or stream [\#438](https://github.com/nlohmann/json/issues/438) -- Use-of-uninitialized-value \(OSS-Fuzz issue 477\) [\#437](https://github.com/nlohmann/json/issues/437) -- add `reserve` function for array to reserve memory before adding json values into it [\#436](https://github.com/nlohmann/json/issues/436) -- Typo in examples page [\#434](https://github.com/nlohmann/json/issues/434) -- avoid malformed json [\#433](https://github.com/nlohmann/json/issues/433) -- How to add json objects to a map? [\#432](https://github.com/nlohmann/json/issues/432) -- create json instance from raw json \(unsigned char\*\) [\#431](https://github.com/nlohmann/json/issues/431) -- Getting std::invalid\_argument: stream error when following example [\#429](https://github.com/nlohmann/json/issues/429) -- Forward declare-only header? [\#427](https://github.com/nlohmann/json/issues/427) -- Implicit conversion from array to object [\#425](https://github.com/nlohmann/json/issues/425) -- Automatic ordered JSON [\#424](https://github.com/nlohmann/json/issues/424) -- error C4996: 'strerror' when reading file [\#422](https://github.com/nlohmann/json/issues/422) -- Get an error - JSON pointer must be empty or begin with '/' [\#421](https://github.com/nlohmann/json/issues/421) -- size parameter for parse\(\) [\#419](https://github.com/nlohmann/json/issues/419) -- json.hpp forcibly defines GCC\_VERSION [\#417](https://github.com/nlohmann/json/issues/417) -- Use-of-uninitialized-value \(OSS-Fuzz issue 377\) [\#416](https://github.com/nlohmann/json/issues/416) -- comparing to 0 literal [\#414](https://github.com/nlohmann/json/issues/414) -- Single char converted to ASCII code instead of string [\#413](https://github.com/nlohmann/json/issues/413) -- How to know if a string was parsed as utf-8? [\#406](https://github.com/nlohmann/json/issues/406) -- Overloaded += to add objects to an array makes no sense? [\#404](https://github.com/nlohmann/json/issues/404) -- Finding a value in an array [\#399](https://github.com/nlohmann/json/issues/399) -- add release information in static function [\#397](https://github.com/nlohmann/json/issues/397) -- Optimize memory usage of json objects in combination with binary serialization [\#373](https://github.com/nlohmann/json/issues/373) -- Conversion operators not considered [\#369](https://github.com/nlohmann/json/issues/369) -- Append ".0" to serialized floating\_point values that are digits-only. [\#362](https://github.com/nlohmann/json/issues/362) -- Add a customization point for user-defined types [\#328](https://github.com/nlohmann/json/issues/328) -- Conformance report for reference [\#307](https://github.com/nlohmann/json/issues/307) -- Document the best way to serialize/deserialize user defined types to json [\#298](https://github.com/nlohmann/json/issues/298) -- Add StringView template typename to basic\_json [\#297](https://github.com/nlohmann/json/issues/297) -- \[Improvement\] Add option to remove exceptions [\#296](https://github.com/nlohmann/json/issues/296) -- Performance in miloyip/nativejson-benchmark [\#202](https://github.com/nlohmann/json/issues/202) - -- conversion from/to user-defined types [\#435](https://github.com/nlohmann/json/pull/435) ([nlohmann](https://github.com/nlohmann)) -- Fix documentation error [\#430](https://github.com/nlohmann/json/pull/430) ([vjon](https://github.com/vjon)) -- locale-independent num-to-str [\#378](https://github.com/nlohmann/json/pull/378) ([TurpentineDistillery](https://github.com/TurpentineDistillery)) - -## [v2.0.10](https://github.com/nlohmann/json/releases/tag/v2.0.10) (2017-01-02) -[Full Changelog](https://github.com/nlohmann/json/compare/v2.0.9...v2.0.10) - -- Heap-buffer-overflow \(OSS-Fuzz issue 367\) [\#412](https://github.com/nlohmann/json/issues/412) -- Heap-buffer-overflow \(OSS-Fuzz issue 366\) [\#411](https://github.com/nlohmann/json/issues/411) -- Use-of-uninitialized-value \(OSS-Fuzz issue 347\) [\#409](https://github.com/nlohmann/json/issues/409) -- Heap-buffer-overflow \(OSS-Fuzz issue 344\) [\#408](https://github.com/nlohmann/json/issues/408) -- Heap-buffer-overflow \(OSS-Fuzz issue 343\) [\#407](https://github.com/nlohmann/json/issues/407) -- Heap-buffer-overflow \(OSS-Fuzz issue 342\) [\#405](https://github.com/nlohmann/json/issues/405) -- strerror throwing error in compiler VS2015 [\#403](https://github.com/nlohmann/json/issues/403) -- json::parse of std::string being underlined by Visual Studio [\#402](https://github.com/nlohmann/json/issues/402) -- Explicitly getting string without .dump\(\) [\#401](https://github.com/nlohmann/json/issues/401) -- Possible to speed up json::parse? [\#398](https://github.com/nlohmann/json/issues/398) -- the alphabetic order in the code influence console\_output. [\#396](https://github.com/nlohmann/json/issues/396) -- Execute tests with clang sanitizers [\#394](https://github.com/nlohmann/json/issues/394) -- Check if library can be used with ETL [\#361](https://github.com/nlohmann/json/issues/361) - -- Feature/clang sanitize [\#410](https://github.com/nlohmann/json/pull/410) ([Daniel599](https://github.com/Daniel599)) -- Add Doozer build badge [\#400](https://github.com/nlohmann/json/pull/400) ([andoma](https://github.com/andoma)) - -## [v2.0.9](https://github.com/nlohmann/json/releases/tag/v2.0.9) (2016-12-16) -[Full Changelog](https://github.com/nlohmann/json/compare/v2.0.8...v2.0.9) - -- \#pragma GCC diagnostic ignored "-Wdocumentation" [\#393](https://github.com/nlohmann/json/issues/393) -- How to parse this json file and write separate sub object as json files? [\#392](https://github.com/nlohmann/json/issues/392) -- Integer-overflow \(OSS-Fuzz issue 267\) [\#389](https://github.com/nlohmann/json/issues/389) -- Implement indefinite-length types from RFC 7049 [\#387](https://github.com/nlohmann/json/issues/387) -- template parameter "T" is not used in declaring the parameter types of function template [\#386](https://github.com/nlohmann/json/issues/386) -- Serializing json instances containing already serialized string values without escaping [\#385](https://github.com/nlohmann/json/issues/385) -- Add test cases from RFC 7049 [\#384](https://github.com/nlohmann/json/issues/384) -- Add a table of contents to the README file [\#383](https://github.com/nlohmann/json/issues/383) -- Update FAQ section in the guidelines for contributing [\#382](https://github.com/nlohmann/json/issues/382) -- Allow for forward declaring nlohmann::json [\#381](https://github.com/nlohmann/json/issues/381) -- Bug in overflow detection when parsing integers [\#380](https://github.com/nlohmann/json/issues/380) -- A unique name to mention the library? [\#377](https://github.com/nlohmann/json/issues/377) -- Support for comments. [\#376](https://github.com/nlohmann/json/issues/376) -- Non-unique keys in objects. [\#375](https://github.com/nlohmann/json/issues/375) -- Request: binary serialization/deserialization [\#358](https://github.com/nlohmann/json/issues/358) - -- Replace class iterator and const\_iterator by using a single template class to reduce code. [\#395](https://github.com/nlohmann/json/pull/395) ([Bosswestfalen](https://github.com/Bosswestfalen)) -- Clang: quiet a warning [\#391](https://github.com/nlohmann/json/pull/391) ([jaredgrubb](https://github.com/jaredgrubb)) -- Fix issue \#380: Signed integer overflow check [\#390](https://github.com/nlohmann/json/pull/390) ([qwename](https://github.com/qwename)) - -## [v2.0.8](https://github.com/nlohmann/json/releases/tag/v2.0.8) (2016-12-02) -[Full Changelog](https://github.com/nlohmann/json/compare/v2.0.7...v2.0.8) - -- Reading from file [\#374](https://github.com/nlohmann/json/issues/374) -- Compiler warnings? [\#372](https://github.com/nlohmann/json/issues/372) -- docs: how to release a json object in memory? [\#371](https://github.com/nlohmann/json/issues/371) -- crash in dump [\#370](https://github.com/nlohmann/json/issues/370) -- Coverity issue \(FORWARD\_NULL\) in lexer\(std::istream& s\) [\#368](https://github.com/nlohmann/json/issues/368) -- json::parse on failed stream gets stuck [\#366](https://github.com/nlohmann/json/issues/366) -- Performance improvements [\#365](https://github.com/nlohmann/json/issues/365) -- 'to\_string' is not a member of 'std' [\#364](https://github.com/nlohmann/json/issues/364) -- Optional comment support. [\#363](https://github.com/nlohmann/json/issues/363) -- Loss of precision when serializing \ [\#360](https://github.com/nlohmann/json/issues/360) -- Crash in dump\(\) from a static object [\#359](https://github.com/nlohmann/json/issues/359) -- json::parse\(...\) vs json j; j.parse\(...\) [\#357](https://github.com/nlohmann/json/issues/357) -- Hi, is there any method to dump json to string with the insert order rather than alphabets [\#356](https://github.com/nlohmann/json/issues/356) -- Provide an example of reading from an json with only a key that has an array of strings. [\#354](https://github.com/nlohmann/json/issues/354) -- Request: access with default value. [\#353](https://github.com/nlohmann/json/issues/353) -- {} and \[\] causes parser error. [\#352](https://github.com/nlohmann/json/issues/352) -- Reading a JSON file into a JSON object [\#351](https://github.com/nlohmann/json/issues/351) -- Request: 'emplace\_back' [\#349](https://github.com/nlohmann/json/issues/349) -- Is it possible to stream data through the json parser without storing everything in memory? [\#347](https://github.com/nlohmann/json/issues/347) -- pure virtual conversion operator [\#346](https://github.com/nlohmann/json/issues/346) -- Floating point precision lost [\#345](https://github.com/nlohmann/json/issues/345) -- unit-conversions SIGSEGV on armv7hl [\#303](https://github.com/nlohmann/json/issues/303) -- Coverity scan fails [\#299](https://github.com/nlohmann/json/issues/299) -- Using QString as string type [\#274](https://github.com/nlohmann/json/issues/274) - -## [v2.0.7](https://github.com/nlohmann/json/releases/tag/v2.0.7) (2016-11-02) -[Full Changelog](https://github.com/nlohmann/json/compare/v2.0.6...v2.0.7) - -- JSON5 [\#348](https://github.com/nlohmann/json/issues/348) -- Check "Parsing JSON is a Minefield" [\#344](https://github.com/nlohmann/json/issues/344) -- Allow hex numbers [\#342](https://github.com/nlohmann/json/issues/342) -- Convert strings to numbers [\#341](https://github.com/nlohmann/json/issues/341) -- ""-operators ignore the length parameter [\#340](https://github.com/nlohmann/json/issues/340) -- JSON into std::tuple [\#339](https://github.com/nlohmann/json/issues/339) -- JSON into vector [\#335](https://github.com/nlohmann/json/issues/335) -- Installing with Homebrew on Mac Errors \(El Capitan\) [\#331](https://github.com/nlohmann/json/issues/331) -- g++ make check results in error [\#312](https://github.com/nlohmann/json/issues/312) -- Cannot convert from 'json' to 'char' [\#276](https://github.com/nlohmann/json/issues/276) -- Please add a Pretty-Print option for arrays to stay always in one line [\#229](https://github.com/nlohmann/json/issues/229) -- Conversion to STL map\\> gives error [\#220](https://github.com/nlohmann/json/issues/220) -- std::unorderd\_map cannot be used as ObjectType [\#164](https://github.com/nlohmann/json/issues/164) - -- fix minor grammar/style issue in README.md [\#336](https://github.com/nlohmann/json/pull/336) ([seeekr](https://github.com/seeekr)) - -## [v2.0.6](https://github.com/nlohmann/json/releases/tag/v2.0.6) (2016-10-15) -[Full Changelog](https://github.com/nlohmann/json/compare/v2.0.5...v2.0.6) - -- How to handle json files? [\#333](https://github.com/nlohmann/json/issues/333) -- This file requires compiler and library support .... [\#332](https://github.com/nlohmann/json/issues/332) -- Segmentation fault on saving json to file [\#326](https://github.com/nlohmann/json/issues/326) -- parse error - unexpected \ with 2.0.5 [\#325](https://github.com/nlohmann/json/issues/325) -- Add nested object capability to pointers [\#323](https://github.com/nlohmann/json/issues/323) -- Fix usage examples' comments for std::multiset [\#322](https://github.com/nlohmann/json/issues/322) -- json\_unit runs forever when executed in build directory [\#319](https://github.com/nlohmann/json/issues/319) -- Visual studio 2015 update3 true != TRUE [\#317](https://github.com/nlohmann/json/issues/317) -- releasing single header file in compressed format [\#316](https://github.com/nlohmann/json/issues/316) -- json object from std::ifstream [\#315](https://github.com/nlohmann/json/issues/315) - -- make has\_mapped\_type struct friendly [\#324](https://github.com/nlohmann/json/pull/324) ([vpetrigo](https://github.com/vpetrigo)) -- Fix usage examples' comments for std::multiset [\#321](https://github.com/nlohmann/json/pull/321) ([vasild](https://github.com/vasild)) -- Include dir relocation [\#318](https://github.com/nlohmann/json/pull/318) ([ChristophJud](https://github.com/ChristophJud)) -- trivial documentation fix [\#313](https://github.com/nlohmann/json/pull/313) ([5tefan](https://github.com/5tefan)) - -## [v2.0.5](https://github.com/nlohmann/json/releases/tag/v2.0.5) (2016-09-14) -[Full Changelog](https://github.com/nlohmann/json/compare/v2.0.4...v2.0.5) - -- \[feature request\]: schema validator and comments [\#311](https://github.com/nlohmann/json/issues/311) -- make json\_benchmarks no longer working in 2.0.4 [\#310](https://github.com/nlohmann/json/issues/310) -- Segmentation fault \(core dumped\) [\#309](https://github.com/nlohmann/json/issues/309) -- No matching member function for call to 'get\_impl' [\#308](https://github.com/nlohmann/json/issues/308) - -## [v2.0.4](https://github.com/nlohmann/json/releases/tag/v2.0.4) (2016-09-11) -[Full Changelog](https://github.com/nlohmann/json/compare/v2.0.3...v2.0.4) - -- Parsing fails without space at end of file [\#306](https://github.com/nlohmann/json/issues/306) -- json schema validator [\#305](https://github.com/nlohmann/json/issues/305) -- Unused variable warning [\#304](https://github.com/nlohmann/json/issues/304) - -## [v2.0.3](https://github.com/nlohmann/json/releases/tag/v2.0.3) (2016-08-31) -[Full Changelog](https://github.com/nlohmann/json/compare/v2.0.2...v2.0.3) - -- warning C4706: assignment within conditional expression [\#295](https://github.com/nlohmann/json/issues/295) -- Strip comments / Minify [\#294](https://github.com/nlohmann/json/issues/294) -- Q: Is it possible to build json tree from already UTF8 encoded values? [\#293](https://github.com/nlohmann/json/issues/293) -- Equality operator results in array when assigned object [\#292](https://github.com/nlohmann/json/issues/292) -- Support for integers not from the range \[-\(2\*\*53\)+1, \(2\*\*53\)-1\] in parser [\#291](https://github.com/nlohmann/json/issues/291) -- Support for iterator-range parsing [\#290](https://github.com/nlohmann/json/issues/290) -- Horribly inconsistent behavior between const/non-const reference in operator \[\] \(\) [\#289](https://github.com/nlohmann/json/issues/289) -- Silently get numbers into smaller types [\#288](https://github.com/nlohmann/json/issues/288) -- Incorrect parsing of large int64\_t numbers [\#287](https://github.com/nlohmann/json/issues/287) -- \[question\]: macro to disable floating point support [\#284](https://github.com/nlohmann/json/issues/284) - -- unit-constructor1.cpp: Fix floating point truncation warning [\#300](https://github.com/nlohmann/json/pull/300) ([t-b](https://github.com/t-b)) - -## [v2.0.2](https://github.com/nlohmann/json/releases/tag/v2.0.2) (2016-07-31) -[Full Changelog](https://github.com/nlohmann/json/compare/v2.0.1...v2.0.2) - -- can function dump\(\) return string in the order I push in the json object ? [\#286](https://github.com/nlohmann/json/issues/286) -- Error on the Mac: Undefined symbols for architecture x86\_64 [\#285](https://github.com/nlohmann/json/issues/285) -- value\(\) does not work with \_json\_pointer types [\#283](https://github.com/nlohmann/json/issues/283) -- Build error for std::int64 [\#282](https://github.com/nlohmann/json/issues/282) -- strings can't be accessed after dump\(\)-\>parse\(\) - type is lost [\#281](https://github.com/nlohmann/json/issues/281) -- Easy serialization of classes [\#280](https://github.com/nlohmann/json/issues/280) -- recursive data structures [\#277](https://github.com/nlohmann/json/issues/277) -- hexify\(\) function emits conversion warning [\#270](https://github.com/nlohmann/json/issues/270) - -- let the makefile choose the correct sed [\#279](https://github.com/nlohmann/json/pull/279) ([murinicanor](https://github.com/murinicanor)) -- Update hexify to use array lookup instead of ternary \(\#270\) [\#275](https://github.com/nlohmann/json/pull/275) ([dtoma](https://github.com/dtoma)) - -## [v2.0.1](https://github.com/nlohmann/json/releases/tag/v2.0.1) (2016-06-28) -[Full Changelog](https://github.com/nlohmann/json/compare/v2.0.0...v2.0.1) - -- Compilation error. [\#273](https://github.com/nlohmann/json/issues/273) -- dump\(\) performance degradation in v2 [\#272](https://github.com/nlohmann/json/issues/272) - -- fixed a tiny typo [\#271](https://github.com/nlohmann/json/pull/271) ([thelostt](https://github.com/thelostt)) - -## [v2.0.0](https://github.com/nlohmann/json/releases/tag/v2.0.0) (2016-06-23) -[Full Changelog](https://github.com/nlohmann/json/compare/v1.1.0...v2.0.0) - -- json::diff generates incorrect patch when removing multiple array elements. [\#269](https://github.com/nlohmann/json/issues/269) -- Docs - What does Json\[key\] return? [\#267](https://github.com/nlohmann/json/issues/267) -- Compiler Errors With JSON.hpp [\#265](https://github.com/nlohmann/json/issues/265) -- Throw exception instead of crashing my app [\#264](https://github.com/nlohmann/json/issues/264) -- Ambiguous push\_back and operator+= overloads [\#263](https://github.com/nlohmann/json/issues/263) -- Preseving order of items in json [\#262](https://github.com/nlohmann/json/issues/262) -- '\' char problem in strings [\#261](https://github.com/nlohmann/json/issues/261) -- VS2015 compile fail [\#260](https://github.com/nlohmann/json/issues/260) -- -Wconversion warning [\#259](https://github.com/nlohmann/json/issues/259) -- Maybe a bug [\#258](https://github.com/nlohmann/json/issues/258) -- Few tests failed on Visual C++ 2015 [\#257](https://github.com/nlohmann/json/issues/257) -- Access keys when iteration with new for loop C++11 [\#256](https://github.com/nlohmann/json/issues/256) -- multiline text values [\#255](https://github.com/nlohmann/json/issues/255) -- Error when using json in g++ [\#254](https://github.com/nlohmann/json/issues/254) -- is the release 2.0? [\#253](https://github.com/nlohmann/json/issues/253) -- concatenate objects [\#252](https://github.com/nlohmann/json/issues/252) -- Encoding [\#251](https://github.com/nlohmann/json/issues/251) -- Unable to build example for constructing json object with stringstreams [\#250](https://github.com/nlohmann/json/issues/250) -- Hexadecimal support [\#249](https://github.com/nlohmann/json/issues/249) -- Update long-term goals [\#246](https://github.com/nlohmann/json/issues/246) -- Contribution To This Json Project [\#245](https://github.com/nlohmann/json/issues/245) -- Trouble using parser with initial dictionary [\#243](https://github.com/nlohmann/json/issues/243) -- Unit test fails when doing a CMake out-of-tree build [\#241](https://github.com/nlohmann/json/issues/241) -- -Wconversion warnings [\#239](https://github.com/nlohmann/json/issues/239) -- Additional integration options [\#237](https://github.com/nlohmann/json/issues/237) -- .get\\(\) works for non spaced string but returns as array for spaced/longer strings [\#236](https://github.com/nlohmann/json/issues/236) -- ambiguous overload for 'push\_back' and 'operator+=' [\#235](https://github.com/nlohmann/json/issues/235) -- Can't use basic\_json::iterator as a base iterator for std::move\_iterator [\#233](https://github.com/nlohmann/json/issues/233) -- json object's creation can freezes execution [\#231](https://github.com/nlohmann/json/issues/231) -- Incorrect dumping of parsed numbers with exponents, but without decimal places [\#230](https://github.com/nlohmann/json/issues/230) -- double values are serialized with commas as decimal points [\#228](https://github.com/nlohmann/json/issues/228) -- Move semantics with std::initializer\_list [\#225](https://github.com/nlohmann/json/issues/225) -- replace emplace [\#224](https://github.com/nlohmann/json/issues/224) -- abort during getline in yyfill [\#223](https://github.com/nlohmann/json/issues/223) -- free\(\): invalid pointer error in GCC 5.2.1 [\#221](https://github.com/nlohmann/json/issues/221) -- Error compile Android NDK error: 'strtof' is not a member of 'std' [\#219](https://github.com/nlohmann/json/issues/219) -- Wrong link in the README.md [\#217](https://github.com/nlohmann/json/issues/217) -- Wide character strings not supported [\#216](https://github.com/nlohmann/json/issues/216) -- Memory allocations using range-based for loops [\#214](https://github.com/nlohmann/json/issues/214) -- would you like to support gcc 4.8.1? [\#211](https://github.com/nlohmann/json/issues/211) -- Reading concatenated json's from an istream [\#210](https://github.com/nlohmann/json/issues/210) -- Conflicting typedef of ssize\_t on Windows 32 bit when using Boost.Python [\#204](https://github.com/nlohmann/json/issues/204) -- Inconsistency between operator\[\] and push\_back [\#203](https://github.com/nlohmann/json/issues/203) -- Small bugs in json.hpp \(get\_number\) and unit.cpp \(non-standard integer type test\) [\#199](https://github.com/nlohmann/json/issues/199) -- GCC/clang floating point parsing bug in strtod\(\) [\#195](https://github.com/nlohmann/json/issues/195) -- What is within scope? [\#192](https://github.com/nlohmann/json/issues/192) -- Bugs in miloyip/nativejson-benchmark: roundtrips [\#187](https://github.com/nlohmann/json/issues/187) -- Floating point exceptions [\#181](https://github.com/nlohmann/json/issues/181) -- Integer conversion to unsigned [\#178](https://github.com/nlohmann/json/issues/178) -- map string string fails to compile [\#176](https://github.com/nlohmann/json/issues/176) -- In basic\_json::basic\_json\(const CompatibleArrayType& val\), the requirement of CompatibleArrayType is not strict enough. [\#174](https://github.com/nlohmann/json/issues/174) -- Provide a FAQ [\#163](https://github.com/nlohmann/json/issues/163) -- Implicit assignment to std::string fails [\#144](https://github.com/nlohmann/json/issues/144) - -- Fix Issue \#265 [\#266](https://github.com/nlohmann/json/pull/266) ([06needhamt](https://github.com/06needhamt)) -- Define CMake/CTest tests [\#247](https://github.com/nlohmann/json/pull/247) ([robertmrk](https://github.com/robertmrk)) -- Out of tree builds and a few other miscellaneous CMake cleanups. [\#242](https://github.com/nlohmann/json/pull/242) ([ChrisKitching](https://github.com/ChrisKitching)) -- Implement additional integration options [\#238](https://github.com/nlohmann/json/pull/238) ([robertmrk](https://github.com/robertmrk)) -- make serialization locale-independent [\#232](https://github.com/nlohmann/json/pull/232) ([nlohmann](https://github.com/nlohmann)) -- fixes \#223 by updating README.md [\#227](https://github.com/nlohmann/json/pull/227) ([kevin--](https://github.com/kevin--)) -- Use namespace std for int64\_t and uint64\_t [\#226](https://github.com/nlohmann/json/pull/226) ([lv-zheng](https://github.com/lv-zheng)) -- Added missing cerrno header to fix ERANGE compile error on android [\#222](https://github.com/nlohmann/json/pull/222) ([Teemperor](https://github.com/Teemperor)) -- Corrected readme [\#218](https://github.com/nlohmann/json/pull/218) ([Annihil](https://github.com/Annihil)) -- Create PULL\_REQUEST\_TEMPLATE.md [\#213](https://github.com/nlohmann/json/pull/213) ([whackashoe](https://github.com/whackashoe)) -- fixed noexcept; added constexpr [\#208](https://github.com/nlohmann/json/pull/208) ([nlohmann](https://github.com/nlohmann)) -- Add support for afl-fuzz testing [\#207](https://github.com/nlohmann/json/pull/207) ([mykter](https://github.com/mykter)) -- replaced ssize\_t occurrences with auto \(addresses \#204\) [\#205](https://github.com/nlohmann/json/pull/205) ([nlohmann](https://github.com/nlohmann)) -- Fixed issue \#199 - Small bugs in json.hpp \(get\_number\) and unit.cpp \(non-standard integer type test\) [\#200](https://github.com/nlohmann/json/pull/200) ([twelsby](https://github.com/twelsby)) -- Fix broken link [\#197](https://github.com/nlohmann/json/pull/197) ([vog](https://github.com/vog)) -- Issue \#195 - update Travis to Trusty due to gcc/clang strtod\(\) bug [\#196](https://github.com/nlohmann/json/pull/196) ([twelsby](https://github.com/twelsby)) -- Issue \#178 - Extending support to full uint64\_t/int64\_t range and unsigned type \(updated\) [\#193](https://github.com/nlohmann/json/pull/193) ([twelsby](https://github.com/twelsby)) - -## [v1.1.0](https://github.com/nlohmann/json/releases/tag/v1.1.0) (2016-01-24) -[Full Changelog](https://github.com/nlohmann/json/compare/v1.0.0...v1.1.0) - -- Small error in pull \#185 [\#194](https://github.com/nlohmann/json/issues/194) -- Bugs in miloyip/nativejson-benchmark: floating-point parsing [\#186](https://github.com/nlohmann/json/issues/186) -- Floating point equality [\#185](https://github.com/nlohmann/json/issues/185) -- Unused variables in catch [\#180](https://github.com/nlohmann/json/issues/180) -- Typo in documentation [\#179](https://github.com/nlohmann/json/issues/179) -- JSON performance benchmark comparision [\#177](https://github.com/nlohmann/json/issues/177) -- Since re2c is often ignored in pull requests, it may make sense to make a contributing.md file [\#175](https://github.com/nlohmann/json/issues/175) -- Question about exceptions [\#173](https://github.com/nlohmann/json/issues/173) -- Android? [\#172](https://github.com/nlohmann/json/issues/172) -- Cannot index by key of type static constexpr const char\* [\#171](https://github.com/nlohmann/json/issues/171) -- Add assertions [\#168](https://github.com/nlohmann/json/issues/168) -- MSVC 2015 build fails when attempting to compare object\_t [\#167](https://github.com/nlohmann/json/issues/167) -- Member detector is not portable [\#166](https://github.com/nlohmann/json/issues/166) -- Unnecessary const\_cast [\#162](https://github.com/nlohmann/json/issues/162) -- Question about get\_ref\(\) [\#128](https://github.com/nlohmann/json/issues/128) -- range based for loop for objects [\#83](https://github.com/nlohmann/json/issues/83) -- Consider submitting this to the Boost Library Incubator [\#66](https://github.com/nlohmann/json/issues/66) - -- Fixed Issue \#186 - add strto\(f|d|ld\) overload wrappers, "-0.0" special case and FP trailing zero [\#191](https://github.com/nlohmann/json/pull/191) ([twelsby](https://github.com/twelsby)) -- Issue \#185 - remove approx\(\) and use \#pragma to kill warnings [\#190](https://github.com/nlohmann/json/pull/190) ([twelsby](https://github.com/twelsby)) -- Fixed Issue \#171 - added two extra template overloads of operator\[\] for T\* arguments [\#189](https://github.com/nlohmann/json/pull/189) ([twelsby](https://github.com/twelsby)) -- Fixed issue \#167 - removed operator ValueType\(\) condition for VS2015 [\#188](https://github.com/nlohmann/json/pull/188) ([twelsby](https://github.com/twelsby)) -- Implementation of get\_ref\(\) [\#184](https://github.com/nlohmann/json/pull/184) ([dariomt](https://github.com/dariomt)) -- Fixed some typos in CONTRIBUTING.md [\#182](https://github.com/nlohmann/json/pull/182) ([nibroc](https://github.com/nibroc)) - -## [v1.0.0](https://github.com/nlohmann/json/releases/tag/v1.0.0) (2015-12-27) -[Full Changelog](https://github.com/nlohmann/json/compare/v1.0.0-rc1...v1.0.0) - -- add key name to exception [\#160](https://github.com/nlohmann/json/issues/160) -- Getting member discarding qualifyer [\#159](https://github.com/nlohmann/json/issues/159) -- basic\_json::iterator::value\(\) output includes quotes while basic\_json::iterator::key\(\) doesn't [\#158](https://github.com/nlohmann/json/issues/158) -- Indexing `const basic\_json\<\>` with `const basic\_string\` [\#157](https://github.com/nlohmann/json/issues/157) -- token\_type\_name\(token\_type t\): not all control paths return a value [\#156](https://github.com/nlohmann/json/issues/156) -- prevent json.hpp from emitting compiler warnings [\#154](https://github.com/nlohmann/json/issues/154) -- json::parse\(string\) does not check utf8 bom [\#152](https://github.com/nlohmann/json/issues/152) -- unsigned 64bit values output as signed [\#151](https://github.com/nlohmann/json/issues/151) -- Wish feature: json5 [\#150](https://github.com/nlohmann/json/issues/150) -- Unable to compile on MSVC 2015 with SDL checking enabled: This function or variable may be unsafe. [\#149](https://github.com/nlohmann/json/issues/149) -- "Json Object" type does not keep object order [\#148](https://github.com/nlohmann/json/issues/148) -- dump\(\) convert strings encoded by utf-8 to shift-jis on windows 10. [\#147](https://github.com/nlohmann/json/issues/147) -- Unable to get field names in a json object [\#145](https://github.com/nlohmann/json/issues/145) -- Question: Is the use of incomplete type correct? [\#138](https://github.com/nlohmann/json/issues/138) -- json.hpp:5746:32: error: 'to\_string' is not a member of 'std' [\#136](https://github.com/nlohmann/json/issues/136) -- Bug in basic\_json::operator\[\] const overload [\#135](https://github.com/nlohmann/json/issues/135) -- wrong enable\_if for const pointer \(instead of pointer-to-const\) [\#134](https://github.com/nlohmann/json/issues/134) -- overload of at\(\) with default value [\#133](https://github.com/nlohmann/json/issues/133) -- Splitting source [\#132](https://github.com/nlohmann/json/issues/132) -- Question about get\_ptr\(\) [\#127](https://github.com/nlohmann/json/issues/127) -- Visual Studio 14 Debug assertion failed [\#125](https://github.com/nlohmann/json/issues/125) -- Memory leak in face of exceptions [\#118](https://github.com/nlohmann/json/issues/118) -- Find and Count for arrays [\#117](https://github.com/nlohmann/json/issues/117) -- dynamically constructing an arbitrarily nested object [\#114](https://github.com/nlohmann/json/issues/114) -- Returning any data type [\#113](https://github.com/nlohmann/json/issues/113) -- Compile error with g++ 4.9.3 cygwin 64-bit [\#112](https://github.com/nlohmann/json/issues/112) -- insert json array issue with gcc4.8.2 [\#110](https://github.com/nlohmann/json/issues/110) -- error: unterminated raw string [\#109](https://github.com/nlohmann/json/issues/109) -- vector\ copy constructor really weird [\#108](https://github.com/nlohmann/json/issues/108) -- \[clang-3.6.2\] string/sstream with number to json issue [\#107](https://github.com/nlohmann/json/issues/107) -- maintaining order of keys during iteration [\#106](https://github.com/nlohmann/json/issues/106) -- object field accessors [\#103](https://github.com/nlohmann/json/issues/103) -- v8pp and json [\#95](https://github.com/nlohmann/json/issues/95) -- Wishlist [\#65](https://github.com/nlohmann/json/issues/65) -- Windows/Visual Studio \(through 2013\) is unsupported [\#62](https://github.com/nlohmann/json/issues/62) - -- Replace sprintf with hex function, this fixes \#149 [\#153](https://github.com/nlohmann/json/pull/153) ([whackashoe](https://github.com/whackashoe)) -- Fix character skipping after a surrogate pair [\#146](https://github.com/nlohmann/json/pull/146) ([robertmrk](https://github.com/robertmrk)) -- Detect correctly pointer-to-const [\#137](https://github.com/nlohmann/json/pull/137) ([dariomt](https://github.com/dariomt)) -- disabled "CopyAssignable" test for MSVC in Debug mode, see \#125 [\#131](https://github.com/nlohmann/json/pull/131) ([dariomt](https://github.com/dariomt)) -- removed stream operator for iterator, resolution for \#125 [\#130](https://github.com/nlohmann/json/pull/130) ([dariomt](https://github.com/dariomt)) -- fixed typos in comments for examples [\#129](https://github.com/nlohmann/json/pull/129) ([dariomt](https://github.com/dariomt)) -- Remove superfluous inefficiency [\#126](https://github.com/nlohmann/json/pull/126) ([d-frey](https://github.com/d-frey)) -- remove invalid parameter '-stdlib=libc++' in CMakeLists.txt [\#124](https://github.com/nlohmann/json/pull/124) ([emvivre](https://github.com/emvivre)) -- exception-safe object creation, fixes \#118 [\#122](https://github.com/nlohmann/json/pull/122) ([d-frey](https://github.com/d-frey)) -- Fix small oversight. [\#121](https://github.com/nlohmann/json/pull/121) ([ColinH](https://github.com/ColinH)) -- Overload parse\(\) to accept an rvalue reference [\#120](https://github.com/nlohmann/json/pull/120) ([silverweed](https://github.com/silverweed)) -- Use the right variable name in doc string [\#115](https://github.com/nlohmann/json/pull/115) ([whoshuu](https://github.com/whoshuu)) - -## [v1.0.0-rc1](https://github.com/nlohmann/json/releases/tag/v1.0.0-rc1) (2015-07-26) -- Finish documenting the public interface in Doxygen [\#102](https://github.com/nlohmann/json/issues/102) -- Binary string causes numbers to be dumped as hex [\#101](https://github.com/nlohmann/json/issues/101) -- failed to iterator json object with reverse\_iterator [\#100](https://github.com/nlohmann/json/issues/100) -- 'noexcept' : unknown override specifier [\#99](https://github.com/nlohmann/json/issues/99) -- json float parsing problem [\#98](https://github.com/nlohmann/json/issues/98) -- Adjust wording to JSON RFC [\#97](https://github.com/nlohmann/json/issues/97) -- 17 MB / 90 MB repo size!? [\#96](https://github.com/nlohmann/json/issues/96) -- static analysis warnings [\#94](https://github.com/nlohmann/json/issues/94) -- reverse\_iterator operator inheritance problem [\#93](https://github.com/nlohmann/json/issues/93) -- init error [\#92](https://github.com/nlohmann/json/issues/92) -- access by \(const\) reference [\#91](https://github.com/nlohmann/json/issues/91) -- is\_integer and is\_float tests [\#90](https://github.com/nlohmann/json/issues/90) -- Nonstandard integer type [\#89](https://github.com/nlohmann/json/issues/89) -- static library build [\#84](https://github.com/nlohmann/json/issues/84) -- lexer::get\_number return NAN [\#82](https://github.com/nlohmann/json/issues/82) -- MinGW have no std::to\_string [\#80](https://github.com/nlohmann/json/issues/80) -- Incorrect behaviour of basic\_json::count method [\#78](https://github.com/nlohmann/json/issues/78) -- Invoking is\_array\(\) function creates "null" value [\#77](https://github.com/nlohmann/json/issues/77) -- dump\(\) / parse\(\) not idempotent [\#76](https://github.com/nlohmann/json/issues/76) -- Handle infinity and NaN cases [\#70](https://github.com/nlohmann/json/issues/70) -- errors in g++-4.8.1 [\#68](https://github.com/nlohmann/json/issues/68) -- Keys when iterating over objects [\#67](https://github.com/nlohmann/json/issues/67) -- Compilation results in tons of warnings [\#64](https://github.com/nlohmann/json/issues/64) -- Complete brief documentation [\#61](https://github.com/nlohmann/json/issues/61) -- Double quotation mark is not parsed correctly [\#60](https://github.com/nlohmann/json/issues/60) -- Get coverage back to 100% [\#58](https://github.com/nlohmann/json/issues/58) -- erase elements using iterators [\#57](https://github.com/nlohmann/json/issues/57) -- Removing item from array [\#56](https://github.com/nlohmann/json/issues/56) -- Serialize/Deserialize like PHP? [\#55](https://github.com/nlohmann/json/issues/55) -- Numbers as keys [\#54](https://github.com/nlohmann/json/issues/54) -- Why are elements alphabetized on key while iterating? [\#53](https://github.com/nlohmann/json/issues/53) -- Document erase, count, and iterators key and value [\#52](https://github.com/nlohmann/json/issues/52) -- Do not use std::to\_string [\#51](https://github.com/nlohmann/json/issues/51) -- Supported compilers [\#50](https://github.com/nlohmann/json/issues/50) -- Confused about iterating through json objects [\#49](https://github.com/nlohmann/json/issues/49) -- Use non-member begin/end [\#48](https://github.com/nlohmann/json/issues/48) -- Erase key [\#47](https://github.com/nlohmann/json/issues/47) -- Key iterator [\#46](https://github.com/nlohmann/json/issues/46) -- Add count member function [\#45](https://github.com/nlohmann/json/issues/45) -- Problem getting vector \(array\) of strings [\#44](https://github.com/nlohmann/json/issues/44) -- Compilation error due to assuming that private=public [\#43](https://github.com/nlohmann/json/issues/43) -- Use of deprecated implicit copy constructor [\#42](https://github.com/nlohmann/json/issues/42) -- Printing attribute names [\#39](https://github.com/nlohmann/json/issues/39) -- dumping a small number\_float just outputs 0.000000 [\#37](https://github.com/nlohmann/json/issues/37) -- find is error [\#32](https://github.com/nlohmann/json/issues/32) -- Avoid using spaces when encoding without pretty print [\#31](https://github.com/nlohmann/json/issues/31) -- Cannot encode long numbers [\#30](https://github.com/nlohmann/json/issues/30) -- segmentation fault when iterating over empty arrays/objects [\#28](https://github.com/nlohmann/json/issues/28) -- Creating an empty array [\#27](https://github.com/nlohmann/json/issues/27) -- Custom allocator support [\#25](https://github.com/nlohmann/json/issues/25) -- make the type of the used string container customizable [\#20](https://github.com/nlohmann/json/issues/20) -- Improper parsing of JSON string "\\" [\#17](https://github.com/nlohmann/json/issues/17) -- create a header-only version [\#16](https://github.com/nlohmann/json/issues/16) -- Don't return "const values" [\#15](https://github.com/nlohmann/json/issues/15) -- Add to\_string overload for indentation [\#13](https://github.com/nlohmann/json/issues/13) -- string parser does not recognize uncompliant strings [\#12](https://github.com/nlohmann/json/issues/12) -- possible double-free in find function [\#11](https://github.com/nlohmann/json/issues/11) -- UTF-8 encoding/deconding/testing [\#10](https://github.com/nlohmann/json/issues/10) -- move code into namespace [\#9](https://github.com/nlohmann/json/issues/9) -- free functions for explicit objects and arrays in initializer lists [\#8](https://github.com/nlohmann/json/issues/8) -- unique\_ptr for ownership [\#7](https://github.com/nlohmann/json/issues/7) -- Add unit tests [\#4](https://github.com/nlohmann/json/issues/4) -- Drop C++98 support [\#3](https://github.com/nlohmann/json/issues/3) -- Test case coverage [\#2](https://github.com/nlohmann/json/issues/2) -- Runtime error in Travis job [\#1](https://github.com/nlohmann/json/issues/1) - -- Keyword 'inline' is useless when member functions are defined in headers [\#87](https://github.com/nlohmann/json/pull/87) ([ahamez](https://github.com/ahamez)) -- Remove useless typename [\#86](https://github.com/nlohmann/json/pull/86) ([ahamez](https://github.com/ahamez)) -- Avoid warning with Xcode's clang [\#85](https://github.com/nlohmann/json/pull/85) ([ahamez](https://github.com/ahamez)) -- Fix typos [\#73](https://github.com/nlohmann/json/pull/73) ([aqnouch](https://github.com/aqnouch)) -- Replace `default\_callback` function with `nullptr` and check for null… [\#72](https://github.com/nlohmann/json/pull/72) ([aburgh](https://github.com/aburgh)) -- support enum [\#71](https://github.com/nlohmann/json/pull/71) ([likebeta](https://github.com/likebeta)) -- Fix performance regression introduced with the parsing callback feature. [\#69](https://github.com/nlohmann/json/pull/69) ([aburgh](https://github.com/aburgh)) -- Improve the implementations of the comparission-operators [\#63](https://github.com/nlohmann/json/pull/63) ([Florianjw](https://github.com/Florianjw)) -- Fix compilation of json\_unit with GCC 5 [\#59](https://github.com/nlohmann/json/pull/59) ([dkopecek](https://github.com/dkopecek)) -- Parse streams incrementally. [\#40](https://github.com/nlohmann/json/pull/40) ([aburgh](https://github.com/aburgh)) -- Feature/small float serialization [\#38](https://github.com/nlohmann/json/pull/38) ([jrandall](https://github.com/jrandall)) -- template version with re2c scanner [\#36](https://github.com/nlohmann/json/pull/36) ([nlohmann](https://github.com/nlohmann)) -- more descriptive documentation in example [\#33](https://github.com/nlohmann/json/pull/33) ([luxe](https://github.com/luxe)) -- Fix string conversion under Clang [\#26](https://github.com/nlohmann/json/pull/26) ([wancw](https://github.com/wancw)) -- Fixed dumping of strings [\#24](https://github.com/nlohmann/json/pull/24) ([Teemperor](https://github.com/Teemperor)) -- Added a remark to the readme that coverage is GCC only for now [\#23](https://github.com/nlohmann/json/pull/23) ([Teemperor](https://github.com/Teemperor)) -- Unicode escaping [\#22](https://github.com/nlohmann/json/pull/22) ([Teemperor](https://github.com/Teemperor)) -- Implemented the JSON spec for string parsing for everything but the \uXXXX escaping [\#21](https://github.com/nlohmann/json/pull/21) ([Teemperor](https://github.com/Teemperor)) -- add the std iterator typedefs to iterator and const\_iterator [\#19](https://github.com/nlohmann/json/pull/19) ([kirkshoop](https://github.com/kirkshoop)) -- Fixed escaped quotes [\#18](https://github.com/nlohmann/json/pull/18) ([Teemperor](https://github.com/Teemperor)) -- Fix double delete on std::bad\_alloc exception [\#14](https://github.com/nlohmann/json/pull/14) ([elliotgoodrich](https://github.com/elliotgoodrich)) -- Added CMake and lcov [\#6](https://github.com/nlohmann/json/pull/6) ([Teemperor](https://github.com/Teemperor)) -- Version 2.0 [\#5](https://github.com/nlohmann/json/pull/5) ([nlohmann](https://github.com/nlohmann)) - - - -\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)* \ No newline at end of file diff --git a/vendor/json/LICENSE.MIT b/vendor/json/LICENSE.MIT deleted file mode 100644 index 00599afe6..000000000 --- a/vendor/json/LICENSE.MIT +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2013-2017 Niels Lohmann - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/vendor/json/README.md b/vendor/json/README.md deleted file mode 100644 index 1334180b0..000000000 --- a/vendor/json/README.md +++ /dev/null @@ -1,903 +0,0 @@ -[![JSON for Modern C++](https://raw.githubusercontent.com/nlohmann/json/master/doc/json.gif)](https://github.com/nlohmann/json/releases) - -[![Build Status](https://travis-ci.org/nlohmann/json.svg?branch=master)](https://travis-ci.org/nlohmann/json) -[![Build Status](https://ci.appveyor.com/api/projects/status/1acb366xfyg3qybk/branch/develop?svg=true)](https://ci.appveyor.com/project/nlohmann/json) -[![Coverage Status](https://img.shields.io/coveralls/nlohmann/json.svg)](https://coveralls.io/r/nlohmann/json) -[![Coverity Scan Build Status](https://scan.coverity.com/projects/5550/badge.svg)](https://scan.coverity.com/projects/nlohmann-json) -[![Codacy Badge](https://api.codacy.com/project/badge/Grade/f3732b3327e34358a0e9d1fe9f661f08)](https://www.codacy.com/app/nlohmann/json?utm_source=github.com&utm_medium=referral&utm_content=nlohmann/json&utm_campaign=Badge_Grade) -[![Try online](https://img.shields.io/badge/try-online-blue.svg)](http://melpon.org/wandbox/permlink/4NEU6ZZMoM9lpIex) -[![Documentation](https://img.shields.io/badge/docs-doxygen-blue.svg)](http://nlohmann.github.io/json) -[![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/nlohmann/json/master/LICENSE.MIT) -[![Github Releases](https://img.shields.io/github/release/nlohmann/json.svg)](https://github.com/nlohmann/json/releases) -[![Github Issues](https://img.shields.io/github/issues/nlohmann/json.svg)](http://github.com/nlohmann/json/issues) -[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/289/badge)](https://bestpractices.coreinfrastructure.org/projects/289) - -- [Design goals](#design-goals) -- [Integration](#integration) -- [Examples](#examples) - - [JSON as first-class data type](#json-as-first-class-data-type) - - [Serialization / Deserialization](#serialization--deserialization) - - [STL-like access](#stl-like-access) - - [Conversion from STL containers](#conversion-from-stl-containers) - - [JSON Pointer and JSON Patch](#json-pointer-and-json-patch) - - [Implicit conversions](#implicit-conversions) - - [Conversions to/from arbitrary types](#arbitrary-types-conversions) - - [Binary formats (CBOR and MessagePack)](#binary-formats-cbor-and-messagepack) -- [Supported compilers](#supported-compilers) -- [License](#license) -- [Thanks](#thanks) -- [Used third-party tools](#used-third-party-tools) -- [Projects using JSON for Modern C++](#projects-using-json-for-modern-c) -- [Notes](#notes) -- [Execute unit tests](#execute-unit-tests) - -## Design goals - -There are myriads of [JSON](http://json.org) libraries out there, and each may even have its reason to exist. Our class had these design goals: - -- **Intuitive syntax**. In languages such as Python, JSON feels like a first class data type. We used all the operator magic of modern C++ to achieve the same feeling in your code. Check out the [examples below](#examples) and you'll know what I mean. - -- **Trivial integration**. Our whole code consists of a single header file [`json.hpp`](https://github.com/nlohmann/json/blob/develop/src/json.hpp). That's it. No library, no subproject, no dependencies, no complex build system. The class is written in vanilla C++11. All in all, everything should require no adjustment of your compiler flags or project settings. - -- **Serious testing**. Our class is heavily [unit-tested](https://github.com/nlohmann/json/blob/master/test/src/unit.cpp) and covers [100%](https://coveralls.io/r/nlohmann/json) of the code, including all exceptional behavior. Furthermore, we checked with [Valgrind](http://valgrind.org) that there are no memory leaks. To maintain high quality, the project is following the [Core Infrastructure Initiative (CII) best practices](https://bestpractices.coreinfrastructure.org/projects/289). - -Other aspects were not so important to us: - -- **Memory efficiency**. Each JSON object has an overhead of one pointer (the maximal size of a union) and one enumeration element (1 byte). The default generalization uses the following C++ data types: `std::string` for strings, `int64_t`, `uint64_t` or `double` for numbers, `std::map` for objects, `std::vector` for arrays, and `bool` for Booleans. However, you can template the generalized class `basic_json` to your needs. - -- **Speed**. There are certainly [faster JSON libraries](https://github.com/miloyip/nativejson-benchmark#parsing-time) out there. However, if your goal is to speed up your development by adding JSON support with a single header, then this library is the way to go. If you know how to use a `std::vector` or `std::map`, you are already set. - -See the [contribution guidelines](https://github.com/nlohmann/json/blob/master/.github/CONTRIBUTING.md#please-dont) for more information. - - -## Integration - -The single required source, file `json.hpp` is in the `src` directory or [released here](https://github.com/nlohmann/json/releases). All you need to do is add - -```cpp -#include "json.hpp" - -// for convenience -using json = nlohmann::json; -``` - -to the files you want to use JSON objects. That's it. Do not forget to set the necessary switches to enable C++11 (e.g., `-std=c++11` for GCC and Clang). - -:beer: If you are using OS X and [Homebrew](http://brew.sh), just type `brew tap nlohmann/json` and `brew install nlohmann_json` and you're set. If you want the bleeding edge rather than the latest release, use `brew install nlohmann_json --HEAD`. - - -## Examples - -Beside the examples below, you may want to check the [documentation](https://nlohmann.github.io/json/) where each function contains a separate code example (e.g., check out [`emplace()`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a602f275f0359ab181221384989810604.html#a602f275f0359ab181221384989810604)). All [example files](https://github.com/nlohmann/json/tree/develop/doc/examples) can be compiled and executed on their own (e.g., file [emplace.cpp](https://github.com/nlohmann/json/blob/develop/doc/examples/emplace.cpp)). - -### JSON as first-class data type - -Here are some examples to give you an idea how to use the class. - -Assume you want to create the JSON object - -```json -{ - "pi": 3.141, - "happy": true, - "name": "Niels", - "nothing": null, - "answer": { - "everything": 42 - }, - "list": [1, 0, 2], - "object": { - "currency": "USD", - "value": 42.99 - } -} -``` - -With the JSON class, you could write: - -```cpp -// create an empty structure (null) -json j; - -// add a number that is stored as double (note the implicit conversion of j to an object) -j["pi"] = 3.141; - -// add a Boolean that is stored as bool -j["happy"] = true; - -// add a string that is stored as std::string -j["name"] = "Niels"; - -// add another null object by passing nullptr -j["nothing"] = nullptr; - -// add an object inside the object -j["answer"]["everything"] = 42; - -// add an array that is stored as std::vector (using an initializer list) -j["list"] = { 1, 0, 2 }; - -// add another object (using an initializer list of pairs) -j["object"] = { {"currency", "USD"}, {"value", 42.99} }; - -// instead, you could also write (which looks very similar to the JSON above) -json j2 = { - {"pi", 3.141}, - {"happy", true}, - {"name", "Niels"}, - {"nothing", nullptr}, - {"answer", { - {"everything", 42} - }}, - {"list", {1, 0, 2}}, - {"object", { - {"currency", "USD"}, - {"value", 42.99} - }} -}; -``` - -Note that in all these cases, you never need to "tell" the compiler which JSON value you want to use. If you want to be explicit or express some edge cases, the functions `json::array` and `json::object` will help: - -```cpp -// a way to express the empty array [] -json empty_array_explicit = json::array(); - -// ways to express the empty object {} -json empty_object_implicit = json({}); -json empty_object_explicit = json::object(); - -// a way to express an _array_ of key/value pairs [["currency", "USD"], ["value", 42.99]] -json array_not_object = { json::array({"currency", "USD"}), json::array({"value", 42.99}) }; -``` - - -### Serialization / Deserialization - -#### To/from strings - -You can create an object (deserialization) by appending `_json` to a string literal: - -```cpp -// create object from string literal -json j = "{ \"happy\": true, \"pi\": 3.141 }"_json; - -// or even nicer with a raw string literal -auto j2 = R"( - { - "happy": true, - "pi": 3.141 - } -)"_json; -``` - -Note that without appending the `_json` suffix, the passed string literal is not parsed, but just used as JSON string value. That is, `json j = "{ \"happy\": true, \"pi\": 3.141 }"` would just store the string `"{ "happy": true, "pi": 3.141 }"` rather than parsing the actual object. - -The above example can also be expressed explicitly using `json::parse()`: - -```cpp -// parse explicitly -auto j3 = json::parse("{ \"happy\": true, \"pi\": 3.141 }"); -``` - -You can also get a string representation (serialize): - -```cpp -// explicit conversion to string -std::string s = j.dump(); // {\"happy\":true,\"pi\":3.141} - -// serialization with pretty printing -// pass in the amount of spaces to indent -std::cout << j.dump(4) << std::endl; -// { -// "happy": true, -// "pi": 3.141 -// } -``` - -#### To/from streams (e.g. files, string streams) - -You can also use streams to serialize and deserialize: - -```cpp -// deserialize from standard input -json j; -std::cin >> j; - -// serialize to standard output -std::cout << j; - -// the setw manipulator was overloaded to set the indentation for pretty printing -std::cout << std::setw(4) << j << std::endl; -``` - -These operators work for any subclasses of `std::istream` or `std::ostream`. Here is the same example with files: - -```cpp -// read a JSON file -std::ifstream i("file.json"); -json j; -i >> j; - -// write prettified JSON to another file -std::ofstream o("pretty.json"); -o << std::setw(4) << j << std::endl; -``` - -Please note that setting the exception bit for `failbit` is inappropriate for this use case. It will result in program termination due to the `noexcept` specifier in use. - -#### Read from iterator range - -You can also read JSON from an iterator range; that is, from any container accessible by iterators whose content is stored as contiguous byte sequence, for instance a `std::vector`: - -```cpp -std::vector v = {'t', 'r', 'u', 'e'}; -json j = json::parse(v.begin(), v.end()); -``` - -You may leave the iterators for the range [begin, end): - -```cpp -std::vector v = {'t', 'r', 'u', 'e'}; -json j = json::parse(v); -``` - - -### STL-like access - -We designed the JSON class to behave just like an STL container. In fact, it satisfies the [**ReversibleContainer**](http://en.cppreference.com/w/cpp/concept/ReversibleContainer) requirement. - -```cpp -// create an array using push_back -json j; -j.push_back("foo"); -j.push_back(1); -j.push_back(true); - -// also use emplace_back -j.emplace_back(1.78); - -// iterate the array -for (json::iterator it = j.begin(); it != j.end(); ++it) { - std::cout << *it << '\n'; -} - -// range-based for -for (auto& element : j) { - std::cout << element << '\n'; -} - -// getter/setter -const std::string tmp = j[0]; -j[1] = 42; -bool foo = j.at(2); - -// comparison -j == "[\"foo\", 1, true]"_json; // true - -// other stuff -j.size(); // 3 entries -j.empty(); // false -j.type(); // json::value_t::array -j.clear(); // the array is empty again - -// convenience type checkers -j.is_null(); -j.is_boolean(); -j.is_number(); -j.is_object(); -j.is_array(); -j.is_string(); - -// create an object -json o; -o["foo"] = 23; -o["bar"] = false; -o["baz"] = 3.141; - -// also use emplace -o.emplace("weather", "sunny"); - -// special iterator member functions for objects -for (json::iterator it = o.begin(); it != o.end(); ++it) { - std::cout << it.key() << " : " << it.value() << "\n"; -} - -// find an entry -if (o.find("foo") != o.end()) { - // there is an entry with key "foo" -} - -// or simpler using count() -int foo_present = o.count("foo"); // 1 -int fob_present = o.count("fob"); // 0 - -// delete an entry -o.erase("foo"); -``` - - -### Conversion from STL containers - -Any sequence container (`std::array`, `std::vector`, `std::deque`, `std::forward_list`, `std::list`) whose values can be used to construct JSON types (e.g., integers, floating point numbers, Booleans, string types, or again STL containers described in this section) can be used to create a JSON array. The same holds for similar associative containers (`std::set`, `std::multiset`, `std::unordered_set`, `std::unordered_multiset`), but in these cases the order of the elements of the array depends how the elements are ordered in the respective STL container. - -```cpp -std::vector c_vector {1, 2, 3, 4}; -json j_vec(c_vector); -// [1, 2, 3, 4] - -std::deque c_deque {1.2, 2.3, 3.4, 5.6}; -json j_deque(c_deque); -// [1.2, 2.3, 3.4, 5.6] - -std::list c_list {true, true, false, true}; -json j_list(c_list); -// [true, true, false, true] - -std::forward_list c_flist {12345678909876, 23456789098765, 34567890987654, 45678909876543}; -json j_flist(c_flist); -// [12345678909876, 23456789098765, 34567890987654, 45678909876543] - -std::array c_array {{1, 2, 3, 4}}; -json j_array(c_array); -// [1, 2, 3, 4] - -std::set c_set {"one", "two", "three", "four", "one"}; -json j_set(c_set); // only one entry for "one" is used -// ["four", "one", "three", "two"] - -std::unordered_set c_uset {"one", "two", "three", "four", "one"}; -json j_uset(c_uset); // only one entry for "one" is used -// maybe ["two", "three", "four", "one"] - -std::multiset c_mset {"one", "two", "one", "four"}; -json j_mset(c_mset); // both entries for "one" are used -// maybe ["one", "two", "one", "four"] - -std::unordered_multiset c_umset {"one", "two", "one", "four"}; -json j_umset(c_umset); // both entries for "one" are used -// maybe ["one", "two", "one", "four"] -``` - -Likewise, any associative key-value containers (`std::map`, `std::multimap`, `std::unordered_map`, `std::unordered_multimap`) whose keys can construct an `std::string` and whose values can be used to construct JSON types (see examples above) can be used to to create a JSON object. Note that in case of multimaps only one key is used in the JSON object and the value depends on the internal order of the STL container. - -```cpp -std::map c_map { {"one", 1}, {"two", 2}, {"three", 3} }; -json j_map(c_map); -// {"one": 1, "three": 3, "two": 2 } - -std::unordered_map c_umap { {"one", 1.2}, {"two", 2.3}, {"three", 3.4} }; -json j_umap(c_umap); -// {"one": 1.2, "two": 2.3, "three": 3.4} - -std::multimap c_mmap { {"one", true}, {"two", true}, {"three", false}, {"three", true} }; -json j_mmap(c_mmap); // only one entry for key "three" is used -// maybe {"one": true, "two": true, "three": true} - -std::unordered_multimap c_ummap { {"one", true}, {"two", true}, {"three", false}, {"three", true} }; -json j_ummap(c_ummap); // only one entry for key "three" is used -// maybe {"one": true, "two": true, "three": true} -``` - -### JSON Pointer and JSON Patch - -The library supports **JSON Pointer** ([RFC 6901](https://tools.ietf.org/html/rfc6901)) as alternative means to address structured values. On top of this, **JSON Patch** ([RFC 6902](https://tools.ietf.org/html/rfc6902)) allows to describe differences between two JSON values - effectively allowing patch and diff operations known from Unix. - -```cpp -// a JSON value -json j_original = R"({ - "baz": ["one", "two", "three"], - "foo": "bar" -})"_json; - -// access members with a JSON pointer (RFC 6901) -j_original["/baz/1"_json_pointer]; -// "two" - -// a JSON patch (RFC 6902) -json j_patch = R"([ - { "op": "replace", "path": "/baz", "value": "boo" }, - { "op": "add", "path": "/hello", "value": ["world"] }, - { "op": "remove", "path": "/foo"} -])"_json; - -// apply the patch -json j_result = j_original.patch(j_patch); -// { -// "baz": "boo", -// "hello": ["world"] -// } - -// calculate a JSON patch from two JSON values -json::diff(j_result, j_original); -// [ -// { "op":" replace", "path": "/baz", "value": ["one", "two", "three"] }, -// { "op": "remove","path": "/hello" }, -// { "op": "add", "path": "/foo", "value": "bar" } -// ] -``` - - -### Implicit conversions - -The type of the JSON object is determined automatically by the expression to store. Likewise, the stored value is implicitly converted. - -```cpp -// strings -std::string s1 = "Hello, world!"; -json js = s1; -std::string s2 = js; - -// Booleans -bool b1 = true; -json jb = b1; -bool b2 = jb; - -// numbers -int i = 42; -json jn = i; -double f = jn; - -// etc. -``` - -You can also explicitly ask for the value: - -```cpp -std::string vs = js.get(); -bool vb = jb.get(); -int vi = jn.get(); - -// etc. -``` - -### Arbitrary types conversions - -Every type can be serialized in JSON, not just STL-containers and scalar types. Usually, you would do something along those lines: - -```cpp -namespace ns { - // a simple struct to model a person - struct person { - std::string name; - std::string address; - int age; - }; -} - -ns::person p = {"Ned Flanders", "744 Evergreen Terrace", 60}; - -// convert to JSON: copy each value into the JSON object -json j; -j["name"] = p.name; -j["address"] = p.address; -j["age"] = p.age; - -// ... - -// convert from JSON: copy each value from the JSON object -ns::person p { - j["name"].get(), - j["address"].get(), - j["age"].get() -}; -``` - -It works, but that's quite a lot of boilerplate... Fortunately, there's a better way: - -```cpp -// create a person -ns::person p {"Ned Flanders", "744 Evergreen Terrace", 60}; - -// conversion: person -> json -json j = p; - -std::cout << j << std::endl; -// {"address":"744 Evergreen Terrace","age":60,"name":"Ned Flanders"} - -// conversion: json -> person -ns::person p2 = j; - -// that's it -assert(p == p2); -``` - -#### Basic usage - -To make this work with one of your types, you only need to provide two functions: - -```cpp -using nlohmann::json; - -namespace ns { - void to_json(json& j, const person& p) { - j = json{{"name", p.name}, {"address", p.address}, {"age", p.age}}; - } - - void from_json(const json& j, person& p) { - p.name = j["name"].get(); - p.address = j["address"].get(); - p.age = j["age"].get(); - } -} // namespace ns -``` - -That's all! When calling the `json` constructor with your type, your custom `to_json` method will be automatically called. -Likewise, when calling `get()`, the `from_json` method will be called. - -Some important things: - -* Those methods **MUST** be in your type's namespace (which can be the global namespace), or the library will not be able to locate them (in this example, they are in namespace `ns`, where `person` is defined). -* When using `get()`, `your_type` **MUST** be [DefaultConstructible](http://en.cppreference.com/w/cpp/concept/DefaultConstructible). (There is a way to bypass this requirement described later.) - -#### How do I convert third-party types? - -This requires a bit more advanced technique. But first, let's see how this conversion mechanism works: - -The library uses **JSON Serializers** to convert types to json. -The default serializer for `nlohmann::json` is `nlohmann::adl_serializer` (ADL means [Argument-Dependent Lookup](http://en.cppreference.com/w/cpp/language/adl)). - -It is implemented like this (simplified): - -```cpp -template -struct adl_serializer { - static void to_json(json& j, const T& value) { - // calls the "to_json" method in T's namespace - } - - static void from_json(const json& j, T& value) { - // same thing, but with the "from_json" method - } -}; -``` - -This serializer works fine when you have control over the type's namespace. However, what about `boost::optional`, or `std::filesystem::path` (C++17)? Hijacking the `boost` namespace is pretty bad, and it's illegal to add something other than template specializations to `std`... - -To solve this, you need to add a specialization of `adl_serializer` to the `nlohmann` namespace, here's an example: - -```cpp -// partial specialization (full specialization works too) -namespace nlohmann { - template - struct adl_serializer> { - static void to_json(json& j, const boost::optional& opt) { - if (opt == boost::none) { - j = nullptr; - } else { - j = *opt; // this will call adl_serializer::to_json which will - // find the free function to_json in T's namespace! - } - } - - static void from_json(const json& j, boost::optional& opt) { - if (j.is_null()) { - opt = boost::none; - } else { - opt = j.get(); // same as above, but with - // adl_serializer::from_json - } - } - }; -} -``` - -#### How can I use `get()` for non-default constructible/non-copyable types? - -There is a way, if your type is [MoveConstructible](http://en.cppreference.com/w/cpp/concept/MoveConstructible). You will need to specialize the `adl_serializer` as well, but with a special `from_json` overload: - -```cpp -struct move_only_type { - move_only_type() = delete; - move_only_type(int ii): i(ii) {} - move_only_type(const move_only_type&) = delete; - move_only_type(move_only_type&&) = default; - - int i; -}; - -namespace nlohmann { - template <> - struct adl_serializer { - // note: the return type is no longer 'void', and the method only takes - // one argument - static move_only_type from_json(const json& j) { - return {j.get()}; - } - - // Here's the catch! You must provide a to_json method! Otherwise you - // will not be able to convert move_only_type to json, since you fully - // specialized adl_serializer on that type - static void to_json(json& j, move_only_type t) { - j = t.i; - } - }; -} -``` - -#### Can I write my own serializer? (Advanced use) - -Yes. You might want to take a look at [`unit-udt.cpp`](https://github.com/nlohmann/json/blob/develop/test/src/unit-udt.cpp) in the test suite, to see a few examples. - -If you write your own serializer, you'll need to do a few things: - -* use a different `basic_json` alias than `nlohmann::json` (the last template parameter of `basic_json` is the `JSONSerializer`) -* use your `basic_json` alias (or a template parameter) in all your `to_json`/`from_json` methods -* use `nlohmann::to_json` and `nlohmann::from_json` when you need ADL - -Here is an example, without simplifications, that only accepts types with a size <= 32, and uses ADL. - -```cpp -// You should use void as a second template argument -// if you don't need compile-time checks on T -template::type> -struct less_than_32_serializer { - template - static void to_json(BasicJsonType& j, T value) { - // we want to use ADL, and call the correct to_json overload - using nlohmann::to_json; // this method is called by adl_serializer, - // this is where the magic happens - to_json(j, value); - } - - template - static void from_json(const BasicJsonType& j, T& value) { - // same thing here - using nlohmann::from_json; - from_json(j, value); - } -}; -``` - -Be **very** careful when reimplementing your serializer, you can stack overflow if you don't pay attention: - -```cpp -template -struct bad_serializer -{ - template - static void to_json(BasicJsonType& j, const T& value) { - // this calls BasicJsonType::json_serializer::to_json(j, value); - // if BasicJsonType::json_serializer == bad_serializer ... oops! - j = value; - } - - template - static void to_json(const BasicJsonType& j, T& value) { - // this calls BasicJsonType::json_serializer::from_json(j, value); - // if BasicJsonType::json_serializer == bad_serializer ... oops! - value = j.template get(); // oops! - } -}; -``` - -### Binary formats (CBOR and MessagePack) - -Though JSON is a ubiquitous data format, it is not a very compact format suitable for data exchange, for instance over a network. Hence, the library supports [CBOR](http://cbor.io) (Concise Binary Object Representation) and [MessagePack](http://msgpack.org) to efficiently encode JSON values to byte vectors and to decode such vectors. - -```cpp -// create a JSON value -json j = R"({"compact": true, "schema": 0})"_json; - -// serialize to CBOR -std::vector v_cbor = json::to_cbor(j); - -// 0xa2, 0x67, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0xf5, 0x66, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x00 - -// roundtrip -json j_from_cbor = json::from_cbor(v_cbor); - -// serialize to MessagePack -std::vector v_msgpack = json::to_msgpack(j); - -// 0x82, 0xa7, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0xc3, 0xa6, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x00 - -// roundtrip -json j_from_msgpack = json::from_msgpack(v_msgpack); -``` - - -## Supported compilers - -Though it's 2016 already, the support for C++11 is still a bit sparse. Currently, the following compilers are known to work: - -- GCC 4.9 - 6.0 (and possibly later) -- Clang 3.4 - 3.9 (and possibly later) -- Microsoft Visual C++ 2015 / Build Tools 14.0.25123.0 (and possibly later) - -I would be happy to learn about other compilers/versions. - -Please note: - -- GCC 4.8 does not work because of two bugs ([55817](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55817) and [57824](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57824)) in the C++11 support. Note there is a [pull request](https://github.com/nlohmann/json/pull/212) to fix some of the issues. -- Android defaults to using very old compilers and C++ libraries. To fix this, add the following to your `Application.mk`. This will switch to the LLVM C++ library, the Clang compiler, and enable C++11 and other features disabled by default. - - ``` - APP_STL := c++_shared - NDK_TOOLCHAIN_VERSION := clang3.6 - APP_CPPFLAGS += -frtti -fexceptions - ``` - - The code compiles successfully with [Android NDK](https://developer.android.com/ndk/index.html?hl=ml), Revision 9 - 11 (and possibly later) and [CrystaX's Android NDK](https://www.crystax.net/en/android/ndk) version 10. - -- For GCC running on MinGW or Android SDK, the error `'to_string' is not a member of 'std'` (or similarly, for `strtod`) may occur. Note this is not an issue with the code, but rather with the compiler itself. On Android, see above to build with a newer environment. For MinGW, please refer to [this site](http://tehsausage.com/mingw-to-string) and [this discussion](https://github.com/nlohmann/json/issues/136) for information on how to fix this bug. For Android NDK using `APP_STL := gnustl_static`, please refer to [this discussion](https://github.com/nlohmann/json/issues/219). - -The following compilers are currently used in continuous integration at [Travis](https://travis-ci.org/nlohmann/json) and [AppVeyor](https://ci.appveyor.com/project/nlohmann/json): - -| Compiler | Operating System | Version String | -|-----------------|------------------------------|----------------| -| GCC 4.9.3 | Ubuntu 14.04.4 LTS | g++-4.9 (Ubuntu 4.9.3-8ubuntu2~14.04) 4.9.3 | -| GCC 5.3.0 | Ubuntu 14.04.4 LTS | g++-5 (Ubuntu 5.3.0-3ubuntu1~14.04) 5.3.0 20151204 | -| GCC 6.1.1 | Ubuntu 14.04.4 LTS | g++-6 (Ubuntu 6.1.1-3ubuntu11~14.04.1) 6.1.1 20160511 | -| Clang 3.6.0 | Ubuntu 14.04.4 LTS | clang version 3.6.0 (tags/RELEASE_360/final) | -| Clang 3.6.1 | Ubuntu 14.04.4 LTS | clang version 3.6.1 (tags/RELEASE_361/final) | -| Clang 3.6.2 | Ubuntu 14.04.4 LTS | clang version 3.6.2 (tags/RELEASE_362/final) | -| Clang 3.7.0 | Ubuntu 14.04.4 LTS | clang version 3.7.0 (tags/RELEASE_370/final) | -| Clang 3.7.1 | Ubuntu 14.04.4 LTS | clang version 3.7.1 (tags/RELEASE_371/final) | -| Clang 3.8.0 | Ubuntu 14.04.4 LTS | clang version 3.8.0 (tags/RELEASE_380/final) | -| Clang 3.8.1 | Ubuntu 14.04.4 LTS | clang version 3.8.1 (tags/RELEASE_381/final) | -| Clang Xcode 6.4 | Darwin Kernel Version 14.3.0 (OSX 10.10.3) | Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn) | -| Clang Xcode 7.3 | Darwin Kernel Version 15.0.0 (OSX 10.10.5) | Apple LLVM version 7.3.0 (clang-703.0.29) | -| Clang Xcode 8.0 | Darwin Kernel Version 15.6.0 | Apple LLVM version 8.0.0 (clang-800.0.38) | -| Clang Xcode 8.1 | Darwin Kernel Version 16.1.0 (macOS 10.12.1) | Apple LLVM version 8.0.0 (clang-800.0.42.1) | -| Clang Xcode 8.2 | Darwin Kernel Version 16.1.0 (macOS 10.12.1) | Apple LLVM version 8.0.0 (clang-800.0.42.1) | -| Visual Studio 14 2015 | Windows Server 2012 R2 (x64) | Microsoft (R) Build Engine version 14.0.25123.0 | - - -## License - - - -The class is licensed under the [MIT License](http://opensource.org/licenses/MIT): - -Copyright © 2013-2017 [Niels Lohmann](http://nlohmann.me) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -## Thanks - -I deeply appreciate the help of the following people. - -- [Teemperor](https://github.com/Teemperor) implemented CMake support and lcov integration, realized escape and Unicode handling in the string parser, and fixed the JSON serialization. -- [elliotgoodrich](https://github.com/elliotgoodrich) fixed an issue with double deletion in the iterator classes. -- [kirkshoop](https://github.com/kirkshoop) made the iterators of the class composable to other libraries. -- [wancw](https://github.com/wanwc) fixed a bug that hindered the class to compile with Clang. -- Tomas Åblad found a bug in the iterator implementation. -- [Joshua C. Randall](https://github.com/jrandall) fixed a bug in the floating-point serialization. -- [Aaron Burghardt](https://github.com/aburgh) implemented code to parse streams incrementally. Furthermore, he greatly improved the parser class by allowing the definition of a filter function to discard undesired elements while parsing. -- [Daniel Kopeček](https://github.com/dkopecek) fixed a bug in the compilation with GCC 5.0. -- [Florian Weber](https://github.com/Florianjw) fixed a bug in and improved the performance of the comparison operators. -- [Eric Cornelius](https://github.com/EricMCornelius) pointed out a bug in the handling with NaN and infinity values. He also improved the performance of the string escaping. -- [易思龙](https://github.com/likebeta) implemented a conversion from anonymous enums. -- [kepkin](https://github.com/kepkin) patiently pushed forward the support for Microsoft Visual studio. -- [gregmarr](https://github.com/gregmarr) simplified the implementation of reverse iterators and helped with numerous hints and improvements. In particular, he pushed forward the implementation of user-defined types. -- [Caio Luppi](https://github.com/caiovlp) fixed a bug in the Unicode handling. -- [dariomt](https://github.com/dariomt) fixed some typos in the examples. -- [Daniel Frey](https://github.com/d-frey) cleaned up some pointers and implemented exception-safe memory allocation. -- [Colin Hirsch](https://github.com/ColinH) took care of a small namespace issue. -- [Huu Nguyen](https://github.com/whoshuu) correct a variable name in the documentation. -- [Silverweed](https://github.com/silverweed) overloaded `parse()` to accept an rvalue reference. -- [dariomt](https://github.com/dariomt) fixed a subtlety in MSVC type support and implemented the `get_ref()` function to get a reference to stored values. -- [ZahlGraf](https://github.com/ZahlGraf) added a workaround that allows compilation using Android NDK. -- [whackashoe](https://github.com/whackashoe) replaced a function that was marked as unsafe by Visual Studio. -- [406345](https://github.com/406345) fixed two small warnings. -- [Glen Fernandes](https://github.com/glenfe) noted a potential portability problem in the `has_mapped_type` function. -- [Corbin Hughes](https://github.com/nibroc) fixed some typos in the contribution guidelines. -- [twelsby](https://github.com/twelsby) fixed the array subscript operator, an issue that failed the MSVC build, and floating-point parsing/dumping. He further added support for unsigned integer numbers and implemented better roundtrip support for parsed numbers. -- [Volker Diels-Grabsch](https://github.com/vog) fixed a link in the README file. -- [msm-](https://github.com/msm-) added support for american fuzzy lop. -- [Annihil](https://github.com/Annihil) fixed an example in the README file. -- [Themercee](https://github.com/Themercee) noted a wrong URL in the README file. -- [Lv Zheng](https://github.com/lv-zheng) fixed a namespace issue with `int64_t` and `uint64_t`. -- [abc100m](https://github.com/abc100m) analyzed the issues with GCC 4.8 and proposed a [partial solution](https://github.com/nlohmann/json/pull/212). -- [zewt](https://github.com/zewt) added useful notes to the README file about Android. -- [Róbert Márki](https://github.com/robertmrk) added a fix to use move iterators and improved the integration via CMake. -- [Chris Kitching](https://github.com/ChrisKitching) cleaned up the CMake files. -- [Tom Needham](https://github.com/06needhamt) fixed a subtle bug with MSVC 2015 which was also proposed by [Michael K.](https://github.com/Epidal). -- [Mário Feroldi](https://github.com/thelostt) fixed a small typo. -- [duncanwerner](https://github.com/duncanwerner) found a really embarrassing performance regression in the 2.0.0 release. -- [Damien](https://github.com/dtoma) fixed one of the last conversion warnings. -- [Thomas Braun](https://github.com/t-b) fixed a warning in a test case. -- [Théo DELRIEU](https://github.com/theodelrieu) patiently and constructively oversaw the long way toward [iterator-range parsing](https://github.com/nlohmann/json/issues/290). He also implemented the magic behind the serialization/deserialization of user-defined types. -- [Stefan](https://github.com/5tefan) fixed a minor issue in the documentation. -- [Vasil Dimov](https://github.com/vasild) fixed the documentation regarding conversions from `std::multiset`. -- [ChristophJud](https://github.com/ChristophJud) overworked the CMake files to ease project inclusion. -- [Vladimir Petrigo](https://github.com/vpetrigo) made a SFINAE hack more readable. -- [Denis Andrejew](https://github.com/seeekr) fixed a grammar issue in the README file. -- [Pierre-Antoine Lacaze](https://github.com/palacaze) found a subtle bug in the `dump()` function. -- [TurpentineDistillery](https://github.com/TurpentineDistillery) pointed to [`std::locale::classic()`](http://en.cppreference.com/w/cpp/locale/locale/classic) to avoid too much locale joggling, found some nice performance improvements in the parser, improved the benchmarking code, and realized locale-independent number parsing and printing. -- [cgzones](https://github.com/cgzones) had an idea how to fix the Coverity scan. -- [Jared Grubb](https://github.com/jaredgrubb) silenced a nasty documentation warning. -- [Yixin Zhang](https://github.com/qwename) fixed an integer overflow check. -- [Bosswestfalen](https://github.com/Bosswestfalen) merged two iterator classes into a smaller one. -- [Daniel599](https://github.com/Daniel599) helped to get Travis execute the tests with Clang's sanitizers. -- [Jonathan Lee](https://github.com/vjon) fixed an example in the README file. -- [gnzlbg](https://github.com/gnzlbg) supported the implementation of user-defined types. -- [Alexej Harm](https://github.com/qis) helped to get the user-defined types working with Visual Studio. -- [Jared Grubb](https://github.com/jaredgrubb) supported the implementation of user-defined types. -- [EnricoBilla](https://github.com/EnricoBilla) noted a typo in an example. -- [Martin Hořeňovský](https://github.com/horenmar) found a way for a 2x speedup for the compilation time of the test suite. -- [ukhegg](https://github.com/ukhegg) found proposed an improvement for the examples section. -- [rswanson-ihi](https://github.com/rswanson-ihi) noted a type in the README. -- [Mihai Stan](https://github.com/stanmihai4) fixed a bug in the comparison with `nullptr`s. -- [Tushar Maheshwari](https://github.com/tusharpm) added [cotire](https://github.com/sakra/cotire) support to speed up the compilation. - -Thanks a lot for helping out! Please [let me know](mailto:mail@nlohmann.me) if I forgot someone. - - -## Used third-party tools - -The library itself contains of a single header file licensed under the MIT license. However, it is built, tested, documented, and whatnot using a lot of thirs-party tools and services. Thanks a lot! - -- [**American fuzzy lop**](http://lcamtuf.coredump.cx/afl/) for fuzz testing -- [**AppVeyor**](https://www.appveyor.com) for [continuous integration](https://ci.appveyor.com/project/nlohmann/json) on Windows -- [**Artistic Style**](http://astyle.sourceforge.net) for automatic source code identation -- [**benchpress**](https://github.com/sbs-ableton/benchpress) to benchmark the code -- [**Catch**](https://github.com/philsquared/Catch) for the unit tests -- [**Clang**](http://clang.llvm.org) for compilation with code sanitizers -- [**Cmake**](https://cmake.org) for build automation -- [**Codacity**](https://www.codacy.com) for further [code analysis](https://www.codacy.com/app/nlohmann/json) -- [**cotire**](https://github.com/sakra/cotire) to speed of compilation -- [**Coveralls**](https://coveralls.io) to measure [code coverage](https://coveralls.io/github/nlohmann/json) -- [**Coverity Scan**](https://scan.coverity.com) for [static analysis](https://scan.coverity.com/projects/nlohmann-json) -- [**cppcheck**](http://cppcheck.sourceforge.net) for static analysis -- [**cxxopts**](https://github.com/jarro2783/cxxopts) to let benchpress parse command-line parameters -- [**Doxygen**](http://www.stack.nl/~dimitri/doxygen/) to generate [documentation](https://nlohmann.github.io/json/) -- [**git-update-ghpages**](https://github.com/rstacruz/git-update-ghpages) to upload the documentation to gh-pages -- [**Github Changelog Generator**](https://github.com/skywinder/github-changelog-generator) to generate the [ChangeLog](https://github.com/nlohmann/json/blob/develop/ChangeLog.md) -- [**libFuzzer**](http://llvm.org/docs/LibFuzzer.html) to implement fuzz testing for OSS-Fuzz -- [**OSS-Fuzz**](https://github.com/google/oss-fuzz) for continuous fuzz testing of the library -- [**re2c**](http://re2c.org) to generate an automaton for the lexical analysis -- [**send_to_wandbox**](https://github.com/nlohmann/json/blob/develop/doc/scripts/send_to_wandbox.py) to send code examples to [Wandbox](http://melpon.org/wandbox) -- [**Travis**](https://travis-ci.org) for [continuous integration](https://travis-ci.org/nlohmann/json) on Linux and macOS -- [**Valgrind**](http://valgrind.org) to check for correct memory management -- [**Wandbox**](http://melpon.org/wandbox) for [online examples](http://melpon.org/wandbox/permlink/4NEU6ZZMoM9lpIex) - - -## Projects using JSON for Modern C++ - -The library is currently used in Apple macOS Sierra and iOS 10. I am not sure what they are using the library for, but I am happy that it runs on so many devices. - - -## Notes - -- The code contains numerous debug **assertions** which can be switched off by defining the preprocessor macro `NDEBUG`, see the [documentation of `assert`](http://en.cppreference.com/w/cpp/error/assert). In particular, note [`operator[]`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a2e26bd0b0168abb61f67ad5bcd5b9fa1.html#a2e26bd0b0168abb61f67ad5bcd5b9fa1) implements **unchecked access** for const objects: If the given key is not present, the behavior is undefined (think of a dereferenced null pointer) and yields an [assertion failure](https://github.com/nlohmann/json/issues/289) if assertions are switched on. If you are not sure whether an element in an object exists, use checked access with the [`at()` function](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a674de1ee73e6bf4843fc5dc1351fb726.html#a674de1ee73e6bf4843fc5dc1351fb726). -- As the exact type of a number is not defined in the [JSON specification](http://rfc7159.net/rfc7159), this library tries to choose the best fitting C++ number type automatically. As a result, the type `double` may be used to store numbers which may yield [**floating-point exceptions**](https://github.com/nlohmann/json/issues/181) in certain rare situations if floating-point exceptions have been unmasked in the calling code. These exceptions are not caused by the library and need to be fixed in the calling code, such as by re-masking the exceptions prior to calling library functions. -- The library supports **Unicode input** as follows: - - Only **UTF-8** encoded input is supported which is the default encoding for JSON according to [RFC 7159](http://rfc7159.net/rfc7159#rfc.section.8.1). - - Other encodings such as Latin-1, UTF-16, or UTF-32 are not supported and will yield parse errors. - - [Unicode noncharacters](http://www.unicode.org/faq/private_use.html#nonchar1) will not be replaced by the library. - - Invalid surrogates (e.g., incomplete pairs such as `\uDEAD`) will yield parse errors. - - The strings stored in the library are UTF-8 encoded. When using the default string type (`std::string`), note that its length/size functions return the number of stored bytes rather than the number of characters or glyphs. -- The code can be compiled without C++ **runtime type identification** features; that is, you can use the `-fno-rtti` compiler flag. -- **Exceptions** are used widly within the library. They can, however, be switched off with either using the compiler flag `-fno-exceptions` or by defining the symbol `JSON_NOEXCEPTION`. In this case, exceptions are replaced by an `abort()` call. - - -## Execute unit tests - -To compile and run the tests, you need to execute - -```sh -$ make json_unit -Ctest -$ ./test/json_unit "*"" - -=============================================================================== -All tests passed (11202597 assertions in 47 test cases) -``` - -Alternatively, you can use [CMake](https://cmake.org) and run - -```sh -$ mkdir build -$ cd build -$ cmake .. -$ make -$ ctest -``` - -For more information, have a look at the file [.travis.yml](https://github.com/nlohmann/json/blob/master/.travis.yml). diff --git a/vendor/json/src/json.hpp b/vendor/json/src/json.hpp deleted file mode 100644 index a83462fbf..000000000 --- a/vendor/json/src/json.hpp +++ /dev/null @@ -1,14031 +0,0 @@ -/* - __ _____ _____ _____ - __| | __| | | | JSON for Modern C++ -| | |__ | | | | | | version 2.1.1 -|_____|_____|_____|_|___| https://github.com/nlohmann/json - -Licensed under the MIT License . -Copyright (c) 2013-2017 Niels Lohmann . - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -#ifndef NLOHMANN_JSON_HPP -#define NLOHMANN_JSON_HPP - -#include // all_of, copy, fill, find, for_each, none_of, remove, reverse, transform -#include // array -#include // assert -#include // and, not, or -#include // lconv, localeconv -#include // isfinite, labs, ldexp, signbit -#include // nullptr_t, ptrdiff_t, size_t -#include // int64_t, uint64_t -#include // abort, strtod, strtof, strtold, strtoul, strtoll, strtoull -#include // strlen -#include // forward_list -#include // function, hash, less -#include // initializer_list -#include // istream, ostream -#include // advance, begin, back_inserter, bidirectional_iterator_tag, distance, end, inserter, iterator, iterator_traits, next, random_access_iterator_tag, reverse_iterator -#include // numeric_limits -#include // locale -#include // map -#include // addressof, allocator, allocator_traits, unique_ptr -#include // accumulate -#include // stringstream -#include // getline, stoi, string, to_string -#include // add_pointer, conditional, decay, enable_if, false_type, integral_constant, is_arithmetic, is_base_of, is_const, is_constructible, is_convertible, is_default_constructible, is_enum, is_floating_point, is_integral, is_nothrow_move_assignable, is_nothrow_move_constructible, is_pointer, is_reference, is_same, is_scalar, is_signed, remove_const, remove_cv, remove_pointer, remove_reference, true_type, underlying_type -#include // declval, forward, make_pair, move, pair, swap -#include // vector - -// exclude unsupported compilers -#if defined(__clang__) - #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400 - #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" - #endif -#elif defined(__GNUC__) - #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40900 - #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" - #endif -#endif - -// disable float-equal warnings on GCC/clang -#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wfloat-equal" -#endif - -// disable documentation warnings on clang -#if defined(__clang__) - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wdocumentation" -#endif - -// allow for portable deprecation warnings -#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) - #define JSON_DEPRECATED __attribute__((deprecated)) -#elif defined(_MSC_VER) - #define JSON_DEPRECATED __declspec(deprecated) -#else - #define JSON_DEPRECATED -#endif - -// allow to disable exceptions -#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && not defined(JSON_NOEXCEPTION) - #define JSON_THROW(exception) throw exception - #define JSON_TRY try - #define JSON_CATCH(exception) catch(exception) -#else - #define JSON_THROW(exception) std::abort() - #define JSON_TRY if(true) - #define JSON_CATCH(exception) if(false) -#endif - -/*! -@brief namespace for Niels Lohmann -@see https://github.com/nlohmann -@since version 1.0.0 -*/ -namespace nlohmann -{ - -/*! -@brief unnamed namespace with internal helper functions - -This namespace collects some functions that could not be defined inside the -@ref basic_json class. - -@since version 2.1.0 -*/ -namespace detail -{ -//////////////// -// exceptions // -//////////////// - -/*! -@brief general exception of the @ref basic_json class - -Extension of std::exception objects with a member @a id for exception ids. - -@note To have nothrow-copy-constructible exceptions, we internally use - std::runtime_error which can cope with arbitrary-length error messages. - Intermediate strings are built with static functions and then passed to - the actual constructor. - -@since version 3.0.0 -*/ -class exception : public std::exception -{ - public: - /// returns the explanatory string - virtual const char* what() const noexcept override - { - return m.what(); - } - - /// the id of the exception - const int id; - - protected: - exception(int id_, const char* what_arg) - : id(id_), m(what_arg) - {} - - static std::string name(const std::string& ename, int id) - { - return "[json.exception." + ename + "." + std::to_string(id) + "] "; - } - - private: - /// an exception object as storage for error messages - std::runtime_error m; -}; - -/*! -@brief exception indicating a parse error - -This excpetion is thrown by the library when a parse error occurs. Parse -errors can occur during the deserialization of JSON text as well as when -using JSON Patch. - -Member @a byte holds the byte index of the last read character in the input -file. - -@note For an input with n bytes, 1 is the index of the first character - and n+1 is the index of the terminating null byte or the end of - file. This also holds true when reading a byte vector (CBOR or - MessagePack). - -Exceptions have ids 1xx. - -name / id | example massage | description ------------------------------- | --------------- | ------------------------- -json.exception.parse_error.101 | parse error at 2: unexpected end of input; expected string literal | This error indicates a syntax error while deserializing a JSON text. The error message describes that an unexpected token (character) was encountered, and the member @a byte indicates the error position. -json.exception.parse_error.102 | parse error at 14: missing or wrong low surrogate | JSON uses the `\uxxxx` format to describe Unicode characters. Code points above above 0xFFFF are split into two `\uxxxx` entries ("surrogate pairs"). This error indicates that the surrogate pair is incomplete or contains an invalid code point. -json.exception.parse_error.103 | parse error: code points above 0x10FFFF are invalid | Unicode supports code points up to 0x10FFFF. Code points above 0x10FFFF are invalid. -json.exception.parse_error.104 | parse error: JSON patch must be an array of objects | [RFC 6902](https://tools.ietf.org/html/rfc6902) requires a JSON Patch document to be a JSON document that represents an array of objects. -json.exception.parse_error.105 | parse error: operation must have string member 'op' | An operation of a JSON Patch document must contain exactly one "op" member, whose value indicates the operation to perform. Its value must be one of "add", "remove", "replace", "move", "copy", or "test"; other values are errors. -json.exception.parse_error.106 | parse error: array index '01' must not begin with '0' | An array index in a JSON Pointer ([RFC 6901](https://tools.ietf.org/html/rfc6901)) may be `0` or any number wihtout a leading `0`. -json.exception.parse_error.107 | parse error: JSON pointer must be empty or begin with '/' - was: 'foo' | A JSON Pointer must be a Unicode string containing a sequence of zero or more reference tokens, each prefixed by a `/` character. -json.exception.parse_error.108 | parse error: escape character '~' must be followed with '0' or '1' | In a JSON Pointer, only `~0` and `~1` are valid escape sequences. -json.exception.parse_error.109 | parse error: array index 'one' is not a number | A JSON Pointer array index must be a number. -json.exception.parse_error.110 | parse error at 1: cannot read 2 bytes from vector | When parsing CBOR or MessagePack, the byte vector ends before the complete value has been read. -json.exception.parse_error.111 | parse error: bad input stream | Parsing CBOR or MessagePack from an input stream where the [`badbit` or `failbit`](http://en.cppreference.com/w/cpp/io/ios_base/iostate) is set. -json.exception.parse_error.112 | parse error at 1: error reading CBOR; last byte: 0xf8 | Not all types of CBOR or MessagePack are supported. This exception occurs if an unsupported byte was read. -json.exception.parse_error.113 | parse error at 2: expected a CBOR string; last byte: 0x98 | While parsing a map key, a value that is not a string has been read. - -@since version 3.0.0 -*/ -class parse_error : public exception -{ - public: - /*! - @brief create a parse error exception - @param[in] id the id of the exception - @param[in] byte_ the byte index where the error occured (or 0 if - the position cannot be determined) - @param[in] what_arg the explanatory string - @return parse_error object - */ - static parse_error create(int id, size_t byte_, const std::string& what_arg) - { - std::string w = exception::name("parse_error", id) + "parse error" + - (byte_ != 0 ? (" at " + std::to_string(byte_)) : "") + - ": " + what_arg; - return parse_error(id, byte_, w.c_str()); - } - - /*! - @brief byte index of the parse error - - The byte index of the last read character in the input file. - - @note For an input with n bytes, 1 is the index of the first character - and n+1 is the index of the terminating null byte or the end of - file. This also holds true when reading a byte vector (CBOR or - MessagePack). - */ - const size_t byte; - - private: - parse_error(int id_, size_t byte_, const char* what_arg) - : exception(id_, what_arg), byte(byte_) - {} -}; - -/*! -@brief exception indicating errors with iterators - -Exceptions have ids 2xx. - -name / id | example massage | description ------------------------------------ | --------------- | ------------------------- -json.exception.invalid_iterator.201 | iterators are not compatible | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid. -json.exception.invalid_iterator.202 | iterator does not fit current value | In an erase or insert function, the passed iterator @a pos does not belong to the JSON value for which the function was called. It hence does not define a valid position for the deletion/insertion. -json.exception.invalid_iterator.203 | iterators do not fit current value | Either iterator passed to function @ref erase(IteratorType first, IteratorType last) does not belong to the JSON value from which values shall be erased. It hence does not define a valid range to delete values from. -json.exception.invalid_iterator.204 | iterators out of range | When an iterator range for a primitive type (number, boolean, or string) is passed to a constructor or an erase function, this range has to be exactly (@ref begin(), @ref end()), because this is the only way the single stored value is expressed. All other ranges are invalid. -json.exception.invalid_iterator.205 | iterator out of range | When an iterator for a primitive type (number, boolean, or string) is passed to an erase function, the iterator has to be the @ref begin() iterator, because it is the only way to address the stored value. All other iterators are invalid. -json.exception.invalid_iterator.206 | cannot construct with iterators from null | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) belong to a JSON null value and hence to not define a valid range. -json.exception.invalid_iterator.207 | cannot use key() for non-object iterators | The key() member function can only be used on iterators belonging to a JSON object, because other types do not have a concept of a key. -json.exception.invalid_iterator.208 | cannot use operator[] for object iterators | The operator[] to specify a concrete offset cannot be used on iterators belonging to a JSON object, because JSON objects are unordered. -json.exception.invalid_iterator.209 | cannot use offsets with object iterators | The offset operators (+, -, +=, -=) cannot be used on iterators belonging to a JSON object, because JSON objects are unordered. -json.exception.invalid_iterator.210 | iterators do not fit | The iterator range passed to the insert function are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid. -json.exception.invalid_iterator.211 | passed iterators may not belong to container | The iterator range passed to the insert function must not be a subrange of the container to insert to. -json.exception.invalid_iterator.212 | cannot compare iterators of different containers | When two iterators are compared, they must belong to the same container. -json.exception.invalid_iterator.213 | cannot compare order of object iterators | The order of object iterators cannot be compated, because JSON objects are unordered. -json.exception.invalid_iterator.214 | cannot get value | Cannot get value for iterator: Either the iterator belongs to a null value or it is an iterator to a primitive type (number, boolean, or string), but the iterator is different to @ref begin(). - -@since version 3.0.0 -*/ -class invalid_iterator : public exception -{ - public: - static invalid_iterator create(int id, const std::string& what_arg) - { - std::string w = exception::name("invalid_iterator", id) + what_arg; - return invalid_iterator(id, w.c_str()); - } - - private: - invalid_iterator(int id_, const char* what_arg) - : exception(id_, what_arg) - {} -}; - -/*! -@brief exception indicating executing a member function with a wrong type - -Exceptions have ids 3xx. - -name / id | example massage | description ------------------------------ | --------------- | ------------------------- -json.exception.type_error.301 | cannot create object from initializer list | To create an object from an initializer list, the initializer list must consist only of a list of pairs whose first element is a string. When this constraint is violated, an array is created instead. -json.exception.type_error.302 | type must be object, but is array | During implicit or explicit value conversion, the JSON type must be compatible to the target type. For instance, a JSON string can only be converted into string types, but not into numbers or boolean types. -json.exception.type_error.303 | incompatible ReferenceType for get_ref, actual type is object | To retrieve a reference to a value stored in a @ref basic_json object with @ref get_ref, the type of the reference must match the value type. For instance, for a JSON array, the @a ReferenceType must be @ref array_t&. -json.exception.type_error.304 | cannot use at() with string | The @ref at() member functions can only be executed for certain JSON types. -json.exception.type_error.305 | cannot use operator[] with string | The @ref operator[] member functions can only be executed for certain JSON types. -json.exception.type_error.306 | cannot use value() with string | The @ref value() member functions can only be executed for certain JSON types. -json.exception.type_error.307 | cannot use erase() with string | The @ref erase() member functions can only be executed for certain JSON types. -json.exception.type_error.308 | cannot use push_back() with string | The @ref push_back() and @ref operator+= member functions can only be executed for certain JSON types. -json.exception.type_error.309 | cannot use insert() with | The @ref insert() member functions can only be executed for certain JSON types. -json.exception.type_error.310 | cannot use swap() with number | The @ref swap() member functions can only be executed for certain JSON types. -json.exception.type_error.311 | cannot use emplace_back() with string | The @ref emplace_back() member function can only be executed for certain JSON types. -json.exception.type_error.313 | invalid value to unflatten | The @ref unflatten function converts an object whose keys are JSON Pointers back into an arbitrary nested JSON value. The JSON Pointers must not overlap, because then the resulting value would not be well defined. -json.exception.type_error.314 | only objects can be unflattened | The @ref unflatten function only works for an object whose keys are JSON Pointers. -json.exception.type_error.315 | values in object must be primitive | The @ref unflatten function only works for an object whose keys are JSON Pointers and whose values are primitive. - -@since version 3.0.0 -*/ -class type_error : public exception -{ - public: - static type_error create(int id, const std::string& what_arg) - { - std::string w = exception::name("type_error", id) + what_arg; - return type_error(id, w.c_str()); - } - - private: - type_error(int id_, const char* what_arg) - : exception(id_, what_arg) - {} -}; - -/*! -@brief exception indicating access out of the defined range - -Exceptions have ids 4xx. - -name / id | example massage | description -------------------------------- | --------------- | ------------------------- -json.exception.out_of_range.401 | array index 3 is out of range | The provided array index @a i is larger than @a size-1. -json.exception.out_of_range.402 | array index '-' (3) is out of range | The special array index `-` in a JSON Pointer never describes a valid element of the array, but the index past the end. That is, it can only be used to add elements at this position, but not to read it. -json.exception.out_of_range.403 | key 'foo' not found | The provided key was not found in the JSON object. -json.exception.out_of_range.404 | unresolved reference token 'foo' | A reference token in a JSON Pointer could not be resolved. -json.exception.out_of_range.405 | JSON pointer has no parent | The JSON Patch operations 'remove' and 'add' can not be applied to the root element of the JSON value. -json.exception.out_of_range.406 | number overflow parsing '10E1000' | A parsed number could not be stored as without changing it to NaN or INF. - -@since version 3.0.0 -*/ -class out_of_range : public exception -{ - public: - static out_of_range create(int id, const std::string& what_arg) - { - std::string w = exception::name("out_of_range", id) + what_arg; - return out_of_range(id, w.c_str()); - } - - private: - out_of_range(int id_, const char* what_arg) - : exception(id_, what_arg) - {} -}; - -/*! -@brief exception indicating other errors - -Exceptions have ids 5xx. - -name / id | example massage | description ------------------------------- | --------------- | ------------------------- -json.exception.other_error.501 | unsuccessful: {"op":"test","path":"/baz", "value":"bar"} | A JSON Patch operation 'test' failed. The unsuccessful operation is also printed. - -@since version 3.0.0 -*/ -class other_error : public exception -{ - public: - static other_error create(int id, const std::string& what_arg) - { - std::string w = exception::name("other_error", id) + what_arg; - return other_error(id, w.c_str()); - } - - private: - other_error(int id_, const char* what_arg) - : exception(id_, what_arg) - {} -}; - - - -/////////////////////////// -// JSON type enumeration // -/////////////////////////// - -/*! -@brief the JSON type enumeration - -This enumeration collects the different JSON types. It is internally used to -distinguish the stored values, and the functions @ref basic_json::is_null(), -@ref basic_json::is_object(), @ref basic_json::is_array(), -@ref basic_json::is_string(), @ref basic_json::is_boolean(), -@ref basic_json::is_number() (with @ref basic_json::is_number_integer(), -@ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()), -@ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and -@ref basic_json::is_structured() rely on it. - -@note There are three enumeration entries (number_integer, number_unsigned, and -number_float), because the library distinguishes these three types for numbers: -@ref basic_json::number_unsigned_t is used for unsigned integers, -@ref basic_json::number_integer_t is used for signed integers, and -@ref basic_json::number_float_t is used for floating-point numbers or to -approximate integers which do not fit in the limits of their respective type. - -@sa @ref basic_json::basic_json(const value_t value_type) -- create a JSON -value with the default value for a given type - -@since version 1.0.0 -*/ -enum class value_t : uint8_t -{ - null, ///< null value - object, ///< object (unordered set of name/value pairs) - array, ///< array (ordered collection of values) - string, ///< string value - boolean, ///< boolean value - number_integer, ///< number value (signed integer) - number_unsigned, ///< number value (unsigned integer) - number_float, ///< number value (floating-point) - discarded ///< discarded by the the parser callback function -}; - -/*! -@brief comparison operator for JSON types - -Returns an ordering that is similar to Python: -- order: null < boolean < number < object < array < string -- furthermore, each type is not smaller than itself - -@since version 1.0.0 -*/ -inline bool operator<(const value_t lhs, const value_t rhs) noexcept -{ - static constexpr std::array order = {{ - 0, // null - 3, // object - 4, // array - 5, // string - 1, // boolean - 2, // integer - 2, // unsigned - 2, // float - } - }; - - // discarded values are not comparable - if (lhs == value_t::discarded or rhs == value_t::discarded) - { - return false; - } - - return order[static_cast(lhs)] < - order[static_cast(rhs)]; -} - - -///////////// -// helpers // -///////////// - -// alias templates to reduce boilerplate -template -using enable_if_t = typename std::enable_if::type; - -template -using uncvref_t = typename std::remove_cv::type>::type; - -/* -Implementation of two C++17 constructs: conjunction, negation. This is needed -to avoid evaluating all the traits in a condition - -For example: not std::is_same::value and has_value_type::value -will not compile when T = void (on MSVC at least). Whereas -conjunction>, has_value_type>::value will -stop evaluating if negation<...>::value == false - -Please note that those constructs must be used with caution, since symbols can -become very long quickly (which can slow down compilation and cause MSVC -internal compiler errors). Only use it when you have to (see example ahead). -*/ -template struct conjunction : std::true_type {}; -template struct conjunction : B1 {}; -template -struct conjunction : std::conditional, B1>::type {}; - -template struct negation : std::integral_constant < bool, !B::value > {}; - -// dispatch utility (taken from ranges-v3) -template struct priority_tag : priority_tag < N - 1 > {}; -template<> struct priority_tag<0> {}; - - -////////////////// -// constructors // -////////////////// - -template struct external_constructor; - -template<> -struct external_constructor -{ - template - static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept - { - j.m_type = value_t::boolean; - j.m_value = b; - j.assert_invariant(); - } -}; - -template<> -struct external_constructor -{ - template - static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s) - { - j.m_type = value_t::string; - j.m_value = s; - j.assert_invariant(); - } -}; - -template<> -struct external_constructor -{ - template - static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept - { - j.m_type = value_t::number_float; - j.m_value = val; - j.assert_invariant(); - } -}; - -template<> -struct external_constructor -{ - template - static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept - { - j.m_type = value_t::number_unsigned; - j.m_value = val; - j.assert_invariant(); - } -}; - -template<> -struct external_constructor -{ - template - static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept - { - j.m_type = value_t::number_integer; - j.m_value = val; - j.assert_invariant(); - } -}; - -template<> -struct external_constructor -{ - template - static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr) - { - j.m_type = value_t::array; - j.m_value = arr; - j.assert_invariant(); - } - - template::value, - int> = 0> - static void construct(BasicJsonType& j, const CompatibleArrayType& arr) - { - using std::begin; - using std::end; - j.m_type = value_t::array; - j.m_value.array = j.template create(begin(arr), end(arr)); - j.assert_invariant(); - } - - template - static void construct(BasicJsonType& j, const std::vector& arr) - { - j.m_type = value_t::array; - j.m_value = value_t::array; - j.m_value.array->reserve(arr.size()); - for (bool x : arr) - { - j.m_value.array->push_back(x); - } - j.assert_invariant(); - } -}; - -template<> -struct external_constructor -{ - template - static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj) - { - j.m_type = value_t::object; - j.m_value = obj; - j.assert_invariant(); - } - - template::value, - int> = 0> - static void construct(BasicJsonType& j, const CompatibleObjectType& obj) - { - using std::begin; - using std::end; - - j.m_type = value_t::object; - j.m_value.object = j.template create(begin(obj), end(obj)); - j.assert_invariant(); - } -}; - - -//////////////////////// -// has_/is_ functions // -//////////////////////// - -/*! -@brief Helper to determine whether there's a key_type for T. - -This helper is used to tell associative containers apart from other containers -such as sequence containers. For instance, `std::map` passes the test as it -contains a `mapped_type`, whereas `std::vector` fails the test. - -@sa http://stackoverflow.com/a/7728728/266378 -@since version 1.0.0, overworked in version 2.0.6 -*/ -#define NLOHMANN_JSON_HAS_HELPER(type) \ - template struct has_##type { \ - private: \ - template \ - static int detect(U &&); \ - static void detect(...); \ - public: \ - static constexpr bool value = \ - std::is_integral()))>::value; \ - } - -NLOHMANN_JSON_HAS_HELPER(mapped_type); -NLOHMANN_JSON_HAS_HELPER(key_type); -NLOHMANN_JSON_HAS_HELPER(value_type); -NLOHMANN_JSON_HAS_HELPER(iterator); - -#undef NLOHMANN_JSON_HAS_HELPER - - -template -struct is_compatible_object_type_impl : std::false_type {}; - -template -struct is_compatible_object_type_impl -{ - static constexpr auto value = - std::is_constructible::value and - std::is_constructible::value; -}; - -template -struct is_compatible_object_type -{ - static auto constexpr value = is_compatible_object_type_impl < - conjunction>, - has_mapped_type, - has_key_type>::value, - typename BasicJsonType::object_t, CompatibleObjectType >::value; -}; - -template -struct is_basic_json_nested_type -{ - static auto constexpr value = std::is_same::value or - std::is_same::value or - std::is_same::value or - std::is_same::value or - std::is_same::value; -}; - -template -struct is_compatible_array_type -{ - static auto constexpr value = - conjunction>, - negation>, - negation>, - negation>, - has_value_type, - has_iterator>::value; -}; - -template -struct is_compatible_integer_type_impl : std::false_type {}; - -template -struct is_compatible_integer_type_impl -{ - // is there an assert somewhere on overflows? - using RealLimits = std::numeric_limits; - using CompatibleLimits = std::numeric_limits; - - static constexpr auto value = - std::is_constructible::value and - CompatibleLimits::is_integer and - RealLimits::is_signed == CompatibleLimits::is_signed; -}; - -template -struct is_compatible_integer_type -{ - static constexpr auto value = - is_compatible_integer_type_impl < - std::is_integral::value and - not std::is_same::value, - RealIntegerType, CompatibleNumberIntegerType > ::value; -}; - - -// trait checking if JSONSerializer::from_json(json const&, udt&) exists -template -struct has_from_json -{ - private: - // also check the return type of from_json - template::from_json( - std::declval(), std::declval()))>::value>> - static int detect(U&&); - static void detect(...); - - public: - static constexpr bool value = std::is_integral>()))>::value; -}; - -// This trait checks if JSONSerializer::from_json(json const&) exists -// this overload is used for non-default-constructible user-defined-types -template -struct has_non_default_from_json -{ - private: - template < - typename U, - typename = enable_if_t::from_json(std::declval()))>::value >> - static int detect(U&&); - static void detect(...); - - public: - static constexpr bool value = std::is_integral>()))>::value; -}; - -// This trait checks if BasicJsonType::json_serializer::to_json exists -template -struct has_to_json -{ - private: - template::to_json( - std::declval(), std::declval()))> - static int detect(U&&); - static void detect(...); - - public: - static constexpr bool value = std::is_integral>()))>::value; -}; - - -///////////// -// to_json // -///////////// - -template::value, int> = 0> -void to_json(BasicJsonType& j, T b) noexcept -{ - external_constructor::construct(j, b); -} - -template::value, int> = 0> -void to_json(BasicJsonType& j, const CompatibleString& s) -{ - external_constructor::construct(j, s); -} - -template::value, int> = 0> -void to_json(BasicJsonType& j, FloatType val) noexcept -{ - external_constructor::construct(j, static_cast(val)); -} - -template < - typename BasicJsonType, typename CompatibleNumberUnsignedType, - enable_if_t::value, int> = 0 > -void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept -{ - external_constructor::construct(j, static_cast(val)); -} - -template < - typename BasicJsonType, typename CompatibleNumberIntegerType, - enable_if_t::value, int> = 0 > -void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept -{ - external_constructor::construct(j, static_cast(val)); -} - -template::value, int> = 0> -void to_json(BasicJsonType& j, EnumType e) noexcept -{ - using underlying_type = typename std::underlying_type::type; - external_constructor::construct(j, static_cast(e)); -} - -template -void to_json(BasicJsonType& j, const std::vector& e) -{ - external_constructor::construct(j, e); -} - -template < - typename BasicJsonType, typename CompatibleArrayType, - enable_if_t < - is_compatible_array_type::value or - std::is_same::value, - int > = 0 > -void to_json(BasicJsonType& j, const CompatibleArrayType& arr) -{ - external_constructor::construct(j, arr); -} - -template < - typename BasicJsonType, typename CompatibleObjectType, - enable_if_t::value, - int> = 0 > -void to_json(BasicJsonType& j, const CompatibleObjectType& arr) -{ - external_constructor::construct(j, arr); -} - -template ::value, - int> = 0> -void to_json(BasicJsonType& j, T (&arr)[N]) -{ - external_constructor::construct(j, arr); -} - -/////////////// -// from_json // -/////////////// - -// overloads for basic_json template parameters -template::value and - not std::is_same::value, - int> = 0> -void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val) -{ - switch (static_cast(j)) - { - case value_t::number_unsigned: - { - val = static_cast( - *j.template get_ptr()); - break; - } - case value_t::number_integer: - { - val = static_cast( - *j.template get_ptr()); - break; - } - case value_t::number_float: - { - val = static_cast( - *j.template get_ptr()); - break; - } - default: - { - JSON_THROW(type_error::create(302, "type must be number, but is " + j.type_name())); - } - } -} - -template -void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b) -{ - if (not j.is_boolean()) - { - JSON_THROW(type_error::create(302, "type must be boolean, but is " + j.type_name())); - } - b = *j.template get_ptr(); -} - -template -void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s) -{ - if (not j.is_string()) - { - JSON_THROW(type_error::create(302, "type must be string, but is " + j.type_name())); - } - s = *j.template get_ptr(); -} - -template -void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val) -{ - get_arithmetic_value(j, val); -} - -template -void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val) -{ - get_arithmetic_value(j, val); -} - -template -void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val) -{ - get_arithmetic_value(j, val); -} - -template::value, int> = 0> -void from_json(const BasicJsonType& j, EnumType& e) -{ - typename std::underlying_type::type val; - get_arithmetic_value(j, val); - e = static_cast(val); -} - -template -void from_json(const BasicJsonType& j, typename BasicJsonType::array_t& arr) -{ - if (not j.is_array()) - { - JSON_THROW(type_error::create(302, "type must be array, but is " + j.type_name())); - } - arr = *j.template get_ptr(); -} - -// forward_list doesn't have an insert method -template::value, int> = 0> -void from_json(const BasicJsonType& j, std::forward_list& l) -{ - if (not j.is_array()) - { - JSON_THROW(type_error::create(302, "type must be array, but is " + j.type_name())); - } - - for (auto it = j.rbegin(), end = j.rend(); it != end; ++it) - { - l.push_front(it->template get()); - } -} - -template -void from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, priority_tag<0>) -{ - using std::begin; - using std::end; - - std::transform(j.begin(), j.end(), - std::inserter(arr, end(arr)), [](const BasicJsonType & i) - { - // get() returns *this, this won't call a from_json - // method when value_type is BasicJsonType - return i.template get(); - }); -} - -template -auto from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, priority_tag<1>) --> decltype( - arr.reserve(std::declval()), - void()) -{ - using std::begin; - using std::end; - - arr.reserve(j.size()); - std::transform(j.begin(), j.end(), - std::inserter(arr, end(arr)), [](const BasicJsonType & i) - { - // get() returns *this, this won't call a from_json - // method when value_type is BasicJsonType - return i.template get(); - }); -} - -template::value and - std::is_convertible::value and - not std::is_same::value, int> = 0> -void from_json(const BasicJsonType& j, CompatibleArrayType& arr) -{ - if (not j.is_array()) - { - JSON_THROW(type_error::create(302, "type must be array, but is " + j.type_name())); - } - - from_json_array_impl(j, arr, priority_tag<1> {}); -} - -template::value, int> = 0> -void from_json(const BasicJsonType& j, CompatibleObjectType& obj) -{ - if (not j.is_object()) - { - JSON_THROW(type_error::create(302, "type must be object, but is " + j.type_name())); - } - - auto inner_object = j.template get_ptr(); - using std::begin; - using std::end; - // we could avoid the assignment, but this might require a for loop, which - // might be less efficient than the container constructor for some - // containers (would it?) - obj = CompatibleObjectType(begin(*inner_object), end(*inner_object)); -} - -// overload for arithmetic types, not chosen for basic_json template arguments -// (BooleanType, etc..); note: Is it really necessary to provide explicit -// overloads for boolean_t etc. in case of a custom BooleanType which is not -// an arithmetic type? -template::value and - not std::is_same::value and - not std::is_same::value and - not std::is_same::value and - not std::is_same::value, - int> = 0> -void from_json(const BasicJsonType& j, ArithmeticType& val) -{ - switch (static_cast(j)) - { - case value_t::number_unsigned: - { - val = static_cast(*j.template get_ptr()); - break; - } - case value_t::number_integer: - { - val = static_cast(*j.template get_ptr()); - break; - } - case value_t::number_float: - { - val = static_cast(*j.template get_ptr()); - break; - } - case value_t::boolean: - { - val = static_cast(*j.template get_ptr()); - break; - } - default: - { - JSON_THROW(type_error::create(302, "type must be number, but is " + j.type_name())); - } - } -} - -struct to_json_fn -{ - private: - template - auto call(BasicJsonType& j, T&& val, priority_tag<1>) const noexcept(noexcept(to_json(j, std::forward(val)))) - -> decltype(to_json(j, std::forward(val)), void()) - { - return to_json(j, std::forward(val)); - } - - template - void call(BasicJsonType&, T&&, priority_tag<0>) const noexcept - { - static_assert(sizeof(BasicJsonType) == 0, - "could not find to_json() method in T's namespace"); - } - - public: - template - void operator()(BasicJsonType& j, T&& val) const - noexcept(noexcept(std::declval().call(j, std::forward(val), priority_tag<1> {}))) - { - return call(j, std::forward(val), priority_tag<1> {}); - } -}; - -struct from_json_fn -{ - private: - template - auto call(const BasicJsonType& j, T& val, priority_tag<1>) const - noexcept(noexcept(from_json(j, val))) - -> decltype(from_json(j, val), void()) - { - return from_json(j, val); - } - - template - void call(const BasicJsonType&, T&, priority_tag<0>) const noexcept - { - static_assert(sizeof(BasicJsonType) == 0, - "could not find from_json() method in T's namespace"); - } - - public: - template - void operator()(const BasicJsonType& j, T& val) const - noexcept(noexcept(std::declval().call(j, val, priority_tag<1> {}))) - { - return call(j, val, priority_tag<1> {}); - } -}; - -// taken from ranges-v3 -template -struct static_const -{ - static constexpr T value{}; -}; - -template -constexpr T static_const::value; -} // namespace detail - - -/// namespace to hold default `to_json` / `from_json` functions -namespace -{ -constexpr const auto& to_json = detail::static_const::value; -constexpr const auto& from_json = detail::static_const::value; -} - - -/*! -@brief default JSONSerializer template argument - -This serializer ignores the template arguments and uses ADL -([argument-dependent lookup](http://en.cppreference.com/w/cpp/language/adl)) -for serialization. -*/ -template -struct adl_serializer -{ - /*! - @brief convert a JSON value to any value type - - This function is usually called by the `get()` function of the - @ref basic_json class (either explicit or via conversion operators). - - @param[in] j JSON value to read from - @param[in,out] val value to write to - */ - template - static void from_json(BasicJsonType&& j, ValueType& val) noexcept( - noexcept(::nlohmann::from_json(std::forward(j), val))) - { - ::nlohmann::from_json(std::forward(j), val); - } - - /*! - @brief convert any value type to a JSON value - - This function is usually called by the constructors of the @ref basic_json - class. - - @param[in,out] j JSON value to write to - @param[in] val value to read from - */ - template - static void to_json(BasicJsonType& j, ValueType&& val) noexcept( - noexcept(::nlohmann::to_json(j, std::forward(val)))) - { - ::nlohmann::to_json(j, std::forward(val)); - } -}; - - -/*! -@brief a class to store JSON values - -@tparam ObjectType type for JSON objects (`std::map` by default; will be used -in @ref object_t) -@tparam ArrayType type for JSON arrays (`std::vector` by default; will be used -in @ref array_t) -@tparam StringType type for JSON strings and object keys (`std::string` by -default; will be used in @ref string_t) -@tparam BooleanType type for JSON booleans (`bool` by default; will be used -in @ref boolean_t) -@tparam NumberIntegerType type for JSON integer numbers (`int64_t` by -default; will be used in @ref number_integer_t) -@tparam NumberUnsignedType type for JSON unsigned integer numbers (@c -`uint64_t` by default; will be used in @ref number_unsigned_t) -@tparam NumberFloatType type for JSON floating-point numbers (`double` by -default; will be used in @ref number_float_t) -@tparam AllocatorType type of the allocator to use (`std::allocator` by -default) -@tparam JSONSerializer the serializer to resolve internal calls to `to_json()` -and `from_json()` (@ref adl_serializer by default) - -@requirement The class satisfies the following concept requirements: -- Basic - - [DefaultConstructible](http://en.cppreference.com/w/cpp/concept/DefaultConstructible): - JSON values can be default constructed. The result will be a JSON null - value. - - [MoveConstructible](http://en.cppreference.com/w/cpp/concept/MoveConstructible): - A JSON value can be constructed from an rvalue argument. - - [CopyConstructible](http://en.cppreference.com/w/cpp/concept/CopyConstructible): - A JSON value can be copy-constructed from an lvalue expression. - - [MoveAssignable](http://en.cppreference.com/w/cpp/concept/MoveAssignable): - A JSON value van be assigned from an rvalue argument. - - [CopyAssignable](http://en.cppreference.com/w/cpp/concept/CopyAssignable): - A JSON value can be copy-assigned from an lvalue expression. - - [Destructible](http://en.cppreference.com/w/cpp/concept/Destructible): - JSON values can be destructed. -- Layout - - [StandardLayoutType](http://en.cppreference.com/w/cpp/concept/StandardLayoutType): - JSON values have - [standard layout](http://en.cppreference.com/w/cpp/language/data_members#Standard_layout): - All non-static data members are private and standard layout types, the - class has no virtual functions or (virtual) base classes. -- Library-wide - - [EqualityComparable](http://en.cppreference.com/w/cpp/concept/EqualityComparable): - JSON values can be compared with `==`, see @ref - operator==(const_reference,const_reference). - - [LessThanComparable](http://en.cppreference.com/w/cpp/concept/LessThanComparable): - JSON values can be compared with `<`, see @ref - operator<(const_reference,const_reference). - - [Swappable](http://en.cppreference.com/w/cpp/concept/Swappable): - Any JSON lvalue or rvalue of can be swapped with any lvalue or rvalue of - other compatible types, using unqualified function call @ref swap(). - - [NullablePointer](http://en.cppreference.com/w/cpp/concept/NullablePointer): - JSON values can be compared against `std::nullptr_t` objects which are used - to model the `null` value. -- Container - - [Container](http://en.cppreference.com/w/cpp/concept/Container): - JSON values can be used like STL containers and provide iterator access. - - [ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer); - JSON values can be used like STL containers and provide reverse iterator - access. - -@invariant The member variables @a m_value and @a m_type have the following -relationship: -- If `m_type == value_t::object`, then `m_value.object != nullptr`. -- If `m_type == value_t::array`, then `m_value.array != nullptr`. -- If `m_type == value_t::string`, then `m_value.string != nullptr`. -The invariants are checked by member function assert_invariant(). - -@internal -@note ObjectType trick from http://stackoverflow.com/a/9860911 -@endinternal - -@see [RFC 7159: The JavaScript Object Notation (JSON) Data Interchange -Format](http://rfc7159.net/rfc7159) - -@since version 1.0.0 - -@nosubgrouping -*/ -template < - template class ObjectType = std::map, - template class ArrayType = std::vector, - class StringType = std::string, - class BooleanType = bool, - class NumberIntegerType = std::int64_t, - class NumberUnsignedType = std::uint64_t, - class NumberFloatType = double, - template class AllocatorType = std::allocator, - template class JSONSerializer = adl_serializer - > -class basic_json -{ - private: - template friend struct detail::external_constructor; - /// workaround type for MSVC - using basic_json_t = basic_json; - - public: - using value_t = detail::value_t; - // forward declarations - template class iter_impl; - template class json_reverse_iterator; - class json_pointer; - template - using json_serializer = JSONSerializer; - - - //////////////// - // exceptions // - //////////////// - - /// @name exceptions - /// Classes to implement user-defined exceptions. - /// @{ - - /// @copydoc detail::exception - using exception = detail::exception; - /// @copydoc detail::parse_error - using parse_error = detail::parse_error; - /// @copydoc detail::invalid_iterator - using invalid_iterator = detail::invalid_iterator; - /// @copydoc detail::type_error - using type_error = detail::type_error; - /// @copydoc detail::out_of_range - using out_of_range = detail::out_of_range; - /// @copydoc detail::other_error - using other_error = detail::other_error; - - /// @} - - - ///////////////////// - // container types // - ///////////////////// - - /// @name container types - /// The canonic container types to use @ref basic_json like any other STL - /// container. - /// @{ - - /// the type of elements in a basic_json container - using value_type = basic_json; - - /// the type of an element reference - using reference = value_type&; - /// the type of an element const reference - using const_reference = const value_type&; - - /// a type to represent differences between iterators - using difference_type = std::ptrdiff_t; - /// a type to represent container sizes - using size_type = std::size_t; - - /// the allocator type - using allocator_type = AllocatorType; - - /// the type of an element pointer - using pointer = typename std::allocator_traits::pointer; - /// the type of an element const pointer - using const_pointer = typename std::allocator_traits::const_pointer; - - /// an iterator for a basic_json container - using iterator = iter_impl; - /// a const iterator for a basic_json container - using const_iterator = iter_impl; - /// a reverse iterator for a basic_json container - using reverse_iterator = json_reverse_iterator; - /// a const reverse iterator for a basic_json container - using const_reverse_iterator = json_reverse_iterator; - - /// @} - - - /*! - @brief returns the allocator associated with the container - */ - static allocator_type get_allocator() - { - return allocator_type(); - } - - /*! - @brief returns version information on the library - - This function returns a JSON object with information about the library, - including the version number and information on the platform and compiler. - - @return JSON object holding version information - key | description - ----------- | --------------- - `compiler` | Information on the used compiler. It is an object with the following keys: `c++` (the used C++ standard), `family` (the compiler family; possible values are `clang`, `icc`, `gcc`, `ilecpp`, `msvc`, `pgcpp`, `sunpro`, and `unknown`), and `version` (the compiler version). - `copyright` | The copyright line for the library as string. - `name` | The name of the library as string. - `platform` | The used platform as string. Possible values are `win32`, `linux`, `apple`, `unix`, and `unknown`. - `url` | The URL of the project as string. - `version` | The version of the library. It is an object with the following keys: `major`, `minor`, and `patch` as defined by [Semantic Versioning](http://semver.org), and `string` (the version string). - - @liveexample{The following code shows an example output of the `meta()` - function.,meta} - - @complexity Constant. - - @since 2.1.0 - */ - static basic_json meta() - { - basic_json result; - - result["copyright"] = "(C) 2013-2017 Niels Lohmann"; - result["name"] = "JSON for Modern C++"; - result["url"] = "https://github.com/nlohmann/json"; - result["version"] = - { - {"string", "2.1.1"}, {"major", 2}, {"minor", 1}, {"patch", 1} - }; - -#ifdef _WIN32 - result["platform"] = "win32"; -#elif defined __linux__ - result["platform"] = "linux"; -#elif defined __APPLE__ - result["platform"] = "apple"; -#elif defined __unix__ - result["platform"] = "unix"; -#else - result["platform"] = "unknown"; -#endif - -#if defined(__clang__) - result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}}; -#elif defined(__ICC) || defined(__INTEL_COMPILER) - result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}}; -#elif defined(__GNUC__) || defined(__GNUG__) - result["compiler"] = {{"family", "gcc"}, {"version", std::to_string(__GNUC__) + "." + std::to_string(__GNUC_MINOR__) + "." + std::to_string(__GNUC_PATCHLEVEL__)}}; -#elif defined(__HP_cc) || defined(__HP_aCC) - result["compiler"] = "hp" -#elif defined(__IBMCPP__) - result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}}; -#elif defined(_MSC_VER) - result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}}; -#elif defined(__PGI) - result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}}; -#elif defined(__SUNPRO_CC) - result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}}; -#else - result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}}; -#endif - -#ifdef __cplusplus - result["compiler"]["c++"] = std::to_string(__cplusplus); -#else - result["compiler"]["c++"] = "unknown"; -#endif - return result; - } - - - /////////////////////////// - // JSON value data types // - /////////////////////////// - - /// @name JSON value data types - /// The data types to store a JSON value. These types are derived from - /// the template arguments passed to class @ref basic_json. - /// @{ - - /*! - @brief a type for an object - - [RFC 7159](http://rfc7159.net/rfc7159) describes JSON objects as follows: - > An object is an unordered collection of zero or more name/value pairs, - > where a name is a string and a value is a string, number, boolean, null, - > object, or array. - - To store objects in C++, a type is defined by the template parameters - described below. - - @tparam ObjectType the container to store objects (e.g., `std::map` or - `std::unordered_map`) - @tparam StringType the type of the keys or names (e.g., `std::string`). - The comparison function `std::less` is used to order elements - inside the container. - @tparam AllocatorType the allocator to use for objects (e.g., - `std::allocator`) - - #### Default type - - With the default values for @a ObjectType (`std::map`), @a StringType - (`std::string`), and @a AllocatorType (`std::allocator`), the default - value for @a object_t is: - - @code {.cpp} - std::map< - std::string, // key_type - basic_json, // value_type - std::less, // key_compare - std::allocator> // allocator_type - > - @endcode - - #### Behavior - - The choice of @a object_t influences the behavior of the JSON class. With - the default type, objects have the following behavior: - - - When all names are unique, objects will be interoperable in the sense - that all software implementations receiving that object will agree on - the name-value mappings. - - When the names within an object are not unique, later stored name/value - pairs overwrite previously stored name/value pairs, leaving the used - names unique. For instance, `{"key": 1}` and `{"key": 2, "key": 1}` will - be treated as equal and both stored as `{"key": 1}`. - - Internally, name/value pairs are stored in lexicographical order of the - names. Objects will also be serialized (see @ref dump) in this order. - For instance, `{"b": 1, "a": 2}` and `{"a": 2, "b": 1}` will be stored - and serialized as `{"a": 2, "b": 1}`. - - When comparing objects, the order of the name/value pairs is irrelevant. - This makes objects interoperable in the sense that they will not be - affected by these differences. For instance, `{"b": 1, "a": 2}` and - `{"a": 2, "b": 1}` will be treated as equal. - - #### Limits - - [RFC 7159](http://rfc7159.net/rfc7159) specifies: - > An implementation may set limits on the maximum depth of nesting. - - In this class, the object's limit of nesting is not constraint explicitly. - However, a maximum depth of nesting may be introduced by the compiler or - runtime environment. A theoretical limit can be queried by calling the - @ref max_size function of a JSON object. - - #### Storage - - Objects are stored as pointers in a @ref basic_json type. That is, for any - access to object values, a pointer of type `object_t*` must be - dereferenced. - - @sa @ref array_t -- type for an array value - - @since version 1.0.0 - - @note The order name/value pairs are added to the object is *not* - preserved by the library. Therefore, iterating an object may return - name/value pairs in a different order than they were originally stored. In - fact, keys will be traversed in alphabetical order as `std::map` with - `std::less` is used by default. Please note this behavior conforms to [RFC - 7159](http://rfc7159.net/rfc7159), because any order implements the - specified "unordered" nature of JSON objects. - */ - using object_t = ObjectType, - AllocatorType>>; - - /*! - @brief a type for an array - - [RFC 7159](http://rfc7159.net/rfc7159) describes JSON arrays as follows: - > An array is an ordered sequence of zero or more values. - - To store objects in C++, a type is defined by the template parameters - explained below. - - @tparam ArrayType container type to store arrays (e.g., `std::vector` or - `std::list`) - @tparam AllocatorType allocator to use for arrays (e.g., `std::allocator`) - - #### Default type - - With the default values for @a ArrayType (`std::vector`) and @a - AllocatorType (`std::allocator`), the default value for @a array_t is: - - @code {.cpp} - std::vector< - basic_json, // value_type - std::allocator // allocator_type - > - @endcode - - #### Limits - - [RFC 7159](http://rfc7159.net/rfc7159) specifies: - > An implementation may set limits on the maximum depth of nesting. - - In this class, the array's limit of nesting is not constraint explicitly. - However, a maximum depth of nesting may be introduced by the compiler or - runtime environment. A theoretical limit can be queried by calling the - @ref max_size function of a JSON array. - - #### Storage - - Arrays are stored as pointers in a @ref basic_json type. That is, for any - access to array values, a pointer of type `array_t*` must be dereferenced. - - @sa @ref object_t -- type for an object value - - @since version 1.0.0 - */ - using array_t = ArrayType>; - - /*! - @brief a type for a string - - [RFC 7159](http://rfc7159.net/rfc7159) describes JSON strings as follows: - > A string is a sequence of zero or more Unicode characters. - - To store objects in C++, a type is defined by the template parameter - described below. Unicode values are split by the JSON class into - byte-sized characters during deserialization. - - @tparam StringType the container to store strings (e.g., `std::string`). - Note this container is used for keys/names in objects, see @ref object_t. - - #### Default type - - With the default values for @a StringType (`std::string`), the default - value for @a string_t is: - - @code {.cpp} - std::string - @endcode - - #### Encoding - - Strings are stored in UTF-8 encoding. Therefore, functions like - `std::string::size()` or `std::string::length()` return the number of - bytes in the string rather than the number of characters or glyphs. - - #### String comparison - - [RFC 7159](http://rfc7159.net/rfc7159) states: - > Software implementations are typically required to test names of object - > members for equality. Implementations that transform the textual - > representation into sequences of Unicode code units and then perform the - > comparison numerically, code unit by code unit, are interoperable in the - > sense that implementations will agree in all cases on equality or - > inequality of two strings. For example, implementations that compare - > strings with escaped characters unconverted may incorrectly find that - > `"a\\b"` and `"a\u005Cb"` are not equal. - - This implementation is interoperable as it does compare strings code unit - by code unit. - - #### Storage - - String values are stored as pointers in a @ref basic_json type. That is, - for any access to string values, a pointer of type `string_t*` must be - dereferenced. - - @since version 1.0.0 - */ - using string_t = StringType; - - /*! - @brief a type for a boolean - - [RFC 7159](http://rfc7159.net/rfc7159) implicitly describes a boolean as a - type which differentiates the two literals `true` and `false`. - - To store objects in C++, a type is defined by the template parameter @a - BooleanType which chooses the type to use. - - #### Default type - - With the default values for @a BooleanType (`bool`), the default value for - @a boolean_t is: - - @code {.cpp} - bool - @endcode - - #### Storage - - Boolean values are stored directly inside a @ref basic_json type. - - @since version 1.0.0 - */ - using boolean_t = BooleanType; - - /*! - @brief a type for a number (integer) - - [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows: - > The representation of numbers is similar to that used in most - > programming languages. A number is represented in base 10 using decimal - > digits. It contains an integer component that may be prefixed with an - > optional minus sign, which may be followed by a fraction part and/or an - > exponent part. Leading zeros are not allowed. (...) Numeric values that - > cannot be represented in the grammar below (such as Infinity and NaN) - > are not permitted. - - This description includes both integer and floating-point numbers. - However, C++ allows more precise storage if it is known whether the number - is a signed integer, an unsigned integer or a floating-point number. - Therefore, three different types, @ref number_integer_t, @ref - number_unsigned_t and @ref number_float_t are used. - - To store integer numbers in C++, a type is defined by the template - parameter @a NumberIntegerType which chooses the type to use. - - #### Default type - - With the default values for @a NumberIntegerType (`int64_t`), the default - value for @a number_integer_t is: - - @code {.cpp} - int64_t - @endcode - - #### Default behavior - - - The restrictions about leading zeros is not enforced in C++. Instead, - leading zeros in integer literals lead to an interpretation as octal - number. Internally, the value will be stored as decimal number. For - instance, the C++ integer literal `010` will be serialized to `8`. - During deserialization, leading zeros yield an error. - - Not-a-number (NaN) values will be serialized to `null`. - - #### Limits - - [RFC 7159](http://rfc7159.net/rfc7159) specifies: - > An implementation may set limits on the range and precision of numbers. - - When the default type is used, the maximal integer number that can be - stored is `9223372036854775807` (INT64_MAX) and the minimal integer number - that can be stored is `-9223372036854775808` (INT64_MIN). Integer numbers - that are out of range will yield over/underflow when used in a - constructor. During deserialization, too large or small integer numbers - will be automatically be stored as @ref number_unsigned_t or @ref - number_float_t. - - [RFC 7159](http://rfc7159.net/rfc7159) further states: - > Note that when such software is used, numbers that are integers and are - > in the range \f$[-2^{53}+1, 2^{53}-1]\f$ are interoperable in the sense - > that implementations will agree exactly on their numeric values. - - As this range is a subrange of the exactly supported range [INT64_MIN, - INT64_MAX], this class's integer type is interoperable. - - #### Storage - - Integer number values are stored directly inside a @ref basic_json type. - - @sa @ref number_float_t -- type for number values (floating-point) - - @sa @ref number_unsigned_t -- type for number values (unsigned integer) - - @since version 1.0.0 - */ - using number_integer_t = NumberIntegerType; - - /*! - @brief a type for a number (unsigned) - - [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows: - > The representation of numbers is similar to that used in most - > programming languages. A number is represented in base 10 using decimal - > digits. It contains an integer component that may be prefixed with an - > optional minus sign, which may be followed by a fraction part and/or an - > exponent part. Leading zeros are not allowed. (...) Numeric values that - > cannot be represented in the grammar below (such as Infinity and NaN) - > are not permitted. - - This description includes both integer and floating-point numbers. - However, C++ allows more precise storage if it is known whether the number - is a signed integer, an unsigned integer or a floating-point number. - Therefore, three different types, @ref number_integer_t, @ref - number_unsigned_t and @ref number_float_t are used. - - To store unsigned integer numbers in C++, a type is defined by the - template parameter @a NumberUnsignedType which chooses the type to use. - - #### Default type - - With the default values for @a NumberUnsignedType (`uint64_t`), the - default value for @a number_unsigned_t is: - - @code {.cpp} - uint64_t - @endcode - - #### Default behavior - - - The restrictions about leading zeros is not enforced in C++. Instead, - leading zeros in integer literals lead to an interpretation as octal - number. Internally, the value will be stored as decimal number. For - instance, the C++ integer literal `010` will be serialized to `8`. - During deserialization, leading zeros yield an error. - - Not-a-number (NaN) values will be serialized to `null`. - - #### Limits - - [RFC 7159](http://rfc7159.net/rfc7159) specifies: - > An implementation may set limits on the range and precision of numbers. - - When the default type is used, the maximal integer number that can be - stored is `18446744073709551615` (UINT64_MAX) and the minimal integer - number that can be stored is `0`. Integer numbers that are out of range - will yield over/underflow when used in a constructor. During - deserialization, too large or small integer numbers will be automatically - be stored as @ref number_integer_t or @ref number_float_t. - - [RFC 7159](http://rfc7159.net/rfc7159) further states: - > Note that when such software is used, numbers that are integers and are - > in the range \f$[-2^{53}+1, 2^{53}-1]\f$ are interoperable in the sense - > that implementations will agree exactly on their numeric values. - - As this range is a subrange (when considered in conjunction with the - number_integer_t type) of the exactly supported range [0, UINT64_MAX], - this class's integer type is interoperable. - - #### Storage - - Integer number values are stored directly inside a @ref basic_json type. - - @sa @ref number_float_t -- type for number values (floating-point) - @sa @ref number_integer_t -- type for number values (integer) - - @since version 2.0.0 - */ - using number_unsigned_t = NumberUnsignedType; - - /*! - @brief a type for a number (floating-point) - - [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows: - > The representation of numbers is similar to that used in most - > programming languages. A number is represented in base 10 using decimal - > digits. It contains an integer component that may be prefixed with an - > optional minus sign, which may be followed by a fraction part and/or an - > exponent part. Leading zeros are not allowed. (...) Numeric values that - > cannot be represented in the grammar below (such as Infinity and NaN) - > are not permitted. - - This description includes both integer and floating-point numbers. - However, C++ allows more precise storage if it is known whether the number - is a signed integer, an unsigned integer or a floating-point number. - Therefore, three different types, @ref number_integer_t, @ref - number_unsigned_t and @ref number_float_t are used. - - To store floating-point numbers in C++, a type is defined by the template - parameter @a NumberFloatType which chooses the type to use. - - #### Default type - - With the default values for @a NumberFloatType (`double`), the default - value for @a number_float_t is: - - @code {.cpp} - double - @endcode - - #### Default behavior - - - The restrictions about leading zeros is not enforced in C++. Instead, - leading zeros in floating-point literals will be ignored. Internally, - the value will be stored as decimal number. For instance, the C++ - floating-point literal `01.2` will be serialized to `1.2`. During - deserialization, leading zeros yield an error. - - Not-a-number (NaN) values will be serialized to `null`. - - #### Limits - - [RFC 7159](http://rfc7159.net/rfc7159) states: - > This specification allows implementations to set limits on the range and - > precision of numbers accepted. Since software that implements IEEE - > 754-2008 binary64 (double precision) numbers is generally available and - > widely used, good interoperability can be achieved by implementations - > that expect no more precision or range than these provide, in the sense - > that implementations will approximate JSON numbers within the expected - > precision. - - This implementation does exactly follow this approach, as it uses double - precision floating-point numbers. Note values smaller than - `-1.79769313486232e+308` and values greater than `1.79769313486232e+308` - will be stored as NaN internally and be serialized to `null`. - - #### Storage - - Floating-point number values are stored directly inside a @ref basic_json - type. - - @sa @ref number_integer_t -- type for number values (integer) - - @sa @ref number_unsigned_t -- type for number values (unsigned integer) - - @since version 1.0.0 - */ - using number_float_t = NumberFloatType; - - /// @} - - private: - - /// helper for exception-safe object creation - template - static T* create(Args&& ... args) - { - AllocatorType alloc; - auto deleter = [&](T * object) - { - alloc.deallocate(object, 1); - }; - std::unique_ptr object(alloc.allocate(1), deleter); - alloc.construct(object.get(), std::forward(args)...); - assert(object != nullptr); - return object.release(); - } - - //////////////////////// - // JSON value storage // - //////////////////////// - - /*! - @brief a JSON value - - The actual storage for a JSON value of the @ref basic_json class. This - union combines the different storage types for the JSON value types - defined in @ref value_t. - - JSON type | value_t type | used type - --------- | --------------- | ------------------------ - object | object | pointer to @ref object_t - array | array | pointer to @ref array_t - string | string | pointer to @ref string_t - boolean | boolean | @ref boolean_t - number | number_integer | @ref number_integer_t - number | number_unsigned | @ref number_unsigned_t - number | number_float | @ref number_float_t - null | null | *no value is stored* - - @note Variable-length types (objects, arrays, and strings) are stored as - pointers. The size of the union should not exceed 64 bits if the default - value types are used. - - @since version 1.0.0 - */ - union json_value - { - /// object (stored with pointer to save storage) - object_t* object; - /// array (stored with pointer to save storage) - array_t* array; - /// string (stored with pointer to save storage) - string_t* string; - /// boolean - boolean_t boolean; - /// number (integer) - number_integer_t number_integer; - /// number (unsigned integer) - number_unsigned_t number_unsigned; - /// number (floating-point) - number_float_t number_float; - - /// default constructor (for null values) - json_value() = default; - /// constructor for booleans - json_value(boolean_t v) noexcept : boolean(v) {} - /// constructor for numbers (integer) - json_value(number_integer_t v) noexcept : number_integer(v) {} - /// constructor for numbers (unsigned) - json_value(number_unsigned_t v) noexcept : number_unsigned(v) {} - /// constructor for numbers (floating-point) - json_value(number_float_t v) noexcept : number_float(v) {} - /// constructor for empty values of a given type - json_value(value_t t) - { - switch (t) - { - case value_t::object: - { - object = create(); - break; - } - - case value_t::array: - { - array = create(); - break; - } - - case value_t::string: - { - string = create(""); - break; - } - - case value_t::boolean: - { - boolean = boolean_t(false); - break; - } - - case value_t::number_integer: - { - number_integer = number_integer_t(0); - break; - } - - case value_t::number_unsigned: - { - number_unsigned = number_unsigned_t(0); - break; - } - - case value_t::number_float: - { - number_float = number_float_t(0.0); - break; - } - - case value_t::null: - { - break; - } - - default: - { - if (t == value_t::null) - { - JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 2.1.1")); // LCOV_EXCL_LINE - } - break; - } - } - } - - /// constructor for strings - json_value(const string_t& value) - { - string = create(value); - } - - /// constructor for objects - json_value(const object_t& value) - { - object = create(value); - } - - /// constructor for arrays - json_value(const array_t& value) - { - array = create(value); - } - }; - - /*! - @brief checks the class invariants - - This function asserts the class invariants. It needs to be called at the - end of every constructor to make sure that created objects respect the - invariant. Furthermore, it has to be called each time the type of a JSON - value is changed, because the invariant expresses a relationship between - @a m_type and @a m_value. - */ - void assert_invariant() const - { - assert(m_type != value_t::object or m_value.object != nullptr); - assert(m_type != value_t::array or m_value.array != nullptr); - assert(m_type != value_t::string or m_value.string != nullptr); - } - - public: - ////////////////////////// - // JSON parser callback // - ////////////////////////// - - /*! - @brief JSON callback events - - This enumeration lists the parser events that can trigger calling a - callback function of type @ref parser_callback_t during parsing. - - @image html callback_events.png "Example when certain parse events are triggered" - - @since version 1.0.0 - */ - enum class parse_event_t : uint8_t - { - /// the parser read `{` and started to process a JSON object - object_start, - /// the parser read `}` and finished processing a JSON object - object_end, - /// the parser read `[` and started to process a JSON array - array_start, - /// the parser read `]` and finished processing a JSON array - array_end, - /// the parser read a key of a value in an object - key, - /// the parser finished reading a JSON value - value - }; - - /*! - @brief per-element parser callback type - - With a parser callback function, the result of parsing a JSON text can be - influenced. When passed to @ref parse(std::istream&, const - parser_callback_t) or @ref parse(const CharT, const parser_callback_t), - it is called on certain events (passed as @ref parse_event_t via parameter - @a event) with a set recursion depth @a depth and context JSON value - @a parsed. The return value of the callback function is a boolean - indicating whether the element that emitted the callback shall be kept or - not. - - We distinguish six scenarios (determined by the event type) in which the - callback function can be called. The following table describes the values - of the parameters @a depth, @a event, and @a parsed. - - parameter @a event | description | parameter @a depth | parameter @a parsed - ------------------ | ----------- | ------------------ | ------------------- - parse_event_t::object_start | the parser read `{` and started to process a JSON object | depth of the parent of the JSON object | a JSON value with type discarded - parse_event_t::key | the parser read a key of a value in an object | depth of the currently parsed JSON object | a JSON string containing the key - parse_event_t::object_end | the parser read `}` and finished processing a JSON object | depth of the parent of the JSON object | the parsed JSON object - parse_event_t::array_start | the parser read `[` and started to process a JSON array | depth of the parent of the JSON array | a JSON value with type discarded - parse_event_t::array_end | the parser read `]` and finished processing a JSON array | depth of the parent of the JSON array | the parsed JSON array - parse_event_t::value | the parser finished reading a JSON value | depth of the value | the parsed JSON value - - @image html callback_events.png "Example when certain parse events are triggered" - - Discarding a value (i.e., returning `false`) has different effects - depending on the context in which function was called: - - - Discarded values in structured types are skipped. That is, the parser - will behave as if the discarded value was never read. - - In case a value outside a structured type is skipped, it is replaced - with `null`. This case happens if the top-level element is skipped. - - @param[in] depth the depth of the recursion during parsing - - @param[in] event an event of type parse_event_t indicating the context in - the callback function has been called - - @param[in,out] parsed the current intermediate parse result; note that - writing to this value has no effect for parse_event_t::key events - - @return Whether the JSON value which called the function during parsing - should be kept (`true`) or not (`false`). In the latter case, it is either - skipped completely or replaced by an empty discarded object. - - @sa @ref parse(std::istream&, parser_callback_t) or - @ref parse(const CharT, const parser_callback_t) for examples - - @since version 1.0.0 - */ - using parser_callback_t = std::function; - - - ////////////////// - // constructors // - ////////////////// - - /// @name constructors and destructors - /// Constructors of class @ref basic_json, copy/move constructor, copy - /// assignment, static functions creating objects, and the destructor. - /// @{ - - /*! - @brief create an empty value with a given type - - Create an empty JSON value with a given type. The value will be default - initialized with an empty value which depends on the type: - - Value type | initial value - ----------- | ------------- - null | `null` - boolean | `false` - string | `""` - number | `0` - object | `{}` - array | `[]` - - @param[in] value_type the type of the value to create - - @complexity Constant. - - @liveexample{The following code shows the constructor for different @ref - value_t values,basic_json__value_t} - - @since version 1.0.0 - */ - basic_json(const value_t value_type) - : m_type(value_type), m_value(value_type) - { - assert_invariant(); - } - - /*! - @brief create a null object - - Create a `null` JSON value. It either takes a null pointer as parameter - (explicitly creating `null`) or no parameter (implicitly creating `null`). - The passed null pointer itself is not read -- it is only used to choose - the right constructor. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this constructor never throws - exceptions. - - @liveexample{The following code shows the constructor with and without a - null pointer parameter.,basic_json__nullptr_t} - - @since version 1.0.0 - */ - basic_json(std::nullptr_t = nullptr) noexcept - : basic_json(value_t::null) - { - assert_invariant(); - } - - /*! - @brief create a JSON value - - This is a "catch all" constructor for all compatible JSON types; that is, - types for which a `to_json()` method exsits. The constructor forwards the - parameter @a val to that method (to `json_serializer::to_json` method - with `U = uncvref_t`, to be exact). - - Template type @a CompatibleType includes, but is not limited to, the - following types: - - **arrays**: @ref array_t and all kinds of compatible containers such as - `std::vector`, `std::deque`, `std::list`, `std::forward_list`, - `std::array`, `std::set`, `std::unordered_set`, `std::multiset`, and - `unordered_multiset` with a `value_type` from which a @ref basic_json - value can be constructed. - - **objects**: @ref object_t and all kinds of compatible associative - containers such as `std::map`, `std::unordered_map`, `std::multimap`, - and `std::unordered_multimap` with a `key_type` compatible to - @ref string_t and a `value_type` from which a @ref basic_json value can - be constructed. - - **strings**: @ref string_t, string literals, and all compatible string - containers can be used. - - **numbers**: @ref number_integer_t, @ref number_unsigned_t, - @ref number_float_t, and all convertible number types such as `int`, - `size_t`, `int64_t`, `float` or `double` can be used. - - **boolean**: @ref boolean_t / `bool` can be used. - - See the examples below. - - @tparam CompatibleType a type such that: - - @a CompatibleType is not derived from `std::istream`, - - @a CompatibleType is not @ref basic_json (to avoid hijacking copy/move - constructors), - - @a CompatibleType is not a @ref basic_json nested type (e.g., - @ref json_pointer, @ref iterator, etc ...) - - @ref @ref json_serializer has a - `to_json(basic_json_t&, CompatibleType&&)` method - - @tparam U = `uncvref_t` - - @param[in] val the value to be forwarded - - @complexity Usually linear in the size of the passed @a val, also - depending on the implementation of the called `to_json()` - method. - - @throw what `json_serializer::to_json()` throws - - @liveexample{The following code shows the constructor with several - compatible types.,basic_json__CompatibleType} - - @since version 2.1.0 - */ - template, - detail::enable_if_t::value and - not std::is_same::value and - not detail::is_basic_json_nested_type< - basic_json_t, U>::value and - detail::has_to_json::value, - int> = 0> - basic_json(CompatibleType && val) noexcept(noexcept(JSONSerializer::to_json( - std::declval(), std::forward(val)))) - { - JSONSerializer::to_json(*this, std::forward(val)); - assert_invariant(); - } - - /*! - @brief create a container (array or object) from an initializer list - - Creates a JSON value of type array or object from the passed initializer - list @a init. In case @a type_deduction is `true` (default), the type of - the JSON value to be created is deducted from the initializer list @a init - according to the following rules: - - 1. If the list is empty, an empty JSON object value `{}` is created. - 2. If the list consists of pairs whose first element is a string, a JSON - object value is created where the first elements of the pairs are - treated as keys and the second elements are as values. - 3. In all other cases, an array is created. - - The rules aim to create the best fit between a C++ initializer list and - JSON values. The rationale is as follows: - - 1. The empty initializer list is written as `{}` which is exactly an empty - JSON object. - 2. C++ has now way of describing mapped types other than to list a list of - pairs. As JSON requires that keys must be of type string, rule 2 is the - weakest constraint one can pose on initializer lists to interpret them - as an object. - 3. In all other cases, the initializer list could not be interpreted as - JSON object type, so interpreting it as JSON array type is safe. - - With the rules described above, the following JSON values cannot be - expressed by an initializer list: - - - the empty array (`[]`): use @ref array(std::initializer_list) - with an empty initializer list in this case - - arrays whose elements satisfy rule 2: use @ref - array(std::initializer_list) with the same initializer list - in this case - - @note When used without parentheses around an empty initializer list, @ref - basic_json() is called instead of this function, yielding the JSON null - value. - - @param[in] init initializer list with JSON values - - @param[in] type_deduction internal parameter; when set to `true`, the type - of the JSON value is deducted from the initializer list @a init; when set - to `false`, the type provided via @a manual_type is forced. This mode is - used by the functions @ref array(std::initializer_list) and - @ref object(std::initializer_list). - - @param[in] manual_type internal parameter; when @a type_deduction is set - to `false`, the created JSON value will use the provided type (only @ref - value_t::array and @ref value_t::object are valid); when @a type_deduction - is set to `true`, this parameter has no effect - - @throw type_error.301 if @a type_deduction is `false`, @a manual_type is - `value_t::object`, but @a init contains an element which is not a pair - whose first element is a string. In this case, the constructor could not - create an object. If @a type_deduction would have be `true`, an array - would have been created. See @ref object(std::initializer_list) - for an example. - - @complexity Linear in the size of the initializer list @a init. - - @liveexample{The example below shows how JSON values are created from - initializer lists.,basic_json__list_init_t} - - @sa @ref array(std::initializer_list) -- create a JSON array - value from an initializer list - @sa @ref object(std::initializer_list) -- create a JSON object - value from an initializer list - - @since version 1.0.0 - */ - basic_json(std::initializer_list init, - bool type_deduction = true, - value_t manual_type = value_t::array) - { - // check if each element is an array with two elements whose first - // element is a string - bool is_an_object = std::all_of(init.begin(), init.end(), - [](const basic_json & element) - { - return element.is_array() and element.size() == 2 and element[0].is_string(); - }); - - // adjust type if type deduction is not wanted - if (not type_deduction) - { - // if array is wanted, do not create an object though possible - if (manual_type == value_t::array) - { - is_an_object = false; - } - - // if object is wanted but impossible, throw an exception - if (manual_type == value_t::object and not is_an_object) - { - JSON_THROW(type_error::create(301, "cannot create object from initializer list")); - } - } - - if (is_an_object) - { - // the initializer list is a list of pairs -> create object - m_type = value_t::object; - m_value = value_t::object; - - std::for_each(init.begin(), init.end(), [this](const basic_json & element) - { - m_value.object->emplace(*(element[0].m_value.string), element[1]); - }); - } - else - { - // the initializer list describes an array -> create array - m_type = value_t::array; - m_value.array = create(init); - } - - assert_invariant(); - } - - /*! - @brief explicitly create an array from an initializer list - - Creates a JSON array value from a given initializer list. That is, given a - list of values `a, b, c`, creates the JSON value `[a, b, c]`. If the - initializer list is empty, the empty array `[]` is created. - - @note This function is only needed to express two edge cases that cannot - be realized with the initializer list constructor (@ref - basic_json(std::initializer_list, bool, value_t)). These cases - are: - 1. creating an array whose elements are all pairs whose first element is a - string -- in this case, the initializer list constructor would create an - object, taking the first elements as keys - 2. creating an empty array -- passing the empty initializer list to the - initializer list constructor yields an empty object - - @param[in] init initializer list with JSON values to create an array from - (optional) - - @return JSON array value - - @complexity Linear in the size of @a init. - - @liveexample{The following code shows an example for the `array` - function.,array} - - @sa @ref basic_json(std::initializer_list, bool, value_t) -- - create a JSON value from an initializer list - @sa @ref object(std::initializer_list) -- create a JSON object - value from an initializer list - - @since version 1.0.0 - */ - static basic_json array(std::initializer_list init = - std::initializer_list()) - { - return basic_json(init, false, value_t::array); - } - - /*! - @brief explicitly create an object from an initializer list - - Creates a JSON object value from a given initializer list. The initializer - lists elements must be pairs, and their first elements must be strings. If - the initializer list is empty, the empty object `{}` is created. - - @note This function is only added for symmetry reasons. In contrast to the - related function @ref array(std::initializer_list), there are - no cases which can only be expressed by this function. That is, any - initializer list @a init can also be passed to the initializer list - constructor @ref basic_json(std::initializer_list, bool, value_t). - - @param[in] init initializer list to create an object from (optional) - - @return JSON object value - - @throw type_error.301 if @a init is not a list of pairs whose first - elements are strings. In this case, no object can be created. When such a - value is passed to @ref basic_json(std::initializer_list, bool, value_t), - an array would have been created from the passed initializer list @a init. - See example below. - - @complexity Linear in the size of @a init. - - @liveexample{The following code shows an example for the `object` - function.,object} - - @sa @ref basic_json(std::initializer_list, bool, value_t) -- - create a JSON value from an initializer list - @sa @ref array(std::initializer_list) -- create a JSON array - value from an initializer list - - @since version 1.0.0 - */ - static basic_json object(std::initializer_list init = - std::initializer_list()) - { - return basic_json(init, false, value_t::object); - } - - /*! - @brief construct an array with count copies of given value - - Constructs a JSON array value by creating @a cnt copies of a passed value. - In case @a cnt is `0`, an empty array is created. As postcondition, - `std::distance(begin(),end()) == cnt` holds. - - @param[in] cnt the number of JSON copies of @a val to create - @param[in] val the JSON value to copy - - @complexity Linear in @a cnt. - - @liveexample{The following code shows examples for the @ref - basic_json(size_type\, const basic_json&) - constructor.,basic_json__size_type_basic_json} - - @since version 1.0.0 - */ - basic_json(size_type cnt, const basic_json& val) - : m_type(value_t::array) - { - m_value.array = create(cnt, val); - assert_invariant(); - } - - /*! - @brief construct a JSON container given an iterator range - - Constructs the JSON value with the contents of the range `[first, last)`. - The semantics depends on the different types a JSON value can have: - - In case of primitive types (number, boolean, or string), @a first must - be `begin()` and @a last must be `end()`. In this case, the value is - copied. Otherwise, invalid_iterator.204 is thrown. - - In case of structured types (array, object), the constructor behaves as - similar versions for `std::vector`. - - In case of a null type, invalid_iterator.206 is thrown. - - @tparam InputIT an input iterator type (@ref iterator or @ref - const_iterator) - - @param[in] first begin of the range to copy from (included) - @param[in] last end of the range to copy from (excluded) - - @pre Iterators @a first and @a last must be initialized. **This - precondition is enforced with an assertion.** - - @pre Range `[first, last)` is valid. Usually, this precondition cannot be - checked efficiently. Only certain edge cases are detected; see the - description of the exceptions below. - - @throw invalid_iterator.201 if iterators @a first and @a last are not - compatible (i.e., do not belong to the same JSON value). In this case, - the range `[first, last)` is undefined. - @throw invalid_iterator.204 if iterators @a first and @a last belong to a - primitive type (number, boolean, or string), but @a first does not point - to the first element any more. In this case, the range `[first, last)` is - undefined. See example code below. - @throw invalid_iterator.206 if iterators @a first and @a last belong to a - null value. In this case, the range `[first, last)` is undefined. - - @complexity Linear in distance between @a first and @a last. - - @liveexample{The example below shows several ways to create JSON values by - specifying a subrange with iterators.,basic_json__InputIt_InputIt} - - @since version 1.0.0 - */ - template::value or - std::is_same::value, int>::type = 0> - basic_json(InputIT first, InputIT last) - { - assert(first.m_object != nullptr); - assert(last.m_object != nullptr); - - // make sure iterator fits the current value - if (first.m_object != last.m_object) - { - JSON_THROW(invalid_iterator::create(201, "iterators are not compatible")); - } - - // copy type from first iterator - m_type = first.m_object->m_type; - - // check if iterator range is complete for primitive values - switch (m_type) - { - case value_t::boolean: - case value_t::number_float: - case value_t::number_integer: - case value_t::number_unsigned: - case value_t::string: - { - if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end()) - { - JSON_THROW(invalid_iterator::create(204, "iterators out of range")); - } - break; - } - - default: - { - break; - } - } - - switch (m_type) - { - case value_t::number_integer: - { - m_value.number_integer = first.m_object->m_value.number_integer; - break; - } - - case value_t::number_unsigned: - { - m_value.number_unsigned = first.m_object->m_value.number_unsigned; - break; - } - - case value_t::number_float: - { - m_value.number_float = first.m_object->m_value.number_float; - break; - } - - case value_t::boolean: - { - m_value.boolean = first.m_object->m_value.boolean; - break; - } - - case value_t::string: - { - m_value = *first.m_object->m_value.string; - break; - } - - case value_t::object: - { - m_value.object = create(first.m_it.object_iterator, - last.m_it.object_iterator); - break; - } - - case value_t::array: - { - m_value.array = create(first.m_it.array_iterator, - last.m_it.array_iterator); - break; - } - - default: - { - JSON_THROW(invalid_iterator::create(206, "cannot construct with iterators from " + - first.m_object->type_name())); - } - } - - assert_invariant(); - } - - - /////////////////////////////////////// - // other constructors and destructor // - /////////////////////////////////////// - - /*! - @brief copy constructor - - Creates a copy of a given JSON value. - - @param[in] other the JSON value to copy - - @complexity Linear in the size of @a other. - - @requirement This function helps `basic_json` satisfying the - [Container](http://en.cppreference.com/w/cpp/concept/Container) - requirements: - - The complexity is linear. - - As postcondition, it holds: `other == basic_json(other)`. - - @liveexample{The following code shows an example for the copy - constructor.,basic_json__basic_json} - - @since version 1.0.0 - */ - basic_json(const basic_json& other) - : m_type(other.m_type) - { - // check of passed value is valid - other.assert_invariant(); - - switch (m_type) - { - case value_t::object: - { - m_value = *other.m_value.object; - break; - } - - case value_t::array: - { - m_value = *other.m_value.array; - break; - } - - case value_t::string: - { - m_value = *other.m_value.string; - break; - } - - case value_t::boolean: - { - m_value = other.m_value.boolean; - break; - } - - case value_t::number_integer: - { - m_value = other.m_value.number_integer; - break; - } - - case value_t::number_unsigned: - { - m_value = other.m_value.number_unsigned; - break; - } - - case value_t::number_float: - { - m_value = other.m_value.number_float; - break; - } - - default: - { - break; - } - } - - assert_invariant(); - } - - /*! - @brief move constructor - - Move constructor. Constructs a JSON value with the contents of the given - value @a other using move semantics. It "steals" the resources from @a - other and leaves it as JSON null value. - - @param[in,out] other value to move to this object - - @post @a other is a JSON null value - - @complexity Constant. - - @liveexample{The code below shows the move constructor explicitly called - via std::move.,basic_json__moveconstructor} - - @since version 1.0.0 - */ - basic_json(basic_json&& other) noexcept - : m_type(std::move(other.m_type)), - m_value(std::move(other.m_value)) - { - // check that passed value is valid - other.assert_invariant(); - - // invalidate payload - other.m_type = value_t::null; - other.m_value = {}; - - assert_invariant(); - } - - /*! - @brief copy assignment - - Copy assignment operator. Copies a JSON value via the "copy and swap" - strategy: It is expressed in terms of the copy constructor, destructor, - and the swap() member function. - - @param[in] other value to copy from - - @complexity Linear. - - @requirement This function helps `basic_json` satisfying the - [Container](http://en.cppreference.com/w/cpp/concept/Container) - requirements: - - The complexity is linear. - - @liveexample{The code below shows and example for the copy assignment. It - creates a copy of value `a` which is then swapped with `b`. Finally\, the - copy of `a` (which is the null value after the swap) is - destroyed.,basic_json__copyassignment} - - @since version 1.0.0 - */ - reference& operator=(basic_json other) noexcept ( - std::is_nothrow_move_constructible::value and - std::is_nothrow_move_assignable::value and - std::is_nothrow_move_constructible::value and - std::is_nothrow_move_assignable::value - ) - { - // check that passed value is valid - other.assert_invariant(); - - using std::swap; - swap(m_type, other.m_type); - swap(m_value, other.m_value); - - assert_invariant(); - return *this; - } - - /*! - @brief destructor - - Destroys the JSON value and frees all allocated memory. - - @complexity Linear. - - @requirement This function helps `basic_json` satisfying the - [Container](http://en.cppreference.com/w/cpp/concept/Container) - requirements: - - The complexity is linear. - - All stored elements are destroyed and all memory is freed. - - @since version 1.0.0 - */ - ~basic_json() - { - assert_invariant(); - - switch (m_type) - { - case value_t::object: - { - AllocatorType alloc; - alloc.destroy(m_value.object); - alloc.deallocate(m_value.object, 1); - break; - } - - case value_t::array: - { - AllocatorType alloc; - alloc.destroy(m_value.array); - alloc.deallocate(m_value.array, 1); - break; - } - - case value_t::string: - { - AllocatorType alloc; - alloc.destroy(m_value.string); - alloc.deallocate(m_value.string, 1); - break; - } - - default: - { - // all other types need no specific destructor - break; - } - } - } - - /// @} - - public: - /////////////////////// - // object inspection // - /////////////////////// - - /// @name object inspection - /// Functions to inspect the type of a JSON value. - /// @{ - - /*! - @brief serialization - - Serialization function for JSON values. The function tries to mimic - Python's `json.dumps()` function, and currently supports its @a indent - parameter. - - @param[in] indent If indent is nonnegative, then array elements and object - members will be pretty-printed with that indent level. An indent level of - `0` will only insert newlines. `-1` (the default) selects the most compact - representation. - - @return string containing the serialization of the JSON value - - @complexity Linear. - - @liveexample{The following example shows the effect of different @a indent - parameters to the result of the serialization.,dump} - - @see https://docs.python.org/2/library/json.html#json.dump - - @since version 1.0.0 - */ - string_t dump(const int indent = -1) const - { - std::stringstream ss; - serializer s(ss); - - if (indent >= 0) - { - s.dump(*this, true, static_cast(indent)); - } - else - { - s.dump(*this, false, 0); - } - - return ss.str(); - } - - /*! - @brief return the type of the JSON value (explicit) - - Return the type of the JSON value as a value from the @ref value_t - enumeration. - - @return the type of the JSON value - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `type()` for all JSON - types.,type} - - @since version 1.0.0 - */ - constexpr value_t type() const noexcept - { - return m_type; - } - - /*! - @brief return whether type is primitive - - This function returns true iff the JSON type is primitive (string, number, - boolean, or null). - - @return `true` if type is primitive (string, number, boolean, or null), - `false` otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_primitive()` for all JSON - types.,is_primitive} - - @sa @ref is_structured() -- returns whether JSON value is structured - @sa @ref is_null() -- returns whether JSON value is `null` - @sa @ref is_string() -- returns whether JSON value is a string - @sa @ref is_boolean() -- returns whether JSON value is a boolean - @sa @ref is_number() -- returns whether JSON value is a number - - @since version 1.0.0 - */ - constexpr bool is_primitive() const noexcept - { - return is_null() or is_string() or is_boolean() or is_number(); - } - - /*! - @brief return whether type is structured - - This function returns true iff the JSON type is structured (array or - object). - - @return `true` if type is structured (array or object), `false` otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_structured()` for all JSON - types.,is_structured} - - @sa @ref is_primitive() -- returns whether value is primitive - @sa @ref is_array() -- returns whether value is an array - @sa @ref is_object() -- returns whether value is an object - - @since version 1.0.0 - */ - constexpr bool is_structured() const noexcept - { - return is_array() or is_object(); - } - - /*! - @brief return whether value is null - - This function returns true iff the JSON value is null. - - @return `true` if type is null, `false` otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_null()` for all JSON - types.,is_null} - - @since version 1.0.0 - */ - constexpr bool is_null() const noexcept - { - return m_type == value_t::null; - } - - /*! - @brief return whether value is a boolean - - This function returns true iff the JSON value is a boolean. - - @return `true` if type is boolean, `false` otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_boolean()` for all JSON - types.,is_boolean} - - @since version 1.0.0 - */ - constexpr bool is_boolean() const noexcept - { - return m_type == value_t::boolean; - } - - /*! - @brief return whether value is a number - - This function returns true iff the JSON value is a number. This includes - both integer and floating-point values. - - @return `true` if type is number (regardless whether integer, unsigned - integer or floating-type), `false` otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_number()` for all JSON - types.,is_number} - - @sa @ref is_number_integer() -- check if value is an integer or unsigned - integer number - @sa @ref is_number_unsigned() -- check if value is an unsigned integer - number - @sa @ref is_number_float() -- check if value is a floating-point number - - @since version 1.0.0 - */ - constexpr bool is_number() const noexcept - { - return is_number_integer() or is_number_float(); - } - - /*! - @brief return whether value is an integer number - - This function returns true iff the JSON value is an integer or unsigned - integer number. This excludes floating-point values. - - @return `true` if type is an integer or unsigned integer number, `false` - otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_number_integer()` for all - JSON types.,is_number_integer} - - @sa @ref is_number() -- check if value is a number - @sa @ref is_number_unsigned() -- check if value is an unsigned integer - number - @sa @ref is_number_float() -- check if value is a floating-point number - - @since version 1.0.0 - */ - constexpr bool is_number_integer() const noexcept - { - return m_type == value_t::number_integer or m_type == value_t::number_unsigned; - } - - /*! - @brief return whether value is an unsigned integer number - - This function returns true iff the JSON value is an unsigned integer - number. This excludes floating-point and (signed) integer values. - - @return `true` if type is an unsigned integer number, `false` otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_number_unsigned()` for all - JSON types.,is_number_unsigned} - - @sa @ref is_number() -- check if value is a number - @sa @ref is_number_integer() -- check if value is an integer or unsigned - integer number - @sa @ref is_number_float() -- check if value is a floating-point number - - @since version 2.0.0 - */ - constexpr bool is_number_unsigned() const noexcept - { - return m_type == value_t::number_unsigned; - } - - /*! - @brief return whether value is a floating-point number - - This function returns true iff the JSON value is a floating-point number. - This excludes integer and unsigned integer values. - - @return `true` if type is a floating-point number, `false` otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_number_float()` for all - JSON types.,is_number_float} - - @sa @ref is_number() -- check if value is number - @sa @ref is_number_integer() -- check if value is an integer number - @sa @ref is_number_unsigned() -- check if value is an unsigned integer - number - - @since version 1.0.0 - */ - constexpr bool is_number_float() const noexcept - { - return m_type == value_t::number_float; - } - - /*! - @brief return whether value is an object - - This function returns true iff the JSON value is an object. - - @return `true` if type is object, `false` otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_object()` for all JSON - types.,is_object} - - @since version 1.0.0 - */ - constexpr bool is_object() const noexcept - { - return m_type == value_t::object; - } - - /*! - @brief return whether value is an array - - This function returns true iff the JSON value is an array. - - @return `true` if type is array, `false` otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_array()` for all JSON - types.,is_array} - - @since version 1.0.0 - */ - constexpr bool is_array() const noexcept - { - return m_type == value_t::array; - } - - /*! - @brief return whether value is a string - - This function returns true iff the JSON value is a string. - - @return `true` if type is string, `false` otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_string()` for all JSON - types.,is_string} - - @since version 1.0.0 - */ - constexpr bool is_string() const noexcept - { - return m_type == value_t::string; - } - - /*! - @brief return whether value is discarded - - This function returns true iff the JSON value was discarded during parsing - with a callback function (see @ref parser_callback_t). - - @note This function will always be `false` for JSON values after parsing. - That is, discarded values can only occur during parsing, but will be - removed when inside a structured value or replaced by null in other cases. - - @return `true` if type is discarded, `false` otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_discarded()` for all JSON - types.,is_discarded} - - @since version 1.0.0 - */ - constexpr bool is_discarded() const noexcept - { - return m_type == value_t::discarded; - } - - /*! - @brief return the type of the JSON value (implicit) - - Implicitly return the type of the JSON value as a value from the @ref - value_t enumeration. - - @return the type of the JSON value - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies the @ref value_t operator for - all JSON types.,operator__value_t} - - @since version 1.0.0 - */ - constexpr operator value_t() const noexcept - { - return m_type; - } - - /// @} - - private: - ////////////////// - // value access // - ////////////////// - - /// get a boolean (explicit) - boolean_t get_impl(boolean_t* /*unused*/) const - { - if (is_boolean()) - { - return m_value.boolean; - } - - JSON_THROW(type_error::create(302, "type must be boolean, but is " + type_name())); - } - - /// get a pointer to the value (object) - object_t* get_impl_ptr(object_t* /*unused*/) noexcept - { - return is_object() ? m_value.object : nullptr; - } - - /// get a pointer to the value (object) - constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept - { - return is_object() ? m_value.object : nullptr; - } - - /// get a pointer to the value (array) - array_t* get_impl_ptr(array_t* /*unused*/) noexcept - { - return is_array() ? m_value.array : nullptr; - } - - /// get a pointer to the value (array) - constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept - { - return is_array() ? m_value.array : nullptr; - } - - /// get a pointer to the value (string) - string_t* get_impl_ptr(string_t* /*unused*/) noexcept - { - return is_string() ? m_value.string : nullptr; - } - - /// get a pointer to the value (string) - constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept - { - return is_string() ? m_value.string : nullptr; - } - - /// get a pointer to the value (boolean) - boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept - { - return is_boolean() ? &m_value.boolean : nullptr; - } - - /// get a pointer to the value (boolean) - constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept - { - return is_boolean() ? &m_value.boolean : nullptr; - } - - /// get a pointer to the value (integer number) - number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept - { - return is_number_integer() ? &m_value.number_integer : nullptr; - } - - /// get a pointer to the value (integer number) - constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept - { - return is_number_integer() ? &m_value.number_integer : nullptr; - } - - /// get a pointer to the value (unsigned number) - number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept - { - return is_number_unsigned() ? &m_value.number_unsigned : nullptr; - } - - /// get a pointer to the value (unsigned number) - constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept - { - return is_number_unsigned() ? &m_value.number_unsigned : nullptr; - } - - /// get a pointer to the value (floating-point number) - number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept - { - return is_number_float() ? &m_value.number_float : nullptr; - } - - /// get a pointer to the value (floating-point number) - constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept - { - return is_number_float() ? &m_value.number_float : nullptr; - } - - /*! - @brief helper function to implement get_ref() - - This funcion helps to implement get_ref() without code duplication for - const and non-const overloads - - @tparam ThisType will be deduced as `basic_json` or `const basic_json` - - @throw type_error.303 if ReferenceType does not match underlying value - type of the current JSON - */ - template - static ReferenceType get_ref_impl(ThisType& obj) - { - // helper type - using PointerType = typename std::add_pointer::type; - - // delegate the call to get_ptr<>() - auto ptr = obj.template get_ptr(); - - if (ptr != nullptr) - { - return *ptr; - } - - JSON_THROW(type_error::create(303, "incompatible ReferenceType for get_ref, actual type is " + obj.type_name())); - } - - public: - /// @name value access - /// Direct access to the stored value of a JSON value. - /// @{ - - /*! - @brief get special-case overload - - This overloads avoids a lot of template boilerplate, it can be seen as the - identity method - - @tparam BasicJsonType == @ref basic_json - - @return a copy of *this - - @complexity Constant. - - @since version 2.1.0 - */ - template < - typename BasicJsonType, - detail::enable_if_t::type, - basic_json_t>::value, - int> = 0 > - basic_json get() const - { - return *this; - } - - /*! - @brief get a value (explicit) - - Explicit type conversion between the JSON value and a compatible value - which is [CopyConstructible](http://en.cppreference.com/w/cpp/concept/CopyConstructible) - and [DefaultConstructible](http://en.cppreference.com/w/cpp/concept/DefaultConstructible). - The value is converted by calling the @ref json_serializer - `from_json()` method. - - The function is equivalent to executing - @code {.cpp} - ValueType ret; - JSONSerializer::from_json(*this, ret); - return ret; - @endcode - - This overloads is chosen if: - - @a ValueType is not @ref basic_json, - - @ref json_serializer has a `from_json()` method of the form - `void from_json(const @ref basic_json&, ValueType&)`, and - - @ref json_serializer does not have a `from_json()` method of - the form `ValueType from_json(const @ref basic_json&)` - - @tparam ValueTypeCV the provided value type - @tparam ValueType the returned value type - - @return copy of the JSON value, converted to @a ValueType - - @throw what @ref json_serializer `from_json()` method throws - - @liveexample{The example below shows several conversions from JSON values - to other types. There a few things to note: (1) Floating-point numbers can - be converted to integers\, (2) A JSON array can be converted to a standard - `std::vector`\, (3) A JSON object can be converted to C++ - associative containers such as `std::unordered_map`.,get__ValueType_const} - - @since version 2.1.0 - */ - template < - typename ValueTypeCV, - typename ValueType = detail::uncvref_t, - detail::enable_if_t < - not std::is_same::value and - detail::has_from_json::value and - not detail::has_non_default_from_json::value, - int > = 0 > - ValueType get() const noexcept(noexcept( - JSONSerializer::from_json(std::declval(), std::declval()))) - { - // we cannot static_assert on ValueTypeCV being non-const, because - // there is support for get(), which is why we - // still need the uncvref - static_assert(not std::is_reference::value, - "get() cannot be used with reference types, you might want to use get_ref()"); - static_assert(std::is_default_constructible::value, - "types must be DefaultConstructible when used with get()"); - - ValueType ret; - JSONSerializer::from_json(*this, ret); - return ret; - } - - /*! - @brief get a value (explicit); special case - - Explicit type conversion between the JSON value and a compatible value - which is **not** [CopyConstructible](http://en.cppreference.com/w/cpp/concept/CopyConstructible) - and **not** [DefaultConstructible](http://en.cppreference.com/w/cpp/concept/DefaultConstructible). - The value is converted by calling the @ref json_serializer - `from_json()` method. - - The function is equivalent to executing - @code {.cpp} - return JSONSerializer::from_json(*this); - @endcode - - This overloads is chosen if: - - @a ValueType is not @ref basic_json and - - @ref json_serializer has a `from_json()` method of the form - `ValueType from_json(const @ref basic_json&)` - - @note If @ref json_serializer has both overloads of - `from_json()`, this one is chosen. - - @tparam ValueTypeCV the provided value type - @tparam ValueType the returned value type - - @return copy of the JSON value, converted to @a ValueType - - @throw what @ref json_serializer `from_json()` method throws - - @since version 2.1.0 - */ - template < - typename ValueTypeCV, - typename ValueType = detail::uncvref_t, - detail::enable_if_t::value and - detail::has_non_default_from_json::value, int> = 0 > - ValueType get() const noexcept(noexcept( - JSONSerializer::from_json(std::declval()))) - { - static_assert(not std::is_reference::value, - "get() cannot be used with reference types, you might want to use get_ref()"); - return JSONSerializer::from_json(*this); - } - - /*! - @brief get a pointer value (explicit) - - Explicit pointer access to the internally stored JSON value. No copies are - made. - - @warning The pointer becomes invalid if the underlying JSON object - changes. - - @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref - object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, - @ref number_unsigned_t, or @ref number_float_t. - - @return pointer to the internally stored JSON value if the requested - pointer type @a PointerType fits to the JSON value; `nullptr` otherwise - - @complexity Constant. - - @liveexample{The example below shows how pointers to internal values of a - JSON value can be requested. Note that no type conversions are made and a - `nullptr` is returned if the value and the requested pointer type does not - match.,get__PointerType} - - @sa @ref get_ptr() for explicit pointer-member access - - @since version 1.0.0 - */ - template::value, int>::type = 0> - PointerType get() noexcept - { - // delegate the call to get_ptr - return get_ptr(); - } - - /*! - @brief get a pointer value (explicit) - @copydoc get() - */ - template::value, int>::type = 0> - constexpr const PointerType get() const noexcept - { - // delegate the call to get_ptr - return get_ptr(); - } - - /*! - @brief get a pointer value (implicit) - - Implicit pointer access to the internally stored JSON value. No copies are - made. - - @warning Writing data to the pointee of the result yields an undefined - state. - - @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref - object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, - @ref number_unsigned_t, or @ref number_float_t. Enforced by a static - assertion. - - @return pointer to the internally stored JSON value if the requested - pointer type @a PointerType fits to the JSON value; `nullptr` otherwise - - @complexity Constant. - - @liveexample{The example below shows how pointers to internal values of a - JSON value can be requested. Note that no type conversions are made and a - `nullptr` is returned if the value and the requested pointer type does not - match.,get_ptr} - - @since version 1.0.0 - */ - template::value, int>::type = 0> - PointerType get_ptr() noexcept - { - // get the type of the PointerType (remove pointer and const) - using pointee_t = typename std::remove_const::type>::type>::type; - // make sure the type matches the allowed types - static_assert( - std::is_same::value - or std::is_same::value - or std::is_same::value - or std::is_same::value - or std::is_same::value - or std::is_same::value - or std::is_same::value - , "incompatible pointer type"); - - // delegate the call to get_impl_ptr<>() - return get_impl_ptr(static_cast(nullptr)); - } - - /*! - @brief get a pointer value (implicit) - @copydoc get_ptr() - */ - template::value and - std::is_const::type>::value, int>::type = 0> - constexpr const PointerType get_ptr() const noexcept - { - // get the type of the PointerType (remove pointer and const) - using pointee_t = typename std::remove_const::type>::type>::type; - // make sure the type matches the allowed types - static_assert( - std::is_same::value - or std::is_same::value - or std::is_same::value - or std::is_same::value - or std::is_same::value - or std::is_same::value - or std::is_same::value - , "incompatible pointer type"); - - // delegate the call to get_impl_ptr<>() const - return get_impl_ptr(static_cast(nullptr)); - } - - /*! - @brief get a reference value (implicit) - - Implicit reference access to the internally stored JSON value. No copies - are made. - - @warning Writing data to the referee of the result yields an undefined - state. - - @tparam ReferenceType reference type; must be a reference to @ref array_t, - @ref object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, or - @ref number_float_t. Enforced by static assertion. - - @return reference to the internally stored JSON value if the requested - reference type @a ReferenceType fits to the JSON value; throws - type_error.303 otherwise - - @throw type_error.303 in case passed type @a ReferenceType is incompatible - with the stored JSON value; see example below - - @complexity Constant. - - @liveexample{The example shows several calls to `get_ref()`.,get_ref} - - @since version 1.1.0 - */ - template::value, int>::type = 0> - ReferenceType get_ref() - { - // delegate call to get_ref_impl - return get_ref_impl(*this); - } - - /*! - @brief get a reference value (implicit) - @copydoc get_ref() - */ - template::value and - std::is_const::type>::value, int>::type = 0> - ReferenceType get_ref() const - { - // delegate call to get_ref_impl - return get_ref_impl(*this); - } - - /*! - @brief get a value (implicit) - - Implicit type conversion between the JSON value and a compatible value. - The call is realized by calling @ref get() const. - - @tparam ValueType non-pointer type compatible to the JSON value, for - instance `int` for JSON integer numbers, `bool` for JSON booleans, or - `std::vector` types for JSON arrays. The character type of @ref string_t - as well as an initializer list of this type is excluded to avoid - ambiguities as these types implicitly convert to `std::string`. - - @return copy of the JSON value, converted to type @a ValueType - - @throw type_error.302 in case passed type @a ValueType is incompatible - to the JSON value type (e.g., the JSON value is of type boolean, but a - string is requested); see example below - - @complexity Linear in the size of the JSON value. - - @liveexample{The example below shows several conversions from JSON values - to other types. There a few things to note: (1) Floating-point numbers can - be converted to integers\, (2) A JSON array can be converted to a standard - `std::vector`\, (3) A JSON object can be converted to C++ - associative containers such as `std::unordered_map`.,operator__ValueType} - - @since version 1.0.0 - */ - template < typename ValueType, typename std::enable_if < - not std::is_pointer::value and - not std::is_same::value -#ifndef _MSC_VER // fix for issue #167 operator<< ambiguity under VS2015 - and not std::is_same>::value -#endif -#if defined(_MSC_VER) && _MSC_VER >1900 && defined(_HAS_CXX17) && _HAS_CXX17 == 1 // fix for issue #464 - and not std::is_same::value -#endif - , int >::type = 0 > - operator ValueType() const - { - // delegate the call to get<>() const - return get(); - } - - /// @} - - - //////////////////// - // element access // - //////////////////// - - /// @name element access - /// Access to the JSON value. - /// @{ - - /*! - @brief access specified array element with bounds checking - - Returns a reference to the element at specified location @a idx, with - bounds checking. - - @param[in] idx index of the element to access - - @return reference to the element at index @a idx - - @throw type_error.304 if the JSON value is not an array; in this case, - calling `at` with an index makes no sense. See example below. - @throw out_of_range.401 if the index @a idx is out of range of the array; - that is, `idx >= size()`. See example below. - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes in the JSON value. - - @complexity Constant. - - @since version 1.0.0 - - @liveexample{The example below shows how array elements can be read and - written using `at()`. It also demonstrates the different exceptions that - can be thrown.,at__size_type} - */ - reference at(size_type idx) - { - // at only works for arrays - if (is_array()) - { - JSON_TRY - { - return m_value.array->at(idx); - } - JSON_CATCH (std::out_of_range&) - { - // create better exception explanation - JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range")); - } - } - else - { - JSON_THROW(type_error::create(304, "cannot use at() with " + type_name())); - } - } - - /*! - @brief access specified array element with bounds checking - - Returns a const reference to the element at specified location @a idx, - with bounds checking. - - @param[in] idx index of the element to access - - @return const reference to the element at index @a idx - - @throw type_error.304 if the JSON value is not an array; in this case, - calling `at` with an index makes no sense. See example below. - @throw out_of_range.401 if the index @a idx is out of range of the array; - that is, `idx >= size()`. See example below. - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes in the JSON value. - - @complexity Constant. - - @since version 1.0.0 - - @liveexample{The example below shows how array elements can be read using - `at()`. It also demonstrates the different exceptions that can be thrown., - at__size_type_const} - */ - const_reference at(size_type idx) const - { - // at only works for arrays - if (is_array()) - { - JSON_TRY - { - return m_value.array->at(idx); - } - JSON_CATCH (std::out_of_range&) - { - // create better exception explanation - JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range")); - } - } - else - { - JSON_THROW(type_error::create(304, "cannot use at() with " + type_name())); - } - } - - /*! - @brief access specified object element with bounds checking - - Returns a reference to the element at with specified key @a key, with - bounds checking. - - @param[in] key key of the element to access - - @return reference to the element at key @a key - - @throw type_error.304 if the JSON value is not an object; in this case, - calling `at` with a key makes no sense. See example below. - @throw out_of_range.403 if the key @a key is is not stored in the object; - that is, `find(key) == end()`. See example below. - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes in the JSON value. - - @complexity Logarithmic in the size of the container. - - @sa @ref operator[](const typename object_t::key_type&) for unchecked - access by reference - @sa @ref value() for access by value with a default value - - @since version 1.0.0 - - @liveexample{The example below shows how object elements can be read and - written using `at()`. It also demonstrates the different exceptions that - can be thrown.,at__object_t_key_type} - */ - reference at(const typename object_t::key_type& key) - { - // at only works for objects - if (is_object()) - { - JSON_TRY - { - return m_value.object->at(key); - } - JSON_CATCH (std::out_of_range&) - { - // create better exception explanation - JSON_THROW(out_of_range::create(403, "key '" + key + "' not found")); - } - } - else - { - JSON_THROW(type_error::create(304, "cannot use at() with " + type_name())); - } - } - - /*! - @brief access specified object element with bounds checking - - Returns a const reference to the element at with specified key @a key, - with bounds checking. - - @param[in] key key of the element to access - - @return const reference to the element at key @a key - - @throw type_error.304 if the JSON value is not an object; in this case, - calling `at` with a key makes no sense. See example below. - @throw out_of_range.403 if the key @a key is is not stored in the object; - that is, `find(key) == end()`. See example below. - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes in the JSON value. - - @complexity Logarithmic in the size of the container. - - @sa @ref operator[](const typename object_t::key_type&) for unchecked - access by reference - @sa @ref value() for access by value with a default value - - @since version 1.0.0 - - @liveexample{The example below shows how object elements can be read using - `at()`. It also demonstrates the different exceptions that can be thrown., - at__object_t_key_type_const} - */ - const_reference at(const typename object_t::key_type& key) const - { - // at only works for objects - if (is_object()) - { - JSON_TRY - { - return m_value.object->at(key); - } - JSON_CATCH (std::out_of_range&) - { - // create better exception explanation - JSON_THROW(out_of_range::create(403, "key '" + key + "' not found")); - } - } - else - { - JSON_THROW(type_error::create(304, "cannot use at() with " + type_name())); - } - } - - /*! - @brief access specified array element - - Returns a reference to the element at specified location @a idx. - - @note If @a idx is beyond the range of the array (i.e., `idx >= size()`), - then the array is silently filled up with `null` values to make `idx` a - valid reference to the last stored element. - - @param[in] idx index of the element to access - - @return reference to the element at index @a idx - - @throw type_error.305 if the JSON value is not an array or null; in that - cases, using the [] operator with an index makes no sense. - - @complexity Constant if @a idx is in the range of the array. Otherwise - linear in `idx - size()`. - - @liveexample{The example below shows how array elements can be read and - written using `[]` operator. Note the addition of `null` - values.,operatorarray__size_type} - - @since version 1.0.0 - */ - reference operator[](size_type idx) - { - // implicitly convert null value to an empty array - if (is_null()) - { - m_type = value_t::array; - m_value.array = create(); - assert_invariant(); - } - - // operator[] only works for arrays - if (is_array()) - { - // fill up array with null values if given idx is outside range - if (idx >= m_value.array->size()) - { - m_value.array->insert(m_value.array->end(), - idx - m_value.array->size() + 1, - basic_json()); - } - - return m_value.array->operator[](idx); - } - - JSON_THROW(type_error::create(305, "cannot use operator[] with " + type_name())); - } - - /*! - @brief access specified array element - - Returns a const reference to the element at specified location @a idx. - - @param[in] idx index of the element to access - - @return const reference to the element at index @a idx - - @throw type_error.305 if the JSON value is not an array; in that cases, - using the [] operator with an index makes no sense. - - @complexity Constant. - - @liveexample{The example below shows how array elements can be read using - the `[]` operator.,operatorarray__size_type_const} - - @since version 1.0.0 - */ - const_reference operator[](size_type idx) const - { - // const operator[] only works for arrays - if (is_array()) - { - return m_value.array->operator[](idx); - } - - JSON_THROW(type_error::create(305, "cannot use operator[] with " + type_name())); - } - - /*! - @brief access specified object element - - Returns a reference to the element at with specified key @a key. - - @note If @a key is not found in the object, then it is silently added to - the object and filled with a `null` value to make `key` a valid reference. - In case the value was `null` before, it is converted to an object. - - @param[in] key key of the element to access - - @return reference to the element at key @a key - - @throw type_error.305 if the JSON value is not an object or null; in that - cases, using the [] operator with a key makes no sense. - - @complexity Logarithmic in the size of the container. - - @liveexample{The example below shows how object elements can be read and - written using the `[]` operator.,operatorarray__key_type} - - @sa @ref at(const typename object_t::key_type&) for access by reference - with range checking - @sa @ref value() for access by value with a default value - - @since version 1.0.0 - */ - reference operator[](const typename object_t::key_type& key) - { - // implicitly convert null value to an empty object - if (is_null()) - { - m_type = value_t::object; - m_value.object = create(); - assert_invariant(); - } - - // operator[] only works for objects - if (is_object()) - { - return m_value.object->operator[](key); - } - - JSON_THROW(type_error::create(305, "cannot use operator[] with " + type_name())); - } - - /*! - @brief read-only access specified object element - - Returns a const reference to the element at with specified key @a key. No - bounds checking is performed. - - @warning If the element with key @a key does not exist, the behavior is - undefined. - - @param[in] key key of the element to access - - @return const reference to the element at key @a key - - @pre The element with key @a key must exist. **This precondition is - enforced with an assertion.** - - @throw type_error.305 if the JSON value is not an object; in that cases, - using the [] operator with a key makes no sense. - - @complexity Logarithmic in the size of the container. - - @liveexample{The example below shows how object elements can be read using - the `[]` operator.,operatorarray__key_type_const} - - @sa @ref at(const typename object_t::key_type&) for access by reference - with range checking - @sa @ref value() for access by value with a default value - - @since version 1.0.0 - */ - const_reference operator[](const typename object_t::key_type& key) const - { - // const operator[] only works for objects - if (is_object()) - { - assert(m_value.object->find(key) != m_value.object->end()); - return m_value.object->find(key)->second; - } - - JSON_THROW(type_error::create(305, "cannot use operator[] with " + type_name())); - } - - /*! - @brief access specified object element - - Returns a reference to the element at with specified key @a key. - - @note If @a key is not found in the object, then it is silently added to - the object and filled with a `null` value to make `key` a valid reference. - In case the value was `null` before, it is converted to an object. - - @param[in] key key of the element to access - - @return reference to the element at key @a key - - @throw type_error.305 if the JSON value is not an object or null; in that - cases, using the [] operator with a key makes no sense. - - @complexity Logarithmic in the size of the container. - - @liveexample{The example below shows how object elements can be read and - written using the `[]` operator.,operatorarray__key_type} - - @sa @ref at(const typename object_t::key_type&) for access by reference - with range checking - @sa @ref value() for access by value with a default value - - @since version 1.0.0 - */ - template - reference operator[](T * (&key)[n]) - { - return operator[](static_cast(key)); - } - - /*! - @brief read-only access specified object element - - Returns a const reference to the element at with specified key @a key. No - bounds checking is performed. - - @warning If the element with key @a key does not exist, the behavior is - undefined. - - @note This function is required for compatibility reasons with Clang. - - @param[in] key key of the element to access - - @return const reference to the element at key @a key - - @throw type_error.305 if the JSON value is not an object; in that cases, - using the [] operator with a key makes no sense. - - @complexity Logarithmic in the size of the container. - - @liveexample{The example below shows how object elements can be read using - the `[]` operator.,operatorarray__key_type_const} - - @sa @ref at(const typename object_t::key_type&) for access by reference - with range checking - @sa @ref value() for access by value with a default value - - @since version 1.0.0 - */ - template - const_reference operator[](T * (&key)[n]) const - { - return operator[](static_cast(key)); - } - - /*! - @brief access specified object element - - Returns a reference to the element at with specified key @a key. - - @note If @a key is not found in the object, then it is silently added to - the object and filled with a `null` value to make `key` a valid reference. - In case the value was `null` before, it is converted to an object. - - @param[in] key key of the element to access - - @return reference to the element at key @a key - - @throw type_error.305 if the JSON value is not an object or null; in that - cases, using the [] operator with a key makes no sense. - - @complexity Logarithmic in the size of the container. - - @liveexample{The example below shows how object elements can be read and - written using the `[]` operator.,operatorarray__key_type} - - @sa @ref at(const typename object_t::key_type&) for access by reference - with range checking - @sa @ref value() for access by value with a default value - - @since version 1.1.0 - */ - template - reference operator[](T* key) - { - // implicitly convert null to object - if (is_null()) - { - m_type = value_t::object; - m_value = value_t::object; - assert_invariant(); - } - - // at only works for objects - if (is_object()) - { - return m_value.object->operator[](key); - } - - JSON_THROW(type_error::create(305, "cannot use operator[] with " + type_name())); - } - - /*! - @brief read-only access specified object element - - Returns a const reference to the element at with specified key @a key. No - bounds checking is performed. - - @warning If the element with key @a key does not exist, the behavior is - undefined. - - @param[in] key key of the element to access - - @return const reference to the element at key @a key - - @pre The element with key @a key must exist. **This precondition is - enforced with an assertion.** - - @throw type_error.305 if the JSON value is not an object; in that cases, - using the [] operator with a key makes no sense. - - @complexity Logarithmic in the size of the container. - - @liveexample{The example below shows how object elements can be read using - the `[]` operator.,operatorarray__key_type_const} - - @sa @ref at(const typename object_t::key_type&) for access by reference - with range checking - @sa @ref value() for access by value with a default value - - @since version 1.1.0 - */ - template - const_reference operator[](T* key) const - { - // at only works for objects - if (is_object()) - { - assert(m_value.object->find(key) != m_value.object->end()); - return m_value.object->find(key)->second; - } - - JSON_THROW(type_error::create(305, "cannot use operator[] with " + type_name())); - } - - /*! - @brief access specified object element with default value - - Returns either a copy of an object's element at the specified key @a key - or a given default value if no element with key @a key exists. - - The function is basically equivalent to executing - @code {.cpp} - try { - return at(key); - } catch(out_of_range) { - return default_value; - } - @endcode - - @note Unlike @ref at(const typename object_t::key_type&), this function - does not throw if the given key @a key was not found. - - @note Unlike @ref operator[](const typename object_t::key_type& key), this - function does not implicitly add an element to the position defined by @a - key. This function is furthermore also applicable to const objects. - - @param[in] key key of the element to access - @param[in] default_value the value to return if @a key is not found - - @tparam ValueType type compatible to JSON values, for instance `int` for - JSON integer numbers, `bool` for JSON booleans, or `std::vector` types for - JSON arrays. Note the type of the expected value at @a key and the default - value @a default_value must be compatible. - - @return copy of the element at key @a key or @a default_value if @a key - is not found - - @throw type_error.306 if the JSON value is not an objec; in that cases, - using `value()` with a key makes no sense. - - @complexity Logarithmic in the size of the container. - - @liveexample{The example below shows how object elements can be queried - with a default value.,basic_json__value} - - @sa @ref at(const typename object_t::key_type&) for access by reference - with range checking - @sa @ref operator[](const typename object_t::key_type&) for unchecked - access by reference - - @since version 1.0.0 - */ - template::value, int>::type = 0> - ValueType value(const typename object_t::key_type& key, ValueType default_value) const - { - // at only works for objects - if (is_object()) - { - // if key is found, return value and given default value otherwise - const auto it = find(key); - if (it != end()) - { - return *it; - } - - return default_value; - } - else - { - JSON_THROW(type_error::create(306, "cannot use value() with " + type_name())); - } - } - - /*! - @brief overload for a default value of type const char* - @copydoc basic_json::value(const typename object_t::key_type&, ValueType) const - */ - string_t value(const typename object_t::key_type& key, const char* default_value) const - { - return value(key, string_t(default_value)); - } - - /*! - @brief access specified object element via JSON Pointer with default value - - Returns either a copy of an object's element at the specified key @a key - or a given default value if no element with key @a key exists. - - The function is basically equivalent to executing - @code {.cpp} - try { - return at(ptr); - } catch(out_of_range) { - return default_value; - } - @endcode - - @note Unlike @ref at(const json_pointer&), this function does not throw - if the given key @a key was not found. - - @param[in] ptr a JSON pointer to the element to access - @param[in] default_value the value to return if @a ptr found no value - - @tparam ValueType type compatible to JSON values, for instance `int` for - JSON integer numbers, `bool` for JSON booleans, or `std::vector` types for - JSON arrays. Note the type of the expected value at @a key and the default - value @a default_value must be compatible. - - @return copy of the element at key @a key or @a default_value if @a key - is not found - - @throw type_error.306 if the JSON value is not an objec; in that cases, - using `value()` with a key makes no sense. - - @complexity Logarithmic in the size of the container. - - @liveexample{The example below shows how object elements can be queried - with a default value.,basic_json__value_ptr} - - @sa @ref operator[](const json_pointer&) for unchecked access by reference - - @since version 2.0.2 - */ - template::value, int>::type = 0> - ValueType value(const json_pointer& ptr, ValueType default_value) const - { - // at only works for objects - if (is_object()) - { - // if pointer resolves a value, return it or use default value - JSON_TRY - { - return ptr.get_checked(this); - } - JSON_CATCH (out_of_range&) - { - return default_value; - } - } - - JSON_THROW(type_error::create(306, "cannot use value() with " + type_name())); - } - - /*! - @brief overload for a default value of type const char* - @copydoc basic_json::value(const json_pointer&, ValueType) const - */ - string_t value(const json_pointer& ptr, const char* default_value) const - { - return value(ptr, string_t(default_value)); - } - - /*! - @brief access the first element - - Returns a reference to the first element in the container. For a JSON - container `c`, the expression `c.front()` is equivalent to `*c.begin()`. - - @return In case of a structured type (array or object), a reference to the - first element is returned. In case of number, string, or boolean values, a - reference to the value is returned. - - @complexity Constant. - - @pre The JSON value must not be `null` (would throw `std::out_of_range`) - or an empty array or object (undefined behavior, **guarded by - assertions**). - @post The JSON value remains unchanged. - - @throw invalid_iterator.214 when called on `null` value - - @liveexample{The following code shows an example for `front()`.,front} - - @sa @ref back() -- access the last element - - @since version 1.0.0 - */ - reference front() - { - return *begin(); - } - - /*! - @copydoc basic_json::front() - */ - const_reference front() const - { - return *cbegin(); - } - - /*! - @brief access the last element - - Returns a reference to the last element in the container. For a JSON - container `c`, the expression `c.back()` is equivalent to - @code {.cpp} - auto tmp = c.end(); - --tmp; - return *tmp; - @endcode - - @return In case of a structured type (array or object), a reference to the - last element is returned. In case of number, string, or boolean values, a - reference to the value is returned. - - @complexity Constant. - - @pre The JSON value must not be `null` (would throw `std::out_of_range`) - or an empty array or object (undefined behavior, **guarded by - assertions**). - @post The JSON value remains unchanged. - - @throw invalid_iterator.214 when called on a `null` value. See example - below. - - @liveexample{The following code shows an example for `back()`.,back} - - @sa @ref front() -- access the first element - - @since version 1.0.0 - */ - reference back() - { - auto tmp = end(); - --tmp; - return *tmp; - } - - /*! - @copydoc basic_json::back() - */ - const_reference back() const - { - auto tmp = cend(); - --tmp; - return *tmp; - } - - /*! - @brief remove element given an iterator - - Removes the element specified by iterator @a pos. The iterator @a pos must - be valid and dereferenceable. Thus the `end()` iterator (which is valid, - but is not dereferenceable) cannot be used as a value for @a pos. - - If called on a primitive type other than `null`, the resulting JSON value - will be `null`. - - @param[in] pos iterator to the element to remove - @return Iterator following the last removed element. If the iterator @a - pos refers to the last element, the `end()` iterator is returned. - - @tparam IteratorType an @ref iterator or @ref const_iterator - - @post Invalidates iterators and references at or after the point of the - erase, including the `end()` iterator. - - @throw type_error.307 if called on a `null` value; example: `"cannot use - erase() with null"` - @throw invalid_iterator.202 if called on an iterator which does not belong - to the current JSON value; example: `"iterator does not fit current - value"` - @throw invalid_iterator.205 if called on a primitive type with invalid - iterator (i.e., any iterator which is not `begin()`); example: `"iterator - out of range"` - - @complexity The complexity depends on the type: - - objects: amortized constant - - arrays: linear in distance between @a pos and the end of the container - - strings: linear in the length of the string - - other types: constant - - @liveexample{The example shows the result of `erase()` for different JSON - types.,erase__IteratorType} - - @sa @ref erase(IteratorType, IteratorType) -- removes the elements in - the given range - @sa @ref erase(const typename object_t::key_type&) -- removes the element - from an object at the given key - @sa @ref erase(const size_type) -- removes the element from an array at - the given index - - @since version 1.0.0 - */ - template::value or - std::is_same::value, int>::type - = 0> - IteratorType erase(IteratorType pos) - { - // make sure iterator fits the current value - if (this != pos.m_object) - { - JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value")); - } - - IteratorType result = end(); - - switch (m_type) - { - case value_t::boolean: - case value_t::number_float: - case value_t::number_integer: - case value_t::number_unsigned: - case value_t::string: - { - if (not pos.m_it.primitive_iterator.is_begin()) - { - JSON_THROW(invalid_iterator::create(205, "iterator out of range")); - } - - if (is_string()) - { - AllocatorType alloc; - alloc.destroy(m_value.string); - alloc.deallocate(m_value.string, 1); - m_value.string = nullptr; - } - - m_type = value_t::null; - assert_invariant(); - break; - } - - case value_t::object: - { - result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator); - break; - } - - case value_t::array: - { - result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator); - break; - } - - default: - { - JSON_THROW(type_error::create(307, "cannot use erase() with " + type_name())); - } - } - - return result; - } - - /*! - @brief remove elements given an iterator range - - Removes the element specified by the range `[first; last)`. The iterator - @a first does not need to be dereferenceable if `first == last`: erasing - an empty range is a no-op. - - If called on a primitive type other than `null`, the resulting JSON value - will be `null`. - - @param[in] first iterator to the beginning of the range to remove - @param[in] last iterator past the end of the range to remove - @return Iterator following the last removed element. If the iterator @a - second refers to the last element, the `end()` iterator is returned. - - @tparam IteratorType an @ref iterator or @ref const_iterator - - @post Invalidates iterators and references at or after the point of the - erase, including the `end()` iterator. - - @throw type_error.307 if called on a `null` value; example: `"cannot use - erase() with null"` - @throw invalid_iterator.203 if called on iterators which does not belong - to the current JSON value; example: `"iterators do not fit current value"` - @throw invalid_iterator.204 if called on a primitive type with invalid - iterators (i.e., if `first != begin()` and `last != end()`); example: - `"iterators out of range"` - - @complexity The complexity depends on the type: - - objects: `log(size()) + std::distance(first, last)` - - arrays: linear in the distance between @a first and @a last, plus linear - in the distance between @a last and end of the container - - strings: linear in the length of the string - - other types: constant - - @liveexample{The example shows the result of `erase()` for different JSON - types.,erase__IteratorType_IteratorType} - - @sa @ref erase(IteratorType) -- removes the element at a given position - @sa @ref erase(const typename object_t::key_type&) -- removes the element - from an object at the given key - @sa @ref erase(const size_type) -- removes the element from an array at - the given index - - @since version 1.0.0 - */ - template::value or - std::is_same::value, int>::type - = 0> - IteratorType erase(IteratorType first, IteratorType last) - { - // make sure iterator fits the current value - if (this != first.m_object or this != last.m_object) - { - JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value")); - } - - IteratorType result = end(); - - switch (m_type) - { - case value_t::boolean: - case value_t::number_float: - case value_t::number_integer: - case value_t::number_unsigned: - case value_t::string: - { - if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end()) - { - JSON_THROW(invalid_iterator::create(204, "iterators out of range")); - } - - if (is_string()) - { - AllocatorType alloc; - alloc.destroy(m_value.string); - alloc.deallocate(m_value.string, 1); - m_value.string = nullptr; - } - - m_type = value_t::null; - assert_invariant(); - break; - } - - case value_t::object: - { - result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator, - last.m_it.object_iterator); - break; - } - - case value_t::array: - { - result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator, - last.m_it.array_iterator); - break; - } - - default: - { - JSON_THROW(type_error::create(307, "cannot use erase() with " + type_name())); - } - } - - return result; - } - - /*! - @brief remove element from a JSON object given a key - - Removes elements from a JSON object with the key value @a key. - - @param[in] key value of the elements to remove - - @return Number of elements removed. If @a ObjectType is the default - `std::map` type, the return value will always be `0` (@a key was not - found) or `1` (@a key was found). - - @post References and iterators to the erased elements are invalidated. - Other references and iterators are not affected. - - @throw type_error.307 when called on a type other than JSON object; - example: `"cannot use erase() with null"` - - @complexity `log(size()) + count(key)` - - @liveexample{The example shows the effect of `erase()`.,erase__key_type} - - @sa @ref erase(IteratorType) -- removes the element at a given position - @sa @ref erase(IteratorType, IteratorType) -- removes the elements in - the given range - @sa @ref erase(const size_type) -- removes the element from an array at - the given index - - @since version 1.0.0 - */ - size_type erase(const typename object_t::key_type& key) - { - // this erase only works for objects - if (is_object()) - { - return m_value.object->erase(key); - } - - JSON_THROW(type_error::create(307, "cannot use erase() with " + type_name())); - } - - /*! - @brief remove element from a JSON array given an index - - Removes element from a JSON array at the index @a idx. - - @param[in] idx index of the element to remove - - @throw type_error.307 when called on a type other than JSON object; - example: `"cannot use erase() with null"` - @throw out_of_range.401 when `idx >= size()`; example: `"array index 17 - is out of range"` - - @complexity Linear in distance between @a idx and the end of the container. - - @liveexample{The example shows the effect of `erase()`.,erase__size_type} - - @sa @ref erase(IteratorType) -- removes the element at a given position - @sa @ref erase(IteratorType, IteratorType) -- removes the elements in - the given range - @sa @ref erase(const typename object_t::key_type&) -- removes the element - from an object at the given key - - @since version 1.0.0 - */ - void erase(const size_type idx) - { - // this erase only works for arrays - if (is_array()) - { - if (idx >= size()) - { - JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range")); - } - - m_value.array->erase(m_value.array->begin() + static_cast(idx)); - } - else - { - JSON_THROW(type_error::create(307, "cannot use erase() with " + type_name())); - } - } - - /// @} - - - //////////// - // lookup // - //////////// - - /// @name lookup - /// @{ - - /*! - @brief find an element in a JSON object - - Finds an element in a JSON object with key equivalent to @a key. If the - element is not found or the JSON value is not an object, end() is - returned. - - @note This method always returns @ref end() when executed on a JSON type - that is not an object. - - @param[in] key key value of the element to search for - - @return Iterator to an element with key equivalent to @a key. If no such - element is found or the JSON value is not an object, past-the-end (see - @ref end()) iterator is returned. - - @complexity Logarithmic in the size of the JSON object. - - @liveexample{The example shows how `find()` is used.,find__key_type} - - @since version 1.0.0 - */ - iterator find(typename object_t::key_type key) - { - auto result = end(); - - if (is_object()) - { - result.m_it.object_iterator = m_value.object->find(key); - } - - return result; - } - - /*! - @brief find an element in a JSON object - @copydoc find(typename object_t::key_type) - */ - const_iterator find(typename object_t::key_type key) const - { - auto result = cend(); - - if (is_object()) - { - result.m_it.object_iterator = m_value.object->find(key); - } - - return result; - } - - /*! - @brief returns the number of occurrences of a key in a JSON object - - Returns the number of elements with key @a key. If ObjectType is the - default `std::map` type, the return value will always be `0` (@a key was - not found) or `1` (@a key was found). - - @note This method always returns `0` when executed on a JSON type that is - not an object. - - @param[in] key key value of the element to count - - @return Number of elements with key @a key. If the JSON value is not an - object, the return value will be `0`. - - @complexity Logarithmic in the size of the JSON object. - - @liveexample{The example shows how `count()` is used.,count} - - @since version 1.0.0 - */ - size_type count(typename object_t::key_type key) const - { - // return 0 for all nonobject types - return is_object() ? m_value.object->count(key) : 0; - } - - /// @} - - - /////////////// - // iterators // - /////////////// - - /// @name iterators - /// @{ - - /*! - @brief returns an iterator to the first element - - Returns an iterator to the first element. - - @image html range-begin-end.svg "Illustration from cppreference.com" - - @return iterator to the first element - - @complexity Constant. - - @requirement This function helps `basic_json` satisfying the - [Container](http://en.cppreference.com/w/cpp/concept/Container) - requirements: - - The complexity is constant. - - @liveexample{The following code shows an example for `begin()`.,begin} - - @sa @ref cbegin() -- returns a const iterator to the beginning - @sa @ref end() -- returns an iterator to the end - @sa @ref cend() -- returns a const iterator to the end - - @since version 1.0.0 - */ - iterator begin() noexcept - { - iterator result(this); - result.set_begin(); - return result; - } - - /*! - @copydoc basic_json::cbegin() - */ - const_iterator begin() const noexcept - { - return cbegin(); - } - - /*! - @brief returns a const iterator to the first element - - Returns a const iterator to the first element. - - @image html range-begin-end.svg "Illustration from cppreference.com" - - @return const iterator to the first element - - @complexity Constant. - - @requirement This function helps `basic_json` satisfying the - [Container](http://en.cppreference.com/w/cpp/concept/Container) - requirements: - - The complexity is constant. - - Has the semantics of `const_cast(*this).begin()`. - - @liveexample{The following code shows an example for `cbegin()`.,cbegin} - - @sa @ref begin() -- returns an iterator to the beginning - @sa @ref end() -- returns an iterator to the end - @sa @ref cend() -- returns a const iterator to the end - - @since version 1.0.0 - */ - const_iterator cbegin() const noexcept - { - const_iterator result(this); - result.set_begin(); - return result; - } - - /*! - @brief returns an iterator to one past the last element - - Returns an iterator to one past the last element. - - @image html range-begin-end.svg "Illustration from cppreference.com" - - @return iterator one past the last element - - @complexity Constant. - - @requirement This function helps `basic_json` satisfying the - [Container](http://en.cppreference.com/w/cpp/concept/Container) - requirements: - - The complexity is constant. - - @liveexample{The following code shows an example for `end()`.,end} - - @sa @ref cend() -- returns a const iterator to the end - @sa @ref begin() -- returns an iterator to the beginning - @sa @ref cbegin() -- returns a const iterator to the beginning - - @since version 1.0.0 - */ - iterator end() noexcept - { - iterator result(this); - result.set_end(); - return result; - } - - /*! - @copydoc basic_json::cend() - */ - const_iterator end() const noexcept - { - return cend(); - } - - /*! - @brief returns a const iterator to one past the last element - - Returns a const iterator to one past the last element. - - @image html range-begin-end.svg "Illustration from cppreference.com" - - @return const iterator one past the last element - - @complexity Constant. - - @requirement This function helps `basic_json` satisfying the - [Container](http://en.cppreference.com/w/cpp/concept/Container) - requirements: - - The complexity is constant. - - Has the semantics of `const_cast(*this).end()`. - - @liveexample{The following code shows an example for `cend()`.,cend} - - @sa @ref end() -- returns an iterator to the end - @sa @ref begin() -- returns an iterator to the beginning - @sa @ref cbegin() -- returns a const iterator to the beginning - - @since version 1.0.0 - */ - const_iterator cend() const noexcept - { - const_iterator result(this); - result.set_end(); - return result; - } - - /*! - @brief returns an iterator to the reverse-beginning - - Returns an iterator to the reverse-beginning; that is, the last element. - - @image html range-rbegin-rend.svg "Illustration from cppreference.com" - - @complexity Constant. - - @requirement This function helps `basic_json` satisfying the - [ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer) - requirements: - - The complexity is constant. - - Has the semantics of `reverse_iterator(end())`. - - @liveexample{The following code shows an example for `rbegin()`.,rbegin} - - @sa @ref crbegin() -- returns a const reverse iterator to the beginning - @sa @ref rend() -- returns a reverse iterator to the end - @sa @ref crend() -- returns a const reverse iterator to the end - - @since version 1.0.0 - */ - reverse_iterator rbegin() noexcept - { - return reverse_iterator(end()); - } - - /*! - @copydoc basic_json::crbegin() - */ - const_reverse_iterator rbegin() const noexcept - { - return crbegin(); - } - - /*! - @brief returns an iterator to the reverse-end - - Returns an iterator to the reverse-end; that is, one before the first - element. - - @image html range-rbegin-rend.svg "Illustration from cppreference.com" - - @complexity Constant. - - @requirement This function helps `basic_json` satisfying the - [ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer) - requirements: - - The complexity is constant. - - Has the semantics of `reverse_iterator(begin())`. - - @liveexample{The following code shows an example for `rend()`.,rend} - - @sa @ref crend() -- returns a const reverse iterator to the end - @sa @ref rbegin() -- returns a reverse iterator to the beginning - @sa @ref crbegin() -- returns a const reverse iterator to the beginning - - @since version 1.0.0 - */ - reverse_iterator rend() noexcept - { - return reverse_iterator(begin()); - } - - /*! - @copydoc basic_json::crend() - */ - const_reverse_iterator rend() const noexcept - { - return crend(); - } - - /*! - @brief returns a const reverse iterator to the last element - - Returns a const iterator to the reverse-beginning; that is, the last - element. - - @image html range-rbegin-rend.svg "Illustration from cppreference.com" - - @complexity Constant. - - @requirement This function helps `basic_json` satisfying the - [ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer) - requirements: - - The complexity is constant. - - Has the semantics of `const_cast(*this).rbegin()`. - - @liveexample{The following code shows an example for `crbegin()`.,crbegin} - - @sa @ref rbegin() -- returns a reverse iterator to the beginning - @sa @ref rend() -- returns a reverse iterator to the end - @sa @ref crend() -- returns a const reverse iterator to the end - - @since version 1.0.0 - */ - const_reverse_iterator crbegin() const noexcept - { - return const_reverse_iterator(cend()); - } - - /*! - @brief returns a const reverse iterator to one before the first - - Returns a const reverse iterator to the reverse-end; that is, one before - the first element. - - @image html range-rbegin-rend.svg "Illustration from cppreference.com" - - @complexity Constant. - - @requirement This function helps `basic_json` satisfying the - [ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer) - requirements: - - The complexity is constant. - - Has the semantics of `const_cast(*this).rend()`. - - @liveexample{The following code shows an example for `crend()`.,crend} - - @sa @ref rend() -- returns a reverse iterator to the end - @sa @ref rbegin() -- returns a reverse iterator to the beginning - @sa @ref crbegin() -- returns a const reverse iterator to the beginning - - @since version 1.0.0 - */ - const_reverse_iterator crend() const noexcept - { - return const_reverse_iterator(cbegin()); - } - - private: - // forward declaration - template class iteration_proxy; - - public: - /*! - @brief wrapper to access iterator member functions in range-based for - - This function allows to access @ref iterator::key() and @ref - iterator::value() during range-based for loops. In these loops, a - reference to the JSON values is returned, so there is no access to the - underlying iterator. - - @note The name of this function is not yet final and may change in the - future. - */ - static iteration_proxy iterator_wrapper(reference cont) - { - return iteration_proxy(cont); - } - - /*! - @copydoc iterator_wrapper(reference) - */ - static iteration_proxy iterator_wrapper(const_reference cont) - { - return iteration_proxy(cont); - } - - /// @} - - - ////////////// - // capacity // - ////////////// - - /// @name capacity - /// @{ - - /*! - @brief checks whether the container is empty - - Checks if a JSON value has no elements. - - @return The return value depends on the different types and is - defined as follows: - Value type | return value - ----------- | ------------- - null | `true` - boolean | `false` - string | `false` - number | `false` - object | result of function `object_t::empty()` - array | result of function `array_t::empty()` - - @note This function does not return whether a string stored as JSON value - is empty - it returns whether the JSON container itself is empty which is - false in the case of a string. - - @complexity Constant, as long as @ref array_t and @ref object_t satisfy - the Container concept; that is, their `empty()` functions have constant - complexity. - - @requirement This function helps `basic_json` satisfying the - [Container](http://en.cppreference.com/w/cpp/concept/Container) - requirements: - - The complexity is constant. - - Has the semantics of `begin() == end()`. - - @liveexample{The following code uses `empty()` to check if a JSON - object contains any elements.,empty} - - @sa @ref size() -- returns the number of elements - - @since version 1.0.0 - */ - bool empty() const noexcept - { - switch (m_type) - { - case value_t::null: - { - // null values are empty - return true; - } - - case value_t::array: - { - // delegate call to array_t::empty() - return m_value.array->empty(); - } - - case value_t::object: - { - // delegate call to object_t::empty() - return m_value.object->empty(); - } - - default: - { - // all other types are nonempty - return false; - } - } - } - - /*! - @brief returns the number of elements - - Returns the number of elements in a JSON value. - - @return The return value depends on the different types and is - defined as follows: - Value type | return value - ----------- | ------------- - null | `0` - boolean | `1` - string | `1` - number | `1` - object | result of function object_t::size() - array | result of function array_t::size() - - @note This function does not return the length of a string stored as JSON - value - it returns the number of elements in the JSON value which is 1 in - the case of a string. - - @complexity Constant, as long as @ref array_t and @ref object_t satisfy - the Container concept; that is, their size() functions have constant - complexity. - - @requirement This function helps `basic_json` satisfying the - [Container](http://en.cppreference.com/w/cpp/concept/Container) - requirements: - - The complexity is constant. - - Has the semantics of `std::distance(begin(), end())`. - - @liveexample{The following code calls `size()` on the different value - types.,size} - - @sa @ref empty() -- checks whether the container is empty - @sa @ref max_size() -- returns the maximal number of elements - - @since version 1.0.0 - */ - size_type size() const noexcept - { - switch (m_type) - { - case value_t::null: - { - // null values are empty - return 0; - } - - case value_t::array: - { - // delegate call to array_t::size() - return m_value.array->size(); - } - - case value_t::object: - { - // delegate call to object_t::size() - return m_value.object->size(); - } - - default: - { - // all other types have size 1 - return 1; - } - } - } - - /*! - @brief returns the maximum possible number of elements - - Returns the maximum number of elements a JSON value is able to hold due to - system or library implementation limitations, i.e. `std::distance(begin(), - end())` for the JSON value. - - @return The return value depends on the different types and is - defined as follows: - Value type | return value - ----------- | ------------- - null | `0` (same as `size()`) - boolean | `1` (same as `size()`) - string | `1` (same as `size()`) - number | `1` (same as `size()`) - object | result of function `object_t::max_size()` - array | result of function `array_t::max_size()` - - @complexity Constant, as long as @ref array_t and @ref object_t satisfy - the Container concept; that is, their `max_size()` functions have constant - complexity. - - @requirement This function helps `basic_json` satisfying the - [Container](http://en.cppreference.com/w/cpp/concept/Container) - requirements: - - The complexity is constant. - - Has the semantics of returning `b.size()` where `b` is the largest - possible JSON value. - - @liveexample{The following code calls `max_size()` on the different value - types. Note the output is implementation specific.,max_size} - - @sa @ref size() -- returns the number of elements - - @since version 1.0.0 - */ - size_type max_size() const noexcept - { - switch (m_type) - { - case value_t::array: - { - // delegate call to array_t::max_size() - return m_value.array->max_size(); - } - - case value_t::object: - { - // delegate call to object_t::max_size() - return m_value.object->max_size(); - } - - default: - { - // all other types have max_size() == size() - return size(); - } - } - } - - /// @} - - - /////////////// - // modifiers // - /////////////// - - /// @name modifiers - /// @{ - - /*! - @brief clears the contents - - Clears the content of a JSON value and resets it to the default value as - if @ref basic_json(value_t) would have been called: - - Value type | initial value - ----------- | ------------- - null | `null` - boolean | `false` - string | `""` - number | `0` - object | `{}` - array | `[]` - - @complexity Linear in the size of the JSON value. - - @liveexample{The example below shows the effect of `clear()` to different - JSON types.,clear} - - @since version 1.0.0 - */ - void clear() noexcept - { - switch (m_type) - { - case value_t::number_integer: - { - m_value.number_integer = 0; - break; - } - - case value_t::number_unsigned: - { - m_value.number_unsigned = 0; - break; - } - - case value_t::number_float: - { - m_value.number_float = 0.0; - break; - } - - case value_t::boolean: - { - m_value.boolean = false; - break; - } - - case value_t::string: - { - m_value.string->clear(); - break; - } - - case value_t::array: - { - m_value.array->clear(); - break; - } - - case value_t::object: - { - m_value.object->clear(); - break; - } - - default: - { - break; - } - } - } - - /*! - @brief add an object to an array - - Appends the given element @a val to the end of the JSON value. If the - function is called on a JSON null value, an empty array is created before - appending @a val. - - @param[in] val the value to add to the JSON array - - @throw type_error.308 when called on a type other than JSON array or - null; example: `"cannot use push_back() with number"` - - @complexity Amortized constant. - - @liveexample{The example shows how `push_back()` and `+=` can be used to - add elements to a JSON array. Note how the `null` value was silently - converted to a JSON array.,push_back} - - @since version 1.0.0 - */ - void push_back(basic_json&& val) - { - // push_back only works for null objects or arrays - if (not(is_null() or is_array())) - { - JSON_THROW(type_error::create(308, "cannot use push_back() with " + type_name())); - } - - // transform null object into an array - if (is_null()) - { - m_type = value_t::array; - m_value = value_t::array; - assert_invariant(); - } - - // add element to array (move semantics) - m_value.array->push_back(std::move(val)); - // invalidate object - val.m_type = value_t::null; - } - - /*! - @brief add an object to an array - @copydoc push_back(basic_json&&) - */ - reference operator+=(basic_json&& val) - { - push_back(std::move(val)); - return *this; - } - - /*! - @brief add an object to an array - @copydoc push_back(basic_json&&) - */ - void push_back(const basic_json& val) - { - // push_back only works for null objects or arrays - if (not(is_null() or is_array())) - { - JSON_THROW(type_error::create(308, "cannot use push_back() with " + type_name())); - } - - // transform null object into an array - if (is_null()) - { - m_type = value_t::array; - m_value = value_t::array; - assert_invariant(); - } - - // add element to array - m_value.array->push_back(val); - } - - /*! - @brief add an object to an array - @copydoc push_back(basic_json&&) - */ - reference operator+=(const basic_json& val) - { - push_back(val); - return *this; - } - - /*! - @brief add an object to an object - - Inserts the given element @a val to the JSON object. If the function is - called on a JSON null value, an empty object is created before inserting - @a val. - - @param[in] val the value to add to the JSON object - - @throw type_error.308 when called on a type other than JSON object or - null; example: `"cannot use push_back() with number"` - - @complexity Logarithmic in the size of the container, O(log(`size()`)). - - @liveexample{The example shows how `push_back()` and `+=` can be used to - add elements to a JSON object. Note how the `null` value was silently - converted to a JSON object.,push_back__object_t__value} - - @since version 1.0.0 - */ - void push_back(const typename object_t::value_type& val) - { - // push_back only works for null objects or objects - if (not(is_null() or is_object())) - { - JSON_THROW(type_error::create(308, "cannot use push_back() with " + type_name())); - } - - // transform null object into an object - if (is_null()) - { - m_type = value_t::object; - m_value = value_t::object; - assert_invariant(); - } - - // add element to array - m_value.object->insert(val); - } - - /*! - @brief add an object to an object - @copydoc push_back(const typename object_t::value_type&) - */ - reference operator+=(const typename object_t::value_type& val) - { - push_back(val); - return *this; - } - - /*! - @brief add an object to an object - - This function allows to use `push_back` with an initializer list. In case - - 1. the current value is an object, - 2. the initializer list @a init contains only two elements, and - 3. the first element of @a init is a string, - - @a init is converted into an object element and added using - @ref push_back(const typename object_t::value_type&). Otherwise, @a init - is converted to a JSON value and added using @ref push_back(basic_json&&). - - @param[in] init an initializer list - - @complexity Linear in the size of the initializer list @a init. - - @note This function is required to resolve an ambiguous overload error, - because pairs like `{"key", "value"}` can be both interpreted as - `object_t::value_type` or `std::initializer_list`, see - https://github.com/nlohmann/json/issues/235 for more information. - - @liveexample{The example shows how initializer lists are treated as - objects when possible.,push_back__initializer_list} - */ - void push_back(std::initializer_list init) - { - if (is_object() and init.size() == 2 and init.begin()->is_string()) - { - const string_t key = *init.begin(); - push_back(typename object_t::value_type(key, *(init.begin() + 1))); - } - else - { - push_back(basic_json(init)); - } - } - - /*! - @brief add an object to an object - @copydoc push_back(std::initializer_list) - */ - reference operator+=(std::initializer_list init) - { - push_back(init); - return *this; - } - - /*! - @brief add an object to an array - - Creates a JSON value from the passed parameters @a args to the end of the - JSON value. If the function is called on a JSON null value, an empty array - is created before appending the value created from @a args. - - @param[in] args arguments to forward to a constructor of @ref basic_json - @tparam Args compatible types to create a @ref basic_json object - - @throw type_error.311 when called on a type other than JSON array or - null; example: `"cannot use emplace_back() with number"` - - @complexity Amortized constant. - - @liveexample{The example shows how `push_back()` can be used to add - elements to a JSON array. Note how the `null` value was silently converted - to a JSON array.,emplace_back} - - @since version 2.0.8 - */ - template - void emplace_back(Args&& ... args) - { - // emplace_back only works for null objects or arrays - if (not(is_null() or is_array())) - { - JSON_THROW(type_error::create(311, "cannot use emplace_back() with " + type_name())); - } - - // transform null object into an array - if (is_null()) - { - m_type = value_t::array; - m_value = value_t::array; - assert_invariant(); - } - - // add element to array (perfect forwarding) - m_value.array->emplace_back(std::forward(args)...); - } - - /*! - @brief add an object to an object if key does not exist - - Inserts a new element into a JSON object constructed in-place with the - given @a args if there is no element with the key in the container. If the - function is called on a JSON null value, an empty object is created before - appending the value created from @a args. - - @param[in] args arguments to forward to a constructor of @ref basic_json - @tparam Args compatible types to create a @ref basic_json object - - @return a pair consisting of an iterator to the inserted element, or the - already-existing element if no insertion happened, and a bool - denoting whether the insertion took place. - - @throw type_error.311 when called on a type other than JSON object or - null; example: `"cannot use emplace() with number"` - - @complexity Logarithmic in the size of the container, O(log(`size()`)). - - @liveexample{The example shows how `emplace()` can be used to add elements - to a JSON object. Note how the `null` value was silently converted to a - JSON object. Further note how no value is added if there was already one - value stored with the same key.,emplace} - - @since version 2.0.8 - */ - template - std::pair emplace(Args&& ... args) - { - // emplace only works for null objects or arrays - if (not(is_null() or is_object())) - { - JSON_THROW(type_error::create(311, "cannot use emplace() with " + type_name())); - } - - // transform null object into an object - if (is_null()) - { - m_type = value_t::object; - m_value = value_t::object; - assert_invariant(); - } - - // add element to array (perfect forwarding) - auto res = m_value.object->emplace(std::forward(args)...); - // create result iterator and set iterator to the result of emplace - auto it = begin(); - it.m_it.object_iterator = res.first; - - // return pair of iterator and boolean - return {it, res.second}; - } - - /*! - @brief inserts element - - Inserts element @a val before iterator @a pos. - - @param[in] pos iterator before which the content will be inserted; may be - the end() iterator - @param[in] val element to insert - @return iterator pointing to the inserted @a val. - - @throw type_error.309 if called on JSON values other than arrays; - example: `"cannot use insert() with string"` - @throw invalid_iterator.202 if @a pos is not an iterator of *this; - example: `"iterator does not fit current value"` - - @complexity Constant plus linear in the distance between @a pos and end of - the container. - - @liveexample{The example shows how `insert()` is used.,insert} - - @since version 1.0.0 - */ - iterator insert(const_iterator pos, const basic_json& val) - { - // insert only works for arrays - if (is_array()) - { - // check if iterator pos fits to this JSON value - if (pos.m_object != this) - { - JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value")); - } - - // insert to array and return iterator - iterator result(this); - result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val); - return result; - } - - JSON_THROW(type_error::create(309, "cannot use insert() with " + type_name())); - } - - /*! - @brief inserts element - @copydoc insert(const_iterator, const basic_json&) - */ - iterator insert(const_iterator pos, basic_json&& val) - { - return insert(pos, val); - } - - /*! - @brief inserts elements - - Inserts @a cnt copies of @a val before iterator @a pos. - - @param[in] pos iterator before which the content will be inserted; may be - the end() iterator - @param[in] cnt number of copies of @a val to insert - @param[in] val element to insert - @return iterator pointing to the first element inserted, or @a pos if - `cnt==0` - - @throw type_error.309 if called on JSON values other than arrays; example: - `"cannot use insert() with string"` - @throw invalid_iterator.202 if @a pos is not an iterator of *this; - example: `"iterator does not fit current value"` - - @complexity Linear in @a cnt plus linear in the distance between @a pos - and end of the container. - - @liveexample{The example shows how `insert()` is used.,insert__count} - - @since version 1.0.0 - */ - iterator insert(const_iterator pos, size_type cnt, const basic_json& val) - { - // insert only works for arrays - if (is_array()) - { - // check if iterator pos fits to this JSON value - if (pos.m_object != this) - { - JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value")); - } - - // insert to array and return iterator - iterator result(this); - result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val); - return result; - } - - JSON_THROW(type_error::create(309, "cannot use insert() with " + type_name())); - } - - /*! - @brief inserts elements - - Inserts elements from range `[first, last)` before iterator @a pos. - - @param[in] pos iterator before which the content will be inserted; may be - the end() iterator - @param[in] first begin of the range of elements to insert - @param[in] last end of the range of elements to insert - - @throw type_error.309 if called on JSON values other than arrays; example: - `"cannot use insert() with string"` - @throw invalid_iterator.202 if @a pos is not an iterator of *this; - example: `"iterator does not fit current value"` - @throw invalid_iterator.210 if @a first and @a last do not belong to the - same JSON value; example: `"iterators do not fit"` - @throw invalid_iterator.211 if @a first or @a last are iterators into - container for which insert is called; example: `"passed iterators may not - belong to container"` - - @return iterator pointing to the first element inserted, or @a pos if - `first==last` - - @complexity Linear in `std::distance(first, last)` plus linear in the - distance between @a pos and end of the container. - - @liveexample{The example shows how `insert()` is used.,insert__range} - - @since version 1.0.0 - */ - iterator insert(const_iterator pos, const_iterator first, const_iterator last) - { - // insert only works for arrays - if (not is_array()) - { - JSON_THROW(type_error::create(309, "cannot use insert() with " + type_name())); - } - - // check if iterator pos fits to this JSON value - if (pos.m_object != this) - { - JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value")); - } - - // check if range iterators belong to the same JSON object - if (first.m_object != last.m_object) - { - JSON_THROW(invalid_iterator::create(210, "iterators do not fit")); - } - - if (first.m_object == this or last.m_object == this) - { - JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container")); - } - - // insert to array and return iterator - iterator result(this); - result.m_it.array_iterator = m_value.array->insert( - pos.m_it.array_iterator, - first.m_it.array_iterator, - last.m_it.array_iterator); - return result; - } - - /*! - @brief inserts elements - - Inserts elements from initializer list @a ilist before iterator @a pos. - - @param[in] pos iterator before which the content will be inserted; may be - the end() iterator - @param[in] ilist initializer list to insert the values from - - @throw type_error.309 if called on JSON values other than arrays; example: - `"cannot use insert() with string"` - @throw invalid_iterator.202 if @a pos is not an iterator of *this; - example: `"iterator does not fit current value"` - - @return iterator pointing to the first element inserted, or @a pos if - `ilist` is empty - - @complexity Linear in `ilist.size()` plus linear in the distance between - @a pos and end of the container. - - @liveexample{The example shows how `insert()` is used.,insert__ilist} - - @since version 1.0.0 - */ - iterator insert(const_iterator pos, std::initializer_list ilist) - { - // insert only works for arrays - if (not is_array()) - { - JSON_THROW(type_error::create(309, "cannot use insert() with " + type_name())); - } - - // check if iterator pos fits to this JSON value - if (pos.m_object != this) - { - JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value")); - } - - // insert to array and return iterator - iterator result(this); - result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist); - return result; - } - - /*! - @brief inserts elements - - Inserts elements from range `[first, last)`. - - @param[in] first begin of the range of elements to insert - @param[in] last end of the range of elements to insert - - @throw type_error.309 if called on JSON values other than objects; example: - `"cannot use insert() with string"` - @throw invalid_iterator.202 if iterator @a first or @a last does does not - point to an object; example: `"iterators first and last must point to - objects"` - @throw invalid_iterator.210 if @a first and @a last do not belong to the - same JSON value; example: `"iterators do not fit"` - - @complexity Logarithmic: `O(N*log(size() + N))`, where `N` is the number - of elements to insert. - - @liveexample{The example shows how `insert()` is used.,insert__range_object} - - @since version 3.0.0 - */ - void insert(const_iterator first, const_iterator last) - { - // insert only works for objects - if (not is_object()) - { - JSON_THROW(type_error::create(309, "cannot use insert() with " + type_name())); - } - - // check if range iterators belong to the same JSON object - if (first.m_object != last.m_object) - { - JSON_THROW(invalid_iterator::create(210, "iterators do not fit")); - } - - // passed iterators must belong to objects - if (not first.m_object->is_object() or not first.m_object->is_object()) - { - JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects")); - } - - m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator); - } - - /*! - @brief exchanges the values - - Exchanges the contents of the JSON value with those of @a other. Does not - invoke any move, copy, or swap operations on individual elements. All - iterators and references remain valid. The past-the-end iterator is - invalidated. - - @param[in,out] other JSON value to exchange the contents with - - @complexity Constant. - - @liveexample{The example below shows how JSON values can be swapped with - `swap()`.,swap__reference} - - @since version 1.0.0 - */ - void swap(reference other) noexcept ( - std::is_nothrow_move_constructible::value and - std::is_nothrow_move_assignable::value and - std::is_nothrow_move_constructible::value and - std::is_nothrow_move_assignable::value - ) - { - std::swap(m_type, other.m_type); - std::swap(m_value, other.m_value); - assert_invariant(); - } - - /*! - @brief exchanges the values - - Exchanges the contents of a JSON array with those of @a other. Does not - invoke any move, copy, or swap operations on individual elements. All - iterators and references remain valid. The past-the-end iterator is - invalidated. - - @param[in,out] other array to exchange the contents with - - @throw type_error.310 when JSON value is not an array; example: `"cannot - use swap() with string"` - - @complexity Constant. - - @liveexample{The example below shows how arrays can be swapped with - `swap()`.,swap__array_t} - - @since version 1.0.0 - */ - void swap(array_t& other) - { - // swap only works for arrays - if (is_array()) - { - std::swap(*(m_value.array), other); - } - else - { - JSON_THROW(type_error::create(310, "cannot use swap() with " + type_name())); - } - } - - /*! - @brief exchanges the values - - Exchanges the contents of a JSON object with those of @a other. Does not - invoke any move, copy, or swap operations on individual elements. All - iterators and references remain valid. The past-the-end iterator is - invalidated. - - @param[in,out] other object to exchange the contents with - - @throw type_error.310 when JSON value is not an object; example: - `"cannot use swap() with string"` - - @complexity Constant. - - @liveexample{The example below shows how objects can be swapped with - `swap()`.,swap__object_t} - - @since version 1.0.0 - */ - void swap(object_t& other) - { - // swap only works for objects - if (is_object()) - { - std::swap(*(m_value.object), other); - } - else - { - JSON_THROW(type_error::create(310, "cannot use swap() with " + type_name())); - } - } - - /*! - @brief exchanges the values - - Exchanges the contents of a JSON string with those of @a other. Does not - invoke any move, copy, or swap operations on individual elements. All - iterators and references remain valid. The past-the-end iterator is - invalidated. - - @param[in,out] other string to exchange the contents with - - @throw type_error.310 when JSON value is not a string; example: `"cannot - use swap() with boolean"` - - @complexity Constant. - - @liveexample{The example below shows how strings can be swapped with - `swap()`.,swap__string_t} - - @since version 1.0.0 - */ - void swap(string_t& other) - { - // swap only works for strings - if (is_string()) - { - std::swap(*(m_value.string), other); - } - else - { - JSON_THROW(type_error::create(310, "cannot use swap() with " + type_name())); - } - } - - /// @} - - public: - ////////////////////////////////////////// - // lexicographical comparison operators // - ////////////////////////////////////////// - - /// @name lexicographical comparison operators - /// @{ - - /*! - @brief comparison: equal - - Compares two JSON values for equality according to the following rules: - - Two JSON values are equal if (1) they are from the same type and (2) - their stored values are the same according to their respective - `operator==`. - - Integer and floating-point numbers are automatically converted before - comparison. Floating-point numbers are compared indirectly: two - floating-point numbers `f1` and `f2` are considered equal if neither - `f1 > f2` nor `f2 > f1` holds. Note than two NaN values are always - treated as unequal. - - Two JSON null values are equal. - - @note NaN values never compare equal to themselves or to other NaN values. - - @param[in] lhs first JSON value to consider - @param[in] rhs second JSON value to consider - @return whether the values @a lhs and @a rhs are equal - - @complexity Linear. - - @liveexample{The example demonstrates comparing several JSON - types.,operator__equal} - - @since version 1.0.0 - */ - friend bool operator==(const_reference lhs, const_reference rhs) noexcept - { - const auto lhs_type = lhs.type(); - const auto rhs_type = rhs.type(); - - if (lhs_type == rhs_type) - { - switch (lhs_type) - { - case value_t::array: - { - return *lhs.m_value.array == *rhs.m_value.array; - } - case value_t::object: - { - return *lhs.m_value.object == *rhs.m_value.object; - } - case value_t::null: - { - return true; - } - case value_t::string: - { - return *lhs.m_value.string == *rhs.m_value.string; - } - case value_t::boolean: - { - return lhs.m_value.boolean == rhs.m_value.boolean; - } - case value_t::number_integer: - { - return lhs.m_value.number_integer == rhs.m_value.number_integer; - } - case value_t::number_unsigned: - { - return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned; - } - case value_t::number_float: - { - return lhs.m_value.number_float == rhs.m_value.number_float; - } - default: - { - return false; - } - } - } - else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float) - { - return static_cast(lhs.m_value.number_integer) == rhs.m_value.number_float; - } - else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer) - { - return lhs.m_value.number_float == static_cast(rhs.m_value.number_integer); - } - else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float) - { - return static_cast(lhs.m_value.number_unsigned) == rhs.m_value.number_float; - } - else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned) - { - return lhs.m_value.number_float == static_cast(rhs.m_value.number_unsigned); - } - else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer) - { - return static_cast(lhs.m_value.number_unsigned) == rhs.m_value.number_integer; - } - else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned) - { - return lhs.m_value.number_integer == static_cast(rhs.m_value.number_unsigned); - } - - return false; - } - - /*! - @brief comparison: equal - @copydoc operator==(const_reference, const_reference) - */ - template::value, int>::type = 0> - friend bool operator==(const_reference lhs, const ScalarType rhs) noexcept - { - return (lhs == basic_json(rhs)); - } - - /*! - @brief comparison: equal - @copydoc operator==(const_reference, const_reference) - */ - template::value, int>::type = 0> - friend bool operator==(const ScalarType lhs, const_reference rhs) noexcept - { - return (basic_json(lhs) == rhs); - } - - /*! - @brief comparison: not equal - - Compares two JSON values for inequality by calculating `not (lhs == rhs)`. - - @param[in] lhs first JSON value to consider - @param[in] rhs second JSON value to consider - @return whether the values @a lhs and @a rhs are not equal - - @complexity Linear. - - @liveexample{The example demonstrates comparing several JSON - types.,operator__notequal} - - @since version 1.0.0 - */ - friend bool operator!=(const_reference lhs, const_reference rhs) noexcept - { - return not (lhs == rhs); - } - - /*! - @brief comparison: not equal - @copydoc operator!=(const_reference, const_reference) - */ - template::value, int>::type = 0> - friend bool operator!=(const_reference lhs, const ScalarType rhs) noexcept - { - return (lhs != basic_json(rhs)); - } - - /*! - @brief comparison: not equal - @copydoc operator!=(const_reference, const_reference) - */ - template::value, int>::type = 0> - friend bool operator!=(const ScalarType lhs, const_reference rhs) noexcept - { - return (basic_json(lhs) != rhs); - } - - /*! - @brief comparison: less than - - Compares whether one JSON value @a lhs is less than another JSON value @a - rhs according to the following rules: - - If @a lhs and @a rhs have the same type, the values are compared using - the default `<` operator. - - Integer and floating-point numbers are automatically converted before - comparison - - In case @a lhs and @a rhs have different types, the values are ignored - and the order of the types is considered, see - @ref operator<(const value_t, const value_t). - - @param[in] lhs first JSON value to consider - @param[in] rhs second JSON value to consider - @return whether @a lhs is less than @a rhs - - @complexity Linear. - - @liveexample{The example demonstrates comparing several JSON - types.,operator__less} - - @since version 1.0.0 - */ - friend bool operator<(const_reference lhs, const_reference rhs) noexcept - { - const auto lhs_type = lhs.type(); - const auto rhs_type = rhs.type(); - - if (lhs_type == rhs_type) - { - switch (lhs_type) - { - case value_t::array: - { - return *lhs.m_value.array < *rhs.m_value.array; - } - case value_t::object: - { - return *lhs.m_value.object < *rhs.m_value.object; - } - case value_t::null: - { - return false; - } - case value_t::string: - { - return *lhs.m_value.string < *rhs.m_value.string; - } - case value_t::boolean: - { - return lhs.m_value.boolean < rhs.m_value.boolean; - } - case value_t::number_integer: - { - return lhs.m_value.number_integer < rhs.m_value.number_integer; - } - case value_t::number_unsigned: - { - return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned; - } - case value_t::number_float: - { - return lhs.m_value.number_float < rhs.m_value.number_float; - } - default: - { - return false; - } - } - } - else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float) - { - return static_cast(lhs.m_value.number_integer) < rhs.m_value.number_float; - } - else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer) - { - return lhs.m_value.number_float < static_cast(rhs.m_value.number_integer); - } - else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float) - { - return static_cast(lhs.m_value.number_unsigned) < rhs.m_value.number_float; - } - else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned) - { - return lhs.m_value.number_float < static_cast(rhs.m_value.number_unsigned); - } - else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned) - { - return lhs.m_value.number_integer < static_cast(rhs.m_value.number_unsigned); - } - else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer) - { - return static_cast(lhs.m_value.number_unsigned) < rhs.m_value.number_integer; - } - - // We only reach this line if we cannot compare values. In that case, - // we compare types. Note we have to call the operator explicitly, - // because MSVC has problems otherwise. - return operator<(lhs_type, rhs_type); - } - - /*! - @brief comparison: less than - @copydoc operator<(const_reference, const_reference) - */ - template::value, int>::type = 0> - friend bool operator<(const_reference lhs, const ScalarType rhs) noexcept - { - return (lhs < basic_json(rhs)); - } - - /*! - @brief comparison: less than - @copydoc operator<(const_reference, const_reference) - */ - template::value, int>::type = 0> - friend bool operator<(const ScalarType lhs, const_reference rhs) noexcept - { - return (basic_json(lhs) < rhs); - } - - /*! - @brief comparison: less than or equal - - Compares whether one JSON value @a lhs is less than or equal to another - JSON value by calculating `not (rhs < lhs)`. - - @param[in] lhs first JSON value to consider - @param[in] rhs second JSON value to consider - @return whether @a lhs is less than or equal to @a rhs - - @complexity Linear. - - @liveexample{The example demonstrates comparing several JSON - types.,operator__greater} - - @since version 1.0.0 - */ - friend bool operator<=(const_reference lhs, const_reference rhs) noexcept - { - return not (rhs < lhs); - } - - /*! - @brief comparison: less than or equal - @copydoc operator<=(const_reference, const_reference) - */ - template::value, int>::type = 0> - friend bool operator<=(const_reference lhs, const ScalarType rhs) noexcept - { - return (lhs <= basic_json(rhs)); - } - - /*! - @brief comparison: less than or equal - @copydoc operator<=(const_reference, const_reference) - */ - template::value, int>::type = 0> - friend bool operator<=(const ScalarType lhs, const_reference rhs) noexcept - { - return (basic_json(lhs) <= rhs); - } - - /*! - @brief comparison: greater than - - Compares whether one JSON value @a lhs is greater than another - JSON value by calculating `not (lhs <= rhs)`. - - @param[in] lhs first JSON value to consider - @param[in] rhs second JSON value to consider - @return whether @a lhs is greater than to @a rhs - - @complexity Linear. - - @liveexample{The example demonstrates comparing several JSON - types.,operator__lessequal} - - @since version 1.0.0 - */ - friend bool operator>(const_reference lhs, const_reference rhs) noexcept - { - return not (lhs <= rhs); - } - - /*! - @brief comparison: greater than - @copydoc operator>(const_reference, const_reference) - */ - template::value, int>::type = 0> - friend bool operator>(const_reference lhs, const ScalarType rhs) noexcept - { - return (lhs > basic_json(rhs)); - } - - /*! - @brief comparison: greater than - @copydoc operator>(const_reference, const_reference) - */ - template::value, int>::type = 0> - friend bool operator>(const ScalarType lhs, const_reference rhs) noexcept - { - return (basic_json(lhs) > rhs); - } - - /*! - @brief comparison: greater than or equal - - Compares whether one JSON value @a lhs is greater than or equal to another - JSON value by calculating `not (lhs < rhs)`. - - @param[in] lhs first JSON value to consider - @param[in] rhs second JSON value to consider - @return whether @a lhs is greater than or equal to @a rhs - - @complexity Linear. - - @liveexample{The example demonstrates comparing several JSON - types.,operator__greaterequal} - - @since version 1.0.0 - */ - friend bool operator>=(const_reference lhs, const_reference rhs) noexcept - { - return not (lhs < rhs); - } - - /*! - @brief comparison: greater than or equal - @copydoc operator>=(const_reference, const_reference) - */ - template::value, int>::type = 0> - friend bool operator>=(const_reference lhs, const ScalarType rhs) noexcept - { - return (lhs >= basic_json(rhs)); - } - - /*! - @brief comparison: greater than or equal - @copydoc operator>=(const_reference, const_reference) - */ - template::value, int>::type = 0> - friend bool operator>=(const ScalarType lhs, const_reference rhs) noexcept - { - return (basic_json(lhs) >= rhs); - } - - /// @} - - - /////////////////// - // serialization // - /////////////////// - - /// @name serialization - /// @{ - - private: - /*! - @brief wrapper around the serialization functions - */ - class serializer - { - private: - serializer(const serializer&) = delete; - serializer& operator=(const serializer&) = delete; - - public: - /*! - @param[in] s output stream to serialize to - */ - serializer(std::ostream& s) - : o(s), loc(std::localeconv()), - thousands_sep(!loc->thousands_sep ? '\0' : loc->thousands_sep[0]), - decimal_point(!loc->decimal_point ? '\0' : loc->decimal_point[0]) - {} - - /*! - @brief internal implementation of the serialization function - - This function is called by the public member function dump and - organizes the serialization internally. The indentation level is - propagated as additional parameter. In case of arrays and objects, the - function is called recursively. - - - strings and object keys are escaped using `escape_string()` - - integer numbers are converted implicitly via `operator<<` - - floating-point numbers are converted to a string using `"%g"` format - - @param[in] val value to serialize - @param[in] pretty_print whether the output shall be pretty-printed - @param[in] indent_step the indent level - @param[in] current_indent the current indent level (only used internally) - */ - void dump(const basic_json& val, - const bool pretty_print, - const unsigned int indent_step, - const unsigned int current_indent = 0) - { - switch (val.m_type) - { - case value_t::object: - { - if (val.m_value.object->empty()) - { - o.write("{}", 2); - return; - } - - if (pretty_print) - { - o.write("{\n", 2); - - // variable to hold indentation for recursive calls - const auto new_indent = current_indent + indent_step; - if (indent_string.size() < new_indent) - { - indent_string.resize(new_indent, ' '); - } - - // first n-1 elements - auto i = val.m_value.object->cbegin(); - for (size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i) - { - o.write(indent_string.c_str(), static_cast(new_indent)); - o.put('\"'); - dump_escaped(i->first); - o.write("\": ", 3); - dump(i->second, true, indent_step, new_indent); - o.write(",\n", 2); - } - - // last element - assert(i != val.m_value.object->cend()); - o.write(indent_string.c_str(), static_cast(new_indent)); - o.put('\"'); - dump_escaped(i->first); - o.write("\": ", 3); - dump(i->second, true, indent_step, new_indent); - - o.put('\n'); - o.write(indent_string.c_str(), static_cast(current_indent)); - o.put('}'); - } - else - { - o.put('{'); - - // first n-1 elements - auto i = val.m_value.object->cbegin(); - for (size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i) - { - o.put('\"'); - dump_escaped(i->first); - o.write("\":", 2); - dump(i->second, false, indent_step, current_indent); - o.put(','); - } - - // last element - assert(i != val.m_value.object->cend()); - o.put('\"'); - dump_escaped(i->first); - o.write("\":", 2); - dump(i->second, false, indent_step, current_indent); - - o.put('}'); - } - - return; - } - - case value_t::array: - { - if (val.m_value.array->empty()) - { - o.write("[]", 2); - return; - } - - if (pretty_print) - { - o.write("[\n", 2); - - // variable to hold indentation for recursive calls - const auto new_indent = current_indent + indent_step; - if (indent_string.size() < new_indent) - { - indent_string.resize(new_indent, ' '); - } - - // first n-1 elements - for (auto i = val.m_value.array->cbegin(); i != val.m_value.array->cend() - 1; ++i) - { - o.write(indent_string.c_str(), static_cast(new_indent)); - dump(*i, true, indent_step, new_indent); - o.write(",\n", 2); - } - - // last element - assert(not val.m_value.array->empty()); - o.write(indent_string.c_str(), static_cast(new_indent)); - dump(val.m_value.array->back(), true, indent_step, new_indent); - - o.put('\n'); - o.write(indent_string.c_str(), static_cast(current_indent)); - o.put(']'); - } - else - { - o.put('['); - - // first n-1 elements - for (auto i = val.m_value.array->cbegin(); i != val.m_value.array->cend() - 1; ++i) - { - dump(*i, false, indent_step, current_indent); - o.put(','); - } - - // last element - assert(not val.m_value.array->empty()); - dump(val.m_value.array->back(), false, indent_step, current_indent); - - o.put(']'); - } - - return; - } - - case value_t::string: - { - o.put('\"'); - dump_escaped(*val.m_value.string); - o.put('\"'); - return; - } - - case value_t::boolean: - { - if (val.m_value.boolean) - { - o.write("true", 4); - } - else - { - o.write("false", 5); - } - return; - } - - case value_t::number_integer: - { - dump_integer(val.m_value.number_integer); - return; - } - - case value_t::number_unsigned: - { - dump_integer(val.m_value.number_unsigned); - return; - } - - case value_t::number_float: - { - dump_float(val.m_value.number_float); - return; - } - - case value_t::discarded: - { - o.write("", 11); - return; - } - - case value_t::null: - { - o.write("null", 4); - return; - } - } - } - - private: - /*! - @brief calculates the extra space to escape a JSON string - - @param[in] s the string to escape - @return the number of characters required to escape string @a s - - @complexity Linear in the length of string @a s. - */ - static std::size_t extra_space(const string_t& s) noexcept - { - return std::accumulate(s.begin(), s.end(), size_t{}, - [](size_t res, typename string_t::value_type c) - { - switch (c) - { - case '"': - case '\\': - case '\b': - case '\f': - case '\n': - case '\r': - case '\t': - { - // from c (1 byte) to \x (2 bytes) - return res + 1; - } - - case 0x00: - case 0x01: - case 0x02: - case 0x03: - case 0x04: - case 0x05: - case 0x06: - case 0x07: - case 0x0b: - case 0x0e: - case 0x0f: - case 0x10: - case 0x11: - case 0x12: - case 0x13: - case 0x14: - case 0x15: - case 0x16: - case 0x17: - case 0x18: - case 0x19: - case 0x1a: - case 0x1b: - case 0x1c: - case 0x1d: - case 0x1e: - case 0x1f: - { - // from c (1 byte) to \uxxxx (6 bytes) - return res + 5; - } - - default: - { - return res; - } - } - }); - } - - /*! - @brief dump escaped string - - Escape a string by replacing certain special characters by a sequence - of an escape character (backslash) and another character and other - control characters by a sequence of "\u" followed by a four-digit hex - representation. The escaped string is written to output stream @a o. - - @param[in] s the string to escape - - @complexity Linear in the length of string @a s. - */ - void dump_escaped(const string_t& s) const - { - const auto space = extra_space(s); - if (space == 0) - { - o.write(s.c_str(), static_cast(s.size())); - return; - } - - // create a result string of necessary size - string_t result(s.size() + space, '\\'); - std::size_t pos = 0; - - for (const auto& c : s) - { - switch (c) - { - // quotation mark (0x22) - case '"': - { - result[pos + 1] = '"'; - pos += 2; - break; - } - - // reverse solidus (0x5c) - case '\\': - { - // nothing to change - pos += 2; - break; - } - - // backspace (0x08) - case '\b': - { - result[pos + 1] = 'b'; - pos += 2; - break; - } - - // formfeed (0x0c) - case '\f': - { - result[pos + 1] = 'f'; - pos += 2; - break; - } - - // newline (0x0a) - case '\n': - { - result[pos + 1] = 'n'; - pos += 2; - break; - } - - // carriage return (0x0d) - case '\r': - { - result[pos + 1] = 'r'; - pos += 2; - break; - } - - // horizontal tab (0x09) - case '\t': - { - result[pos + 1] = 't'; - pos += 2; - break; - } - - case 0x00: - case 0x01: - case 0x02: - case 0x03: - case 0x04: - case 0x05: - case 0x06: - case 0x07: - case 0x0b: - case 0x0e: - case 0x0f: - case 0x10: - case 0x11: - case 0x12: - case 0x13: - case 0x14: - case 0x15: - case 0x16: - case 0x17: - case 0x18: - case 0x19: - case 0x1a: - case 0x1b: - case 0x1c: - case 0x1d: - case 0x1e: - case 0x1f: - { - // convert a number 0..15 to its hex representation - // (0..f) - static const char hexify[16] = - { - '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' - }; - - // print character c as \uxxxx - for (const char m : - { 'u', '0', '0', hexify[c >> 4], hexify[c & 0x0f] - }) - { - result[++pos] = m; - } - - ++pos; - break; - } - - default: - { - // all other characters are added as-is - result[pos++] = c; - break; - } - } - } - - assert(pos == s.size() + space); - o.write(result.c_str(), static_cast(result.size())); - } - - /*! - @brief dump an integer - - Dump a given integer to output stream @a o. Works internally with - @a number_buffer. - - @param[in] x integer number (signed or unsigned) to dump - @tparam NumberType either @a number_integer_t or @a number_unsigned_t - */ - template::value or - std::is_same::value, int> = 0> - void dump_integer(NumberType x) - { - // special case for "0" - if (x == 0) - { - o.put('0'); - return; - } - - const bool is_negative = x < 0; - size_t i = 0; - - // spare 1 byte for '\0' - while (x != 0 and i < number_buffer.size() - 1) - { - const auto digit = std::labs(static_cast(x % 10)); - number_buffer[i++] = static_cast('0' + digit); - x /= 10; - } - - // make sure the number has been processed completely - assert(x == 0); - - if (is_negative) - { - // make sure there is capacity for the '-' - assert(i < number_buffer.size() - 2); - number_buffer[i++] = '-'; - } - - std::reverse(number_buffer.begin(), number_buffer.begin() + i); - o.write(number_buffer.data(), static_cast(i)); - } - - /*! - @brief dump a floating-point number - - Dump a given floating-point number to output stream @a o. Works - internally with @a number_buffer. - - @param[in] x floating-point number to dump - */ - void dump_float(number_float_t x) - { - // NaN / inf - if (not std::isfinite(x) or std::isnan(x)) - { - o.write("null", 4); - return; - } - - // special case for 0.0 and -0.0 - if (x == 0) - { - if (std::signbit(x)) - { - o.write("-0.0", 4); - } - else - { - o.write("0.0", 3); - } - return; - } - - // get number of digits for a text -> float -> text round-trip - static constexpr auto d = std::numeric_limits::digits10; - - // the actual conversion - std::ptrdiff_t len = snprintf(number_buffer.data(), number_buffer.size(), - "%.*g", d, x); - - // negative value indicates an error - assert(len > 0); - // check if buffer was large enough - assert(static_cast(len) < number_buffer.size()); - - // erase thousands separator - if (thousands_sep != '\0') - { - const auto end = std::remove(number_buffer.begin(), - number_buffer.begin() + len, - thousands_sep); - std::fill(end, number_buffer.end(), '\0'); - assert((end - number_buffer.begin()) <= len); - len = (end - number_buffer.begin()); - } - - // convert decimal point to '.' - if (decimal_point != '\0' and decimal_point != '.') - { - for (auto& c : number_buffer) - { - if (c == decimal_point) - { - c = '.'; - break; - } - } - } - - o.write(number_buffer.data(), static_cast(len)); - - // determine if need to append ".0" - const bool value_is_int_like = std::none_of(number_buffer.begin(), - number_buffer.begin() + len + 1, - [](char c) - { - return c == '.' or c == 'e'; - }); - - if (value_is_int_like) - { - o.write(".0", 2); - } - } - - private: - /// the output of the serializer - std::ostream& o; - - /// a (hopefully) large enough character buffer - std::array number_buffer{{}}; - - /// the locale - const std::lconv* loc = nullptr; - /// the locale's thousand separator character - const char thousands_sep = '\0'; - /// the locale's decimal point character - const char decimal_point = '\0'; - - /// the indentation string - string_t indent_string = string_t(512, ' '); - }; - - public: - /*! - @brief serialize to stream - - Serialize the given JSON value @a j to the output stream @a o. The JSON - value will be serialized using the @ref dump member function. The - indentation of the output can be controlled with the member variable - `width` of the output stream @a o. For instance, using the manipulator - `std::setw(4)` on @a o sets the indentation level to `4` and the - serialization result is the same as calling `dump(4)`. - - @param[in,out] o stream to serialize to - @param[in] j JSON value to serialize - - @return the stream @a o - - @complexity Linear. - - @liveexample{The example below shows the serialization with different - parameters to `width` to adjust the indentation level.,operator_serialize} - - @since version 1.0.0 - */ - friend std::ostream& operator<<(std::ostream& o, const basic_json& j) - { - // read width member and use it as indentation parameter if nonzero - const bool pretty_print = (o.width() > 0); - const auto indentation = (pretty_print ? o.width() : 0); - - // reset width to 0 for subsequent calls to this stream - o.width(0); - - // do the actual serialization - serializer s(o); - s.dump(j, pretty_print, static_cast(indentation)); - return o; - } - - /*! - @brief serialize to stream - @deprecated This stream operator is deprecated and will be removed in a - future version of the library. Please use - @ref std::ostream& operator<<(std::ostream&, const basic_json&) - instead; that is, replace calls like `j >> o;` with `o << j;`. - */ - JSON_DEPRECATED - friend std::ostream& operator>>(const basic_json& j, std::ostream& o) - { - return o << j; - } - - /// @} - - - ///////////////////// - // deserialization // - ///////////////////// - - /// @name deserialization - /// @{ - - /*! - @brief deserialize from an array - - This function reads from an array of 1-byte values. - - @pre Each element of the container has a size of 1 byte. Violating this - precondition yields undefined behavior. **This precondition is enforced - with a static assertion.** - - @param[in] array array to read from - @param[in] cb a parser callback function of type @ref parser_callback_t - which is used to control the deserialization by filtering unwanted values - (optional) - - @return result of the deserialization - - @throw parse_error.101 if a parse error occurs; example: `""unexpected end - of input; expected string literal""` - @throw parse_error.102 if to_unicode fails or surrogate error - @throw parse_error.103 if to_unicode fails - - @complexity Linear in the length of the input. The parser is a predictive - LL(1) parser. The complexity can be higher if the parser callback function - @a cb has a super-linear complexity. - - @note A UTF-8 byte order mark is silently ignored. - - @liveexample{The example below demonstrates the `parse()` function reading - from an array.,parse__array__parser_callback_t} - - @since version 2.0.3 - */ - template - static basic_json parse(T (&array)[N], - const parser_callback_t cb = nullptr) - { - // delegate the call to the iterator-range parse overload - return parse(std::begin(array), std::end(array), cb); - } - - /*! - @brief deserialize from string literal - - @tparam CharT character/literal type with size of 1 byte - @param[in] s string literal to read a serialized JSON value from - @param[in] cb a parser callback function of type @ref parser_callback_t - which is used to control the deserialization by filtering unwanted values - (optional) - - @return result of the deserialization - - @throw parse_error.101 in case of an unexpected token - @throw parse_error.102 if to_unicode fails or surrogate error - @throw parse_error.103 if to_unicode fails - - @complexity Linear in the length of the input. The parser is a predictive - LL(1) parser. The complexity can be higher if the parser callback function - @a cb has a super-linear complexity. - - @note A UTF-8 byte order mark is silently ignored. - @note String containers like `std::string` or @ref string_t can be parsed - with @ref parse(const ContiguousContainer&, const parser_callback_t) - - @liveexample{The example below demonstrates the `parse()` function with - and without callback function.,parse__string__parser_callback_t} - - @sa @ref parse(std::istream&, const parser_callback_t) for a version that - reads from an input stream - - @since version 1.0.0 (originally for @ref string_t) - */ - template::value and - std::is_integral::type>::value and - sizeof(typename std::remove_pointer::type) == 1, int>::type = 0> - static basic_json parse(const CharT s, - const parser_callback_t cb = nullptr) - { - return parser(reinterpret_cast(s), cb).parse(); - } - - /*! - @brief deserialize from stream - - @param[in,out] i stream to read a serialized JSON value from - @param[in] cb a parser callback function of type @ref parser_callback_t - which is used to control the deserialization by filtering unwanted values - (optional) - - @return result of the deserialization - - @throw parse_error.101 in case of an unexpected token - @throw parse_error.102 if to_unicode fails or surrogate error - @throw parse_error.103 if to_unicode fails - @throw parse_error.111 if input stream is in a bad state - - @complexity Linear in the length of the input. The parser is a predictive - LL(1) parser. The complexity can be higher if the parser callback function - @a cb has a super-linear complexity. - - @note A UTF-8 byte order mark is silently ignored. - - @liveexample{The example below demonstrates the `parse()` function with - and without callback function.,parse__istream__parser_callback_t} - - @sa @ref parse(const CharT, const parser_callback_t) for a version - that reads from a string - - @since version 1.0.0 - */ - static basic_json parse(std::istream& i, - const parser_callback_t cb = nullptr) - { - return parser(i, cb).parse(); - } - - /*! - @copydoc parse(std::istream&, const parser_callback_t) - */ - static basic_json parse(std::istream&& i, - const parser_callback_t cb = nullptr) - { - return parser(i, cb).parse(); - } - - /*! - @brief deserialize from an iterator range with contiguous storage - - This function reads from an iterator range of a container with contiguous - storage of 1-byte values. Compatible container types include - `std::vector`, `std::string`, `std::array`, `std::valarray`, and - `std::initializer_list`. Furthermore, C-style arrays can be used with - `std::begin()`/`std::end()`. User-defined containers can be used as long - as they implement random-access iterators and a contiguous storage. - - @pre The iterator range is contiguous. Violating this precondition yields - undefined behavior. **This precondition is enforced with an assertion.** - @pre Each element in the range has a size of 1 byte. Violating this - precondition yields undefined behavior. **This precondition is enforced - with a static assertion.** - - @warning There is no way to enforce all preconditions at compile-time. If - the function is called with noncompliant iterators and with - assertions switched off, the behavior is undefined and will most - likely yield segmentation violation. - - @tparam IteratorType iterator of container with contiguous storage - @param[in] first begin of the range to parse (included) - @param[in] last end of the range to parse (excluded) - @param[in] cb a parser callback function of type @ref parser_callback_t - which is used to control the deserialization by filtering unwanted values - (optional) - - @return result of the deserialization - - @throw parse_error.101 in case of an unexpected token - @throw parse_error.102 if to_unicode fails or surrogate error - @throw parse_error.103 if to_unicode fails - - @complexity Linear in the length of the input. The parser is a predictive - LL(1) parser. The complexity can be higher if the parser callback function - @a cb has a super-linear complexity. - - @note A UTF-8 byte order mark is silently ignored. - - @liveexample{The example below demonstrates the `parse()` function reading - from an iterator range.,parse__iteratortype__parser_callback_t} - - @since version 2.0.3 - */ - template::iterator_category>::value, int>::type = 0> - static basic_json parse(IteratorType first, IteratorType last, - const parser_callback_t cb = nullptr) - { - // assertion to check that the iterator range is indeed contiguous, - // see http://stackoverflow.com/a/35008842/266378 for more discussion - assert(std::accumulate(first, last, std::pair(true, 0), - [&first](std::pair res, decltype(*first) val) - { - res.first &= (val == *(std::next(std::addressof(*first), res.second++))); - return res; - }).first); - - // assertion to check that each element is 1 byte long - static_assert(sizeof(typename std::iterator_traits::value_type) == 1, - "each element in the iterator range must have the size of 1 byte"); - - // if iterator range is empty, create a parser with an empty string - // to generate "unexpected EOF" error message - if (std::distance(first, last) <= 0) - { - return parser("").parse(); - } - - return parser(first, last, cb).parse(); - } - - /*! - @brief deserialize from a container with contiguous storage - - This function reads from a container with contiguous storage of 1-byte - values. Compatible container types include `std::vector`, `std::string`, - `std::array`, and `std::initializer_list`. User-defined containers can be - used as long as they implement random-access iterators and a contiguous - storage. - - @pre The container storage is contiguous. Violating this precondition - yields undefined behavior. **This precondition is enforced with an - assertion.** - @pre Each element of the container has a size of 1 byte. Violating this - precondition yields undefined behavior. **This precondition is enforced - with a static assertion.** - - @warning There is no way to enforce all preconditions at compile-time. If - the function is called with a noncompliant container and with - assertions switched off, the behavior is undefined and will most - likely yield segmentation violation. - - @tparam ContiguousContainer container type with contiguous storage - @param[in] c container to read from - @param[in] cb a parser callback function of type @ref parser_callback_t - which is used to control the deserialization by filtering unwanted values - (optional) - - @return result of the deserialization - - @throw parse_error.101 in case of an unexpected token - @throw parse_error.102 if to_unicode fails or surrogate error - @throw parse_error.103 if to_unicode fails - - @complexity Linear in the length of the input. The parser is a predictive - LL(1) parser. The complexity can be higher if the parser callback function - @a cb has a super-linear complexity. - - @note A UTF-8 byte order mark is silently ignored. - - @liveexample{The example below demonstrates the `parse()` function reading - from a contiguous container.,parse__contiguouscontainer__parser_callback_t} - - @since version 2.0.3 - */ - template::value and - std::is_base_of< - std::random_access_iterator_tag, - typename std::iterator_traits()))>::iterator_category>::value - , int>::type = 0> - static basic_json parse(const ContiguousContainer& c, - const parser_callback_t cb = nullptr) - { - // delegate the call to the iterator-range parse overload - return parse(std::begin(c), std::end(c), cb); - } - - /*! - @brief deserialize from stream - @deprecated This stream operator is deprecated and will be removed in a - future version of the library. Please use - @ref std::istream& operator>>(std::istream&, basic_json&) - instead; that is, replace calls like `j << i;` with `i >> j;`. - */ - JSON_DEPRECATED - friend std::istream& operator<<(basic_json& j, std::istream& i) - { - j = parser(i).parse(); - return i; - } - - /*! - @brief deserialize from stream - - Deserializes an input stream to a JSON value. - - @param[in,out] i input stream to read a serialized JSON value from - @param[in,out] j JSON value to write the deserialized input to - - @throw parse_error.101 in case of an unexpected token - @throw parse_error.102 if to_unicode fails or surrogate error - @throw parse_error.103 if to_unicode fails - @throw parse_error.111 if input stream is in a bad state - - @complexity Linear in the length of the input. The parser is a predictive - LL(1) parser. - - @note A UTF-8 byte order mark is silently ignored. - - @liveexample{The example below shows how a JSON value is constructed by - reading a serialization from a stream.,operator_deserialize} - - @sa parse(std::istream&, const parser_callback_t) for a variant with a - parser callback function to filter values while parsing - - @since version 1.0.0 - */ - friend std::istream& operator>>(std::istream& i, basic_json& j) - { - j = parser(i).parse(); - return i; - } - - /// @} - - ////////////////////////////////////////// - // binary serialization/deserialization // - ////////////////////////////////////////// - - /// @name binary serialization/deserialization support - /// @{ - - private: - /*! - @note Some code in the switch cases has been copied, because otherwise - copilers would complain about implicit fallthrough and there is no - portable attribute to mute such warnings. - */ - template - static void add_to_vector(std::vector& vec, size_t bytes, const T number) - { - assert(bytes == 1 or bytes == 2 or bytes == 4 or bytes == 8); - - switch (bytes) - { - case 8: - { - vec.push_back(static_cast((static_cast(number) >> 070) & 0xff)); - vec.push_back(static_cast((static_cast(number) >> 060) & 0xff)); - vec.push_back(static_cast((static_cast(number) >> 050) & 0xff)); - vec.push_back(static_cast((static_cast(number) >> 040) & 0xff)); - vec.push_back(static_cast((number >> 030) & 0xff)); - vec.push_back(static_cast((number >> 020) & 0xff)); - vec.push_back(static_cast((number >> 010) & 0xff)); - vec.push_back(static_cast(number & 0xff)); - break; - } - - case 4: - { - vec.push_back(static_cast((number >> 030) & 0xff)); - vec.push_back(static_cast((number >> 020) & 0xff)); - vec.push_back(static_cast((number >> 010) & 0xff)); - vec.push_back(static_cast(number & 0xff)); - break; - } - - case 2: - { - vec.push_back(static_cast((number >> 010) & 0xff)); - vec.push_back(static_cast(number & 0xff)); - break; - } - - case 1: - { - vec.push_back(static_cast(number & 0xff)); - break; - } - } - } - - /*! - @brief take sufficient bytes from a vector to fill an integer variable - - In the context of binary serialization formats, we need to read several - bytes from a byte vector and combine them to multi-byte integral data - types. - - @param[in] vec byte vector to read from - @param[in] current_index the position in the vector after which to read - - @return the next sizeof(T) bytes from @a vec, in reverse order as T - - @tparam T the integral return type - - @throw parse_error.110 if there are less than sizeof(T)+1 bytes in the - vector @a vec to read - - In the for loop, the bytes from the vector are copied in reverse order into - the return value. In the figures below, let sizeof(T)=4 and `i` be the loop - variable. - - Precondition: - - vec: | | | a | b | c | d | T: | | | | | - ^ ^ ^ ^ - current_index i ptr sizeof(T) - - Postcondition: - - vec: | | | a | b | c | d | T: | d | c | b | a | - ^ ^ ^ - | i ptr - current_index - - @sa Code adapted from . - */ - template - static T get_from_vector(const std::vector& vec, const size_t current_index) - { - // check if we can read sizeof(T) bytes starting the next index - check_length(vec.size(), sizeof(T), current_index + 1); - - T result; - auto* ptr = reinterpret_cast(&result); - for (size_t i = 0; i < sizeof(T); ++i) - { - *ptr++ = vec[current_index + sizeof(T) - i]; - } - return result; - } - - /*! - @brief create a MessagePack serialization of a given JSON value - - This is a straightforward implementation of the MessagePack specification. - - @param[in] j JSON value to serialize - @param[in,out] v byte vector to write the serialization to - - @sa https://github.com/msgpack/msgpack/blob/master/spec.md - */ - static void to_msgpack_internal(const basic_json& j, std::vector& v) - { - switch (j.type()) - { - case value_t::null: - { - // nil - v.push_back(0xc0); - break; - } - - case value_t::boolean: - { - // true and false - v.push_back(j.m_value.boolean ? 0xc3 : 0xc2); - break; - } - - case value_t::number_integer: - { - if (j.m_value.number_integer >= 0) - { - // MessagePack does not differentiate between positive - // signed integers and unsigned integers. Therefore, we - // used the code from the value_t::number_unsigned case - // here. - if (j.m_value.number_unsigned < 128) - { - // positive fixnum - add_to_vector(v, 1, j.m_value.number_unsigned); - } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - // uint 8 - v.push_back(0xcc); - add_to_vector(v, 1, j.m_value.number_unsigned); - } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - // uint 16 - v.push_back(0xcd); - add_to_vector(v, 2, j.m_value.number_unsigned); - } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - // uint 32 - v.push_back(0xce); - add_to_vector(v, 4, j.m_value.number_unsigned); - } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - // uint 64 - v.push_back(0xcf); - add_to_vector(v, 8, j.m_value.number_unsigned); - } - } - else - { - if (j.m_value.number_integer >= -32) - { - // negative fixnum - add_to_vector(v, 1, j.m_value.number_integer); - } - else if (j.m_value.number_integer >= (std::numeric_limits::min)() and j.m_value.number_integer <= (std::numeric_limits::max)()) - { - // int 8 - v.push_back(0xd0); - add_to_vector(v, 1, j.m_value.number_integer); - } - else if (j.m_value.number_integer >= (std::numeric_limits::min)() and j.m_value.number_integer <= (std::numeric_limits::max)()) - { - // int 16 - v.push_back(0xd1); - add_to_vector(v, 2, j.m_value.number_integer); - } - else if (j.m_value.number_integer >= (std::numeric_limits::min)() and j.m_value.number_integer <= (std::numeric_limits::max)()) - { - // int 32 - v.push_back(0xd2); - add_to_vector(v, 4, j.m_value.number_integer); - } - else if (j.m_value.number_integer >= (std::numeric_limits::min)() and j.m_value.number_integer <= (std::numeric_limits::max)()) - { - // int 64 - v.push_back(0xd3); - add_to_vector(v, 8, j.m_value.number_integer); - } - } - break; - } - - case value_t::number_unsigned: - { - if (j.m_value.number_unsigned < 128) - { - // positive fixnum - add_to_vector(v, 1, j.m_value.number_unsigned); - } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - // uint 8 - v.push_back(0xcc); - add_to_vector(v, 1, j.m_value.number_unsigned); - } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - // uint 16 - v.push_back(0xcd); - add_to_vector(v, 2, j.m_value.number_unsigned); - } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - // uint 32 - v.push_back(0xce); - add_to_vector(v, 4, j.m_value.number_unsigned); - } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - // uint 64 - v.push_back(0xcf); - add_to_vector(v, 8, j.m_value.number_unsigned); - } - break; - } - - case value_t::number_float: - { - // float 64 - v.push_back(0xcb); - const auto* helper = reinterpret_cast(&(j.m_value.number_float)); - for (size_t i = 0; i < 8; ++i) - { - v.push_back(helper[7 - i]); - } - break; - } - - case value_t::string: - { - const auto N = j.m_value.string->size(); - if (N <= 31) - { - // fixstr - v.push_back(static_cast(0xa0 | N)); - } - else if (N <= 255) - { - // str 8 - v.push_back(0xd9); - add_to_vector(v, 1, N); - } - else if (N <= 65535) - { - // str 16 - v.push_back(0xda); - add_to_vector(v, 2, N); - } - else if (N <= 4294967295) - { - // str 32 - v.push_back(0xdb); - add_to_vector(v, 4, N); - } - - // append string - std::copy(j.m_value.string->begin(), j.m_value.string->end(), - std::back_inserter(v)); - break; - } - - case value_t::array: - { - const auto N = j.m_value.array->size(); - if (N <= 15) - { - // fixarray - v.push_back(static_cast(0x90 | N)); - } - else if (N <= 0xffff) - { - // array 16 - v.push_back(0xdc); - add_to_vector(v, 2, N); - } - else if (N <= 0xffffffff) - { - // array 32 - v.push_back(0xdd); - add_to_vector(v, 4, N); - } - - // append each element - for (const auto& el : *j.m_value.array) - { - to_msgpack_internal(el, v); - } - break; - } - - case value_t::object: - { - const auto N = j.m_value.object->size(); - if (N <= 15) - { - // fixmap - v.push_back(static_cast(0x80 | (N & 0xf))); - } - else if (N <= 65535) - { - // map 16 - v.push_back(0xde); - add_to_vector(v, 2, N); - } - else if (N <= 4294967295) - { - // map 32 - v.push_back(0xdf); - add_to_vector(v, 4, N); - } - - // append each element - for (const auto& el : *j.m_value.object) - { - to_msgpack_internal(el.first, v); - to_msgpack_internal(el.second, v); - } - break; - } - - default: - { - break; - } - } - } - - /*! - @brief create a CBOR serialization of a given JSON value - - This is a straightforward implementation of the CBOR specification. - - @param[in] j JSON value to serialize - @param[in,out] v byte vector to write the serialization to - - @sa https://tools.ietf.org/html/rfc7049 - */ - static void to_cbor_internal(const basic_json& j, std::vector& v) - { - switch (j.type()) - { - case value_t::null: - { - v.push_back(0xf6); - break; - } - - case value_t::boolean: - { - v.push_back(j.m_value.boolean ? 0xf5 : 0xf4); - break; - } - - case value_t::number_integer: - { - if (j.m_value.number_integer >= 0) - { - // CBOR does not differentiate between positive signed - // integers and unsigned integers. Therefore, we used the - // code from the value_t::number_unsigned case here. - if (j.m_value.number_integer <= 0x17) - { - add_to_vector(v, 1, j.m_value.number_integer); - } - else if (j.m_value.number_integer <= (std::numeric_limits::max)()) - { - v.push_back(0x18); - // one-byte uint8_t - add_to_vector(v, 1, j.m_value.number_integer); - } - else if (j.m_value.number_integer <= (std::numeric_limits::max)()) - { - v.push_back(0x19); - // two-byte uint16_t - add_to_vector(v, 2, j.m_value.number_integer); - } - else if (j.m_value.number_integer <= (std::numeric_limits::max)()) - { - v.push_back(0x1a); - // four-byte uint32_t - add_to_vector(v, 4, j.m_value.number_integer); - } - else - { - v.push_back(0x1b); - // eight-byte uint64_t - add_to_vector(v, 8, j.m_value.number_integer); - } - } - else - { - // The conversions below encode the sign in the first - // byte, and the value is converted to a positive number. - const auto positive_number = -1 - j.m_value.number_integer; - if (j.m_value.number_integer >= -24) - { - v.push_back(static_cast(0x20 + positive_number)); - } - else if (positive_number <= (std::numeric_limits::max)()) - { - // int 8 - v.push_back(0x38); - add_to_vector(v, 1, positive_number); - } - else if (positive_number <= (std::numeric_limits::max)()) - { - // int 16 - v.push_back(0x39); - add_to_vector(v, 2, positive_number); - } - else if (positive_number <= (std::numeric_limits::max)()) - { - // int 32 - v.push_back(0x3a); - add_to_vector(v, 4, positive_number); - } - else - { - // int 64 - v.push_back(0x3b); - add_to_vector(v, 8, positive_number); - } - } - break; - } - - case value_t::number_unsigned: - { - if (j.m_value.number_unsigned <= 0x17) - { - v.push_back(static_cast(j.m_value.number_unsigned)); - } - else if (j.m_value.number_unsigned <= 0xff) - { - v.push_back(0x18); - // one-byte uint8_t - add_to_vector(v, 1, j.m_value.number_unsigned); - } - else if (j.m_value.number_unsigned <= 0xffff) - { - v.push_back(0x19); - // two-byte uint16_t - add_to_vector(v, 2, j.m_value.number_unsigned); - } - else if (j.m_value.number_unsigned <= 0xffffffff) - { - v.push_back(0x1a); - // four-byte uint32_t - add_to_vector(v, 4, j.m_value.number_unsigned); - } - else if (j.m_value.number_unsigned <= 0xffffffffffffffff) - { - v.push_back(0x1b); - // eight-byte uint64_t - add_to_vector(v, 8, j.m_value.number_unsigned); - } - break; - } - - case value_t::number_float: - { - // Double-Precision Float - v.push_back(0xfb); - const auto* helper = reinterpret_cast(&(j.m_value.number_float)); - for (size_t i = 0; i < 8; ++i) - { - v.push_back(helper[7 - i]); - } - break; - } - - case value_t::string: - { - const auto N = j.m_value.string->size(); - if (N <= 0x17) - { - v.push_back(static_cast(0x60 + N)); // 1 byte for string + size - } - else if (N <= 0xff) - { - v.push_back(0x78); // one-byte uint8_t for N - add_to_vector(v, 1, N); - } - else if (N <= 0xffff) - { - v.push_back(0x79); // two-byte uint16_t for N - add_to_vector(v, 2, N); - } - else if (N <= 0xffffffff) - { - v.push_back(0x7a); // four-byte uint32_t for N - add_to_vector(v, 4, N); - } - // LCOV_EXCL_START - else if (N <= 0xffffffffffffffff) - { - v.push_back(0x7b); // eight-byte uint64_t for N - add_to_vector(v, 8, N); - } - // LCOV_EXCL_STOP - - // append string - std::copy(j.m_value.string->begin(), j.m_value.string->end(), - std::back_inserter(v)); - break; - } - - case value_t::array: - { - const auto N = j.m_value.array->size(); - if (N <= 0x17) - { - v.push_back(static_cast(0x80 + N)); // 1 byte for array + size - } - else if (N <= 0xff) - { - v.push_back(0x98); // one-byte uint8_t for N - add_to_vector(v, 1, N); - } - else if (N <= 0xffff) - { - v.push_back(0x99); // two-byte uint16_t for N - add_to_vector(v, 2, N); - } - else if (N <= 0xffffffff) - { - v.push_back(0x9a); // four-byte uint32_t for N - add_to_vector(v, 4, N); - } - // LCOV_EXCL_START - else if (N <= 0xffffffffffffffff) - { - v.push_back(0x9b); // eight-byte uint64_t for N - add_to_vector(v, 8, N); - } - // LCOV_EXCL_STOP - - // append each element - for (const auto& el : *j.m_value.array) - { - to_cbor_internal(el, v); - } - break; - } - - case value_t::object: - { - const auto N = j.m_value.object->size(); - if (N <= 0x17) - { - v.push_back(static_cast(0xa0 + N)); // 1 byte for object + size - } - else if (N <= 0xff) - { - v.push_back(0xb8); - add_to_vector(v, 1, N); // one-byte uint8_t for N - } - else if (N <= 0xffff) - { - v.push_back(0xb9); - add_to_vector(v, 2, N); // two-byte uint16_t for N - } - else if (N <= 0xffffffff) - { - v.push_back(0xba); - add_to_vector(v, 4, N); // four-byte uint32_t for N - } - // LCOV_EXCL_START - else if (N <= 0xffffffffffffffff) - { - v.push_back(0xbb); - add_to_vector(v, 8, N); // eight-byte uint64_t for N - } - // LCOV_EXCL_STOP - - // append each element - for (const auto& el : *j.m_value.object) - { - to_cbor_internal(el.first, v); - to_cbor_internal(el.second, v); - } - break; - } - - default: - { - break; - } - } - } - - - /* - @brief checks if given lengths do not exceed the size of a given vector - - To secure the access to the byte vector during CBOR/MessagePack - deserialization, bytes are copied from the vector into buffers. This - function checks if the number of bytes to copy (@a len) does not exceed - the size @s size of the vector. Additionally, an @a offset is given from - where to start reading the bytes. - - This function checks whether reading the bytes is safe; that is, offset is - a valid index in the vector, offset+len - - @param[in] size size of the byte vector - @param[in] len number of bytes to read - @param[in] offset offset where to start reading - - vec: x x x x x X X X X X - ^ ^ ^ - 0 offset len - - @throws out_of_range if `len > v.size()` - */ - static void check_length(const size_t size, const size_t len, const size_t offset) - { - // simple case: requested length is greater than the vector's length - if (len > size or offset > size) - { - JSON_THROW(parse_error::create(110, offset + 1, "cannot read " + std::to_string(len) + " bytes from vector")); - } - - // second case: adding offset would result in overflow - if ((size > ((std::numeric_limits::max)() - offset))) - { - JSON_THROW(parse_error::create(110, offset + 1, "cannot read " + std::to_string(len) + " bytes from vector")); - } - - // last case: reading past the end of the vector - if (len + offset > size) - { - JSON_THROW(parse_error::create(110, offset + 1, "cannot read " + std::to_string(len) + " bytes from vector")); - } - } - - /*! - @brief check if the next byte belongs to a string - - While parsing a map, the keys must be strings. This function checks if the - current byte is one of the start bytes for a string in MessagePack: - - - 0xa0 - 0xbf: fixstr - - 0xd9: str 8 - - 0xda: str 16 - - 0xdb: str 32 - - @param[in] v MessagePack serialization - @param[in] idx byte index in @a v to check for a string - - @throw parse_error.113 if `v[idx]` does not belong to a string - */ - static void msgpack_expect_string(const std::vector& v, size_t idx) - { - check_length(v.size(), 1, idx); - - const auto byte = v[idx]; - if ((byte >= 0xa0 and byte <= 0xbf) or (byte >= 0xd9 and byte <= 0xdb)) - { - return; - } - - std::stringstream ss; - ss << std::hex << static_cast(v[idx]); - JSON_THROW(parse_error::create(113, idx + 1, "expected a MessagePack string; last byte: 0x" + ss.str())); - } - - /*! - @brief check if the next byte belongs to a string - - While parsing a map, the keys must be strings. This function checks if the - current byte is one of the start bytes for a string in CBOR: - - - 0x60 - 0x77: fixed length - - 0x78 - 0x7b: variable length - - 0x7f: indefinity length - - @param[in] v CBOR serialization - @param[in] idx byte index in @a v to check for a string - - @throw parse_error.113 if `v[idx]` does not belong to a string - */ - static void cbor_expect_string(const std::vector& v, size_t idx) - { - check_length(v.size(), 1, idx); - - const auto byte = v[idx]; - if ((byte >= 0x60 and byte <= 0x7b) or byte == 0x7f) - { - return; - } - - std::stringstream ss; - ss << std::hex << static_cast(v[idx]); - JSON_THROW(parse_error::create(113, idx + 1, "expected a CBOR string; last byte: 0x" + ss.str())); - } - - /*! - @brief create a JSON value from a given MessagePack vector - - @param[in] v MessagePack serialization - @param[in] idx byte index to start reading from @a v - - @return deserialized JSON value - - @throw parse_error.110 if the given vector ends prematurely - @throw parse_error.112 if unsupported features from MessagePack were - used in the given vector @a v or if the input is not valid MessagePack - @throw parse_error.113 if a string was expected as map key, but not found - - @sa https://github.com/msgpack/msgpack/blob/master/spec.md - */ - static basic_json from_msgpack_internal(const std::vector& v, size_t& idx) - { - // store and increment index - const size_t current_idx = idx++; - - // make sure reading 1 byte is safe - check_length(v.size(), 1, current_idx); - - if (v[current_idx] <= 0xbf) - { - if (v[current_idx] <= 0x7f) // positive fixint - { - return v[current_idx]; - } - if (v[current_idx] <= 0x8f) // fixmap - { - basic_json result = value_t::object; - const size_t len = v[current_idx] & 0x0f; - for (size_t i = 0; i < len; ++i) - { - msgpack_expect_string(v, idx); - std::string key = from_msgpack_internal(v, idx); - result[key] = from_msgpack_internal(v, idx); - } - return result; - } - else if (v[current_idx] <= 0x9f) // fixarray - { - basic_json result = value_t::array; - const size_t len = v[current_idx] & 0x0f; - for (size_t i = 0; i < len; ++i) - { - result.push_back(from_msgpack_internal(v, idx)); - } - return result; - } - else // fixstr - { - const size_t len = v[current_idx] & 0x1f; - const size_t offset = current_idx + 1; - idx += len; // skip content bytes - check_length(v.size(), len, offset); - return std::string(reinterpret_cast(v.data()) + offset, len); - } - } - else if (v[current_idx] >= 0xe0) // negative fixint - { - return static_cast(v[current_idx]); - } - else - { - switch (v[current_idx]) - { - case 0xc0: // nil - { - return value_t::null; - } - - case 0xc2: // false - { - return false; - } - - case 0xc3: // true - { - return true; - } - - case 0xca: // float 32 - { - // copy bytes in reverse order into the double variable - float res; - check_length(v.size(), sizeof(float), current_idx + 1); - for (size_t byte = 0; byte < sizeof(float); ++byte) - { - reinterpret_cast(&res)[sizeof(float) - byte - 1] = v[current_idx + 1 + byte]; - } - idx += sizeof(float); // skip content bytes - return res; - } - - case 0xcb: // float 64 - { - // copy bytes in reverse order into the double variable - double res; - check_length(v.size(), sizeof(double), current_idx + 1); - for (size_t byte = 0; byte < sizeof(double); ++byte) - { - reinterpret_cast(&res)[sizeof(double) - byte - 1] = v[current_idx + 1 + byte]; - } - idx += sizeof(double); // skip content bytes - return res; - } - - case 0xcc: // uint 8 - { - idx += 1; // skip content byte - return get_from_vector(v, current_idx); - } - - case 0xcd: // uint 16 - { - idx += 2; // skip 2 content bytes - return get_from_vector(v, current_idx); - } - - case 0xce: // uint 32 - { - idx += 4; // skip 4 content bytes - return get_from_vector(v, current_idx); - } - - case 0xcf: // uint 64 - { - idx += 8; // skip 8 content bytes - return get_from_vector(v, current_idx); - } - - case 0xd0: // int 8 - { - idx += 1; // skip content byte - return get_from_vector(v, current_idx); - } - - case 0xd1: // int 16 - { - idx += 2; // skip 2 content bytes - return get_from_vector(v, current_idx); - } - - case 0xd2: // int 32 - { - idx += 4; // skip 4 content bytes - return get_from_vector(v, current_idx); - } - - case 0xd3: // int 64 - { - idx += 8; // skip 8 content bytes - return get_from_vector(v, current_idx); - } - - case 0xd9: // str 8 - { - const auto len = static_cast(get_from_vector(v, current_idx)); - const size_t offset = current_idx + 2; - idx += len + 1; // skip size byte + content bytes - check_length(v.size(), len, offset); - return std::string(reinterpret_cast(v.data()) + offset, len); - } - - case 0xda: // str 16 - { - const auto len = static_cast(get_from_vector(v, current_idx)); - const size_t offset = current_idx + 3; - idx += len + 2; // skip 2 size bytes + content bytes - check_length(v.size(), len, offset); - return std::string(reinterpret_cast(v.data()) + offset, len); - } - - case 0xdb: // str 32 - { - const auto len = static_cast(get_from_vector(v, current_idx)); - const size_t offset = current_idx + 5; - idx += len + 4; // skip 4 size bytes + content bytes - check_length(v.size(), len, offset); - return std::string(reinterpret_cast(v.data()) + offset, len); - } - - case 0xdc: // array 16 - { - basic_json result = value_t::array; - const auto len = static_cast(get_from_vector(v, current_idx)); - idx += 2; // skip 2 size bytes - for (size_t i = 0; i < len; ++i) - { - result.push_back(from_msgpack_internal(v, idx)); - } - return result; - } - - case 0xdd: // array 32 - { - basic_json result = value_t::array; - const auto len = static_cast(get_from_vector(v, current_idx)); - idx += 4; // skip 4 size bytes - for (size_t i = 0; i < len; ++i) - { - result.push_back(from_msgpack_internal(v, idx)); - } - return result; - } - - case 0xde: // map 16 - { - basic_json result = value_t::object; - const auto len = static_cast(get_from_vector(v, current_idx)); - idx += 2; // skip 2 size bytes - for (size_t i = 0; i < len; ++i) - { - msgpack_expect_string(v, idx); - std::string key = from_msgpack_internal(v, idx); - result[key] = from_msgpack_internal(v, idx); - } - return result; - } - - case 0xdf: // map 32 - { - basic_json result = value_t::object; - const auto len = static_cast(get_from_vector(v, current_idx)); - idx += 4; // skip 4 size bytes - for (size_t i = 0; i < len; ++i) - { - msgpack_expect_string(v, idx); - std::string key = from_msgpack_internal(v, idx); - result[key] = from_msgpack_internal(v, idx); - } - return result; - } - - default: - { - std::stringstream ss; - ss << std::hex << static_cast(v[current_idx]); - JSON_THROW(parse_error::create(112, current_idx + 1, "error reading MessagePack; last byte: 0x" + ss.str())); - } - } - } - } - - /*! - @brief create a JSON value from a given CBOR vector - - @param[in] v CBOR serialization - @param[in] idx byte index to start reading from @a v - - @return deserialized JSON value - - @throw parse_error.110 if the given vector ends prematurely - @throw parse_error.112 if unsupported features from CBOR were - used in the given vector @a v or if the input is not valid CBOR - @throw parse_error.113 if a string was expected as map key, but not found - - @sa https://tools.ietf.org/html/rfc7049 - */ - static basic_json from_cbor_internal(const std::vector& v, size_t& idx) - { - // store and increment index - const size_t current_idx = idx++; - - // make sure reading 1 byte is safe - check_length(v.size(), 1, current_idx); - - switch (v[current_idx]) - { - // Integer 0x00..0x17 (0..23) - case 0x00: - case 0x01: - case 0x02: - case 0x03: - case 0x04: - case 0x05: - case 0x06: - case 0x07: - case 0x08: - case 0x09: - case 0x0a: - case 0x0b: - case 0x0c: - case 0x0d: - case 0x0e: - case 0x0f: - case 0x10: - case 0x11: - case 0x12: - case 0x13: - case 0x14: - case 0x15: - case 0x16: - case 0x17: - { - return v[current_idx]; - } - - case 0x18: // Unsigned integer (one-byte uint8_t follows) - { - idx += 1; // skip content byte - return get_from_vector(v, current_idx); - } - - case 0x19: // Unsigned integer (two-byte uint16_t follows) - { - idx += 2; // skip 2 content bytes - return get_from_vector(v, current_idx); - } - - case 0x1a: // Unsigned integer (four-byte uint32_t follows) - { - idx += 4; // skip 4 content bytes - return get_from_vector(v, current_idx); - } - - case 0x1b: // Unsigned integer (eight-byte uint64_t follows) - { - idx += 8; // skip 8 content bytes - return get_from_vector(v, current_idx); - } - - // Negative integer -1-0x00..-1-0x17 (-1..-24) - case 0x20: - case 0x21: - case 0x22: - case 0x23: - case 0x24: - case 0x25: - case 0x26: - case 0x27: - case 0x28: - case 0x29: - case 0x2a: - case 0x2b: - case 0x2c: - case 0x2d: - case 0x2e: - case 0x2f: - case 0x30: - case 0x31: - case 0x32: - case 0x33: - case 0x34: - case 0x35: - case 0x36: - case 0x37: - { - return static_cast(0x20 - 1 - v[current_idx]); - } - - case 0x38: // Negative integer (one-byte uint8_t follows) - { - idx += 1; // skip content byte - // must be uint8_t ! - return static_cast(-1) - get_from_vector(v, current_idx); - } - - case 0x39: // Negative integer -1-n (two-byte uint16_t follows) - { - idx += 2; // skip 2 content bytes - return static_cast(-1) - get_from_vector(v, current_idx); - } - - case 0x3a: // Negative integer -1-n (four-byte uint32_t follows) - { - idx += 4; // skip 4 content bytes - return static_cast(-1) - get_from_vector(v, current_idx); - } - - case 0x3b: // Negative integer -1-n (eight-byte uint64_t follows) - { - idx += 8; // skip 8 content bytes - return static_cast(-1) - static_cast(get_from_vector(v, current_idx)); - } - - // UTF-8 string (0x00..0x17 bytes follow) - case 0x60: - case 0x61: - case 0x62: - case 0x63: - case 0x64: - case 0x65: - case 0x66: - case 0x67: - case 0x68: - case 0x69: - case 0x6a: - case 0x6b: - case 0x6c: - case 0x6d: - case 0x6e: - case 0x6f: - case 0x70: - case 0x71: - case 0x72: - case 0x73: - case 0x74: - case 0x75: - case 0x76: - case 0x77: - { - const auto len = static_cast(v[current_idx] - 0x60); - const size_t offset = current_idx + 1; - idx += len; // skip content bytes - check_length(v.size(), len, offset); - return std::string(reinterpret_cast(v.data()) + offset, len); - } - - case 0x78: // UTF-8 string (one-byte uint8_t for n follows) - { - const auto len = static_cast(get_from_vector(v, current_idx)); - const size_t offset = current_idx + 2; - idx += len + 1; // skip size byte + content bytes - check_length(v.size(), len, offset); - return std::string(reinterpret_cast(v.data()) + offset, len); - } - - case 0x79: // UTF-8 string (two-byte uint16_t for n follow) - { - const auto len = static_cast(get_from_vector(v, current_idx)); - const size_t offset = current_idx + 3; - idx += len + 2; // skip 2 size bytes + content bytes - check_length(v.size(), len, offset); - return std::string(reinterpret_cast(v.data()) + offset, len); - } - - case 0x7a: // UTF-8 string (four-byte uint32_t for n follow) - { - const auto len = static_cast(get_from_vector(v, current_idx)); - const size_t offset = current_idx + 5; - idx += len + 4; // skip 4 size bytes + content bytes - check_length(v.size(), len, offset); - return std::string(reinterpret_cast(v.data()) + offset, len); - } - - case 0x7b: // UTF-8 string (eight-byte uint64_t for n follow) - { - const auto len = static_cast(get_from_vector(v, current_idx)); - const size_t offset = current_idx + 9; - idx += len + 8; // skip 8 size bytes + content bytes - check_length(v.size(), len, offset); - return std::string(reinterpret_cast(v.data()) + offset, len); - } - - case 0x7f: // UTF-8 string (indefinite length) - { - std::string result; - while (static_cast(check_length(v.size(), 1, idx)), v[idx] != 0xff) - { - string_t s = from_cbor_internal(v, idx); - result += s; - } - // skip break byte (0xFF) - idx += 1; - return result; - } - - // array (0x00..0x17 data items follow) - case 0x80: - case 0x81: - case 0x82: - case 0x83: - case 0x84: - case 0x85: - case 0x86: - case 0x87: - case 0x88: - case 0x89: - case 0x8a: - case 0x8b: - case 0x8c: - case 0x8d: - case 0x8e: - case 0x8f: - case 0x90: - case 0x91: - case 0x92: - case 0x93: - case 0x94: - case 0x95: - case 0x96: - case 0x97: - { - basic_json result = value_t::array; - const auto len = static_cast(v[current_idx] - 0x80); - for (size_t i = 0; i < len; ++i) - { - result.push_back(from_cbor_internal(v, idx)); - } - return result; - } - - case 0x98: // array (one-byte uint8_t for n follows) - { - basic_json result = value_t::array; - const auto len = static_cast(get_from_vector(v, current_idx)); - idx += 1; // skip 1 size byte - for (size_t i = 0; i < len; ++i) - { - result.push_back(from_cbor_internal(v, idx)); - } - return result; - } - - case 0x99: // array (two-byte uint16_t for n follow) - { - basic_json result = value_t::array; - const auto len = static_cast(get_from_vector(v, current_idx)); - idx += 2; // skip 4 size bytes - for (size_t i = 0; i < len; ++i) - { - result.push_back(from_cbor_internal(v, idx)); - } - return result; - } - - case 0x9a: // array (four-byte uint32_t for n follow) - { - basic_json result = value_t::array; - const auto len = static_cast(get_from_vector(v, current_idx)); - idx += 4; // skip 4 size bytes - for (size_t i = 0; i < len; ++i) - { - result.push_back(from_cbor_internal(v, idx)); - } - return result; - } - - case 0x9b: // array (eight-byte uint64_t for n follow) - { - basic_json result = value_t::array; - const auto len = static_cast(get_from_vector(v, current_idx)); - idx += 8; // skip 8 size bytes - for (size_t i = 0; i < len; ++i) - { - result.push_back(from_cbor_internal(v, idx)); - } - return result; - } - - case 0x9f: // array (indefinite length) - { - basic_json result = value_t::array; - while (static_cast(check_length(v.size(), 1, idx)), v[idx] != 0xff) - { - result.push_back(from_cbor_internal(v, idx)); - } - // skip break byte (0xFF) - idx += 1; - return result; - } - - // map (0x00..0x17 pairs of data items follow) - case 0xa0: - case 0xa1: - case 0xa2: - case 0xa3: - case 0xa4: - case 0xa5: - case 0xa6: - case 0xa7: - case 0xa8: - case 0xa9: - case 0xaa: - case 0xab: - case 0xac: - case 0xad: - case 0xae: - case 0xaf: - case 0xb0: - case 0xb1: - case 0xb2: - case 0xb3: - case 0xb4: - case 0xb5: - case 0xb6: - case 0xb7: - { - basic_json result = value_t::object; - const auto len = static_cast(v[current_idx] - 0xa0); - for (size_t i = 0; i < len; ++i) - { - cbor_expect_string(v, idx); - std::string key = from_cbor_internal(v, idx); - result[key] = from_cbor_internal(v, idx); - } - return result; - } - - case 0xb8: // map (one-byte uint8_t for n follows) - { - basic_json result = value_t::object; - const auto len = static_cast(get_from_vector(v, current_idx)); - idx += 1; // skip 1 size byte - for (size_t i = 0; i < len; ++i) - { - cbor_expect_string(v, idx); - std::string key = from_cbor_internal(v, idx); - result[key] = from_cbor_internal(v, idx); - } - return result; - } - - case 0xb9: // map (two-byte uint16_t for n follow) - { - basic_json result = value_t::object; - const auto len = static_cast(get_from_vector(v, current_idx)); - idx += 2; // skip 2 size bytes - for (size_t i = 0; i < len; ++i) - { - cbor_expect_string(v, idx); - std::string key = from_cbor_internal(v, idx); - result[key] = from_cbor_internal(v, idx); - } - return result; - } - - case 0xba: // map (four-byte uint32_t for n follow) - { - basic_json result = value_t::object; - const auto len = static_cast(get_from_vector(v, current_idx)); - idx += 4; // skip 4 size bytes - for (size_t i = 0; i < len; ++i) - { - cbor_expect_string(v, idx); - std::string key = from_cbor_internal(v, idx); - result[key] = from_cbor_internal(v, idx); - } - return result; - } - - case 0xbb: // map (eight-byte uint64_t for n follow) - { - basic_json result = value_t::object; - const auto len = static_cast(get_from_vector(v, current_idx)); - idx += 8; // skip 8 size bytes - for (size_t i = 0; i < len; ++i) - { - cbor_expect_string(v, idx); - std::string key = from_cbor_internal(v, idx); - result[key] = from_cbor_internal(v, idx); - } - return result; - } - - case 0xbf: // map (indefinite length) - { - basic_json result = value_t::object; - while (static_cast(check_length(v.size(), 1, idx)), v[idx] != 0xff) - { - cbor_expect_string(v, idx); - std::string key = from_cbor_internal(v, idx); - result[key] = from_cbor_internal(v, idx); - } - // skip break byte (0xFF) - idx += 1; - return result; - } - - case 0xf4: // false - { - return false; - } - - case 0xf5: // true - { - return true; - } - - case 0xf6: // null - { - return value_t::null; - } - - case 0xf9: // Half-Precision Float (two-byte IEEE 754) - { - idx += 2; // skip two content bytes - - // code from RFC 7049, Appendix D, Figure 3: - // As half-precision floating-point numbers were only added to - // IEEE 754 in 2008, today's programming platforms often still - // only have limited support for them. It is very easy to - // include at least decoding support for them even without such - // support. An example of a small decoder for half-precision - // floating-point numbers in the C language is shown in Fig. 3. - check_length(v.size(), 2, current_idx + 1); - const int half = (v[current_idx + 1] << 8) + v[current_idx + 2]; - const int exp = (half >> 10) & 0x1f; - const int mant = half & 0x3ff; - double val; - if (exp == 0) - { - val = std::ldexp(mant, -24); - } - else if (exp != 31) - { - val = std::ldexp(mant + 1024, exp - 25); - } - else - { - val = mant == 0 - ? std::numeric_limits::infinity() - : std::numeric_limits::quiet_NaN(); - } - return (half & 0x8000) != 0 ? -val : val; - } - - case 0xfa: // Single-Precision Float (four-byte IEEE 754) - { - // copy bytes in reverse order into the float variable - float res; - check_length(v.size(), sizeof(float), current_idx + 1); - for (size_t byte = 0; byte < sizeof(float); ++byte) - { - reinterpret_cast(&res)[sizeof(float) - byte - 1] = v[current_idx + 1 + byte]; - } - idx += sizeof(float); // skip content bytes - return res; - } - - case 0xfb: // Double-Precision Float (eight-byte IEEE 754) - { - // copy bytes in reverse order into the double variable - double res; - check_length(v.size(), sizeof(double), current_idx + 1); - for (size_t byte = 0; byte < sizeof(double); ++byte) - { - reinterpret_cast(&res)[sizeof(double) - byte - 1] = v[current_idx + 1 + byte]; - } - idx += sizeof(double); // skip content bytes - return res; - } - - default: // anything else (0xFF is handled inside the other types) - { - std::stringstream ss; - ss << std::hex << static_cast(v[current_idx]); - JSON_THROW(parse_error::create(112, current_idx + 1, "error reading CBOR; last byte: 0x" + ss.str())); - } - } - } - - public: - /*! - @brief create a MessagePack serialization of a given JSON value - - Serializes a given JSON value @a j to a byte vector using the MessagePack - serialization format. MessagePack is a binary serialization format which - aims to be more compact than JSON itself, yet more efficient to parse. - - The library uses the following mapping from JSON values types to - MessagePack types according to the MessagePack specification: - - JSON value type | value/range | MessagePack type | first byte - --------------- | --------------------------------- | ---------------- | ---------- - null | `null` | nil | 0xc0 - boolean | `true` | true | 0xc3 - boolean | `false` | false | 0xc2 - number_integer | -9223372036854775808..-2147483649 | int64 | 0xd3 - number_integer | -2147483648..-32769 | int32 | 0xd2 - number_integer | -32768..-129 | int16 | 0xd1 - number_integer | -128..-33 | int8 | 0xd0 - number_integer | -32..-1 | negative fixint | 0xe0..0xff - number_integer | 0..127 | positive fixint | 0x00..0x7f - number_integer | 128..255 | uint 8 | 0xcc - number_integer | 256..65535 | uint 16 | 0xcd - number_integer | 65536..4294967295 | uint 32 | 0xce - number_integer | 4294967296..18446744073709551615 | uint 64 | 0xcf - number_unsigned | 0..127 | positive fixint | 0x00..0x7f - number_unsigned | 128..255 | uint 8 | 0xcc - number_unsigned | 256..65535 | uint 16 | 0xcd - number_unsigned | 65536..4294967295 | uint 32 | 0xce - number_unsigned | 4294967296..18446744073709551615 | uint 64 | 0xcf - number_float | *any value* | float 64 | 0xcb - string | *length*: 0..31 | fixstr | 0xa0..0xbf - string | *length*: 32..255 | str 8 | 0xd9 - string | *length*: 256..65535 | str 16 | 0xda - string | *length*: 65536..4294967295 | str 32 | 0xdb - array | *size*: 0..15 | fixarray | 0x90..0x9f - array | *size*: 16..65535 | array 16 | 0xdc - array | *size*: 65536..4294967295 | array 32 | 0xdd - object | *size*: 0..15 | fix map | 0x80..0x8f - object | *size*: 16..65535 | map 16 | 0xde - object | *size*: 65536..4294967295 | map 32 | 0xdf - - @note The mapping is **complete** in the sense that any JSON value type - can be converted to a MessagePack value. - - @note The following values can **not** be converted to a MessagePack value: - - strings with more than 4294967295 bytes - - arrays with more than 4294967295 elements - - objects with more than 4294967295 elements - - @note The following MessagePack types are not used in the conversion: - - bin 8 - bin 32 (0xc4..0xc6) - - ext 8 - ext 32 (0xc7..0xc9) - - float 32 (0xca) - - fixext 1 - fixext 16 (0xd4..0xd8) - - @note Any MessagePack output created @ref to_msgpack can be successfully - parsed by @ref from_msgpack. - - @param[in] j JSON value to serialize - @return MessagePack serialization as byte vector - - @complexity Linear in the size of the JSON value @a j. - - @liveexample{The example shows the serialization of a JSON value to a byte - vector in MessagePack format.,to_msgpack} - - @sa http://msgpack.org - @sa @ref from_msgpack(const std::vector&, const size_t) for the - analogous deserialization - @sa @ref to_cbor(const basic_json& for the related CBOR format - - @since version 2.0.9 - */ - static std::vector to_msgpack(const basic_json& j) - { - std::vector result; - to_msgpack_internal(j, result); - return result; - } - - /*! - @brief create a JSON value from a byte vector in MessagePack format - - Deserializes a given byte vector @a v to a JSON value using the MessagePack - serialization format. - - The library maps MessagePack types to JSON value types as follows: - - MessagePack type | JSON value type | first byte - ---------------- | --------------- | ---------- - positive fixint | number_unsigned | 0x00..0x7f - fixmap | object | 0x80..0x8f - fixarray | array | 0x90..0x9f - fixstr | string | 0xa0..0xbf - nil | `null` | 0xc0 - false | `false` | 0xc2 - true | `true` | 0xc3 - float 32 | number_float | 0xca - float 64 | number_float | 0xcb - uint 8 | number_unsigned | 0xcc - uint 16 | number_unsigned | 0xcd - uint 32 | number_unsigned | 0xce - uint 64 | number_unsigned | 0xcf - int 8 | number_integer | 0xd0 - int 16 | number_integer | 0xd1 - int 32 | number_integer | 0xd2 - int 64 | number_integer | 0xd3 - str 8 | string | 0xd9 - str 16 | string | 0xda - str 32 | string | 0xdb - array 16 | array | 0xdc - array 32 | array | 0xdd - map 16 | object | 0xde - map 32 | object | 0xdf - negative fixint | number_integer | 0xe0-0xff - - @warning The mapping is **incomplete** in the sense that not all - MessagePack types can be converted to a JSON value. The following - MessagePack types are not supported and will yield parse errors: - - bin 8 - bin 32 (0xc4..0xc6) - - ext 8 - ext 32 (0xc7..0xc9) - - fixext 1 - fixext 16 (0xd4..0xd8) - - @note Any MessagePack output created @ref to_msgpack can be successfully - parsed by @ref from_msgpack. - - @param[in] v a byte vector in MessagePack format - @param[in] start_index the index to start reading from @a v (0 by default) - @return deserialized JSON value - - @throw parse_error.110 if the given vector ends prematurely - @throw parse_error.112 if unsupported features from MessagePack were - used in the given vector @a v or if the input is not valid MessagePack - @throw parse_error.113 if a string was expected as map key, but not found - - @complexity Linear in the size of the byte vector @a v. - - @liveexample{The example shows the deserialization of a byte vector in - MessagePack format to a JSON value.,from_msgpack} - - @sa http://msgpack.org - @sa @ref to_msgpack(const basic_json&) for the analogous serialization - @sa @ref from_cbor(const std::vector&, const size_t) for the - related CBOR format - - @since version 2.0.9, parameter @a start_index since 2.1.1 - */ - static basic_json from_msgpack(const std::vector& v, - const size_t start_index = 0) - { - size_t i = start_index; - return from_msgpack_internal(v, i); - } - - /*! - @brief create a MessagePack serialization of a given JSON value - - Serializes a given JSON value @a j to a byte vector using the CBOR (Concise - Binary Object Representation) serialization format. CBOR is a binary - serialization format which aims to be more compact than JSON itself, yet - more efficient to parse. - - The library uses the following mapping from JSON values types to - CBOR types according to the CBOR specification (RFC 7049): - - JSON value type | value/range | CBOR type | first byte - --------------- | ------------------------------------------ | ---------------------------------- | --------------- - null | `null` | Null | 0xf6 - boolean | `true` | True | 0xf5 - boolean | `false` | False | 0xf4 - number_integer | -9223372036854775808..-2147483649 | Negative integer (8 bytes follow) | 0x3b - number_integer | -2147483648..-32769 | Negative integer (4 bytes follow) | 0x3a - number_integer | -32768..-129 | Negative integer (2 bytes follow) | 0x39 - number_integer | -128..-25 | Negative integer (1 byte follow) | 0x38 - number_integer | -24..-1 | Negative integer | 0x20..0x37 - number_integer | 0..23 | Integer | 0x00..0x17 - number_integer | 24..255 | Unsigned integer (1 byte follow) | 0x18 - number_integer | 256..65535 | Unsigned integer (2 bytes follow) | 0x19 - number_integer | 65536..4294967295 | Unsigned integer (4 bytes follow) | 0x1a - number_integer | 4294967296..18446744073709551615 | Unsigned integer (8 bytes follow) | 0x1b - number_unsigned | 0..23 | Integer | 0x00..0x17 - number_unsigned | 24..255 | Unsigned integer (1 byte follow) | 0x18 - number_unsigned | 256..65535 | Unsigned integer (2 bytes follow) | 0x19 - number_unsigned | 65536..4294967295 | Unsigned integer (4 bytes follow) | 0x1a - number_unsigned | 4294967296..18446744073709551615 | Unsigned integer (8 bytes follow) | 0x1b - number_float | *any value* | Double-Precision Float | 0xfb - string | *length*: 0..23 | UTF-8 string | 0x60..0x77 - string | *length*: 23..255 | UTF-8 string (1 byte follow) | 0x78 - string | *length*: 256..65535 | UTF-8 string (2 bytes follow) | 0x79 - string | *length*: 65536..4294967295 | UTF-8 string (4 bytes follow) | 0x7a - string | *length*: 4294967296..18446744073709551615 | UTF-8 string (8 bytes follow) | 0x7b - array | *size*: 0..23 | array | 0x80..0x97 - array | *size*: 23..255 | array (1 byte follow) | 0x98 - array | *size*: 256..65535 | array (2 bytes follow) | 0x99 - array | *size*: 65536..4294967295 | array (4 bytes follow) | 0x9a - array | *size*: 4294967296..18446744073709551615 | array (8 bytes follow) | 0x9b - object | *size*: 0..23 | map | 0xa0..0xb7 - object | *size*: 23..255 | map (1 byte follow) | 0xb8 - object | *size*: 256..65535 | map (2 bytes follow) | 0xb9 - object | *size*: 65536..4294967295 | map (4 bytes follow) | 0xba - object | *size*: 4294967296..18446744073709551615 | map (8 bytes follow) | 0xbb - - @note The mapping is **complete** in the sense that any JSON value type - can be converted to a CBOR value. - - @note The following CBOR types are not used in the conversion: - - byte strings (0x40..0x5f) - - UTF-8 strings terminated by "break" (0x7f) - - arrays terminated by "break" (0x9f) - - maps terminated by "break" (0xbf) - - date/time (0xc0..0xc1) - - bignum (0xc2..0xc3) - - decimal fraction (0xc4) - - bigfloat (0xc5) - - tagged items (0xc6..0xd4, 0xd8..0xdb) - - expected conversions (0xd5..0xd7) - - simple values (0xe0..0xf3, 0xf8) - - undefined (0xf7) - - half and single-precision floats (0xf9-0xfa) - - break (0xff) - - @param[in] j JSON value to serialize - @return MessagePack serialization as byte vector - - @complexity Linear in the size of the JSON value @a j. - - @liveexample{The example shows the serialization of a JSON value to a byte - vector in CBOR format.,to_cbor} - - @sa http://cbor.io - @sa @ref from_cbor(const std::vector&, const size_t) for the - analogous deserialization - @sa @ref to_msgpack(const basic_json& for the related MessagePack format - - @since version 2.0.9 - */ - static std::vector to_cbor(const basic_json& j) - { - std::vector result; - to_cbor_internal(j, result); - return result; - } - - /*! - @brief create a JSON value from a byte vector in CBOR format - - Deserializes a given byte vector @a v to a JSON value using the CBOR - (Concise Binary Object Representation) serialization format. - - The library maps CBOR types to JSON value types as follows: - - CBOR type | JSON value type | first byte - ---------------------- | --------------- | ---------- - Integer | number_unsigned | 0x00..0x17 - Unsigned integer | number_unsigned | 0x18 - Unsigned integer | number_unsigned | 0x19 - Unsigned integer | number_unsigned | 0x1a - Unsigned integer | number_unsigned | 0x1b - Negative integer | number_integer | 0x20..0x37 - Negative integer | number_integer | 0x38 - Negative integer | number_integer | 0x39 - Negative integer | number_integer | 0x3a - Negative integer | number_integer | 0x3b - Negative integer | number_integer | 0x40..0x57 - UTF-8 string | string | 0x60..0x77 - UTF-8 string | string | 0x78 - UTF-8 string | string | 0x79 - UTF-8 string | string | 0x7a - UTF-8 string | string | 0x7b - UTF-8 string | string | 0x7f - array | array | 0x80..0x97 - array | array | 0x98 - array | array | 0x99 - array | array | 0x9a - array | array | 0x9b - array | array | 0x9f - map | object | 0xa0..0xb7 - map | object | 0xb8 - map | object | 0xb9 - map | object | 0xba - map | object | 0xbb - map | object | 0xbf - False | `false` | 0xf4 - True | `true` | 0xf5 - Nill | `null` | 0xf6 - Half-Precision Float | number_float | 0xf9 - Single-Precision Float | number_float | 0xfa - Double-Precision Float | number_float | 0xfb - - @warning The mapping is **incomplete** in the sense that not all CBOR - types can be converted to a JSON value. The following CBOR types - are not supported and will yield parse errors (parse_error.112): - - byte strings (0x40..0x5f) - - date/time (0xc0..0xc1) - - bignum (0xc2..0xc3) - - decimal fraction (0xc4) - - bigfloat (0xc5) - - tagged items (0xc6..0xd4, 0xd8..0xdb) - - expected conversions (0xd5..0xd7) - - simple values (0xe0..0xf3, 0xf8) - - undefined (0xf7) - - @warning CBOR allows map keys of any type, whereas JSON only allows - strings as keys in object values. Therefore, CBOR maps with keys - other than UTF-8 strings are rejected (parse_error.113). - - @note Any CBOR output created @ref to_cbor can be successfully parsed by - @ref from_cbor. - - @param[in] v a byte vector in CBOR format - @param[in] start_index the index to start reading from @a v (0 by default) - @return deserialized JSON value - - @throw parse_error.110 if the given vector ends prematurely - @throw parse_error.112 if unsupported features from CBOR were - used in the given vector @a v or if the input is not valid CBOR - @throw parse_error.113 if a string was expected as map key, but not found - - @complexity Linear in the size of the byte vector @a v. - - @liveexample{The example shows the deserialization of a byte vector in CBOR - format to a JSON value.,from_cbor} - - @sa http://cbor.io - @sa @ref to_cbor(const basic_json&) for the analogous serialization - @sa @ref from_msgpack(const std::vector&, const size_t) for the - related MessagePack format - - @since version 2.0.9, parameter @a start_index since 2.1.1 - */ - static basic_json from_cbor(const std::vector& v, - const size_t start_index = 0) - { - size_t i = start_index; - return from_cbor_internal(v, i); - } - - /// @} - - /////////////////////////// - // convenience functions // - /////////////////////////// - - /*! - @brief return the type as string - - Returns the type name as string to be used in error messages - usually to - indicate that a function was called on a wrong JSON type. - - @return basically a string representation of a the @a m_type member - - @complexity Constant. - - @liveexample{The following code exemplifies `type_name()` for all JSON - types.,type_name} - - @since version 1.0.0, public since 2.1.0 - */ - std::string type_name() const - { - { - switch (m_type) - { - case value_t::null: - return "null"; - case value_t::object: - return "object"; - case value_t::array: - return "array"; - case value_t::string: - return "string"; - case value_t::boolean: - return "boolean"; - case value_t::discarded: - return "discarded"; - default: - return "number"; - } - } - } - - - private: - ////////////////////// - // member variables // - ////////////////////// - - /// the type of the current element - value_t m_type = value_t::null; - - /// the value of the current element - json_value m_value = {}; - - - private: - /////////////// - // iterators // - /////////////// - - /*! - @brief an iterator for primitive JSON types - - This class models an iterator for primitive JSON types (boolean, number, - string). It's only purpose is to allow the iterator/const_iterator classes - to "iterate" over primitive values. Internally, the iterator is modeled by - a `difference_type` variable. Value begin_value (`0`) models the begin, - end_value (`1`) models past the end. - */ - class primitive_iterator_t - { - public: - - difference_type get_value() const noexcept - { - return m_it; - } - /// set iterator to a defined beginning - void set_begin() noexcept - { - m_it = begin_value; - } - - /// set iterator to a defined past the end - void set_end() noexcept - { - m_it = end_value; - } - - /// return whether the iterator can be dereferenced - constexpr bool is_begin() const noexcept - { - return (m_it == begin_value); - } - - /// return whether the iterator is at end - constexpr bool is_end() const noexcept - { - return (m_it == end_value); - } - - friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept - { - return lhs.m_it == rhs.m_it; - } - - friend constexpr bool operator!=(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept - { - return !(lhs == rhs); - } - - friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept - { - return lhs.m_it < rhs.m_it; - } - - friend constexpr bool operator<=(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept - { - return lhs.m_it <= rhs.m_it; - } - - friend constexpr bool operator>(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept - { - return lhs.m_it > rhs.m_it; - } - - friend constexpr bool operator>=(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept - { - return lhs.m_it >= rhs.m_it; - } - - primitive_iterator_t operator+(difference_type i) - { - auto result = *this; - result += i; - return result; - } - - friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept - { - return lhs.m_it - rhs.m_it; - } - - friend std::ostream& operator<<(std::ostream& os, primitive_iterator_t it) - { - return os << it.m_it; - } - - primitive_iterator_t& operator++() - { - ++m_it; - return *this; - } - - primitive_iterator_t operator++(int) - { - auto result = *this; - m_it++; - return result; - } - - primitive_iterator_t& operator--() - { - --m_it; - return *this; - } - - primitive_iterator_t operator--(int) - { - auto result = *this; - m_it--; - return result; - } - - primitive_iterator_t& operator+=(difference_type n) - { - m_it += n; - return *this; - } - - primitive_iterator_t& operator-=(difference_type n) - { - m_it -= n; - return *this; - } - - private: - static constexpr difference_type begin_value = 0; - static constexpr difference_type end_value = begin_value + 1; - - /// iterator as signed integer type - difference_type m_it = std::numeric_limits::denorm_min(); - }; - - /*! - @brief an iterator value - - @note This structure could easily be a union, but MSVC currently does not - allow unions members with complex constructors, see - https://github.com/nlohmann/json/pull/105. - */ - struct internal_iterator - { - /// iterator for JSON objects - typename object_t::iterator object_iterator; - /// iterator for JSON arrays - typename array_t::iterator array_iterator; - /// generic iterator for all other types - primitive_iterator_t primitive_iterator; - - /// create an uninitialized internal_iterator - internal_iterator() noexcept - : object_iterator(), array_iterator(), primitive_iterator() - {} - }; - - /// proxy class for the iterator_wrapper functions - template - class iteration_proxy - { - private: - /// helper class for iteration - class iteration_proxy_internal - { - private: - /// the iterator - IteratorType anchor; - /// an index for arrays (used to create key names) - size_t array_index = 0; - - public: - explicit iteration_proxy_internal(IteratorType it) noexcept - : anchor(it) - {} - - /// dereference operator (needed for range-based for) - iteration_proxy_internal& operator*() - { - return *this; - } - - /// increment operator (needed for range-based for) - iteration_proxy_internal& operator++() - { - ++anchor; - ++array_index; - - return *this; - } - - /// inequality operator (needed for range-based for) - bool operator!= (const iteration_proxy_internal& o) const - { - return anchor != o.anchor; - } - - /// return key of the iterator - typename basic_json::string_t key() const - { - assert(anchor.m_object != nullptr); - - switch (anchor.m_object->type()) - { - // use integer array index as key - case value_t::array: - { - return std::to_string(array_index); - } - - // use key from the object - case value_t::object: - { - return anchor.key(); - } - - // use an empty key for all primitive types - default: - { - return ""; - } - } - } - - /// return value of the iterator - typename IteratorType::reference value() const - { - return anchor.value(); - } - }; - - /// the container to iterate - typename IteratorType::reference container; - - public: - /// construct iteration proxy from a container - explicit iteration_proxy(typename IteratorType::reference cont) - : container(cont) - {} - - /// return iterator begin (needed for range-based for) - iteration_proxy_internal begin() noexcept - { - return iteration_proxy_internal(container.begin()); - } - - /// return iterator end (needed for range-based for) - iteration_proxy_internal end() noexcept - { - return iteration_proxy_internal(container.end()); - } - }; - - public: - /*! - @brief a template for a random access iterator for the @ref basic_json class - - This class implements a both iterators (iterator and const_iterator) for the - @ref basic_json class. - - @note An iterator is called *initialized* when a pointer to a JSON value - has been set (e.g., by a constructor or a copy assignment). If the - iterator is default-constructed, it is *uninitialized* and most - methods are undefined. **The library uses assertions to detect calls - on uninitialized iterators.** - - @requirement The class satisfies the following concept requirements: - - [RandomAccessIterator](http://en.cppreference.com/w/cpp/concept/RandomAccessIterator): - The iterator that can be moved to point (forward and backward) to any - element in constant time. - - @since version 1.0.0, simplified in version 2.0.9 - */ - template - class iter_impl : public std::iterator - { - /// allow basic_json to access private members - friend class basic_json; - - // make sure U is basic_json or const basic_json - static_assert(std::is_same::value - or std::is_same::value, - "iter_impl only accepts (const) basic_json"); - - public: - /// the type of the values when the iterator is dereferenced - using value_type = typename basic_json::value_type; - /// a type to represent differences between iterators - using difference_type = typename basic_json::difference_type; - /// defines a pointer to the type iterated over (value_type) - using pointer = typename std::conditional::value, - typename basic_json::const_pointer, - typename basic_json::pointer>::type; - /// defines a reference to the type iterated over (value_type) - using reference = typename std::conditional::value, - typename basic_json::const_reference, - typename basic_json::reference>::type; - /// the category of the iterator - using iterator_category = std::bidirectional_iterator_tag; - - /// default constructor - iter_impl() = default; - - /*! - @brief constructor for a given JSON instance - @param[in] object pointer to a JSON object for this iterator - @pre object != nullptr - @post The iterator is initialized; i.e. `m_object != nullptr`. - */ - explicit iter_impl(pointer object) noexcept - : m_object(object) - { - assert(m_object != nullptr); - - switch (m_object->m_type) - { - case basic_json::value_t::object: - { - m_it.object_iterator = typename object_t::iterator(); - break; - } - - case basic_json::value_t::array: - { - m_it.array_iterator = typename array_t::iterator(); - break; - } - - default: - { - m_it.primitive_iterator = primitive_iterator_t(); - break; - } - } - } - - /* - Use operator `const_iterator` instead of `const_iterator(const iterator& - other) noexcept` to avoid two class definitions for @ref iterator and - @ref const_iterator. - - This function is only called if this class is an @ref iterator. If this - class is a @ref const_iterator this function is not called. - */ - operator const_iterator() const - { - const_iterator ret; - - if (m_object) - { - ret.m_object = m_object; - ret.m_it = m_it; - } - - return ret; - } - - /*! - @brief copy constructor - @param[in] other iterator to copy from - @note It is not checked whether @a other is initialized. - */ - iter_impl(const iter_impl& other) noexcept - : m_object(other.m_object), m_it(other.m_it) - {} - - /*! - @brief copy assignment - @param[in,out] other iterator to copy from - @note It is not checked whether @a other is initialized. - */ - iter_impl& operator=(iter_impl other) noexcept( - std::is_nothrow_move_constructible::value and - std::is_nothrow_move_assignable::value and - std::is_nothrow_move_constructible::value and - std::is_nothrow_move_assignable::value - ) - { - std::swap(m_object, other.m_object); - std::swap(m_it, other.m_it); - return *this; - } - - private: - /*! - @brief set the iterator to the first value - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - void set_begin() noexcept - { - assert(m_object != nullptr); - - switch (m_object->m_type) - { - case basic_json::value_t::object: - { - m_it.object_iterator = m_object->m_value.object->begin(); - break; - } - - case basic_json::value_t::array: - { - m_it.array_iterator = m_object->m_value.array->begin(); - break; - } - - case basic_json::value_t::null: - { - // set to end so begin()==end() is true: null is empty - m_it.primitive_iterator.set_end(); - break; - } - - default: - { - m_it.primitive_iterator.set_begin(); - break; - } - } - } - - /*! - @brief set the iterator past the last value - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - void set_end() noexcept - { - assert(m_object != nullptr); - - switch (m_object->m_type) - { - case basic_json::value_t::object: - { - m_it.object_iterator = m_object->m_value.object->end(); - break; - } - - case basic_json::value_t::array: - { - m_it.array_iterator = m_object->m_value.array->end(); - break; - } - - default: - { - m_it.primitive_iterator.set_end(); - break; - } - } - } - - public: - /*! - @brief return a reference to the value pointed to by the iterator - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - reference operator*() const - { - assert(m_object != nullptr); - - switch (m_object->m_type) - { - case basic_json::value_t::object: - { - assert(m_it.object_iterator != m_object->m_value.object->end()); - return m_it.object_iterator->second; - } - - case basic_json::value_t::array: - { - assert(m_it.array_iterator != m_object->m_value.array->end()); - return *m_it.array_iterator; - } - - case basic_json::value_t::null: - { - JSON_THROW(invalid_iterator::create(214, "cannot get value")); - } - - default: - { - if (m_it.primitive_iterator.is_begin()) - { - return *m_object; - } - - JSON_THROW(invalid_iterator::create(214, "cannot get value")); - } - } - } - - /*! - @brief dereference the iterator - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - pointer operator->() const - { - assert(m_object != nullptr); - - switch (m_object->m_type) - { - case basic_json::value_t::object: - { - assert(m_it.object_iterator != m_object->m_value.object->end()); - return &(m_it.object_iterator->second); - } - - case basic_json::value_t::array: - { - assert(m_it.array_iterator != m_object->m_value.array->end()); - return &*m_it.array_iterator; - } - - default: - { - if (m_it.primitive_iterator.is_begin()) - { - return m_object; - } - - JSON_THROW(invalid_iterator::create(214, "cannot get value")); - } - } - } - - /*! - @brief post-increment (it++) - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - iter_impl operator++(int) - { - auto result = *this; - ++(*this); - return result; - } - - /*! - @brief pre-increment (++it) - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - iter_impl& operator++() - { - assert(m_object != nullptr); - - switch (m_object->m_type) - { - case basic_json::value_t::object: - { - std::advance(m_it.object_iterator, 1); - break; - } - - case basic_json::value_t::array: - { - std::advance(m_it.array_iterator, 1); - break; - } - - default: - { - ++m_it.primitive_iterator; - break; - } - } - - return *this; - } - - /*! - @brief post-decrement (it--) - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - iter_impl operator--(int) - { - auto result = *this; - --(*this); - return result; - } - - /*! - @brief pre-decrement (--it) - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - iter_impl& operator--() - { - assert(m_object != nullptr); - - switch (m_object->m_type) - { - case basic_json::value_t::object: - { - std::advance(m_it.object_iterator, -1); - break; - } - - case basic_json::value_t::array: - { - std::advance(m_it.array_iterator, -1); - break; - } - - default: - { - --m_it.primitive_iterator; - break; - } - } - - return *this; - } - - /*! - @brief comparison: equal - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - bool operator==(const iter_impl& other) const - { - // if objects are not the same, the comparison is undefined - if (m_object != other.m_object) - { - JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers")); - } - - assert(m_object != nullptr); - - switch (m_object->m_type) - { - case basic_json::value_t::object: - { - return (m_it.object_iterator == other.m_it.object_iterator); - } - - case basic_json::value_t::array: - { - return (m_it.array_iterator == other.m_it.array_iterator); - } - - default: - { - return (m_it.primitive_iterator == other.m_it.primitive_iterator); - } - } - } - - /*! - @brief comparison: not equal - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - bool operator!=(const iter_impl& other) const - { - return not operator==(other); - } - - /*! - @brief comparison: smaller - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - bool operator<(const iter_impl& other) const - { - // if objects are not the same, the comparison is undefined - if (m_object != other.m_object) - { - JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers")); - } - - assert(m_object != nullptr); - - switch (m_object->m_type) - { - case basic_json::value_t::object: - { - JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators")); - } - - case basic_json::value_t::array: - { - return (m_it.array_iterator < other.m_it.array_iterator); - } - - default: - { - return (m_it.primitive_iterator < other.m_it.primitive_iterator); - } - } - } - - /*! - @brief comparison: less than or equal - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - bool operator<=(const iter_impl& other) const - { - return not other.operator < (*this); - } - - /*! - @brief comparison: greater than - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - bool operator>(const iter_impl& other) const - { - return not operator<=(other); - } - - /*! - @brief comparison: greater than or equal - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - bool operator>=(const iter_impl& other) const - { - return not operator<(other); - } - - /*! - @brief add to iterator - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - iter_impl& operator+=(difference_type i) - { - assert(m_object != nullptr); - - switch (m_object->m_type) - { - case basic_json::value_t::object: - { - JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators")); - } - - case basic_json::value_t::array: - { - std::advance(m_it.array_iterator, i); - break; - } - - default: - { - m_it.primitive_iterator += i; - break; - } - } - - return *this; - } - - /*! - @brief subtract from iterator - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - iter_impl& operator-=(difference_type i) - { - return operator+=(-i); - } - - /*! - @brief add to iterator - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - iter_impl operator+(difference_type i) - { - auto result = *this; - result += i; - return result; - } - - /*! - @brief subtract from iterator - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - iter_impl operator-(difference_type i) - { - auto result = *this; - result -= i; - return result; - } - - /*! - @brief return difference - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - difference_type operator-(const iter_impl& other) const - { - assert(m_object != nullptr); - - switch (m_object->m_type) - { - case basic_json::value_t::object: - { - JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators")); - } - - case basic_json::value_t::array: - { - return m_it.array_iterator - other.m_it.array_iterator; - } - - default: - { - return m_it.primitive_iterator - other.m_it.primitive_iterator; - } - } - } - - /*! - @brief access to successor - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - reference operator[](difference_type n) const - { - assert(m_object != nullptr); - - switch (m_object->m_type) - { - case basic_json::value_t::object: - { - JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators")); - } - - case basic_json::value_t::array: - { - return *std::next(m_it.array_iterator, n); - } - - case basic_json::value_t::null: - { - JSON_THROW(invalid_iterator::create(214, "cannot get value")); - } - - default: - { - if (m_it.primitive_iterator.get_value() == -n) - { - return *m_object; - } - - JSON_THROW(invalid_iterator::create(214, "cannot get value")); - } - } - } - - /*! - @brief return the key of an object iterator - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - typename object_t::key_type key() const - { - assert(m_object != nullptr); - - if (m_object->is_object()) - { - return m_it.object_iterator->first; - } - - JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators")); - } - - /*! - @brief return the value of an iterator - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - reference value() const - { - return operator*(); - } - - private: - /// associated JSON instance - pointer m_object = nullptr; - /// the actual iterator of the associated instance - internal_iterator m_it = internal_iterator(); - }; - - /*! - @brief a template for a reverse iterator class - - @tparam Base the base iterator type to reverse. Valid types are @ref - iterator (to create @ref reverse_iterator) and @ref const_iterator (to - create @ref const_reverse_iterator). - - @requirement The class satisfies the following concept requirements: - - [RandomAccessIterator](http://en.cppreference.com/w/cpp/concept/RandomAccessIterator): - The iterator that can be moved to point (forward and backward) to any - element in constant time. - - [OutputIterator](http://en.cppreference.com/w/cpp/concept/OutputIterator): - It is possible to write to the pointed-to element (only if @a Base is - @ref iterator). - - @since version 1.0.0 - */ - template - class json_reverse_iterator : public std::reverse_iterator - { - public: - /// shortcut to the reverse iterator adaptor - using base_iterator = std::reverse_iterator; - /// the reference type for the pointed-to element - using reference = typename Base::reference; - - /// create reverse iterator from iterator - json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept - : base_iterator(it) - {} - - /// create reverse iterator from base class - json_reverse_iterator(const base_iterator& it) noexcept - : base_iterator(it) - {} - - /// post-increment (it++) - json_reverse_iterator operator++(int) - { - return base_iterator::operator++(1); - } - - /// pre-increment (++it) - json_reverse_iterator& operator++() - { - base_iterator::operator++(); - return *this; - } - - /// post-decrement (it--) - json_reverse_iterator operator--(int) - { - return base_iterator::operator--(1); - } - - /// pre-decrement (--it) - json_reverse_iterator& operator--() - { - base_iterator::operator--(); - return *this; - } - - /// add to iterator - json_reverse_iterator& operator+=(difference_type i) - { - base_iterator::operator+=(i); - return *this; - } - - /// add to iterator - json_reverse_iterator operator+(difference_type i) const - { - auto result = *this; - result += i; - return result; - } - - /// subtract from iterator - json_reverse_iterator operator-(difference_type i) const - { - auto result = *this; - result -= i; - return result; - } - - /// return difference - difference_type operator-(const json_reverse_iterator& other) const - { - return this->base() - other.base(); - } - - /// access to successor - reference operator[](difference_type n) const - { - return *(this->operator+(n)); - } - - /// return the key of an object iterator - typename object_t::key_type key() const - { - auto it = --this->base(); - return it.key(); - } - - /// return the value of an iterator - reference value() const - { - auto it = --this->base(); - return it.operator * (); - } - }; - - - private: - ////////////////////// - // lexer and parser // - ////////////////////// - - /*! - @brief lexical analysis - - This class organizes the lexical analysis during JSON deserialization. The - core of it is a scanner generated by [re2c](http://re2c.org) that - processes a buffer and recognizes tokens according to RFC 7159. - */ - class lexer - { - public: - /// token types for the parser - enum class token_type - { - uninitialized, ///< indicating the scanner is uninitialized - literal_true, ///< the `true` literal - literal_false, ///< the `false` literal - literal_null, ///< the `null` literal - value_string, ///< a string -- use get_string() for actual value - value_unsigned, ///< an unsigned integer -- use get_number() for actual value - value_integer, ///< a signed integer -- use get_number() for actual value - value_float, ///< an floating point number -- use get_number() for actual value - begin_array, ///< the character for array begin `[` - begin_object, ///< the character for object begin `{` - end_array, ///< the character for array end `]` - end_object, ///< the character for object end `}` - name_separator, ///< the name separator `:` - value_separator, ///< the value separator `,` - parse_error, ///< indicating a parse error - end_of_input ///< indicating the end of the input buffer - }; - - /// the char type to use in the lexer - using lexer_char_t = unsigned char; - - /// a lexer from a buffer with given length - lexer(const lexer_char_t* buff, const size_t len) noexcept - : m_content(buff) - { - assert(m_content != nullptr); - m_start = m_cursor = m_content; - m_limit = m_content + len; - } - - /*! - @brief a lexer from an input stream - @throw parse_error.111 if input stream is in a bad state - */ - explicit lexer(std::istream& s) - : m_stream(&s), m_line_buffer() - { - // immediately abort if stream is erroneous - if (s.fail()) - { - JSON_THROW(parse_error::create(111, 0, "bad input stream")); - } - - // fill buffer - fill_line_buffer(); - - // skip UTF-8 byte-order mark - if (m_line_buffer.size() >= 3 and m_line_buffer.substr(0, 3) == "\xEF\xBB\xBF") - { - m_line_buffer[0] = ' '; - m_line_buffer[1] = ' '; - m_line_buffer[2] = ' '; - } - } - - // switch off unwanted functions (due to pointer members) - lexer() = delete; - lexer(const lexer&) = delete; - lexer operator=(const lexer&) = delete; - - /*! - @brief create a string from one or two Unicode code points - - There are two cases: (1) @a codepoint1 is in the Basic Multilingual - Plane (U+0000 through U+FFFF) and @a codepoint2 is 0, or (2) - @a codepoint1 and @a codepoint2 are a UTF-16 surrogate pair to - represent a code point above U+FFFF. - - @param[in] codepoint1 the code point (can be high surrogate) - @param[in] codepoint2 the code point (can be low surrogate or 0) - - @return string representation of the code point; the length of the - result string is between 1 and 4 characters. - - @throw parse_error.102 if the low surrogate is invalid; example: - `""missing or wrong low surrogate""` - @throw parse_error.103 if code point is > 0x10ffff; example: `"code - points above 0x10FFFF are invalid"` - - @complexity Constant. - - @see - */ - string_t to_unicode(const std::size_t codepoint1, - const std::size_t codepoint2 = 0) const - { - // calculate the code point from the given code points - std::size_t codepoint = codepoint1; - - // check if codepoint1 is a high surrogate - if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF) - { - // check if codepoint2 is a low surrogate - if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF) - { - codepoint = - // high surrogate occupies the most significant 22 bits - (codepoint1 << 10) - // low surrogate occupies the least significant 15 bits - + codepoint2 - // there is still the 0xD800, 0xDC00 and 0x10000 noise - // in the result so we have to subtract with: - // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00 - - 0x35FDC00; - } - else - { - JSON_THROW(parse_error::create(102, get_position(), "missing or wrong low surrogate")); - } - } - - string_t result; - - if (codepoint < 0x80) - { - // 1-byte characters: 0xxxxxxx (ASCII) - result.append(1, static_cast(codepoint)); - } - else if (codepoint <= 0x7ff) - { - // 2-byte characters: 110xxxxx 10xxxxxx - result.append(1, static_cast(0xC0 | (codepoint >> 6))); - result.append(1, static_cast(0x80 | (codepoint & 0x3F))); - } - else if (codepoint <= 0xffff) - { - // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx - result.append(1, static_cast(0xE0 | (codepoint >> 12))); - result.append(1, static_cast(0x80 | ((codepoint >> 6) & 0x3F))); - result.append(1, static_cast(0x80 | (codepoint & 0x3F))); - } - else if (codepoint <= 0x10ffff) - { - // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx - result.append(1, static_cast(0xF0 | (codepoint >> 18))); - result.append(1, static_cast(0x80 | ((codepoint >> 12) & 0x3F))); - result.append(1, static_cast(0x80 | ((codepoint >> 6) & 0x3F))); - result.append(1, static_cast(0x80 | (codepoint & 0x3F))); - } - else - { - JSON_THROW(parse_error::create(103, get_position(), "code points above 0x10FFFF are invalid")); - } - - return result; - } - - /// return name of values of type token_type (only used for errors) - static std::string token_type_name(const token_type t) - { - switch (t) - { - case token_type::uninitialized: - return ""; - case token_type::literal_true: - return "true literal"; - case token_type::literal_false: - return "false literal"; - case token_type::literal_null: - return "null literal"; - case token_type::value_string: - return "string literal"; - case lexer::token_type::value_unsigned: - case lexer::token_type::value_integer: - case lexer::token_type::value_float: - return "number literal"; - case token_type::begin_array: - return "'['"; - case token_type::begin_object: - return "'{'"; - case token_type::end_array: - return "']'"; - case token_type::end_object: - return "'}'"; - case token_type::name_separator: - return "':'"; - case token_type::value_separator: - return "','"; - case token_type::parse_error: - return ""; - case token_type::end_of_input: - return "end of input"; - default: - { - // catch non-enum values - return "unknown token"; // LCOV_EXCL_LINE - } - } - } - - /*! - This function implements a scanner for JSON. It is specified using - regular expressions that try to follow RFC 7159 as close as possible. - These regular expressions are then translated into a minimized - deterministic finite automaton (DFA) by the tool - [re2c](http://re2c.org). As a result, the translated code for this - function consists of a large block of code with `goto` jumps. - - @return the class of the next token read from the buffer - - @complexity Linear in the length of the input.\n - - Proposition: The loop below will always terminate for finite input.\n - - Proof (by contradiction): Assume a finite input. To loop forever, the - loop must never hit code with a `break` statement. The only code - snippets without a `break` statement is the continue statement for - whitespace. To loop forever, the input must be an infinite sequence - whitespace. This contradicts the assumption of finite input, q.e.d. - */ - token_type scan() - { - while (true) - { - // pointer for backtracking information - m_marker = nullptr; - - // remember the begin of the token - m_start = m_cursor; - assert(m_start != nullptr); - - - { - lexer_char_t yych; - unsigned int yyaccept = 0; - static const unsigned char yybm[] = - { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 32, 32, 0, 0, 32, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 160, 128, 0, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 192, 192, 192, 192, 192, 192, 192, 192, - 192, 192, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 0, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - }; - if ((m_limit - m_cursor) < 5) - { - fill_line_buffer(5); // LCOV_EXCL_LINE - } - yych = *m_cursor; - if (yybm[0 + yych] & 32) - { - goto basic_json_parser_6; - } - if (yych <= '[') - { - if (yych <= '-') - { - if (yych <= '"') - { - if (yych <= 0x00) - { - goto basic_json_parser_2; - } - if (yych <= '!') - { - goto basic_json_parser_4; - } - goto basic_json_parser_9; - } - else - { - if (yych <= '+') - { - goto basic_json_parser_4; - } - if (yych <= ',') - { - goto basic_json_parser_10; - } - goto basic_json_parser_12; - } - } - else - { - if (yych <= '9') - { - if (yych <= '/') - { - goto basic_json_parser_4; - } - if (yych <= '0') - { - goto basic_json_parser_13; - } - goto basic_json_parser_15; - } - else - { - if (yych <= ':') - { - goto basic_json_parser_17; - } - if (yych <= 'Z') - { - goto basic_json_parser_4; - } - goto basic_json_parser_19; - } - } - } - else - { - if (yych <= 'n') - { - if (yych <= 'e') - { - if (yych == ']') - { - goto basic_json_parser_21; - } - goto basic_json_parser_4; - } - else - { - if (yych <= 'f') - { - goto basic_json_parser_23; - } - if (yych <= 'm') - { - goto basic_json_parser_4; - } - goto basic_json_parser_24; - } - } - else - { - if (yych <= 'z') - { - if (yych == 't') - { - goto basic_json_parser_25; - } - goto basic_json_parser_4; - } - else - { - if (yych <= '{') - { - goto basic_json_parser_26; - } - if (yych == '}') - { - goto basic_json_parser_28; - } - goto basic_json_parser_4; - } - } - } -basic_json_parser_2: - ++m_cursor; - { - last_token_type = token_type::end_of_input; - break; - } -basic_json_parser_4: - ++m_cursor; -basic_json_parser_5: - { - last_token_type = token_type::parse_error; - break; - } -basic_json_parser_6: - ++m_cursor; - if (m_limit <= m_cursor) - { - fill_line_buffer(1); // LCOV_EXCL_LINE - } - yych = *m_cursor; - if (yybm[0 + yych] & 32) - { - goto basic_json_parser_6; - } - { - position += static_cast((m_cursor - m_start)); - continue; - } -basic_json_parser_9: - yyaccept = 0; - yych = *(m_marker = ++m_cursor); - if (yych <= 0x1F) - { - goto basic_json_parser_5; - } - if (yych <= 0x7F) - { - goto basic_json_parser_31; - } - if (yych <= 0xC1) - { - goto basic_json_parser_5; - } - if (yych <= 0xF4) - { - goto basic_json_parser_31; - } - goto basic_json_parser_5; -basic_json_parser_10: - ++m_cursor; - { - last_token_type = token_type::value_separator; - break; - } -basic_json_parser_12: - yych = *++m_cursor; - if (yych <= '/') - { - goto basic_json_parser_5; - } - if (yych <= '0') - { - goto basic_json_parser_43; - } - if (yych <= '9') - { - goto basic_json_parser_45; - } - goto basic_json_parser_5; -basic_json_parser_13: - yyaccept = 1; - yych = *(m_marker = ++m_cursor); - if (yych <= '9') - { - if (yych == '.') - { - goto basic_json_parser_47; - } - if (yych >= '0') - { - goto basic_json_parser_48; - } - } - else - { - if (yych <= 'E') - { - if (yych >= 'E') - { - goto basic_json_parser_51; - } - } - else - { - if (yych == 'e') - { - goto basic_json_parser_51; - } - } - } -basic_json_parser_14: - { - last_token_type = token_type::value_unsigned; - break; - } -basic_json_parser_15: - yyaccept = 1; - m_marker = ++m_cursor; - if ((m_limit - m_cursor) < 3) - { - fill_line_buffer(3); // LCOV_EXCL_LINE - } - yych = *m_cursor; - if (yybm[0 + yych] & 64) - { - goto basic_json_parser_15; - } - if (yych <= 'D') - { - if (yych == '.') - { - goto basic_json_parser_47; - } - goto basic_json_parser_14; - } - else - { - if (yych <= 'E') - { - goto basic_json_parser_51; - } - if (yych == 'e') - { - goto basic_json_parser_51; - } - goto basic_json_parser_14; - } -basic_json_parser_17: - ++m_cursor; - { - last_token_type = token_type::name_separator; - break; - } -basic_json_parser_19: - ++m_cursor; - { - last_token_type = token_type::begin_array; - break; - } -basic_json_parser_21: - ++m_cursor; - { - last_token_type = token_type::end_array; - break; - } -basic_json_parser_23: - yyaccept = 0; - yych = *(m_marker = ++m_cursor); - if (yych == 'a') - { - goto basic_json_parser_52; - } - goto basic_json_parser_5; -basic_json_parser_24: - yyaccept = 0; - yych = *(m_marker = ++m_cursor); - if (yych == 'u') - { - goto basic_json_parser_53; - } - goto basic_json_parser_5; -basic_json_parser_25: - yyaccept = 0; - yych = *(m_marker = ++m_cursor); - if (yych == 'r') - { - goto basic_json_parser_54; - } - goto basic_json_parser_5; -basic_json_parser_26: - ++m_cursor; - { - last_token_type = token_type::begin_object; - break; - } -basic_json_parser_28: - ++m_cursor; - { - last_token_type = token_type::end_object; - break; - } -basic_json_parser_30: - ++m_cursor; - if (m_limit <= m_cursor) - { - fill_line_buffer(1); // LCOV_EXCL_LINE - } - yych = *m_cursor; -basic_json_parser_31: - if (yybm[0 + yych] & 128) - { - goto basic_json_parser_30; - } - if (yych <= 0xE0) - { - if (yych <= '\\') - { - if (yych <= 0x1F) - { - goto basic_json_parser_32; - } - if (yych <= '"') - { - goto basic_json_parser_33; - } - goto basic_json_parser_35; - } - else - { - if (yych <= 0xC1) - { - goto basic_json_parser_32; - } - if (yych <= 0xDF) - { - goto basic_json_parser_36; - } - goto basic_json_parser_37; - } - } - else - { - if (yych <= 0xEF) - { - if (yych == 0xED) - { - goto basic_json_parser_39; - } - goto basic_json_parser_38; - } - else - { - if (yych <= 0xF0) - { - goto basic_json_parser_40; - } - if (yych <= 0xF3) - { - goto basic_json_parser_41; - } - if (yych <= 0xF4) - { - goto basic_json_parser_42; - } - } - } -basic_json_parser_32: - m_cursor = m_marker; - if (yyaccept <= 1) - { - if (yyaccept == 0) - { - goto basic_json_parser_5; - } - else - { - goto basic_json_parser_14; - } - } - else - { - if (yyaccept == 2) - { - goto basic_json_parser_44; - } - else - { - goto basic_json_parser_58; - } - } -basic_json_parser_33: - ++m_cursor; - { - last_token_type = token_type::value_string; - break; - } -basic_json_parser_35: - ++m_cursor; - if (m_limit <= m_cursor) - { - fill_line_buffer(1); // LCOV_EXCL_LINE - } - yych = *m_cursor; - if (yych <= 'e') - { - if (yych <= '/') - { - if (yych == '"') - { - goto basic_json_parser_30; - } - if (yych <= '.') - { - goto basic_json_parser_32; - } - goto basic_json_parser_30; - } - else - { - if (yych <= '\\') - { - if (yych <= '[') - { - goto basic_json_parser_32; - } - goto basic_json_parser_30; - } - else - { - if (yych == 'b') - { - goto basic_json_parser_30; - } - goto basic_json_parser_32; - } - } - } - else - { - if (yych <= 'q') - { - if (yych <= 'f') - { - goto basic_json_parser_30; - } - if (yych == 'n') - { - goto basic_json_parser_30; - } - goto basic_json_parser_32; - } - else - { - if (yych <= 's') - { - if (yych <= 'r') - { - goto basic_json_parser_30; - } - goto basic_json_parser_32; - } - else - { - if (yych <= 't') - { - goto basic_json_parser_30; - } - if (yych <= 'u') - { - goto basic_json_parser_55; - } - goto basic_json_parser_32; - } - } - } -basic_json_parser_36: - ++m_cursor; - if (m_limit <= m_cursor) - { - fill_line_buffer(1); // LCOV_EXCL_LINE - } - yych = *m_cursor; - if (yych <= 0x7F) - { - goto basic_json_parser_32; - } - if (yych <= 0xBF) - { - goto basic_json_parser_30; - } - goto basic_json_parser_32; -basic_json_parser_37: - ++m_cursor; - if (m_limit <= m_cursor) - { - fill_line_buffer(1); // LCOV_EXCL_LINE - } - yych = *m_cursor; - if (yych <= 0x9F) - { - goto basic_json_parser_32; - } - if (yych <= 0xBF) - { - goto basic_json_parser_36; - } - goto basic_json_parser_32; -basic_json_parser_38: - ++m_cursor; - if (m_limit <= m_cursor) - { - fill_line_buffer(1); // LCOV_EXCL_LINE - } - yych = *m_cursor; - if (yych <= 0x7F) - { - goto basic_json_parser_32; - } - if (yych <= 0xBF) - { - goto basic_json_parser_36; - } - goto basic_json_parser_32; -basic_json_parser_39: - ++m_cursor; - if (m_limit <= m_cursor) - { - fill_line_buffer(1); // LCOV_EXCL_LINE - } - yych = *m_cursor; - if (yych <= 0x7F) - { - goto basic_json_parser_32; - } - if (yych <= 0x9F) - { - goto basic_json_parser_36; - } - goto basic_json_parser_32; -basic_json_parser_40: - ++m_cursor; - if (m_limit <= m_cursor) - { - fill_line_buffer(1); // LCOV_EXCL_LINE - } - yych = *m_cursor; - if (yych <= 0x8F) - { - goto basic_json_parser_32; - } - if (yych <= 0xBF) - { - goto basic_json_parser_38; - } - goto basic_json_parser_32; -basic_json_parser_41: - ++m_cursor; - if (m_limit <= m_cursor) - { - fill_line_buffer(1); // LCOV_EXCL_LINE - } - yych = *m_cursor; - if (yych <= 0x7F) - { - goto basic_json_parser_32; - } - if (yych <= 0xBF) - { - goto basic_json_parser_38; - } - goto basic_json_parser_32; -basic_json_parser_42: - ++m_cursor; - if (m_limit <= m_cursor) - { - fill_line_buffer(1); // LCOV_EXCL_LINE - } - yych = *m_cursor; - if (yych <= 0x7F) - { - goto basic_json_parser_32; - } - if (yych <= 0x8F) - { - goto basic_json_parser_38; - } - goto basic_json_parser_32; -basic_json_parser_43: - yyaccept = 2; - yych = *(m_marker = ++m_cursor); - if (yych <= '9') - { - if (yych == '.') - { - goto basic_json_parser_47; - } - if (yych >= '0') - { - goto basic_json_parser_48; - } - } - else - { - if (yych <= 'E') - { - if (yych >= 'E') - { - goto basic_json_parser_51; - } - } - else - { - if (yych == 'e') - { - goto basic_json_parser_51; - } - } - } -basic_json_parser_44: - { - last_token_type = token_type::value_integer; - break; - } -basic_json_parser_45: - yyaccept = 2; - m_marker = ++m_cursor; - if ((m_limit - m_cursor) < 3) - { - fill_line_buffer(3); // LCOV_EXCL_LINE - } - yych = *m_cursor; - if (yych <= '9') - { - if (yych == '.') - { - goto basic_json_parser_47; - } - if (yych <= '/') - { - goto basic_json_parser_44; - } - goto basic_json_parser_45; - } - else - { - if (yych <= 'E') - { - if (yych <= 'D') - { - goto basic_json_parser_44; - } - goto basic_json_parser_51; - } - else - { - if (yych == 'e') - { - goto basic_json_parser_51; - } - goto basic_json_parser_44; - } - } -basic_json_parser_47: - yych = *++m_cursor; - if (yych <= '/') - { - goto basic_json_parser_32; - } - if (yych <= '9') - { - goto basic_json_parser_56; - } - goto basic_json_parser_32; -basic_json_parser_48: - ++m_cursor; - if (m_limit <= m_cursor) - { - fill_line_buffer(1); // LCOV_EXCL_LINE - } - yych = *m_cursor; - if (yych <= '/') - { - goto basic_json_parser_50; - } - if (yych <= '9') - { - goto basic_json_parser_48; - } -basic_json_parser_50: - { - last_token_type = token_type::parse_error; - break; - } -basic_json_parser_51: - yych = *++m_cursor; - if (yych <= ',') - { - if (yych == '+') - { - goto basic_json_parser_59; - } - goto basic_json_parser_32; - } - else - { - if (yych <= '-') - { - goto basic_json_parser_59; - } - if (yych <= '/') - { - goto basic_json_parser_32; - } - if (yych <= '9') - { - goto basic_json_parser_60; - } - goto basic_json_parser_32; - } -basic_json_parser_52: - yych = *++m_cursor; - if (yych == 'l') - { - goto basic_json_parser_62; - } - goto basic_json_parser_32; -basic_json_parser_53: - yych = *++m_cursor; - if (yych == 'l') - { - goto basic_json_parser_63; - } - goto basic_json_parser_32; -basic_json_parser_54: - yych = *++m_cursor; - if (yych == 'u') - { - goto basic_json_parser_64; - } - goto basic_json_parser_32; -basic_json_parser_55: - ++m_cursor; - if (m_limit <= m_cursor) - { - fill_line_buffer(1); // LCOV_EXCL_LINE - } - yych = *m_cursor; - if (yych <= '@') - { - if (yych <= '/') - { - goto basic_json_parser_32; - } - if (yych <= '9') - { - goto basic_json_parser_65; - } - goto basic_json_parser_32; - } - else - { - if (yych <= 'F') - { - goto basic_json_parser_65; - } - if (yych <= '`') - { - goto basic_json_parser_32; - } - if (yych <= 'f') - { - goto basic_json_parser_65; - } - goto basic_json_parser_32; - } -basic_json_parser_56: - yyaccept = 3; - m_marker = ++m_cursor; - if ((m_limit - m_cursor) < 3) - { - fill_line_buffer(3); // LCOV_EXCL_LINE - } - yych = *m_cursor; - if (yych <= 'D') - { - if (yych <= '/') - { - goto basic_json_parser_58; - } - if (yych <= '9') - { - goto basic_json_parser_56; - } - } - else - { - if (yych <= 'E') - { - goto basic_json_parser_51; - } - if (yych == 'e') - { - goto basic_json_parser_51; - } - } -basic_json_parser_58: - { - last_token_type = token_type::value_float; - break; - } -basic_json_parser_59: - yych = *++m_cursor; - if (yych <= '/') - { - goto basic_json_parser_32; - } - if (yych >= ':') - { - goto basic_json_parser_32; - } -basic_json_parser_60: - ++m_cursor; - if (m_limit <= m_cursor) - { - fill_line_buffer(1); // LCOV_EXCL_LINE - } - yych = *m_cursor; - if (yych <= '/') - { - goto basic_json_parser_58; - } - if (yych <= '9') - { - goto basic_json_parser_60; - } - goto basic_json_parser_58; -basic_json_parser_62: - yych = *++m_cursor; - if (yych == 's') - { - goto basic_json_parser_66; - } - goto basic_json_parser_32; -basic_json_parser_63: - yych = *++m_cursor; - if (yych == 'l') - { - goto basic_json_parser_67; - } - goto basic_json_parser_32; -basic_json_parser_64: - yych = *++m_cursor; - if (yych == 'e') - { - goto basic_json_parser_69; - } - goto basic_json_parser_32; -basic_json_parser_65: - ++m_cursor; - if (m_limit <= m_cursor) - { - fill_line_buffer(1); // LCOV_EXCL_LINE - } - yych = *m_cursor; - if (yych <= '@') - { - if (yych <= '/') - { - goto basic_json_parser_32; - } - if (yych <= '9') - { - goto basic_json_parser_71; - } - goto basic_json_parser_32; - } - else - { - if (yych <= 'F') - { - goto basic_json_parser_71; - } - if (yych <= '`') - { - goto basic_json_parser_32; - } - if (yych <= 'f') - { - goto basic_json_parser_71; - } - goto basic_json_parser_32; - } -basic_json_parser_66: - yych = *++m_cursor; - if (yych == 'e') - { - goto basic_json_parser_72; - } - goto basic_json_parser_32; -basic_json_parser_67: - ++m_cursor; - { - last_token_type = token_type::literal_null; - break; - } -basic_json_parser_69: - ++m_cursor; - { - last_token_type = token_type::literal_true; - break; - } -basic_json_parser_71: - ++m_cursor; - if (m_limit <= m_cursor) - { - fill_line_buffer(1); // LCOV_EXCL_LINE - } - yych = *m_cursor; - if (yych <= '@') - { - if (yych <= '/') - { - goto basic_json_parser_32; - } - if (yych <= '9') - { - goto basic_json_parser_74; - } - goto basic_json_parser_32; - } - else - { - if (yych <= 'F') - { - goto basic_json_parser_74; - } - if (yych <= '`') - { - goto basic_json_parser_32; - } - if (yych <= 'f') - { - goto basic_json_parser_74; - } - goto basic_json_parser_32; - } -basic_json_parser_72: - ++m_cursor; - { - last_token_type = token_type::literal_false; - break; - } -basic_json_parser_74: - ++m_cursor; - if (m_limit <= m_cursor) - { - fill_line_buffer(1); // LCOV_EXCL_LINE - } - yych = *m_cursor; - if (yych <= '@') - { - if (yych <= '/') - { - goto basic_json_parser_32; - } - if (yych <= '9') - { - goto basic_json_parser_30; - } - goto basic_json_parser_32; - } - else - { - if (yych <= 'F') - { - goto basic_json_parser_30; - } - if (yych <= '`') - { - goto basic_json_parser_32; - } - if (yych <= 'f') - { - goto basic_json_parser_30; - } - goto basic_json_parser_32; - } - } - - } - - position += static_cast((m_cursor - m_start)); - return last_token_type; - } - - /*! - @brief append data from the stream to the line buffer - - This function is called by the scan() function when the end of the - buffer (`m_limit`) is reached and the `m_cursor` pointer cannot be - incremented without leaving the limits of the line buffer. Note re2c - decides when to call this function. - - If the lexer reads from contiguous storage, there is no trailing null - byte. Therefore, this function must make sure to add these padding - null bytes. - - If the lexer reads from an input stream, this function reads the next - line of the input. - - @pre - p p p p p p u u u u u x . . . . . . - ^ ^ ^ ^ - m_content m_start | m_limit - m_cursor - - @post - u u u u u x x x x x x x . . . . . . - ^ ^ ^ - | m_cursor m_limit - m_start - m_content - */ - void fill_line_buffer(size_t n = 0) - { - // if line buffer is used, m_content points to its data - assert(m_line_buffer.empty() - or m_content == reinterpret_cast(m_line_buffer.data())); - - // if line buffer is used, m_limit is set past the end of its data - assert(m_line_buffer.empty() - or m_limit == m_content + m_line_buffer.size()); - - // pointer relationships - assert(m_content <= m_start); - assert(m_start <= m_cursor); - assert(m_cursor <= m_limit); - assert(m_marker == nullptr or m_marker <= m_limit); - - // number of processed characters (p) - const auto num_processed_chars = static_cast(m_start - m_content); - // offset for m_marker wrt. to m_start - const auto offset_marker = (m_marker == nullptr) ? 0 : m_marker - m_start; - // number of unprocessed characters (u) - const auto offset_cursor = m_cursor - m_start; - - // no stream is used or end of file is reached - if (m_stream == nullptr or m_stream->eof()) - { - // m_start may or may not be pointing into m_line_buffer at - // this point. We trust the standard library to do the right - // thing. See http://stackoverflow.com/q/28142011/266378 - m_line_buffer.assign(m_start, m_limit); - - // append n characters to make sure that there is sufficient - // space between m_cursor and m_limit - m_line_buffer.append(1, '\x00'); - if (n > 0) - { - m_line_buffer.append(n - 1, '\x01'); - } - } - else - { - // delete processed characters from line buffer - m_line_buffer.erase(0, num_processed_chars); - // read next line from input stream - m_line_buffer_tmp.clear(); - - // check if stream is still good - if (m_stream->fail()) - { - JSON_THROW(parse_error::create(111, 0, "bad input stream")); - } - - std::getline(*m_stream, m_line_buffer_tmp, '\n'); - - // add line with newline symbol to the line buffer - m_line_buffer += m_line_buffer_tmp; - m_line_buffer.push_back('\n'); - } - - // set pointers - m_content = reinterpret_cast(m_line_buffer.data()); - assert(m_content != nullptr); - m_start = m_content; - m_marker = m_start + offset_marker; - m_cursor = m_start + offset_cursor; - m_limit = m_start + m_line_buffer.size(); - } - - /// return string representation of last read token - string_t get_token_string() const - { - assert(m_start != nullptr); - return string_t(reinterpret_cast(m_start), - static_cast(m_cursor - m_start)); - } - - /*! - @brief return string value for string tokens - - The function iterates the characters between the opening and closing - quotes of the string value. The complete string is the range - [m_start,m_cursor). Consequently, we iterate from m_start+1 to - m_cursor-1. - - We differentiate two cases: - - 1. Escaped characters. In this case, a new character is constructed - according to the nature of the escape. Some escapes create new - characters (e.g., `"\\n"` is replaced by `"\n"`), some are copied - as is (e.g., `"\\\\"`). Furthermore, Unicode escapes of the shape - `"\\uxxxx"` need special care. In this case, to_unicode takes care - of the construction of the values. - 2. Unescaped characters are copied as is. - - @pre `m_cursor - m_start >= 2`, meaning the length of the last token - is at least 2 bytes which is trivially true for any string (which - consists of at least two quotes). - - " c1 c2 c3 ... " - ^ ^ - m_start m_cursor - - @complexity Linear in the length of the string.\n - - Lemma: The loop body will always terminate.\n - - Proof (by contradiction): Assume the loop body does not terminate. As - the loop body does not contain another loop, one of the called - functions must never return. The called functions are `std::strtoul` - and to_unicode. Neither function can loop forever, so the loop body - will never loop forever which contradicts the assumption that the loop - body does not terminate, q.e.d.\n - - Lemma: The loop condition for the for loop is eventually false.\n - - Proof (by contradiction): Assume the loop does not terminate. Due to - the above lemma, this can only be due to a tautological loop - condition; that is, the loop condition i < m_cursor - 1 must always be - true. Let x be the change of i for any loop iteration. Then - m_start + 1 + x < m_cursor - 1 must hold to loop indefinitely. This - can be rephrased to m_cursor - m_start - 2 > x. With the - precondition, we x <= 0, meaning that the loop condition holds - indefinitely if i is always decreased. However, observe that the value - of i is strictly increasing with each iteration, as it is incremented - by 1 in the iteration expression and never decremented inside the loop - body. Hence, the loop condition will eventually be false which - contradicts the assumption that the loop condition is a tautology, - q.e.d. - - @return string value of current token without opening and closing - quotes - @throw parse_error.102 if to_unicode fails or surrogate error - @throw parse_error.103 if to_unicode fails - */ - string_t get_string() const - { - assert(m_cursor - m_start >= 2); - - string_t result; - result.reserve(static_cast(m_cursor - m_start - 2)); - - // iterate the result between the quotes - for (const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i) - { - // find next escape character - auto e = std::find(i, m_cursor - 1, '\\'); - if (e != i) - { - // see https://github.com/nlohmann/json/issues/365#issuecomment-262874705 - for (auto k = i; k < e; k++) - { - result.push_back(static_cast(*k)); - } - i = e - 1; // -1 because of ++i - } - else - { - // processing escaped character - // read next character - ++i; - - switch (*i) - { - // the default escapes - case 't': - { - result += "\t"; - break; - } - case 'b': - { - result += "\b"; - break; - } - case 'f': - { - result += "\f"; - break; - } - case 'n': - { - result += "\n"; - break; - } - case 'r': - { - result += "\r"; - break; - } - case '\\': - { - result += "\\"; - break; - } - case '/': - { - result += "/"; - break; - } - case '"': - { - result += "\""; - break; - } - - // unicode - case 'u': - { - // get code xxxx from uxxxx - auto codepoint = std::strtoul(std::string(reinterpret_cast(i + 1), - 4).c_str(), nullptr, 16); - - // check if codepoint is a high surrogate - if (codepoint >= 0xD800 and codepoint <= 0xDBFF) - { - // make sure there is a subsequent unicode - if ((i + 6 >= m_limit) or * (i + 5) != '\\' or * (i + 6) != 'u') - { - JSON_THROW(parse_error::create(102, get_position(), "missing low surrogate")); - } - - // get code yyyy from uxxxx\uyyyy - auto codepoint2 = std::strtoul(std::string(reinterpret_cast - (i + 7), 4).c_str(), nullptr, 16); - result += to_unicode(codepoint, codepoint2); - // skip the next 10 characters (xxxx\uyyyy) - i += 10; - } - else if (codepoint >= 0xDC00 and codepoint <= 0xDFFF) - { - // we found a lone low surrogate - JSON_THROW(parse_error::create(102, get_position(), "missing high surrogate")); - } - else - { - // add unicode character(s) - result += to_unicode(codepoint); - // skip the next four characters (xxxx) - i += 4; - } - break; - } - } - } - } - - return result; - } - - - /*! - @brief parse string into a built-in arithmetic type as if the current - locale is POSIX. - - @note in floating-point case strtod may parse past the token's end - - this is not an error - - @note any leading blanks are not handled - */ - struct strtonum - { - public: - strtonum(const char* start, const char* end) - : m_start(start), m_end(end) - {} - - /*! - @return true iff parsed successfully as number of type T - - @param[in,out] val shall contain parsed value, or undefined value - if could not parse - */ - template::value>::type> - bool to(T& val) const - { - return parse(val, std::is_integral()); - } - - private: - const char* const m_start = nullptr; - const char* const m_end = nullptr; - - // floating-point conversion - - // overloaded wrappers for strtod/strtof/strtold - // that will be called from parse - static void strtof(float& f, const char* str, char** endptr) - { - f = std::strtof(str, endptr); - } - - static void strtof(double& f, const char* str, char** endptr) - { - f = std::strtod(str, endptr); - } - - static void strtof(long double& f, const char* str, char** endptr) - { - f = std::strtold(str, endptr); - } - - template - bool parse(T& value, /*is_integral=*/std::false_type) const - { - // replace decimal separator with locale-specific version, - // when necessary; data will point to either the original - // string, or buf, or tempstr containing the fixed string. - std::string tempstr; - std::array buf; - const size_t len = static_cast(m_end - m_start); - - // lexer will reject empty numbers - assert(len > 0); - - // since dealing with strtod family of functions, we're - // getting the decimal point char from the C locale facilities - // instead of C++'s numpunct facet of the current std::locale - const auto loc = localeconv(); - assert(loc != nullptr); - const char decimal_point_char = (loc->decimal_point == nullptr) ? '.' : loc->decimal_point[0]; - - const char* data = m_start; - - if (decimal_point_char != '.') - { - const size_t ds_pos = static_cast(std::find(m_start, m_end, '.') - m_start); - - if (ds_pos != len) - { - // copy the data into the local buffer or tempstr, if - // buffer is too small; replace decimal separator, and - // update data to point to the modified bytes - if ((len + 1) < buf.size()) - { - std::copy(m_start, m_end, buf.begin()); - buf[len] = 0; - buf[ds_pos] = decimal_point_char; - data = buf.data(); - } - else - { - tempstr.assign(m_start, m_end); - tempstr[ds_pos] = decimal_point_char; - data = tempstr.c_str(); - } - } - } - - char* endptr = nullptr; - value = 0; - // this calls appropriate overload depending on T - strtof(value, data, &endptr); - - // parsing was successful iff strtof parsed exactly the number - // of characters determined by the lexer (len) - const bool ok = (endptr == (data + len)); - - if (ok and (value == static_cast(0.0)) and (*data == '-')) - { - // some implementations forget to negate the zero - value = -0.0; - } - - return ok; - } - - // integral conversion - - signed long long parse_integral(char** endptr, /*is_signed*/std::true_type) const - { - return std::strtoll(m_start, endptr, 10); - } - - unsigned long long parse_integral(char** endptr, /*is_signed*/std::false_type) const - { - return std::strtoull(m_start, endptr, 10); - } - - template - bool parse(T& value, /*is_integral=*/std::true_type) const - { - char* endptr = nullptr; - errno = 0; // these are thread-local - const auto x = parse_integral(&endptr, std::is_signed()); - - // called right overload? - static_assert(std::is_signed() == std::is_signed(), ""); - - value = static_cast(x); - - return (x == static_cast(value)) // x fits into destination T - and (x < 0) == (value < 0) // preserved sign - //and ((x != 0) or is_integral()) // strto[u]ll did nto fail - and (errno == 0) // strto[u]ll did not overflow - and (m_start < m_end) // token was not empty - and (endptr == m_end); // parsed entire token exactly - } - }; - - /*! - @brief return number value for number tokens - - This function translates the last token into the most appropriate - number type (either integer, unsigned integer or floating point), - which is passed back to the caller via the result parameter. - - integral numbers that don't fit into the the range of the respective - type are parsed as number_float_t - - floating-point values do not satisfy std::isfinite predicate - are converted to value_t::null - - throws if the entire string [m_start .. m_cursor) cannot be - interpreted as a number - - @param[out] result @ref basic_json object to receive the number. - @param[in] token the type of the number token - */ - bool get_number(basic_json& result, const token_type token) const - { - assert(m_start != nullptr); - assert(m_start < m_cursor); - assert((token == token_type::value_unsigned) or - (token == token_type::value_integer) or - (token == token_type::value_float)); - - strtonum num_converter(reinterpret_cast(m_start), - reinterpret_cast(m_cursor)); - - switch (token) - { - case lexer::token_type::value_unsigned: - { - number_unsigned_t val; - if (num_converter.to(val)) - { - // parsing successful - result.m_type = value_t::number_unsigned; - result.m_value = val; - return true; - } - break; - } - - case lexer::token_type::value_integer: - { - number_integer_t val; - if (num_converter.to(val)) - { - // parsing successful - result.m_type = value_t::number_integer; - result.m_value = val; - return true; - } - break; - } - - default: - { - break; - } - } - - // parse float (either explicitly or because a previous conversion - // failed) - number_float_t val; - if (num_converter.to(val)) - { - // parsing successful - result.m_type = value_t::number_float; - result.m_value = val; - - // throw in case of infinity or NAN - if (not std::isfinite(result.m_value.number_float)) - { - JSON_THROW(out_of_range::create(406, "number overflow parsing '" + get_token_string() + "'")); - } - - return true; - } - - // couldn't parse number in any format - return false; - } - - constexpr size_t get_position() const - { - return position; - } - - private: - /// optional input stream - std::istream* m_stream = nullptr; - /// line buffer buffer for m_stream - string_t m_line_buffer {}; - /// used for filling m_line_buffer - string_t m_line_buffer_tmp {}; - /// the buffer pointer - const lexer_char_t* m_content = nullptr; - /// pointer to the beginning of the current symbol - const lexer_char_t* m_start = nullptr; - /// pointer for backtracking information - const lexer_char_t* m_marker = nullptr; - /// pointer to the current symbol - const lexer_char_t* m_cursor = nullptr; - /// pointer to the end of the buffer - const lexer_char_t* m_limit = nullptr; - /// the last token type - token_type last_token_type = token_type::end_of_input; - /// current position in the input (read bytes) - size_t position = 0; - }; - - /*! - @brief syntax analysis - - This class implements a recursive decent parser. - */ - class parser - { - public: - /// a parser reading from a string literal - parser(const char* buff, const parser_callback_t cb = nullptr) - : callback(cb), - m_lexer(reinterpret_cast(buff), std::strlen(buff)) - {} - - /*! - @brief a parser reading from an input stream - @throw parse_error.111 if input stream is in a bad state - */ - parser(std::istream& is, const parser_callback_t cb = nullptr) - : callback(cb), m_lexer(is) - {} - - /// a parser reading from an iterator range with contiguous storage - template::iterator_category, std::random_access_iterator_tag>::value - , int>::type - = 0> - parser(IteratorType first, IteratorType last, const parser_callback_t cb = nullptr) - : callback(cb), - m_lexer(reinterpret_cast(&(*first)), - static_cast(std::distance(first, last))) - {} - - /*! - @brief public parser interface - @throw parse_error.101 in case of an unexpected token - @throw parse_error.102 if to_unicode fails or surrogate error - @throw parse_error.103 if to_unicode fails - */ - basic_json parse() - { - // read first token - get_token(); - - basic_json result = parse_internal(true); - result.assert_invariant(); - - expect(lexer::token_type::end_of_input); - - // return parser result and replace it with null in case the - // top-level value was discarded by the callback function - return result.is_discarded() ? basic_json() : std::move(result); - } - - private: - /*! - @brief the actual parser - @throw parse_error.101 in case of an unexpected token - @throw parse_error.102 if to_unicode fails or surrogate error - @throw parse_error.103 if to_unicode fails - */ - basic_json parse_internal(bool keep) - { - auto result = basic_json(value_t::discarded); - - switch (last_token) - { - case lexer::token_type::begin_object: - { - if (keep and (not callback - or ((keep = callback(depth++, parse_event_t::object_start, result)) != 0))) - { - // explicitly set result to object to cope with {} - result.m_type = value_t::object; - result.m_value = value_t::object; - } - - // read next token - get_token(); - - // closing } -> we are done - if (last_token == lexer::token_type::end_object) - { - get_token(); - if (keep and callback and not callback(--depth, parse_event_t::object_end, result)) - { - result = basic_json(value_t::discarded); - } - return result; - } - - // no comma is expected here - unexpect(lexer::token_type::value_separator); - - // otherwise: parse key-value pairs - do - { - // ugly, but could be fixed with loop reorganization - if (last_token == lexer::token_type::value_separator) - { - get_token(); - } - - // store key - expect(lexer::token_type::value_string); - const auto key = m_lexer.get_string(); - - bool keep_tag = false; - if (keep) - { - if (callback) - { - basic_json k(key); - keep_tag = callback(depth, parse_event_t::key, k); - } - else - { - keep_tag = true; - } - } - - // parse separator (:) - get_token(); - expect(lexer::token_type::name_separator); - - // parse and add value - get_token(); - auto value = parse_internal(keep); - if (keep and keep_tag and not value.is_discarded()) - { - result[key] = std::move(value); - } - } - while (last_token == lexer::token_type::value_separator); - - // closing } - expect(lexer::token_type::end_object); - get_token(); - if (keep and callback and not callback(--depth, parse_event_t::object_end, result)) - { - result = basic_json(value_t::discarded); - } - - return result; - } - - case lexer::token_type::begin_array: - { - if (keep and (not callback - or ((keep = callback(depth++, parse_event_t::array_start, result)) != 0))) - { - // explicitly set result to object to cope with [] - result.m_type = value_t::array; - result.m_value = value_t::array; - } - - // read next token - get_token(); - - // closing ] -> we are done - if (last_token == lexer::token_type::end_array) - { - get_token(); - if (callback and not callback(--depth, parse_event_t::array_end, result)) - { - result = basic_json(value_t::discarded); - } - return result; - } - - // no comma is expected here - unexpect(lexer::token_type::value_separator); - - // otherwise: parse values - do - { - // ugly, but could be fixed with loop reorganization - if (last_token == lexer::token_type::value_separator) - { - get_token(); - } - - // parse value - auto value = parse_internal(keep); - if (keep and not value.is_discarded()) - { - result.push_back(std::move(value)); - } - } - while (last_token == lexer::token_type::value_separator); - - // closing ] - expect(lexer::token_type::end_array); - get_token(); - if (keep and callback and not callback(--depth, parse_event_t::array_end, result)) - { - result = basic_json(value_t::discarded); - } - - return result; - } - - case lexer::token_type::literal_null: - { - get_token(); - result.m_type = value_t::null; - break; - } - - case lexer::token_type::value_string: - { - const auto s = m_lexer.get_string(); - get_token(); - result = basic_json(s); - break; - } - - case lexer::token_type::literal_true: - { - get_token(); - result.m_type = value_t::boolean; - result.m_value = true; - break; - } - - case lexer::token_type::literal_false: - { - get_token(); - result.m_type = value_t::boolean; - result.m_value = false; - break; - } - - case lexer::token_type::value_unsigned: - case lexer::token_type::value_integer: - case lexer::token_type::value_float: - { - m_lexer.get_number(result, last_token); - get_token(); - break; - } - - default: - { - // the last token was unexpected - unexpect(last_token); - } - } - - if (keep and callback and not callback(depth, parse_event_t::value, result)) - { - result = basic_json(value_t::discarded); - } - return result; - } - - /// get next token from lexer - typename lexer::token_type get_token() - { - last_token = m_lexer.scan(); - return last_token; - } - - /*! - @throw parse_error.101 if expected token did not occur - */ - void expect(typename lexer::token_type t) const - { - if (t != last_token) - { - std::string error_msg = "parse error - unexpected "; - error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token_string() + - "'") : - lexer::token_type_name(last_token)); - error_msg += "; expected " + lexer::token_type_name(t); - JSON_THROW(parse_error::create(101, m_lexer.get_position(), error_msg)); - } - } - - /*! - @throw parse_error.101 if unexpected token occurred - */ - void unexpect(typename lexer::token_type t) const - { - if (t == last_token) - { - std::string error_msg = "parse error - unexpected "; - error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token_string() + - "'") : - lexer::token_type_name(last_token)); - JSON_THROW(parse_error::create(101, m_lexer.get_position(), error_msg)); - } - } - - private: - /// current level of recursion - int depth = 0; - /// callback function - const parser_callback_t callback = nullptr; - /// the type of the last read token - typename lexer::token_type last_token = lexer::token_type::uninitialized; - /// the lexer - lexer m_lexer; - }; - - public: - /*! - @brief JSON Pointer - - A JSON pointer defines a string syntax for identifying a specific value - within a JSON document. It can be used with functions `at` and - `operator[]`. Furthermore, JSON pointers are the base for JSON patches. - - @sa [RFC 6901](https://tools.ietf.org/html/rfc6901) - - @since version 2.0.0 - */ - class json_pointer - { - /// allow basic_json to access private members - friend class basic_json; - - public: - /*! - @brief create JSON pointer - - Create a JSON pointer according to the syntax described in - [Section 3 of RFC6901](https://tools.ietf.org/html/rfc6901#section-3). - - @param[in] s string representing the JSON pointer; if omitted, the - empty string is assumed which references the whole JSON - value - - @throw parse_error.107 if the given JSON pointer @a s is nonempty and - does not begin with a slash (`/`); see example below - - @throw parse_error.108 if a tilde (`~`) in the given JSON pointer @a s - is not followed by `0` (representing `~`) or `1` (representing `/`); - see example below - - @liveexample{The example shows the construction several valid JSON - pointers as well as the exceptional behavior.,json_pointer} - - @since version 2.0.0 - */ - explicit json_pointer(const std::string& s = "") - : reference_tokens(split(s)) - {} - - /*! - @brief return a string representation of the JSON pointer - - @invariant For each JSON pointer `ptr`, it holds: - @code {.cpp} - ptr == json_pointer(ptr.to_string()); - @endcode - - @return a string representation of the JSON pointer - - @liveexample{The example shows the result of `to_string`., - json_pointer__to_string} - - @since version 2.0.0 - */ - std::string to_string() const noexcept - { - return std::accumulate(reference_tokens.begin(), - reference_tokens.end(), std::string{}, - [](const std::string & a, const std::string & b) - { - return a + "/" + escape(b); - }); - } - - /// @copydoc to_string() - operator std::string() const - { - return to_string(); - } - - private: - /*! - @brief remove and return last reference pointer - @throw out_of_range.405 if JSON pointer has no parent - */ - std::string pop_back() - { - if (is_root()) - { - JSON_THROW(out_of_range::create(405, "JSON pointer has no parent")); - } - - auto last = reference_tokens.back(); - reference_tokens.pop_back(); - return last; - } - - /// return whether pointer points to the root document - bool is_root() const - { - return reference_tokens.empty(); - } - - json_pointer top() const - { - if (is_root()) - { - JSON_THROW(out_of_range::create(405, "JSON pointer has no parent")); - } - - json_pointer result = *this; - result.reference_tokens = {reference_tokens[0]}; - return result; - } - - /*! - @brief create and return a reference to the pointed to value - - @complexity Linear in the number of reference tokens. - - @throw parse_error.109 if array index is not a number - @throw type_error.313 if value cannot be unflattened - */ - reference get_and_create(reference j) const - { - pointer result = &j; - - // in case no reference tokens exist, return a reference to the - // JSON value j which will be overwritten by a primitive value - for (const auto& reference_token : reference_tokens) - { - switch (result->m_type) - { - case value_t::null: - { - if (reference_token == "0") - { - // start a new array if reference token is 0 - result = &result->operator[](0); - } - else - { - // start a new object otherwise - result = &result->operator[](reference_token); - } - break; - } - - case value_t::object: - { - // create an entry in the object - result = &result->operator[](reference_token); - break; - } - - case value_t::array: - { - // create an entry in the array - JSON_TRY - { - result = &result->operator[](static_cast(std::stoi(reference_token))); - } - JSON_CATCH (std::invalid_argument&) - { - JSON_THROW(parse_error::create(109, 0, "array index '" + reference_token + "' is not a number")); - } - break; - } - - /* - The following code is only reached if there exists a - reference token _and_ the current value is primitive. In - this case, we have an error situation, because primitive - values may only occur as single value; that is, with an - empty list of reference tokens. - */ - default: - { - JSON_THROW(type_error::create(313, "invalid value to unflatten")); - } - } - } - - return *result; - } - - /*! - @brief return a reference to the pointed to value - - @note This version does not throw if a value is not present, but tries - to create nested values instead. For instance, calling this function - with pointer `"/this/that"` on a null value is equivalent to calling - `operator[]("this").operator[]("that")` on that value, effectively - changing the null value to an object. - - @param[in] ptr a JSON value - - @return reference to the JSON value pointed to by the JSON pointer - - @complexity Linear in the length of the JSON pointer. - - @throw parse_error.106 if an array index begins with '0' - @throw parse_error.109 if an array index was not a number - @throw out_of_range.404 if the JSON pointer can not be resolved - */ - reference get_unchecked(pointer ptr) const - { - for (const auto& reference_token : reference_tokens) - { - // convert null values to arrays or objects before continuing - if (ptr->m_type == value_t::null) - { - // check if reference token is a number - const bool nums = std::all_of(reference_token.begin(), - reference_token.end(), - [](const char x) - { - return (x >= '0' and x <= '9'); - }); - - // change value to array for numbers or "-" or to object - // otherwise - if (nums or reference_token == "-") - { - *ptr = value_t::array; - } - else - { - *ptr = value_t::object; - } - } - - switch (ptr->m_type) - { - case value_t::object: - { - // use unchecked object access - ptr = &ptr->operator[](reference_token); - break; - } - - case value_t::array: - { - // error condition (cf. RFC 6901, Sect. 4) - if (reference_token.size() > 1 and reference_token[0] == '0') - { - JSON_THROW(parse_error::create(106, 0, "array index '" + reference_token + "' must not begin with '0'")); - } - - if (reference_token == "-") - { - // explicitly treat "-" as index beyond the end - ptr = &ptr->operator[](ptr->m_value.array->size()); - } - else - { - // convert array index to number; unchecked access - JSON_TRY - { - ptr = &ptr->operator[](static_cast(std::stoi(reference_token))); - } - JSON_CATCH (std::invalid_argument&) - { - JSON_THROW(parse_error::create(109, 0, "array index '" + reference_token + "' is not a number")); - } - } - break; - } - - default: - { - JSON_THROW(out_of_range::create(404, "unresolved reference token '" + reference_token + "'")); - } - } - } - - return *ptr; - } - - /*! - @throw parse_error.106 if an array index begins with '0' - @throw parse_error.109 if an array index was not a number - @throw out_of_range.402 if the array index '-' is used - @throw out_of_range.404 if the JSON pointer can not be resolved - */ - reference get_checked(pointer ptr) const - { - for (const auto& reference_token : reference_tokens) - { - switch (ptr->m_type) - { - case value_t::object: - { - // note: at performs range check - ptr = &ptr->at(reference_token); - break; - } - - case value_t::array: - { - if (reference_token == "-") - { - // "-" always fails the range check - JSON_THROW(out_of_range::create(402, "array index '-' (" + - std::to_string(ptr->m_value.array->size()) + - ") is out of range")); - } - - // error condition (cf. RFC 6901, Sect. 4) - if (reference_token.size() > 1 and reference_token[0] == '0') - { - JSON_THROW(parse_error::create(106, 0, "array index '" + reference_token + "' must not begin with '0'")); - } - - // note: at performs range check - JSON_TRY - { - ptr = &ptr->at(static_cast(std::stoi(reference_token))); - } - JSON_CATCH (std::invalid_argument&) - { - JSON_THROW(parse_error::create(109, 0, "array index '" + reference_token + "' is not a number")); - } - break; - } - - default: - { - JSON_THROW(out_of_range::create(404, "unresolved reference token '" + reference_token + "'")); - } - } - } - - return *ptr; - } - - /*! - @brief return a const reference to the pointed to value - - @param[in] ptr a JSON value - - @return const reference to the JSON value pointed to by the JSON - pointer - - @throw parse_error.106 if an array index begins with '0' - @throw parse_error.109 if an array index was not a number - @throw out_of_range.402 if the array index '-' is used - @throw out_of_range.404 if the JSON pointer can not be resolved - */ - const_reference get_unchecked(const_pointer ptr) const - { - for (const auto& reference_token : reference_tokens) - { - switch (ptr->m_type) - { - case value_t::object: - { - // use unchecked object access - ptr = &ptr->operator[](reference_token); - break; - } - - case value_t::array: - { - if (reference_token == "-") - { - // "-" cannot be used for const access - JSON_THROW(out_of_range::create(402, "array index '-' (" + - std::to_string(ptr->m_value.array->size()) + - ") is out of range")); - } - - // error condition (cf. RFC 6901, Sect. 4) - if (reference_token.size() > 1 and reference_token[0] == '0') - { - JSON_THROW(parse_error::create(106, 0, "array index '" + reference_token + "' must not begin with '0'")); - } - - // use unchecked array access - JSON_TRY - { - ptr = &ptr->operator[](static_cast(std::stoi(reference_token))); - } - JSON_CATCH (std::invalid_argument&) - { - JSON_THROW(parse_error::create(109, 0, "array index '" + reference_token + "' is not a number")); - } - break; - } - - default: - { - JSON_THROW(out_of_range::create(404, "unresolved reference token '" + reference_token + "'")); - } - } - } - - return *ptr; - } - - /*! - @throw parse_error.106 if an array index begins with '0' - @throw parse_error.109 if an array index was not a number - @throw out_of_range.402 if the array index '-' is used - @throw out_of_range.404 if the JSON pointer can not be resolved - */ - const_reference get_checked(const_pointer ptr) const - { - for (const auto& reference_token : reference_tokens) - { - switch (ptr->m_type) - { - case value_t::object: - { - // note: at performs range check - ptr = &ptr->at(reference_token); - break; - } - - case value_t::array: - { - if (reference_token == "-") - { - // "-" always fails the range check - JSON_THROW(out_of_range::create(402, "array index '-' (" + - std::to_string(ptr->m_value.array->size()) + - ") is out of range")); - } - - // error condition (cf. RFC 6901, Sect. 4) - if (reference_token.size() > 1 and reference_token[0] == '0') - { - JSON_THROW(parse_error::create(106, 0, "array index '" + reference_token + "' must not begin with '0'")); - } - - // note: at performs range check - JSON_TRY - { - ptr = &ptr->at(static_cast(std::stoi(reference_token))); - } - JSON_CATCH (std::invalid_argument&) - { - JSON_THROW(parse_error::create(109, 0, "array index '" + reference_token + "' is not a number")); - } - break; - } - - default: - { - JSON_THROW(out_of_range::create(404, "unresolved reference token '" + reference_token + "'")); - } - } - } - - return *ptr; - } - - /*! - @brief split the string input to reference tokens - - @note This function is only called by the json_pointer constructor. - All exceptions below are documented there. - - @throw parse_error.107 if the pointer is not empty or begins with '/' - @throw parse_error.108 if character '~' is not followed by '0' or '1' - */ - static std::vector split(const std::string& reference_string) - { - std::vector result; - - // special case: empty reference string -> no reference tokens - if (reference_string.empty()) - { - return result; - } - - // check if nonempty reference string begins with slash - if (reference_string[0] != '/') - { - JSON_THROW(parse_error::create(107, 1, "JSON pointer must be empty or begin with '/' - was: '" + reference_string + "'")); - } - - // extract the reference tokens: - // - slash: position of the last read slash (or end of string) - // - start: position after the previous slash - for ( - // search for the first slash after the first character - size_t slash = reference_string.find_first_of('/', 1), - // set the beginning of the first reference token - start = 1; - // we can stop if start == string::npos+1 = 0 - start != 0; - // set the beginning of the next reference token - // (will eventually be 0 if slash == std::string::npos) - start = slash + 1, - // find next slash - slash = reference_string.find_first_of('/', start)) - { - // use the text between the beginning of the reference token - // (start) and the last slash (slash). - auto reference_token = reference_string.substr(start, slash - start); - - // check reference tokens are properly escaped - for (size_t pos = reference_token.find_first_of('~'); - pos != std::string::npos; - pos = reference_token.find_first_of('~', pos + 1)) - { - assert(reference_token[pos] == '~'); - - // ~ must be followed by 0 or 1 - if (pos == reference_token.size() - 1 or - (reference_token[pos + 1] != '0' and - reference_token[pos + 1] != '1')) - { - JSON_THROW(parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'")); - } - } - - // finally, store the reference token - unescape(reference_token); - result.push_back(reference_token); - } - - return result; - } - - /*! - @brief replace all occurrences of a substring by another string - - @param[in,out] s the string to manipulate; changed so that all - occurrences of @a f are replaced with @a t - @param[in] f the substring to replace with @a t - @param[in] t the string to replace @a f - - @pre The search string @a f must not be empty. **This precondition is - enforced with an assertion.** - - @since version 2.0.0 - */ - static void replace_substring(std::string& s, - const std::string& f, - const std::string& t) - { - assert(not f.empty()); - - for ( - size_t pos = s.find(f); // find first occurrence of f - pos != std::string::npos; // make sure f was found - s.replace(pos, f.size(), t), // replace with t - pos = s.find(f, pos + t.size()) // find next occurrence of f - ); - } - - /// escape tilde and slash - static std::string escape(std::string s) - { - // escape "~"" to "~0" and "/" to "~1" - replace_substring(s, "~", "~0"); - replace_substring(s, "/", "~1"); - return s; - } - - /// unescape tilde and slash - static void unescape(std::string& s) - { - // first transform any occurrence of the sequence '~1' to '/' - replace_substring(s, "~1", "/"); - // then transform any occurrence of the sequence '~0' to '~' - replace_substring(s, "~0", "~"); - } - - /*! - @param[in] reference_string the reference string to the current value - @param[in] value the value to consider - @param[in,out] result the result object to insert values to - - @note Empty objects or arrays are flattened to `null`. - */ - static void flatten(const std::string& reference_string, - const basic_json& value, - basic_json& result) - { - switch (value.m_type) - { - case value_t::array: - { - if (value.m_value.array->empty()) - { - // flatten empty array as null - result[reference_string] = nullptr; - } - else - { - // iterate array and use index as reference string - for (size_t i = 0; i < value.m_value.array->size(); ++i) - { - flatten(reference_string + "/" + std::to_string(i), - value.m_value.array->operator[](i), result); - } - } - break; - } - - case value_t::object: - { - if (value.m_value.object->empty()) - { - // flatten empty object as null - result[reference_string] = nullptr; - } - else - { - // iterate object and use keys as reference string - for (const auto& element : *value.m_value.object) - { - flatten(reference_string + "/" + escape(element.first), - element.second, result); - } - } - break; - } - - default: - { - // add primitive value with its reference string - result[reference_string] = value; - break; - } - } - } - - /*! - @param[in] value flattened JSON - - @return unflattened JSON - - @throw parse_error.109 if array index is not a number - @throw type_error.314 if value is not an object - @throw type_error.315 if object values are not primitive - @throw type_error.313 if value cannot be unflattened - */ - static basic_json unflatten(const basic_json& value) - { - if (not value.is_object()) - { - JSON_THROW(type_error::create(314, "only objects can be unflattened")); - } - - basic_json result; - - // iterate the JSON object values - for (const auto& element : *value.m_value.object) - { - if (not element.second.is_primitive()) - { - JSON_THROW(type_error::create(315, "values in object must be primitive")); - } - - // assign value to reference pointed to by JSON pointer; Note - // that if the JSON pointer is "" (i.e., points to the whole - // value), function get_and_create returns a reference to - // result itself. An assignment will then create a primitive - // value. - json_pointer(element.first).get_and_create(result) = element.second; - } - - return result; - } - - friend bool operator==(json_pointer const& lhs, - json_pointer const& rhs) noexcept - { - return lhs.reference_tokens == rhs.reference_tokens; - } - - friend bool operator!=(json_pointer const& lhs, - json_pointer const& rhs) noexcept - { - return !(lhs == rhs); - } - - /// the reference tokens - std::vector reference_tokens {}; - }; - - ////////////////////////// - // JSON Pointer support // - ////////////////////////// - - /// @name JSON Pointer functions - /// @{ - - /*! - @brief access specified element via JSON Pointer - - Uses a JSON pointer to retrieve a reference to the respective JSON value. - No bound checking is performed. Similar to @ref operator[](const typename - object_t::key_type&), `null` values are created in arrays and objects if - necessary. - - In particular: - - If the JSON pointer points to an object key that does not exist, it - is created an filled with a `null` value before a reference to it - is returned. - - If the JSON pointer points to an array index that does not exist, it - is created an filled with a `null` value before a reference to it - is returned. All indices between the current maximum and the given - index are also filled with `null`. - - The special value `-` is treated as a synonym for the index past the - end. - - @param[in] ptr a JSON pointer - - @return reference to the element pointed to by @a ptr - - @complexity Constant. - - @throw parse_error.106 if an array index begins with '0' - @throw parse_error.109 if an array index was not a number - @throw out_of_range.404 if the JSON pointer can not be resolved - - @liveexample{The behavior is shown in the example.,operatorjson_pointer} - - @since version 2.0.0 - */ - reference operator[](const json_pointer& ptr) - { - return ptr.get_unchecked(this); - } - - /*! - @brief access specified element via JSON Pointer - - Uses a JSON pointer to retrieve a reference to the respective JSON value. - No bound checking is performed. The function does not change the JSON - value; no `null` values are created. In particular, the the special value - `-` yields an exception. - - @param[in] ptr JSON pointer to the desired element - - @return const reference to the element pointed to by @a ptr - - @complexity Constant. - - @throw parse_error.106 if an array index begins with '0' - @throw parse_error.109 if an array index was not a number - @throw out_of_range.402 if the array index '-' is used - @throw out_of_range.404 if the JSON pointer can not be resolved - - @liveexample{The behavior is shown in the example.,operatorjson_pointer_const} - - @since version 2.0.0 - */ - const_reference operator[](const json_pointer& ptr) const - { - return ptr.get_unchecked(this); - } - - /*! - @brief access specified element via JSON Pointer - - Returns a reference to the element at with specified JSON pointer @a ptr, - with bounds checking. - - @param[in] ptr JSON pointer to the desired element - - @return reference to the element pointed to by @a ptr - - @throw parse_error.106 if an array index in the passed JSON pointer @a ptr - begins with '0'. See example below. - - @throw parse_error.109 if an array index in the passed JSON pointer @a ptr - is not a number. See example below. - - @throw out_of_range.401 if an array index in the passed JSON pointer @a ptr - is out of range. See example below. - - @throw out_of_range.402 if the array index '-' is used in the passed JSON - pointer @a ptr. As `at` provides checked access (and no elements are - implicitly inserted), the index '-' is always invalid. See example below. - - @throw out_of_range.404 if the JSON pointer @a ptr can not be resolved. - See example below. - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes in the JSON value. - - @complexity Constant. - - @since version 2.0.0 - - @liveexample{The behavior is shown in the example.,at_json_pointer} - */ - reference at(const json_pointer& ptr) - { - return ptr.get_checked(this); - } - - /*! - @brief access specified element via JSON Pointer - - Returns a const reference to the element at with specified JSON pointer @a - ptr, with bounds checking. - - @param[in] ptr JSON pointer to the desired element - - @return reference to the element pointed to by @a ptr - - @throw parse_error.106 if an array index in the passed JSON pointer @a ptr - begins with '0'. See example below. - - @throw parse_error.109 if an array index in the passed JSON pointer @a ptr - is not a number. See example below. - - @throw out_of_range.401 if an array index in the passed JSON pointer @a ptr - is out of range. See example below. - - @throw out_of_range.402 if the array index '-' is used in the passed JSON - pointer @a ptr. As `at` provides checked access (and no elements are - implicitly inserted), the index '-' is always invalid. See example below. - - @throw out_of_range.404 if the JSON pointer @a ptr can not be resolved. - See example below. - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes in the JSON value. - - @complexity Constant. - - @since version 2.0.0 - - @liveexample{The behavior is shown in the example.,at_json_pointer_const} - */ - const_reference at(const json_pointer& ptr) const - { - return ptr.get_checked(this); - } - - /*! - @brief return flattened JSON value - - The function creates a JSON object whose keys are JSON pointers (see [RFC - 6901](https://tools.ietf.org/html/rfc6901)) and whose values are all - primitive. The original JSON value can be restored using the @ref - unflatten() function. - - @return an object that maps JSON pointers to primitive values - - @note Empty objects and arrays are flattened to `null` and will not be - reconstructed correctly by the @ref unflatten() function. - - @complexity Linear in the size the JSON value. - - @liveexample{The following code shows how a JSON object is flattened to an - object whose keys consist of JSON pointers.,flatten} - - @sa @ref unflatten() for the reverse function - - @since version 2.0.0 - */ - basic_json flatten() const - { - basic_json result(value_t::object); - json_pointer::flatten("", *this, result); - return result; - } - - /*! - @brief unflatten a previously flattened JSON value - - The function restores the arbitrary nesting of a JSON value that has been - flattened before using the @ref flatten() function. The JSON value must - meet certain constraints: - 1. The value must be an object. - 2. The keys must be JSON pointers (see - [RFC 6901](https://tools.ietf.org/html/rfc6901)) - 3. The mapped values must be primitive JSON types. - - @return the original JSON from a flattened version - - @note Empty objects and arrays are flattened by @ref flatten() to `null` - values and can not unflattened to their original type. Apart from - this example, for a JSON value `j`, the following is always true: - `j == j.flatten().unflatten()`. - - @complexity Linear in the size the JSON value. - - @throw type_error.314 if value is not an object - @throw type_error.315 if object values are not primitve - - @liveexample{The following code shows how a flattened JSON object is - unflattened into the original nested JSON object.,unflatten} - - @sa @ref flatten() for the reverse function - - @since version 2.0.0 - */ - basic_json unflatten() const - { - return json_pointer::unflatten(*this); - } - - /// @} - - ////////////////////////// - // JSON Patch functions // - ////////////////////////// - - /// @name JSON Patch functions - /// @{ - - /*! - @brief applies a JSON patch - - [JSON Patch](http://jsonpatch.com) defines a JSON document structure for - expressing a sequence of operations to apply to a JSON) document. With - this function, a JSON Patch is applied to the current JSON value by - executing all operations from the patch. - - @param[in] json_patch JSON patch document - @return patched document - - @note The application of a patch is atomic: Either all operations succeed - and the patched document is returned or an exception is thrown. In - any case, the original value is not changed: the patch is applied - to a copy of the value. - - @throw parse_error.104 if the JSON patch does not consist of an array of - objects - - @throw parse_error.105 if the JSON patch is malformed (e.g., mandatory - attributes are missing); example: `"operation add must have member path"` - - @throw out_of_range.401 if an array index is out of range. - - @throw out_of_range.403 if a JSON pointer inside the patch could not be - resolved successfully in the current JSON value; example: `"key baz not - found"` - - @throw out_of_range.405 if JSON pointer has no parent ("add", "remove", - "move") - - @throw other_error.501 if "test" operation was unsuccessful - - @complexity Linear in the size of the JSON value and the length of the - JSON patch. As usually only a fraction of the JSON value is affected by - the patch, the complexity can usually be neglected. - - @liveexample{The following code shows how a JSON patch is applied to a - value.,patch} - - @sa @ref diff -- create a JSON patch by comparing two JSON values - - @sa [RFC 6902 (JSON Patch)](https://tools.ietf.org/html/rfc6902) - @sa [RFC 6901 (JSON Pointer)](https://tools.ietf.org/html/rfc6901) - - @since version 2.0.0 - */ - basic_json patch(const basic_json& json_patch) const - { - // make a working copy to apply the patch to - basic_json result = *this; - - // the valid JSON Patch operations - enum class patch_operations {add, remove, replace, move, copy, test, invalid}; - - const auto get_op = [](const std::string & op) - { - if (op == "add") - { - return patch_operations::add; - } - if (op == "remove") - { - return patch_operations::remove; - } - if (op == "replace") - { - return patch_operations::replace; - } - if (op == "move") - { - return patch_operations::move; - } - if (op == "copy") - { - return patch_operations::copy; - } - if (op == "test") - { - return patch_operations::test; - } - - return patch_operations::invalid; - }; - - // wrapper for "add" operation; add value at ptr - const auto operation_add = [&result](json_pointer & ptr, basic_json val) - { - // adding to the root of the target document means replacing it - if (ptr.is_root()) - { - result = val; - } - else - { - // make sure the top element of the pointer exists - json_pointer top_pointer = ptr.top(); - if (top_pointer != ptr) - { - result.at(top_pointer); - } - - // get reference to parent of JSON pointer ptr - const auto last_path = ptr.pop_back(); - basic_json& parent = result[ptr]; - - switch (parent.m_type) - { - case value_t::null: - case value_t::object: - { - // use operator[] to add value - parent[last_path] = val; - break; - } - - case value_t::array: - { - if (last_path == "-") - { - // special case: append to back - parent.push_back(val); - } - else - { - const auto idx = std::stoi(last_path); - if (static_cast(idx) > parent.size()) - { - // avoid undefined behavior - JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range")); - } - else - { - // default case: insert add offset - parent.insert(parent.begin() + static_cast(idx), val); - } - } - break; - } - - default: - { - // if there exists a parent it cannot be primitive - assert(false); // LCOV_EXCL_LINE - } - } - } - }; - - // wrapper for "remove" operation; remove value at ptr - const auto operation_remove = [&result](json_pointer & ptr) - { - // get reference to parent of JSON pointer ptr - const auto last_path = ptr.pop_back(); - basic_json& parent = result.at(ptr); - - // remove child - if (parent.is_object()) - { - // perform range check - auto it = parent.find(last_path); - if (it != parent.end()) - { - parent.erase(it); - } - else - { - JSON_THROW(out_of_range::create(403, "key '" + last_path + "' not found")); - } - } - else if (parent.is_array()) - { - // note erase performs range check - parent.erase(static_cast(std::stoi(last_path))); - } - }; - - // type check: top level value must be an array - if (not json_patch.is_array()) - { - JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects")); - } - - // iterate and apply the operations - for (const auto& val : json_patch) - { - // wrapper to get a value for an operation - const auto get_value = [&val](const std::string & op, - const std::string & member, - bool string_type) -> basic_json& - { - // find value - auto it = val.m_value.object->find(member); - - // context-sensitive error message - const auto error_msg = (op == "op") ? "operation" : "operation '" + op + "'"; - - // check if desired value is present - if (it == val.m_value.object->end()) - { - JSON_THROW(parse_error::create(105, 0, error_msg + " must have member '" + member + "'")); - } - - // check if result is of type string - if (string_type and not it->second.is_string()) - { - JSON_THROW(parse_error::create(105, 0, error_msg + " must have string member '" + member + "'")); - } - - // no error: return value - return it->second; - }; - - // type check: every element of the array must be an object - if (not val.is_object()) - { - JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects")); - } - - // collect mandatory members - const std::string op = get_value("op", "op", true); - const std::string path = get_value(op, "path", true); - json_pointer ptr(path); - - switch (get_op(op)) - { - case patch_operations::add: - { - operation_add(ptr, get_value("add", "value", false)); - break; - } - - case patch_operations::remove: - { - operation_remove(ptr); - break; - } - - case patch_operations::replace: - { - // the "path" location must exist - use at() - result.at(ptr) = get_value("replace", "value", false); - break; - } - - case patch_operations::move: - { - const std::string from_path = get_value("move", "from", true); - json_pointer from_ptr(from_path); - - // the "from" location must exist - use at() - basic_json v = result.at(from_ptr); - - // The move operation is functionally identical to a - // "remove" operation on the "from" location, followed - // immediately by an "add" operation at the target - // location with the value that was just removed. - operation_remove(from_ptr); - operation_add(ptr, v); - break; - } - - case patch_operations::copy: - { - const std::string from_path = get_value("copy", "from", true);; - const json_pointer from_ptr(from_path); - - // the "from" location must exist - use at() - result[ptr] = result.at(from_ptr); - break; - } - - case patch_operations::test: - { - bool success = false; - JSON_TRY - { - // check if "value" matches the one at "path" - // the "path" location must exist - use at() - success = (result.at(ptr) == get_value("test", "value", false)); - } - JSON_CATCH (out_of_range&) - { - // ignore out of range errors: success remains false - } - - // throw an exception if test fails - if (not success) - { - JSON_THROW(other_error::create(501, "unsuccessful: " + val.dump())); - } - - break; - } - - case patch_operations::invalid: - { - // op must be "add", "remove", "replace", "move", "copy", or - // "test" - JSON_THROW(parse_error::create(105, 0, "operation value '" + op + "' is invalid")); - } - } - } - - return result; - } - - /*! - @brief creates a diff as a JSON patch - - Creates a [JSON Patch](http://jsonpatch.com) so that value @a source can - be changed into the value @a target by calling @ref patch function. - - @invariant For two JSON values @a source and @a target, the following code - yields always `true`: - @code {.cpp} - source.patch(diff(source, target)) == target; - @endcode - - @note Currently, only `remove`, `add`, and `replace` operations are - generated. - - @param[in] source JSON value to compare from - @param[in] target JSON value to compare against - @param[in] path helper value to create JSON pointers - - @return a JSON patch to convert the @a source to @a target - - @complexity Linear in the lengths of @a source and @a target. - - @liveexample{The following code shows how a JSON patch is created as a - diff for two JSON values.,diff} - - @sa @ref patch -- apply a JSON patch - - @sa [RFC 6902 (JSON Patch)](https://tools.ietf.org/html/rfc6902) - - @since version 2.0.0 - */ - static basic_json diff(const basic_json& source, - const basic_json& target, - const std::string& path = "") - { - // the patch - basic_json result(value_t::array); - - // if the values are the same, return empty patch - if (source == target) - { - return result; - } - - if (source.type() != target.type()) - { - // different types: replace value - result.push_back( - { - {"op", "replace"}, - {"path", path}, - {"value", target} - }); - } - else - { - switch (source.type()) - { - case value_t::array: - { - // first pass: traverse common elements - size_t i = 0; - while (i < source.size() and i < target.size()) - { - // recursive call to compare array values at index i - auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i)); - result.insert(result.end(), temp_diff.begin(), temp_diff.end()); - ++i; - } - - // i now reached the end of at least one array - // in a second pass, traverse the remaining elements - - // remove my remaining elements - const auto end_index = static_cast(result.size()); - while (i < source.size()) - { - // add operations in reverse order to avoid invalid - // indices - result.insert(result.begin() + end_index, object( - { - {"op", "remove"}, - {"path", path + "/" + std::to_string(i)} - })); - ++i; - } - - // add other remaining elements - while (i < target.size()) - { - result.push_back( - { - {"op", "add"}, - {"path", path + "/" + std::to_string(i)}, - {"value", target[i]} - }); - ++i; - } - - break; - } - - case value_t::object: - { - // first pass: traverse this object's elements - for (auto it = source.begin(); it != source.end(); ++it) - { - // escape the key name to be used in a JSON patch - const auto key = json_pointer::escape(it.key()); - - if (target.find(it.key()) != target.end()) - { - // recursive call to compare object values at key it - auto temp_diff = diff(it.value(), target[it.key()], path + "/" + key); - result.insert(result.end(), temp_diff.begin(), temp_diff.end()); - } - else - { - // found a key that is not in o -> remove it - result.push_back(object( - { - {"op", "remove"}, - {"path", path + "/" + key} - })); - } - } - - // second pass: traverse other object's elements - for (auto it = target.begin(); it != target.end(); ++it) - { - if (source.find(it.key()) == source.end()) - { - // found a key that is not in this -> add it - const auto key = json_pointer::escape(it.key()); - result.push_back( - { - {"op", "add"}, - {"path", path + "/" + key}, - {"value", it.value()} - }); - } - } - - break; - } - - default: - { - // both primitive type: replace value - result.push_back( - { - {"op", "replace"}, - {"path", path}, - {"value", target} - }); - break; - } - } - } - - return result; - } - - /// @} -}; - -///////////// -// presets // -///////////// - -/*! -@brief default JSON class - -This type is the default specialization of the @ref basic_json class which -uses the standard template types. - -@since version 1.0.0 -*/ -using json = basic_json<>; -} // namespace nlohmann - - -/////////////////////// -// nonmember support // -/////////////////////// - -// specialization of std::swap, and std::hash -namespace std -{ -/*! -@brief exchanges the values of two JSON objects - -@since version 1.0.0 -*/ -template<> -inline void swap(nlohmann::json& j1, - nlohmann::json& j2) noexcept( - is_nothrow_move_constructible::value and - is_nothrow_move_assignable::value - ) -{ - j1.swap(j2); -} - -/// hash value for JSON objects -template<> -struct hash -{ - /*! - @brief return a hash value for a JSON object - - @since version 1.0.0 - */ - std::size_t operator()(const nlohmann::json& j) const - { - // a naive hashing via the string representation - const auto& h = hash(); - return h(j.dump()); - } -}; - -/// specialization for std::less -template <> -struct less<::nlohmann::detail::value_t> -{ - /*! - @brief compare two value_t enum values - @since version 3.0.0 - */ - bool operator()(nlohmann::detail::value_t lhs, - nlohmann::detail::value_t rhs) const noexcept - { - return nlohmann::detail::operator<(lhs, rhs); - } -}; - -} // namespace std - -/*! -@brief user-defined string literal for JSON values - -This operator implements a user-defined string literal for JSON objects. It -can be used by adding `"_json"` to a string literal and returns a JSON object -if no parse error occurred. - -@param[in] s a string representation of a JSON object -@param[in] n the length of string @a s -@return a JSON object - -@since version 1.0.0 -*/ -inline nlohmann::json operator "" _json(const char* s, std::size_t n) -{ - return nlohmann::json::parse(s, s + n); -} - -/*! -@brief user-defined string literal for JSON pointer - -This operator implements a user-defined string literal for JSON Pointers. It -can be used by adding `"_json_pointer"` to a string literal and returns a JSON pointer -object if no parse error occurred. - -@param[in] s a string representation of a JSON Pointer -@param[in] n the length of string @a s -@return a JSON pointer object - -@since version 2.0.0 -*/ -inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n) -{ - return nlohmann::json::json_pointer(std::string(s, n)); -} - -// restore GCC/clang diagnostic settings -#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) - #pragma GCC diagnostic pop -#endif -#if defined(__clang__) - #pragma GCC diagnostic pop -#endif - -// clean up -#undef JSON_CATCH -#undef JSON_THROW -#undef JSON_TRY -#undef JSON_DEPRECATED - -#endif diff --git a/vendor/json/src/json.hpp.re2c b/vendor/json/src/json.hpp.re2c deleted file mode 100644 index 9903aa49d..000000000 --- a/vendor/json/src/json.hpp.re2c +++ /dev/null @@ -1,13064 +0,0 @@ -/* - __ _____ _____ _____ - __| | __| | | | JSON for Modern C++ -| | |__ | | | | | | version 2.1.1 -|_____|_____|_____|_|___| https://github.com/nlohmann/json - -Licensed under the MIT License . -Copyright (c) 2013-2017 Niels Lohmann . - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -#ifndef NLOHMANN_JSON_HPP -#define NLOHMANN_JSON_HPP - -#include // all_of, copy, fill, find, for_each, none_of, remove, reverse, transform -#include // array -#include // assert -#include // and, not, or -#include // lconv, localeconv -#include // isfinite, labs, ldexp, signbit -#include // nullptr_t, ptrdiff_t, size_t -#include // int64_t, uint64_t -#include // abort, strtod, strtof, strtold, strtoul, strtoll, strtoull -#include // strlen -#include // forward_list -#include // function, hash, less -#include // initializer_list -#include // istream, ostream -#include // advance, begin, back_inserter, bidirectional_iterator_tag, distance, end, inserter, iterator, iterator_traits, next, random_access_iterator_tag, reverse_iterator -#include // numeric_limits -#include // locale -#include // map -#include // addressof, allocator, allocator_traits, unique_ptr -#include // accumulate -#include // stringstream -#include // getline, stoi, string, to_string -#include // add_pointer, conditional, decay, enable_if, false_type, integral_constant, is_arithmetic, is_base_of, is_const, is_constructible, is_convertible, is_default_constructible, is_enum, is_floating_point, is_integral, is_nothrow_move_assignable, is_nothrow_move_constructible, is_pointer, is_reference, is_same, is_scalar, is_signed, remove_const, remove_cv, remove_pointer, remove_reference, true_type, underlying_type -#include // declval, forward, make_pair, move, pair, swap -#include // vector - -// exclude unsupported compilers -#if defined(__clang__) - #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400 - #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" - #endif -#elif defined(__GNUC__) - #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40900 - #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" - #endif -#endif - -// disable float-equal warnings on GCC/clang -#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wfloat-equal" -#endif - -// disable documentation warnings on clang -#if defined(__clang__) - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wdocumentation" -#endif - -// allow for portable deprecation warnings -#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) - #define JSON_DEPRECATED __attribute__((deprecated)) -#elif defined(_MSC_VER) - #define JSON_DEPRECATED __declspec(deprecated) -#else - #define JSON_DEPRECATED -#endif - -// allow to disable exceptions -#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && not defined(JSON_NOEXCEPTION) - #define JSON_THROW(exception) throw exception - #define JSON_TRY try - #define JSON_CATCH(exception) catch(exception) -#else - #define JSON_THROW(exception) std::abort() - #define JSON_TRY if(true) - #define JSON_CATCH(exception) if(false) -#endif - -/*! -@brief namespace for Niels Lohmann -@see https://github.com/nlohmann -@since version 1.0.0 -*/ -namespace nlohmann -{ - -/*! -@brief unnamed namespace with internal helper functions - -This namespace collects some functions that could not be defined inside the -@ref basic_json class. - -@since version 2.1.0 -*/ -namespace detail -{ -//////////////// -// exceptions // -//////////////// - -/*! -@brief general exception of the @ref basic_json class - -Extension of std::exception objects with a member @a id for exception ids. - -@note To have nothrow-copy-constructible exceptions, we internally use - std::runtime_error which can cope with arbitrary-length error messages. - Intermediate strings are built with static functions and then passed to - the actual constructor. - -@since version 3.0.0 -*/ -class exception : public std::exception -{ - public: - /// returns the explanatory string - virtual const char* what() const noexcept override - { - return m.what(); - } - - /// the id of the exception - const int id; - - protected: - exception(int id_, const char* what_arg) - : id(id_), m(what_arg) - {} - - static std::string name(const std::string& ename, int id) - { - return "[json.exception." + ename + "." + std::to_string(id) + "] "; - } - - private: - /// an exception object as storage for error messages - std::runtime_error m; -}; - -/*! -@brief exception indicating a parse error - -This excpetion is thrown by the library when a parse error occurs. Parse -errors can occur during the deserialization of JSON text as well as when -using JSON Patch. - -Member @a byte holds the byte index of the last read character in the input -file. - -@note For an input with n bytes, 1 is the index of the first character - and n+1 is the index of the terminating null byte or the end of - file. This also holds true when reading a byte vector (CBOR or - MessagePack). - -Exceptions have ids 1xx. - -name / id | example massage | description ------------------------------- | --------------- | ------------------------- -json.exception.parse_error.101 | parse error at 2: unexpected end of input; expected string literal | This error indicates a syntax error while deserializing a JSON text. The error message describes that an unexpected token (character) was encountered, and the member @a byte indicates the error position. -json.exception.parse_error.102 | parse error at 14: missing or wrong low surrogate | JSON uses the `\uxxxx` format to describe Unicode characters. Code points above above 0xFFFF are split into two `\uxxxx` entries ("surrogate pairs"). This error indicates that the surrogate pair is incomplete or contains an invalid code point. -json.exception.parse_error.103 | parse error: code points above 0x10FFFF are invalid | Unicode supports code points up to 0x10FFFF. Code points above 0x10FFFF are invalid. -json.exception.parse_error.104 | parse error: JSON patch must be an array of objects | [RFC 6902](https://tools.ietf.org/html/rfc6902) requires a JSON Patch document to be a JSON document that represents an array of objects. -json.exception.parse_error.105 | parse error: operation must have string member 'op' | An operation of a JSON Patch document must contain exactly one "op" member, whose value indicates the operation to perform. Its value must be one of "add", "remove", "replace", "move", "copy", or "test"; other values are errors. -json.exception.parse_error.106 | parse error: array index '01' must not begin with '0' | An array index in a JSON Pointer ([RFC 6901](https://tools.ietf.org/html/rfc6901)) may be `0` or any number wihtout a leading `0`. -json.exception.parse_error.107 | parse error: JSON pointer must be empty or begin with '/' - was: 'foo' | A JSON Pointer must be a Unicode string containing a sequence of zero or more reference tokens, each prefixed by a `/` character. -json.exception.parse_error.108 | parse error: escape character '~' must be followed with '0' or '1' | In a JSON Pointer, only `~0` and `~1` are valid escape sequences. -json.exception.parse_error.109 | parse error: array index 'one' is not a number | A JSON Pointer array index must be a number. -json.exception.parse_error.110 | parse error at 1: cannot read 2 bytes from vector | When parsing CBOR or MessagePack, the byte vector ends before the complete value has been read. -json.exception.parse_error.111 | parse error: bad input stream | Parsing CBOR or MessagePack from an input stream where the [`badbit` or `failbit`](http://en.cppreference.com/w/cpp/io/ios_base/iostate) is set. -json.exception.parse_error.112 | parse error at 1: error reading CBOR; last byte: 0xf8 | Not all types of CBOR or MessagePack are supported. This exception occurs if an unsupported byte was read. -json.exception.parse_error.113 | parse error at 2: expected a CBOR string; last byte: 0x98 | While parsing a map key, a value that is not a string has been read. - -@since version 3.0.0 -*/ -class parse_error : public exception -{ - public: - /*! - @brief create a parse error exception - @param[in] id the id of the exception - @param[in] byte_ the byte index where the error occured (or 0 if - the position cannot be determined) - @param[in] what_arg the explanatory string - @return parse_error object - */ - static parse_error create(int id, size_t byte_, const std::string& what_arg) - { - std::string w = exception::name("parse_error", id) + "parse error" + - (byte_ != 0 ? (" at " + std::to_string(byte_)) : "") + - ": " + what_arg; - return parse_error(id, byte_, w.c_str()); - } - - /*! - @brief byte index of the parse error - - The byte index of the last read character in the input file. - - @note For an input with n bytes, 1 is the index of the first character - and n+1 is the index of the terminating null byte or the end of - file. This also holds true when reading a byte vector (CBOR or - MessagePack). - */ - const size_t byte; - - private: - parse_error(int id_, size_t byte_, const char* what_arg) - : exception(id_, what_arg), byte(byte_) - {} -}; - -/*! -@brief exception indicating errors with iterators - -Exceptions have ids 2xx. - -name / id | example massage | description ------------------------------------ | --------------- | ------------------------- -json.exception.invalid_iterator.201 | iterators are not compatible | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid. -json.exception.invalid_iterator.202 | iterator does not fit current value | In an erase or insert function, the passed iterator @a pos does not belong to the JSON value for which the function was called. It hence does not define a valid position for the deletion/insertion. -json.exception.invalid_iterator.203 | iterators do not fit current value | Either iterator passed to function @ref erase(IteratorType first, IteratorType last) does not belong to the JSON value from which values shall be erased. It hence does not define a valid range to delete values from. -json.exception.invalid_iterator.204 | iterators out of range | When an iterator range for a primitive type (number, boolean, or string) is passed to a constructor or an erase function, this range has to be exactly (@ref begin(), @ref end()), because this is the only way the single stored value is expressed. All other ranges are invalid. -json.exception.invalid_iterator.205 | iterator out of range | When an iterator for a primitive type (number, boolean, or string) is passed to an erase function, the iterator has to be the @ref begin() iterator, because it is the only way to address the stored value. All other iterators are invalid. -json.exception.invalid_iterator.206 | cannot construct with iterators from null | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) belong to a JSON null value and hence to not define a valid range. -json.exception.invalid_iterator.207 | cannot use key() for non-object iterators | The key() member function can only be used on iterators belonging to a JSON object, because other types do not have a concept of a key. -json.exception.invalid_iterator.208 | cannot use operator[] for object iterators | The operator[] to specify a concrete offset cannot be used on iterators belonging to a JSON object, because JSON objects are unordered. -json.exception.invalid_iterator.209 | cannot use offsets with object iterators | The offset operators (+, -, +=, -=) cannot be used on iterators belonging to a JSON object, because JSON objects are unordered. -json.exception.invalid_iterator.210 | iterators do not fit | The iterator range passed to the insert function are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid. -json.exception.invalid_iterator.211 | passed iterators may not belong to container | The iterator range passed to the insert function must not be a subrange of the container to insert to. -json.exception.invalid_iterator.212 | cannot compare iterators of different containers | When two iterators are compared, they must belong to the same container. -json.exception.invalid_iterator.213 | cannot compare order of object iterators | The order of object iterators cannot be compated, because JSON objects are unordered. -json.exception.invalid_iterator.214 | cannot get value | Cannot get value for iterator: Either the iterator belongs to a null value or it is an iterator to a primitive type (number, boolean, or string), but the iterator is different to @ref begin(). - -@since version 3.0.0 -*/ -class invalid_iterator : public exception -{ - public: - static invalid_iterator create(int id, const std::string& what_arg) - { - std::string w = exception::name("invalid_iterator", id) + what_arg; - return invalid_iterator(id, w.c_str()); - } - - private: - invalid_iterator(int id_, const char* what_arg) - : exception(id_, what_arg) - {} -}; - -/*! -@brief exception indicating executing a member function with a wrong type - -Exceptions have ids 3xx. - -name / id | example massage | description ------------------------------ | --------------- | ------------------------- -json.exception.type_error.301 | cannot create object from initializer list | To create an object from an initializer list, the initializer list must consist only of a list of pairs whose first element is a string. When this constraint is violated, an array is created instead. -json.exception.type_error.302 | type must be object, but is array | During implicit or explicit value conversion, the JSON type must be compatible to the target type. For instance, a JSON string can only be converted into string types, but not into numbers or boolean types. -json.exception.type_error.303 | incompatible ReferenceType for get_ref, actual type is object | To retrieve a reference to a value stored in a @ref basic_json object with @ref get_ref, the type of the reference must match the value type. For instance, for a JSON array, the @a ReferenceType must be @ref array_t&. -json.exception.type_error.304 | cannot use at() with string | The @ref at() member functions can only be executed for certain JSON types. -json.exception.type_error.305 | cannot use operator[] with string | The @ref operator[] member functions can only be executed for certain JSON types. -json.exception.type_error.306 | cannot use value() with string | The @ref value() member functions can only be executed for certain JSON types. -json.exception.type_error.307 | cannot use erase() with string | The @ref erase() member functions can only be executed for certain JSON types. -json.exception.type_error.308 | cannot use push_back() with string | The @ref push_back() and @ref operator+= member functions can only be executed for certain JSON types. -json.exception.type_error.309 | cannot use insert() with | The @ref insert() member functions can only be executed for certain JSON types. -json.exception.type_error.310 | cannot use swap() with number | The @ref swap() member functions can only be executed for certain JSON types. -json.exception.type_error.311 | cannot use emplace_back() with string | The @ref emplace_back() member function can only be executed for certain JSON types. -json.exception.type_error.313 | invalid value to unflatten | The @ref unflatten function converts an object whose keys are JSON Pointers back into an arbitrary nested JSON value. The JSON Pointers must not overlap, because then the resulting value would not be well defined. -json.exception.type_error.314 | only objects can be unflattened | The @ref unflatten function only works for an object whose keys are JSON Pointers. -json.exception.type_error.315 | values in object must be primitive | The @ref unflatten function only works for an object whose keys are JSON Pointers and whose values are primitive. - -@since version 3.0.0 -*/ -class type_error : public exception -{ - public: - static type_error create(int id, const std::string& what_arg) - { - std::string w = exception::name("type_error", id) + what_arg; - return type_error(id, w.c_str()); - } - - private: - type_error(int id_, const char* what_arg) - : exception(id_, what_arg) - {} -}; - -/*! -@brief exception indicating access out of the defined range - -Exceptions have ids 4xx. - -name / id | example massage | description -------------------------------- | --------------- | ------------------------- -json.exception.out_of_range.401 | array index 3 is out of range | The provided array index @a i is larger than @a size-1. -json.exception.out_of_range.402 | array index '-' (3) is out of range | The special array index `-` in a JSON Pointer never describes a valid element of the array, but the index past the end. That is, it can only be used to add elements at this position, but not to read it. -json.exception.out_of_range.403 | key 'foo' not found | The provided key was not found in the JSON object. -json.exception.out_of_range.404 | unresolved reference token 'foo' | A reference token in a JSON Pointer could not be resolved. -json.exception.out_of_range.405 | JSON pointer has no parent | The JSON Patch operations 'remove' and 'add' can not be applied to the root element of the JSON value. -json.exception.out_of_range.406 | number overflow parsing '10E1000' | A parsed number could not be stored as without changing it to NaN or INF. - -@since version 3.0.0 -*/ -class out_of_range : public exception -{ - public: - static out_of_range create(int id, const std::string& what_arg) - { - std::string w = exception::name("out_of_range", id) + what_arg; - return out_of_range(id, w.c_str()); - } - - private: - out_of_range(int id_, const char* what_arg) - : exception(id_, what_arg) - {} -}; - -/*! -@brief exception indicating other errors - -Exceptions have ids 5xx. - -name / id | example massage | description ------------------------------- | --------------- | ------------------------- -json.exception.other_error.501 | unsuccessful: {"op":"test","path":"/baz", "value":"bar"} | A JSON Patch operation 'test' failed. The unsuccessful operation is also printed. - -@since version 3.0.0 -*/ -class other_error : public exception -{ - public: - static other_error create(int id, const std::string& what_arg) - { - std::string w = exception::name("other_error", id) + what_arg; - return other_error(id, w.c_str()); - } - - private: - other_error(int id_, const char* what_arg) - : exception(id_, what_arg) - {} -}; - - - -/////////////////////////// -// JSON type enumeration // -/////////////////////////// - -/*! -@brief the JSON type enumeration - -This enumeration collects the different JSON types. It is internally used to -distinguish the stored values, and the functions @ref basic_json::is_null(), -@ref basic_json::is_object(), @ref basic_json::is_array(), -@ref basic_json::is_string(), @ref basic_json::is_boolean(), -@ref basic_json::is_number() (with @ref basic_json::is_number_integer(), -@ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()), -@ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and -@ref basic_json::is_structured() rely on it. - -@note There are three enumeration entries (number_integer, number_unsigned, and -number_float), because the library distinguishes these three types for numbers: -@ref basic_json::number_unsigned_t is used for unsigned integers, -@ref basic_json::number_integer_t is used for signed integers, and -@ref basic_json::number_float_t is used for floating-point numbers or to -approximate integers which do not fit in the limits of their respective type. - -@sa @ref basic_json::basic_json(const value_t value_type) -- create a JSON -value with the default value for a given type - -@since version 1.0.0 -*/ -enum class value_t : uint8_t -{ - null, ///< null value - object, ///< object (unordered set of name/value pairs) - array, ///< array (ordered collection of values) - string, ///< string value - boolean, ///< boolean value - number_integer, ///< number value (signed integer) - number_unsigned, ///< number value (unsigned integer) - number_float, ///< number value (floating-point) - discarded ///< discarded by the the parser callback function -}; - -/*! -@brief comparison operator for JSON types - -Returns an ordering that is similar to Python: -- order: null < boolean < number < object < array < string -- furthermore, each type is not smaller than itself - -@since version 1.0.0 -*/ -inline bool operator<(const value_t lhs, const value_t rhs) noexcept -{ - static constexpr std::array order = {{ - 0, // null - 3, // object - 4, // array - 5, // string - 1, // boolean - 2, // integer - 2, // unsigned - 2, // float - } - }; - - // discarded values are not comparable - if (lhs == value_t::discarded or rhs == value_t::discarded) - { - return false; - } - - return order[static_cast(lhs)] < - order[static_cast(rhs)]; -} - - -///////////// -// helpers // -///////////// - -// alias templates to reduce boilerplate -template -using enable_if_t = typename std::enable_if::type; - -template -using uncvref_t = typename std::remove_cv::type>::type; - -/* -Implementation of two C++17 constructs: conjunction, negation. This is needed -to avoid evaluating all the traits in a condition - -For example: not std::is_same::value and has_value_type::value -will not compile when T = void (on MSVC at least). Whereas -conjunction>, has_value_type>::value will -stop evaluating if negation<...>::value == false - -Please note that those constructs must be used with caution, since symbols can -become very long quickly (which can slow down compilation and cause MSVC -internal compiler errors). Only use it when you have to (see example ahead). -*/ -template struct conjunction : std::true_type {}; -template struct conjunction : B1 {}; -template -struct conjunction : std::conditional, B1>::type {}; - -template struct negation : std::integral_constant < bool, !B::value > {}; - -// dispatch utility (taken from ranges-v3) -template struct priority_tag : priority_tag < N - 1 > {}; -template<> struct priority_tag<0> {}; - - -////////////////// -// constructors // -////////////////// - -template struct external_constructor; - -template<> -struct external_constructor -{ - template - static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept - { - j.m_type = value_t::boolean; - j.m_value = b; - j.assert_invariant(); - } -}; - -template<> -struct external_constructor -{ - template - static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s) - { - j.m_type = value_t::string; - j.m_value = s; - j.assert_invariant(); - } -}; - -template<> -struct external_constructor -{ - template - static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept - { - j.m_type = value_t::number_float; - j.m_value = val; - j.assert_invariant(); - } -}; - -template<> -struct external_constructor -{ - template - static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept - { - j.m_type = value_t::number_unsigned; - j.m_value = val; - j.assert_invariant(); - } -}; - -template<> -struct external_constructor -{ - template - static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept - { - j.m_type = value_t::number_integer; - j.m_value = val; - j.assert_invariant(); - } -}; - -template<> -struct external_constructor -{ - template - static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr) - { - j.m_type = value_t::array; - j.m_value = arr; - j.assert_invariant(); - } - - template::value, - int> = 0> - static void construct(BasicJsonType& j, const CompatibleArrayType& arr) - { - using std::begin; - using std::end; - j.m_type = value_t::array; - j.m_value.array = j.template create(begin(arr), end(arr)); - j.assert_invariant(); - } - - template - static void construct(BasicJsonType& j, const std::vector& arr) - { - j.m_type = value_t::array; - j.m_value = value_t::array; - j.m_value.array->reserve(arr.size()); - for (bool x : arr) - { - j.m_value.array->push_back(x); - } - j.assert_invariant(); - } -}; - -template<> -struct external_constructor -{ - template - static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj) - { - j.m_type = value_t::object; - j.m_value = obj; - j.assert_invariant(); - } - - template::value, - int> = 0> - static void construct(BasicJsonType& j, const CompatibleObjectType& obj) - { - using std::begin; - using std::end; - - j.m_type = value_t::object; - j.m_value.object = j.template create(begin(obj), end(obj)); - j.assert_invariant(); - } -}; - - -//////////////////////// -// has_/is_ functions // -//////////////////////// - -/*! -@brief Helper to determine whether there's a key_type for T. - -This helper is used to tell associative containers apart from other containers -such as sequence containers. For instance, `std::map` passes the test as it -contains a `mapped_type`, whereas `std::vector` fails the test. - -@sa http://stackoverflow.com/a/7728728/266378 -@since version 1.0.0, overworked in version 2.0.6 -*/ -#define NLOHMANN_JSON_HAS_HELPER(type) \ - template struct has_##type { \ - private: \ - template \ - static int detect(U &&); \ - static void detect(...); \ - public: \ - static constexpr bool value = \ - std::is_integral()))>::value; \ - } - -NLOHMANN_JSON_HAS_HELPER(mapped_type); -NLOHMANN_JSON_HAS_HELPER(key_type); -NLOHMANN_JSON_HAS_HELPER(value_type); -NLOHMANN_JSON_HAS_HELPER(iterator); - -#undef NLOHMANN_JSON_HAS_HELPER - - -template -struct is_compatible_object_type_impl : std::false_type {}; - -template -struct is_compatible_object_type_impl -{ - static constexpr auto value = - std::is_constructible::value and - std::is_constructible::value; -}; - -template -struct is_compatible_object_type -{ - static auto constexpr value = is_compatible_object_type_impl < - conjunction>, - has_mapped_type, - has_key_type>::value, - typename BasicJsonType::object_t, CompatibleObjectType >::value; -}; - -template -struct is_basic_json_nested_type -{ - static auto constexpr value = std::is_same::value or - std::is_same::value or - std::is_same::value or - std::is_same::value or - std::is_same::value; -}; - -template -struct is_compatible_array_type -{ - static auto constexpr value = - conjunction>, - negation>, - negation>, - negation>, - has_value_type, - has_iterator>::value; -}; - -template -struct is_compatible_integer_type_impl : std::false_type {}; - -template -struct is_compatible_integer_type_impl -{ - // is there an assert somewhere on overflows? - using RealLimits = std::numeric_limits; - using CompatibleLimits = std::numeric_limits; - - static constexpr auto value = - std::is_constructible::value and - CompatibleLimits::is_integer and - RealLimits::is_signed == CompatibleLimits::is_signed; -}; - -template -struct is_compatible_integer_type -{ - static constexpr auto value = - is_compatible_integer_type_impl < - std::is_integral::value and - not std::is_same::value, - RealIntegerType, CompatibleNumberIntegerType > ::value; -}; - - -// trait checking if JSONSerializer::from_json(json const&, udt&) exists -template -struct has_from_json -{ - private: - // also check the return type of from_json - template::from_json( - std::declval(), std::declval()))>::value>> - static int detect(U&&); - static void detect(...); - - public: - static constexpr bool value = std::is_integral>()))>::value; -}; - -// This trait checks if JSONSerializer::from_json(json const&) exists -// this overload is used for non-default-constructible user-defined-types -template -struct has_non_default_from_json -{ - private: - template < - typename U, - typename = enable_if_t::from_json(std::declval()))>::value >> - static int detect(U&&); - static void detect(...); - - public: - static constexpr bool value = std::is_integral>()))>::value; -}; - -// This trait checks if BasicJsonType::json_serializer::to_json exists -template -struct has_to_json -{ - private: - template::to_json( - std::declval(), std::declval()))> - static int detect(U&&); - static void detect(...); - - public: - static constexpr bool value = std::is_integral>()))>::value; -}; - - -///////////// -// to_json // -///////////// - -template::value, int> = 0> -void to_json(BasicJsonType& j, T b) noexcept -{ - external_constructor::construct(j, b); -} - -template::value, int> = 0> -void to_json(BasicJsonType& j, const CompatibleString& s) -{ - external_constructor::construct(j, s); -} - -template::value, int> = 0> -void to_json(BasicJsonType& j, FloatType val) noexcept -{ - external_constructor::construct(j, static_cast(val)); -} - -template < - typename BasicJsonType, typename CompatibleNumberUnsignedType, - enable_if_t::value, int> = 0 > -void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept -{ - external_constructor::construct(j, static_cast(val)); -} - -template < - typename BasicJsonType, typename CompatibleNumberIntegerType, - enable_if_t::value, int> = 0 > -void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept -{ - external_constructor::construct(j, static_cast(val)); -} - -template::value, int> = 0> -void to_json(BasicJsonType& j, EnumType e) noexcept -{ - using underlying_type = typename std::underlying_type::type; - external_constructor::construct(j, static_cast(e)); -} - -template -void to_json(BasicJsonType& j, const std::vector& e) -{ - external_constructor::construct(j, e); -} - -template < - typename BasicJsonType, typename CompatibleArrayType, - enable_if_t < - is_compatible_array_type::value or - std::is_same::value, - int > = 0 > -void to_json(BasicJsonType& j, const CompatibleArrayType& arr) -{ - external_constructor::construct(j, arr); -} - -template < - typename BasicJsonType, typename CompatibleObjectType, - enable_if_t::value, - int> = 0 > -void to_json(BasicJsonType& j, const CompatibleObjectType& arr) -{ - external_constructor::construct(j, arr); -} - -template ::value, - int> = 0> -void to_json(BasicJsonType& j, T (&arr)[N]) -{ - external_constructor::construct(j, arr); -} - -/////////////// -// from_json // -/////////////// - -// overloads for basic_json template parameters -template::value and - not std::is_same::value, - int> = 0> -void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val) -{ - switch (static_cast(j)) - { - case value_t::number_unsigned: - { - val = static_cast( - *j.template get_ptr()); - break; - } - case value_t::number_integer: - { - val = static_cast( - *j.template get_ptr()); - break; - } - case value_t::number_float: - { - val = static_cast( - *j.template get_ptr()); - break; - } - default: - { - JSON_THROW(type_error::create(302, "type must be number, but is " + j.type_name())); - } - } -} - -template -void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b) -{ - if (not j.is_boolean()) - { - JSON_THROW(type_error::create(302, "type must be boolean, but is " + j.type_name())); - } - b = *j.template get_ptr(); -} - -template -void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s) -{ - if (not j.is_string()) - { - JSON_THROW(type_error::create(302, "type must be string, but is " + j.type_name())); - } - s = *j.template get_ptr(); -} - -template -void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val) -{ - get_arithmetic_value(j, val); -} - -template -void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val) -{ - get_arithmetic_value(j, val); -} - -template -void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val) -{ - get_arithmetic_value(j, val); -} - -template::value, int> = 0> -void from_json(const BasicJsonType& j, EnumType& e) -{ - typename std::underlying_type::type val; - get_arithmetic_value(j, val); - e = static_cast(val); -} - -template -void from_json(const BasicJsonType& j, typename BasicJsonType::array_t& arr) -{ - if (not j.is_array()) - { - JSON_THROW(type_error::create(302, "type must be array, but is " + j.type_name())); - } - arr = *j.template get_ptr(); -} - -// forward_list doesn't have an insert method -template::value, int> = 0> -void from_json(const BasicJsonType& j, std::forward_list& l) -{ - if (not j.is_array()) - { - JSON_THROW(type_error::create(302, "type must be array, but is " + j.type_name())); - } - - for (auto it = j.rbegin(), end = j.rend(); it != end; ++it) - { - l.push_front(it->template get()); - } -} - -template -void from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, priority_tag<0>) -{ - using std::begin; - using std::end; - - std::transform(j.begin(), j.end(), - std::inserter(arr, end(arr)), [](const BasicJsonType & i) - { - // get() returns *this, this won't call a from_json - // method when value_type is BasicJsonType - return i.template get(); - }); -} - -template -auto from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, priority_tag<1>) --> decltype( - arr.reserve(std::declval()), - void()) -{ - using std::begin; - using std::end; - - arr.reserve(j.size()); - std::transform(j.begin(), j.end(), - std::inserter(arr, end(arr)), [](const BasicJsonType & i) - { - // get() returns *this, this won't call a from_json - // method when value_type is BasicJsonType - return i.template get(); - }); -} - -template::value and - std::is_convertible::value and - not std::is_same::value, int> = 0> -void from_json(const BasicJsonType& j, CompatibleArrayType& arr) -{ - if (not j.is_array()) - { - JSON_THROW(type_error::create(302, "type must be array, but is " + j.type_name())); - } - - from_json_array_impl(j, arr, priority_tag<1> {}); -} - -template::value, int> = 0> -void from_json(const BasicJsonType& j, CompatibleObjectType& obj) -{ - if (not j.is_object()) - { - JSON_THROW(type_error::create(302, "type must be object, but is " + j.type_name())); - } - - auto inner_object = j.template get_ptr(); - using std::begin; - using std::end; - // we could avoid the assignment, but this might require a for loop, which - // might be less efficient than the container constructor for some - // containers (would it?) - obj = CompatibleObjectType(begin(*inner_object), end(*inner_object)); -} - -// overload for arithmetic types, not chosen for basic_json template arguments -// (BooleanType, etc..); note: Is it really necessary to provide explicit -// overloads for boolean_t etc. in case of a custom BooleanType which is not -// an arithmetic type? -template::value and - not std::is_same::value and - not std::is_same::value and - not std::is_same::value and - not std::is_same::value, - int> = 0> -void from_json(const BasicJsonType& j, ArithmeticType& val) -{ - switch (static_cast(j)) - { - case value_t::number_unsigned: - { - val = static_cast(*j.template get_ptr()); - break; - } - case value_t::number_integer: - { - val = static_cast(*j.template get_ptr()); - break; - } - case value_t::number_float: - { - val = static_cast(*j.template get_ptr()); - break; - } - case value_t::boolean: - { - val = static_cast(*j.template get_ptr()); - break; - } - default: - { - JSON_THROW(type_error::create(302, "type must be number, but is " + j.type_name())); - } - } -} - -struct to_json_fn -{ - private: - template - auto call(BasicJsonType& j, T&& val, priority_tag<1>) const noexcept(noexcept(to_json(j, std::forward(val)))) - -> decltype(to_json(j, std::forward(val)), void()) - { - return to_json(j, std::forward(val)); - } - - template - void call(BasicJsonType&, T&&, priority_tag<0>) const noexcept - { - static_assert(sizeof(BasicJsonType) == 0, - "could not find to_json() method in T's namespace"); - } - - public: - template - void operator()(BasicJsonType& j, T&& val) const - noexcept(noexcept(std::declval().call(j, std::forward(val), priority_tag<1> {}))) - { - return call(j, std::forward(val), priority_tag<1> {}); - } -}; - -struct from_json_fn -{ - private: - template - auto call(const BasicJsonType& j, T& val, priority_tag<1>) const - noexcept(noexcept(from_json(j, val))) - -> decltype(from_json(j, val), void()) - { - return from_json(j, val); - } - - template - void call(const BasicJsonType&, T&, priority_tag<0>) const noexcept - { - static_assert(sizeof(BasicJsonType) == 0, - "could not find from_json() method in T's namespace"); - } - - public: - template - void operator()(const BasicJsonType& j, T& val) const - noexcept(noexcept(std::declval().call(j, val, priority_tag<1> {}))) - { - return call(j, val, priority_tag<1> {}); - } -}; - -// taken from ranges-v3 -template -struct static_const -{ - static constexpr T value{}; -}; - -template -constexpr T static_const::value; -} // namespace detail - - -/// namespace to hold default `to_json` / `from_json` functions -namespace -{ -constexpr const auto& to_json = detail::static_const::value; -constexpr const auto& from_json = detail::static_const::value; -} - - -/*! -@brief default JSONSerializer template argument - -This serializer ignores the template arguments and uses ADL -([argument-dependent lookup](http://en.cppreference.com/w/cpp/language/adl)) -for serialization. -*/ -template -struct adl_serializer -{ - /*! - @brief convert a JSON value to any value type - - This function is usually called by the `get()` function of the - @ref basic_json class (either explicit or via conversion operators). - - @param[in] j JSON value to read from - @param[in,out] val value to write to - */ - template - static void from_json(BasicJsonType&& j, ValueType& val) noexcept( - noexcept(::nlohmann::from_json(std::forward(j), val))) - { - ::nlohmann::from_json(std::forward(j), val); - } - - /*! - @brief convert any value type to a JSON value - - This function is usually called by the constructors of the @ref basic_json - class. - - @param[in,out] j JSON value to write to - @param[in] val value to read from - */ - template - static void to_json(BasicJsonType& j, ValueType&& val) noexcept( - noexcept(::nlohmann::to_json(j, std::forward(val)))) - { - ::nlohmann::to_json(j, std::forward(val)); - } -}; - - -/*! -@brief a class to store JSON values - -@tparam ObjectType type for JSON objects (`std::map` by default; will be used -in @ref object_t) -@tparam ArrayType type for JSON arrays (`std::vector` by default; will be used -in @ref array_t) -@tparam StringType type for JSON strings and object keys (`std::string` by -default; will be used in @ref string_t) -@tparam BooleanType type for JSON booleans (`bool` by default; will be used -in @ref boolean_t) -@tparam NumberIntegerType type for JSON integer numbers (`int64_t` by -default; will be used in @ref number_integer_t) -@tparam NumberUnsignedType type for JSON unsigned integer numbers (@c -`uint64_t` by default; will be used in @ref number_unsigned_t) -@tparam NumberFloatType type for JSON floating-point numbers (`double` by -default; will be used in @ref number_float_t) -@tparam AllocatorType type of the allocator to use (`std::allocator` by -default) -@tparam JSONSerializer the serializer to resolve internal calls to `to_json()` -and `from_json()` (@ref adl_serializer by default) - -@requirement The class satisfies the following concept requirements: -- Basic - - [DefaultConstructible](http://en.cppreference.com/w/cpp/concept/DefaultConstructible): - JSON values can be default constructed. The result will be a JSON null - value. - - [MoveConstructible](http://en.cppreference.com/w/cpp/concept/MoveConstructible): - A JSON value can be constructed from an rvalue argument. - - [CopyConstructible](http://en.cppreference.com/w/cpp/concept/CopyConstructible): - A JSON value can be copy-constructed from an lvalue expression. - - [MoveAssignable](http://en.cppreference.com/w/cpp/concept/MoveAssignable): - A JSON value van be assigned from an rvalue argument. - - [CopyAssignable](http://en.cppreference.com/w/cpp/concept/CopyAssignable): - A JSON value can be copy-assigned from an lvalue expression. - - [Destructible](http://en.cppreference.com/w/cpp/concept/Destructible): - JSON values can be destructed. -- Layout - - [StandardLayoutType](http://en.cppreference.com/w/cpp/concept/StandardLayoutType): - JSON values have - [standard layout](http://en.cppreference.com/w/cpp/language/data_members#Standard_layout): - All non-static data members are private and standard layout types, the - class has no virtual functions or (virtual) base classes. -- Library-wide - - [EqualityComparable](http://en.cppreference.com/w/cpp/concept/EqualityComparable): - JSON values can be compared with `==`, see @ref - operator==(const_reference,const_reference). - - [LessThanComparable](http://en.cppreference.com/w/cpp/concept/LessThanComparable): - JSON values can be compared with `<`, see @ref - operator<(const_reference,const_reference). - - [Swappable](http://en.cppreference.com/w/cpp/concept/Swappable): - Any JSON lvalue or rvalue of can be swapped with any lvalue or rvalue of - other compatible types, using unqualified function call @ref swap(). - - [NullablePointer](http://en.cppreference.com/w/cpp/concept/NullablePointer): - JSON values can be compared against `std::nullptr_t` objects which are used - to model the `null` value. -- Container - - [Container](http://en.cppreference.com/w/cpp/concept/Container): - JSON values can be used like STL containers and provide iterator access. - - [ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer); - JSON values can be used like STL containers and provide reverse iterator - access. - -@invariant The member variables @a m_value and @a m_type have the following -relationship: -- If `m_type == value_t::object`, then `m_value.object != nullptr`. -- If `m_type == value_t::array`, then `m_value.array != nullptr`. -- If `m_type == value_t::string`, then `m_value.string != nullptr`. -The invariants are checked by member function assert_invariant(). - -@internal -@note ObjectType trick from http://stackoverflow.com/a/9860911 -@endinternal - -@see [RFC 7159: The JavaScript Object Notation (JSON) Data Interchange -Format](http://rfc7159.net/rfc7159) - -@since version 1.0.0 - -@nosubgrouping -*/ -template < - template class ObjectType = std::map, - template class ArrayType = std::vector, - class StringType = std::string, - class BooleanType = bool, - class NumberIntegerType = std::int64_t, - class NumberUnsignedType = std::uint64_t, - class NumberFloatType = double, - template class AllocatorType = std::allocator, - template class JSONSerializer = adl_serializer - > -class basic_json -{ - private: - template friend struct detail::external_constructor; - /// workaround type for MSVC - using basic_json_t = basic_json; - - public: - using value_t = detail::value_t; - // forward declarations - template class iter_impl; - template class json_reverse_iterator; - class json_pointer; - template - using json_serializer = JSONSerializer; - - - //////////////// - // exceptions // - //////////////// - - /// @name exceptions - /// Classes to implement user-defined exceptions. - /// @{ - - /// @copydoc detail::exception - using exception = detail::exception; - /// @copydoc detail::parse_error - using parse_error = detail::parse_error; - /// @copydoc detail::invalid_iterator - using invalid_iterator = detail::invalid_iterator; - /// @copydoc detail::type_error - using type_error = detail::type_error; - /// @copydoc detail::out_of_range - using out_of_range = detail::out_of_range; - /// @copydoc detail::other_error - using other_error = detail::other_error; - - /// @} - - - ///////////////////// - // container types // - ///////////////////// - - /// @name container types - /// The canonic container types to use @ref basic_json like any other STL - /// container. - /// @{ - - /// the type of elements in a basic_json container - using value_type = basic_json; - - /// the type of an element reference - using reference = value_type&; - /// the type of an element const reference - using const_reference = const value_type&; - - /// a type to represent differences between iterators - using difference_type = std::ptrdiff_t; - /// a type to represent container sizes - using size_type = std::size_t; - - /// the allocator type - using allocator_type = AllocatorType; - - /// the type of an element pointer - using pointer = typename std::allocator_traits::pointer; - /// the type of an element const pointer - using const_pointer = typename std::allocator_traits::const_pointer; - - /// an iterator for a basic_json container - using iterator = iter_impl; - /// a const iterator for a basic_json container - using const_iterator = iter_impl; - /// a reverse iterator for a basic_json container - using reverse_iterator = json_reverse_iterator; - /// a const reverse iterator for a basic_json container - using const_reverse_iterator = json_reverse_iterator; - - /// @} - - - /*! - @brief returns the allocator associated with the container - */ - static allocator_type get_allocator() - { - return allocator_type(); - } - - /*! - @brief returns version information on the library - - This function returns a JSON object with information about the library, - including the version number and information on the platform and compiler. - - @return JSON object holding version information - key | description - ----------- | --------------- - `compiler` | Information on the used compiler. It is an object with the following keys: `c++` (the used C++ standard), `family` (the compiler family; possible values are `clang`, `icc`, `gcc`, `ilecpp`, `msvc`, `pgcpp`, `sunpro`, and `unknown`), and `version` (the compiler version). - `copyright` | The copyright line for the library as string. - `name` | The name of the library as string. - `platform` | The used platform as string. Possible values are `win32`, `linux`, `apple`, `unix`, and `unknown`. - `url` | The URL of the project as string. - `version` | The version of the library. It is an object with the following keys: `major`, `minor`, and `patch` as defined by [Semantic Versioning](http://semver.org), and `string` (the version string). - - @liveexample{The following code shows an example output of the `meta()` - function.,meta} - - @complexity Constant. - - @since 2.1.0 - */ - static basic_json meta() - { - basic_json result; - - result["copyright"] = "(C) 2013-2017 Niels Lohmann"; - result["name"] = "JSON for Modern C++"; - result["url"] = "https://github.com/nlohmann/json"; - result["version"] = - { - {"string", "2.1.1"}, {"major", 2}, {"minor", 1}, {"patch", 1} - }; - -#ifdef _WIN32 - result["platform"] = "win32"; -#elif defined __linux__ - result["platform"] = "linux"; -#elif defined __APPLE__ - result["platform"] = "apple"; -#elif defined __unix__ - result["platform"] = "unix"; -#else - result["platform"] = "unknown"; -#endif - -#if defined(__clang__) - result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}}; -#elif defined(__ICC) || defined(__INTEL_COMPILER) - result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}}; -#elif defined(__GNUC__) || defined(__GNUG__) - result["compiler"] = {{"family", "gcc"}, {"version", std::to_string(__GNUC__) + "." + std::to_string(__GNUC_MINOR__) + "." + std::to_string(__GNUC_PATCHLEVEL__)}}; -#elif defined(__HP_cc) || defined(__HP_aCC) - result["compiler"] = "hp" -#elif defined(__IBMCPP__) - result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}}; -#elif defined(_MSC_VER) - result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}}; -#elif defined(__PGI) - result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}}; -#elif defined(__SUNPRO_CC) - result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}}; -#else - result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}}; -#endif - -#ifdef __cplusplus - result["compiler"]["c++"] = std::to_string(__cplusplus); -#else - result["compiler"]["c++"] = "unknown"; -#endif - return result; - } - - - /////////////////////////// - // JSON value data types // - /////////////////////////// - - /// @name JSON value data types - /// The data types to store a JSON value. These types are derived from - /// the template arguments passed to class @ref basic_json. - /// @{ - - /*! - @brief a type for an object - - [RFC 7159](http://rfc7159.net/rfc7159) describes JSON objects as follows: - > An object is an unordered collection of zero or more name/value pairs, - > where a name is a string and a value is a string, number, boolean, null, - > object, or array. - - To store objects in C++, a type is defined by the template parameters - described below. - - @tparam ObjectType the container to store objects (e.g., `std::map` or - `std::unordered_map`) - @tparam StringType the type of the keys or names (e.g., `std::string`). - The comparison function `std::less` is used to order elements - inside the container. - @tparam AllocatorType the allocator to use for objects (e.g., - `std::allocator`) - - #### Default type - - With the default values for @a ObjectType (`std::map`), @a StringType - (`std::string`), and @a AllocatorType (`std::allocator`), the default - value for @a object_t is: - - @code {.cpp} - std::map< - std::string, // key_type - basic_json, // value_type - std::less, // key_compare - std::allocator> // allocator_type - > - @endcode - - #### Behavior - - The choice of @a object_t influences the behavior of the JSON class. With - the default type, objects have the following behavior: - - - When all names are unique, objects will be interoperable in the sense - that all software implementations receiving that object will agree on - the name-value mappings. - - When the names within an object are not unique, later stored name/value - pairs overwrite previously stored name/value pairs, leaving the used - names unique. For instance, `{"key": 1}` and `{"key": 2, "key": 1}` will - be treated as equal and both stored as `{"key": 1}`. - - Internally, name/value pairs are stored in lexicographical order of the - names. Objects will also be serialized (see @ref dump) in this order. - For instance, `{"b": 1, "a": 2}` and `{"a": 2, "b": 1}` will be stored - and serialized as `{"a": 2, "b": 1}`. - - When comparing objects, the order of the name/value pairs is irrelevant. - This makes objects interoperable in the sense that they will not be - affected by these differences. For instance, `{"b": 1, "a": 2}` and - `{"a": 2, "b": 1}` will be treated as equal. - - #### Limits - - [RFC 7159](http://rfc7159.net/rfc7159) specifies: - > An implementation may set limits on the maximum depth of nesting. - - In this class, the object's limit of nesting is not constraint explicitly. - However, a maximum depth of nesting may be introduced by the compiler or - runtime environment. A theoretical limit can be queried by calling the - @ref max_size function of a JSON object. - - #### Storage - - Objects are stored as pointers in a @ref basic_json type. That is, for any - access to object values, a pointer of type `object_t*` must be - dereferenced. - - @sa @ref array_t -- type for an array value - - @since version 1.0.0 - - @note The order name/value pairs are added to the object is *not* - preserved by the library. Therefore, iterating an object may return - name/value pairs in a different order than they were originally stored. In - fact, keys will be traversed in alphabetical order as `std::map` with - `std::less` is used by default. Please note this behavior conforms to [RFC - 7159](http://rfc7159.net/rfc7159), because any order implements the - specified "unordered" nature of JSON objects. - */ - using object_t = ObjectType, - AllocatorType>>; - - /*! - @brief a type for an array - - [RFC 7159](http://rfc7159.net/rfc7159) describes JSON arrays as follows: - > An array is an ordered sequence of zero or more values. - - To store objects in C++, a type is defined by the template parameters - explained below. - - @tparam ArrayType container type to store arrays (e.g., `std::vector` or - `std::list`) - @tparam AllocatorType allocator to use for arrays (e.g., `std::allocator`) - - #### Default type - - With the default values for @a ArrayType (`std::vector`) and @a - AllocatorType (`std::allocator`), the default value for @a array_t is: - - @code {.cpp} - std::vector< - basic_json, // value_type - std::allocator // allocator_type - > - @endcode - - #### Limits - - [RFC 7159](http://rfc7159.net/rfc7159) specifies: - > An implementation may set limits on the maximum depth of nesting. - - In this class, the array's limit of nesting is not constraint explicitly. - However, a maximum depth of nesting may be introduced by the compiler or - runtime environment. A theoretical limit can be queried by calling the - @ref max_size function of a JSON array. - - #### Storage - - Arrays are stored as pointers in a @ref basic_json type. That is, for any - access to array values, a pointer of type `array_t*` must be dereferenced. - - @sa @ref object_t -- type for an object value - - @since version 1.0.0 - */ - using array_t = ArrayType>; - - /*! - @brief a type for a string - - [RFC 7159](http://rfc7159.net/rfc7159) describes JSON strings as follows: - > A string is a sequence of zero or more Unicode characters. - - To store objects in C++, a type is defined by the template parameter - described below. Unicode values are split by the JSON class into - byte-sized characters during deserialization. - - @tparam StringType the container to store strings (e.g., `std::string`). - Note this container is used for keys/names in objects, see @ref object_t. - - #### Default type - - With the default values for @a StringType (`std::string`), the default - value for @a string_t is: - - @code {.cpp} - std::string - @endcode - - #### Encoding - - Strings are stored in UTF-8 encoding. Therefore, functions like - `std::string::size()` or `std::string::length()` return the number of - bytes in the string rather than the number of characters or glyphs. - - #### String comparison - - [RFC 7159](http://rfc7159.net/rfc7159) states: - > Software implementations are typically required to test names of object - > members for equality. Implementations that transform the textual - > representation into sequences of Unicode code units and then perform the - > comparison numerically, code unit by code unit, are interoperable in the - > sense that implementations will agree in all cases on equality or - > inequality of two strings. For example, implementations that compare - > strings with escaped characters unconverted may incorrectly find that - > `"a\\b"` and `"a\u005Cb"` are not equal. - - This implementation is interoperable as it does compare strings code unit - by code unit. - - #### Storage - - String values are stored as pointers in a @ref basic_json type. That is, - for any access to string values, a pointer of type `string_t*` must be - dereferenced. - - @since version 1.0.0 - */ - using string_t = StringType; - - /*! - @brief a type for a boolean - - [RFC 7159](http://rfc7159.net/rfc7159) implicitly describes a boolean as a - type which differentiates the two literals `true` and `false`. - - To store objects in C++, a type is defined by the template parameter @a - BooleanType which chooses the type to use. - - #### Default type - - With the default values for @a BooleanType (`bool`), the default value for - @a boolean_t is: - - @code {.cpp} - bool - @endcode - - #### Storage - - Boolean values are stored directly inside a @ref basic_json type. - - @since version 1.0.0 - */ - using boolean_t = BooleanType; - - /*! - @brief a type for a number (integer) - - [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows: - > The representation of numbers is similar to that used in most - > programming languages. A number is represented in base 10 using decimal - > digits. It contains an integer component that may be prefixed with an - > optional minus sign, which may be followed by a fraction part and/or an - > exponent part. Leading zeros are not allowed. (...) Numeric values that - > cannot be represented in the grammar below (such as Infinity and NaN) - > are not permitted. - - This description includes both integer and floating-point numbers. - However, C++ allows more precise storage if it is known whether the number - is a signed integer, an unsigned integer or a floating-point number. - Therefore, three different types, @ref number_integer_t, @ref - number_unsigned_t and @ref number_float_t are used. - - To store integer numbers in C++, a type is defined by the template - parameter @a NumberIntegerType which chooses the type to use. - - #### Default type - - With the default values for @a NumberIntegerType (`int64_t`), the default - value for @a number_integer_t is: - - @code {.cpp} - int64_t - @endcode - - #### Default behavior - - - The restrictions about leading zeros is not enforced in C++. Instead, - leading zeros in integer literals lead to an interpretation as octal - number. Internally, the value will be stored as decimal number. For - instance, the C++ integer literal `010` will be serialized to `8`. - During deserialization, leading zeros yield an error. - - Not-a-number (NaN) values will be serialized to `null`. - - #### Limits - - [RFC 7159](http://rfc7159.net/rfc7159) specifies: - > An implementation may set limits on the range and precision of numbers. - - When the default type is used, the maximal integer number that can be - stored is `9223372036854775807` (INT64_MAX) and the minimal integer number - that can be stored is `-9223372036854775808` (INT64_MIN). Integer numbers - that are out of range will yield over/underflow when used in a - constructor. During deserialization, too large or small integer numbers - will be automatically be stored as @ref number_unsigned_t or @ref - number_float_t. - - [RFC 7159](http://rfc7159.net/rfc7159) further states: - > Note that when such software is used, numbers that are integers and are - > in the range \f$[-2^{53}+1, 2^{53}-1]\f$ are interoperable in the sense - > that implementations will agree exactly on their numeric values. - - As this range is a subrange of the exactly supported range [INT64_MIN, - INT64_MAX], this class's integer type is interoperable. - - #### Storage - - Integer number values are stored directly inside a @ref basic_json type. - - @sa @ref number_float_t -- type for number values (floating-point) - - @sa @ref number_unsigned_t -- type for number values (unsigned integer) - - @since version 1.0.0 - */ - using number_integer_t = NumberIntegerType; - - /*! - @brief a type for a number (unsigned) - - [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows: - > The representation of numbers is similar to that used in most - > programming languages. A number is represented in base 10 using decimal - > digits. It contains an integer component that may be prefixed with an - > optional minus sign, which may be followed by a fraction part and/or an - > exponent part. Leading zeros are not allowed. (...) Numeric values that - > cannot be represented in the grammar below (such as Infinity and NaN) - > are not permitted. - - This description includes both integer and floating-point numbers. - However, C++ allows more precise storage if it is known whether the number - is a signed integer, an unsigned integer or a floating-point number. - Therefore, three different types, @ref number_integer_t, @ref - number_unsigned_t and @ref number_float_t are used. - - To store unsigned integer numbers in C++, a type is defined by the - template parameter @a NumberUnsignedType which chooses the type to use. - - #### Default type - - With the default values for @a NumberUnsignedType (`uint64_t`), the - default value for @a number_unsigned_t is: - - @code {.cpp} - uint64_t - @endcode - - #### Default behavior - - - The restrictions about leading zeros is not enforced in C++. Instead, - leading zeros in integer literals lead to an interpretation as octal - number. Internally, the value will be stored as decimal number. For - instance, the C++ integer literal `010` will be serialized to `8`. - During deserialization, leading zeros yield an error. - - Not-a-number (NaN) values will be serialized to `null`. - - #### Limits - - [RFC 7159](http://rfc7159.net/rfc7159) specifies: - > An implementation may set limits on the range and precision of numbers. - - When the default type is used, the maximal integer number that can be - stored is `18446744073709551615` (UINT64_MAX) and the minimal integer - number that can be stored is `0`. Integer numbers that are out of range - will yield over/underflow when used in a constructor. During - deserialization, too large or small integer numbers will be automatically - be stored as @ref number_integer_t or @ref number_float_t. - - [RFC 7159](http://rfc7159.net/rfc7159) further states: - > Note that when such software is used, numbers that are integers and are - > in the range \f$[-2^{53}+1, 2^{53}-1]\f$ are interoperable in the sense - > that implementations will agree exactly on their numeric values. - - As this range is a subrange (when considered in conjunction with the - number_integer_t type) of the exactly supported range [0, UINT64_MAX], - this class's integer type is interoperable. - - #### Storage - - Integer number values are stored directly inside a @ref basic_json type. - - @sa @ref number_float_t -- type for number values (floating-point) - @sa @ref number_integer_t -- type for number values (integer) - - @since version 2.0.0 - */ - using number_unsigned_t = NumberUnsignedType; - - /*! - @brief a type for a number (floating-point) - - [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows: - > The representation of numbers is similar to that used in most - > programming languages. A number is represented in base 10 using decimal - > digits. It contains an integer component that may be prefixed with an - > optional minus sign, which may be followed by a fraction part and/or an - > exponent part. Leading zeros are not allowed. (...) Numeric values that - > cannot be represented in the grammar below (such as Infinity and NaN) - > are not permitted. - - This description includes both integer and floating-point numbers. - However, C++ allows more precise storage if it is known whether the number - is a signed integer, an unsigned integer or a floating-point number. - Therefore, three different types, @ref number_integer_t, @ref - number_unsigned_t and @ref number_float_t are used. - - To store floating-point numbers in C++, a type is defined by the template - parameter @a NumberFloatType which chooses the type to use. - - #### Default type - - With the default values for @a NumberFloatType (`double`), the default - value for @a number_float_t is: - - @code {.cpp} - double - @endcode - - #### Default behavior - - - The restrictions about leading zeros is not enforced in C++. Instead, - leading zeros in floating-point literals will be ignored. Internally, - the value will be stored as decimal number. For instance, the C++ - floating-point literal `01.2` will be serialized to `1.2`. During - deserialization, leading zeros yield an error. - - Not-a-number (NaN) values will be serialized to `null`. - - #### Limits - - [RFC 7159](http://rfc7159.net/rfc7159) states: - > This specification allows implementations to set limits on the range and - > precision of numbers accepted. Since software that implements IEEE - > 754-2008 binary64 (double precision) numbers is generally available and - > widely used, good interoperability can be achieved by implementations - > that expect no more precision or range than these provide, in the sense - > that implementations will approximate JSON numbers within the expected - > precision. - - This implementation does exactly follow this approach, as it uses double - precision floating-point numbers. Note values smaller than - `-1.79769313486232e+308` and values greater than `1.79769313486232e+308` - will be stored as NaN internally and be serialized to `null`. - - #### Storage - - Floating-point number values are stored directly inside a @ref basic_json - type. - - @sa @ref number_integer_t -- type for number values (integer) - - @sa @ref number_unsigned_t -- type for number values (unsigned integer) - - @since version 1.0.0 - */ - using number_float_t = NumberFloatType; - - /// @} - - private: - - /// helper for exception-safe object creation - template - static T* create(Args&& ... args) - { - AllocatorType alloc; - auto deleter = [&](T * object) - { - alloc.deallocate(object, 1); - }; - std::unique_ptr object(alloc.allocate(1), deleter); - alloc.construct(object.get(), std::forward(args)...); - assert(object != nullptr); - return object.release(); - } - - //////////////////////// - // JSON value storage // - //////////////////////// - - /*! - @brief a JSON value - - The actual storage for a JSON value of the @ref basic_json class. This - union combines the different storage types for the JSON value types - defined in @ref value_t. - - JSON type | value_t type | used type - --------- | --------------- | ------------------------ - object | object | pointer to @ref object_t - array | array | pointer to @ref array_t - string | string | pointer to @ref string_t - boolean | boolean | @ref boolean_t - number | number_integer | @ref number_integer_t - number | number_unsigned | @ref number_unsigned_t - number | number_float | @ref number_float_t - null | null | *no value is stored* - - @note Variable-length types (objects, arrays, and strings) are stored as - pointers. The size of the union should not exceed 64 bits if the default - value types are used. - - @since version 1.0.0 - */ - union json_value - { - /// object (stored with pointer to save storage) - object_t* object; - /// array (stored with pointer to save storage) - array_t* array; - /// string (stored with pointer to save storage) - string_t* string; - /// boolean - boolean_t boolean; - /// number (integer) - number_integer_t number_integer; - /// number (unsigned integer) - number_unsigned_t number_unsigned; - /// number (floating-point) - number_float_t number_float; - - /// default constructor (for null values) - json_value() = default; - /// constructor for booleans - json_value(boolean_t v) noexcept : boolean(v) {} - /// constructor for numbers (integer) - json_value(number_integer_t v) noexcept : number_integer(v) {} - /// constructor for numbers (unsigned) - json_value(number_unsigned_t v) noexcept : number_unsigned(v) {} - /// constructor for numbers (floating-point) - json_value(number_float_t v) noexcept : number_float(v) {} - /// constructor for empty values of a given type - json_value(value_t t) - { - switch (t) - { - case value_t::object: - { - object = create(); - break; - } - - case value_t::array: - { - array = create(); - break; - } - - case value_t::string: - { - string = create(""); - break; - } - - case value_t::boolean: - { - boolean = boolean_t(false); - break; - } - - case value_t::number_integer: - { - number_integer = number_integer_t(0); - break; - } - - case value_t::number_unsigned: - { - number_unsigned = number_unsigned_t(0); - break; - } - - case value_t::number_float: - { - number_float = number_float_t(0.0); - break; - } - - case value_t::null: - { - break; - } - - default: - { - if (t == value_t::null) - { - JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 2.1.1")); // LCOV_EXCL_LINE - } - break; - } - } - } - - /// constructor for strings - json_value(const string_t& value) - { - string = create(value); - } - - /// constructor for objects - json_value(const object_t& value) - { - object = create(value); - } - - /// constructor for arrays - json_value(const array_t& value) - { - array = create(value); - } - }; - - /*! - @brief checks the class invariants - - This function asserts the class invariants. It needs to be called at the - end of every constructor to make sure that created objects respect the - invariant. Furthermore, it has to be called each time the type of a JSON - value is changed, because the invariant expresses a relationship between - @a m_type and @a m_value. - */ - void assert_invariant() const - { - assert(m_type != value_t::object or m_value.object != nullptr); - assert(m_type != value_t::array or m_value.array != nullptr); - assert(m_type != value_t::string or m_value.string != nullptr); - } - - public: - ////////////////////////// - // JSON parser callback // - ////////////////////////// - - /*! - @brief JSON callback events - - This enumeration lists the parser events that can trigger calling a - callback function of type @ref parser_callback_t during parsing. - - @image html callback_events.png "Example when certain parse events are triggered" - - @since version 1.0.0 - */ - enum class parse_event_t : uint8_t - { - /// the parser read `{` and started to process a JSON object - object_start, - /// the parser read `}` and finished processing a JSON object - object_end, - /// the parser read `[` and started to process a JSON array - array_start, - /// the parser read `]` and finished processing a JSON array - array_end, - /// the parser read a key of a value in an object - key, - /// the parser finished reading a JSON value - value - }; - - /*! - @brief per-element parser callback type - - With a parser callback function, the result of parsing a JSON text can be - influenced. When passed to @ref parse(std::istream&, const - parser_callback_t) or @ref parse(const CharT, const parser_callback_t), - it is called on certain events (passed as @ref parse_event_t via parameter - @a event) with a set recursion depth @a depth and context JSON value - @a parsed. The return value of the callback function is a boolean - indicating whether the element that emitted the callback shall be kept or - not. - - We distinguish six scenarios (determined by the event type) in which the - callback function can be called. The following table describes the values - of the parameters @a depth, @a event, and @a parsed. - - parameter @a event | description | parameter @a depth | parameter @a parsed - ------------------ | ----------- | ------------------ | ------------------- - parse_event_t::object_start | the parser read `{` and started to process a JSON object | depth of the parent of the JSON object | a JSON value with type discarded - parse_event_t::key | the parser read a key of a value in an object | depth of the currently parsed JSON object | a JSON string containing the key - parse_event_t::object_end | the parser read `}` and finished processing a JSON object | depth of the parent of the JSON object | the parsed JSON object - parse_event_t::array_start | the parser read `[` and started to process a JSON array | depth of the parent of the JSON array | a JSON value with type discarded - parse_event_t::array_end | the parser read `]` and finished processing a JSON array | depth of the parent of the JSON array | the parsed JSON array - parse_event_t::value | the parser finished reading a JSON value | depth of the value | the parsed JSON value - - @image html callback_events.png "Example when certain parse events are triggered" - - Discarding a value (i.e., returning `false`) has different effects - depending on the context in which function was called: - - - Discarded values in structured types are skipped. That is, the parser - will behave as if the discarded value was never read. - - In case a value outside a structured type is skipped, it is replaced - with `null`. This case happens if the top-level element is skipped. - - @param[in] depth the depth of the recursion during parsing - - @param[in] event an event of type parse_event_t indicating the context in - the callback function has been called - - @param[in,out] parsed the current intermediate parse result; note that - writing to this value has no effect for parse_event_t::key events - - @return Whether the JSON value which called the function during parsing - should be kept (`true`) or not (`false`). In the latter case, it is either - skipped completely or replaced by an empty discarded object. - - @sa @ref parse(std::istream&, parser_callback_t) or - @ref parse(const CharT, const parser_callback_t) for examples - - @since version 1.0.0 - */ - using parser_callback_t = std::function; - - - ////////////////// - // constructors // - ////////////////// - - /// @name constructors and destructors - /// Constructors of class @ref basic_json, copy/move constructor, copy - /// assignment, static functions creating objects, and the destructor. - /// @{ - - /*! - @brief create an empty value with a given type - - Create an empty JSON value with a given type. The value will be default - initialized with an empty value which depends on the type: - - Value type | initial value - ----------- | ------------- - null | `null` - boolean | `false` - string | `""` - number | `0` - object | `{}` - array | `[]` - - @param[in] value_type the type of the value to create - - @complexity Constant. - - @liveexample{The following code shows the constructor for different @ref - value_t values,basic_json__value_t} - - @since version 1.0.0 - */ - basic_json(const value_t value_type) - : m_type(value_type), m_value(value_type) - { - assert_invariant(); - } - - /*! - @brief create a null object - - Create a `null` JSON value. It either takes a null pointer as parameter - (explicitly creating `null`) or no parameter (implicitly creating `null`). - The passed null pointer itself is not read -- it is only used to choose - the right constructor. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this constructor never throws - exceptions. - - @liveexample{The following code shows the constructor with and without a - null pointer parameter.,basic_json__nullptr_t} - - @since version 1.0.0 - */ - basic_json(std::nullptr_t = nullptr) noexcept - : basic_json(value_t::null) - { - assert_invariant(); - } - - /*! - @brief create a JSON value - - This is a "catch all" constructor for all compatible JSON types; that is, - types for which a `to_json()` method exsits. The constructor forwards the - parameter @a val to that method (to `json_serializer::to_json` method - with `U = uncvref_t`, to be exact). - - Template type @a CompatibleType includes, but is not limited to, the - following types: - - **arrays**: @ref array_t and all kinds of compatible containers such as - `std::vector`, `std::deque`, `std::list`, `std::forward_list`, - `std::array`, `std::set`, `std::unordered_set`, `std::multiset`, and - `unordered_multiset` with a `value_type` from which a @ref basic_json - value can be constructed. - - **objects**: @ref object_t and all kinds of compatible associative - containers such as `std::map`, `std::unordered_map`, `std::multimap`, - and `std::unordered_multimap` with a `key_type` compatible to - @ref string_t and a `value_type` from which a @ref basic_json value can - be constructed. - - **strings**: @ref string_t, string literals, and all compatible string - containers can be used. - - **numbers**: @ref number_integer_t, @ref number_unsigned_t, - @ref number_float_t, and all convertible number types such as `int`, - `size_t`, `int64_t`, `float` or `double` can be used. - - **boolean**: @ref boolean_t / `bool` can be used. - - See the examples below. - - @tparam CompatibleType a type such that: - - @a CompatibleType is not derived from `std::istream`, - - @a CompatibleType is not @ref basic_json (to avoid hijacking copy/move - constructors), - - @a CompatibleType is not a @ref basic_json nested type (e.g., - @ref json_pointer, @ref iterator, etc ...) - - @ref @ref json_serializer has a - `to_json(basic_json_t&, CompatibleType&&)` method - - @tparam U = `uncvref_t` - - @param[in] val the value to be forwarded - - @complexity Usually linear in the size of the passed @a val, also - depending on the implementation of the called `to_json()` - method. - - @throw what `json_serializer::to_json()` throws - - @liveexample{The following code shows the constructor with several - compatible types.,basic_json__CompatibleType} - - @since version 2.1.0 - */ - template, - detail::enable_if_t::value and - not std::is_same::value and - not detail::is_basic_json_nested_type< - basic_json_t, U>::value and - detail::has_to_json::value, - int> = 0> - basic_json(CompatibleType && val) noexcept(noexcept(JSONSerializer::to_json( - std::declval(), std::forward(val)))) - { - JSONSerializer::to_json(*this, std::forward(val)); - assert_invariant(); - } - - /*! - @brief create a container (array or object) from an initializer list - - Creates a JSON value of type array or object from the passed initializer - list @a init. In case @a type_deduction is `true` (default), the type of - the JSON value to be created is deducted from the initializer list @a init - according to the following rules: - - 1. If the list is empty, an empty JSON object value `{}` is created. - 2. If the list consists of pairs whose first element is a string, a JSON - object value is created where the first elements of the pairs are - treated as keys and the second elements are as values. - 3. In all other cases, an array is created. - - The rules aim to create the best fit between a C++ initializer list and - JSON values. The rationale is as follows: - - 1. The empty initializer list is written as `{}` which is exactly an empty - JSON object. - 2. C++ has now way of describing mapped types other than to list a list of - pairs. As JSON requires that keys must be of type string, rule 2 is the - weakest constraint one can pose on initializer lists to interpret them - as an object. - 3. In all other cases, the initializer list could not be interpreted as - JSON object type, so interpreting it as JSON array type is safe. - - With the rules described above, the following JSON values cannot be - expressed by an initializer list: - - - the empty array (`[]`): use @ref array(std::initializer_list) - with an empty initializer list in this case - - arrays whose elements satisfy rule 2: use @ref - array(std::initializer_list) with the same initializer list - in this case - - @note When used without parentheses around an empty initializer list, @ref - basic_json() is called instead of this function, yielding the JSON null - value. - - @param[in] init initializer list with JSON values - - @param[in] type_deduction internal parameter; when set to `true`, the type - of the JSON value is deducted from the initializer list @a init; when set - to `false`, the type provided via @a manual_type is forced. This mode is - used by the functions @ref array(std::initializer_list) and - @ref object(std::initializer_list). - - @param[in] manual_type internal parameter; when @a type_deduction is set - to `false`, the created JSON value will use the provided type (only @ref - value_t::array and @ref value_t::object are valid); when @a type_deduction - is set to `true`, this parameter has no effect - - @throw type_error.301 if @a type_deduction is `false`, @a manual_type is - `value_t::object`, but @a init contains an element which is not a pair - whose first element is a string. In this case, the constructor could not - create an object. If @a type_deduction would have be `true`, an array - would have been created. See @ref object(std::initializer_list) - for an example. - - @complexity Linear in the size of the initializer list @a init. - - @liveexample{The example below shows how JSON values are created from - initializer lists.,basic_json__list_init_t} - - @sa @ref array(std::initializer_list) -- create a JSON array - value from an initializer list - @sa @ref object(std::initializer_list) -- create a JSON object - value from an initializer list - - @since version 1.0.0 - */ - basic_json(std::initializer_list init, - bool type_deduction = true, - value_t manual_type = value_t::array) - { - // check if each element is an array with two elements whose first - // element is a string - bool is_an_object = std::all_of(init.begin(), init.end(), - [](const basic_json & element) - { - return element.is_array() and element.size() == 2 and element[0].is_string(); - }); - - // adjust type if type deduction is not wanted - if (not type_deduction) - { - // if array is wanted, do not create an object though possible - if (manual_type == value_t::array) - { - is_an_object = false; - } - - // if object is wanted but impossible, throw an exception - if (manual_type == value_t::object and not is_an_object) - { - JSON_THROW(type_error::create(301, "cannot create object from initializer list")); - } - } - - if (is_an_object) - { - // the initializer list is a list of pairs -> create object - m_type = value_t::object; - m_value = value_t::object; - - std::for_each(init.begin(), init.end(), [this](const basic_json & element) - { - m_value.object->emplace(*(element[0].m_value.string), element[1]); - }); - } - else - { - // the initializer list describes an array -> create array - m_type = value_t::array; - m_value.array = create(init); - } - - assert_invariant(); - } - - /*! - @brief explicitly create an array from an initializer list - - Creates a JSON array value from a given initializer list. That is, given a - list of values `a, b, c`, creates the JSON value `[a, b, c]`. If the - initializer list is empty, the empty array `[]` is created. - - @note This function is only needed to express two edge cases that cannot - be realized with the initializer list constructor (@ref - basic_json(std::initializer_list, bool, value_t)). These cases - are: - 1. creating an array whose elements are all pairs whose first element is a - string -- in this case, the initializer list constructor would create an - object, taking the first elements as keys - 2. creating an empty array -- passing the empty initializer list to the - initializer list constructor yields an empty object - - @param[in] init initializer list with JSON values to create an array from - (optional) - - @return JSON array value - - @complexity Linear in the size of @a init. - - @liveexample{The following code shows an example for the `array` - function.,array} - - @sa @ref basic_json(std::initializer_list, bool, value_t) -- - create a JSON value from an initializer list - @sa @ref object(std::initializer_list) -- create a JSON object - value from an initializer list - - @since version 1.0.0 - */ - static basic_json array(std::initializer_list init = - std::initializer_list()) - { - return basic_json(init, false, value_t::array); - } - - /*! - @brief explicitly create an object from an initializer list - - Creates a JSON object value from a given initializer list. The initializer - lists elements must be pairs, and their first elements must be strings. If - the initializer list is empty, the empty object `{}` is created. - - @note This function is only added for symmetry reasons. In contrast to the - related function @ref array(std::initializer_list), there are - no cases which can only be expressed by this function. That is, any - initializer list @a init can also be passed to the initializer list - constructor @ref basic_json(std::initializer_list, bool, value_t). - - @param[in] init initializer list to create an object from (optional) - - @return JSON object value - - @throw type_error.301 if @a init is not a list of pairs whose first - elements are strings. In this case, no object can be created. When such a - value is passed to @ref basic_json(std::initializer_list, bool, value_t), - an array would have been created from the passed initializer list @a init. - See example below. - - @complexity Linear in the size of @a init. - - @liveexample{The following code shows an example for the `object` - function.,object} - - @sa @ref basic_json(std::initializer_list, bool, value_t) -- - create a JSON value from an initializer list - @sa @ref array(std::initializer_list) -- create a JSON array - value from an initializer list - - @since version 1.0.0 - */ - static basic_json object(std::initializer_list init = - std::initializer_list()) - { - return basic_json(init, false, value_t::object); - } - - /*! - @brief construct an array with count copies of given value - - Constructs a JSON array value by creating @a cnt copies of a passed value. - In case @a cnt is `0`, an empty array is created. As postcondition, - `std::distance(begin(),end()) == cnt` holds. - - @param[in] cnt the number of JSON copies of @a val to create - @param[in] val the JSON value to copy - - @complexity Linear in @a cnt. - - @liveexample{The following code shows examples for the @ref - basic_json(size_type\, const basic_json&) - constructor.,basic_json__size_type_basic_json} - - @since version 1.0.0 - */ - basic_json(size_type cnt, const basic_json& val) - : m_type(value_t::array) - { - m_value.array = create(cnt, val); - assert_invariant(); - } - - /*! - @brief construct a JSON container given an iterator range - - Constructs the JSON value with the contents of the range `[first, last)`. - The semantics depends on the different types a JSON value can have: - - In case of primitive types (number, boolean, or string), @a first must - be `begin()` and @a last must be `end()`. In this case, the value is - copied. Otherwise, invalid_iterator.204 is thrown. - - In case of structured types (array, object), the constructor behaves as - similar versions for `std::vector`. - - In case of a null type, invalid_iterator.206 is thrown. - - @tparam InputIT an input iterator type (@ref iterator or @ref - const_iterator) - - @param[in] first begin of the range to copy from (included) - @param[in] last end of the range to copy from (excluded) - - @pre Iterators @a first and @a last must be initialized. **This - precondition is enforced with an assertion.** - - @pre Range `[first, last)` is valid. Usually, this precondition cannot be - checked efficiently. Only certain edge cases are detected; see the - description of the exceptions below. - - @throw invalid_iterator.201 if iterators @a first and @a last are not - compatible (i.e., do not belong to the same JSON value). In this case, - the range `[first, last)` is undefined. - @throw invalid_iterator.204 if iterators @a first and @a last belong to a - primitive type (number, boolean, or string), but @a first does not point - to the first element any more. In this case, the range `[first, last)` is - undefined. See example code below. - @throw invalid_iterator.206 if iterators @a first and @a last belong to a - null value. In this case, the range `[first, last)` is undefined. - - @complexity Linear in distance between @a first and @a last. - - @liveexample{The example below shows several ways to create JSON values by - specifying a subrange with iterators.,basic_json__InputIt_InputIt} - - @since version 1.0.0 - */ - template::value or - std::is_same::value, int>::type = 0> - basic_json(InputIT first, InputIT last) - { - assert(first.m_object != nullptr); - assert(last.m_object != nullptr); - - // make sure iterator fits the current value - if (first.m_object != last.m_object) - { - JSON_THROW(invalid_iterator::create(201, "iterators are not compatible")); - } - - // copy type from first iterator - m_type = first.m_object->m_type; - - // check if iterator range is complete for primitive values - switch (m_type) - { - case value_t::boolean: - case value_t::number_float: - case value_t::number_integer: - case value_t::number_unsigned: - case value_t::string: - { - if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end()) - { - JSON_THROW(invalid_iterator::create(204, "iterators out of range")); - } - break; - } - - default: - { - break; - } - } - - switch (m_type) - { - case value_t::number_integer: - { - m_value.number_integer = first.m_object->m_value.number_integer; - break; - } - - case value_t::number_unsigned: - { - m_value.number_unsigned = first.m_object->m_value.number_unsigned; - break; - } - - case value_t::number_float: - { - m_value.number_float = first.m_object->m_value.number_float; - break; - } - - case value_t::boolean: - { - m_value.boolean = first.m_object->m_value.boolean; - break; - } - - case value_t::string: - { - m_value = *first.m_object->m_value.string; - break; - } - - case value_t::object: - { - m_value.object = create(first.m_it.object_iterator, - last.m_it.object_iterator); - break; - } - - case value_t::array: - { - m_value.array = create(first.m_it.array_iterator, - last.m_it.array_iterator); - break; - } - - default: - { - JSON_THROW(invalid_iterator::create(206, "cannot construct with iterators from " + - first.m_object->type_name())); - } - } - - assert_invariant(); - } - - - /////////////////////////////////////// - // other constructors and destructor // - /////////////////////////////////////// - - /*! - @brief copy constructor - - Creates a copy of a given JSON value. - - @param[in] other the JSON value to copy - - @complexity Linear in the size of @a other. - - @requirement This function helps `basic_json` satisfying the - [Container](http://en.cppreference.com/w/cpp/concept/Container) - requirements: - - The complexity is linear. - - As postcondition, it holds: `other == basic_json(other)`. - - @liveexample{The following code shows an example for the copy - constructor.,basic_json__basic_json} - - @since version 1.0.0 - */ - basic_json(const basic_json& other) - : m_type(other.m_type) - { - // check of passed value is valid - other.assert_invariant(); - - switch (m_type) - { - case value_t::object: - { - m_value = *other.m_value.object; - break; - } - - case value_t::array: - { - m_value = *other.m_value.array; - break; - } - - case value_t::string: - { - m_value = *other.m_value.string; - break; - } - - case value_t::boolean: - { - m_value = other.m_value.boolean; - break; - } - - case value_t::number_integer: - { - m_value = other.m_value.number_integer; - break; - } - - case value_t::number_unsigned: - { - m_value = other.m_value.number_unsigned; - break; - } - - case value_t::number_float: - { - m_value = other.m_value.number_float; - break; - } - - default: - { - break; - } - } - - assert_invariant(); - } - - /*! - @brief move constructor - - Move constructor. Constructs a JSON value with the contents of the given - value @a other using move semantics. It "steals" the resources from @a - other and leaves it as JSON null value. - - @param[in,out] other value to move to this object - - @post @a other is a JSON null value - - @complexity Constant. - - @liveexample{The code below shows the move constructor explicitly called - via std::move.,basic_json__moveconstructor} - - @since version 1.0.0 - */ - basic_json(basic_json&& other) noexcept - : m_type(std::move(other.m_type)), - m_value(std::move(other.m_value)) - { - // check that passed value is valid - other.assert_invariant(); - - // invalidate payload - other.m_type = value_t::null; - other.m_value = {}; - - assert_invariant(); - } - - /*! - @brief copy assignment - - Copy assignment operator. Copies a JSON value via the "copy and swap" - strategy: It is expressed in terms of the copy constructor, destructor, - and the swap() member function. - - @param[in] other value to copy from - - @complexity Linear. - - @requirement This function helps `basic_json` satisfying the - [Container](http://en.cppreference.com/w/cpp/concept/Container) - requirements: - - The complexity is linear. - - @liveexample{The code below shows and example for the copy assignment. It - creates a copy of value `a` which is then swapped with `b`. Finally\, the - copy of `a` (which is the null value after the swap) is - destroyed.,basic_json__copyassignment} - - @since version 1.0.0 - */ - reference& operator=(basic_json other) noexcept ( - std::is_nothrow_move_constructible::value and - std::is_nothrow_move_assignable::value and - std::is_nothrow_move_constructible::value and - std::is_nothrow_move_assignable::value - ) - { - // check that passed value is valid - other.assert_invariant(); - - using std::swap; - swap(m_type, other.m_type); - swap(m_value, other.m_value); - - assert_invariant(); - return *this; - } - - /*! - @brief destructor - - Destroys the JSON value and frees all allocated memory. - - @complexity Linear. - - @requirement This function helps `basic_json` satisfying the - [Container](http://en.cppreference.com/w/cpp/concept/Container) - requirements: - - The complexity is linear. - - All stored elements are destroyed and all memory is freed. - - @since version 1.0.0 - */ - ~basic_json() - { - assert_invariant(); - - switch (m_type) - { - case value_t::object: - { - AllocatorType alloc; - alloc.destroy(m_value.object); - alloc.deallocate(m_value.object, 1); - break; - } - - case value_t::array: - { - AllocatorType alloc; - alloc.destroy(m_value.array); - alloc.deallocate(m_value.array, 1); - break; - } - - case value_t::string: - { - AllocatorType alloc; - alloc.destroy(m_value.string); - alloc.deallocate(m_value.string, 1); - break; - } - - default: - { - // all other types need no specific destructor - break; - } - } - } - - /// @} - - public: - /////////////////////// - // object inspection // - /////////////////////// - - /// @name object inspection - /// Functions to inspect the type of a JSON value. - /// @{ - - /*! - @brief serialization - - Serialization function for JSON values. The function tries to mimic - Python's `json.dumps()` function, and currently supports its @a indent - parameter. - - @param[in] indent If indent is nonnegative, then array elements and object - members will be pretty-printed with that indent level. An indent level of - `0` will only insert newlines. `-1` (the default) selects the most compact - representation. - - @return string containing the serialization of the JSON value - - @complexity Linear. - - @liveexample{The following example shows the effect of different @a indent - parameters to the result of the serialization.,dump} - - @see https://docs.python.org/2/library/json.html#json.dump - - @since version 1.0.0 - */ - string_t dump(const int indent = -1) const - { - std::stringstream ss; - serializer s(ss); - - if (indent >= 0) - { - s.dump(*this, true, static_cast(indent)); - } - else - { - s.dump(*this, false, 0); - } - - return ss.str(); - } - - /*! - @brief return the type of the JSON value (explicit) - - Return the type of the JSON value as a value from the @ref value_t - enumeration. - - @return the type of the JSON value - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `type()` for all JSON - types.,type} - - @since version 1.0.0 - */ - constexpr value_t type() const noexcept - { - return m_type; - } - - /*! - @brief return whether type is primitive - - This function returns true iff the JSON type is primitive (string, number, - boolean, or null). - - @return `true` if type is primitive (string, number, boolean, or null), - `false` otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_primitive()` for all JSON - types.,is_primitive} - - @sa @ref is_structured() -- returns whether JSON value is structured - @sa @ref is_null() -- returns whether JSON value is `null` - @sa @ref is_string() -- returns whether JSON value is a string - @sa @ref is_boolean() -- returns whether JSON value is a boolean - @sa @ref is_number() -- returns whether JSON value is a number - - @since version 1.0.0 - */ - constexpr bool is_primitive() const noexcept - { - return is_null() or is_string() or is_boolean() or is_number(); - } - - /*! - @brief return whether type is structured - - This function returns true iff the JSON type is structured (array or - object). - - @return `true` if type is structured (array or object), `false` otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_structured()` for all JSON - types.,is_structured} - - @sa @ref is_primitive() -- returns whether value is primitive - @sa @ref is_array() -- returns whether value is an array - @sa @ref is_object() -- returns whether value is an object - - @since version 1.0.0 - */ - constexpr bool is_structured() const noexcept - { - return is_array() or is_object(); - } - - /*! - @brief return whether value is null - - This function returns true iff the JSON value is null. - - @return `true` if type is null, `false` otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_null()` for all JSON - types.,is_null} - - @since version 1.0.0 - */ - constexpr bool is_null() const noexcept - { - return m_type == value_t::null; - } - - /*! - @brief return whether value is a boolean - - This function returns true iff the JSON value is a boolean. - - @return `true` if type is boolean, `false` otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_boolean()` for all JSON - types.,is_boolean} - - @since version 1.0.0 - */ - constexpr bool is_boolean() const noexcept - { - return m_type == value_t::boolean; - } - - /*! - @brief return whether value is a number - - This function returns true iff the JSON value is a number. This includes - both integer and floating-point values. - - @return `true` if type is number (regardless whether integer, unsigned - integer or floating-type), `false` otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_number()` for all JSON - types.,is_number} - - @sa @ref is_number_integer() -- check if value is an integer or unsigned - integer number - @sa @ref is_number_unsigned() -- check if value is an unsigned integer - number - @sa @ref is_number_float() -- check if value is a floating-point number - - @since version 1.0.0 - */ - constexpr bool is_number() const noexcept - { - return is_number_integer() or is_number_float(); - } - - /*! - @brief return whether value is an integer number - - This function returns true iff the JSON value is an integer or unsigned - integer number. This excludes floating-point values. - - @return `true` if type is an integer or unsigned integer number, `false` - otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_number_integer()` for all - JSON types.,is_number_integer} - - @sa @ref is_number() -- check if value is a number - @sa @ref is_number_unsigned() -- check if value is an unsigned integer - number - @sa @ref is_number_float() -- check if value is a floating-point number - - @since version 1.0.0 - */ - constexpr bool is_number_integer() const noexcept - { - return m_type == value_t::number_integer or m_type == value_t::number_unsigned; - } - - /*! - @brief return whether value is an unsigned integer number - - This function returns true iff the JSON value is an unsigned integer - number. This excludes floating-point and (signed) integer values. - - @return `true` if type is an unsigned integer number, `false` otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_number_unsigned()` for all - JSON types.,is_number_unsigned} - - @sa @ref is_number() -- check if value is a number - @sa @ref is_number_integer() -- check if value is an integer or unsigned - integer number - @sa @ref is_number_float() -- check if value is a floating-point number - - @since version 2.0.0 - */ - constexpr bool is_number_unsigned() const noexcept - { - return m_type == value_t::number_unsigned; - } - - /*! - @brief return whether value is a floating-point number - - This function returns true iff the JSON value is a floating-point number. - This excludes integer and unsigned integer values. - - @return `true` if type is a floating-point number, `false` otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_number_float()` for all - JSON types.,is_number_float} - - @sa @ref is_number() -- check if value is number - @sa @ref is_number_integer() -- check if value is an integer number - @sa @ref is_number_unsigned() -- check if value is an unsigned integer - number - - @since version 1.0.0 - */ - constexpr bool is_number_float() const noexcept - { - return m_type == value_t::number_float; - } - - /*! - @brief return whether value is an object - - This function returns true iff the JSON value is an object. - - @return `true` if type is object, `false` otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_object()` for all JSON - types.,is_object} - - @since version 1.0.0 - */ - constexpr bool is_object() const noexcept - { - return m_type == value_t::object; - } - - /*! - @brief return whether value is an array - - This function returns true iff the JSON value is an array. - - @return `true` if type is array, `false` otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_array()` for all JSON - types.,is_array} - - @since version 1.0.0 - */ - constexpr bool is_array() const noexcept - { - return m_type == value_t::array; - } - - /*! - @brief return whether value is a string - - This function returns true iff the JSON value is a string. - - @return `true` if type is string, `false` otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_string()` for all JSON - types.,is_string} - - @since version 1.0.0 - */ - constexpr bool is_string() const noexcept - { - return m_type == value_t::string; - } - - /*! - @brief return whether value is discarded - - This function returns true iff the JSON value was discarded during parsing - with a callback function (see @ref parser_callback_t). - - @note This function will always be `false` for JSON values after parsing. - That is, discarded values can only occur during parsing, but will be - removed when inside a structured value or replaced by null in other cases. - - @return `true` if type is discarded, `false` otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_discarded()` for all JSON - types.,is_discarded} - - @since version 1.0.0 - */ - constexpr bool is_discarded() const noexcept - { - return m_type == value_t::discarded; - } - - /*! - @brief return the type of the JSON value (implicit) - - Implicitly return the type of the JSON value as a value from the @ref - value_t enumeration. - - @return the type of the JSON value - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies the @ref value_t operator for - all JSON types.,operator__value_t} - - @since version 1.0.0 - */ - constexpr operator value_t() const noexcept - { - return m_type; - } - - /// @} - - private: - ////////////////// - // value access // - ////////////////// - - /// get a boolean (explicit) - boolean_t get_impl(boolean_t* /*unused*/) const - { - if (is_boolean()) - { - return m_value.boolean; - } - - JSON_THROW(type_error::create(302, "type must be boolean, but is " + type_name())); - } - - /// get a pointer to the value (object) - object_t* get_impl_ptr(object_t* /*unused*/) noexcept - { - return is_object() ? m_value.object : nullptr; - } - - /// get a pointer to the value (object) - constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept - { - return is_object() ? m_value.object : nullptr; - } - - /// get a pointer to the value (array) - array_t* get_impl_ptr(array_t* /*unused*/) noexcept - { - return is_array() ? m_value.array : nullptr; - } - - /// get a pointer to the value (array) - constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept - { - return is_array() ? m_value.array : nullptr; - } - - /// get a pointer to the value (string) - string_t* get_impl_ptr(string_t* /*unused*/) noexcept - { - return is_string() ? m_value.string : nullptr; - } - - /// get a pointer to the value (string) - constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept - { - return is_string() ? m_value.string : nullptr; - } - - /// get a pointer to the value (boolean) - boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept - { - return is_boolean() ? &m_value.boolean : nullptr; - } - - /// get a pointer to the value (boolean) - constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept - { - return is_boolean() ? &m_value.boolean : nullptr; - } - - /// get a pointer to the value (integer number) - number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept - { - return is_number_integer() ? &m_value.number_integer : nullptr; - } - - /// get a pointer to the value (integer number) - constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept - { - return is_number_integer() ? &m_value.number_integer : nullptr; - } - - /// get a pointer to the value (unsigned number) - number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept - { - return is_number_unsigned() ? &m_value.number_unsigned : nullptr; - } - - /// get a pointer to the value (unsigned number) - constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept - { - return is_number_unsigned() ? &m_value.number_unsigned : nullptr; - } - - /// get a pointer to the value (floating-point number) - number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept - { - return is_number_float() ? &m_value.number_float : nullptr; - } - - /// get a pointer to the value (floating-point number) - constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept - { - return is_number_float() ? &m_value.number_float : nullptr; - } - - /*! - @brief helper function to implement get_ref() - - This funcion helps to implement get_ref() without code duplication for - const and non-const overloads - - @tparam ThisType will be deduced as `basic_json` or `const basic_json` - - @throw type_error.303 if ReferenceType does not match underlying value - type of the current JSON - */ - template - static ReferenceType get_ref_impl(ThisType& obj) - { - // helper type - using PointerType = typename std::add_pointer::type; - - // delegate the call to get_ptr<>() - auto ptr = obj.template get_ptr(); - - if (ptr != nullptr) - { - return *ptr; - } - - JSON_THROW(type_error::create(303, "incompatible ReferenceType for get_ref, actual type is " + obj.type_name())); - } - - public: - /// @name value access - /// Direct access to the stored value of a JSON value. - /// @{ - - /*! - @brief get special-case overload - - This overloads avoids a lot of template boilerplate, it can be seen as the - identity method - - @tparam BasicJsonType == @ref basic_json - - @return a copy of *this - - @complexity Constant. - - @since version 2.1.0 - */ - template < - typename BasicJsonType, - detail::enable_if_t::type, - basic_json_t>::value, - int> = 0 > - basic_json get() const - { - return *this; - } - - /*! - @brief get a value (explicit) - - Explicit type conversion between the JSON value and a compatible value - which is [CopyConstructible](http://en.cppreference.com/w/cpp/concept/CopyConstructible) - and [DefaultConstructible](http://en.cppreference.com/w/cpp/concept/DefaultConstructible). - The value is converted by calling the @ref json_serializer - `from_json()` method. - - The function is equivalent to executing - @code {.cpp} - ValueType ret; - JSONSerializer::from_json(*this, ret); - return ret; - @endcode - - This overloads is chosen if: - - @a ValueType is not @ref basic_json, - - @ref json_serializer has a `from_json()` method of the form - `void from_json(const @ref basic_json&, ValueType&)`, and - - @ref json_serializer does not have a `from_json()` method of - the form `ValueType from_json(const @ref basic_json&)` - - @tparam ValueTypeCV the provided value type - @tparam ValueType the returned value type - - @return copy of the JSON value, converted to @a ValueType - - @throw what @ref json_serializer `from_json()` method throws - - @liveexample{The example below shows several conversions from JSON values - to other types. There a few things to note: (1) Floating-point numbers can - be converted to integers\, (2) A JSON array can be converted to a standard - `std::vector`\, (3) A JSON object can be converted to C++ - associative containers such as `std::unordered_map`.,get__ValueType_const} - - @since version 2.1.0 - */ - template < - typename ValueTypeCV, - typename ValueType = detail::uncvref_t, - detail::enable_if_t < - not std::is_same::value and - detail::has_from_json::value and - not detail::has_non_default_from_json::value, - int > = 0 > - ValueType get() const noexcept(noexcept( - JSONSerializer::from_json(std::declval(), std::declval()))) - { - // we cannot static_assert on ValueTypeCV being non-const, because - // there is support for get(), which is why we - // still need the uncvref - static_assert(not std::is_reference::value, - "get() cannot be used with reference types, you might want to use get_ref()"); - static_assert(std::is_default_constructible::value, - "types must be DefaultConstructible when used with get()"); - - ValueType ret; - JSONSerializer::from_json(*this, ret); - return ret; - } - - /*! - @brief get a value (explicit); special case - - Explicit type conversion between the JSON value and a compatible value - which is **not** [CopyConstructible](http://en.cppreference.com/w/cpp/concept/CopyConstructible) - and **not** [DefaultConstructible](http://en.cppreference.com/w/cpp/concept/DefaultConstructible). - The value is converted by calling the @ref json_serializer - `from_json()` method. - - The function is equivalent to executing - @code {.cpp} - return JSONSerializer::from_json(*this); - @endcode - - This overloads is chosen if: - - @a ValueType is not @ref basic_json and - - @ref json_serializer has a `from_json()` method of the form - `ValueType from_json(const @ref basic_json&)` - - @note If @ref json_serializer has both overloads of - `from_json()`, this one is chosen. - - @tparam ValueTypeCV the provided value type - @tparam ValueType the returned value type - - @return copy of the JSON value, converted to @a ValueType - - @throw what @ref json_serializer `from_json()` method throws - - @since version 2.1.0 - */ - template < - typename ValueTypeCV, - typename ValueType = detail::uncvref_t, - detail::enable_if_t::value and - detail::has_non_default_from_json::value, int> = 0 > - ValueType get() const noexcept(noexcept( - JSONSerializer::from_json(std::declval()))) - { - static_assert(not std::is_reference::value, - "get() cannot be used with reference types, you might want to use get_ref()"); - return JSONSerializer::from_json(*this); - } - - /*! - @brief get a pointer value (explicit) - - Explicit pointer access to the internally stored JSON value. No copies are - made. - - @warning The pointer becomes invalid if the underlying JSON object - changes. - - @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref - object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, - @ref number_unsigned_t, or @ref number_float_t. - - @return pointer to the internally stored JSON value if the requested - pointer type @a PointerType fits to the JSON value; `nullptr` otherwise - - @complexity Constant. - - @liveexample{The example below shows how pointers to internal values of a - JSON value can be requested. Note that no type conversions are made and a - `nullptr` is returned if the value and the requested pointer type does not - match.,get__PointerType} - - @sa @ref get_ptr() for explicit pointer-member access - - @since version 1.0.0 - */ - template::value, int>::type = 0> - PointerType get() noexcept - { - // delegate the call to get_ptr - return get_ptr(); - } - - /*! - @brief get a pointer value (explicit) - @copydoc get() - */ - template::value, int>::type = 0> - constexpr const PointerType get() const noexcept - { - // delegate the call to get_ptr - return get_ptr(); - } - - /*! - @brief get a pointer value (implicit) - - Implicit pointer access to the internally stored JSON value. No copies are - made. - - @warning Writing data to the pointee of the result yields an undefined - state. - - @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref - object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, - @ref number_unsigned_t, or @ref number_float_t. Enforced by a static - assertion. - - @return pointer to the internally stored JSON value if the requested - pointer type @a PointerType fits to the JSON value; `nullptr` otherwise - - @complexity Constant. - - @liveexample{The example below shows how pointers to internal values of a - JSON value can be requested. Note that no type conversions are made and a - `nullptr` is returned if the value and the requested pointer type does not - match.,get_ptr} - - @since version 1.0.0 - */ - template::value, int>::type = 0> - PointerType get_ptr() noexcept - { - // get the type of the PointerType (remove pointer and const) - using pointee_t = typename std::remove_const::type>::type>::type; - // make sure the type matches the allowed types - static_assert( - std::is_same::value - or std::is_same::value - or std::is_same::value - or std::is_same::value - or std::is_same::value - or std::is_same::value - or std::is_same::value - , "incompatible pointer type"); - - // delegate the call to get_impl_ptr<>() - return get_impl_ptr(static_cast(nullptr)); - } - - /*! - @brief get a pointer value (implicit) - @copydoc get_ptr() - */ - template::value and - std::is_const::type>::value, int>::type = 0> - constexpr const PointerType get_ptr() const noexcept - { - // get the type of the PointerType (remove pointer and const) - using pointee_t = typename std::remove_const::type>::type>::type; - // make sure the type matches the allowed types - static_assert( - std::is_same::value - or std::is_same::value - or std::is_same::value - or std::is_same::value - or std::is_same::value - or std::is_same::value - or std::is_same::value - , "incompatible pointer type"); - - // delegate the call to get_impl_ptr<>() const - return get_impl_ptr(static_cast(nullptr)); - } - - /*! - @brief get a reference value (implicit) - - Implicit reference access to the internally stored JSON value. No copies - are made. - - @warning Writing data to the referee of the result yields an undefined - state. - - @tparam ReferenceType reference type; must be a reference to @ref array_t, - @ref object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, or - @ref number_float_t. Enforced by static assertion. - - @return reference to the internally stored JSON value if the requested - reference type @a ReferenceType fits to the JSON value; throws - type_error.303 otherwise - - @throw type_error.303 in case passed type @a ReferenceType is incompatible - with the stored JSON value; see example below - - @complexity Constant. - - @liveexample{The example shows several calls to `get_ref()`.,get_ref} - - @since version 1.1.0 - */ - template::value, int>::type = 0> - ReferenceType get_ref() - { - // delegate call to get_ref_impl - return get_ref_impl(*this); - } - - /*! - @brief get a reference value (implicit) - @copydoc get_ref() - */ - template::value and - std::is_const::type>::value, int>::type = 0> - ReferenceType get_ref() const - { - // delegate call to get_ref_impl - return get_ref_impl(*this); - } - - /*! - @brief get a value (implicit) - - Implicit type conversion between the JSON value and a compatible value. - The call is realized by calling @ref get() const. - - @tparam ValueType non-pointer type compatible to the JSON value, for - instance `int` for JSON integer numbers, `bool` for JSON booleans, or - `std::vector` types for JSON arrays. The character type of @ref string_t - as well as an initializer list of this type is excluded to avoid - ambiguities as these types implicitly convert to `std::string`. - - @return copy of the JSON value, converted to type @a ValueType - - @throw type_error.302 in case passed type @a ValueType is incompatible - to the JSON value type (e.g., the JSON value is of type boolean, but a - string is requested); see example below - - @complexity Linear in the size of the JSON value. - - @liveexample{The example below shows several conversions from JSON values - to other types. There a few things to note: (1) Floating-point numbers can - be converted to integers\, (2) A JSON array can be converted to a standard - `std::vector`\, (3) A JSON object can be converted to C++ - associative containers such as `std::unordered_map`.,operator__ValueType} - - @since version 1.0.0 - */ - template < typename ValueType, typename std::enable_if < - not std::is_pointer::value and - not std::is_same::value -#ifndef _MSC_VER // fix for issue #167 operator<< ambiguity under VS2015 - and not std::is_same>::value -#endif -#if defined(_MSC_VER) && _MSC_VER >1900 && defined(_HAS_CXX17) && _HAS_CXX17 == 1 // fix for issue #464 - and not std::is_same::value -#endif - , int >::type = 0 > - operator ValueType() const - { - // delegate the call to get<>() const - return get(); - } - - /// @} - - - //////////////////// - // element access // - //////////////////// - - /// @name element access - /// Access to the JSON value. - /// @{ - - /*! - @brief access specified array element with bounds checking - - Returns a reference to the element at specified location @a idx, with - bounds checking. - - @param[in] idx index of the element to access - - @return reference to the element at index @a idx - - @throw type_error.304 if the JSON value is not an array; in this case, - calling `at` with an index makes no sense. See example below. - @throw out_of_range.401 if the index @a idx is out of range of the array; - that is, `idx >= size()`. See example below. - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes in the JSON value. - - @complexity Constant. - - @since version 1.0.0 - - @liveexample{The example below shows how array elements can be read and - written using `at()`. It also demonstrates the different exceptions that - can be thrown.,at__size_type} - */ - reference at(size_type idx) - { - // at only works for arrays - if (is_array()) - { - JSON_TRY - { - return m_value.array->at(idx); - } - JSON_CATCH (std::out_of_range&) - { - // create better exception explanation - JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range")); - } - } - else - { - JSON_THROW(type_error::create(304, "cannot use at() with " + type_name())); - } - } - - /*! - @brief access specified array element with bounds checking - - Returns a const reference to the element at specified location @a idx, - with bounds checking. - - @param[in] idx index of the element to access - - @return const reference to the element at index @a idx - - @throw type_error.304 if the JSON value is not an array; in this case, - calling `at` with an index makes no sense. See example below. - @throw out_of_range.401 if the index @a idx is out of range of the array; - that is, `idx >= size()`. See example below. - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes in the JSON value. - - @complexity Constant. - - @since version 1.0.0 - - @liveexample{The example below shows how array elements can be read using - `at()`. It also demonstrates the different exceptions that can be thrown., - at__size_type_const} - */ - const_reference at(size_type idx) const - { - // at only works for arrays - if (is_array()) - { - JSON_TRY - { - return m_value.array->at(idx); - } - JSON_CATCH (std::out_of_range&) - { - // create better exception explanation - JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range")); - } - } - else - { - JSON_THROW(type_error::create(304, "cannot use at() with " + type_name())); - } - } - - /*! - @brief access specified object element with bounds checking - - Returns a reference to the element at with specified key @a key, with - bounds checking. - - @param[in] key key of the element to access - - @return reference to the element at key @a key - - @throw type_error.304 if the JSON value is not an object; in this case, - calling `at` with a key makes no sense. See example below. - @throw out_of_range.403 if the key @a key is is not stored in the object; - that is, `find(key) == end()`. See example below. - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes in the JSON value. - - @complexity Logarithmic in the size of the container. - - @sa @ref operator[](const typename object_t::key_type&) for unchecked - access by reference - @sa @ref value() for access by value with a default value - - @since version 1.0.0 - - @liveexample{The example below shows how object elements can be read and - written using `at()`. It also demonstrates the different exceptions that - can be thrown.,at__object_t_key_type} - */ - reference at(const typename object_t::key_type& key) - { - // at only works for objects - if (is_object()) - { - JSON_TRY - { - return m_value.object->at(key); - } - JSON_CATCH (std::out_of_range&) - { - // create better exception explanation - JSON_THROW(out_of_range::create(403, "key '" + key + "' not found")); - } - } - else - { - JSON_THROW(type_error::create(304, "cannot use at() with " + type_name())); - } - } - - /*! - @brief access specified object element with bounds checking - - Returns a const reference to the element at with specified key @a key, - with bounds checking. - - @param[in] key key of the element to access - - @return const reference to the element at key @a key - - @throw type_error.304 if the JSON value is not an object; in this case, - calling `at` with a key makes no sense. See example below. - @throw out_of_range.403 if the key @a key is is not stored in the object; - that is, `find(key) == end()`. See example below. - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes in the JSON value. - - @complexity Logarithmic in the size of the container. - - @sa @ref operator[](const typename object_t::key_type&) for unchecked - access by reference - @sa @ref value() for access by value with a default value - - @since version 1.0.0 - - @liveexample{The example below shows how object elements can be read using - `at()`. It also demonstrates the different exceptions that can be thrown., - at__object_t_key_type_const} - */ - const_reference at(const typename object_t::key_type& key) const - { - // at only works for objects - if (is_object()) - { - JSON_TRY - { - return m_value.object->at(key); - } - JSON_CATCH (std::out_of_range&) - { - // create better exception explanation - JSON_THROW(out_of_range::create(403, "key '" + key + "' not found")); - } - } - else - { - JSON_THROW(type_error::create(304, "cannot use at() with " + type_name())); - } - } - - /*! - @brief access specified array element - - Returns a reference to the element at specified location @a idx. - - @note If @a idx is beyond the range of the array (i.e., `idx >= size()`), - then the array is silently filled up with `null` values to make `idx` a - valid reference to the last stored element. - - @param[in] idx index of the element to access - - @return reference to the element at index @a idx - - @throw type_error.305 if the JSON value is not an array or null; in that - cases, using the [] operator with an index makes no sense. - - @complexity Constant if @a idx is in the range of the array. Otherwise - linear in `idx - size()`. - - @liveexample{The example below shows how array elements can be read and - written using `[]` operator. Note the addition of `null` - values.,operatorarray__size_type} - - @since version 1.0.0 - */ - reference operator[](size_type idx) - { - // implicitly convert null value to an empty array - if (is_null()) - { - m_type = value_t::array; - m_value.array = create(); - assert_invariant(); - } - - // operator[] only works for arrays - if (is_array()) - { - // fill up array with null values if given idx is outside range - if (idx >= m_value.array->size()) - { - m_value.array->insert(m_value.array->end(), - idx - m_value.array->size() + 1, - basic_json()); - } - - return m_value.array->operator[](idx); - } - - JSON_THROW(type_error::create(305, "cannot use operator[] with " + type_name())); - } - - /*! - @brief access specified array element - - Returns a const reference to the element at specified location @a idx. - - @param[in] idx index of the element to access - - @return const reference to the element at index @a idx - - @throw type_error.305 if the JSON value is not an array; in that cases, - using the [] operator with an index makes no sense. - - @complexity Constant. - - @liveexample{The example below shows how array elements can be read using - the `[]` operator.,operatorarray__size_type_const} - - @since version 1.0.0 - */ - const_reference operator[](size_type idx) const - { - // const operator[] only works for arrays - if (is_array()) - { - return m_value.array->operator[](idx); - } - - JSON_THROW(type_error::create(305, "cannot use operator[] with " + type_name())); - } - - /*! - @brief access specified object element - - Returns a reference to the element at with specified key @a key. - - @note If @a key is not found in the object, then it is silently added to - the object and filled with a `null` value to make `key` a valid reference. - In case the value was `null` before, it is converted to an object. - - @param[in] key key of the element to access - - @return reference to the element at key @a key - - @throw type_error.305 if the JSON value is not an object or null; in that - cases, using the [] operator with a key makes no sense. - - @complexity Logarithmic in the size of the container. - - @liveexample{The example below shows how object elements can be read and - written using the `[]` operator.,operatorarray__key_type} - - @sa @ref at(const typename object_t::key_type&) for access by reference - with range checking - @sa @ref value() for access by value with a default value - - @since version 1.0.0 - */ - reference operator[](const typename object_t::key_type& key) - { - // implicitly convert null value to an empty object - if (is_null()) - { - m_type = value_t::object; - m_value.object = create(); - assert_invariant(); - } - - // operator[] only works for objects - if (is_object()) - { - return m_value.object->operator[](key); - } - - JSON_THROW(type_error::create(305, "cannot use operator[] with " + type_name())); - } - - /*! - @brief read-only access specified object element - - Returns a const reference to the element at with specified key @a key. No - bounds checking is performed. - - @warning If the element with key @a key does not exist, the behavior is - undefined. - - @param[in] key key of the element to access - - @return const reference to the element at key @a key - - @pre The element with key @a key must exist. **This precondition is - enforced with an assertion.** - - @throw type_error.305 if the JSON value is not an object; in that cases, - using the [] operator with a key makes no sense. - - @complexity Logarithmic in the size of the container. - - @liveexample{The example below shows how object elements can be read using - the `[]` operator.,operatorarray__key_type_const} - - @sa @ref at(const typename object_t::key_type&) for access by reference - with range checking - @sa @ref value() for access by value with a default value - - @since version 1.0.0 - */ - const_reference operator[](const typename object_t::key_type& key) const - { - // const operator[] only works for objects - if (is_object()) - { - assert(m_value.object->find(key) != m_value.object->end()); - return m_value.object->find(key)->second; - } - - JSON_THROW(type_error::create(305, "cannot use operator[] with " + type_name())); - } - - /*! - @brief access specified object element - - Returns a reference to the element at with specified key @a key. - - @note If @a key is not found in the object, then it is silently added to - the object and filled with a `null` value to make `key` a valid reference. - In case the value was `null` before, it is converted to an object. - - @param[in] key key of the element to access - - @return reference to the element at key @a key - - @throw type_error.305 if the JSON value is not an object or null; in that - cases, using the [] operator with a key makes no sense. - - @complexity Logarithmic in the size of the container. - - @liveexample{The example below shows how object elements can be read and - written using the `[]` operator.,operatorarray__key_type} - - @sa @ref at(const typename object_t::key_type&) for access by reference - with range checking - @sa @ref value() for access by value with a default value - - @since version 1.0.0 - */ - template - reference operator[](T * (&key)[n]) - { - return operator[](static_cast(key)); - } - - /*! - @brief read-only access specified object element - - Returns a const reference to the element at with specified key @a key. No - bounds checking is performed. - - @warning If the element with key @a key does not exist, the behavior is - undefined. - - @note This function is required for compatibility reasons with Clang. - - @param[in] key key of the element to access - - @return const reference to the element at key @a key - - @throw type_error.305 if the JSON value is not an object; in that cases, - using the [] operator with a key makes no sense. - - @complexity Logarithmic in the size of the container. - - @liveexample{The example below shows how object elements can be read using - the `[]` operator.,operatorarray__key_type_const} - - @sa @ref at(const typename object_t::key_type&) for access by reference - with range checking - @sa @ref value() for access by value with a default value - - @since version 1.0.0 - */ - template - const_reference operator[](T * (&key)[n]) const - { - return operator[](static_cast(key)); - } - - /*! - @brief access specified object element - - Returns a reference to the element at with specified key @a key. - - @note If @a key is not found in the object, then it is silently added to - the object and filled with a `null` value to make `key` a valid reference. - In case the value was `null` before, it is converted to an object. - - @param[in] key key of the element to access - - @return reference to the element at key @a key - - @throw type_error.305 if the JSON value is not an object or null; in that - cases, using the [] operator with a key makes no sense. - - @complexity Logarithmic in the size of the container. - - @liveexample{The example below shows how object elements can be read and - written using the `[]` operator.,operatorarray__key_type} - - @sa @ref at(const typename object_t::key_type&) for access by reference - with range checking - @sa @ref value() for access by value with a default value - - @since version 1.1.0 - */ - template - reference operator[](T* key) - { - // implicitly convert null to object - if (is_null()) - { - m_type = value_t::object; - m_value = value_t::object; - assert_invariant(); - } - - // at only works for objects - if (is_object()) - { - return m_value.object->operator[](key); - } - - JSON_THROW(type_error::create(305, "cannot use operator[] with " + type_name())); - } - - /*! - @brief read-only access specified object element - - Returns a const reference to the element at with specified key @a key. No - bounds checking is performed. - - @warning If the element with key @a key does not exist, the behavior is - undefined. - - @param[in] key key of the element to access - - @return const reference to the element at key @a key - - @pre The element with key @a key must exist. **This precondition is - enforced with an assertion.** - - @throw type_error.305 if the JSON value is not an object; in that cases, - using the [] operator with a key makes no sense. - - @complexity Logarithmic in the size of the container. - - @liveexample{The example below shows how object elements can be read using - the `[]` operator.,operatorarray__key_type_const} - - @sa @ref at(const typename object_t::key_type&) for access by reference - with range checking - @sa @ref value() for access by value with a default value - - @since version 1.1.0 - */ - template - const_reference operator[](T* key) const - { - // at only works for objects - if (is_object()) - { - assert(m_value.object->find(key) != m_value.object->end()); - return m_value.object->find(key)->second; - } - - JSON_THROW(type_error::create(305, "cannot use operator[] with " + type_name())); - } - - /*! - @brief access specified object element with default value - - Returns either a copy of an object's element at the specified key @a key - or a given default value if no element with key @a key exists. - - The function is basically equivalent to executing - @code {.cpp} - try { - return at(key); - } catch(out_of_range) { - return default_value; - } - @endcode - - @note Unlike @ref at(const typename object_t::key_type&), this function - does not throw if the given key @a key was not found. - - @note Unlike @ref operator[](const typename object_t::key_type& key), this - function does not implicitly add an element to the position defined by @a - key. This function is furthermore also applicable to const objects. - - @param[in] key key of the element to access - @param[in] default_value the value to return if @a key is not found - - @tparam ValueType type compatible to JSON values, for instance `int` for - JSON integer numbers, `bool` for JSON booleans, or `std::vector` types for - JSON arrays. Note the type of the expected value at @a key and the default - value @a default_value must be compatible. - - @return copy of the element at key @a key or @a default_value if @a key - is not found - - @throw type_error.306 if the JSON value is not an objec; in that cases, - using `value()` with a key makes no sense. - - @complexity Logarithmic in the size of the container. - - @liveexample{The example below shows how object elements can be queried - with a default value.,basic_json__value} - - @sa @ref at(const typename object_t::key_type&) for access by reference - with range checking - @sa @ref operator[](const typename object_t::key_type&) for unchecked - access by reference - - @since version 1.0.0 - */ - template::value, int>::type = 0> - ValueType value(const typename object_t::key_type& key, ValueType default_value) const - { - // at only works for objects - if (is_object()) - { - // if key is found, return value and given default value otherwise - const auto it = find(key); - if (it != end()) - { - return *it; - } - - return default_value; - } - else - { - JSON_THROW(type_error::create(306, "cannot use value() with " + type_name())); - } - } - - /*! - @brief overload for a default value of type const char* - @copydoc basic_json::value(const typename object_t::key_type&, ValueType) const - */ - string_t value(const typename object_t::key_type& key, const char* default_value) const - { - return value(key, string_t(default_value)); - } - - /*! - @brief access specified object element via JSON Pointer with default value - - Returns either a copy of an object's element at the specified key @a key - or a given default value if no element with key @a key exists. - - The function is basically equivalent to executing - @code {.cpp} - try { - return at(ptr); - } catch(out_of_range) { - return default_value; - } - @endcode - - @note Unlike @ref at(const json_pointer&), this function does not throw - if the given key @a key was not found. - - @param[in] ptr a JSON pointer to the element to access - @param[in] default_value the value to return if @a ptr found no value - - @tparam ValueType type compatible to JSON values, for instance `int` for - JSON integer numbers, `bool` for JSON booleans, or `std::vector` types for - JSON arrays. Note the type of the expected value at @a key and the default - value @a default_value must be compatible. - - @return copy of the element at key @a key or @a default_value if @a key - is not found - - @throw type_error.306 if the JSON value is not an objec; in that cases, - using `value()` with a key makes no sense. - - @complexity Logarithmic in the size of the container. - - @liveexample{The example below shows how object elements can be queried - with a default value.,basic_json__value_ptr} - - @sa @ref operator[](const json_pointer&) for unchecked access by reference - - @since version 2.0.2 - */ - template::value, int>::type = 0> - ValueType value(const json_pointer& ptr, ValueType default_value) const - { - // at only works for objects - if (is_object()) - { - // if pointer resolves a value, return it or use default value - JSON_TRY - { - return ptr.get_checked(this); - } - JSON_CATCH (out_of_range&) - { - return default_value; - } - } - - JSON_THROW(type_error::create(306, "cannot use value() with " + type_name())); - } - - /*! - @brief overload for a default value of type const char* - @copydoc basic_json::value(const json_pointer&, ValueType) const - */ - string_t value(const json_pointer& ptr, const char* default_value) const - { - return value(ptr, string_t(default_value)); - } - - /*! - @brief access the first element - - Returns a reference to the first element in the container. For a JSON - container `c`, the expression `c.front()` is equivalent to `*c.begin()`. - - @return In case of a structured type (array or object), a reference to the - first element is returned. In case of number, string, or boolean values, a - reference to the value is returned. - - @complexity Constant. - - @pre The JSON value must not be `null` (would throw `std::out_of_range`) - or an empty array or object (undefined behavior, **guarded by - assertions**). - @post The JSON value remains unchanged. - - @throw invalid_iterator.214 when called on `null` value - - @liveexample{The following code shows an example for `front()`.,front} - - @sa @ref back() -- access the last element - - @since version 1.0.0 - */ - reference front() - { - return *begin(); - } - - /*! - @copydoc basic_json::front() - */ - const_reference front() const - { - return *cbegin(); - } - - /*! - @brief access the last element - - Returns a reference to the last element in the container. For a JSON - container `c`, the expression `c.back()` is equivalent to - @code {.cpp} - auto tmp = c.end(); - --tmp; - return *tmp; - @endcode - - @return In case of a structured type (array or object), a reference to the - last element is returned. In case of number, string, or boolean values, a - reference to the value is returned. - - @complexity Constant. - - @pre The JSON value must not be `null` (would throw `std::out_of_range`) - or an empty array or object (undefined behavior, **guarded by - assertions**). - @post The JSON value remains unchanged. - - @throw invalid_iterator.214 when called on a `null` value. See example - below. - - @liveexample{The following code shows an example for `back()`.,back} - - @sa @ref front() -- access the first element - - @since version 1.0.0 - */ - reference back() - { - auto tmp = end(); - --tmp; - return *tmp; - } - - /*! - @copydoc basic_json::back() - */ - const_reference back() const - { - auto tmp = cend(); - --tmp; - return *tmp; - } - - /*! - @brief remove element given an iterator - - Removes the element specified by iterator @a pos. The iterator @a pos must - be valid and dereferenceable. Thus the `end()` iterator (which is valid, - but is not dereferenceable) cannot be used as a value for @a pos. - - If called on a primitive type other than `null`, the resulting JSON value - will be `null`. - - @param[in] pos iterator to the element to remove - @return Iterator following the last removed element. If the iterator @a - pos refers to the last element, the `end()` iterator is returned. - - @tparam IteratorType an @ref iterator or @ref const_iterator - - @post Invalidates iterators and references at or after the point of the - erase, including the `end()` iterator. - - @throw type_error.307 if called on a `null` value; example: `"cannot use - erase() with null"` - @throw invalid_iterator.202 if called on an iterator which does not belong - to the current JSON value; example: `"iterator does not fit current - value"` - @throw invalid_iterator.205 if called on a primitive type with invalid - iterator (i.e., any iterator which is not `begin()`); example: `"iterator - out of range"` - - @complexity The complexity depends on the type: - - objects: amortized constant - - arrays: linear in distance between @a pos and the end of the container - - strings: linear in the length of the string - - other types: constant - - @liveexample{The example shows the result of `erase()` for different JSON - types.,erase__IteratorType} - - @sa @ref erase(IteratorType, IteratorType) -- removes the elements in - the given range - @sa @ref erase(const typename object_t::key_type&) -- removes the element - from an object at the given key - @sa @ref erase(const size_type) -- removes the element from an array at - the given index - - @since version 1.0.0 - */ - template::value or - std::is_same::value, int>::type - = 0> - IteratorType erase(IteratorType pos) - { - // make sure iterator fits the current value - if (this != pos.m_object) - { - JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value")); - } - - IteratorType result = end(); - - switch (m_type) - { - case value_t::boolean: - case value_t::number_float: - case value_t::number_integer: - case value_t::number_unsigned: - case value_t::string: - { - if (not pos.m_it.primitive_iterator.is_begin()) - { - JSON_THROW(invalid_iterator::create(205, "iterator out of range")); - } - - if (is_string()) - { - AllocatorType alloc; - alloc.destroy(m_value.string); - alloc.deallocate(m_value.string, 1); - m_value.string = nullptr; - } - - m_type = value_t::null; - assert_invariant(); - break; - } - - case value_t::object: - { - result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator); - break; - } - - case value_t::array: - { - result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator); - break; - } - - default: - { - JSON_THROW(type_error::create(307, "cannot use erase() with " + type_name())); - } - } - - return result; - } - - /*! - @brief remove elements given an iterator range - - Removes the element specified by the range `[first; last)`. The iterator - @a first does not need to be dereferenceable if `first == last`: erasing - an empty range is a no-op. - - If called on a primitive type other than `null`, the resulting JSON value - will be `null`. - - @param[in] first iterator to the beginning of the range to remove - @param[in] last iterator past the end of the range to remove - @return Iterator following the last removed element. If the iterator @a - second refers to the last element, the `end()` iterator is returned. - - @tparam IteratorType an @ref iterator or @ref const_iterator - - @post Invalidates iterators and references at or after the point of the - erase, including the `end()` iterator. - - @throw type_error.307 if called on a `null` value; example: `"cannot use - erase() with null"` - @throw invalid_iterator.203 if called on iterators which does not belong - to the current JSON value; example: `"iterators do not fit current value"` - @throw invalid_iterator.204 if called on a primitive type with invalid - iterators (i.e., if `first != begin()` and `last != end()`); example: - `"iterators out of range"` - - @complexity The complexity depends on the type: - - objects: `log(size()) + std::distance(first, last)` - - arrays: linear in the distance between @a first and @a last, plus linear - in the distance between @a last and end of the container - - strings: linear in the length of the string - - other types: constant - - @liveexample{The example shows the result of `erase()` for different JSON - types.,erase__IteratorType_IteratorType} - - @sa @ref erase(IteratorType) -- removes the element at a given position - @sa @ref erase(const typename object_t::key_type&) -- removes the element - from an object at the given key - @sa @ref erase(const size_type) -- removes the element from an array at - the given index - - @since version 1.0.0 - */ - template::value or - std::is_same::value, int>::type - = 0> - IteratorType erase(IteratorType first, IteratorType last) - { - // make sure iterator fits the current value - if (this != first.m_object or this != last.m_object) - { - JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value")); - } - - IteratorType result = end(); - - switch (m_type) - { - case value_t::boolean: - case value_t::number_float: - case value_t::number_integer: - case value_t::number_unsigned: - case value_t::string: - { - if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end()) - { - JSON_THROW(invalid_iterator::create(204, "iterators out of range")); - } - - if (is_string()) - { - AllocatorType alloc; - alloc.destroy(m_value.string); - alloc.deallocate(m_value.string, 1); - m_value.string = nullptr; - } - - m_type = value_t::null; - assert_invariant(); - break; - } - - case value_t::object: - { - result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator, - last.m_it.object_iterator); - break; - } - - case value_t::array: - { - result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator, - last.m_it.array_iterator); - break; - } - - default: - { - JSON_THROW(type_error::create(307, "cannot use erase() with " + type_name())); - } - } - - return result; - } - - /*! - @brief remove element from a JSON object given a key - - Removes elements from a JSON object with the key value @a key. - - @param[in] key value of the elements to remove - - @return Number of elements removed. If @a ObjectType is the default - `std::map` type, the return value will always be `0` (@a key was not - found) or `1` (@a key was found). - - @post References and iterators to the erased elements are invalidated. - Other references and iterators are not affected. - - @throw type_error.307 when called on a type other than JSON object; - example: `"cannot use erase() with null"` - - @complexity `log(size()) + count(key)` - - @liveexample{The example shows the effect of `erase()`.,erase__key_type} - - @sa @ref erase(IteratorType) -- removes the element at a given position - @sa @ref erase(IteratorType, IteratorType) -- removes the elements in - the given range - @sa @ref erase(const size_type) -- removes the element from an array at - the given index - - @since version 1.0.0 - */ - size_type erase(const typename object_t::key_type& key) - { - // this erase only works for objects - if (is_object()) - { - return m_value.object->erase(key); - } - - JSON_THROW(type_error::create(307, "cannot use erase() with " + type_name())); - } - - /*! - @brief remove element from a JSON array given an index - - Removes element from a JSON array at the index @a idx. - - @param[in] idx index of the element to remove - - @throw type_error.307 when called on a type other than JSON object; - example: `"cannot use erase() with null"` - @throw out_of_range.401 when `idx >= size()`; example: `"array index 17 - is out of range"` - - @complexity Linear in distance between @a idx and the end of the container. - - @liveexample{The example shows the effect of `erase()`.,erase__size_type} - - @sa @ref erase(IteratorType) -- removes the element at a given position - @sa @ref erase(IteratorType, IteratorType) -- removes the elements in - the given range - @sa @ref erase(const typename object_t::key_type&) -- removes the element - from an object at the given key - - @since version 1.0.0 - */ - void erase(const size_type idx) - { - // this erase only works for arrays - if (is_array()) - { - if (idx >= size()) - { - JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range")); - } - - m_value.array->erase(m_value.array->begin() + static_cast(idx)); - } - else - { - JSON_THROW(type_error::create(307, "cannot use erase() with " + type_name())); - } - } - - /// @} - - - //////////// - // lookup // - //////////// - - /// @name lookup - /// @{ - - /*! - @brief find an element in a JSON object - - Finds an element in a JSON object with key equivalent to @a key. If the - element is not found or the JSON value is not an object, end() is - returned. - - @note This method always returns @ref end() when executed on a JSON type - that is not an object. - - @param[in] key key value of the element to search for - - @return Iterator to an element with key equivalent to @a key. If no such - element is found or the JSON value is not an object, past-the-end (see - @ref end()) iterator is returned. - - @complexity Logarithmic in the size of the JSON object. - - @liveexample{The example shows how `find()` is used.,find__key_type} - - @since version 1.0.0 - */ - iterator find(typename object_t::key_type key) - { - auto result = end(); - - if (is_object()) - { - result.m_it.object_iterator = m_value.object->find(key); - } - - return result; - } - - /*! - @brief find an element in a JSON object - @copydoc find(typename object_t::key_type) - */ - const_iterator find(typename object_t::key_type key) const - { - auto result = cend(); - - if (is_object()) - { - result.m_it.object_iterator = m_value.object->find(key); - } - - return result; - } - - /*! - @brief returns the number of occurrences of a key in a JSON object - - Returns the number of elements with key @a key. If ObjectType is the - default `std::map` type, the return value will always be `0` (@a key was - not found) or `1` (@a key was found). - - @note This method always returns `0` when executed on a JSON type that is - not an object. - - @param[in] key key value of the element to count - - @return Number of elements with key @a key. If the JSON value is not an - object, the return value will be `0`. - - @complexity Logarithmic in the size of the JSON object. - - @liveexample{The example shows how `count()` is used.,count} - - @since version 1.0.0 - */ - size_type count(typename object_t::key_type key) const - { - // return 0 for all nonobject types - return is_object() ? m_value.object->count(key) : 0; - } - - /// @} - - - /////////////// - // iterators // - /////////////// - - /// @name iterators - /// @{ - - /*! - @brief returns an iterator to the first element - - Returns an iterator to the first element. - - @image html range-begin-end.svg "Illustration from cppreference.com" - - @return iterator to the first element - - @complexity Constant. - - @requirement This function helps `basic_json` satisfying the - [Container](http://en.cppreference.com/w/cpp/concept/Container) - requirements: - - The complexity is constant. - - @liveexample{The following code shows an example for `begin()`.,begin} - - @sa @ref cbegin() -- returns a const iterator to the beginning - @sa @ref end() -- returns an iterator to the end - @sa @ref cend() -- returns a const iterator to the end - - @since version 1.0.0 - */ - iterator begin() noexcept - { - iterator result(this); - result.set_begin(); - return result; - } - - /*! - @copydoc basic_json::cbegin() - */ - const_iterator begin() const noexcept - { - return cbegin(); - } - - /*! - @brief returns a const iterator to the first element - - Returns a const iterator to the first element. - - @image html range-begin-end.svg "Illustration from cppreference.com" - - @return const iterator to the first element - - @complexity Constant. - - @requirement This function helps `basic_json` satisfying the - [Container](http://en.cppreference.com/w/cpp/concept/Container) - requirements: - - The complexity is constant. - - Has the semantics of `const_cast(*this).begin()`. - - @liveexample{The following code shows an example for `cbegin()`.,cbegin} - - @sa @ref begin() -- returns an iterator to the beginning - @sa @ref end() -- returns an iterator to the end - @sa @ref cend() -- returns a const iterator to the end - - @since version 1.0.0 - */ - const_iterator cbegin() const noexcept - { - const_iterator result(this); - result.set_begin(); - return result; - } - - /*! - @brief returns an iterator to one past the last element - - Returns an iterator to one past the last element. - - @image html range-begin-end.svg "Illustration from cppreference.com" - - @return iterator one past the last element - - @complexity Constant. - - @requirement This function helps `basic_json` satisfying the - [Container](http://en.cppreference.com/w/cpp/concept/Container) - requirements: - - The complexity is constant. - - @liveexample{The following code shows an example for `end()`.,end} - - @sa @ref cend() -- returns a const iterator to the end - @sa @ref begin() -- returns an iterator to the beginning - @sa @ref cbegin() -- returns a const iterator to the beginning - - @since version 1.0.0 - */ - iterator end() noexcept - { - iterator result(this); - result.set_end(); - return result; - } - - /*! - @copydoc basic_json::cend() - */ - const_iterator end() const noexcept - { - return cend(); - } - - /*! - @brief returns a const iterator to one past the last element - - Returns a const iterator to one past the last element. - - @image html range-begin-end.svg "Illustration from cppreference.com" - - @return const iterator one past the last element - - @complexity Constant. - - @requirement This function helps `basic_json` satisfying the - [Container](http://en.cppreference.com/w/cpp/concept/Container) - requirements: - - The complexity is constant. - - Has the semantics of `const_cast(*this).end()`. - - @liveexample{The following code shows an example for `cend()`.,cend} - - @sa @ref end() -- returns an iterator to the end - @sa @ref begin() -- returns an iterator to the beginning - @sa @ref cbegin() -- returns a const iterator to the beginning - - @since version 1.0.0 - */ - const_iterator cend() const noexcept - { - const_iterator result(this); - result.set_end(); - return result; - } - - /*! - @brief returns an iterator to the reverse-beginning - - Returns an iterator to the reverse-beginning; that is, the last element. - - @image html range-rbegin-rend.svg "Illustration from cppreference.com" - - @complexity Constant. - - @requirement This function helps `basic_json` satisfying the - [ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer) - requirements: - - The complexity is constant. - - Has the semantics of `reverse_iterator(end())`. - - @liveexample{The following code shows an example for `rbegin()`.,rbegin} - - @sa @ref crbegin() -- returns a const reverse iterator to the beginning - @sa @ref rend() -- returns a reverse iterator to the end - @sa @ref crend() -- returns a const reverse iterator to the end - - @since version 1.0.0 - */ - reverse_iterator rbegin() noexcept - { - return reverse_iterator(end()); - } - - /*! - @copydoc basic_json::crbegin() - */ - const_reverse_iterator rbegin() const noexcept - { - return crbegin(); - } - - /*! - @brief returns an iterator to the reverse-end - - Returns an iterator to the reverse-end; that is, one before the first - element. - - @image html range-rbegin-rend.svg "Illustration from cppreference.com" - - @complexity Constant. - - @requirement This function helps `basic_json` satisfying the - [ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer) - requirements: - - The complexity is constant. - - Has the semantics of `reverse_iterator(begin())`. - - @liveexample{The following code shows an example for `rend()`.,rend} - - @sa @ref crend() -- returns a const reverse iterator to the end - @sa @ref rbegin() -- returns a reverse iterator to the beginning - @sa @ref crbegin() -- returns a const reverse iterator to the beginning - - @since version 1.0.0 - */ - reverse_iterator rend() noexcept - { - return reverse_iterator(begin()); - } - - /*! - @copydoc basic_json::crend() - */ - const_reverse_iterator rend() const noexcept - { - return crend(); - } - - /*! - @brief returns a const reverse iterator to the last element - - Returns a const iterator to the reverse-beginning; that is, the last - element. - - @image html range-rbegin-rend.svg "Illustration from cppreference.com" - - @complexity Constant. - - @requirement This function helps `basic_json` satisfying the - [ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer) - requirements: - - The complexity is constant. - - Has the semantics of `const_cast(*this).rbegin()`. - - @liveexample{The following code shows an example for `crbegin()`.,crbegin} - - @sa @ref rbegin() -- returns a reverse iterator to the beginning - @sa @ref rend() -- returns a reverse iterator to the end - @sa @ref crend() -- returns a const reverse iterator to the end - - @since version 1.0.0 - */ - const_reverse_iterator crbegin() const noexcept - { - return const_reverse_iterator(cend()); - } - - /*! - @brief returns a const reverse iterator to one before the first - - Returns a const reverse iterator to the reverse-end; that is, one before - the first element. - - @image html range-rbegin-rend.svg "Illustration from cppreference.com" - - @complexity Constant. - - @requirement This function helps `basic_json` satisfying the - [ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer) - requirements: - - The complexity is constant. - - Has the semantics of `const_cast(*this).rend()`. - - @liveexample{The following code shows an example for `crend()`.,crend} - - @sa @ref rend() -- returns a reverse iterator to the end - @sa @ref rbegin() -- returns a reverse iterator to the beginning - @sa @ref crbegin() -- returns a const reverse iterator to the beginning - - @since version 1.0.0 - */ - const_reverse_iterator crend() const noexcept - { - return const_reverse_iterator(cbegin()); - } - - private: - // forward declaration - template class iteration_proxy; - - public: - /*! - @brief wrapper to access iterator member functions in range-based for - - This function allows to access @ref iterator::key() and @ref - iterator::value() during range-based for loops. In these loops, a - reference to the JSON values is returned, so there is no access to the - underlying iterator. - - @note The name of this function is not yet final and may change in the - future. - */ - static iteration_proxy iterator_wrapper(reference cont) - { - return iteration_proxy(cont); - } - - /*! - @copydoc iterator_wrapper(reference) - */ - static iteration_proxy iterator_wrapper(const_reference cont) - { - return iteration_proxy(cont); - } - - /// @} - - - ////////////// - // capacity // - ////////////// - - /// @name capacity - /// @{ - - /*! - @brief checks whether the container is empty - - Checks if a JSON value has no elements. - - @return The return value depends on the different types and is - defined as follows: - Value type | return value - ----------- | ------------- - null | `true` - boolean | `false` - string | `false` - number | `false` - object | result of function `object_t::empty()` - array | result of function `array_t::empty()` - - @note This function does not return whether a string stored as JSON value - is empty - it returns whether the JSON container itself is empty which is - false in the case of a string. - - @complexity Constant, as long as @ref array_t and @ref object_t satisfy - the Container concept; that is, their `empty()` functions have constant - complexity. - - @requirement This function helps `basic_json` satisfying the - [Container](http://en.cppreference.com/w/cpp/concept/Container) - requirements: - - The complexity is constant. - - Has the semantics of `begin() == end()`. - - @liveexample{The following code uses `empty()` to check if a JSON - object contains any elements.,empty} - - @sa @ref size() -- returns the number of elements - - @since version 1.0.0 - */ - bool empty() const noexcept - { - switch (m_type) - { - case value_t::null: - { - // null values are empty - return true; - } - - case value_t::array: - { - // delegate call to array_t::empty() - return m_value.array->empty(); - } - - case value_t::object: - { - // delegate call to object_t::empty() - return m_value.object->empty(); - } - - default: - { - // all other types are nonempty - return false; - } - } - } - - /*! - @brief returns the number of elements - - Returns the number of elements in a JSON value. - - @return The return value depends on the different types and is - defined as follows: - Value type | return value - ----------- | ------------- - null | `0` - boolean | `1` - string | `1` - number | `1` - object | result of function object_t::size() - array | result of function array_t::size() - - @note This function does not return the length of a string stored as JSON - value - it returns the number of elements in the JSON value which is 1 in - the case of a string. - - @complexity Constant, as long as @ref array_t and @ref object_t satisfy - the Container concept; that is, their size() functions have constant - complexity. - - @requirement This function helps `basic_json` satisfying the - [Container](http://en.cppreference.com/w/cpp/concept/Container) - requirements: - - The complexity is constant. - - Has the semantics of `std::distance(begin(), end())`. - - @liveexample{The following code calls `size()` on the different value - types.,size} - - @sa @ref empty() -- checks whether the container is empty - @sa @ref max_size() -- returns the maximal number of elements - - @since version 1.0.0 - */ - size_type size() const noexcept - { - switch (m_type) - { - case value_t::null: - { - // null values are empty - return 0; - } - - case value_t::array: - { - // delegate call to array_t::size() - return m_value.array->size(); - } - - case value_t::object: - { - // delegate call to object_t::size() - return m_value.object->size(); - } - - default: - { - // all other types have size 1 - return 1; - } - } - } - - /*! - @brief returns the maximum possible number of elements - - Returns the maximum number of elements a JSON value is able to hold due to - system or library implementation limitations, i.e. `std::distance(begin(), - end())` for the JSON value. - - @return The return value depends on the different types and is - defined as follows: - Value type | return value - ----------- | ------------- - null | `0` (same as `size()`) - boolean | `1` (same as `size()`) - string | `1` (same as `size()`) - number | `1` (same as `size()`) - object | result of function `object_t::max_size()` - array | result of function `array_t::max_size()` - - @complexity Constant, as long as @ref array_t and @ref object_t satisfy - the Container concept; that is, their `max_size()` functions have constant - complexity. - - @requirement This function helps `basic_json` satisfying the - [Container](http://en.cppreference.com/w/cpp/concept/Container) - requirements: - - The complexity is constant. - - Has the semantics of returning `b.size()` where `b` is the largest - possible JSON value. - - @liveexample{The following code calls `max_size()` on the different value - types. Note the output is implementation specific.,max_size} - - @sa @ref size() -- returns the number of elements - - @since version 1.0.0 - */ - size_type max_size() const noexcept - { - switch (m_type) - { - case value_t::array: - { - // delegate call to array_t::max_size() - return m_value.array->max_size(); - } - - case value_t::object: - { - // delegate call to object_t::max_size() - return m_value.object->max_size(); - } - - default: - { - // all other types have max_size() == size() - return size(); - } - } - } - - /// @} - - - /////////////// - // modifiers // - /////////////// - - /// @name modifiers - /// @{ - - /*! - @brief clears the contents - - Clears the content of a JSON value and resets it to the default value as - if @ref basic_json(value_t) would have been called: - - Value type | initial value - ----------- | ------------- - null | `null` - boolean | `false` - string | `""` - number | `0` - object | `{}` - array | `[]` - - @complexity Linear in the size of the JSON value. - - @liveexample{The example below shows the effect of `clear()` to different - JSON types.,clear} - - @since version 1.0.0 - */ - void clear() noexcept - { - switch (m_type) - { - case value_t::number_integer: - { - m_value.number_integer = 0; - break; - } - - case value_t::number_unsigned: - { - m_value.number_unsigned = 0; - break; - } - - case value_t::number_float: - { - m_value.number_float = 0.0; - break; - } - - case value_t::boolean: - { - m_value.boolean = false; - break; - } - - case value_t::string: - { - m_value.string->clear(); - break; - } - - case value_t::array: - { - m_value.array->clear(); - break; - } - - case value_t::object: - { - m_value.object->clear(); - break; - } - - default: - { - break; - } - } - } - - /*! - @brief add an object to an array - - Appends the given element @a val to the end of the JSON value. If the - function is called on a JSON null value, an empty array is created before - appending @a val. - - @param[in] val the value to add to the JSON array - - @throw type_error.308 when called on a type other than JSON array or - null; example: `"cannot use push_back() with number"` - - @complexity Amortized constant. - - @liveexample{The example shows how `push_back()` and `+=` can be used to - add elements to a JSON array. Note how the `null` value was silently - converted to a JSON array.,push_back} - - @since version 1.0.0 - */ - void push_back(basic_json&& val) - { - // push_back only works for null objects or arrays - if (not(is_null() or is_array())) - { - JSON_THROW(type_error::create(308, "cannot use push_back() with " + type_name())); - } - - // transform null object into an array - if (is_null()) - { - m_type = value_t::array; - m_value = value_t::array; - assert_invariant(); - } - - // add element to array (move semantics) - m_value.array->push_back(std::move(val)); - // invalidate object - val.m_type = value_t::null; - } - - /*! - @brief add an object to an array - @copydoc push_back(basic_json&&) - */ - reference operator+=(basic_json&& val) - { - push_back(std::move(val)); - return *this; - } - - /*! - @brief add an object to an array - @copydoc push_back(basic_json&&) - */ - void push_back(const basic_json& val) - { - // push_back only works for null objects or arrays - if (not(is_null() or is_array())) - { - JSON_THROW(type_error::create(308, "cannot use push_back() with " + type_name())); - } - - // transform null object into an array - if (is_null()) - { - m_type = value_t::array; - m_value = value_t::array; - assert_invariant(); - } - - // add element to array - m_value.array->push_back(val); - } - - /*! - @brief add an object to an array - @copydoc push_back(basic_json&&) - */ - reference operator+=(const basic_json& val) - { - push_back(val); - return *this; - } - - /*! - @brief add an object to an object - - Inserts the given element @a val to the JSON object. If the function is - called on a JSON null value, an empty object is created before inserting - @a val. - - @param[in] val the value to add to the JSON object - - @throw type_error.308 when called on a type other than JSON object or - null; example: `"cannot use push_back() with number"` - - @complexity Logarithmic in the size of the container, O(log(`size()`)). - - @liveexample{The example shows how `push_back()` and `+=` can be used to - add elements to a JSON object. Note how the `null` value was silently - converted to a JSON object.,push_back__object_t__value} - - @since version 1.0.0 - */ - void push_back(const typename object_t::value_type& val) - { - // push_back only works for null objects or objects - if (not(is_null() or is_object())) - { - JSON_THROW(type_error::create(308, "cannot use push_back() with " + type_name())); - } - - // transform null object into an object - if (is_null()) - { - m_type = value_t::object; - m_value = value_t::object; - assert_invariant(); - } - - // add element to array - m_value.object->insert(val); - } - - /*! - @brief add an object to an object - @copydoc push_back(const typename object_t::value_type&) - */ - reference operator+=(const typename object_t::value_type& val) - { - push_back(val); - return *this; - } - - /*! - @brief add an object to an object - - This function allows to use `push_back` with an initializer list. In case - - 1. the current value is an object, - 2. the initializer list @a init contains only two elements, and - 3. the first element of @a init is a string, - - @a init is converted into an object element and added using - @ref push_back(const typename object_t::value_type&). Otherwise, @a init - is converted to a JSON value and added using @ref push_back(basic_json&&). - - @param[in] init an initializer list - - @complexity Linear in the size of the initializer list @a init. - - @note This function is required to resolve an ambiguous overload error, - because pairs like `{"key", "value"}` can be both interpreted as - `object_t::value_type` or `std::initializer_list`, see - https://github.com/nlohmann/json/issues/235 for more information. - - @liveexample{The example shows how initializer lists are treated as - objects when possible.,push_back__initializer_list} - */ - void push_back(std::initializer_list init) - { - if (is_object() and init.size() == 2 and init.begin()->is_string()) - { - const string_t key = *init.begin(); - push_back(typename object_t::value_type(key, *(init.begin() + 1))); - } - else - { - push_back(basic_json(init)); - } - } - - /*! - @brief add an object to an object - @copydoc push_back(std::initializer_list) - */ - reference operator+=(std::initializer_list init) - { - push_back(init); - return *this; - } - - /*! - @brief add an object to an array - - Creates a JSON value from the passed parameters @a args to the end of the - JSON value. If the function is called on a JSON null value, an empty array - is created before appending the value created from @a args. - - @param[in] args arguments to forward to a constructor of @ref basic_json - @tparam Args compatible types to create a @ref basic_json object - - @throw type_error.311 when called on a type other than JSON array or - null; example: `"cannot use emplace_back() with number"` - - @complexity Amortized constant. - - @liveexample{The example shows how `push_back()` can be used to add - elements to a JSON array. Note how the `null` value was silently converted - to a JSON array.,emplace_back} - - @since version 2.0.8 - */ - template - void emplace_back(Args&& ... args) - { - // emplace_back only works for null objects or arrays - if (not(is_null() or is_array())) - { - JSON_THROW(type_error::create(311, "cannot use emplace_back() with " + type_name())); - } - - // transform null object into an array - if (is_null()) - { - m_type = value_t::array; - m_value = value_t::array; - assert_invariant(); - } - - // add element to array (perfect forwarding) - m_value.array->emplace_back(std::forward(args)...); - } - - /*! - @brief add an object to an object if key does not exist - - Inserts a new element into a JSON object constructed in-place with the - given @a args if there is no element with the key in the container. If the - function is called on a JSON null value, an empty object is created before - appending the value created from @a args. - - @param[in] args arguments to forward to a constructor of @ref basic_json - @tparam Args compatible types to create a @ref basic_json object - - @return a pair consisting of an iterator to the inserted element, or the - already-existing element if no insertion happened, and a bool - denoting whether the insertion took place. - - @throw type_error.311 when called on a type other than JSON object or - null; example: `"cannot use emplace() with number"` - - @complexity Logarithmic in the size of the container, O(log(`size()`)). - - @liveexample{The example shows how `emplace()` can be used to add elements - to a JSON object. Note how the `null` value was silently converted to a - JSON object. Further note how no value is added if there was already one - value stored with the same key.,emplace} - - @since version 2.0.8 - */ - template - std::pair emplace(Args&& ... args) - { - // emplace only works for null objects or arrays - if (not(is_null() or is_object())) - { - JSON_THROW(type_error::create(311, "cannot use emplace() with " + type_name())); - } - - // transform null object into an object - if (is_null()) - { - m_type = value_t::object; - m_value = value_t::object; - assert_invariant(); - } - - // add element to array (perfect forwarding) - auto res = m_value.object->emplace(std::forward(args)...); - // create result iterator and set iterator to the result of emplace - auto it = begin(); - it.m_it.object_iterator = res.first; - - // return pair of iterator and boolean - return {it, res.second}; - } - - /*! - @brief inserts element - - Inserts element @a val before iterator @a pos. - - @param[in] pos iterator before which the content will be inserted; may be - the end() iterator - @param[in] val element to insert - @return iterator pointing to the inserted @a val. - - @throw type_error.309 if called on JSON values other than arrays; - example: `"cannot use insert() with string"` - @throw invalid_iterator.202 if @a pos is not an iterator of *this; - example: `"iterator does not fit current value"` - - @complexity Constant plus linear in the distance between @a pos and end of - the container. - - @liveexample{The example shows how `insert()` is used.,insert} - - @since version 1.0.0 - */ - iterator insert(const_iterator pos, const basic_json& val) - { - // insert only works for arrays - if (is_array()) - { - // check if iterator pos fits to this JSON value - if (pos.m_object != this) - { - JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value")); - } - - // insert to array and return iterator - iterator result(this); - result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val); - return result; - } - - JSON_THROW(type_error::create(309, "cannot use insert() with " + type_name())); - } - - /*! - @brief inserts element - @copydoc insert(const_iterator, const basic_json&) - */ - iterator insert(const_iterator pos, basic_json&& val) - { - return insert(pos, val); - } - - /*! - @brief inserts elements - - Inserts @a cnt copies of @a val before iterator @a pos. - - @param[in] pos iterator before which the content will be inserted; may be - the end() iterator - @param[in] cnt number of copies of @a val to insert - @param[in] val element to insert - @return iterator pointing to the first element inserted, or @a pos if - `cnt==0` - - @throw type_error.309 if called on JSON values other than arrays; example: - `"cannot use insert() with string"` - @throw invalid_iterator.202 if @a pos is not an iterator of *this; - example: `"iterator does not fit current value"` - - @complexity Linear in @a cnt plus linear in the distance between @a pos - and end of the container. - - @liveexample{The example shows how `insert()` is used.,insert__count} - - @since version 1.0.0 - */ - iterator insert(const_iterator pos, size_type cnt, const basic_json& val) - { - // insert only works for arrays - if (is_array()) - { - // check if iterator pos fits to this JSON value - if (pos.m_object != this) - { - JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value")); - } - - // insert to array and return iterator - iterator result(this); - result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val); - return result; - } - - JSON_THROW(type_error::create(309, "cannot use insert() with " + type_name())); - } - - /*! - @brief inserts elements - - Inserts elements from range `[first, last)` before iterator @a pos. - - @param[in] pos iterator before which the content will be inserted; may be - the end() iterator - @param[in] first begin of the range of elements to insert - @param[in] last end of the range of elements to insert - - @throw type_error.309 if called on JSON values other than arrays; example: - `"cannot use insert() with string"` - @throw invalid_iterator.202 if @a pos is not an iterator of *this; - example: `"iterator does not fit current value"` - @throw invalid_iterator.210 if @a first and @a last do not belong to the - same JSON value; example: `"iterators do not fit"` - @throw invalid_iterator.211 if @a first or @a last are iterators into - container for which insert is called; example: `"passed iterators may not - belong to container"` - - @return iterator pointing to the first element inserted, or @a pos if - `first==last` - - @complexity Linear in `std::distance(first, last)` plus linear in the - distance between @a pos and end of the container. - - @liveexample{The example shows how `insert()` is used.,insert__range} - - @since version 1.0.0 - */ - iterator insert(const_iterator pos, const_iterator first, const_iterator last) - { - // insert only works for arrays - if (not is_array()) - { - JSON_THROW(type_error::create(309, "cannot use insert() with " + type_name())); - } - - // check if iterator pos fits to this JSON value - if (pos.m_object != this) - { - JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value")); - } - - // check if range iterators belong to the same JSON object - if (first.m_object != last.m_object) - { - JSON_THROW(invalid_iterator::create(210, "iterators do not fit")); - } - - if (first.m_object == this or last.m_object == this) - { - JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container")); - } - - // insert to array and return iterator - iterator result(this); - result.m_it.array_iterator = m_value.array->insert( - pos.m_it.array_iterator, - first.m_it.array_iterator, - last.m_it.array_iterator); - return result; - } - - /*! - @brief inserts elements - - Inserts elements from initializer list @a ilist before iterator @a pos. - - @param[in] pos iterator before which the content will be inserted; may be - the end() iterator - @param[in] ilist initializer list to insert the values from - - @throw type_error.309 if called on JSON values other than arrays; example: - `"cannot use insert() with string"` - @throw invalid_iterator.202 if @a pos is not an iterator of *this; - example: `"iterator does not fit current value"` - - @return iterator pointing to the first element inserted, or @a pos if - `ilist` is empty - - @complexity Linear in `ilist.size()` plus linear in the distance between - @a pos and end of the container. - - @liveexample{The example shows how `insert()` is used.,insert__ilist} - - @since version 1.0.0 - */ - iterator insert(const_iterator pos, std::initializer_list ilist) - { - // insert only works for arrays - if (not is_array()) - { - JSON_THROW(type_error::create(309, "cannot use insert() with " + type_name())); - } - - // check if iterator pos fits to this JSON value - if (pos.m_object != this) - { - JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value")); - } - - // insert to array and return iterator - iterator result(this); - result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist); - return result; - } - - /*! - @brief inserts elements - - Inserts elements from range `[first, last)`. - - @param[in] first begin of the range of elements to insert - @param[in] last end of the range of elements to insert - - @throw type_error.309 if called on JSON values other than objects; example: - `"cannot use insert() with string"` - @throw invalid_iterator.202 if iterator @a first or @a last does does not - point to an object; example: `"iterators first and last must point to - objects"` - @throw invalid_iterator.210 if @a first and @a last do not belong to the - same JSON value; example: `"iterators do not fit"` - - @complexity Logarithmic: `O(N*log(size() + N))`, where `N` is the number - of elements to insert. - - @liveexample{The example shows how `insert()` is used.,insert__range_object} - - @since version 3.0.0 - */ - void insert(const_iterator first, const_iterator last) - { - // insert only works for objects - if (not is_object()) - { - JSON_THROW(type_error::create(309, "cannot use insert() with " + type_name())); - } - - // check if range iterators belong to the same JSON object - if (first.m_object != last.m_object) - { - JSON_THROW(invalid_iterator::create(210, "iterators do not fit")); - } - - // passed iterators must belong to objects - if (not first.m_object->is_object() or not first.m_object->is_object()) - { - JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects")); - } - - m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator); - } - - /*! - @brief exchanges the values - - Exchanges the contents of the JSON value with those of @a other. Does not - invoke any move, copy, or swap operations on individual elements. All - iterators and references remain valid. The past-the-end iterator is - invalidated. - - @param[in,out] other JSON value to exchange the contents with - - @complexity Constant. - - @liveexample{The example below shows how JSON values can be swapped with - `swap()`.,swap__reference} - - @since version 1.0.0 - */ - void swap(reference other) noexcept ( - std::is_nothrow_move_constructible::value and - std::is_nothrow_move_assignable::value and - std::is_nothrow_move_constructible::value and - std::is_nothrow_move_assignable::value - ) - { - std::swap(m_type, other.m_type); - std::swap(m_value, other.m_value); - assert_invariant(); - } - - /*! - @brief exchanges the values - - Exchanges the contents of a JSON array with those of @a other. Does not - invoke any move, copy, or swap operations on individual elements. All - iterators and references remain valid. The past-the-end iterator is - invalidated. - - @param[in,out] other array to exchange the contents with - - @throw type_error.310 when JSON value is not an array; example: `"cannot - use swap() with string"` - - @complexity Constant. - - @liveexample{The example below shows how arrays can be swapped with - `swap()`.,swap__array_t} - - @since version 1.0.0 - */ - void swap(array_t& other) - { - // swap only works for arrays - if (is_array()) - { - std::swap(*(m_value.array), other); - } - else - { - JSON_THROW(type_error::create(310, "cannot use swap() with " + type_name())); - } - } - - /*! - @brief exchanges the values - - Exchanges the contents of a JSON object with those of @a other. Does not - invoke any move, copy, or swap operations on individual elements. All - iterators and references remain valid. The past-the-end iterator is - invalidated. - - @param[in,out] other object to exchange the contents with - - @throw type_error.310 when JSON value is not an object; example: - `"cannot use swap() with string"` - - @complexity Constant. - - @liveexample{The example below shows how objects can be swapped with - `swap()`.,swap__object_t} - - @since version 1.0.0 - */ - void swap(object_t& other) - { - // swap only works for objects - if (is_object()) - { - std::swap(*(m_value.object), other); - } - else - { - JSON_THROW(type_error::create(310, "cannot use swap() with " + type_name())); - } - } - - /*! - @brief exchanges the values - - Exchanges the contents of a JSON string with those of @a other. Does not - invoke any move, copy, or swap operations on individual elements. All - iterators and references remain valid. The past-the-end iterator is - invalidated. - - @param[in,out] other string to exchange the contents with - - @throw type_error.310 when JSON value is not a string; example: `"cannot - use swap() with boolean"` - - @complexity Constant. - - @liveexample{The example below shows how strings can be swapped with - `swap()`.,swap__string_t} - - @since version 1.0.0 - */ - void swap(string_t& other) - { - // swap only works for strings - if (is_string()) - { - std::swap(*(m_value.string), other); - } - else - { - JSON_THROW(type_error::create(310, "cannot use swap() with " + type_name())); - } - } - - /// @} - - public: - ////////////////////////////////////////// - // lexicographical comparison operators // - ////////////////////////////////////////// - - /// @name lexicographical comparison operators - /// @{ - - /*! - @brief comparison: equal - - Compares two JSON values for equality according to the following rules: - - Two JSON values are equal if (1) they are from the same type and (2) - their stored values are the same according to their respective - `operator==`. - - Integer and floating-point numbers are automatically converted before - comparison. Floating-point numbers are compared indirectly: two - floating-point numbers `f1` and `f2` are considered equal if neither - `f1 > f2` nor `f2 > f1` holds. Note than two NaN values are always - treated as unequal. - - Two JSON null values are equal. - - @note NaN values never compare equal to themselves or to other NaN values. - - @param[in] lhs first JSON value to consider - @param[in] rhs second JSON value to consider - @return whether the values @a lhs and @a rhs are equal - - @complexity Linear. - - @liveexample{The example demonstrates comparing several JSON - types.,operator__equal} - - @since version 1.0.0 - */ - friend bool operator==(const_reference lhs, const_reference rhs) noexcept - { - const auto lhs_type = lhs.type(); - const auto rhs_type = rhs.type(); - - if (lhs_type == rhs_type) - { - switch (lhs_type) - { - case value_t::array: - { - return *lhs.m_value.array == *rhs.m_value.array; - } - case value_t::object: - { - return *lhs.m_value.object == *rhs.m_value.object; - } - case value_t::null: - { - return true; - } - case value_t::string: - { - return *lhs.m_value.string == *rhs.m_value.string; - } - case value_t::boolean: - { - return lhs.m_value.boolean == rhs.m_value.boolean; - } - case value_t::number_integer: - { - return lhs.m_value.number_integer == rhs.m_value.number_integer; - } - case value_t::number_unsigned: - { - return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned; - } - case value_t::number_float: - { - return lhs.m_value.number_float == rhs.m_value.number_float; - } - default: - { - return false; - } - } - } - else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float) - { - return static_cast(lhs.m_value.number_integer) == rhs.m_value.number_float; - } - else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer) - { - return lhs.m_value.number_float == static_cast(rhs.m_value.number_integer); - } - else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float) - { - return static_cast(lhs.m_value.number_unsigned) == rhs.m_value.number_float; - } - else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned) - { - return lhs.m_value.number_float == static_cast(rhs.m_value.number_unsigned); - } - else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer) - { - return static_cast(lhs.m_value.number_unsigned) == rhs.m_value.number_integer; - } - else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned) - { - return lhs.m_value.number_integer == static_cast(rhs.m_value.number_unsigned); - } - - return false; - } - - /*! - @brief comparison: equal - @copydoc operator==(const_reference, const_reference) - */ - template::value, int>::type = 0> - friend bool operator==(const_reference lhs, const ScalarType rhs) noexcept - { - return (lhs == basic_json(rhs)); - } - - /*! - @brief comparison: equal - @copydoc operator==(const_reference, const_reference) - */ - template::value, int>::type = 0> - friend bool operator==(const ScalarType lhs, const_reference rhs) noexcept - { - return (basic_json(lhs) == rhs); - } - - /*! - @brief comparison: not equal - - Compares two JSON values for inequality by calculating `not (lhs == rhs)`. - - @param[in] lhs first JSON value to consider - @param[in] rhs second JSON value to consider - @return whether the values @a lhs and @a rhs are not equal - - @complexity Linear. - - @liveexample{The example demonstrates comparing several JSON - types.,operator__notequal} - - @since version 1.0.0 - */ - friend bool operator!=(const_reference lhs, const_reference rhs) noexcept - { - return not (lhs == rhs); - } - - /*! - @brief comparison: not equal - @copydoc operator!=(const_reference, const_reference) - */ - template::value, int>::type = 0> - friend bool operator!=(const_reference lhs, const ScalarType rhs) noexcept - { - return (lhs != basic_json(rhs)); - } - - /*! - @brief comparison: not equal - @copydoc operator!=(const_reference, const_reference) - */ - template::value, int>::type = 0> - friend bool operator!=(const ScalarType lhs, const_reference rhs) noexcept - { - return (basic_json(lhs) != rhs); - } - - /*! - @brief comparison: less than - - Compares whether one JSON value @a lhs is less than another JSON value @a - rhs according to the following rules: - - If @a lhs and @a rhs have the same type, the values are compared using - the default `<` operator. - - Integer and floating-point numbers are automatically converted before - comparison - - In case @a lhs and @a rhs have different types, the values are ignored - and the order of the types is considered, see - @ref operator<(const value_t, const value_t). - - @param[in] lhs first JSON value to consider - @param[in] rhs second JSON value to consider - @return whether @a lhs is less than @a rhs - - @complexity Linear. - - @liveexample{The example demonstrates comparing several JSON - types.,operator__less} - - @since version 1.0.0 - */ - friend bool operator<(const_reference lhs, const_reference rhs) noexcept - { - const auto lhs_type = lhs.type(); - const auto rhs_type = rhs.type(); - - if (lhs_type == rhs_type) - { - switch (lhs_type) - { - case value_t::array: - { - return *lhs.m_value.array < *rhs.m_value.array; - } - case value_t::object: - { - return *lhs.m_value.object < *rhs.m_value.object; - } - case value_t::null: - { - return false; - } - case value_t::string: - { - return *lhs.m_value.string < *rhs.m_value.string; - } - case value_t::boolean: - { - return lhs.m_value.boolean < rhs.m_value.boolean; - } - case value_t::number_integer: - { - return lhs.m_value.number_integer < rhs.m_value.number_integer; - } - case value_t::number_unsigned: - { - return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned; - } - case value_t::number_float: - { - return lhs.m_value.number_float < rhs.m_value.number_float; - } - default: - { - return false; - } - } - } - else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float) - { - return static_cast(lhs.m_value.number_integer) < rhs.m_value.number_float; - } - else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer) - { - return lhs.m_value.number_float < static_cast(rhs.m_value.number_integer); - } - else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float) - { - return static_cast(lhs.m_value.number_unsigned) < rhs.m_value.number_float; - } - else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned) - { - return lhs.m_value.number_float < static_cast(rhs.m_value.number_unsigned); - } - else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned) - { - return lhs.m_value.number_integer < static_cast(rhs.m_value.number_unsigned); - } - else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer) - { - return static_cast(lhs.m_value.number_unsigned) < rhs.m_value.number_integer; - } - - // We only reach this line if we cannot compare values. In that case, - // we compare types. Note we have to call the operator explicitly, - // because MSVC has problems otherwise. - return operator<(lhs_type, rhs_type); - } - - /*! - @brief comparison: less than - @copydoc operator<(const_reference, const_reference) - */ - template::value, int>::type = 0> - friend bool operator<(const_reference lhs, const ScalarType rhs) noexcept - { - return (lhs < basic_json(rhs)); - } - - /*! - @brief comparison: less than - @copydoc operator<(const_reference, const_reference) - */ - template::value, int>::type = 0> - friend bool operator<(const ScalarType lhs, const_reference rhs) noexcept - { - return (basic_json(lhs) < rhs); - } - - /*! - @brief comparison: less than or equal - - Compares whether one JSON value @a lhs is less than or equal to another - JSON value by calculating `not (rhs < lhs)`. - - @param[in] lhs first JSON value to consider - @param[in] rhs second JSON value to consider - @return whether @a lhs is less than or equal to @a rhs - - @complexity Linear. - - @liveexample{The example demonstrates comparing several JSON - types.,operator__greater} - - @since version 1.0.0 - */ - friend bool operator<=(const_reference lhs, const_reference rhs) noexcept - { - return not (rhs < lhs); - } - - /*! - @brief comparison: less than or equal - @copydoc operator<=(const_reference, const_reference) - */ - template::value, int>::type = 0> - friend bool operator<=(const_reference lhs, const ScalarType rhs) noexcept - { - return (lhs <= basic_json(rhs)); - } - - /*! - @brief comparison: less than or equal - @copydoc operator<=(const_reference, const_reference) - */ - template::value, int>::type = 0> - friend bool operator<=(const ScalarType lhs, const_reference rhs) noexcept - { - return (basic_json(lhs) <= rhs); - } - - /*! - @brief comparison: greater than - - Compares whether one JSON value @a lhs is greater than another - JSON value by calculating `not (lhs <= rhs)`. - - @param[in] lhs first JSON value to consider - @param[in] rhs second JSON value to consider - @return whether @a lhs is greater than to @a rhs - - @complexity Linear. - - @liveexample{The example demonstrates comparing several JSON - types.,operator__lessequal} - - @since version 1.0.0 - */ - friend bool operator>(const_reference lhs, const_reference rhs) noexcept - { - return not (lhs <= rhs); - } - - /*! - @brief comparison: greater than - @copydoc operator>(const_reference, const_reference) - */ - template::value, int>::type = 0> - friend bool operator>(const_reference lhs, const ScalarType rhs) noexcept - { - return (lhs > basic_json(rhs)); - } - - /*! - @brief comparison: greater than - @copydoc operator>(const_reference, const_reference) - */ - template::value, int>::type = 0> - friend bool operator>(const ScalarType lhs, const_reference rhs) noexcept - { - return (basic_json(lhs) > rhs); - } - - /*! - @brief comparison: greater than or equal - - Compares whether one JSON value @a lhs is greater than or equal to another - JSON value by calculating `not (lhs < rhs)`. - - @param[in] lhs first JSON value to consider - @param[in] rhs second JSON value to consider - @return whether @a lhs is greater than or equal to @a rhs - - @complexity Linear. - - @liveexample{The example demonstrates comparing several JSON - types.,operator__greaterequal} - - @since version 1.0.0 - */ - friend bool operator>=(const_reference lhs, const_reference rhs) noexcept - { - return not (lhs < rhs); - } - - /*! - @brief comparison: greater than or equal - @copydoc operator>=(const_reference, const_reference) - */ - template::value, int>::type = 0> - friend bool operator>=(const_reference lhs, const ScalarType rhs) noexcept - { - return (lhs >= basic_json(rhs)); - } - - /*! - @brief comparison: greater than or equal - @copydoc operator>=(const_reference, const_reference) - */ - template::value, int>::type = 0> - friend bool operator>=(const ScalarType lhs, const_reference rhs) noexcept - { - return (basic_json(lhs) >= rhs); - } - - /// @} - - - /////////////////// - // serialization // - /////////////////// - - /// @name serialization - /// @{ - - private: - /*! - @brief wrapper around the serialization functions - */ - class serializer - { - private: - serializer(const serializer&) = delete; - serializer& operator=(const serializer&) = delete; - - public: - /*! - @param[in] s output stream to serialize to - */ - serializer(std::ostream& s) - : o(s), loc(std::localeconv()), - thousands_sep(!loc->thousands_sep ? '\0' : loc->thousands_sep[0]), - decimal_point(!loc->decimal_point ? '\0' : loc->decimal_point[0]) - {} - - /*! - @brief internal implementation of the serialization function - - This function is called by the public member function dump and - organizes the serialization internally. The indentation level is - propagated as additional parameter. In case of arrays and objects, the - function is called recursively. - - - strings and object keys are escaped using `escape_string()` - - integer numbers are converted implicitly via `operator<<` - - floating-point numbers are converted to a string using `"%g"` format - - @param[in] val value to serialize - @param[in] pretty_print whether the output shall be pretty-printed - @param[in] indent_step the indent level - @param[in] current_indent the current indent level (only used internally) - */ - void dump(const basic_json& val, - const bool pretty_print, - const unsigned int indent_step, - const unsigned int current_indent = 0) - { - switch (val.m_type) - { - case value_t::object: - { - if (val.m_value.object->empty()) - { - o.write("{}", 2); - return; - } - - if (pretty_print) - { - o.write("{\n", 2); - - // variable to hold indentation for recursive calls - const auto new_indent = current_indent + indent_step; - if (indent_string.size() < new_indent) - { - indent_string.resize(new_indent, ' '); - } - - // first n-1 elements - auto i = val.m_value.object->cbegin(); - for (size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i) - { - o.write(indent_string.c_str(), static_cast(new_indent)); - o.put('\"'); - dump_escaped(i->first); - o.write("\": ", 3); - dump(i->second, true, indent_step, new_indent); - o.write(",\n", 2); - } - - // last element - assert(i != val.m_value.object->cend()); - o.write(indent_string.c_str(), static_cast(new_indent)); - o.put('\"'); - dump_escaped(i->first); - o.write("\": ", 3); - dump(i->second, true, indent_step, new_indent); - - o.put('\n'); - o.write(indent_string.c_str(), static_cast(current_indent)); - o.put('}'); - } - else - { - o.put('{'); - - // first n-1 elements - auto i = val.m_value.object->cbegin(); - for (size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i) - { - o.put('\"'); - dump_escaped(i->first); - o.write("\":", 2); - dump(i->second, false, indent_step, current_indent); - o.put(','); - } - - // last element - assert(i != val.m_value.object->cend()); - o.put('\"'); - dump_escaped(i->first); - o.write("\":", 2); - dump(i->second, false, indent_step, current_indent); - - o.put('}'); - } - - return; - } - - case value_t::array: - { - if (val.m_value.array->empty()) - { - o.write("[]", 2); - return; - } - - if (pretty_print) - { - o.write("[\n", 2); - - // variable to hold indentation for recursive calls - const auto new_indent = current_indent + indent_step; - if (indent_string.size() < new_indent) - { - indent_string.resize(new_indent, ' '); - } - - // first n-1 elements - for (auto i = val.m_value.array->cbegin(); i != val.m_value.array->cend() - 1; ++i) - { - o.write(indent_string.c_str(), static_cast(new_indent)); - dump(*i, true, indent_step, new_indent); - o.write(",\n", 2); - } - - // last element - assert(not val.m_value.array->empty()); - o.write(indent_string.c_str(), static_cast(new_indent)); - dump(val.m_value.array->back(), true, indent_step, new_indent); - - o.put('\n'); - o.write(indent_string.c_str(), static_cast(current_indent)); - o.put(']'); - } - else - { - o.put('['); - - // first n-1 elements - for (auto i = val.m_value.array->cbegin(); i != val.m_value.array->cend() - 1; ++i) - { - dump(*i, false, indent_step, current_indent); - o.put(','); - } - - // last element - assert(not val.m_value.array->empty()); - dump(val.m_value.array->back(), false, indent_step, current_indent); - - o.put(']'); - } - - return; - } - - case value_t::string: - { - o.put('\"'); - dump_escaped(*val.m_value.string); - o.put('\"'); - return; - } - - case value_t::boolean: - { - if (val.m_value.boolean) - { - o.write("true", 4); - } - else - { - o.write("false", 5); - } - return; - } - - case value_t::number_integer: - { - dump_integer(val.m_value.number_integer); - return; - } - - case value_t::number_unsigned: - { - dump_integer(val.m_value.number_unsigned); - return; - } - - case value_t::number_float: - { - dump_float(val.m_value.number_float); - return; - } - - case value_t::discarded: - { - o.write("", 11); - return; - } - - case value_t::null: - { - o.write("null", 4); - return; - } - } - } - - private: - /*! - @brief calculates the extra space to escape a JSON string - - @param[in] s the string to escape - @return the number of characters required to escape string @a s - - @complexity Linear in the length of string @a s. - */ - static std::size_t extra_space(const string_t& s) noexcept - { - return std::accumulate(s.begin(), s.end(), size_t{}, - [](size_t res, typename string_t::value_type c) - { - switch (c) - { - case '"': - case '\\': - case '\b': - case '\f': - case '\n': - case '\r': - case '\t': - { - // from c (1 byte) to \x (2 bytes) - return res + 1; - } - - case 0x00: - case 0x01: - case 0x02: - case 0x03: - case 0x04: - case 0x05: - case 0x06: - case 0x07: - case 0x0b: - case 0x0e: - case 0x0f: - case 0x10: - case 0x11: - case 0x12: - case 0x13: - case 0x14: - case 0x15: - case 0x16: - case 0x17: - case 0x18: - case 0x19: - case 0x1a: - case 0x1b: - case 0x1c: - case 0x1d: - case 0x1e: - case 0x1f: - { - // from c (1 byte) to \uxxxx (6 bytes) - return res + 5; - } - - default: - { - return res; - } - } - }); - } - - /*! - @brief dump escaped string - - Escape a string by replacing certain special characters by a sequence - of an escape character (backslash) and another character and other - control characters by a sequence of "\u" followed by a four-digit hex - representation. The escaped string is written to output stream @a o. - - @param[in] s the string to escape - - @complexity Linear in the length of string @a s. - */ - void dump_escaped(const string_t& s) const - { - const auto space = extra_space(s); - if (space == 0) - { - o.write(s.c_str(), static_cast(s.size())); - return; - } - - // create a result string of necessary size - string_t result(s.size() + space, '\\'); - std::size_t pos = 0; - - for (const auto& c : s) - { - switch (c) - { - // quotation mark (0x22) - case '"': - { - result[pos + 1] = '"'; - pos += 2; - break; - } - - // reverse solidus (0x5c) - case '\\': - { - // nothing to change - pos += 2; - break; - } - - // backspace (0x08) - case '\b': - { - result[pos + 1] = 'b'; - pos += 2; - break; - } - - // formfeed (0x0c) - case '\f': - { - result[pos + 1] = 'f'; - pos += 2; - break; - } - - // newline (0x0a) - case '\n': - { - result[pos + 1] = 'n'; - pos += 2; - break; - } - - // carriage return (0x0d) - case '\r': - { - result[pos + 1] = 'r'; - pos += 2; - break; - } - - // horizontal tab (0x09) - case '\t': - { - result[pos + 1] = 't'; - pos += 2; - break; - } - - case 0x00: - case 0x01: - case 0x02: - case 0x03: - case 0x04: - case 0x05: - case 0x06: - case 0x07: - case 0x0b: - case 0x0e: - case 0x0f: - case 0x10: - case 0x11: - case 0x12: - case 0x13: - case 0x14: - case 0x15: - case 0x16: - case 0x17: - case 0x18: - case 0x19: - case 0x1a: - case 0x1b: - case 0x1c: - case 0x1d: - case 0x1e: - case 0x1f: - { - // convert a number 0..15 to its hex representation - // (0..f) - static const char hexify[16] = - { - '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' - }; - - // print character c as \uxxxx - for (const char m : - { 'u', '0', '0', hexify[c >> 4], hexify[c & 0x0f] - }) - { - result[++pos] = m; - } - - ++pos; - break; - } - - default: - { - // all other characters are added as-is - result[pos++] = c; - break; - } - } - } - - assert(pos == s.size() + space); - o.write(result.c_str(), static_cast(result.size())); - } - - /*! - @brief dump an integer - - Dump a given integer to output stream @a o. Works internally with - @a number_buffer. - - @param[in] x integer number (signed or unsigned) to dump - @tparam NumberType either @a number_integer_t or @a number_unsigned_t - */ - template::value or - std::is_same::value, int> = 0> - void dump_integer(NumberType x) - { - // special case for "0" - if (x == 0) - { - o.put('0'); - return; - } - - const bool is_negative = x < 0; - size_t i = 0; - - // spare 1 byte for '\0' - while (x != 0 and i < number_buffer.size() - 1) - { - const auto digit = std::labs(static_cast(x % 10)); - number_buffer[i++] = static_cast('0' + digit); - x /= 10; - } - - // make sure the number has been processed completely - assert(x == 0); - - if (is_negative) - { - // make sure there is capacity for the '-' - assert(i < number_buffer.size() - 2); - number_buffer[i++] = '-'; - } - - std::reverse(number_buffer.begin(), number_buffer.begin() + i); - o.write(number_buffer.data(), static_cast(i)); - } - - /*! - @brief dump a floating-point number - - Dump a given floating-point number to output stream @a o. Works - internally with @a number_buffer. - - @param[in] x floating-point number to dump - */ - void dump_float(number_float_t x) - { - // NaN / inf - if (not std::isfinite(x) or std::isnan(x)) - { - o.write("null", 4); - return; - } - - // special case for 0.0 and -0.0 - if (x == 0) - { - if (std::signbit(x)) - { - o.write("-0.0", 4); - } - else - { - o.write("0.0", 3); - } - return; - } - - // get number of digits for a text -> float -> text round-trip - static constexpr auto d = std::numeric_limits::digits10; - - // the actual conversion - std::ptrdiff_t len = snprintf(number_buffer.data(), number_buffer.size(), - "%.*g", d, x); - - // negative value indicates an error - assert(len > 0); - // check if buffer was large enough - assert(static_cast(len) < number_buffer.size()); - - // erase thousands separator - if (thousands_sep != '\0') - { - const auto end = std::remove(number_buffer.begin(), - number_buffer.begin() + len, - thousands_sep); - std::fill(end, number_buffer.end(), '\0'); - assert((end - number_buffer.begin()) <= len); - len = (end - number_buffer.begin()); - } - - // convert decimal point to '.' - if (decimal_point != '\0' and decimal_point != '.') - { - for (auto& c : number_buffer) - { - if (c == decimal_point) - { - c = '.'; - break; - } - } - } - - o.write(number_buffer.data(), static_cast(len)); - - // determine if need to append ".0" - const bool value_is_int_like = std::none_of(number_buffer.begin(), - number_buffer.begin() + len + 1, - [](char c) - { - return c == '.' or c == 'e'; - }); - - if (value_is_int_like) - { - o.write(".0", 2); - } - } - - private: - /// the output of the serializer - std::ostream& o; - - /// a (hopefully) large enough character buffer - std::array number_buffer{{}}; - - /// the locale - const std::lconv* loc = nullptr; - /// the locale's thousand separator character - const char thousands_sep = '\0'; - /// the locale's decimal point character - const char decimal_point = '\0'; - - /// the indentation string - string_t indent_string = string_t(512, ' '); - }; - - public: - /*! - @brief serialize to stream - - Serialize the given JSON value @a j to the output stream @a o. The JSON - value will be serialized using the @ref dump member function. The - indentation of the output can be controlled with the member variable - `width` of the output stream @a o. For instance, using the manipulator - `std::setw(4)` on @a o sets the indentation level to `4` and the - serialization result is the same as calling `dump(4)`. - - @param[in,out] o stream to serialize to - @param[in] j JSON value to serialize - - @return the stream @a o - - @complexity Linear. - - @liveexample{The example below shows the serialization with different - parameters to `width` to adjust the indentation level.,operator_serialize} - - @since version 1.0.0 - */ - friend std::ostream& operator<<(std::ostream& o, const basic_json& j) - { - // read width member and use it as indentation parameter if nonzero - const bool pretty_print = (o.width() > 0); - const auto indentation = (pretty_print ? o.width() : 0); - - // reset width to 0 for subsequent calls to this stream - o.width(0); - - // do the actual serialization - serializer s(o); - s.dump(j, pretty_print, static_cast(indentation)); - return o; - } - - /*! - @brief serialize to stream - @deprecated This stream operator is deprecated and will be removed in a - future version of the library. Please use - @ref std::ostream& operator<<(std::ostream&, const basic_json&) - instead; that is, replace calls like `j >> o;` with `o << j;`. - */ - JSON_DEPRECATED - friend std::ostream& operator>>(const basic_json& j, std::ostream& o) - { - return o << j; - } - - /// @} - - - ///////////////////// - // deserialization // - ///////////////////// - - /// @name deserialization - /// @{ - - /*! - @brief deserialize from an array - - This function reads from an array of 1-byte values. - - @pre Each element of the container has a size of 1 byte. Violating this - precondition yields undefined behavior. **This precondition is enforced - with a static assertion.** - - @param[in] array array to read from - @param[in] cb a parser callback function of type @ref parser_callback_t - which is used to control the deserialization by filtering unwanted values - (optional) - - @return result of the deserialization - - @throw parse_error.101 if a parse error occurs; example: `""unexpected end - of input; expected string literal""` - @throw parse_error.102 if to_unicode fails or surrogate error - @throw parse_error.103 if to_unicode fails - - @complexity Linear in the length of the input. The parser is a predictive - LL(1) parser. The complexity can be higher if the parser callback function - @a cb has a super-linear complexity. - - @note A UTF-8 byte order mark is silently ignored. - - @liveexample{The example below demonstrates the `parse()` function reading - from an array.,parse__array__parser_callback_t} - - @since version 2.0.3 - */ - template - static basic_json parse(T (&array)[N], - const parser_callback_t cb = nullptr) - { - // delegate the call to the iterator-range parse overload - return parse(std::begin(array), std::end(array), cb); - } - - /*! - @brief deserialize from string literal - - @tparam CharT character/literal type with size of 1 byte - @param[in] s string literal to read a serialized JSON value from - @param[in] cb a parser callback function of type @ref parser_callback_t - which is used to control the deserialization by filtering unwanted values - (optional) - - @return result of the deserialization - - @throw parse_error.101 in case of an unexpected token - @throw parse_error.102 if to_unicode fails or surrogate error - @throw parse_error.103 if to_unicode fails - - @complexity Linear in the length of the input. The parser is a predictive - LL(1) parser. The complexity can be higher if the parser callback function - @a cb has a super-linear complexity. - - @note A UTF-8 byte order mark is silently ignored. - @note String containers like `std::string` or @ref string_t can be parsed - with @ref parse(const ContiguousContainer&, const parser_callback_t) - - @liveexample{The example below demonstrates the `parse()` function with - and without callback function.,parse__string__parser_callback_t} - - @sa @ref parse(std::istream&, const parser_callback_t) for a version that - reads from an input stream - - @since version 1.0.0 (originally for @ref string_t) - */ - template::value and - std::is_integral::type>::value and - sizeof(typename std::remove_pointer::type) == 1, int>::type = 0> - static basic_json parse(const CharT s, - const parser_callback_t cb = nullptr) - { - return parser(reinterpret_cast(s), cb).parse(); - } - - /*! - @brief deserialize from stream - - @param[in,out] i stream to read a serialized JSON value from - @param[in] cb a parser callback function of type @ref parser_callback_t - which is used to control the deserialization by filtering unwanted values - (optional) - - @return result of the deserialization - - @throw parse_error.101 in case of an unexpected token - @throw parse_error.102 if to_unicode fails or surrogate error - @throw parse_error.103 if to_unicode fails - @throw parse_error.111 if input stream is in a bad state - - @complexity Linear in the length of the input. The parser is a predictive - LL(1) parser. The complexity can be higher if the parser callback function - @a cb has a super-linear complexity. - - @note A UTF-8 byte order mark is silently ignored. - - @liveexample{The example below demonstrates the `parse()` function with - and without callback function.,parse__istream__parser_callback_t} - - @sa @ref parse(const CharT, const parser_callback_t) for a version - that reads from a string - - @since version 1.0.0 - */ - static basic_json parse(std::istream& i, - const parser_callback_t cb = nullptr) - { - return parser(i, cb).parse(); - } - - /*! - @copydoc parse(std::istream&, const parser_callback_t) - */ - static basic_json parse(std::istream&& i, - const parser_callback_t cb = nullptr) - { - return parser(i, cb).parse(); - } - - /*! - @brief deserialize from an iterator range with contiguous storage - - This function reads from an iterator range of a container with contiguous - storage of 1-byte values. Compatible container types include - `std::vector`, `std::string`, `std::array`, `std::valarray`, and - `std::initializer_list`. Furthermore, C-style arrays can be used with - `std::begin()`/`std::end()`. User-defined containers can be used as long - as they implement random-access iterators and a contiguous storage. - - @pre The iterator range is contiguous. Violating this precondition yields - undefined behavior. **This precondition is enforced with an assertion.** - @pre Each element in the range has a size of 1 byte. Violating this - precondition yields undefined behavior. **This precondition is enforced - with a static assertion.** - - @warning There is no way to enforce all preconditions at compile-time. If - the function is called with noncompliant iterators and with - assertions switched off, the behavior is undefined and will most - likely yield segmentation violation. - - @tparam IteratorType iterator of container with contiguous storage - @param[in] first begin of the range to parse (included) - @param[in] last end of the range to parse (excluded) - @param[in] cb a parser callback function of type @ref parser_callback_t - which is used to control the deserialization by filtering unwanted values - (optional) - - @return result of the deserialization - - @throw parse_error.101 in case of an unexpected token - @throw parse_error.102 if to_unicode fails or surrogate error - @throw parse_error.103 if to_unicode fails - - @complexity Linear in the length of the input. The parser is a predictive - LL(1) parser. The complexity can be higher if the parser callback function - @a cb has a super-linear complexity. - - @note A UTF-8 byte order mark is silently ignored. - - @liveexample{The example below demonstrates the `parse()` function reading - from an iterator range.,parse__iteratortype__parser_callback_t} - - @since version 2.0.3 - */ - template::iterator_category>::value, int>::type = 0> - static basic_json parse(IteratorType first, IteratorType last, - const parser_callback_t cb = nullptr) - { - // assertion to check that the iterator range is indeed contiguous, - // see http://stackoverflow.com/a/35008842/266378 for more discussion - assert(std::accumulate(first, last, std::pair(true, 0), - [&first](std::pair res, decltype(*first) val) - { - res.first &= (val == *(std::next(std::addressof(*first), res.second++))); - return res; - }).first); - - // assertion to check that each element is 1 byte long - static_assert(sizeof(typename std::iterator_traits::value_type) == 1, - "each element in the iterator range must have the size of 1 byte"); - - // if iterator range is empty, create a parser with an empty string - // to generate "unexpected EOF" error message - if (std::distance(first, last) <= 0) - { - return parser("").parse(); - } - - return parser(first, last, cb).parse(); - } - - /*! - @brief deserialize from a container with contiguous storage - - This function reads from a container with contiguous storage of 1-byte - values. Compatible container types include `std::vector`, `std::string`, - `std::array`, and `std::initializer_list`. User-defined containers can be - used as long as they implement random-access iterators and a contiguous - storage. - - @pre The container storage is contiguous. Violating this precondition - yields undefined behavior. **This precondition is enforced with an - assertion.** - @pre Each element of the container has a size of 1 byte. Violating this - precondition yields undefined behavior. **This precondition is enforced - with a static assertion.** - - @warning There is no way to enforce all preconditions at compile-time. If - the function is called with a noncompliant container and with - assertions switched off, the behavior is undefined and will most - likely yield segmentation violation. - - @tparam ContiguousContainer container type with contiguous storage - @param[in] c container to read from - @param[in] cb a parser callback function of type @ref parser_callback_t - which is used to control the deserialization by filtering unwanted values - (optional) - - @return result of the deserialization - - @throw parse_error.101 in case of an unexpected token - @throw parse_error.102 if to_unicode fails or surrogate error - @throw parse_error.103 if to_unicode fails - - @complexity Linear in the length of the input. The parser is a predictive - LL(1) parser. The complexity can be higher if the parser callback function - @a cb has a super-linear complexity. - - @note A UTF-8 byte order mark is silently ignored. - - @liveexample{The example below demonstrates the `parse()` function reading - from a contiguous container.,parse__contiguouscontainer__parser_callback_t} - - @since version 2.0.3 - */ - template::value and - std::is_base_of< - std::random_access_iterator_tag, - typename std::iterator_traits()))>::iterator_category>::value - , int>::type = 0> - static basic_json parse(const ContiguousContainer& c, - const parser_callback_t cb = nullptr) - { - // delegate the call to the iterator-range parse overload - return parse(std::begin(c), std::end(c), cb); - } - - /*! - @brief deserialize from stream - @deprecated This stream operator is deprecated and will be removed in a - future version of the library. Please use - @ref std::istream& operator>>(std::istream&, basic_json&) - instead; that is, replace calls like `j << i;` with `i >> j;`. - */ - JSON_DEPRECATED - friend std::istream& operator<<(basic_json& j, std::istream& i) - { - j = parser(i).parse(); - return i; - } - - /*! - @brief deserialize from stream - - Deserializes an input stream to a JSON value. - - @param[in,out] i input stream to read a serialized JSON value from - @param[in,out] j JSON value to write the deserialized input to - - @throw parse_error.101 in case of an unexpected token - @throw parse_error.102 if to_unicode fails or surrogate error - @throw parse_error.103 if to_unicode fails - @throw parse_error.111 if input stream is in a bad state - - @complexity Linear in the length of the input. The parser is a predictive - LL(1) parser. - - @note A UTF-8 byte order mark is silently ignored. - - @liveexample{The example below shows how a JSON value is constructed by - reading a serialization from a stream.,operator_deserialize} - - @sa parse(std::istream&, const parser_callback_t) for a variant with a - parser callback function to filter values while parsing - - @since version 1.0.0 - */ - friend std::istream& operator>>(std::istream& i, basic_json& j) - { - j = parser(i).parse(); - return i; - } - - /// @} - - ////////////////////////////////////////// - // binary serialization/deserialization // - ////////////////////////////////////////// - - /// @name binary serialization/deserialization support - /// @{ - - private: - /*! - @note Some code in the switch cases has been copied, because otherwise - copilers would complain about implicit fallthrough and there is no - portable attribute to mute such warnings. - */ - template - static void add_to_vector(std::vector& vec, size_t bytes, const T number) - { - assert(bytes == 1 or bytes == 2 or bytes == 4 or bytes == 8); - - switch (bytes) - { - case 8: - { - vec.push_back(static_cast((static_cast(number) >> 070) & 0xff)); - vec.push_back(static_cast((static_cast(number) >> 060) & 0xff)); - vec.push_back(static_cast((static_cast(number) >> 050) & 0xff)); - vec.push_back(static_cast((static_cast(number) >> 040) & 0xff)); - vec.push_back(static_cast((number >> 030) & 0xff)); - vec.push_back(static_cast((number >> 020) & 0xff)); - vec.push_back(static_cast((number >> 010) & 0xff)); - vec.push_back(static_cast(number & 0xff)); - break; - } - - case 4: - { - vec.push_back(static_cast((number >> 030) & 0xff)); - vec.push_back(static_cast((number >> 020) & 0xff)); - vec.push_back(static_cast((number >> 010) & 0xff)); - vec.push_back(static_cast(number & 0xff)); - break; - } - - case 2: - { - vec.push_back(static_cast((number >> 010) & 0xff)); - vec.push_back(static_cast(number & 0xff)); - break; - } - - case 1: - { - vec.push_back(static_cast(number & 0xff)); - break; - } - } - } - - /*! - @brief take sufficient bytes from a vector to fill an integer variable - - In the context of binary serialization formats, we need to read several - bytes from a byte vector and combine them to multi-byte integral data - types. - - @param[in] vec byte vector to read from - @param[in] current_index the position in the vector after which to read - - @return the next sizeof(T) bytes from @a vec, in reverse order as T - - @tparam T the integral return type - - @throw parse_error.110 if there are less than sizeof(T)+1 bytes in the - vector @a vec to read - - In the for loop, the bytes from the vector are copied in reverse order into - the return value. In the figures below, let sizeof(T)=4 and `i` be the loop - variable. - - Precondition: - - vec: | | | a | b | c | d | T: | | | | | - ^ ^ ^ ^ - current_index i ptr sizeof(T) - - Postcondition: - - vec: | | | a | b | c | d | T: | d | c | b | a | - ^ ^ ^ - | i ptr - current_index - - @sa Code adapted from . - */ - template - static T get_from_vector(const std::vector& vec, const size_t current_index) - { - // check if we can read sizeof(T) bytes starting the next index - check_length(vec.size(), sizeof(T), current_index + 1); - - T result; - auto* ptr = reinterpret_cast(&result); - for (size_t i = 0; i < sizeof(T); ++i) - { - *ptr++ = vec[current_index + sizeof(T) - i]; - } - return result; - } - - /*! - @brief create a MessagePack serialization of a given JSON value - - This is a straightforward implementation of the MessagePack specification. - - @param[in] j JSON value to serialize - @param[in,out] v byte vector to write the serialization to - - @sa https://github.com/msgpack/msgpack/blob/master/spec.md - */ - static void to_msgpack_internal(const basic_json& j, std::vector& v) - { - switch (j.type()) - { - case value_t::null: - { - // nil - v.push_back(0xc0); - break; - } - - case value_t::boolean: - { - // true and false - v.push_back(j.m_value.boolean ? 0xc3 : 0xc2); - break; - } - - case value_t::number_integer: - { - if (j.m_value.number_integer >= 0) - { - // MessagePack does not differentiate between positive - // signed integers and unsigned integers. Therefore, we - // used the code from the value_t::number_unsigned case - // here. - if (j.m_value.number_unsigned < 128) - { - // positive fixnum - add_to_vector(v, 1, j.m_value.number_unsigned); - } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - // uint 8 - v.push_back(0xcc); - add_to_vector(v, 1, j.m_value.number_unsigned); - } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - // uint 16 - v.push_back(0xcd); - add_to_vector(v, 2, j.m_value.number_unsigned); - } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - // uint 32 - v.push_back(0xce); - add_to_vector(v, 4, j.m_value.number_unsigned); - } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - // uint 64 - v.push_back(0xcf); - add_to_vector(v, 8, j.m_value.number_unsigned); - } - } - else - { - if (j.m_value.number_integer >= -32) - { - // negative fixnum - add_to_vector(v, 1, j.m_value.number_integer); - } - else if (j.m_value.number_integer >= (std::numeric_limits::min)() and j.m_value.number_integer <= (std::numeric_limits::max)()) - { - // int 8 - v.push_back(0xd0); - add_to_vector(v, 1, j.m_value.number_integer); - } - else if (j.m_value.number_integer >= (std::numeric_limits::min)() and j.m_value.number_integer <= (std::numeric_limits::max)()) - { - // int 16 - v.push_back(0xd1); - add_to_vector(v, 2, j.m_value.number_integer); - } - else if (j.m_value.number_integer >= (std::numeric_limits::min)() and j.m_value.number_integer <= (std::numeric_limits::max)()) - { - // int 32 - v.push_back(0xd2); - add_to_vector(v, 4, j.m_value.number_integer); - } - else if (j.m_value.number_integer >= (std::numeric_limits::min)() and j.m_value.number_integer <= (std::numeric_limits::max)()) - { - // int 64 - v.push_back(0xd3); - add_to_vector(v, 8, j.m_value.number_integer); - } - } - break; - } - - case value_t::number_unsigned: - { - if (j.m_value.number_unsigned < 128) - { - // positive fixnum - add_to_vector(v, 1, j.m_value.number_unsigned); - } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - // uint 8 - v.push_back(0xcc); - add_to_vector(v, 1, j.m_value.number_unsigned); - } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - // uint 16 - v.push_back(0xcd); - add_to_vector(v, 2, j.m_value.number_unsigned); - } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - // uint 32 - v.push_back(0xce); - add_to_vector(v, 4, j.m_value.number_unsigned); - } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - // uint 64 - v.push_back(0xcf); - add_to_vector(v, 8, j.m_value.number_unsigned); - } - break; - } - - case value_t::number_float: - { - // float 64 - v.push_back(0xcb); - const auto* helper = reinterpret_cast(&(j.m_value.number_float)); - for (size_t i = 0; i < 8; ++i) - { - v.push_back(helper[7 - i]); - } - break; - } - - case value_t::string: - { - const auto N = j.m_value.string->size(); - if (N <= 31) - { - // fixstr - v.push_back(static_cast(0xa0 | N)); - } - else if (N <= 255) - { - // str 8 - v.push_back(0xd9); - add_to_vector(v, 1, N); - } - else if (N <= 65535) - { - // str 16 - v.push_back(0xda); - add_to_vector(v, 2, N); - } - else if (N <= 4294967295) - { - // str 32 - v.push_back(0xdb); - add_to_vector(v, 4, N); - } - - // append string - std::copy(j.m_value.string->begin(), j.m_value.string->end(), - std::back_inserter(v)); - break; - } - - case value_t::array: - { - const auto N = j.m_value.array->size(); - if (N <= 15) - { - // fixarray - v.push_back(static_cast(0x90 | N)); - } - else if (N <= 0xffff) - { - // array 16 - v.push_back(0xdc); - add_to_vector(v, 2, N); - } - else if (N <= 0xffffffff) - { - // array 32 - v.push_back(0xdd); - add_to_vector(v, 4, N); - } - - // append each element - for (const auto& el : *j.m_value.array) - { - to_msgpack_internal(el, v); - } - break; - } - - case value_t::object: - { - const auto N = j.m_value.object->size(); - if (N <= 15) - { - // fixmap - v.push_back(static_cast(0x80 | (N & 0xf))); - } - else if (N <= 65535) - { - // map 16 - v.push_back(0xde); - add_to_vector(v, 2, N); - } - else if (N <= 4294967295) - { - // map 32 - v.push_back(0xdf); - add_to_vector(v, 4, N); - } - - // append each element - for (const auto& el : *j.m_value.object) - { - to_msgpack_internal(el.first, v); - to_msgpack_internal(el.second, v); - } - break; - } - - default: - { - break; - } - } - } - - /*! - @brief create a CBOR serialization of a given JSON value - - This is a straightforward implementation of the CBOR specification. - - @param[in] j JSON value to serialize - @param[in,out] v byte vector to write the serialization to - - @sa https://tools.ietf.org/html/rfc7049 - */ - static void to_cbor_internal(const basic_json& j, std::vector& v) - { - switch (j.type()) - { - case value_t::null: - { - v.push_back(0xf6); - break; - } - - case value_t::boolean: - { - v.push_back(j.m_value.boolean ? 0xf5 : 0xf4); - break; - } - - case value_t::number_integer: - { - if (j.m_value.number_integer >= 0) - { - // CBOR does not differentiate between positive signed - // integers and unsigned integers. Therefore, we used the - // code from the value_t::number_unsigned case here. - if (j.m_value.number_integer <= 0x17) - { - add_to_vector(v, 1, j.m_value.number_integer); - } - else if (j.m_value.number_integer <= (std::numeric_limits::max)()) - { - v.push_back(0x18); - // one-byte uint8_t - add_to_vector(v, 1, j.m_value.number_integer); - } - else if (j.m_value.number_integer <= (std::numeric_limits::max)()) - { - v.push_back(0x19); - // two-byte uint16_t - add_to_vector(v, 2, j.m_value.number_integer); - } - else if (j.m_value.number_integer <= (std::numeric_limits::max)()) - { - v.push_back(0x1a); - // four-byte uint32_t - add_to_vector(v, 4, j.m_value.number_integer); - } - else - { - v.push_back(0x1b); - // eight-byte uint64_t - add_to_vector(v, 8, j.m_value.number_integer); - } - } - else - { - // The conversions below encode the sign in the first - // byte, and the value is converted to a positive number. - const auto positive_number = -1 - j.m_value.number_integer; - if (j.m_value.number_integer >= -24) - { - v.push_back(static_cast(0x20 + positive_number)); - } - else if (positive_number <= (std::numeric_limits::max)()) - { - // int 8 - v.push_back(0x38); - add_to_vector(v, 1, positive_number); - } - else if (positive_number <= (std::numeric_limits::max)()) - { - // int 16 - v.push_back(0x39); - add_to_vector(v, 2, positive_number); - } - else if (positive_number <= (std::numeric_limits::max)()) - { - // int 32 - v.push_back(0x3a); - add_to_vector(v, 4, positive_number); - } - else - { - // int 64 - v.push_back(0x3b); - add_to_vector(v, 8, positive_number); - } - } - break; - } - - case value_t::number_unsigned: - { - if (j.m_value.number_unsigned <= 0x17) - { - v.push_back(static_cast(j.m_value.number_unsigned)); - } - else if (j.m_value.number_unsigned <= 0xff) - { - v.push_back(0x18); - // one-byte uint8_t - add_to_vector(v, 1, j.m_value.number_unsigned); - } - else if (j.m_value.number_unsigned <= 0xffff) - { - v.push_back(0x19); - // two-byte uint16_t - add_to_vector(v, 2, j.m_value.number_unsigned); - } - else if (j.m_value.number_unsigned <= 0xffffffff) - { - v.push_back(0x1a); - // four-byte uint32_t - add_to_vector(v, 4, j.m_value.number_unsigned); - } - else if (j.m_value.number_unsigned <= 0xffffffffffffffff) - { - v.push_back(0x1b); - // eight-byte uint64_t - add_to_vector(v, 8, j.m_value.number_unsigned); - } - break; - } - - case value_t::number_float: - { - // Double-Precision Float - v.push_back(0xfb); - const auto* helper = reinterpret_cast(&(j.m_value.number_float)); - for (size_t i = 0; i < 8; ++i) - { - v.push_back(helper[7 - i]); - } - break; - } - - case value_t::string: - { - const auto N = j.m_value.string->size(); - if (N <= 0x17) - { - v.push_back(static_cast(0x60 + N)); // 1 byte for string + size - } - else if (N <= 0xff) - { - v.push_back(0x78); // one-byte uint8_t for N - add_to_vector(v, 1, N); - } - else if (N <= 0xffff) - { - v.push_back(0x79); // two-byte uint16_t for N - add_to_vector(v, 2, N); - } - else if (N <= 0xffffffff) - { - v.push_back(0x7a); // four-byte uint32_t for N - add_to_vector(v, 4, N); - } - // LCOV_EXCL_START - else if (N <= 0xffffffffffffffff) - { - v.push_back(0x7b); // eight-byte uint64_t for N - add_to_vector(v, 8, N); - } - // LCOV_EXCL_STOP - - // append string - std::copy(j.m_value.string->begin(), j.m_value.string->end(), - std::back_inserter(v)); - break; - } - - case value_t::array: - { - const auto N = j.m_value.array->size(); - if (N <= 0x17) - { - v.push_back(static_cast(0x80 + N)); // 1 byte for array + size - } - else if (N <= 0xff) - { - v.push_back(0x98); // one-byte uint8_t for N - add_to_vector(v, 1, N); - } - else if (N <= 0xffff) - { - v.push_back(0x99); // two-byte uint16_t for N - add_to_vector(v, 2, N); - } - else if (N <= 0xffffffff) - { - v.push_back(0x9a); // four-byte uint32_t for N - add_to_vector(v, 4, N); - } - // LCOV_EXCL_START - else if (N <= 0xffffffffffffffff) - { - v.push_back(0x9b); // eight-byte uint64_t for N - add_to_vector(v, 8, N); - } - // LCOV_EXCL_STOP - - // append each element - for (const auto& el : *j.m_value.array) - { - to_cbor_internal(el, v); - } - break; - } - - case value_t::object: - { - const auto N = j.m_value.object->size(); - if (N <= 0x17) - { - v.push_back(static_cast(0xa0 + N)); // 1 byte for object + size - } - else if (N <= 0xff) - { - v.push_back(0xb8); - add_to_vector(v, 1, N); // one-byte uint8_t for N - } - else if (N <= 0xffff) - { - v.push_back(0xb9); - add_to_vector(v, 2, N); // two-byte uint16_t for N - } - else if (N <= 0xffffffff) - { - v.push_back(0xba); - add_to_vector(v, 4, N); // four-byte uint32_t for N - } - // LCOV_EXCL_START - else if (N <= 0xffffffffffffffff) - { - v.push_back(0xbb); - add_to_vector(v, 8, N); // eight-byte uint64_t for N - } - // LCOV_EXCL_STOP - - // append each element - for (const auto& el : *j.m_value.object) - { - to_cbor_internal(el.first, v); - to_cbor_internal(el.second, v); - } - break; - } - - default: - { - break; - } - } - } - - - /* - @brief checks if given lengths do not exceed the size of a given vector - - To secure the access to the byte vector during CBOR/MessagePack - deserialization, bytes are copied from the vector into buffers. This - function checks if the number of bytes to copy (@a len) does not exceed - the size @s size of the vector. Additionally, an @a offset is given from - where to start reading the bytes. - - This function checks whether reading the bytes is safe; that is, offset is - a valid index in the vector, offset+len - - @param[in] size size of the byte vector - @param[in] len number of bytes to read - @param[in] offset offset where to start reading - - vec: x x x x x X X X X X - ^ ^ ^ - 0 offset len - - @throws out_of_range if `len > v.size()` - */ - static void check_length(const size_t size, const size_t len, const size_t offset) - { - // simple case: requested length is greater than the vector's length - if (len > size or offset > size) - { - JSON_THROW(parse_error::create(110, offset + 1, "cannot read " + std::to_string(len) + " bytes from vector")); - } - - // second case: adding offset would result in overflow - if ((size > ((std::numeric_limits::max)() - offset))) - { - JSON_THROW(parse_error::create(110, offset + 1, "cannot read " + std::to_string(len) + " bytes from vector")); - } - - // last case: reading past the end of the vector - if (len + offset > size) - { - JSON_THROW(parse_error::create(110, offset + 1, "cannot read " + std::to_string(len) + " bytes from vector")); - } - } - - /*! - @brief check if the next byte belongs to a string - - While parsing a map, the keys must be strings. This function checks if the - current byte is one of the start bytes for a string in MessagePack: - - - 0xa0 - 0xbf: fixstr - - 0xd9: str 8 - - 0xda: str 16 - - 0xdb: str 32 - - @param[in] v MessagePack serialization - @param[in] idx byte index in @a v to check for a string - - @throw parse_error.113 if `v[idx]` does not belong to a string - */ - static void msgpack_expect_string(const std::vector& v, size_t idx) - { - check_length(v.size(), 1, idx); - - const auto byte = v[idx]; - if ((byte >= 0xa0 and byte <= 0xbf) or (byte >= 0xd9 and byte <= 0xdb)) - { - return; - } - - std::stringstream ss; - ss << std::hex << static_cast(v[idx]); - JSON_THROW(parse_error::create(113, idx + 1, "expected a MessagePack string; last byte: 0x" + ss.str())); - } - - /*! - @brief check if the next byte belongs to a string - - While parsing a map, the keys must be strings. This function checks if the - current byte is one of the start bytes for a string in CBOR: - - - 0x60 - 0x77: fixed length - - 0x78 - 0x7b: variable length - - 0x7f: indefinity length - - @param[in] v CBOR serialization - @param[in] idx byte index in @a v to check for a string - - @throw parse_error.113 if `v[idx]` does not belong to a string - */ - static void cbor_expect_string(const std::vector& v, size_t idx) - { - check_length(v.size(), 1, idx); - - const auto byte = v[idx]; - if ((byte >= 0x60 and byte <= 0x7b) or byte == 0x7f) - { - return; - } - - std::stringstream ss; - ss << std::hex << static_cast(v[idx]); - JSON_THROW(parse_error::create(113, idx + 1, "expected a CBOR string; last byte: 0x" + ss.str())); - } - - /*! - @brief create a JSON value from a given MessagePack vector - - @param[in] v MessagePack serialization - @param[in] idx byte index to start reading from @a v - - @return deserialized JSON value - - @throw parse_error.110 if the given vector ends prematurely - @throw parse_error.112 if unsupported features from MessagePack were - used in the given vector @a v or if the input is not valid MessagePack - @throw parse_error.113 if a string was expected as map key, but not found - - @sa https://github.com/msgpack/msgpack/blob/master/spec.md - */ - static basic_json from_msgpack_internal(const std::vector& v, size_t& idx) - { - // store and increment index - const size_t current_idx = idx++; - - // make sure reading 1 byte is safe - check_length(v.size(), 1, current_idx); - - if (v[current_idx] <= 0xbf) - { - if (v[current_idx] <= 0x7f) // positive fixint - { - return v[current_idx]; - } - if (v[current_idx] <= 0x8f) // fixmap - { - basic_json result = value_t::object; - const size_t len = v[current_idx] & 0x0f; - for (size_t i = 0; i < len; ++i) - { - msgpack_expect_string(v, idx); - std::string key = from_msgpack_internal(v, idx); - result[key] = from_msgpack_internal(v, idx); - } - return result; - } - else if (v[current_idx] <= 0x9f) // fixarray - { - basic_json result = value_t::array; - const size_t len = v[current_idx] & 0x0f; - for (size_t i = 0; i < len; ++i) - { - result.push_back(from_msgpack_internal(v, idx)); - } - return result; - } - else // fixstr - { - const size_t len = v[current_idx] & 0x1f; - const size_t offset = current_idx + 1; - idx += len; // skip content bytes - check_length(v.size(), len, offset); - return std::string(reinterpret_cast(v.data()) + offset, len); - } - } - else if (v[current_idx] >= 0xe0) // negative fixint - { - return static_cast(v[current_idx]); - } - else - { - switch (v[current_idx]) - { - case 0xc0: // nil - { - return value_t::null; - } - - case 0xc2: // false - { - return false; - } - - case 0xc3: // true - { - return true; - } - - case 0xca: // float 32 - { - // copy bytes in reverse order into the double variable - float res; - check_length(v.size(), sizeof(float), current_idx + 1); - for (size_t byte = 0; byte < sizeof(float); ++byte) - { - reinterpret_cast(&res)[sizeof(float) - byte - 1] = v[current_idx + 1 + byte]; - } - idx += sizeof(float); // skip content bytes - return res; - } - - case 0xcb: // float 64 - { - // copy bytes in reverse order into the double variable - double res; - check_length(v.size(), sizeof(double), current_idx + 1); - for (size_t byte = 0; byte < sizeof(double); ++byte) - { - reinterpret_cast(&res)[sizeof(double) - byte - 1] = v[current_idx + 1 + byte]; - } - idx += sizeof(double); // skip content bytes - return res; - } - - case 0xcc: // uint 8 - { - idx += 1; // skip content byte - return get_from_vector(v, current_idx); - } - - case 0xcd: // uint 16 - { - idx += 2; // skip 2 content bytes - return get_from_vector(v, current_idx); - } - - case 0xce: // uint 32 - { - idx += 4; // skip 4 content bytes - return get_from_vector(v, current_idx); - } - - case 0xcf: // uint 64 - { - idx += 8; // skip 8 content bytes - return get_from_vector(v, current_idx); - } - - case 0xd0: // int 8 - { - idx += 1; // skip content byte - return get_from_vector(v, current_idx); - } - - case 0xd1: // int 16 - { - idx += 2; // skip 2 content bytes - return get_from_vector(v, current_idx); - } - - case 0xd2: // int 32 - { - idx += 4; // skip 4 content bytes - return get_from_vector(v, current_idx); - } - - case 0xd3: // int 64 - { - idx += 8; // skip 8 content bytes - return get_from_vector(v, current_idx); - } - - case 0xd9: // str 8 - { - const auto len = static_cast(get_from_vector(v, current_idx)); - const size_t offset = current_idx + 2; - idx += len + 1; // skip size byte + content bytes - check_length(v.size(), len, offset); - return std::string(reinterpret_cast(v.data()) + offset, len); - } - - case 0xda: // str 16 - { - const auto len = static_cast(get_from_vector(v, current_idx)); - const size_t offset = current_idx + 3; - idx += len + 2; // skip 2 size bytes + content bytes - check_length(v.size(), len, offset); - return std::string(reinterpret_cast(v.data()) + offset, len); - } - - case 0xdb: // str 32 - { - const auto len = static_cast(get_from_vector(v, current_idx)); - const size_t offset = current_idx + 5; - idx += len + 4; // skip 4 size bytes + content bytes - check_length(v.size(), len, offset); - return std::string(reinterpret_cast(v.data()) + offset, len); - } - - case 0xdc: // array 16 - { - basic_json result = value_t::array; - const auto len = static_cast(get_from_vector(v, current_idx)); - idx += 2; // skip 2 size bytes - for (size_t i = 0; i < len; ++i) - { - result.push_back(from_msgpack_internal(v, idx)); - } - return result; - } - - case 0xdd: // array 32 - { - basic_json result = value_t::array; - const auto len = static_cast(get_from_vector(v, current_idx)); - idx += 4; // skip 4 size bytes - for (size_t i = 0; i < len; ++i) - { - result.push_back(from_msgpack_internal(v, idx)); - } - return result; - } - - case 0xde: // map 16 - { - basic_json result = value_t::object; - const auto len = static_cast(get_from_vector(v, current_idx)); - idx += 2; // skip 2 size bytes - for (size_t i = 0; i < len; ++i) - { - msgpack_expect_string(v, idx); - std::string key = from_msgpack_internal(v, idx); - result[key] = from_msgpack_internal(v, idx); - } - return result; - } - - case 0xdf: // map 32 - { - basic_json result = value_t::object; - const auto len = static_cast(get_from_vector(v, current_idx)); - idx += 4; // skip 4 size bytes - for (size_t i = 0; i < len; ++i) - { - msgpack_expect_string(v, idx); - std::string key = from_msgpack_internal(v, idx); - result[key] = from_msgpack_internal(v, idx); - } - return result; - } - - default: - { - std::stringstream ss; - ss << std::hex << static_cast(v[current_idx]); - JSON_THROW(parse_error::create(112, current_idx + 1, "error reading MessagePack; last byte: 0x" + ss.str())); - } - } - } - } - - /*! - @brief create a JSON value from a given CBOR vector - - @param[in] v CBOR serialization - @param[in] idx byte index to start reading from @a v - - @return deserialized JSON value - - @throw parse_error.110 if the given vector ends prematurely - @throw parse_error.112 if unsupported features from CBOR were - used in the given vector @a v or if the input is not valid CBOR - @throw parse_error.113 if a string was expected as map key, but not found - - @sa https://tools.ietf.org/html/rfc7049 - */ - static basic_json from_cbor_internal(const std::vector& v, size_t& idx) - { - // store and increment index - const size_t current_idx = idx++; - - // make sure reading 1 byte is safe - check_length(v.size(), 1, current_idx); - - switch (v[current_idx]) - { - // Integer 0x00..0x17 (0..23) - case 0x00: - case 0x01: - case 0x02: - case 0x03: - case 0x04: - case 0x05: - case 0x06: - case 0x07: - case 0x08: - case 0x09: - case 0x0a: - case 0x0b: - case 0x0c: - case 0x0d: - case 0x0e: - case 0x0f: - case 0x10: - case 0x11: - case 0x12: - case 0x13: - case 0x14: - case 0x15: - case 0x16: - case 0x17: - { - return v[current_idx]; - } - - case 0x18: // Unsigned integer (one-byte uint8_t follows) - { - idx += 1; // skip content byte - return get_from_vector(v, current_idx); - } - - case 0x19: // Unsigned integer (two-byte uint16_t follows) - { - idx += 2; // skip 2 content bytes - return get_from_vector(v, current_idx); - } - - case 0x1a: // Unsigned integer (four-byte uint32_t follows) - { - idx += 4; // skip 4 content bytes - return get_from_vector(v, current_idx); - } - - case 0x1b: // Unsigned integer (eight-byte uint64_t follows) - { - idx += 8; // skip 8 content bytes - return get_from_vector(v, current_idx); - } - - // Negative integer -1-0x00..-1-0x17 (-1..-24) - case 0x20: - case 0x21: - case 0x22: - case 0x23: - case 0x24: - case 0x25: - case 0x26: - case 0x27: - case 0x28: - case 0x29: - case 0x2a: - case 0x2b: - case 0x2c: - case 0x2d: - case 0x2e: - case 0x2f: - case 0x30: - case 0x31: - case 0x32: - case 0x33: - case 0x34: - case 0x35: - case 0x36: - case 0x37: - { - return static_cast(0x20 - 1 - v[current_idx]); - } - - case 0x38: // Negative integer (one-byte uint8_t follows) - { - idx += 1; // skip content byte - // must be uint8_t ! - return static_cast(-1) - get_from_vector(v, current_idx); - } - - case 0x39: // Negative integer -1-n (two-byte uint16_t follows) - { - idx += 2; // skip 2 content bytes - return static_cast(-1) - get_from_vector(v, current_idx); - } - - case 0x3a: // Negative integer -1-n (four-byte uint32_t follows) - { - idx += 4; // skip 4 content bytes - return static_cast(-1) - get_from_vector(v, current_idx); - } - - case 0x3b: // Negative integer -1-n (eight-byte uint64_t follows) - { - idx += 8; // skip 8 content bytes - return static_cast(-1) - static_cast(get_from_vector(v, current_idx)); - } - - // UTF-8 string (0x00..0x17 bytes follow) - case 0x60: - case 0x61: - case 0x62: - case 0x63: - case 0x64: - case 0x65: - case 0x66: - case 0x67: - case 0x68: - case 0x69: - case 0x6a: - case 0x6b: - case 0x6c: - case 0x6d: - case 0x6e: - case 0x6f: - case 0x70: - case 0x71: - case 0x72: - case 0x73: - case 0x74: - case 0x75: - case 0x76: - case 0x77: - { - const auto len = static_cast(v[current_idx] - 0x60); - const size_t offset = current_idx + 1; - idx += len; // skip content bytes - check_length(v.size(), len, offset); - return std::string(reinterpret_cast(v.data()) + offset, len); - } - - case 0x78: // UTF-8 string (one-byte uint8_t for n follows) - { - const auto len = static_cast(get_from_vector(v, current_idx)); - const size_t offset = current_idx + 2; - idx += len + 1; // skip size byte + content bytes - check_length(v.size(), len, offset); - return std::string(reinterpret_cast(v.data()) + offset, len); - } - - case 0x79: // UTF-8 string (two-byte uint16_t for n follow) - { - const auto len = static_cast(get_from_vector(v, current_idx)); - const size_t offset = current_idx + 3; - idx += len + 2; // skip 2 size bytes + content bytes - check_length(v.size(), len, offset); - return std::string(reinterpret_cast(v.data()) + offset, len); - } - - case 0x7a: // UTF-8 string (four-byte uint32_t for n follow) - { - const auto len = static_cast(get_from_vector(v, current_idx)); - const size_t offset = current_idx + 5; - idx += len + 4; // skip 4 size bytes + content bytes - check_length(v.size(), len, offset); - return std::string(reinterpret_cast(v.data()) + offset, len); - } - - case 0x7b: // UTF-8 string (eight-byte uint64_t for n follow) - { - const auto len = static_cast(get_from_vector(v, current_idx)); - const size_t offset = current_idx + 9; - idx += len + 8; // skip 8 size bytes + content bytes - check_length(v.size(), len, offset); - return std::string(reinterpret_cast(v.data()) + offset, len); - } - - case 0x7f: // UTF-8 string (indefinite length) - { - std::string result; - while (static_cast(check_length(v.size(), 1, idx)), v[idx] != 0xff) - { - string_t s = from_cbor_internal(v, idx); - result += s; - } - // skip break byte (0xFF) - idx += 1; - return result; - } - - // array (0x00..0x17 data items follow) - case 0x80: - case 0x81: - case 0x82: - case 0x83: - case 0x84: - case 0x85: - case 0x86: - case 0x87: - case 0x88: - case 0x89: - case 0x8a: - case 0x8b: - case 0x8c: - case 0x8d: - case 0x8e: - case 0x8f: - case 0x90: - case 0x91: - case 0x92: - case 0x93: - case 0x94: - case 0x95: - case 0x96: - case 0x97: - { - basic_json result = value_t::array; - const auto len = static_cast(v[current_idx] - 0x80); - for (size_t i = 0; i < len; ++i) - { - result.push_back(from_cbor_internal(v, idx)); - } - return result; - } - - case 0x98: // array (one-byte uint8_t for n follows) - { - basic_json result = value_t::array; - const auto len = static_cast(get_from_vector(v, current_idx)); - idx += 1; // skip 1 size byte - for (size_t i = 0; i < len; ++i) - { - result.push_back(from_cbor_internal(v, idx)); - } - return result; - } - - case 0x99: // array (two-byte uint16_t for n follow) - { - basic_json result = value_t::array; - const auto len = static_cast(get_from_vector(v, current_idx)); - idx += 2; // skip 4 size bytes - for (size_t i = 0; i < len; ++i) - { - result.push_back(from_cbor_internal(v, idx)); - } - return result; - } - - case 0x9a: // array (four-byte uint32_t for n follow) - { - basic_json result = value_t::array; - const auto len = static_cast(get_from_vector(v, current_idx)); - idx += 4; // skip 4 size bytes - for (size_t i = 0; i < len; ++i) - { - result.push_back(from_cbor_internal(v, idx)); - } - return result; - } - - case 0x9b: // array (eight-byte uint64_t for n follow) - { - basic_json result = value_t::array; - const auto len = static_cast(get_from_vector(v, current_idx)); - idx += 8; // skip 8 size bytes - for (size_t i = 0; i < len; ++i) - { - result.push_back(from_cbor_internal(v, idx)); - } - return result; - } - - case 0x9f: // array (indefinite length) - { - basic_json result = value_t::array; - while (static_cast(check_length(v.size(), 1, idx)), v[idx] != 0xff) - { - result.push_back(from_cbor_internal(v, idx)); - } - // skip break byte (0xFF) - idx += 1; - return result; - } - - // map (0x00..0x17 pairs of data items follow) - case 0xa0: - case 0xa1: - case 0xa2: - case 0xa3: - case 0xa4: - case 0xa5: - case 0xa6: - case 0xa7: - case 0xa8: - case 0xa9: - case 0xaa: - case 0xab: - case 0xac: - case 0xad: - case 0xae: - case 0xaf: - case 0xb0: - case 0xb1: - case 0xb2: - case 0xb3: - case 0xb4: - case 0xb5: - case 0xb6: - case 0xb7: - { - basic_json result = value_t::object; - const auto len = static_cast(v[current_idx] - 0xa0); - for (size_t i = 0; i < len; ++i) - { - cbor_expect_string(v, idx); - std::string key = from_cbor_internal(v, idx); - result[key] = from_cbor_internal(v, idx); - } - return result; - } - - case 0xb8: // map (one-byte uint8_t for n follows) - { - basic_json result = value_t::object; - const auto len = static_cast(get_from_vector(v, current_idx)); - idx += 1; // skip 1 size byte - for (size_t i = 0; i < len; ++i) - { - cbor_expect_string(v, idx); - std::string key = from_cbor_internal(v, idx); - result[key] = from_cbor_internal(v, idx); - } - return result; - } - - case 0xb9: // map (two-byte uint16_t for n follow) - { - basic_json result = value_t::object; - const auto len = static_cast(get_from_vector(v, current_idx)); - idx += 2; // skip 2 size bytes - for (size_t i = 0; i < len; ++i) - { - cbor_expect_string(v, idx); - std::string key = from_cbor_internal(v, idx); - result[key] = from_cbor_internal(v, idx); - } - return result; - } - - case 0xba: // map (four-byte uint32_t for n follow) - { - basic_json result = value_t::object; - const auto len = static_cast(get_from_vector(v, current_idx)); - idx += 4; // skip 4 size bytes - for (size_t i = 0; i < len; ++i) - { - cbor_expect_string(v, idx); - std::string key = from_cbor_internal(v, idx); - result[key] = from_cbor_internal(v, idx); - } - return result; - } - - case 0xbb: // map (eight-byte uint64_t for n follow) - { - basic_json result = value_t::object; - const auto len = static_cast(get_from_vector(v, current_idx)); - idx += 8; // skip 8 size bytes - for (size_t i = 0; i < len; ++i) - { - cbor_expect_string(v, idx); - std::string key = from_cbor_internal(v, idx); - result[key] = from_cbor_internal(v, idx); - } - return result; - } - - case 0xbf: // map (indefinite length) - { - basic_json result = value_t::object; - while (static_cast(check_length(v.size(), 1, idx)), v[idx] != 0xff) - { - cbor_expect_string(v, idx); - std::string key = from_cbor_internal(v, idx); - result[key] = from_cbor_internal(v, idx); - } - // skip break byte (0xFF) - idx += 1; - return result; - } - - case 0xf4: // false - { - return false; - } - - case 0xf5: // true - { - return true; - } - - case 0xf6: // null - { - return value_t::null; - } - - case 0xf9: // Half-Precision Float (two-byte IEEE 754) - { - idx += 2; // skip two content bytes - - // code from RFC 7049, Appendix D, Figure 3: - // As half-precision floating-point numbers were only added to - // IEEE 754 in 2008, today's programming platforms often still - // only have limited support for them. It is very easy to - // include at least decoding support for them even without such - // support. An example of a small decoder for half-precision - // floating-point numbers in the C language is shown in Fig. 3. - check_length(v.size(), 2, current_idx + 1); - const int half = (v[current_idx + 1] << 8) + v[current_idx + 2]; - const int exp = (half >> 10) & 0x1f; - const int mant = half & 0x3ff; - double val; - if (exp == 0) - { - val = std::ldexp(mant, -24); - } - else if (exp != 31) - { - val = std::ldexp(mant + 1024, exp - 25); - } - else - { - val = mant == 0 - ? std::numeric_limits::infinity() - : std::numeric_limits::quiet_NaN(); - } - return (half & 0x8000) != 0 ? -val : val; - } - - case 0xfa: // Single-Precision Float (four-byte IEEE 754) - { - // copy bytes in reverse order into the float variable - float res; - check_length(v.size(), sizeof(float), current_idx + 1); - for (size_t byte = 0; byte < sizeof(float); ++byte) - { - reinterpret_cast(&res)[sizeof(float) - byte - 1] = v[current_idx + 1 + byte]; - } - idx += sizeof(float); // skip content bytes - return res; - } - - case 0xfb: // Double-Precision Float (eight-byte IEEE 754) - { - // copy bytes in reverse order into the double variable - double res; - check_length(v.size(), sizeof(double), current_idx + 1); - for (size_t byte = 0; byte < sizeof(double); ++byte) - { - reinterpret_cast(&res)[sizeof(double) - byte - 1] = v[current_idx + 1 + byte]; - } - idx += sizeof(double); // skip content bytes - return res; - } - - default: // anything else (0xFF is handled inside the other types) - { - std::stringstream ss; - ss << std::hex << static_cast(v[current_idx]); - JSON_THROW(parse_error::create(112, current_idx + 1, "error reading CBOR; last byte: 0x" + ss.str())); - } - } - } - - public: - /*! - @brief create a MessagePack serialization of a given JSON value - - Serializes a given JSON value @a j to a byte vector using the MessagePack - serialization format. MessagePack is a binary serialization format which - aims to be more compact than JSON itself, yet more efficient to parse. - - The library uses the following mapping from JSON values types to - MessagePack types according to the MessagePack specification: - - JSON value type | value/range | MessagePack type | first byte - --------------- | --------------------------------- | ---------------- | ---------- - null | `null` | nil | 0xc0 - boolean | `true` | true | 0xc3 - boolean | `false` | false | 0xc2 - number_integer | -9223372036854775808..-2147483649 | int64 | 0xd3 - number_integer | -2147483648..-32769 | int32 | 0xd2 - number_integer | -32768..-129 | int16 | 0xd1 - number_integer | -128..-33 | int8 | 0xd0 - number_integer | -32..-1 | negative fixint | 0xe0..0xff - number_integer | 0..127 | positive fixint | 0x00..0x7f - number_integer | 128..255 | uint 8 | 0xcc - number_integer | 256..65535 | uint 16 | 0xcd - number_integer | 65536..4294967295 | uint 32 | 0xce - number_integer | 4294967296..18446744073709551615 | uint 64 | 0xcf - number_unsigned | 0..127 | positive fixint | 0x00..0x7f - number_unsigned | 128..255 | uint 8 | 0xcc - number_unsigned | 256..65535 | uint 16 | 0xcd - number_unsigned | 65536..4294967295 | uint 32 | 0xce - number_unsigned | 4294967296..18446744073709551615 | uint 64 | 0xcf - number_float | *any value* | float 64 | 0xcb - string | *length*: 0..31 | fixstr | 0xa0..0xbf - string | *length*: 32..255 | str 8 | 0xd9 - string | *length*: 256..65535 | str 16 | 0xda - string | *length*: 65536..4294967295 | str 32 | 0xdb - array | *size*: 0..15 | fixarray | 0x90..0x9f - array | *size*: 16..65535 | array 16 | 0xdc - array | *size*: 65536..4294967295 | array 32 | 0xdd - object | *size*: 0..15 | fix map | 0x80..0x8f - object | *size*: 16..65535 | map 16 | 0xde - object | *size*: 65536..4294967295 | map 32 | 0xdf - - @note The mapping is **complete** in the sense that any JSON value type - can be converted to a MessagePack value. - - @note The following values can **not** be converted to a MessagePack value: - - strings with more than 4294967295 bytes - - arrays with more than 4294967295 elements - - objects with more than 4294967295 elements - - @note The following MessagePack types are not used in the conversion: - - bin 8 - bin 32 (0xc4..0xc6) - - ext 8 - ext 32 (0xc7..0xc9) - - float 32 (0xca) - - fixext 1 - fixext 16 (0xd4..0xd8) - - @note Any MessagePack output created @ref to_msgpack can be successfully - parsed by @ref from_msgpack. - - @param[in] j JSON value to serialize - @return MessagePack serialization as byte vector - - @complexity Linear in the size of the JSON value @a j. - - @liveexample{The example shows the serialization of a JSON value to a byte - vector in MessagePack format.,to_msgpack} - - @sa http://msgpack.org - @sa @ref from_msgpack(const std::vector&, const size_t) for the - analogous deserialization - @sa @ref to_cbor(const basic_json& for the related CBOR format - - @since version 2.0.9 - */ - static std::vector to_msgpack(const basic_json& j) - { - std::vector result; - to_msgpack_internal(j, result); - return result; - } - - /*! - @brief create a JSON value from a byte vector in MessagePack format - - Deserializes a given byte vector @a v to a JSON value using the MessagePack - serialization format. - - The library maps MessagePack types to JSON value types as follows: - - MessagePack type | JSON value type | first byte - ---------------- | --------------- | ---------- - positive fixint | number_unsigned | 0x00..0x7f - fixmap | object | 0x80..0x8f - fixarray | array | 0x90..0x9f - fixstr | string | 0xa0..0xbf - nil | `null` | 0xc0 - false | `false` | 0xc2 - true | `true` | 0xc3 - float 32 | number_float | 0xca - float 64 | number_float | 0xcb - uint 8 | number_unsigned | 0xcc - uint 16 | number_unsigned | 0xcd - uint 32 | number_unsigned | 0xce - uint 64 | number_unsigned | 0xcf - int 8 | number_integer | 0xd0 - int 16 | number_integer | 0xd1 - int 32 | number_integer | 0xd2 - int 64 | number_integer | 0xd3 - str 8 | string | 0xd9 - str 16 | string | 0xda - str 32 | string | 0xdb - array 16 | array | 0xdc - array 32 | array | 0xdd - map 16 | object | 0xde - map 32 | object | 0xdf - negative fixint | number_integer | 0xe0-0xff - - @warning The mapping is **incomplete** in the sense that not all - MessagePack types can be converted to a JSON value. The following - MessagePack types are not supported and will yield parse errors: - - bin 8 - bin 32 (0xc4..0xc6) - - ext 8 - ext 32 (0xc7..0xc9) - - fixext 1 - fixext 16 (0xd4..0xd8) - - @note Any MessagePack output created @ref to_msgpack can be successfully - parsed by @ref from_msgpack. - - @param[in] v a byte vector in MessagePack format - @param[in] start_index the index to start reading from @a v (0 by default) - @return deserialized JSON value - - @throw parse_error.110 if the given vector ends prematurely - @throw parse_error.112 if unsupported features from MessagePack were - used in the given vector @a v or if the input is not valid MessagePack - @throw parse_error.113 if a string was expected as map key, but not found - - @complexity Linear in the size of the byte vector @a v. - - @liveexample{The example shows the deserialization of a byte vector in - MessagePack format to a JSON value.,from_msgpack} - - @sa http://msgpack.org - @sa @ref to_msgpack(const basic_json&) for the analogous serialization - @sa @ref from_cbor(const std::vector&, const size_t) for the - related CBOR format - - @since version 2.0.9, parameter @a start_index since 2.1.1 - */ - static basic_json from_msgpack(const std::vector& v, - const size_t start_index = 0) - { - size_t i = start_index; - return from_msgpack_internal(v, i); - } - - /*! - @brief create a MessagePack serialization of a given JSON value - - Serializes a given JSON value @a j to a byte vector using the CBOR (Concise - Binary Object Representation) serialization format. CBOR is a binary - serialization format which aims to be more compact than JSON itself, yet - more efficient to parse. - - The library uses the following mapping from JSON values types to - CBOR types according to the CBOR specification (RFC 7049): - - JSON value type | value/range | CBOR type | first byte - --------------- | ------------------------------------------ | ---------------------------------- | --------------- - null | `null` | Null | 0xf6 - boolean | `true` | True | 0xf5 - boolean | `false` | False | 0xf4 - number_integer | -9223372036854775808..-2147483649 | Negative integer (8 bytes follow) | 0x3b - number_integer | -2147483648..-32769 | Negative integer (4 bytes follow) | 0x3a - number_integer | -32768..-129 | Negative integer (2 bytes follow) | 0x39 - number_integer | -128..-25 | Negative integer (1 byte follow) | 0x38 - number_integer | -24..-1 | Negative integer | 0x20..0x37 - number_integer | 0..23 | Integer | 0x00..0x17 - number_integer | 24..255 | Unsigned integer (1 byte follow) | 0x18 - number_integer | 256..65535 | Unsigned integer (2 bytes follow) | 0x19 - number_integer | 65536..4294967295 | Unsigned integer (4 bytes follow) | 0x1a - number_integer | 4294967296..18446744073709551615 | Unsigned integer (8 bytes follow) | 0x1b - number_unsigned | 0..23 | Integer | 0x00..0x17 - number_unsigned | 24..255 | Unsigned integer (1 byte follow) | 0x18 - number_unsigned | 256..65535 | Unsigned integer (2 bytes follow) | 0x19 - number_unsigned | 65536..4294967295 | Unsigned integer (4 bytes follow) | 0x1a - number_unsigned | 4294967296..18446744073709551615 | Unsigned integer (8 bytes follow) | 0x1b - number_float | *any value* | Double-Precision Float | 0xfb - string | *length*: 0..23 | UTF-8 string | 0x60..0x77 - string | *length*: 23..255 | UTF-8 string (1 byte follow) | 0x78 - string | *length*: 256..65535 | UTF-8 string (2 bytes follow) | 0x79 - string | *length*: 65536..4294967295 | UTF-8 string (4 bytes follow) | 0x7a - string | *length*: 4294967296..18446744073709551615 | UTF-8 string (8 bytes follow) | 0x7b - array | *size*: 0..23 | array | 0x80..0x97 - array | *size*: 23..255 | array (1 byte follow) | 0x98 - array | *size*: 256..65535 | array (2 bytes follow) | 0x99 - array | *size*: 65536..4294967295 | array (4 bytes follow) | 0x9a - array | *size*: 4294967296..18446744073709551615 | array (8 bytes follow) | 0x9b - object | *size*: 0..23 | map | 0xa0..0xb7 - object | *size*: 23..255 | map (1 byte follow) | 0xb8 - object | *size*: 256..65535 | map (2 bytes follow) | 0xb9 - object | *size*: 65536..4294967295 | map (4 bytes follow) | 0xba - object | *size*: 4294967296..18446744073709551615 | map (8 bytes follow) | 0xbb - - @note The mapping is **complete** in the sense that any JSON value type - can be converted to a CBOR value. - - @note The following CBOR types are not used in the conversion: - - byte strings (0x40..0x5f) - - UTF-8 strings terminated by "break" (0x7f) - - arrays terminated by "break" (0x9f) - - maps terminated by "break" (0xbf) - - date/time (0xc0..0xc1) - - bignum (0xc2..0xc3) - - decimal fraction (0xc4) - - bigfloat (0xc5) - - tagged items (0xc6..0xd4, 0xd8..0xdb) - - expected conversions (0xd5..0xd7) - - simple values (0xe0..0xf3, 0xf8) - - undefined (0xf7) - - half and single-precision floats (0xf9-0xfa) - - break (0xff) - - @param[in] j JSON value to serialize - @return MessagePack serialization as byte vector - - @complexity Linear in the size of the JSON value @a j. - - @liveexample{The example shows the serialization of a JSON value to a byte - vector in CBOR format.,to_cbor} - - @sa http://cbor.io - @sa @ref from_cbor(const std::vector&, const size_t) for the - analogous deserialization - @sa @ref to_msgpack(const basic_json& for the related MessagePack format - - @since version 2.0.9 - */ - static std::vector to_cbor(const basic_json& j) - { - std::vector result; - to_cbor_internal(j, result); - return result; - } - - /*! - @brief create a JSON value from a byte vector in CBOR format - - Deserializes a given byte vector @a v to a JSON value using the CBOR - (Concise Binary Object Representation) serialization format. - - The library maps CBOR types to JSON value types as follows: - - CBOR type | JSON value type | first byte - ---------------------- | --------------- | ---------- - Integer | number_unsigned | 0x00..0x17 - Unsigned integer | number_unsigned | 0x18 - Unsigned integer | number_unsigned | 0x19 - Unsigned integer | number_unsigned | 0x1a - Unsigned integer | number_unsigned | 0x1b - Negative integer | number_integer | 0x20..0x37 - Negative integer | number_integer | 0x38 - Negative integer | number_integer | 0x39 - Negative integer | number_integer | 0x3a - Negative integer | number_integer | 0x3b - Negative integer | number_integer | 0x40..0x57 - UTF-8 string | string | 0x60..0x77 - UTF-8 string | string | 0x78 - UTF-8 string | string | 0x79 - UTF-8 string | string | 0x7a - UTF-8 string | string | 0x7b - UTF-8 string | string | 0x7f - array | array | 0x80..0x97 - array | array | 0x98 - array | array | 0x99 - array | array | 0x9a - array | array | 0x9b - array | array | 0x9f - map | object | 0xa0..0xb7 - map | object | 0xb8 - map | object | 0xb9 - map | object | 0xba - map | object | 0xbb - map | object | 0xbf - False | `false` | 0xf4 - True | `true` | 0xf5 - Nill | `null` | 0xf6 - Half-Precision Float | number_float | 0xf9 - Single-Precision Float | number_float | 0xfa - Double-Precision Float | number_float | 0xfb - - @warning The mapping is **incomplete** in the sense that not all CBOR - types can be converted to a JSON value. The following CBOR types - are not supported and will yield parse errors (parse_error.112): - - byte strings (0x40..0x5f) - - date/time (0xc0..0xc1) - - bignum (0xc2..0xc3) - - decimal fraction (0xc4) - - bigfloat (0xc5) - - tagged items (0xc6..0xd4, 0xd8..0xdb) - - expected conversions (0xd5..0xd7) - - simple values (0xe0..0xf3, 0xf8) - - undefined (0xf7) - - @warning CBOR allows map keys of any type, whereas JSON only allows - strings as keys in object values. Therefore, CBOR maps with keys - other than UTF-8 strings are rejected (parse_error.113). - - @note Any CBOR output created @ref to_cbor can be successfully parsed by - @ref from_cbor. - - @param[in] v a byte vector in CBOR format - @param[in] start_index the index to start reading from @a v (0 by default) - @return deserialized JSON value - - @throw parse_error.110 if the given vector ends prematurely - @throw parse_error.112 if unsupported features from CBOR were - used in the given vector @a v or if the input is not valid CBOR - @throw parse_error.113 if a string was expected as map key, but not found - - @complexity Linear in the size of the byte vector @a v. - - @liveexample{The example shows the deserialization of a byte vector in CBOR - format to a JSON value.,from_cbor} - - @sa http://cbor.io - @sa @ref to_cbor(const basic_json&) for the analogous serialization - @sa @ref from_msgpack(const std::vector&, const size_t) for the - related MessagePack format - - @since version 2.0.9, parameter @a start_index since 2.1.1 - */ - static basic_json from_cbor(const std::vector& v, - const size_t start_index = 0) - { - size_t i = start_index; - return from_cbor_internal(v, i); - } - - /// @} - - /////////////////////////// - // convenience functions // - /////////////////////////// - - /*! - @brief return the type as string - - Returns the type name as string to be used in error messages - usually to - indicate that a function was called on a wrong JSON type. - - @return basically a string representation of a the @a m_type member - - @complexity Constant. - - @liveexample{The following code exemplifies `type_name()` for all JSON - types.,type_name} - - @since version 1.0.0, public since 2.1.0 - */ - std::string type_name() const - { - { - switch (m_type) - { - case value_t::null: - return "null"; - case value_t::object: - return "object"; - case value_t::array: - return "array"; - case value_t::string: - return "string"; - case value_t::boolean: - return "boolean"; - case value_t::discarded: - return "discarded"; - default: - return "number"; - } - } - } - - - private: - ////////////////////// - // member variables // - ////////////////////// - - /// the type of the current element - value_t m_type = value_t::null; - - /// the value of the current element - json_value m_value = {}; - - - private: - /////////////// - // iterators // - /////////////// - - /*! - @brief an iterator for primitive JSON types - - This class models an iterator for primitive JSON types (boolean, number, - string). It's only purpose is to allow the iterator/const_iterator classes - to "iterate" over primitive values. Internally, the iterator is modeled by - a `difference_type` variable. Value begin_value (`0`) models the begin, - end_value (`1`) models past the end. - */ - class primitive_iterator_t - { - public: - - difference_type get_value() const noexcept - { - return m_it; - } - /// set iterator to a defined beginning - void set_begin() noexcept - { - m_it = begin_value; - } - - /// set iterator to a defined past the end - void set_end() noexcept - { - m_it = end_value; - } - - /// return whether the iterator can be dereferenced - constexpr bool is_begin() const noexcept - { - return (m_it == begin_value); - } - - /// return whether the iterator is at end - constexpr bool is_end() const noexcept - { - return (m_it == end_value); - } - - friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept - { - return lhs.m_it == rhs.m_it; - } - - friend constexpr bool operator!=(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept - { - return !(lhs == rhs); - } - - friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept - { - return lhs.m_it < rhs.m_it; - } - - friend constexpr bool operator<=(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept - { - return lhs.m_it <= rhs.m_it; - } - - friend constexpr bool operator>(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept - { - return lhs.m_it > rhs.m_it; - } - - friend constexpr bool operator>=(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept - { - return lhs.m_it >= rhs.m_it; - } - - primitive_iterator_t operator+(difference_type i) - { - auto result = *this; - result += i; - return result; - } - - friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept - { - return lhs.m_it - rhs.m_it; - } - - friend std::ostream& operator<<(std::ostream& os, primitive_iterator_t it) - { - return os << it.m_it; - } - - primitive_iterator_t& operator++() - { - ++m_it; - return *this; - } - - primitive_iterator_t operator++(int) - { - auto result = *this; - m_it++; - return result; - } - - primitive_iterator_t& operator--() - { - --m_it; - return *this; - } - - primitive_iterator_t operator--(int) - { - auto result = *this; - m_it--; - return result; - } - - primitive_iterator_t& operator+=(difference_type n) - { - m_it += n; - return *this; - } - - primitive_iterator_t& operator-=(difference_type n) - { - m_it -= n; - return *this; - } - - private: - static constexpr difference_type begin_value = 0; - static constexpr difference_type end_value = begin_value + 1; - - /// iterator as signed integer type - difference_type m_it = std::numeric_limits::denorm_min(); - }; - - /*! - @brief an iterator value - - @note This structure could easily be a union, but MSVC currently does not - allow unions members with complex constructors, see - https://github.com/nlohmann/json/pull/105. - */ - struct internal_iterator - { - /// iterator for JSON objects - typename object_t::iterator object_iterator; - /// iterator for JSON arrays - typename array_t::iterator array_iterator; - /// generic iterator for all other types - primitive_iterator_t primitive_iterator; - - /// create an uninitialized internal_iterator - internal_iterator() noexcept - : object_iterator(), array_iterator(), primitive_iterator() - {} - }; - - /// proxy class for the iterator_wrapper functions - template - class iteration_proxy - { - private: - /// helper class for iteration - class iteration_proxy_internal - { - private: - /// the iterator - IteratorType anchor; - /// an index for arrays (used to create key names) - size_t array_index = 0; - - public: - explicit iteration_proxy_internal(IteratorType it) noexcept - : anchor(it) - {} - - /// dereference operator (needed for range-based for) - iteration_proxy_internal& operator*() - { - return *this; - } - - /// increment operator (needed for range-based for) - iteration_proxy_internal& operator++() - { - ++anchor; - ++array_index; - - return *this; - } - - /// inequality operator (needed for range-based for) - bool operator!= (const iteration_proxy_internal& o) const - { - return anchor != o.anchor; - } - - /// return key of the iterator - typename basic_json::string_t key() const - { - assert(anchor.m_object != nullptr); - - switch (anchor.m_object->type()) - { - // use integer array index as key - case value_t::array: - { - return std::to_string(array_index); - } - - // use key from the object - case value_t::object: - { - return anchor.key(); - } - - // use an empty key for all primitive types - default: - { - return ""; - } - } - } - - /// return value of the iterator - typename IteratorType::reference value() const - { - return anchor.value(); - } - }; - - /// the container to iterate - typename IteratorType::reference container; - - public: - /// construct iteration proxy from a container - explicit iteration_proxy(typename IteratorType::reference cont) - : container(cont) - {} - - /// return iterator begin (needed for range-based for) - iteration_proxy_internal begin() noexcept - { - return iteration_proxy_internal(container.begin()); - } - - /// return iterator end (needed for range-based for) - iteration_proxy_internal end() noexcept - { - return iteration_proxy_internal(container.end()); - } - }; - - public: - /*! - @brief a template for a random access iterator for the @ref basic_json class - - This class implements a both iterators (iterator and const_iterator) for the - @ref basic_json class. - - @note An iterator is called *initialized* when a pointer to a JSON value - has been set (e.g., by a constructor or a copy assignment). If the - iterator is default-constructed, it is *uninitialized* and most - methods are undefined. **The library uses assertions to detect calls - on uninitialized iterators.** - - @requirement The class satisfies the following concept requirements: - - [RandomAccessIterator](http://en.cppreference.com/w/cpp/concept/RandomAccessIterator): - The iterator that can be moved to point (forward and backward) to any - element in constant time. - - @since version 1.0.0, simplified in version 2.0.9 - */ - template - class iter_impl : public std::iterator - { - /// allow basic_json to access private members - friend class basic_json; - - // make sure U is basic_json or const basic_json - static_assert(std::is_same::value - or std::is_same::value, - "iter_impl only accepts (const) basic_json"); - - public: - /// the type of the values when the iterator is dereferenced - using value_type = typename basic_json::value_type; - /// a type to represent differences between iterators - using difference_type = typename basic_json::difference_type; - /// defines a pointer to the type iterated over (value_type) - using pointer = typename std::conditional::value, - typename basic_json::const_pointer, - typename basic_json::pointer>::type; - /// defines a reference to the type iterated over (value_type) - using reference = typename std::conditional::value, - typename basic_json::const_reference, - typename basic_json::reference>::type; - /// the category of the iterator - using iterator_category = std::bidirectional_iterator_tag; - - /// default constructor - iter_impl() = default; - - /*! - @brief constructor for a given JSON instance - @param[in] object pointer to a JSON object for this iterator - @pre object != nullptr - @post The iterator is initialized; i.e. `m_object != nullptr`. - */ - explicit iter_impl(pointer object) noexcept - : m_object(object) - { - assert(m_object != nullptr); - - switch (m_object->m_type) - { - case basic_json::value_t::object: - { - m_it.object_iterator = typename object_t::iterator(); - break; - } - - case basic_json::value_t::array: - { - m_it.array_iterator = typename array_t::iterator(); - break; - } - - default: - { - m_it.primitive_iterator = primitive_iterator_t(); - break; - } - } - } - - /* - Use operator `const_iterator` instead of `const_iterator(const iterator& - other) noexcept` to avoid two class definitions for @ref iterator and - @ref const_iterator. - - This function is only called if this class is an @ref iterator. If this - class is a @ref const_iterator this function is not called. - */ - operator const_iterator() const - { - const_iterator ret; - - if (m_object) - { - ret.m_object = m_object; - ret.m_it = m_it; - } - - return ret; - } - - /*! - @brief copy constructor - @param[in] other iterator to copy from - @note It is not checked whether @a other is initialized. - */ - iter_impl(const iter_impl& other) noexcept - : m_object(other.m_object), m_it(other.m_it) - {} - - /*! - @brief copy assignment - @param[in,out] other iterator to copy from - @note It is not checked whether @a other is initialized. - */ - iter_impl& operator=(iter_impl other) noexcept( - std::is_nothrow_move_constructible::value and - std::is_nothrow_move_assignable::value and - std::is_nothrow_move_constructible::value and - std::is_nothrow_move_assignable::value - ) - { - std::swap(m_object, other.m_object); - std::swap(m_it, other.m_it); - return *this; - } - - private: - /*! - @brief set the iterator to the first value - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - void set_begin() noexcept - { - assert(m_object != nullptr); - - switch (m_object->m_type) - { - case basic_json::value_t::object: - { - m_it.object_iterator = m_object->m_value.object->begin(); - break; - } - - case basic_json::value_t::array: - { - m_it.array_iterator = m_object->m_value.array->begin(); - break; - } - - case basic_json::value_t::null: - { - // set to end so begin()==end() is true: null is empty - m_it.primitive_iterator.set_end(); - break; - } - - default: - { - m_it.primitive_iterator.set_begin(); - break; - } - } - } - - /*! - @brief set the iterator past the last value - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - void set_end() noexcept - { - assert(m_object != nullptr); - - switch (m_object->m_type) - { - case basic_json::value_t::object: - { - m_it.object_iterator = m_object->m_value.object->end(); - break; - } - - case basic_json::value_t::array: - { - m_it.array_iterator = m_object->m_value.array->end(); - break; - } - - default: - { - m_it.primitive_iterator.set_end(); - break; - } - } - } - - public: - /*! - @brief return a reference to the value pointed to by the iterator - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - reference operator*() const - { - assert(m_object != nullptr); - - switch (m_object->m_type) - { - case basic_json::value_t::object: - { - assert(m_it.object_iterator != m_object->m_value.object->end()); - return m_it.object_iterator->second; - } - - case basic_json::value_t::array: - { - assert(m_it.array_iterator != m_object->m_value.array->end()); - return *m_it.array_iterator; - } - - case basic_json::value_t::null: - { - JSON_THROW(invalid_iterator::create(214, "cannot get value")); - } - - default: - { - if (m_it.primitive_iterator.is_begin()) - { - return *m_object; - } - - JSON_THROW(invalid_iterator::create(214, "cannot get value")); - } - } - } - - /*! - @brief dereference the iterator - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - pointer operator->() const - { - assert(m_object != nullptr); - - switch (m_object->m_type) - { - case basic_json::value_t::object: - { - assert(m_it.object_iterator != m_object->m_value.object->end()); - return &(m_it.object_iterator->second); - } - - case basic_json::value_t::array: - { - assert(m_it.array_iterator != m_object->m_value.array->end()); - return &*m_it.array_iterator; - } - - default: - { - if (m_it.primitive_iterator.is_begin()) - { - return m_object; - } - - JSON_THROW(invalid_iterator::create(214, "cannot get value")); - } - } - } - - /*! - @brief post-increment (it++) - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - iter_impl operator++(int) - { - auto result = *this; - ++(*this); - return result; - } - - /*! - @brief pre-increment (++it) - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - iter_impl& operator++() - { - assert(m_object != nullptr); - - switch (m_object->m_type) - { - case basic_json::value_t::object: - { - std::advance(m_it.object_iterator, 1); - break; - } - - case basic_json::value_t::array: - { - std::advance(m_it.array_iterator, 1); - break; - } - - default: - { - ++m_it.primitive_iterator; - break; - } - } - - return *this; - } - - /*! - @brief post-decrement (it--) - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - iter_impl operator--(int) - { - auto result = *this; - --(*this); - return result; - } - - /*! - @brief pre-decrement (--it) - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - iter_impl& operator--() - { - assert(m_object != nullptr); - - switch (m_object->m_type) - { - case basic_json::value_t::object: - { - std::advance(m_it.object_iterator, -1); - break; - } - - case basic_json::value_t::array: - { - std::advance(m_it.array_iterator, -1); - break; - } - - default: - { - --m_it.primitive_iterator; - break; - } - } - - return *this; - } - - /*! - @brief comparison: equal - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - bool operator==(const iter_impl& other) const - { - // if objects are not the same, the comparison is undefined - if (m_object != other.m_object) - { - JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers")); - } - - assert(m_object != nullptr); - - switch (m_object->m_type) - { - case basic_json::value_t::object: - { - return (m_it.object_iterator == other.m_it.object_iterator); - } - - case basic_json::value_t::array: - { - return (m_it.array_iterator == other.m_it.array_iterator); - } - - default: - { - return (m_it.primitive_iterator == other.m_it.primitive_iterator); - } - } - } - - /*! - @brief comparison: not equal - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - bool operator!=(const iter_impl& other) const - { - return not operator==(other); - } - - /*! - @brief comparison: smaller - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - bool operator<(const iter_impl& other) const - { - // if objects are not the same, the comparison is undefined - if (m_object != other.m_object) - { - JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers")); - } - - assert(m_object != nullptr); - - switch (m_object->m_type) - { - case basic_json::value_t::object: - { - JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators")); - } - - case basic_json::value_t::array: - { - return (m_it.array_iterator < other.m_it.array_iterator); - } - - default: - { - return (m_it.primitive_iterator < other.m_it.primitive_iterator); - } - } - } - - /*! - @brief comparison: less than or equal - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - bool operator<=(const iter_impl& other) const - { - return not other.operator < (*this); - } - - /*! - @brief comparison: greater than - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - bool operator>(const iter_impl& other) const - { - return not operator<=(other); - } - - /*! - @brief comparison: greater than or equal - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - bool operator>=(const iter_impl& other) const - { - return not operator<(other); - } - - /*! - @brief add to iterator - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - iter_impl& operator+=(difference_type i) - { - assert(m_object != nullptr); - - switch (m_object->m_type) - { - case basic_json::value_t::object: - { - JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators")); - } - - case basic_json::value_t::array: - { - std::advance(m_it.array_iterator, i); - break; - } - - default: - { - m_it.primitive_iterator += i; - break; - } - } - - return *this; - } - - /*! - @brief subtract from iterator - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - iter_impl& operator-=(difference_type i) - { - return operator+=(-i); - } - - /*! - @brief add to iterator - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - iter_impl operator+(difference_type i) - { - auto result = *this; - result += i; - return result; - } - - /*! - @brief subtract from iterator - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - iter_impl operator-(difference_type i) - { - auto result = *this; - result -= i; - return result; - } - - /*! - @brief return difference - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - difference_type operator-(const iter_impl& other) const - { - assert(m_object != nullptr); - - switch (m_object->m_type) - { - case basic_json::value_t::object: - { - JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators")); - } - - case basic_json::value_t::array: - { - return m_it.array_iterator - other.m_it.array_iterator; - } - - default: - { - return m_it.primitive_iterator - other.m_it.primitive_iterator; - } - } - } - - /*! - @brief access to successor - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - reference operator[](difference_type n) const - { - assert(m_object != nullptr); - - switch (m_object->m_type) - { - case basic_json::value_t::object: - { - JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators")); - } - - case basic_json::value_t::array: - { - return *std::next(m_it.array_iterator, n); - } - - case basic_json::value_t::null: - { - JSON_THROW(invalid_iterator::create(214, "cannot get value")); - } - - default: - { - if (m_it.primitive_iterator.get_value() == -n) - { - return *m_object; - } - - JSON_THROW(invalid_iterator::create(214, "cannot get value")); - } - } - } - - /*! - @brief return the key of an object iterator - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - typename object_t::key_type key() const - { - assert(m_object != nullptr); - - if (m_object->is_object()) - { - return m_it.object_iterator->first; - } - - JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators")); - } - - /*! - @brief return the value of an iterator - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - reference value() const - { - return operator*(); - } - - private: - /// associated JSON instance - pointer m_object = nullptr; - /// the actual iterator of the associated instance - internal_iterator m_it = internal_iterator(); - }; - - /*! - @brief a template for a reverse iterator class - - @tparam Base the base iterator type to reverse. Valid types are @ref - iterator (to create @ref reverse_iterator) and @ref const_iterator (to - create @ref const_reverse_iterator). - - @requirement The class satisfies the following concept requirements: - - [RandomAccessIterator](http://en.cppreference.com/w/cpp/concept/RandomAccessIterator): - The iterator that can be moved to point (forward and backward) to any - element in constant time. - - [OutputIterator](http://en.cppreference.com/w/cpp/concept/OutputIterator): - It is possible to write to the pointed-to element (only if @a Base is - @ref iterator). - - @since version 1.0.0 - */ - template - class json_reverse_iterator : public std::reverse_iterator - { - public: - /// shortcut to the reverse iterator adaptor - using base_iterator = std::reverse_iterator; - /// the reference type for the pointed-to element - using reference = typename Base::reference; - - /// create reverse iterator from iterator - json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept - : base_iterator(it) - {} - - /// create reverse iterator from base class - json_reverse_iterator(const base_iterator& it) noexcept - : base_iterator(it) - {} - - /// post-increment (it++) - json_reverse_iterator operator++(int) - { - return base_iterator::operator++(1); - } - - /// pre-increment (++it) - json_reverse_iterator& operator++() - { - base_iterator::operator++(); - return *this; - } - - /// post-decrement (it--) - json_reverse_iterator operator--(int) - { - return base_iterator::operator--(1); - } - - /// pre-decrement (--it) - json_reverse_iterator& operator--() - { - base_iterator::operator--(); - return *this; - } - - /// add to iterator - json_reverse_iterator& operator+=(difference_type i) - { - base_iterator::operator+=(i); - return *this; - } - - /// add to iterator - json_reverse_iterator operator+(difference_type i) const - { - auto result = *this; - result += i; - return result; - } - - /// subtract from iterator - json_reverse_iterator operator-(difference_type i) const - { - auto result = *this; - result -= i; - return result; - } - - /// return difference - difference_type operator-(const json_reverse_iterator& other) const - { - return this->base() - other.base(); - } - - /// access to successor - reference operator[](difference_type n) const - { - return *(this->operator+(n)); - } - - /// return the key of an object iterator - typename object_t::key_type key() const - { - auto it = --this->base(); - return it.key(); - } - - /// return the value of an iterator - reference value() const - { - auto it = --this->base(); - return it.operator * (); - } - }; - - - private: - ////////////////////// - // lexer and parser // - ////////////////////// - - /*! - @brief lexical analysis - - This class organizes the lexical analysis during JSON deserialization. The - core of it is a scanner generated by [re2c](http://re2c.org) that - processes a buffer and recognizes tokens according to RFC 7159. - */ - class lexer - { - public: - /// token types for the parser - enum class token_type - { - uninitialized, ///< indicating the scanner is uninitialized - literal_true, ///< the `true` literal - literal_false, ///< the `false` literal - literal_null, ///< the `null` literal - value_string, ///< a string -- use get_string() for actual value - value_unsigned, ///< an unsigned integer -- use get_number() for actual value - value_integer, ///< a signed integer -- use get_number() for actual value - value_float, ///< an floating point number -- use get_number() for actual value - begin_array, ///< the character for array begin `[` - begin_object, ///< the character for object begin `{` - end_array, ///< the character for array end `]` - end_object, ///< the character for object end `}` - name_separator, ///< the name separator `:` - value_separator, ///< the value separator `,` - parse_error, ///< indicating a parse error - end_of_input ///< indicating the end of the input buffer - }; - - /// the char type to use in the lexer - using lexer_char_t = unsigned char; - - /// a lexer from a buffer with given length - lexer(const lexer_char_t* buff, const size_t len) noexcept - : m_content(buff) - { - assert(m_content != nullptr); - m_start = m_cursor = m_content; - m_limit = m_content + len; - } - - /*! - @brief a lexer from an input stream - @throw parse_error.111 if input stream is in a bad state - */ - explicit lexer(std::istream& s) - : m_stream(&s), m_line_buffer() - { - // immediately abort if stream is erroneous - if (s.fail()) - { - JSON_THROW(parse_error::create(111, 0, "bad input stream")); - } - - // fill buffer - fill_line_buffer(); - - // skip UTF-8 byte-order mark - if (m_line_buffer.size() >= 3 and m_line_buffer.substr(0, 3) == "\xEF\xBB\xBF") - { - m_line_buffer[0] = ' '; - m_line_buffer[1] = ' '; - m_line_buffer[2] = ' '; - } - } - - // switch off unwanted functions (due to pointer members) - lexer() = delete; - lexer(const lexer&) = delete; - lexer operator=(const lexer&) = delete; - - /*! - @brief create a string from one or two Unicode code points - - There are two cases: (1) @a codepoint1 is in the Basic Multilingual - Plane (U+0000 through U+FFFF) and @a codepoint2 is 0, or (2) - @a codepoint1 and @a codepoint2 are a UTF-16 surrogate pair to - represent a code point above U+FFFF. - - @param[in] codepoint1 the code point (can be high surrogate) - @param[in] codepoint2 the code point (can be low surrogate or 0) - - @return string representation of the code point; the length of the - result string is between 1 and 4 characters. - - @throw parse_error.102 if the low surrogate is invalid; example: - `""missing or wrong low surrogate""` - @throw parse_error.103 if code point is > 0x10ffff; example: `"code - points above 0x10FFFF are invalid"` - - @complexity Constant. - - @see - */ - string_t to_unicode(const std::size_t codepoint1, - const std::size_t codepoint2 = 0) const - { - // calculate the code point from the given code points - std::size_t codepoint = codepoint1; - - // check if codepoint1 is a high surrogate - if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF) - { - // check if codepoint2 is a low surrogate - if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF) - { - codepoint = - // high surrogate occupies the most significant 22 bits - (codepoint1 << 10) - // low surrogate occupies the least significant 15 bits - + codepoint2 - // there is still the 0xD800, 0xDC00 and 0x10000 noise - // in the result so we have to subtract with: - // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00 - - 0x35FDC00; - } - else - { - JSON_THROW(parse_error::create(102, get_position(), "missing or wrong low surrogate")); - } - } - - string_t result; - - if (codepoint < 0x80) - { - // 1-byte characters: 0xxxxxxx (ASCII) - result.append(1, static_cast(codepoint)); - } - else if (codepoint <= 0x7ff) - { - // 2-byte characters: 110xxxxx 10xxxxxx - result.append(1, static_cast(0xC0 | (codepoint >> 6))); - result.append(1, static_cast(0x80 | (codepoint & 0x3F))); - } - else if (codepoint <= 0xffff) - { - // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx - result.append(1, static_cast(0xE0 | (codepoint >> 12))); - result.append(1, static_cast(0x80 | ((codepoint >> 6) & 0x3F))); - result.append(1, static_cast(0x80 | (codepoint & 0x3F))); - } - else if (codepoint <= 0x10ffff) - { - // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx - result.append(1, static_cast(0xF0 | (codepoint >> 18))); - result.append(1, static_cast(0x80 | ((codepoint >> 12) & 0x3F))); - result.append(1, static_cast(0x80 | ((codepoint >> 6) & 0x3F))); - result.append(1, static_cast(0x80 | (codepoint & 0x3F))); - } - else - { - JSON_THROW(parse_error::create(103, get_position(), "code points above 0x10FFFF are invalid")); - } - - return result; - } - - /// return name of values of type token_type (only used for errors) - static std::string token_type_name(const token_type t) - { - switch (t) - { - case token_type::uninitialized: - return ""; - case token_type::literal_true: - return "true literal"; - case token_type::literal_false: - return "false literal"; - case token_type::literal_null: - return "null literal"; - case token_type::value_string: - return "string literal"; - case lexer::token_type::value_unsigned: - case lexer::token_type::value_integer: - case lexer::token_type::value_float: - return "number literal"; - case token_type::begin_array: - return "'['"; - case token_type::begin_object: - return "'{'"; - case token_type::end_array: - return "']'"; - case token_type::end_object: - return "'}'"; - case token_type::name_separator: - return "':'"; - case token_type::value_separator: - return "','"; - case token_type::parse_error: - return ""; - case token_type::end_of_input: - return "end of input"; - default: - { - // catch non-enum values - return "unknown token"; // LCOV_EXCL_LINE - } - } - } - - /*! - This function implements a scanner for JSON. It is specified using - regular expressions that try to follow RFC 7159 as close as possible. - These regular expressions are then translated into a minimized - deterministic finite automaton (DFA) by the tool - [re2c](http://re2c.org). As a result, the translated code for this - function consists of a large block of code with `goto` jumps. - - @return the class of the next token read from the buffer - - @complexity Linear in the length of the input.\n - - Proposition: The loop below will always terminate for finite input.\n - - Proof (by contradiction): Assume a finite input. To loop forever, the - loop must never hit code with a `break` statement. The only code - snippets without a `break` statement is the continue statement for - whitespace. To loop forever, the input must be an infinite sequence - whitespace. This contradicts the assumption of finite input, q.e.d. - */ - token_type scan() - { - while (true) - { - // pointer for backtracking information - m_marker = nullptr; - - // remember the begin of the token - m_start = m_cursor; - assert(m_start != nullptr); - - /*!re2c - re2c:define:YYCTYPE = lexer_char_t; - re2c:define:YYCURSOR = m_cursor; - re2c:define:YYLIMIT = m_limit; - re2c:define:YYMARKER = m_marker; - re2c:define:YYFILL = "fill_line_buffer(@@); // LCOV_EXCL_LINE"; - re2c:define:YYFILL:naked = 1; - re2c:yyfill:enable = 1; - re2c:indent:string = " "; - re2c:indent:top = 1; - re2c:labelprefix = "basic_json_parser_"; - - // ignore whitespace - ws = [ \t\n\r]+; - ws { position += static_cast((m_cursor - m_start)); continue; } - - // structural characters - "[" { last_token_type = token_type::begin_array; break; } - "]" { last_token_type = token_type::end_array; break; } - "{" { last_token_type = token_type::begin_object; break; } - "}" { last_token_type = token_type::end_object; break; } - "," { last_token_type = token_type::value_separator; break; } - ":" { last_token_type = token_type::name_separator; break; } - - // literal names - "null" { last_token_type = token_type::literal_null; break; } - "true" { last_token_type = token_type::literal_true; break; } - "false" { last_token_type = token_type::literal_false; break; } - - // number - decimal_point = "."; - digit = [0-9]; - digit_1_9 = [1-9]; - e = "e" | "E"; - minus = "-"; - plus = "+"; - zero = "0"; - exp = e (minus | plus)? digit+; - frac = decimal_point digit+; - int = (zero | digit_1_9 digit*); - invalid_int = minus? "0" digit+; - invalid_int { last_token_type = token_type::parse_error; break; } - number_unsigned = int; - number_unsigned { last_token_type = token_type::value_unsigned; break; } - number_integer = minus int; - number_integer { last_token_type = token_type::value_integer; break; } - number_float = minus? int frac? exp?; - number_float { last_token_type = token_type::value_float; break; } - - // string - quotation_mark = "\""; - escape = "\\"; - unescaped = [^"\\\x00-\x1f]; - single_escaped = "\"" | "\\" | "/" | "b" | "f" | "n" | "r" | "t"; - unicode_escaped = "u" [0-9a-fA-F]{4}; - escaped = escape (single_escaped | unicode_escaped); - char = unescaped | escaped; - string = quotation_mark char* quotation_mark; - string { last_token_type = token_type::value_string; break; } - - // end of file - "\x00" { last_token_type = token_type::end_of_input; break; } - - // anything else is an error - * { last_token_type = token_type::parse_error; break; } - */ - } - - position += static_cast((m_cursor - m_start)); - return last_token_type; - } - - /*! - @brief append data from the stream to the line buffer - - This function is called by the scan() function when the end of the - buffer (`m_limit`) is reached and the `m_cursor` pointer cannot be - incremented without leaving the limits of the line buffer. Note re2c - decides when to call this function. - - If the lexer reads from contiguous storage, there is no trailing null - byte. Therefore, this function must make sure to add these padding - null bytes. - - If the lexer reads from an input stream, this function reads the next - line of the input. - - @pre - p p p p p p u u u u u x . . . . . . - ^ ^ ^ ^ - m_content m_start | m_limit - m_cursor - - @post - u u u u u x x x x x x x . . . . . . - ^ ^ ^ - | m_cursor m_limit - m_start - m_content - */ - void fill_line_buffer(size_t n = 0) - { - // if line buffer is used, m_content points to its data - assert(m_line_buffer.empty() - or m_content == reinterpret_cast(m_line_buffer.data())); - - // if line buffer is used, m_limit is set past the end of its data - assert(m_line_buffer.empty() - or m_limit == m_content + m_line_buffer.size()); - - // pointer relationships - assert(m_content <= m_start); - assert(m_start <= m_cursor); - assert(m_cursor <= m_limit); - assert(m_marker == nullptr or m_marker <= m_limit); - - // number of processed characters (p) - const auto num_processed_chars = static_cast(m_start - m_content); - // offset for m_marker wrt. to m_start - const auto offset_marker = (m_marker == nullptr) ? 0 : m_marker - m_start; - // number of unprocessed characters (u) - const auto offset_cursor = m_cursor - m_start; - - // no stream is used or end of file is reached - if (m_stream == nullptr or m_stream->eof()) - { - // m_start may or may not be pointing into m_line_buffer at - // this point. We trust the standard library to do the right - // thing. See http://stackoverflow.com/q/28142011/266378 - m_line_buffer.assign(m_start, m_limit); - - // append n characters to make sure that there is sufficient - // space between m_cursor and m_limit - m_line_buffer.append(1, '\x00'); - if (n > 0) - { - m_line_buffer.append(n - 1, '\x01'); - } - } - else - { - // delete processed characters from line buffer - m_line_buffer.erase(0, num_processed_chars); - // read next line from input stream - m_line_buffer_tmp.clear(); - - // check if stream is still good - if (m_stream->fail()) - { - JSON_THROW(parse_error::create(111, 0, "bad input stream")); - } - - std::getline(*m_stream, m_line_buffer_tmp, '\n'); - - // add line with newline symbol to the line buffer - m_line_buffer += m_line_buffer_tmp; - m_line_buffer.push_back('\n'); - } - - // set pointers - m_content = reinterpret_cast(m_line_buffer.data()); - assert(m_content != nullptr); - m_start = m_content; - m_marker = m_start + offset_marker; - m_cursor = m_start + offset_cursor; - m_limit = m_start + m_line_buffer.size(); - } - - /// return string representation of last read token - string_t get_token_string() const - { - assert(m_start != nullptr); - return string_t(reinterpret_cast(m_start), - static_cast(m_cursor - m_start)); - } - - /*! - @brief return string value for string tokens - - The function iterates the characters between the opening and closing - quotes of the string value. The complete string is the range - [m_start,m_cursor). Consequently, we iterate from m_start+1 to - m_cursor-1. - - We differentiate two cases: - - 1. Escaped characters. In this case, a new character is constructed - according to the nature of the escape. Some escapes create new - characters (e.g., `"\\n"` is replaced by `"\n"`), some are copied - as is (e.g., `"\\\\"`). Furthermore, Unicode escapes of the shape - `"\\uxxxx"` need special care. In this case, to_unicode takes care - of the construction of the values. - 2. Unescaped characters are copied as is. - - @pre `m_cursor - m_start >= 2`, meaning the length of the last token - is at least 2 bytes which is trivially true for any string (which - consists of at least two quotes). - - " c1 c2 c3 ... " - ^ ^ - m_start m_cursor - - @complexity Linear in the length of the string.\n - - Lemma: The loop body will always terminate.\n - - Proof (by contradiction): Assume the loop body does not terminate. As - the loop body does not contain another loop, one of the called - functions must never return. The called functions are `std::strtoul` - and to_unicode. Neither function can loop forever, so the loop body - will never loop forever which contradicts the assumption that the loop - body does not terminate, q.e.d.\n - - Lemma: The loop condition for the for loop is eventually false.\n - - Proof (by contradiction): Assume the loop does not terminate. Due to - the above lemma, this can only be due to a tautological loop - condition; that is, the loop condition i < m_cursor - 1 must always be - true. Let x be the change of i for any loop iteration. Then - m_start + 1 + x < m_cursor - 1 must hold to loop indefinitely. This - can be rephrased to m_cursor - m_start - 2 > x. With the - precondition, we x <= 0, meaning that the loop condition holds - indefinitely if i is always decreased. However, observe that the value - of i is strictly increasing with each iteration, as it is incremented - by 1 in the iteration expression and never decremented inside the loop - body. Hence, the loop condition will eventually be false which - contradicts the assumption that the loop condition is a tautology, - q.e.d. - - @return string value of current token without opening and closing - quotes - @throw parse_error.102 if to_unicode fails or surrogate error - @throw parse_error.103 if to_unicode fails - */ - string_t get_string() const - { - assert(m_cursor - m_start >= 2); - - string_t result; - result.reserve(static_cast(m_cursor - m_start - 2)); - - // iterate the result between the quotes - for (const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i) - { - // find next escape character - auto e = std::find(i, m_cursor - 1, '\\'); - if (e != i) - { - // see https://github.com/nlohmann/json/issues/365#issuecomment-262874705 - for (auto k = i; k < e; k++) - { - result.push_back(static_cast(*k)); - } - i = e - 1; // -1 because of ++i - } - else - { - // processing escaped character - // read next character - ++i; - - switch (*i) - { - // the default escapes - case 't': - { - result += "\t"; - break; - } - case 'b': - { - result += "\b"; - break; - } - case 'f': - { - result += "\f"; - break; - } - case 'n': - { - result += "\n"; - break; - } - case 'r': - { - result += "\r"; - break; - } - case '\\': - { - result += "\\"; - break; - } - case '/': - { - result += "/"; - break; - } - case '"': - { - result += "\""; - break; - } - - // unicode - case 'u': - { - // get code xxxx from uxxxx - auto codepoint = std::strtoul(std::string(reinterpret_cast(i + 1), - 4).c_str(), nullptr, 16); - - // check if codepoint is a high surrogate - if (codepoint >= 0xD800 and codepoint <= 0xDBFF) - { - // make sure there is a subsequent unicode - if ((i + 6 >= m_limit) or * (i + 5) != '\\' or * (i + 6) != 'u') - { - JSON_THROW(parse_error::create(102, get_position(), "missing low surrogate")); - } - - // get code yyyy from uxxxx\uyyyy - auto codepoint2 = std::strtoul(std::string(reinterpret_cast - (i + 7), 4).c_str(), nullptr, 16); - result += to_unicode(codepoint, codepoint2); - // skip the next 10 characters (xxxx\uyyyy) - i += 10; - } - else if (codepoint >= 0xDC00 and codepoint <= 0xDFFF) - { - // we found a lone low surrogate - JSON_THROW(parse_error::create(102, get_position(), "missing high surrogate")); - } - else - { - // add unicode character(s) - result += to_unicode(codepoint); - // skip the next four characters (xxxx) - i += 4; - } - break; - } - } - } - } - - return result; - } - - - /*! - @brief parse string into a built-in arithmetic type as if the current - locale is POSIX. - - @note in floating-point case strtod may parse past the token's end - - this is not an error - - @note any leading blanks are not handled - */ - struct strtonum - { - public: - strtonum(const char* start, const char* end) - : m_start(start), m_end(end) - {} - - /*! - @return true iff parsed successfully as number of type T - - @param[in,out] val shall contain parsed value, or undefined value - if could not parse - */ - template::value>::type> - bool to(T& val) const - { - return parse(val, std::is_integral()); - } - - private: - const char* const m_start = nullptr; - const char* const m_end = nullptr; - - // floating-point conversion - - // overloaded wrappers for strtod/strtof/strtold - // that will be called from parse - static void strtof(float& f, const char* str, char** endptr) - { - f = std::strtof(str, endptr); - } - - static void strtof(double& f, const char* str, char** endptr) - { - f = std::strtod(str, endptr); - } - - static void strtof(long double& f, const char* str, char** endptr) - { - f = std::strtold(str, endptr); - } - - template - bool parse(T& value, /*is_integral=*/std::false_type) const - { - // replace decimal separator with locale-specific version, - // when necessary; data will point to either the original - // string, or buf, or tempstr containing the fixed string. - std::string tempstr; - std::array buf; - const size_t len = static_cast(m_end - m_start); - - // lexer will reject empty numbers - assert(len > 0); - - // since dealing with strtod family of functions, we're - // getting the decimal point char from the C locale facilities - // instead of C++'s numpunct facet of the current std::locale - const auto loc = localeconv(); - assert(loc != nullptr); - const char decimal_point_char = (loc->decimal_point == nullptr) ? '.' : loc->decimal_point[0]; - - const char* data = m_start; - - if (decimal_point_char != '.') - { - const size_t ds_pos = static_cast(std::find(m_start, m_end, '.') - m_start); - - if (ds_pos != len) - { - // copy the data into the local buffer or tempstr, if - // buffer is too small; replace decimal separator, and - // update data to point to the modified bytes - if ((len + 1) < buf.size()) - { - std::copy(m_start, m_end, buf.begin()); - buf[len] = 0; - buf[ds_pos] = decimal_point_char; - data = buf.data(); - } - else - { - tempstr.assign(m_start, m_end); - tempstr[ds_pos] = decimal_point_char; - data = tempstr.c_str(); - } - } - } - - char* endptr = nullptr; - value = 0; - // this calls appropriate overload depending on T - strtof(value, data, &endptr); - - // parsing was successful iff strtof parsed exactly the number - // of characters determined by the lexer (len) - const bool ok = (endptr == (data + len)); - - if (ok and (value == static_cast(0.0)) and (*data == '-')) - { - // some implementations forget to negate the zero - value = -0.0; - } - - return ok; - } - - // integral conversion - - signed long long parse_integral(char** endptr, /*is_signed*/std::true_type) const - { - return std::strtoll(m_start, endptr, 10); - } - - unsigned long long parse_integral(char** endptr, /*is_signed*/std::false_type) const - { - return std::strtoull(m_start, endptr, 10); - } - - template - bool parse(T& value, /*is_integral=*/std::true_type) const - { - char* endptr = nullptr; - errno = 0; // these are thread-local - const auto x = parse_integral(&endptr, std::is_signed()); - - // called right overload? - static_assert(std::is_signed() == std::is_signed(), ""); - - value = static_cast(x); - - return (x == static_cast(value)) // x fits into destination T - and (x < 0) == (value < 0) // preserved sign - //and ((x != 0) or is_integral()) // strto[u]ll did nto fail - and (errno == 0) // strto[u]ll did not overflow - and (m_start < m_end) // token was not empty - and (endptr == m_end); // parsed entire token exactly - } - }; - - /*! - @brief return number value for number tokens - - This function translates the last token into the most appropriate - number type (either integer, unsigned integer or floating point), - which is passed back to the caller via the result parameter. - - integral numbers that don't fit into the the range of the respective - type are parsed as number_float_t - - floating-point values do not satisfy std::isfinite predicate - are converted to value_t::null - - throws if the entire string [m_start .. m_cursor) cannot be - interpreted as a number - - @param[out] result @ref basic_json object to receive the number. - @param[in] token the type of the number token - */ - bool get_number(basic_json& result, const token_type token) const - { - assert(m_start != nullptr); - assert(m_start < m_cursor); - assert((token == token_type::value_unsigned) or - (token == token_type::value_integer) or - (token == token_type::value_float)); - - strtonum num_converter(reinterpret_cast(m_start), - reinterpret_cast(m_cursor)); - - switch (token) - { - case lexer::token_type::value_unsigned: - { - number_unsigned_t val; - if (num_converter.to(val)) - { - // parsing successful - result.m_type = value_t::number_unsigned; - result.m_value = val; - return true; - } - break; - } - - case lexer::token_type::value_integer: - { - number_integer_t val; - if (num_converter.to(val)) - { - // parsing successful - result.m_type = value_t::number_integer; - result.m_value = val; - return true; - } - break; - } - - default: - { - break; - } - } - - // parse float (either explicitly or because a previous conversion - // failed) - number_float_t val; - if (num_converter.to(val)) - { - // parsing successful - result.m_type = value_t::number_float; - result.m_value = val; - - // throw in case of infinity or NAN - if (not std::isfinite(result.m_value.number_float)) - { - JSON_THROW(out_of_range::create(406, "number overflow parsing '" + get_token_string() + "'")); - } - - return true; - } - - // couldn't parse number in any format - return false; - } - - constexpr size_t get_position() const - { - return position; - } - - private: - /// optional input stream - std::istream* m_stream = nullptr; - /// line buffer buffer for m_stream - string_t m_line_buffer {}; - /// used for filling m_line_buffer - string_t m_line_buffer_tmp {}; - /// the buffer pointer - const lexer_char_t* m_content = nullptr; - /// pointer to the beginning of the current symbol - const lexer_char_t* m_start = nullptr; - /// pointer for backtracking information - const lexer_char_t* m_marker = nullptr; - /// pointer to the current symbol - const lexer_char_t* m_cursor = nullptr; - /// pointer to the end of the buffer - const lexer_char_t* m_limit = nullptr; - /// the last token type - token_type last_token_type = token_type::end_of_input; - /// current position in the input (read bytes) - size_t position = 0; - }; - - /*! - @brief syntax analysis - - This class implements a recursive decent parser. - */ - class parser - { - public: - /// a parser reading from a string literal - parser(const char* buff, const parser_callback_t cb = nullptr) - : callback(cb), - m_lexer(reinterpret_cast(buff), std::strlen(buff)) - {} - - /*! - @brief a parser reading from an input stream - @throw parse_error.111 if input stream is in a bad state - */ - parser(std::istream& is, const parser_callback_t cb = nullptr) - : callback(cb), m_lexer(is) - {} - - /// a parser reading from an iterator range with contiguous storage - template::iterator_category, std::random_access_iterator_tag>::value - , int>::type - = 0> - parser(IteratorType first, IteratorType last, const parser_callback_t cb = nullptr) - : callback(cb), - m_lexer(reinterpret_cast(&(*first)), - static_cast(std::distance(first, last))) - {} - - /*! - @brief public parser interface - @throw parse_error.101 in case of an unexpected token - @throw parse_error.102 if to_unicode fails or surrogate error - @throw parse_error.103 if to_unicode fails - */ - basic_json parse() - { - // read first token - get_token(); - - basic_json result = parse_internal(true); - result.assert_invariant(); - - expect(lexer::token_type::end_of_input); - - // return parser result and replace it with null in case the - // top-level value was discarded by the callback function - return result.is_discarded() ? basic_json() : std::move(result); - } - - private: - /*! - @brief the actual parser - @throw parse_error.101 in case of an unexpected token - @throw parse_error.102 if to_unicode fails or surrogate error - @throw parse_error.103 if to_unicode fails - */ - basic_json parse_internal(bool keep) - { - auto result = basic_json(value_t::discarded); - - switch (last_token) - { - case lexer::token_type::begin_object: - { - if (keep and (not callback - or ((keep = callback(depth++, parse_event_t::object_start, result)) != 0))) - { - // explicitly set result to object to cope with {} - result.m_type = value_t::object; - result.m_value = value_t::object; - } - - // read next token - get_token(); - - // closing } -> we are done - if (last_token == lexer::token_type::end_object) - { - get_token(); - if (keep and callback and not callback(--depth, parse_event_t::object_end, result)) - { - result = basic_json(value_t::discarded); - } - return result; - } - - // no comma is expected here - unexpect(lexer::token_type::value_separator); - - // otherwise: parse key-value pairs - do - { - // ugly, but could be fixed with loop reorganization - if (last_token == lexer::token_type::value_separator) - { - get_token(); - } - - // store key - expect(lexer::token_type::value_string); - const auto key = m_lexer.get_string(); - - bool keep_tag = false; - if (keep) - { - if (callback) - { - basic_json k(key); - keep_tag = callback(depth, parse_event_t::key, k); - } - else - { - keep_tag = true; - } - } - - // parse separator (:) - get_token(); - expect(lexer::token_type::name_separator); - - // parse and add value - get_token(); - auto value = parse_internal(keep); - if (keep and keep_tag and not value.is_discarded()) - { - result[key] = std::move(value); - } - } - while (last_token == lexer::token_type::value_separator); - - // closing } - expect(lexer::token_type::end_object); - get_token(); - if (keep and callback and not callback(--depth, parse_event_t::object_end, result)) - { - result = basic_json(value_t::discarded); - } - - return result; - } - - case lexer::token_type::begin_array: - { - if (keep and (not callback - or ((keep = callback(depth++, parse_event_t::array_start, result)) != 0))) - { - // explicitly set result to object to cope with [] - result.m_type = value_t::array; - result.m_value = value_t::array; - } - - // read next token - get_token(); - - // closing ] -> we are done - if (last_token == lexer::token_type::end_array) - { - get_token(); - if (callback and not callback(--depth, parse_event_t::array_end, result)) - { - result = basic_json(value_t::discarded); - } - return result; - } - - // no comma is expected here - unexpect(lexer::token_type::value_separator); - - // otherwise: parse values - do - { - // ugly, but could be fixed with loop reorganization - if (last_token == lexer::token_type::value_separator) - { - get_token(); - } - - // parse value - auto value = parse_internal(keep); - if (keep and not value.is_discarded()) - { - result.push_back(std::move(value)); - } - } - while (last_token == lexer::token_type::value_separator); - - // closing ] - expect(lexer::token_type::end_array); - get_token(); - if (keep and callback and not callback(--depth, parse_event_t::array_end, result)) - { - result = basic_json(value_t::discarded); - } - - return result; - } - - case lexer::token_type::literal_null: - { - get_token(); - result.m_type = value_t::null; - break; - } - - case lexer::token_type::value_string: - { - const auto s = m_lexer.get_string(); - get_token(); - result = basic_json(s); - break; - } - - case lexer::token_type::literal_true: - { - get_token(); - result.m_type = value_t::boolean; - result.m_value = true; - break; - } - - case lexer::token_type::literal_false: - { - get_token(); - result.m_type = value_t::boolean; - result.m_value = false; - break; - } - - case lexer::token_type::value_unsigned: - case lexer::token_type::value_integer: - case lexer::token_type::value_float: - { - m_lexer.get_number(result, last_token); - get_token(); - break; - } - - default: - { - // the last token was unexpected - unexpect(last_token); - } - } - - if (keep and callback and not callback(depth, parse_event_t::value, result)) - { - result = basic_json(value_t::discarded); - } - return result; - } - - /// get next token from lexer - typename lexer::token_type get_token() - { - last_token = m_lexer.scan(); - return last_token; - } - - /*! - @throw parse_error.101 if expected token did not occur - */ - void expect(typename lexer::token_type t) const - { - if (t != last_token) - { - std::string error_msg = "parse error - unexpected "; - error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token_string() + - "'") : - lexer::token_type_name(last_token)); - error_msg += "; expected " + lexer::token_type_name(t); - JSON_THROW(parse_error::create(101, m_lexer.get_position(), error_msg)); - } - } - - /*! - @throw parse_error.101 if unexpected token occurred - */ - void unexpect(typename lexer::token_type t) const - { - if (t == last_token) - { - std::string error_msg = "parse error - unexpected "; - error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token_string() + - "'") : - lexer::token_type_name(last_token)); - JSON_THROW(parse_error::create(101, m_lexer.get_position(), error_msg)); - } - } - - private: - /// current level of recursion - int depth = 0; - /// callback function - const parser_callback_t callback = nullptr; - /// the type of the last read token - typename lexer::token_type last_token = lexer::token_type::uninitialized; - /// the lexer - lexer m_lexer; - }; - - public: - /*! - @brief JSON Pointer - - A JSON pointer defines a string syntax for identifying a specific value - within a JSON document. It can be used with functions `at` and - `operator[]`. Furthermore, JSON pointers are the base for JSON patches. - - @sa [RFC 6901](https://tools.ietf.org/html/rfc6901) - - @since version 2.0.0 - */ - class json_pointer - { - /// allow basic_json to access private members - friend class basic_json; - - public: - /*! - @brief create JSON pointer - - Create a JSON pointer according to the syntax described in - [Section 3 of RFC6901](https://tools.ietf.org/html/rfc6901#section-3). - - @param[in] s string representing the JSON pointer; if omitted, the - empty string is assumed which references the whole JSON - value - - @throw parse_error.107 if the given JSON pointer @a s is nonempty and - does not begin with a slash (`/`); see example below - - @throw parse_error.108 if a tilde (`~`) in the given JSON pointer @a s - is not followed by `0` (representing `~`) or `1` (representing `/`); - see example below - - @liveexample{The example shows the construction several valid JSON - pointers as well as the exceptional behavior.,json_pointer} - - @since version 2.0.0 - */ - explicit json_pointer(const std::string& s = "") - : reference_tokens(split(s)) - {} - - /*! - @brief return a string representation of the JSON pointer - - @invariant For each JSON pointer `ptr`, it holds: - @code {.cpp} - ptr == json_pointer(ptr.to_string()); - @endcode - - @return a string representation of the JSON pointer - - @liveexample{The example shows the result of `to_string`., - json_pointer__to_string} - - @since version 2.0.0 - */ - std::string to_string() const noexcept - { - return std::accumulate(reference_tokens.begin(), - reference_tokens.end(), std::string{}, - [](const std::string & a, const std::string & b) - { - return a + "/" + escape(b); - }); - } - - /// @copydoc to_string() - operator std::string() const - { - return to_string(); - } - - private: - /*! - @brief remove and return last reference pointer - @throw out_of_range.405 if JSON pointer has no parent - */ - std::string pop_back() - { - if (is_root()) - { - JSON_THROW(out_of_range::create(405, "JSON pointer has no parent")); - } - - auto last = reference_tokens.back(); - reference_tokens.pop_back(); - return last; - } - - /// return whether pointer points to the root document - bool is_root() const - { - return reference_tokens.empty(); - } - - json_pointer top() const - { - if (is_root()) - { - JSON_THROW(out_of_range::create(405, "JSON pointer has no parent")); - } - - json_pointer result = *this; - result.reference_tokens = {reference_tokens[0]}; - return result; - } - - /*! - @brief create and return a reference to the pointed to value - - @complexity Linear in the number of reference tokens. - - @throw parse_error.109 if array index is not a number - @throw type_error.313 if value cannot be unflattened - */ - reference get_and_create(reference j) const - { - pointer result = &j; - - // in case no reference tokens exist, return a reference to the - // JSON value j which will be overwritten by a primitive value - for (const auto& reference_token : reference_tokens) - { - switch (result->m_type) - { - case value_t::null: - { - if (reference_token == "0") - { - // start a new array if reference token is 0 - result = &result->operator[](0); - } - else - { - // start a new object otherwise - result = &result->operator[](reference_token); - } - break; - } - - case value_t::object: - { - // create an entry in the object - result = &result->operator[](reference_token); - break; - } - - case value_t::array: - { - // create an entry in the array - JSON_TRY - { - result = &result->operator[](static_cast(std::stoi(reference_token))); - } - JSON_CATCH (std::invalid_argument&) - { - JSON_THROW(parse_error::create(109, 0, "array index '" + reference_token + "' is not a number")); - } - break; - } - - /* - The following code is only reached if there exists a - reference token _and_ the current value is primitive. In - this case, we have an error situation, because primitive - values may only occur as single value; that is, with an - empty list of reference tokens. - */ - default: - { - JSON_THROW(type_error::create(313, "invalid value to unflatten")); - } - } - } - - return *result; - } - - /*! - @brief return a reference to the pointed to value - - @note This version does not throw if a value is not present, but tries - to create nested values instead. For instance, calling this function - with pointer `"/this/that"` on a null value is equivalent to calling - `operator[]("this").operator[]("that")` on that value, effectively - changing the null value to an object. - - @param[in] ptr a JSON value - - @return reference to the JSON value pointed to by the JSON pointer - - @complexity Linear in the length of the JSON pointer. - - @throw parse_error.106 if an array index begins with '0' - @throw parse_error.109 if an array index was not a number - @throw out_of_range.404 if the JSON pointer can not be resolved - */ - reference get_unchecked(pointer ptr) const - { - for (const auto& reference_token : reference_tokens) - { - // convert null values to arrays or objects before continuing - if (ptr->m_type == value_t::null) - { - // check if reference token is a number - const bool nums = std::all_of(reference_token.begin(), - reference_token.end(), - [](const char x) - { - return (x >= '0' and x <= '9'); - }); - - // change value to array for numbers or "-" or to object - // otherwise - if (nums or reference_token == "-") - { - *ptr = value_t::array; - } - else - { - *ptr = value_t::object; - } - } - - switch (ptr->m_type) - { - case value_t::object: - { - // use unchecked object access - ptr = &ptr->operator[](reference_token); - break; - } - - case value_t::array: - { - // error condition (cf. RFC 6901, Sect. 4) - if (reference_token.size() > 1 and reference_token[0] == '0') - { - JSON_THROW(parse_error::create(106, 0, "array index '" + reference_token + "' must not begin with '0'")); - } - - if (reference_token == "-") - { - // explicitly treat "-" as index beyond the end - ptr = &ptr->operator[](ptr->m_value.array->size()); - } - else - { - // convert array index to number; unchecked access - JSON_TRY - { - ptr = &ptr->operator[](static_cast(std::stoi(reference_token))); - } - JSON_CATCH (std::invalid_argument&) - { - JSON_THROW(parse_error::create(109, 0, "array index '" + reference_token + "' is not a number")); - } - } - break; - } - - default: - { - JSON_THROW(out_of_range::create(404, "unresolved reference token '" + reference_token + "'")); - } - } - } - - return *ptr; - } - - /*! - @throw parse_error.106 if an array index begins with '0' - @throw parse_error.109 if an array index was not a number - @throw out_of_range.402 if the array index '-' is used - @throw out_of_range.404 if the JSON pointer can not be resolved - */ - reference get_checked(pointer ptr) const - { - for (const auto& reference_token : reference_tokens) - { - switch (ptr->m_type) - { - case value_t::object: - { - // note: at performs range check - ptr = &ptr->at(reference_token); - break; - } - - case value_t::array: - { - if (reference_token == "-") - { - // "-" always fails the range check - JSON_THROW(out_of_range::create(402, "array index '-' (" + - std::to_string(ptr->m_value.array->size()) + - ") is out of range")); - } - - // error condition (cf. RFC 6901, Sect. 4) - if (reference_token.size() > 1 and reference_token[0] == '0') - { - JSON_THROW(parse_error::create(106, 0, "array index '" + reference_token + "' must not begin with '0'")); - } - - // note: at performs range check - JSON_TRY - { - ptr = &ptr->at(static_cast(std::stoi(reference_token))); - } - JSON_CATCH (std::invalid_argument&) - { - JSON_THROW(parse_error::create(109, 0, "array index '" + reference_token + "' is not a number")); - } - break; - } - - default: - { - JSON_THROW(out_of_range::create(404, "unresolved reference token '" + reference_token + "'")); - } - } - } - - return *ptr; - } - - /*! - @brief return a const reference to the pointed to value - - @param[in] ptr a JSON value - - @return const reference to the JSON value pointed to by the JSON - pointer - - @throw parse_error.106 if an array index begins with '0' - @throw parse_error.109 if an array index was not a number - @throw out_of_range.402 if the array index '-' is used - @throw out_of_range.404 if the JSON pointer can not be resolved - */ - const_reference get_unchecked(const_pointer ptr) const - { - for (const auto& reference_token : reference_tokens) - { - switch (ptr->m_type) - { - case value_t::object: - { - // use unchecked object access - ptr = &ptr->operator[](reference_token); - break; - } - - case value_t::array: - { - if (reference_token == "-") - { - // "-" cannot be used for const access - JSON_THROW(out_of_range::create(402, "array index '-' (" + - std::to_string(ptr->m_value.array->size()) + - ") is out of range")); - } - - // error condition (cf. RFC 6901, Sect. 4) - if (reference_token.size() > 1 and reference_token[0] == '0') - { - JSON_THROW(parse_error::create(106, 0, "array index '" + reference_token + "' must not begin with '0'")); - } - - // use unchecked array access - JSON_TRY - { - ptr = &ptr->operator[](static_cast(std::stoi(reference_token))); - } - JSON_CATCH (std::invalid_argument&) - { - JSON_THROW(parse_error::create(109, 0, "array index '" + reference_token + "' is not a number")); - } - break; - } - - default: - { - JSON_THROW(out_of_range::create(404, "unresolved reference token '" + reference_token + "'")); - } - } - } - - return *ptr; - } - - /*! - @throw parse_error.106 if an array index begins with '0' - @throw parse_error.109 if an array index was not a number - @throw out_of_range.402 if the array index '-' is used - @throw out_of_range.404 if the JSON pointer can not be resolved - */ - const_reference get_checked(const_pointer ptr) const - { - for (const auto& reference_token : reference_tokens) - { - switch (ptr->m_type) - { - case value_t::object: - { - // note: at performs range check - ptr = &ptr->at(reference_token); - break; - } - - case value_t::array: - { - if (reference_token == "-") - { - // "-" always fails the range check - JSON_THROW(out_of_range::create(402, "array index '-' (" + - std::to_string(ptr->m_value.array->size()) + - ") is out of range")); - } - - // error condition (cf. RFC 6901, Sect. 4) - if (reference_token.size() > 1 and reference_token[0] == '0') - { - JSON_THROW(parse_error::create(106, 0, "array index '" + reference_token + "' must not begin with '0'")); - } - - // note: at performs range check - JSON_TRY - { - ptr = &ptr->at(static_cast(std::stoi(reference_token))); - } - JSON_CATCH (std::invalid_argument&) - { - JSON_THROW(parse_error::create(109, 0, "array index '" + reference_token + "' is not a number")); - } - break; - } - - default: - { - JSON_THROW(out_of_range::create(404, "unresolved reference token '" + reference_token + "'")); - } - } - } - - return *ptr; - } - - /*! - @brief split the string input to reference tokens - - @note This function is only called by the json_pointer constructor. - All exceptions below are documented there. - - @throw parse_error.107 if the pointer is not empty or begins with '/' - @throw parse_error.108 if character '~' is not followed by '0' or '1' - */ - static std::vector split(const std::string& reference_string) - { - std::vector result; - - // special case: empty reference string -> no reference tokens - if (reference_string.empty()) - { - return result; - } - - // check if nonempty reference string begins with slash - if (reference_string[0] != '/') - { - JSON_THROW(parse_error::create(107, 1, "JSON pointer must be empty or begin with '/' - was: '" + reference_string + "'")); - } - - // extract the reference tokens: - // - slash: position of the last read slash (or end of string) - // - start: position after the previous slash - for ( - // search for the first slash after the first character - size_t slash = reference_string.find_first_of('/', 1), - // set the beginning of the first reference token - start = 1; - // we can stop if start == string::npos+1 = 0 - start != 0; - // set the beginning of the next reference token - // (will eventually be 0 if slash == std::string::npos) - start = slash + 1, - // find next slash - slash = reference_string.find_first_of('/', start)) - { - // use the text between the beginning of the reference token - // (start) and the last slash (slash). - auto reference_token = reference_string.substr(start, slash - start); - - // check reference tokens are properly escaped - for (size_t pos = reference_token.find_first_of('~'); - pos != std::string::npos; - pos = reference_token.find_first_of('~', pos + 1)) - { - assert(reference_token[pos] == '~'); - - // ~ must be followed by 0 or 1 - if (pos == reference_token.size() - 1 or - (reference_token[pos + 1] != '0' and - reference_token[pos + 1] != '1')) - { - JSON_THROW(parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'")); - } - } - - // finally, store the reference token - unescape(reference_token); - result.push_back(reference_token); - } - - return result; - } - - /*! - @brief replace all occurrences of a substring by another string - - @param[in,out] s the string to manipulate; changed so that all - occurrences of @a f are replaced with @a t - @param[in] f the substring to replace with @a t - @param[in] t the string to replace @a f - - @pre The search string @a f must not be empty. **This precondition is - enforced with an assertion.** - - @since version 2.0.0 - */ - static void replace_substring(std::string& s, - const std::string& f, - const std::string& t) - { - assert(not f.empty()); - - for ( - size_t pos = s.find(f); // find first occurrence of f - pos != std::string::npos; // make sure f was found - s.replace(pos, f.size(), t), // replace with t - pos = s.find(f, pos + t.size()) // find next occurrence of f - ); - } - - /// escape tilde and slash - static std::string escape(std::string s) - { - // escape "~"" to "~0" and "/" to "~1" - replace_substring(s, "~", "~0"); - replace_substring(s, "/", "~1"); - return s; - } - - /// unescape tilde and slash - static void unescape(std::string& s) - { - // first transform any occurrence of the sequence '~1' to '/' - replace_substring(s, "~1", "/"); - // then transform any occurrence of the sequence '~0' to '~' - replace_substring(s, "~0", "~"); - } - - /*! - @param[in] reference_string the reference string to the current value - @param[in] value the value to consider - @param[in,out] result the result object to insert values to - - @note Empty objects or arrays are flattened to `null`. - */ - static void flatten(const std::string& reference_string, - const basic_json& value, - basic_json& result) - { - switch (value.m_type) - { - case value_t::array: - { - if (value.m_value.array->empty()) - { - // flatten empty array as null - result[reference_string] = nullptr; - } - else - { - // iterate array and use index as reference string - for (size_t i = 0; i < value.m_value.array->size(); ++i) - { - flatten(reference_string + "/" + std::to_string(i), - value.m_value.array->operator[](i), result); - } - } - break; - } - - case value_t::object: - { - if (value.m_value.object->empty()) - { - // flatten empty object as null - result[reference_string] = nullptr; - } - else - { - // iterate object and use keys as reference string - for (const auto& element : *value.m_value.object) - { - flatten(reference_string + "/" + escape(element.first), - element.second, result); - } - } - break; - } - - default: - { - // add primitive value with its reference string - result[reference_string] = value; - break; - } - } - } - - /*! - @param[in] value flattened JSON - - @return unflattened JSON - - @throw parse_error.109 if array index is not a number - @throw type_error.314 if value is not an object - @throw type_error.315 if object values are not primitive - @throw type_error.313 if value cannot be unflattened - */ - static basic_json unflatten(const basic_json& value) - { - if (not value.is_object()) - { - JSON_THROW(type_error::create(314, "only objects can be unflattened")); - } - - basic_json result; - - // iterate the JSON object values - for (const auto& element : *value.m_value.object) - { - if (not element.second.is_primitive()) - { - JSON_THROW(type_error::create(315, "values in object must be primitive")); - } - - // assign value to reference pointed to by JSON pointer; Note - // that if the JSON pointer is "" (i.e., points to the whole - // value), function get_and_create returns a reference to - // result itself. An assignment will then create a primitive - // value. - json_pointer(element.first).get_and_create(result) = element.second; - } - - return result; - } - - friend bool operator==(json_pointer const& lhs, - json_pointer const& rhs) noexcept - { - return lhs.reference_tokens == rhs.reference_tokens; - } - - friend bool operator!=(json_pointer const& lhs, - json_pointer const& rhs) noexcept - { - return !(lhs == rhs); - } - - /// the reference tokens - std::vector reference_tokens {}; - }; - - ////////////////////////// - // JSON Pointer support // - ////////////////////////// - - /// @name JSON Pointer functions - /// @{ - - /*! - @brief access specified element via JSON Pointer - - Uses a JSON pointer to retrieve a reference to the respective JSON value. - No bound checking is performed. Similar to @ref operator[](const typename - object_t::key_type&), `null` values are created in arrays and objects if - necessary. - - In particular: - - If the JSON pointer points to an object key that does not exist, it - is created an filled with a `null` value before a reference to it - is returned. - - If the JSON pointer points to an array index that does not exist, it - is created an filled with a `null` value before a reference to it - is returned. All indices between the current maximum and the given - index are also filled with `null`. - - The special value `-` is treated as a synonym for the index past the - end. - - @param[in] ptr a JSON pointer - - @return reference to the element pointed to by @a ptr - - @complexity Constant. - - @throw parse_error.106 if an array index begins with '0' - @throw parse_error.109 if an array index was not a number - @throw out_of_range.404 if the JSON pointer can not be resolved - - @liveexample{The behavior is shown in the example.,operatorjson_pointer} - - @since version 2.0.0 - */ - reference operator[](const json_pointer& ptr) - { - return ptr.get_unchecked(this); - } - - /*! - @brief access specified element via JSON Pointer - - Uses a JSON pointer to retrieve a reference to the respective JSON value. - No bound checking is performed. The function does not change the JSON - value; no `null` values are created. In particular, the the special value - `-` yields an exception. - - @param[in] ptr JSON pointer to the desired element - - @return const reference to the element pointed to by @a ptr - - @complexity Constant. - - @throw parse_error.106 if an array index begins with '0' - @throw parse_error.109 if an array index was not a number - @throw out_of_range.402 if the array index '-' is used - @throw out_of_range.404 if the JSON pointer can not be resolved - - @liveexample{The behavior is shown in the example.,operatorjson_pointer_const} - - @since version 2.0.0 - */ - const_reference operator[](const json_pointer& ptr) const - { - return ptr.get_unchecked(this); - } - - /*! - @brief access specified element via JSON Pointer - - Returns a reference to the element at with specified JSON pointer @a ptr, - with bounds checking. - - @param[in] ptr JSON pointer to the desired element - - @return reference to the element pointed to by @a ptr - - @throw parse_error.106 if an array index in the passed JSON pointer @a ptr - begins with '0'. See example below. - - @throw parse_error.109 if an array index in the passed JSON pointer @a ptr - is not a number. See example below. - - @throw out_of_range.401 if an array index in the passed JSON pointer @a ptr - is out of range. See example below. - - @throw out_of_range.402 if the array index '-' is used in the passed JSON - pointer @a ptr. As `at` provides checked access (and no elements are - implicitly inserted), the index '-' is always invalid. See example below. - - @throw out_of_range.404 if the JSON pointer @a ptr can not be resolved. - See example below. - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes in the JSON value. - - @complexity Constant. - - @since version 2.0.0 - - @liveexample{The behavior is shown in the example.,at_json_pointer} - */ - reference at(const json_pointer& ptr) - { - return ptr.get_checked(this); - } - - /*! - @brief access specified element via JSON Pointer - - Returns a const reference to the element at with specified JSON pointer @a - ptr, with bounds checking. - - @param[in] ptr JSON pointer to the desired element - - @return reference to the element pointed to by @a ptr - - @throw parse_error.106 if an array index in the passed JSON pointer @a ptr - begins with '0'. See example below. - - @throw parse_error.109 if an array index in the passed JSON pointer @a ptr - is not a number. See example below. - - @throw out_of_range.401 if an array index in the passed JSON pointer @a ptr - is out of range. See example below. - - @throw out_of_range.402 if the array index '-' is used in the passed JSON - pointer @a ptr. As `at` provides checked access (and no elements are - implicitly inserted), the index '-' is always invalid. See example below. - - @throw out_of_range.404 if the JSON pointer @a ptr can not be resolved. - See example below. - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes in the JSON value. - - @complexity Constant. - - @since version 2.0.0 - - @liveexample{The behavior is shown in the example.,at_json_pointer_const} - */ - const_reference at(const json_pointer& ptr) const - { - return ptr.get_checked(this); - } - - /*! - @brief return flattened JSON value - - The function creates a JSON object whose keys are JSON pointers (see [RFC - 6901](https://tools.ietf.org/html/rfc6901)) and whose values are all - primitive. The original JSON value can be restored using the @ref - unflatten() function. - - @return an object that maps JSON pointers to primitive values - - @note Empty objects and arrays are flattened to `null` and will not be - reconstructed correctly by the @ref unflatten() function. - - @complexity Linear in the size the JSON value. - - @liveexample{The following code shows how a JSON object is flattened to an - object whose keys consist of JSON pointers.,flatten} - - @sa @ref unflatten() for the reverse function - - @since version 2.0.0 - */ - basic_json flatten() const - { - basic_json result(value_t::object); - json_pointer::flatten("", *this, result); - return result; - } - - /*! - @brief unflatten a previously flattened JSON value - - The function restores the arbitrary nesting of a JSON value that has been - flattened before using the @ref flatten() function. The JSON value must - meet certain constraints: - 1. The value must be an object. - 2. The keys must be JSON pointers (see - [RFC 6901](https://tools.ietf.org/html/rfc6901)) - 3. The mapped values must be primitive JSON types. - - @return the original JSON from a flattened version - - @note Empty objects and arrays are flattened by @ref flatten() to `null` - values and can not unflattened to their original type. Apart from - this example, for a JSON value `j`, the following is always true: - `j == j.flatten().unflatten()`. - - @complexity Linear in the size the JSON value. - - @throw type_error.314 if value is not an object - @throw type_error.315 if object values are not primitve - - @liveexample{The following code shows how a flattened JSON object is - unflattened into the original nested JSON object.,unflatten} - - @sa @ref flatten() for the reverse function - - @since version 2.0.0 - */ - basic_json unflatten() const - { - return json_pointer::unflatten(*this); - } - - /// @} - - ////////////////////////// - // JSON Patch functions // - ////////////////////////// - - /// @name JSON Patch functions - /// @{ - - /*! - @brief applies a JSON patch - - [JSON Patch](http://jsonpatch.com) defines a JSON document structure for - expressing a sequence of operations to apply to a JSON) document. With - this function, a JSON Patch is applied to the current JSON value by - executing all operations from the patch. - - @param[in] json_patch JSON patch document - @return patched document - - @note The application of a patch is atomic: Either all operations succeed - and the patched document is returned or an exception is thrown. In - any case, the original value is not changed: the patch is applied - to a copy of the value. - - @throw parse_error.104 if the JSON patch does not consist of an array of - objects - - @throw parse_error.105 if the JSON patch is malformed (e.g., mandatory - attributes are missing); example: `"operation add must have member path"` - - @throw out_of_range.401 if an array index is out of range. - - @throw out_of_range.403 if a JSON pointer inside the patch could not be - resolved successfully in the current JSON value; example: `"key baz not - found"` - - @throw out_of_range.405 if JSON pointer has no parent ("add", "remove", - "move") - - @throw other_error.501 if "test" operation was unsuccessful - - @complexity Linear in the size of the JSON value and the length of the - JSON patch. As usually only a fraction of the JSON value is affected by - the patch, the complexity can usually be neglected. - - @liveexample{The following code shows how a JSON patch is applied to a - value.,patch} - - @sa @ref diff -- create a JSON patch by comparing two JSON values - - @sa [RFC 6902 (JSON Patch)](https://tools.ietf.org/html/rfc6902) - @sa [RFC 6901 (JSON Pointer)](https://tools.ietf.org/html/rfc6901) - - @since version 2.0.0 - */ - basic_json patch(const basic_json& json_patch) const - { - // make a working copy to apply the patch to - basic_json result = *this; - - // the valid JSON Patch operations - enum class patch_operations {add, remove, replace, move, copy, test, invalid}; - - const auto get_op = [](const std::string & op) - { - if (op == "add") - { - return patch_operations::add; - } - if (op == "remove") - { - return patch_operations::remove; - } - if (op == "replace") - { - return patch_operations::replace; - } - if (op == "move") - { - return patch_operations::move; - } - if (op == "copy") - { - return patch_operations::copy; - } - if (op == "test") - { - return patch_operations::test; - } - - return patch_operations::invalid; - }; - - // wrapper for "add" operation; add value at ptr - const auto operation_add = [&result](json_pointer & ptr, basic_json val) - { - // adding to the root of the target document means replacing it - if (ptr.is_root()) - { - result = val; - } - else - { - // make sure the top element of the pointer exists - json_pointer top_pointer = ptr.top(); - if (top_pointer != ptr) - { - result.at(top_pointer); - } - - // get reference to parent of JSON pointer ptr - const auto last_path = ptr.pop_back(); - basic_json& parent = result[ptr]; - - switch (parent.m_type) - { - case value_t::null: - case value_t::object: - { - // use operator[] to add value - parent[last_path] = val; - break; - } - - case value_t::array: - { - if (last_path == "-") - { - // special case: append to back - parent.push_back(val); - } - else - { - const auto idx = std::stoi(last_path); - if (static_cast(idx) > parent.size()) - { - // avoid undefined behavior - JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range")); - } - else - { - // default case: insert add offset - parent.insert(parent.begin() + static_cast(idx), val); - } - } - break; - } - - default: - { - // if there exists a parent it cannot be primitive - assert(false); // LCOV_EXCL_LINE - } - } - } - }; - - // wrapper for "remove" operation; remove value at ptr - const auto operation_remove = [&result](json_pointer & ptr) - { - // get reference to parent of JSON pointer ptr - const auto last_path = ptr.pop_back(); - basic_json& parent = result.at(ptr); - - // remove child - if (parent.is_object()) - { - // perform range check - auto it = parent.find(last_path); - if (it != parent.end()) - { - parent.erase(it); - } - else - { - JSON_THROW(out_of_range::create(403, "key '" + last_path + "' not found")); - } - } - else if (parent.is_array()) - { - // note erase performs range check - parent.erase(static_cast(std::stoi(last_path))); - } - }; - - // type check: top level value must be an array - if (not json_patch.is_array()) - { - JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects")); - } - - // iterate and apply the operations - for (const auto& val : json_patch) - { - // wrapper to get a value for an operation - const auto get_value = [&val](const std::string & op, - const std::string & member, - bool string_type) -> basic_json& - { - // find value - auto it = val.m_value.object->find(member); - - // context-sensitive error message - const auto error_msg = (op == "op") ? "operation" : "operation '" + op + "'"; - - // check if desired value is present - if (it == val.m_value.object->end()) - { - JSON_THROW(parse_error::create(105, 0, error_msg + " must have member '" + member + "'")); - } - - // check if result is of type string - if (string_type and not it->second.is_string()) - { - JSON_THROW(parse_error::create(105, 0, error_msg + " must have string member '" + member + "'")); - } - - // no error: return value - return it->second; - }; - - // type check: every element of the array must be an object - if (not val.is_object()) - { - JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects")); - } - - // collect mandatory members - const std::string op = get_value("op", "op", true); - const std::string path = get_value(op, "path", true); - json_pointer ptr(path); - - switch (get_op(op)) - { - case patch_operations::add: - { - operation_add(ptr, get_value("add", "value", false)); - break; - } - - case patch_operations::remove: - { - operation_remove(ptr); - break; - } - - case patch_operations::replace: - { - // the "path" location must exist - use at() - result.at(ptr) = get_value("replace", "value", false); - break; - } - - case patch_operations::move: - { - const std::string from_path = get_value("move", "from", true); - json_pointer from_ptr(from_path); - - // the "from" location must exist - use at() - basic_json v = result.at(from_ptr); - - // The move operation is functionally identical to a - // "remove" operation on the "from" location, followed - // immediately by an "add" operation at the target - // location with the value that was just removed. - operation_remove(from_ptr); - operation_add(ptr, v); - break; - } - - case patch_operations::copy: - { - const std::string from_path = get_value("copy", "from", true);; - const json_pointer from_ptr(from_path); - - // the "from" location must exist - use at() - result[ptr] = result.at(from_ptr); - break; - } - - case patch_operations::test: - { - bool success = false; - JSON_TRY - { - // check if "value" matches the one at "path" - // the "path" location must exist - use at() - success = (result.at(ptr) == get_value("test", "value", false)); - } - JSON_CATCH (out_of_range&) - { - // ignore out of range errors: success remains false - } - - // throw an exception if test fails - if (not success) - { - JSON_THROW(other_error::create(501, "unsuccessful: " + val.dump())); - } - - break; - } - - case patch_operations::invalid: - { - // op must be "add", "remove", "replace", "move", "copy", or - // "test" - JSON_THROW(parse_error::create(105, 0, "operation value '" + op + "' is invalid")); - } - } - } - - return result; - } - - /*! - @brief creates a diff as a JSON patch - - Creates a [JSON Patch](http://jsonpatch.com) so that value @a source can - be changed into the value @a target by calling @ref patch function. - - @invariant For two JSON values @a source and @a target, the following code - yields always `true`: - @code {.cpp} - source.patch(diff(source, target)) == target; - @endcode - - @note Currently, only `remove`, `add`, and `replace` operations are - generated. - - @param[in] source JSON value to compare from - @param[in] target JSON value to compare against - @param[in] path helper value to create JSON pointers - - @return a JSON patch to convert the @a source to @a target - - @complexity Linear in the lengths of @a source and @a target. - - @liveexample{The following code shows how a JSON patch is created as a - diff for two JSON values.,diff} - - @sa @ref patch -- apply a JSON patch - - @sa [RFC 6902 (JSON Patch)](https://tools.ietf.org/html/rfc6902) - - @since version 2.0.0 - */ - static basic_json diff(const basic_json& source, - const basic_json& target, - const std::string& path = "") - { - // the patch - basic_json result(value_t::array); - - // if the values are the same, return empty patch - if (source == target) - { - return result; - } - - if (source.type() != target.type()) - { - // different types: replace value - result.push_back( - { - {"op", "replace"}, - {"path", path}, - {"value", target} - }); - } - else - { - switch (source.type()) - { - case value_t::array: - { - // first pass: traverse common elements - size_t i = 0; - while (i < source.size() and i < target.size()) - { - // recursive call to compare array values at index i - auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i)); - result.insert(result.end(), temp_diff.begin(), temp_diff.end()); - ++i; - } - - // i now reached the end of at least one array - // in a second pass, traverse the remaining elements - - // remove my remaining elements - const auto end_index = static_cast(result.size()); - while (i < source.size()) - { - // add operations in reverse order to avoid invalid - // indices - result.insert(result.begin() + end_index, object( - { - {"op", "remove"}, - {"path", path + "/" + std::to_string(i)} - })); - ++i; - } - - // add other remaining elements - while (i < target.size()) - { - result.push_back( - { - {"op", "add"}, - {"path", path + "/" + std::to_string(i)}, - {"value", target[i]} - }); - ++i; - } - - break; - } - - case value_t::object: - { - // first pass: traverse this object's elements - for (auto it = source.begin(); it != source.end(); ++it) - { - // escape the key name to be used in a JSON patch - const auto key = json_pointer::escape(it.key()); - - if (target.find(it.key()) != target.end()) - { - // recursive call to compare object values at key it - auto temp_diff = diff(it.value(), target[it.key()], path + "/" + key); - result.insert(result.end(), temp_diff.begin(), temp_diff.end()); - } - else - { - // found a key that is not in o -> remove it - result.push_back(object( - { - {"op", "remove"}, - {"path", path + "/" + key} - })); - } - } - - // second pass: traverse other object's elements - for (auto it = target.begin(); it != target.end(); ++it) - { - if (source.find(it.key()) == source.end()) - { - // found a key that is not in this -> add it - const auto key = json_pointer::escape(it.key()); - result.push_back( - { - {"op", "add"}, - {"path", path + "/" + key}, - {"value", it.value()} - }); - } - } - - break; - } - - default: - { - // both primitive type: replace value - result.push_back( - { - {"op", "replace"}, - {"path", path}, - {"value", target} - }); - break; - } - } - } - - return result; - } - - /// @} -}; - -///////////// -// presets // -///////////// - -/*! -@brief default JSON class - -This type is the default specialization of the @ref basic_json class which -uses the standard template types. - -@since version 1.0.0 -*/ -using json = basic_json<>; -} // namespace nlohmann - - -/////////////////////// -// nonmember support // -/////////////////////// - -// specialization of std::swap, and std::hash -namespace std -{ -/*! -@brief exchanges the values of two JSON objects - -@since version 1.0.0 -*/ -template<> -inline void swap(nlohmann::json& j1, - nlohmann::json& j2) noexcept( - is_nothrow_move_constructible::value and - is_nothrow_move_assignable::value - ) -{ - j1.swap(j2); -} - -/// hash value for JSON objects -template<> -struct hash -{ - /*! - @brief return a hash value for a JSON object - - @since version 1.0.0 - */ - std::size_t operator()(const nlohmann::json& j) const - { - // a naive hashing via the string representation - const auto& h = hash(); - return h(j.dump()); - } -}; - -/// specialization for std::less -template <> -struct less<::nlohmann::detail::value_t> -{ - /*! - @brief compare two value_t enum values - @since version 3.0.0 - */ - bool operator()(nlohmann::detail::value_t lhs, - nlohmann::detail::value_t rhs) const noexcept - { - return nlohmann::detail::operator<(lhs, rhs); - } -}; - -} // namespace std - -/*! -@brief user-defined string literal for JSON values - -This operator implements a user-defined string literal for JSON objects. It -can be used by adding `"_json"` to a string literal and returns a JSON object -if no parse error occurred. - -@param[in] s a string representation of a JSON object -@param[in] n the length of string @a s -@return a JSON object - -@since version 1.0.0 -*/ -inline nlohmann::json operator "" _json(const char* s, std::size_t n) -{ - return nlohmann::json::parse(s, s + n); -} - -/*! -@brief user-defined string literal for JSON pointer - -This operator implements a user-defined string literal for JSON Pointers. It -can be used by adding `"_json_pointer"` to a string literal and returns a JSON pointer -object if no parse error occurred. - -@param[in] s a string representation of a JSON Pointer -@param[in] n the length of string @a s -@return a JSON pointer object - -@since version 2.0.0 -*/ -inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n) -{ - return nlohmann::json::json_pointer(std::string(s, n)); -} - -// restore GCC/clang diagnostic settings -#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) - #pragma GCC diagnostic pop -#endif -#if defined(__clang__) - #pragma GCC diagnostic pop -#endif - -// clean up -#undef JSON_CATCH -#undef JSON_THROW -#undef JSON_TRY -#undef JSON_DEPRECATED - -#endif diff --git a/vendor/libuv/.gitignore b/vendor/libuv/.gitignore deleted file mode 100644 index eb54f9248..000000000 --- a/vendor/libuv/.gitignore +++ /dev/null @@ -1,78 +0,0 @@ -*.swp -*.[oa] -*.l[oa] -*.opensdf -*.orig -*.pyc -*.sdf -*.suo -.vs/ -*.VC.db -*.VC.opendb -core -vgcore.* -.buildstamp -.dirstamp -.deps/ -/.libs/ -/aclocal.m4 -/ar-lib -/autom4te.cache/ -/compile -/config.guess -/config.log -/config.status -/config.sub -/configure -/depcomp -/install-sh -/libtool -/libuv.a -/libuv.dylib -/libuv.pc -/libuv.so -/ltmain.sh -/missing -/test-driver -Makefile -Makefile.in - -# Generated by gyp for android -*.target.mk - -/out/ -/build/gyp - -/test/.libs/ -/test/run-tests -/test/run-tests.exe -/test/run-tests.dSYM -/test/run-benchmarks -/test/run-benchmarks.exe -/test/run-benchmarks.dSYM - -*.sln -*.sln.cache -*.ncb -*.vcproj -*.vcproj*.user -*.vcxproj -*.vcxproj.filters -*.vcxproj.user -_UpgradeReport_Files/ -UpgradeLog*.XML -Debug -Release -ipch - -# sphinx generated files -/docs/build/ - -# Clion / IntelliJ project files -/.idea/ - -*.xcodeproj -*.xcworkspace - -# make dist output -libuv-*.tar.* diff --git a/vendor/libuv/.mailmap b/vendor/libuv/.mailmap deleted file mode 100644 index 8acf8fecd..000000000 --- a/vendor/libuv/.mailmap +++ /dev/null @@ -1,41 +0,0 @@ -Aaron Bieber -Alan Gutierrez -Andrius Bentkus -Bert Belder -Bert Belder -Bert Belder -Brandon Philips -Brian White -Brian White -Caleb James DeLisle -Christoph Iserlohn -Devchandra Meetei Leishangthem -Fedor Indutny -Frank Denis -Imran Iqbal -Isaac Z. Schlueter -Jason Williams -Justin Venus -Keno Fischer -Keno Fischer -Leith Bade -Leonard Hecker -Maciej Małecki -Marc Schlaich -Michael -Michael Neumann -Nicholas Vavilov -Rasmus Christian Pedersen -Rasmus Christian Pedersen -Robert Mustacchi -Ryan Dahl -Ryan Emery -Sam Roberts -San-Tai Hsu -Santiago Gimeno -Saúl Ibarra Corretgé -Shigeki Ohtsu -Timothy J. Fontaine -Yasuhiro Matsumoto -Yazhong Liu -Yuki Okumura diff --git a/vendor/libuv/AUTHORS b/vendor/libuv/AUTHORS deleted file mode 100644 index 4719d2368..000000000 --- a/vendor/libuv/AUTHORS +++ /dev/null @@ -1,286 +0,0 @@ -# Authors ordered by first contribution. -Ryan Dahl -Bert Belder -Josh Roesslein -Alan Gutierrez -Joshua Peek -Igor Zinkovsky -San-Tai Hsu -Ben Noordhuis -Henry Rawas -Robert Mustacchi -Matt Stevens -Paul Querna -Shigeki Ohtsu -Tom Hughes -Peter Bright -Jeroen Janssen -Andrea Lattuada -Augusto Henrique Hentz -Clifford Heath -Jorge Chamorro Bieling -Luis Lavena -Matthew Sporleder -Erick Tryzelaar -Isaac Z. Schlueter -Pieter Noordhuis -Marek Jelen -Fedor Indutny -Saúl Ibarra Corretgé -Felix Geisendörfer -Yuki Okumura -Roman Shtylman -Frank Denis -Carter Allen -Tj Holowaychuk -Shimon Doodkin -Ryan Emery -Bruce Mitchener -Maciej Małecki -Yasuhiro Matsumoto -Daisuke Murase -Paddy Byers -Dan VerWeire -Brandon Benvie -Brandon Philips -Nathan Rajlich -Charlie McConnell -Vladimir Dronnikov -Aaron Bieber -Bulat Shakirzyanov -Brian White -Erik Dubbelboer -Keno Fischer -Ira Cooper -Andrius Bentkus -Iñaki Baz Castillo -Mark Cavage -George Yohng -Xidorn Quan -Roman Neuhauser -Shuhei Tanuma -Bryan Cantrill -Trond Norbye -Tim Holy -Prancesco Pertugio -Leonard Hecker -Andrew Paprocki -Luigi Grilli -Shannen Saez -Artur Adib -Hiroaki Nakamura -Ting-Yu Lin -Stephen Gallagher -Shane Holloway -Andrew Shaffer -Vlad Tudose -Ben Leslie -Tim Bradshaw -Timothy J. Fontaine -Marc Schlaich -Brian Mazza -Elliot Saba -Ben Kelly -Nils Maier -Nicholas Vavilov -Miroslav Bajtoš -Sean Silva -Wynn Wilkes -Andrei Sedoi -Alex Crichton -Brent Cook -Brian Kaisner -Luca Bruno -Reini Urban -Maks Naumov -Sean Farrell -Chris Bank -Geert Jansen -Christoph Iserlohn -Steven Kabbes -Alex Gaynor -huxingyi -Tenor Biel -Andrej Manduch -Joshua Neuheisel -Alexis Campailla -Yazhong Liu -Sam Roberts -River Tarnell -Nathan Sweet -Trevor Norris -Oguz Bastemur -Dylan Cali -Austin Foxley -Benjamin Saunders -Geoffry Song -Rasmus Christian Pedersen -William Light -Oleg Efimov -Lars Gierth -Rasmus Christian Pedersen -Justin Venus -Kristian Evensen -Linus Mårtensson -Navaneeth Kedaram Nambiathan -Yorkie -StarWing -thierry-FreeBSD -Isaiah Norton -Raul Martins -David Capello -Paul Tan -Javier Hernández -Tonis Tiigi -Norio Kobota -李港平 -Chernyshev Viacheslav -Stephen von Takach -JD Ballard -Luka Perkov -Ryan Cole -HungMingWu -Jay Satiro -Leith Bade -Peter Atashian -Tim Cooper -Caleb James DeLisle -Jameson Nash -Graham Lee -Andrew Low -Pavel Platto -Tony Kelman -John Firebaugh -lilohuang -Paul Goldsmith -Julien Gilli -Michael Hudson-Doyle -Recep ASLANTAS -Rob Adams -Zachary Newman -Robin Hahling -Jeff Widman -cjihrig -Tomasz Kołodziejski -Unknown W. Brackets -Emmanuel Odeke -Mikhail Mukovnikov -Thorsten Lorenz -Yuri D'Elia -Manos Nikolaidis -Elijah Andrews -Michael Ira Krufky -Helge Deller -Joey Geralnik -Tim Caswell -Logan Rosen -Kenneth Perry -John Marino -Alexey Melnichuk -Johan Bergström -Alex Mo -Luis Martinez de Bartolome -Michael Penick -Michael -Massimiliano Torromeo -TomCrypto -Brett Vickers -Ole André Vadla Ravnås -Kazuho Oku -Ryan Phillips -Brian Green -Devchandra Meetei Leishangthem -Corey Farrell -Per Nilsson -Alan Rogers -Daryl Haresign -Rui Abreu Ferreira -João Reis -farblue68 -Jason Williams -Igor Soarez -Miodrag Milanovic -Cheng Zhao -Michael Neumann -Stefano Cristiano -heshamsafi -A. Hauptmann -John McNamee -Yosuke Furukawa -Santiago Gimeno -guworks -RossBencina -Roger A. Light -chenttuuvv -Richard Lau -ronkorving -Corbin Simpson -Zachary Hamm -Karl Skomski -Jeremy Whitlock -Willem Thiart -Ben Trask -Jianghua Yang -Colin Snover -Sakthipriyan Vairamani -Eli Skeggs -nmushell -Gireesh Punathil -Ryan Johnston -Adam Stylinski -Nathan Corvino -Wink Saville -Angel Leon -Louis DeJardin -Imran Iqbal -Petka Antonov -Ian Kronquist -kkdaemon -Yuval Brik -Joran Dirk Greef -Andrey Mazo -sztomi -Martin Bark -Dave -Alexis Murzeau -Didiet -Nan Xiang <514580344@qq.com> -Samuel Lorétan -Nándor István Krácser -Katsutoshi Horie -Lukasz Jagiello -Robert Chiras -Kári Tristan Helgason -Krishnaraj Bhat -Enno Boland -Michael Fero -Robert Jefe Lindstaedt -Myles Borins -Tony Theodore -Jason Ginchereau -Nicolas Cavallari -Pierre-Marie de Rodat -Brian Maher -neevek -John Barboza -liuxiaobo -Michele Caini -Bartosz Sosnowski -Matej Knopp -sunjin.lee -Matt Clarkson -Jeffrey Clark -Bart Robinson -Vit Gottwald -Vladimír Čunát -Alex Hultman -Brad King -Philippe Laferriere -Will Speak -Hitesh Kanwathirtha -Eric Sciple -jBarz -muflub -Daniel Bevenius -Howard Hellyer -Chris Araman diff --git a/vendor/libuv/CMakeLists.txt b/vendor/libuv/CMakeLists.txt deleted file mode 100644 index 416a29118..000000000 --- a/vendor/libuv/CMakeLists.txt +++ /dev/null @@ -1,248 +0,0 @@ -# CMake module to build libuv FOR LiubSourcey. -# Based heavily off of libuv's Makefile.am, but using CMake paradigms. -# Works with libuv 1.11.1 dev - -# Create configuration containers -set(libuv_FLAGS) # Compiler flags -set(libuv_DEFINITIONS) # Compiler definitions -set(libuv_INCLUDE_DIRS) # Include directories -set(libuv_SOURCE_FILES) # Source files -set(libuv_HEADER_FILES) # Headers to install -set(libuv_DEPENDENCIES) # Library dependencies - -# Utility function which will only add compiler flags if supported -include(CheckCCompilerFlag) -function(add_flag_if_supported container flag) - CHECK_C_COMPILER_FLAG(${flag} _flag_supported) - if(_flag_supported) - # NOTE: Can't use list(APPEND...) here because it doesn't support - # PARENT_SCOPE: - # http://stackoverflow.com/a/10032337 - set(${container} ${${container}} ${flag} PARENT_SCOPE) - endif() -endfunction() - -# Common configuration -if(BUILD_SHARED_LIBS) - list(APPEND libuv_DEFINITIONS BUILDING_UV_SHARED) -endif() -list(APPEND libuv_INCLUDE_DIRS include src) -list(APPEND libuv_SOURCE_FILES - src/fs-poll.c - src/inet.c - src/queue.h - src/threadpool.c - src/uv-common.c - src/uv-common.h - src/version.c -) - -list(APPEND libuv_HEADER_FILES - include/uv.h - include/uv-errno.h - include/uv-threadpool.h - include/uv-version.h -) - -# Handle system-specific flags/sources -if(CMAKE_SYSTEM_NAME STREQUAL "Windows") - list(APPEND libuv_DEFINITIONS - WIN32_LEAN_AND_MEAN - _WIN32_WINNT=0x0600 - ) - list(APPEND libuv_INCLUDE_DIRS - src/win - ) - list(APPEND libuv_SOURCE_FILES - src/win/async.c - src/win/atomicops-inl.h - src/win/core.c - src/win/detect-wakeup.c - src/win/dl.c - src/win/error.c - src/win/fs-event.c - src/win/fs.c - src/win/getaddrinfo.c - src/win/getnameinfo.c - src/win/handle.c - src/win/handle-inl.h - src/win/internal.h - src/win/loop-watcher.c - src/win/pipe.c - src/win/poll.c - src/win/process-stdio.c - src/win/process.c - src/win/req.c - src/win/req-inl.h - src/win/signal.c - src/win/stream.c - src/win/stream-inl.h - src/win/tcp.c - src/win/thread.c - src/win/timer.c - src/win/tty.c - src/win/udp.c - src/win/util.c - src/win/winapi.c - src/win/winapi.h - src/win/winsock.c - src/win/winsock.h - ) - list(APPEND libuv_DEPENDENCIES - ws2_32 - psapi - iphlpapi - shell32 - userenv - ) - list(APPEND libuv_HEADER_FILES - include/uv-win.h - include/tree.h - ) - if((MSVC AND MSVC_VERSION VERSION_LESS 1600) OR MINGW) - list(APPEND libuv_HEADER_FILES - include/stdint-msvc2008.h - ) - endif() - -else() # Non-Windows - - # These flags are geared to match the libuv autotools flags, but -g is - # excluded since it is better-controlled by CMAKE_BUILD_TYPE - add_flag_if_supported(libuv_FLAGS -fvisibility=hidden) - add_flag_if_supported(libuv_FLAGS -pedantic) - add_flag_if_supported(libuv_FLAGS -Wall) - add_flag_if_supported(libuv_FLAGS -Wextra) - add_flag_if_supported(libuv_FLAGS -Wno-unused-parameter) - if(NOT CMAKE_COMPILER_IS_GNUCC) - add_flag_if_supported(libuv_FLAGS -std=gnu89) - endif() - list(APPEND libuv_DEFINITIONS - _LARGEFILE_SOURCE - _FILE_OFFSET_BITS=64 - ) - list(APPEND libuv_INCLUDE_DIRS - src/unix - ) - list(APPEND libuv_SOURCE_FILES - src/unix/async.c - src/unix/atomic-ops.h - src/unix/core.c - src/unix/dl.c - src/unix/fs.c - src/unix/getaddrinfo.c - src/unix/getnameinfo.c - src/unix/internal.h - src/unix/loop-watcher.c - src/unix/loop.c - src/unix/pipe.c - src/unix/poll.c - src/unix/process.c - src/unix/signal.c - src/unix/spinlock.h - src/unix/stream.c - src/unix/tcp.c - src/unix/thread.c - src/unix/timer.c - src/unix/tty.c - src/unix/udp.c - ) - - find_package(Threads REQUIRED) - list(APPEND libuv_DEPENDENCIES ${CMAKE_THREAD_LIBS_INIT} dl) - list(APPEND libuv_HEADER_FILES - include/uv-unix.h - ) - if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") - list(APPEND libuv_DEFINITIONS - _DARWIN_USE_64_BIT_INODE=1 - _DARWIN_UNLIMITED_SELECT=1 - ) - list(APPEND libuv_SOURCE_FILES - src/unix/darwin.c - src/unix/darwin-proctitle.c - src/unix/fsevents.c - src/unix/kqueue.c - src/unix/proctitle.c - src/unix/pthread-barrier.c - ) - list(APPEND libuv_HEADER_FILES - include/uv-darwin.h - include/pthread-barrier.h - ) - elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux") - list(APPEND libuv_DEFINITIONS - _GNU_SOURCE - ) - list(APPEND libuv_SOURCE_FILES - src/unix/linux-core.c - src/unix/linux-inotify.c - src/unix/linux-syscalls.c - src/unix/proctitle.c - ) - list(APPEND libuv_HEADER_FILES - include/uv-linux.h - ) - elseif(CMAKE_SYSTEM_NAME STREQUAL "DragonFly") - list(APPEND libuv_HEADER_FILES - include/uv-bsd.h - ) - elseif(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD") - list(APPEND libuv_SOURCE_FILES - src/unix/kqueue.c - src/unix/freebsd.c - ) - list(APPEND libuv_HEADER_FILES - include/uv-bsd.h - ) - elseif(CMAKE_SYSTEM_NAME STREQUAL "NetBSD") - list(APPEND libuv_SOURCE_FILES - src/unix/kqueue.c - src/unix/netbsd.c - ) - list(APPEND libuv_HEADER_FILES - include/uv-bsd.h - ) - elseif(CMAKE_SYSTEM_NAME STREQUAL "OpenBSD") - list(APPEND libuv_SOURCE_FILES - src/unix/kqueue.c - src/unix/openbsd.c - ) - list(APPEND libuv_HEADER_FILES - include/uv-bsd.h - ) - elseif(CMAKE_SYSTEM_NAME STREQUAL "AIX") - list(APPEND libuv_DEFINITIONS - _ALL_SOURCE - _XOPEN_SOURCE=500 - _LINUX_SOURCE_COMPAT - ) - list(APPEND libuv_SOURCE_FILES - src/unix/aix.c - ) - elseif(CMAKE_SYSTEM_NAME STREQUAL "SunOS") - add_flag_if_supported(libuv_FLAGS -pthread) - list(APPEND libuv_DEFINITIONS - __EXTENSIONS__ - _XOPEN_SOURCE=500 - ) - list(APPEND libuv_SOURCE_FILES - src/unix/sunos.c - ) - list(APPEND libuv_HEADER_FILES - include/uv-sunos.h - ) - elseif(DEFINED ANDROID_NDK) - list(APPEND libuv_SOURCE_FILES - src/unix/android-ifaddrs.c - src/unix/pthread-fixes.c - src/unix/pthread-barrier.c - ) - list(APPEND libuv_HEADER_FILES - include/android-ifaddrs.h - include/pthread-fixes.h - ) - endif() -endif() - -define_sourcey_dependency(libuv) diff --git a/vendor/libuv/CONTRIBUTING.md b/vendor/libuv/CONTRIBUTING.md deleted file mode 100644 index aa97506db..000000000 --- a/vendor/libuv/CONTRIBUTING.md +++ /dev/null @@ -1,169 +0,0 @@ -# CONTRIBUTING - -The libuv project welcomes new contributors. This document will guide you -through the process. - - -### FORK - -Fork the project [on GitHub](https://github.com/libuv/libuv) and check out -your copy. - -``` -$ git clone https://github.com/username/libuv.git -$ cd libuv -$ git remote add upstream https://github.com/libuv/libuv.git -``` - -Now decide if you want your feature or bug fix to go into the master branch -or the stable branch. As a rule of thumb, bug fixes go into the stable branch -while new features go into the master branch. - -The stable branch is effectively frozen; patches that change the libuv -API/ABI or affect the run-time behavior of applications get rejected. - -In case of doubt, open an issue in the [issue tracker][], post your question -to the [libuv mailing list], or contact one of [project maintainers][] on [IRC][]. - -Especially do so if you plan to work on something big. Nothing is more -frustrating than seeing your hard work go to waste because your vision -does not align with that of a project maintainers. - - -### BRANCH - -Okay, so you have decided on the proper branch. Create a feature branch -and start hacking: - -``` -$ git checkout -b my-feature-branch -t origin/v1.x -``` - -(Where v1.x is the latest stable branch as of this writing.) - -### CODE - -Please adhere to libuv's code style. In general it follows the conventions from -the [Google C/C++ style guide]. Some of the key points, as well as some -additional guidelines, are enumerated below. - -* Code that is specific to unix-y platforms should be placed in `src/unix`, and - declarations go into `include/uv-unix.h`. - -* Source code that is Windows-specific goes into `src/win`, and related - publicly exported types, functions and macro declarations should generally - be declared in `include/uv-win.h`. - -* Names should be descriptive and concise. - -* All the symbols and types that libuv makes available publicly should be - prefixed with `uv_` (or `UV_` in case of macros). - -* Internal, non-static functions should be prefixed with `uv__`. - -* Use two spaces and no tabs. - -* Lines should be wrapped at 80 characters. - -* Ensure that lines have no trailing whitespace, and use unix-style (LF) line - endings. - -* Use C89-compliant syntax. In other words, variables can only be declared at - the top of a scope (function, if/for/while-block). - -* When writing comments, use properly constructed sentences, including - punctuation. - -* When documenting APIs and/or source code, don't make assumptions or make - implications about race, gender, religion, political orientation or anything - else that isn't relevant to the project. - -* Remember that source code usually gets written once and read often: ensure - the reader doesn't have to make guesses. Make sure that the purpose and inner - logic are either obvious to a reasonably skilled professional, or add a - comment that explains it. - - -### COMMIT - -Make sure git knows your name and email address: - -``` -$ git config --global user.name "J. Random User" -$ git config --global user.email "j.random.user@example.com" -``` - -Writing good commit logs is important. A commit log should describe what -changed and why. Follow these guidelines when writing one: - -1. The first line should be 50 characters or less and contain a short - description of the change prefixed with the name of the changed - subsystem (e.g. "net: add localAddress and localPort to Socket"). -2. Keep the second line blank. -3. Wrap all other lines at 72 columns. - -A good commit log looks like this: - -``` -subsystem: explaining the commit in one line - -Body of commit message is a few lines of text, explaining things -in more detail, possibly giving some background about the issue -being fixed, etc etc. - -The body of the commit message can be several paragraphs, and -please do proper word-wrap and keep columns shorter than about -72 characters or so. That way `git log` will show things -nicely even when it is indented. -``` - -The header line should be meaningful; it is what other people see when they -run `git shortlog` or `git log --oneline`. - -Check the output of `git log --oneline files_that_you_changed` to find out -what subsystem (or subsystems) your changes touch. - - -### REBASE - -Use `git rebase` (not `git merge`) to sync your work from time to time. - -``` -$ git fetch upstream -$ git rebase upstream/v1.x # or upstream/master -``` - - -### TEST - -Bug fixes and features should come with tests. Add your tests in the -`test/` directory. Each new test needs to be registered in `test/test-list.h`. If you add a new test file, it needs to be registered in two places: -- `Makefile.am`: add the file's name to the `test_run_tests_SOURCES` list. -- `uv.gyp`: add the file's name to the `sources` list in the `run-tests` target. - -Look at other tests to see how they should be structured (license boilerplate, -the way entry points are declared, etc.). - -Check README.md file to find out how to run the test suite and make sure that -there are no test regressions. - -### PUSH - -``` -$ git push origin my-feature-branch -``` - -Go to https://github.com/username/libuv and select your feature branch. Click -the 'Pull Request' button and fill out the form. - -Pull requests are usually reviewed within a few days. If there are comments -to address, apply your changes in a separate commit and push that to your -feature branch. Post a comment in the pull request afterwards; GitHub does -not send out notifications when you add commits. - - -[issue tracker]: https://github.com/libuv/libuv/issues -[libuv mailing list]: http://groups.google.com/group/libuv -[IRC]: http://webchat.freelibuv.net/?channels=libuv -[Google C/C++ style guide]: https://google.github.io/styleguide/cppguide.html -[project maintainers]: https://github.com/libuv/libuv/blob/master/MAINTAINERS.md diff --git a/vendor/libuv/ChangeLog b/vendor/libuv/ChangeLog deleted file mode 100644 index da4c3b13f..000000000 --- a/vendor/libuv/ChangeLog +++ /dev/null @@ -1,2906 +0,0 @@ -2017.02.02, Version 1.11.0 (Stable), 7452ef4e06a4f99ee26b694c65476401534f2725 - -Changes since version 1.10.2: - -* Now working on version 1.10.3 (cjihrig) - -* win: added fcntl.h to uv-win.h (Michele Caini) - -* unix: move function call out of assert (jBarz) - -* fs: cleanup uv__fs_scandir (Santiago Gimeno) - -* fs: fix crash in uv_fs_scandir_next (muflub) - -* win,signal: fix potential deadlock (Bartosz Sosnowski) - -* unix: use async-signal safe functions between fork and exec (jBarz) - -* sunos: fix SUNOS_NO_IFADDRS build (Ben Noordhuis) - -* zos: make platform functional (John Barboza) - -* doc: add repitition qualifier to version regexs (Daniel Bevenius) - -* zos: use gyp OS label "os390" on z/OS (John Barboza) - -* aix: enable uv_get/set_process_title (Howard Hellyer) - -* zos: use built-in proctitle implementation (John Barboza) - -* Revert "darwin: use clock_gettime in macOS 10.12" (Chris Araman) - -* win,test: don't write uninitialized buffer to tty (Bert Belder) - -* win: define ERROR_ELEVATION_REQUIRED for MinGW (Richard Lau) - -* aix: re-enable fs watch facility (Gireesh Punathil) - - -2017.01.10, Version 1.10.2 (Stable), cb9f579a454b8db592030ffa274ae58df78dbe20 - -Changes since version 1.10.1: - -* Now working on version 1.10.2 (cjihrig) - -* darwin: fix fsync and fdatasync (Joran Dirk Greef) - -* Revert "Revert "win,tty: add support for ANSI codes in win10 v1511"" - (Santiago Gimeno) - -* win,tty: fix MultiByteToWideChar output buffer (Santiago Gimeno) - -* win: remove dead code related to BACKUP_SEMANTICS (Sam Roberts) - -* win: fix comment in quote_cmd_arg (Eric Sciple) - -* darwin: use clock_gettime in macOS 10.12 (Saúl Ibarra Corretgé) - -* win, tty: fix crash on restarting with pending data (Nicholas Vavilov) - -* fs: fix uv__to_stat on BSD platforms (Santiago Gimeno) - -* win: map ERROR_ELEVATION_REQUIRED to UV_EACCES (Richard Lau) - -* win: fix free() on bad input in uv_getaddrinfo() (Ben Noordhuis) - - -2016.11.17, Version 1.10.1 (Stable), 2e49e332bdede6db7cf17fa784a902e8386d5d86 - -Changes since version 1.10.0: - -* Now working on version 1.10.1 (cjihrig) - -* win: fix anonymous union syntax (Brad King) - -* unix: use uv__is_closing everywhere (Santiago Gimeno) - -* win: add missing break statement (cjihrig) - -* doc: fix wrong man page link for uv_fs_lstat() (Michele Caini) - -* win, tty: handle empty buffer in uv_tty_write_bufs (Hitesh Kanwathirtha) - -* doc: add cjihrig alternative GPG ID (cjihrig) - -* Revert "win,tty: add support for ANSI codes in win10 v1511" (Ben Noordhuis) - - -2016.10.25, Version 1.10.0 (Stable), c8a373c729b4c9392e0e14fc53cd6b67b3051ab9 - -Changes since version 1.9.1: - -* Now working on version 1.9.2 (Saúl Ibarra Corretgé) - -* doc: add cjihrig GPG ID (cjihrig) - -* win,build: fix compilation on old Windows / MSVC (Saúl Ibarra Corretgé) - -* darwin: fix setting fd to non-blocking in select(() trick (Saúl Ibarra - Corretgé) - -* unix: allow nesting of kqueue fds in uv_poll_start (Ben Noordhuis) - -* doc: fix generation the first time livehtml runs (Saúl Ibarra Corretgé) - -* test: fix test_close_accept flakiness on Centos5 (Santiago Gimeno) - -* license: libuv is no longer a Node project (Saúl Ibarra Corretgé) - -* license: add license text we've been using for a while (Saúl Ibarra Corretgé) - -* doc: add licensing information to README (Saúl Ibarra Corretgé) - -* win,pipe: fixed formatting, DWORD is long unsigned (Miodrag Milanovic) - -* win: support sub-second precision in uv_fs_futimes() (Jason Ginchereau) - -* unix: ignore EINPROGRESS in uv__close (Saúl Ibarra Corretgé) - -* doc: add Imran Iqbal (iWuzHere) to maintainers (Imran Iqbal) - -* doc: update docs with AIX related information (Imran Iqbal) - -* test: silence build warnings (Kári Tristan Helgason) - -* doc: add iWuzHere GPG ID (Imran Iqbal) - -* linux-core: fix uv_get_total/free_memory on uclibc (Nicolas Cavallari) - -* build: fix build on DragonFly (Michael Neumann) - -* unix: correctly detect named pipes on DragonFly (Michael Neumann) - -* test: make tap output the default (Ben Noordhuis) - -* test: don't dump output for skipped tests (Ben Noordhuis) - -* test: improve formatting of diagnostic messages (Ben Noordhuis) - -* test: remove unused RETURN_TODO macro (Ben Noordhuis) - -* doc: fix stream typos (Pierre-Marie de Rodat) - -* doc: update coding style link (Imran Iqbal) - -* unix,fs: use uint64_t instead of unsigned long (Imran Iqbal) - -* build: check for warnings for -fvisibility=hidden (Imran Iqbal) - -* unix: remove unneeded TODO note (Saúl Ibarra Corretgé) - -* test: skip tty_pty test if pty is not available (Luca Bruno) - -* sunos: set phys_addr of interface_address using ARP (Brian Maher) - -* doc: clarify callbacks won't be called in error case (Saúl Ibarra Corretgé) - -* unix: don't convert stat buffer when syscall fails (Ben Noordhuis) - -* win: compare entire filename in watch events (cjihrig) - -* doc: add a note on safe reuse of uv_write_t (neevek) - -* linux: fix potential event loop stall (Ben Noordhuis) - -* unix,win: make uv_get_process_title() stricter (cjihrig) - -* test: close server before initiating new connection (John Barboza) - -* test: account for multiple handles in one ipc read (John Barboza) - -* unix: fix errno and retval conflict (liuxiaobo) - -* doc: add missing entry in uv_fs_type enum (Michele Caini) - -* unix: preserve loop->data across loop init/done (Ben Noordhuis) - -* win: return UV_EINVAL on bad uv_tty_mode mode arg (Ben Noordhuis) - -* win: simplify memory copy logic in fs.c (Ben Noordhuis) - -* win: fix compilation on mingw (Bartosz Sosnowski) - -* win: ensure 32-bit printf precision (Matej Knopp) - -* darwin: handle EINTR in /dev/tty workaround (Ben Noordhuis) - -* test: fix OOB buffer access (Saúl Ibarra Corretgé) - -* test: don't close CRT fd handed off to uv_pipe_t (Saúl Ibarra Corretgé) - -* test: fix android build error. (sunjin.lee) - -* win: evaluate timers when system wakes up (Bartosz Sosnowski) - -* doc: add supported platforms description (Saúl Ibarra Corretgé) - -* win: fix lstat reparse point without link data (Jason Ginchereau) - -* unix,win: make on_alloc_cb failures more resilient (Saúl Ibarra Corretgé) - -* zos: add support for new platform (John Barboza) - -* test: make tcp_close_while_connecting more resilient (Saúl Ibarra Corretgé) - -* build: use '${prefix}' for pkg-config 'exec_prefix' (Matt Clarkson) - -* build: GNU/kFreeBSD support (Jeffrey Clark) - -* zos: use PLO instruction for atomic operations (John Barboza) - -* zos: use pthread helper functions (John Barboza) - -* zos: implement uv__fs_futime (John Barboza) - -* unix: expand range of values for usleep (John Barboza) - -* zos: track unbound handles and bind before listen (John Barboza) - -* test: improve tap output on test failures (Santiago Gimeno) - -* test: refactor fs_event_close_in_callback (Julien Gilli) - -* zos: implement uv__io_check_fd (John Barboza) - -* unix: unneccessary use const qualifier in container_of (John Barboza) - -* win,tty: add support for ANSI codes in win10 v1511 (Imran Iqbal) - -* doc: add santigimeno to maintainers (Santiago Gimeno) - -* win: fix typo in type name (Saúl Ibarra Corretgé) - -* unix: always define pthread barrier fallback pad (Saúl Ibarra Corretgé) - -* test: use RETURN_SKIP in spawn_setuid_setgid test (Santiago Gimeno) - -* win: add disk read/write count to uv_getrusage (Imran Iqbal) - -* doc: document uv_fs_realpath caveats (Saúl Ibarra Corretgé) - -* test: improve spawn_setuid_setgid test (Santiago Gimeno) - -* test: fix building pty test on Android (Saúl Ibarra Corretgé) - -* doc: uv_buf_t members are not readonly (Saúl Ibarra Corretgé) - -* doc: improve documentation on uv_alloc_cb (Saúl Ibarra Corretgé) - -* fs: fix uv_fs_fstat on platforms using musl libc (Santiago Gimeno) - -* doc: update supported fields for uv_rusage_t (Imran Iqbal) - -* test: fix test-tcp-writealot flakiness on arm (Santiago Gimeno) - -* test: fix fs_event_watch_dir flakiness on arm (Santiago Gimeno) - -* unix: don't use alphasort in uv_fs_scandir() (Ben Noordhuis) - -* doc: fix confusing doc of uv_tcp_nodelay (Bart Robinson) - -* build,osx: fix warnings on tests compilation with gyp (Santiago Gimeno) - -* doc: add ABI tracker link to README (Saúl Ibarra Corretgé) - -* win,tty: fix uv_tty_set_mode race conditions (Bartosz Sosnowski) - -* test: fix fs_fstat on Android (Vit Gottwald) - -* win, test: fix fs_event_watch_dir_recursive (Bartosz Sosnowski) - -* doc: add description of uv_handle_type (Vit Gottwald) - -* build: use -pthreads for tests with autotools (Julien Gilli) - -* win: fix leaky fs request buffer (Jason Ginchereau) - -* doc: note buffer lifetime requirements in uv_write (Vladimír Čunát) - -* doc: add reference to uv_update_time on uv_timer_start (Alex Hultman) - -* win: fix winapi function pointer typedef syntax (Brad King) - -* test: fix tcp_close_while_connecting CI failures (Ben Noordhuis) - -* test: make threadpool_cancel_single deterministic (Ben Noordhuis) - -* test: make threadpool saturation reliable (Ben Noordhuis) - -* unix: don't malloc in uv_thread_create() (Ben Noordhuis) - -* unix: don't include CoreServices globally on macOS (Brad King) - -* unix,win: add uv_translate_sys_error() public API (Philippe Laferriere) - -* win: remove unused static variables (Ben Noordhuis) - -* win: silence -Wmaybe-uninitialized warning (Ben Noordhuis) - -* signal: replace pthread_once with uv_once (Santiago Gimeno) - -* test: fix sign-compare warning (Will Speak) - -* common: fix unused variable warning (Brad King) - - -2016.05.17, Version 1.9.1 (Stable), d989902ac658b4323a4f4020446e6f4dc449e25c - -Changes since version 1.9.0: - -* test: handle root home directories (cjihrig) - -* unix: implement uv__fs_futime for AIX 7.1 (Imran Iqbal) - -* test: skip early bind tests if no IPv6 is supported (Saúl Ibarra Corretgé) - -* win: fix var declaration to be C89 compliant (Michael Fero) - -* unix: use POLL{IN,OUT,etc} constants directly (Ben Noordhuis) - -* doc: add ability to live reload and regenerate HTML (Saúl Ibarra Corretgé) - -* Revert "win,build: remove unused build defines" (cjihrig) - -* linux: fix fd leaks in uv_cpu_info() error paths (Ben Noordhuis) - -* linux: don't abort on malformed /proc/stat (Ben Noordhuis) - -* linux: fix long lines in linux-core.c (Ben Noordhuis) - -* test: fix fs_event_watch_file_current_dir for AIX (Imran Iqbal) - -* unix,fs: code cleanup of uv_fs_event_start for AIX (Imran Iqbal) - -* unix: delay signal handling until after normal i/o (Ben Noordhuis) - -* android: pthread_sigmask() does not set errno (Oguz Bastemur) - -* win: work around sharepoint scandir bug (Ben Noordhuis) - -* unix: guard against clobbering errno in uv__free() (Ben Noordhuis) - -* unix: remove unneeded SAVE_ERRNO wrappers (Ben Noordhuis) - -* test: skip fs_event_close_in_callback on AIX (Imran Iqbal) - -* win: add maxrss, pagefaults to uv_getrusage() (Robert Jefe Lindstaedt) - -* test: set a big send buffer size for tcp_write_queue_order (Andrius Bentkus) - -* unix: error on realpath if PATH_MAX is undefined (Myles Borins) - -* unix: fix bug in barrier fallback implementation (Kári Tristan Helgason) - -* build: bump android ndk version (Kári Tristan Helgason) - -* build: always compile with -fvisibility=hidden (Ben Noordhuis) - -* test: fix -Wformat warnings in platform test (Ben Noordhuis) - -* win: clarify fsevents handling code (Saúl Ibarra Corretgé) - -* test: fix POLLHDRUP related failures for AIX (Imran Iqbal) - -* build, mingw: set LIBS in configure.ac (Tony Theodore) - -* win: improve uv__convert_utf16_to_utf8 (Saúl Ibarra Corretgé) - -* win: simplified UTF16 -> UTF8 conversions (Saúl Ibarra Corretgé) - -* win: remove unneeded condition (Saúl Ibarra Corretgé) - -* darwin: work around condition variable kernel bug (Ben Noordhuis) - -* darwin: make thread stack multiple of page size (Ben Noordhuis) - -* build,win: rename platform to msbuild_platform (João Reis) - -* gitignore: ignore VS temporary database files (João Reis) - -* test: skip emfile on AIX (Imran Iqbal) - -* unix: use system allocator for scandir() (cjihrig) - -* common: release uv_fs_scandir() array (cjihrig) - -* win: call uv__fs_scandir_cleanup() (cjihrig) - -* win,tty: fix read stop in line mode (João Reis) - -* win,tty: don't duplicate handle for line reads (João Reis) - -* win,tty: restore cursor after canceling line read (Alexis Campailla) - - -2016.04.08, Version 1.9.0 (Stable), 229b3a4cc150aebd6561e6bd43076eafa7a03756 - -Changes since version 1.8.0: - -* win: wait for full timeout duration (João Reis) - -* unix: fix support for uClibc-ng (Martin Bark) - -* doc: indicate where new test files need to be added (Dave) - -* test,unix: fix logic error in test runner (Ben Noordhuis) - -* fs: don't nullify req->bufs on EINTR (Dave) - -* osx: set the default thread stack size to RLIMIT_STACK (Saúl Ibarra Corretgé) - -* build: invoke libtoolize with --copy (Ben Noordhuis) - -* test: fixup eintr_handling (Saúl Ibarra Corretgé) - -* osx: avoid compilation warning with Clang (Saúl Ibarra Corretgé) - -* test,win: fix compilation with shared lib (Alexis Murzeau) - -* test: fix race condition in pipe-close-stdout (Imran Iqbal) - -* unix,win: add uv_os_tmpdir() (cjihrig) - -* ios: fix undefined PTHREAD_STACK_MIN (Didiet) - -* test: fix threadpool_multiple_event_loops for AIX (Imran Iqbal) - -* unix: report errors for unpollable fds (Ben Noordhuis) - -* win: fix watching root files (Nicholas Vavilov) - -* build,win: print the Visual Studio version in use (Saúl Ibarra Corretgé) - -* build,win: remove unneeded condition from GYP file (Saúl Ibarra Corretgé) - -* test,win: fix compilation warning (Saúl Ibarra Corretgé) - -* test: use uv_loop_close and assert its result (Nan Xiang) - -* build: map 'AMD64' host arch to 'x64' (Ben Noordhuis) - -* osx: protected use of potentially undefined macro (Samuel Lorétan) - -* linux: fix compilation with musl (Saúl Ibarra Corretgé) - -* doc: describe how to make release builds on Unix (Saúl Ibarra Corretgé) - -* doc: add missing link in README (Saúl Ibarra Corretgé) - -* build: python 2.x/3.x consistent print usage (Rasmus Christian Pedersen) - -* test: assume no IPv6 if interfaces cannot be listed (Nan Xiang) - -* darwin: replace F_FULLFSYNC with fdatasync syscall (Saúl Ibarra Corretgé) - -* doc: add missing write callback to example (Nándor István Krácser) - -* build: compile with -D_THREAD_SAFE on AIX (Imran Iqbal) - -* test: fix threadpool_multiple_event_loops on PPC (Imran Iqbal) - -* test: reduce timeout in tcp_close_while_connecting (Imran Iqbal) - -* unix, win: consistently null-terminate buffers (Saúl Ibarra Corretgé) - -* unix, win: count null byte on UV_ENOBUFS (Saúl Ibarra Corretgé) - -* test: fix deadlocks in uv_cond_wait (Katsutoshi Horie) - -* linux: fix cpu count (Lukasz Jagiello) - -* unix: fix uv__handle_type for AIX (Imran Iqbal) - -* linux: call fclose(), fix fdopen() memory leak (Ben Noordhuis) - -* win: remove unneeded condition (Saúl Ibarra Corretgé) - -* unix: fix compile error in Android using bionic (Robert Chiras) - -* linux: add braces to multi-statement if (Kári Tristan Helgason) - -* doc: add @cjihrig as a maintainer (Saúl Ibarra Corretgé) - -* unix: add fork-safe open file function (Kári Tristan Helgason) - -* linux: replace calls to fopen with uv__open_file (Kári Tristan Helgason) - -* linux: remove redundant call to rewind() (Krishnaraj Bhat) - -* win: remove duplicated code when processing fsevents (Saúl Ibarra Corretgé) - -* test: fix poll_bad_fdtype for AIX (Imran Iqbal) - -* linux: fix error checking in uv__open_file (Saúl Ibarra Corretgé) - -* poll: add UV_DISCONNECT event (Santiago Gimeno) - -* fs: realpath: fix string size before converting (Yuval Brik) - -* win: use native APIs for UTF conversions (cjihrig) - -* doc: clarify uv_loop_close() (Ben Noordhuis) - -* unix: retry ioctl(TIOCGWINSZ) on EINTR (Ben Noordhuis) - -* win,build: remove unused build defines (Saúl Ibarra Corretgé) - -* win: fix buffer overflow in fs events (Joran Dirk Greef) - -* win: fix uv_relative_path and remove dead branch (Joran Dirk Greef) - -* unix: use open(2) with O_CLOEXEC on OS X (Kári Tristan Helgason) - -* test: add missing copyright header (cjihrig) - -* aix: fix 'POLLRDHUP undeclared' build error (Ben Noordhuis) - -* unix,win: add uv_get_passwd() (cjihrig) - -* process: fix uv_spawn edge-case (Santiago Gimeno) - -* test: use %ld for printing uid/gid (Ben Noordhuis) - -* aix: fix ahafs implementation (Imran Iqbal) - -* aix: do not store absolute path to ahafs (Imran Iqbal) - -* process: close process pipes safely (Santiago Gimeno) - -* unix: open ttyname instead of /dev/tty (Enno Boland) - -* unix: remove outdated comment (Kári Tristan Helgason) - - -2015.12.15, Version 1.8.0 (Stable), 5467299450ecf61635657557b6e01aaaf6c3fdf4 - -Changes since version 1.7.5: - -* unix: fix memory leak in uv_interface_addresses (Jianghua Yang) - -* unix: make uv_guess_handle work properly for AIX (Gireesh Punathil) - -* fs: undo uv__req_init when uv__malloc failed (Jianghua Yang) - -* build: remove unused 'component' GYP option (Saúl Ibarra Corretgé) - -* include: remove duplicate extern declaration (Jianghua Yang) - -* win: use the MSVC provided snprintf where possible (Jason Williams) - -* win, test: fix compilation warning (Saúl Ibarra Corretgé) - -* win: fix compilation with VS < 2012 (Ryan Johnston) - -* stream: support empty uv_try_write on unix (Fedor Indutny) - -* unix: fix request handle leak in uv__udp_send (Jianghua Yang) - -* src: replace QUEUE_SPLIT with QUEUE_MOVE (Ben Noordhuis) - -* unix: use QUEUE_MOVE when iterating over lists (Ben Noordhuis) - -* unix: squelch harmless valgrind warning (Ben Noordhuis) - -* test: don't abort on setrlimit() failure (Ben Noordhuis) - -* unix: only undo fs req registration in async mode (Ben Noordhuis) - -* unix: fix uv__getiovmax return value (HungMingWu) - -* unix: make work with Solaris Studio. (Adam Stylinski) - -* test: fix fs_event_watch_file_currentdir flakiness (Santiago Gimeno) - -* unix: skip prohibited syscalls on tvOS and watchOS (Nathan Corvino) - -* test: use FQDN in getaddrinfo_fail test (Wink Saville) - -* docs: clarify documentation of uv_tcp_init_ex (Andrius Bentkus) - -* win: fix comment (Miodrag Milanovic) - -* doc: fix typo in README (Angel Leon) - -* darwin: abort() if (un)locking fs mutex fails (Ben Noordhuis) - -* pipe: enable inprocess uv_write2 on Windows (Louis DeJardin) - -* win: properly return UV_EBADF when _close() fails (Nicholas Vavilov) - -* test: skip process_title for AIX (Imran Iqbal) - -* misc: expose handle print APIs (Petka Antonov) - -* include: add stdio.h to uv.h (Saúl Ibarra Corretgé) - -* misc: remove unnecessary null pointer checks (Ian Kronquist) - -* test,freebsd: skip udp_dual_stack if not supported (Santiago Gimeno) - -* linux: don't retry dup2/dup3 on EINTR (Ben Noordhuis) - -* unix: don't retry dup2/dup3 on EINTR (Ben Noordhuis) - -* test: fix -Wtautological-pointer-compare warnings (Saúl Ibarra Corretgé) - -* win: map ERROR_BAD_PATHNAME to UV_ENOENT (Tony Kelman) - -* test: fix test/test-tty.c for AIX (Imran Iqbal) - -* android: support api level less than 21 (kkdaemon) - -* fsevents: fix race on simultaneous init+close (Fedor Indutny) - -* linux,fs: fix p{read,write}v with a 64bit offset (Saúl Ibarra Corretgé) - -* fs: add uv_fs_realpath() (Yuval Brik) - -* win: fix path for removed and renamed fs events (Joran Dirk Greef) - -* win: do not read more from stream than available (Jeremy Whitlock) - -* test: test that uv_close() doesn't corrupt QUEUE (Andrey Mazo) - -* unix: fix uv_fs_event_stop() from fs_event_cb (Andrey Mazo) - -* test: fix self-deadlocks in thread_rwlock_trylock (Ben Noordhuis) - -* src: remove non ascii character (sztomi) - -* test: fix test udp_multicast_join6 for AIX (Imran Iqbal) - - -2015.09.23, Version 1.7.5 (Stable), a8c1136de2cabf25b143021488cbaab05834daa8 - -Changes since version 1.7.4: - -* unix: Support atomic compare & swap xlC on AIX (nmushell) - -* unix: Fix including uv-aix.h on AIX (nmushell) - -* unix: consolidate rwlock tryrdlock trywrlock errors (Saúl Ibarra Corretgé) - -* unix, win: consolidate mutex trylock errors (Saúl Ibarra Corretgé) - -* darwin: fix memory leak in uv_cpu_info (Jianghua Yang) - -* test: add tests for the uv_rwlock implementation (Bert Belder) - -* win: redo/fix the uv_rwlock APIs (Bert Belder) - -* win: don't fetch function pointers to SRWLock APIs (Bert Belder) - - -2015.09.12, Version 1.7.4 (Stable), a7ad4f52189d89cfcba35f78bfc5ff3b1f4105c4 - -Changes since version 1.7.3: - -* doc: uv_read_start and uv_read_cb clarifications (Ben Trask) - -* freebsd: obtain true uptime through clock_gettime() (Jianghua Yang) - -* win, tty: do not convert \r to \r\n (Colin Snover) - -* build,gyp: add DragonFly to the list of OSes (Michael Neumann) - -* fs: fix bug in sendfile for DragonFly (Michael Neumann) - -* doc: add uv_dlsym() return type (Brian White) - -* tests: fix fs tests run w/o full getdents support (Jeremy Whitlock) - -* doc: fix typo (Devchandra Meetei Leishangthem) - -* doc: fix uv-unix.h location (Sakthipriyan Vairamani) - -* unix: fix error check when closing process pipe fd (Ben Noordhuis) - -* test,freebsd: fix ipc_listen_xx_write tests (Santiago Gimeno) - -* win: fix unsavory rwlock fallback implementation (Bert Belder) - -* doc: clarify repeat timer behavior (Eli Skeggs) - - -2015.08.28, Version 1.7.3 (Stable), 93877b11c8b86e0a6befcda83a54555c1e36e4f0 - -Changes since version 1.7.2: - -* threadpool: fix thread starvation bug (Ben Noordhuis) - - -2015.08.25, Version 1.7.2 (Stable), 4d13a013fcfa72311f0102751fdc7951873f466c - -Changes since version 1.7.1: - -* unix, win: make uv_loop_init return on error (Willem Thiart) - -* win: reset pipe handle for pipe servers (Saúl Ibarra Corretgé) - -* win: fix replacing pipe handle for pipe servers (Saúl Ibarra Corretgé) - -* win: fix setting pipe pending instances after bind (Saúl Ibarra Corretgé) - - -2015.08.20, Version 1.7.1 (Stable), 44f4b6bd82d8ae4583ccc4768a83af778ef69f85 - -Changes since version 1.7.0: - -* doc: document the procedure for verifying releases (Saúl Ibarra Corretgé) - -* doc: add note about Windows binaries to the README (Saúl Ibarra Corretgé) - -* doc: use long GPG IDs in MAINTAINERS.md (Saúl Ibarra Corretgé) - -* Revert "stream: squelch ECONNRESET error if already closed" (Saúl Ibarra - Corretgé) - -* doc: clarify uv_read_stop() is idempotent (Corbin Simpson) - -* unix: OpenBSD's setsockopt needs an unsigned char for multicast (Zachary - Hamm) - -* test: Fix two memory leaks (Karl Skomski) - -* unix,win: return EINVAL on nullptr args in uv_fs_{read,write} (Karl Skomski) - -* win: set accepted TCP sockets as non-inheritable (Saúl Ibarra Corretgé) - -* unix: remove superfluous parentheses in fs macros (Ben Noordhuis) - -* unix: don't copy arguments for sync fs requests (Ben Noordhuis) - -* test: plug small memory leak in unix test runner (Ben Noordhuis) - -* unix,windows: allow NULL loop for sync fs requests (Ben Noordhuis) - -* unix,windows: don't assert on unknown error code (Ben Noordhuis) - -* stream: retry write on EPROTOTYPE on OSX (Brian White) - -* common: fix use of snprintf on Windows (Saúl Ibarra Corretgé) - -* tests: refactored fs watch_dir tests for stability (Jeremy Whitlock) - - -2015.08.06, Version 1.7.0 (Stable), 415a865d6365ba58d02b92b89d46ba5d7744ec8b - -Changes since version 1.6.1: - -* win,stream: add slot to remember CRT fd (Bert Belder) - -* win,pipe: properly close when created from CRT fd (Bert Belder) - -* win,pipe: don't close fd 0-2 (Bert Belder) - -* win,tty: convert fd -> handle safely (Bert Belder) - -* win,tty: properly close when created from CRT fd (Bert Belder) - -* win,tty: don't close fd 0-2 (Bert Belder) - -* win,fs: don't close fd 0-2 (Bert Belder) - -* win: include "malloc.h" (Cheng Zhao) - -* windows: MSVC 2015 has C99 inline (Jason Williams) - -* dragonflybsd: fixes for nonblocking and cloexec (Michael Neumann) - -* dragonflybsd: use sendfile(2) for uv_fs_sendfile (Michael Neumann) - -* dragonflybsd: fix uv_exepath (Michael Neumann) - -* win,fs: Fixes align(8) directive on mingw (Stefano Cristiano) - -* unix, win: prevent replacing fd in uv_{udp,tcp,pipe}_t (Saúl Ibarra Corretgé) - -* win: move logic to set socket non-inheritable to uv_tcp_set_socket (Saúl - Ibarra Corretgé) - -* unix, win: add ability to create tcp/udp sockets early (Saúl Ibarra Corretgé) - -* test: retry select() on EINTR, honor milliseconds (Ben Noordhuis) - -* unix: consolidate tcp and udp bind error (Saúl Ibarra Corretgé) - -* test: conditionally skip udp_ipv6_multicast_join6 (heshamsafi) - -* core: add UV_VERSION_HEX macro (Saúl Ibarra Corretgé) - -* doc: add section with version-checking macros and functions (Saúl Ibarra - Corretgé) - -* tty: cleanup handle if uv_tty_init fails (Saúl Ibarra Corretgé) - -* darwin: save a fd when FSEvents is used (Saúl Ibarra Corretgé) - -* win: fix returning thread id in uv_thread_self (Saúl Ibarra Corretgé) - -* common: use offsetof for QUEUE_DATA (Saúl Ibarra Corretgé) - -* win: remove UV_HANDLE_CONNECTED (A. Hauptmann) - -* docs: add Windows specific note for uv_fs_open (Saúl Ibarra Corretgé) - -* doc: add note about uv_fs_scandir (Saúl Ibarra Corretgé) - -* test,unix: reduce stack size of watchdog threads (Ben Noordhuis) - -* win: add support for recursive file watching (Saúl Ibarra Corretgé) - -* win,tty: support consoles with non-default colors (John McNamee) - -* doc: add missing variable name (Yosuke Furukawa) - -* stream: squelch ECONNRESET error if already closed (Santiago Gimeno) - -* build: remove ancient condition from common.gypi (Saúl Ibarra Corretgé) - -* tests: skip some tests when network is unreachable (Luca Bruno) - -* build: proper support for android cross compilation (guworks) - -* android: add missing include to pthread-fixes.c (RossBencina) - -* test: fix compilation warning (Saúl Ibarra Corretgé) - -* doc: add a note about uv_dirent_t.type (Saúl Ibarra Corretgé) - -* win,test: fix shared library build (Saúl Ibarra Corretgé) - -* test: fix compilation warning (Santiago Gimeno) - -* build: add experimental Windows installer (Roger A. Light) - -* threadpool: send signal only when queue is empty (chenttuuvv) - -* aix: fix uv_exepath with relative paths (Richard Lau) - -* build: fix version syntax in AppVeyor file (Saúl Ibarra Corretgé) - -* unix: allow nbufs > IOV_MAX in uv_fs_{read,write} (ronkorving) - - -2015.06.06, Version 1.6.1 (Stable), 30c8be07bb78a66fdee5141626bf53a49a17094a - -Changes since version 1.6.0: - -* unix: handle invalid _SC_GETPW_R_SIZE_MAX values (cjihrig) - - -2015.06.04, Version 1.6.0 (Stable), adfccad76456061dfcf79b8df8e7dbfee51791d7 - -Changes since version 1.5.0: - -* aix: fix setsockopt for multicast options (Michael) - -* unix: don't block for io if any io handle is primed (Saúl Ibarra Corretgé) - -* windows: MSVC 2015 has snprintf() (Rui Abreu Ferreira) - -* windows: Add VS2015 support to vcbuild.bat (Jason Williams) - -* doc: fix typo in tcp.rst (Igor Soarez) - -* linux: work around epoll bug in kernels < 2.6.37 (Ben Noordhuis) - -* unix,win: add uv_os_homedir() (cjihrig) - -* stream: fix `select()` race condition (Fedor Indutny) - -* unix: prevent infinite loop in uv__run_pending (Saúl Ibarra Corretgé) - -* unix: make sure UDP send callbacks are asynchronous (Saúl Ibarra Corretgé) - -* test: fix `platform_output` netmask printing. (Andrew Paprocki) - -* aix: add ahafs autoconf detection and README notes (Andrew Paprocki) - -* core: add ability to customize memory allocator (Saúl Ibarra Corretgé) - - -2015.05.07, Version 1.5.0 (Stable), 4e77f74c7b95b639b3397095db1bc5bcc016c203 - -Changes since version 1.4.2: - -* doc: clarify that the thread pool primites are not thread safe (Andrius - Bentkus) - -* aix: always deregister closing fds from epoll (Michael) - -* unix: fix glibc-2.20+ macro incompatibility (Massimiliano Torromeo) - -* doc: add Sphinx plugin for generating links to man pages (Saúl Ibarra - Corretgé) - -* doc: link system and library calls to man pages (Saúl Ibarra Corretgé) - -* doc: document uv_getnameinfo_t.{host|service} (Saúl Ibarra Corretgé) - -* build: update the location of gyp (Stephen von Takach) - -* win: name all anonymous structs and unions (TomCrypto) - -* linux: work around epoll bug in kernels 3.10-3.19 (Ben Noordhuis) - -* darwin: fix size calculation in select() fallback (Ole André Vadla Ravnås) - -* solaris: fix setsockopt for multicast options (Julien Gilli) - -* test: fix race condition in multithreaded test (Ben Noordhuis) - -* doc: fix long lines in tty.rst (Ben Noordhuis) - -* test: use UV_TTY_MODE_* values in tty test (Ben Noordhuis) - -* unix: don't clobber errno in uv_tty_reset_mode() (Ben Noordhuis) - -* unix: reject non-tty fds in uv_tty_init() (Ben Noordhuis) - -* win: fix pipe blocking writes (Alexis Campailla) - -* build: fix cross-compiling for iOS (Steven Kabbes) - -* win: remove unnecessary malloc.h - -* include: use `extern "c++"` for defining C++ code (Kazuho Oku) - -* unix: reap child on execvp() failure (Ryan Phillips) - -* windows: fix handle leak on EMFILE (Brian Green) - -* test: fix tty_file, close handle if initialized (Saúl Ibarra Corretgé) - -* doc: clarify what uv_*_open accepts (Saúl Ibarra Corretgé) - -* doc: clarify that we don't maintain external doc resources (Saúl Ibarra - Corretgé) - -* build: add documentation for ninja support (Devchandra Meetei Leishangthem) - -* doc: document uv_buf_t members (Corey Farrell) - -* linux: fix epoll_pwait() fallback on arm64 (Ben Noordhuis) - -* android: fix compilation warning (Saúl Ibarra Corretgé) - -* unix: don't close the fds we just setup (Sam Roberts) - -* test: spawn child replacing std{out,err} to stderr (Saúl Ibarra Corretgé) - -* unix: fix swapping fds order in uv_spawn (Saúl Ibarra Corretgé) - -* unix: fix potential bug if dup2 fails in uv_spawn (Saúl Ibarra Corretgé) - -* test: remove LOG and LOGF variadic macros (Saúl Ibarra Corretgé) - -* win: fix uv_fs_access on directories (Saúl Ibarra Corretgé) - -* win: fix of double free in uv_uptime (Per Nilsson) - -* unix: open "/dev/null" instead of "/" for emfile_fd (Alan Rogers) - -* docs: add some missing words (Daryl Haresign) - -* unix: clean up uv_fs_open() O_CLOEXEC logic (Ben Noordhuis) - -* build: set SONAME for shared library in uv.gyp (Rui Abreu Ferreira) - -* windows: define snprintf replacement as inline instead of static (Rui Abreu - Ferreira) - -* win: fix unlink of readonly files (João Reis) - -* doc: fix uv_run(UV_RUN_DEFAULT) description (Ben Noordhuis) - -* linux: intercept syscall when running under memory sanitizer (Keno Fischer) - -* aix: fix uv_interface_addresses return value (farblue68) - -* windows: defer reporting TCP write failure until next tick (Saúl Ibarra - Corretgé) - -* test: add test for deferred TCP write failure (Saúl Ibarra Corretgé) - - -2015.02.27, Version 1.4.2 (Stable), 1a7391348a11d5450c0f69c828d5302e2cb842eb - -Changes since version 1.4.1: - -* stream: ignore EINVAL for SO_OOBINLINE on OS X (Fedor Indutny) - - -2015.02.25, Version 1.4.1 (Stable), e8e3fc5789cc0f02937879d141cca0411274093c - -Changes since version 1.4.0: - -* win: don't use inline keyword in thread.c (Ben Noordhuis) - -* windows: fix setting dirent types on uv_fs_scandir_next (Saúl Ibarra - Corretgé) - -* unix,windows: make uv_thread_create() return errno (Ben Noordhuis) - -* tty: fix build for SmartOS (Julien Gilli) - -* unix: fix for uv_async data race (Michael Penick) - -* unix, windows: map EHOSTDOWN errno (Ben Noordhuis) - -* stream: use SO_OOBINLINE on OS X (Fedor Indutny) - - -2015.02.10, Version 1.4.0 (Stable), 19fb8a90648f3763240db004b77ab984264409be - -Changes since version 1.3.0: - -* unix: check Android support for pthread_cond_timedwait_monotonic_np (Leith - Bade) - -* test: use modified path in test (cjihrig) - -* unix: implement uv_stream_set_blocking() (Ben Noordhuis) - - -2015.01.29, Version 1.3.0 (Stable), 165685b2a9a42cf96501d79cd6d48a18aaa16e3b - -Changes since version 1.2.1: - -* unix, windows: set non-block mode in uv_poll_init (Saúl Ibarra Corretgé) - -* doc: clarify which flags are supported in uv_fs_event_start (Saúl Ibarra - Corretgé) - -* win,unix: move loop functions which have identical implementations (Andrius - Bentkus) - -* doc: explain how the threadpool is allocated (Alex Mo) - -* doc: clarify uv_default_loop (Saúl Ibarra Corretgé) - -* unix: fix implicit declaration compiler warning (Ben Noordhuis) - -* unix: fix long line introduced in commit 94e628fa (Ben Noordhuis) - -* unix, win: add synchronous uv_get{addr,name}info (Saúl Ibarra Corretgé) - -* linux: fix epoll_pwait() regression with < 2.6.19 (Ben Noordhuis) - -* build: compile -D_GNU_SOURCE on linux (Ben Noordhuis) - -* build: use -fvisibility=hidden in autotools build (Ben Noordhuis) - -* fs, pipe: no trailing terminator in exact sized buffers (Andrius Bentkus) - -* style: rename buf to buffer and len to size for consistency (Andrius Bentkus) - -* test: fix test-spawn on MinGW32 (Luis Martinez de Bartolome) - -* win, pipe: fix assertion when destroying timer (Andrius Bentkus) - -* win, unix: add pipe_peername implementation (Andrius Bentkus) - - -2015.01.29, Version 0.10.33 (Stable), 7a2253d33ad8215a26c1b34f1952aee7242dd687 - -Changes since version 0.10.32: - -* linux: fix epoll_pwait() regression with < 2.6.19 (Ben Noordhuis) - -* test: back-port uv_loop_configure() test (Ben Noordhuis) - - -2015.01.15, Version 1.2.1 (Stable), 4ca78e989062a1099dc4b9ad182a98e8374134b1 - -Changes since version 1.2.0: - -* unix: remove unused dtrace file (Saúl Ibarra Corretgé) - -* test: skip TTY select test if /dev/tty can't be opened (Saúl Ibarra Corretgé) - -* doc: clarify the behavior of uv_tty_init (Saúl Ibarra Corretgé) - -* doc: clarify how uv_async_send behaves (Saúl Ibarra Corretgé) - -* build: make dist now generates a full tarball (Johan Bergström) - -* freebsd: make uv_exepath more resilient (Saúl Ibarra Corretgé) - -* unix: make setting the tty mode to the same value a no-op (Saúl Ibarra - Corretgé) - -* win,tcp: support uv_try_write (Bert Belder) - -* test: enable test-tcp-try-write on windows (Bert Belder) - -* win,tty: support uv_try_write (Bert Belder) - -* unix: set non-block mode in uv_{pipe,tcp,udp}_open (Ben Noordhuis) - - -2015.01.06, Version 1.2.0 (Stable), 09f25b13cd149c7981108fc1a75611daf1277f83 - -Changes since version 1.1.0: - -* linux: fix epoll_pwait() sigmask size calculation (Ben Noordhuis) - -* tty: implement binary I/O terminal mode (Yuri D'Elia) - -* test: fix spawn test with autotools build (Ben Noordhuis) - -* test: skip ipv6 tests when ipv6 is not supported (Ben Noordhuis) - -* common: move STATIC_ASSERT to uv-common.h (Alexey Melnichuk) - -* win/thread: store thread handle in a TLS slot (Alexey Melnichuk) - -* unix: fix ttl, multicast ttl and loop options on IPv6 (Saúl Ibarra Corretgé) - -* linux: fix support for preadv/pwritev-less kernels (Ben Noordhuis) - -* unix: make uv_exepath(size=0) return UV_EINVAL (Ben Noordhuis) - -* darwin: fix uv_exepath(smallbuf) UV_EPERM error (Ben Noordhuis) - -* openbsd: fix uv_exepath(smallbuf) UV_EINVAL error (Ben Noordhuis) - -* linux: fix uv_exepath(size=1) UV_EINVAL error (Ben Noordhuis) - -* sunos: preemptively fix uv_exepath(size=1) (Ben Noordhuis) - -* win: fix and clarify comments in winapi.h (Bert Belder) - -* win: make available NtQueryDirectoryFile (Bert Belder) - -* win: add definitions for directory information types (Bert Belder) - -* win: use NtQueryDirectoryFile to implement uv_fs_scandir (Bert Belder) - -* unix: don't unlink unix socket on bind error (Ben Noordhuis) - -* build: fix bad comment in autogen.sh (Ben Noordhuis) - -* build: add AC_PROG_LIBTOOL to configure.ac (Ben Noordhuis) - -* test: skip udp_options6 if there no IPv6 support (Saúl Ibarra Corretgé) - -* win: add definitions for MUI errors mingw lacks (Bert Belder) - -* build: enable warnings in autotools build (Ben Noordhuis) - -* build: remove -Wno-dollar-in-identifier-extension (Ben Noordhuis) - -* build: move flags from Makefile.am to configure.ac (Ben Noordhuis) - - -2015.01.06, Version 0.10.32 (Stable), 378de30c59aef5fdb6d130fa5cfcb0a68fce571c - -Changes since version 0.10.31: - -* linux: fix epoll_pwait() sigmask size calculation (Ben Noordhuis) - - -2014.12.25, Version 1.1.0 (Stable), 9572f3e74a167f59a8017e57ca3ebe91ffd88e18 - -Changes since version 1.0.2: - -* test: test that closing a poll handle doesn't corrupt the stack (Bert Belder) - -* win: fix compilation of tests (Marc Schlaich) - -* Revert "win: keep a reference to AFD_POLL_INFO in cancel poll" (Bert Belder) - -* win: avoid stack corruption when closing a poll handle (Bert Belder) - -* test: fix test-fs-file-loop on Windows (Bert Belder) - -* test: fix test-cwd-and-chdir (Bert Belder) - -* doc: indicate what version uv_loop_configure was added on (Saúl Ibarra - Corretgé) - -* doc: fix sphinx warning (Saúl Ibarra Corretgé) - -* test: skip spawn_setuid_setgid if we get EACCES (Saúl Ibarra Corretgé) - -* test: silence some Clang warnings (Saúl Ibarra Corretgé) - -* test: relax osx_select_many_fds (Saúl Ibarra Corretgé) - -* test: fix compilation warnings when building with Clang (Saúl Ibarra - Corretgé) - -* win: fix autotools build of tests (Luis Lavena) - -* gitignore: ignore Visual Studio files (Marc Schlaich) - -* win: set fallback message if FormatMessage fails (Marc Schlaich) - -* win: fall back to default language in uv_dlerror (Marc Schlaich) - -* test: improve compatibility for dlerror test (Marc Schlaich) - -* test: check dlerror is "no error" in no error case (Marc Schlaich) - -* unix: change uv_cwd not to return a trailing slash (Saúl Ibarra Corretgé) - -* test: fix cwd_and_chdir test on Unix (Saúl Ibarra Corretgé) - -* test: add uv_cwd output to platform_output test (Saúl Ibarra Corretgé) - -* build: fix dragonflybsd autotools build (John Marino) - -* win: scandir use 'ls' for formatting long strings (Kenneth Perry) - -* build: remove clang and gcc_version gyp defines (Ben Noordhuis) - -* unix, windows: don't treat uv_run_mode as a bitmask (Saúl Ibarra Corretgé) - -* unix, windows: fix UV_RUN_ONCE mode if progress was made (Saúl Ibarra - Corretgé) - - -2014.12.25, Version 0.10.31 (Stable), 4dbd27e2219069a6daa769fb37f98673b77b4261 - -Changes since version 0.10.30: - -* test: test that closing a poll handle doesn't corrupt the stack (Bert Belder) - -* win: fix compilation of tests (Marc Schlaich) - -* Revert "win: keep a reference to AFD_POLL_INFO in cancel poll" (Bert Belder) - -* win: avoid stack corruption when closing a poll handle (Bert Belder) - -* gitignore: ignore Visual Studio files (Marc Schlaich) - -* win: set fallback message if FormatMessage fails (Marc Schlaich) - -* win: fall back to default language in uv_dlerror (Marc Schlaich) - -* test: improve compatibility for dlerror test (Marc Schlaich) - -* test: check dlerror is "no error" in no error case (Marc Schlaich) - -* build: link against -pthread (Logan Rosen) - -* win: scandir use 'ls' for formatting long strings (Kenneth Perry) - - -2014.12.10, Version 1.0.2 (Stable), eec671f0059953505f9a3c9aeb7f9f31466dd7cd - -Changes since version 1.0.1: - -* linux: fix sigmask size arg in epoll_pwait() call (Ben Noordhuis) - -* linux: handle O_NONBLOCK != SOCK_NONBLOCK case (Helge Deller) - -* doc: fix spelling (Joey Geralnik) - -* unix, windows: fix typos in comments (Joey Geralnik) - -* test: canonicalize test runner path (Ben Noordhuis) - -* test: fix compilation warnings (Saúl Ibarra Corretgé) - -* test: skip tty test if detected width and height are 0 (Saúl Ibarra Corretgé) - -* doc: update README with IRC channel (Saúl Ibarra Corretgé) - -* Revert "unix: use cfmakeraw() for setting raw TTY mode" (Ben Noordhuis) - -* doc: document how to get result of uv_fs_mkdtemp (Tim Caswell) - -* unix: add flag for blocking SIGPROF during poll (Ben Noordhuis) - -* unix, windows: add uv_loop_configure() function (Ben Noordhuis) - -* win: keep a reference to AFD_POLL_INFO in cancel poll (Marc Schlaich) - -* test: raise fd limit for OSX select test (Saúl Ibarra Corretgé) - -* unix: remove overzealous assert in uv_read_stop (Saúl Ibarra Corretgé) - -* unix: reset the reading flag when a stream gets EOF (Saúl Ibarra Corretgé) - -* unix: stop reading if an error is produced (Saúl Ibarra Corretgé) - -* cleanup: remove all dead assignments (Maciej Małecki) - -* linux: return early if we have no interfaces (Maciej Małecki) - -* cleanup: remove a dead increment (Maciej Małecki) - - -2014.12.10, Version 0.10.30 (Stable), 5a63f5e9546dca482eeebc3054139b21f509f21f - -Changes since version 0.10.29: - -* linux: fix sigmask size arg in epoll_pwait() call (Ben Noordhuis) - -* linux: handle O_NONBLOCK != SOCK_NONBLOCK case (Helge Deller) - -* doc: update project links (Ben Noordhuis) - -* windows: fix compilation of tests (Marc Schlaich) - -* unix: add flag for blocking SIGPROF during poll (Ben Noordhuis) - -* unix, windows: add uv_loop_configure() function (Ben Noordhuis) - -* win: keep a reference to AFD_POLL_INFO in cancel poll (Marc Schlaich) - - -2014.11.27, Version 1.0.1 (Stable), 0a8e81374e861d425b56c45c8599595d848911d2 - -Changes since version 1.0.0: - -* readme: remove Rust from users (Elijah Andrews) - -* doc,build,include: update project links (Ben Noordhuis) - -* doc: fix typo: Strcutures -> Structures (Michael Ira Krufky) - -* unix: fix processing process handles queue (Saúl Ibarra Corretgé) - -* win: replace non-ansi characters in source file (Bert Belder) - - -2014.11.21, Version 1.0.0 (Stable), feb2a9e6947d892f449b2770c4090f7d8c88381b - -Changes since version 1.0.0-rc2: - -* doc: fix git/svn url for gyp repo in README (Emmanuel Odeke) - -* windows: fix fs_read with nbufs > 1 and offset (Unknown W. Brackets) - -* win: add missing IP_ADAPTER_UNICAST_ADDRESS_LH definition for MinGW - (huxingyi) - -* doc: mention homebrew in README (Mikhail Mukovnikov) - -* doc: add learnuv workshop to README (Thorsten Lorenz) - -* doc: fix parameter name in uv_fs_access (Saúl Ibarra Corretgé) - -* unix: use cfmakeraw() for setting raw TTY mode (Yuri D'Elia) - -* win: fix uv_thread_self() (Alexis Campailla) - -* build: add x32 support to gyp build (Ben Noordhuis) - -* build: remove dtrace probes (Ben Noordhuis) - -* doc: fix link in misc.rst (Manos Nikolaidis) - -* mailmap: remove duplicated entries (Saúl Ibarra Corretgé) - -* gyp: fix comment regarding version info location (Saúl Ibarra Corretgé) - - -2014.10.21, Version 1.0.0-rc2 (Pre-release) - -Changes since version 1.0.0-rc1: - -* build: add missing fixtures to distribution tarball (Rob Adams) - -* doc: update references to current stable branch (Zachary Newman) - -* fs: fix readdir on empty directory (Fedor Indutny) - -* fs: rename uv_fs_readdir to uv_fs_scandir (Saúl Ibarra Corretgé) - -* doc: document uv_alloc_cb (Saúl Ibarra Corretgé) - -* doc: add migration guide from version 0.10 (Saúl Ibarra Corretgé) - -* build: add DragonFly BSD support in autotools (Robin Hahling) - -* doc: document missing stream related structures (Saúl Ibarra Corretgé) - -* doc: clarify uv_loop_t.data field lifetime (Saúl Ibarra Corretgé) - -* doc: add documentation for missing functions and structures (Saúl Ibarra - Corretgé) - -* doc: fix punctuation and grammar in README (Jeff Widman) - -* windows: return libuv error codes in uv_poll_init() (cjihrig) - -* unix, windows: add uv_fs_access() (cjihrig) - -* windows: fix netmask detection (Alexis Campailla) - -* unix, windows: don't include null byte in uv_cwd size (Saúl Ibarra Corretgé) - -* unix, windows: add uv_thread_equal (Tomasz Kołodziejski) - -* windows: fix fs_write with nbufs > 1 and offset (Unknown W. Brackets) - - -2014.10.21, Version 0.10.29 (Stable), 2d728542d3790183417f8f122a110693cd85db14 - -Changes since version 0.10.28: - -* darwin: allocate enough space for select() hack (Fedor Indutny) - -* linux: try epoll_pwait if epoll_wait is missing (Michael Hudson-Doyle) - -* windows: map ERROR_INVALID_DRIVE to UV_ENOENT (Saúl Ibarra Corretgé) - - -2014.09.18, Version 1.0.0-rc1 (Unstable), 0c28bbf7b42882853d1799ab96ff68b07f7f8d49 - -Changes since version 0.11.29: - -* windows: improve timer precision (Alexis Campailla) - -* build, gyp: set xcode flags (Recep ASLANTAS) - -* ignore: include m4 files which are created manually (Recep ASLANTAS) - -* build: add m4 for feature/flag-testing (Recep ASLANTAS) - -* ignore: ignore Xcode project and workspace files (Recep ASLANTAS) - -* unix: fix warnings about dollar symbol usage in identifiers (Recep ASLANTAS) - -* unix: fix warnings when loading functions with dlsym (Recep ASLANTAS) - -* linux: try epoll_pwait if epoll_wait is missing (Michael Hudson-Doyle) - -* test: add test for closing and recreating default loop (Saúl Ibarra Corretgé) - -* windows: properly close the default loop (Saúl Ibarra Corretgé) - -* version: add ability to specify a version suffix (Saúl Ibarra Corretgé) - -* doc: add API documentation (Saúl Ibarra Corretgé) - -* test: don't close connection on write error (Trevor Norris) - -* windows: further simplify the code for timers (Saúl Ibarra Corretgé) - -* gyp: remove UNLIMITED_SELECT from dependent define (Fedor Indutny) - -* darwin: allocate enough space for select() hack (Fedor Indutny) - -* unix, windows: don't allow a NULL callback on timers (Saúl Ibarra Corretgé) - -* windows: simplify code in uv_timer_again (Saúl Ibarra Corretgé) - -* test: use less requests on tcp-write-queue-order (Saúl Ibarra Corretgé) - -* unix: stop child process watcher after last one exits (Saúl Ibarra Corretgé) - -* unix: simplify how process handle queue is managed (Saúl Ibarra Corretgé) - -* windows: remove duplicated field (mattn) - -* core: add a reserved field to uv_handle_t and uv_req_t (Saúl Ibarra Corretgé) - -* windows: fix buffer leak after failed udp send (Bert Belder) - -* windows: make sure sockets and handles are reset on close (Saúl Ibarra Corretgé) - -* unix, windows: add uv_fileno (Saúl Ibarra Corretgé) - -* build: use same CFLAGS in autotools build as in gyp (Saúl Ibarra Corretgé) - -* build: remove unneeded define in uv.gyp (Saúl Ibarra Corretgé) - -* test: fix watcher_cross_stop on Windows (Saúl Ibarra Corretgé) - -* unix, windows: move includes for EAI constants (Saúl Ibarra Corretgé) - -* unix: fix exposing EAI_* glibc-isms (Saúl Ibarra Corretgé) - -* unix: fix tcp write after bad connect freezing (Andrius Bentkus) - - -2014.08.20, Version 0.11.29 (Unstable), 35451fed830807095bbae8ef981af004a4b9259e - -Changes since version 0.11.28: - -* windows: make uv_read_stop immediately stop reading (Jameson Nash) - -* windows: fix uv__getaddrinfo_translate_error (Alexis Campailla) - -* netbsd: fix build (Saúl Ibarra Corretgé) - -* unix, windows: add uv_recv_buffer_size and uv_send_buffer_size (Andrius - Bentkus) - -* windows: add support for UNC paths on uv_spawn (Paul Goldsmith) - -* windows: replace use of inet_addr with uv_inet_pton (Saúl Ibarra Corretgé) - -* unix: replace some asserts with returning errors (Andrius Bentkus) - -* windows: use OpenBSD implementation for uv_fs_mkdtemp (Pavel Platto) - -* windows: fix GetNameInfoW error handling (Alexis Campailla) - -* fs: introduce uv_readdir_next() and report types (Fedor Indutny) - -* fs: extend reported types in uv_fs_readdir_next (Saúl Ibarra Corretgé) - -* unix: read on stream even when UV__POLLHUP set. (Julien Gilli) - - -2014.08.08, Version 0.11.28 (Unstable), fc9e2a0bc487b299c0cd3b2c9a23aeb554b5d8d1 - -Changes since version 0.11.27: - -* unix, windows: const-ify handle in uv_udp_getsockname (Rasmus Pedersen) - -* windows: use UV_ECANCELED for aborted TCP writes (Saúl Ibarra Corretgé) - -* windows: add more required environment variables (Jameson Nash) - -* windows: sort environment variables before calling CreateProcess (Jameson - Nash) - -* unix, windows: move uv_loop_close out of assert (John Firebaugh) - -* windows: fix buffer overflow on uv__getnameinfo_work() (lilohuang) - -* windows: add uv_backend_timeout (Jameson Nash) - -* test: disable tcp_close_accept on Windows (Saúl Ibarra Corretgé) - -* windows: read the PATH env var of the child (Alex Crichton) - -* include: avoid using C++ 'template' reserved word (Iñaki Baz Castillo) - -* include: fix version number (Saúl Ibarra Corretgé) - - -2014.07.32, Version 0.11.27 (Unstable), ffe24f955032d060968ea0289af365006afed55e - -Changes since version 0.11.26: - -* unix, windows: use the same threadpool implementation (Saúl Ibarra Corretgé) - -* unix: use struct sockaddr_storage for target UDP addr (Saúl Ibarra Corretgé) - -* doc: add documentation to uv_udp_start_recv (Andrius Bentkus) - -* common: use common uv__count_bufs code (Andrius Bentkus) - -* unix, win: add send_queue_size and send_queue_count to uv_udp_t (Andrius - Bentkus) - -* unix, win: add uv_udp_try_send (Andrius Bentkus) - -* unix: return UV_EAGAIN if uv_try_write cannot write any data (Saúl Ibarra - Corretgé) - -* windows: fix compatibility with cygwin pipes (Jameson Nash) - -* windows: count queued bytes even if request completed immediately (Saúl - Ibarra Corretgé) - -* windows: disable CRT debug handler on MinGW32 (Saúl Ibarra Corretgé) - -* windows: map ERROR_INVALID_DRIVE to UV_ENOENT (Saúl Ibarra Corretgé) - -* unix: try to write immediately in uv_udp_send (Saúl Ibarra Corretgé) - -* unix: remove incorrect assert (Saúl Ibarra Corretgé) - -* openbsd: avoid requiring privileges for uv_resident_set_memory (Aaron Bieber) - -* unix: guarantee write queue cb execution order in streams (Andrius Bentkus) - -* img: add logo files (Saúl Ibarra Corretgé) - -* aix: improve AIX compatibility (Andrew Low) - -* windows: return bind error immediately when implicitly binding (Saúl Ibarra - Corretgé) - -* windows: don't use atexit for cleaning up the threadpool (Saúl Ibarra - Corretgé) - -* windows: destroy work queue elements when colsing a loop (Saúl Ibarra - Corretgé) - -* unix, windows: add uv_fs_mkdtemp (Pavel Platto) - -* build: handle platforms without multiprocessing.synchronize (Saúl Ibarra - Corretgé) - -* windows: change GENERIC_ALL to GENERIC_WRITE in fs__create_junction (Tony - Kelman) - -* windows: relay TCP bind errors via ipc (Alexis Campailla) - - -2014.07.32, Version 0.10.28 (Stable), 9c14b616f5fb84bfd7d45707bab4bbb85894443e - -Changes since version 0.10.27: - -* windows: fix handling closed socket while poll handle is closing (Saúl Ibarra - Corretgé) - -* unix: return system error on EAI_SYSTEM (Saúl Ibarra Corretgé) - -* unix: fix bogus structure field name (Saúl Ibarra Corretgé) - -* darwin: invoke `mach_timebase_info` only once (Fedor Indutny) - - -2014.06.28, Version 0.11.26 (Unstable), 115281a1058c4034d5c5ccedacb667fe3f6327ea - -Changes since version 0.11.25: - -* windows: add VT100 codes ?25l and ?25h (JD Ballard) - -* windows: add invert ANSI (7 / 27) emulation (JD Ballard) - -* unix: fix handling error on UDP socket creation (Saúl Ibarra Corretgé) - -* unix, windows: getnameinfo implementation (Rasmus Pedersen) - -* heap: fix `heap_remove()` (Fedor Indutny) - -* unix, windows: fix parsing scoped IPv6 addresses (Saúl Ibarra Corretgé) - -* windows: fix handling closed socket while poll handle is closing (Saúl Ibarra - Corretgé) - -* thread: barrier functions (Ben Noordhuis) - -* windows: fix PYTHON environment variable usage (Jay Satiro) - -* unix, windows: return system error on EAI_SYSTEM (Saúl Ibarra Corretgé) - -* windows: fix handling closed socket while poll handle is closing (Saúl Ibarra - Corretgé) - -* unix: don't run i/o callbacks after prepare callbacks (Saúl Ibarra Corretgé) - -* windows: add tty unicode support for input (Peter Atashian) - -* header: introduce `uv_loop_size()` (Andrius Bentkus) - -* darwin: invoke `mach_timebase_info` only once (Fedor Indutny) - - -2014.05.02, Version 0.11.25 (Unstable), 2acd544cff7142e06aa3b09ec64b4a33dd9ab996 - -Changes since version 0.11.24: - -* osx: pass const handle pointer to uv___stream_fd (Chernyshev Viacheslav) - -* unix, windows: pass const handle ptr to uv_tcp_get*name (Chernyshev - Viacheslav) - -* common: pass const sockaddr ptr to uv_ip*_name (Chernyshev Viacheslav) - -* unix, windows: validate flags on uv_udp|tcp_bind (Saúl Ibarra Corretgé) - -* unix: handle case when addr is not initialized after recvmsg (Saúl Ibarra - Corretgé) - -* unix, windows: uv_now constness (Rasmus Pedersen) - - -2014.04.15, Version 0.11.24 (Unstable), ed948c29f6e8c290f79325a6f0bc9ef35bcde644 - -Changes since version 0.11.23: - -* linux: reduce file descriptor count of async pipe (Ben Noordhuis) - -* sunos: support IPv6 qualified link-local addresses (Saúl Ibarra Corretgé) - -* windows: fix opening of read-only stdin pipes (Alexis Campailla) - -* windows: Fix an infinite loop in uv_spawn (Alex Crichton) - -* windows: fix console signal handler refcount (李港平) - -* inet: allow scopeid in uv_inet_pton (Fedor Indutny) - - -2014.04.07, Version 0.11.23 (Unstable), e54de537efcacd593f36fcaaf8b4cb9e64313275 - -Changes since version 0.11.22: - -* fs: avoid using readv/writev where possible (Fedor Indutny) - -* mingw: fix build with autotools (Saúl Ibarra Corretgé) - -* bsd: support IPv6 qualified link-local addresses (Saúl Ibarra Corretgé) - -* unix: add UV_HANDLE_IPV6 flag to tcp and udp handles (Saúl Ibarra Corretgé) - -* unix, windows: do not set SO_REUSEADDR by default on udp (Saúl Ibarra - Corretgé) - -* windows: fix check in uv_tty_endgame() (Maks Naumov) - -* unix, windows: add IPv6 support for uv_udp_multicast_interface (Saúl Ibarra - Corretgé) - -* unix: fallback to blocking writes if reopening a tty fails (Saúl Ibarra - Corretgé) - -* unix: fix handling uv__open_cloexec failure (Saúl Ibarra Corretgé) - -* unix, windows: add IPv6 support to uv_udp_set_membership (Saúl Ibarra - Corretgé) - -* unix, windows: removed unused status parameter (Saúl Ibarra Corretgé) - -* android: add support of ifaddrs in android (Javier Hernández) - -* build: fix SunOS and AIX build with autotools (Saúl Ibarra Corretgé) - -* build: freebsd link with libelf if dtrace enabled (Saúl Ibarra Corretgé) - -* stream: do not leak `alloc_cb` buffers on error (Fedor Indutny) - -* unix: fix setting written size on uv_wd (Saúl Ibarra Corretgé) - - -2014.03.11, Version 0.11.22 (Unstable), cd0c19b1d3c56acf0ade7687006e12e75fbda36d - -Changes since version 0.11.21: - -* unix, windows: map ERANGE errno (Saúl Ibarra Corretgé) - -* unix, windows: make uv_cwd be consistent with uv_exepath (Saúl Ibarra - Corretgé) - -* process: remove debug perror() prints (Fedor Indutny) - -* windows: fall back for volume info query (Isaiah Norton) - -* pipe: allow queueing pending handles (Fedor Indutny) - -* windows: fix winsock status codes for address errors (Raul Martins) - -* windows: Remove unused variable from uv__pipe_insert_pending_socket (David - Capello) - -* unix: workaround broken pthread_sigmask on Android (Paul Tan) - -* error: add ENXIO for O_NONBLOCK FIFO open() (Fedor Indutny) - -* freebsd: use accept4, introduced in version 10 (Saúl Ibarra Corretgé) - -* windows: fix warnings of MinGW -Wall -O3 (StarWing) - -* openbsd, osx: fix compilation warning on scandir (Saúl Ibarra Corretgé) - -* linux: always deregister closing fds from epoll (Geoffry Song) - -* unix: reopen tty as /dev/tty (Saúl Ibarra Corretgé) - -* kqueue: invalidate fd in uv_fs_event_t (Fedor Indutny) - - -2014.02.28, Version 0.11.21 (Unstable), 3ef958158ae1019e027ebaa93114160099db5206 - -Changes since version 0.11.20: - -* unix: fix uv_fs_write when using an empty buffer (Saúl Ibarra Corretgé) - -* unix, windows: add assertion in uv_loop_delete (Saúl Ibarra Corretgé) - - -2014.02.27, Version 0.11.20 (Unstable), 88355e081b51c69ee1e2b6b0015a4e3d38bd0579 - -Changes since version 0.11.19: - -* stream: start thread after assignments (Oguz Bastemur) - -* fs: `uv__cloexec()` opened fd (Fedor Indutny) - -* gyp: qualify `library` variable (Fedor Indutny) - -* unix, win: add uv_udp_set_multicast_interface() (Austin Foxley) - -* unix: fix uv_tcp_nodelay return value in case of error (Saúl Ibarra Corretgé) - -* unix: call setgoups before calling setuid/setgid (Saúl Ibarra Corretgé) - -* include: mark close_cb field as private (Saúl Ibarra Corretgé) - -* unix, windows: map EFBIG errno (Saúl Ibarra Corretgé) - -* unix: correct error when calling uv_shutdown twice (Keno Fischer) - -* windows: fix building on MinGW (Alex Crichton) - -* windows: always initialize uv_process_t (Alex Crichton) - -* include: expose libuv version in header files (Saúl Ibarra Corretgé) - -* fs: vectored IO API for filesystem read/write (Benjamin Saunders) - -* windows: freeze in uv_tcp_endgame (Alexis Campailla) - -* sunos: handle rearm errors (Fedor Indutny) - -* unix: use a heap for timers (Ben Noordhuis) - -* linux: always deregister closing fds from epoll (Geoffry Song) - -* linux: include grp.h for setgroups() (William Light) - -* unix, windows: add uv_loop_init and uv_loop_close (Saúl Ibarra Corretgé) - -* unix, windows: add uv_getrusage() function (Oleg Efimov) - -* win: minor error handle fix to uv_pipe_write_impl (Rasmus Pedersen) - -* heap: fix node removal (Keno Fischer) - -* win: fix C99/C++ comment (Rasmus Pedersen) - -* fs: vectored IO API for filesystem read/write (Benjamin Saunders) - -* unix, windows: add uv_pipe_getsockname (Saúl Ibarra Corretgé) - -* unix, windows: map ENOPROTOOPT errno (Saúl Ibarra Corretgé) - -* errno: add ETXTBSY (Fedor Indutny) - -* fsevent: rename filename field to path (Saúl Ibarra Corretgé) - -* unix, windows: add uv_fs_event_getpath (Saúl Ibarra Corretgé) - -* unix, windows: add uv_fs_poll_getpath (Saúl Ibarra Corretgé) - -* unix, windows: map ERANGE errno (Saúl Ibarra Corretgé) - -* unix, windows: set required size on UV_ENOBUFS (Saúl Ibarra Corretgé) - -* unix, windows: clarify what uv_stream_set_blocking does (Saúl Ibarra - Corretgé) - -* fs: use preadv on Linux if available (Brian White) - - -2014.01.30, Version 0.11.19 (Unstable), 336a1825309744f920230ec3e427e78571772347 - -Changes since version 0.11.18: - -* linux: move sscanf() out of the assert() (Trevor Norris) - -* linux: fix C99/C++ comment (Fedor Indutny) - - -2014.05.02, Version 0.10.27 (Stable), 6e24ce23b1e7576059f85a608eca13b766458a01 - -Changes since version 0.10.26: - -* windows: fix console signal handler refcount (Saúl Ibarra Corretgé) - -* win: always leave crit section in get_proc_title (Fedor Indutny) - - -2014.04.07, Version 0.10.26 (Stable), d864907611c25ec986c5e77d4d6d6dee88f26926 - -Changes since version 0.10.25: - -* process: don't close stdio fds during spawn (Tonis Tiigi) - -* build, windows: do not fail on Windows SDK Prompt (Marc Schlaich) - -* build, windows: fix x64 configuration issue (Marc Schlaich) - -* win: fix buffer leak on error in pipe.c (Fedor Indutny) - -* kqueue: invalidate fd in uv_fs_event_t (Fedor Indutny) - -* linux: always deregister closing fds from epoll (Geoffry Song) - -* error: add ENXIO for O_NONBLOCK FIFO open() (Fedor Indutny) - - -2014.02.19, Version 0.10.25 (Stable), d778dc588507588b12b9f9d2905078db542ed751 - -Changes since version 0.10.24: - -* stream: start thread after assignments (Oguz Bastemur) - -* unix: correct error when calling uv_shutdown twice (Saúl Ibarra Corretgé) - -2014.01.30, Version 0.10.24 (Stable), aecd296b6bce9b40f06a61c5c94e43d45ac7308a - -Changes since version 0.10.23: - -* linux: move sscanf() out of the assert() (Trevor Norris) - -* linux: fix C99/C++ comment (Fedor Indutny) - - -2014.01.23, Version 0.11.18 (Unstable), d47962e9d93d4a55a9984623feaf546406c9cdbb - -Changes since version 0.11.17: - -* osx: Fix a possible segfault in uv__io_poll (Alex Crichton) - -* windows: improved handling of invalid FDs (Alexis Campailla) - -* doc: adding ARCHS flag to OS X build command (Nathan Sweet) - -* tcp: reveal bind-time errors before listen (Alexis Campailla) - -* tcp: uv_tcp_dualstack() (Fedor Indutny) - -* linux: relax assumption on /proc/stat parsing (Luca Bruno) - -* openbsd: fix obvious bug in uv_cpu_info (Fedor Indutny) - -* process: close stdio after dup2'ing it (Fedor Indutny) - -* linux: move sscanf() out of the assert() (Trevor Norris) - - -2014.01.23, Version 0.10.23 (Stable), dbd218e699fec8be311d85e4788be9e28ae884f8 - -Changes since version 0.10.22: - -* linux: relax assumption on /proc/stat parsing (Luca Bruno) - -* openbsd: fix obvious bug in uv_cpu_info (Fedor Indutny) - -* process: close stdio after dup2'ing it (Fedor Indutny) - - -2014.01.08, Version 0.10.22 (Stable), f526c90eeff271d9323a9107b9a64a4671fd3103 - -Changes since version 0.10.21: - -* windows: avoid assertion failure when pipe server is closed (Bert Belder) - - -2013.12.32, Version 0.11.17 (Unstable), 589c224d4c2e79fec65db01d361948f1e4976858 - -Changes since version 0.11.16: - -* stream: allow multiple buffers for uv_try_write (Fedor Indutny) - -* unix: fix a possible memory leak in uv_fs_readdir (Alex Crichton) - -* unix, windows: add uv_loop_alive() function (Sam Roberts) - -* windows: avoid assertion failure when pipe server is closed (Bert Belder) - -* osx: Fix a possible segfault in uv__io_poll (Alex Crichton) - -* stream: fix uv__stream_osx_select (Fedor Indutny) - - -2013.12.14, Version 0.11.16 (Unstable), ae0ed8c49d0d313c935c22077511148b6e8408a4 - -Changes since version 0.11.15: - -* fsevents: remove kFSEventStreamCreateFlagNoDefer polyfill (ci-innoq) - -* libuv: add more getaddrinfo errors (Steven Kabbes) - -* unix: fix accept() EMFILE error handling (Ben Noordhuis) - -* linux: fix up SO_REUSEPORT back-port (Ben Noordhuis) - -* fsevents: fix subfolder check (Fedor Indutny) - -* fsevents: fix invalid memory access (huxingyi) - -* windows/timer: fix uv_hrtime discontinuity (Bert Belder) - -* unix: fix various memory leaks and undef behavior (Fedor Indutny) - -* unix, windows: always update loop time (Saúl Ibarra Corretgé) - -* windows: translate system errors in uv_spawn (Alexis Campailla) - -* windows: uv_spawn code refactor (Alexis Campailla) - -* unix, windows: detect errors in uv_ip4/6_addr (Yorkie) - -* stream: introduce uv_try_write(...) (Fedor Indutny) - - -2013.12.13, Version 0.10.20 (Stable), 04141464dd0fba90ace9aa6f7003ce139b888a40 - -Changes since version 0.10.19: - -* linux: fix up SO_REUSEPORT back-port (Ben Noordhuis) - -* fs-event: fix invalid memory access (huxingyi) - - -2013.11.21, Version 0.11.15 (Unstable), bfe645ed7e99ca5670d9279ad472b604c129d2e5 - -Changes since version 0.11.14: - -* fsevents: report errors to user (Fedor Indutny) - -* include: UV_FS_EVENT_RECURSIVE is a flag (Fedor Indutny) - -* linux: use CLOCK_MONOTONIC_COARSE if available (Ben Noordhuis) - -* build: make systemtap probes work with gyp build (Ben Noordhuis) - -* unix: update events from pevents between polls (Fedor Indutny) - -* fsevents: support japaneese characters in path (Chris Bank) - -* linux: don't turn on SO_REUSEPORT socket option (Ben Noordhuis) - -* queue: strengthen type checks (Ben Noordhuis) - -* include: remove uv_strlcat() and uv_strlcpy() (Ben Noordhuis) - -* build: fix windows smp build with gyp (Geert Jansen) - -* unix: return exec errors from uv_spawn, not async (Alex Crichton) - -* fsevents: use native character encoding file paths (Ben Noordhuis) - -* linux: handle EPOLLHUP without EPOLLIN/EPOLLOUT (Ben Noordhuis) - -* windows: use _snwprintf(), not swprintf() (Ben Noordhuis) - -* fsevents: use FlagNoDefer for FSEventStreamCreate (Fedor Indutny) - -* unix: fix reopened fd bug (Fedor Indutny) - -* core: fix fake watcher list and count preservation (Fedor Indutny) - -* unix: set close-on-exec flag on received fds (Ben Noordhuis) - -* netbsd, openbsd: enable futimes() wrapper (Ben Noordhuis) - -* unix: nicer error message when kqueue() fails (Ben Noordhuis) - -* samples: add socks5 proxy sample application (Ben Noordhuis) - - -2013.11.13, Version 0.10.19 (Stable), 33959f7524090b8d2c6c41e2400ca77e31755059 - -Changes since version 0.10.18: - -* darwin: avoid calling GetCurrentProcess (Fedor Indutny) - -* unix: update events from pevents between polls (Fedor Indutny) - -* fsevents: support japaneese characters in path (Chris Bank) - -* linux: don't turn on SO_REUSEPORT socket option (Ben Noordhuis) - -* build: fix windows smp build with gyp (Geert Jansen) - -* linux: handle EPOLLHUP without EPOLLIN/EPOLLOUT (Ben Noordhuis) - -* unix: fix reopened fd bug (Fedor Indutny) - -* core: fix fake watcher list and count preservation (Fedor Indutny) - - -2013.10.30, Version 0.11.14 (Unstable), d7a6482f45c1b4eb4a853dbe1a9ce8090a35633a - -Changes since version 0.11.13: - -* darwin: create fsevents thread on demand (Ben Noordhuis) - -* fsevents: FSEvents is most likely not thread-safe (Fedor Indutny) - -* fsevents: use shared FSEventStream (Fedor Indutny) - -* windows: make uv_fs_chmod() report errors correctly (Bert Belder) - -* windows: make uv_shutdown() for write-only pipes work (Bert Belder) - -* windows/fs: wrap multi-statement macros in do..while block (Bert Belder) - -* windows/fs: make uv_fs_open() report EINVAL correctly (Bert Belder) - -* windows/fs: handle _open_osfhandle() failure correctly (Bert Belder) - -* windows/fs: wrap multi-statement macros in do..while block (Bert Belder) - -* windows/fs: make uv_fs_open() report EINVAL correctly (Bert Belder) - -* windows/fs: handle _open_osfhandle() failure correctly (Bert Belder) - -* build: clarify instructions for Windows (Brian Kaisner) - -* build: remove GCC_WARN_ABOUT_MISSING_NEWLINE (Ben Noordhuis) - -* darwin: fix 10.6 build error in fsevents.c (Ben Noordhuis) - -* windows: run close callbacks after polling for i/o (Saúl Ibarra Corretgé) - -* include: clarify uv_tcp_bind() behavior (Ben Noordhuis) - -* include: clean up includes in uv.h (Ben Noordhuis) - -* include: remove UV_IO_PRIVATE_FIELDS macro (Ben Noordhuis) - -* include: fix typo in comment in uv.h (Ben Noordhuis) - -* include: update uv_is_active() documentation (Ben Noordhuis) - -* include: make uv_process_options_t.cwd const (Ben Noordhuis) - -* unix: wrap long lines at 80 columns (Ben Noordhuis) - -* unix, windows: make uv_is_*() always return 0 or 1 (Ben Noordhuis) - -* bench: measure total/init/dispatch/cleanup times (Ben Noordhuis) - -* build: use -pthread on sunos (Timothy J. Fontaine) - -* windows: remove duplicate check in stream.c (Ben Noordhuis) - -* unix: sanity-check fds before closing (Ben Noordhuis) - -* unix: remove uv__pipe_accept() (Ben Noordhuis) - -* unix: fix uv_spawn() NULL pointer deref on ENOMEM (Ben Noordhuis) - -* unix: don't close inherited fds on uv_spawn() fail (Ben Noordhuis) - -* unix: revert recent FSEvent changes (Ben Noordhuis) - -* fsevents: fix clever rescheduling (Fedor Indutny) - -* linux: ignore fractional time in uv_uptime() (Ben Noordhuis) - -* unix: fix SIGCHLD waitpid() race in process.c (Ben Noordhuis) - -* unix, windows: add uv_fs_event_start/stop functions (Saúl Ibarra Corretgé) - -* unix: fix non-synchronized access in signal.c (Ben Noordhuis) - -* unix: add atomic-ops.h (Ben Noordhuis) - -* unix: add spinlock.h (Ben Noordhuis) - -* unix: clean up uv_tty_set_mode() a little (Ben Noordhuis) - -* unix: make uv_tty_reset_mode() async signal-safe (Ben Noordhuis) - -* include: add E2BIG status code mapping (Ben Noordhuis) - -* windows: fix duplicate case build error (Ben Noordhuis) - -* windows: remove unneeded check (Saúl Ibarra Corretgé) - -* include: document pipe path truncation behavior (Ben Noordhuis) - -* fsevents: increase stack size for OSX 10.9 (Fedor Indutny) - -* windows: _snprintf expected wrong parameter type in string (Maks Naumov) - -* windows: "else" keyword is missing (Maks Naumov) - -* windows: incorrect check for SOCKET_ERROR (Maks Naumov) - -* windows: add stdlib.h to satisfy reference to abort (Sean Farrell) - -* build: fix check target for mingw (Sean Farrell) - -* unix: move uv_shutdown() assertion (Keno Fischer) - -* darwin: avoid calling GetCurrentProcess (Fedor Indutny) - - -2013.10.19, Version 0.10.18 (Stable), 9ec52963b585e822e87bdc5de28d6143aff0d2e5 - -Changes since version 0.10.17: - -* unix: fix uv_spawn() NULL pointer deref on ENOMEM (Ben Noordhuis) - -* unix: don't close inherited fds on uv_spawn() fail (Ben Noordhuis) - -* unix: revert recent FSEvent changes (Ben Noordhuis) - -* unix: fix non-synchronized access in signal.c (Ben Noordhuis) - - -2013.09.25, Version 0.10.17 (Stable), 9670e0a93540c2f0d86c84a375f2303383c11e7e - -Changes since version 0.10.16: - -* build: remove GCC_WARN_ABOUT_MISSING_NEWLINE (Ben Noordhuis) - -* darwin: fix 10.6 build error in fsevents.c (Ben Noordhuis) - - -2013.09.06, Version 0.10.16 (Stable), 2bce230d81f4853a23662cbeb26fe98010b1084b - -Changes since version 0.10.15: - -* windows: make uv_shutdown() for write-only pipes work (Bert Belder) - -* windows: make uv_fs_open() report EINVAL when invalid arguments are passed - (Bert Belder) - -* windows: make uv_fs_open() report _open_osfhandle() failure correctly (Bert - Belder) - -* windows: make uv_fs_chmod() report errors correctly (Bert Belder) - -* windows: wrap multi-statement macros in do..while block (Bert Belder) - - -2013.09.05, Version 0.11.13 (Unstable), f5b6db6c1d7f93d28281207fd47c3841c9a9792e - -Changes since version 0.11.12: - -* unix: define _GNU_SOURCE, exposes glibc-isms (Ben Noordhuis) - -* windows: check for nonconforming swprintf arguments (Brent Cook) - -* build: include internal headers in source list (Brent Cook) - -* include: merge uv_tcp_bind and uv_tcp_bind6 (Ben Noordhuis) - -* include: merge uv_tcp_connect and uv_tcp_connect6 (Ben Noordhuis) - -* include: merge uv_udp_bind and uv_udp_bind6 (Ben Noordhuis) - -* include: merge uv_udp_send and uv_udp_send6 (Ben Noordhuis) - - -2013.09.03, Version 0.11.12 (Unstable), 82d01d5f6780d178f5176a01425ec297583c0811 - -Changes since version 0.11.11: - -* test: fix epoll_wait() usage in test-embed.c (Ben Noordhuis) - -* include: uv_alloc_cb now takes uv_buf_t* (Ben Noordhuis) - -* include: uv_read{2}_cb now takes const uv_buf_t* (Ben Noordhuis) - -* include: uv_ip[46]_addr now takes sockaddr_in* (Ben Noordhuis) - -* include: uv_tcp_bind{6} now takes sockaddr_in* (Ben Noordhuis) - -* include: uv_tcp_connect{6} now takes sockaddr_in* (Ben Noordhuis) - -* include: uv_udp_recv_cb now takes const uv_buf_t* (Ben Noordhuis) - -* include: uv_udp_bind{6} now takes sockaddr_in* (Ben Noordhuis) - -* include: uv_udp_send{6} now takes sockaddr_in* (Ben Noordhuis) - -* include: uv_spawn takes const uv_process_options_t* (Ben Noordhuis) - -* include: make uv_write{2} const correct (Ben Noordhuis) - -* windows: fix flags assignment in uv_fs_readdir() (Ben Noordhuis) - -* windows: fix stray comments (Ben Noordhuis) - -* windows: remove unused is_path_dir() function (Ben Noordhuis) - - -2013.08.30, Version 0.11.11 (Unstable), ba876d53539ed0427c52039012419cd9374c6f0d - -Changes since version 0.11.10: - -* unix, windows: add thread-local storage API (Ben Noordhuis) - -* linux: don't turn on SO_REUSEPORT socket option (Ben Noordhuis) - -* darwin: fix 10.6 build error in fsevents.c (Ben Noordhuis) - -* windows: make uv_shutdown() for write-only pipes work (Bert Belder) - -* include: update uv_udp_open() / uv_udp_bind() docs (Ben Noordhuis) - -* unix: req queue must be empty when destroying loop (Ben Noordhuis) - -* unix: move loop functions from core.c to loop.c (Ben Noordhuis) - -* darwin: remove CoreFoundation dependency (Ben Noordhuis) - -* windows: make autotools build system work with mingw (Keno Fischer) - -* windows: fix mingw build (Alex Crichton) - -* windows: tweak Makefile.mingw for easier usage (Alex Crichton) - -* build: remove _GNU_SOURCE macro definition (Ben Noordhuis) - - -2013.08.25, Version 0.11.10 (Unstable), 742dadcb7154cc7bb89c0c228a223b767a36cf0d - -* windows: Re-implement uv_fs_stat. The st_ctime field now contains the change - time, not the creation time, like on unix systems. st_dev, st_ino, st_blocks - and st_blksize are now also filled out. (Bert Belder) - -* linux: fix setsockopt(SO_REUSEPORT) error handling (Ben Noordhuis) - -* windows: report uv_process_t exit code correctly (Bert Belder) - -* windows: make uv_fs_chmod() report errors correctly (Bert Belder) - -* windows: make some more NT apis available for libuv's internal use (Bert - Belder) - -* windows: squelch some compiler warnings (Bert Belder) - - -2013.08.24, Version 0.11.9 (Unstable), a2d29b5b068cbac93dc16138fb30a74e2669daad - -Changes since version 0.11.8: - -* fsevents: share FSEventStream between multiple FS watchers, which removes a - limit on the maximum number of file watchers that can be created on OS X. - (Fedor Indutny) - -* process: the `exit_status` parameter for a uv_process_t's exit callback now - is an int64_t, and no longer an int. (Bert Belder) - -* process: make uv_spawn() return some types of errors immediately on windows, - instead of passing the error code the the exit callback. This brings it on - par with libuv's behavior on unix. (Bert Belder) - - -2013.08.24, Version 0.10.15 (Stable), 221078a8fdd9b853c6b557b3d9a5dd744b4fdd6b - -Changes since version 0.10.14: - -* fsevents: create FSEvents thread on demand (Ben Noordhuis) - -* fsevents: use a single thread for interacting with FSEvents, because it's not - thread-safe. (Fedor Indutny) - -* fsevents: share FSEventStream between multiple FS watchers, which removes a - limit on the maximum number of file watchers that can be created on OS X. - (Fedor Indutny) - - -2013.08.22, Version 0.11.8 (Unstable), a5260462db80ab0deab6b9e6a8991dd8f5a9a2f8 - -Changes since version 0.11.7: - -* unix: fix missing return value warning in stream.c (Ben Noordhuis) - -* build: serial-tests was added in automake v1.12 (Ben Noordhuis) - -* windows: fix uninitialized local variable warning (Ben Noordhuis) - -* windows: fix missing return value warning (Ben Noordhuis) - -* build: fix string comparisons in autogen.sh (Ben Noordhuis) - -* windows: move INLINE macro, remove UNUSED (Ben Noordhuis) - -* unix: clean up __attribute__((quux)) usage (Ben Noordhuis) - -* sunos: remove futimes() macro (Ben Noordhuis) - -* unix: fix uv__signal_unlock() prototype (Ben Noordhuis) - -* unix, windows: allow NULL async callback (Ben Noordhuis) - -* build: apply dtrace -G to all object files (Timothy J. Fontaine) - -* darwin: fix indentation in uv__hrtime() (Ben Noordhuis) - -* darwin: create fsevents thread on demand (Ben Noordhuis) - -* darwin: reduce fsevents thread stack size (Ben Noordhuis) - -* darwin: call pthread_setname_np() if available (Ben Noordhuis) - -* build: fix automake serial-tests check again (Ben Noordhuis) - -* unix: retry waitpid() on EINTR (Ben Noordhuis) - -* darwin: fix ios build error (Ben Noordhuis) - -* darwin: fix ios compiler warning (Ben Noordhuis) - -* test: simplify test-ip6-addr.c (Ben Noordhuis) - -* unix, windows: fix ipv6 link-local address parsing (Ben Noordhuis) - -* fsevents: FSEvents is most likely not thread-safe (Fedor Indutny) - -* windows: omit stdint.h, fix msvc 2008 build error (Ben Noordhuis) - - -2013.08.22, Version 0.10.14 (Stable), 15d64132151c18b26346afa892444b95e2addad0 - -Changes since version 0.10.13: - -* unix: retry waitpid() on EINTR (Ben Noordhuis) - - -2013.08.07, Version 0.11.7 (Unstable), 3cad361f8776f70941b39d65bd9426bcb1aa817b - -Changes since version 0.11.6: - -* unix, windows: fix uv_fs_chown() function prototype (Ben Noordhuis) - -* unix, windows: remove unused variables (Brian White) - -* test: fix signed/unsigned comparison warnings (Ben Noordhuis) - -* build: dtrace shouldn't break out of tree builds (Timothy J. Fontaine) - -* unix, windows: don't read/recv if buf.len==0 (Ben Noordhuis) - -* build: add mingw makefile (Ben Noordhuis) - -* unix, windows: add MAC to uv_interface_addresses() (Brian White) - -* build: enable AM_INIT_AUTOMAKE([subdir-objects]) (Ben Noordhuis) - -* unix, windows: make buf arg to uv_fs_write const (Ben Noordhuis) - -* sunos: fix build breakage introduced in e3a657c (Ben Noordhuis) - -* aix: fix build breakage introduced in 3ee4d3f (Ben Noordhuis) - -* windows: fix mingw32 build, define JOB_OBJECT_XXX (Yasuhiro Matsumoto) - -* windows: fix mingw32 build, include limits.h (Yasuhiro Matsumoto) - -* test: replace sprintf() with snprintf() (Ben Noordhuis) - -* test: replace strcpy() with strncpy() (Ben Noordhuis) - -* openbsd: fix uv_ip6_addr() unused variable warnings (Ben Noordhuis) - -* openbsd: fix dlerror() const correctness warning (Ben Noordhuis) - -* openbsd: fix uv_fs_sendfile() unused variable warnings (Ben Noordhuis) - -* build: disable parallel automake tests (Ben Noordhuis) - -* test: add windows-only snprintf() function (Ben Noordhuis) - -* build: add automake serial-tests version check (Ben Noordhuis) - - -2013.07.26, Version 0.10.13 (Stable), 381312e1fe6fecbabc943ccd56f0e7d114b3d064 - -Changes since version 0.10.12: - -* unix, windows: fix uv_fs_chown() function prototype (Ben Noordhuis) - - -2013.07.21, Version 0.11.6 (Unstable), 6645b93273e0553d23823c576573b82b129bf28c - -Changes since version 0.11.5: - -* test: open stdout fd in write-only mode (Ben Noordhuis) - -* windows: uv_spawn shouldn't reject reparse points (Bert Belder) - -* windows: use WSAGetLastError(), not errno (Ben Noordhuis) - -* build: darwin: disable -fstrict-aliasing warnings (Ben Noordhuis) - -* test: fix signed/unsigned compiler warning (Ben Noordhuis) - -* test: add 'start timer from check handle' test (Ben Noordhuis) - -* build: `all` now builds static and dynamic lib (Ben Noordhuis) - -* unix, windows: add extra fields to uv_stat_t (Saúl Ibarra Corretgé) - -* build: add install target to the makefile (Navaneeth Kedaram Nambiathan) - -* build: switch to autotools (Ben Noordhuis) - -* build: use AM_PROG_AR conditionally (Ben Noordhuis) - -* test: fix fs_fstat test on sunos (Ben Noordhuis) - -* test: fix fs_chown when running as root (Ben Noordhuis) - -* test: fix spawn_setgid_fails and spawn_setuid_fails (Ben Noordhuis) - -* build: use AM_SILENT_RULES conditionally (Ben Noordhuis) - -* build: add DTrace detection for autotools (Timothy J. Fontaine) - -* linux,darwin,win: link-local IPv6 addresses (Miroslav Bajtoš) - -* unix: fix build when !defined(PTHREAD_MUTEX_ERRORCHECK) (Ben Noordhuis) - -* unix, windows: return error codes directly (Ben Noordhuis) - - -2013.07.10, Version 0.10.12 (Stable), 58a46221bba726746887a661a9f36fe9ff204209 - -Changes since version 0.10.11: - -* linux: add support for MIPS (Andrei Sedoi) - -* windows: uv_spawn shouldn't reject reparse points (Bert Belder) - -* windows: use WSAGetLastError(), not errno (Ben Noordhuis) - -* build: darwin: disable -fstrict-aliasing warnings (Ben Noordhuis) - -* build: `all` now builds static and dynamic lib (Ben Noordhuis) - -* unix: fix build when !defined(PTHREAD_MUTEX_ERRORCHECK) (Ben Noordhuis) - - -2013.06.27, Version 0.11.5 (Unstable), e3c63ff1627a14e96f54c1c62b0d68b446d8425b - -Changes since version 0.11.4: - -* build: remove CSTDFLAG, use only CFLAGS (Ben Noordhuis) - -* unix: support for android builds (Linus Mårtensson) - -* unix: avoid extra read, short-circuit on POLLHUP (Ben Noordhuis) - -* uv: support android libuv standalone build (Linus Mårtensson) - -* src: make queue.h c++ compatible (Ben Noordhuis) - -* unix: s/ngx-queue.h/queue.h/ in checksparse.sh (Ben Noordhuis) - -* unix: unconditionally stop handle on close (Ben Noordhuis) - -* freebsd: don't enable dtrace if it's not available (Brian White) - -* build: make HAVE_DTRACE=0 should disable dtrace (Timothy J. Fontaine) - -* unix: remove overzealous assert (Ben Noordhuis) - -* unix: remove unused function uv_fatal_error() (Ben Noordhuis) - -* unix, windows: clean up uv_thread_create() (Ben Noordhuis) - -* queue: fix pointer truncation on LLP64 platforms (Bert Belder) - -* build: set OS=="android" for android builds (Linus Mårtensson) - -* windows: don't use uppercase in include filename (Ben Noordhuis) - -* stream: add an API to make streams do blocking writes (Henry Rawas) - -* windows: use WSAGetLastError(), not errno (Ben Noordhuis) - - -2013.06.13, Version 0.10.11 (Stable), c3b75406a66a10222a589cb173e8f469e9665c7e - -Changes since version 0.10.10: - -* unix: unconditionally stop handle on close (Ben Noordhuis) - -* freebsd: don't enable dtrace if it's not available (Brian White) - -* build: make HAVE_DTRACE=0 should disable dtrace (Timothy J. Fontaine) - -* unix: remove overzealous assert (Ben Noordhuis) - -* unix: clear UV_STREAM_SHUTTING after shutdown() (Ben Noordhuis) - -* unix: fix busy loop, write if POLLERR or POLLHUP (Ben Noordhuis) - - -2013.06.05, Version 0.10.10 (Stable), 0d95a88bd35fce93863c57a460be613aea34d2c5 - -Changes since version 0.10.9: - -* include: document uv_update_time() and uv_now() (Ben Noordhuis) - -* linux: fix cpu model parsing on newer arm kernels (Ben Noordhuis) - -* linux: fix a memory leak in uv_cpu_info() error path (Ben Noordhuis) - -* linux: don't ignore out-of-memory errors in uv_cpu_info() (Ben Noordhuis) - -* unix, windows: move uv_now() to uv-common.c (Ben Noordhuis) - -* test: fix a compilation problem in test-osx-select.c that was caused by the - use of c-style comments (Bert Belder) - -* darwin: use uv_fs_sendfile() use the sendfile api correctly (Wynn Wilkes) - - -2013.05.30, Version 0.11.4 (Unstable), e43e5b3d954a0989db5588aa110e1fe4fe6e0219 - -Changes since version 0.11.3: - -* windows: make uv_spawn not fail when the libuv embedding application is run - under external job control (Bert Belder) - -* darwin: assume CFRunLoopStop() isn't thread-safe, fixing a race condition - when stopping the 'stdin select hack' thread (Fedor Indutny) - -* win: fix UV_EALREADY not being reported correctly to the libuv user in some - cases (Bert Belder) - -* darwin: make the uv__cf_loop_runner and uv__cf_loop_cb functions static (Ben - Noordhuis) - -* darwin: task_info() cannot fail (Ben Noordhuis) - -* unix: add error mapping for ENETDOWN (Ben Noordhuis) - -* unix: implicitly signal write errors to the libuv user (Ben Noordhuis) - -* unix: fix assertion error on signal pipe overflow (Bert Belder) - -* unix: turn off POLLOUT after stream connect (Ben Noordhuis) - -* unix: fix stream refcounting buglet (Ben Noordhuis) - -* unix: remove assert statements that are no longer correct (Ben Noordhuis) - -* unix: appease warning about non-standard `inline` (Sean Silva) - -* unix: add uv__is_closing() macro (Ben Noordhuis) - -* unix: stop stream POLLOUT watcher on write error (Ben Noordhuis) - -* include: document uv_update_time() and uv_now() (Ben Noordhuis) - -* linux: fix cpu model parsing on newer arm kernels (Ben Noordhuis) - -* linux: fix a memory leak in uv_cpu_info() error path (Ben Noordhuis) - -* linux: don't ignore out-of-memory errors in uv_cpu_info() (Ben Noordhuis) - -* unix, windows: move uv_now() to uv-common.c (Ben Noordhuis) - -* test: fix a compilation problem in test-osx-select.c that was caused by the - use of c-style comments (Bert Belder) - -* darwin: use uv_fs_sendfile() use the sendfile api correctly (Wynn Wilkes) - -* windows: call idle handles on every loop iteration, something the unix - implementation already did (Bert Belder) - -* test: update the idle-starvation test to verify that idle handles are called - in every loop iteration (Bert Belder) - -* unix, windows: ensure that uv_run() in RUN_ONCE mode calls timers that expire - after blocking (Ben Noordhuis) - - -2013.05.29, Version 0.10.9 (Stable), a195f9ace23d92345baf57582678bfc3017e6632 - -Changes since version 0.10.8: - -* unix: fix stream refcounting buglet (Ben Noordhuis) - -* unix: remove erroneous asserts (Ben Noordhuis) - -* unix: add uv__is_closing() macro (Ben Noordhuis) - -* unix: stop stream POLLOUT watcher on write error (Ben Noordhuis) - - -2013.05.25, Version 0.10.8 (Stable), 0f39be12926fe2d8766a9f025797a473003e6504 - -Changes since version 0.10.7: - -* windows: make uv_spawn not fail under job control (Bert Belder) - -* darwin: assume CFRunLoopStop() isn't thread-safe (Fedor Indutny) - -* win: fix UV_EALREADY incorrectly set (Bert Belder) - -* darwin: make two uv__cf_*() functions static (Ben Noordhuis) - -* darwin: task_info() cannot fail (Ben Noordhuis) - -* unix: add mapping for ENETDOWN (Ben Noordhuis) - -* unix: implicitly signal write errors to libuv user (Ben Noordhuis) - -* unix: fix assert on signal pipe overflow (Bert Belder) - -* unix: turn off POLLOUT after stream connect (Ben Noordhuis) - - -2013.05.16, Version 0.11.3 (Unstable), 0a48c05b5988aea84c605751900926fa25443b34 - -Changes since version 0.11.2: - -* unix: clean up uv_accept() (Ben Noordhuis) - -* unix: remove errno preserving code (Ben Noordhuis) - -* darwin: fix ios build, don't require ApplicationServices (Ben Noordhuis) - -* windows: kill child processes when the parent dies (Bert Belder) - -* build: set soname in shared library (Ben Noordhuis) - -* build: make `make test` link against .a again (Ben Noordhuis) - -* build: only set soname on shared object builds (Timothy J. Fontaine) - -* build: convert predefined $PLATFORM to lower case (Elliot Saba) - -* test: fix process_title failing on linux (Miroslav Bajtoš) - -* test, sunos: disable process_title test (Miroslav Bajtoš) - -* test: add error logging to tty unit test (Miroslav Bajtoš) - - -2013.05.15, Version 0.10.7 (Stable), 028baaf0846b686a81e992cb2f2f5a9b8e841fcf - -Changes since version 0.10.6: - -* windows: kill child processes when the parent dies (Bert Belder) - - -2013.05.15, Version 0.10.6 (Stable), 11e6613e6260d95c8cf11bf89a2759c24649319a - -Changes since version 0.10.5: - -* stream: fix osx select hack (Fedor Indutny) - -* stream: fix small nit in select hack, add test (Fedor Indutny) - -* build: link with libkvm on openbsd (Ben Noordhuis) - -* stream: use harder sync restrictions for osx-hack (Fedor Indutny) - -* unix: fix EMFILE error handling (Ben Noordhuis) - -* darwin: fix unnecessary include headers (Daisuke Murase) - -* darwin: rename darwin-getproctitle.m (Ben Noordhuis) - -* build: convert predefined $PLATFORM to lower case (Elliot Saba) - -* build: set soname in shared library (Ben Noordhuis) - -* build: make `make test` link against .a again (Ben Noordhuis) - -* darwin: fix ios build, don't require ApplicationServices (Ben Noordhuis) - -* build: only set soname on shared object builds (Timothy J. Fontaine) - - -2013.05.11, Version 0.11.2 (Unstable), 3fba0bf65f091b91a9760530c05c6339c658d88b - -Changes since version 0.11.1: - -* darwin: look up file path with F_GETPATH (Ben Noordhuis) - -* unix, windows: add uv_has_ref() function (Saúl Ibarra Corretgé) - -* build: avoid double / in paths for dtrace (Timothy J. Fontaine) - -* unix: remove src/unix/cygwin.c (Ben Noordhuis) - -* windows: deal with the fact that GetTickCount might lag (Bert Belder) - -* unix: silence STATIC_ASSERT compiler warnings (Ben Noordhuis) - -* linux: don't use fopen() in uv_resident_set_memory() (Ben Noordhuis) - - -2013.04.24, Version 0.10.5 (Stable), 6595a7732c52eb4f8e57c88655f72997a8567a67 - -Changes since version 0.10.4: - -* unix: silence STATIC_ASSERT compiler warnings (Ben Noordhuis) - -* windows: make timers handle large timeouts (Miroslav Bajtoš) - -* windows: remove superfluous assert statement (Bert Belder) - -* unix: silence STATIC_ASSERT compiler warnings (Ben Noordhuis) - -* linux: don't use fopen() in uv_resident_set_memory() (Ben Noordhuis) - - -2013.04.12, Version 0.10.4 (Stable), 85827e26403ac6dfa331af8ec9916ea7e27bd833 - -Changes since version 0.10.3: - -* include: update uv_backend_fd() documentation (Ben Noordhuis) - -* unix: include uv.h in src/version.c (Ben Noordhuis) - -* unix: don't write more than IOV_MAX iovecs (Fedor Indutny) - -* mingw-w64: don't call _set_invalid_parameter_handler (Nils Maier) - -* build: gyp disable thin archives (Timothy J. Fontaine) - -* sunos: re-export entire library when static (Timothy J. Fontaine) - -* unix: dtrace probes for tick-start and tick-stop (Timothy J. Fontaine) - -* windows: fix memory leak in fs__sendfile (Shannen Saez) - -* windows: remove double initialization in uv_tty_init (Shannen Saez) - -* build: fix dtrace-enabled out of tree build (Ben Noordhuis) - -* build: squelch -Wdollar-in-identifier-extension warnings (Ben Noordhuis) - -* inet: snprintf returns int, not size_t (Brian White) - -* win: refactor uv_cpu_info (Bert Belder) - -* build: add support for Visual Studio 2012 (Nicholas Vavilov) - -* build: -Wno-dollar-in-identifier-extension is clang only (Ben Noordhuis) - - -2013.04.11, Version 0.11.1 (Unstable), 5c10e82ae0bc99eff86d4b9baff1f1aa0bf84c0a - -This is the first versioned release from the current unstable libuv branch. - -Changes since Node.js v0.11.0: - -* all platforms: nanosecond resolution support for uv_fs_[fl]stat (Timothy J. - Fontaine) - -* all platforms: add netmask to uv_interface_address (Ben Kelly) - -* unix: make sure the `status` parameter passed to the `uv_getaddrinfo` is 0 or - -1 (Ben Noordhuis) - -* unix: limit the number of iovecs written in a single `writev` syscall to - IOV_MAX (Fedor Indutny) - -* unix: add dtrace probes for tick-start and tick-stop (Timothy J. Fontaine) - -* mingw-w64: don't call _set_invalid_parameter_handler (Nils Maier) - -* windows: fix memory leak in fs__sendfile (Shannen Saez) - -* windows: fix edge case bugs in uv_cpu_info (Bert Belder) - -* include: no longer ship with / include ngx-queue.h (Ben Noordhuis) - -* include: remove UV_VERSION_* macros from uv.h (Ben Noordhuis) - -* documentation updates (Kristian Evensen, Ben Kelly, Ben Noordhuis) - -* build: fix dtrace-enabled builds (Ben Noordhuis, Timothy J. Fontaine) - -* build: gyp disable thin archives (Timothy J. Fontaine) - -* build: add support for Visual Studio 2012 (Nicholas Vavilov) - - -2013.03.28, Version 0.10.3 (Stable), 31ebe23973dd98fd8a24c042b606f37a794e99d0 - -Changes since version 0.10.2: - -* include: remove extraneous const from uv_version() (Ben Noordhuis) - -* doc: update README, replace `OS` by `PLATFORM` (Ben Noordhuis) - -* build: simplify .buildstamp rule (Ben Noordhuis) - -* build: disable -Wstrict-aliasing on darwin (Ben Noordhuis) - -* darwin: don't select(&exceptfds) in fallback path (Ben Noordhuis) - -* unix: don't clear flags after closing UDP handle (Saúl Ibarra Corretgé) - - -2013.03.25, Version 0.10.2 (Stable), 0f36a00568f3e7608f97f6c6cdb081f4800a50c9 - -This is the first officially versioned release of libuv. Starting now -libuv will make releases independently of Node.js. - -Changes since Node.js v0.10.0: - -* test: add tap output for windows (Timothy J. Fontaine) - -* unix: fix uv_tcp_simultaneous_accepts() logic (Ben Noordhuis) - -* include: bump UV_VERSION_MINOR (Ben Noordhuis) - -* unix: improve uv_guess_handle() implementation (Ben Noordhuis) - -* stream: run try_select only for pipes and ttys (Fedor Indutny) - -Changes since Node.js v0.10.1: - -* build: rename OS to PLATFORM (Ben Noordhuis) - -* unix: make uv_timer_init() initialize repeat (Brian Mazza) - -* unix: make timers handle large timeouts (Ben Noordhuis) - -* build: add OBJC makefile var (Ben Noordhuis) - -* Add `uv_version()` and `uv_version_string()` APIs (Bert Belder) diff --git a/vendor/libuv/LICENSE b/vendor/libuv/LICENSE deleted file mode 100644 index 41ba44c28..000000000 --- a/vendor/libuv/LICENSE +++ /dev/null @@ -1,70 +0,0 @@ -libuv is licensed for use as follows: - -==== -Copyright (c) 2015-present libuv project contributors. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to -deal in the Software without restriction, including without limitation the -rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -sell copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -IN THE SOFTWARE. -==== - -This license applies to parts of libuv originating from the -https://github.com/joyent/libuv repository: - -==== - -Copyright Joyent, Inc. and other Node contributors. All rights reserved. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to -deal in the Software without restriction, including without limitation the -rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -sell copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -IN THE SOFTWARE. - -==== - -This license applies to all parts of libuv that are not externally -maintained libraries. - -The externally maintained libraries used by libuv are: - - - tree.h (from FreeBSD), copyright Niels Provos. Two clause BSD license. - - - inet_pton and inet_ntop implementations, contained in src/inet.c, are - copyright the Internet Systems Consortium, Inc., and licensed under the ISC - license. - - - stdint-msvc2008.h (from msinttypes), copyright Alexander Chemeris. Three - clause BSD license. - - - pthread-fixes.h, pthread-fixes.c, copyright Google Inc. and Sony Mobile - Communications AB. Three clause BSD license. - - - android-ifaddrs.h, android-ifaddrs.c, copyright Berkeley Software Design - Inc, Kenneth MacKay and Emergya (Cloud4all, FP7/2007-2013, grant agreement - n° 289016). Three clause BSD license. diff --git a/vendor/libuv/MAINTAINERS.md b/vendor/libuv/MAINTAINERS.md deleted file mode 100644 index 27a3523ea..000000000 --- a/vendor/libuv/MAINTAINERS.md +++ /dev/null @@ -1,42 +0,0 @@ - -# Project Maintainers - -libuv is currently managed by the following individuals: - -* **Ben Noordhuis** ([@bnoordhuis](https://github.com/bnoordhuis)) - - GPG key: D77B 1E34 243F BAF0 5F8E 9CC3 4F55 C8C8 46AB 89B9 (pubkey-bnoordhuis) -* **Bert Belder** ([@piscisaureus](https://github.com/piscisaureus)) -* **Colin Ihrig** ([@cjihrig](https://github.com/cjihrig)) - - GPG key: 94AE 3667 5C46 4D64 BAFA 68DD 7434 390B DBE9 B9C5 (pubkey-cjihrig) - - GPG key: 5735 3E0D BDAA A7E8 39B6 6A1A FF47 D5E4 AD8B 4FDC (pubkey-cjihrig-kb) -* **Fedor Indutny** ([@indutny](https://github.com/indutny)) - - GPG key: AF2E EA41 EC34 47BF DD86 FED9 D706 3CCE 19B7 E890 (pubkey-indutny) -* **Imran Iqbal** ([@iWuzHere](https://github.com/iWuzHere)) - - GPG key: 9DFE AA5F 481B BF77 2D90 03CE D592 4925 2F8E C41A (pubkey-iwuzhere) -* **Santiago Gimeno** ([@santigimeno](https://github.com/santigimeno)) - - GPG key: 612F 0EAD 9401 6223 79DF 4402 F28C 3C8D A33C 03BE (pubkey-santigimeno) -* **Saúl Ibarra Corretgé** ([@saghul](https://github.com/saghul)) - - GPG key: FDF5 1936 4458 319F A823 3DC9 410E 5553 AE9B C059 (pubkey-saghul) - -## Storing a maintainer key in Git - -It's quite handy to store a maintainer's signature as a git blob, and have -that object tagged and signed with such key. - -Export your public key: - - $ gpg --armor --export saghul@gmail.com > saghul.asc - -Store it as a blob on the repo: - - $ git hash-object -w saghul.asc - -The previous command returns a hash, copy it. For the sake of this explanation, -we'll assume it's 'abcd1234'. Storing the blob in git is not enough, it could -be garbage collected since nothing references it, so we'll create a tag for it: - - $ git tag -s pubkey-saghul abcd1234 - -Commit the changes and push: - - $ git push origin pubkey-saghul diff --git a/vendor/libuv/Makefile.am b/vendor/libuv/Makefile.am deleted file mode 100644 index 036464e71..000000000 --- a/vendor/libuv/Makefile.am +++ /dev/null @@ -1,418 +0,0 @@ -# Copyright (c) 2013, Ben Noordhuis -# -# Permission to use, copy, modify, and/or distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -ACLOCAL_AMFLAGS = -I m4 - -AM_CPPFLAGS = -I$(top_srcdir)/include \ - -I$(top_srcdir)/src - -include_HEADERS=include/uv.h include/uv-errno.h include/uv-threadpool.h include/uv-version.h - -CLEANFILES = - -lib_LTLIBRARIES = libuv.la -libuv_la_CFLAGS = @CFLAGS@ -libuv_la_LDFLAGS = -no-undefined -version-info 1:0:0 -libuv_la_SOURCES = src/fs-poll.c \ - src/heap-inl.h \ - src/inet.c \ - src/queue.h \ - src/threadpool.c \ - src/uv-common.c \ - src/uv-common.h \ - src/version.c - -if SUNOS -# Can't be turned into a CC_CHECK_CFLAGS in configure.ac, it makes compilers -# on other platforms complain that the argument is unused during compilation. -libuv_la_CFLAGS += -pthreads -endif - -if WINNT - -include_HEADERS += include/uv-win.h include/tree.h -AM_CPPFLAGS += -I$(top_srcdir)/src/win \ - -DWIN32_LEAN_AND_MEAN \ - -D_WIN32_WINNT=0x0600 -libuv_la_SOURCES += src/win/async.c \ - src/win/atomicops-inl.h \ - src/win/core.c \ - src/win/detect-wakeup.c \ - src/win/dl.c \ - src/win/error.c \ - src/win/fs-event.c \ - src/win/fs.c \ - src/win/getaddrinfo.c \ - src/win/getnameinfo.c \ - src/win/handle.c \ - src/win/handle-inl.h \ - src/win/internal.h \ - src/win/loop-watcher.c \ - src/win/pipe.c \ - src/win/poll.c \ - src/win/process-stdio.c \ - src/win/process.c \ - src/win/req.c \ - src/win/req-inl.h \ - src/win/signal.c \ - src/win/stream.c \ - src/win/stream-inl.h \ - src/win/tcp.c \ - src/win/thread.c \ - src/win/timer.c \ - src/win/tty.c \ - src/win/udp.c \ - src/win/util.c \ - src/win/winapi.c \ - src/win/winapi.h \ - src/win/winsock.c \ - src/win/winsock.h - -else # WINNT - -include_HEADERS += include/uv-unix.h -AM_CPPFLAGS += -I$(top_srcdir)/src/unix -libuv_la_SOURCES += src/unix/async.c \ - src/unix/atomic-ops.h \ - src/unix/core.c \ - src/unix/dl.c \ - src/unix/fs.c \ - src/unix/getaddrinfo.c \ - src/unix/getnameinfo.c \ - src/unix/internal.h \ - src/unix/loop-watcher.c \ - src/unix/loop.c \ - src/unix/pipe.c \ - src/unix/poll.c \ - src/unix/process.c \ - src/unix/signal.c \ - src/unix/spinlock.h \ - src/unix/stream.c \ - src/unix/tcp.c \ - src/unix/thread.c \ - src/unix/timer.c \ - src/unix/tty.c \ - src/unix/udp.c - -endif # WINNT - -EXTRA_DIST = test/fixtures/empty_file \ - test/fixtures/load_error.node \ - include \ - test \ - docs \ - img \ - samples \ - android-configure \ - CONTRIBUTING.md \ - LICENSE \ - README.md \ - checksparse.sh \ - vcbuild.bat \ - Makefile.mingw \ - common.gypi \ - gyp_uv.py \ - uv.gyp - - - -TESTS = test/run-tests -check_PROGRAMS = test/run-tests -if OS390 -test_run_tests_CFLAGS = -else -test_run_tests_CFLAGS = -Wno-long-long -endif - -if SUNOS -# Can't be turned into a CC_CHECK_CFLAGS in configure.ac, it makes compilers -# on other platforms complain that the argument is unused during compilation. -test_run_tests_CFLAGS += -pthreads -endif - -test_run_tests_LDFLAGS = -test_run_tests_SOURCES = test/blackhole-server.c \ - test/dns-server.c \ - test/echo-server.c \ - test/run-tests.c \ - test/runner.c \ - test/runner.h \ - test/task.h \ - test/test-active.c \ - test/test-async.c \ - test/test-async-null-cb.c \ - test/test-barrier.c \ - test/test-callback-order.c \ - test/test-callback-stack.c \ - test/test-close-fd.c \ - test/test-close-order.c \ - test/test-condvar.c \ - test/test-connection-fail.c \ - test/test-cwd-and-chdir.c \ - test/test-default-loop-close.c \ - test/test-delayed-accept.c \ - test/test-dlerror.c \ - test/test-eintr-handling.c \ - test/test-embed.c \ - test/test-emfile.c \ - test/test-error.c \ - test/test-fail-always.c \ - test/test-fs-event.c \ - test/test-fs-poll.c \ - test/test-fs.c \ - test/test-get-currentexe.c \ - test/test-get-loadavg.c \ - test/test-get-memory.c \ - test/test-get-passwd.c \ - test/test-getaddrinfo.c \ - test/test-getnameinfo.c \ - test/test-getsockname.c \ - test/test-handle-fileno.c \ - test/test-homedir.c \ - test/test-hrtime.c \ - test/test-idle.c \ - test/test-ip4-addr.c \ - test/test-ip6-addr.c \ - test/test-ipc-send-recv.c \ - test/test-ipc.c \ - test/test-list.h \ - test/test-loop-handles.c \ - test/test-loop-alive.c \ - test/test-loop-close.c \ - test/test-loop-stop.c \ - test/test-loop-time.c \ - test/test-loop-configure.c \ - test/test-multiple-listen.c \ - test/test-mutexes.c \ - test/test-osx-select.c \ - test/test-pass-always.c \ - test/test-ping-pong.c \ - test/test-pipe-bind-error.c \ - test/test-pipe-connect-error.c \ - test/test-pipe-connect-multiple.c \ - test/test-pipe-connect-prepare.c \ - test/test-pipe-getsockname.c \ - test/test-pipe-pending-instances.c \ - test/test-pipe-sendmsg.c \ - test/test-pipe-server-close.c \ - test/test-pipe-close-stdout-read-stdin.c \ - test/test-pipe-set-non-blocking.c \ - test/test-platform-output.c \ - test/test-poll-close.c \ - test/test-poll-close-doesnt-corrupt-stack.c \ - test/test-poll-closesocket.c \ - test/test-poll.c \ - test/test-process-title.c \ - test/test-queue-foreach-delete.c \ - test/test-ref.c \ - test/test-run-nowait.c \ - test/test-run-once.c \ - test/test-semaphore.c \ - test/test-shutdown-close.c \ - test/test-shutdown-eof.c \ - test/test-shutdown-twice.c \ - test/test-signal-multiple-loops.c \ - test/test-signal.c \ - test/test-socket-buffer-size.c \ - test/test-spawn.c \ - test/test-stdio-over-pipes.c \ - test/test-tcp-alloc-cb-fail.c \ - test/test-tcp-bind-error.c \ - test/test-tcp-bind6-error.c \ - test/test-tcp-close-accept.c \ - test/test-tcp-close-while-connecting.c \ - test/test-tcp-close.c \ - test/test-tcp-create-socket-early.c \ - test/test-tcp-connect-error-after-write.c \ - test/test-tcp-connect-error.c \ - test/test-tcp-connect-timeout.c \ - test/test-tcp-connect6-error.c \ - test/test-tcp-flags.c \ - test/test-tcp-open.c \ - test/test-tcp-read-stop.c \ - test/test-tcp-shutdown-after-write.c \ - test/test-tcp-unexpected-read.c \ - test/test-tcp-oob.c \ - test/test-tcp-write-to-half-open-connection.c \ - test/test-tcp-write-after-connect.c \ - test/test-tcp-writealot.c \ - test/test-tcp-write-fail.c \ - test/test-tcp-try-write.c \ - test/test-tcp-write-queue-order.c \ - test/test-thread-equal.c \ - test/test-thread.c \ - test/test-threadpool-cancel.c \ - test/test-threadpool.c \ - test/test-timer-again.c \ - test/test-timer-from-check.c \ - test/test-timer.c \ - test/test-tmpdir.c \ - test/test-tty.c \ - test/test-udp-alloc-cb-fail.c \ - test/test-udp-bind.c \ - test/test-udp-create-socket-early.c \ - test/test-udp-dgram-too-big.c \ - test/test-udp-ipv6.c \ - test/test-udp-multicast-interface.c \ - test/test-udp-multicast-interface6.c \ - test/test-udp-multicast-join.c \ - test/test-udp-multicast-join6.c \ - test/test-udp-multicast-ttl.c \ - test/test-udp-open.c \ - test/test-udp-options.c \ - test/test-udp-send-and-recv.c \ - test/test-udp-send-immediate.c \ - test/test-udp-send-unreachable.c \ - test/test-udp-try-send.c \ - test/test-walk-handles.c \ - test/test-watcher-cross-stop.c -test_run_tests_LDADD = libuv.la - -if WINNT -test_run_tests_SOURCES += test/runner-win.c \ - test/runner-win.h -else -test_run_tests_SOURCES += test/runner-unix.c \ - test/runner-unix.h -endif - -if AIX -test_run_tests_CFLAGS += -D_ALL_SOURCE -D_XOPEN_SOURCE=500 -D_LINUX_SOURCE_COMPAT -endif - -if LINUX -test_run_tests_CFLAGS += -D_GNU_SOURCE -endif - -if SUNOS -test_run_tests_CFLAGS += -D__EXTENSIONS__ -D_XOPEN_SOURCE=500 -endif - -if OS390 -test_run_tests_CFLAGS += -D_UNIX03_THREADS \ - -D_UNIX03_SOURCE \ - -D_OPEN_SYS_IF_EXT=1 \ - -D_OPEN_SYS_SOCK_IPV6 \ - -D_OPEN_MSGQ_EXT \ - -D_XOPEN_SOURCE_EXTENDED \ - -D_ALL_SOURCE \ - -D_LARGE_TIME_API \ - -D_OPEN_SYS_FILE_EXT \ - -DPATH_MAX=255 \ - -qCHARS=signed \ - -qXPLINK \ - -qFLOAT=IEEE -endif - -if AIX -libuv_la_CFLAGS += -D_ALL_SOURCE \ - -D_XOPEN_SOURCE=500 \ - -D_LINUX_SOURCE_COMPAT \ - -D_THREAD_SAFE \ - -DHAVE_SYS_AHAFS_EVPRODS_H -include_HEADERS += include/uv-aix.h -libuv_la_SOURCES += src/unix/aix.c -endif - -if ANDROID -include_HEADERS += include/android-ifaddrs.h \ - include/pthread-barrier.h -libuv_la_SOURCES += src/unix/android-ifaddrs.c \ - src/unix/pthread-fixes.c \ - src/unix/pthread-barrier.c -endif - -if DARWIN -include_HEADERS += include/uv-darwin.h \ - include/pthread-barrier.h -libuv_la_CFLAGS += -D_DARWIN_USE_64_BIT_INODE=1 -libuv_la_CFLAGS += -D_DARWIN_UNLIMITED_SELECT=1 -libuv_la_SOURCES += src/unix/darwin.c \ - src/unix/darwin-proctitle.c \ - src/unix/fsevents.c \ - src/unix/kqueue.c \ - src/unix/proctitle.c \ - src/unix/pthread-barrier.c -test_run_tests_LDFLAGS += -lutil -endif - -if DRAGONFLY -include_HEADERS += include/uv-bsd.h -libuv_la_SOURCES += src/unix/freebsd.c src/unix/kqueue.c -test_run_tests_LDFLAGS += -lutil -endif - -if FREEBSD -include_HEADERS += include/uv-bsd.h -libuv_la_SOURCES += src/unix/freebsd.c src/unix/kqueue.c -test_run_tests_LDFLAGS += -lutil -endif - -if LINUX -include_HEADERS += include/uv-linux.h -libuv_la_CFLAGS += -D_GNU_SOURCE -libuv_la_SOURCES += src/unix/linux-core.c \ - src/unix/linux-inotify.c \ - src/unix/linux-syscalls.c \ - src/unix/linux-syscalls.h \ - src/unix/proctitle.c -test_run_tests_LDFLAGS += -lutil -endif - -if NETBSD -include_HEADERS += include/uv-bsd.h -libuv_la_SOURCES += src/unix/kqueue.c src/unix/netbsd.c -test_run_tests_LDFLAGS += -lutil -endif - -if OPENBSD -include_HEADERS += include/uv-bsd.h -libuv_la_SOURCES += src/unix/kqueue.c src/unix/openbsd.c -test_run_tests_LDFLAGS += -lutil -endif - -if SUNOS -include_HEADERS += include/uv-sunos.h -libuv_la_CFLAGS += -D__EXTENSIONS__ -D_XOPEN_SOURCE=500 -libuv_la_SOURCES += src/unix/sunos.c -endif - -if OS390 -include_HEADERS += include/pthread-fixes.h include/pthread-barrier.h -libuv_la_CFLAGS += -D_UNIX03_THREADS \ - -D_UNIX03_SOURCE \ - -D_OPEN_SYS_IF_EXT=1 \ - -D_OPEN_MSGQ_EXT \ - -D_XOPEN_SOURCE_EXTENDED \ - -D_ALL_SOURCE \ - -D_LARGE_TIME_API \ - -D_OPEN_SYS_SOCK_IPV6 \ - -D_OPEN_SYS_FILE_EXT \ - -DUV_PLATFORM_SEM_T=int \ - -DPATH_MAX=255 \ - -qCHARS=signed \ - -qXPLINK \ - -qFLOAT=IEEE -libuv_la_LDFLAGS += -qXPLINK -libuv_la_SOURCES += src/unix/pthread-fixes.c \ - src/unix/pthread-barrier.c \ - src/unix/os390.c \ - src/unix/os390-syscalls.c \ - src/unix/proctitle.c -endif - -if HAVE_PKG_CONFIG -pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = @PACKAGE_NAME@.pc -endif diff --git a/vendor/libuv/Makefile.mingw b/vendor/libuv/Makefile.mingw deleted file mode 100644 index 8139138fc..000000000 --- a/vendor/libuv/Makefile.mingw +++ /dev/null @@ -1,85 +0,0 @@ -# Copyright (c) 2013, Ben Noordhuis -# -# Permission to use, copy, modify, and/or distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -CC ?= gcc - -CFLAGS += -Wall \ - -Wextra \ - -Wno-unused-parameter \ - -Iinclude \ - -Isrc \ - -Isrc/win \ - -DWIN32_LEAN_AND_MEAN \ - -D_WIN32_WINNT=0x0600 - -INCLUDES = include/stdint-msvc2008.h \ - include/tree.h \ - include/uv-errno.h \ - include/uv-threadpool.h \ - include/uv-version.h \ - include/uv-win.h \ - include/uv.h \ - src/heap-inl.h \ - src/queue.h \ - src/uv-common.h \ - src/win/atomicops-inl.h \ - src/win/handle-inl.h \ - src/win/internal.h \ - src/win/req-inl.h \ - src/win/stream-inl.h \ - src/win/winapi.h \ - src/win/winsock.h - -OBJS = src/fs-poll.o \ - src/inet.o \ - src/threadpool.o \ - src/uv-common.o \ - src/version.o \ - src/win/async.o \ - src/win/core.o \ - src/win/detect-wakeup.o \ - src/win/dl.o \ - src/win/error.o \ - src/win/fs-event.o \ - src/win/fs.o \ - src/win/getaddrinfo.o \ - src/win/getnameinfo.o \ - src/win/handle.o \ - src/win/loop-watcher.o \ - src/win/pipe.o \ - src/win/poll.o \ - src/win/process-stdio.o \ - src/win/process.o \ - src/win/req.o \ - src/win/signal.o \ - src/win/stream.o \ - src/win/tcp.o \ - src/win/thread.o \ - src/win/timer.o \ - src/win/tty.o \ - src/win/udp.o \ - src/win/util.o \ - src/win/winapi.o \ - src/win/winsock.o - -all: libuv.a - -clean: - -$(RM) $(OBJS) libuv.a - -libuv.a: $(OBJS) - $(AR) crs $@ $^ - -$(OBJS): %.o : %.c $(INCLUDES) - $(CC) $(CFLAGS) -c -o $@ $< diff --git a/vendor/libuv/README.md b/vendor/libuv/README.md deleted file mode 100644 index 284dfb47c..000000000 --- a/vendor/libuv/README.md +++ /dev/null @@ -1,250 +0,0 @@ -![libuv][libuv_banner] - -## Overview - -libuv is a multi-platform support library with a focus on asynchronous I/O. It -was primarily developed for use by [Node.js](http://nodejs.org), but it's also -used by [Luvit](http://luvit.io/), [Julia](http://julialang.org/), -[pyuv](https://github.com/saghul/pyuv), and [others](https://github.com/libuv/libuv/wiki/Projects-that-use-libuv). - -## Feature highlights - - * Full-featured event loop backed by epoll, kqueue, IOCP, event ports. - - * Asynchronous TCP and UDP sockets - - * Asynchronous DNS resolution - - * Asynchronous file and file system operations - - * File system events - - * ANSI escape code controlled TTY - - * IPC with socket sharing, using Unix domain sockets or named pipes (Windows) - - * Child processes - - * Thread pool - - * Signal handling - - * High resolution clock - - * Threading and synchronization primitives - -## Versioning - -Starting with version 1.0.0 libuv follows the [semantic versioning](http://semver.org/) -scheme. The API change and backwards compatibility rules are those indicated by -SemVer. libuv will keep a stable ABI across major releases. - -The ABI/API changes can be tracked [here](http://abi-laboratory.pro/tracker/timeline/libuv/). - -## Licensing - -libuv is licensed under the MIT license. Check the [LICENSE file](LICENSE). - -## Community - - * [Mailing list](http://groups.google.com/group/libuv) - * [IRC chatroom (#libuv@irc.freenode.org)](http://webchat.freenode.net?channels=libuv&uio=d4) - -## Documentation - -### Official API documentation - -Located in the docs/ subdirectory. It uses the [Sphinx](http://sphinx-doc.org/) -framework, which makes it possible to build the documentation in multiple -formats. - -Show different supported building options: - - $ make help - -Build documentation as HTML: - - $ make html - -Build documentation as HTML and live reload it when it changes (this requires -sphinx-autobuild to be installed and is only supported on Unix): - - $ make livehtml - -Build documentation as man pages: - - $ make man - -Build documentation as ePub: - - $ make epub - -NOTE: Windows users need to use make.bat instead of plain 'make'. - -Documentation can be browsed online [here](http://docs.libuv.org). - -The [tests and benchmarks](https://github.com/libuv/libuv/tree/master/test) -also serve as API specification and usage examples. - -### Other resources - - * [An Introduction to libuv](http://nikhilm.github.com/uvbook/) - — An overview of libuv with tutorials. - * [LXJS 2012 talk](http://www.youtube.com/watch?v=nGn60vDSxQ4) - — High-level introductory talk about libuv. - * [libuv-dox](https://github.com/thlorenz/libuv-dox) - — Documenting types and methods of libuv, mostly by reading uv.h. - * [learnuv](https://github.com/thlorenz/learnuv) - — Learn uv for fun and profit, a self guided workshop to libuv. - -These resources are not handled by libuv maintainers and might be out of -date. Please verify it before opening new issues. - -## Downloading - -libuv can be downloaded either from the -[GitHub repository](https://github.com/libuv/libuv) -or from the [downloads site](http://dist.libuv.org/dist/). - -Starting with libuv 1.7.0, binaries for Windows are also provided. This is to -be considered EXPERIMENTAL. - -Before verifying the git tags or signature files, importing the relevant keys -is necessary. Key IDs are listed in the -[MAINTAINERS](https://github.com/libuv/libuv/blob/master/MAINTAINERS.md) -file, but are also available as git blob objects for easier use. - -Importing a key the usual way: - - $ gpg --keyserver pool.sks-keyservers.net \ - --recv-keys AE9BC059 - -Importing a key from a git blob object: - - $ git show pubkey-saghul | gpg --import - -### Verifying releases - -Git tags are signed with the developer's key, they can be verified as follows: - - $ git verify-tag v1.6.1 - -Starting with libuv 1.7.0, the tarballs stored in the -[downloads site](http://dist.libuv.org/dist/) are signed and an accompanying -signature file sit alongside each. Once both the release tarball and the -signature file are downloaded, the file can be verified as follows: - - $ gpg --verify libuv-1.7.0.tar.gz.sign - -## Build Instructions - -For GCC there are two build methods: via autotools or via [GYP][]. -GYP is a meta-build system which can generate MSVS, Makefile, and XCode -backends. It is best used for integration into other projects. - -To build with autotools: - - $ sh autogen.sh - $ ./configure - $ make - $ make check - $ make install - -### Windows - -First, [Python][] 2.6 or 2.7 must be installed as it is required by [GYP][]. -If python is not in your path, set the environment variable `PYTHON` to its -location. For example: `set PYTHON=C:\Python27\python.exe` - -To build with Visual Studio, launch a git shell (e.g. Cmd or PowerShell) -and run vcbuild.bat which will checkout the GYP code into build/gyp and -generate uv.sln as well as related project files. - -To have GYP generate build script for another system, checkout GYP into the -project tree manually: - - $ git clone https://chromium.googlesource.com/external/gyp.git build/gyp - -### Unix - -For Debug builds (recommended) run: - - $ ./gyp_uv.py -f make - $ make -C out - -For Release builds run: - - $ ./gyp_uv.py -f make - $ BUILDTYPE=Release make -C out - -Run `./gyp_uv.py -f make -Dtarget_arch=x32` to build [x32][] binaries. - -### OS X - -Run: - - $ ./gyp_uv.py -f xcode - $ xcodebuild -ARCHS="x86_64" -project uv.xcodeproj \ - -configuration Release -target All - -Using Homebrew: - - $ brew install --HEAD libuv - -Note to OS X users: - -Make sure that you specify the architecture you wish to build for in the -"ARCHS" flag. You can specify more than one by delimiting with a space -(e.g. "x86_64 i386"). - -### Android - -Run: - - $ source ./android-configure NDK_PATH gyp - $ make -C out - -Note for UNIX users: compile your project with `-D_LARGEFILE_SOURCE` and -`-D_FILE_OFFSET_BITS=64`. GYP builds take care of that automatically. - -### Using Ninja - -To use ninja for build on ninja supported platforms, run: - - $ ./gyp_uv.py -f ninja - $ ninja -C out/Debug #for debug build OR - $ ninja -C out/Release - - -### Running tests - -Run: - - $ ./gyp_uv.py -f make - $ make -C out - $ ./out/Debug/run-tests - -## Supported Platforms - -Check the [SUPPORTED_PLATFORMS file](SUPPORTED_PLATFORMS.md). - -### AIX Notes - -AIX support for filesystem events requires the non-default IBM `bos.ahafs` -package to be installed. This package provides the AIX Event Infrastructure -that is detected by `autoconf`. -[IBM documentation](http://www.ibm.com/developerworks/aix/library/au-aix_event_infrastructure/) -describes the package in more detail. - -AIX support for filesystem events is not compiled when building with `gyp`. - -## Patches - -See the [guidelines for contributing][]. - -[node.js]: http://nodejs.org/ -[GYP]: http://code.google.com/p/gyp/ -[Python]: https://www.python.org/downloads/ -[guidelines for contributing]: https://github.com/libuv/libuv/blob/master/CONTRIBUTING.md -[libuv_banner]: https://raw.githubusercontent.com/libuv/libuv/master/img/banner.png -[x32]: https://en.wikipedia.org/wiki/X32_ABI diff --git a/vendor/libuv/SUPPORTED_PLATFORMS.md b/vendor/libuv/SUPPORTED_PLATFORMS.md deleted file mode 100644 index bff1050d6..000000000 --- a/vendor/libuv/SUPPORTED_PLATFORMS.md +++ /dev/null @@ -1,70 +0,0 @@ -# Supported platforms - -| System | Support type | Supported versions | Notes | -|---|---|---|---| -| GNU/Linux | Tier 1 | Linux >= 2.6.18 with glibc >= 2.5 | | -| macOS | Tier 1 | macOS >= 10.7 | | -| Windows | Tier 1 | Windows >= XP SP1 | MSVC 2008 and later are supported | -| FreeBSD | Tier 1 | >= 9 (see note) | | -| AIX | Tier 2 | >= 6 | Maintainers: @libuv/aix | -| z/OS | Tier 2 | >= V2R2 | Maintainers: @libuv/zos | -| Linux with musl | Tier 2 | musl >= 1.0 | | -| SunOS | Tier 2 | Solaris 121 and later | Maintainers: @libuv/sunos | -| MinGW | Tier 3 | MinGW32 and MinGW-w64 | | -| Other | Tier 3 | N/A | | - -#### Note on FreeBSD 9 - -While FreeBSD is supported as Tier 1, FreeBSD 9 will get Tier 2 support until -it reaches end of life, in December 2016. - -## Support types - -* **Tier 1**: Officially supported and tested with CI. Any contributed patch - MUST NOT break such systems. These are supported by @libuv/collaborators. - -* **Tier 2**: Officially supported, but not necessarily tested with CI. These - systems are maintained to the best of @libuv/collaborators ability, - without being a top priority. - -* **Tier 3**: Community maintained. These systems may inadvertently break and the - community and interested parties are expected to help with the maintenance. - -## Adding support for a new platform - -**IMPORTANT**: Before attempting to add support for a new platform please open -an issue about it for discussion. - -### Unix - -I/O handling is abstracted by an internal `uv__io_t` handle. The new platform -will need to implement some of the functions, the prototypes are in -``src/unix/internal.h``. - -If the new platform requires extra fields for any handle structure, create a -new include file in ``include/`` with the name ``uv-theplatform.h`` and add -the appropriate defines there. - -All functionality related to the new platform must be implemented in its own -file inside ``src/unix/`` unless it's already done in a common file, in which -case adding an `ifdef` is fine. - -Two build systems are supported: autotools and GYP. Ideally both need to be -supported, but if GYP does not support the new platform it can be left out. - -### Windows - -Windows is treated as a single platform, so adding support for a new platform -would mean adding support for a new version. - -Compilation and runtime must succeed for the minimum supported version. If a -new API is to be used, it must be done optionally, only in supported versions. - -### Common - -Some common notes when adding support for new platforms: - -* Generally libuv tries to avoid compile time checks. Do not add any to the - autotools based build system or use version checking macros. - Dynamically load functions and symbols if they are not supported by the - minimum supported version. diff --git a/vendor/libuv/android-configure b/vendor/libuv/android-configure deleted file mode 100644 index 7ffc035c1..000000000 --- a/vendor/libuv/android-configure +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/bash - -export TOOLCHAIN=$PWD/android-toolchain -mkdir -p $TOOLCHAIN -$1/build/tools/make-standalone-toolchain.sh \ - --toolchain=arm-linux-androideabi-4.9 \ - --arch=arm \ - --install-dir=$TOOLCHAIN \ - --platform=android-21 -export PATH=$TOOLCHAIN/bin:$PATH -export AR=arm-linux-androideabi-ar -export CC=arm-linux-androideabi-gcc -export CXX=arm-linux-androideabi-g++ -export LINK=arm-linux-androideabi-g++ -export PLATFORM=android - -if [[ $2 == 'gyp' ]] - then - ./gyp_uv.py -Dtarget_arch=arm -DOS=android -f make-android -fi diff --git a/vendor/libuv/appveyor.yml b/vendor/libuv/appveyor.yml deleted file mode 100644 index e8e79f051..000000000 --- a/vendor/libuv/appveyor.yml +++ /dev/null @@ -1,36 +0,0 @@ -version: v1.11.0.build{build} - -install: - - cinst -y nsis - -matrix: - fast_finish: true - allow_failures: - - platform: x86 - configuration: Release - - platform: x64 - configuration: Release - -platform: - - x86 - - x64 - -configuration: - - Release - -build_script: - # Fixed tag version number if using a tag. - - cmd: if "%APPVEYOR_REPO_TAG%" == "true" set APPVEYOR_BUILD_VERSION=%APPVEYOR_REPO_TAG_NAME% - # vcbuild overwrites the platform variable. - - cmd: set ARCH=%platform% - - cmd: vcbuild.bat release %ARCH% shared - -after_build: - - '"%PROGRAMFILES(x86)%\NSIS\makensis" /DVERSION=%APPVEYOR_BUILD_VERSION% /DARCH=%ARCH% libuv.nsi' - -artifacts: - - name: Installer - path: 'libuv-*.exe' - -cache: - - C:\projects\libuv\build\gyp diff --git a/vendor/libuv/autogen.sh b/vendor/libuv/autogen.sh deleted file mode 100644 index 271c2ee8c..000000000 --- a/vendor/libuv/autogen.sh +++ /dev/null @@ -1,46 +0,0 @@ -#!/bin/sh - -# Copyright (c) 2013, Ben Noordhuis -# -# Permission to use, copy, modify, and/or distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -cd `dirname "$0"` - -if [ "$LIBTOOLIZE" = "" ] && [ "`uname`" = "Darwin" ]; then - LIBTOOLIZE=glibtoolize -fi - -ACLOCAL=${ACLOCAL:-aclocal} -AUTOCONF=${AUTOCONF:-autoconf} -AUTOMAKE=${AUTOMAKE:-automake} -LIBTOOLIZE=${LIBTOOLIZE:-libtoolize} - -automake_version=`"$AUTOMAKE" --version | head -n 1 | sed 's/[^.0-9]//g'` -automake_version_major=`echo "$automake_version" | cut -d. -f1` -automake_version_minor=`echo "$automake_version" | cut -d. -f2` - -UV_EXTRA_AUTOMAKE_FLAGS= -if test "$automake_version_major" -gt 1 || \ - test "$automake_version_major" -eq 1 && \ - test "$automake_version_minor" -gt 11; then - # serial-tests is available in v1.12 and newer. - UV_EXTRA_AUTOMAKE_FLAGS="$UV_EXTRA_AUTOMAKE_FLAGS serial-tests" -fi -echo "m4_define([UV_EXTRA_AUTOMAKE_FLAGS], [$UV_EXTRA_AUTOMAKE_FLAGS])" \ - > m4/libuv-extra-automake-flags.m4 - -set -ex -"$LIBTOOLIZE" --copy -"$ACLOCAL" -I m4 -"$AUTOCONF" -"$AUTOMAKE" --add-missing --copy diff --git a/vendor/libuv/checksparse.sh b/vendor/libuv/checksparse.sh deleted file mode 100644 index 68e3bde39..000000000 --- a/vendor/libuv/checksparse.sh +++ /dev/null @@ -1,236 +0,0 @@ -#!/bin/sh - -# Copyright (c) 2013, Ben Noordhuis -# -# Permission to use, copy, modify, and/or distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -SPARSE=${SPARSE:-sparse} - -SPARSE_FLAGS=${SPARSE_FLAGS:-" --D__POSIX__ --Wsparse-all --Wno-do-while --Wno-transparent-union --Iinclude --Isrc -"} - -SOURCES=" -include/tree.h -include/uv-unix.h -include/uv.h -src/fs-poll.c -src/inet.c -src/queue.h -src/unix/async.c -src/unix/core.c -src/unix/dl.c -src/unix/fs.c -src/unix/getaddrinfo.c -src/unix/internal.h -src/unix/loop-watcher.c -src/unix/loop.c -src/unix/pipe.c -src/unix/poll.c -src/unix/process.c -src/unix/signal.c -src/unix/stream.c -src/unix/tcp.c -src/unix/thread.c -src/unix/threadpool.c -src/unix/timer.c -src/unix/tty.c -src/unix/udp.c -src/uv-common.c -src/uv-common.h -" - -TESTS=" -test/benchmark-async-pummel.c -test/benchmark-async.c -test/benchmark-fs-stat.c -test/benchmark-getaddrinfo.c -test/benchmark-loop-count.c -test/benchmark-million-async.c -test/benchmark-million-timers.c -test/benchmark-multi-accept.c -test/benchmark-ping-pongs.c -test/benchmark-pound.c -test/benchmark-pump.c -test/benchmark-sizes.c -test/benchmark-spawn.c -test/benchmark-tcp-write-batch.c -test/benchmark-thread.c -test/benchmark-udp-pummel.c -test/blackhole-server.c -test/dns-server.c -test/echo-server.c -test/run-benchmarks.c -test/run-tests.c -test/runner-unix.c -test/runner-unix.h -test/runner.c -test/runner.h -test/task.h -test/test-active.c -test/test-async.c -test/test-barrier.c -test/test-callback-order.c -test/test-callback-stack.c -test/test-condvar.c -test/test-connection-fail.c -test/test-cwd-and-chdir.c -test/test-delayed-accept.c -test/test-dlerror.c -test/test-embed.c -test/test-error.c -test/test-fail-always.c -test/test-fs-event.c -test/test-fs-poll.c -test/test-fs.c -test/test-get-currentexe.c -test/test-get-loadavg.c -test/test-get-memory.c -test/test-get-passwd.c -test/test-getaddrinfo.c -test/test-getsockname.c -test/test-homedir.c -test/test-hrtime.c -test/test-idle.c -test/test-ip6-addr.c -test/test-ipc-send-recv.c -test/test-ipc.c -test/test-loop-handles.c -test/test-multiple-listen.c -test/test-mutexes.c -test/test-pass-always.c -test/test-ping-pong.c -test/test-pipe-bind-error.c -test/test-pipe-connect-error.c -test/test-pipe-sendmsg.c -test/test-pipe-server-close.c -test/test-platform-output.c -test/test-poll-close.c -test/test-poll.c -test/test-process-title.c -test/test-ref.c -test/test-run-nowait.c -test/test-run-once.c -test/test-semaphore.c -test/test-shutdown-close.c -test/test-shutdown-eof.c -test/test-signal-multiple-loops.c -test/test-signal.c -test/test-spawn.c -test/test-stdio-over-pipes.c -test/test-tcp-bind-error.c -test/test-tcp-bind6-error.c -test/test-tcp-close-while-connecting.c -test/test-tcp-close-accept.c -test/test-tcp-close.c -test/test-tcp-connect-error-after-write.c -test/test-tcp-connect-error.c -test/test-tcp-connect-timeout.c -test/test-tcp-connect6-error.c -test/test-tcp-flags.c -test/test-tcp-open.c -test/test-tcp-read-stop.c -test/test-tcp-shutdown-after-write.c -test/test-tcp-unexpected-read.c -test/test-tcp-oob.c -test/test-tcp-write-error.c -test/test-tcp-write-to-half-open-connection.c -test/test-tcp-writealot.c -test/test-thread.c -test/test-threadpool-cancel.c -test/test-threadpool.c -test/test-timer-again.c -test/test-timer.c -test/test-tmpdir.c -test/test-tty.c -test/test-udp-dgram-too-big.c -test/test-udp-ipv6.c -test/test-udp-multicast-join.c -test/test-udp-multicast-ttl.c -test/test-udp-open.c -test/test-udp-options.c -test/test-udp-send-and-recv.c -test/test-walk-handles.c -test/test-watcher-cross-stop.c -" - -case `uname -s` in -AIX) - SPARSE_FLAGS="$SPARSE_FLAGS -D_AIX=1" - SOURCES="$SOURCES - src/unix/aix.c" - ;; -Darwin) - SPARSE_FLAGS="$SPARSE_FLAGS -D__APPLE__=1" - SOURCES="$SOURCES - include/uv-bsd.h - src/unix/darwin.c - src/unix/kqueue.c - src/unix/fsevents.c" - ;; -DragonFly) - SPARSE_FLAGS="$SPARSE_FLAGS -D__DragonFly__=1" - SOURCES="$SOURCES - include/uv-bsd.h - src/unix/kqueue.c - src/unix/freebsd.c" - ;; -FreeBSD) - SPARSE_FLAGS="$SPARSE_FLAGS -D__FreeBSD__=1" - SOURCES="$SOURCES - include/uv-bsd.h - src/unix/kqueue.c - src/unix/freebsd.c" - ;; -Linux) - SPARSE_FLAGS="$SPARSE_FLAGS -D__linux__=1" - SOURCES="$SOURCES - include/uv-linux.h - src/unix/linux-inotify.c - src/unix/linux-core.c - src/unix/linux-syscalls.c - src/unix/linux-syscalls.h" - ;; -NetBSD) - SPARSE_FLAGS="$SPARSE_FLAGS -D__NetBSD__=1" - SOURCES="$SOURCES - include/uv-bsd.h - src/unix/kqueue.c - src/unix/netbsd.c" - ;; -OpenBSD) - SPARSE_FLAGS="$SPARSE_FLAGS -D__OpenBSD__=1" - SOURCES="$SOURCES - include/uv-bsd.h - src/unix/kqueue.c - src/unix/openbsd.c" - ;; -SunOS) - SPARSE_FLAGS="$SPARSE_FLAGS -D__sun=1" - SOURCES="$SOURCES - include/uv-sunos.h - src/unix/sunos.c" - ;; -esac - -for ARCH in __i386__ __x86_64__ __arm__ __mips__; do - $SPARSE $SPARSE_FLAGS -D$ARCH=1 $SOURCES -done - -# Tests are architecture independent. -$SPARSE $SPARSE_FLAGS -Itest $TESTS diff --git a/vendor/libuv/common.gypi b/vendor/libuv/common.gypi deleted file mode 100644 index 470b73385..000000000 --- a/vendor/libuv/common.gypi +++ /dev/null @@ -1,206 +0,0 @@ -{ - 'variables': { - 'target_arch%': 'ia32', # set v8's target architecture - 'host_arch%': 'ia32', # set v8's host architecture - 'uv_library%': 'static_library', # allow override to 'shared_library' for DLL/.so builds - 'msvs_multi_core_compile': '0', # we do enable multicore compiles, but not using the V8 way - }, - - 'target_defaults': { - 'default_configuration': 'Debug', - 'configurations': { - 'Debug': { - 'defines': [ 'DEBUG', '_DEBUG' ], - 'cflags': [ '-g' ], - 'msvs_settings': { - 'VCCLCompilerTool': { - 'target_conditions': [ - ['uv_library=="static_library"', { - 'RuntimeLibrary': 1, # static debug - }, { - 'RuntimeLibrary': 3, # DLL debug - }], - ], - 'Optimization': 0, # /Od, no optimization - 'MinimalRebuild': 'false', - 'OmitFramePointers': 'false', - 'BasicRuntimeChecks': 3, # /RTC1 - }, - 'VCLinkerTool': { - 'LinkIncremental': 2, # enable incremental linking - }, - }, - 'xcode_settings': { - 'GCC_OPTIMIZATION_LEVEL': '0', - 'OTHER_CFLAGS': [ '-Wno-strict-aliasing' ], - }, - 'conditions': [ - ['OS != "os390"', { - 'cflags': [ '-O0', '-fwrapv' ] - }], - ['OS == "android"', { - 'cflags': [ '-fPIE' ], - 'ldflags': [ '-fPIE', '-pie' ] - }] - ] - }, - 'Release': { - 'defines': [ 'NDEBUG' ], - 'cflags': [ - '-O3', - '-fstrict-aliasing', - '-fomit-frame-pointer', - '-fdata-sections', - '-ffunction-sections', - ], - 'msvs_settings': { - 'VCCLCompilerTool': { - 'target_conditions': [ - ['uv_library=="static_library"', { - 'RuntimeLibrary': 0, # static release - }, { - 'RuntimeLibrary': 2, # debug release - }], - ], - 'Optimization': 3, # /Ox, full optimization - 'FavorSizeOrSpeed': 1, # /Ot, favour speed over size - 'InlineFunctionExpansion': 2, # /Ob2, inline anything eligible - 'WholeProgramOptimization': 'true', # /GL, whole program optimization, needed for LTCG - 'OmitFramePointers': 'true', - 'EnableFunctionLevelLinking': 'true', - 'EnableIntrinsicFunctions': 'true', - }, - 'VCLibrarianTool': { - 'AdditionalOptions': [ - '/LTCG', # link time code generation - ], - }, - 'VCLinkerTool': { - 'LinkTimeCodeGeneration': 1, # link-time code generation - 'OptimizeReferences': 2, # /OPT:REF - 'EnableCOMDATFolding': 2, # /OPT:ICF - 'LinkIncremental': 1, # disable incremental linking - }, - }, - } - }, - 'msvs_settings': { - 'VCCLCompilerTool': { - 'StringPooling': 'true', # pool string literals - 'DebugInformationFormat': 3, # Generate a PDB - 'WarningLevel': 3, - 'BufferSecurityCheck': 'true', - 'ExceptionHandling': 1, # /EHsc - 'SuppressStartupBanner': 'true', - 'WarnAsError': 'false', - 'AdditionalOptions': [ - '/MP', # compile across multiple CPUs - ], - }, - 'VCLibrarianTool': { - }, - 'VCLinkerTool': { - 'GenerateDebugInformation': 'true', - 'RandomizedBaseAddress': 2, # enable ASLR - 'DataExecutionPrevention': 2, # enable DEP - 'AllowIsolation': 'true', - 'SuppressStartupBanner': 'true', - 'target_conditions': [ - ['_type=="executable"', { - 'SubSystem': 1, # console executable - }], - ], - }, - }, - 'conditions': [ - ['OS == "win"', { - 'msvs_cygwin_shell': 0, # prevent actions from trying to use cygwin - 'defines': [ - 'WIN32', - # we don't really want VC++ warning us about - # how dangerous C functions are... - '_CRT_SECURE_NO_DEPRECATE', - # ... or that C implementations shouldn't use - # POSIX names - '_CRT_NONSTDC_NO_DEPRECATE', - ], - 'target_conditions': [ - ['target_arch=="x64"', { - 'msvs_configuration_platform': 'x64' - }] - ] - }], - ['OS in "freebsd dragonflybsd linux openbsd solaris android"', { - 'cflags': [ '-Wall' ], - 'cflags_cc': [ '-fno-rtti', '-fno-exceptions' ], - 'target_conditions': [ - ['_type=="static_library"', { - 'standalone_static_library': 1, # disable thin archive which needs binutils >= 2.19 - }], - ], - 'conditions': [ - [ 'host_arch != target_arch and target_arch=="ia32"', { - 'cflags': [ '-m32' ], - 'ldflags': [ '-m32' ], - }], - [ 'target_arch=="x32"', { - 'cflags': [ '-mx32' ], - 'ldflags': [ '-mx32' ], - }], - [ 'OS=="linux"', { - 'cflags': [ '-ansi' ], - }], - [ 'OS=="solaris"', { - 'cflags': [ '-pthreads' ], - 'ldflags': [ '-pthreads' ], - }], - [ 'OS not in "solaris android os390"', { - 'cflags': [ '-pthread' ], - 'ldflags': [ '-pthread' ], - }], - ], - }], - ['OS=="mac"', { - 'xcode_settings': { - 'ALWAYS_SEARCH_USER_PATHS': 'NO', - 'GCC_CW_ASM_SYNTAX': 'NO', # No -fasm-blocks - 'GCC_DYNAMIC_NO_PIC': 'NO', # No -mdynamic-no-pic - # (Equivalent to -fPIC) - 'GCC_ENABLE_CPP_EXCEPTIONS': 'NO', # -fno-exceptions - 'GCC_ENABLE_CPP_RTTI': 'NO', # -fno-rtti - 'GCC_ENABLE_PASCAL_STRINGS': 'NO', # No -mpascal-strings - 'GCC_THREADSAFE_STATICS': 'NO', # -fno-threadsafe-statics - 'PREBINDING': 'NO', # No -Wl,-prebind - 'USE_HEADERMAP': 'NO', - 'OTHER_CFLAGS': [ - '-fstrict-aliasing', - ], - 'WARNING_CFLAGS': [ - '-Wall', - '-Wendif-labels', - '-W', - '-Wno-unused-parameter', - ], - }, - 'conditions': [ - ['target_arch=="ia32"', { - 'xcode_settings': {'ARCHS': ['i386']}, - }], - ['target_arch=="x64"', { - 'xcode_settings': {'ARCHS': ['x86_64']}, - }], - ], - 'target_conditions': [ - ['_type!="static_library"', { - 'xcode_settings': {'OTHER_LDFLAGS': ['-Wl,-search_paths_first']}, - }], - ], - }], - ['OS=="solaris"', { - 'cflags': [ '-fno-omit-frame-pointer' ], - # pull in V8's postmortem metadata - 'ldflags': [ '-Wl,-z,allextract' ] - }], - ], - }, -} diff --git a/vendor/libuv/configure.ac b/vendor/libuv/configure.ac deleted file mode 100644 index 360652198..000000000 --- a/vendor/libuv/configure.ac +++ /dev/null @@ -1,74 +0,0 @@ -# Copyright (c) 2013, Ben Noordhuis -# -# Permission to use, copy, modify, and/or distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -AC_PREREQ(2.57) -AC_INIT([libuv], [1.11.0], [https://github.com/libuv/libuv/issues]) -AC_CONFIG_MACRO_DIR([m4]) -m4_include([m4/libuv-extra-automake-flags.m4]) -m4_include([m4/as_case.m4]) -m4_include([m4/libuv-check-flags.m4]) -AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects] UV_EXTRA_AUTOMAKE_FLAGS) -AC_CANONICAL_HOST -AC_ENABLE_SHARED -AC_ENABLE_STATIC -AC_PROG_CC -AM_PROG_CC_C_O -AS_IF([AS_CASE([$host_os],[openedition*], [false], [true])], [ - CC_CHECK_CFLAGS_APPEND([-pedantic]) -]) -CC_FLAG_VISIBILITY #[-fvisibility=hidden] -CC_CHECK_CFLAGS_APPEND([-g]) -CC_CHECK_CFLAGS_APPEND([-std=gnu89]) -CC_CHECK_CFLAGS_APPEND([-Wall]) -CC_CHECK_CFLAGS_APPEND([-Wextra]) -CC_CHECK_CFLAGS_APPEND([-Wno-unused-parameter]) -# AM_PROG_AR is not available in automake v0.11 but it's essential in v0.12. -m4_ifdef([AM_PROG_AR], [AM_PROG_AR]) -# autoconf complains if AC_PROG_LIBTOOL precedes AM_PROG_AR. -AC_PROG_LIBTOOL -m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) -LT_INIT -# TODO(bnoordhuis) Check for -pthread vs. -pthreads -AC_CHECK_LIB([dl], [dlopen]) -AC_CHECK_LIB([kstat], [kstat_lookup]) -AC_CHECK_LIB([kvm], [kvm_open]) -AC_CHECK_LIB([nsl], [gethostbyname]) -AC_CHECK_LIB([perfstat], [perfstat_cpu]) -AC_CHECK_LIB([pthread], [pthread_mutex_init]) -AC_CHECK_LIB([rt], [clock_gettime]) -AC_CHECK_LIB([sendfile], [sendfile]) -AC_CHECK_LIB([socket], [socket]) -AC_SYS_LARGEFILE -AM_CONDITIONAL([AIX], [AS_CASE([$host_os],[aix*], [true], [false])]) -AM_CONDITIONAL([ANDROID], [AS_CASE([$host_os],[linux-android*],[true], [false])]) -AM_CONDITIONAL([DARWIN], [AS_CASE([$host_os],[darwin*], [true], [false])]) -AM_CONDITIONAL([DRAGONFLY],[AS_CASE([$host_os],[dragonfly*], [true], [false])]) -AM_CONDITIONAL([FREEBSD], [AS_CASE([$host_os],[*freebsd*], [true], [false])]) -AM_CONDITIONAL([LINUX], [AS_CASE([$host_os],[linux*], [true], [false])]) -AM_CONDITIONAL([NETBSD], [AS_CASE([$host_os],[netbsd*], [true], [false])]) -AM_CONDITIONAL([OPENBSD], [AS_CASE([$host_os],[openbsd*], [true], [false])]) -AM_CONDITIONAL([OS390], [AS_CASE([$host_os],[openedition*], [true], [false])]) -AM_CONDITIONAL([SUNOS], [AS_CASE([$host_os],[solaris*], [true], [false])]) -AM_CONDITIONAL([WINNT], [AS_CASE([$host_os],[mingw*], [true], [false])]) -AS_CASE([$host_os],[mingw*], [ - LIBS="$LIBS -lws2_32 -lpsapi -liphlpapi -lshell32 -luserenv -luser32" -]) -AC_CHECK_HEADERS([sys/ahafs_evProds.h]) -AC_CHECK_PROG(PKG_CONFIG, pkg-config, yes) -AM_CONDITIONAL([HAVE_PKG_CONFIG], [test "x$PKG_CONFIG" != "x"]) -AS_IF([test "x$PKG_CONFIG" != "x"], [ - AC_CONFIG_FILES([libuv.pc]) -]) -AC_CONFIG_FILES([Makefile]) -AC_OUTPUT diff --git a/vendor/libuv/gyp_uv.py b/vendor/libuv/gyp_uv.py deleted file mode 100644 index bd37d95c4..000000000 --- a/vendor/libuv/gyp_uv.py +++ /dev/null @@ -1,94 +0,0 @@ -#!/usr/bin/env python - -import os -import platform -import sys - -try: - import multiprocessing.synchronize - gyp_parallel_support = True -except ImportError: - gyp_parallel_support = False - - -CC = os.environ.get('CC', 'cc') -script_dir = os.path.dirname(__file__) -uv_root = os.path.normpath(script_dir) -output_dir = os.path.join(os.path.abspath(uv_root), 'out') - -sys.path.insert(0, os.path.join(uv_root, 'build', 'gyp', 'pylib')) -try: - import gyp -except ImportError: - print('You need to install gyp in build/gyp first. See the README.') - sys.exit(42) - - -def host_arch(): - machine = platform.machine() - if machine == 'i386': return 'ia32' - if machine == 'AMD64': return 'x64' - if machine == 'x86_64': return 'x64' - if machine.startswith('arm'): return 'arm' - if machine.startswith('mips'): return 'mips' - return machine # Return as-is and hope for the best. - - -def run_gyp(args): - rc = gyp.main(args) - if rc != 0: - print('Error running GYP') - sys.exit(rc) - - -if __name__ == '__main__': - args = sys.argv[1:] - - # GYP bug. - # On msvs it will crash if it gets an absolute path. - # On Mac/make it will crash if it doesn't get an absolute path. - if sys.platform == 'win32': - args.append(os.path.join(uv_root, 'uv.gyp')) - common_fn = os.path.join(uv_root, 'common.gypi') - options_fn = os.path.join(uv_root, 'options.gypi') - # we force vs 2010 over 2008 which would otherwise be the default for gyp - if not os.environ.get('GYP_MSVS_VERSION'): - os.environ['GYP_MSVS_VERSION'] = '2010' - else: - args.append(os.path.join(os.path.abspath(uv_root), 'uv.gyp')) - common_fn = os.path.join(os.path.abspath(uv_root), 'common.gypi') - options_fn = os.path.join(os.path.abspath(uv_root), 'options.gypi') - - if os.path.exists(common_fn): - args.extend(['-I', common_fn]) - - if os.path.exists(options_fn): - args.extend(['-I', options_fn]) - - args.append('--depth=' + uv_root) - - # There's a bug with windows which doesn't allow this feature. - if sys.platform != 'win32': - if '-f' not in args: - args.extend('-f make'.split()) - if 'eclipse' not in args and 'ninja' not in args: - args.extend(['-Goutput_dir=' + output_dir]) - args.extend(['--generator-output', output_dir]) - - if not any(a.startswith('-Dhost_arch=') for a in args): - args.append('-Dhost_arch=%s' % host_arch()) - - if not any(a.startswith('-Dtarget_arch=') for a in args): - args.append('-Dtarget_arch=%s' % host_arch()) - - if not any(a.startswith('-Duv_library=') for a in args): - args.append('-Duv_library=static_library') - - # Some platforms (OpenBSD for example) don't have multiprocessing.synchronize - # so gyp must be run with --no-parallel - if not gyp_parallel_support: - args.append('--no-parallel') - - gyp_args = list(args) - print(gyp_args) - run_gyp(gyp_args) diff --git a/vendor/libuv/include/android-ifaddrs.h b/vendor/libuv/include/android-ifaddrs.h deleted file mode 100644 index 9cd19fec1..000000000 --- a/vendor/libuv/include/android-ifaddrs.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 1995, 1999 - * Berkeley Software Design, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * BSDI ifaddrs.h,v 2.5 2000/02/23 14:51:59 dab Exp - */ - -#ifndef _IFADDRS_H_ -#define _IFADDRS_H_ - -struct ifaddrs { - struct ifaddrs *ifa_next; - char *ifa_name; - unsigned int ifa_flags; - struct sockaddr *ifa_addr; - struct sockaddr *ifa_netmask; - struct sockaddr *ifa_dstaddr; - void *ifa_data; -}; - -/* - * This may have been defined in . Note that if is - * to be included it must be included before this header file. - */ -#ifndef ifa_broadaddr -#define ifa_broadaddr ifa_dstaddr /* broadcast address interface */ -#endif - -#include - -__BEGIN_DECLS -extern int getifaddrs(struct ifaddrs **ifap); -extern void freeifaddrs(struct ifaddrs *ifa); -__END_DECLS - -#endif diff --git a/vendor/libuv/include/pthread-barrier.h b/vendor/libuv/include/pthread-barrier.h deleted file mode 100644 index 900ebedd3..000000000 --- a/vendor/libuv/include/pthread-barrier.h +++ /dev/null @@ -1,68 +0,0 @@ -/* -Copyright (c) 2016, Kari Tristan Helgason - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -#ifndef _UV_PTHREAD_BARRIER_ -#define _UV_PTHREAD_BARRIER_ -#include -#include -#if !defined(__MVS__) -#include /* sem_t */ -#endif - -#define PTHREAD_BARRIER_SERIAL_THREAD 0x12345 - -/* - * To maintain ABI compatibility with - * libuv v1.x struct is padded according - * to target platform - */ -#if defined(__ANDROID__) -# define UV_BARRIER_STRUCT_PADDING \ - sizeof(pthread_mutex_t) + \ - sizeof(pthread_cond_t) + \ - sizeof(unsigned int) - \ - sizeof(void *) -#elif defined(__APPLE__) -# define UV_BARRIER_STRUCT_PADDING \ - sizeof(pthread_mutex_t) + \ - 2 * sizeof(sem_t) + \ - 2 * sizeof(unsigned int) - \ - sizeof(void *) -#else -# define UV_BARRIER_STRUCT_PADDING 0 -#endif - -typedef struct { - pthread_mutex_t mutex; - pthread_cond_t cond; - unsigned threshold; - unsigned in; - unsigned out; -} _uv_barrier; - -typedef struct { - _uv_barrier* b; - char _pad[UV_BARRIER_STRUCT_PADDING]; -} pthread_barrier_t; - -int pthread_barrier_init(pthread_barrier_t* barrier, - const void* barrier_attr, - unsigned count); - -int pthread_barrier_wait(pthread_barrier_t* barrier); -int pthread_barrier_destroy(pthread_barrier_t *barrier); - -#endif /* _UV_PTHREAD_BARRIER_ */ diff --git a/vendor/libuv/include/stdint-msvc2008.h b/vendor/libuv/include/stdint-msvc2008.h deleted file mode 100644 index d02608a59..000000000 --- a/vendor/libuv/include/stdint-msvc2008.h +++ /dev/null @@ -1,247 +0,0 @@ -// ISO C9x compliant stdint.h for Microsoft Visual Studio -// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 -// -// Copyright (c) 2006-2008 Alexander Chemeris -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// 3. The name of the author may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO -// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; -// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef _MSC_VER // [ -#error "Use this header only with Microsoft Visual C++ compilers!" -#endif // _MSC_VER ] - -#ifndef _MSC_STDINT_H_ // [ -#define _MSC_STDINT_H_ - -#if _MSC_VER > 1000 -#pragma once -#endif - -#include - -// For Visual Studio 6 in C++ mode and for many Visual Studio versions when -// compiling for ARM we should wrap include with 'extern "C++" {}' -// or compiler give many errors like this: -// error C2733: second C linkage of overloaded function 'wmemchr' not allowed -#ifdef __cplusplus -extern "C" { -#endif -# include -#ifdef __cplusplus -} -#endif - -// Define _W64 macros to mark types changing their size, like intptr_t. -#ifndef _W64 -# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 -# define _W64 __w64 -# else -# define _W64 -# endif -#endif - - -// 7.18.1 Integer types - -// 7.18.1.1 Exact-width integer types - -// Visual Studio 6 and Embedded Visual C++ 4 doesn't -// realize that, e.g. char has the same size as __int8 -// so we give up on __intX for them. -#if (_MSC_VER < 1300) - typedef signed char int8_t; - typedef signed short int16_t; - typedef signed int int32_t; - typedef unsigned char uint8_t; - typedef unsigned short uint16_t; - typedef unsigned int uint32_t; -#else - typedef signed __int8 int8_t; - typedef signed __int16 int16_t; - typedef signed __int32 int32_t; - typedef unsigned __int8 uint8_t; - typedef unsigned __int16 uint16_t; - typedef unsigned __int32 uint32_t; -#endif -typedef signed __int64 int64_t; -typedef unsigned __int64 uint64_t; - - -// 7.18.1.2 Minimum-width integer types -typedef int8_t int_least8_t; -typedef int16_t int_least16_t; -typedef int32_t int_least32_t; -typedef int64_t int_least64_t; -typedef uint8_t uint_least8_t; -typedef uint16_t uint_least16_t; -typedef uint32_t uint_least32_t; -typedef uint64_t uint_least64_t; - -// 7.18.1.3 Fastest minimum-width integer types -typedef int8_t int_fast8_t; -typedef int16_t int_fast16_t; -typedef int32_t int_fast32_t; -typedef int64_t int_fast64_t; -typedef uint8_t uint_fast8_t; -typedef uint16_t uint_fast16_t; -typedef uint32_t uint_fast32_t; -typedef uint64_t uint_fast64_t; - -// 7.18.1.4 Integer types capable of holding object pointers -#ifdef _WIN64 // [ - typedef signed __int64 intptr_t; - typedef unsigned __int64 uintptr_t; -#else // _WIN64 ][ - typedef _W64 signed int intptr_t; - typedef _W64 unsigned int uintptr_t; -#endif // _WIN64 ] - -// 7.18.1.5 Greatest-width integer types -typedef int64_t intmax_t; -typedef uint64_t uintmax_t; - - -// 7.18.2 Limits of specified-width integer types - -#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259 - -// 7.18.2.1 Limits of exact-width integer types -#define INT8_MIN ((int8_t)_I8_MIN) -#define INT8_MAX _I8_MAX -#define INT16_MIN ((int16_t)_I16_MIN) -#define INT16_MAX _I16_MAX -#define INT32_MIN ((int32_t)_I32_MIN) -#define INT32_MAX _I32_MAX -#define INT64_MIN ((int64_t)_I64_MIN) -#define INT64_MAX _I64_MAX -#define UINT8_MAX _UI8_MAX -#define UINT16_MAX _UI16_MAX -#define UINT32_MAX _UI32_MAX -#define UINT64_MAX _UI64_MAX - -// 7.18.2.2 Limits of minimum-width integer types -#define INT_LEAST8_MIN INT8_MIN -#define INT_LEAST8_MAX INT8_MAX -#define INT_LEAST16_MIN INT16_MIN -#define INT_LEAST16_MAX INT16_MAX -#define INT_LEAST32_MIN INT32_MIN -#define INT_LEAST32_MAX INT32_MAX -#define INT_LEAST64_MIN INT64_MIN -#define INT_LEAST64_MAX INT64_MAX -#define UINT_LEAST8_MAX UINT8_MAX -#define UINT_LEAST16_MAX UINT16_MAX -#define UINT_LEAST32_MAX UINT32_MAX -#define UINT_LEAST64_MAX UINT64_MAX - -// 7.18.2.3 Limits of fastest minimum-width integer types -#define INT_FAST8_MIN INT8_MIN -#define INT_FAST8_MAX INT8_MAX -#define INT_FAST16_MIN INT16_MIN -#define INT_FAST16_MAX INT16_MAX -#define INT_FAST32_MIN INT32_MIN -#define INT_FAST32_MAX INT32_MAX -#define INT_FAST64_MIN INT64_MIN -#define INT_FAST64_MAX INT64_MAX -#define UINT_FAST8_MAX UINT8_MAX -#define UINT_FAST16_MAX UINT16_MAX -#define UINT_FAST32_MAX UINT32_MAX -#define UINT_FAST64_MAX UINT64_MAX - -// 7.18.2.4 Limits of integer types capable of holding object pointers -#ifdef _WIN64 // [ -# define INTPTR_MIN INT64_MIN -# define INTPTR_MAX INT64_MAX -# define UINTPTR_MAX UINT64_MAX -#else // _WIN64 ][ -# define INTPTR_MIN INT32_MIN -# define INTPTR_MAX INT32_MAX -# define UINTPTR_MAX UINT32_MAX -#endif // _WIN64 ] - -// 7.18.2.5 Limits of greatest-width integer types -#define INTMAX_MIN INT64_MIN -#define INTMAX_MAX INT64_MAX -#define UINTMAX_MAX UINT64_MAX - -// 7.18.3 Limits of other integer types - -#ifdef _WIN64 // [ -# define PTRDIFF_MIN _I64_MIN -# define PTRDIFF_MAX _I64_MAX -#else // _WIN64 ][ -# define PTRDIFF_MIN _I32_MIN -# define PTRDIFF_MAX _I32_MAX -#endif // _WIN64 ] - -#define SIG_ATOMIC_MIN INT_MIN -#define SIG_ATOMIC_MAX INT_MAX - -#ifndef SIZE_MAX // [ -# ifdef _WIN64 // [ -# define SIZE_MAX _UI64_MAX -# else // _WIN64 ][ -# define SIZE_MAX _UI32_MAX -# endif // _WIN64 ] -#endif // SIZE_MAX ] - -// WCHAR_MIN and WCHAR_MAX are also defined in -#ifndef WCHAR_MIN // [ -# define WCHAR_MIN 0 -#endif // WCHAR_MIN ] -#ifndef WCHAR_MAX // [ -# define WCHAR_MAX _UI16_MAX -#endif // WCHAR_MAX ] - -#define WINT_MIN 0 -#define WINT_MAX _UI16_MAX - -#endif // __STDC_LIMIT_MACROS ] - - -// 7.18.4 Limits of other integer types - -#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 - -// 7.18.4.1 Macros for minimum-width integer constants - -#define INT8_C(val) val##i8 -#define INT16_C(val) val##i16 -#define INT32_C(val) val##i32 -#define INT64_C(val) val##i64 - -#define UINT8_C(val) val##ui8 -#define UINT16_C(val) val##ui16 -#define UINT32_C(val) val##ui32 -#define UINT64_C(val) val##ui64 - -// 7.18.4.2 Macros for greatest-width integer constants -#define INTMAX_C INT64_C -#define UINTMAX_C UINT64_C - -#endif // __STDC_CONSTANT_MACROS ] - - -#endif // _MSC_STDINT_H_ ] diff --git a/vendor/libuv/include/tree.h b/vendor/libuv/include/tree.h deleted file mode 100644 index f936416e3..000000000 --- a/vendor/libuv/include/tree.h +++ /dev/null @@ -1,768 +0,0 @@ -/*- - * Copyright 2002 Niels Provos - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef UV_TREE_H_ -#define UV_TREE_H_ - -#ifndef UV__UNUSED -# if __GNUC__ -# define UV__UNUSED __attribute__((unused)) -# else -# define UV__UNUSED -# endif -#endif - -/* - * This file defines data structures for different types of trees: - * splay trees and red-black trees. - * - * A splay tree is a self-organizing data structure. Every operation - * on the tree causes a splay to happen. The splay moves the requested - * node to the root of the tree and partly rebalances it. - * - * This has the benefit that request locality causes faster lookups as - * the requested nodes move to the top of the tree. On the other hand, - * every lookup causes memory writes. - * - * The Balance Theorem bounds the total access time for m operations - * and n inserts on an initially empty tree as O((m + n)lg n). The - * amortized cost for a sequence of m accesses to a splay tree is O(lg n); - * - * A red-black tree is a binary search tree with the node color as an - * extra attribute. It fulfills a set of conditions: - * - every search path from the root to a leaf consists of the - * same number of black nodes, - * - each red node (except for the root) has a black parent, - * - each leaf node is black. - * - * Every operation on a red-black tree is bounded as O(lg n). - * The maximum height of a red-black tree is 2lg (n+1). - */ - -#define SPLAY_HEAD(name, type) \ -struct name { \ - struct type *sph_root; /* root of the tree */ \ -} - -#define SPLAY_INITIALIZER(root) \ - { NULL } - -#define SPLAY_INIT(root) do { \ - (root)->sph_root = NULL; \ -} while (/*CONSTCOND*/ 0) - -#define SPLAY_ENTRY(type) \ -struct { \ - struct type *spe_left; /* left element */ \ - struct type *spe_right; /* right element */ \ -} - -#define SPLAY_LEFT(elm, field) (elm)->field.spe_left -#define SPLAY_RIGHT(elm, field) (elm)->field.spe_right -#define SPLAY_ROOT(head) (head)->sph_root -#define SPLAY_EMPTY(head) (SPLAY_ROOT(head) == NULL) - -/* SPLAY_ROTATE_{LEFT,RIGHT} expect that tmp hold SPLAY_{RIGHT,LEFT} */ -#define SPLAY_ROTATE_RIGHT(head, tmp, field) do { \ - SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field); \ - SPLAY_RIGHT(tmp, field) = (head)->sph_root; \ - (head)->sph_root = tmp; \ -} while (/*CONSTCOND*/ 0) - -#define SPLAY_ROTATE_LEFT(head, tmp, field) do { \ - SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field); \ - SPLAY_LEFT(tmp, field) = (head)->sph_root; \ - (head)->sph_root = tmp; \ -} while (/*CONSTCOND*/ 0) - -#define SPLAY_LINKLEFT(head, tmp, field) do { \ - SPLAY_LEFT(tmp, field) = (head)->sph_root; \ - tmp = (head)->sph_root; \ - (head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \ -} while (/*CONSTCOND*/ 0) - -#define SPLAY_LINKRIGHT(head, tmp, field) do { \ - SPLAY_RIGHT(tmp, field) = (head)->sph_root; \ - tmp = (head)->sph_root; \ - (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \ -} while (/*CONSTCOND*/ 0) - -#define SPLAY_ASSEMBLE(head, node, left, right, field) do { \ - SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field); \ - SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field); \ - SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field); \ - SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field); \ -} while (/*CONSTCOND*/ 0) - -/* Generates prototypes and inline functions */ - -#define SPLAY_PROTOTYPE(name, type, field, cmp) \ -void name##_SPLAY(struct name *, struct type *); \ -void name##_SPLAY_MINMAX(struct name *, int); \ -struct type *name##_SPLAY_INSERT(struct name *, struct type *); \ -struct type *name##_SPLAY_REMOVE(struct name *, struct type *); \ - \ -/* Finds the node with the same key as elm */ \ -static __inline struct type * \ -name##_SPLAY_FIND(struct name *head, struct type *elm) \ -{ \ - if (SPLAY_EMPTY(head)) \ - return(NULL); \ - name##_SPLAY(head, elm); \ - if ((cmp)(elm, (head)->sph_root) == 0) \ - return (head->sph_root); \ - return (NULL); \ -} \ - \ -static __inline struct type * \ -name##_SPLAY_NEXT(struct name *head, struct type *elm) \ -{ \ - name##_SPLAY(head, elm); \ - if (SPLAY_RIGHT(elm, field) != NULL) { \ - elm = SPLAY_RIGHT(elm, field); \ - while (SPLAY_LEFT(elm, field) != NULL) { \ - elm = SPLAY_LEFT(elm, field); \ - } \ - } else \ - elm = NULL; \ - return (elm); \ -} \ - \ -static __inline struct type * \ -name##_SPLAY_MIN_MAX(struct name *head, int val) \ -{ \ - name##_SPLAY_MINMAX(head, val); \ - return (SPLAY_ROOT(head)); \ -} - -/* Main splay operation. - * Moves node close to the key of elm to top - */ -#define SPLAY_GENERATE(name, type, field, cmp) \ -struct type * \ -name##_SPLAY_INSERT(struct name *head, struct type *elm) \ -{ \ - if (SPLAY_EMPTY(head)) { \ - SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = NULL; \ - } else { \ - int __comp; \ - name##_SPLAY(head, elm); \ - __comp = (cmp)(elm, (head)->sph_root); \ - if(__comp < 0) { \ - SPLAY_LEFT(elm, field) = SPLAY_LEFT((head)->sph_root, field); \ - SPLAY_RIGHT(elm, field) = (head)->sph_root; \ - SPLAY_LEFT((head)->sph_root, field) = NULL; \ - } else if (__comp > 0) { \ - SPLAY_RIGHT(elm, field) = SPLAY_RIGHT((head)->sph_root, field); \ - SPLAY_LEFT(elm, field) = (head)->sph_root; \ - SPLAY_RIGHT((head)->sph_root, field) = NULL; \ - } else \ - return ((head)->sph_root); \ - } \ - (head)->sph_root = (elm); \ - return (NULL); \ -} \ - \ -struct type * \ -name##_SPLAY_REMOVE(struct name *head, struct type *elm) \ -{ \ - struct type *__tmp; \ - if (SPLAY_EMPTY(head)) \ - return (NULL); \ - name##_SPLAY(head, elm); \ - if ((cmp)(elm, (head)->sph_root) == 0) { \ - if (SPLAY_LEFT((head)->sph_root, field) == NULL) { \ - (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \ - } else { \ - __tmp = SPLAY_RIGHT((head)->sph_root, field); \ - (head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \ - name##_SPLAY(head, elm); \ - SPLAY_RIGHT((head)->sph_root, field) = __tmp; \ - } \ - return (elm); \ - } \ - return (NULL); \ -} \ - \ -void \ -name##_SPLAY(struct name *head, struct type *elm) \ -{ \ - struct type __node, *__left, *__right, *__tmp; \ - int __comp; \ - \ - SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL; \ - __left = __right = &__node; \ - \ - while ((__comp = (cmp)(elm, (head)->sph_root)) != 0) { \ - if (__comp < 0) { \ - __tmp = SPLAY_LEFT((head)->sph_root, field); \ - if (__tmp == NULL) \ - break; \ - if ((cmp)(elm, __tmp) < 0){ \ - SPLAY_ROTATE_RIGHT(head, __tmp, field); \ - if (SPLAY_LEFT((head)->sph_root, field) == NULL) \ - break; \ - } \ - SPLAY_LINKLEFT(head, __right, field); \ - } else if (__comp > 0) { \ - __tmp = SPLAY_RIGHT((head)->sph_root, field); \ - if (__tmp == NULL) \ - break; \ - if ((cmp)(elm, __tmp) > 0){ \ - SPLAY_ROTATE_LEFT(head, __tmp, field); \ - if (SPLAY_RIGHT((head)->sph_root, field) == NULL) \ - break; \ - } \ - SPLAY_LINKRIGHT(head, __left, field); \ - } \ - } \ - SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \ -} \ - \ -/* Splay with either the minimum or the maximum element \ - * Used to find minimum or maximum element in tree. \ - */ \ -void name##_SPLAY_MINMAX(struct name *head, int __comp) \ -{ \ - struct type __node, *__left, *__right, *__tmp; \ - \ - SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL; \ - __left = __right = &__node; \ - \ - while (1) { \ - if (__comp < 0) { \ - __tmp = SPLAY_LEFT((head)->sph_root, field); \ - if (__tmp == NULL) \ - break; \ - if (__comp < 0){ \ - SPLAY_ROTATE_RIGHT(head, __tmp, field); \ - if (SPLAY_LEFT((head)->sph_root, field) == NULL) \ - break; \ - } \ - SPLAY_LINKLEFT(head, __right, field); \ - } else if (__comp > 0) { \ - __tmp = SPLAY_RIGHT((head)->sph_root, field); \ - if (__tmp == NULL) \ - break; \ - if (__comp > 0) { \ - SPLAY_ROTATE_LEFT(head, __tmp, field); \ - if (SPLAY_RIGHT((head)->sph_root, field) == NULL) \ - break; \ - } \ - SPLAY_LINKRIGHT(head, __left, field); \ - } \ - } \ - SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \ -} - -#define SPLAY_NEGINF -1 -#define SPLAY_INF 1 - -#define SPLAY_INSERT(name, x, y) name##_SPLAY_INSERT(x, y) -#define SPLAY_REMOVE(name, x, y) name##_SPLAY_REMOVE(x, y) -#define SPLAY_FIND(name, x, y) name##_SPLAY_FIND(x, y) -#define SPLAY_NEXT(name, x, y) name##_SPLAY_NEXT(x, y) -#define SPLAY_MIN(name, x) (SPLAY_EMPTY(x) ? NULL \ - : name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF)) -#define SPLAY_MAX(name, x) (SPLAY_EMPTY(x) ? NULL \ - : name##_SPLAY_MIN_MAX(x, SPLAY_INF)) - -#define SPLAY_FOREACH(x, name, head) \ - for ((x) = SPLAY_MIN(name, head); \ - (x) != NULL; \ - (x) = SPLAY_NEXT(name, head, x)) - -/* Macros that define a red-black tree */ -#define RB_HEAD(name, type) \ -struct name { \ - struct type *rbh_root; /* root of the tree */ \ -} - -#define RB_INITIALIZER(root) \ - { NULL } - -#define RB_INIT(root) do { \ - (root)->rbh_root = NULL; \ -} while (/*CONSTCOND*/ 0) - -#define RB_BLACK 0 -#define RB_RED 1 -#define RB_ENTRY(type) \ -struct { \ - struct type *rbe_left; /* left element */ \ - struct type *rbe_right; /* right element */ \ - struct type *rbe_parent; /* parent element */ \ - int rbe_color; /* node color */ \ -} - -#define RB_LEFT(elm, field) (elm)->field.rbe_left -#define RB_RIGHT(elm, field) (elm)->field.rbe_right -#define RB_PARENT(elm, field) (elm)->field.rbe_parent -#define RB_COLOR(elm, field) (elm)->field.rbe_color -#define RB_ROOT(head) (head)->rbh_root -#define RB_EMPTY(head) (RB_ROOT(head) == NULL) - -#define RB_SET(elm, parent, field) do { \ - RB_PARENT(elm, field) = parent; \ - RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL; \ - RB_COLOR(elm, field) = RB_RED; \ -} while (/*CONSTCOND*/ 0) - -#define RB_SET_BLACKRED(black, red, field) do { \ - RB_COLOR(black, field) = RB_BLACK; \ - RB_COLOR(red, field) = RB_RED; \ -} while (/*CONSTCOND*/ 0) - -#ifndef RB_AUGMENT -#define RB_AUGMENT(x) do {} while (0) -#endif - -#define RB_ROTATE_LEFT(head, elm, tmp, field) do { \ - (tmp) = RB_RIGHT(elm, field); \ - if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field)) != NULL) { \ - RB_PARENT(RB_LEFT(tmp, field), field) = (elm); \ - } \ - RB_AUGMENT(elm); \ - if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) { \ - if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \ - RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \ - else \ - RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \ - } else \ - (head)->rbh_root = (tmp); \ - RB_LEFT(tmp, field) = (elm); \ - RB_PARENT(elm, field) = (tmp); \ - RB_AUGMENT(tmp); \ - if ((RB_PARENT(tmp, field))) \ - RB_AUGMENT(RB_PARENT(tmp, field)); \ -} while (/*CONSTCOND*/ 0) - -#define RB_ROTATE_RIGHT(head, elm, tmp, field) do { \ - (tmp) = RB_LEFT(elm, field); \ - if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field)) != NULL) { \ - RB_PARENT(RB_RIGHT(tmp, field), field) = (elm); \ - } \ - RB_AUGMENT(elm); \ - if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) { \ - if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \ - RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \ - else \ - RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \ - } else \ - (head)->rbh_root = (tmp); \ - RB_RIGHT(tmp, field) = (elm); \ - RB_PARENT(elm, field) = (tmp); \ - RB_AUGMENT(tmp); \ - if ((RB_PARENT(tmp, field))) \ - RB_AUGMENT(RB_PARENT(tmp, field)); \ -} while (/*CONSTCOND*/ 0) - -/* Generates prototypes and inline functions */ -#define RB_PROTOTYPE(name, type, field, cmp) \ - RB_PROTOTYPE_INTERNAL(name, type, field, cmp,) -#define RB_PROTOTYPE_STATIC(name, type, field, cmp) \ - RB_PROTOTYPE_INTERNAL(name, type, field, cmp, UV__UNUSED static) -#define RB_PROTOTYPE_INTERNAL(name, type, field, cmp, attr) \ -attr void name##_RB_INSERT_COLOR(struct name *, struct type *); \ -attr void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\ -attr struct type *name##_RB_REMOVE(struct name *, struct type *); \ -attr struct type *name##_RB_INSERT(struct name *, struct type *); \ -attr struct type *name##_RB_FIND(struct name *, struct type *); \ -attr struct type *name##_RB_NFIND(struct name *, struct type *); \ -attr struct type *name##_RB_NEXT(struct type *); \ -attr struct type *name##_RB_PREV(struct type *); \ -attr struct type *name##_RB_MINMAX(struct name *, int); \ - \ - -/* Main rb operation. - * Moves node close to the key of elm to top - */ -#define RB_GENERATE(name, type, field, cmp) \ - RB_GENERATE_INTERNAL(name, type, field, cmp,) -#define RB_GENERATE_STATIC(name, type, field, cmp) \ - RB_GENERATE_INTERNAL(name, type, field, cmp, UV__UNUSED static) -#define RB_GENERATE_INTERNAL(name, type, field, cmp, attr) \ -attr void \ -name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \ -{ \ - struct type *parent, *gparent, *tmp; \ - while ((parent = RB_PARENT(elm, field)) != NULL && \ - RB_COLOR(parent, field) == RB_RED) { \ - gparent = RB_PARENT(parent, field); \ - if (parent == RB_LEFT(gparent, field)) { \ - tmp = RB_RIGHT(gparent, field); \ - if (tmp && RB_COLOR(tmp, field) == RB_RED) { \ - RB_COLOR(tmp, field) = RB_BLACK; \ - RB_SET_BLACKRED(parent, gparent, field); \ - elm = gparent; \ - continue; \ - } \ - if (RB_RIGHT(parent, field) == elm) { \ - RB_ROTATE_LEFT(head, parent, tmp, field); \ - tmp = parent; \ - parent = elm; \ - elm = tmp; \ - } \ - RB_SET_BLACKRED(parent, gparent, field); \ - RB_ROTATE_RIGHT(head, gparent, tmp, field); \ - } else { \ - tmp = RB_LEFT(gparent, field); \ - if (tmp && RB_COLOR(tmp, field) == RB_RED) { \ - RB_COLOR(tmp, field) = RB_BLACK; \ - RB_SET_BLACKRED(parent, gparent, field); \ - elm = gparent; \ - continue; \ - } \ - if (RB_LEFT(parent, field) == elm) { \ - RB_ROTATE_RIGHT(head, parent, tmp, field); \ - tmp = parent; \ - parent = elm; \ - elm = tmp; \ - } \ - RB_SET_BLACKRED(parent, gparent, field); \ - RB_ROTATE_LEFT(head, gparent, tmp, field); \ - } \ - } \ - RB_COLOR(head->rbh_root, field) = RB_BLACK; \ -} \ - \ -attr void \ -name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, \ - struct type *elm) \ -{ \ - struct type *tmp; \ - while ((elm == NULL || RB_COLOR(elm, field) == RB_BLACK) && \ - elm != RB_ROOT(head)) { \ - if (RB_LEFT(parent, field) == elm) { \ - tmp = RB_RIGHT(parent, field); \ - if (RB_COLOR(tmp, field) == RB_RED) { \ - RB_SET_BLACKRED(tmp, parent, field); \ - RB_ROTATE_LEFT(head, parent, tmp, field); \ - tmp = RB_RIGHT(parent, field); \ - } \ - if ((RB_LEFT(tmp, field) == NULL || \ - RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) && \ - (RB_RIGHT(tmp, field) == NULL || \ - RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) { \ - RB_COLOR(tmp, field) = RB_RED; \ - elm = parent; \ - parent = RB_PARENT(elm, field); \ - } else { \ - if (RB_RIGHT(tmp, field) == NULL || \ - RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK) { \ - struct type *oleft; \ - if ((oleft = RB_LEFT(tmp, field)) \ - != NULL) \ - RB_COLOR(oleft, field) = RB_BLACK; \ - RB_COLOR(tmp, field) = RB_RED; \ - RB_ROTATE_RIGHT(head, tmp, oleft, field); \ - tmp = RB_RIGHT(parent, field); \ - } \ - RB_COLOR(tmp, field) = RB_COLOR(parent, field); \ - RB_COLOR(parent, field) = RB_BLACK; \ - if (RB_RIGHT(tmp, field)) \ - RB_COLOR(RB_RIGHT(tmp, field), field) = RB_BLACK; \ - RB_ROTATE_LEFT(head, parent, tmp, field); \ - elm = RB_ROOT(head); \ - break; \ - } \ - } else { \ - tmp = RB_LEFT(parent, field); \ - if (RB_COLOR(tmp, field) == RB_RED) { \ - RB_SET_BLACKRED(tmp, parent, field); \ - RB_ROTATE_RIGHT(head, parent, tmp, field); \ - tmp = RB_LEFT(parent, field); \ - } \ - if ((RB_LEFT(tmp, field) == NULL || \ - RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) && \ - (RB_RIGHT(tmp, field) == NULL || \ - RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) { \ - RB_COLOR(tmp, field) = RB_RED; \ - elm = parent; \ - parent = RB_PARENT(elm, field); \ - } else { \ - if (RB_LEFT(tmp, field) == NULL || \ - RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) { \ - struct type *oright; \ - if ((oright = RB_RIGHT(tmp, field)) \ - != NULL) \ - RB_COLOR(oright, field) = RB_BLACK; \ - RB_COLOR(tmp, field) = RB_RED; \ - RB_ROTATE_LEFT(head, tmp, oright, field); \ - tmp = RB_LEFT(parent, field); \ - } \ - RB_COLOR(tmp, field) = RB_COLOR(parent, field); \ - RB_COLOR(parent, field) = RB_BLACK; \ - if (RB_LEFT(tmp, field)) \ - RB_COLOR(RB_LEFT(tmp, field), field) = RB_BLACK; \ - RB_ROTATE_RIGHT(head, parent, tmp, field); \ - elm = RB_ROOT(head); \ - break; \ - } \ - } \ - } \ - if (elm) \ - RB_COLOR(elm, field) = RB_BLACK; \ -} \ - \ -attr struct type * \ -name##_RB_REMOVE(struct name *head, struct type *elm) \ -{ \ - struct type *child, *parent, *old = elm; \ - int color; \ - if (RB_LEFT(elm, field) == NULL) \ - child = RB_RIGHT(elm, field); \ - else if (RB_RIGHT(elm, field) == NULL) \ - child = RB_LEFT(elm, field); \ - else { \ - struct type *left; \ - elm = RB_RIGHT(elm, field); \ - while ((left = RB_LEFT(elm, field)) != NULL) \ - elm = left; \ - child = RB_RIGHT(elm, field); \ - parent = RB_PARENT(elm, field); \ - color = RB_COLOR(elm, field); \ - if (child) \ - RB_PARENT(child, field) = parent; \ - if (parent) { \ - if (RB_LEFT(parent, field) == elm) \ - RB_LEFT(parent, field) = child; \ - else \ - RB_RIGHT(parent, field) = child; \ - RB_AUGMENT(parent); \ - } else \ - RB_ROOT(head) = child; \ - if (RB_PARENT(elm, field) == old) \ - parent = elm; \ - (elm)->field = (old)->field; \ - if (RB_PARENT(old, field)) { \ - if (RB_LEFT(RB_PARENT(old, field), field) == old) \ - RB_LEFT(RB_PARENT(old, field), field) = elm; \ - else \ - RB_RIGHT(RB_PARENT(old, field), field) = elm; \ - RB_AUGMENT(RB_PARENT(old, field)); \ - } else \ - RB_ROOT(head) = elm; \ - RB_PARENT(RB_LEFT(old, field), field) = elm; \ - if (RB_RIGHT(old, field)) \ - RB_PARENT(RB_RIGHT(old, field), field) = elm; \ - if (parent) { \ - left = parent; \ - do { \ - RB_AUGMENT(left); \ - } while ((left = RB_PARENT(left, field)) != NULL); \ - } \ - goto color; \ - } \ - parent = RB_PARENT(elm, field); \ - color = RB_COLOR(elm, field); \ - if (child) \ - RB_PARENT(child, field) = parent; \ - if (parent) { \ - if (RB_LEFT(parent, field) == elm) \ - RB_LEFT(parent, field) = child; \ - else \ - RB_RIGHT(parent, field) = child; \ - RB_AUGMENT(parent); \ - } else \ - RB_ROOT(head) = child; \ -color: \ - if (color == RB_BLACK) \ - name##_RB_REMOVE_COLOR(head, parent, child); \ - return (old); \ -} \ - \ -/* Inserts a node into the RB tree */ \ -attr struct type * \ -name##_RB_INSERT(struct name *head, struct type *elm) \ -{ \ - struct type *tmp; \ - struct type *parent = NULL; \ - int comp = 0; \ - tmp = RB_ROOT(head); \ - while (tmp) { \ - parent = tmp; \ - comp = (cmp)(elm, parent); \ - if (comp < 0) \ - tmp = RB_LEFT(tmp, field); \ - else if (comp > 0) \ - tmp = RB_RIGHT(tmp, field); \ - else \ - return (tmp); \ - } \ - RB_SET(elm, parent, field); \ - if (parent != NULL) { \ - if (comp < 0) \ - RB_LEFT(parent, field) = elm; \ - else \ - RB_RIGHT(parent, field) = elm; \ - RB_AUGMENT(parent); \ - } else \ - RB_ROOT(head) = elm; \ - name##_RB_INSERT_COLOR(head, elm); \ - return (NULL); \ -} \ - \ -/* Finds the node with the same key as elm */ \ -attr struct type * \ -name##_RB_FIND(struct name *head, struct type *elm) \ -{ \ - struct type *tmp = RB_ROOT(head); \ - int comp; \ - while (tmp) { \ - comp = cmp(elm, tmp); \ - if (comp < 0) \ - tmp = RB_LEFT(tmp, field); \ - else if (comp > 0) \ - tmp = RB_RIGHT(tmp, field); \ - else \ - return (tmp); \ - } \ - return (NULL); \ -} \ - \ -/* Finds the first node greater than or equal to the search key */ \ -attr struct type * \ -name##_RB_NFIND(struct name *head, struct type *elm) \ -{ \ - struct type *tmp = RB_ROOT(head); \ - struct type *res = NULL; \ - int comp; \ - while (tmp) { \ - comp = cmp(elm, tmp); \ - if (comp < 0) { \ - res = tmp; \ - tmp = RB_LEFT(tmp, field); \ - } \ - else if (comp > 0) \ - tmp = RB_RIGHT(tmp, field); \ - else \ - return (tmp); \ - } \ - return (res); \ -} \ - \ -/* ARGSUSED */ \ -attr struct type * \ -name##_RB_NEXT(struct type *elm) \ -{ \ - if (RB_RIGHT(elm, field)) { \ - elm = RB_RIGHT(elm, field); \ - while (RB_LEFT(elm, field)) \ - elm = RB_LEFT(elm, field); \ - } else { \ - if (RB_PARENT(elm, field) && \ - (elm == RB_LEFT(RB_PARENT(elm, field), field))) \ - elm = RB_PARENT(elm, field); \ - else { \ - while (RB_PARENT(elm, field) && \ - (elm == RB_RIGHT(RB_PARENT(elm, field), field))) \ - elm = RB_PARENT(elm, field); \ - elm = RB_PARENT(elm, field); \ - } \ - } \ - return (elm); \ -} \ - \ -/* ARGSUSED */ \ -attr struct type * \ -name##_RB_PREV(struct type *elm) \ -{ \ - if (RB_LEFT(elm, field)) { \ - elm = RB_LEFT(elm, field); \ - while (RB_RIGHT(elm, field)) \ - elm = RB_RIGHT(elm, field); \ - } else { \ - if (RB_PARENT(elm, field) && \ - (elm == RB_RIGHT(RB_PARENT(elm, field), field))) \ - elm = RB_PARENT(elm, field); \ - else { \ - while (RB_PARENT(elm, field) && \ - (elm == RB_LEFT(RB_PARENT(elm, field), field))) \ - elm = RB_PARENT(elm, field); \ - elm = RB_PARENT(elm, field); \ - } \ - } \ - return (elm); \ -} \ - \ -attr struct type * \ -name##_RB_MINMAX(struct name *head, int val) \ -{ \ - struct type *tmp = RB_ROOT(head); \ - struct type *parent = NULL; \ - while (tmp) { \ - parent = tmp; \ - if (val < 0) \ - tmp = RB_LEFT(tmp, field); \ - else \ - tmp = RB_RIGHT(tmp, field); \ - } \ - return (parent); \ -} - -#define RB_NEGINF -1 -#define RB_INF 1 - -#define RB_INSERT(name, x, y) name##_RB_INSERT(x, y) -#define RB_REMOVE(name, x, y) name##_RB_REMOVE(x, y) -#define RB_FIND(name, x, y) name##_RB_FIND(x, y) -#define RB_NFIND(name, x, y) name##_RB_NFIND(x, y) -#define RB_NEXT(name, x, y) name##_RB_NEXT(y) -#define RB_PREV(name, x, y) name##_RB_PREV(y) -#define RB_MIN(name, x) name##_RB_MINMAX(x, RB_NEGINF) -#define RB_MAX(name, x) name##_RB_MINMAX(x, RB_INF) - -#define RB_FOREACH(x, name, head) \ - for ((x) = RB_MIN(name, head); \ - (x) != NULL; \ - (x) = name##_RB_NEXT(x)) - -#define RB_FOREACH_FROM(x, name, y) \ - for ((x) = (y); \ - ((x) != NULL) && ((y) = name##_RB_NEXT(x), (x) != NULL); \ - (x) = (y)) - -#define RB_FOREACH_SAFE(x, name, head, y) \ - for ((x) = RB_MIN(name, head); \ - ((x) != NULL) && ((y) = name##_RB_NEXT(x), (x) != NULL); \ - (x) = (y)) - -#define RB_FOREACH_REVERSE(x, name, head) \ - for ((x) = RB_MAX(name, head); \ - (x) != NULL; \ - (x) = name##_RB_PREV(x)) - -#define RB_FOREACH_REVERSE_FROM(x, name, y) \ - for ((x) = (y); \ - ((x) != NULL) && ((y) = name##_RB_PREV(x), (x) != NULL); \ - (x) = (y)) - -#define RB_FOREACH_REVERSE_SAFE(x, name, head, y) \ - for ((x) = RB_MAX(name, head); \ - ((x) != NULL) && ((y) = name##_RB_PREV(x), (x) != NULL); \ - (x) = (y)) - -#endif /* UV_TREE_H_ */ diff --git a/vendor/libuv/include/uv-aix.h b/vendor/libuv/include/uv-aix.h deleted file mode 100644 index 7dc992fa6..000000000 --- a/vendor/libuv/include/uv-aix.h +++ /dev/null @@ -1,32 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef UV_AIX_H -#define UV_AIX_H - -#define UV_PLATFORM_LOOP_FIELDS \ - int fs_fd; \ - -#define UV_PLATFORM_FS_EVENT_FIELDS \ - uv__io_t event_watcher; \ - char *dir_filename; \ - -#endif /* UV_AIX_H */ diff --git a/vendor/libuv/include/uv-bsd.h b/vendor/libuv/include/uv-bsd.h deleted file mode 100644 index 2d72b3d77..000000000 --- a/vendor/libuv/include/uv-bsd.h +++ /dev/null @@ -1,34 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef UV_BSD_H -#define UV_BSD_H - -#define UV_PLATFORM_FS_EVENT_FIELDS \ - uv__io_t event_watcher; \ - -#define UV_IO_PRIVATE_PLATFORM_FIELDS \ - int rcount; \ - int wcount; \ - -#define UV_HAVE_KQUEUE 1 - -#endif /* UV_BSD_H */ diff --git a/vendor/libuv/include/uv-darwin.h b/vendor/libuv/include/uv-darwin.h deleted file mode 100644 index d22641582..000000000 --- a/vendor/libuv/include/uv-darwin.h +++ /dev/null @@ -1,61 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef UV_DARWIN_H -#define UV_DARWIN_H - -#if defined(__APPLE__) && defined(__MACH__) -# include -# include -# include -# include -# define UV_PLATFORM_SEM_T semaphore_t -#endif - -#define UV_IO_PRIVATE_PLATFORM_FIELDS \ - int rcount; \ - int wcount; \ - -#define UV_PLATFORM_LOOP_FIELDS \ - uv_thread_t cf_thread; \ - void* _cf_reserved; \ - void* cf_state; \ - uv_mutex_t cf_mutex; \ - uv_sem_t cf_sem; \ - void* cf_signals[2]; \ - -#define UV_PLATFORM_FS_EVENT_FIELDS \ - uv__io_t event_watcher; \ - char* realpath; \ - int realpath_len; \ - int cf_flags; \ - uv_async_t* cf_cb; \ - void* cf_events[2]; \ - void* cf_member[2]; \ - int cf_error; \ - uv_mutex_t cf_mutex; \ - -#define UV_STREAM_PRIVATE_PLATFORM_FIELDS \ - void* select; \ - -#define UV_HAVE_KQUEUE 1 - -#endif /* UV_DARWIN_H */ diff --git a/vendor/libuv/include/uv-errno.h b/vendor/libuv/include/uv-errno.h deleted file mode 100644 index f1371517c..000000000 --- a/vendor/libuv/include/uv-errno.h +++ /dev/null @@ -1,419 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef UV_ERRNO_H_ -#define UV_ERRNO_H_ - -#include - -#define UV__EOF (-4095) -#define UV__UNKNOWN (-4094) - -#define UV__EAI_ADDRFAMILY (-3000) -#define UV__EAI_AGAIN (-3001) -#define UV__EAI_BADFLAGS (-3002) -#define UV__EAI_CANCELED (-3003) -#define UV__EAI_FAIL (-3004) -#define UV__EAI_FAMILY (-3005) -#define UV__EAI_MEMORY (-3006) -#define UV__EAI_NODATA (-3007) -#define UV__EAI_NONAME (-3008) -#define UV__EAI_OVERFLOW (-3009) -#define UV__EAI_SERVICE (-3010) -#define UV__EAI_SOCKTYPE (-3011) -#define UV__EAI_BADHINTS (-3013) -#define UV__EAI_PROTOCOL (-3014) - -/* Only map to the system errno on non-Windows platforms. It's apparently - * a fairly common practice for Windows programmers to redefine errno codes. - */ -#if defined(E2BIG) && !defined(_WIN32) -# define UV__E2BIG (-E2BIG) -#else -# define UV__E2BIG (-4093) -#endif - -#if defined(EACCES) && !defined(_WIN32) -# define UV__EACCES (-EACCES) -#else -# define UV__EACCES (-4092) -#endif - -#if defined(EADDRINUSE) && !defined(_WIN32) -# define UV__EADDRINUSE (-EADDRINUSE) -#else -# define UV__EADDRINUSE (-4091) -#endif - -#if defined(EADDRNOTAVAIL) && !defined(_WIN32) -# define UV__EADDRNOTAVAIL (-EADDRNOTAVAIL) -#else -# define UV__EADDRNOTAVAIL (-4090) -#endif - -#if defined(EAFNOSUPPORT) && !defined(_WIN32) -# define UV__EAFNOSUPPORT (-EAFNOSUPPORT) -#else -# define UV__EAFNOSUPPORT (-4089) -#endif - -#if defined(EAGAIN) && !defined(_WIN32) -# define UV__EAGAIN (-EAGAIN) -#else -# define UV__EAGAIN (-4088) -#endif - -#if defined(EALREADY) && !defined(_WIN32) -# define UV__EALREADY (-EALREADY) -#else -# define UV__EALREADY (-4084) -#endif - -#if defined(EBADF) && !defined(_WIN32) -# define UV__EBADF (-EBADF) -#else -# define UV__EBADF (-4083) -#endif - -#if defined(EBUSY) && !defined(_WIN32) -# define UV__EBUSY (-EBUSY) -#else -# define UV__EBUSY (-4082) -#endif - -#if defined(ECANCELED) && !defined(_WIN32) -# define UV__ECANCELED (-ECANCELED) -#else -# define UV__ECANCELED (-4081) -#endif - -#if defined(ECHARSET) && !defined(_WIN32) -# define UV__ECHARSET (-ECHARSET) -#else -# define UV__ECHARSET (-4080) -#endif - -#if defined(ECONNABORTED) && !defined(_WIN32) -# define UV__ECONNABORTED (-ECONNABORTED) -#else -# define UV__ECONNABORTED (-4079) -#endif - -#if defined(ECONNREFUSED) && !defined(_WIN32) -# define UV__ECONNREFUSED (-ECONNREFUSED) -#else -# define UV__ECONNREFUSED (-4078) -#endif - -#if defined(ECONNRESET) && !defined(_WIN32) -# define UV__ECONNRESET (-ECONNRESET) -#else -# define UV__ECONNRESET (-4077) -#endif - -#if defined(EDESTADDRREQ) && !defined(_WIN32) -# define UV__EDESTADDRREQ (-EDESTADDRREQ) -#else -# define UV__EDESTADDRREQ (-4076) -#endif - -#if defined(EEXIST) && !defined(_WIN32) -# define UV__EEXIST (-EEXIST) -#else -# define UV__EEXIST (-4075) -#endif - -#if defined(EFAULT) && !defined(_WIN32) -# define UV__EFAULT (-EFAULT) -#else -# define UV__EFAULT (-4074) -#endif - -#if defined(EHOSTUNREACH) && !defined(_WIN32) -# define UV__EHOSTUNREACH (-EHOSTUNREACH) -#else -# define UV__EHOSTUNREACH (-4073) -#endif - -#if defined(EINTR) && !defined(_WIN32) -# define UV__EINTR (-EINTR) -#else -# define UV__EINTR (-4072) -#endif - -#if defined(EINVAL) && !defined(_WIN32) -# define UV__EINVAL (-EINVAL) -#else -# define UV__EINVAL (-4071) -#endif - -#if defined(EIO) && !defined(_WIN32) -# define UV__EIO (-EIO) -#else -# define UV__EIO (-4070) -#endif - -#if defined(EISCONN) && !defined(_WIN32) -# define UV__EISCONN (-EISCONN) -#else -# define UV__EISCONN (-4069) -#endif - -#if defined(EISDIR) && !defined(_WIN32) -# define UV__EISDIR (-EISDIR) -#else -# define UV__EISDIR (-4068) -#endif - -#if defined(ELOOP) && !defined(_WIN32) -# define UV__ELOOP (-ELOOP) -#else -# define UV__ELOOP (-4067) -#endif - -#if defined(EMFILE) && !defined(_WIN32) -# define UV__EMFILE (-EMFILE) -#else -# define UV__EMFILE (-4066) -#endif - -#if defined(EMSGSIZE) && !defined(_WIN32) -# define UV__EMSGSIZE (-EMSGSIZE) -#else -# define UV__EMSGSIZE (-4065) -#endif - -#if defined(ENAMETOOLONG) && !defined(_WIN32) -# define UV__ENAMETOOLONG (-ENAMETOOLONG) -#else -# define UV__ENAMETOOLONG (-4064) -#endif - -#if defined(ENETDOWN) && !defined(_WIN32) -# define UV__ENETDOWN (-ENETDOWN) -#else -# define UV__ENETDOWN (-4063) -#endif - -#if defined(ENETUNREACH) && !defined(_WIN32) -# define UV__ENETUNREACH (-ENETUNREACH) -#else -# define UV__ENETUNREACH (-4062) -#endif - -#if defined(ENFILE) && !defined(_WIN32) -# define UV__ENFILE (-ENFILE) -#else -# define UV__ENFILE (-4061) -#endif - -#if defined(ENOBUFS) && !defined(_WIN32) -# define UV__ENOBUFS (-ENOBUFS) -#else -# define UV__ENOBUFS (-4060) -#endif - -#if defined(ENODEV) && !defined(_WIN32) -# define UV__ENODEV (-ENODEV) -#else -# define UV__ENODEV (-4059) -#endif - -#if defined(ENOENT) && !defined(_WIN32) -# define UV__ENOENT (-ENOENT) -#else -# define UV__ENOENT (-4058) -#endif - -#if defined(ENOMEM) && !defined(_WIN32) -# define UV__ENOMEM (-ENOMEM) -#else -# define UV__ENOMEM (-4057) -#endif - -#if defined(ENONET) && !defined(_WIN32) -# define UV__ENONET (-ENONET) -#else -# define UV__ENONET (-4056) -#endif - -#if defined(ENOSPC) && !defined(_WIN32) -# define UV__ENOSPC (-ENOSPC) -#else -# define UV__ENOSPC (-4055) -#endif - -#if defined(ENOSYS) && !defined(_WIN32) -# define UV__ENOSYS (-ENOSYS) -#else -# define UV__ENOSYS (-4054) -#endif - -#if defined(ENOTCONN) && !defined(_WIN32) -# define UV__ENOTCONN (-ENOTCONN) -#else -# define UV__ENOTCONN (-4053) -#endif - -#if defined(ENOTDIR) && !defined(_WIN32) -# define UV__ENOTDIR (-ENOTDIR) -#else -# define UV__ENOTDIR (-4052) -#endif - -#if defined(ENOTEMPTY) && !defined(_WIN32) -# define UV__ENOTEMPTY (-ENOTEMPTY) -#else -# define UV__ENOTEMPTY (-4051) -#endif - -#if defined(ENOTSOCK) && !defined(_WIN32) -# define UV__ENOTSOCK (-ENOTSOCK) -#else -# define UV__ENOTSOCK (-4050) -#endif - -#if defined(ENOTSUP) && !defined(_WIN32) -# define UV__ENOTSUP (-ENOTSUP) -#else -# define UV__ENOTSUP (-4049) -#endif - -#if defined(EPERM) && !defined(_WIN32) -# define UV__EPERM (-EPERM) -#else -# define UV__EPERM (-4048) -#endif - -#if defined(EPIPE) && !defined(_WIN32) -# define UV__EPIPE (-EPIPE) -#else -# define UV__EPIPE (-4047) -#endif - -#if defined(EPROTO) && !defined(_WIN32) -# define UV__EPROTO (-EPROTO) -#else -# define UV__EPROTO (-4046) -#endif - -#if defined(EPROTONOSUPPORT) && !defined(_WIN32) -# define UV__EPROTONOSUPPORT (-EPROTONOSUPPORT) -#else -# define UV__EPROTONOSUPPORT (-4045) -#endif - -#if defined(EPROTOTYPE) && !defined(_WIN32) -# define UV__EPROTOTYPE (-EPROTOTYPE) -#else -# define UV__EPROTOTYPE (-4044) -#endif - -#if defined(EROFS) && !defined(_WIN32) -# define UV__EROFS (-EROFS) -#else -# define UV__EROFS (-4043) -#endif - -#if defined(ESHUTDOWN) && !defined(_WIN32) -# define UV__ESHUTDOWN (-ESHUTDOWN) -#else -# define UV__ESHUTDOWN (-4042) -#endif - -#if defined(ESPIPE) && !defined(_WIN32) -# define UV__ESPIPE (-ESPIPE) -#else -# define UV__ESPIPE (-4041) -#endif - -#if defined(ESRCH) && !defined(_WIN32) -# define UV__ESRCH (-ESRCH) -#else -# define UV__ESRCH (-4040) -#endif - -#if defined(ETIMEDOUT) && !defined(_WIN32) -# define UV__ETIMEDOUT (-ETIMEDOUT) -#else -# define UV__ETIMEDOUT (-4039) -#endif - -#if defined(ETXTBSY) && !defined(_WIN32) -# define UV__ETXTBSY (-ETXTBSY) -#else -# define UV__ETXTBSY (-4038) -#endif - -#if defined(EXDEV) && !defined(_WIN32) -# define UV__EXDEV (-EXDEV) -#else -# define UV__EXDEV (-4037) -#endif - -#if defined(EFBIG) && !defined(_WIN32) -# define UV__EFBIG (-EFBIG) -#else -# define UV__EFBIG (-4036) -#endif - -#if defined(ENOPROTOOPT) && !defined(_WIN32) -# define UV__ENOPROTOOPT (-ENOPROTOOPT) -#else -# define UV__ENOPROTOOPT (-4035) -#endif - -#if defined(ERANGE) && !defined(_WIN32) -# define UV__ERANGE (-ERANGE) -#else -# define UV__ERANGE (-4034) -#endif - -#if defined(ENXIO) && !defined(_WIN32) -# define UV__ENXIO (-ENXIO) -#else -# define UV__ENXIO (-4033) -#endif - -#if defined(EMLINK) && !defined(_WIN32) -# define UV__EMLINK (-EMLINK) -#else -# define UV__EMLINK (-4032) -#endif - -/* EHOSTDOWN is not visible on BSD-like systems when _POSIX_C_SOURCE is - * defined. Fortunately, its value is always 64 so it's possible albeit - * icky to hard-code it. - */ -#if defined(EHOSTDOWN) && !defined(_WIN32) -# define UV__EHOSTDOWN (-EHOSTDOWN) -#elif defined(__APPLE__) || \ - defined(__DragonFly__) || \ - defined(__FreeBSD__) || \ - defined(__FreeBSD_kernel__) || \ - defined(__NetBSD__) || \ - defined(__OpenBSD__) -# define UV__EHOSTDOWN (-64) -#else -# define UV__EHOSTDOWN (-4031) -#endif - -#endif /* UV_ERRNO_H_ */ diff --git a/vendor/libuv/include/uv-linux.h b/vendor/libuv/include/uv-linux.h deleted file mode 100644 index 9b38405a1..000000000 --- a/vendor/libuv/include/uv-linux.h +++ /dev/null @@ -1,34 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef UV_LINUX_H -#define UV_LINUX_H - -#define UV_PLATFORM_LOOP_FIELDS \ - uv__io_t inotify_read_watcher; \ - void* inotify_watchers; \ - int inotify_fd; \ - -#define UV_PLATFORM_FS_EVENT_FIELDS \ - void* watchers[2]; \ - int wd; \ - -#endif /* UV_LINUX_H */ diff --git a/vendor/libuv/include/uv-os390.h b/vendor/libuv/include/uv-os390.h deleted file mode 100644 index 58f926111..000000000 --- a/vendor/libuv/include/uv-os390.h +++ /dev/null @@ -1,30 +0,0 @@ -/* Copyright libuv project contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef UV_MVS_H -#define UV_MVS_H - -#define UV_PLATFORM_SEM_T int - -#define UV_PLATFORM_LOOP_FIELDS \ - void* ep; \ - -#endif /* UV_MVS_H */ diff --git a/vendor/libuv/include/uv-sunos.h b/vendor/libuv/include/uv-sunos.h deleted file mode 100644 index 042166424..000000000 --- a/vendor/libuv/include/uv-sunos.h +++ /dev/null @@ -1,44 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef UV_SUNOS_H -#define UV_SUNOS_H - -#include -#include - -/* For the sake of convenience and reduced #ifdef-ery in src/unix/sunos.c, - * add the fs_event fields even when this version of SunOS doesn't support - * file watching. - */ -#define UV_PLATFORM_LOOP_FIELDS \ - uv__io_t fs_event_watcher; \ - int fs_fd; \ - -#if defined(PORT_SOURCE_FILE) - -# define UV_PLATFORM_FS_EVENT_FIELDS \ - file_obj_t fo; \ - int fd; \ - -#endif /* defined(PORT_SOURCE_FILE) */ - -#endif /* UV_SUNOS_H */ diff --git a/vendor/libuv/include/uv-threadpool.h b/vendor/libuv/include/uv-threadpool.h deleted file mode 100644 index 9708ebdd5..000000000 --- a/vendor/libuv/include/uv-threadpool.h +++ /dev/null @@ -1,37 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -/* - * This file is private to libuv. It provides common functionality to both - * Windows and Unix backends. - */ - -#ifndef UV_THREADPOOL_H_ -#define UV_THREADPOOL_H_ - -struct uv__work { - void (*work)(struct uv__work *w); - void (*done)(struct uv__work *w, int status); - struct uv_loop_s* loop; - void* wq[2]; -}; - -#endif /* UV_THREADPOOL_H_ */ diff --git a/vendor/libuv/include/uv-unix.h b/vendor/libuv/include/uv-unix.h deleted file mode 100644 index 3030f719a..000000000 --- a/vendor/libuv/include/uv-unix.h +++ /dev/null @@ -1,375 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef UV_UNIX_H -#define UV_UNIX_H - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include - -#if !defined(__MVS__) -#include -#endif -#include -#include - -#include "uv-threadpool.h" - -#if defined(__linux__) -# include "uv-linux.h" -#elif defined (__MVS__) -# include "uv-os390.h" -#elif defined(_AIX) -# include "uv-aix.h" -#elif defined(__sun) -# include "uv-sunos.h" -#elif defined(__APPLE__) -# include "uv-darwin.h" -#elif defined(__DragonFly__) || \ - defined(__FreeBSD__) || \ - defined(__FreeBSD_kernel__) || \ - defined(__OpenBSD__) || \ - defined(__NetBSD__) -# include "uv-bsd.h" -#endif - -#ifndef PTHREAD_BARRIER_SERIAL_THREAD -# include "pthread-barrier.h" -#endif - -#ifndef NI_MAXHOST -# define NI_MAXHOST 1025 -#endif - -#ifndef NI_MAXSERV -# define NI_MAXSERV 32 -#endif - -#ifndef UV_IO_PRIVATE_PLATFORM_FIELDS -# define UV_IO_PRIVATE_PLATFORM_FIELDS /* empty */ -#endif - -struct uv__io_s; -struct uv__async; -struct uv_loop_s; - -typedef void (*uv__io_cb)(struct uv_loop_s* loop, - struct uv__io_s* w, - unsigned int events); -typedef struct uv__io_s uv__io_t; - -struct uv__io_s { - uv__io_cb cb; - void* pending_queue[2]; - void* watcher_queue[2]; - unsigned int pevents; /* Pending event mask i.e. mask at next tick. */ - unsigned int events; /* Current event mask. */ - int fd; - UV_IO_PRIVATE_PLATFORM_FIELDS -}; - -typedef void (*uv__async_cb)(struct uv_loop_s* loop, - struct uv__async* w, - unsigned int nevents); - -struct uv__async { - uv__async_cb cb; - uv__io_t io_watcher; - int wfd; -}; - -#ifndef UV_PLATFORM_SEM_T -# define UV_PLATFORM_SEM_T sem_t -#endif - -#ifndef UV_PLATFORM_LOOP_FIELDS -# define UV_PLATFORM_LOOP_FIELDS /* empty */ -#endif - -#ifndef UV_PLATFORM_FS_EVENT_FIELDS -# define UV_PLATFORM_FS_EVENT_FIELDS /* empty */ -#endif - -#ifndef UV_STREAM_PRIVATE_PLATFORM_FIELDS -# define UV_STREAM_PRIVATE_PLATFORM_FIELDS /* empty */ -#endif - -/* Note: May be cast to struct iovec. See writev(2). */ -typedef struct uv_buf_t { - char* base; - size_t len; -} uv_buf_t; - -typedef int uv_file; -typedef int uv_os_sock_t; -typedef int uv_os_fd_t; - -#define UV_ONCE_INIT PTHREAD_ONCE_INIT - -typedef pthread_once_t uv_once_t; -typedef pthread_t uv_thread_t; -typedef pthread_mutex_t uv_mutex_t; -typedef pthread_rwlock_t uv_rwlock_t; -typedef UV_PLATFORM_SEM_T uv_sem_t; -typedef pthread_cond_t uv_cond_t; -typedef pthread_key_t uv_key_t; -typedef pthread_barrier_t uv_barrier_t; - - -/* Platform-specific definitions for uv_spawn support. */ -typedef gid_t uv_gid_t; -typedef uid_t uv_uid_t; - -typedef struct dirent uv__dirent_t; - -#if defined(DT_UNKNOWN) -# define HAVE_DIRENT_TYPES -# if defined(DT_REG) -# define UV__DT_FILE DT_REG -# else -# define UV__DT_FILE -1 -# endif -# if defined(DT_DIR) -# define UV__DT_DIR DT_DIR -# else -# define UV__DT_DIR -2 -# endif -# if defined(DT_LNK) -# define UV__DT_LINK DT_LNK -# else -# define UV__DT_LINK -3 -# endif -# if defined(DT_FIFO) -# define UV__DT_FIFO DT_FIFO -# else -# define UV__DT_FIFO -4 -# endif -# if defined(DT_SOCK) -# define UV__DT_SOCKET DT_SOCK -# else -# define UV__DT_SOCKET -5 -# endif -# if defined(DT_CHR) -# define UV__DT_CHAR DT_CHR -# else -# define UV__DT_CHAR -6 -# endif -# if defined(DT_BLK) -# define UV__DT_BLOCK DT_BLK -# else -# define UV__DT_BLOCK -7 -# endif -#endif - -/* Platform-specific definitions for uv_dlopen support. */ -#define UV_DYNAMIC /* empty */ - -typedef struct { - void* handle; - char* errmsg; -} uv_lib_t; - -#define UV_LOOP_PRIVATE_FIELDS \ - unsigned long flags; \ - int backend_fd; \ - void* pending_queue[2]; \ - void* watcher_queue[2]; \ - uv__io_t** watchers; \ - unsigned int nwatchers; \ - unsigned int nfds; \ - void* wq[2]; \ - uv_mutex_t wq_mutex; \ - uv_async_t wq_async; \ - uv_rwlock_t cloexec_lock; \ - uv_handle_t* closing_handles; \ - void* process_handles[2]; \ - void* prepare_handles[2]; \ - void* check_handles[2]; \ - void* idle_handles[2]; \ - void* async_handles[2]; \ - struct uv__async async_watcher; \ - struct { \ - void* min; \ - unsigned int nelts; \ - } timer_heap; \ - uint64_t timer_counter; \ - uint64_t time; \ - int signal_pipefd[2]; \ - uv__io_t signal_io_watcher; \ - uv_signal_t child_watcher; \ - int emfile_fd; \ - UV_PLATFORM_LOOP_FIELDS \ - -#define UV_REQ_TYPE_PRIVATE /* empty */ - -#define UV_REQ_PRIVATE_FIELDS /* empty */ - -#define UV_PRIVATE_REQ_TYPES /* empty */ - -#define UV_WRITE_PRIVATE_FIELDS \ - void* queue[2]; \ - unsigned int write_index; \ - uv_buf_t* bufs; \ - unsigned int nbufs; \ - int error; \ - uv_buf_t bufsml[4]; \ - -#define UV_CONNECT_PRIVATE_FIELDS \ - void* queue[2]; \ - -#define UV_SHUTDOWN_PRIVATE_FIELDS /* empty */ - -#define UV_UDP_SEND_PRIVATE_FIELDS \ - void* queue[2]; \ - struct sockaddr_storage addr; \ - unsigned int nbufs; \ - uv_buf_t* bufs; \ - ssize_t status; \ - uv_udp_send_cb send_cb; \ - uv_buf_t bufsml[4]; \ - -#define UV_HANDLE_PRIVATE_FIELDS \ - uv_handle_t* next_closing; \ - unsigned int flags; \ - -#define UV_STREAM_PRIVATE_FIELDS \ - uv_connect_t *connect_req; \ - uv_shutdown_t *shutdown_req; \ - uv__io_t io_watcher; \ - void* write_queue[2]; \ - void* write_completed_queue[2]; \ - uv_connection_cb connection_cb; \ - int delayed_error; \ - int accepted_fd; \ - void* queued_fds; \ - UV_STREAM_PRIVATE_PLATFORM_FIELDS \ - -#define UV_TCP_PRIVATE_FIELDS /* empty */ - -#define UV_UDP_PRIVATE_FIELDS \ - uv_alloc_cb alloc_cb; \ - uv_udp_recv_cb recv_cb; \ - uv__io_t io_watcher; \ - void* write_queue[2]; \ - void* write_completed_queue[2]; \ - -#define UV_PIPE_PRIVATE_FIELDS \ - const char* pipe_fname; /* strdup'ed */ - -#define UV_POLL_PRIVATE_FIELDS \ - uv__io_t io_watcher; - -#define UV_PREPARE_PRIVATE_FIELDS \ - uv_prepare_cb prepare_cb; \ - void* queue[2]; \ - -#define UV_CHECK_PRIVATE_FIELDS \ - uv_check_cb check_cb; \ - void* queue[2]; \ - -#define UV_IDLE_PRIVATE_FIELDS \ - uv_idle_cb idle_cb; \ - void* queue[2]; \ - -#define UV_ASYNC_PRIVATE_FIELDS \ - uv_async_cb async_cb; \ - void* queue[2]; \ - int pending; \ - -#define UV_TIMER_PRIVATE_FIELDS \ - uv_timer_cb timer_cb; \ - void* heap_node[3]; \ - uint64_t timeout; \ - uint64_t repeat; \ - uint64_t start_id; - -#define UV_GETADDRINFO_PRIVATE_FIELDS \ - struct uv__work work_req; \ - uv_getaddrinfo_cb cb; \ - struct addrinfo* hints; \ - char* hostname; \ - char* service; \ - struct addrinfo* addrinfo; \ - int retcode; - -#define UV_GETNAMEINFO_PRIVATE_FIELDS \ - struct uv__work work_req; \ - uv_getnameinfo_cb getnameinfo_cb; \ - struct sockaddr_storage storage; \ - int flags; \ - char host[NI_MAXHOST]; \ - char service[NI_MAXSERV]; \ - int retcode; - -#define UV_PROCESS_PRIVATE_FIELDS \ - void* queue[2]; \ - int status; \ - -#define UV_FS_PRIVATE_FIELDS \ - const char *new_path; \ - uv_file file; \ - int flags; \ - mode_t mode; \ - unsigned int nbufs; \ - uv_buf_t* bufs; \ - off_t off; \ - uv_uid_t uid; \ - uv_gid_t gid; \ - double atime; \ - double mtime; \ - struct uv__work work_req; \ - uv_buf_t bufsml[4]; \ - -#define UV_WORK_PRIVATE_FIELDS \ - struct uv__work work_req; - -#define UV_TTY_PRIVATE_FIELDS \ - struct termios orig_termios; \ - int mode; - -#define UV_SIGNAL_PRIVATE_FIELDS \ - /* RB_ENTRY(uv_signal_s) tree_entry; */ \ - struct { \ - struct uv_signal_s* rbe_left; \ - struct uv_signal_s* rbe_right; \ - struct uv_signal_s* rbe_parent; \ - int rbe_color; \ - } tree_entry; \ - /* Use two counters here so we don have to fiddle with atomics. */ \ - unsigned int caught_signals; \ - unsigned int dispatched_signals; - -#define UV_FS_EVENT_PRIVATE_FIELDS \ - uv_fs_event_cb cb; \ - UV_PLATFORM_FS_EVENT_FIELDS \ - -#endif /* UV_UNIX_H */ diff --git a/vendor/libuv/include/uv-version.h b/vendor/libuv/include/uv-version.h deleted file mode 100644 index e16580903..000000000 --- a/vendor/libuv/include/uv-version.h +++ /dev/null @@ -1,43 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef UV_VERSION_H -#define UV_VERSION_H - - /* - * Versions with the same major number are ABI stable. API is allowed to - * evolve between minor releases, but only in a backwards compatible way. - * Make sure you update the -soname directives in configure.ac - * and uv.gyp whenever you bump UV_VERSION_MAJOR or UV_VERSION_MINOR (but - * not UV_VERSION_PATCH.) - */ - -#define UV_VERSION_MAJOR 1 -#define UV_VERSION_MINOR 11 -#define UV_VERSION_PATCH 1 -#define UV_VERSION_IS_RELEASE 0 -#define UV_VERSION_SUFFIX "dev" - -#define UV_VERSION_HEX ((UV_VERSION_MAJOR << 16) | \ - (UV_VERSION_MINOR << 8) | \ - (UV_VERSION_PATCH)) - -#endif /* UV_VERSION_H */ diff --git a/vendor/libuv/include/uv-win.h b/vendor/libuv/include/uv-win.h deleted file mode 100644 index 9677ff164..000000000 --- a/vendor/libuv/include/uv-win.h +++ /dev/null @@ -1,650 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef _WIN32_WINNT -# define _WIN32_WINNT 0x0502 -#endif - -#if !defined(_SSIZE_T_) && !defined(_SSIZE_T_DEFINED) -typedef intptr_t ssize_t; -# define _SSIZE_T_ -# define _SSIZE_T_DEFINED -#endif - -#include - -#if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR) -typedef struct pollfd { - SOCKET fd; - short events; - short revents; -} WSAPOLLFD, *PWSAPOLLFD, *LPWSAPOLLFD; -#endif - -#ifndef LOCALE_INVARIANT -# define LOCALE_INVARIANT 0x007f -#endif - -#include -#include -#include - -#include -#include -#include -#include - -#if defined(_MSC_VER) && _MSC_VER < 1600 -# include "stdint-msvc2008.h" -#else -# include -#endif - -#include "tree.h" -#include "uv-threadpool.h" - -#define MAX_PIPENAME_LEN 256 - -#ifndef S_IFLNK -# define S_IFLNK 0xA000 -#endif - -/* Additional signals supported by uv_signal and or uv_kill. The CRT defines - * the following signals already: - * - * #define SIGINT 2 - * #define SIGILL 4 - * #define SIGABRT_COMPAT 6 - * #define SIGFPE 8 - * #define SIGSEGV 11 - * #define SIGTERM 15 - * #define SIGBREAK 21 - * #define SIGABRT 22 - * - * The additional signals have values that are common on other Unix - * variants (Linux and Darwin) - */ -#define SIGHUP 1 -#define SIGKILL 9 -#define SIGWINCH 28 - -/* The CRT defines SIGABRT_COMPAT as 6, which equals SIGABRT on many */ -/* unix-like platforms. However MinGW doesn't define it, so we do. */ -#ifndef SIGABRT_COMPAT -# define SIGABRT_COMPAT 6 -#endif - -/* - * Guids and typedefs for winsock extension functions - * Mingw32 doesn't have these :-( - */ -#ifndef WSAID_ACCEPTEX -# define WSAID_ACCEPTEX \ - {0xb5367df1, 0xcbac, 0x11cf, \ - {0x95, 0xca, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}} - -# define WSAID_CONNECTEX \ - {0x25a207b9, 0xddf3, 0x4660, \ - {0x8e, 0xe9, 0x76, 0xe5, 0x8c, 0x74, 0x06, 0x3e}} - -# define WSAID_GETACCEPTEXSOCKADDRS \ - {0xb5367df2, 0xcbac, 0x11cf, \ - {0x95, 0xca, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}} - -# define WSAID_DISCONNECTEX \ - {0x7fda2e11, 0x8630, 0x436f, \ - {0xa0, 0x31, 0xf5, 0x36, 0xa6, 0xee, 0xc1, 0x57}} - -# define WSAID_TRANSMITFILE \ - {0xb5367df0, 0xcbac, 0x11cf, \ - {0x95, 0xca, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}} - - typedef BOOL (PASCAL *LPFN_ACCEPTEX) - (SOCKET sListenSocket, - SOCKET sAcceptSocket, - PVOID lpOutputBuffer, - DWORD dwReceiveDataLength, - DWORD dwLocalAddressLength, - DWORD dwRemoteAddressLength, - LPDWORD lpdwBytesReceived, - LPOVERLAPPED lpOverlapped); - - typedef BOOL (PASCAL *LPFN_CONNECTEX) - (SOCKET s, - const struct sockaddr* name, - int namelen, - PVOID lpSendBuffer, - DWORD dwSendDataLength, - LPDWORD lpdwBytesSent, - LPOVERLAPPED lpOverlapped); - - typedef void (PASCAL *LPFN_GETACCEPTEXSOCKADDRS) - (PVOID lpOutputBuffer, - DWORD dwReceiveDataLength, - DWORD dwLocalAddressLength, - DWORD dwRemoteAddressLength, - LPSOCKADDR* LocalSockaddr, - LPINT LocalSockaddrLength, - LPSOCKADDR* RemoteSockaddr, - LPINT RemoteSockaddrLength); - - typedef BOOL (PASCAL *LPFN_DISCONNECTEX) - (SOCKET hSocket, - LPOVERLAPPED lpOverlapped, - DWORD dwFlags, - DWORD reserved); - - typedef BOOL (PASCAL *LPFN_TRANSMITFILE) - (SOCKET hSocket, - HANDLE hFile, - DWORD nNumberOfBytesToWrite, - DWORD nNumberOfBytesPerSend, - LPOVERLAPPED lpOverlapped, - LPTRANSMIT_FILE_BUFFERS lpTransmitBuffers, - DWORD dwFlags); - - typedef PVOID RTL_SRWLOCK; - typedef RTL_SRWLOCK SRWLOCK, *PSRWLOCK; -#endif - -typedef int (WSAAPI* LPFN_WSARECV) - (SOCKET socket, - LPWSABUF buffers, - DWORD buffer_count, - LPDWORD bytes, - LPDWORD flags, - LPWSAOVERLAPPED overlapped, - LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_routine); - -typedef int (WSAAPI* LPFN_WSARECVFROM) - (SOCKET socket, - LPWSABUF buffers, - DWORD buffer_count, - LPDWORD bytes, - LPDWORD flags, - struct sockaddr* addr, - LPINT addr_len, - LPWSAOVERLAPPED overlapped, - LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_routine); - -#ifndef _NTDEF_ - typedef LONG NTSTATUS; - typedef NTSTATUS *PNTSTATUS; -#endif - -#ifndef RTL_CONDITION_VARIABLE_INIT - typedef PVOID CONDITION_VARIABLE, *PCONDITION_VARIABLE; -#endif - -typedef struct _AFD_POLL_HANDLE_INFO { - HANDLE Handle; - ULONG Events; - NTSTATUS Status; -} AFD_POLL_HANDLE_INFO, *PAFD_POLL_HANDLE_INFO; - -typedef struct _AFD_POLL_INFO { - LARGE_INTEGER Timeout; - ULONG NumberOfHandles; - ULONG Exclusive; - AFD_POLL_HANDLE_INFO Handles[1]; -} AFD_POLL_INFO, *PAFD_POLL_INFO; - -#define UV_MSAFD_PROVIDER_COUNT 3 - - -/** - * It should be possible to cast uv_buf_t[] to WSABUF[] - * see http://msdn.microsoft.com/en-us/library/ms741542(v=vs.85).aspx - */ -typedef struct uv_buf_t { - ULONG len; - char* base; -} uv_buf_t; - -typedef int uv_file; -typedef SOCKET uv_os_sock_t; -typedef HANDLE uv_os_fd_t; - -typedef HANDLE uv_thread_t; - -typedef HANDLE uv_sem_t; - -typedef CRITICAL_SECTION uv_mutex_t; - -/* This condition variable implementation is based on the SetEvent solution - * (section 3.2) at http://www.cs.wustl.edu/~schmidt/win32-cv-1.html - * We could not use the SignalObjectAndWait solution (section 3.4) because - * it want the 2nd argument (type uv_mutex_t) of uv_cond_wait() and - * uv_cond_timedwait() to be HANDLEs, but we use CRITICAL_SECTIONs. - */ - -typedef union { - CONDITION_VARIABLE cond_var; - struct { - unsigned int waiters_count; - CRITICAL_SECTION waiters_count_lock; - HANDLE signal_event; - HANDLE broadcast_event; - } fallback; -} uv_cond_t; - -typedef union { - struct { - unsigned int num_readers_; - CRITICAL_SECTION num_readers_lock_; - HANDLE write_semaphore_; - } state_; - /* TODO: remove me in v2.x. */ - struct { - SRWLOCK unused_; - } unused1_; - /* TODO: remove me in v2.x. */ - struct { - uv_mutex_t unused1_; - uv_mutex_t unused2_; - } unused2_; -} uv_rwlock_t; - -typedef struct { - unsigned int n; - unsigned int count; - uv_mutex_t mutex; - uv_sem_t turnstile1; - uv_sem_t turnstile2; -} uv_barrier_t; - -typedef struct { - DWORD tls_index; -} uv_key_t; - -#define UV_ONCE_INIT { 0, NULL } - -typedef struct uv_once_s { - unsigned char ran; - HANDLE event; -} uv_once_t; - -/* Platform-specific definitions for uv_spawn support. */ -typedef unsigned char uv_uid_t; -typedef unsigned char uv_gid_t; - -typedef struct uv__dirent_s { - int d_type; - char d_name[1]; -} uv__dirent_t; - -#define HAVE_DIRENT_TYPES -#define UV__DT_DIR UV_DIRENT_DIR -#define UV__DT_FILE UV_DIRENT_FILE -#define UV__DT_LINK UV_DIRENT_LINK -#define UV__DT_FIFO UV_DIRENT_FIFO -#define UV__DT_SOCKET UV_DIRENT_SOCKET -#define UV__DT_CHAR UV_DIRENT_CHAR -#define UV__DT_BLOCK UV_DIRENT_BLOCK - -/* Platform-specific definitions for uv_dlopen support. */ -#define UV_DYNAMIC FAR WINAPI -typedef struct { - HMODULE handle; - char* errmsg; -} uv_lib_t; - -RB_HEAD(uv_timer_tree_s, uv_timer_s); - -#define UV_LOOP_PRIVATE_FIELDS \ - /* The loop's I/O completion port */ \ - HANDLE iocp; \ - /* The current time according to the event loop. in msecs. */ \ - uint64_t time; \ - /* Tail of a single-linked circular queue of pending reqs. If the queue */ \ - /* is empty, tail_ is NULL. If there is only one item, */ \ - /* tail_->next_req == tail_ */ \ - uv_req_t* pending_reqs_tail; \ - /* Head of a single-linked list of closed handles */ \ - uv_handle_t* endgame_handles; \ - /* The head of the timers tree */ \ - struct uv_timer_tree_s timers; \ - /* Lists of active loop (prepare / check / idle) watchers */ \ - uv_prepare_t* prepare_handles; \ - uv_check_t* check_handles; \ - uv_idle_t* idle_handles; \ - /* This pointer will refer to the prepare/check/idle handle whose */ \ - /* callback is scheduled to be called next. This is needed to allow */ \ - /* safe removal from one of the lists above while that list being */ \ - /* iterated over. */ \ - uv_prepare_t* next_prepare_handle; \ - uv_check_t* next_check_handle; \ - uv_idle_t* next_idle_handle; \ - /* This handle holds the peer sockets for the fast variant of uv_poll_t */ \ - SOCKET poll_peer_sockets[UV_MSAFD_PROVIDER_COUNT]; \ - /* Counter to keep track of active tcp streams */ \ - unsigned int active_tcp_streams; \ - /* Counter to keep track of active udp streams */ \ - unsigned int active_udp_streams; \ - /* Counter to started timer */ \ - uint64_t timer_counter; \ - /* Threadpool */ \ - void* wq[2]; \ - uv_mutex_t wq_mutex; \ - uv_async_t wq_async; - -#define UV_REQ_TYPE_PRIVATE \ - /* TODO: remove the req suffix */ \ - UV_ACCEPT, \ - UV_FS_EVENT_REQ, \ - UV_POLL_REQ, \ - UV_PROCESS_EXIT, \ - UV_READ, \ - UV_UDP_RECV, \ - UV_WAKEUP, \ - UV_SIGNAL_REQ, - -#define UV_REQ_PRIVATE_FIELDS \ - union { \ - /* Used by I/O operations */ \ - struct { \ - OVERLAPPED overlapped; \ - size_t queued_bytes; \ - } io; \ - } u; \ - struct uv_req_s* next_req; - -#define UV_WRITE_PRIVATE_FIELDS \ - int ipc_header; \ - uv_buf_t write_buffer; \ - HANDLE event_handle; \ - HANDLE wait_handle; - -#define UV_CONNECT_PRIVATE_FIELDS \ - /* empty */ - -#define UV_SHUTDOWN_PRIVATE_FIELDS \ - /* empty */ - -#define UV_UDP_SEND_PRIVATE_FIELDS \ - /* empty */ - -#define UV_PRIVATE_REQ_TYPES \ - typedef struct uv_pipe_accept_s { \ - UV_REQ_FIELDS \ - HANDLE pipeHandle; \ - struct uv_pipe_accept_s* next_pending; \ - } uv_pipe_accept_t; \ - \ - typedef struct uv_tcp_accept_s { \ - UV_REQ_FIELDS \ - SOCKET accept_socket; \ - char accept_buffer[sizeof(struct sockaddr_storage) * 2 + 32]; \ - HANDLE event_handle; \ - HANDLE wait_handle; \ - struct uv_tcp_accept_s* next_pending; \ - } uv_tcp_accept_t; \ - \ - typedef struct uv_read_s { \ - UV_REQ_FIELDS \ - HANDLE event_handle; \ - HANDLE wait_handle; \ - } uv_read_t; - -#define uv_stream_connection_fields \ - unsigned int write_reqs_pending; \ - uv_shutdown_t* shutdown_req; - -#define uv_stream_server_fields \ - uv_connection_cb connection_cb; - -#define UV_STREAM_PRIVATE_FIELDS \ - unsigned int reqs_pending; \ - int activecnt; \ - uv_read_t read_req; \ - union { \ - struct { uv_stream_connection_fields } conn; \ - struct { uv_stream_server_fields } serv; \ - } stream; - -#define uv_tcp_server_fields \ - uv_tcp_accept_t* accept_reqs; \ - unsigned int processed_accepts; \ - uv_tcp_accept_t* pending_accepts; \ - LPFN_ACCEPTEX func_acceptex; - -#define uv_tcp_connection_fields \ - uv_buf_t read_buffer; \ - LPFN_CONNECTEX func_connectex; - -#define UV_TCP_PRIVATE_FIELDS \ - SOCKET socket; \ - int delayed_error; \ - union { \ - struct { uv_tcp_server_fields } serv; \ - struct { uv_tcp_connection_fields } conn; \ - } tcp; - -#define UV_UDP_PRIVATE_FIELDS \ - SOCKET socket; \ - unsigned int reqs_pending; \ - int activecnt; \ - uv_req_t recv_req; \ - uv_buf_t recv_buffer; \ - struct sockaddr_storage recv_from; \ - int recv_from_len; \ - uv_udp_recv_cb recv_cb; \ - uv_alloc_cb alloc_cb; \ - LPFN_WSARECV func_wsarecv; \ - LPFN_WSARECVFROM func_wsarecvfrom; - -#define uv_pipe_server_fields \ - int pending_instances; \ - uv_pipe_accept_t* accept_reqs; \ - uv_pipe_accept_t* pending_accepts; - -#define uv_pipe_connection_fields \ - uv_timer_t* eof_timer; \ - uv_write_t ipc_header_write_req; \ - int ipc_pid; \ - uint64_t remaining_ipc_rawdata_bytes; \ - struct { \ - void* queue[2]; \ - int queue_len; \ - } pending_ipc_info; \ - uv_write_t* non_overlapped_writes_tail; \ - uv_mutex_t readfile_mutex; \ - volatile HANDLE readfile_thread; - -#define UV_PIPE_PRIVATE_FIELDS \ - HANDLE handle; \ - WCHAR* name; \ - union { \ - struct { uv_pipe_server_fields } serv; \ - struct { uv_pipe_connection_fields } conn; \ - } pipe; - -/* TODO: put the parser states in an union - TTY handles are always */ -/* half-duplex so read-state can safely overlap write-state. */ -#define UV_TTY_PRIVATE_FIELDS \ - HANDLE handle; \ - union { \ - struct { \ - /* Used for readable TTY handles */ \ - /* TODO: remove me in v2.x. */ \ - HANDLE unused_; \ - uv_buf_t read_line_buffer; \ - HANDLE read_raw_wait; \ - /* Fields used for translating win keystrokes into vt100 characters */ \ - char last_key[8]; \ - unsigned char last_key_offset; \ - unsigned char last_key_len; \ - WCHAR last_utf16_high_surrogate; \ - INPUT_RECORD last_input_record; \ - } rd; \ - struct { \ - /* Used for writable TTY handles */ \ - /* utf8-to-utf16 conversion state */ \ - unsigned int utf8_codepoint; \ - unsigned char utf8_bytes_left; \ - /* eol conversion state */ \ - unsigned char previous_eol; \ - /* ansi parser state */ \ - unsigned char ansi_parser_state; \ - unsigned char ansi_csi_argc; \ - unsigned short ansi_csi_argv[4]; \ - COORD saved_position; \ - WORD saved_attributes; \ - } wr; \ - } tty; - -#define UV_POLL_PRIVATE_FIELDS \ - SOCKET socket; \ - /* Used in fast mode */ \ - SOCKET peer_socket; \ - AFD_POLL_INFO afd_poll_info_1; \ - AFD_POLL_INFO afd_poll_info_2; \ - /* Used in fast and slow mode. */ \ - uv_req_t poll_req_1; \ - uv_req_t poll_req_2; \ - unsigned char submitted_events_1; \ - unsigned char submitted_events_2; \ - unsigned char mask_events_1; \ - unsigned char mask_events_2; \ - unsigned char events; - -#define UV_TIMER_PRIVATE_FIELDS \ - RB_ENTRY(uv_timer_s) tree_entry; \ - uint64_t due; \ - uint64_t repeat; \ - uint64_t start_id; \ - uv_timer_cb timer_cb; - -#define UV_ASYNC_PRIVATE_FIELDS \ - struct uv_req_s async_req; \ - uv_async_cb async_cb; \ - /* char to avoid alignment issues */ \ - char volatile async_sent; - -#define UV_PREPARE_PRIVATE_FIELDS \ - uv_prepare_t* prepare_prev; \ - uv_prepare_t* prepare_next; \ - uv_prepare_cb prepare_cb; - -#define UV_CHECK_PRIVATE_FIELDS \ - uv_check_t* check_prev; \ - uv_check_t* check_next; \ - uv_check_cb check_cb; - -#define UV_IDLE_PRIVATE_FIELDS \ - uv_idle_t* idle_prev; \ - uv_idle_t* idle_next; \ - uv_idle_cb idle_cb; - -#define UV_HANDLE_PRIVATE_FIELDS \ - uv_handle_t* endgame_next; \ - unsigned int flags; - -#define UV_GETADDRINFO_PRIVATE_FIELDS \ - struct uv__work work_req; \ - uv_getaddrinfo_cb getaddrinfo_cb; \ - void* alloc; \ - WCHAR* node; \ - WCHAR* service; \ - /* The addrinfoW field is used to store a pointer to the hints, and */ \ - /* later on to store the result of GetAddrInfoW. The final result will */ \ - /* be converted to struct addrinfo* and stored in the addrinfo field. */ \ - struct addrinfoW* addrinfow; \ - struct addrinfo* addrinfo; \ - int retcode; - -#define UV_GETNAMEINFO_PRIVATE_FIELDS \ - struct uv__work work_req; \ - uv_getnameinfo_cb getnameinfo_cb; \ - struct sockaddr_storage storage; \ - int flags; \ - char host[NI_MAXHOST]; \ - char service[NI_MAXSERV]; \ - int retcode; - -#define UV_PROCESS_PRIVATE_FIELDS \ - struct uv_process_exit_s { \ - UV_REQ_FIELDS \ - } exit_req; \ - BYTE* child_stdio_buffer; \ - int exit_signal; \ - HANDLE wait_handle; \ - HANDLE process_handle; \ - volatile char exit_cb_pending; - -#define UV_FS_PRIVATE_FIELDS \ - struct uv__work work_req; \ - int flags; \ - DWORD sys_errno_; \ - union { \ - /* TODO: remove me in 0.9. */ \ - WCHAR* pathw; \ - int fd; \ - } file; \ - union { \ - struct { \ - int mode; \ - WCHAR* new_pathw; \ - int file_flags; \ - int fd_out; \ - unsigned int nbufs; \ - uv_buf_t* bufs; \ - int64_t offset; \ - uv_buf_t bufsml[4]; \ - } info; \ - struct { \ - double atime; \ - double mtime; \ - } time; \ - } fs; - -#define UV_WORK_PRIVATE_FIELDS \ - struct uv__work work_req; - -#define UV_FS_EVENT_PRIVATE_FIELDS \ - struct uv_fs_event_req_s { \ - UV_REQ_FIELDS \ - } req; \ - HANDLE dir_handle; \ - int req_pending; \ - uv_fs_event_cb cb; \ - WCHAR* filew; \ - WCHAR* short_filew; \ - WCHAR* dirw; \ - char* buffer; - -#define UV_SIGNAL_PRIVATE_FIELDS \ - RB_ENTRY(uv_signal_s) tree_entry; \ - struct uv_req_s signal_req; \ - unsigned long pending_signum; - -#ifndef F_OK -#define F_OK 0 -#endif -#ifndef R_OK -#define R_OK 4 -#endif -#ifndef W_OK -#define W_OK 2 -#endif -#ifndef X_OK -#define X_OK 1 -#endif diff --git a/vendor/libuv/include/uv.h b/vendor/libuv/include/uv.h deleted file mode 100644 index 31f09f0f6..000000000 --- a/vendor/libuv/include/uv.h +++ /dev/null @@ -1,1497 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -/* See https://github.com/libuv/libuv#documentation for documentation. */ - -#ifndef UV_H -#define UV_H -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef _WIN32 - /* Windows - set up dll import/export decorators. */ -# if defined(BUILDING_UV_SHARED) - /* Building shared library. */ -# define UV_EXTERN __declspec(dllexport) -# elif defined(USING_UV_SHARED) - /* Using shared library. */ -# define UV_EXTERN __declspec(dllimport) -# else - /* Building static library. */ -# define UV_EXTERN /* nothing */ -# endif -#elif __GNUC__ >= 4 -# define UV_EXTERN __attribute__((visibility("default"))) -#else -# define UV_EXTERN /* nothing */ -#endif - -#include "uv-errno.h" -#include "uv-version.h" -#include -#include - -#if defined(_MSC_VER) && _MSC_VER < 1600 -# include "stdint-msvc2008.h" -#else -# include -#endif - -#if defined(_WIN32) -# include "uv-win.h" -#else -# include "uv-unix.h" -#endif - -/* Expand this list if necessary. */ -#define UV_ERRNO_MAP(XX) \ - XX(E2BIG, "argument list too long") \ - XX(EACCES, "permission denied") \ - XX(EADDRINUSE, "address already in use") \ - XX(EADDRNOTAVAIL, "address not available") \ - XX(EAFNOSUPPORT, "address family not supported") \ - XX(EAGAIN, "resource temporarily unavailable") \ - XX(EAI_ADDRFAMILY, "address family not supported") \ - XX(EAI_AGAIN, "temporary failure") \ - XX(EAI_BADFLAGS, "bad ai_flags value") \ - XX(EAI_BADHINTS, "invalid value for hints") \ - XX(EAI_CANCELED, "request canceled") \ - XX(EAI_FAIL, "permanent failure") \ - XX(EAI_FAMILY, "ai_family not supported") \ - XX(EAI_MEMORY, "out of memory") \ - XX(EAI_NODATA, "no address") \ - XX(EAI_NONAME, "unknown node or service") \ - XX(EAI_OVERFLOW, "argument buffer overflow") \ - XX(EAI_PROTOCOL, "resolved protocol is unknown") \ - XX(EAI_SERVICE, "service not available for socket type") \ - XX(EAI_SOCKTYPE, "socket type not supported") \ - XX(EALREADY, "connection already in progress") \ - XX(EBADF, "bad file descriptor") \ - XX(EBUSY, "resource busy or locked") \ - XX(ECANCELED, "operation canceled") \ - XX(ECHARSET, "invalid Unicode character") \ - XX(ECONNABORTED, "software caused connection abort") \ - XX(ECONNREFUSED, "connection refused") \ - XX(ECONNRESET, "connection reset by peer") \ - XX(EDESTADDRREQ, "destination address required") \ - XX(EEXIST, "file already exists") \ - XX(EFAULT, "bad address in system call argument") \ - XX(EFBIG, "file too large") \ - XX(EHOSTUNREACH, "host is unreachable") \ - XX(EINTR, "interrupted system call") \ - XX(EINVAL, "invalid argument") \ - XX(EIO, "i/o error") \ - XX(EISCONN, "socket is already connected") \ - XX(EISDIR, "illegal operation on a directory") \ - XX(ELOOP, "too many symbolic links encountered") \ - XX(EMFILE, "too many open files") \ - XX(EMSGSIZE, "message too long") \ - XX(ENAMETOOLONG, "name too long") \ - XX(ENETDOWN, "network is down") \ - XX(ENETUNREACH, "network is unreachable") \ - XX(ENFILE, "file table overflow") \ - XX(ENOBUFS, "no buffer space available") \ - XX(ENODEV, "no such device") \ - XX(ENOENT, "no such file or directory") \ - XX(ENOMEM, "not enough memory") \ - XX(ENONET, "machine is not on the network") \ - XX(ENOPROTOOPT, "protocol not available") \ - XX(ENOSPC, "no space left on device") \ - XX(ENOSYS, "function not implemented") \ - XX(ENOTCONN, "socket is not connected") \ - XX(ENOTDIR, "not a directory") \ - XX(ENOTEMPTY, "directory not empty") \ - XX(ENOTSOCK, "socket operation on non-socket") \ - XX(ENOTSUP, "operation not supported on socket") \ - XX(EPERM, "operation not permitted") \ - XX(EPIPE, "broken pipe") \ - XX(EPROTO, "protocol error") \ - XX(EPROTONOSUPPORT, "protocol not supported") \ - XX(EPROTOTYPE, "protocol wrong type for socket") \ - XX(ERANGE, "result too large") \ - XX(EROFS, "read-only file system") \ - XX(ESHUTDOWN, "cannot send after transport endpoint shutdown") \ - XX(ESPIPE, "invalid seek") \ - XX(ESRCH, "no such process") \ - XX(ETIMEDOUT, "connection timed out") \ - XX(ETXTBSY, "text file is busy") \ - XX(EXDEV, "cross-device link not permitted") \ - XX(UNKNOWN, "unknown error") \ - XX(EOF, "end of file") \ - XX(ENXIO, "no such device or address") \ - XX(EMLINK, "too many links") \ - XX(EHOSTDOWN, "host is down") \ - -#define UV_HANDLE_TYPE_MAP(XX) \ - XX(ASYNC, async) \ - XX(CHECK, check) \ - XX(FS_EVENT, fs_event) \ - XX(FS_POLL, fs_poll) \ - XX(HANDLE, handle) \ - XX(IDLE, idle) \ - XX(NAMED_PIPE, pipe) \ - XX(POLL, poll) \ - XX(PREPARE, prepare) \ - XX(PROCESS, process) \ - XX(STREAM, stream) \ - XX(TCP, tcp) \ - XX(TIMER, timer) \ - XX(TTY, tty) \ - XX(UDP, udp) \ - XX(SIGNAL, signal) \ - -#define UV_REQ_TYPE_MAP(XX) \ - XX(REQ, req) \ - XX(CONNECT, connect) \ - XX(WRITE, write) \ - XX(SHUTDOWN, shutdown) \ - XX(UDP_SEND, udp_send) \ - XX(FS, fs) \ - XX(WORK, work) \ - XX(GETADDRINFO, getaddrinfo) \ - XX(GETNAMEINFO, getnameinfo) \ - -typedef enum { -#define XX(code, _) UV_ ## code = UV__ ## code, - UV_ERRNO_MAP(XX) -#undef XX - UV_ERRNO_MAX = UV__EOF - 1 -} uv_errno_t; - -typedef enum { - UV_UNKNOWN_HANDLE = 0, -#define XX(uc, lc) UV_##uc, - UV_HANDLE_TYPE_MAP(XX) -#undef XX - UV_FILE, - UV_HANDLE_TYPE_MAX -} uv_handle_type; - -typedef enum { - UV_UNKNOWN_REQ = 0, -#define XX(uc, lc) UV_##uc, - UV_REQ_TYPE_MAP(XX) -#undef XX - UV_REQ_TYPE_PRIVATE - UV_REQ_TYPE_MAX -} uv_req_type; - - -/* Handle types. */ -typedef struct uv_loop_s uv_loop_t; -typedef struct uv_handle_s uv_handle_t; -typedef struct uv_stream_s uv_stream_t; -typedef struct uv_tcp_s uv_tcp_t; -typedef struct uv_udp_s uv_udp_t; -typedef struct uv_pipe_s uv_pipe_t; -typedef struct uv_tty_s uv_tty_t; -typedef struct uv_poll_s uv_poll_t; -typedef struct uv_timer_s uv_timer_t; -typedef struct uv_prepare_s uv_prepare_t; -typedef struct uv_check_s uv_check_t; -typedef struct uv_idle_s uv_idle_t; -typedef struct uv_async_s uv_async_t; -typedef struct uv_process_s uv_process_t; -typedef struct uv_fs_event_s uv_fs_event_t; -typedef struct uv_fs_poll_s uv_fs_poll_t; -typedef struct uv_signal_s uv_signal_t; - -/* Request types. */ -typedef struct uv_req_s uv_req_t; -typedef struct uv_getaddrinfo_s uv_getaddrinfo_t; -typedef struct uv_getnameinfo_s uv_getnameinfo_t; -typedef struct uv_shutdown_s uv_shutdown_t; -typedef struct uv_write_s uv_write_t; -typedef struct uv_connect_s uv_connect_t; -typedef struct uv_udp_send_s uv_udp_send_t; -typedef struct uv_fs_s uv_fs_t; -typedef struct uv_work_s uv_work_t; - -/* None of the above. */ -typedef struct uv_cpu_info_s uv_cpu_info_t; -typedef struct uv_interface_address_s uv_interface_address_t; -typedef struct uv_dirent_s uv_dirent_t; -typedef struct uv_passwd_s uv_passwd_t; - -typedef enum { - UV_LOOP_BLOCK_SIGNAL -} uv_loop_option; - -typedef enum { - UV_RUN_DEFAULT = 0, - UV_RUN_ONCE, - UV_RUN_NOWAIT -} uv_run_mode; - - -UV_EXTERN unsigned int uv_version(void); -UV_EXTERN const char* uv_version_string(void); - -typedef void* (*uv_malloc_func)(size_t size); -typedef void* (*uv_realloc_func)(void* ptr, size_t size); -typedef void* (*uv_calloc_func)(size_t count, size_t size); -typedef void (*uv_free_func)(void* ptr); - -UV_EXTERN int uv_replace_allocator(uv_malloc_func malloc_func, - uv_realloc_func realloc_func, - uv_calloc_func calloc_func, - uv_free_func free_func); - -UV_EXTERN uv_loop_t* uv_default_loop(void); -UV_EXTERN int uv_loop_init(uv_loop_t* loop); -UV_EXTERN int uv_loop_close(uv_loop_t* loop); -/* - * NOTE: - * This function is DEPRECATED (to be removed after 0.12), users should - * allocate the loop manually and use uv_loop_init instead. - */ -UV_EXTERN uv_loop_t* uv_loop_new(void); -/* - * NOTE: - * This function is DEPRECATED (to be removed after 0.12). Users should use - * uv_loop_close and free the memory manually instead. - */ -UV_EXTERN void uv_loop_delete(uv_loop_t*); -UV_EXTERN size_t uv_loop_size(void); -UV_EXTERN int uv_loop_alive(const uv_loop_t* loop); -UV_EXTERN int uv_loop_configure(uv_loop_t* loop, uv_loop_option option, ...); - -UV_EXTERN int uv_run(uv_loop_t*, uv_run_mode mode); -UV_EXTERN void uv_stop(uv_loop_t*); - -UV_EXTERN void uv_ref(uv_handle_t*); -UV_EXTERN void uv_unref(uv_handle_t*); -UV_EXTERN int uv_has_ref(const uv_handle_t*); - -UV_EXTERN void uv_update_time(uv_loop_t*); -UV_EXTERN uint64_t uv_now(const uv_loop_t*); - -UV_EXTERN int uv_backend_fd(const uv_loop_t*); -UV_EXTERN int uv_backend_timeout(const uv_loop_t*); - -typedef void (*uv_alloc_cb)(uv_handle_t* handle, - size_t suggested_size, - uv_buf_t* buf); -typedef void (*uv_read_cb)(uv_stream_t* stream, - ssize_t nread, - const uv_buf_t* buf); -typedef void (*uv_write_cb)(uv_write_t* req, int status); -typedef void (*uv_connect_cb)(uv_connect_t* req, int status); -typedef void (*uv_shutdown_cb)(uv_shutdown_t* req, int status); -typedef void (*uv_connection_cb)(uv_stream_t* server, int status); -typedef void (*uv_close_cb)(uv_handle_t* handle); -typedef void (*uv_poll_cb)(uv_poll_t* handle, int status, int events); -typedef void (*uv_timer_cb)(uv_timer_t* handle); -typedef void (*uv_async_cb)(uv_async_t* handle); -typedef void (*uv_prepare_cb)(uv_prepare_t* handle); -typedef void (*uv_check_cb)(uv_check_t* handle); -typedef void (*uv_idle_cb)(uv_idle_t* handle); -typedef void (*uv_exit_cb)(uv_process_t*, int64_t exit_status, int term_signal); -typedef void (*uv_walk_cb)(uv_handle_t* handle, void* arg); -typedef void (*uv_fs_cb)(uv_fs_t* req); -typedef void (*uv_work_cb)(uv_work_t* req); -typedef void (*uv_after_work_cb)(uv_work_t* req, int status); -typedef void (*uv_getaddrinfo_cb)(uv_getaddrinfo_t* req, - int status, - struct addrinfo* res); -typedef void (*uv_getnameinfo_cb)(uv_getnameinfo_t* req, - int status, - const char* hostname, - const char* service); - -typedef struct { - long tv_sec; - long tv_nsec; -} uv_timespec_t; - - -typedef struct { - uint64_t st_dev; - uint64_t st_mode; - uint64_t st_nlink; - uint64_t st_uid; - uint64_t st_gid; - uint64_t st_rdev; - uint64_t st_ino; - uint64_t st_size; - uint64_t st_blksize; - uint64_t st_blocks; - uint64_t st_flags; - uint64_t st_gen; - uv_timespec_t st_atim; - uv_timespec_t st_mtim; - uv_timespec_t st_ctim; - uv_timespec_t st_birthtim; -} uv_stat_t; - - -typedef void (*uv_fs_event_cb)(uv_fs_event_t* handle, - const char* filename, - int events, - int status); - -typedef void (*uv_fs_poll_cb)(uv_fs_poll_t* handle, - int status, - const uv_stat_t* prev, - const uv_stat_t* curr); - -typedef void (*uv_signal_cb)(uv_signal_t* handle, int signum); - - -typedef enum { - UV_LEAVE_GROUP = 0, - UV_JOIN_GROUP -} uv_membership; - - -UV_EXTERN int uv_translate_sys_error(int sys_errno); - -UV_EXTERN const char* uv_strerror(int err); -UV_EXTERN const char* uv_err_name(int err); - - -#define UV_REQ_FIELDS \ - /* public */ \ - void* data; \ - /* read-only */ \ - uv_req_type type; \ - /* private */ \ - void* active_queue[2]; \ - void* reserved[4]; \ - UV_REQ_PRIVATE_FIELDS \ - -/* Abstract base class of all requests. */ -struct uv_req_s { - UV_REQ_FIELDS -}; - - -/* Platform-specific request types. */ -UV_PRIVATE_REQ_TYPES - - -UV_EXTERN int uv_shutdown(uv_shutdown_t* req, - uv_stream_t* handle, - uv_shutdown_cb cb); - -struct uv_shutdown_s { - UV_REQ_FIELDS - uv_stream_t* handle; - uv_shutdown_cb cb; - UV_SHUTDOWN_PRIVATE_FIELDS -}; - - -#define UV_HANDLE_FIELDS \ - /* public */ \ - void* data; \ - /* read-only */ \ - uv_loop_t* loop; \ - uv_handle_type type; \ - /* private */ \ - uv_close_cb close_cb; \ - void* handle_queue[2]; \ - union { \ - int fd; \ - void* reserved[4]; \ - } u; \ - UV_HANDLE_PRIVATE_FIELDS \ - -/* The abstract base class of all handles. */ -struct uv_handle_s { - UV_HANDLE_FIELDS -}; - -UV_EXTERN size_t uv_handle_size(uv_handle_type type); -UV_EXTERN size_t uv_req_size(uv_req_type type); - -UV_EXTERN int uv_is_active(const uv_handle_t* handle); - -UV_EXTERN void uv_walk(uv_loop_t* loop, uv_walk_cb walk_cb, void* arg); - -/* Helpers for ad hoc debugging, no API/ABI stability guaranteed. */ -UV_EXTERN void uv_print_all_handles(uv_loop_t* loop, FILE* stream); -UV_EXTERN void uv_print_active_handles(uv_loop_t* loop, FILE* stream); - -UV_EXTERN void uv_close(uv_handle_t* handle, uv_close_cb close_cb); - -UV_EXTERN int uv_send_buffer_size(uv_handle_t* handle, int* value); -UV_EXTERN int uv_recv_buffer_size(uv_handle_t* handle, int* value); - -UV_EXTERN int uv_fileno(const uv_handle_t* handle, uv_os_fd_t* fd); - -UV_EXTERN uv_buf_t uv_buf_init(char* base, unsigned int len); - - -#define UV_STREAM_FIELDS \ - /* number of bytes queued for writing */ \ - size_t write_queue_size; \ - uv_alloc_cb alloc_cb; \ - uv_read_cb read_cb; \ - /* private */ \ - UV_STREAM_PRIVATE_FIELDS - -/* - * uv_stream_t is a subclass of uv_handle_t. - * - * uv_stream is an abstract class. - * - * uv_stream_t is the parent class of uv_tcp_t, uv_pipe_t and uv_tty_t. - */ -struct uv_stream_s { - UV_HANDLE_FIELDS - UV_STREAM_FIELDS -}; - -UV_EXTERN int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb); -UV_EXTERN int uv_accept(uv_stream_t* server, uv_stream_t* client); - -UV_EXTERN int uv_read_start(uv_stream_t*, - uv_alloc_cb alloc_cb, - uv_read_cb read_cb); -UV_EXTERN int uv_read_stop(uv_stream_t*); - -UV_EXTERN int uv_write(uv_write_t* req, - uv_stream_t* handle, - const uv_buf_t bufs[], - unsigned int nbufs, - uv_write_cb cb); -UV_EXTERN int uv_write2(uv_write_t* req, - uv_stream_t* handle, - const uv_buf_t bufs[], - unsigned int nbufs, - uv_stream_t* send_handle, - uv_write_cb cb); -UV_EXTERN int uv_try_write(uv_stream_t* handle, - const uv_buf_t bufs[], - unsigned int nbufs); - -/* uv_write_t is a subclass of uv_req_t. */ -struct uv_write_s { - UV_REQ_FIELDS - uv_write_cb cb; - uv_stream_t* send_handle; - uv_stream_t* handle; - UV_WRITE_PRIVATE_FIELDS -}; - - -UV_EXTERN int uv_is_readable(const uv_stream_t* handle); -UV_EXTERN int uv_is_writable(const uv_stream_t* handle); - -UV_EXTERN int uv_stream_set_blocking(uv_stream_t* handle, int blocking); - -UV_EXTERN int uv_is_closing(const uv_handle_t* handle); - - -/* - * uv_tcp_t is a subclass of uv_stream_t. - * - * Represents a TCP stream or TCP server. - */ -struct uv_tcp_s { - UV_HANDLE_FIELDS - UV_STREAM_FIELDS - UV_TCP_PRIVATE_FIELDS -}; - -UV_EXTERN int uv_tcp_init(uv_loop_t*, uv_tcp_t* handle); -UV_EXTERN int uv_tcp_init_ex(uv_loop_t*, uv_tcp_t* handle, unsigned int flags); -UV_EXTERN int uv_tcp_open(uv_tcp_t* handle, uv_os_sock_t sock); -UV_EXTERN int uv_tcp_nodelay(uv_tcp_t* handle, int enable); -UV_EXTERN int uv_tcp_keepalive(uv_tcp_t* handle, - int enable, - unsigned int delay); -UV_EXTERN int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable); - -enum uv_tcp_flags { - /* Used with uv_tcp_bind, when an IPv6 address is used. */ - UV_TCP_IPV6ONLY = 1 -}; - -UV_EXTERN int uv_tcp_bind(uv_tcp_t* handle, - const struct sockaddr* addr, - unsigned int flags); -UV_EXTERN int uv_tcp_getsockname(const uv_tcp_t* handle, - struct sockaddr* name, - int* namelen); -UV_EXTERN int uv_tcp_getpeername(const uv_tcp_t* handle, - struct sockaddr* name, - int* namelen); -UV_EXTERN int uv_tcp_connect(uv_connect_t* req, - uv_tcp_t* handle, - const struct sockaddr* addr, - uv_connect_cb cb); - -/* uv_connect_t is a subclass of uv_req_t. */ -struct uv_connect_s { - UV_REQ_FIELDS - uv_connect_cb cb; - uv_stream_t* handle; - UV_CONNECT_PRIVATE_FIELDS -}; - - -/* - * UDP support. - */ - -enum uv_udp_flags { - /* Disables dual stack mode. */ - UV_UDP_IPV6ONLY = 1, - /* - * Indicates message was truncated because read buffer was too small. The - * remainder was discarded by the OS. Used in uv_udp_recv_cb. - */ - UV_UDP_PARTIAL = 2, - /* - * Indicates if SO_REUSEADDR will be set when binding the handle. - * This sets the SO_REUSEPORT socket flag on the BSDs and OS X. On other - * Unix platforms, it sets the SO_REUSEADDR flag. What that means is that - * multiple threads or processes can bind to the same address without error - * (provided they all set the flag) but only the last one to bind will receive - * any traffic, in effect "stealing" the port from the previous listener. - */ - UV_UDP_REUSEADDR = 4 -}; - -typedef void (*uv_udp_send_cb)(uv_udp_send_t* req, int status); -typedef void (*uv_udp_recv_cb)(uv_udp_t* handle, - ssize_t nread, - const uv_buf_t* buf, - const struct sockaddr* addr, - unsigned flags); - -/* uv_udp_t is a subclass of uv_handle_t. */ -struct uv_udp_s { - UV_HANDLE_FIELDS - /* read-only */ - /* - * Number of bytes queued for sending. This field strictly shows how much - * information is currently queued. - */ - size_t send_queue_size; - /* - * Number of send requests currently in the queue awaiting to be processed. - */ - size_t send_queue_count; - UV_UDP_PRIVATE_FIELDS -}; - -/* uv_udp_send_t is a subclass of uv_req_t. */ -struct uv_udp_send_s { - UV_REQ_FIELDS - uv_udp_t* handle; - uv_udp_send_cb cb; - UV_UDP_SEND_PRIVATE_FIELDS -}; - -UV_EXTERN int uv_udp_init(uv_loop_t*, uv_udp_t* handle); -UV_EXTERN int uv_udp_init_ex(uv_loop_t*, uv_udp_t* handle, unsigned int flags); -UV_EXTERN int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock); -UV_EXTERN int uv_udp_bind(uv_udp_t* handle, - const struct sockaddr* addr, - unsigned int flags); - -UV_EXTERN int uv_udp_getsockname(const uv_udp_t* handle, - struct sockaddr* name, - int* namelen); -UV_EXTERN int uv_udp_set_membership(uv_udp_t* handle, - const char* multicast_addr, - const char* interface_addr, - uv_membership membership); -UV_EXTERN int uv_udp_set_multicast_loop(uv_udp_t* handle, int on); -UV_EXTERN int uv_udp_set_multicast_ttl(uv_udp_t* handle, int ttl); -UV_EXTERN int uv_udp_set_multicast_interface(uv_udp_t* handle, - const char* interface_addr); -UV_EXTERN int uv_udp_set_broadcast(uv_udp_t* handle, int on); -UV_EXTERN int uv_udp_set_ttl(uv_udp_t* handle, int ttl); -UV_EXTERN int uv_udp_send(uv_udp_send_t* req, - uv_udp_t* handle, - const uv_buf_t bufs[], - unsigned int nbufs, - const struct sockaddr* addr, - uv_udp_send_cb send_cb); -UV_EXTERN int uv_udp_try_send(uv_udp_t* handle, - const uv_buf_t bufs[], - unsigned int nbufs, - const struct sockaddr* addr); -UV_EXTERN int uv_udp_recv_start(uv_udp_t* handle, - uv_alloc_cb alloc_cb, - uv_udp_recv_cb recv_cb); -UV_EXTERN int uv_udp_recv_stop(uv_udp_t* handle); - - -/* - * uv_tty_t is a subclass of uv_stream_t. - * - * Representing a stream for the console. - */ -struct uv_tty_s { - UV_HANDLE_FIELDS - UV_STREAM_FIELDS - UV_TTY_PRIVATE_FIELDS -}; - -typedef enum { - /* Initial/normal terminal mode */ - UV_TTY_MODE_NORMAL, - /* Raw input mode (On Windows, ENABLE_WINDOW_INPUT is also enabled) */ - UV_TTY_MODE_RAW, - /* Binary-safe I/O mode for IPC (Unix-only) */ - UV_TTY_MODE_IO -} uv_tty_mode_t; - -UV_EXTERN int uv_tty_init(uv_loop_t*, uv_tty_t*, uv_file fd, int readable); -UV_EXTERN int uv_tty_set_mode(uv_tty_t*, uv_tty_mode_t mode); -UV_EXTERN int uv_tty_reset_mode(void); -UV_EXTERN int uv_tty_get_winsize(uv_tty_t*, int* width, int* height); - -#ifdef __cplusplus -extern "C++" { - -inline int uv_tty_set_mode(uv_tty_t* handle, int mode) { - return uv_tty_set_mode(handle, static_cast(mode)); -} - -} -#endif - -UV_EXTERN uv_handle_type uv_guess_handle(uv_file file); - -/* - * uv_pipe_t is a subclass of uv_stream_t. - * - * Representing a pipe stream or pipe server. On Windows this is a Named - * Pipe. On Unix this is a Unix domain socket. - */ -struct uv_pipe_s { - UV_HANDLE_FIELDS - UV_STREAM_FIELDS - int ipc; /* non-zero if this pipe is used for passing handles */ - UV_PIPE_PRIVATE_FIELDS -}; - -UV_EXTERN int uv_pipe_init(uv_loop_t*, uv_pipe_t* handle, int ipc); -UV_EXTERN int uv_pipe_open(uv_pipe_t*, uv_file file); -UV_EXTERN int uv_pipe_bind(uv_pipe_t* handle, const char* name); -UV_EXTERN void uv_pipe_connect(uv_connect_t* req, - uv_pipe_t* handle, - const char* name, - uv_connect_cb cb); -UV_EXTERN int uv_pipe_getsockname(const uv_pipe_t* handle, - char* buffer, - size_t* size); -UV_EXTERN int uv_pipe_getpeername(const uv_pipe_t* handle, - char* buffer, - size_t* size); -UV_EXTERN void uv_pipe_pending_instances(uv_pipe_t* handle, int count); -UV_EXTERN int uv_pipe_pending_count(uv_pipe_t* handle); -UV_EXTERN uv_handle_type uv_pipe_pending_type(uv_pipe_t* handle); - - -struct uv_poll_s { - UV_HANDLE_FIELDS - uv_poll_cb poll_cb; - UV_POLL_PRIVATE_FIELDS -}; - -enum uv_poll_event { - UV_READABLE = 1, - UV_WRITABLE = 2, - UV_DISCONNECT = 4 -}; - -UV_EXTERN int uv_poll_init(uv_loop_t* loop, uv_poll_t* handle, int fd); -UV_EXTERN int uv_poll_init_socket(uv_loop_t* loop, - uv_poll_t* handle, - uv_os_sock_t socket); -UV_EXTERN int uv_poll_start(uv_poll_t* handle, int events, uv_poll_cb cb); -UV_EXTERN int uv_poll_stop(uv_poll_t* handle); - - -struct uv_prepare_s { - UV_HANDLE_FIELDS - UV_PREPARE_PRIVATE_FIELDS -}; - -UV_EXTERN int uv_prepare_init(uv_loop_t*, uv_prepare_t* prepare); -UV_EXTERN int uv_prepare_start(uv_prepare_t* prepare, uv_prepare_cb cb); -UV_EXTERN int uv_prepare_stop(uv_prepare_t* prepare); - - -struct uv_check_s { - UV_HANDLE_FIELDS - UV_CHECK_PRIVATE_FIELDS -}; - -UV_EXTERN int uv_check_init(uv_loop_t*, uv_check_t* check); -UV_EXTERN int uv_check_start(uv_check_t* check, uv_check_cb cb); -UV_EXTERN int uv_check_stop(uv_check_t* check); - - -struct uv_idle_s { - UV_HANDLE_FIELDS - UV_IDLE_PRIVATE_FIELDS -}; - -UV_EXTERN int uv_idle_init(uv_loop_t*, uv_idle_t* idle); -UV_EXTERN int uv_idle_start(uv_idle_t* idle, uv_idle_cb cb); -UV_EXTERN int uv_idle_stop(uv_idle_t* idle); - - -struct uv_async_s { - UV_HANDLE_FIELDS - UV_ASYNC_PRIVATE_FIELDS -}; - -UV_EXTERN int uv_async_init(uv_loop_t*, - uv_async_t* async, - uv_async_cb async_cb); -UV_EXTERN int uv_async_send(uv_async_t* async); - - -/* - * uv_timer_t is a subclass of uv_handle_t. - * - * Used to get woken up at a specified time in the future. - */ -struct uv_timer_s { - UV_HANDLE_FIELDS - UV_TIMER_PRIVATE_FIELDS -}; - -UV_EXTERN int uv_timer_init(uv_loop_t*, uv_timer_t* handle); -UV_EXTERN int uv_timer_start(uv_timer_t* handle, - uv_timer_cb cb, - uint64_t timeout, - uint64_t repeat); -UV_EXTERN int uv_timer_stop(uv_timer_t* handle); -UV_EXTERN int uv_timer_again(uv_timer_t* handle); -UV_EXTERN void uv_timer_set_repeat(uv_timer_t* handle, uint64_t repeat); -UV_EXTERN uint64_t uv_timer_get_repeat(const uv_timer_t* handle); - - -/* - * uv_getaddrinfo_t is a subclass of uv_req_t. - * - * Request object for uv_getaddrinfo. - */ -struct uv_getaddrinfo_s { - UV_REQ_FIELDS - /* read-only */ - uv_loop_t* loop; - /* struct addrinfo* addrinfo is marked as private, but it really isn't. */ - UV_GETADDRINFO_PRIVATE_FIELDS -}; - - -UV_EXTERN int uv_getaddrinfo(uv_loop_t* loop, - uv_getaddrinfo_t* req, - uv_getaddrinfo_cb getaddrinfo_cb, - const char* node, - const char* service, - const struct addrinfo* hints); -UV_EXTERN void uv_freeaddrinfo(struct addrinfo* ai); - - -/* -* uv_getnameinfo_t is a subclass of uv_req_t. -* -* Request object for uv_getnameinfo. -*/ -struct uv_getnameinfo_s { - UV_REQ_FIELDS - /* read-only */ - uv_loop_t* loop; - /* host and service are marked as private, but they really aren't. */ - UV_GETNAMEINFO_PRIVATE_FIELDS -}; - -UV_EXTERN int uv_getnameinfo(uv_loop_t* loop, - uv_getnameinfo_t* req, - uv_getnameinfo_cb getnameinfo_cb, - const struct sockaddr* addr, - int flags); - - -/* uv_spawn() options. */ -typedef enum { - UV_IGNORE = 0x00, - UV_CREATE_PIPE = 0x01, - UV_INHERIT_FD = 0x02, - UV_INHERIT_STREAM = 0x04, - - /* - * When UV_CREATE_PIPE is specified, UV_READABLE_PIPE and UV_WRITABLE_PIPE - * determine the direction of flow, from the child process' perspective. Both - * flags may be specified to create a duplex data stream. - */ - UV_READABLE_PIPE = 0x10, - UV_WRITABLE_PIPE = 0x20 -} uv_stdio_flags; - -typedef struct uv_stdio_container_s { - uv_stdio_flags flags; - - union { - uv_stream_t* stream; - int fd; - } data; -} uv_stdio_container_t; - -typedef struct uv_process_options_s { - uv_exit_cb exit_cb; /* Called after the process exits. */ - const char* file; /* Path to program to execute. */ - /* - * Command line arguments. args[0] should be the path to the program. On - * Windows this uses CreateProcess which concatenates the arguments into a - * string this can cause some strange errors. See the note at - * windows_verbatim_arguments. - */ - char** args; - /* - * This will be set as the environ variable in the subprocess. If this is - * NULL then the parents environ will be used. - */ - char** env; - /* - * If non-null this represents a directory the subprocess should execute - * in. Stands for current working directory. - */ - const char* cwd; - /* - * Various flags that control how uv_spawn() behaves. See the definition of - * `enum uv_process_flags` below. - */ - unsigned int flags; - /* - * The `stdio` field points to an array of uv_stdio_container_t structs that - * describe the file descriptors that will be made available to the child - * process. The convention is that stdio[0] points to stdin, fd 1 is used for - * stdout, and fd 2 is stderr. - * - * Note that on windows file descriptors greater than 2 are available to the - * child process only if the child processes uses the MSVCRT runtime. - */ - int stdio_count; - uv_stdio_container_t* stdio; - /* - * Libuv can change the child process' user/group id. This happens only when - * the appropriate bits are set in the flags fields. This is not supported on - * windows; uv_spawn() will fail and set the error to UV_ENOTSUP. - */ - uv_uid_t uid; - uv_gid_t gid; -} uv_process_options_t; - -/* - * These are the flags that can be used for the uv_process_options.flags field. - */ -enum uv_process_flags { - /* - * Set the child process' user id. The user id is supplied in the `uid` field - * of the options struct. This does not work on windows; setting this flag - * will cause uv_spawn() to fail. - */ - UV_PROCESS_SETUID = (1 << 0), - /* - * Set the child process' group id. The user id is supplied in the `gid` - * field of the options struct. This does not work on windows; setting this - * flag will cause uv_spawn() to fail. - */ - UV_PROCESS_SETGID = (1 << 1), - /* - * Do not wrap any arguments in quotes, or perform any other escaping, when - * converting the argument list into a command line string. This option is - * only meaningful on Windows systems. On Unix it is silently ignored. - */ - UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS = (1 << 2), - /* - * Spawn the child process in a detached state - this will make it a process - * group leader, and will effectively enable the child to keep running after - * the parent exits. Note that the child process will still keep the - * parent's event loop alive unless the parent process calls uv_unref() on - * the child's process handle. - */ - UV_PROCESS_DETACHED = (1 << 3), - /* - * Hide the subprocess console window that would normally be created. This - * option is only meaningful on Windows systems. On Unix it is silently - * ignored. - */ - UV_PROCESS_WINDOWS_HIDE = (1 << 4) -}; - -/* - * uv_process_t is a subclass of uv_handle_t. - */ -struct uv_process_s { - UV_HANDLE_FIELDS - uv_exit_cb exit_cb; - int pid; - UV_PROCESS_PRIVATE_FIELDS -}; - -UV_EXTERN int uv_spawn(uv_loop_t* loop, - uv_process_t* handle, - const uv_process_options_t* options); -UV_EXTERN int uv_process_kill(uv_process_t*, int signum); -UV_EXTERN int uv_kill(int pid, int signum); - - -/* - * uv_work_t is a subclass of uv_req_t. - */ -struct uv_work_s { - UV_REQ_FIELDS - uv_loop_t* loop; - uv_work_cb work_cb; - uv_after_work_cb after_work_cb; - UV_WORK_PRIVATE_FIELDS -}; - -UV_EXTERN int uv_queue_work(uv_loop_t* loop, - uv_work_t* req, - uv_work_cb work_cb, - uv_after_work_cb after_work_cb); - -UV_EXTERN int uv_cancel(uv_req_t* req); - - -struct uv_cpu_info_s { - char* model; - int speed; - struct uv_cpu_times_s { - uint64_t user; - uint64_t nice; - uint64_t sys; - uint64_t idle; - uint64_t irq; - } cpu_times; -}; - -struct uv_interface_address_s { - char* name; - char phys_addr[6]; - int is_internal; - union { - struct sockaddr_in address4; - struct sockaddr_in6 address6; - } address; - union { - struct sockaddr_in netmask4; - struct sockaddr_in6 netmask6; - } netmask; -}; - -struct uv_passwd_s { - char* username; - long uid; - long gid; - char* shell; - char* homedir; -}; - -typedef enum { - UV_DIRENT_UNKNOWN, - UV_DIRENT_FILE, - UV_DIRENT_DIR, - UV_DIRENT_LINK, - UV_DIRENT_FIFO, - UV_DIRENT_SOCKET, - UV_DIRENT_CHAR, - UV_DIRENT_BLOCK -} uv_dirent_type_t; - -struct uv_dirent_s { - const char* name; - uv_dirent_type_t type; -}; - -UV_EXTERN char** uv_setup_args(int argc, char** argv); -UV_EXTERN int uv_get_process_title(char* buffer, size_t size); -UV_EXTERN int uv_set_process_title(const char* title); -UV_EXTERN int uv_resident_set_memory(size_t* rss); -UV_EXTERN int uv_uptime(double* uptime); - -typedef struct { - long tv_sec; - long tv_usec; -} uv_timeval_t; - -typedef struct { - uv_timeval_t ru_utime; /* user CPU time used */ - uv_timeval_t ru_stime; /* system CPU time used */ - uint64_t ru_maxrss; /* maximum resident set size */ - uint64_t ru_ixrss; /* integral shared memory size */ - uint64_t ru_idrss; /* integral unshared data size */ - uint64_t ru_isrss; /* integral unshared stack size */ - uint64_t ru_minflt; /* page reclaims (soft page faults) */ - uint64_t ru_majflt; /* page faults (hard page faults) */ - uint64_t ru_nswap; /* swaps */ - uint64_t ru_inblock; /* block input operations */ - uint64_t ru_oublock; /* block output operations */ - uint64_t ru_msgsnd; /* IPC messages sent */ - uint64_t ru_msgrcv; /* IPC messages received */ - uint64_t ru_nsignals; /* signals received */ - uint64_t ru_nvcsw; /* voluntary context switches */ - uint64_t ru_nivcsw; /* involuntary context switches */ -} uv_rusage_t; - -UV_EXTERN int uv_getrusage(uv_rusage_t* rusage); - -UV_EXTERN int uv_os_homedir(char* buffer, size_t* size); -UV_EXTERN int uv_os_tmpdir(char* buffer, size_t* size); -UV_EXTERN int uv_os_get_passwd(uv_passwd_t* pwd); -UV_EXTERN void uv_os_free_passwd(uv_passwd_t* pwd); - -UV_EXTERN int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count); -UV_EXTERN void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count); - -UV_EXTERN int uv_interface_addresses(uv_interface_address_t** addresses, - int* count); -UV_EXTERN void uv_free_interface_addresses(uv_interface_address_t* addresses, - int count); - - -typedef enum { - UV_FS_UNKNOWN = -1, - UV_FS_CUSTOM, - UV_FS_OPEN, - UV_FS_CLOSE, - UV_FS_READ, - UV_FS_WRITE, - UV_FS_SENDFILE, - UV_FS_STAT, - UV_FS_LSTAT, - UV_FS_FSTAT, - UV_FS_FTRUNCATE, - UV_FS_UTIME, - UV_FS_FUTIME, - UV_FS_ACCESS, - UV_FS_CHMOD, - UV_FS_FCHMOD, - UV_FS_FSYNC, - UV_FS_FDATASYNC, - UV_FS_UNLINK, - UV_FS_RMDIR, - UV_FS_MKDIR, - UV_FS_MKDTEMP, - UV_FS_RENAME, - UV_FS_SCANDIR, - UV_FS_LINK, - UV_FS_SYMLINK, - UV_FS_READLINK, - UV_FS_CHOWN, - UV_FS_FCHOWN, - UV_FS_REALPATH -} uv_fs_type; - -/* uv_fs_t is a subclass of uv_req_t. */ -struct uv_fs_s { - UV_REQ_FIELDS - uv_fs_type fs_type; - uv_loop_t* loop; - uv_fs_cb cb; - ssize_t result; - void* ptr; - const char* path; - uv_stat_t statbuf; /* Stores the result of uv_fs_stat() and uv_fs_fstat(). */ - UV_FS_PRIVATE_FIELDS -}; - -UV_EXTERN void uv_fs_req_cleanup(uv_fs_t* req); -UV_EXTERN int uv_fs_close(uv_loop_t* loop, - uv_fs_t* req, - uv_file file, - uv_fs_cb cb); -UV_EXTERN int uv_fs_open(uv_loop_t* loop, - uv_fs_t* req, - const char* path, - int flags, - int mode, - uv_fs_cb cb); -UV_EXTERN int uv_fs_read(uv_loop_t* loop, - uv_fs_t* req, - uv_file file, - const uv_buf_t bufs[], - unsigned int nbufs, - int64_t offset, - uv_fs_cb cb); -UV_EXTERN int uv_fs_unlink(uv_loop_t* loop, - uv_fs_t* req, - const char* path, - uv_fs_cb cb); -UV_EXTERN int uv_fs_write(uv_loop_t* loop, - uv_fs_t* req, - uv_file file, - const uv_buf_t bufs[], - unsigned int nbufs, - int64_t offset, - uv_fs_cb cb); -UV_EXTERN int uv_fs_mkdir(uv_loop_t* loop, - uv_fs_t* req, - const char* path, - int mode, - uv_fs_cb cb); -UV_EXTERN int uv_fs_mkdtemp(uv_loop_t* loop, - uv_fs_t* req, - const char* tpl, - uv_fs_cb cb); -UV_EXTERN int uv_fs_rmdir(uv_loop_t* loop, - uv_fs_t* req, - const char* path, - uv_fs_cb cb); -UV_EXTERN int uv_fs_scandir(uv_loop_t* loop, - uv_fs_t* req, - const char* path, - int flags, - uv_fs_cb cb); -UV_EXTERN int uv_fs_scandir_next(uv_fs_t* req, - uv_dirent_t* ent); -UV_EXTERN int uv_fs_stat(uv_loop_t* loop, - uv_fs_t* req, - const char* path, - uv_fs_cb cb); -UV_EXTERN int uv_fs_fstat(uv_loop_t* loop, - uv_fs_t* req, - uv_file file, - uv_fs_cb cb); -UV_EXTERN int uv_fs_rename(uv_loop_t* loop, - uv_fs_t* req, - const char* path, - const char* new_path, - uv_fs_cb cb); -UV_EXTERN int uv_fs_fsync(uv_loop_t* loop, - uv_fs_t* req, - uv_file file, - uv_fs_cb cb); -UV_EXTERN int uv_fs_fdatasync(uv_loop_t* loop, - uv_fs_t* req, - uv_file file, - uv_fs_cb cb); -UV_EXTERN int uv_fs_ftruncate(uv_loop_t* loop, - uv_fs_t* req, - uv_file file, - int64_t offset, - uv_fs_cb cb); -UV_EXTERN int uv_fs_sendfile(uv_loop_t* loop, - uv_fs_t* req, - uv_file out_fd, - uv_file in_fd, - int64_t in_offset, - size_t length, - uv_fs_cb cb); -UV_EXTERN int uv_fs_access(uv_loop_t* loop, - uv_fs_t* req, - const char* path, - int mode, - uv_fs_cb cb); -UV_EXTERN int uv_fs_chmod(uv_loop_t* loop, - uv_fs_t* req, - const char* path, - int mode, - uv_fs_cb cb); -UV_EXTERN int uv_fs_utime(uv_loop_t* loop, - uv_fs_t* req, - const char* path, - double atime, - double mtime, - uv_fs_cb cb); -UV_EXTERN int uv_fs_futime(uv_loop_t* loop, - uv_fs_t* req, - uv_file file, - double atime, - double mtime, - uv_fs_cb cb); -UV_EXTERN int uv_fs_lstat(uv_loop_t* loop, - uv_fs_t* req, - const char* path, - uv_fs_cb cb); -UV_EXTERN int uv_fs_link(uv_loop_t* loop, - uv_fs_t* req, - const char* path, - const char* new_path, - uv_fs_cb cb); - -/* - * This flag can be used with uv_fs_symlink() on Windows to specify whether - * path argument points to a directory. - */ -#define UV_FS_SYMLINK_DIR 0x0001 - -/* - * This flag can be used with uv_fs_symlink() on Windows to specify whether - * the symlink is to be created using junction points. - */ -#define UV_FS_SYMLINK_JUNCTION 0x0002 - -UV_EXTERN int uv_fs_symlink(uv_loop_t* loop, - uv_fs_t* req, - const char* path, - const char* new_path, - int flags, - uv_fs_cb cb); -UV_EXTERN int uv_fs_readlink(uv_loop_t* loop, - uv_fs_t* req, - const char* path, - uv_fs_cb cb); -UV_EXTERN int uv_fs_realpath(uv_loop_t* loop, - uv_fs_t* req, - const char* path, - uv_fs_cb cb); -UV_EXTERN int uv_fs_fchmod(uv_loop_t* loop, - uv_fs_t* req, - uv_file file, - int mode, - uv_fs_cb cb); -UV_EXTERN int uv_fs_chown(uv_loop_t* loop, - uv_fs_t* req, - const char* path, - uv_uid_t uid, - uv_gid_t gid, - uv_fs_cb cb); -UV_EXTERN int uv_fs_fchown(uv_loop_t* loop, - uv_fs_t* req, - uv_file file, - uv_uid_t uid, - uv_gid_t gid, - uv_fs_cb cb); - - -enum uv_fs_event { - UV_RENAME = 1, - UV_CHANGE = 2 -}; - - -struct uv_fs_event_s { - UV_HANDLE_FIELDS - /* private */ - char* path; - UV_FS_EVENT_PRIVATE_FIELDS -}; - - -/* - * uv_fs_stat() based polling file watcher. - */ -struct uv_fs_poll_s { - UV_HANDLE_FIELDS - /* Private, don't touch. */ - void* poll_ctx; -}; - -UV_EXTERN int uv_fs_poll_init(uv_loop_t* loop, uv_fs_poll_t* handle); -UV_EXTERN int uv_fs_poll_start(uv_fs_poll_t* handle, - uv_fs_poll_cb poll_cb, - const char* path, - unsigned int interval); -UV_EXTERN int uv_fs_poll_stop(uv_fs_poll_t* handle); -UV_EXTERN int uv_fs_poll_getpath(uv_fs_poll_t* handle, - char* buffer, - size_t* size); - - -struct uv_signal_s { - UV_HANDLE_FIELDS - uv_signal_cb signal_cb; - int signum; - UV_SIGNAL_PRIVATE_FIELDS -}; - -UV_EXTERN int uv_signal_init(uv_loop_t* loop, uv_signal_t* handle); -UV_EXTERN int uv_signal_start(uv_signal_t* handle, - uv_signal_cb signal_cb, - int signum); -UV_EXTERN int uv_signal_stop(uv_signal_t* handle); - -UV_EXTERN void uv_loadavg(double avg[3]); - - -/* - * Flags to be passed to uv_fs_event_start(). - */ -enum uv_fs_event_flags { - /* - * By default, if the fs event watcher is given a directory name, we will - * watch for all events in that directory. This flags overrides this behavior - * and makes fs_event report only changes to the directory entry itself. This - * flag does not affect individual files watched. - * This flag is currently not implemented yet on any backend. - */ - UV_FS_EVENT_WATCH_ENTRY = 1, - - /* - * By default uv_fs_event will try to use a kernel interface such as inotify - * or kqueue to detect events. This may not work on remote filesystems such - * as NFS mounts. This flag makes fs_event fall back to calling stat() on a - * regular interval. - * This flag is currently not implemented yet on any backend. - */ - UV_FS_EVENT_STAT = 2, - - /* - * By default, event watcher, when watching directory, is not registering - * (is ignoring) changes in it's subdirectories. - * This flag will override this behaviour on platforms that support it. - */ - UV_FS_EVENT_RECURSIVE = 4 -}; - - -UV_EXTERN int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle); -UV_EXTERN int uv_fs_event_start(uv_fs_event_t* handle, - uv_fs_event_cb cb, - const char* path, - unsigned int flags); -UV_EXTERN int uv_fs_event_stop(uv_fs_event_t* handle); -UV_EXTERN int uv_fs_event_getpath(uv_fs_event_t* handle, - char* buffer, - size_t* size); - -UV_EXTERN int uv_ip4_addr(const char* ip, int port, struct sockaddr_in* addr); -UV_EXTERN int uv_ip6_addr(const char* ip, int port, struct sockaddr_in6* addr); - -UV_EXTERN int uv_ip4_name(const struct sockaddr_in* src, char* dst, size_t size); -UV_EXTERN int uv_ip6_name(const struct sockaddr_in6* src, char* dst, size_t size); - -UV_EXTERN int uv_inet_ntop(int af, const void* src, char* dst, size_t size); -UV_EXTERN int uv_inet_pton(int af, const char* src, void* dst); - -UV_EXTERN int uv_exepath(char* buffer, size_t* size); - -UV_EXTERN int uv_cwd(char* buffer, size_t* size); - -UV_EXTERN int uv_chdir(const char* dir); - -UV_EXTERN uint64_t uv_get_free_memory(void); -UV_EXTERN uint64_t uv_get_total_memory(void); - -UV_EXTERN uint64_t uv_hrtime(void); - -UV_EXTERN void uv_disable_stdio_inheritance(void); - -UV_EXTERN int uv_dlopen(const char* filename, uv_lib_t* lib); -UV_EXTERN void uv_dlclose(uv_lib_t* lib); -UV_EXTERN int uv_dlsym(uv_lib_t* lib, const char* name, void** ptr); -UV_EXTERN const char* uv_dlerror(const uv_lib_t* lib); - -UV_EXTERN int uv_mutex_init(uv_mutex_t* handle); -UV_EXTERN void uv_mutex_destroy(uv_mutex_t* handle); -UV_EXTERN void uv_mutex_lock(uv_mutex_t* handle); -UV_EXTERN int uv_mutex_trylock(uv_mutex_t* handle); -UV_EXTERN void uv_mutex_unlock(uv_mutex_t* handle); - -UV_EXTERN int uv_rwlock_init(uv_rwlock_t* rwlock); -UV_EXTERN void uv_rwlock_destroy(uv_rwlock_t* rwlock); -UV_EXTERN void uv_rwlock_rdlock(uv_rwlock_t* rwlock); -UV_EXTERN int uv_rwlock_tryrdlock(uv_rwlock_t* rwlock); -UV_EXTERN void uv_rwlock_rdunlock(uv_rwlock_t* rwlock); -UV_EXTERN void uv_rwlock_wrlock(uv_rwlock_t* rwlock); -UV_EXTERN int uv_rwlock_trywrlock(uv_rwlock_t* rwlock); -UV_EXTERN void uv_rwlock_wrunlock(uv_rwlock_t* rwlock); - -UV_EXTERN int uv_sem_init(uv_sem_t* sem, unsigned int value); -UV_EXTERN void uv_sem_destroy(uv_sem_t* sem); -UV_EXTERN void uv_sem_post(uv_sem_t* sem); -UV_EXTERN void uv_sem_wait(uv_sem_t* sem); -UV_EXTERN int uv_sem_trywait(uv_sem_t* sem); - -UV_EXTERN int uv_cond_init(uv_cond_t* cond); -UV_EXTERN void uv_cond_destroy(uv_cond_t* cond); -UV_EXTERN void uv_cond_signal(uv_cond_t* cond); -UV_EXTERN void uv_cond_broadcast(uv_cond_t* cond); - -UV_EXTERN int uv_barrier_init(uv_barrier_t* barrier, unsigned int count); -UV_EXTERN void uv_barrier_destroy(uv_barrier_t* barrier); -UV_EXTERN int uv_barrier_wait(uv_barrier_t* barrier); - -UV_EXTERN void uv_cond_wait(uv_cond_t* cond, uv_mutex_t* mutex); -UV_EXTERN int uv_cond_timedwait(uv_cond_t* cond, - uv_mutex_t* mutex, - uint64_t timeout); - -UV_EXTERN void uv_once(uv_once_t* guard, void (*callback)(void)); - -UV_EXTERN int uv_key_create(uv_key_t* key); -UV_EXTERN void uv_key_delete(uv_key_t* key); -UV_EXTERN void* uv_key_get(uv_key_t* key); -UV_EXTERN void uv_key_set(uv_key_t* key, void* value); - -typedef void (*uv_thread_cb)(void* arg); - -UV_EXTERN int uv_thread_create(uv_thread_t* tid, uv_thread_cb entry, void* arg); -UV_EXTERN uv_thread_t uv_thread_self(void); -UV_EXTERN int uv_thread_join(uv_thread_t *tid); -UV_EXTERN int uv_thread_equal(const uv_thread_t* t1, const uv_thread_t* t2); - -/* The presence of these unions force similar struct layout. */ -#define XX(_, name) uv_ ## name ## _t name; -union uv_any_handle { - UV_HANDLE_TYPE_MAP(XX) -}; - -union uv_any_req { - UV_REQ_TYPE_MAP(XX) -}; -#undef XX - - -struct uv_loop_s { - /* User data - use this for whatever. */ - void* data; - /* Loop reference counting. */ - unsigned int active_handles; - void* handle_queue[2]; - void* active_reqs[2]; - /* Internal flag to signal loop stop. */ - unsigned int stop_flag; - UV_LOOP_PRIVATE_FIELDS -}; - - -/* Don't export the private CPP symbols. */ -#undef UV_HANDLE_TYPE_PRIVATE -#undef UV_REQ_TYPE_PRIVATE -#undef UV_REQ_PRIVATE_FIELDS -#undef UV_STREAM_PRIVATE_FIELDS -#undef UV_TCP_PRIVATE_FIELDS -#undef UV_PREPARE_PRIVATE_FIELDS -#undef UV_CHECK_PRIVATE_FIELDS -#undef UV_IDLE_PRIVATE_FIELDS -#undef UV_ASYNC_PRIVATE_FIELDS -#undef UV_TIMER_PRIVATE_FIELDS -#undef UV_GETADDRINFO_PRIVATE_FIELDS -#undef UV_GETNAMEINFO_PRIVATE_FIELDS -#undef UV_FS_REQ_PRIVATE_FIELDS -#undef UV_WORK_PRIVATE_FIELDS -#undef UV_FS_EVENT_PRIVATE_FIELDS -#undef UV_SIGNAL_PRIVATE_FIELDS -#undef UV_LOOP_PRIVATE_FIELDS -#undef UV_LOOP_PRIVATE_PLATFORM_FIELDS - -#ifdef __cplusplus -} -#endif -#endif /* UV_H */ diff --git a/vendor/libuv/libuv.nsi b/vendor/libuv/libuv.nsi deleted file mode 100644 index 159756e19..000000000 --- a/vendor/libuv/libuv.nsi +++ /dev/null @@ -1,86 +0,0 @@ -; NSIS installer script for libuv - -!include "MUI2.nsh" - -Name "libuv" -OutFile "libuv-${ARCH}-${VERSION}.exe" - -!include "x64.nsh" -# Default install location, for 32-bit files -InstallDir "$PROGRAMFILES\libuv" - -# Override install and registry locations if this is a 64-bit install. -function .onInit - ${If} ${ARCH} == "x64" - SetRegView 64 - StrCpy $INSTDIR "$PROGRAMFILES64\libuv" - ${EndIf} -functionEnd - -;-------------------------------- -; Installer pages -!insertmacro MUI_PAGE_WELCOME -!insertmacro MUI_PAGE_DIRECTORY -!insertmacro MUI_PAGE_INSTFILES -!insertmacro MUI_PAGE_FINISH - - -;-------------------------------- -; Uninstaller pages -!insertmacro MUI_UNPAGE_WELCOME -!insertmacro MUI_UNPAGE_CONFIRM -!insertmacro MUI_UNPAGE_INSTFILES -!insertmacro MUI_UNPAGE_FINISH - -;-------------------------------- -; Languages -!insertmacro MUI_LANGUAGE "English" - -;-------------------------------- -; Installer sections - -Section "Files" SecInstall - SectionIn RO - SetOutPath "$INSTDIR" - File "Release\*.dll" - File "Release\*.lib" - File "LICENSE" - File "README.md" - - SetOutPath "$INSTDIR\include" - File "include\uv.h" - File "include\uv-errno.h" - File "include\uv-threadpool.h" - File "include\uv-version.h" - File "include\uv-win.h" - File "include\tree.h" - - WriteUninstaller "$INSTDIR\Uninstall.exe" - WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\libuv-${ARCH}-${VERSION}" "DisplayName" "libuv-${ARCH}-${VERSION}" - WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\libuv-${ARCH}-${VERSION}" "UninstallString" "$\"$INSTDIR\Uninstall.exe$\"" - WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\libuv-${ARCH}-${VERSION}" "QuietUninstallString" "$\"$INSTDIR\Uninstall.exe$\" /S" - WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\libuv-${ARCH}-${VERSION}" "HelpLink" "http://libuv.org/" - WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\libuv-${ARCH}-${VERSION}" "URLInfoAbout" "http://libuv.org/" - WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\libuv-${ARCH}-${VERSION}" "DisplayVersion" "${VERSION}" - WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\libuv-${ARCH}-${VERSION}" "NoModify" "1" - WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\libuv-${ARCH}-${VERSION}" "NoRepair" "1" -SectionEnd - -Section "Uninstall" - Delete "$INSTDIR\libuv.dll" - Delete "$INSTDIR\libuv.lib" - Delete "$INSTDIR\LICENSE" - Delete "$INSTDIR\README.md" - - Delete "$INSTDIR\include\uv.h" - Delete "$INSTDIR\include\uv-errno.h" - Delete "$INSTDIR\include\uv-threadpool.h" - Delete "$INSTDIR\include\uv-version.h" - Delete "$INSTDIR\include\uv-win.h" - Delete "$INSTDIR\include\tree.h" - - Delete "$INSTDIR\Uninstall.exe" - RMDir "$INSTDIR" - DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\libuv-${ARCH}-${VERSION}" -SectionEnd - diff --git a/vendor/libuv/libuv.pc.in b/vendor/libuv/libuv.pc.in deleted file mode 100644 index 9174fe151..000000000 --- a/vendor/libuv/libuv.pc.in +++ /dev/null @@ -1,11 +0,0 @@ -prefix=@prefix@ -exec_prefix=${prefix} -libdir=@libdir@ -includedir=@includedir@ - -Name: @PACKAGE_NAME@ -Version: @PACKAGE_VERSION@ -Description: multi-platform support library with a focus on asynchronous I/O. - -Libs: -L${libdir} -luv @LIBS@ -Cflags: -I${includedir} diff --git a/vendor/libuv/m4/.gitignore b/vendor/libuv/m4/.gitignore deleted file mode 100644 index c44e4c292..000000000 --- a/vendor/libuv/m4/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -# Ignore libtoolize-generated files. -*.m4 -!as_case.m4 -!libuv-check-flags.m4 diff --git a/vendor/libuv/m4/as_case.m4 b/vendor/libuv/m4/as_case.m4 deleted file mode 100644 index c7ae0f0f5..000000000 --- a/vendor/libuv/m4/as_case.m4 +++ /dev/null @@ -1,21 +0,0 @@ -# AS_CASE(WORD, [PATTERN1], [IF-MATCHED1]...[DEFAULT]) -# ---------------------------------------------------- -# Expand into -# | case WORD in -# | PATTERN1) IF-MATCHED1 ;; -# | ... -# | *) DEFAULT ;; -# | esac -m4_define([_AS_CASE], -[m4_if([$#], 0, [m4_fatal([$0: too few arguments: $#])], - [$#], 1, [ *) $1 ;;], - [$#], 2, [ $1) m4_default([$2], [:]) ;;], - [ $1) m4_default([$2], [:]) ;; -$0(m4_shiftn(2, $@))])dnl -]) -m4_defun([AS_CASE], -[m4_ifval([$2$3], -[case $1 in -_AS_CASE(m4_shift($@)) -esac])]) - diff --git a/vendor/libuv/m4/libuv-check-flags.m4 b/vendor/libuv/m4/libuv-check-flags.m4 deleted file mode 100644 index 59c306355..000000000 --- a/vendor/libuv/m4/libuv-check-flags.m4 +++ /dev/null @@ -1,319 +0,0 @@ -dnl Macros to check the presence of generic (non-typed) symbols. -dnl Copyright (c) 2006-2008 Diego Pettenà -dnl Copyright (c) 2006-2008 xine project -dnl -dnl This program is free software; you can redistribute it and/or modify -dnl it under the terms of the GNU General Public License as published by -dnl the Free Software Foundation; either version 3, or (at your option) -dnl any later version. -dnl -dnl This program is distributed in the hope that it will be useful, -dnl but WITHOUT ANY WARRANTY; without even the implied warranty of -dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -dnl GNU General Public License for more details. -dnl -dnl You should have received a copy of the GNU General Public License -dnl along with this program; if not, write to the Free Software -dnl Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -dnl 02110-1301, USA. -dnl -dnl As a special exception, the copyright owners of the -dnl macro gives unlimited permission to copy, distribute and modify the -dnl configure scripts that are the output of Autoconf when processing the -dnl Macro. You need not follow the terms of the GNU General Public -dnl License when using or distributing such scripts, even though portions -dnl of the text of the Macro appear in them. The GNU General Public -dnl License (GPL) does govern all other use of the material that -dnl constitutes the Autoconf Macro. -dnl -dnl This special exception to the GPL applies to versions of the -dnl Autoconf Macro released by this project. When you make and -dnl distribute a modified version of the Autoconf Macro, you may extend -dnl this special exception to the GPL to apply to your modified version as -dnl well. - -dnl Check if the flag is supported by compiler -dnl CC_CHECK_CFLAGS_SILENT([FLAG], [ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND]) - -AC_DEFUN([CC_CHECK_CFLAGS_SILENT], [ - AC_CACHE_VAL(AS_TR_SH([cc_cv_cflags_$1]), - [ac_save_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS $1" - AC_COMPILE_IFELSE([AC_LANG_SOURCE([int a;])], - [eval "AS_TR_SH([cc_cv_cflags_$1])='yes'"], - [eval "AS_TR_SH([cc_cv_cflags_$1])='no'"]) - CFLAGS="$ac_save_CFLAGS" - ]) - - AS_IF([eval test x$]AS_TR_SH([cc_cv_cflags_$1])[ = xyes], - [$2], [$3]) -]) - -dnl Check if the flag is supported by compiler (cacheable) -dnl CC_CHECK_CFLAGS([FLAG], [ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND]) - -AC_DEFUN([CC_CHECK_CFLAGS], [ - AC_CACHE_CHECK([if $CC supports $1 flag], - AS_TR_SH([cc_cv_cflags_$1]), - CC_CHECK_CFLAGS_SILENT([$1]) dnl Don't execute actions here! - ) - - AS_IF([eval test x$]AS_TR_SH([cc_cv_cflags_$1])[ = xyes], - [$2], [$3]) -]) - -dnl CC_CHECK_CFLAG_APPEND(FLAG, [action-if-found], [action-if-not-found]) -dnl Check for CFLAG and appends them to CFLAGS if supported -AC_DEFUN([CC_CHECK_CFLAG_APPEND], [ - AC_CACHE_CHECK([if $CC supports $1 flag], - AS_TR_SH([cc_cv_cflags_$1]), - CC_CHECK_CFLAGS_SILENT([$1]) dnl Don't execute actions here! - ) - - AS_IF([eval test x$]AS_TR_SH([cc_cv_cflags_$1])[ = xyes], - [CFLAGS="$CFLAGS $1"; DEBUG_CFLAGS="$DEBUG_CFLAGS $1"; $2], [$3]) -]) - -dnl CC_CHECK_CFLAGS_APPEND([FLAG1 FLAG2], [action-if-found], [action-if-not]) -AC_DEFUN([CC_CHECK_CFLAGS_APPEND], [ - for flag in $1; do - CC_CHECK_CFLAG_APPEND($flag, [$2], [$3]) - done -]) - -dnl Check if the flag is supported by linker (cacheable) -dnl CC_CHECK_LDFLAGS([FLAG], [ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND]) - -AC_DEFUN([CC_CHECK_LDFLAGS], [ - AC_CACHE_CHECK([if $CC supports $1 flag], - AS_TR_SH([cc_cv_ldflags_$1]), - [ac_save_LDFLAGS="$LDFLAGS" - LDFLAGS="$LDFLAGS $1" - AC_LANG_PUSH([C]) - AC_LINK_IFELSE([AC_LANG_SOURCE([int main() { return 1; }])], - [eval "AS_TR_SH([cc_cv_ldflags_$1])='yes'"], - [eval "AS_TR_SH([cc_cv_ldflags_$1])="]) - AC_LANG_POP([C]) - LDFLAGS="$ac_save_LDFLAGS" - ]) - - AS_IF([eval test x$]AS_TR_SH([cc_cv_ldflags_$1])[ = xyes], - [$2], [$3]) -]) - -dnl define the LDFLAGS_NOUNDEFINED variable with the correct value for -dnl the current linker to avoid undefined references in a shared object. -AC_DEFUN([CC_NOUNDEFINED], [ - dnl We check $host for which systems to enable this for. - AC_REQUIRE([AC_CANONICAL_HOST]) - - case $host in - dnl FreeBSD (et al.) does not complete linking for shared objects when pthreads - dnl are requested, as different implementations are present; to avoid problems - dnl use -Wl,-z,defs only for those platform not behaving this way. - *-freebsd* | *-openbsd*) ;; - *) - dnl First of all check for the --no-undefined variant of GNU ld. This allows - dnl for a much more readable commandline, so that people can understand what - dnl it does without going to look for what the heck -z defs does. - for possible_flags in "-Wl,--no-undefined" "-Wl,-z,defs"; do - CC_CHECK_LDFLAGS([$possible_flags], [LDFLAGS_NOUNDEFINED="$possible_flags"]) - break - done - ;; - esac - - AC_SUBST([LDFLAGS_NOUNDEFINED]) -]) - -dnl Check for a -Werror flag or equivalent. -Werror is the GCC -dnl and ICC flag that tells the compiler to treat all the warnings -dnl as fatal. We usually need this option to make sure that some -dnl constructs (like attributes) are not simply ignored. -dnl -dnl Other compilers don't support -Werror per se, but they support -dnl an equivalent flag: -dnl - Sun Studio compiler supports -errwarn=%all -AC_DEFUN([CC_CHECK_WERROR], [ - AC_CACHE_CHECK( - [for $CC way to treat warnings as errors], - [cc_cv_werror], - [CC_CHECK_CFLAGS_SILENT([-Werror], [cc_cv_werror=-Werror], - [CC_CHECK_CFLAGS_SILENT([-errwarn=%all], [cc_cv_werror=-errwarn=%all])]) - ]) -]) - -AC_DEFUN([CC_CHECK_ATTRIBUTE], [ - AC_REQUIRE([CC_CHECK_WERROR]) - AC_CACHE_CHECK([if $CC supports __attribute__(( ifelse([$2], , [$1], [$2]) ))], - AS_TR_SH([cc_cv_attribute_$1]), - [ac_save_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS $cc_cv_werror" - AC_LANG_PUSH([C]) - AC_COMPILE_IFELSE([AC_LANG_SOURCE([$3])], - [eval "AS_TR_SH([cc_cv_attribute_$1])='yes'"], - [eval "AS_TR_SH([cc_cv_attribute_$1])='no'"]) - AC_LANG_POP([C]) - CFLAGS="$ac_save_CFLAGS" - ]) - - AS_IF([eval test x$]AS_TR_SH([cc_cv_attribute_$1])[ = xyes], - [AC_DEFINE( - AS_TR_CPP([SUPPORT_ATTRIBUTE_$1]), 1, - [Define this if the compiler supports __attribute__(( ifelse([$2], , [$1], [$2]) ))] - ) - $4], - [$5]) -]) - -AC_DEFUN([CC_ATTRIBUTE_CONSTRUCTOR], [ - CC_CHECK_ATTRIBUTE( - [constructor],, - [void __attribute__((constructor)) ctor() { int a; }], - [$1], [$2]) -]) - -AC_DEFUN([CC_ATTRIBUTE_FORMAT], [ - CC_CHECK_ATTRIBUTE( - [format], [format(printf, n, n)], - [void __attribute__((format(printf, 1, 2))) printflike(const char *fmt, ...) { fmt = (void *)0; }], - [$1], [$2]) -]) - -AC_DEFUN([CC_ATTRIBUTE_FORMAT_ARG], [ - CC_CHECK_ATTRIBUTE( - [format_arg], [format_arg(printf)], - [char *__attribute__((format_arg(1))) gettextlike(const char *fmt) { fmt = (void *)0; }], - [$1], [$2]) -]) - -AC_DEFUN([CC_ATTRIBUTE_VISIBILITY], [ - CC_CHECK_ATTRIBUTE( - [visibility_$1], [visibility("$1")], - [void __attribute__((visibility("$1"))) $1_function() { }], - [$2], [$3]) -]) - -AC_DEFUN([CC_ATTRIBUTE_NONNULL], [ - CC_CHECK_ATTRIBUTE( - [nonnull], [nonnull()], - [void __attribute__((nonnull())) some_function(void *foo, void *bar) { foo = (void*)0; bar = (void*)0; }], - [$1], [$2]) -]) - -AC_DEFUN([CC_ATTRIBUTE_UNUSED], [ - CC_CHECK_ATTRIBUTE( - [unused], , - [void some_function(void *foo, __attribute__((unused)) void *bar);], - [$1], [$2]) -]) - -AC_DEFUN([CC_ATTRIBUTE_SENTINEL], [ - CC_CHECK_ATTRIBUTE( - [sentinel], , - [void some_function(void *foo, ...) __attribute__((sentinel));], - [$1], [$2]) -]) - -AC_DEFUN([CC_ATTRIBUTE_DEPRECATED], [ - CC_CHECK_ATTRIBUTE( - [deprecated], , - [void some_function(void *foo, ...) __attribute__((deprecated));], - [$1], [$2]) -]) - -AC_DEFUN([CC_ATTRIBUTE_ALIAS], [ - CC_CHECK_ATTRIBUTE( - [alias], [weak, alias], - [void other_function(void *foo) { } - void some_function(void *foo) __attribute__((weak, alias("other_function")));], - [$1], [$2]) -]) - -AC_DEFUN([CC_ATTRIBUTE_MALLOC], [ - CC_CHECK_ATTRIBUTE( - [malloc], , - [void * __attribute__((malloc)) my_alloc(int n);], - [$1], [$2]) -]) - -AC_DEFUN([CC_ATTRIBUTE_PACKED], [ - CC_CHECK_ATTRIBUTE( - [packed], , - [struct astructure { char a; int b; long c; void *d; } __attribute__((packed));], - [$1], [$2]) -]) - -AC_DEFUN([CC_ATTRIBUTE_CONST], [ - CC_CHECK_ATTRIBUTE( - [const], , - [int __attribute__((const)) twopow(int n) { return 1 << n; } ], - [$1], [$2]) -]) - -AC_DEFUN([CC_FLAG_VISIBILITY], [ - AC_REQUIRE([CC_CHECK_WERROR]) - AC_CACHE_CHECK([if $CC supports -fvisibility=hidden], - [cc_cv_flag_visibility], - [cc_flag_visibility_save_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS $cc_cv_werror" - CC_CHECK_CFLAGS_SILENT([-fvisibility=hidden], - cc_cv_flag_visibility='yes', - cc_cv_flag_visibility='no') - CFLAGS="$cc_flag_visibility_save_CFLAGS"]) - - AS_IF([test "x$cc_cv_flag_visibility" = "xyes"], - [AC_DEFINE([SUPPORT_FLAG_VISIBILITY], 1, - [Define this if the compiler supports the -fvisibility flag]) - $1], - [$2]) -]) - -AC_DEFUN([CC_FUNC_EXPECT], [ - AC_REQUIRE([CC_CHECK_WERROR]) - AC_CACHE_CHECK([if compiler has __builtin_expect function], - [cc_cv_func_expect], - [ac_save_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS $cc_cv_werror" - AC_LANG_PUSH([C]) - AC_COMPILE_IFELSE([AC_LANG_SOURCE( - [int some_function() { - int a = 3; - return (int)__builtin_expect(a, 3); - }])], - [cc_cv_func_expect=yes], - [cc_cv_func_expect=no]) - AC_LANG_POP([C]) - CFLAGS="$ac_save_CFLAGS" - ]) - - AS_IF([test "x$cc_cv_func_expect" = "xyes"], - [AC_DEFINE([SUPPORT__BUILTIN_EXPECT], 1, - [Define this if the compiler supports __builtin_expect() function]) - $1], - [$2]) -]) - -AC_DEFUN([CC_ATTRIBUTE_ALIGNED], [ - AC_REQUIRE([CC_CHECK_WERROR]) - AC_CACHE_CHECK([highest __attribute__ ((aligned ())) supported], - [cc_cv_attribute_aligned], - [ac_save_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS $cc_cv_werror" - AC_LANG_PUSH([C]) - for cc_attribute_align_try in 64 32 16 8 4 2; do - AC_COMPILE_IFELSE([AC_LANG_SOURCE([ - int main() { - static char c __attribute__ ((aligned($cc_attribute_align_try))) = 0; - return c; - }])], [cc_cv_attribute_aligned=$cc_attribute_align_try; break]) - done - AC_LANG_POP([C]) - CFLAGS="$ac_save_CFLAGS" - ]) - - if test "x$cc_cv_attribute_aligned" != "x"; then - AC_DEFINE_UNQUOTED([ATTRIBUTE_ALIGNED_MAX], [$cc_cv_attribute_aligned], - [Define the highest alignment supported]) - fi -]) \ No newline at end of file diff --git a/vendor/libuv/src/fs-poll.c b/vendor/libuv/src/fs-poll.c deleted file mode 100644 index ee73d5a2e..000000000 --- a/vendor/libuv/src/fs-poll.c +++ /dev/null @@ -1,256 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "uv-common.h" - -#include -#include -#include - -struct poll_ctx { - uv_fs_poll_t* parent_handle; /* NULL if parent has been stopped or closed */ - int busy_polling; - unsigned int interval; - uint64_t start_time; - uv_loop_t* loop; - uv_fs_poll_cb poll_cb; - uv_timer_t timer_handle; - uv_fs_t fs_req; /* TODO(bnoordhuis) mark fs_req internal */ - uv_stat_t statbuf; - char path[1]; /* variable length */ -}; - -static int statbuf_eq(const uv_stat_t* a, const uv_stat_t* b); -static void poll_cb(uv_fs_t* req); -static void timer_cb(uv_timer_t* timer); -static void timer_close_cb(uv_handle_t* handle); - -static uv_stat_t zero_statbuf; - - -int uv_fs_poll_init(uv_loop_t* loop, uv_fs_poll_t* handle) { - uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_POLL); - return 0; -} - - -int uv_fs_poll_start(uv_fs_poll_t* handle, - uv_fs_poll_cb cb, - const char* path, - unsigned int interval) { - struct poll_ctx* ctx; - uv_loop_t* loop; - size_t len; - int err; - - if (uv__is_active(handle)) - return 0; - - loop = handle->loop; - len = strlen(path); - ctx = uv__calloc(1, sizeof(*ctx) + len); - - if (ctx == NULL) - return UV_ENOMEM; - - ctx->loop = loop; - ctx->poll_cb = cb; - ctx->interval = interval ? interval : 1; - ctx->start_time = uv_now(loop); - ctx->parent_handle = handle; - memcpy(ctx->path, path, len + 1); - - err = uv_timer_init(loop, &ctx->timer_handle); - if (err < 0) - goto error; - - ctx->timer_handle.flags |= UV__HANDLE_INTERNAL; - uv__handle_unref(&ctx->timer_handle); - - err = uv_fs_stat(loop, &ctx->fs_req, ctx->path, poll_cb); - if (err < 0) - goto error; - - handle->poll_ctx = ctx; - uv__handle_start(handle); - - return 0; - -error: - uv__free(ctx); - return err; -} - - -int uv_fs_poll_stop(uv_fs_poll_t* handle) { - struct poll_ctx* ctx; - - if (!uv__is_active(handle)) - return 0; - - ctx = handle->poll_ctx; - assert(ctx != NULL); - assert(ctx->parent_handle != NULL); - ctx->parent_handle = NULL; - handle->poll_ctx = NULL; - - /* Close the timer if it's active. If it's inactive, there's a stat request - * in progress and poll_cb will take care of the cleanup. - */ - if (uv__is_active(&ctx->timer_handle)) - uv_close((uv_handle_t*)&ctx->timer_handle, timer_close_cb); - - uv__handle_stop(handle); - - return 0; -} - - -int uv_fs_poll_getpath(uv_fs_poll_t* handle, char* buffer, size_t* size) { - struct poll_ctx* ctx; - size_t required_len; - - if (!uv__is_active(handle)) { - *size = 0; - return UV_EINVAL; - } - - ctx = handle->poll_ctx; - assert(ctx != NULL); - - required_len = strlen(ctx->path); - if (required_len >= *size) { - *size = required_len + 1; - return UV_ENOBUFS; - } - - memcpy(buffer, ctx->path, required_len); - *size = required_len; - buffer[required_len] = '\0'; - - return 0; -} - - -void uv__fs_poll_close(uv_fs_poll_t* handle) { - uv_fs_poll_stop(handle); -} - - -static void timer_cb(uv_timer_t* timer) { - struct poll_ctx* ctx; - - ctx = container_of(timer, struct poll_ctx, timer_handle); - assert(ctx->parent_handle != NULL); - assert(ctx->parent_handle->poll_ctx == ctx); - ctx->start_time = uv_now(ctx->loop); - - if (uv_fs_stat(ctx->loop, &ctx->fs_req, ctx->path, poll_cb)) - abort(); -} - - -static void poll_cb(uv_fs_t* req) { - uv_stat_t* statbuf; - struct poll_ctx* ctx; - uint64_t interval; - - ctx = container_of(req, struct poll_ctx, fs_req); - - if (ctx->parent_handle == NULL) { /* handle has been stopped or closed */ - uv_close((uv_handle_t*)&ctx->timer_handle, timer_close_cb); - uv_fs_req_cleanup(req); - return; - } - - if (req->result != 0) { - if (ctx->busy_polling != req->result) { - ctx->poll_cb(ctx->parent_handle, - req->result, - &ctx->statbuf, - &zero_statbuf); - ctx->busy_polling = req->result; - } - goto out; - } - - statbuf = &req->statbuf; - - if (ctx->busy_polling != 0) - if (ctx->busy_polling < 0 || !statbuf_eq(&ctx->statbuf, statbuf)) - ctx->poll_cb(ctx->parent_handle, 0, &ctx->statbuf, statbuf); - - ctx->statbuf = *statbuf; - ctx->busy_polling = 1; - -out: - uv_fs_req_cleanup(req); - - if (ctx->parent_handle == NULL) { /* handle has been stopped by callback */ - uv_close((uv_handle_t*)&ctx->timer_handle, timer_close_cb); - return; - } - - /* Reschedule timer, subtract the delay from doing the stat(). */ - interval = ctx->interval; - interval -= (uv_now(ctx->loop) - ctx->start_time) % interval; - - if (uv_timer_start(&ctx->timer_handle, timer_cb, interval, 0)) - abort(); -} - - -static void timer_close_cb(uv_handle_t* handle) { - uv__free(container_of(handle, struct poll_ctx, timer_handle)); -} - - -static int statbuf_eq(const uv_stat_t* a, const uv_stat_t* b) { - return a->st_ctim.tv_nsec == b->st_ctim.tv_nsec - && a->st_mtim.tv_nsec == b->st_mtim.tv_nsec - && a->st_birthtim.tv_nsec == b->st_birthtim.tv_nsec - && a->st_ctim.tv_sec == b->st_ctim.tv_sec - && a->st_mtim.tv_sec == b->st_mtim.tv_sec - && a->st_birthtim.tv_sec == b->st_birthtim.tv_sec - && a->st_size == b->st_size - && a->st_mode == b->st_mode - && a->st_uid == b->st_uid - && a->st_gid == b->st_gid - && a->st_ino == b->st_ino - && a->st_dev == b->st_dev - && a->st_flags == b->st_flags - && a->st_gen == b->st_gen; -} - - -#if defined(_WIN32) - -#include "win/internal.h" -#include "win/handle-inl.h" - -void uv__fs_poll_endgame(uv_loop_t* loop, uv_fs_poll_t* handle) { - assert(handle->flags & UV__HANDLE_CLOSING); - assert(!(handle->flags & UV_HANDLE_CLOSED)); - uv__handle_close(handle); -} - -#endif /* _WIN32 */ diff --git a/vendor/libuv/src/heap-inl.h b/vendor/libuv/src/heap-inl.h deleted file mode 100644 index 1e2ed60e0..000000000 --- a/vendor/libuv/src/heap-inl.h +++ /dev/null @@ -1,245 +0,0 @@ -/* Copyright (c) 2013, Ben Noordhuis - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef UV_SRC_HEAP_H_ -#define UV_SRC_HEAP_H_ - -#include /* NULL */ - -#if defined(__GNUC__) -# define HEAP_EXPORT(declaration) __attribute__((unused)) static declaration -#else -# define HEAP_EXPORT(declaration) static declaration -#endif - -struct heap_node { - struct heap_node* left; - struct heap_node* right; - struct heap_node* parent; -}; - -/* A binary min heap. The usual properties hold: the root is the lowest - * element in the set, the height of the tree is at most log2(nodes) and - * it's always a complete binary tree. - * - * The heap function try hard to detect corrupted tree nodes at the cost - * of a minor reduction in performance. Compile with -DNDEBUG to disable. - */ -struct heap { - struct heap_node* min; - unsigned int nelts; -}; - -/* Return non-zero if a < b. */ -typedef int (*heap_compare_fn)(const struct heap_node* a, - const struct heap_node* b); - -/* Public functions. */ -HEAP_EXPORT(void heap_init(struct heap* heap)); -HEAP_EXPORT(struct heap_node* heap_min(const struct heap* heap)); -HEAP_EXPORT(void heap_insert(struct heap* heap, - struct heap_node* newnode, - heap_compare_fn less_than)); -HEAP_EXPORT(void heap_remove(struct heap* heap, - struct heap_node* node, - heap_compare_fn less_than)); -HEAP_EXPORT(void heap_dequeue(struct heap* heap, heap_compare_fn less_than)); - -/* Implementation follows. */ - -HEAP_EXPORT(void heap_init(struct heap* heap)) { - heap->min = NULL; - heap->nelts = 0; -} - -HEAP_EXPORT(struct heap_node* heap_min(const struct heap* heap)) { - return heap->min; -} - -/* Swap parent with child. Child moves closer to the root, parent moves away. */ -static void heap_node_swap(struct heap* heap, - struct heap_node* parent, - struct heap_node* child) { - struct heap_node* sibling; - struct heap_node t; - - t = *parent; - *parent = *child; - *child = t; - - parent->parent = child; - if (child->left == child) { - child->left = parent; - sibling = child->right; - } else { - child->right = parent; - sibling = child->left; - } - if (sibling != NULL) - sibling->parent = child; - - if (parent->left != NULL) - parent->left->parent = parent; - if (parent->right != NULL) - parent->right->parent = parent; - - if (child->parent == NULL) - heap->min = child; - else if (child->parent->left == parent) - child->parent->left = child; - else - child->parent->right = child; -} - -HEAP_EXPORT(void heap_insert(struct heap* heap, - struct heap_node* newnode, - heap_compare_fn less_than)) { - struct heap_node** parent; - struct heap_node** child; - unsigned int path; - unsigned int n; - unsigned int k; - - newnode->left = NULL; - newnode->right = NULL; - newnode->parent = NULL; - - /* Calculate the path from the root to the insertion point. This is a min - * heap so we always insert at the left-most free node of the bottom row. - */ - path = 0; - for (k = 0, n = 1 + heap->nelts; n >= 2; k += 1, n /= 2) - path = (path << 1) | (n & 1); - - /* Now traverse the heap using the path we calculated in the previous step. */ - parent = child = &heap->min; - while (k > 0) { - parent = child; - if (path & 1) - child = &(*child)->right; - else - child = &(*child)->left; - path >>= 1; - k -= 1; - } - - /* Insert the new node. */ - newnode->parent = *parent; - *child = newnode; - heap->nelts += 1; - - /* Walk up the tree and check at each node if the heap property holds. - * It's a min heap so parent < child must be true. - */ - while (newnode->parent != NULL && less_than(newnode, newnode->parent)) - heap_node_swap(heap, newnode->parent, newnode); -} - -HEAP_EXPORT(void heap_remove(struct heap* heap, - struct heap_node* node, - heap_compare_fn less_than)) { - struct heap_node* smallest; - struct heap_node** max; - struct heap_node* child; - unsigned int path; - unsigned int k; - unsigned int n; - - if (heap->nelts == 0) - return; - - /* Calculate the path from the min (the root) to the max, the left-most node - * of the bottom row. - */ - path = 0; - for (k = 0, n = heap->nelts; n >= 2; k += 1, n /= 2) - path = (path << 1) | (n & 1); - - /* Now traverse the heap using the path we calculated in the previous step. */ - max = &heap->min; - while (k > 0) { - if (path & 1) - max = &(*max)->right; - else - max = &(*max)->left; - path >>= 1; - k -= 1; - } - - heap->nelts -= 1; - - /* Unlink the max node. */ - child = *max; - *max = NULL; - - if (child == node) { - /* We're removing either the max or the last node in the tree. */ - if (child == heap->min) { - heap->min = NULL; - } - return; - } - - /* Replace the to be deleted node with the max node. */ - child->left = node->left; - child->right = node->right; - child->parent = node->parent; - - if (child->left != NULL) { - child->left->parent = child; - } - - if (child->right != NULL) { - child->right->parent = child; - } - - if (node->parent == NULL) { - heap->min = child; - } else if (node->parent->left == node) { - node->parent->left = child; - } else { - node->parent->right = child; - } - - /* Walk down the subtree and check at each node if the heap property holds. - * It's a min heap so parent < child must be true. If the parent is bigger, - * swap it with the smallest child. - */ - for (;;) { - smallest = child; - if (child->left != NULL && less_than(child->left, smallest)) - smallest = child->left; - if (child->right != NULL && less_than(child->right, smallest)) - smallest = child->right; - if (smallest == child) - break; - heap_node_swap(heap, child, smallest); - } - - /* Walk up the subtree and check that each parent is less than the node - * this is required, because `max` node is not guaranteed to be the - * actual maximum in tree - */ - while (child->parent != NULL && less_than(child, child->parent)) - heap_node_swap(heap, child->parent, child); -} - -HEAP_EXPORT(void heap_dequeue(struct heap* heap, heap_compare_fn less_than)) { - heap_remove(heap, heap->min, less_than); -} - -#undef HEAP_EXPORT - -#endif /* UV_SRC_HEAP_H_ */ diff --git a/vendor/libuv/src/inet.c b/vendor/libuv/src/inet.c deleted file mode 100644 index da63a688c..000000000 --- a/vendor/libuv/src/inet.c +++ /dev/null @@ -1,309 +0,0 @@ -/* - * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") - * Copyright (c) 1996-1999 by Internet Software Consortium. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include - -#if defined(_MSC_VER) && _MSC_VER < 1600 -# include "stdint-msvc2008.h" -#else -# include -#endif - -#include "uv.h" -#include "uv-common.h" - -#define UV__INET_ADDRSTRLEN 16 -#define UV__INET6_ADDRSTRLEN 46 - - -static int inet_ntop4(const unsigned char *src, char *dst, size_t size); -static int inet_ntop6(const unsigned char *src, char *dst, size_t size); -static int inet_pton4(const char *src, unsigned char *dst); -static int inet_pton6(const char *src, unsigned char *dst); - - -int uv_inet_ntop(int af, const void* src, char* dst, size_t size) { - switch (af) { - case AF_INET: - return (inet_ntop4(src, dst, size)); - case AF_INET6: - return (inet_ntop6(src, dst, size)); - default: - return UV_EAFNOSUPPORT; - } - /* NOTREACHED */ -} - - -static int inet_ntop4(const unsigned char *src, char *dst, size_t size) { - static const char fmt[] = "%u.%u.%u.%u"; - char tmp[UV__INET_ADDRSTRLEN]; - int l; - - l = snprintf(tmp, sizeof(tmp), fmt, src[0], src[1], src[2], src[3]); - if (l <= 0 || (size_t) l >= size) { - return UV_ENOSPC; - } - strncpy(dst, tmp, size); - dst[size - 1] = '\0'; - return 0; -} - - -static int inet_ntop6(const unsigned char *src, char *dst, size_t size) { - /* - * Note that int32_t and int16_t need only be "at least" large enough - * to contain a value of the specified size. On some systems, like - * Crays, there is no such thing as an integer variable with 16 bits. - * Keep this in mind if you think this function should have been coded - * to use pointer overlays. All the world's not a VAX. - */ - char tmp[UV__INET6_ADDRSTRLEN], *tp; - struct { int base, len; } best, cur; - unsigned int words[sizeof(struct in6_addr) / sizeof(uint16_t)]; - int i; - - /* - * Preprocess: - * Copy the input (bytewise) array into a wordwise array. - * Find the longest run of 0x00's in src[] for :: shorthanding. - */ - memset(words, '\0', sizeof words); - for (i = 0; i < (int) sizeof(struct in6_addr); i++) - words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3)); - best.base = -1; - best.len = 0; - cur.base = -1; - cur.len = 0; - for (i = 0; i < (int) ARRAY_SIZE(words); i++) { - if (words[i] == 0) { - if (cur.base == -1) - cur.base = i, cur.len = 1; - else - cur.len++; - } else { - if (cur.base != -1) { - if (best.base == -1 || cur.len > best.len) - best = cur; - cur.base = -1; - } - } - } - if (cur.base != -1) { - if (best.base == -1 || cur.len > best.len) - best = cur; - } - if (best.base != -1 && best.len < 2) - best.base = -1; - - /* - * Format the result. - */ - tp = tmp; - for (i = 0; i < (int) ARRAY_SIZE(words); i++) { - /* Are we inside the best run of 0x00's? */ - if (best.base != -1 && i >= best.base && - i < (best.base + best.len)) { - if (i == best.base) - *tp++ = ':'; - continue; - } - /* Are we following an initial run of 0x00s or any real hex? */ - if (i != 0) - *tp++ = ':'; - /* Is this address an encapsulated IPv4? */ - if (i == 6 && best.base == 0 && (best.len == 6 || - (best.len == 7 && words[7] != 0x0001) || - (best.len == 5 && words[5] == 0xffff))) { - int err = inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp)); - if (err) - return err; - tp += strlen(tp); - break; - } - tp += sprintf(tp, "%x", words[i]); - } - /* Was it a trailing run of 0x00's? */ - if (best.base != -1 && (best.base + best.len) == ARRAY_SIZE(words)) - *tp++ = ':'; - *tp++ = '\0'; - - /* - * Check for overflow, copy, and we're done. - */ - if ((size_t)(tp - tmp) > size) { - return UV_ENOSPC; - } - strcpy(dst, tmp); - return 0; -} - - -int uv_inet_pton(int af, const char* src, void* dst) { - if (src == NULL || dst == NULL) - return UV_EINVAL; - - switch (af) { - case AF_INET: - return (inet_pton4(src, dst)); - case AF_INET6: { - int len; - char tmp[UV__INET6_ADDRSTRLEN], *s, *p; - s = (char*) src; - p = strchr(src, '%'); - if (p != NULL) { - s = tmp; - len = p - src; - if (len > UV__INET6_ADDRSTRLEN-1) - return UV_EINVAL; - memcpy(s, src, len); - s[len] = '\0'; - } - return inet_pton6(s, dst); - } - default: - return UV_EAFNOSUPPORT; - } - /* NOTREACHED */ -} - - -static int inet_pton4(const char *src, unsigned char *dst) { - static const char digits[] = "0123456789"; - int saw_digit, octets, ch; - unsigned char tmp[sizeof(struct in_addr)], *tp; - - saw_digit = 0; - octets = 0; - *(tp = tmp) = 0; - while ((ch = *src++) != '\0') { - const char *pch; - - if ((pch = strchr(digits, ch)) != NULL) { - unsigned int nw = *tp * 10 + (pch - digits); - - if (saw_digit && *tp == 0) - return UV_EINVAL; - if (nw > 255) - return UV_EINVAL; - *tp = nw; - if (!saw_digit) { - if (++octets > 4) - return UV_EINVAL; - saw_digit = 1; - } - } else if (ch == '.' && saw_digit) { - if (octets == 4) - return UV_EINVAL; - *++tp = 0; - saw_digit = 0; - } else - return UV_EINVAL; - } - if (octets < 4) - return UV_EINVAL; - memcpy(dst, tmp, sizeof(struct in_addr)); - return 0; -} - - -static int inet_pton6(const char *src, unsigned char *dst) { - static const char xdigits_l[] = "0123456789abcdef", - xdigits_u[] = "0123456789ABCDEF"; - unsigned char tmp[sizeof(struct in6_addr)], *tp, *endp, *colonp; - const char *xdigits, *curtok; - int ch, seen_xdigits; - unsigned int val; - - memset((tp = tmp), '\0', sizeof tmp); - endp = tp + sizeof tmp; - colonp = NULL; - /* Leading :: requires some special handling. */ - if (*src == ':') - if (*++src != ':') - return UV_EINVAL; - curtok = src; - seen_xdigits = 0; - val = 0; - while ((ch = *src++) != '\0') { - const char *pch; - - if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL) - pch = strchr((xdigits = xdigits_u), ch); - if (pch != NULL) { - val <<= 4; - val |= (pch - xdigits); - if (++seen_xdigits > 4) - return UV_EINVAL; - continue; - } - if (ch == ':') { - curtok = src; - if (!seen_xdigits) { - if (colonp) - return UV_EINVAL; - colonp = tp; - continue; - } else if (*src == '\0') { - return UV_EINVAL; - } - if (tp + sizeof(uint16_t) > endp) - return UV_EINVAL; - *tp++ = (unsigned char) (val >> 8) & 0xff; - *tp++ = (unsigned char) val & 0xff; - seen_xdigits = 0; - val = 0; - continue; - } - if (ch == '.' && ((tp + sizeof(struct in_addr)) <= endp)) { - int err = inet_pton4(curtok, tp); - if (err == 0) { - tp += sizeof(struct in_addr); - seen_xdigits = 0; - break; /*%< '\\0' was seen by inet_pton4(). */ - } - } - return UV_EINVAL; - } - if (seen_xdigits) { - if (tp + sizeof(uint16_t) > endp) - return UV_EINVAL; - *tp++ = (unsigned char) (val >> 8) & 0xff; - *tp++ = (unsigned char) val & 0xff; - } - if (colonp != NULL) { - /* - * Since some memmove()'s erroneously fail to handle - * overlapping regions, we'll do the shift by hand. - */ - const int n = tp - colonp; - int i; - - if (tp == endp) - return UV_EINVAL; - for (i = 1; i <= n; i++) { - endp[- i] = colonp[n - i]; - colonp[n - i] = 0; - } - tp = endp; - } - if (tp != endp) - return UV_EINVAL; - memcpy(dst, tmp, sizeof tmp); - return 0; -} diff --git a/vendor/libuv/src/queue.h b/vendor/libuv/src/queue.h deleted file mode 100644 index ff3540a0a..000000000 --- a/vendor/libuv/src/queue.h +++ /dev/null @@ -1,108 +0,0 @@ -/* Copyright (c) 2013, Ben Noordhuis - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef QUEUE_H_ -#define QUEUE_H_ - -#include - -typedef void *QUEUE[2]; - -/* Private macros. */ -#define QUEUE_NEXT(q) (*(QUEUE **) &((*(q))[0])) -#define QUEUE_PREV(q) (*(QUEUE **) &((*(q))[1])) -#define QUEUE_PREV_NEXT(q) (QUEUE_NEXT(QUEUE_PREV(q))) -#define QUEUE_NEXT_PREV(q) (QUEUE_PREV(QUEUE_NEXT(q))) - -/* Public macros. */ -#define QUEUE_DATA(ptr, type, field) \ - ((type *) ((char *) (ptr) - offsetof(type, field))) - -/* Important note: mutating the list while QUEUE_FOREACH is - * iterating over its elements results in undefined behavior. - */ -#define QUEUE_FOREACH(q, h) \ - for ((q) = QUEUE_NEXT(h); (q) != (h); (q) = QUEUE_NEXT(q)) - -#define QUEUE_EMPTY(q) \ - ((const QUEUE *) (q) == (const QUEUE *) QUEUE_NEXT(q)) - -#define QUEUE_HEAD(q) \ - (QUEUE_NEXT(q)) - -#define QUEUE_INIT(q) \ - do { \ - QUEUE_NEXT(q) = (q); \ - QUEUE_PREV(q) = (q); \ - } \ - while (0) - -#define QUEUE_ADD(h, n) \ - do { \ - QUEUE_PREV_NEXT(h) = QUEUE_NEXT(n); \ - QUEUE_NEXT_PREV(n) = QUEUE_PREV(h); \ - QUEUE_PREV(h) = QUEUE_PREV(n); \ - QUEUE_PREV_NEXT(h) = (h); \ - } \ - while (0) - -#define QUEUE_SPLIT(h, q, n) \ - do { \ - QUEUE_PREV(n) = QUEUE_PREV(h); \ - QUEUE_PREV_NEXT(n) = (n); \ - QUEUE_NEXT(n) = (q); \ - QUEUE_PREV(h) = QUEUE_PREV(q); \ - QUEUE_PREV_NEXT(h) = (h); \ - QUEUE_PREV(q) = (n); \ - } \ - while (0) - -#define QUEUE_MOVE(h, n) \ - do { \ - if (QUEUE_EMPTY(h)) \ - QUEUE_INIT(n); \ - else { \ - QUEUE* q = QUEUE_HEAD(h); \ - QUEUE_SPLIT(h, q, n); \ - } \ - } \ - while (0) - -#define QUEUE_INSERT_HEAD(h, q) \ - do { \ - QUEUE_NEXT(q) = QUEUE_NEXT(h); \ - QUEUE_PREV(q) = (h); \ - QUEUE_NEXT_PREV(q) = (q); \ - QUEUE_NEXT(h) = (q); \ - } \ - while (0) - -#define QUEUE_INSERT_TAIL(h, q) \ - do { \ - QUEUE_NEXT(q) = (h); \ - QUEUE_PREV(q) = QUEUE_PREV(h); \ - QUEUE_PREV_NEXT(q) = (q); \ - QUEUE_PREV(h) = (q); \ - } \ - while (0) - -#define QUEUE_REMOVE(q) \ - do { \ - QUEUE_PREV_NEXT(q) = QUEUE_NEXT(q); \ - QUEUE_NEXT_PREV(q) = QUEUE_PREV(q); \ - } \ - while (0) - -#endif /* QUEUE_H_ */ diff --git a/vendor/libuv/src/threadpool.c b/vendor/libuv/src/threadpool.c deleted file mode 100644 index 2c5152b42..000000000 --- a/vendor/libuv/src/threadpool.c +++ /dev/null @@ -1,303 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv-common.h" - -#if !defined(_WIN32) -# include "unix/internal.h" -#else -# include "win/req-inl.h" -/* TODO(saghul): unify internal req functions */ -static void uv__req_init(uv_loop_t* loop, - uv_req_t* req, - uv_req_type type) { - uv_req_init(loop, req); - req->type = type; - uv__req_register(loop, req); -} -# define uv__req_init(loop, req, type) \ - uv__req_init((loop), (uv_req_t*)(req), (type)) -#endif - -#include - -#define MAX_THREADPOOL_SIZE 128 - -static uv_once_t once = UV_ONCE_INIT; -static uv_cond_t cond; -static uv_mutex_t mutex; -static unsigned int idle_threads; -static unsigned int nthreads; -static uv_thread_t* threads; -static uv_thread_t default_threads[4]; -static QUEUE exit_message; -static QUEUE wq; -static volatile int initialized; - - -static void uv__cancelled(struct uv__work* w) { - abort(); -} - - -/* To avoid deadlock with uv_cancel() it's crucial that the worker - * never holds the global mutex and the loop-local mutex at the same time. - */ -static void worker(void* arg) { - struct uv__work* w; - QUEUE* q; - - (void) arg; - - for (;;) { - uv_mutex_lock(&mutex); - - while (QUEUE_EMPTY(&wq)) { - idle_threads += 1; - uv_cond_wait(&cond, &mutex); - idle_threads -= 1; - } - - q = QUEUE_HEAD(&wq); - - if (q == &exit_message) - uv_cond_signal(&cond); - else { - QUEUE_REMOVE(q); - QUEUE_INIT(q); /* Signal uv_cancel() that the work req is - executing. */ - } - - uv_mutex_unlock(&mutex); - - if (q == &exit_message) - break; - - w = QUEUE_DATA(q, struct uv__work, wq); - w->work(w); - - uv_mutex_lock(&w->loop->wq_mutex); - w->work = NULL; /* Signal uv_cancel() that the work req is done - executing. */ - QUEUE_INSERT_TAIL(&w->loop->wq, &w->wq); - uv_async_send(&w->loop->wq_async); - uv_mutex_unlock(&w->loop->wq_mutex); - } -} - - -static void post(QUEUE* q) { - uv_mutex_lock(&mutex); - QUEUE_INSERT_TAIL(&wq, q); - if (idle_threads > 0) - uv_cond_signal(&cond); - uv_mutex_unlock(&mutex); -} - - -#ifndef _WIN32 -UV_DESTRUCTOR(static void cleanup(void)) { - unsigned int i; - - if (initialized == 0) - return; - - post(&exit_message); - - for (i = 0; i < nthreads; i++) - if (uv_thread_join(threads + i)) - abort(); - - if (threads != default_threads) - uv__free(threads); - - uv_mutex_destroy(&mutex); - uv_cond_destroy(&cond); - - threads = NULL; - nthreads = 0; - initialized = 0; -} -#endif - - -static void init_once(void) { - unsigned int i; - const char* val; - - nthreads = ARRAY_SIZE(default_threads); - val = getenv("UV_THREADPOOL_SIZE"); - if (val != NULL) - nthreads = atoi(val); - if (nthreads == 0) - nthreads = 1; - if (nthreads > MAX_THREADPOOL_SIZE) - nthreads = MAX_THREADPOOL_SIZE; - - threads = default_threads; - if (nthreads > ARRAY_SIZE(default_threads)) { - threads = uv__malloc(nthreads * sizeof(threads[0])); - if (threads == NULL) { - nthreads = ARRAY_SIZE(default_threads); - threads = default_threads; - } - } - - if (uv_cond_init(&cond)) - abort(); - - if (uv_mutex_init(&mutex)) - abort(); - - QUEUE_INIT(&wq); - - for (i = 0; i < nthreads; i++) - if (uv_thread_create(threads + i, worker, NULL)) - abort(); - - initialized = 1; -} - - -void uv__work_submit(uv_loop_t* loop, - struct uv__work* w, - void (*work)(struct uv__work* w), - void (*done)(struct uv__work* w, int status)) { - uv_once(&once, init_once); - w->loop = loop; - w->work = work; - w->done = done; - post(&w->wq); -} - - -static int uv__work_cancel(uv_loop_t* loop, uv_req_t* req, struct uv__work* w) { - int cancelled; - - uv_mutex_lock(&mutex); - uv_mutex_lock(&w->loop->wq_mutex); - - cancelled = !QUEUE_EMPTY(&w->wq) && w->work != NULL; - if (cancelled) - QUEUE_REMOVE(&w->wq); - - uv_mutex_unlock(&w->loop->wq_mutex); - uv_mutex_unlock(&mutex); - - if (!cancelled) - return UV_EBUSY; - - w->work = uv__cancelled; - uv_mutex_lock(&loop->wq_mutex); - QUEUE_INSERT_TAIL(&loop->wq, &w->wq); - uv_async_send(&loop->wq_async); - uv_mutex_unlock(&loop->wq_mutex); - - return 0; -} - - -void uv__work_done(uv_async_t* handle) { - struct uv__work* w; - uv_loop_t* loop; - QUEUE* q; - QUEUE wq; - int err; - - loop = container_of(handle, uv_loop_t, wq_async); - uv_mutex_lock(&loop->wq_mutex); - QUEUE_MOVE(&loop->wq, &wq); - uv_mutex_unlock(&loop->wq_mutex); - - while (!QUEUE_EMPTY(&wq)) { - q = QUEUE_HEAD(&wq); - QUEUE_REMOVE(q); - - w = container_of(q, struct uv__work, wq); - err = (w->work == uv__cancelled) ? UV_ECANCELED : 0; - w->done(w, err); - } -} - - -static void uv__queue_work(struct uv__work* w) { - uv_work_t* req = container_of(w, uv_work_t, work_req); - - req->work_cb(req); -} - - -static void uv__queue_done(struct uv__work* w, int err) { - uv_work_t* req; - - req = container_of(w, uv_work_t, work_req); - uv__req_unregister(req->loop, req); - - if (req->after_work_cb == NULL) - return; - - req->after_work_cb(req, err); -} - - -int uv_queue_work(uv_loop_t* loop, - uv_work_t* req, - uv_work_cb work_cb, - uv_after_work_cb after_work_cb) { - if (work_cb == NULL) - return UV_EINVAL; - - uv__req_init(loop, req, UV_WORK); - req->loop = loop; - req->work_cb = work_cb; - req->after_work_cb = after_work_cb; - uv__work_submit(loop, &req->work_req, uv__queue_work, uv__queue_done); - return 0; -} - - -int uv_cancel(uv_req_t* req) { - struct uv__work* wreq; - uv_loop_t* loop; - - switch (req->type) { - case UV_FS: - loop = ((uv_fs_t*) req)->loop; - wreq = &((uv_fs_t*) req)->work_req; - break; - case UV_GETADDRINFO: - loop = ((uv_getaddrinfo_t*) req)->loop; - wreq = &((uv_getaddrinfo_t*) req)->work_req; - break; - case UV_GETNAMEINFO: - loop = ((uv_getnameinfo_t*) req)->loop; - wreq = &((uv_getnameinfo_t*) req)->work_req; - break; - case UV_WORK: - loop = ((uv_work_t*) req)->loop; - wreq = &((uv_work_t*) req)->work_req; - break; - default: - return UV_EINVAL; - } - - return uv__work_cancel(loop, req, wreq); -} diff --git a/vendor/libuv/src/unix/aix.c b/vendor/libuv/src/unix/aix.c deleted file mode 100644 index 1d2cd4a80..000000000 --- a/vendor/libuv/src/unix/aix.c +++ /dev/null @@ -1,1236 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "internal.h" - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - -#include -#include -#ifdef HAVE_SYS_AHAFS_EVPRODS_H -#include -#endif - -#include -#include -#include -#include -#include - -#define RDWR_BUF_SIZE 4096 -#define EQ(a,b) (strcmp(a,b) == 0) - -static void* args_mem = NULL; -static char** process_argv = NULL; -static int process_argc = 0; -static char* process_title_ptr = NULL; - -int uv__platform_loop_init(uv_loop_t* loop) { - loop->fs_fd = -1; - - /* Passing maxfd of -1 should mean the limit is determined - * by the user's ulimit or the global limit as per the doc */ - loop->backend_fd = pollset_create(-1); - - if (loop->backend_fd == -1) - return -1; - - return 0; -} - - -void uv__platform_loop_delete(uv_loop_t* loop) { - if (loop->fs_fd != -1) { - uv__close(loop->fs_fd); - loop->fs_fd = -1; - } - - if (loop->backend_fd != -1) { - pollset_destroy(loop->backend_fd); - loop->backend_fd = -1; - } -} - - -int uv__io_check_fd(uv_loop_t* loop, int fd) { - struct poll_ctl pc; - - pc.events = POLLIN; - pc.cmd = PS_MOD; /* Equivalent to PS_ADD if the fd is not in the pollset. */ - pc.fd = fd; - - if (pollset_ctl(loop->backend_fd, &pc, 1)) - return -errno; - - pc.cmd = PS_DELETE; - if (pollset_ctl(loop->backend_fd, &pc, 1)) - abort(); - - return 0; -} - - -void uv__io_poll(uv_loop_t* loop, int timeout) { - struct pollfd events[1024]; - struct pollfd pqry; - struct pollfd* pe; - struct poll_ctl pc; - QUEUE* q; - uv__io_t* w; - uint64_t base; - uint64_t diff; - int have_signals; - int nevents; - int count; - int nfds; - int i; - int rc; - int add_failed; - - if (loop->nfds == 0) { - assert(QUEUE_EMPTY(&loop->watcher_queue)); - return; - } - - while (!QUEUE_EMPTY(&loop->watcher_queue)) { - q = QUEUE_HEAD(&loop->watcher_queue); - QUEUE_REMOVE(q); - QUEUE_INIT(q); - - w = QUEUE_DATA(q, uv__io_t, watcher_queue); - assert(w->pevents != 0); - assert(w->fd >= 0); - assert(w->fd < (int) loop->nwatchers); - - pc.events = w->pevents; - pc.fd = w->fd; - - add_failed = 0; - if (w->events == 0) { - pc.cmd = PS_ADD; - if (pollset_ctl(loop->backend_fd, &pc, 1)) { - if (errno != EINVAL) { - assert(0 && "Failed to add file descriptor (pc.fd) to pollset"); - abort(); - } - /* Check if the fd is already in the pollset */ - pqry.fd = pc.fd; - rc = pollset_query(loop->backend_fd, &pqry); - switch (rc) { - case -1: - assert(0 && "Failed to query pollset for file descriptor"); - abort(); - case 0: - assert(0 && "Pollset does not contain file descriptor"); - abort(); - } - /* If we got here then the pollset already contained the file descriptor even though - * we didn't think it should. This probably shouldn't happen, but we can continue. */ - add_failed = 1; - } - } - if (w->events != 0 || add_failed) { - /* Modify, potentially removing events -- need to delete then add. - * Could maybe mod if we knew for sure no events are removed, but - * content of w->events is handled above as not reliable (falls back) - * so may require a pollset_query() which would have to be pretty cheap - * compared to a PS_DELETE to be worth optimizing. Alternatively, could - * lazily remove events, squelching them in the mean time. */ - pc.cmd = PS_DELETE; - if (pollset_ctl(loop->backend_fd, &pc, 1)) { - assert(0 && "Failed to delete file descriptor (pc.fd) from pollset"); - abort(); - } - pc.cmd = PS_ADD; - if (pollset_ctl(loop->backend_fd, &pc, 1)) { - assert(0 && "Failed to add file descriptor (pc.fd) to pollset"); - abort(); - } - } - - w->events = w->pevents; - } - - assert(timeout >= -1); - base = loop->time; - count = 48; /* Benchmarks suggest this gives the best throughput. */ - - for (;;) { - nfds = pollset_poll(loop->backend_fd, - events, - ARRAY_SIZE(events), - timeout); - - /* Update loop->time unconditionally. It's tempting to skip the update when - * timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the - * operating system didn't reschedule our process while in the syscall. - */ - SAVE_ERRNO(uv__update_time(loop)); - - if (nfds == 0) { - assert(timeout != -1); - return; - } - - if (nfds == -1) { - if (errno != EINTR) { - abort(); - } - - if (timeout == -1) - continue; - - if (timeout == 0) - return; - - /* Interrupted by a signal. Update timeout and poll again. */ - goto update_timeout; - } - - have_signals = 0; - nevents = 0; - - assert(loop->watchers != NULL); - loop->watchers[loop->nwatchers] = (void*) events; - loop->watchers[loop->nwatchers + 1] = (void*) (uintptr_t) nfds; - - for (i = 0; i < nfds; i++) { - pe = events + i; - pc.cmd = PS_DELETE; - pc.fd = pe->fd; - - /* Skip invalidated events, see uv__platform_invalidate_fd */ - if (pc.fd == -1) - continue; - - assert(pc.fd >= 0); - assert((unsigned) pc.fd < loop->nwatchers); - - w = loop->watchers[pc.fd]; - - if (w == NULL) { - /* File descriptor that we've stopped watching, disarm it. - * - * Ignore all errors because we may be racing with another thread - * when the file descriptor is closed. - */ - pollset_ctl(loop->backend_fd, &pc, 1); - continue; - } - - /* Run signal watchers last. This also affects child process watchers - * because those are implemented in terms of signal watchers. - */ - if (w == &loop->signal_io_watcher) - have_signals = 1; - else - w->cb(loop, w, pe->revents); - - nevents++; - } - - if (have_signals != 0) - loop->signal_io_watcher.cb(loop, &loop->signal_io_watcher, POLLIN); - - loop->watchers[loop->nwatchers] = NULL; - loop->watchers[loop->nwatchers + 1] = NULL; - - if (have_signals != 0) - return; /* Event loop should cycle now so don't poll again. */ - - if (nevents != 0) { - if (nfds == ARRAY_SIZE(events) && --count != 0) { - /* Poll for more events but don't block this time. */ - timeout = 0; - continue; - } - return; - } - - if (timeout == 0) - return; - - if (timeout == -1) - continue; - -update_timeout: - assert(timeout > 0); - - diff = loop->time - base; - if (diff >= (uint64_t) timeout) - return; - - timeout -= diff; - } -} - - -uint64_t uv__hrtime(uv_clocktype_t type) { - uint64_t G = 1000000000; - timebasestruct_t t; - read_wall_time(&t, TIMEBASE_SZ); - time_base_to_time(&t, TIMEBASE_SZ); - return (uint64_t) t.tb_high * G + t.tb_low; -} - - -/* - * We could use a static buffer for the path manipulations that we need outside - * of the function, but this function could be called by multiple consumers and - * we don't want to potentially create a race condition in the use of snprintf. - * There is no direct way of getting the exe path in AIX - either through /procfs - * or through some libc APIs. The below approach is to parse the argv[0]'s pattern - * and use it in conjunction with PATH environment variable to craft one. - */ -int uv_exepath(char* buffer, size_t* size) { - int res; - char args[PATH_MAX]; - char abspath[PATH_MAX]; - size_t abspath_size; - struct procsinfo pi; - - if (buffer == NULL || size == NULL || *size == 0) - return -EINVAL; - - pi.pi_pid = getpid(); - res = getargs(&pi, sizeof(pi), args, sizeof(args)); - if (res < 0) - return -EINVAL; - - /* - * Possibilities for args: - * i) an absolute path such as: /home/user/myprojects/nodejs/node - * ii) a relative path such as: ./node or ../myprojects/nodejs/node - * iii) a bare filename such as "node", after exporting PATH variable - * to its location. - */ - - /* Case i) and ii) absolute or relative paths */ - if (strchr(args, '/') != NULL) { - if (realpath(args, abspath) != abspath) - return -errno; - - abspath_size = strlen(abspath); - - *size -= 1; - if (*size > abspath_size) - *size = abspath_size; - - memcpy(buffer, abspath, *size); - buffer[*size] = '\0'; - - return 0; - } else { - /* Case iii). Search PATH environment variable */ - char trypath[PATH_MAX]; - char *clonedpath = NULL; - char *token = NULL; - char *path = getenv("PATH"); - - if (path == NULL) - return -EINVAL; - - clonedpath = uv__strdup(path); - if (clonedpath == NULL) - return -ENOMEM; - - token = strtok(clonedpath, ":"); - while (token != NULL) { - snprintf(trypath, sizeof(trypath) - 1, "%s/%s", token, args); - if (realpath(trypath, abspath) == abspath) { - /* Check the match is executable */ - if (access(abspath, X_OK) == 0) { - abspath_size = strlen(abspath); - - *size -= 1; - if (*size > abspath_size) - *size = abspath_size; - - memcpy(buffer, abspath, *size); - buffer[*size] = '\0'; - - uv__free(clonedpath); - return 0; - } - } - token = strtok(NULL, ":"); - } - uv__free(clonedpath); - - /* Out of tokens (path entries), and no match found */ - return -EINVAL; - } -} - - -uint64_t uv_get_free_memory(void) { - perfstat_memory_total_t mem_total; - int result = perfstat_memory_total(NULL, &mem_total, sizeof(mem_total), 1); - if (result == -1) { - return 0; - } - return mem_total.real_free * 4096; -} - - -uint64_t uv_get_total_memory(void) { - perfstat_memory_total_t mem_total; - int result = perfstat_memory_total(NULL, &mem_total, sizeof(mem_total), 1); - if (result == -1) { - return 0; - } - return mem_total.real_total * 4096; -} - - -void uv_loadavg(double avg[3]) { - perfstat_cpu_total_t ps_total; - int result = perfstat_cpu_total(NULL, &ps_total, sizeof(ps_total), 1); - if (result == -1) { - avg[0] = 0.; avg[1] = 0.; avg[2] = 0.; - return; - } - avg[0] = ps_total.loadavg[0] / (double)(1 << SBITS); - avg[1] = ps_total.loadavg[1] / (double)(1 << SBITS); - avg[2] = ps_total.loadavg[2] / (double)(1 << SBITS); -} - - -#ifdef HAVE_SYS_AHAFS_EVPRODS_H -static char *uv__rawname(char *cp) { - static char rawbuf[FILENAME_MAX+1]; - char *dp = rindex(cp, '/'); - - if (dp == 0) - return 0; - - *dp = 0; - strcpy(rawbuf, cp); - *dp = '/'; - strcat(rawbuf, "/r"); - strcat(rawbuf, dp+1); - return rawbuf; -} - - -/* - * Determine whether given pathname is a directory - * Returns 0 if the path is a directory, -1 if not - * - * Note: Opportunity here for more detailed error information but - * that requires changing callers of this function as well - */ -static int uv__path_is_a_directory(char* filename) { - struct stat statbuf; - - if (stat(filename, &statbuf) < 0) - return -1; /* failed: not a directory, assume it is a file */ - - if (statbuf.st_type == VDIR) - return 0; - - return -1; -} - - -/* - * Check whether AHAFS is mounted. - * Returns 0 if AHAFS is mounted, or an error code < 0 on failure - */ -static int uv__is_ahafs_mounted(void){ - int rv, i = 2; - struct vmount *p; - int size_multiplier = 10; - size_t siz = sizeof(struct vmount)*size_multiplier; - struct vmount *vmt; - const char *dev = "/aha"; - char *obj, *stub; - - p = uv__malloc(siz); - if (p == NULL) - return -errno; - - /* Retrieve all mounted filesystems */ - rv = mntctl(MCTL_QUERY, siz, (char*)p); - if (rv < 0) - return -errno; - if (rv == 0) { - /* buffer was not large enough, reallocate to correct size */ - siz = *(int*)p; - uv__free(p); - p = uv__malloc(siz); - if (p == NULL) - return -errno; - rv = mntctl(MCTL_QUERY, siz, (char*)p); - if (rv < 0) - return -errno; - } - - /* Look for dev in filesystems mount info */ - for(vmt = p, i = 0; i < rv; i++) { - obj = vmt2dataptr(vmt, VMT_OBJECT); /* device */ - stub = vmt2dataptr(vmt, VMT_STUB); /* mount point */ - - if (EQ(obj, dev) || EQ(uv__rawname(obj), dev) || EQ(stub, dev)) { - uv__free(p); /* Found a match */ - return 0; - } - vmt = (struct vmount *) ((char *) vmt + vmt->vmt_length); - } - - /* /aha is required for monitoring filesystem changes */ - return -1; -} - -/* - * Recursive call to mkdir() to create intermediate folders, if any - * Returns code from mkdir call - */ -static int uv__makedir_p(const char *dir) { - char tmp[256]; - char *p = NULL; - size_t len; - int err; - - snprintf(tmp, sizeof(tmp),"%s",dir); - len = strlen(tmp); - if (tmp[len - 1] == '/') - tmp[len - 1] = 0; - for (p = tmp + 1; *p; p++) { - if (*p == '/') { - *p = 0; - err = mkdir(tmp, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); - if (err != 0 && errno != EEXIST) - return err; - *p = '/'; - } - } - return mkdir(tmp, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); -} - -/* - * Creates necessary subdirectories in the AIX Event Infrastructure - * file system for monitoring the object specified. - * Returns code from mkdir call - */ -static int uv__make_subdirs_p(const char *filename) { - char cmd[2048]; - char *p; - int rc = 0; - - /* Strip off the monitor file name */ - p = strrchr(filename, '/'); - - if (p == NULL) - return 0; - - if (uv__path_is_a_directory((char*)filename) == 0) { - sprintf(cmd, "/aha/fs/modDir.monFactory"); - } else { - sprintf(cmd, "/aha/fs/modFile.monFactory"); - } - - strncat(cmd, filename, (p - filename)); - rc = uv__makedir_p(cmd); - - if (rc == -1 && errno != EEXIST){ - return -errno; - } - - return rc; -} - - -/* - * Checks if /aha is mounted, then proceeds to set up the monitoring - * objects for the specified file. - * Returns 0 on success, or an error code < 0 on failure - */ -static int uv__setup_ahafs(const char* filename, int *fd) { - int rc = 0; - char mon_file_write_string[RDWR_BUF_SIZE]; - char mon_file[PATH_MAX]; - int file_is_directory = 0; /* -1 == NO, 0 == YES */ - - /* Create monitor file name for object */ - file_is_directory = uv__path_is_a_directory((char*)filename); - - if (file_is_directory == 0) - sprintf(mon_file, "/aha/fs/modDir.monFactory"); - else - sprintf(mon_file, "/aha/fs/modFile.monFactory"); - - if ((strlen(mon_file) + strlen(filename) + 5) > PATH_MAX) - return -ENAMETOOLONG; - - /* Make the necessary subdirectories for the monitor file */ - rc = uv__make_subdirs_p(filename); - if (rc == -1 && errno != EEXIST) - return rc; - - strcat(mon_file, filename); - strcat(mon_file, ".mon"); - - *fd = 0; errno = 0; - - /* Open the monitor file, creating it if necessary */ - *fd = open(mon_file, O_CREAT|O_RDWR); - if (*fd < 0) - return -errno; - - /* Write out the monitoring specifications. - * In this case, we are monitoring for a state change event type - * CHANGED=YES - * We will be waiting in select call, rather than a read: - * WAIT_TYPE=WAIT_IN_SELECT - * We only want minimal information for files: - * INFO_LVL=1 - * For directories, we want more information to track what file - * caused the change - * INFO_LVL=2 - */ - - if (file_is_directory == 0) - sprintf(mon_file_write_string, "CHANGED=YES;WAIT_TYPE=WAIT_IN_SELECT;INFO_LVL=2"); - else - sprintf(mon_file_write_string, "CHANGED=YES;WAIT_TYPE=WAIT_IN_SELECT;INFO_LVL=1"); - - rc = write(*fd, mon_file_write_string, strlen(mon_file_write_string)+1); - if (rc < 0) - return -errno; - - return 0; -} - -/* - * Skips a specified number of lines in the buffer passed in. - * Walks the buffer pointed to by p and attempts to skip n lines. - * Returns the total number of lines skipped - */ -static int uv__skip_lines(char **p, int n) { - int lines = 0; - - while(n > 0) { - *p = strchr(*p, '\n'); - if (!p) - return lines; - - (*p)++; - n--; - lines++; - } - return lines; -} - - -/* - * Parse the event occurrence data to figure out what event just occurred - * and take proper action. - * - * The buf is a pointer to the buffer containing the event occurrence data - * Returns 0 on success, -1 if unrecoverable error in parsing - * - */ -static int uv__parse_data(char *buf, int *events, uv_fs_event_t* handle) { - int evp_rc, i; - char *p; - char filename[PATH_MAX]; /* To be used when handling directories */ - - p = buf; - *events = 0; - - /* Clean the filename buffer*/ - for(i = 0; i < PATH_MAX; i++) { - filename[i] = 0; - } - i = 0; - - /* Check for BUF_WRAP */ - if (strncmp(buf, "BUF_WRAP", strlen("BUF_WRAP")) == 0) { - assert(0 && "Buffer wrap detected, Some event occurrences lost!"); - return 0; - } - - /* Since we are using the default buffer size (4K), and have specified - * INFO_LVL=1, we won't see any EVENT_OVERFLOW conditions. Applications - * should check for this keyword if they are using an INFO_LVL of 2 or - * higher, and have a buffer size of <= 4K - */ - - /* Skip to RC_FROM_EVPROD */ - if (uv__skip_lines(&p, 9) != 9) - return -1; - - if (sscanf(p, "RC_FROM_EVPROD=%d\nEND_EVENT_DATA", &evp_rc) == 1) { - if (uv__path_is_a_directory(handle->path) == 0) { /* Directory */ - if (evp_rc == AHAFS_MODDIR_UNMOUNT || evp_rc == AHAFS_MODDIR_REMOVE_SELF) { - /* The directory is no longer available for monitoring */ - *events = UV_RENAME; - handle->dir_filename = NULL; - } else { - /* A file was added/removed inside the directory */ - *events = UV_CHANGE; - - /* Get the EVPROD_INFO */ - if (uv__skip_lines(&p, 1) != 1) - return -1; - - /* Scan out the name of the file that triggered the event*/ - if (sscanf(p, "BEGIN_EVPROD_INFO\n%sEND_EVPROD_INFO", filename) == 1) { - handle->dir_filename = uv__strdup((const char*)&filename); - } else - return -1; - } - } else { /* Regular File */ - if (evp_rc == AHAFS_MODFILE_RENAME) - *events = UV_RENAME; - else - *events = UV_CHANGE; - } - } - else - return -1; - - return 0; -} - - -/* This is the internal callback */ -static void uv__ahafs_event(uv_loop_t* loop, uv__io_t* event_watch, unsigned int fflags) { - char result_data[RDWR_BUF_SIZE]; - int bytes, rc = 0; - uv_fs_event_t* handle; - int events = 0; - char fname[PATH_MAX]; - char *p; - - handle = container_of(event_watch, uv_fs_event_t, event_watcher); - - /* At this point, we assume that polling has been done on the - * file descriptor, so we can just read the AHAFS event occurrence - * data and parse its results without having to block anything - */ - bytes = pread(event_watch->fd, result_data, RDWR_BUF_SIZE, 0); - - assert((bytes >= 0) && "uv__ahafs_event - Error reading monitor file"); - - /* In file / directory move cases, AIX Event infrastructure - * produces a second event with no data. - * Ignore it and return gracefully. - */ - if(bytes == 0) - return; - - /* Parse the data */ - if(bytes > 0) - rc = uv__parse_data(result_data, &events, handle); - - /* Unrecoverable error */ - if (rc == -1) - return; - - /* For directory changes, the name of the files that triggered the change - * are never absolute pathnames - */ - if (uv__path_is_a_directory(handle->path) == 0) { - p = handle->dir_filename; - } else { - p = strrchr(handle->path, '/'); - if (p == NULL) - p = handle->path; - else - p++; - } - strncpy(fname, p, sizeof(fname) - 1); - /* Just in case */ - fname[sizeof(fname) - 1] = '\0'; - - handle->cb(handle, fname, events, 0); -} -#endif - - -int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) { -#ifdef HAVE_SYS_AHAFS_EVPRODS_H - uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_EVENT); - return 0; -#else - return -ENOSYS; -#endif -} - - -int uv_fs_event_start(uv_fs_event_t* handle, - uv_fs_event_cb cb, - const char* filename, - unsigned int flags) { -#ifdef HAVE_SYS_AHAFS_EVPRODS_H - int fd, rc, str_offset = 0; - char cwd[PATH_MAX]; - char absolute_path[PATH_MAX]; - char readlink_cwd[PATH_MAX]; - - - /* Figure out whether filename is absolute or not */ - if (filename[0] == '/') { - /* We have absolute pathname */ - snprintf(absolute_path, sizeof(absolute_path), "%s", filename); - } else { - /* We have a relative pathname, compose the absolute pathname */ - snprintf(cwd, sizeof(cwd), "/proc/%lu/cwd", (unsigned long) getpid()); - rc = readlink(cwd, readlink_cwd, sizeof(readlink_cwd) - 1); - if (rc < 0) - return rc; - /* readlink does not null terminate our string */ - readlink_cwd[rc] = '\0'; - - if (filename[0] == '.' && filename[1] == '/') - str_offset = 2; - - snprintf(absolute_path, sizeof(absolute_path), "%s%s", readlink_cwd, - filename + str_offset); - } - - if (uv__is_ahafs_mounted() < 0) /* /aha checks failed */ - return UV_ENOSYS; - - /* Setup ahafs */ - rc = uv__setup_ahafs((const char *)absolute_path, &fd); - if (rc != 0) - return rc; - - /* Setup/Initialize all the libuv routines */ - uv__handle_start(handle); - uv__io_init(&handle->event_watcher, uv__ahafs_event, fd); - handle->path = uv__strdup(filename); - handle->cb = cb; - - uv__io_start(handle->loop, &handle->event_watcher, POLLIN); - - return 0; -#else - return -ENOSYS; -#endif -} - - -int uv_fs_event_stop(uv_fs_event_t* handle) { -#ifdef HAVE_SYS_AHAFS_EVPRODS_H - if (!uv__is_active(handle)) - return 0; - - uv__io_close(handle->loop, &handle->event_watcher); - uv__handle_stop(handle); - - if (uv__path_is_a_directory(handle->path) == 0) { - uv__free(handle->dir_filename); - handle->dir_filename = NULL; - } - - uv__free(handle->path); - handle->path = NULL; - uv__close(handle->event_watcher.fd); - handle->event_watcher.fd = -1; - - return 0; -#else - return -ENOSYS; -#endif -} - - -void uv__fs_event_close(uv_fs_event_t* handle) { -#ifdef HAVE_SYS_AHAFS_EVPRODS_H - uv_fs_event_stop(handle); -#else - UNREACHABLE(); -#endif -} - - -char** uv_setup_args(int argc, char** argv) { - char** new_argv; - size_t size; - char* s; - int i; - - if (argc <= 0) - return argv; - - /* Save the original pointer to argv. - * AIX uses argv to read the process name. - * (Not the memory pointed to by argv[0..n] as on Linux.) - */ - process_argv = argv; - process_argc = argc; - - /* Calculate how much memory we need for the argv strings. */ - size = 0; - for (i = 0; i < argc; i++) - size += strlen(argv[i]) + 1; - - /* Add space for the argv pointers. */ - size += (argc + 1) * sizeof(char*); - - new_argv = uv__malloc(size); - if (new_argv == NULL) - return argv; - args_mem = new_argv; - - /* Copy over the strings and set up the pointer table. */ - s = (char*) &new_argv[argc + 1]; - for (i = 0; i < argc; i++) { - size = strlen(argv[i]) + 1; - memcpy(s, argv[i], size); - new_argv[i] = s; - s += size; - } - new_argv[i] = NULL; - - return new_argv; -} - - -int uv_set_process_title(const char* title) { - char* new_title; - - /* We cannot free this pointer when libuv shuts down, - * the process may still be using it. - */ - new_title = uv__strdup(title); - if (new_title == NULL) - return -ENOMEM; - - /* If this is the first time this is set, - * don't free and set argv[1] to NULL. - */ - if (process_title_ptr != NULL) - uv__free(process_title_ptr); - - process_title_ptr = new_title; - - process_argv[0] = process_title_ptr; - if (process_argc > 1) - process_argv[1] = NULL; - - return 0; -} - - -int uv_get_process_title(char* buffer, size_t size) { - size_t len; - len = strlen(process_argv[0]); - if (buffer == NULL || size == 0) - return -EINVAL; - else if (size <= len) - return -ENOBUFS; - - memcpy(buffer, process_argv[0], len + 1); - - return 0; -} - - -UV_DESTRUCTOR(static void free_args_mem(void)) { - uv__free(args_mem); /* Keep valgrind happy. */ - args_mem = NULL; -} - - -int uv_resident_set_memory(size_t* rss) { - char pp[64]; - psinfo_t psinfo; - int err; - int fd; - - snprintf(pp, sizeof(pp), "/proc/%lu/psinfo", (unsigned long) getpid()); - - fd = open(pp, O_RDONLY); - if (fd == -1) - return -errno; - - /* FIXME(bnoordhuis) Handle EINTR. */ - err = -EINVAL; - if (read(fd, &psinfo, sizeof(psinfo)) == sizeof(psinfo)) { - *rss = (size_t)psinfo.pr_rssize * 1024; - err = 0; - } - uv__close(fd); - - return err; -} - - -int uv_uptime(double* uptime) { - struct utmp *utmp_buf; - size_t entries = 0; - time_t boot_time; - - utmpname(UTMP_FILE); - - setutent(); - - while ((utmp_buf = getutent()) != NULL) { - if (utmp_buf->ut_user[0] && utmp_buf->ut_type == USER_PROCESS) - ++entries; - if (utmp_buf->ut_type == BOOT_TIME) - boot_time = utmp_buf->ut_time; - } - - endutent(); - - if (boot_time == 0) - return -ENOSYS; - - *uptime = time(NULL) - boot_time; - return 0; -} - - -int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { - uv_cpu_info_t* cpu_info; - perfstat_cpu_total_t ps_total; - perfstat_cpu_t* ps_cpus; - perfstat_id_t cpu_id; - int result, ncpus, idx = 0; - - result = perfstat_cpu_total(NULL, &ps_total, sizeof(ps_total), 1); - if (result == -1) { - return -ENOSYS; - } - - ncpus = result = perfstat_cpu(NULL, NULL, sizeof(perfstat_cpu_t), 0); - if (result == -1) { - return -ENOSYS; - } - - ps_cpus = (perfstat_cpu_t*) uv__malloc(ncpus * sizeof(perfstat_cpu_t)); - if (!ps_cpus) { - return -ENOMEM; - } - - strcpy(cpu_id.name, FIRST_CPU); - result = perfstat_cpu(&cpu_id, ps_cpus, sizeof(perfstat_cpu_t), ncpus); - if (result == -1) { - uv__free(ps_cpus); - return -ENOSYS; - } - - *cpu_infos = (uv_cpu_info_t*) uv__malloc(ncpus * sizeof(uv_cpu_info_t)); - if (!*cpu_infos) { - uv__free(ps_cpus); - return -ENOMEM; - } - - *count = ncpus; - - cpu_info = *cpu_infos; - while (idx < ncpus) { - cpu_info->speed = (int)(ps_total.processorHZ / 1000000); - cpu_info->model = uv__strdup(ps_total.description); - cpu_info->cpu_times.user = ps_cpus[idx].user; - cpu_info->cpu_times.sys = ps_cpus[idx].sys; - cpu_info->cpu_times.idle = ps_cpus[idx].idle; - cpu_info->cpu_times.irq = ps_cpus[idx].wait; - cpu_info->cpu_times.nice = 0; - cpu_info++; - idx++; - } - - uv__free(ps_cpus); - return 0; -} - - -void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { - int i; - - for (i = 0; i < count; ++i) { - uv__free(cpu_infos[i].model); - } - - uv__free(cpu_infos); -} - - -int uv_interface_addresses(uv_interface_address_t** addresses, - int* count) { - uv_interface_address_t* address; - int sockfd, size = 1; - struct ifconf ifc; - struct ifreq *ifr, *p, flg; - - *count = 0; - - if (0 > (sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP))) { - return -errno; - } - - if (ioctl(sockfd, SIOCGSIZIFCONF, &size) == -1) { - uv__close(sockfd); - return -errno; - } - - ifc.ifc_req = (struct ifreq*)uv__malloc(size); - ifc.ifc_len = size; - if (ioctl(sockfd, SIOCGIFCONF, &ifc) == -1) { - uv__close(sockfd); - return -errno; - } - -#define ADDR_SIZE(p) MAX((p).sa_len, sizeof(p)) - - /* Count all up and running ipv4/ipv6 addresses */ - ifr = ifc.ifc_req; - while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) { - p = ifr; - ifr = (struct ifreq*) - ((char*)ifr + sizeof(ifr->ifr_name) + ADDR_SIZE(ifr->ifr_addr)); - - if (!(p->ifr_addr.sa_family == AF_INET6 || - p->ifr_addr.sa_family == AF_INET)) - continue; - - memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name)); - if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) { - uv__close(sockfd); - return -errno; - } - - if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING)) - continue; - - (*count)++; - } - - /* Alloc the return interface structs */ - *addresses = (uv_interface_address_t*) - uv__malloc(*count * sizeof(uv_interface_address_t)); - if (!(*addresses)) { - uv__close(sockfd); - return -ENOMEM; - } - address = *addresses; - - ifr = ifc.ifc_req; - while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) { - p = ifr; - ifr = (struct ifreq*) - ((char*)ifr + sizeof(ifr->ifr_name) + ADDR_SIZE(ifr->ifr_addr)); - - if (!(p->ifr_addr.sa_family == AF_INET6 || - p->ifr_addr.sa_family == AF_INET)) - continue; - - memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name)); - if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) { - uv__close(sockfd); - return -ENOSYS; - } - - if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING)) - continue; - - /* All conditions above must match count loop */ - - address->name = uv__strdup(p->ifr_name); - - if (p->ifr_addr.sa_family == AF_INET6) { - address->address.address6 = *((struct sockaddr_in6*) &p->ifr_addr); - } else { - address->address.address4 = *((struct sockaddr_in*) &p->ifr_addr); - } - - /* TODO: Retrieve netmask using SIOCGIFNETMASK ioctl */ - - address->is_internal = flg.ifr_flags & IFF_LOOPBACK ? 1 : 0; - - address++; - } - -#undef ADDR_SIZE - - uv__close(sockfd); - return 0; -} - - -void uv_free_interface_addresses(uv_interface_address_t* addresses, - int count) { - int i; - - for (i = 0; i < count; ++i) { - uv__free(addresses[i].name); - } - - uv__free(addresses); -} - -void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) { - struct pollfd* events; - uintptr_t i; - uintptr_t nfds; - struct poll_ctl pc; - - assert(loop->watchers != NULL); - - events = (struct pollfd*) loop->watchers[loop->nwatchers]; - nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1]; - - if (events != NULL) - /* Invalidate events with same file descriptor */ - for (i = 0; i < nfds; i++) - if ((int) events[i].fd == fd) - events[i].fd = -1; - - /* Remove the file descriptor from the poll set */ - pc.events = 0; - pc.cmd = PS_DELETE; - pc.fd = fd; - if(loop->backend_fd >= 0) - pollset_ctl(loop->backend_fd, &pc, 1); -} diff --git a/vendor/libuv/src/unix/android-ifaddrs.c b/vendor/libuv/src/unix/android-ifaddrs.c deleted file mode 100644 index 30f681b7d..000000000 --- a/vendor/libuv/src/unix/android-ifaddrs.c +++ /dev/null @@ -1,703 +0,0 @@ -/* -Copyright (c) 2013, Kenneth MacKay -Copyright (c) 2014, Emergya (Cloud4all, FP7/2007-2013 grant agreement #289016) -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#include "android-ifaddrs.h" -#include "uv-common.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -typedef struct NetlinkList -{ - struct NetlinkList *m_next; - struct nlmsghdr *m_data; - unsigned int m_size; -} NetlinkList; - -static int netlink_socket(void) -{ - struct sockaddr_nl l_addr; - - int l_socket = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); - if(l_socket < 0) - { - return -1; - } - - memset(&l_addr, 0, sizeof(l_addr)); - l_addr.nl_family = AF_NETLINK; - if(bind(l_socket, (struct sockaddr *)&l_addr, sizeof(l_addr)) < 0) - { - close(l_socket); - return -1; - } - - return l_socket; -} - -static int netlink_send(int p_socket, int p_request) -{ - char l_buffer[NLMSG_ALIGN(sizeof(struct nlmsghdr)) + NLMSG_ALIGN(sizeof(struct rtgenmsg))]; - - struct nlmsghdr *l_hdr; - struct rtgenmsg *l_msg; - struct sockaddr_nl l_addr; - - memset(l_buffer, 0, sizeof(l_buffer)); - - l_hdr = (struct nlmsghdr *)l_buffer; - l_msg = (struct rtgenmsg *)NLMSG_DATA(l_hdr); - - l_hdr->nlmsg_len = NLMSG_LENGTH(sizeof(*l_msg)); - l_hdr->nlmsg_type = p_request; - l_hdr->nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST; - l_hdr->nlmsg_pid = 0; - l_hdr->nlmsg_seq = p_socket; - l_msg->rtgen_family = AF_UNSPEC; - - memset(&l_addr, 0, sizeof(l_addr)); - l_addr.nl_family = AF_NETLINK; - return (sendto(p_socket, l_hdr, l_hdr->nlmsg_len, 0, (struct sockaddr *)&l_addr, sizeof(l_addr))); -} - -static int netlink_recv(int p_socket, void *p_buffer, size_t p_len) -{ - struct sockaddr_nl l_addr; - struct msghdr l_msg; - - struct iovec l_iov; - l_iov.iov_base = p_buffer; - l_iov.iov_len = p_len; - - for(;;) - { - int l_result; - l_msg.msg_name = (void *)&l_addr; - l_msg.msg_namelen = sizeof(l_addr); - l_msg.msg_iov = &l_iov; - l_msg.msg_iovlen = 1; - l_msg.msg_control = NULL; - l_msg.msg_controllen = 0; - l_msg.msg_flags = 0; - l_result = recvmsg(p_socket, &l_msg, 0); - - if(l_result < 0) - { - if(errno == EINTR) - { - continue; - } - return -2; - } - - /* Buffer was too small */ - if(l_msg.msg_flags & MSG_TRUNC) - { - return -1; - } - return l_result; - } -} - -static struct nlmsghdr *getNetlinkResponse(int p_socket, int *p_size, int *p_done) -{ - size_t l_size = 4096; - void *l_buffer = NULL; - - for(;;) - { - int l_read; - - uv__free(l_buffer); - l_buffer = uv__malloc(l_size); - if (l_buffer == NULL) - { - return NULL; - } - - l_read = netlink_recv(p_socket, l_buffer, l_size); - *p_size = l_read; - if(l_read == -2) - { - uv__free(l_buffer); - return NULL; - } - if(l_read >= 0) - { - pid_t l_pid = getpid(); - struct nlmsghdr *l_hdr; - for(l_hdr = (struct nlmsghdr *)l_buffer; NLMSG_OK(l_hdr, (unsigned int)l_read); l_hdr = (struct nlmsghdr *)NLMSG_NEXT(l_hdr, l_read)) - { - if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket) - { - continue; - } - - if(l_hdr->nlmsg_type == NLMSG_DONE) - { - *p_done = 1; - break; - } - - if(l_hdr->nlmsg_type == NLMSG_ERROR) - { - uv__free(l_buffer); - return NULL; - } - } - return l_buffer; - } - - l_size *= 2; - } -} - -static NetlinkList *newListItem(struct nlmsghdr *p_data, unsigned int p_size) -{ - NetlinkList *l_item = uv__malloc(sizeof(NetlinkList)); - if (l_item == NULL) - { - return NULL; - } - - l_item->m_next = NULL; - l_item->m_data = p_data; - l_item->m_size = p_size; - return l_item; -} - -static void freeResultList(NetlinkList *p_list) -{ - NetlinkList *l_cur; - while(p_list) - { - l_cur = p_list; - p_list = p_list->m_next; - uv__free(l_cur->m_data); - uv__free(l_cur); - } -} - -static NetlinkList *getResultList(int p_socket, int p_request) -{ - int l_size; - int l_done; - NetlinkList *l_list; - NetlinkList *l_end; - - if(netlink_send(p_socket, p_request) < 0) - { - return NULL; - } - - l_list = NULL; - l_end = NULL; - - l_done = 0; - while(!l_done) - { - NetlinkList *l_item; - - struct nlmsghdr *l_hdr = getNetlinkResponse(p_socket, &l_size, &l_done); - /* Error */ - if(!l_hdr) - { - freeResultList(l_list); - return NULL; - } - - l_item = newListItem(l_hdr, l_size); - if (!l_item) - { - freeResultList(l_list); - return NULL; - } - if(!l_list) - { - l_list = l_item; - } - else - { - l_end->m_next = l_item; - } - l_end = l_item; - } - return l_list; -} - -static size_t maxSize(size_t a, size_t b) -{ - return (a > b ? a : b); -} - -static size_t calcAddrLen(sa_family_t p_family, int p_dataSize) -{ - switch(p_family) - { - case AF_INET: - return sizeof(struct sockaddr_in); - case AF_INET6: - return sizeof(struct sockaddr_in6); - case AF_PACKET: - return maxSize(sizeof(struct sockaddr_ll), offsetof(struct sockaddr_ll, sll_addr) + p_dataSize); - default: - return maxSize(sizeof(struct sockaddr), offsetof(struct sockaddr, sa_data) + p_dataSize); - } -} - -static void makeSockaddr(sa_family_t p_family, struct sockaddr *p_dest, void *p_data, size_t p_size) -{ - switch(p_family) - { - case AF_INET: - memcpy(&((struct sockaddr_in*)p_dest)->sin_addr, p_data, p_size); - break; - case AF_INET6: - memcpy(&((struct sockaddr_in6*)p_dest)->sin6_addr, p_data, p_size); - break; - case AF_PACKET: - memcpy(((struct sockaddr_ll*)p_dest)->sll_addr, p_data, p_size); - ((struct sockaddr_ll*)p_dest)->sll_halen = p_size; - break; - default: - memcpy(p_dest->sa_data, p_data, p_size); - break; - } - p_dest->sa_family = p_family; -} - -static void addToEnd(struct ifaddrs **p_resultList, struct ifaddrs *p_entry) -{ - if(!*p_resultList) - { - *p_resultList = p_entry; - } - else - { - struct ifaddrs *l_cur = *p_resultList; - while(l_cur->ifa_next) - { - l_cur = l_cur->ifa_next; - } - l_cur->ifa_next = p_entry; - } -} - -static int interpretLink(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList) -{ - struct ifaddrs *l_entry; - - char *l_index; - char *l_name; - char *l_addr; - char *l_data; - - struct ifinfomsg *l_info = (struct ifinfomsg *)NLMSG_DATA(p_hdr); - - size_t l_nameSize = 0; - size_t l_addrSize = 0; - size_t l_dataSize = 0; - - size_t l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifinfomsg)); - struct rtattr *l_rta; - for(l_rta = IFLA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize)) - { - size_t l_rtaDataSize = RTA_PAYLOAD(l_rta); - switch(l_rta->rta_type) - { - case IFLA_ADDRESS: - case IFLA_BROADCAST: - l_addrSize += NLMSG_ALIGN(calcAddrLen(AF_PACKET, l_rtaDataSize)); - break; - case IFLA_IFNAME: - l_nameSize += NLMSG_ALIGN(l_rtaSize + 1); - break; - case IFLA_STATS: - l_dataSize += NLMSG_ALIGN(l_rtaSize); - break; - default: - break; - } - } - - l_entry = uv__malloc(sizeof(struct ifaddrs) + sizeof(int) + l_nameSize + l_addrSize + l_dataSize); - if (l_entry == NULL) - { - return -1; - } - memset(l_entry, 0, sizeof(struct ifaddrs)); - l_entry->ifa_name = ""; - - l_index = ((char *)l_entry) + sizeof(struct ifaddrs); - l_name = l_index + sizeof(int); - l_addr = l_name + l_nameSize; - l_data = l_addr + l_addrSize; - - /* Save the interface index so we can look it up when handling the - * addresses. - */ - memcpy(l_index, &l_info->ifi_index, sizeof(int)); - - l_entry->ifa_flags = l_info->ifi_flags; - - l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifinfomsg)); - for(l_rta = IFLA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize)) - { - void *l_rtaData = RTA_DATA(l_rta); - size_t l_rtaDataSize = RTA_PAYLOAD(l_rta); - switch(l_rta->rta_type) - { - case IFLA_ADDRESS: - case IFLA_BROADCAST: - { - size_t l_addrLen = calcAddrLen(AF_PACKET, l_rtaDataSize); - makeSockaddr(AF_PACKET, (struct sockaddr *)l_addr, l_rtaData, l_rtaDataSize); - ((struct sockaddr_ll *)l_addr)->sll_ifindex = l_info->ifi_index; - ((struct sockaddr_ll *)l_addr)->sll_hatype = l_info->ifi_type; - if(l_rta->rta_type == IFLA_ADDRESS) - { - l_entry->ifa_addr = (struct sockaddr *)l_addr; - } - else - { - l_entry->ifa_broadaddr = (struct sockaddr *)l_addr; - } - l_addr += NLMSG_ALIGN(l_addrLen); - break; - } - case IFLA_IFNAME: - strncpy(l_name, l_rtaData, l_rtaDataSize); - l_name[l_rtaDataSize] = '\0'; - l_entry->ifa_name = l_name; - break; - case IFLA_STATS: - memcpy(l_data, l_rtaData, l_rtaDataSize); - l_entry->ifa_data = l_data; - break; - default: - break; - } - } - - addToEnd(p_resultList, l_entry); - return 0; -} - -static struct ifaddrs *findInterface(int p_index, struct ifaddrs **p_links, int p_numLinks) -{ - int l_num = 0; - struct ifaddrs *l_cur = *p_links; - while(l_cur && l_num < p_numLinks) - { - char *l_indexPtr = ((char *)l_cur) + sizeof(struct ifaddrs); - int l_index; - memcpy(&l_index, l_indexPtr, sizeof(int)); - if(l_index == p_index) - { - return l_cur; - } - - l_cur = l_cur->ifa_next; - ++l_num; - } - return NULL; -} - -static int interpretAddr(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList, int p_numLinks) -{ - struct ifaddrmsg *l_info = (struct ifaddrmsg *)NLMSG_DATA(p_hdr); - struct ifaddrs *l_interface = findInterface(l_info->ifa_index, p_resultList, p_numLinks); - - size_t l_nameSize = 0; - size_t l_addrSize = 0; - - int l_addedNetmask = 0; - - size_t l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifaddrmsg)); - struct rtattr *l_rta; - struct ifaddrs *l_entry; - - char *l_name; - char *l_addr; - - for(l_rta = IFLA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize)) - { - size_t l_rtaDataSize = RTA_PAYLOAD(l_rta); - if(l_info->ifa_family == AF_PACKET) - { - continue; - } - - switch(l_rta->rta_type) - { - case IFA_ADDRESS: - case IFA_LOCAL: - if((l_info->ifa_family == AF_INET || l_info->ifa_family == AF_INET6) && !l_addedNetmask) - { - /* Make room for netmask */ - l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize)); - l_addedNetmask = 1; - } - case IFA_BROADCAST: - l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize)); - break; - case IFA_LABEL: - l_nameSize += NLMSG_ALIGN(l_rtaSize + 1); - break; - default: - break; - } - } - - l_entry = uv__malloc(sizeof(struct ifaddrs) + l_nameSize + l_addrSize); - if (l_entry == NULL) - { - return -1; - } - memset(l_entry, 0, sizeof(struct ifaddrs)); - l_entry->ifa_name = (l_interface ? l_interface->ifa_name : ""); - - l_name = ((char *)l_entry) + sizeof(struct ifaddrs); - l_addr = l_name + l_nameSize; - - l_entry->ifa_flags = l_info->ifa_flags; - if(l_interface) - { - l_entry->ifa_flags |= l_interface->ifa_flags; - } - - l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifaddrmsg)); - for(l_rta = IFLA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize)) - { - void *l_rtaData = RTA_DATA(l_rta); - size_t l_rtaDataSize = RTA_PAYLOAD(l_rta); - switch(l_rta->rta_type) - { - case IFA_ADDRESS: - case IFA_BROADCAST: - case IFA_LOCAL: - { - size_t l_addrLen = calcAddrLen(l_info->ifa_family, l_rtaDataSize); - makeSockaddr(l_info->ifa_family, (struct sockaddr *)l_addr, l_rtaData, l_rtaDataSize); - if(l_info->ifa_family == AF_INET6) - { - if(IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)l_rtaData) || IN6_IS_ADDR_MC_LINKLOCAL((struct in6_addr *)l_rtaData)) - { - ((struct sockaddr_in6 *)l_addr)->sin6_scope_id = l_info->ifa_index; - } - } - - /* Apparently in a point-to-point network IFA_ADDRESS contains - * the dest address and IFA_LOCAL contains the local address - */ - if(l_rta->rta_type == IFA_ADDRESS) - { - if(l_entry->ifa_addr) - { - l_entry->ifa_dstaddr = (struct sockaddr *)l_addr; - } - else - { - l_entry->ifa_addr = (struct sockaddr *)l_addr; - } - } - else if(l_rta->rta_type == IFA_LOCAL) - { - if(l_entry->ifa_addr) - { - l_entry->ifa_dstaddr = l_entry->ifa_addr; - } - l_entry->ifa_addr = (struct sockaddr *)l_addr; - } - else - { - l_entry->ifa_broadaddr = (struct sockaddr *)l_addr; - } - l_addr += NLMSG_ALIGN(l_addrLen); - break; - } - case IFA_LABEL: - strncpy(l_name, l_rtaData, l_rtaDataSize); - l_name[l_rtaDataSize] = '\0'; - l_entry->ifa_name = l_name; - break; - default: - break; - } - } - - if(l_entry->ifa_addr && (l_entry->ifa_addr->sa_family == AF_INET || l_entry->ifa_addr->sa_family == AF_INET6)) - { - unsigned l_maxPrefix = (l_entry->ifa_addr->sa_family == AF_INET ? 32 : 128); - unsigned l_prefix = (l_info->ifa_prefixlen > l_maxPrefix ? l_maxPrefix : l_info->ifa_prefixlen); - char l_mask[16] = {0}; - unsigned i; - for(i=0; i<(l_prefix/8); ++i) - { - l_mask[i] = 0xff; - } - if(l_prefix % 8) - { - l_mask[i] = 0xff << (8 - (l_prefix % 8)); - } - - makeSockaddr(l_entry->ifa_addr->sa_family, (struct sockaddr *)l_addr, l_mask, l_maxPrefix / 8); - l_entry->ifa_netmask = (struct sockaddr *)l_addr; - } - - addToEnd(p_resultList, l_entry); - return 0; -} - -static int interpretLinks(int p_socket, NetlinkList *p_netlinkList, struct ifaddrs **p_resultList) -{ - - int l_numLinks = 0; - pid_t l_pid = getpid(); - for(; p_netlinkList; p_netlinkList = p_netlinkList->m_next) - { - unsigned int l_nlsize = p_netlinkList->m_size; - struct nlmsghdr *l_hdr; - for(l_hdr = p_netlinkList->m_data; NLMSG_OK(l_hdr, l_nlsize); l_hdr = NLMSG_NEXT(l_hdr, l_nlsize)) - { - if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket) - { - continue; - } - - if(l_hdr->nlmsg_type == NLMSG_DONE) - { - break; - } - - if(l_hdr->nlmsg_type == RTM_NEWLINK) - { - if(interpretLink(l_hdr, p_resultList) == -1) - { - return -1; - } - ++l_numLinks; - } - } - } - return l_numLinks; -} - -static int interpretAddrs(int p_socket, NetlinkList *p_netlinkList, struct ifaddrs **p_resultList, int p_numLinks) -{ - pid_t l_pid = getpid(); - for(; p_netlinkList; p_netlinkList = p_netlinkList->m_next) - { - unsigned int l_nlsize = p_netlinkList->m_size; - struct nlmsghdr *l_hdr; - for(l_hdr = p_netlinkList->m_data; NLMSG_OK(l_hdr, l_nlsize); l_hdr = NLMSG_NEXT(l_hdr, l_nlsize)) - { - if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket) - { - continue; - } - - if(l_hdr->nlmsg_type == NLMSG_DONE) - { - break; - } - - if(l_hdr->nlmsg_type == RTM_NEWADDR) - { - if (interpretAddr(l_hdr, p_resultList, p_numLinks) == -1) - { - return -1; - } - } - } - } - return 0; -} - -int getifaddrs(struct ifaddrs **ifap) -{ - int l_socket; - int l_result; - int l_numLinks; - NetlinkList *l_linkResults; - NetlinkList *l_addrResults; - - if(!ifap) - { - return -1; - } - *ifap = NULL; - - l_socket = netlink_socket(); - if(l_socket < 0) - { - return -1; - } - - l_linkResults = getResultList(l_socket, RTM_GETLINK); - if(!l_linkResults) - { - close(l_socket); - return -1; - } - - l_addrResults = getResultList(l_socket, RTM_GETADDR); - if(!l_addrResults) - { - close(l_socket); - freeResultList(l_linkResults); - return -1; - } - - l_result = 0; - l_numLinks = interpretLinks(l_socket, l_linkResults, ifap); - if(l_numLinks == -1 || interpretAddrs(l_socket, l_addrResults, ifap, l_numLinks) == -1) - { - l_result = -1; - } - - freeResultList(l_linkResults); - freeResultList(l_addrResults); - close(l_socket); - return l_result; -} - -void freeifaddrs(struct ifaddrs *ifa) -{ - struct ifaddrs *l_cur; - while(ifa) - { - l_cur = ifa; - ifa = ifa->ifa_next; - uv__free(l_cur); - } -} diff --git a/vendor/libuv/src/unix/async.c b/vendor/libuv/src/unix/async.c deleted file mode 100644 index 393cdebd4..000000000 --- a/vendor/libuv/src/unix/async.c +++ /dev/null @@ -1,290 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -/* This file contains both the uv__async internal infrastructure and the - * user-facing uv_async_t functions. - */ - -#include "uv.h" -#include "internal.h" -#include "atomic-ops.h" - -#include -#include /* snprintf() */ -#include -#include -#include -#include - -static void uv__async_event(uv_loop_t* loop, - struct uv__async* w, - unsigned int nevents); -static int uv__async_eventfd(void); - - -int uv_async_init(uv_loop_t* loop, uv_async_t* handle, uv_async_cb async_cb) { - int err; - - err = uv__async_start(loop, &loop->async_watcher, uv__async_event); - if (err) - return err; - - uv__handle_init(loop, (uv_handle_t*)handle, UV_ASYNC); - handle->async_cb = async_cb; - handle->pending = 0; - - QUEUE_INSERT_TAIL(&loop->async_handles, &handle->queue); - uv__handle_start(handle); - - return 0; -} - - -int uv_async_send(uv_async_t* handle) { - /* Do a cheap read first. */ - if (ACCESS_ONCE(int, handle->pending) != 0) - return 0; - - if (cmpxchgi(&handle->pending, 0, 1) == 0) - uv__async_send(&handle->loop->async_watcher); - - return 0; -} - - -void uv__async_close(uv_async_t* handle) { - QUEUE_REMOVE(&handle->queue); - uv__handle_stop(handle); -} - - -static void uv__async_event(uv_loop_t* loop, - struct uv__async* w, - unsigned int nevents) { - QUEUE queue; - QUEUE* q; - uv_async_t* h; - - QUEUE_MOVE(&loop->async_handles, &queue); - while (!QUEUE_EMPTY(&queue)) { - q = QUEUE_HEAD(&queue); - h = QUEUE_DATA(q, uv_async_t, queue); - - QUEUE_REMOVE(q); - QUEUE_INSERT_TAIL(&loop->async_handles, q); - - if (cmpxchgi(&h->pending, 1, 0) == 0) - continue; - - if (h->async_cb == NULL) - continue; - h->async_cb(h); - } -} - - -static void uv__async_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) { - struct uv__async* wa; - char buf[1024]; - unsigned n; - ssize_t r; - - n = 0; - for (;;) { - r = read(w->fd, buf, sizeof(buf)); - - if (r > 0) - n += r; - - if (r == sizeof(buf)) - continue; - - if (r != -1) - break; - - if (errno == EAGAIN || errno == EWOULDBLOCK) - break; - - if (errno == EINTR) - continue; - - abort(); - } - - wa = container_of(w, struct uv__async, io_watcher); - -#if defined(__linux__) - if (wa->wfd == -1) { - uint64_t val; - assert(n == sizeof(val)); - memcpy(&val, buf, sizeof(val)); /* Avoid alignment issues. */ - wa->cb(loop, wa, val); - return; - } -#endif - - wa->cb(loop, wa, n); -} - - -void uv__async_send(struct uv__async* wa) { - const void* buf; - ssize_t len; - int fd; - int r; - - buf = ""; - len = 1; - fd = wa->wfd; - -#if defined(__linux__) - if (fd == -1) { - static const uint64_t val = 1; - buf = &val; - len = sizeof(val); - fd = wa->io_watcher.fd; /* eventfd */ - } -#endif - - do - r = write(fd, buf, len); - while (r == -1 && errno == EINTR); - - if (r == len) - return; - - if (r == -1) - if (errno == EAGAIN || errno == EWOULDBLOCK) - return; - - abort(); -} - - -void uv__async_init(struct uv__async* wa) { - wa->io_watcher.fd = -1; - wa->wfd = -1; -} - - -int uv__async_start(uv_loop_t* loop, struct uv__async* wa, uv__async_cb cb) { - int pipefd[2]; - int err; - - if (wa->io_watcher.fd != -1) - return 0; - - err = uv__async_eventfd(); - if (err >= 0) { - pipefd[0] = err; - pipefd[1] = -1; - } - else if (err == -ENOSYS) { - err = uv__make_pipe(pipefd, UV__F_NONBLOCK); -#if defined(__linux__) - /* Save a file descriptor by opening one of the pipe descriptors as - * read/write through the procfs. That file descriptor can then - * function as both ends of the pipe. - */ - if (err == 0) { - char buf[32]; - int fd; - - snprintf(buf, sizeof(buf), "/proc/self/fd/%d", pipefd[0]); - fd = uv__open_cloexec(buf, O_RDWR); - if (fd >= 0) { - uv__close(pipefd[0]); - uv__close(pipefd[1]); - pipefd[0] = fd; - pipefd[1] = fd; - } - } -#endif - } - - if (err < 0) - return err; - - uv__io_init(&wa->io_watcher, uv__async_io, pipefd[0]); - uv__io_start(loop, &wa->io_watcher, POLLIN); - wa->wfd = pipefd[1]; - wa->cb = cb; - - return 0; -} - - -void uv__async_stop(uv_loop_t* loop, struct uv__async* wa) { - if (wa->io_watcher.fd == -1) - return; - - if (wa->wfd != -1) { - if (wa->wfd != wa->io_watcher.fd) - uv__close(wa->wfd); - wa->wfd = -1; - } - - uv__io_stop(loop, &wa->io_watcher, POLLIN); - uv__close(wa->io_watcher.fd); - wa->io_watcher.fd = -1; -} - - -static int uv__async_eventfd() { -#if defined(__linux__) - static int no_eventfd2; - static int no_eventfd; - int fd; - - if (no_eventfd2) - goto skip_eventfd2; - - fd = uv__eventfd2(0, UV__EFD_CLOEXEC | UV__EFD_NONBLOCK); - if (fd != -1) - return fd; - - if (errno != ENOSYS) - return -errno; - - no_eventfd2 = 1; - -skip_eventfd2: - - if (no_eventfd) - goto skip_eventfd; - - fd = uv__eventfd(0); - if (fd != -1) { - uv__cloexec(fd, 1); - uv__nonblock(fd, 1); - return fd; - } - - if (errno != ENOSYS) - return -errno; - - no_eventfd = 1; - -skip_eventfd: - -#endif - - return -ENOSYS; -} diff --git a/vendor/libuv/src/unix/atomic-ops.h b/vendor/libuv/src/unix/atomic-ops.h deleted file mode 100644 index 9dac2557f..000000000 --- a/vendor/libuv/src/unix/atomic-ops.h +++ /dev/null @@ -1,97 +0,0 @@ -/* Copyright (c) 2013, Ben Noordhuis - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef UV_ATOMIC_OPS_H_ -#define UV_ATOMIC_OPS_H_ - -#include "internal.h" /* UV_UNUSED */ - -#if defined(__SUNPRO_C) || defined(__SUNPRO_CC) -#include -#define __sync_val_compare_and_swap(p, o, n) atomic_cas_ptr(p, o, n) -#endif - -UV_UNUSED(static int cmpxchgi(int* ptr, int oldval, int newval)); -UV_UNUSED(static long cmpxchgl(long* ptr, long oldval, long newval)); -UV_UNUSED(static void cpu_relax(void)); - -/* Prefer hand-rolled assembly over the gcc builtins because the latter also - * issue full memory barriers. - */ -UV_UNUSED(static int cmpxchgi(int* ptr, int oldval, int newval)) { -#if defined(__i386__) || defined(__x86_64__) - int out; - __asm__ __volatile__ ("lock; cmpxchg %2, %1;" - : "=a" (out), "+m" (*(volatile int*) ptr) - : "r" (newval), "0" (oldval) - : "memory"); - return out; -#elif defined(_AIX) && defined(__xlC__) - const int out = (*(volatile int*) ptr); - __compare_and_swap(ptr, &oldval, newval); - return out; -#elif defined(__MVS__) - unsigned int op4; - if (__plo_CSST(ptr, (unsigned int*) &oldval, newval, - (unsigned int*) ptr, *ptr, &op4)) - return oldval; - else - return op4; -#else - return __sync_val_compare_and_swap(ptr, oldval, newval); -#endif -} - -UV_UNUSED(static long cmpxchgl(long* ptr, long oldval, long newval)) { -#if defined(__i386__) || defined(__x86_64__) - long out; - __asm__ __volatile__ ("lock; cmpxchg %2, %1;" - : "=a" (out), "+m" (*(volatile long*) ptr) - : "r" (newval), "0" (oldval) - : "memory"); - return out; -#elif defined(_AIX) && defined(__xlC__) - const long out = (*(volatile int*) ptr); -# if defined(__64BIT__) - __compare_and_swaplp(ptr, &oldval, newval); -# else - __compare_and_swap(ptr, &oldval, newval); -# endif /* if defined(__64BIT__) */ - return out; -#elif defined (__MVS__) -#ifdef _LP64 - unsigned long long op4; - if (__plo_CSSTGR(ptr, (unsigned long long*) &oldval, newval, - (unsigned long long*) ptr, *ptr, &op4)) -#else - unsigned long op4; - if (__plo_CSST(ptr, (unsigned int*) &oldval, newval, - (unsigned int*) ptr, *ptr, &op4)) -#endif - return oldval; - else - return op4; -#else - return __sync_val_compare_and_swap(ptr, oldval, newval); -#endif -} - -UV_UNUSED(static void cpu_relax(void)) { -#if defined(__i386__) || defined(__x86_64__) - __asm__ __volatile__ ("rep; nop"); /* a.k.a. PAUSE */ -#endif -} - -#endif /* UV_ATOMIC_OPS_H_ */ diff --git a/vendor/libuv/src/unix/core.c b/vendor/libuv/src/unix/core.c deleted file mode 100644 index 1e1c6c0d9..000000000 --- a/vendor/libuv/src/unix/core.c +++ /dev/null @@ -1,1248 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "internal.h" - -#include /* NULL */ -#include /* printf */ -#include -#include /* strerror */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include /* INT_MAX, PATH_MAX, IOV_MAX */ -#include /* writev */ -#include /* getrusage */ -#include - -#ifdef __sun -# include -# include -# include -#endif - -#ifdef __APPLE__ -# include /* _NSGetExecutablePath */ -# include -# if defined(O_CLOEXEC) -# define UV__O_CLOEXEC O_CLOEXEC -# endif -#endif - -#if defined(__DragonFly__) || \ - defined(__FreeBSD__) || \ - defined(__FreeBSD_kernel__) -# include -# include -# include -# define UV__O_CLOEXEC O_CLOEXEC -# if defined(__FreeBSD__) && __FreeBSD__ >= 10 -# define uv__accept4 accept4 -# define UV__SOCK_NONBLOCK SOCK_NONBLOCK -# define UV__SOCK_CLOEXEC SOCK_CLOEXEC -# endif -# if !defined(F_DUP2FD_CLOEXEC) && defined(_F_DUP2FD_CLOEXEC) -# define F_DUP2FD_CLOEXEC _F_DUP2FD_CLOEXEC -# endif -#endif - -#if defined(__ANDROID_API__) && __ANDROID_API__ < 21 -# include /* for dlsym */ -#endif - -#if defined(__MVS__) -#include -#endif - -static int uv__run_pending(uv_loop_t* loop); - -/* Verify that uv_buf_t is ABI-compatible with struct iovec. */ -STATIC_ASSERT(sizeof(uv_buf_t) == sizeof(struct iovec)); -STATIC_ASSERT(sizeof(&((uv_buf_t*) 0)->base) == - sizeof(((struct iovec*) 0)->iov_base)); -STATIC_ASSERT(sizeof(&((uv_buf_t*) 0)->len) == - sizeof(((struct iovec*) 0)->iov_len)); -STATIC_ASSERT(offsetof(uv_buf_t, base) == offsetof(struct iovec, iov_base)); -STATIC_ASSERT(offsetof(uv_buf_t, len) == offsetof(struct iovec, iov_len)); - - -uint64_t uv_hrtime(void) { - return uv__hrtime(UV_CLOCK_PRECISE); -} - - -void uv_close(uv_handle_t* handle, uv_close_cb close_cb) { - assert(!uv__is_closing(handle)); - - handle->flags |= UV_CLOSING; - handle->close_cb = close_cb; - - switch (handle->type) { - case UV_NAMED_PIPE: - uv__pipe_close((uv_pipe_t*)handle); - break; - - case UV_TTY: - uv__stream_close((uv_stream_t*)handle); - break; - - case UV_TCP: - uv__tcp_close((uv_tcp_t*)handle); - break; - - case UV_UDP: - uv__udp_close((uv_udp_t*)handle); - break; - - case UV_PREPARE: - uv__prepare_close((uv_prepare_t*)handle); - break; - - case UV_CHECK: - uv__check_close((uv_check_t*)handle); - break; - - case UV_IDLE: - uv__idle_close((uv_idle_t*)handle); - break; - - case UV_ASYNC: - uv__async_close((uv_async_t*)handle); - break; - - case UV_TIMER: - uv__timer_close((uv_timer_t*)handle); - break; - - case UV_PROCESS: - uv__process_close((uv_process_t*)handle); - break; - - case UV_FS_EVENT: - uv__fs_event_close((uv_fs_event_t*)handle); - break; - - case UV_POLL: - uv__poll_close((uv_poll_t*)handle); - break; - - case UV_FS_POLL: - uv__fs_poll_close((uv_fs_poll_t*)handle); - break; - - case UV_SIGNAL: - uv__signal_close((uv_signal_t*) handle); - /* Signal handles may not be closed immediately. The signal code will */ - /* itself close uv__make_close_pending whenever appropriate. */ - return; - - default: - printf("closing uninitialized handle: %p\n", (void*) handle); - assert(0); - } - - uv__make_close_pending(handle); -} - -int uv__socket_sockopt(uv_handle_t* handle, int optname, int* value) { - int r; - int fd; - socklen_t len; - - if (handle == NULL || value == NULL) - return -EINVAL; - - if (handle->type == UV_TCP || handle->type == UV_NAMED_PIPE) - fd = uv__stream_fd((uv_stream_t*) handle); - else if (handle->type == UV_UDP) - fd = ((uv_udp_t *) handle)->io_watcher.fd; - else - return -ENOTSUP; - - len = sizeof(*value); - - if (*value == 0) - r = getsockopt(fd, SOL_SOCKET, optname, value, &len); - else - r = setsockopt(fd, SOL_SOCKET, optname, (const void*) value, len); - - if (r < 0) - return -errno; - - return 0; -} - -void uv__make_close_pending(uv_handle_t* handle) { - assert(handle->flags & UV_CLOSING); - assert(!(handle->flags & UV_CLOSED)); - handle->next_closing = handle->loop->closing_handles; - handle->loop->closing_handles = handle; -} - -int uv__getiovmax(void) { -#if defined(IOV_MAX) - return IOV_MAX; -#elif defined(_SC_IOV_MAX) - static int iovmax = -1; - if (iovmax == -1) { - iovmax = sysconf(_SC_IOV_MAX); - /* On some embedded devices (arm-linux-uclibc based ip camera), - * sysconf(_SC_IOV_MAX) can not get the correct value. The return - * value is -1 and the errno is EINPROGRESS. Degrade the value to 1. - */ - if (iovmax == -1) iovmax = 1; - } - return iovmax; -#else - return 1024; -#endif -} - - -static void uv__finish_close(uv_handle_t* handle) { - /* Note: while the handle is in the UV_CLOSING state now, it's still possible - * for it to be active in the sense that uv__is_active() returns true. - * A good example is when the user calls uv_shutdown(), immediately followed - * by uv_close(). The handle is considered active at this point because the - * completion of the shutdown req is still pending. - */ - assert(handle->flags & UV_CLOSING); - assert(!(handle->flags & UV_CLOSED)); - handle->flags |= UV_CLOSED; - - switch (handle->type) { - case UV_PREPARE: - case UV_CHECK: - case UV_IDLE: - case UV_ASYNC: - case UV_TIMER: - case UV_PROCESS: - case UV_FS_EVENT: - case UV_FS_POLL: - case UV_POLL: - case UV_SIGNAL: - break; - - case UV_NAMED_PIPE: - case UV_TCP: - case UV_TTY: - uv__stream_destroy((uv_stream_t*)handle); - break; - - case UV_UDP: - uv__udp_finish_close((uv_udp_t*)handle); - break; - - default: - assert(0); - break; - } - - uv__handle_unref(handle); - QUEUE_REMOVE(&handle->handle_queue); - - if (handle->close_cb) { - handle->close_cb(handle); - } -} - - -static void uv__run_closing_handles(uv_loop_t* loop) { - uv_handle_t* p; - uv_handle_t* q; - - p = loop->closing_handles; - loop->closing_handles = NULL; - - while (p) { - q = p->next_closing; - uv__finish_close(p); - p = q; - } -} - - -int uv_is_closing(const uv_handle_t* handle) { - return uv__is_closing(handle); -} - - -int uv_backend_fd(const uv_loop_t* loop) { - return loop->backend_fd; -} - - -int uv_backend_timeout(const uv_loop_t* loop) { - if (loop->stop_flag != 0) - return 0; - - if (!uv__has_active_handles(loop) && !uv__has_active_reqs(loop)) - return 0; - - if (!QUEUE_EMPTY(&loop->idle_handles)) - return 0; - - if (!QUEUE_EMPTY(&loop->pending_queue)) - return 0; - - if (loop->closing_handles) - return 0; - - return uv__next_timeout(loop); -} - - -static int uv__loop_alive(const uv_loop_t* loop) { - return uv__has_active_handles(loop) || - uv__has_active_reqs(loop) || - loop->closing_handles != NULL; -} - - -int uv_loop_alive(const uv_loop_t* loop) { - return uv__loop_alive(loop); -} - - -int uv_run(uv_loop_t* loop, uv_run_mode mode) { - int timeout; - int r; - int ran_pending; - - r = uv__loop_alive(loop); - if (!r) - uv__update_time(loop); - - while (r != 0 && loop->stop_flag == 0) { - uv__update_time(loop); - uv__run_timers(loop); - ran_pending = uv__run_pending(loop); - uv__run_idle(loop); - uv__run_prepare(loop); - - timeout = 0; - if ((mode == UV_RUN_ONCE && !ran_pending) || mode == UV_RUN_DEFAULT) - timeout = uv_backend_timeout(loop); - - uv__io_poll(loop, timeout); - uv__run_check(loop); - uv__run_closing_handles(loop); - - if (mode == UV_RUN_ONCE) { - /* UV_RUN_ONCE implies forward progress: at least one callback must have - * been invoked when it returns. uv__io_poll() can return without doing - * I/O (meaning: no callbacks) when its timeout expires - which means we - * have pending timers that satisfy the forward progress constraint. - * - * UV_RUN_NOWAIT makes no guarantees about progress so it's omitted from - * the check. - */ - uv__update_time(loop); - uv__run_timers(loop); - } - - r = uv__loop_alive(loop); - if (mode == UV_RUN_ONCE || mode == UV_RUN_NOWAIT) - break; - } - - /* The if statement lets gcc compile it to a conditional store. Avoids - * dirtying a cache line. - */ - if (loop->stop_flag != 0) - loop->stop_flag = 0; - - return r; -} - - -void uv_update_time(uv_loop_t* loop) { - uv__update_time(loop); -} - - -int uv_is_active(const uv_handle_t* handle) { - return uv__is_active(handle); -} - - -/* Open a socket in non-blocking close-on-exec mode, atomically if possible. */ -int uv__socket(int domain, int type, int protocol) { - int sockfd; - int err; - -#if defined(SOCK_NONBLOCK) && defined(SOCK_CLOEXEC) - sockfd = socket(domain, type | SOCK_NONBLOCK | SOCK_CLOEXEC, protocol); - if (sockfd != -1) - return sockfd; - - if (errno != EINVAL) - return -errno; -#endif - - sockfd = socket(domain, type, protocol); - if (sockfd == -1) - return -errno; - - err = uv__nonblock(sockfd, 1); - if (err == 0) - err = uv__cloexec(sockfd, 1); - - if (err) { - uv__close(sockfd); - return err; - } - -#if defined(SO_NOSIGPIPE) - { - int on = 1; - setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, &on, sizeof(on)); - } -#endif - - return sockfd; -} - -/* get a file pointer to a file in read-only and close-on-exec mode */ -FILE* uv__open_file(const char* path) { - int fd; - FILE* fp; - - fd = uv__open_cloexec(path, O_RDONLY); - if (fd < 0) - return NULL; - - fp = fdopen(fd, "r"); - if (fp == NULL) - uv__close(fd); - - return fp; -} - - -int uv__accept(int sockfd) { - int peerfd; - int err; - - assert(sockfd >= 0); - - while (1) { -#if defined(__linux__) || (defined(__FreeBSD__) && __FreeBSD__ >= 10) - static int no_accept4; - - if (no_accept4) - goto skip; - - peerfd = uv__accept4(sockfd, - NULL, - NULL, - UV__SOCK_NONBLOCK|UV__SOCK_CLOEXEC); - if (peerfd != -1) - return peerfd; - - if (errno == EINTR) - continue; - - if (errno != ENOSYS) - return -errno; - - no_accept4 = 1; -skip: -#endif - - peerfd = accept(sockfd, NULL, NULL); - if (peerfd == -1) { - if (errno == EINTR) - continue; - return -errno; - } - - err = uv__cloexec(peerfd, 1); - if (err == 0) - err = uv__nonblock(peerfd, 1); - - if (err) { - uv__close(peerfd); - return err; - } - - return peerfd; - } -} - - -int uv__close_nocheckstdio(int fd) { - int saved_errno; - int rc; - - assert(fd > -1); /* Catch uninitialized io_watcher.fd bugs. */ - - saved_errno = errno; - rc = close(fd); - if (rc == -1) { - rc = -errno; - if (rc == -EINTR || rc == -EINPROGRESS) - rc = 0; /* The close is in progress, not an error. */ - errno = saved_errno; - } - - return rc; -} - - -int uv__close(int fd) { - assert(fd > STDERR_FILENO); /* Catch stdio close bugs. */ -#if defined(__MVS__) - epoll_file_close(fd); -#endif - return uv__close_nocheckstdio(fd); -} - - -int uv__nonblock_ioctl(int fd, int set) { - int r; - - do - r = ioctl(fd, FIONBIO, &set); - while (r == -1 && errno == EINTR); - - if (r) - return -errno; - - return 0; -} - - -int uv__cloexec_ioctl(int fd, int set) { - int r; - - do - r = ioctl(fd, set ? FIOCLEX : FIONCLEX); - while (r == -1 && errno == EINTR); - - if (r) - return -errno; - - return 0; -} - - -int uv__nonblock_fcntl(int fd, int set) { - int flags; - int r; - - do - r = fcntl(fd, F_GETFL); - while (r == -1 && errno == EINTR); - - if (r == -1) - return -errno; - - /* Bail out now if already set/clear. */ - if (!!(r & O_NONBLOCK) == !!set) - return 0; - - if (set) - flags = r | O_NONBLOCK; - else - flags = r & ~O_NONBLOCK; - - do - r = fcntl(fd, F_SETFL, flags); - while (r == -1 && errno == EINTR); - - if (r) - return -errno; - - return 0; -} - - -int uv__cloexec_fcntl(int fd, int set) { - int flags; - int r; - - do - r = fcntl(fd, F_GETFD); - while (r == -1 && errno == EINTR); - - if (r == -1) - return -errno; - - /* Bail out now if already set/clear. */ - if (!!(r & FD_CLOEXEC) == !!set) - return 0; - - if (set) - flags = r | FD_CLOEXEC; - else - flags = r & ~FD_CLOEXEC; - - do - r = fcntl(fd, F_SETFD, flags); - while (r == -1 && errno == EINTR); - - if (r) - return -errno; - - return 0; -} - - -/* This function is not execve-safe, there is a race window - * between the call to dup() and fcntl(FD_CLOEXEC). - */ -int uv__dup(int fd) { - int err; - - fd = dup(fd); - - if (fd == -1) - return -errno; - - err = uv__cloexec(fd, 1); - if (err) { - uv__close(fd); - return err; - } - - return fd; -} - - -ssize_t uv__recvmsg(int fd, struct msghdr* msg, int flags) { - struct cmsghdr* cmsg; - ssize_t rc; - int* pfd; - int* end; -#if defined(__linux__) - static int no_msg_cmsg_cloexec; - if (no_msg_cmsg_cloexec == 0) { - rc = recvmsg(fd, msg, flags | 0x40000000); /* MSG_CMSG_CLOEXEC */ - if (rc != -1) - return rc; - if (errno != EINVAL) - return -errno; - rc = recvmsg(fd, msg, flags); - if (rc == -1) - return -errno; - no_msg_cmsg_cloexec = 1; - } else { - rc = recvmsg(fd, msg, flags); - } -#else - rc = recvmsg(fd, msg, flags); -#endif - if (rc == -1) - return -errno; - if (msg->msg_controllen == 0) - return rc; - for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL; cmsg = CMSG_NXTHDR(msg, cmsg)) - if (cmsg->cmsg_type == SCM_RIGHTS) - for (pfd = (int*) CMSG_DATA(cmsg), - end = (int*) ((char*) cmsg + cmsg->cmsg_len); - pfd < end; - pfd += 1) - uv__cloexec(*pfd, 1); - return rc; -} - - -int uv_cwd(char* buffer, size_t* size) { - if (buffer == NULL || size == NULL) - return -EINVAL; - - if (getcwd(buffer, *size) == NULL) - return -errno; - - *size = strlen(buffer); - if (*size > 1 && buffer[*size - 1] == '/') { - buffer[*size-1] = '\0'; - (*size)--; - } - - return 0; -} - - -int uv_chdir(const char* dir) { - if (chdir(dir)) - return -errno; - - return 0; -} - - -void uv_disable_stdio_inheritance(void) { - int fd; - - /* Set the CLOEXEC flag on all open descriptors. Unconditionally try the - * first 16 file descriptors. After that, bail out after the first error. - */ - for (fd = 0; ; fd++) - if (uv__cloexec(fd, 1) && fd > 15) - break; -} - - -int uv_fileno(const uv_handle_t* handle, uv_os_fd_t* fd) { - int fd_out; - - switch (handle->type) { - case UV_TCP: - case UV_NAMED_PIPE: - case UV_TTY: - fd_out = uv__stream_fd((uv_stream_t*) handle); - break; - - case UV_UDP: - fd_out = ((uv_udp_t *) handle)->io_watcher.fd; - break; - - case UV_POLL: - fd_out = ((uv_poll_t *) handle)->io_watcher.fd; - break; - - default: - return -EINVAL; - } - - if (uv__is_closing(handle) || fd_out == -1) - return -EBADF; - - *fd = fd_out; - return 0; -} - - -static int uv__run_pending(uv_loop_t* loop) { - QUEUE* q; - QUEUE pq; - uv__io_t* w; - - if (QUEUE_EMPTY(&loop->pending_queue)) - return 0; - - QUEUE_MOVE(&loop->pending_queue, &pq); - - while (!QUEUE_EMPTY(&pq)) { - q = QUEUE_HEAD(&pq); - QUEUE_REMOVE(q); - QUEUE_INIT(q); - w = QUEUE_DATA(q, uv__io_t, pending_queue); - w->cb(loop, w, POLLOUT); - } - - return 1; -} - - -static unsigned int next_power_of_two(unsigned int val) { - val -= 1; - val |= val >> 1; - val |= val >> 2; - val |= val >> 4; - val |= val >> 8; - val |= val >> 16; - val += 1; - return val; -} - -static void maybe_resize(uv_loop_t* loop, unsigned int len) { - uv__io_t** watchers; - void* fake_watcher_list; - void* fake_watcher_count; - unsigned int nwatchers; - unsigned int i; - - if (len <= loop->nwatchers) - return; - - /* Preserve fake watcher list and count at the end of the watchers */ - if (loop->watchers != NULL) { - fake_watcher_list = loop->watchers[loop->nwatchers]; - fake_watcher_count = loop->watchers[loop->nwatchers + 1]; - } else { - fake_watcher_list = NULL; - fake_watcher_count = NULL; - } - - nwatchers = next_power_of_two(len + 2) - 2; - watchers = uv__realloc(loop->watchers, - (nwatchers + 2) * sizeof(loop->watchers[0])); - - if (watchers == NULL) - abort(); - for (i = loop->nwatchers; i < nwatchers; i++) - watchers[i] = NULL; - watchers[nwatchers] = fake_watcher_list; - watchers[nwatchers + 1] = fake_watcher_count; - - loop->watchers = watchers; - loop->nwatchers = nwatchers; -} - - -void uv__io_init(uv__io_t* w, uv__io_cb cb, int fd) { - assert(cb != NULL); - assert(fd >= -1); - QUEUE_INIT(&w->pending_queue); - QUEUE_INIT(&w->watcher_queue); - w->cb = cb; - w->fd = fd; - w->events = 0; - w->pevents = 0; - -#if defined(UV_HAVE_KQUEUE) - w->rcount = 0; - w->wcount = 0; -#endif /* defined(UV_HAVE_KQUEUE) */ -} - - -void uv__io_start(uv_loop_t* loop, uv__io_t* w, unsigned int events) { - assert(0 == (events & ~(POLLIN | POLLOUT | UV__POLLRDHUP))); - assert(0 != events); - assert(w->fd >= 0); - assert(w->fd < INT_MAX); - - w->pevents |= events; - maybe_resize(loop, w->fd + 1); - -#if !defined(__sun) - /* The event ports backend needs to rearm all file descriptors on each and - * every tick of the event loop but the other backends allow us to - * short-circuit here if the event mask is unchanged. - */ - if (w->events == w->pevents) { - if (w->events == 0 && !QUEUE_EMPTY(&w->watcher_queue)) { - QUEUE_REMOVE(&w->watcher_queue); - QUEUE_INIT(&w->watcher_queue); - } - return; - } -#endif - - if (QUEUE_EMPTY(&w->watcher_queue)) - QUEUE_INSERT_TAIL(&loop->watcher_queue, &w->watcher_queue); - - if (loop->watchers[w->fd] == NULL) { - loop->watchers[w->fd] = w; - loop->nfds++; - } -} - - -void uv__io_stop(uv_loop_t* loop, uv__io_t* w, unsigned int events) { - assert(0 == (events & ~(POLLIN | POLLOUT | UV__POLLRDHUP))); - assert(0 != events); - - if (w->fd == -1) - return; - - assert(w->fd >= 0); - - /* Happens when uv__io_stop() is called on a handle that was never started. */ - if ((unsigned) w->fd >= loop->nwatchers) - return; - - w->pevents &= ~events; - - if (w->pevents == 0) { - QUEUE_REMOVE(&w->watcher_queue); - QUEUE_INIT(&w->watcher_queue); - - if (loop->watchers[w->fd] != NULL) { - assert(loop->watchers[w->fd] == w); - assert(loop->nfds > 0); - loop->watchers[w->fd] = NULL; - loop->nfds--; - w->events = 0; - } - } - else if (QUEUE_EMPTY(&w->watcher_queue)) - QUEUE_INSERT_TAIL(&loop->watcher_queue, &w->watcher_queue); -} - - -void uv__io_close(uv_loop_t* loop, uv__io_t* w) { - uv__io_stop(loop, w, POLLIN | POLLOUT | UV__POLLRDHUP); - QUEUE_REMOVE(&w->pending_queue); - - /* Remove stale events for this file descriptor */ - uv__platform_invalidate_fd(loop, w->fd); -} - - -void uv__io_feed(uv_loop_t* loop, uv__io_t* w) { - if (QUEUE_EMPTY(&w->pending_queue)) - QUEUE_INSERT_TAIL(&loop->pending_queue, &w->pending_queue); -} - - -int uv__io_active(const uv__io_t* w, unsigned int events) { - assert(0 == (events & ~(POLLIN | POLLOUT | UV__POLLRDHUP))); - assert(0 != events); - return 0 != (w->pevents & events); -} - - -int uv_getrusage(uv_rusage_t* rusage) { - struct rusage usage; - - if (getrusage(RUSAGE_SELF, &usage)) - return -errno; - - rusage->ru_utime.tv_sec = usage.ru_utime.tv_sec; - rusage->ru_utime.tv_usec = usage.ru_utime.tv_usec; - - rusage->ru_stime.tv_sec = usage.ru_stime.tv_sec; - rusage->ru_stime.tv_usec = usage.ru_stime.tv_usec; - -#if !defined(__MVS__) - rusage->ru_maxrss = usage.ru_maxrss; - rusage->ru_ixrss = usage.ru_ixrss; - rusage->ru_idrss = usage.ru_idrss; - rusage->ru_isrss = usage.ru_isrss; - rusage->ru_minflt = usage.ru_minflt; - rusage->ru_majflt = usage.ru_majflt; - rusage->ru_nswap = usage.ru_nswap; - rusage->ru_inblock = usage.ru_inblock; - rusage->ru_oublock = usage.ru_oublock; - rusage->ru_msgsnd = usage.ru_msgsnd; - rusage->ru_msgrcv = usage.ru_msgrcv; - rusage->ru_nsignals = usage.ru_nsignals; - rusage->ru_nvcsw = usage.ru_nvcsw; - rusage->ru_nivcsw = usage.ru_nivcsw; -#endif - - return 0; -} - - -int uv__open_cloexec(const char* path, int flags) { - int err; - int fd; - -#if defined(UV__O_CLOEXEC) - static int no_cloexec; - - if (!no_cloexec) { - fd = open(path, flags | UV__O_CLOEXEC); - if (fd != -1) - return fd; - - if (errno != EINVAL) - return -errno; - - /* O_CLOEXEC not supported. */ - no_cloexec = 1; - } -#endif - - fd = open(path, flags); - if (fd == -1) - return -errno; - - err = uv__cloexec(fd, 1); - if (err) { - uv__close(fd); - return err; - } - - return fd; -} - - -int uv__dup2_cloexec(int oldfd, int newfd) { - int r; -#if defined(__FreeBSD__) && __FreeBSD__ >= 10 - r = dup3(oldfd, newfd, O_CLOEXEC); - if (r == -1) - return -errno; - return r; -#elif defined(__FreeBSD__) && defined(F_DUP2FD_CLOEXEC) - r = fcntl(oldfd, F_DUP2FD_CLOEXEC, newfd); - if (r != -1) - return r; - if (errno != EINVAL) - return -errno; - /* Fall through. */ -#elif defined(__linux__) - static int no_dup3; - if (!no_dup3) { - do - r = uv__dup3(oldfd, newfd, UV__O_CLOEXEC); - while (r == -1 && errno == EBUSY); - if (r != -1) - return r; - if (errno != ENOSYS) - return -errno; - /* Fall through. */ - no_dup3 = 1; - } -#endif - { - int err; - do - r = dup2(oldfd, newfd); -#if defined(__linux__) - while (r == -1 && errno == EBUSY); -#else - while (0); /* Never retry. */ -#endif - - if (r == -1) - return -errno; - - err = uv__cloexec(newfd, 1); - if (err) { - uv__close(newfd); - return err; - } - - return r; - } -} - - -int uv_os_homedir(char* buffer, size_t* size) { - uv_passwd_t pwd; - char* buf; - size_t len; - int r; - - if (buffer == NULL || size == NULL || *size == 0) - return -EINVAL; - - /* Check if the HOME environment variable is set first */ - buf = getenv("HOME"); - - if (buf != NULL) { - len = strlen(buf); - - if (len >= *size) { - *size = len + 1; - return -ENOBUFS; - } - - memcpy(buffer, buf, len + 1); - *size = len; - - return 0; - } - - /* HOME is not set, so call uv__getpwuid_r() */ - r = uv__getpwuid_r(&pwd); - - if (r != 0) { - return r; - } - - len = strlen(pwd.homedir); - - if (len >= *size) { - *size = len + 1; - uv_os_free_passwd(&pwd); - return -ENOBUFS; - } - - memcpy(buffer, pwd.homedir, len + 1); - *size = len; - uv_os_free_passwd(&pwd); - - return 0; -} - - -int uv_os_tmpdir(char* buffer, size_t* size) { - const char* buf; - size_t len; - - if (buffer == NULL || size == NULL || *size == 0) - return -EINVAL; - -#define CHECK_ENV_VAR(name) \ - do { \ - buf = getenv(name); \ - if (buf != NULL) \ - goto return_buffer; \ - } \ - while (0) - - /* Check the TMPDIR, TMP, TEMP, and TEMPDIR environment variables in order */ - CHECK_ENV_VAR("TMPDIR"); - CHECK_ENV_VAR("TMP"); - CHECK_ENV_VAR("TEMP"); - CHECK_ENV_VAR("TEMPDIR"); - -#undef CHECK_ENV_VAR - - /* No temp environment variables defined */ - #if defined(__ANDROID__) - buf = "/data/local/tmp"; - #else - buf = "/tmp"; - #endif - -return_buffer: - len = strlen(buf); - - if (len >= *size) { - *size = len + 1; - return -ENOBUFS; - } - - /* The returned directory should not have a trailing slash. */ - if (len > 1 && buf[len - 1] == '/') { - len--; - } - - memcpy(buffer, buf, len + 1); - buffer[len] = '\0'; - *size = len; - - return 0; -} - - -int uv__getpwuid_r(uv_passwd_t* pwd) { - struct passwd pw; - struct passwd* result; - char* buf; - uid_t uid; - size_t bufsize; - size_t name_size; - size_t homedir_size; - size_t shell_size; - long initsize; - int r; -#if defined(__ANDROID_API__) && __ANDROID_API__ < 21 - int (*getpwuid_r)(uid_t, struct passwd*, char*, size_t, struct passwd**); - - getpwuid_r = dlsym(RTLD_DEFAULT, "getpwuid_r"); - if (getpwuid_r == NULL) - return -ENOSYS; -#endif - - if (pwd == NULL) - return -EINVAL; - - initsize = sysconf(_SC_GETPW_R_SIZE_MAX); - - if (initsize <= 0) - bufsize = 4096; - else - bufsize = (size_t) initsize; - - uid = geteuid(); - buf = NULL; - - for (;;) { - uv__free(buf); - buf = uv__malloc(bufsize); - - if (buf == NULL) - return -ENOMEM; - - r = getpwuid_r(uid, &pw, buf, bufsize, &result); - - if (r != ERANGE) - break; - - bufsize *= 2; - } - - if (r != 0) { - uv__free(buf); - return -r; - } - - if (result == NULL) { - uv__free(buf); - return -ENOENT; - } - - /* Allocate memory for the username, shell, and home directory */ - name_size = strlen(pw.pw_name) + 1; - homedir_size = strlen(pw.pw_dir) + 1; - shell_size = strlen(pw.pw_shell) + 1; - pwd->username = uv__malloc(name_size + homedir_size + shell_size); - - if (pwd->username == NULL) { - uv__free(buf); - return -ENOMEM; - } - - /* Copy the username */ - memcpy(pwd->username, pw.pw_name, name_size); - - /* Copy the home directory */ - pwd->homedir = pwd->username + name_size; - memcpy(pwd->homedir, pw.pw_dir, homedir_size); - - /* Copy the shell */ - pwd->shell = pwd->homedir + homedir_size; - memcpy(pwd->shell, pw.pw_shell, shell_size); - - /* Copy the uid and gid */ - pwd->uid = pw.pw_uid; - pwd->gid = pw.pw_gid; - - uv__free(buf); - - return 0; -} - - -void uv_os_free_passwd(uv_passwd_t* pwd) { - if (pwd == NULL) - return; - - /* - The memory for name, shell, and homedir are allocated in a single - uv__malloc() call. The base of the pointer is stored in pwd->username, so - that is the field that needs to be freed. - */ - uv__free(pwd->username); - pwd->username = NULL; - pwd->shell = NULL; - pwd->homedir = NULL; -} - - -int uv_os_get_passwd(uv_passwd_t* pwd) { - return uv__getpwuid_r(pwd); -} - - -int uv_translate_sys_error(int sys_errno) { - /* If < 0 then it's already a libuv error. */ - return sys_errno <= 0 ? sys_errno : -sys_errno; -} diff --git a/vendor/libuv/src/unix/darwin-proctitle.c b/vendor/libuv/src/unix/darwin-proctitle.c deleted file mode 100644 index 114231160..000000000 --- a/vendor/libuv/src/unix/darwin-proctitle.c +++ /dev/null @@ -1,206 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include -#include -#include -#include - -#include - -#if !TARGET_OS_IPHONE -# include -# include -#endif - - -static int uv__pthread_setname_np(const char* name) { - int (*dynamic_pthread_setname_np)(const char* name); - char namebuf[64]; /* MAXTHREADNAMESIZE */ - int err; - - /* pthread_setname_np() first appeared in OS X 10.6 and iOS 3.2. */ - *(void **)(&dynamic_pthread_setname_np) = - dlsym(RTLD_DEFAULT, "pthread_setname_np"); - - if (dynamic_pthread_setname_np == NULL) - return -ENOSYS; - - strncpy(namebuf, name, sizeof(namebuf) - 1); - namebuf[sizeof(namebuf) - 1] = '\0'; - - err = dynamic_pthread_setname_np(namebuf); - if (err) - return -err; - - return 0; -} - - -int uv__set_process_title(const char* title) { -#if TARGET_OS_IPHONE - return uv__pthread_setname_np(title); -#else - CFStringRef (*pCFStringCreateWithCString)(CFAllocatorRef, - const char*, - CFStringEncoding); - CFBundleRef (*pCFBundleGetBundleWithIdentifier)(CFStringRef); - void *(*pCFBundleGetDataPointerForName)(CFBundleRef, CFStringRef); - void *(*pCFBundleGetFunctionPointerForName)(CFBundleRef, CFStringRef); - CFTypeRef (*pLSGetCurrentApplicationASN)(void); - OSStatus (*pLSSetApplicationInformationItem)(int, - CFTypeRef, - CFStringRef, - CFStringRef, - CFDictionaryRef*); - void* application_services_handle; - void* core_foundation_handle; - CFBundleRef launch_services_bundle; - CFStringRef* display_name_key; - CFDictionaryRef (*pCFBundleGetInfoDictionary)(CFBundleRef); - CFBundleRef (*pCFBundleGetMainBundle)(void); - CFBundleRef hi_services_bundle; - OSStatus (*pSetApplicationIsDaemon)(int); - CFDictionaryRef (*pLSApplicationCheckIn)(int, CFDictionaryRef); - void (*pLSSetApplicationLaunchServicesServerConnectionStatus)(uint64_t, - void*); - CFTypeRef asn; - int err; - - err = -ENOENT; - application_services_handle = dlopen("/System/Library/Frameworks/" - "ApplicationServices.framework/" - "Versions/A/ApplicationServices", - RTLD_LAZY | RTLD_LOCAL); - core_foundation_handle = dlopen("/System/Library/Frameworks/" - "CoreFoundation.framework/" - "Versions/A/CoreFoundation", - RTLD_LAZY | RTLD_LOCAL); - - if (application_services_handle == NULL || core_foundation_handle == NULL) - goto out; - - *(void **)(&pCFStringCreateWithCString) = - dlsym(core_foundation_handle, "CFStringCreateWithCString"); - *(void **)(&pCFBundleGetBundleWithIdentifier) = - dlsym(core_foundation_handle, "CFBundleGetBundleWithIdentifier"); - *(void **)(&pCFBundleGetDataPointerForName) = - dlsym(core_foundation_handle, "CFBundleGetDataPointerForName"); - *(void **)(&pCFBundleGetFunctionPointerForName) = - dlsym(core_foundation_handle, "CFBundleGetFunctionPointerForName"); - - if (pCFStringCreateWithCString == NULL || - pCFBundleGetBundleWithIdentifier == NULL || - pCFBundleGetDataPointerForName == NULL || - pCFBundleGetFunctionPointerForName == NULL) { - goto out; - } - -#define S(s) pCFStringCreateWithCString(NULL, (s), kCFStringEncodingUTF8) - - launch_services_bundle = - pCFBundleGetBundleWithIdentifier(S("com.apple.LaunchServices")); - - if (launch_services_bundle == NULL) - goto out; - - *(void **)(&pLSGetCurrentApplicationASN) = - pCFBundleGetFunctionPointerForName(launch_services_bundle, - S("_LSGetCurrentApplicationASN")); - - if (pLSGetCurrentApplicationASN == NULL) - goto out; - - *(void **)(&pLSSetApplicationInformationItem) = - pCFBundleGetFunctionPointerForName(launch_services_bundle, - S("_LSSetApplicationInformationItem")); - - if (pLSSetApplicationInformationItem == NULL) - goto out; - - display_name_key = pCFBundleGetDataPointerForName(launch_services_bundle, - S("_kLSDisplayNameKey")); - - if (display_name_key == NULL || *display_name_key == NULL) - goto out; - - *(void **)(&pCFBundleGetInfoDictionary) = dlsym(core_foundation_handle, - "CFBundleGetInfoDictionary"); - *(void **)(&pCFBundleGetMainBundle) = dlsym(core_foundation_handle, - "CFBundleGetMainBundle"); - if (pCFBundleGetInfoDictionary == NULL || pCFBundleGetMainBundle == NULL) - goto out; - - /* Black 10.9 magic, to remove (Not responding) mark in Activity Monitor */ - hi_services_bundle = - pCFBundleGetBundleWithIdentifier(S("com.apple.HIServices")); - err = -ENOENT; - if (hi_services_bundle == NULL) - goto out; - - *(void **)(&pSetApplicationIsDaemon) = pCFBundleGetFunctionPointerForName( - hi_services_bundle, - S("SetApplicationIsDaemon")); - *(void **)(&pLSApplicationCheckIn) = pCFBundleGetFunctionPointerForName( - launch_services_bundle, - S("_LSApplicationCheckIn")); - *(void **)(&pLSSetApplicationLaunchServicesServerConnectionStatus) = - pCFBundleGetFunctionPointerForName( - launch_services_bundle, - S("_LSSetApplicationLaunchServicesServerConnectionStatus")); - if (pSetApplicationIsDaemon == NULL || - pLSApplicationCheckIn == NULL || - pLSSetApplicationLaunchServicesServerConnectionStatus == NULL) { - goto out; - } - - if (pSetApplicationIsDaemon(1) != noErr) - goto out; - - pLSSetApplicationLaunchServicesServerConnectionStatus(0, NULL); - - /* Check into process manager?! */ - pLSApplicationCheckIn(-2, - pCFBundleGetInfoDictionary(pCFBundleGetMainBundle())); - - asn = pLSGetCurrentApplicationASN(); - - err = -EINVAL; - if (pLSSetApplicationInformationItem(-2, /* Magic value. */ - asn, - *display_name_key, - S(title), - NULL) != noErr) { - goto out; - } - - uv__pthread_setname_np(title); /* Don't care if it fails. */ - err = 0; - -out: - if (core_foundation_handle != NULL) - dlclose(core_foundation_handle); - - if (application_services_handle != NULL) - dlclose(application_services_handle); - - return err; -#endif /* !TARGET_OS_IPHONE */ -} diff --git a/vendor/libuv/src/unix/darwin.c b/vendor/libuv/src/unix/darwin.c deleted file mode 100644 index cf95da216..000000000 --- a/vendor/libuv/src/unix/darwin.c +++ /dev/null @@ -1,335 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "internal.h" - -#include -#include -#include - -#include -#include -#include - -#include -#include -#include /* _NSGetExecutablePath */ -#include -#include -#include /* sysconf */ - - -int uv__platform_loop_init(uv_loop_t* loop) { - loop->cf_state = NULL; - - if (uv__kqueue_init(loop)) - return -errno; - - return 0; -} - - -void uv__platform_loop_delete(uv_loop_t* loop) { - uv__fsevents_loop_delete(loop); -} - - -uint64_t uv__hrtime(uv_clocktype_t type) { - static mach_timebase_info_data_t info; - - if ((ACCESS_ONCE(uint32_t, info.numer) == 0 || - ACCESS_ONCE(uint32_t, info.denom) == 0) && - mach_timebase_info(&info) != KERN_SUCCESS) - abort(); - - return mach_absolute_time() * info.numer / info.denom; -} - - -int uv_exepath(char* buffer, size_t* size) { - /* realpath(exepath) may be > PATH_MAX so double it to be on the safe side. */ - char abspath[PATH_MAX * 2 + 1]; - char exepath[PATH_MAX + 1]; - uint32_t exepath_size; - size_t abspath_size; - - if (buffer == NULL || size == NULL || *size == 0) - return -EINVAL; - - exepath_size = sizeof(exepath); - if (_NSGetExecutablePath(exepath, &exepath_size)) - return -EIO; - - if (realpath(exepath, abspath) != abspath) - return -errno; - - abspath_size = strlen(abspath); - if (abspath_size == 0) - return -EIO; - - *size -= 1; - if (*size > abspath_size) - *size = abspath_size; - - memcpy(buffer, abspath, *size); - buffer[*size] = '\0'; - - return 0; -} - - -uint64_t uv_get_free_memory(void) { - vm_statistics_data_t info; - mach_msg_type_number_t count = sizeof(info) / sizeof(integer_t); - - if (host_statistics(mach_host_self(), HOST_VM_INFO, - (host_info_t)&info, &count) != KERN_SUCCESS) { - return -EINVAL; /* FIXME(bnoordhuis) Translate error. */ - } - - return (uint64_t) info.free_count * sysconf(_SC_PAGESIZE); -} - - -uint64_t uv_get_total_memory(void) { - uint64_t info; - int which[] = {CTL_HW, HW_MEMSIZE}; - size_t size = sizeof(info); - - if (sysctl(which, 2, &info, &size, NULL, 0)) - return -errno; - - return (uint64_t) info; -} - - -void uv_loadavg(double avg[3]) { - struct loadavg info; - size_t size = sizeof(info); - int which[] = {CTL_VM, VM_LOADAVG}; - - if (sysctl(which, 2, &info, &size, NULL, 0) < 0) return; - - avg[0] = (double) info.ldavg[0] / info.fscale; - avg[1] = (double) info.ldavg[1] / info.fscale; - avg[2] = (double) info.ldavg[2] / info.fscale; -} - - -int uv_resident_set_memory(size_t* rss) { - mach_msg_type_number_t count; - task_basic_info_data_t info; - kern_return_t err; - - count = TASK_BASIC_INFO_COUNT; - err = task_info(mach_task_self(), - TASK_BASIC_INFO, - (task_info_t) &info, - &count); - (void) &err; - /* task_info(TASK_BASIC_INFO) cannot really fail. Anything other than - * KERN_SUCCESS implies a libuv bug. - */ - assert(err == KERN_SUCCESS); - *rss = info.resident_size; - - return 0; -} - - -int uv_uptime(double* uptime) { - time_t now; - struct timeval info; - size_t size = sizeof(info); - static int which[] = {CTL_KERN, KERN_BOOTTIME}; - - if (sysctl(which, 2, &info, &size, NULL, 0)) - return -errno; - - now = time(NULL); - *uptime = now - info.tv_sec; - - return 0; -} - -int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { - unsigned int ticks = (unsigned int)sysconf(_SC_CLK_TCK), - multiplier = ((uint64_t)1000L / ticks); - char model[512]; - uint64_t cpuspeed; - size_t size; - unsigned int i; - natural_t numcpus; - mach_msg_type_number_t msg_type; - processor_cpu_load_info_data_t *info; - uv_cpu_info_t* cpu_info; - - size = sizeof(model); - if (sysctlbyname("machdep.cpu.brand_string", &model, &size, NULL, 0) && - sysctlbyname("hw.model", &model, &size, NULL, 0)) { - return -errno; - } - - size = sizeof(cpuspeed); - if (sysctlbyname("hw.cpufrequency", &cpuspeed, &size, NULL, 0)) - return -errno; - - if (host_processor_info(mach_host_self(), PROCESSOR_CPU_LOAD_INFO, &numcpus, - (processor_info_array_t*)&info, - &msg_type) != KERN_SUCCESS) { - return -EINVAL; /* FIXME(bnoordhuis) Translate error. */ - } - - *cpu_infos = uv__malloc(numcpus * sizeof(**cpu_infos)); - if (!(*cpu_infos)) { - vm_deallocate(mach_task_self(), (vm_address_t)info, msg_type); - return -ENOMEM; - } - - *count = numcpus; - - for (i = 0; i < numcpus; i++) { - cpu_info = &(*cpu_infos)[i]; - - cpu_info->cpu_times.user = (uint64_t)(info[i].cpu_ticks[0]) * multiplier; - cpu_info->cpu_times.nice = (uint64_t)(info[i].cpu_ticks[3]) * multiplier; - cpu_info->cpu_times.sys = (uint64_t)(info[i].cpu_ticks[1]) * multiplier; - cpu_info->cpu_times.idle = (uint64_t)(info[i].cpu_ticks[2]) * multiplier; - cpu_info->cpu_times.irq = 0; - - cpu_info->model = uv__strdup(model); - cpu_info->speed = cpuspeed/1000000; - } - vm_deallocate(mach_task_self(), (vm_address_t)info, msg_type); - - return 0; -} - - -void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { - int i; - - for (i = 0; i < count; i++) { - uv__free(cpu_infos[i].model); - } - - uv__free(cpu_infos); -} - - -int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { - struct ifaddrs *addrs, *ent; - uv_interface_address_t* address; - int i; - struct sockaddr_dl *sa_addr; - - if (getifaddrs(&addrs)) - return -errno; - - *count = 0; - - /* Count the number of interfaces */ - for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)) || - (ent->ifa_addr == NULL) || - (ent->ifa_addr->sa_family == AF_LINK)) { - continue; - } - - (*count)++; - } - - *addresses = uv__malloc(*count * sizeof(**addresses)); - if (!(*addresses)) { - freeifaddrs(addrs); - return -ENOMEM; - } - - address = *addresses; - - for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING))) - continue; - - if (ent->ifa_addr == NULL) - continue; - - /* - * On Mac OS X getifaddrs returns information related to Mac Addresses for - * various devices, such as firewire, etc. These are not relevant here. - */ - if (ent->ifa_addr->sa_family == AF_LINK) - continue; - - address->name = uv__strdup(ent->ifa_name); - - if (ent->ifa_addr->sa_family == AF_INET6) { - address->address.address6 = *((struct sockaddr_in6*) ent->ifa_addr); - } else { - address->address.address4 = *((struct sockaddr_in*) ent->ifa_addr); - } - - if (ent->ifa_netmask->sa_family == AF_INET6) { - address->netmask.netmask6 = *((struct sockaddr_in6*) ent->ifa_netmask); - } else { - address->netmask.netmask4 = *((struct sockaddr_in*) ent->ifa_netmask); - } - - address->is_internal = !!(ent->ifa_flags & IFF_LOOPBACK); - - address++; - } - - /* Fill in physical addresses for each interface */ - for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)) || - (ent->ifa_addr == NULL) || - (ent->ifa_addr->sa_family != AF_LINK)) { - continue; - } - - address = *addresses; - - for (i = 0; i < (*count); i++) { - if (strcmp(address->name, ent->ifa_name) == 0) { - sa_addr = (struct sockaddr_dl*)(ent->ifa_addr); - memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr)); - } - address++; - } - } - - freeifaddrs(addrs); - - return 0; -} - - -void uv_free_interface_addresses(uv_interface_address_t* addresses, - int count) { - int i; - - for (i = 0; i < count; i++) { - uv__free(addresses[i].name); - } - - uv__free(addresses); -} diff --git a/vendor/libuv/src/unix/dl.c b/vendor/libuv/src/unix/dl.c deleted file mode 100644 index fc1c052bb..000000000 --- a/vendor/libuv/src/unix/dl.c +++ /dev/null @@ -1,80 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "internal.h" - -#include -#include -#include -#include - -static int uv__dlerror(uv_lib_t* lib); - - -int uv_dlopen(const char* filename, uv_lib_t* lib) { - dlerror(); /* Reset error status. */ - lib->errmsg = NULL; - lib->handle = dlopen(filename, RTLD_LAZY); - return lib->handle ? 0 : uv__dlerror(lib); -} - - -void uv_dlclose(uv_lib_t* lib) { - uv__free(lib->errmsg); - lib->errmsg = NULL; - - if (lib->handle) { - /* Ignore errors. No good way to signal them without leaking memory. */ - dlclose(lib->handle); - lib->handle = NULL; - } -} - - -int uv_dlsym(uv_lib_t* lib, const char* name, void** ptr) { - dlerror(); /* Reset error status. */ - *ptr = dlsym(lib->handle, name); - return uv__dlerror(lib); -} - - -const char* uv_dlerror(const uv_lib_t* lib) { - return lib->errmsg ? lib->errmsg : "no error"; -} - - -static int uv__dlerror(uv_lib_t* lib) { - const char* errmsg; - - uv__free(lib->errmsg); - - errmsg = dlerror(); - - if (errmsg) { - lib->errmsg = uv__strdup(errmsg); - return -1; - } - else { - lib->errmsg = NULL; - return 0; - } -} diff --git a/vendor/libuv/src/unix/freebsd.c b/vendor/libuv/src/unix/freebsd.c deleted file mode 100644 index cba44a3e0..000000000 --- a/vendor/libuv/src/unix/freebsd.c +++ /dev/null @@ -1,460 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "internal.h" - -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include /* VM_LOADAVG */ -#include -#include -#include /* sysconf */ -#include - -#undef NANOSEC -#define NANOSEC ((uint64_t) 1e9) - -#ifndef CPUSTATES -# define CPUSTATES 5U -#endif -#ifndef CP_USER -# define CP_USER 0 -# define CP_NICE 1 -# define CP_SYS 2 -# define CP_IDLE 3 -# define CP_INTR 4 -#endif - -static char *process_title; - - -int uv__platform_loop_init(uv_loop_t* loop) { - return uv__kqueue_init(loop); -} - - -void uv__platform_loop_delete(uv_loop_t* loop) { -} - - -uint64_t uv__hrtime(uv_clocktype_t type) { - struct timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - return (((uint64_t) ts.tv_sec) * NANOSEC + ts.tv_nsec); -} - - -#ifdef __DragonFly__ -int uv_exepath(char* buffer, size_t* size) { - char abspath[PATH_MAX * 2 + 1]; - ssize_t abspath_size; - - if (buffer == NULL || size == NULL || *size == 0) - return -EINVAL; - - abspath_size = readlink("/proc/curproc/file", abspath, sizeof(abspath)); - if (abspath_size < 0) - return -errno; - - assert(abspath_size > 0); - *size -= 1; - - if (*size > abspath_size) - *size = abspath_size; - - memcpy(buffer, abspath, *size); - buffer[*size] = '\0'; - - return 0; -} -#else -int uv_exepath(char* buffer, size_t* size) { - char abspath[PATH_MAX * 2 + 1]; - int mib[4]; - size_t abspath_size; - - if (buffer == NULL || size == NULL || *size == 0) - return -EINVAL; - - mib[0] = CTL_KERN; - mib[1] = KERN_PROC; - mib[2] = KERN_PROC_PATHNAME; - mib[3] = -1; - - abspath_size = sizeof abspath; - if (sysctl(mib, 4, abspath, &abspath_size, NULL, 0)) - return -errno; - - assert(abspath_size > 0); - abspath_size -= 1; - *size -= 1; - - if (*size > abspath_size) - *size = abspath_size; - - memcpy(buffer, abspath, *size); - buffer[*size] = '\0'; - - return 0; -} -#endif - -uint64_t uv_get_free_memory(void) { - int freecount; - size_t size = sizeof(freecount); - - if (sysctlbyname("vm.stats.vm.v_free_count", &freecount, &size, NULL, 0)) - return -errno; - - return (uint64_t) freecount * sysconf(_SC_PAGESIZE); - -} - - -uint64_t uv_get_total_memory(void) { - unsigned long info; - int which[] = {CTL_HW, HW_PHYSMEM}; - - size_t size = sizeof(info); - - if (sysctl(which, 2, &info, &size, NULL, 0)) - return -errno; - - return (uint64_t) info; -} - - -void uv_loadavg(double avg[3]) { - struct loadavg info; - size_t size = sizeof(info); - int which[] = {CTL_VM, VM_LOADAVG}; - - if (sysctl(which, 2, &info, &size, NULL, 0) < 0) return; - - avg[0] = (double) info.ldavg[0] / info.fscale; - avg[1] = (double) info.ldavg[1] / info.fscale; - avg[2] = (double) info.ldavg[2] / info.fscale; -} - - -char** uv_setup_args(int argc, char** argv) { - process_title = argc ? uv__strdup(argv[0]) : NULL; - return argv; -} - - -int uv_set_process_title(const char* title) { - int oid[4]; - - uv__free(process_title); - process_title = uv__strdup(title); - - oid[0] = CTL_KERN; - oid[1] = KERN_PROC; - oid[2] = KERN_PROC_ARGS; - oid[3] = getpid(); - - sysctl(oid, - ARRAY_SIZE(oid), - NULL, - NULL, - process_title, - strlen(process_title) + 1); - - return 0; -} - - -int uv_get_process_title(char* buffer, size_t size) { - size_t len; - - if (buffer == NULL || size == 0) - return -EINVAL; - - if (process_title) { - len = strlen(process_title) + 1; - - if (size < len) - return -ENOBUFS; - - memcpy(buffer, process_title, len); - } else { - len = 0; - } - - buffer[len] = '\0'; - - return 0; -} - - -int uv_resident_set_memory(size_t* rss) { - kvm_t *kd = NULL; - struct kinfo_proc *kinfo = NULL; - pid_t pid; - int nprocs; - size_t page_size = getpagesize(); - - pid = getpid(); - - kd = kvm_open(NULL, _PATH_DEVNULL, NULL, O_RDONLY, "kvm_open"); - if (kd == NULL) goto error; - - kinfo = kvm_getprocs(kd, KERN_PROC_PID, pid, &nprocs); - if (kinfo == NULL) goto error; - -#ifdef __DragonFly__ - *rss = kinfo->kp_vm_rssize * page_size; -#else - *rss = kinfo->ki_rssize * page_size; -#endif - - kvm_close(kd); - - return 0; - -error: - if (kd) kvm_close(kd); - return -EPERM; -} - - -int uv_uptime(double* uptime) { - int r; - struct timespec sp; - r = clock_gettime(CLOCK_MONOTONIC, &sp); - if (r) - return -errno; - - *uptime = sp.tv_sec; - return 0; -} - - -int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { - unsigned int ticks = (unsigned int)sysconf(_SC_CLK_TCK), - multiplier = ((uint64_t)1000L / ticks), cpuspeed, maxcpus, - cur = 0; - uv_cpu_info_t* cpu_info; - const char* maxcpus_key; - const char* cptimes_key; - char model[512]; - long* cp_times; - int numcpus; - size_t size; - int i; - -#if defined(__DragonFly__) - /* This is not quite correct but DragonFlyBSD doesn't seem to have anything - * comparable to kern.smp.maxcpus or kern.cp_times (kern.cp_time is a total, - * not per CPU). At least this stops uv_cpu_info() from failing completely. - */ - maxcpus_key = "hw.ncpu"; - cptimes_key = "kern.cp_time"; -#else - maxcpus_key = "kern.smp.maxcpus"; - cptimes_key = "kern.cp_times"; -#endif - - size = sizeof(model); - if (sysctlbyname("hw.model", &model, &size, NULL, 0)) - return -errno; - - size = sizeof(numcpus); - if (sysctlbyname("hw.ncpu", &numcpus, &size, NULL, 0)) - return -errno; - - *cpu_infos = uv__malloc(numcpus * sizeof(**cpu_infos)); - if (!(*cpu_infos)) - return -ENOMEM; - - *count = numcpus; - - size = sizeof(cpuspeed); - if (sysctlbyname("hw.clockrate", &cpuspeed, &size, NULL, 0)) { - uv__free(*cpu_infos); - return -errno; - } - - /* kern.cp_times on FreeBSD i386 gives an array up to maxcpus instead of - * ncpu. - */ - size = sizeof(maxcpus); - if (sysctlbyname(maxcpus_key, &maxcpus, &size, NULL, 0)) { - uv__free(*cpu_infos); - return -errno; - } - - size = maxcpus * CPUSTATES * sizeof(long); - - cp_times = uv__malloc(size); - if (cp_times == NULL) { - uv__free(*cpu_infos); - return -ENOMEM; - } - - if (sysctlbyname(cptimes_key, cp_times, &size, NULL, 0)) { - uv__free(cp_times); - uv__free(*cpu_infos); - return -errno; - } - - for (i = 0; i < numcpus; i++) { - cpu_info = &(*cpu_infos)[i]; - - cpu_info->cpu_times.user = (uint64_t)(cp_times[CP_USER+cur]) * multiplier; - cpu_info->cpu_times.nice = (uint64_t)(cp_times[CP_NICE+cur]) * multiplier; - cpu_info->cpu_times.sys = (uint64_t)(cp_times[CP_SYS+cur]) * multiplier; - cpu_info->cpu_times.idle = (uint64_t)(cp_times[CP_IDLE+cur]) * multiplier; - cpu_info->cpu_times.irq = (uint64_t)(cp_times[CP_INTR+cur]) * multiplier; - - cpu_info->model = uv__strdup(model); - cpu_info->speed = cpuspeed; - - cur+=CPUSTATES; - } - - uv__free(cp_times); - return 0; -} - - -void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { - int i; - - for (i = 0; i < count; i++) { - uv__free(cpu_infos[i].model); - } - - uv__free(cpu_infos); -} - - -int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { - struct ifaddrs *addrs, *ent; - uv_interface_address_t* address; - int i; - struct sockaddr_dl *sa_addr; - - if (getifaddrs(&addrs)) - return -errno; - - *count = 0; - - /* Count the number of interfaces */ - for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)) || - (ent->ifa_addr == NULL) || - (ent->ifa_addr->sa_family == AF_LINK)) { - continue; - } - - (*count)++; - } - - *addresses = uv__malloc(*count * sizeof(**addresses)); - if (!(*addresses)) { - freeifaddrs(addrs); - return -ENOMEM; - } - - address = *addresses; - - for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING))) - continue; - - if (ent->ifa_addr == NULL) - continue; - - /* - * On FreeBSD getifaddrs returns information related to the raw underlying - * devices. We're not interested in this information yet. - */ - if (ent->ifa_addr->sa_family == AF_LINK) - continue; - - address->name = uv__strdup(ent->ifa_name); - - if (ent->ifa_addr->sa_family == AF_INET6) { - address->address.address6 = *((struct sockaddr_in6*) ent->ifa_addr); - } else { - address->address.address4 = *((struct sockaddr_in*) ent->ifa_addr); - } - - if (ent->ifa_netmask->sa_family == AF_INET6) { - address->netmask.netmask6 = *((struct sockaddr_in6*) ent->ifa_netmask); - } else { - address->netmask.netmask4 = *((struct sockaddr_in*) ent->ifa_netmask); - } - - address->is_internal = !!(ent->ifa_flags & IFF_LOOPBACK); - - address++; - } - - /* Fill in physical addresses for each interface */ - for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)) || - (ent->ifa_addr == NULL) || - (ent->ifa_addr->sa_family != AF_LINK)) { - continue; - } - - address = *addresses; - - for (i = 0; i < (*count); i++) { - if (strcmp(address->name, ent->ifa_name) == 0) { - sa_addr = (struct sockaddr_dl*)(ent->ifa_addr); - memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr)); - } - address++; - } - } - - freeifaddrs(addrs); - - return 0; -} - - -void uv_free_interface_addresses(uv_interface_address_t* addresses, - int count) { - int i; - - for (i = 0; i < count; i++) { - uv__free(addresses[i].name); - } - - uv__free(addresses); -} diff --git a/vendor/libuv/src/unix/fs.c b/vendor/libuv/src/unix/fs.c deleted file mode 100644 index f9513ea55..000000000 --- a/vendor/libuv/src/unix/fs.c +++ /dev/null @@ -1,1369 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -/* Caveat emptor: this file deviates from the libuv convention of returning - * negated errno codes. Most uv_fs_*() functions map directly to the system - * call of the same name. For more complex wrappers, it's easier to just - * return -1 with errno set. The dispatcher in uv__fs_work() takes care of - * getting the errno to the right place (req->result or as the return value.) - */ - -#include "uv.h" -#include "internal.h" - -#include -#include -#include -#include -#include /* PATH_MAX */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(__DragonFly__) || \ - defined(__FreeBSD__) || \ - defined(__FreeBSD_kernel_) || \ - defined(__OpenBSD__) || \ - defined(__NetBSD__) -# define HAVE_PREADV 1 -#else -# define HAVE_PREADV 0 -#endif - -#if defined(__linux__) || defined(__sun) -# include -#endif - -#define INIT(subtype) \ - do { \ - req->type = UV_FS; \ - if (cb != NULL) \ - uv__req_init(loop, req, UV_FS); \ - req->fs_type = UV_FS_ ## subtype; \ - req->result = 0; \ - req->ptr = NULL; \ - req->loop = loop; \ - req->path = NULL; \ - req->new_path = NULL; \ - req->cb = cb; \ - } \ - while (0) - -#define PATH \ - do { \ - assert(path != NULL); \ - if (cb == NULL) { \ - req->path = path; \ - } else { \ - req->path = uv__strdup(path); \ - if (req->path == NULL) { \ - uv__req_unregister(loop, req); \ - return -ENOMEM; \ - } \ - } \ - } \ - while (0) - -#define PATH2 \ - do { \ - if (cb == NULL) { \ - req->path = path; \ - req->new_path = new_path; \ - } else { \ - size_t path_len; \ - size_t new_path_len; \ - path_len = strlen(path) + 1; \ - new_path_len = strlen(new_path) + 1; \ - req->path = uv__malloc(path_len + new_path_len); \ - if (req->path == NULL) { \ - uv__req_unregister(loop, req); \ - return -ENOMEM; \ - } \ - req->new_path = req->path + path_len; \ - memcpy((void*) req->path, path, path_len); \ - memcpy((void*) req->new_path, new_path, new_path_len); \ - } \ - } \ - while (0) - -#define POST \ - do { \ - if (cb != NULL) { \ - uv__work_submit(loop, &req->work_req, uv__fs_work, uv__fs_done); \ - return 0; \ - } \ - else { \ - uv__fs_work(&req->work_req); \ - return req->result; \ - } \ - } \ - while (0) - - -static ssize_t uv__fs_fdatasync(uv_fs_t* req) { -#if defined(__linux__) || defined(__sun) || defined(__NetBSD__) - return fdatasync(req->file); -#elif defined(__APPLE__) - /* Apple's fdatasync and fsync explicitly do NOT flush the drive write cache - * to the drive platters. This is in contrast to Linux's fdatasync and fsync - * which do, according to recent man pages. F_FULLFSYNC is Apple's equivalent - * for flushing buffered data to permanent storage. - */ - return fcntl(req->file, F_FULLFSYNC); -#else - return fsync(req->file); -#endif -} - - -static ssize_t uv__fs_fsync(uv_fs_t* req) { -#if defined(__APPLE__) - /* See the comment in uv__fs_fdatasync. */ - return fcntl(req->file, F_FULLFSYNC); -#else - return fsync(req->file); -#endif -} - - -static ssize_t uv__fs_futime(uv_fs_t* req) { -#if defined(__linux__) - /* utimesat() has nanosecond resolution but we stick to microseconds - * for the sake of consistency with other platforms. - */ - static int no_utimesat; - struct timespec ts[2]; - struct timeval tv[2]; - char path[sizeof("/proc/self/fd/") + 3 * sizeof(int)]; - int r; - - if (no_utimesat) - goto skip; - - ts[0].tv_sec = req->atime; - ts[0].tv_nsec = (uint64_t)(req->atime * 1000000) % 1000000 * 1000; - ts[1].tv_sec = req->mtime; - ts[1].tv_nsec = (uint64_t)(req->mtime * 1000000) % 1000000 * 1000; - - r = uv__utimesat(req->file, NULL, ts, 0); - if (r == 0) - return r; - - if (errno != ENOSYS) - return r; - - no_utimesat = 1; - -skip: - - tv[0].tv_sec = req->atime; - tv[0].tv_usec = (uint64_t)(req->atime * 1000000) % 1000000; - tv[1].tv_sec = req->mtime; - tv[1].tv_usec = (uint64_t)(req->mtime * 1000000) % 1000000; - snprintf(path, sizeof(path), "/proc/self/fd/%d", (int) req->file); - - r = utimes(path, tv); - if (r == 0) - return r; - - switch (errno) { - case ENOENT: - if (fcntl(req->file, F_GETFL) == -1 && errno == EBADF) - break; - /* Fall through. */ - - case EACCES: - case ENOTDIR: - errno = ENOSYS; - break; - } - - return r; - -#elif defined(__APPLE__) \ - || defined(__DragonFly__) \ - || defined(__FreeBSD__) \ - || defined(__FreeBSD_kernel__) \ - || defined(__NetBSD__) \ - || defined(__OpenBSD__) \ - || defined(__sun) - struct timeval tv[2]; - tv[0].tv_sec = req->atime; - tv[0].tv_usec = (uint64_t)(req->atime * 1000000) % 1000000; - tv[1].tv_sec = req->mtime; - tv[1].tv_usec = (uint64_t)(req->mtime * 1000000) % 1000000; -# if defined(__sun) - return futimesat(req->file, NULL, tv); -# else - return futimes(req->file, tv); -# endif -#elif defined(_AIX71) - struct timespec ts[2]; - ts[0].tv_sec = req->atime; - ts[0].tv_nsec = (uint64_t)(req->atime * 1000000) % 1000000 * 1000; - ts[1].tv_sec = req->mtime; - ts[1].tv_nsec = (uint64_t)(req->mtime * 1000000) % 1000000 * 1000; - return futimens(req->file, ts); -#elif defined(__MVS__) - attrib_t atr; - memset(&atr, 0, sizeof(atr)); - atr.att_mtimechg = 1; - atr.att_atimechg = 1; - atr.att_mtime = req->mtime; - atr.att_atime = req->atime; - return __fchattr(req->file, &atr, sizeof(atr)); -#else - errno = ENOSYS; - return -1; -#endif -} - - -static ssize_t uv__fs_mkdtemp(uv_fs_t* req) { - return mkdtemp((char*) req->path) ? 0 : -1; -} - - -static ssize_t uv__fs_open(uv_fs_t* req) { - static int no_cloexec_support; - int r; - - /* Try O_CLOEXEC before entering locks */ - if (no_cloexec_support == 0) { -#ifdef O_CLOEXEC - r = open(req->path, req->flags | O_CLOEXEC, req->mode); - if (r >= 0) - return r; - if (errno != EINVAL) - return r; - no_cloexec_support = 1; -#endif /* O_CLOEXEC */ - } - - if (req->cb != NULL) - uv_rwlock_rdlock(&req->loop->cloexec_lock); - - r = open(req->path, req->flags, req->mode); - - /* In case of failure `uv__cloexec` will leave error in `errno`, - * so it is enough to just set `r` to `-1`. - */ - if (r >= 0 && uv__cloexec(r, 1) != 0) { - r = uv__close(r); - if (r != 0) - abort(); - r = -1; - } - - if (req->cb != NULL) - uv_rwlock_rdunlock(&req->loop->cloexec_lock); - - return r; -} - - -static ssize_t uv__fs_read(uv_fs_t* req) { -#if defined(__linux__) - static int no_preadv; -#endif - ssize_t result; - -#if defined(_AIX) - struct stat buf; - if(fstat(req->file, &buf)) - return -1; - if(S_ISDIR(buf.st_mode)) { - errno = EISDIR; - return -1; - } -#endif /* defined(_AIX) */ - if (req->off < 0) { - if (req->nbufs == 1) - result = read(req->file, req->bufs[0].base, req->bufs[0].len); - else - result = readv(req->file, (struct iovec*) req->bufs, req->nbufs); - } else { - if (req->nbufs == 1) { - result = pread(req->file, req->bufs[0].base, req->bufs[0].len, req->off); - goto done; - } - -#if HAVE_PREADV - result = preadv(req->file, (struct iovec*) req->bufs, req->nbufs, req->off); -#else -# if defined(__linux__) - if (no_preadv) retry: -# endif - { - off_t nread; - size_t index; - - nread = 0; - index = 0; - result = 1; - do { - if (req->bufs[index].len > 0) { - result = pread(req->file, - req->bufs[index].base, - req->bufs[index].len, - req->off + nread); - if (result > 0) - nread += result; - } - index++; - } while (index < req->nbufs && result > 0); - if (nread > 0) - result = nread; - } -# if defined(__linux__) - else { - result = uv__preadv(req->file, - (struct iovec*)req->bufs, - req->nbufs, - req->off); - if (result == -1 && errno == ENOSYS) { - no_preadv = 1; - goto retry; - } - } -# endif -#endif - } - -done: - return result; -} - - -#if defined(__APPLE__) && !defined(MAC_OS_X_VERSION_10_8) -#define UV_CONST_DIRENT uv__dirent_t -#else -#define UV_CONST_DIRENT const uv__dirent_t -#endif - - -static int uv__fs_scandir_filter(UV_CONST_DIRENT* dent) { - return strcmp(dent->d_name, ".") != 0 && strcmp(dent->d_name, "..") != 0; -} - - -static int uv__fs_scandir_sort(UV_CONST_DIRENT** a, UV_CONST_DIRENT** b) { - return strcmp((*a)->d_name, (*b)->d_name); -} - - -static ssize_t uv__fs_scandir(uv_fs_t* req) { - uv__dirent_t **dents; - int n; - - dents = NULL; - n = scandir(req->path, &dents, uv__fs_scandir_filter, uv__fs_scandir_sort); - - /* NOTE: We will use nbufs as an index field */ - req->nbufs = 0; - - if (n == 0) { - /* OS X still needs to deallocate some memory. - * Memory was allocated using the system allocator, so use free() here. - */ - free(dents); - dents = NULL; - } else if (n == -1) { - return n; - } - - req->ptr = dents; - - return n; -} - - -static ssize_t uv__fs_pathmax_size(const char* path) { - ssize_t pathmax; - - pathmax = pathconf(path, _PC_PATH_MAX); - - if (pathmax == -1) { -#if defined(PATH_MAX) - return PATH_MAX; -#else -#error "PATH_MAX undefined in the current platform" -#endif - } - - return pathmax; -} - -static ssize_t uv__fs_readlink(uv_fs_t* req) { - ssize_t len; - char* buf; - - len = uv__fs_pathmax_size(req->path); - buf = uv__malloc(len + 1); - - if (buf == NULL) { - errno = ENOMEM; - return -1; - } - - len = readlink(req->path, buf, len); - - if (len == -1) { - uv__free(buf); - return -1; - } - - buf[len] = '\0'; - req->ptr = buf; - - return 0; -} - -static ssize_t uv__fs_realpath(uv_fs_t* req) { - ssize_t len; - char* buf; - - len = uv__fs_pathmax_size(req->path); - buf = uv__malloc(len + 1); - - if (buf == NULL) { - errno = ENOMEM; - return -1; - } - - if (realpath(req->path, buf) == NULL) { - uv__free(buf); - return -1; - } - - req->ptr = buf; - - return 0; -} - -static ssize_t uv__fs_sendfile_emul(uv_fs_t* req) { - struct pollfd pfd; - int use_pread; - off_t offset; - ssize_t nsent; - ssize_t nread; - ssize_t nwritten; - size_t buflen; - size_t len; - ssize_t n; - int in_fd; - int out_fd; - char buf[8192]; - - len = req->bufsml[0].len; - in_fd = req->flags; - out_fd = req->file; - offset = req->off; - use_pread = 1; - - /* Here are the rules regarding errors: - * - * 1. Read errors are reported only if nsent==0, otherwise we return nsent. - * The user needs to know that some data has already been sent, to stop - * them from sending it twice. - * - * 2. Write errors are always reported. Write errors are bad because they - * mean data loss: we've read data but now we can't write it out. - * - * We try to use pread() and fall back to regular read() if the source fd - * doesn't support positional reads, for example when it's a pipe fd. - * - * If we get EAGAIN when writing to the target fd, we poll() on it until - * it becomes writable again. - * - * FIXME: If we get a write error when use_pread==1, it should be safe to - * return the number of sent bytes instead of an error because pread() - * is, in theory, idempotent. However, special files in /dev or /proc - * may support pread() but not necessarily return the same data on - * successive reads. - * - * FIXME: There is no way now to signal that we managed to send *some* data - * before a write error. - */ - for (nsent = 0; (size_t) nsent < len; ) { - buflen = len - nsent; - - if (buflen > sizeof(buf)) - buflen = sizeof(buf); - - do - if (use_pread) - nread = pread(in_fd, buf, buflen, offset); - else - nread = read(in_fd, buf, buflen); - while (nread == -1 && errno == EINTR); - - if (nread == 0) - goto out; - - if (nread == -1) { - if (use_pread && nsent == 0 && (errno == EIO || errno == ESPIPE)) { - use_pread = 0; - continue; - } - - if (nsent == 0) - nsent = -1; - - goto out; - } - - for (nwritten = 0; nwritten < nread; ) { - do - n = write(out_fd, buf + nwritten, nread - nwritten); - while (n == -1 && errno == EINTR); - - if (n != -1) { - nwritten += n; - continue; - } - - if (errno != EAGAIN && errno != EWOULDBLOCK) { - nsent = -1; - goto out; - } - - pfd.fd = out_fd; - pfd.events = POLLOUT; - pfd.revents = 0; - - do - n = poll(&pfd, 1, -1); - while (n == -1 && errno == EINTR); - - if (n == -1 || (pfd.revents & ~POLLOUT) != 0) { - errno = EIO; - nsent = -1; - goto out; - } - } - - offset += nread; - nsent += nread; - } - -out: - if (nsent != -1) - req->off = offset; - - return nsent; -} - - -static ssize_t uv__fs_sendfile(uv_fs_t* req) { - int in_fd; - int out_fd; - - in_fd = req->flags; - out_fd = req->file; - -#if defined(__linux__) || defined(__sun) - { - off_t off; - ssize_t r; - - off = req->off; - r = sendfile(out_fd, in_fd, &off, req->bufsml[0].len); - - /* sendfile() on SunOS returns EINVAL if the target fd is not a socket but - * it still writes out data. Fortunately, we can detect it by checking if - * the offset has been updated. - */ - if (r != -1 || off > req->off) { - r = off - req->off; - req->off = off; - return r; - } - - if (errno == EINVAL || - errno == EIO || - errno == ENOTSOCK || - errno == EXDEV) { - errno = 0; - return uv__fs_sendfile_emul(req); - } - - return -1; - } -#elif defined(__APPLE__) || \ - defined(__DragonFly__) || \ - defined(__FreeBSD__) || \ - defined(__FreeBSD_kernel__) - { - off_t len; - ssize_t r; - - /* sendfile() on FreeBSD and Darwin returns EAGAIN if the target fd is in - * non-blocking mode and not all data could be written. If a non-zero - * number of bytes have been sent, we don't consider it an error. - */ - -#if defined(__FreeBSD__) || defined(__DragonFly__) - len = 0; - r = sendfile(in_fd, out_fd, req->off, req->bufsml[0].len, NULL, &len, 0); -#elif defined(__FreeBSD_kernel__) - len = 0; - r = bsd_sendfile(in_fd, - out_fd, - req->off, - req->bufsml[0].len, - NULL, - &len, - 0); -#else - /* The darwin sendfile takes len as an input for the length to send, - * so make sure to initialize it with the caller's value. */ - len = req->bufsml[0].len; - r = sendfile(in_fd, out_fd, req->off, &len, NULL, 0); -#endif - - /* - * The man page for sendfile(2) on DragonFly states that `len` contains - * a meaningful value ONLY in case of EAGAIN and EINTR. - * Nothing is said about it's value in case of other errors, so better - * not depend on the potential wrong assumption that is was not modified - * by the syscall. - */ - if (r == 0 || ((errno == EAGAIN || errno == EINTR) && len != 0)) { - req->off += len; - return (ssize_t) len; - } - - if (errno == EINVAL || - errno == EIO || - errno == ENOTSOCK || - errno == EXDEV) { - errno = 0; - return uv__fs_sendfile_emul(req); - } - - return -1; - } -#else - /* Squelch compiler warnings. */ - (void) &in_fd; - (void) &out_fd; - - return uv__fs_sendfile_emul(req); -#endif -} - - -static ssize_t uv__fs_utime(uv_fs_t* req) { - struct utimbuf buf; - buf.actime = req->atime; - buf.modtime = req->mtime; - return utime(req->path, &buf); /* TODO use utimes() where available */ -} - - -static ssize_t uv__fs_write(uv_fs_t* req) { -#if defined(__linux__) - static int no_pwritev; -#endif - ssize_t r; - - /* Serialize writes on OS X, concurrent write() and pwrite() calls result in - * data loss. We can't use a per-file descriptor lock, the descriptor may be - * a dup(). - */ -#if defined(__APPLE__) - static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; - - if (pthread_mutex_lock(&lock)) - abort(); -#endif - - if (req->off < 0) { - if (req->nbufs == 1) - r = write(req->file, req->bufs[0].base, req->bufs[0].len); - else - r = writev(req->file, (struct iovec*) req->bufs, req->nbufs); - } else { - if (req->nbufs == 1) { - r = pwrite(req->file, req->bufs[0].base, req->bufs[0].len, req->off); - goto done; - } -#if HAVE_PREADV - r = pwritev(req->file, (struct iovec*) req->bufs, req->nbufs, req->off); -#else -# if defined(__linux__) - if (no_pwritev) retry: -# endif - { - off_t written; - size_t index; - - written = 0; - index = 0; - r = 0; - do { - if (req->bufs[index].len > 0) { - r = pwrite(req->file, - req->bufs[index].base, - req->bufs[index].len, - req->off + written); - if (r > 0) - written += r; - } - index++; - } while (index < req->nbufs && r >= 0); - if (written > 0) - r = written; - } -# if defined(__linux__) - else { - r = uv__pwritev(req->file, - (struct iovec*) req->bufs, - req->nbufs, - req->off); - if (r == -1 && errno == ENOSYS) { - no_pwritev = 1; - goto retry; - } - } -# endif -#endif - } - -done: -#if defined(__APPLE__) - if (pthread_mutex_unlock(&lock)) - abort(); -#endif - - return r; -} - -static void uv__to_stat(struct stat* src, uv_stat_t* dst) { - dst->st_dev = src->st_dev; - dst->st_mode = src->st_mode; - dst->st_nlink = src->st_nlink; - dst->st_uid = src->st_uid; - dst->st_gid = src->st_gid; - dst->st_rdev = src->st_rdev; - dst->st_ino = src->st_ino; - dst->st_size = src->st_size; - dst->st_blksize = src->st_blksize; - dst->st_blocks = src->st_blocks; - -#if defined(__APPLE__) - dst->st_atim.tv_sec = src->st_atimespec.tv_sec; - dst->st_atim.tv_nsec = src->st_atimespec.tv_nsec; - dst->st_mtim.tv_sec = src->st_mtimespec.tv_sec; - dst->st_mtim.tv_nsec = src->st_mtimespec.tv_nsec; - dst->st_ctim.tv_sec = src->st_ctimespec.tv_sec; - dst->st_ctim.tv_nsec = src->st_ctimespec.tv_nsec; - dst->st_birthtim.tv_sec = src->st_birthtimespec.tv_sec; - dst->st_birthtim.tv_nsec = src->st_birthtimespec.tv_nsec; - dst->st_flags = src->st_flags; - dst->st_gen = src->st_gen; -#elif defined(__ANDROID__) - dst->st_atim.tv_sec = src->st_atime; - dst->st_atim.tv_nsec = src->st_atimensec; - dst->st_mtim.tv_sec = src->st_mtime; - dst->st_mtim.tv_nsec = src->st_mtimensec; - dst->st_ctim.tv_sec = src->st_ctime; - dst->st_ctim.tv_nsec = src->st_ctimensec; - dst->st_birthtim.tv_sec = src->st_ctime; - dst->st_birthtim.tv_nsec = src->st_ctimensec; - dst->st_flags = 0; - dst->st_gen = 0; -#elif !defined(_AIX) && ( \ - defined(__DragonFly__) || \ - defined(__FreeBSD__) || \ - defined(__OpenBSD__) || \ - defined(__NetBSD__) || \ - defined(_GNU_SOURCE) || \ - defined(_BSD_SOURCE) || \ - defined(_SVID_SOURCE) || \ - defined(_XOPEN_SOURCE) || \ - defined(_DEFAULT_SOURCE)) - dst->st_atim.tv_sec = src->st_atim.tv_sec; - dst->st_atim.tv_nsec = src->st_atim.tv_nsec; - dst->st_mtim.tv_sec = src->st_mtim.tv_sec; - dst->st_mtim.tv_nsec = src->st_mtim.tv_nsec; - dst->st_ctim.tv_sec = src->st_ctim.tv_sec; - dst->st_ctim.tv_nsec = src->st_ctim.tv_nsec; -# if defined(__FreeBSD__) || \ - defined(__NetBSD__) - dst->st_birthtim.tv_sec = src->st_birthtim.tv_sec; - dst->st_birthtim.tv_nsec = src->st_birthtim.tv_nsec; - dst->st_flags = src->st_flags; - dst->st_gen = src->st_gen; -# else - dst->st_birthtim.tv_sec = src->st_ctim.tv_sec; - dst->st_birthtim.tv_nsec = src->st_ctim.tv_nsec; - dst->st_flags = 0; - dst->st_gen = 0; -# endif -#else - dst->st_atim.tv_sec = src->st_atime; - dst->st_atim.tv_nsec = 0; - dst->st_mtim.tv_sec = src->st_mtime; - dst->st_mtim.tv_nsec = 0; - dst->st_ctim.tv_sec = src->st_ctime; - dst->st_ctim.tv_nsec = 0; - dst->st_birthtim.tv_sec = src->st_ctime; - dst->st_birthtim.tv_nsec = 0; - dst->st_flags = 0; - dst->st_gen = 0; -#endif -} - - -static int uv__fs_stat(const char *path, uv_stat_t *buf) { - struct stat pbuf; - int ret; - - ret = stat(path, &pbuf); - if (ret == 0) - uv__to_stat(&pbuf, buf); - - return ret; -} - - -static int uv__fs_lstat(const char *path, uv_stat_t *buf) { - struct stat pbuf; - int ret; - - ret = lstat(path, &pbuf); - if (ret == 0) - uv__to_stat(&pbuf, buf); - - return ret; -} - - -static int uv__fs_fstat(int fd, uv_stat_t *buf) { - struct stat pbuf; - int ret; - - ret = fstat(fd, &pbuf); - if (ret == 0) - uv__to_stat(&pbuf, buf); - - return ret; -} - - -typedef ssize_t (*uv__fs_buf_iter_processor)(uv_fs_t* req); -static ssize_t uv__fs_buf_iter(uv_fs_t* req, uv__fs_buf_iter_processor process) { - unsigned int iovmax; - unsigned int nbufs; - uv_buf_t* bufs; - ssize_t total; - ssize_t result; - - iovmax = uv__getiovmax(); - nbufs = req->nbufs; - bufs = req->bufs; - total = 0; - - while (nbufs > 0) { - req->nbufs = nbufs; - if (req->nbufs > iovmax) - req->nbufs = iovmax; - - result = process(req); - if (result <= 0) { - if (total == 0) - total = result; - break; - } - - if (req->off >= 0) - req->off += result; - - req->bufs += req->nbufs; - nbufs -= req->nbufs; - total += result; - } - - if (errno == EINTR && total == -1) - return total; - - if (bufs != req->bufsml) - uv__free(bufs); - - req->bufs = NULL; - req->nbufs = 0; - - return total; -} - - -static void uv__fs_work(struct uv__work* w) { - int retry_on_eintr; - uv_fs_t* req; - ssize_t r; - - req = container_of(w, uv_fs_t, work_req); - retry_on_eintr = !(req->fs_type == UV_FS_CLOSE); - - do { - errno = 0; - -#define X(type, action) \ - case UV_FS_ ## type: \ - r = action; \ - break; - - switch (req->fs_type) { - X(ACCESS, access(req->path, req->flags)); - X(CHMOD, chmod(req->path, req->mode)); - X(CHOWN, chown(req->path, req->uid, req->gid)); - X(CLOSE, close(req->file)); - X(FCHMOD, fchmod(req->file, req->mode)); - X(FCHOWN, fchown(req->file, req->uid, req->gid)); - X(FDATASYNC, uv__fs_fdatasync(req)); - X(FSTAT, uv__fs_fstat(req->file, &req->statbuf)); - X(FSYNC, uv__fs_fsync(req)); - X(FTRUNCATE, ftruncate(req->file, req->off)); - X(FUTIME, uv__fs_futime(req)); - X(LSTAT, uv__fs_lstat(req->path, &req->statbuf)); - X(LINK, link(req->path, req->new_path)); - X(MKDIR, mkdir(req->path, req->mode)); - X(MKDTEMP, uv__fs_mkdtemp(req)); - X(OPEN, uv__fs_open(req)); - X(READ, uv__fs_buf_iter(req, uv__fs_read)); - X(SCANDIR, uv__fs_scandir(req)); - X(READLINK, uv__fs_readlink(req)); - X(REALPATH, uv__fs_realpath(req)); - X(RENAME, rename(req->path, req->new_path)); - X(RMDIR, rmdir(req->path)); - X(SENDFILE, uv__fs_sendfile(req)); - X(STAT, uv__fs_stat(req->path, &req->statbuf)); - X(SYMLINK, symlink(req->path, req->new_path)); - X(UNLINK, unlink(req->path)); - X(UTIME, uv__fs_utime(req)); - X(WRITE, uv__fs_buf_iter(req, uv__fs_write)); - default: abort(); - } -#undef X - } while (r == -1 && errno == EINTR && retry_on_eintr); - - if (r == -1) - req->result = -errno; - else - req->result = r; - - if (r == 0 && (req->fs_type == UV_FS_STAT || - req->fs_type == UV_FS_FSTAT || - req->fs_type == UV_FS_LSTAT)) { - req->ptr = &req->statbuf; - } -} - - -static void uv__fs_done(struct uv__work* w, int status) { - uv_fs_t* req; - - req = container_of(w, uv_fs_t, work_req); - uv__req_unregister(req->loop, req); - - if (status == -ECANCELED) { - assert(req->result == 0); - req->result = -ECANCELED; - } - - req->cb(req); -} - - -int uv_fs_access(uv_loop_t* loop, - uv_fs_t* req, - const char* path, - int flags, - uv_fs_cb cb) { - INIT(ACCESS); - PATH; - req->flags = flags; - POST; -} - - -int uv_fs_chmod(uv_loop_t* loop, - uv_fs_t* req, - const char* path, - int mode, - uv_fs_cb cb) { - INIT(CHMOD); - PATH; - req->mode = mode; - POST; -} - - -int uv_fs_chown(uv_loop_t* loop, - uv_fs_t* req, - const char* path, - uv_uid_t uid, - uv_gid_t gid, - uv_fs_cb cb) { - INIT(CHOWN); - PATH; - req->uid = uid; - req->gid = gid; - POST; -} - - -int uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) { - INIT(CLOSE); - req->file = file; - POST; -} - - -int uv_fs_fchmod(uv_loop_t* loop, - uv_fs_t* req, - uv_file file, - int mode, - uv_fs_cb cb) { - INIT(FCHMOD); - req->file = file; - req->mode = mode; - POST; -} - - -int uv_fs_fchown(uv_loop_t* loop, - uv_fs_t* req, - uv_file file, - uv_uid_t uid, - uv_gid_t gid, - uv_fs_cb cb) { - INIT(FCHOWN); - req->file = file; - req->uid = uid; - req->gid = gid; - POST; -} - - -int uv_fs_fdatasync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) { - INIT(FDATASYNC); - req->file = file; - POST; -} - - -int uv_fs_fstat(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) { - INIT(FSTAT); - req->file = file; - POST; -} - - -int uv_fs_fsync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) { - INIT(FSYNC); - req->file = file; - POST; -} - - -int uv_fs_ftruncate(uv_loop_t* loop, - uv_fs_t* req, - uv_file file, - int64_t off, - uv_fs_cb cb) { - INIT(FTRUNCATE); - req->file = file; - req->off = off; - POST; -} - - -int uv_fs_futime(uv_loop_t* loop, - uv_fs_t* req, - uv_file file, - double atime, - double mtime, - uv_fs_cb cb) { - INIT(FUTIME); - req->file = file; - req->atime = atime; - req->mtime = mtime; - POST; -} - - -int uv_fs_lstat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) { - INIT(LSTAT); - PATH; - POST; -} - - -int uv_fs_link(uv_loop_t* loop, - uv_fs_t* req, - const char* path, - const char* new_path, - uv_fs_cb cb) { - INIT(LINK); - PATH2; - POST; -} - - -int uv_fs_mkdir(uv_loop_t* loop, - uv_fs_t* req, - const char* path, - int mode, - uv_fs_cb cb) { - INIT(MKDIR); - PATH; - req->mode = mode; - POST; -} - - -int uv_fs_mkdtemp(uv_loop_t* loop, - uv_fs_t* req, - const char* tpl, - uv_fs_cb cb) { - INIT(MKDTEMP); - req->path = uv__strdup(tpl); - if (req->path == NULL) { - if (cb != NULL) - uv__req_unregister(loop, req); - return -ENOMEM; - } - POST; -} - - -int uv_fs_open(uv_loop_t* loop, - uv_fs_t* req, - const char* path, - int flags, - int mode, - uv_fs_cb cb) { - INIT(OPEN); - PATH; - req->flags = flags; - req->mode = mode; - POST; -} - - -int uv_fs_read(uv_loop_t* loop, uv_fs_t* req, - uv_file file, - const uv_buf_t bufs[], - unsigned int nbufs, - int64_t off, - uv_fs_cb cb) { - if (bufs == NULL || nbufs == 0) - return -EINVAL; - - INIT(READ); - req->file = file; - - req->nbufs = nbufs; - req->bufs = req->bufsml; - if (nbufs > ARRAY_SIZE(req->bufsml)) - req->bufs = uv__malloc(nbufs * sizeof(*bufs)); - - if (req->bufs == NULL) { - if (cb != NULL) - uv__req_unregister(loop, req); - return -ENOMEM; - } - - memcpy(req->bufs, bufs, nbufs * sizeof(*bufs)); - - req->off = off; - POST; -} - - -int uv_fs_scandir(uv_loop_t* loop, - uv_fs_t* req, - const char* path, - int flags, - uv_fs_cb cb) { - INIT(SCANDIR); - PATH; - req->flags = flags; - POST; -} - - -int uv_fs_readlink(uv_loop_t* loop, - uv_fs_t* req, - const char* path, - uv_fs_cb cb) { - INIT(READLINK); - PATH; - POST; -} - - -int uv_fs_realpath(uv_loop_t* loop, - uv_fs_t* req, - const char * path, - uv_fs_cb cb) { - INIT(REALPATH); - PATH; - POST; -} - - -int uv_fs_rename(uv_loop_t* loop, - uv_fs_t* req, - const char* path, - const char* new_path, - uv_fs_cb cb) { - INIT(RENAME); - PATH2; - POST; -} - - -int uv_fs_rmdir(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) { - INIT(RMDIR); - PATH; - POST; -} - - -int uv_fs_sendfile(uv_loop_t* loop, - uv_fs_t* req, - uv_file out_fd, - uv_file in_fd, - int64_t off, - size_t len, - uv_fs_cb cb) { - INIT(SENDFILE); - req->flags = in_fd; /* hack */ - req->file = out_fd; - req->off = off; - req->bufsml[0].len = len; - POST; -} - - -int uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) { - INIT(STAT); - PATH; - POST; -} - - -int uv_fs_symlink(uv_loop_t* loop, - uv_fs_t* req, - const char* path, - const char* new_path, - int flags, - uv_fs_cb cb) { - INIT(SYMLINK); - PATH2; - req->flags = flags; - POST; -} - - -int uv_fs_unlink(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) { - INIT(UNLINK); - PATH; - POST; -} - - -int uv_fs_utime(uv_loop_t* loop, - uv_fs_t* req, - const char* path, - double atime, - double mtime, - uv_fs_cb cb) { - INIT(UTIME); - PATH; - req->atime = atime; - req->mtime = mtime; - POST; -} - - -int uv_fs_write(uv_loop_t* loop, - uv_fs_t* req, - uv_file file, - const uv_buf_t bufs[], - unsigned int nbufs, - int64_t off, - uv_fs_cb cb) { - if (bufs == NULL || nbufs == 0) - return -EINVAL; - - INIT(WRITE); - req->file = file; - - req->nbufs = nbufs; - req->bufs = req->bufsml; - if (nbufs > ARRAY_SIZE(req->bufsml)) - req->bufs = uv__malloc(nbufs * sizeof(*bufs)); - - if (req->bufs == NULL) { - if (cb != NULL) - uv__req_unregister(loop, req); - return -ENOMEM; - } - - memcpy(req->bufs, bufs, nbufs * sizeof(*bufs)); - - req->off = off; - POST; -} - - -void uv_fs_req_cleanup(uv_fs_t* req) { - /* Only necessary for asychronous requests, i.e., requests with a callback. - * Synchronous ones don't copy their arguments and have req->path and - * req->new_path pointing to user-owned memory. UV_FS_MKDTEMP is the - * exception to the rule, it always allocates memory. - */ - if (req->path != NULL && (req->cb != NULL || req->fs_type == UV_FS_MKDTEMP)) - uv__free((void*) req->path); /* Memory is shared with req->new_path. */ - - req->path = NULL; - req->new_path = NULL; - - if (req->fs_type == UV_FS_SCANDIR && req->ptr != NULL) - uv__fs_scandir_cleanup(req); - - if (req->ptr != &req->statbuf) - uv__free(req->ptr); - req->ptr = NULL; -} diff --git a/vendor/libuv/src/unix/fsevents.c b/vendor/libuv/src/unix/fsevents.c deleted file mode 100644 index d331a1317..000000000 --- a/vendor/libuv/src/unix/fsevents.c +++ /dev/null @@ -1,904 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "internal.h" - -#if TARGET_OS_IPHONE - -/* iOS (currently) doesn't provide the FSEvents-API (nor CoreServices) */ - -int uv__fsevents_init(uv_fs_event_t* handle) { - return 0; -} - - -int uv__fsevents_close(uv_fs_event_t* handle) { - return 0; -} - - -void uv__fsevents_loop_delete(uv_loop_t* loop) { -} - -#else /* TARGET_OS_IPHONE */ - -#include -#include -#include -#include - -#include -#include - -/* These are macros to avoid "initializer element is not constant" errors - * with old versions of gcc. - */ -#define kFSEventsModified (kFSEventStreamEventFlagItemFinderInfoMod | \ - kFSEventStreamEventFlagItemModified | \ - kFSEventStreamEventFlagItemInodeMetaMod | \ - kFSEventStreamEventFlagItemChangeOwner | \ - kFSEventStreamEventFlagItemXattrMod) - -#define kFSEventsRenamed (kFSEventStreamEventFlagItemCreated | \ - kFSEventStreamEventFlagItemRemoved | \ - kFSEventStreamEventFlagItemRenamed) - -#define kFSEventsSystem (kFSEventStreamEventFlagUserDropped | \ - kFSEventStreamEventFlagKernelDropped | \ - kFSEventStreamEventFlagEventIdsWrapped | \ - kFSEventStreamEventFlagHistoryDone | \ - kFSEventStreamEventFlagMount | \ - kFSEventStreamEventFlagUnmount | \ - kFSEventStreamEventFlagRootChanged) - -typedef struct uv__fsevents_event_s uv__fsevents_event_t; -typedef struct uv__cf_loop_signal_s uv__cf_loop_signal_t; -typedef struct uv__cf_loop_state_s uv__cf_loop_state_t; - -enum uv__cf_loop_signal_type_e { - kUVCFLoopSignalRegular, - kUVCFLoopSignalClosing -}; -typedef enum uv__cf_loop_signal_type_e uv__cf_loop_signal_type_t; - -struct uv__cf_loop_signal_s { - QUEUE member; - uv_fs_event_t* handle; - uv__cf_loop_signal_type_t type; -}; - -struct uv__fsevents_event_s { - QUEUE member; - int events; - char path[1]; -}; - -struct uv__cf_loop_state_s { - CFRunLoopRef loop; - CFRunLoopSourceRef signal_source; - int fsevent_need_reschedule; - FSEventStreamRef fsevent_stream; - uv_sem_t fsevent_sem; - uv_mutex_t fsevent_mutex; - void* fsevent_handles[2]; - unsigned int fsevent_handle_count; -}; - -/* Forward declarations */ -static void uv__cf_loop_cb(void* arg); -static void* uv__cf_loop_runner(void* arg); -static int uv__cf_loop_signal(uv_loop_t* loop, - uv_fs_event_t* handle, - uv__cf_loop_signal_type_t type); - -/* Lazy-loaded by uv__fsevents_global_init(). */ -static CFArrayRef (*pCFArrayCreate)(CFAllocatorRef, - const void**, - CFIndex, - const CFArrayCallBacks*); -static void (*pCFRelease)(CFTypeRef); -static void (*pCFRunLoopAddSource)(CFRunLoopRef, - CFRunLoopSourceRef, - CFStringRef); -static CFRunLoopRef (*pCFRunLoopGetCurrent)(void); -static void (*pCFRunLoopRemoveSource)(CFRunLoopRef, - CFRunLoopSourceRef, - CFStringRef); -static void (*pCFRunLoopRun)(void); -static CFRunLoopSourceRef (*pCFRunLoopSourceCreate)(CFAllocatorRef, - CFIndex, - CFRunLoopSourceContext*); -static void (*pCFRunLoopSourceSignal)(CFRunLoopSourceRef); -static void (*pCFRunLoopStop)(CFRunLoopRef); -static void (*pCFRunLoopWakeUp)(CFRunLoopRef); -static CFStringRef (*pCFStringCreateWithFileSystemRepresentation)( - CFAllocatorRef, - const char*); -static CFStringEncoding (*pCFStringGetSystemEncoding)(void); -static CFStringRef (*pkCFRunLoopDefaultMode); -static FSEventStreamRef (*pFSEventStreamCreate)(CFAllocatorRef, - FSEventStreamCallback, - FSEventStreamContext*, - CFArrayRef, - FSEventStreamEventId, - CFTimeInterval, - FSEventStreamCreateFlags); -static void (*pFSEventStreamFlushSync)(FSEventStreamRef); -static void (*pFSEventStreamInvalidate)(FSEventStreamRef); -static void (*pFSEventStreamRelease)(FSEventStreamRef); -static void (*pFSEventStreamScheduleWithRunLoop)(FSEventStreamRef, - CFRunLoopRef, - CFStringRef); -static Boolean (*pFSEventStreamStart)(FSEventStreamRef); -static void (*pFSEventStreamStop)(FSEventStreamRef); - -#define UV__FSEVENTS_PROCESS(handle, block) \ - do { \ - QUEUE events; \ - QUEUE* q; \ - uv__fsevents_event_t* event; \ - int err; \ - uv_mutex_lock(&(handle)->cf_mutex); \ - /* Split-off all events and empty original queue */ \ - QUEUE_MOVE(&(handle)->cf_events, &events); \ - /* Get error (if any) and zero original one */ \ - err = (handle)->cf_error; \ - (handle)->cf_error = 0; \ - uv_mutex_unlock(&(handle)->cf_mutex); \ - /* Loop through events, deallocating each after processing */ \ - while (!QUEUE_EMPTY(&events)) { \ - q = QUEUE_HEAD(&events); \ - event = QUEUE_DATA(q, uv__fsevents_event_t, member); \ - QUEUE_REMOVE(q); \ - /* NOTE: Checking uv__is_active() is required here, because handle \ - * callback may close handle and invoking it after it will lead to \ - * incorrect behaviour */ \ - if (!uv__is_closing((handle)) && uv__is_active((handle))) \ - block \ - /* Free allocated data */ \ - uv__free(event); \ - } \ - if (err != 0 && !uv__is_closing((handle)) && uv__is_active((handle))) \ - (handle)->cb((handle), NULL, 0, err); \ - } while (0) - - -/* Runs in UV loop's thread, when there're events to report to handle */ -static void uv__fsevents_cb(uv_async_t* cb) { - uv_fs_event_t* handle; - - handle = cb->data; - - UV__FSEVENTS_PROCESS(handle, { - handle->cb(handle, event->path[0] ? event->path : NULL, event->events, 0); - }); -} - - -/* Runs in CF thread, pushed event into handle's event list */ -static void uv__fsevents_push_event(uv_fs_event_t* handle, - QUEUE* events, - int err) { - assert(events != NULL || err != 0); - uv_mutex_lock(&handle->cf_mutex); - - /* Concatenate two queues */ - if (events != NULL) - QUEUE_ADD(&handle->cf_events, events); - - /* Propagate error */ - if (err != 0) - handle->cf_error = err; - uv_mutex_unlock(&handle->cf_mutex); - - uv_async_send(handle->cf_cb); -} - - -/* Runs in CF thread, when there're events in FSEventStream */ -static void uv__fsevents_event_cb(ConstFSEventStreamRef streamRef, - void* info, - size_t numEvents, - void* eventPaths, - const FSEventStreamEventFlags eventFlags[], - const FSEventStreamEventId eventIds[]) { - size_t i; - int len; - char** paths; - char* path; - char* pos; - uv_fs_event_t* handle; - QUEUE* q; - uv_loop_t* loop; - uv__cf_loop_state_t* state; - uv__fsevents_event_t* event; - QUEUE head; - - loop = info; - state = loop->cf_state; - assert(state != NULL); - paths = eventPaths; - - /* For each handle */ - uv_mutex_lock(&state->fsevent_mutex); - QUEUE_FOREACH(q, &state->fsevent_handles) { - handle = QUEUE_DATA(q, uv_fs_event_t, cf_member); - QUEUE_INIT(&head); - - /* Process and filter out events */ - for (i = 0; i < numEvents; i++) { - /* Ignore system events */ - if (eventFlags[i] & kFSEventsSystem) - continue; - - path = paths[i]; - len = strlen(path); - - /* Filter out paths that are outside handle's request */ - if (strncmp(path, handle->realpath, handle->realpath_len) != 0) - continue; - - if (handle->realpath_len > 1 || *handle->realpath != '/') { - path += handle->realpath_len; - len -= handle->realpath_len; - - /* Skip forward slash */ - if (*path != '\0') { - path++; - len--; - } - } - -#ifdef MAC_OS_X_VERSION_10_7 - /* Ignore events with path equal to directory itself */ - if (len == 0) - continue; -#endif /* MAC_OS_X_VERSION_10_7 */ - - /* Do not emit events from subdirectories (without option set) */ - if ((handle->cf_flags & UV_FS_EVENT_RECURSIVE) == 0 && *path != 0) { - pos = strchr(path + 1, '/'); - if (pos != NULL) - continue; - } - -#ifndef MAC_OS_X_VERSION_10_7 - path = ""; - len = 0; -#endif /* MAC_OS_X_VERSION_10_7 */ - - event = uv__malloc(sizeof(*event) + len); - if (event == NULL) - break; - - memset(event, 0, sizeof(*event)); - memcpy(event->path, path, len + 1); - - if ((eventFlags[i] & kFSEventsModified) != 0 && - (eventFlags[i] & kFSEventsRenamed) == 0) - event->events = UV_CHANGE; - else - event->events = UV_RENAME; - - QUEUE_INSERT_TAIL(&head, &event->member); - } - - if (!QUEUE_EMPTY(&head)) - uv__fsevents_push_event(handle, &head, 0); - } - uv_mutex_unlock(&state->fsevent_mutex); -} - - -/* Runs in CF thread */ -static int uv__fsevents_create_stream(uv_loop_t* loop, CFArrayRef paths) { - uv__cf_loop_state_t* state; - FSEventStreamContext ctx; - FSEventStreamRef ref; - CFAbsoluteTime latency; - FSEventStreamCreateFlags flags; - - /* Initialize context */ - ctx.version = 0; - ctx.info = loop; - ctx.retain = NULL; - ctx.release = NULL; - ctx.copyDescription = NULL; - - latency = 0.05; - - /* Explanation of selected flags: - * 1. NoDefer - without this flag, events that are happening continuously - * (i.e. each event is happening after time interval less than `latency`, - * counted from previous event), will be deferred and passed to callback - * once they'll either fill whole OS buffer, or when this continuous stream - * will stop (i.e. there'll be delay between events, bigger than - * `latency`). - * Specifying this flag will invoke callback after `latency` time passed - * since event. - * 2. FileEvents - fire callback for file changes too (by default it is firing - * it only for directory changes). - */ - flags = kFSEventStreamCreateFlagNoDefer | kFSEventStreamCreateFlagFileEvents; - - /* - * NOTE: It might sound like a good idea to remember last seen StreamEventId, - * but in reality one dir might have last StreamEventId less than, the other, - * that is being watched now. Which will cause FSEventStream API to report - * changes to files from the past. - */ - ref = pFSEventStreamCreate(NULL, - &uv__fsevents_event_cb, - &ctx, - paths, - kFSEventStreamEventIdSinceNow, - latency, - flags); - assert(ref != NULL); - - state = loop->cf_state; - pFSEventStreamScheduleWithRunLoop(ref, - state->loop, - *pkCFRunLoopDefaultMode); - if (!pFSEventStreamStart(ref)) { - pFSEventStreamInvalidate(ref); - pFSEventStreamRelease(ref); - return -EMFILE; - } - - state->fsevent_stream = ref; - return 0; -} - - -/* Runs in CF thread */ -static void uv__fsevents_destroy_stream(uv_loop_t* loop) { - uv__cf_loop_state_t* state; - - state = loop->cf_state; - - if (state->fsevent_stream == NULL) - return; - - /* Flush all accumulated events */ - pFSEventStreamFlushSync(state->fsevent_stream); - - /* Stop emitting events */ - pFSEventStreamStop(state->fsevent_stream); - - /* Release stream */ - pFSEventStreamInvalidate(state->fsevent_stream); - pFSEventStreamRelease(state->fsevent_stream); - state->fsevent_stream = NULL; -} - - -/* Runs in CF thread, when there're new fsevent handles to add to stream */ -static void uv__fsevents_reschedule(uv_fs_event_t* handle, - uv__cf_loop_signal_type_t type) { - uv__cf_loop_state_t* state; - QUEUE* q; - uv_fs_event_t* curr; - CFArrayRef cf_paths; - CFStringRef* paths; - unsigned int i; - int err; - unsigned int path_count; - - state = handle->loop->cf_state; - paths = NULL; - cf_paths = NULL; - err = 0; - /* NOTE: `i` is used in deallocation loop below */ - i = 0; - - /* Optimization to prevent O(n^2) time spent when starting to watch - * many files simultaneously - */ - uv_mutex_lock(&state->fsevent_mutex); - if (state->fsevent_need_reschedule == 0) { - uv_mutex_unlock(&state->fsevent_mutex); - goto final; - } - state->fsevent_need_reschedule = 0; - uv_mutex_unlock(&state->fsevent_mutex); - - /* Destroy previous FSEventStream */ - uv__fsevents_destroy_stream(handle->loop); - - /* Any failure below will be a memory failure */ - err = -ENOMEM; - - /* Create list of all watched paths */ - uv_mutex_lock(&state->fsevent_mutex); - path_count = state->fsevent_handle_count; - if (path_count != 0) { - paths = uv__malloc(sizeof(*paths) * path_count); - if (paths == NULL) { - uv_mutex_unlock(&state->fsevent_mutex); - goto final; - } - - q = &state->fsevent_handles; - for (; i < path_count; i++) { - q = QUEUE_NEXT(q); - assert(q != &state->fsevent_handles); - curr = QUEUE_DATA(q, uv_fs_event_t, cf_member); - - assert(curr->realpath != NULL); - paths[i] = - pCFStringCreateWithFileSystemRepresentation(NULL, curr->realpath); - if (paths[i] == NULL) { - uv_mutex_unlock(&state->fsevent_mutex); - goto final; - } - } - } - uv_mutex_unlock(&state->fsevent_mutex); - err = 0; - - if (path_count != 0) { - /* Create new FSEventStream */ - cf_paths = pCFArrayCreate(NULL, (const void**) paths, path_count, NULL); - if (cf_paths == NULL) { - err = -ENOMEM; - goto final; - } - err = uv__fsevents_create_stream(handle->loop, cf_paths); - } - -final: - /* Deallocate all paths in case of failure */ - if (err != 0) { - if (cf_paths == NULL) { - while (i != 0) - pCFRelease(paths[--i]); - uv__free(paths); - } else { - /* CFArray takes ownership of both strings and original C-array */ - pCFRelease(cf_paths); - } - - /* Broadcast error to all handles */ - uv_mutex_lock(&state->fsevent_mutex); - QUEUE_FOREACH(q, &state->fsevent_handles) { - curr = QUEUE_DATA(q, uv_fs_event_t, cf_member); - uv__fsevents_push_event(curr, NULL, err); - } - uv_mutex_unlock(&state->fsevent_mutex); - } - - /* - * Main thread will block until the removal of handle from the list, - * we must tell it when we're ready. - * - * NOTE: This is coupled with `uv_sem_wait()` in `uv__fsevents_close` - */ - if (type == kUVCFLoopSignalClosing) - uv_sem_post(&state->fsevent_sem); -} - - -static int uv__fsevents_global_init(void) { - static pthread_mutex_t global_init_mutex = PTHREAD_MUTEX_INITIALIZER; - static void* core_foundation_handle; - static void* core_services_handle; - int err; - - err = 0; - pthread_mutex_lock(&global_init_mutex); - if (core_foundation_handle != NULL) - goto out; - - /* The libraries are never unloaded because we currently don't have a good - * mechanism for keeping a reference count. It's unlikely to be an issue - * but if it ever becomes one, we can turn the dynamic library handles into - * per-event loop properties and have the dynamic linker keep track for us. - */ - err = -ENOSYS; - core_foundation_handle = dlopen("/System/Library/Frameworks/" - "CoreFoundation.framework/" - "Versions/A/CoreFoundation", - RTLD_LAZY | RTLD_LOCAL); - if (core_foundation_handle == NULL) - goto out; - - core_services_handle = dlopen("/System/Library/Frameworks/" - "CoreServices.framework/" - "Versions/A/CoreServices", - RTLD_LAZY | RTLD_LOCAL); - if (core_services_handle == NULL) - goto out; - - err = -ENOENT; -#define V(handle, symbol) \ - do { \ - *(void **)(&p ## symbol) = dlsym((handle), #symbol); \ - if (p ## symbol == NULL) \ - goto out; \ - } \ - while (0) - V(core_foundation_handle, CFArrayCreate); - V(core_foundation_handle, CFRelease); - V(core_foundation_handle, CFRunLoopAddSource); - V(core_foundation_handle, CFRunLoopGetCurrent); - V(core_foundation_handle, CFRunLoopRemoveSource); - V(core_foundation_handle, CFRunLoopRun); - V(core_foundation_handle, CFRunLoopSourceCreate); - V(core_foundation_handle, CFRunLoopSourceSignal); - V(core_foundation_handle, CFRunLoopStop); - V(core_foundation_handle, CFRunLoopWakeUp); - V(core_foundation_handle, CFStringCreateWithFileSystemRepresentation); - V(core_foundation_handle, CFStringGetSystemEncoding); - V(core_foundation_handle, kCFRunLoopDefaultMode); - V(core_services_handle, FSEventStreamCreate); - V(core_services_handle, FSEventStreamFlushSync); - V(core_services_handle, FSEventStreamInvalidate); - V(core_services_handle, FSEventStreamRelease); - V(core_services_handle, FSEventStreamScheduleWithRunLoop); - V(core_services_handle, FSEventStreamStart); - V(core_services_handle, FSEventStreamStop); -#undef V - err = 0; - -out: - if (err && core_services_handle != NULL) { - dlclose(core_services_handle); - core_services_handle = NULL; - } - - if (err && core_foundation_handle != NULL) { - dlclose(core_foundation_handle); - core_foundation_handle = NULL; - } - - pthread_mutex_unlock(&global_init_mutex); - return err; -} - - -/* Runs in UV loop */ -static int uv__fsevents_loop_init(uv_loop_t* loop) { - CFRunLoopSourceContext ctx; - uv__cf_loop_state_t* state; - pthread_attr_t attr_storage; - pthread_attr_t* attr; - int err; - - if (loop->cf_state != NULL) - return 0; - - err = uv__fsevents_global_init(); - if (err) - return err; - - state = uv__calloc(1, sizeof(*state)); - if (state == NULL) - return -ENOMEM; - - err = uv_mutex_init(&loop->cf_mutex); - if (err) - goto fail_mutex_init; - - err = uv_sem_init(&loop->cf_sem, 0); - if (err) - goto fail_sem_init; - - QUEUE_INIT(&loop->cf_signals); - - err = uv_sem_init(&state->fsevent_sem, 0); - if (err) - goto fail_fsevent_sem_init; - - err = uv_mutex_init(&state->fsevent_mutex); - if (err) - goto fail_fsevent_mutex_init; - - QUEUE_INIT(&state->fsevent_handles); - state->fsevent_need_reschedule = 0; - state->fsevent_handle_count = 0; - - memset(&ctx, 0, sizeof(ctx)); - ctx.info = loop; - ctx.perform = uv__cf_loop_cb; - state->signal_source = pCFRunLoopSourceCreate(NULL, 0, &ctx); - if (state->signal_source == NULL) { - err = -ENOMEM; - goto fail_signal_source_create; - } - - /* In the unlikely event that pthread_attr_init() fails, create the thread - * with the default stack size. We'll use a little more address space but - * that in itself is not a fatal error. - */ - attr = &attr_storage; - if (pthread_attr_init(attr)) - attr = NULL; - - if (attr != NULL) - if (pthread_attr_setstacksize(attr, 4 * PTHREAD_STACK_MIN)) - abort(); - - loop->cf_state = state; - - /* uv_thread_t is an alias for pthread_t. */ - err = -pthread_create(&loop->cf_thread, attr, uv__cf_loop_runner, loop); - - if (attr != NULL) - pthread_attr_destroy(attr); - - if (err) - goto fail_thread_create; - - /* Synchronize threads */ - uv_sem_wait(&loop->cf_sem); - return 0; - -fail_thread_create: - loop->cf_state = NULL; - -fail_signal_source_create: - uv_mutex_destroy(&state->fsevent_mutex); - -fail_fsevent_mutex_init: - uv_sem_destroy(&state->fsevent_sem); - -fail_fsevent_sem_init: - uv_sem_destroy(&loop->cf_sem); - -fail_sem_init: - uv_mutex_destroy(&loop->cf_mutex); - -fail_mutex_init: - uv__free(state); - return err; -} - - -/* Runs in UV loop */ -void uv__fsevents_loop_delete(uv_loop_t* loop) { - uv__cf_loop_signal_t* s; - uv__cf_loop_state_t* state; - QUEUE* q; - - if (loop->cf_state == NULL) - return; - - if (uv__cf_loop_signal(loop, NULL, kUVCFLoopSignalRegular) != 0) - abort(); - - uv_thread_join(&loop->cf_thread); - uv_sem_destroy(&loop->cf_sem); - uv_mutex_destroy(&loop->cf_mutex); - - /* Free any remaining data */ - while (!QUEUE_EMPTY(&loop->cf_signals)) { - q = QUEUE_HEAD(&loop->cf_signals); - s = QUEUE_DATA(q, uv__cf_loop_signal_t, member); - QUEUE_REMOVE(q); - uv__free(s); - } - - /* Destroy state */ - state = loop->cf_state; - uv_sem_destroy(&state->fsevent_sem); - uv_mutex_destroy(&state->fsevent_mutex); - pCFRelease(state->signal_source); - uv__free(state); - loop->cf_state = NULL; -} - - -/* Runs in CF thread. This is the CF loop's body */ -static void* uv__cf_loop_runner(void* arg) { - uv_loop_t* loop; - uv__cf_loop_state_t* state; - - loop = arg; - state = loop->cf_state; - state->loop = pCFRunLoopGetCurrent(); - - pCFRunLoopAddSource(state->loop, - state->signal_source, - *pkCFRunLoopDefaultMode); - - uv_sem_post(&loop->cf_sem); - - pCFRunLoopRun(); - pCFRunLoopRemoveSource(state->loop, - state->signal_source, - *pkCFRunLoopDefaultMode); - - return NULL; -} - - -/* Runs in CF thread, executed after `uv__cf_loop_signal()` */ -static void uv__cf_loop_cb(void* arg) { - uv_loop_t* loop; - uv__cf_loop_state_t* state; - QUEUE* item; - QUEUE split_head; - uv__cf_loop_signal_t* s; - - loop = arg; - state = loop->cf_state; - - uv_mutex_lock(&loop->cf_mutex); - QUEUE_MOVE(&loop->cf_signals, &split_head); - uv_mutex_unlock(&loop->cf_mutex); - - while (!QUEUE_EMPTY(&split_head)) { - item = QUEUE_HEAD(&split_head); - QUEUE_REMOVE(item); - - s = QUEUE_DATA(item, uv__cf_loop_signal_t, member); - - /* This was a termination signal */ - if (s->handle == NULL) - pCFRunLoopStop(state->loop); - else - uv__fsevents_reschedule(s->handle, s->type); - - uv__free(s); - } -} - - -/* Runs in UV loop to notify CF thread */ -int uv__cf_loop_signal(uv_loop_t* loop, - uv_fs_event_t* handle, - uv__cf_loop_signal_type_t type) { - uv__cf_loop_signal_t* item; - uv__cf_loop_state_t* state; - - item = uv__malloc(sizeof(*item)); - if (item == NULL) - return -ENOMEM; - - item->handle = handle; - item->type = type; - - uv_mutex_lock(&loop->cf_mutex); - QUEUE_INSERT_TAIL(&loop->cf_signals, &item->member); - uv_mutex_unlock(&loop->cf_mutex); - - state = loop->cf_state; - assert(state != NULL); - pCFRunLoopSourceSignal(state->signal_source); - pCFRunLoopWakeUp(state->loop); - - return 0; -} - - -/* Runs in UV loop to initialize handle */ -int uv__fsevents_init(uv_fs_event_t* handle) { - int err; - uv__cf_loop_state_t* state; - - err = uv__fsevents_loop_init(handle->loop); - if (err) - return err; - - /* Get absolute path to file */ - handle->realpath = realpath(handle->path, NULL); - if (handle->realpath == NULL) - return -errno; - handle->realpath_len = strlen(handle->realpath); - - /* Initialize event queue */ - QUEUE_INIT(&handle->cf_events); - handle->cf_error = 0; - - /* - * Events will occur in other thread. - * Initialize callback for getting them back into event loop's thread - */ - handle->cf_cb = uv__malloc(sizeof(*handle->cf_cb)); - if (handle->cf_cb == NULL) { - err = -ENOMEM; - goto fail_cf_cb_malloc; - } - - handle->cf_cb->data = handle; - uv_async_init(handle->loop, handle->cf_cb, uv__fsevents_cb); - handle->cf_cb->flags |= UV__HANDLE_INTERNAL; - uv_unref((uv_handle_t*) handle->cf_cb); - - err = uv_mutex_init(&handle->cf_mutex); - if (err) - goto fail_cf_mutex_init; - - /* Insert handle into the list */ - state = handle->loop->cf_state; - uv_mutex_lock(&state->fsevent_mutex); - QUEUE_INSERT_TAIL(&state->fsevent_handles, &handle->cf_member); - state->fsevent_handle_count++; - state->fsevent_need_reschedule = 1; - uv_mutex_unlock(&state->fsevent_mutex); - - /* Reschedule FSEventStream */ - assert(handle != NULL); - err = uv__cf_loop_signal(handle->loop, handle, kUVCFLoopSignalRegular); - if (err) - goto fail_loop_signal; - - return 0; - -fail_loop_signal: - uv_mutex_destroy(&handle->cf_mutex); - -fail_cf_mutex_init: - uv__free(handle->cf_cb); - handle->cf_cb = NULL; - -fail_cf_cb_malloc: - uv__free(handle->realpath); - handle->realpath = NULL; - handle->realpath_len = 0; - - return err; -} - - -/* Runs in UV loop to de-initialize handle */ -int uv__fsevents_close(uv_fs_event_t* handle) { - int err; - uv__cf_loop_state_t* state; - - if (handle->cf_cb == NULL) - return -EINVAL; - - /* Remove handle from the list */ - state = handle->loop->cf_state; - uv_mutex_lock(&state->fsevent_mutex); - QUEUE_REMOVE(&handle->cf_member); - state->fsevent_handle_count--; - state->fsevent_need_reschedule = 1; - uv_mutex_unlock(&state->fsevent_mutex); - - /* Reschedule FSEventStream */ - assert(handle != NULL); - err = uv__cf_loop_signal(handle->loop, handle, kUVCFLoopSignalClosing); - if (err) - return -err; - - /* Wait for deinitialization */ - uv_sem_wait(&state->fsevent_sem); - - uv_close((uv_handle_t*) handle->cf_cb, (uv_close_cb) uv__free); - handle->cf_cb = NULL; - - /* Free data in queue */ - UV__FSEVENTS_PROCESS(handle, { - /* NOP */ - }); - - uv_mutex_destroy(&handle->cf_mutex); - uv__free(handle->realpath); - handle->realpath = NULL; - handle->realpath_len = 0; - - return 0; -} - -#endif /* TARGET_OS_IPHONE */ diff --git a/vendor/libuv/src/unix/getaddrinfo.c b/vendor/libuv/src/unix/getaddrinfo.c deleted file mode 100644 index 2049aea2f..000000000 --- a/vendor/libuv/src/unix/getaddrinfo.c +++ /dev/null @@ -1,202 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -/* Expose glibc-specific EAI_* error codes. Needs to be defined before we - * include any headers. - */ -#ifndef _GNU_SOURCE -# define _GNU_SOURCE -#endif - -#include "uv.h" -#include "internal.h" - -#include -#include /* NULL */ -#include -#include - -/* EAI_* constants. */ -#include - - -int uv__getaddrinfo_translate_error(int sys_err) { - switch (sys_err) { - case 0: return 0; -#if defined(EAI_ADDRFAMILY) - case EAI_ADDRFAMILY: return UV_EAI_ADDRFAMILY; -#endif -#if defined(EAI_AGAIN) - case EAI_AGAIN: return UV_EAI_AGAIN; -#endif -#if defined(EAI_BADFLAGS) - case EAI_BADFLAGS: return UV_EAI_BADFLAGS; -#endif -#if defined(EAI_BADHINTS) - case EAI_BADHINTS: return UV_EAI_BADHINTS; -#endif -#if defined(EAI_CANCELED) - case EAI_CANCELED: return UV_EAI_CANCELED; -#endif -#if defined(EAI_FAIL) - case EAI_FAIL: return UV_EAI_FAIL; -#endif -#if defined(EAI_FAMILY) - case EAI_FAMILY: return UV_EAI_FAMILY; -#endif -#if defined(EAI_MEMORY) - case EAI_MEMORY: return UV_EAI_MEMORY; -#endif -#if defined(EAI_NODATA) - case EAI_NODATA: return UV_EAI_NODATA; -#endif -#if defined(EAI_NONAME) -# if !defined(EAI_NODATA) || EAI_NODATA != EAI_NONAME - case EAI_NONAME: return UV_EAI_NONAME; -# endif -#endif -#if defined(EAI_OVERFLOW) - case EAI_OVERFLOW: return UV_EAI_OVERFLOW; -#endif -#if defined(EAI_PROTOCOL) - case EAI_PROTOCOL: return UV_EAI_PROTOCOL; -#endif -#if defined(EAI_SERVICE) - case EAI_SERVICE: return UV_EAI_SERVICE; -#endif -#if defined(EAI_SOCKTYPE) - case EAI_SOCKTYPE: return UV_EAI_SOCKTYPE; -#endif -#if defined(EAI_SYSTEM) - case EAI_SYSTEM: return -errno; -#endif - } - assert(!"unknown EAI_* error code"); - abort(); - return 0; /* Pacify compiler. */ -} - - -static void uv__getaddrinfo_work(struct uv__work* w) { - uv_getaddrinfo_t* req; - int err; - - req = container_of(w, uv_getaddrinfo_t, work_req); - err = getaddrinfo(req->hostname, req->service, req->hints, &req->addrinfo); - req->retcode = uv__getaddrinfo_translate_error(err); -} - - -static void uv__getaddrinfo_done(struct uv__work* w, int status) { - uv_getaddrinfo_t* req; - - req = container_of(w, uv_getaddrinfo_t, work_req); - uv__req_unregister(req->loop, req); - - /* See initialization in uv_getaddrinfo(). */ - if (req->hints) - uv__free(req->hints); - else if (req->service) - uv__free(req->service); - else if (req->hostname) - uv__free(req->hostname); - else - assert(0); - - req->hints = NULL; - req->service = NULL; - req->hostname = NULL; - - if (status == -ECANCELED) { - assert(req->retcode == 0); - req->retcode = UV_EAI_CANCELED; - } - - if (req->cb) - req->cb(req, req->retcode, req->addrinfo); -} - - -int uv_getaddrinfo(uv_loop_t* loop, - uv_getaddrinfo_t* req, - uv_getaddrinfo_cb cb, - const char* hostname, - const char* service, - const struct addrinfo* hints) { - size_t hostname_len; - size_t service_len; - size_t hints_len; - size_t len; - char* buf; - - if (req == NULL || (hostname == NULL && service == NULL)) - return -EINVAL; - - hostname_len = hostname ? strlen(hostname) + 1 : 0; - service_len = service ? strlen(service) + 1 : 0; - hints_len = hints ? sizeof(*hints) : 0; - buf = uv__malloc(hostname_len + service_len + hints_len); - - if (buf == NULL) - return -ENOMEM; - - uv__req_init(loop, req, UV_GETADDRINFO); - req->loop = loop; - req->cb = cb; - req->addrinfo = NULL; - req->hints = NULL; - req->service = NULL; - req->hostname = NULL; - req->retcode = 0; - - /* order matters, see uv_getaddrinfo_done() */ - len = 0; - - if (hints) { - req->hints = memcpy(buf + len, hints, sizeof(*hints)); - len += sizeof(*hints); - } - - if (service) { - req->service = memcpy(buf + len, service, service_len); - len += service_len; - } - - if (hostname) - req->hostname = memcpy(buf + len, hostname, hostname_len); - - if (cb) { - uv__work_submit(loop, - &req->work_req, - uv__getaddrinfo_work, - uv__getaddrinfo_done); - return 0; - } else { - uv__getaddrinfo_work(&req->work_req); - uv__getaddrinfo_done(&req->work_req, 0); - return req->retcode; - } -} - - -void uv_freeaddrinfo(struct addrinfo* ai) { - if (ai) - freeaddrinfo(ai); -} diff --git a/vendor/libuv/src/unix/getnameinfo.c b/vendor/libuv/src/unix/getnameinfo.c deleted file mode 100644 index daa798a45..000000000 --- a/vendor/libuv/src/unix/getnameinfo.c +++ /dev/null @@ -1,120 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to -* deal in the Software without restriction, including without limitation the -* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -* sell copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -* IN THE SOFTWARE. -*/ - -#include -#include -#include -#include - -#include "uv.h" -#include "internal.h" - - -static void uv__getnameinfo_work(struct uv__work* w) { - uv_getnameinfo_t* req; - int err; - socklen_t salen; - - req = container_of(w, uv_getnameinfo_t, work_req); - - if (req->storage.ss_family == AF_INET) - salen = sizeof(struct sockaddr_in); - else if (req->storage.ss_family == AF_INET6) - salen = sizeof(struct sockaddr_in6); - else - abort(); - - err = getnameinfo((struct sockaddr*) &req->storage, - salen, - req->host, - sizeof(req->host), - req->service, - sizeof(req->service), - req->flags); - req->retcode = uv__getaddrinfo_translate_error(err); -} - -static void uv__getnameinfo_done(struct uv__work* w, int status) { - uv_getnameinfo_t* req; - char* host; - char* service; - - req = container_of(w, uv_getnameinfo_t, work_req); - uv__req_unregister(req->loop, req); - host = service = NULL; - - if (status == -ECANCELED) { - assert(req->retcode == 0); - req->retcode = UV_EAI_CANCELED; - } else if (req->retcode == 0) { - host = req->host; - service = req->service; - } - - if (req->getnameinfo_cb) - req->getnameinfo_cb(req, req->retcode, host, service); -} - -/* -* Entry point for getnameinfo -* return 0 if a callback will be made -* return error code if validation fails -*/ -int uv_getnameinfo(uv_loop_t* loop, - uv_getnameinfo_t* req, - uv_getnameinfo_cb getnameinfo_cb, - const struct sockaddr* addr, - int flags) { - if (req == NULL || addr == NULL) - return UV_EINVAL; - - if (addr->sa_family == AF_INET) { - memcpy(&req->storage, - addr, - sizeof(struct sockaddr_in)); - } else if (addr->sa_family == AF_INET6) { - memcpy(&req->storage, - addr, - sizeof(struct sockaddr_in6)); - } else { - return UV_EINVAL; - } - - uv__req_init(loop, (uv_req_t*)req, UV_GETNAMEINFO); - - req->getnameinfo_cb = getnameinfo_cb; - req->flags = flags; - req->type = UV_GETNAMEINFO; - req->loop = loop; - req->retcode = 0; - - if (getnameinfo_cb) { - uv__work_submit(loop, - &req->work_req, - uv__getnameinfo_work, - uv__getnameinfo_done); - return 0; - } else { - uv__getnameinfo_work(&req->work_req); - uv__getnameinfo_done(&req->work_req, 0); - return req->retcode; - } -} diff --git a/vendor/libuv/src/unix/internal.h b/vendor/libuv/src/unix/internal.h deleted file mode 100644 index 1188e8fe7..000000000 --- a/vendor/libuv/src/unix/internal.h +++ /dev/null @@ -1,329 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef UV_UNIX_INTERNAL_H_ -#define UV_UNIX_INTERNAL_H_ - -#include "uv-common.h" - -#include -#include /* abort */ -#include /* strrchr */ -#include /* O_CLOEXEC, may be */ -#include - -#if defined(__STRICT_ANSI__) -# define inline __inline -#endif - -#if defined(__linux__) -# include "linux-syscalls.h" -#endif /* __linux__ */ - -#if defined(__MVS__) -# include "os390-syscalls.h" -#endif /* __MVS__ */ - -#if defined(__sun) -# include -# include -#endif /* __sun */ - -#if defined(_AIX) -# define reqevents events -# define rtnevents revents -# include -#else -# include -#endif /* _AIX */ - -#if defined(__APPLE__) && !TARGET_OS_IPHONE -# include -#endif - -#if defined(__ANDROID__) -int uv__pthread_sigmask(int how, const sigset_t* set, sigset_t* oset); -# ifdef pthread_sigmask -# undef pthread_sigmask -# endif -# define pthread_sigmask(how, set, oldset) uv__pthread_sigmask(how, set, oldset) -#endif - -#define ACCESS_ONCE(type, var) \ - (*(volatile type*) &(var)) - -#define ROUND_UP(a, b) \ - ((a) % (b) ? ((a) + (b)) - ((a) % (b)) : (a)) - -#define UNREACHABLE() \ - do { \ - assert(0 && "unreachable code"); \ - abort(); \ - } \ - while (0) - -#define SAVE_ERRNO(block) \ - do { \ - int _saved_errno = errno; \ - do { block; } while (0); \ - errno = _saved_errno; \ - } \ - while (0) - -/* The __clang__ and __INTEL_COMPILER checks are superfluous because they - * define __GNUC__. They are here to convey to you, dear reader, that these - * macros are enabled when compiling with clang or icc. - */ -#if defined(__clang__) || \ - defined(__GNUC__) || \ - defined(__INTEL_COMPILER) || \ - defined(__SUNPRO_C) -# define UV_DESTRUCTOR(declaration) __attribute__((destructor)) declaration -# define UV_UNUSED(declaration) __attribute__((unused)) declaration -#else -# define UV_DESTRUCTOR(declaration) declaration -# define UV_UNUSED(declaration) declaration -#endif - -/* Leans on the fact that, on Linux, POLLRDHUP == EPOLLRDHUP. */ -#ifdef POLLRDHUP -# define UV__POLLRDHUP POLLRDHUP -#else -# define UV__POLLRDHUP 0x2000 -#endif - -#if !defined(O_CLOEXEC) && defined(__FreeBSD__) -/* - * It may be that we are just missing `__POSIX_VISIBLE >= 200809`. - * Try using fixed value const and give up, if it doesn't work - */ -# define O_CLOEXEC 0x00100000 -#endif - -typedef struct uv__stream_queued_fds_s uv__stream_queued_fds_t; - -/* handle flags */ -enum { - UV_CLOSING = 0x01, /* uv_close() called but not finished. */ - UV_CLOSED = 0x02, /* close(2) finished. */ - UV_STREAM_READING = 0x04, /* uv_read_start() called. */ - UV_STREAM_SHUTTING = 0x08, /* uv_shutdown() called but not complete. */ - UV_STREAM_SHUT = 0x10, /* Write side closed. */ - UV_STREAM_READABLE = 0x20, /* The stream is readable */ - UV_STREAM_WRITABLE = 0x40, /* The stream is writable */ - UV_STREAM_BLOCKING = 0x80, /* Synchronous writes. */ - UV_STREAM_READ_PARTIAL = 0x100, /* read(2) read less than requested. */ - UV_STREAM_READ_EOF = 0x200, /* read(2) read EOF. */ - UV_TCP_NODELAY = 0x400, /* Disable Nagle. */ - UV_TCP_KEEPALIVE = 0x800, /* Turn on keep-alive. */ - UV_TCP_SINGLE_ACCEPT = 0x1000, /* Only accept() when idle. */ - UV_HANDLE_IPV6 = 0x10000, /* Handle is bound to a IPv6 socket. */ - UV_UDP_PROCESSING = 0x20000, /* Handle is running the send callback queue. */ - UV_HANDLE_BOUND = 0x40000 /* Handle is bound to an address and port */ -}; - -/* loop flags */ -enum { - UV_LOOP_BLOCK_SIGPROF = 1 -}; - -typedef enum { - UV_CLOCK_PRECISE = 0, /* Use the highest resolution clock available. */ - UV_CLOCK_FAST = 1 /* Use the fastest clock with <= 1ms granularity. */ -} uv_clocktype_t; - -struct uv__stream_queued_fds_s { - unsigned int size; - unsigned int offset; - int fds[1]; -}; - - -#if defined(_AIX) || \ - defined(__APPLE__) || \ - defined(__DragonFly__) || \ - defined(__FreeBSD__) || \ - defined(__FreeBSD_kernel__) || \ - defined(__linux__) -#define uv__cloexec uv__cloexec_ioctl -#define uv__nonblock uv__nonblock_ioctl -#else -#define uv__cloexec uv__cloexec_fcntl -#define uv__nonblock uv__nonblock_fcntl -#endif - -/* core */ -int uv__cloexec_ioctl(int fd, int set); -int uv__cloexec_fcntl(int fd, int set); -int uv__nonblock_ioctl(int fd, int set); -int uv__nonblock_fcntl(int fd, int set); -int uv__close(int fd); -int uv__close_nocheckstdio(int fd); -int uv__socket(int domain, int type, int protocol); -int uv__dup(int fd); -ssize_t uv__recvmsg(int fd, struct msghdr *msg, int flags); -void uv__make_close_pending(uv_handle_t* handle); -int uv__getiovmax(void); - -void uv__io_init(uv__io_t* w, uv__io_cb cb, int fd); -void uv__io_start(uv_loop_t* loop, uv__io_t* w, unsigned int events); -void uv__io_stop(uv_loop_t* loop, uv__io_t* w, unsigned int events); -void uv__io_close(uv_loop_t* loop, uv__io_t* w); -void uv__io_feed(uv_loop_t* loop, uv__io_t* w); -int uv__io_active(const uv__io_t* w, unsigned int events); -int uv__io_check_fd(uv_loop_t* loop, int fd); -void uv__io_poll(uv_loop_t* loop, int timeout); /* in milliseconds or -1 */ - -/* async */ -void uv__async_send(struct uv__async* wa); -void uv__async_init(struct uv__async* wa); -int uv__async_start(uv_loop_t* loop, struct uv__async* wa, uv__async_cb cb); -void uv__async_stop(uv_loop_t* loop, struct uv__async* wa); - -/* loop */ -void uv__run_idle(uv_loop_t* loop); -void uv__run_check(uv_loop_t* loop); -void uv__run_prepare(uv_loop_t* loop); - -/* stream */ -void uv__stream_init(uv_loop_t* loop, uv_stream_t* stream, - uv_handle_type type); -int uv__stream_open(uv_stream_t*, int fd, int flags); -void uv__stream_destroy(uv_stream_t* stream); -#if defined(__APPLE__) -int uv__stream_try_select(uv_stream_t* stream, int* fd); -#endif /* defined(__APPLE__) */ -void uv__server_io(uv_loop_t* loop, uv__io_t* w, unsigned int events); -int uv__accept(int sockfd); -int uv__dup2_cloexec(int oldfd, int newfd); -int uv__open_cloexec(const char* path, int flags); - -/* tcp */ -int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb); -int uv__tcp_nodelay(int fd, int on); -int uv__tcp_keepalive(int fd, int on, unsigned int delay); - -/* pipe */ -int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb); - -/* timer */ -void uv__run_timers(uv_loop_t* loop); -int uv__next_timeout(const uv_loop_t* loop); - -/* signal */ -void uv__signal_close(uv_signal_t* handle); -void uv__signal_global_once_init(void); -void uv__signal_loop_cleanup(uv_loop_t* loop); - -/* platform specific */ -uint64_t uv__hrtime(uv_clocktype_t type); -int uv__kqueue_init(uv_loop_t* loop); -int uv__platform_loop_init(uv_loop_t* loop); -void uv__platform_loop_delete(uv_loop_t* loop); -void uv__platform_invalidate_fd(uv_loop_t* loop, int fd); - -/* various */ -void uv__async_close(uv_async_t* handle); -void uv__check_close(uv_check_t* handle); -void uv__fs_event_close(uv_fs_event_t* handle); -void uv__idle_close(uv_idle_t* handle); -void uv__pipe_close(uv_pipe_t* handle); -void uv__poll_close(uv_poll_t* handle); -void uv__prepare_close(uv_prepare_t* handle); -void uv__process_close(uv_process_t* handle); -void uv__stream_close(uv_stream_t* handle); -void uv__tcp_close(uv_tcp_t* handle); -void uv__timer_close(uv_timer_t* handle); -void uv__udp_close(uv_udp_t* handle); -void uv__udp_finish_close(uv_udp_t* handle); -uv_handle_type uv__handle_type(int fd); -FILE* uv__open_file(const char* path); -int uv__getpwuid_r(uv_passwd_t* pwd); - - -#if defined(__APPLE__) -int uv___stream_fd(const uv_stream_t* handle); -#define uv__stream_fd(handle) (uv___stream_fd((const uv_stream_t*) (handle))) -#else -#define uv__stream_fd(handle) ((handle)->io_watcher.fd) -#endif /* defined(__APPLE__) */ - -#ifdef UV__O_NONBLOCK -# define UV__F_NONBLOCK UV__O_NONBLOCK -#else -# define UV__F_NONBLOCK 1 -#endif - -int uv__make_socketpair(int fds[2], int flags); -int uv__make_pipe(int fds[2], int flags); - -#if defined(__APPLE__) - -int uv__fsevents_init(uv_fs_event_t* handle); -int uv__fsevents_close(uv_fs_event_t* handle); -void uv__fsevents_loop_delete(uv_loop_t* loop); - -/* OSX < 10.7 has no file events, polyfill them */ -#ifndef MAC_OS_X_VERSION_10_7 - -static const int kFSEventStreamCreateFlagFileEvents = 0x00000010; -static const int kFSEventStreamEventFlagItemCreated = 0x00000100; -static const int kFSEventStreamEventFlagItemRemoved = 0x00000200; -static const int kFSEventStreamEventFlagItemInodeMetaMod = 0x00000400; -static const int kFSEventStreamEventFlagItemRenamed = 0x00000800; -static const int kFSEventStreamEventFlagItemModified = 0x00001000; -static const int kFSEventStreamEventFlagItemFinderInfoMod = 0x00002000; -static const int kFSEventStreamEventFlagItemChangeOwner = 0x00004000; -static const int kFSEventStreamEventFlagItemXattrMod = 0x00008000; -static const int kFSEventStreamEventFlagItemIsFile = 0x00010000; -static const int kFSEventStreamEventFlagItemIsDir = 0x00020000; -static const int kFSEventStreamEventFlagItemIsSymlink = 0x00040000; - -#endif /* __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1070 */ - -#endif /* defined(__APPLE__) */ - -UV_UNUSED(static void uv__req_init(uv_loop_t* loop, - uv_req_t* req, - uv_req_type type)) { - req->type = type; - uv__req_register(loop, req); -} -#define uv__req_init(loop, req, type) \ - uv__req_init((loop), (uv_req_t*)(req), (type)) - -UV_UNUSED(static void uv__update_time(uv_loop_t* loop)) { - /* Use a fast time source if available. We only need millisecond precision. - */ - loop->time = uv__hrtime(UV_CLOCK_FAST) / 1000000; -} - -UV_UNUSED(static char* uv__basename_r(const char* path)) { - char* s; - - s = strrchr(path, '/'); - if (s == NULL) - return (char*) path; - - return s + 1; -} - -#endif /* UV_UNIX_INTERNAL_H_ */ diff --git a/vendor/libuv/src/unix/kqueue.c b/vendor/libuv/src/unix/kqueue.c deleted file mode 100644 index fffd4626f..000000000 --- a/vendor/libuv/src/unix/kqueue.c +++ /dev/null @@ -1,463 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "internal.h" - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -static void uv__fs_event(uv_loop_t* loop, uv__io_t* w, unsigned int fflags); - - -int uv__kqueue_init(uv_loop_t* loop) { - loop->backend_fd = kqueue(); - if (loop->backend_fd == -1) - return -errno; - - uv__cloexec(loop->backend_fd, 1); - - return 0; -} - - -int uv__io_check_fd(uv_loop_t* loop, int fd) { - struct kevent ev; - int rc; - - rc = 0; - EV_SET(&ev, fd, EVFILT_READ, EV_ADD, 0, 0, 0); - if (kevent(loop->backend_fd, &ev, 1, NULL, 0, NULL)) - rc = -errno; - - EV_SET(&ev, fd, EVFILT_READ, EV_DELETE, 0, 0, 0); - if (rc == 0) - if (kevent(loop->backend_fd, &ev, 1, NULL, 0, NULL)) - abort(); - - return rc; -} - - -void uv__io_poll(uv_loop_t* loop, int timeout) { - struct kevent events[1024]; - struct kevent* ev; - struct timespec spec; - unsigned int nevents; - unsigned int revents; - QUEUE* q; - uv__io_t* w; - sigset_t* pset; - sigset_t set; - uint64_t base; - uint64_t diff; - int have_signals; - int filter; - int fflags; - int count; - int nfds; - int fd; - int op; - int i; - - if (loop->nfds == 0) { - assert(QUEUE_EMPTY(&loop->watcher_queue)); - return; - } - - nevents = 0; - - while (!QUEUE_EMPTY(&loop->watcher_queue)) { - q = QUEUE_HEAD(&loop->watcher_queue); - QUEUE_REMOVE(q); - QUEUE_INIT(q); - - w = QUEUE_DATA(q, uv__io_t, watcher_queue); - assert(w->pevents != 0); - assert(w->fd >= 0); - assert(w->fd < (int) loop->nwatchers); - - if ((w->events & POLLIN) == 0 && (w->pevents & POLLIN) != 0) { - filter = EVFILT_READ; - fflags = 0; - op = EV_ADD; - - if (w->cb == uv__fs_event) { - filter = EVFILT_VNODE; - fflags = NOTE_ATTRIB | NOTE_WRITE | NOTE_RENAME - | NOTE_DELETE | NOTE_EXTEND | NOTE_REVOKE; - op = EV_ADD | EV_ONESHOT; /* Stop the event from firing repeatedly. */ - } - - EV_SET(events + nevents, w->fd, filter, op, fflags, 0, 0); - - if (++nevents == ARRAY_SIZE(events)) { - if (kevent(loop->backend_fd, events, nevents, NULL, 0, NULL)) - abort(); - nevents = 0; - } - } - - if ((w->events & POLLOUT) == 0 && (w->pevents & POLLOUT) != 0) { - EV_SET(events + nevents, w->fd, EVFILT_WRITE, EV_ADD, 0, 0, 0); - - if (++nevents == ARRAY_SIZE(events)) { - if (kevent(loop->backend_fd, events, nevents, NULL, 0, NULL)) - abort(); - nevents = 0; - } - } - - w->events = w->pevents; - } - - pset = NULL; - if (loop->flags & UV_LOOP_BLOCK_SIGPROF) { - pset = &set; - sigemptyset(pset); - sigaddset(pset, SIGPROF); - } - - assert(timeout >= -1); - base = loop->time; - count = 48; /* Benchmarks suggest this gives the best throughput. */ - - for (;; nevents = 0) { - if (timeout != -1) { - spec.tv_sec = timeout / 1000; - spec.tv_nsec = (timeout % 1000) * 1000000; - } - - if (pset != NULL) - pthread_sigmask(SIG_BLOCK, pset, NULL); - - nfds = kevent(loop->backend_fd, - events, - nevents, - events, - ARRAY_SIZE(events), - timeout == -1 ? NULL : &spec); - - if (pset != NULL) - pthread_sigmask(SIG_UNBLOCK, pset, NULL); - - /* Update loop->time unconditionally. It's tempting to skip the update when - * timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the - * operating system didn't reschedule our process while in the syscall. - */ - SAVE_ERRNO(uv__update_time(loop)); - - if (nfds == 0) { - assert(timeout != -1); - return; - } - - if (nfds == -1) { - if (errno != EINTR) - abort(); - - if (timeout == 0) - return; - - if (timeout == -1) - continue; - - /* Interrupted by a signal. Update timeout and poll again. */ - goto update_timeout; - } - - have_signals = 0; - nevents = 0; - - assert(loop->watchers != NULL); - loop->watchers[loop->nwatchers] = (void*) events; - loop->watchers[loop->nwatchers + 1] = (void*) (uintptr_t) nfds; - for (i = 0; i < nfds; i++) { - ev = events + i; - fd = ev->ident; - /* Skip invalidated events, see uv__platform_invalidate_fd */ - if (fd == -1) - continue; - w = loop->watchers[fd]; - - if (w == NULL) { - /* File descriptor that we've stopped watching, disarm it. */ - /* TODO batch up */ - struct kevent events[1]; - - EV_SET(events + 0, fd, ev->filter, EV_DELETE, 0, 0, 0); - if (kevent(loop->backend_fd, events, 1, NULL, 0, NULL)) - if (errno != EBADF && errno != ENOENT) - abort(); - - continue; - } - - if (ev->filter == EVFILT_VNODE) { - assert(w->events == POLLIN); - assert(w->pevents == POLLIN); - w->cb(loop, w, ev->fflags); /* XXX always uv__fs_event() */ - nevents++; - continue; - } - - revents = 0; - - if (ev->filter == EVFILT_READ) { - if (w->pevents & POLLIN) { - revents |= POLLIN; - w->rcount = ev->data; - } else { - /* TODO batch up */ - struct kevent events[1]; - EV_SET(events + 0, fd, ev->filter, EV_DELETE, 0, 0, 0); - if (kevent(loop->backend_fd, events, 1, NULL, 0, NULL)) - if (errno != ENOENT) - abort(); - } - } - - if (ev->filter == EVFILT_WRITE) { - if (w->pevents & POLLOUT) { - revents |= POLLOUT; - w->wcount = ev->data; - } else { - /* TODO batch up */ - struct kevent events[1]; - EV_SET(events + 0, fd, ev->filter, EV_DELETE, 0, 0, 0); - if (kevent(loop->backend_fd, events, 1, NULL, 0, NULL)) - if (errno != ENOENT) - abort(); - } - } - - if (ev->flags & EV_ERROR) - revents |= POLLERR; - - if ((ev->flags & EV_EOF) && (w->pevents & UV__POLLRDHUP)) - revents |= UV__POLLRDHUP; - - if (revents == 0) - continue; - - /* Run signal watchers last. This also affects child process watchers - * because those are implemented in terms of signal watchers. - */ - if (w == &loop->signal_io_watcher) - have_signals = 1; - else - w->cb(loop, w, revents); - - nevents++; - } - - if (have_signals != 0) - loop->signal_io_watcher.cb(loop, &loop->signal_io_watcher, POLLIN); - - loop->watchers[loop->nwatchers] = NULL; - loop->watchers[loop->nwatchers + 1] = NULL; - - if (have_signals != 0) - return; /* Event loop should cycle now so don't poll again. */ - - if (nevents != 0) { - if (nfds == ARRAY_SIZE(events) && --count != 0) { - /* Poll for more events but don't block this time. */ - timeout = 0; - continue; - } - return; - } - - if (timeout == 0) - return; - - if (timeout == -1) - continue; - -update_timeout: - assert(timeout > 0); - - diff = loop->time - base; - if (diff >= (uint64_t) timeout) - return; - - timeout -= diff; - } -} - - -void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) { - struct kevent* events; - uintptr_t i; - uintptr_t nfds; - - assert(loop->watchers != NULL); - - events = (struct kevent*) loop->watchers[loop->nwatchers]; - nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1]; - if (events == NULL) - return; - - /* Invalidate events with same file descriptor */ - for (i = 0; i < nfds; i++) - if ((int) events[i].ident == fd) - events[i].ident = -1; -} - - -static void uv__fs_event(uv_loop_t* loop, uv__io_t* w, unsigned int fflags) { - uv_fs_event_t* handle; - struct kevent ev; - int events; - const char* path; -#if defined(F_GETPATH) - /* MAXPATHLEN == PATH_MAX but the former is what XNU calls it internally. */ - char pathbuf[MAXPATHLEN]; -#endif - - handle = container_of(w, uv_fs_event_t, event_watcher); - - if (fflags & (NOTE_ATTRIB | NOTE_EXTEND)) - events = UV_CHANGE; - else - events = UV_RENAME; - - path = NULL; -#if defined(F_GETPATH) - /* Also works when the file has been unlinked from the file system. Passing - * in the path when the file has been deleted is arguably a little strange - * but it's consistent with what the inotify backend does. - */ - if (fcntl(handle->event_watcher.fd, F_GETPATH, pathbuf) == 0) - path = uv__basename_r(pathbuf); -#endif - handle->cb(handle, path, events, 0); - - if (handle->event_watcher.fd == -1) - return; - - /* Watcher operates in one-shot mode, re-arm it. */ - fflags = NOTE_ATTRIB | NOTE_WRITE | NOTE_RENAME - | NOTE_DELETE | NOTE_EXTEND | NOTE_REVOKE; - - EV_SET(&ev, w->fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, fflags, 0, 0); - - if (kevent(loop->backend_fd, &ev, 1, NULL, 0, NULL)) - abort(); -} - - -int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) { - uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_EVENT); - return 0; -} - - -int uv_fs_event_start(uv_fs_event_t* handle, - uv_fs_event_cb cb, - const char* path, - unsigned int flags) { -#if defined(__APPLE__) - struct stat statbuf; -#endif /* defined(__APPLE__) */ - int fd; - - if (uv__is_active(handle)) - return -EINVAL; - - /* TODO open asynchronously - but how do we report back errors? */ - fd = open(path, O_RDONLY); - if (fd == -1) - return -errno; - - uv__handle_start(handle); - uv__io_init(&handle->event_watcher, uv__fs_event, fd); - handle->path = uv__strdup(path); - handle->cb = cb; - -#if defined(__APPLE__) - /* Nullify field to perform checks later */ - handle->cf_cb = NULL; - handle->realpath = NULL; - handle->realpath_len = 0; - handle->cf_flags = flags; - - if (fstat(fd, &statbuf)) - goto fallback; - /* FSEvents works only with directories */ - if (!(statbuf.st_mode & S_IFDIR)) - goto fallback; - - /* The fallback fd is no longer needed */ - uv__close(fd); - handle->event_watcher.fd = -1; - - return uv__fsevents_init(handle); - -fallback: -#endif /* defined(__APPLE__) */ - - uv__io_start(handle->loop, &handle->event_watcher, POLLIN); - - return 0; -} - - -int uv_fs_event_stop(uv_fs_event_t* handle) { - if (!uv__is_active(handle)) - return 0; - - uv__handle_stop(handle); - -#if defined(__APPLE__) - if (uv__fsevents_close(handle)) -#endif /* defined(__APPLE__) */ - { - uv__io_close(handle->loop, &handle->event_watcher); - } - - uv__free(handle->path); - handle->path = NULL; - - if (handle->event_watcher.fd != -1) { - /* When FSEvents is used, we don't use the event_watcher's fd under certain - * confitions. (see uv_fs_event_start) */ - uv__close(handle->event_watcher.fd); - handle->event_watcher.fd = -1; - } - - return 0; -} - - -void uv__fs_event_close(uv_fs_event_t* handle) { - uv_fs_event_stop(handle); -} diff --git a/vendor/libuv/src/unix/linux-core.c b/vendor/libuv/src/unix/linux-core.c deleted file mode 100644 index 58dd813dd..000000000 --- a/vendor/libuv/src/unix/linux-core.c +++ /dev/null @@ -1,985 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -/* We lean on the fact that POLL{IN,OUT,ERR,HUP} correspond with their - * EPOLL* counterparts. We use the POLL* variants in this file because that - * is what libuv uses elsewhere and it avoids a dependency on . - */ - -#include "uv.h" -#include "internal.h" - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#define HAVE_IFADDRS_H 1 - -#ifdef __UCLIBC__ -# if __UCLIBC_MAJOR__ < 0 && __UCLIBC_MINOR__ < 9 && __UCLIBC_SUBLEVEL__ < 32 -# undef HAVE_IFADDRS_H -# endif -#endif - -#ifdef HAVE_IFADDRS_H -# if defined(__ANDROID__) -# include "android-ifaddrs.h" -# else -# include -# endif -# include -# include -# include -#endif /* HAVE_IFADDRS_H */ - -/* Available from 2.6.32 onwards. */ -#ifndef CLOCK_MONOTONIC_COARSE -# define CLOCK_MONOTONIC_COARSE 6 -#endif - -/* This is rather annoying: CLOCK_BOOTTIME lives in but we can't - * include that file because it conflicts with . We'll just have to - * define it ourselves. - */ -#ifndef CLOCK_BOOTTIME -# define CLOCK_BOOTTIME 7 -#endif - -static int read_models(unsigned int numcpus, uv_cpu_info_t* ci); -static int read_times(FILE* statfile_fp, - unsigned int numcpus, - uv_cpu_info_t* ci); -static void read_speeds(unsigned int numcpus, uv_cpu_info_t* ci); -static unsigned long read_cpufreq(unsigned int cpunum); - - -int uv__platform_loop_init(uv_loop_t* loop) { - int fd; - - fd = uv__epoll_create1(UV__EPOLL_CLOEXEC); - - /* epoll_create1() can fail either because it's not implemented (old kernel) - * or because it doesn't understand the EPOLL_CLOEXEC flag. - */ - if (fd == -1 && (errno == ENOSYS || errno == EINVAL)) { - fd = uv__epoll_create(256); - - if (fd != -1) - uv__cloexec(fd, 1); - } - - loop->backend_fd = fd; - loop->inotify_fd = -1; - loop->inotify_watchers = NULL; - - if (fd == -1) - return -errno; - - return 0; -} - - -void uv__platform_loop_delete(uv_loop_t* loop) { - if (loop->inotify_fd == -1) return; - uv__io_stop(loop, &loop->inotify_read_watcher, POLLIN); - uv__close(loop->inotify_fd); - loop->inotify_fd = -1; -} - - -void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) { - struct uv__epoll_event* events; - struct uv__epoll_event dummy; - uintptr_t i; - uintptr_t nfds; - - assert(loop->watchers != NULL); - - events = (struct uv__epoll_event*) loop->watchers[loop->nwatchers]; - nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1]; - if (events != NULL) - /* Invalidate events with same file descriptor */ - for (i = 0; i < nfds; i++) - if ((int) events[i].data == fd) - events[i].data = -1; - - /* Remove the file descriptor from the epoll. - * This avoids a problem where the same file description remains open - * in another process, causing repeated junk epoll events. - * - * We pass in a dummy epoll_event, to work around a bug in old kernels. - */ - if (loop->backend_fd >= 0) { - /* Work around a bug in kernels 3.10 to 3.19 where passing a struct that - * has the EPOLLWAKEUP flag set generates spurious audit syslog warnings. - */ - memset(&dummy, 0, sizeof(dummy)); - uv__epoll_ctl(loop->backend_fd, UV__EPOLL_CTL_DEL, fd, &dummy); - } -} - - -int uv__io_check_fd(uv_loop_t* loop, int fd) { - struct uv__epoll_event e; - int rc; - - e.events = POLLIN; - e.data = -1; - - rc = 0; - if (uv__epoll_ctl(loop->backend_fd, UV__EPOLL_CTL_ADD, fd, &e)) - if (errno != EEXIST) - rc = -errno; - - if (rc == 0) - if (uv__epoll_ctl(loop->backend_fd, UV__EPOLL_CTL_DEL, fd, &e)) - abort(); - - return rc; -} - - -void uv__io_poll(uv_loop_t* loop, int timeout) { - /* A bug in kernels < 2.6.37 makes timeouts larger than ~30 minutes - * effectively infinite on 32 bits architectures. To avoid blocking - * indefinitely, we cap the timeout and poll again if necessary. - * - * Note that "30 minutes" is a simplification because it depends on - * the value of CONFIG_HZ. The magic constant assumes CONFIG_HZ=1200, - * that being the largest value I have seen in the wild (and only once.) - */ - static const int max_safe_timeout = 1789569; - static int no_epoll_pwait; - static int no_epoll_wait; - struct uv__epoll_event events[1024]; - struct uv__epoll_event* pe; - struct uv__epoll_event e; - int real_timeout; - QUEUE* q; - uv__io_t* w; - sigset_t sigset; - uint64_t sigmask; - uint64_t base; - int have_signals; - int nevents; - int count; - int nfds; - int fd; - int op; - int i; - - if (loop->nfds == 0) { - assert(QUEUE_EMPTY(&loop->watcher_queue)); - return; - } - - while (!QUEUE_EMPTY(&loop->watcher_queue)) { - q = QUEUE_HEAD(&loop->watcher_queue); - QUEUE_REMOVE(q); - QUEUE_INIT(q); - - w = QUEUE_DATA(q, uv__io_t, watcher_queue); - assert(w->pevents != 0); - assert(w->fd >= 0); - assert(w->fd < (int) loop->nwatchers); - - e.events = w->pevents; - e.data = w->fd; - - if (w->events == 0) - op = UV__EPOLL_CTL_ADD; - else - op = UV__EPOLL_CTL_MOD; - - /* XXX Future optimization: do EPOLL_CTL_MOD lazily if we stop watching - * events, skip the syscall and squelch the events after epoll_wait(). - */ - if (uv__epoll_ctl(loop->backend_fd, op, w->fd, &e)) { - if (errno != EEXIST) - abort(); - - assert(op == UV__EPOLL_CTL_ADD); - - /* We've reactivated a file descriptor that's been watched before. */ - if (uv__epoll_ctl(loop->backend_fd, UV__EPOLL_CTL_MOD, w->fd, &e)) - abort(); - } - - w->events = w->pevents; - } - - sigmask = 0; - if (loop->flags & UV_LOOP_BLOCK_SIGPROF) { - sigemptyset(&sigset); - sigaddset(&sigset, SIGPROF); - sigmask |= 1 << (SIGPROF - 1); - } - - assert(timeout >= -1); - base = loop->time; - count = 48; /* Benchmarks suggest this gives the best throughput. */ - real_timeout = timeout; - - for (;;) { - /* See the comment for max_safe_timeout for an explanation of why - * this is necessary. Executive summary: kernel bug workaround. - */ - if (sizeof(int32_t) == sizeof(long) && timeout >= max_safe_timeout) - timeout = max_safe_timeout; - - if (sigmask != 0 && no_epoll_pwait != 0) - if (pthread_sigmask(SIG_BLOCK, &sigset, NULL)) - abort(); - - if (no_epoll_wait != 0 || (sigmask != 0 && no_epoll_pwait == 0)) { - nfds = uv__epoll_pwait(loop->backend_fd, - events, - ARRAY_SIZE(events), - timeout, - sigmask); - if (nfds == -1 && errno == ENOSYS) - no_epoll_pwait = 1; - } else { - nfds = uv__epoll_wait(loop->backend_fd, - events, - ARRAY_SIZE(events), - timeout); - if (nfds == -1 && errno == ENOSYS) - no_epoll_wait = 1; - } - - if (sigmask != 0 && no_epoll_pwait != 0) - if (pthread_sigmask(SIG_UNBLOCK, &sigset, NULL)) - abort(); - - /* Update loop->time unconditionally. It's tempting to skip the update when - * timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the - * operating system didn't reschedule our process while in the syscall. - */ - SAVE_ERRNO(uv__update_time(loop)); - - if (nfds == 0) { - assert(timeout != -1); - - if (timeout == 0) - return; - - /* We may have been inside the system call for longer than |timeout| - * milliseconds so we need to update the timestamp to avoid drift. - */ - goto update_timeout; - } - - if (nfds == -1) { - if (errno == ENOSYS) { - /* epoll_wait() or epoll_pwait() failed, try the other system call. */ - assert(no_epoll_wait == 0 || no_epoll_pwait == 0); - continue; - } - - if (errno != EINTR) - abort(); - - if (timeout == -1) - continue; - - if (timeout == 0) - return; - - /* Interrupted by a signal. Update timeout and poll again. */ - goto update_timeout; - } - - have_signals = 0; - nevents = 0; - - assert(loop->watchers != NULL); - loop->watchers[loop->nwatchers] = (void*) events; - loop->watchers[loop->nwatchers + 1] = (void*) (uintptr_t) nfds; - for (i = 0; i < nfds; i++) { - pe = events + i; - fd = pe->data; - - /* Skip invalidated events, see uv__platform_invalidate_fd */ - if (fd == -1) - continue; - - assert(fd >= 0); - assert((unsigned) fd < loop->nwatchers); - - w = loop->watchers[fd]; - - if (w == NULL) { - /* File descriptor that we've stopped watching, disarm it. - * - * Ignore all errors because we may be racing with another thread - * when the file descriptor is closed. - */ - uv__epoll_ctl(loop->backend_fd, UV__EPOLL_CTL_DEL, fd, pe); - continue; - } - - /* Give users only events they're interested in. Prevents spurious - * callbacks when previous callback invocation in this loop has stopped - * the current watcher. Also, filters out events that users has not - * requested us to watch. - */ - pe->events &= w->pevents | POLLERR | POLLHUP; - - /* Work around an epoll quirk where it sometimes reports just the - * EPOLLERR or EPOLLHUP event. In order to force the event loop to - * move forward, we merge in the read/write events that the watcher - * is interested in; uv__read() and uv__write() will then deal with - * the error or hangup in the usual fashion. - * - * Note to self: happens when epoll reports EPOLLIN|EPOLLHUP, the user - * reads the available data, calls uv_read_stop(), then sometime later - * calls uv_read_start() again. By then, libuv has forgotten about the - * hangup and the kernel won't report EPOLLIN again because there's - * nothing left to read. If anything, libuv is to blame here. The - * current hack is just a quick bandaid; to properly fix it, libuv - * needs to remember the error/hangup event. We should get that for - * free when we switch over to edge-triggered I/O. - */ - if (pe->events == POLLERR || pe->events == POLLHUP) - pe->events |= w->pevents & (POLLIN | POLLOUT); - - if (pe->events != 0) { - /* Run signal watchers last. This also affects child process watchers - * because those are implemented in terms of signal watchers. - */ - if (w == &loop->signal_io_watcher) - have_signals = 1; - else - w->cb(loop, w, pe->events); - - nevents++; - } - } - - if (have_signals != 0) - loop->signal_io_watcher.cb(loop, &loop->signal_io_watcher, POLLIN); - - loop->watchers[loop->nwatchers] = NULL; - loop->watchers[loop->nwatchers + 1] = NULL; - - if (have_signals != 0) - return; /* Event loop should cycle now so don't poll again. */ - - if (nevents != 0) { - if (nfds == ARRAY_SIZE(events) && --count != 0) { - /* Poll for more events but don't block this time. */ - timeout = 0; - continue; - } - return; - } - - if (timeout == 0) - return; - - if (timeout == -1) - continue; - -update_timeout: - assert(timeout > 0); - - real_timeout -= (loop->time - base); - if (real_timeout <= 0) - return; - - timeout = real_timeout; - } -} - - -uint64_t uv__hrtime(uv_clocktype_t type) { - static clock_t fast_clock_id = -1; - struct timespec t; - clock_t clock_id; - - /* Prefer CLOCK_MONOTONIC_COARSE if available but only when it has - * millisecond granularity or better. CLOCK_MONOTONIC_COARSE is - * serviced entirely from the vDSO, whereas CLOCK_MONOTONIC may - * decide to make a costly system call. - */ - /* TODO(bnoordhuis) Use CLOCK_MONOTONIC_COARSE for UV_CLOCK_PRECISE - * when it has microsecond granularity or better (unlikely). - */ - if (type == UV_CLOCK_FAST && fast_clock_id == -1) { - if (clock_getres(CLOCK_MONOTONIC_COARSE, &t) == 0 && - t.tv_nsec <= 1 * 1000 * 1000) { - fast_clock_id = CLOCK_MONOTONIC_COARSE; - } else { - fast_clock_id = CLOCK_MONOTONIC; - } - } - - clock_id = CLOCK_MONOTONIC; - if (type == UV_CLOCK_FAST) - clock_id = fast_clock_id; - - if (clock_gettime(clock_id, &t)) - return 0; /* Not really possible. */ - - return t.tv_sec * (uint64_t) 1e9 + t.tv_nsec; -} - - -void uv_loadavg(double avg[3]) { - struct sysinfo info; - - if (sysinfo(&info) < 0) return; - - avg[0] = (double) info.loads[0] / 65536.0; - avg[1] = (double) info.loads[1] / 65536.0; - avg[2] = (double) info.loads[2] / 65536.0; -} - - -int uv_exepath(char* buffer, size_t* size) { - ssize_t n; - - if (buffer == NULL || size == NULL || *size == 0) - return -EINVAL; - - n = *size - 1; - if (n > 0) - n = readlink("/proc/self/exe", buffer, n); - - if (n == -1) - return -errno; - - buffer[n] = '\0'; - *size = n; - - return 0; -} - - -uint64_t uv_get_free_memory(void) { - struct sysinfo info; - - if (sysinfo(&info) == 0) - return (uint64_t) info.freeram * info.mem_unit; - return 0; -} - - -uint64_t uv_get_total_memory(void) { - struct sysinfo info; - - if (sysinfo(&info) == 0) - return (uint64_t) info.totalram * info.mem_unit; - return 0; -} - - -int uv_resident_set_memory(size_t* rss) { - char buf[1024]; - const char* s; - ssize_t n; - long val; - int fd; - int i; - - do - fd = open("/proc/self/stat", O_RDONLY); - while (fd == -1 && errno == EINTR); - - if (fd == -1) - return -errno; - - do - n = read(fd, buf, sizeof(buf) - 1); - while (n == -1 && errno == EINTR); - - uv__close(fd); - if (n == -1) - return -errno; - buf[n] = '\0'; - - s = strchr(buf, ' '); - if (s == NULL) - goto err; - - s += 1; - if (*s != '(') - goto err; - - s = strchr(s, ')'); - if (s == NULL) - goto err; - - for (i = 1; i <= 22; i++) { - s = strchr(s + 1, ' '); - if (s == NULL) - goto err; - } - - errno = 0; - val = strtol(s, NULL, 10); - if (errno != 0) - goto err; - if (val < 0) - goto err; - - *rss = val * getpagesize(); - return 0; - -err: - return -EINVAL; -} - - -int uv_uptime(double* uptime) { - static volatile int no_clock_boottime; - struct timespec now; - int r; - - /* Try CLOCK_BOOTTIME first, fall back to CLOCK_MONOTONIC if not available - * (pre-2.6.39 kernels). CLOCK_MONOTONIC doesn't increase when the system - * is suspended. - */ - if (no_clock_boottime) { - retry: r = clock_gettime(CLOCK_MONOTONIC, &now); - } - else if ((r = clock_gettime(CLOCK_BOOTTIME, &now)) && errno == EINVAL) { - no_clock_boottime = 1; - goto retry; - } - - if (r) - return -errno; - - *uptime = now.tv_sec; - return 0; -} - - -static int uv__cpu_num(FILE* statfile_fp, unsigned int* numcpus) { - unsigned int num; - char buf[1024]; - - if (!fgets(buf, sizeof(buf), statfile_fp)) - return -EIO; - - num = 0; - while (fgets(buf, sizeof(buf), statfile_fp)) { - if (strncmp(buf, "cpu", 3)) - break; - num++; - } - - if (num == 0) - return -EIO; - - *numcpus = num; - return 0; -} - - -int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { - unsigned int numcpus; - uv_cpu_info_t* ci; - int err; - FILE* statfile_fp; - - *cpu_infos = NULL; - *count = 0; - - statfile_fp = uv__open_file("/proc/stat"); - if (statfile_fp == NULL) - return -errno; - - err = uv__cpu_num(statfile_fp, &numcpus); - if (err < 0) - goto out; - - err = -ENOMEM; - ci = uv__calloc(numcpus, sizeof(*ci)); - if (ci == NULL) - goto out; - - err = read_models(numcpus, ci); - if (err == 0) - err = read_times(statfile_fp, numcpus, ci); - - if (err) { - uv_free_cpu_info(ci, numcpus); - goto out; - } - - /* read_models() on x86 also reads the CPU speed from /proc/cpuinfo. - * We don't check for errors here. Worst case, the field is left zero. - */ - if (ci[0].speed == 0) - read_speeds(numcpus, ci); - - *cpu_infos = ci; - *count = numcpus; - err = 0; - -out: - - if (fclose(statfile_fp)) - if (errno != EINTR && errno != EINPROGRESS) - abort(); - - return err; -} - - -static void read_speeds(unsigned int numcpus, uv_cpu_info_t* ci) { - unsigned int num; - - for (num = 0; num < numcpus; num++) - ci[num].speed = read_cpufreq(num) / 1000; -} - - -/* Also reads the CPU frequency on x86. The other architectures only have - * a BogoMIPS field, which may not be very accurate. - * - * Note: Simply returns on error, uv_cpu_info() takes care of the cleanup. - */ -static int read_models(unsigned int numcpus, uv_cpu_info_t* ci) { - static const char model_marker[] = "model name\t: "; - static const char speed_marker[] = "cpu MHz\t\t: "; - const char* inferred_model; - unsigned int model_idx; - unsigned int speed_idx; - char buf[1024]; - char* model; - FILE* fp; - - /* Most are unused on non-ARM, non-MIPS and non-x86 architectures. */ - (void) &model_marker; - (void) &speed_marker; - (void) &speed_idx; - (void) &model; - (void) &buf; - (void) &fp; - - model_idx = 0; - speed_idx = 0; - -#if defined(__arm__) || \ - defined(__i386__) || \ - defined(__mips__) || \ - defined(__x86_64__) - fp = uv__open_file("/proc/cpuinfo"); - if (fp == NULL) - return -errno; - - while (fgets(buf, sizeof(buf), fp)) { - if (model_idx < numcpus) { - if (strncmp(buf, model_marker, sizeof(model_marker) - 1) == 0) { - model = buf + sizeof(model_marker) - 1; - model = uv__strndup(model, strlen(model) - 1); /* Strip newline. */ - if (model == NULL) { - fclose(fp); - return -ENOMEM; - } - ci[model_idx++].model = model; - continue; - } - } -#if defined(__arm__) || defined(__mips__) - if (model_idx < numcpus) { -#if defined(__arm__) - /* Fallback for pre-3.8 kernels. */ - static const char model_marker[] = "Processor\t: "; -#else /* defined(__mips__) */ - static const char model_marker[] = "cpu model\t\t: "; -#endif - if (strncmp(buf, model_marker, sizeof(model_marker) - 1) == 0) { - model = buf + sizeof(model_marker) - 1; - model = uv__strndup(model, strlen(model) - 1); /* Strip newline. */ - if (model == NULL) { - fclose(fp); - return -ENOMEM; - } - ci[model_idx++].model = model; - continue; - } - } -#else /* !__arm__ && !__mips__ */ - if (speed_idx < numcpus) { - if (strncmp(buf, speed_marker, sizeof(speed_marker) - 1) == 0) { - ci[speed_idx++].speed = atoi(buf + sizeof(speed_marker) - 1); - continue; - } - } -#endif /* __arm__ || __mips__ */ - } - - fclose(fp); -#endif /* __arm__ || __i386__ || __mips__ || __x86_64__ */ - - /* Now we want to make sure that all the models contain *something* because - * it's not safe to leave them as null. Copy the last entry unless there - * isn't one, in that case we simply put "unknown" into everything. - */ - inferred_model = "unknown"; - if (model_idx > 0) - inferred_model = ci[model_idx - 1].model; - - while (model_idx < numcpus) { - model = uv__strndup(inferred_model, strlen(inferred_model)); - if (model == NULL) - return -ENOMEM; - ci[model_idx++].model = model; - } - - return 0; -} - - -static int read_times(FILE* statfile_fp, - unsigned int numcpus, - uv_cpu_info_t* ci) { - unsigned long clock_ticks; - struct uv_cpu_times_s ts; - unsigned long user; - unsigned long nice; - unsigned long sys; - unsigned long idle; - unsigned long dummy; - unsigned long irq; - unsigned int num; - unsigned int len; - char buf[1024]; - - clock_ticks = sysconf(_SC_CLK_TCK); - assert(clock_ticks != (unsigned long) -1); - assert(clock_ticks != 0); - - rewind(statfile_fp); - - if (!fgets(buf, sizeof(buf), statfile_fp)) - abort(); - - num = 0; - - while (fgets(buf, sizeof(buf), statfile_fp)) { - if (num >= numcpus) - break; - - if (strncmp(buf, "cpu", 3)) - break; - - /* skip "cpu " marker */ - { - unsigned int n; - int r = sscanf(buf, "cpu%u ", &n); - assert(r == 1); - (void) r; /* silence build warning */ - for (len = sizeof("cpu0"); n /= 10; len++); - } - - /* Line contains user, nice, system, idle, iowait, irq, softirq, steal, - * guest, guest_nice but we're only interested in the first four + irq. - * - * Don't use %*s to skip fields or %ll to read straight into the uint64_t - * fields, they're not allowed in C89 mode. - */ - if (6 != sscanf(buf + len, - "%lu %lu %lu %lu %lu %lu", - &user, - &nice, - &sys, - &idle, - &dummy, - &irq)) - abort(); - - ts.user = clock_ticks * user; - ts.nice = clock_ticks * nice; - ts.sys = clock_ticks * sys; - ts.idle = clock_ticks * idle; - ts.irq = clock_ticks * irq; - ci[num++].cpu_times = ts; - } - assert(num == numcpus); - - return 0; -} - - -static unsigned long read_cpufreq(unsigned int cpunum) { - unsigned long val; - char buf[1024]; - FILE* fp; - - snprintf(buf, - sizeof(buf), - "/sys/devices/system/cpu/cpu%u/cpufreq/scaling_cur_freq", - cpunum); - - fp = uv__open_file(buf); - if (fp == NULL) - return 0; - - if (fscanf(fp, "%lu", &val) != 1) - val = 0; - - fclose(fp); - - return val; -} - - -void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { - int i; - - for (i = 0; i < count; i++) { - uv__free(cpu_infos[i].model); - } - - uv__free(cpu_infos); -} - - -int uv_interface_addresses(uv_interface_address_t** addresses, - int* count) { -#ifndef HAVE_IFADDRS_H - return -ENOSYS; -#else - struct ifaddrs *addrs, *ent; - uv_interface_address_t* address; - int i; - struct sockaddr_ll *sll; - - if (getifaddrs(&addrs)) - return -errno; - - *count = 0; - *addresses = NULL; - - /* Count the number of interfaces */ - for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)) || - (ent->ifa_addr == NULL) || - (ent->ifa_addr->sa_family == PF_PACKET)) { - continue; - } - - (*count)++; - } - - if (*count == 0) - return 0; - - *addresses = uv__malloc(*count * sizeof(**addresses)); - if (!(*addresses)) { - freeifaddrs(addrs); - return -ENOMEM; - } - - address = *addresses; - - for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING))) - continue; - - if (ent->ifa_addr == NULL) - continue; - - /* - * On Linux getifaddrs returns information related to the raw underlying - * devices. We're not interested in this information yet. - */ - if (ent->ifa_addr->sa_family == PF_PACKET) - continue; - - address->name = uv__strdup(ent->ifa_name); - - if (ent->ifa_addr->sa_family == AF_INET6) { - address->address.address6 = *((struct sockaddr_in6*) ent->ifa_addr); - } else { - address->address.address4 = *((struct sockaddr_in*) ent->ifa_addr); - } - - if (ent->ifa_netmask->sa_family == AF_INET6) { - address->netmask.netmask6 = *((struct sockaddr_in6*) ent->ifa_netmask); - } else { - address->netmask.netmask4 = *((struct sockaddr_in*) ent->ifa_netmask); - } - - address->is_internal = !!(ent->ifa_flags & IFF_LOOPBACK); - - address++; - } - - /* Fill in physical addresses for each interface */ - for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)) || - (ent->ifa_addr == NULL) || - (ent->ifa_addr->sa_family != PF_PACKET)) { - continue; - } - - address = *addresses; - - for (i = 0; i < (*count); i++) { - if (strcmp(address->name, ent->ifa_name) == 0) { - sll = (struct sockaddr_ll*)ent->ifa_addr; - memcpy(address->phys_addr, sll->sll_addr, sizeof(address->phys_addr)); - } - address++; - } - } - - freeifaddrs(addrs); - - return 0; -#endif -} - - -void uv_free_interface_addresses(uv_interface_address_t* addresses, - int count) { - int i; - - for (i = 0; i < count; i++) { - uv__free(addresses[i].name); - } - - uv__free(addresses); -} - - -void uv__set_process_title(const char* title) { -#if defined(PR_SET_NAME) - prctl(PR_SET_NAME, title); /* Only copies first 16 characters. */ -#endif -} diff --git a/vendor/libuv/src/unix/linux-inotify.c b/vendor/libuv/src/unix/linux-inotify.c deleted file mode 100644 index 4708c051d..000000000 --- a/vendor/libuv/src/unix/linux-inotify.c +++ /dev/null @@ -1,285 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "tree.h" -#include "internal.h" - -#include -#include -#include -#include -#include -#include - -#include -#include - -struct watcher_list { - RB_ENTRY(watcher_list) entry; - QUEUE watchers; - int iterating; - char* path; - int wd; -}; - -struct watcher_root { - struct watcher_list* rbh_root; -}; -#define CAST(p) ((struct watcher_root*)(p)) - - -static int compare_watchers(const struct watcher_list* a, - const struct watcher_list* b) { - if (a->wd < b->wd) return -1; - if (a->wd > b->wd) return 1; - return 0; -} - - -RB_GENERATE_STATIC(watcher_root, watcher_list, entry, compare_watchers) - - -static void uv__inotify_read(uv_loop_t* loop, - uv__io_t* w, - unsigned int revents); - - -static int new_inotify_fd(void) { - int err; - int fd; - - fd = uv__inotify_init1(UV__IN_NONBLOCK | UV__IN_CLOEXEC); - if (fd != -1) - return fd; - - if (errno != ENOSYS) - return -errno; - - fd = uv__inotify_init(); - if (fd == -1) - return -errno; - - err = uv__cloexec(fd, 1); - if (err == 0) - err = uv__nonblock(fd, 1); - - if (err) { - uv__close(fd); - return err; - } - - return fd; -} - - -static int init_inotify(uv_loop_t* loop) { - int err; - - if (loop->inotify_fd != -1) - return 0; - - err = new_inotify_fd(); - if (err < 0) - return err; - - loop->inotify_fd = err; - uv__io_init(&loop->inotify_read_watcher, uv__inotify_read, loop->inotify_fd); - uv__io_start(loop, &loop->inotify_read_watcher, POLLIN); - - return 0; -} - - -static struct watcher_list* find_watcher(uv_loop_t* loop, int wd) { - struct watcher_list w; - w.wd = wd; - return RB_FIND(watcher_root, CAST(&loop->inotify_watchers), &w); -} - -static void maybe_free_watcher_list(struct watcher_list* w, uv_loop_t* loop) { - /* if the watcher_list->watchers is being iterated over, we can't free it. */ - if ((!w->iterating) && QUEUE_EMPTY(&w->watchers)) { - /* No watchers left for this path. Clean up. */ - RB_REMOVE(watcher_root, CAST(&loop->inotify_watchers), w); - uv__inotify_rm_watch(loop->inotify_fd, w->wd); - uv__free(w); - } -} - -static void uv__inotify_read(uv_loop_t* loop, - uv__io_t* dummy, - unsigned int events) { - const struct uv__inotify_event* e; - struct watcher_list* w; - uv_fs_event_t* h; - QUEUE queue; - QUEUE* q; - const char* path; - ssize_t size; - const char *p; - /* needs to be large enough for sizeof(inotify_event) + strlen(path) */ - char buf[4096]; - - while (1) { - do - size = read(loop->inotify_fd, buf, sizeof(buf)); - while (size == -1 && errno == EINTR); - - if (size == -1) { - assert(errno == EAGAIN || errno == EWOULDBLOCK); - break; - } - - assert(size > 0); /* pre-2.6.21 thing, size=0 == read buffer too small */ - - /* Now we have one or more inotify_event structs. */ - for (p = buf; p < buf + size; p += sizeof(*e) + e->len) { - e = (const struct uv__inotify_event*)p; - - events = 0; - if (e->mask & (UV__IN_ATTRIB|UV__IN_MODIFY)) - events |= UV_CHANGE; - if (e->mask & ~(UV__IN_ATTRIB|UV__IN_MODIFY)) - events |= UV_RENAME; - - w = find_watcher(loop, e->wd); - if (w == NULL) - continue; /* Stale event, no watchers left. */ - - /* inotify does not return the filename when monitoring a single file - * for modifications. Repurpose the filename for API compatibility. - * I'm not convinced this is a good thing, maybe it should go. - */ - path = e->len ? (const char*) (e + 1) : uv__basename_r(w->path); - - /* We're about to iterate over the queue and call user's callbacks. - * What can go wrong? - * A callback could call uv_fs_event_stop() - * and the queue can change under our feet. - * So, we use QUEUE_MOVE() trick to safely iterate over the queue. - * And we don't free the watcher_list until we're done iterating. - * - * First, - * tell uv_fs_event_stop() (that could be called from a user's callback) - * not to free watcher_list. - */ - w->iterating = 1; - QUEUE_MOVE(&w->watchers, &queue); - while (!QUEUE_EMPTY(&queue)) { - q = QUEUE_HEAD(&queue); - h = QUEUE_DATA(q, uv_fs_event_t, watchers); - - QUEUE_REMOVE(q); - QUEUE_INSERT_TAIL(&w->watchers, q); - - h->cb(h, path, events, 0); - } - /* done iterating, time to (maybe) free empty watcher_list */ - w->iterating = 0; - maybe_free_watcher_list(w, loop); - } - } -} - - -int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) { - uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_EVENT); - return 0; -} - - -int uv_fs_event_start(uv_fs_event_t* handle, - uv_fs_event_cb cb, - const char* path, - unsigned int flags) { - struct watcher_list* w; - int events; - int err; - int wd; - - if (uv__is_active(handle)) - return -EINVAL; - - err = init_inotify(handle->loop); - if (err) - return err; - - events = UV__IN_ATTRIB - | UV__IN_CREATE - | UV__IN_MODIFY - | UV__IN_DELETE - | UV__IN_DELETE_SELF - | UV__IN_MOVE_SELF - | UV__IN_MOVED_FROM - | UV__IN_MOVED_TO; - - wd = uv__inotify_add_watch(handle->loop->inotify_fd, path, events); - if (wd == -1) - return -errno; - - w = find_watcher(handle->loop, wd); - if (w) - goto no_insert; - - w = uv__malloc(sizeof(*w) + strlen(path) + 1); - if (w == NULL) - return -ENOMEM; - - w->wd = wd; - w->path = strcpy((char*)(w + 1), path); - QUEUE_INIT(&w->watchers); - w->iterating = 0; - RB_INSERT(watcher_root, CAST(&handle->loop->inotify_watchers), w); - -no_insert: - uv__handle_start(handle); - QUEUE_INSERT_TAIL(&w->watchers, &handle->watchers); - handle->path = w->path; - handle->cb = cb; - handle->wd = wd; - - return 0; -} - - -int uv_fs_event_stop(uv_fs_event_t* handle) { - struct watcher_list* w; - - if (!uv__is_active(handle)) - return 0; - - w = find_watcher(handle->loop, handle->wd); - assert(w != NULL); - - handle->wd = -1; - handle->path = NULL; - uv__handle_stop(handle); - QUEUE_REMOVE(&handle->watchers); - - maybe_free_watcher_list(w, handle->loop); - - return 0; -} - - -void uv__fs_event_close(uv_fs_event_t* handle) { - uv_fs_event_stop(handle); -} diff --git a/vendor/libuv/src/unix/linux-syscalls.c b/vendor/libuv/src/unix/linux-syscalls.c deleted file mode 100644 index 89998ded2..000000000 --- a/vendor/libuv/src/unix/linux-syscalls.c +++ /dev/null @@ -1,471 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "linux-syscalls.h" -#include -#include -#include -#include -#include - -#if defined(__has_feature) -# if __has_feature(memory_sanitizer) -# define MSAN_ACTIVE 1 -# include -# endif -#endif - -#if defined(__i386__) -# ifndef __NR_socketcall -# define __NR_socketcall 102 -# endif -#endif - -#if defined(__arm__) -# if defined(__thumb__) || defined(__ARM_EABI__) -# define UV_SYSCALL_BASE 0 -# else -# define UV_SYSCALL_BASE 0x900000 -# endif -#endif /* __arm__ */ - -#ifndef __NR_accept4 -# if defined(__x86_64__) -# define __NR_accept4 288 -# elif defined(__i386__) - /* Nothing. Handled through socketcall(). */ -# elif defined(__arm__) -# define __NR_accept4 (UV_SYSCALL_BASE + 366) -# endif -#endif /* __NR_accept4 */ - -#ifndef __NR_eventfd -# if defined(__x86_64__) -# define __NR_eventfd 284 -# elif defined(__i386__) -# define __NR_eventfd 323 -# elif defined(__arm__) -# define __NR_eventfd (UV_SYSCALL_BASE + 351) -# endif -#endif /* __NR_eventfd */ - -#ifndef __NR_eventfd2 -# if defined(__x86_64__) -# define __NR_eventfd2 290 -# elif defined(__i386__) -# define __NR_eventfd2 328 -# elif defined(__arm__) -# define __NR_eventfd2 (UV_SYSCALL_BASE + 356) -# endif -#endif /* __NR_eventfd2 */ - -#ifndef __NR_epoll_create -# if defined(__x86_64__) -# define __NR_epoll_create 213 -# elif defined(__i386__) -# define __NR_epoll_create 254 -# elif defined(__arm__) -# define __NR_epoll_create (UV_SYSCALL_BASE + 250) -# endif -#endif /* __NR_epoll_create */ - -#ifndef __NR_epoll_create1 -# if defined(__x86_64__) -# define __NR_epoll_create1 291 -# elif defined(__i386__) -# define __NR_epoll_create1 329 -# elif defined(__arm__) -# define __NR_epoll_create1 (UV_SYSCALL_BASE + 357) -# endif -#endif /* __NR_epoll_create1 */ - -#ifndef __NR_epoll_ctl -# if defined(__x86_64__) -# define __NR_epoll_ctl 233 /* used to be 214 */ -# elif defined(__i386__) -# define __NR_epoll_ctl 255 -# elif defined(__arm__) -# define __NR_epoll_ctl (UV_SYSCALL_BASE + 251) -# endif -#endif /* __NR_epoll_ctl */ - -#ifndef __NR_epoll_wait -# if defined(__x86_64__) -# define __NR_epoll_wait 232 /* used to be 215 */ -# elif defined(__i386__) -# define __NR_epoll_wait 256 -# elif defined(__arm__) -# define __NR_epoll_wait (UV_SYSCALL_BASE + 252) -# endif -#endif /* __NR_epoll_wait */ - -#ifndef __NR_epoll_pwait -# if defined(__x86_64__) -# define __NR_epoll_pwait 281 -# elif defined(__i386__) -# define __NR_epoll_pwait 319 -# elif defined(__arm__) -# define __NR_epoll_pwait (UV_SYSCALL_BASE + 346) -# endif -#endif /* __NR_epoll_pwait */ - -#ifndef __NR_inotify_init -# if defined(__x86_64__) -# define __NR_inotify_init 253 -# elif defined(__i386__) -# define __NR_inotify_init 291 -# elif defined(__arm__) -# define __NR_inotify_init (UV_SYSCALL_BASE + 316) -# endif -#endif /* __NR_inotify_init */ - -#ifndef __NR_inotify_init1 -# if defined(__x86_64__) -# define __NR_inotify_init1 294 -# elif defined(__i386__) -# define __NR_inotify_init1 332 -# elif defined(__arm__) -# define __NR_inotify_init1 (UV_SYSCALL_BASE + 360) -# endif -#endif /* __NR_inotify_init1 */ - -#ifndef __NR_inotify_add_watch -# if defined(__x86_64__) -# define __NR_inotify_add_watch 254 -# elif defined(__i386__) -# define __NR_inotify_add_watch 292 -# elif defined(__arm__) -# define __NR_inotify_add_watch (UV_SYSCALL_BASE + 317) -# endif -#endif /* __NR_inotify_add_watch */ - -#ifndef __NR_inotify_rm_watch -# if defined(__x86_64__) -# define __NR_inotify_rm_watch 255 -# elif defined(__i386__) -# define __NR_inotify_rm_watch 293 -# elif defined(__arm__) -# define __NR_inotify_rm_watch (UV_SYSCALL_BASE + 318) -# endif -#endif /* __NR_inotify_rm_watch */ - -#ifndef __NR_pipe2 -# if defined(__x86_64__) -# define __NR_pipe2 293 -# elif defined(__i386__) -# define __NR_pipe2 331 -# elif defined(__arm__) -# define __NR_pipe2 (UV_SYSCALL_BASE + 359) -# endif -#endif /* __NR_pipe2 */ - -#ifndef __NR_recvmmsg -# if defined(__x86_64__) -# define __NR_recvmmsg 299 -# elif defined(__i386__) -# define __NR_recvmmsg 337 -# elif defined(__arm__) -# define __NR_recvmmsg (UV_SYSCALL_BASE + 365) -# endif -#endif /* __NR_recvmsg */ - -#ifndef __NR_sendmmsg -# if defined(__x86_64__) -# define __NR_sendmmsg 307 -# elif defined(__i386__) -# define __NR_sendmmsg 345 -# elif defined(__arm__) -# define __NR_sendmmsg (UV_SYSCALL_BASE + 374) -# endif -#endif /* __NR_sendmmsg */ - -#ifndef __NR_utimensat -# if defined(__x86_64__) -# define __NR_utimensat 280 -# elif defined(__i386__) -# define __NR_utimensat 320 -# elif defined(__arm__) -# define __NR_utimensat (UV_SYSCALL_BASE + 348) -# endif -#endif /* __NR_utimensat */ - -#ifndef __NR_preadv -# if defined(__x86_64__) -# define __NR_preadv 295 -# elif defined(__i386__) -# define __NR_preadv 333 -# elif defined(__arm__) -# define __NR_preadv (UV_SYSCALL_BASE + 361) -# endif -#endif /* __NR_preadv */ - -#ifndef __NR_pwritev -# if defined(__x86_64__) -# define __NR_pwritev 296 -# elif defined(__i386__) -# define __NR_pwritev 334 -# elif defined(__arm__) -# define __NR_pwritev (UV_SYSCALL_BASE + 362) -# endif -#endif /* __NR_pwritev */ - -#ifndef __NR_dup3 -# if defined(__x86_64__) -# define __NR_dup3 292 -# elif defined(__i386__) -# define __NR_dup3 330 -# elif defined(__arm__) -# define __NR_dup3 (UV_SYSCALL_BASE + 358) -# endif -#endif /* __NR_pwritev */ - - -int uv__accept4(int fd, struct sockaddr* addr, socklen_t* addrlen, int flags) { -#if defined(__i386__) - unsigned long args[4]; - int r; - - args[0] = (unsigned long) fd; - args[1] = (unsigned long) addr; - args[2] = (unsigned long) addrlen; - args[3] = (unsigned long) flags; - - r = syscall(__NR_socketcall, 18 /* SYS_ACCEPT4 */, args); - - /* socketcall() raises EINVAL when SYS_ACCEPT4 is not supported but so does - * a bad flags argument. Try to distinguish between the two cases. - */ - if (r == -1) - if (errno == EINVAL) - if ((flags & ~(UV__SOCK_CLOEXEC|UV__SOCK_NONBLOCK)) == 0) - errno = ENOSYS; - - return r; -#elif defined(__NR_accept4) - return syscall(__NR_accept4, fd, addr, addrlen, flags); -#else - return errno = ENOSYS, -1; -#endif -} - - -int uv__eventfd(unsigned int count) { -#if defined(__NR_eventfd) - return syscall(__NR_eventfd, count); -#else - return errno = ENOSYS, -1; -#endif -} - - -int uv__eventfd2(unsigned int count, int flags) { -#if defined(__NR_eventfd2) - return syscall(__NR_eventfd2, count, flags); -#else - return errno = ENOSYS, -1; -#endif -} - - -int uv__epoll_create(int size) { -#if defined(__NR_epoll_create) - return syscall(__NR_epoll_create, size); -#else - return errno = ENOSYS, -1; -#endif -} - - -int uv__epoll_create1(int flags) { -#if defined(__NR_epoll_create1) - return syscall(__NR_epoll_create1, flags); -#else - return errno = ENOSYS, -1; -#endif -} - - -int uv__epoll_ctl(int epfd, int op, int fd, struct uv__epoll_event* events) { -#if defined(__NR_epoll_ctl) - return syscall(__NR_epoll_ctl, epfd, op, fd, events); -#else - return errno = ENOSYS, -1; -#endif -} - - -int uv__epoll_wait(int epfd, - struct uv__epoll_event* events, - int nevents, - int timeout) { -#if defined(__NR_epoll_wait) - int result; - result = syscall(__NR_epoll_wait, epfd, events, nevents, timeout); -#if MSAN_ACTIVE - if (result > 0) - __msan_unpoison(events, sizeof(events[0]) * result); -#endif - return result; -#else - return errno = ENOSYS, -1; -#endif -} - - -int uv__epoll_pwait(int epfd, - struct uv__epoll_event* events, - int nevents, - int timeout, - uint64_t sigmask) { -#if defined(__NR_epoll_pwait) - int result; - result = syscall(__NR_epoll_pwait, - epfd, - events, - nevents, - timeout, - &sigmask, - sizeof(sigmask)); -#if MSAN_ACTIVE - if (result > 0) - __msan_unpoison(events, sizeof(events[0]) * result); -#endif - return result; -#else - return errno = ENOSYS, -1; -#endif -} - - -int uv__inotify_init(void) { -#if defined(__NR_inotify_init) - return syscall(__NR_inotify_init); -#else - return errno = ENOSYS, -1; -#endif -} - - -int uv__inotify_init1(int flags) { -#if defined(__NR_inotify_init1) - return syscall(__NR_inotify_init1, flags); -#else - return errno = ENOSYS, -1; -#endif -} - - -int uv__inotify_add_watch(int fd, const char* path, uint32_t mask) { -#if defined(__NR_inotify_add_watch) - return syscall(__NR_inotify_add_watch, fd, path, mask); -#else - return errno = ENOSYS, -1; -#endif -} - - -int uv__inotify_rm_watch(int fd, int32_t wd) { -#if defined(__NR_inotify_rm_watch) - return syscall(__NR_inotify_rm_watch, fd, wd); -#else - return errno = ENOSYS, -1; -#endif -} - - -int uv__pipe2(int pipefd[2], int flags) { -#if defined(__NR_pipe2) - int result; - result = syscall(__NR_pipe2, pipefd, flags); -#if MSAN_ACTIVE - if (!result) - __msan_unpoison(pipefd, sizeof(int[2])); -#endif - return result; -#else - return errno = ENOSYS, -1; -#endif -} - - -int uv__sendmmsg(int fd, - struct uv__mmsghdr* mmsg, - unsigned int vlen, - unsigned int flags) { -#if defined(__NR_sendmmsg) - return syscall(__NR_sendmmsg, fd, mmsg, vlen, flags); -#else - return errno = ENOSYS, -1; -#endif -} - - -int uv__recvmmsg(int fd, - struct uv__mmsghdr* mmsg, - unsigned int vlen, - unsigned int flags, - struct timespec* timeout) { -#if defined(__NR_recvmmsg) - return syscall(__NR_recvmmsg, fd, mmsg, vlen, flags, timeout); -#else - return errno = ENOSYS, -1; -#endif -} - - -int uv__utimesat(int dirfd, - const char* path, - const struct timespec times[2], - int flags) -{ -#if defined(__NR_utimensat) - return syscall(__NR_utimensat, dirfd, path, times, flags); -#else - return errno = ENOSYS, -1; -#endif -} - - -ssize_t uv__preadv(int fd, const struct iovec *iov, int iovcnt, int64_t offset) { -#if defined(__NR_preadv) - return syscall(__NR_preadv, fd, iov, iovcnt, (long)offset, (long)(offset >> 32)); -#else - return errno = ENOSYS, -1; -#endif -} - - -ssize_t uv__pwritev(int fd, const struct iovec *iov, int iovcnt, int64_t offset) { -#if defined(__NR_pwritev) - return syscall(__NR_pwritev, fd, iov, iovcnt, (long)offset, (long)(offset >> 32)); -#else - return errno = ENOSYS, -1; -#endif -} - - -int uv__dup3(int oldfd, int newfd, int flags) { -#if defined(__NR_dup3) - return syscall(__NR_dup3, oldfd, newfd, flags); -#else - return errno = ENOSYS, -1; -#endif -} diff --git a/vendor/libuv/src/unix/linux-syscalls.h b/vendor/libuv/src/unix/linux-syscalls.h deleted file mode 100644 index 4c095e9b5..000000000 --- a/vendor/libuv/src/unix/linux-syscalls.h +++ /dev/null @@ -1,151 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef UV_LINUX_SYSCALL_H_ -#define UV_LINUX_SYSCALL_H_ - -#undef _GNU_SOURCE -#define _GNU_SOURCE - -#include -#include -#include -#include -#include - -#if defined(__alpha__) -# define UV__O_CLOEXEC 0x200000 -#elif defined(__hppa__) -# define UV__O_CLOEXEC 0x200000 -#elif defined(__sparc__) -# define UV__O_CLOEXEC 0x400000 -#else -# define UV__O_CLOEXEC 0x80000 -#endif - -#if defined(__alpha__) -# define UV__O_NONBLOCK 0x4 -#elif defined(__hppa__) -# define UV__O_NONBLOCK O_NONBLOCK -#elif defined(__mips__) -# define UV__O_NONBLOCK 0x80 -#elif defined(__sparc__) -# define UV__O_NONBLOCK 0x4000 -#else -# define UV__O_NONBLOCK 0x800 -#endif - -#define UV__EFD_CLOEXEC UV__O_CLOEXEC -#define UV__EFD_NONBLOCK UV__O_NONBLOCK - -#define UV__IN_CLOEXEC UV__O_CLOEXEC -#define UV__IN_NONBLOCK UV__O_NONBLOCK - -#define UV__SOCK_CLOEXEC UV__O_CLOEXEC -#if defined(SOCK_NONBLOCK) -# define UV__SOCK_NONBLOCK SOCK_NONBLOCK -#else -# define UV__SOCK_NONBLOCK UV__O_NONBLOCK -#endif - -/* epoll flags */ -#define UV__EPOLL_CLOEXEC UV__O_CLOEXEC -#define UV__EPOLL_CTL_ADD 1 -#define UV__EPOLL_CTL_DEL 2 -#define UV__EPOLL_CTL_MOD 3 - -/* inotify flags */ -#define UV__IN_ACCESS 0x001 -#define UV__IN_MODIFY 0x002 -#define UV__IN_ATTRIB 0x004 -#define UV__IN_CLOSE_WRITE 0x008 -#define UV__IN_CLOSE_NOWRITE 0x010 -#define UV__IN_OPEN 0x020 -#define UV__IN_MOVED_FROM 0x040 -#define UV__IN_MOVED_TO 0x080 -#define UV__IN_CREATE 0x100 -#define UV__IN_DELETE 0x200 -#define UV__IN_DELETE_SELF 0x400 -#define UV__IN_MOVE_SELF 0x800 - -#if defined(__x86_64__) -struct uv__epoll_event { - uint32_t events; - uint64_t data; -} __attribute__((packed)); -#else -struct uv__epoll_event { - uint32_t events; - uint64_t data; -}; -#endif - -struct uv__inotify_event { - int32_t wd; - uint32_t mask; - uint32_t cookie; - uint32_t len; - /* char name[0]; */ -}; - -struct uv__mmsghdr { - struct msghdr msg_hdr; - unsigned int msg_len; -}; - -int uv__accept4(int fd, struct sockaddr* addr, socklen_t* addrlen, int flags); -int uv__eventfd(unsigned int count); -int uv__epoll_create(int size); -int uv__epoll_create1(int flags); -int uv__epoll_ctl(int epfd, int op, int fd, struct uv__epoll_event *ev); -int uv__epoll_wait(int epfd, - struct uv__epoll_event* events, - int nevents, - int timeout); -int uv__epoll_pwait(int epfd, - struct uv__epoll_event* events, - int nevents, - int timeout, - uint64_t sigmask); -int uv__eventfd2(unsigned int count, int flags); -int uv__inotify_init(void); -int uv__inotify_init1(int flags); -int uv__inotify_add_watch(int fd, const char* path, uint32_t mask); -int uv__inotify_rm_watch(int fd, int32_t wd); -int uv__pipe2(int pipefd[2], int flags); -int uv__recvmmsg(int fd, - struct uv__mmsghdr* mmsg, - unsigned int vlen, - unsigned int flags, - struct timespec* timeout); -int uv__sendmmsg(int fd, - struct uv__mmsghdr* mmsg, - unsigned int vlen, - unsigned int flags); -int uv__utimesat(int dirfd, - const char* path, - const struct timespec times[2], - int flags); -ssize_t uv__preadv(int fd, const struct iovec *iov, int iovcnt, int64_t offset); -ssize_t uv__pwritev(int fd, const struct iovec *iov, int iovcnt, int64_t offset); -int uv__dup3(int oldfd, int newfd, int flags); - -#endif /* UV_LINUX_SYSCALL_H_ */ diff --git a/vendor/libuv/src/unix/loop-watcher.c b/vendor/libuv/src/unix/loop-watcher.c deleted file mode 100644 index 340bb0dfa..000000000 --- a/vendor/libuv/src/unix/loop-watcher.c +++ /dev/null @@ -1,68 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "internal.h" - -#define UV_LOOP_WATCHER_DEFINE(name, type) \ - int uv_##name##_init(uv_loop_t* loop, uv_##name##_t* handle) { \ - uv__handle_init(loop, (uv_handle_t*)handle, UV_##type); \ - handle->name##_cb = NULL; \ - return 0; \ - } \ - \ - int uv_##name##_start(uv_##name##_t* handle, uv_##name##_cb cb) { \ - if (uv__is_active(handle)) return 0; \ - if (cb == NULL) return -EINVAL; \ - QUEUE_INSERT_HEAD(&handle->loop->name##_handles, &handle->queue); \ - handle->name##_cb = cb; \ - uv__handle_start(handle); \ - return 0; \ - } \ - \ - int uv_##name##_stop(uv_##name##_t* handle) { \ - if (!uv__is_active(handle)) return 0; \ - QUEUE_REMOVE(&handle->queue); \ - uv__handle_stop(handle); \ - return 0; \ - } \ - \ - void uv__run_##name(uv_loop_t* loop) { \ - uv_##name##_t* h; \ - QUEUE queue; \ - QUEUE* q; \ - QUEUE_MOVE(&loop->name##_handles, &queue); \ - while (!QUEUE_EMPTY(&queue)) { \ - q = QUEUE_HEAD(&queue); \ - h = QUEUE_DATA(q, uv_##name##_t, queue); \ - QUEUE_REMOVE(q); \ - QUEUE_INSERT_TAIL(&loop->name##_handles, q); \ - h->name##_cb(h); \ - } \ - } \ - \ - void uv__##name##_close(uv_##name##_t* handle) { \ - uv_##name##_stop(handle); \ - } - -UV_LOOP_WATCHER_DEFINE(prepare, PREPARE) -UV_LOOP_WATCHER_DEFINE(check, CHECK) -UV_LOOP_WATCHER_DEFINE(idle, IDLE) diff --git a/vendor/libuv/src/unix/loop.c b/vendor/libuv/src/unix/loop.c deleted file mode 100644 index bd63c2f9d..000000000 --- a/vendor/libuv/src/unix/loop.c +++ /dev/null @@ -1,159 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "tree.h" -#include "internal.h" -#include "heap-inl.h" -#include -#include -#include - -int uv_loop_init(uv_loop_t* loop) { - void* saved_data; - int err; - - uv__signal_global_once_init(); - - saved_data = loop->data; - memset(loop, 0, sizeof(*loop)); - loop->data = saved_data; - - heap_init((struct heap*) &loop->timer_heap); - QUEUE_INIT(&loop->wq); - QUEUE_INIT(&loop->active_reqs); - QUEUE_INIT(&loop->idle_handles); - QUEUE_INIT(&loop->async_handles); - QUEUE_INIT(&loop->check_handles); - QUEUE_INIT(&loop->prepare_handles); - QUEUE_INIT(&loop->handle_queue); - - loop->nfds = 0; - loop->watchers = NULL; - loop->nwatchers = 0; - QUEUE_INIT(&loop->pending_queue); - QUEUE_INIT(&loop->watcher_queue); - - loop->closing_handles = NULL; - uv__update_time(loop); - uv__async_init(&loop->async_watcher); - loop->signal_pipefd[0] = -1; - loop->signal_pipefd[1] = -1; - loop->backend_fd = -1; - loop->emfile_fd = -1; - - loop->timer_counter = 0; - loop->stop_flag = 0; - - err = uv__platform_loop_init(loop); - if (err) - return err; - - err = uv_signal_init(loop, &loop->child_watcher); - if (err) - goto fail_signal_init; - - uv__handle_unref(&loop->child_watcher); - loop->child_watcher.flags |= UV__HANDLE_INTERNAL; - QUEUE_INIT(&loop->process_handles); - - err = uv_rwlock_init(&loop->cloexec_lock); - if (err) - goto fail_rwlock_init; - - err = uv_mutex_init(&loop->wq_mutex); - if (err) - goto fail_mutex_init; - - err = uv_async_init(loop, &loop->wq_async, uv__work_done); - if (err) - goto fail_async_init; - - uv__handle_unref(&loop->wq_async); - loop->wq_async.flags |= UV__HANDLE_INTERNAL; - - return 0; - -fail_async_init: - uv_mutex_destroy(&loop->wq_mutex); - -fail_mutex_init: - uv_rwlock_destroy(&loop->cloexec_lock); - -fail_rwlock_init: - uv__signal_loop_cleanup(loop); - -fail_signal_init: - uv__platform_loop_delete(loop); - - return err; -} - - -void uv__loop_close(uv_loop_t* loop) { - uv__signal_loop_cleanup(loop); - uv__platform_loop_delete(loop); - uv__async_stop(loop, &loop->async_watcher); - - if (loop->emfile_fd != -1) { - uv__close(loop->emfile_fd); - loop->emfile_fd = -1; - } - - if (loop->backend_fd != -1) { - uv__close(loop->backend_fd); - loop->backend_fd = -1; - } - - uv_mutex_lock(&loop->wq_mutex); - assert(QUEUE_EMPTY(&loop->wq) && "thread pool work queue not empty!"); - assert(!uv__has_active_reqs(loop)); - uv_mutex_unlock(&loop->wq_mutex); - uv_mutex_destroy(&loop->wq_mutex); - - /* - * Note that all thread pool stuff is finished at this point and - * it is safe to just destroy rw lock - */ - uv_rwlock_destroy(&loop->cloexec_lock); - -#if 0 - assert(QUEUE_EMPTY(&loop->pending_queue)); - assert(QUEUE_EMPTY(&loop->watcher_queue)); - assert(loop->nfds == 0); -#endif - - uv__free(loop->watchers); - loop->watchers = NULL; - loop->nwatchers = 0; -} - - -int uv__loop_configure(uv_loop_t* loop, uv_loop_option option, va_list ap) { - if (option != UV_LOOP_BLOCK_SIGNAL) - return UV_ENOSYS; - - if (va_arg(ap, int) != SIGPROF) - return UV_EINVAL; - - loop->flags |= UV_LOOP_BLOCK_SIGPROF; - return 0; -} diff --git a/vendor/libuv/src/unix/netbsd.c b/vendor/libuv/src/unix/netbsd.c deleted file mode 100644 index 4a9e6cbc1..000000000 --- a/vendor/libuv/src/unix/netbsd.c +++ /dev/null @@ -1,380 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "internal.h" - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include - -#undef NANOSEC -#define NANOSEC ((uint64_t) 1e9) - -static char *process_title; - - -int uv__platform_loop_init(uv_loop_t* loop) { - return uv__kqueue_init(loop); -} - - -void uv__platform_loop_delete(uv_loop_t* loop) { -} - - -uint64_t uv__hrtime(uv_clocktype_t type) { - struct timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - return (((uint64_t) ts.tv_sec) * NANOSEC + ts.tv_nsec); -} - - -void uv_loadavg(double avg[3]) { - struct loadavg info; - size_t size = sizeof(info); - int which[] = {CTL_VM, VM_LOADAVG}; - - if (sysctl(which, 2, &info, &size, NULL, 0) == -1) return; - - avg[0] = (double) info.ldavg[0] / info.fscale; - avg[1] = (double) info.ldavg[1] / info.fscale; - avg[2] = (double) info.ldavg[2] / info.fscale; -} - - -int uv_exepath(char* buffer, size_t* size) { - int mib[4]; - size_t cb; - pid_t mypid; - - if (buffer == NULL || size == NULL || *size == 0) - return -EINVAL; - - mypid = getpid(); - mib[0] = CTL_KERN; - mib[1] = KERN_PROC_ARGS; - mib[2] = mypid; - mib[3] = KERN_PROC_ARGV; - - cb = *size; - if (sysctl(mib, 4, buffer, &cb, NULL, 0)) - return -errno; - *size = strlen(buffer); - - return 0; -} - - -uint64_t uv_get_free_memory(void) { - struct uvmexp info; - size_t size = sizeof(info); - int which[] = {CTL_VM, VM_UVMEXP}; - - if (sysctl(which, 2, &info, &size, NULL, 0)) - return -errno; - - return (uint64_t) info.free * sysconf(_SC_PAGESIZE); -} - - -uint64_t uv_get_total_memory(void) { -#if defined(HW_PHYSMEM64) - uint64_t info; - int which[] = {CTL_HW, HW_PHYSMEM64}; -#else - unsigned int info; - int which[] = {CTL_HW, HW_PHYSMEM}; -#endif - size_t size = sizeof(info); - - if (sysctl(which, 2, &info, &size, NULL, 0)) - return -errno; - - return (uint64_t) info; -} - - -char** uv_setup_args(int argc, char** argv) { - process_title = argc ? uv__strdup(argv[0]) : NULL; - return argv; -} - - -int uv_set_process_title(const char* title) { - if (process_title) uv__free(process_title); - - process_title = uv__strdup(title); - setproctitle("%s", title); - - return 0; -} - - -int uv_get_process_title(char* buffer, size_t size) { - size_t len; - - if (buffer == NULL || size == 0) - return -EINVAL; - - if (process_title) { - len = strlen(process_title) + 1; - - if (size < len) - return -ENOBUFS; - - memcpy(buffer, process_title, len); - } else { - len = 0; - } - - buffer[len] = '\0'; - - return 0; -} - - -int uv_resident_set_memory(size_t* rss) { - kvm_t *kd = NULL; - struct kinfo_proc2 *kinfo = NULL; - pid_t pid; - int nprocs; - int max_size = sizeof(struct kinfo_proc2); - int page_size; - - page_size = getpagesize(); - pid = getpid(); - - kd = kvm_open(NULL, NULL, NULL, KVM_NO_FILES, "kvm_open"); - - if (kd == NULL) goto error; - - kinfo = kvm_getproc2(kd, KERN_PROC_PID, pid, max_size, &nprocs); - if (kinfo == NULL) goto error; - - *rss = kinfo->p_vm_rssize * page_size; - - kvm_close(kd); - - return 0; - -error: - if (kd) kvm_close(kd); - return -EPERM; -} - - -int uv_uptime(double* uptime) { - time_t now; - struct timeval info; - size_t size = sizeof(info); - static int which[] = {CTL_KERN, KERN_BOOTTIME}; - - if (sysctl(which, 2, &info, &size, NULL, 0)) - return -errno; - - now = time(NULL); - - *uptime = (double)(now - info.tv_sec); - return 0; -} - - -int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { - unsigned int ticks = (unsigned int)sysconf(_SC_CLK_TCK); - unsigned int multiplier = ((uint64_t)1000L / ticks); - unsigned int cur = 0; - uv_cpu_info_t* cpu_info; - u_int64_t* cp_times; - char model[512]; - u_int64_t cpuspeed; - int numcpus; - size_t size; - int i; - - size = sizeof(model); - if (sysctlbyname("machdep.cpu_brand", &model, &size, NULL, 0) && - sysctlbyname("hw.model", &model, &size, NULL, 0)) { - return -errno; - } - - size = sizeof(numcpus); - if (sysctlbyname("hw.ncpu", &numcpus, &size, NULL, 0)) - return -errno; - *count = numcpus; - - /* Only i386 and amd64 have machdep.tsc_freq */ - size = sizeof(cpuspeed); - if (sysctlbyname("machdep.tsc_freq", &cpuspeed, &size, NULL, 0)) - cpuspeed = 0; - - size = numcpus * CPUSTATES * sizeof(*cp_times); - cp_times = uv__malloc(size); - if (cp_times == NULL) - return -ENOMEM; - - if (sysctlbyname("kern.cp_time", cp_times, &size, NULL, 0)) - return -errno; - - *cpu_infos = uv__malloc(numcpus * sizeof(**cpu_infos)); - if (!(*cpu_infos)) { - uv__free(cp_times); - uv__free(*cpu_infos); - return -ENOMEM; - } - - for (i = 0; i < numcpus; i++) { - cpu_info = &(*cpu_infos)[i]; - cpu_info->cpu_times.user = (uint64_t)(cp_times[CP_USER+cur]) * multiplier; - cpu_info->cpu_times.nice = (uint64_t)(cp_times[CP_NICE+cur]) * multiplier; - cpu_info->cpu_times.sys = (uint64_t)(cp_times[CP_SYS+cur]) * multiplier; - cpu_info->cpu_times.idle = (uint64_t)(cp_times[CP_IDLE+cur]) * multiplier; - cpu_info->cpu_times.irq = (uint64_t)(cp_times[CP_INTR+cur]) * multiplier; - cpu_info->model = uv__strdup(model); - cpu_info->speed = (int)(cpuspeed/(uint64_t) 1e6); - cur += CPUSTATES; - } - uv__free(cp_times); - return 0; -} - - -void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { - int i; - - for (i = 0; i < count; i++) { - uv__free(cpu_infos[i].model); - } - - uv__free(cpu_infos); -} - - -int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { - struct ifaddrs *addrs, *ent; - uv_interface_address_t* address; - int i; - struct sockaddr_dl *sa_addr; - - if (getifaddrs(&addrs)) - return -errno; - - *count = 0; - - /* Count the number of interfaces */ - for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)) || - (ent->ifa_addr == NULL) || - (ent->ifa_addr->sa_family != PF_INET)) { - continue; - } - (*count)++; - } - - *addresses = uv__malloc(*count * sizeof(**addresses)); - - if (!(*addresses)) { - freeifaddrs(addrs); - return -ENOMEM; - } - - address = *addresses; - - for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING))) - continue; - - if (ent->ifa_addr == NULL) - continue; - - if (ent->ifa_addr->sa_family != PF_INET) - continue; - - address->name = uv__strdup(ent->ifa_name); - - if (ent->ifa_addr->sa_family == AF_INET6) { - address->address.address6 = *((struct sockaddr_in6*) ent->ifa_addr); - } else { - address->address.address4 = *((struct sockaddr_in*) ent->ifa_addr); - } - - if (ent->ifa_netmask->sa_family == AF_INET6) { - address->netmask.netmask6 = *((struct sockaddr_in6*) ent->ifa_netmask); - } else { - address->netmask.netmask4 = *((struct sockaddr_in*) ent->ifa_netmask); - } - - address->is_internal = !!(ent->ifa_flags & IFF_LOOPBACK); - - address++; - } - - /* Fill in physical addresses for each interface */ - for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)) || - (ent->ifa_addr == NULL) || - (ent->ifa_addr->sa_family != AF_LINK)) { - continue; - } - - address = *addresses; - - for (i = 0; i < (*count); i++) { - if (strcmp(address->name, ent->ifa_name) == 0) { - sa_addr = (struct sockaddr_dl*)(ent->ifa_addr); - memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr)); - } - address++; - } - } - - freeifaddrs(addrs); - - return 0; -} - - -void uv_free_interface_addresses(uv_interface_address_t* addresses, int count) { - int i; - - for (i = 0; i < count; i++) { - uv__free(addresses[i].name); - } - - uv__free(addresses); -} diff --git a/vendor/libuv/src/unix/openbsd.c b/vendor/libuv/src/unix/openbsd.c deleted file mode 100644 index 909288cc8..000000000 --- a/vendor/libuv/src/unix/openbsd.c +++ /dev/null @@ -1,396 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "internal.h" - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#undef NANOSEC -#define NANOSEC ((uint64_t) 1e9) - - -static char *process_title; - - -int uv__platform_loop_init(uv_loop_t* loop) { - return uv__kqueue_init(loop); -} - - -void uv__platform_loop_delete(uv_loop_t* loop) { -} - - -uint64_t uv__hrtime(uv_clocktype_t type) { - struct timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - return (((uint64_t) ts.tv_sec) * NANOSEC + ts.tv_nsec); -} - - -void uv_loadavg(double avg[3]) { - struct loadavg info; - size_t size = sizeof(info); - int which[] = {CTL_VM, VM_LOADAVG}; - - if (sysctl(which, 2, &info, &size, NULL, 0) < 0) return; - - avg[0] = (double) info.ldavg[0] / info.fscale; - avg[1] = (double) info.ldavg[1] / info.fscale; - avg[2] = (double) info.ldavg[2] / info.fscale; -} - - -int uv_exepath(char* buffer, size_t* size) { - int mib[4]; - char **argsbuf = NULL; - char **argsbuf_tmp; - size_t argsbuf_size = 100U; - size_t exepath_size; - pid_t mypid; - int err; - - if (buffer == NULL || size == NULL || *size == 0) - return -EINVAL; - - mypid = getpid(); - for (;;) { - err = -ENOMEM; - argsbuf_tmp = uv__realloc(argsbuf, argsbuf_size); - if (argsbuf_tmp == NULL) - goto out; - argsbuf = argsbuf_tmp; - mib[0] = CTL_KERN; - mib[1] = KERN_PROC_ARGS; - mib[2] = mypid; - mib[3] = KERN_PROC_ARGV; - if (sysctl(mib, 4, argsbuf, &argsbuf_size, NULL, 0) == 0) { - break; - } - if (errno != ENOMEM) { - err = -errno; - goto out; - } - argsbuf_size *= 2U; - } - - if (argsbuf[0] == NULL) { - err = -EINVAL; /* FIXME(bnoordhuis) More appropriate error. */ - goto out; - } - - *size -= 1; - exepath_size = strlen(argsbuf[0]); - if (*size > exepath_size) - *size = exepath_size; - - memcpy(buffer, argsbuf[0], *size); - buffer[*size] = '\0'; - err = 0; - -out: - uv__free(argsbuf); - - return err; -} - - -uint64_t uv_get_free_memory(void) { - struct uvmexp info; - size_t size = sizeof(info); - int which[] = {CTL_VM, VM_UVMEXP}; - - if (sysctl(which, 2, &info, &size, NULL, 0)) - return -errno; - - return (uint64_t) info.free * sysconf(_SC_PAGESIZE); -} - - -uint64_t uv_get_total_memory(void) { - uint64_t info; - int which[] = {CTL_HW, HW_PHYSMEM64}; - size_t size = sizeof(info); - - if (sysctl(which, 2, &info, &size, NULL, 0)) - return -errno; - - return (uint64_t) info; -} - - -char** uv_setup_args(int argc, char** argv) { - process_title = argc ? uv__strdup(argv[0]) : NULL; - return argv; -} - - -int uv_set_process_title(const char* title) { - uv__free(process_title); - process_title = uv__strdup(title); - setproctitle(title); - return 0; -} - - -int uv_get_process_title(char* buffer, size_t size) { - size_t len; - - if (buffer == NULL || size == 0) - return -EINVAL; - - if (process_title) { - len = strlen(process_title) + 1; - - if (size < len) - return -ENOBUFS; - - memcpy(buffer, process_title, len); - } else { - len = 0; - } - - buffer[len] = '\0'; - - return 0; -} - - -int uv_resident_set_memory(size_t* rss) { - struct kinfo_proc kinfo; - size_t page_size = getpagesize(); - size_t size = sizeof(struct kinfo_proc); - int mib[6]; - - mib[0] = CTL_KERN; - mib[1] = KERN_PROC; - mib[2] = KERN_PROC_PID; - mib[3] = getpid(); - mib[4] = sizeof(struct kinfo_proc); - mib[5] = 1; - - if (sysctl(mib, 6, &kinfo, &size, NULL, 0) < 0) - return -errno; - - *rss = kinfo.p_vm_rssize * page_size; - return 0; -} - - -int uv_uptime(double* uptime) { - time_t now; - struct timeval info; - size_t size = sizeof(info); - static int which[] = {CTL_KERN, KERN_BOOTTIME}; - - if (sysctl(which, 2, &info, &size, NULL, 0)) - return -errno; - - now = time(NULL); - - *uptime = (double)(now - info.tv_sec); - return 0; -} - - -int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { - unsigned int ticks = (unsigned int)sysconf(_SC_CLK_TCK), - multiplier = ((uint64_t)1000L / ticks), cpuspeed; - uint64_t info[CPUSTATES]; - char model[512]; - int numcpus = 1; - int which[] = {CTL_HW,HW_MODEL,0}; - size_t size; - int i; - uv_cpu_info_t* cpu_info; - - size = sizeof(model); - if (sysctl(which, 2, &model, &size, NULL, 0)) - return -errno; - - which[1] = HW_NCPU; - size = sizeof(numcpus); - if (sysctl(which, 2, &numcpus, &size, NULL, 0)) - return -errno; - - *cpu_infos = uv__malloc(numcpus * sizeof(**cpu_infos)); - if (!(*cpu_infos)) - return -ENOMEM; - - *count = numcpus; - - which[1] = HW_CPUSPEED; - size = sizeof(cpuspeed); - if (sysctl(which, 2, &cpuspeed, &size, NULL, 0)) { - uv__free(*cpu_infos); - return -errno; - } - - size = sizeof(info); - which[0] = CTL_KERN; - which[1] = KERN_CPTIME2; - for (i = 0; i < numcpus; i++) { - which[2] = i; - size = sizeof(info); - if (sysctl(which, 3, &info, &size, NULL, 0)) { - uv__free(*cpu_infos); - return -errno; - } - - cpu_info = &(*cpu_infos)[i]; - - cpu_info->cpu_times.user = (uint64_t)(info[CP_USER]) * multiplier; - cpu_info->cpu_times.nice = (uint64_t)(info[CP_NICE]) * multiplier; - cpu_info->cpu_times.sys = (uint64_t)(info[CP_SYS]) * multiplier; - cpu_info->cpu_times.idle = (uint64_t)(info[CP_IDLE]) * multiplier; - cpu_info->cpu_times.irq = (uint64_t)(info[CP_INTR]) * multiplier; - - cpu_info->model = uv__strdup(model); - cpu_info->speed = cpuspeed; - } - - return 0; -} - - -void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { - int i; - - for (i = 0; i < count; i++) { - uv__free(cpu_infos[i].model); - } - - uv__free(cpu_infos); -} - - -int uv_interface_addresses(uv_interface_address_t** addresses, - int* count) { - struct ifaddrs *addrs, *ent; - uv_interface_address_t* address; - int i; - struct sockaddr_dl *sa_addr; - - if (getifaddrs(&addrs) != 0) - return -errno; - - *count = 0; - - /* Count the number of interfaces */ - for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)) || - (ent->ifa_addr == NULL) || - (ent->ifa_addr->sa_family != PF_INET)) { - continue; - } - (*count)++; - } - - *addresses = uv__malloc(*count * sizeof(**addresses)); - - if (!(*addresses)) { - freeifaddrs(addrs); - return -ENOMEM; - } - - address = *addresses; - - for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING))) - continue; - - if (ent->ifa_addr == NULL) - continue; - - if (ent->ifa_addr->sa_family != PF_INET) - continue; - - address->name = uv__strdup(ent->ifa_name); - - if (ent->ifa_addr->sa_family == AF_INET6) { - address->address.address6 = *((struct sockaddr_in6*) ent->ifa_addr); - } else { - address->address.address4 = *((struct sockaddr_in*) ent->ifa_addr); - } - - if (ent->ifa_netmask->sa_family == AF_INET6) { - address->netmask.netmask6 = *((struct sockaddr_in6*) ent->ifa_netmask); - } else { - address->netmask.netmask4 = *((struct sockaddr_in*) ent->ifa_netmask); - } - - address->is_internal = !!(ent->ifa_flags & IFF_LOOPBACK); - - address++; - } - - /* Fill in physical addresses for each interface */ - for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)) || - (ent->ifa_addr == NULL) || - (ent->ifa_addr->sa_family != AF_LINK)) { - continue; - } - - address = *addresses; - - for (i = 0; i < (*count); i++) { - if (strcmp(address->name, ent->ifa_name) == 0) { - sa_addr = (struct sockaddr_dl*)(ent->ifa_addr); - memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr)); - } - address++; - } - } - - freeifaddrs(addrs); - - return 0; -} - - -void uv_free_interface_addresses(uv_interface_address_t* addresses, - int count) { - int i; - - for (i = 0; i < count; i++) { - uv__free(addresses[i].name); - } - - uv__free(addresses); -} diff --git a/vendor/libuv/src/unix/os390-syscalls.c b/vendor/libuv/src/unix/os390-syscalls.c deleted file mode 100644 index 2bf3b7381..000000000 --- a/vendor/libuv/src/unix/os390-syscalls.c +++ /dev/null @@ -1,334 +0,0 @@ -/* Copyright libuv project contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - - -#include "os390-syscalls.h" -#include -#include -#include -#include - -#define CW_CONDVAR 32 - -#pragma linkage(BPX4CTW, OS) -#pragma linkage(BPX1CTW, OS) - -static int number_of_epolls; -static QUEUE global_epoll_queue; -static uv_mutex_t global_epoll_lock; -static uv_once_t once = UV_ONCE_INIT; - -int scandir(const char* maindir, struct dirent*** namelist, - int (*filter)(const struct dirent*), - int (*compar)(const struct dirent**, - const struct dirent **)) { - struct dirent** nl; - struct dirent* dirent; - unsigned count; - size_t allocated; - DIR* mdir; - - nl = NULL; - count = 0; - allocated = 0; - mdir = opendir(maindir); - if (!mdir) - return -1; - - while (1) { - dirent = readdir(mdir); - if (!dirent) - break; - if (!filter || filter(dirent)) { - struct dirent* copy; - copy = uv__malloc(sizeof(*copy)); - if (!copy) { - while (count) { - dirent = nl[--count]; - uv__free(dirent); - } - uv__free(nl); - closedir(mdir); - errno = ENOMEM; - return -1; - } - memcpy(copy, dirent, sizeof(*copy)); - - nl = uv__realloc(nl, sizeof(*copy) * (count + 1)); - nl[count++] = copy; - } - } - - qsort(nl, count, sizeof(struct dirent *), - (int (*)(const void *, const void *)) compar); - - closedir(mdir); - - *namelist = nl; - return count; -} - - -static unsigned int next_power_of_two(unsigned int val) { - val -= 1; - val |= val >> 1; - val |= val >> 2; - val |= val >> 4; - val |= val >> 8; - val |= val >> 16; - val += 1; - return val; -} - - -static void maybe_resize(uv__os390_epoll* lst, unsigned int len) { - unsigned int newsize; - unsigned int i; - struct pollfd* newlst; - - if (len <= lst->size) - return; - - newsize = next_power_of_two(len); - newlst = uv__realloc(lst->items, newsize * sizeof(lst->items[0])); - - if (newlst == NULL) - abort(); - for (i = lst->size; i < newsize; ++i) - newlst[i].fd = -1; - - lst->items = newlst; - lst->size = newsize; -} - - -static void epoll_init() { - QUEUE_INIT(&global_epoll_queue); - if (uv_mutex_init(&global_epoll_lock)) - abort(); -} - - -uv__os390_epoll* epoll_create1(int flags) { - uv__os390_epoll* lst; - - uv_once(&once, epoll_init); - uv_mutex_lock(&global_epoll_lock); - lst = uv__malloc(sizeof(*lst)); - if (lst == -1) - return NULL; - QUEUE_INSERT_TAIL(&global_epoll_queue, &lst->member); - uv_mutex_unlock(&global_epoll_lock); - - /* initialize list */ - lst->size = 0; - lst->items = NULL; - return lst; -} - - -int epoll_ctl(uv__os390_epoll* lst, - int op, - int fd, - struct epoll_event *event) { - if(op == EPOLL_CTL_DEL) { - if (fd >= lst->size || lst->items[fd].fd == -1) { - errno = ENOENT; - return -1; - } - lst->items[fd].fd = -1; - } else if(op == EPOLL_CTL_ADD) { - maybe_resize(lst, fd + 1); - if (lst->items[fd].fd != -1) { - errno = EEXIST; - return -1; - } - lst->items[fd].fd = fd; - lst->items[fd].events = event->events; - } else if(op == EPOLL_CTL_MOD) { - if (fd >= lst->size || lst->items[fd].fd == -1) { - errno = ENOENT; - return -1; - } - lst->items[fd].events = event->events; - } else - abort(); - - return 0; -} - - -int epoll_wait(uv__os390_epoll* lst, struct epoll_event* events, - int maxevents, int timeout) { - size_t size; - struct pollfd* pfds; - int pollret; - int reventcount; - - uv_mutex_lock(&global_epoll_lock); - uv_mutex_unlock(&global_epoll_lock); - size = lst->size; - pfds = lst->items; - pollret = poll(pfds, size, timeout); - if(pollret == -1) - return pollret; - - reventcount = 0; - for (int i = 0; i < lst->size && i < maxevents; ++i) { - struct epoll_event ev; - - ev.events = 0; - ev.fd = pfds[i].fd; - if(!pfds[i].revents) - continue; - - if(pfds[i].revents & POLLRDNORM) - ev.events = ev.events | POLLIN; - - if(pfds[i].revents & POLLWRNORM) - ev.events = ev.events | POLLOUT; - - if(pfds[i].revents & POLLHUP) - ev.events = ev.events | POLLHUP; - - pfds[i].revents = 0; - events[reventcount++] = ev; - } - - return reventcount; -} - - -int epoll_file_close(int fd) { - QUEUE* q; - - uv_once(&once, epoll_init); - uv_mutex_lock(&global_epoll_lock); - QUEUE_FOREACH(q, &global_epoll_queue) { - uv__os390_epoll* lst; - - lst = QUEUE_DATA(q, uv__os390_epoll, member); - if (fd < lst->size && lst->items != NULL && lst->items[fd].fd != -1) - lst->items[fd].fd = -1; - } - - uv_mutex_unlock(&global_epoll_lock); - return 0; -} - -void epoll_queue_close(uv__os390_epoll* lst) { - uv_mutex_lock(&global_epoll_lock); - QUEUE_REMOVE(&lst->member); - uv_mutex_unlock(&global_epoll_lock); - uv__free(lst->items); - lst->items = NULL; -} - - -int nanosleep(const struct timespec* req, struct timespec* rem) { - unsigned nano; - unsigned seconds; - unsigned events; - unsigned secrem; - unsigned nanorem; - int rv; - int rc; - int rsn; - - nano = (int)req->tv_nsec; - seconds = req->tv_sec; - events = CW_CONDVAR; - -#if defined(_LP64) - BPX4CTW(&seconds, &nano, &events, &secrem, &nanorem, &rv, &rc, &rsn); -#else - BPX1CTW(&seconds, &nano, &events, &secrem, &nanorem, &rv, &rc, &rsn); -#endif - - assert(rv == -1 && errno == EAGAIN); - - if(rem != NULL) { - rem->tv_nsec = nanorem; - rem->tv_sec = secrem; - } - - return 0; -} - - -char* mkdtemp(char* path) { - static const char* tempchars = - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; - static const size_t num_chars = 62; - static const size_t num_x = 6; - char *ep, *cp; - unsigned int tries, i; - size_t len; - uint64_t v; - int fd; - int retval; - int saved_errno; - - len = strlen(path); - ep = path + len; - if (len < num_x || strncmp(ep - num_x, "XXXXXX", num_x)) { - errno = EINVAL; - return NULL; - } - - fd = open("/dev/urandom", O_RDONLY); - if (fd == -1) - return NULL; - - tries = TMP_MAX; - retval = -1; - do { - if (read(fd, &v, sizeof(v)) != sizeof(v)) - break; - - cp = ep - num_x; - for (i = 0; i < num_x; i++) { - *cp++ = tempchars[v % num_chars]; - v /= num_chars; - } - - if (mkdir(path, S_IRWXU) == 0) { - retval = 0; - break; - } - else if (errno != EEXIST) - break; - } while (--tries); - - saved_errno = errno; - uv__close(fd); - if (tries == 0) { - errno = EEXIST; - return NULL; - } - - if (retval == -1) { - errno = saved_errno; - return NULL; - } - - return path; -} diff --git a/vendor/libuv/src/unix/os390-syscalls.h b/vendor/libuv/src/unix/os390-syscalls.h deleted file mode 100644 index 61a7cee83..000000000 --- a/vendor/libuv/src/unix/os390-syscalls.h +++ /dev/null @@ -1,69 +0,0 @@ -/* Copyright libuv project contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - - -#ifndef UV_OS390_SYSCALL_H_ -#define UV_OS390_SYSCALL_H_ - -#include "uv.h" -#include "internal.h" -#include -#include -#include - -#define EPOLL_CTL_ADD 1 -#define EPOLL_CTL_DEL 2 -#define EPOLL_CTL_MOD 3 -#define MAX_EPOLL_INSTANCES 256 -#define MAX_ITEMS_PER_EPOLL 1024 - -#define UV__O_CLOEXEC 0x80000 -#define UV__EPOLL_CLOEXEC UV__O_CLOEXEC -#define UV__EPOLL_CTL_ADD EPOLL_CTL_ADD -#define UV__EPOLL_CTL_DEL EPOLL_CTL_DEL -#define UV__EPOLL_CTL_MOD EPOLL_CTL_MOD - -struct epoll_event { - int events; - int fd; -}; - -typedef struct { - QUEUE member; - struct pollfd* items; - unsigned long size; -} uv__os390_epoll; - -/* epoll api */ -uv__os390_epoll* epoll_create1(int flags); -int epoll_ctl(uv__os390_epoll* ep, int op, int fd, struct epoll_event *event); -int epoll_wait(uv__os390_epoll* ep, struct epoll_event *events, int maxevents, int timeout); -int epoll_file_close(int fd); - -/* utility functions */ -int nanosleep(const struct timespec* req, struct timespec* rem); -int scandir(const char* maindir, struct dirent*** namelist, - int (*filter)(const struct dirent *), - int (*compar)(const struct dirent **, - const struct dirent **)); -char *mkdtemp(char* path); - -#endif /* UV_OS390_SYSCALL_H_ */ diff --git a/vendor/libuv/src/unix/os390.c b/vendor/libuv/src/unix/os390.c deleted file mode 100644 index be325a923..000000000 --- a/vendor/libuv/src/unix/os390.c +++ /dev/null @@ -1,865 +0,0 @@ -/* Copyright libuv project contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "internal.h" -#include -#include -#include -#include -#include -#if defined(__clang__) -#include "csrsic.h" -#else -#include "//'SYS1.SAMPLIB(CSRSIC)'" -#endif - -#define CVT_PTR 0x10 -#define CSD_OFFSET 0x294 - -/* - Long-term average CPU service used by this logical partition, - in millions of service units per hour. If this value is above - the partition's defined capacity, the partition will be capped. - It is calculated using the physical CPU adjustment factor - (RCTPCPUA) so it may not match other measures of service which - are based on the logical CPU adjustment factor. It is available - if the hardware supports LPAR cluster. -*/ -#define RCTLACS_OFFSET 0xC4 - -/* 32-bit count of alive CPUs. This includes both CPs and IFAs */ -#define CSD_NUMBER_ONLINE_CPUS 0xD4 - -/* Address of system resources manager (SRM) control table */ -#define CVTOPCTP_OFFSET 0x25C - -/* Address of the RCT table */ -#define RMCTRCT_OFFSET 0xE4 - -/* Address of the rsm control and enumeration area. */ -#define CVTRCEP_OFFSET 0x490 - -/* - Number of frames currently available to system. - Excluded are frames backing perm storage, frames offline, and bad frames. -*/ -#define RCEPOOL_OFFSET 0x004 - -/* Total number of frames currently on all available frame queues. */ -#define RCEAFC_OFFSET 0x088 - -/* CPC model length from the CSRSI Service. */ -#define CPCMODEL_LENGTH 16 - -/* Thread Entry constants */ -#define PGTH_CURRENT 1 -#define PGTH_LEN 26 -#define PGTHAPATH 0x20 -#pragma linkage(BPX4GTH, OS) -#pragma linkage(BPX1GTH, OS) - -typedef unsigned data_area_ptr_assign_type; - -typedef union { - struct { -#if defined(_LP64) - data_area_ptr_assign_type lower; -#endif - data_area_ptr_assign_type assign; - }; - char* deref; -} data_area_ptr; - - -void uv_loadavg(double avg[3]) { - /* TODO: implement the following */ - avg[0] = 0; - avg[1] = 0; - avg[2] = 0; -} - - -int uv__platform_loop_init(uv_loop_t* loop) { - uv__os390_epoll* ep; - - ep = epoll_create1(UV__EPOLL_CLOEXEC); - loop->ep = ep; - if (ep == NULL) - return -errno; - - return 0; -} - - -void uv__platform_loop_delete(uv_loop_t* loop) { - if (loop->ep != NULL) { - epoll_queue_close(loop->ep); - loop->ep = NULL; - } -} - - -uint64_t uv__hrtime(uv_clocktype_t type) { - struct timeval time; - gettimeofday(&time, NULL); - return (uint64_t) time.tv_sec * 1e9 + time.tv_usec * 1e3; -} - - -/* - Get the exe path using the thread entry information - in the address space. -*/ -static int getexe(const int pid, char* buf, size_t len) { - struct { - int pid; - int thid[2]; - char accesspid; - char accessthid; - char asid[2]; - char loginname[8]; - char flag; - char len; - } Input_data; - - union { - struct { - char gthb[4]; - int pid; - int thid[2]; - char accesspid; - char accessthid[3]; - int lenused; - int offsetProcess; - int offsetConTTY; - int offsetPath; - int offsetCommand; - int offsetFileData; - int offsetThread; - } Output_data; - char buf[2048]; - } Output_buf; - - struct Output_path_type { - char gthe[4]; - short int len; - char path[1024]; - }; - - int Input_length; - int Output_length; - void* Input_address; - void* Output_address; - struct Output_path_type* Output_path; - int rv; - int rc; - int rsn; - - Input_length = PGTH_LEN; - Output_length = sizeof(Output_buf); - Output_address = &Output_buf; - Input_address = &Input_data; - memset(&Input_data, 0, sizeof Input_data); - Input_data.flag |= PGTHAPATH; - Input_data.pid = pid; - Input_data.accesspid = PGTH_CURRENT; - -#ifdef _LP64 - BPX4GTH(&Input_length, - &Input_address, - &Output_length, - &Output_address, - &rv, - &rc, - &rsn); -#else - BPX1GTH(&Input_length, - &Input_address, - &Output_length, - &Output_address, - &rv, - &rc, - &rsn); -#endif - - if (rv == -1) { - errno = rc; - return -1; - } - - /* Check highest byte to ensure data availability */ - assert(((Output_buf.Output_data.offsetPath >>24) & 0xFF) == 'A'); - - /* Get the offset from the lowest 3 bytes */ - Output_path = (char*)(&Output_buf) + - (Output_buf.Output_data.offsetPath & 0x00FFFFFF); - - if (Output_path->len >= len) { - errno = ENOBUFS; - return -1; - } - - strncpy(buf, Output_path->path, len); - - return 0; -} - - -/* - * We could use a static buffer for the path manipulations that we need outside - * of the function, but this function could be called by multiple consumers and - * we don't want to potentially create a race condition in the use of snprintf. - * There is no direct way of getting the exe path in zOS - either through /procfs - * or through some libc APIs. The below approach is to parse the argv[0]'s pattern - * and use it in conjunction with PATH environment variable to craft one. - */ -int uv_exepath(char* buffer, size_t* size) { - int res; - char args[PATH_MAX]; - char abspath[PATH_MAX]; - size_t abspath_size; - int pid; - - if (buffer == NULL || size == NULL || *size == 0) - return -EINVAL; - - pid = getpid(); - res = getexe(pid, args, sizeof(args)); - if (res < 0) - return -EINVAL; - - /* - * Possibilities for args: - * i) an absolute path such as: /home/user/myprojects/nodejs/node - * ii) a relative path such as: ./node or ../myprojects/nodejs/node - * iii) a bare filename such as "node", after exporting PATH variable - * to its location. - */ - - /* Case i) and ii) absolute or relative paths */ - if (strchr(args, '/') != NULL) { - if (realpath(args, abspath) != abspath) - return -errno; - - abspath_size = strlen(abspath); - - *size -= 1; - if (*size > abspath_size) - *size = abspath_size; - - memcpy(buffer, abspath, *size); - buffer[*size] = '\0'; - - return 0; - } else { - /* Case iii). Search PATH environment variable */ - char trypath[PATH_MAX]; - char* clonedpath = NULL; - char* token = NULL; - char* path = getenv("PATH"); - - if (path == NULL) - return -EINVAL; - - clonedpath = uv__strdup(path); - if (clonedpath == NULL) - return -ENOMEM; - - token = strtok(clonedpath, ":"); - while (token != NULL) { - snprintf(trypath, sizeof(trypath) - 1, "%s/%s", token, args); - if (realpath(trypath, abspath) == abspath) { - /* Check the match is executable */ - if (access(abspath, X_OK) == 0) { - abspath_size = strlen(abspath); - - *size -= 1; - if (*size > abspath_size) - *size = abspath_size; - - memcpy(buffer, abspath, *size); - buffer[*size] = '\0'; - - uv__free(clonedpath); - return 0; - } - } - token = strtok(NULL, ":"); - } - uv__free(clonedpath); - - /* Out of tokens (path entries), and no match found */ - return -EINVAL; - } -} - - -uint64_t uv_get_free_memory(void) { - uint64_t freeram; - - data_area_ptr cvt = {0}; - data_area_ptr rcep = {0}; - cvt.assign = *(data_area_ptr_assign_type*)(CVT_PTR); - rcep.assign = *(data_area_ptr_assign_type*)(cvt.deref + CVTRCEP_OFFSET); - freeram = *((uint64_t*)(rcep.deref + RCEAFC_OFFSET)) * 4; - return freeram; -} - - -uint64_t uv_get_total_memory(void) { - uint64_t totalram; - - data_area_ptr cvt = {0}; - data_area_ptr rcep = {0}; - cvt.assign = *(data_area_ptr_assign_type*)(CVT_PTR); - rcep.assign = *(data_area_ptr_assign_type*)(cvt.deref + CVTRCEP_OFFSET); - totalram = *((uint64_t*)(rcep.deref + RCEPOOL_OFFSET)) * 4; - return totalram; -} - - -int uv_resident_set_memory(size_t* rss) { - W_PSPROC buf; - - memset(&buf, 0, sizeof(buf)); - if (w_getpsent(0, &buf, sizeof(W_PSPROC)) == -1) - return -EINVAL; - - *rss = buf.ps_size; - return 0; -} - - -int uv_uptime(double* uptime) { - struct utmpx u ; - struct utmpx *v; - time64_t t; - - u.ut_type = BOOT_TIME; - v = getutxid(&u); - if (v == NULL) - return -1; - *uptime = difftime64(time64(&t), v->ut_tv.tv_sec); - return 0; -} - - -int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { - uv_cpu_info_t* cpu_info; - int result; - int idx; - siv1v2 info; - data_area_ptr cvt = {0}; - data_area_ptr csd = {0}; - data_area_ptr rmctrct = {0}; - data_area_ptr cvtopctp = {0}; - int cpu_usage_avg; - - cvt.assign = *(data_area_ptr_assign_type*)(CVT_PTR); - - csd.assign = *((data_area_ptr_assign_type *) (cvt.deref + CSD_OFFSET)); - cvtopctp.assign = *((data_area_ptr_assign_type *) (cvt.deref + CVTOPCTP_OFFSET)); - rmctrct.assign = *((data_area_ptr_assign_type *) (cvtopctp.deref + RMCTRCT_OFFSET)); - - *count = *((int*) (csd.deref + CSD_NUMBER_ONLINE_CPUS)); - cpu_usage_avg = *((unsigned short int*) (rmctrct.deref + RCTLACS_OFFSET)); - - *cpu_infos = uv__malloc(*count * sizeof(uv_cpu_info_t)); - if (!*cpu_infos) - return -ENOMEM; - - cpu_info = *cpu_infos; - idx = 0; - while (idx < *count) { - cpu_info->speed = *(int*)(info.siv1v2si22v1.si22v1cpucapability); - cpu_info->model = uv__malloc(CPCMODEL_LENGTH + 1); - memset(cpu_info->model, '\0', CPCMODEL_LENGTH + 1); - memcpy(cpu_info->model, info.siv1v2si11v1.si11v1cpcmodel, CPCMODEL_LENGTH); - cpu_info->cpu_times.user = cpu_usage_avg; - /* TODO: implement the following */ - cpu_info->cpu_times.sys = 0; - cpu_info->cpu_times.idle = 0; - cpu_info->cpu_times.irq = 0; - cpu_info->cpu_times.nice = 0; - ++cpu_info; - ++idx; - } - - return 0; -} - - -void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { - for (int i = 0; i < count; ++i) - uv__free(cpu_infos[i].model); - uv__free(cpu_infos); -} - - -static int uv__interface_addresses_v6(uv_interface_address_t** addresses, - int* count) { - uv_interface_address_t* address; - int sockfd; - int maxsize; - __net_ifconf6header_t ifc; - __net_ifconf6entry_t* ifr; - __net_ifconf6entry_t* p; - __net_ifconf6entry_t flg; - - *count = 0; - /* Assume maximum buffer size allowable */ - maxsize = 16384; - - if (0 > (sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP))) - return -errno; - - ifc.__nif6h_version = 1; - ifc.__nif6h_buflen = maxsize; - ifc.__nif6h_buffer = uv__calloc(1, maxsize);; - - if (ioctl(sockfd, SIOCGIFCONF6, &ifc) == -1) { - uv__close(sockfd); - return -errno; - } - - - *count = 0; - ifr = (__net_ifconf6entry_t*)(ifc.__nif6h_buffer); - while ((char*)ifr < (char*)ifc.__nif6h_buffer + ifc.__nif6h_buflen) { - p = ifr; - ifr = (__net_ifconf6entry_t*)((char*)ifr + ifc.__nif6h_entrylen); - - if (!(p->__nif6e_addr.sin6_family == AF_INET6 || - p->__nif6e_addr.sin6_family == AF_INET)) - continue; - - if (!(p->__nif6e_flags & _NIF6E_FLAGS_ON_LINK_ACTIVE)) - continue; - - ++(*count); - } - - /* Alloc the return interface structs */ - *addresses = uv__malloc(*count * sizeof(uv_interface_address_t)); - if (!(*addresses)) { - uv__close(sockfd); - return -ENOMEM; - } - address = *addresses; - - ifr = (__net_ifconf6entry_t*)(ifc.__nif6h_buffer); - while ((char*)ifr < (char*)ifc.__nif6h_buffer + ifc.__nif6h_buflen) { - p = ifr; - ifr = (__net_ifconf6entry_t*)((char*)ifr + ifc.__nif6h_entrylen); - - if (!(p->__nif6e_addr.sin6_family == AF_INET6 || - p->__nif6e_addr.sin6_family == AF_INET)) - continue; - - if (!(p->__nif6e_flags & _NIF6E_FLAGS_ON_LINK_ACTIVE)) - continue; - - /* All conditions above must match count loop */ - - address->name = uv__strdup(p->__nif6e_name); - - if (p->__nif6e_addr.sin6_family == AF_INET6) - address->address.address6 = *((struct sockaddr_in6*) &p->__nif6e_addr); - else - address->address.address4 = *((struct sockaddr_in*) &p->__nif6e_addr); - - /* TODO: Retrieve netmask using SIOCGIFNETMASK ioctl */ - - address->is_internal = flg.__nif6e_flags & _NIF6E_FLAGS_LOOPBACK ? 1 : 0; - - address++; - } - - uv__close(sockfd); - return 0; -} - - -int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { - uv_interface_address_t* address; - int sockfd; - int maxsize; - struct ifconf ifc; - struct ifreq flg; - struct ifreq* ifr; - struct ifreq* p; - int count_v6; - - /* get the ipv6 addresses first */ - uv_interface_address_t* addresses_v6; - uv__interface_addresses_v6(&addresses_v6, &count_v6); - - /* now get the ipv4 addresses */ - *count = 0; - - /* Assume maximum buffer size allowable */ - maxsize = 16384; - - sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); - if (0 > sockfd) - return -errno; - - ifc.ifc_req = uv__calloc(1, maxsize); - ifc.ifc_len = maxsize; - if (ioctl(sockfd, SIOCGIFCONF, &ifc) == -1) { - uv__close(sockfd); - return -errno; - } - -#define MAX(a,b) (((a)>(b))?(a):(b)) -#define ADDR_SIZE(p) MAX((p).sa_len, sizeof(p)) - - /* Count all up and running ipv4/ipv6 addresses */ - ifr = ifc.ifc_req; - while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) { - p = ifr; - ifr = (struct ifreq*) - ((char*)ifr + sizeof(ifr->ifr_name) + ADDR_SIZE(ifr->ifr_addr)); - - if (!(p->ifr_addr.sa_family == AF_INET6 || - p->ifr_addr.sa_family == AF_INET)) - continue; - - memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name)); - if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) { - uv__close(sockfd); - return -errno; - } - - if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING)) - continue; - - (*count)++; - } - - /* Alloc the return interface structs */ - *addresses = uv__malloc((*count + count_v6) * - sizeof(uv_interface_address_t)); - - if (!(*addresses)) { - uv__close(sockfd); - return -ENOMEM; - } - address = *addresses; - - /* copy over the ipv6 addresses */ - memcpy(address, addresses_v6, count_v6 * sizeof(uv_interface_address_t)); - address += count_v6; - *count += count_v6; - uv__free(addresses_v6); - - ifr = ifc.ifc_req; - while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) { - p = ifr; - ifr = (struct ifreq*) - ((char*)ifr + sizeof(ifr->ifr_name) + ADDR_SIZE(ifr->ifr_addr)); - - if (!(p->ifr_addr.sa_family == AF_INET6 || - p->ifr_addr.sa_family == AF_INET)) - continue; - - memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name)); - if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) { - uv__close(sockfd); - return -ENOSYS; - } - - if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING)) - continue; - - /* All conditions above must match count loop */ - - address->name = uv__strdup(p->ifr_name); - - if (p->ifr_addr.sa_family == AF_INET6) { - address->address.address6 = *((struct sockaddr_in6*) &p->ifr_addr); - } else { - address->address.address4 = *((struct sockaddr_in*) &p->ifr_addr); - } - - address->is_internal = flg.ifr_flags & IFF_LOOPBACK ? 1 : 0; - address++; - } - -#undef ADDR_SIZE -#undef MAX - - uv__close(sockfd); - return 0; -} - - -void uv_free_interface_addresses(uv_interface_address_t* addresses, - int count) { - int i; - for (i = 0; i < count; ++i) - uv__free(addresses[i].name); - uv__free(addresses); -} - - -void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) { - struct epoll_event* events; - struct epoll_event dummy; - uintptr_t i; - uintptr_t nfds; - - assert(loop->watchers != NULL); - - events = (struct epoll_event*) loop->watchers[loop->nwatchers]; - nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1]; - if (events != NULL) - /* Invalidate events with same file descriptor */ - for (i = 0; i < nfds; i++) - if ((int) events[i].fd == fd) - events[i].fd = -1; - - /* Remove the file descriptor from the epoll. */ - if (loop->ep != NULL) - epoll_ctl(loop->ep, UV__EPOLL_CTL_DEL, fd, &dummy); -} - - -int uv__io_check_fd(uv_loop_t* loop, int fd) { - struct pollfd p[1]; - int rv; - - p[0].fd = fd; - p[0].events = POLLIN; - - do - rv = poll(p, 1, 0); - while (rv == -1 && errno == EINTR); - - if (rv == -1) - abort(); - - if (p[0].revents & POLLNVAL) - return -1; - - return 0; -} - - -void uv__fs_event_close(uv_fs_event_t* handle) { - UNREACHABLE(); -} - - -int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) { - return -ENOSYS; -} - - -int uv_fs_event_start(uv_fs_event_t* handle, uv_fs_event_cb cb, - const char* filename, unsigned int flags) { - return -ENOSYS; -} - - -int uv_fs_event_stop(uv_fs_event_t* handle) { - return -ENOSYS; -} - - -void uv__io_poll(uv_loop_t* loop, int timeout) { - static const int max_safe_timeout = 1789569; - struct epoll_event events[1024]; - struct epoll_event* pe; - struct epoll_event e; - int real_timeout; - QUEUE* q; - uv__io_t* w; - uint64_t base; - int count; - int nfds; - int fd; - int op; - int i; - - if (loop->nfds == 0) { - assert(QUEUE_EMPTY(&loop->watcher_queue)); - return; - } - - while (!QUEUE_EMPTY(&loop->watcher_queue)) { - uv_stream_t* stream; - - q = QUEUE_HEAD(&loop->watcher_queue); - QUEUE_REMOVE(q); - QUEUE_INIT(q); - w = QUEUE_DATA(q, uv__io_t, watcher_queue); - - assert(w->pevents != 0); - assert(w->fd >= 0); - - stream= container_of(w, uv_stream_t, io_watcher); - - assert(w->fd < (int) loop->nwatchers); - - e.events = w->pevents; - e.fd = w->fd; - - if (w->events == 0) - op = UV__EPOLL_CTL_ADD; - else - op = UV__EPOLL_CTL_MOD; - - /* XXX Future optimization: do EPOLL_CTL_MOD lazily if we stop watching - * events, skip the syscall and squelch the events after epoll_wait(). - */ - if (epoll_ctl(loop->ep, op, w->fd, &e)) { - if (errno != EEXIST) - abort(); - - assert(op == UV__EPOLL_CTL_ADD); - - /* We've reactivated a file descriptor that's been watched before. */ - if (epoll_ctl(loop->ep, UV__EPOLL_CTL_MOD, w->fd, &e)) - abort(); - } - - w->events = w->pevents; - } - - assert(timeout >= -1); - base = loop->time; - count = 48; /* Benchmarks suggest this gives the best throughput. */ - real_timeout = timeout; - int nevents = 0; - - nfds = 0; - for (;;) { - if (sizeof(int32_t) == sizeof(long) && timeout >= max_safe_timeout) - timeout = max_safe_timeout; - - nfds = epoll_wait(loop->ep, events, - ARRAY_SIZE(events), timeout); - - /* Update loop->time unconditionally. It's tempting to skip the update when - * timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the - * operating system didn't reschedule our process while in the syscall. - */ - base = loop->time; - SAVE_ERRNO(uv__update_time(loop)); - if (nfds == 0) { - assert(timeout != -1); - timeout = real_timeout - timeout; - if (timeout > 0) - continue; - - return; - } - - if (nfds == -1) { - - if (errno != EINTR) - abort(); - - if (timeout == -1) - continue; - - if (timeout == 0) - return; - - /* Interrupted by a signal. Update timeout and poll again. */ - goto update_timeout; - } - - - assert(loop->watchers != NULL); - loop->watchers[loop->nwatchers] = (void*) events; - loop->watchers[loop->nwatchers + 1] = (void*) (uintptr_t) nfds; - for (i = 0; i < nfds; i++) { - pe = events + i; - fd = pe->fd; - - /* Skip invalidated events, see uv__platform_invalidate_fd */ - if (fd == -1) - continue; - - assert(fd >= 0); - assert((unsigned) fd < loop->nwatchers); - - w = loop->watchers[fd]; - - if (w == NULL) { - /* File descriptor that we've stopped watching, disarm it. - * - * Ignore all errors because we may be racing with another thread - * when the file descriptor is closed. - */ - epoll_ctl(loop->ep, UV__EPOLL_CTL_DEL, fd, pe); - continue; - } - - /* Give users only events they're interested in. Prevents spurious - * callbacks when previous callback invocation in this loop has stopped - * the current watcher. Also, filters out events that users has not - * requested us to watch. - */ - pe->events &= w->pevents | POLLERR | POLLHUP; - - if (pe->events == POLLERR || pe->events == POLLHUP) - pe->events |= w->pevents & (POLLIN | POLLOUT); - - if (pe->events != 0) { - w->cb(loop, w, pe->events); - nevents++; - } - } - loop->watchers[loop->nwatchers] = NULL; - loop->watchers[loop->nwatchers + 1] = NULL; - - if (nevents != 0) { - if (nfds == ARRAY_SIZE(events) && --count != 0) { - /* Poll for more events but don't block this time. */ - timeout = 0; - continue; - } - return; - } - - if (timeout == 0) - return; - - if (timeout == -1) - continue; - -update_timeout: - assert(timeout > 0); - - real_timeout -= (loop->time - base); - if (real_timeout <= 0) - return; - - timeout = real_timeout; - } -} - -void uv__set_process_title(const char* title) { - /* do nothing */ -} diff --git a/vendor/libuv/src/unix/pipe.c b/vendor/libuv/src/unix/pipe.c deleted file mode 100644 index b73994cb8..000000000 --- a/vendor/libuv/src/unix/pipe.c +++ /dev/null @@ -1,298 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "internal.h" - -#include -#include -#include -#include -#include -#include - - -int uv_pipe_init(uv_loop_t* loop, uv_pipe_t* handle, int ipc) { - uv__stream_init(loop, (uv_stream_t*)handle, UV_NAMED_PIPE); - handle->shutdown_req = NULL; - handle->connect_req = NULL; - handle->pipe_fname = NULL; - handle->ipc = ipc; - return 0; -} - - -int uv_pipe_bind(uv_pipe_t* handle, const char* name) { - struct sockaddr_un saddr; - const char* pipe_fname; - int sockfd; - int err; - - pipe_fname = NULL; - sockfd = -1; - - /* Already bound? */ - if (uv__stream_fd(handle) >= 0) - return -EINVAL; - - /* Make a copy of the file name, it outlives this function's scope. */ - pipe_fname = uv__strdup(name); - if (pipe_fname == NULL) - return -ENOMEM; - - /* We've got a copy, don't touch the original any more. */ - name = NULL; - - err = uv__socket(AF_UNIX, SOCK_STREAM, 0); - if (err < 0) - goto err_socket; - sockfd = err; - - memset(&saddr, 0, sizeof saddr); - strncpy(saddr.sun_path, pipe_fname, sizeof(saddr.sun_path) - 1); - saddr.sun_path[sizeof(saddr.sun_path) - 1] = '\0'; - saddr.sun_family = AF_UNIX; - - if (bind(sockfd, (struct sockaddr*)&saddr, sizeof saddr)) { - err = -errno; - /* Convert ENOENT to EACCES for compatibility with Windows. */ - if (err == -ENOENT) - err = -EACCES; - goto err_bind; - } - - /* Success. */ - handle->flags |= UV_HANDLE_BOUND; - handle->pipe_fname = pipe_fname; /* Is a strdup'ed copy. */ - handle->io_watcher.fd = sockfd; - return 0; - -err_bind: - uv__close(sockfd); - -err_socket: - uv__free((void*)pipe_fname); - return err; -} - - -int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) { - if (uv__stream_fd(handle) == -1) - return -EINVAL; - -#if defined(__MVS__) - /* On zOS, backlog=0 has undefined behaviour */ - if (backlog == 0) - backlog = 1; - else if (backlog < 0) - backlog = SOMAXCONN; -#endif - - if (listen(uv__stream_fd(handle), backlog)) - return -errno; - - handle->connection_cb = cb; - handle->io_watcher.cb = uv__server_io; - uv__io_start(handle->loop, &handle->io_watcher, POLLIN); - return 0; -} - - -void uv__pipe_close(uv_pipe_t* handle) { - if (handle->pipe_fname) { - /* - * Unlink the file system entity before closing the file descriptor. - * Doing it the other way around introduces a race where our process - * unlinks a socket with the same name that's just been created by - * another thread or process. - */ - unlink(handle->pipe_fname); - uv__free((void*)handle->pipe_fname); - handle->pipe_fname = NULL; - } - - uv__stream_close((uv_stream_t*)handle); -} - - -int uv_pipe_open(uv_pipe_t* handle, uv_file fd) { - int err; - - err = uv__nonblock(fd, 1); - if (err) - return err; - -#if defined(__APPLE__) - err = uv__stream_try_select((uv_stream_t*) handle, &fd); - if (err) - return err; -#endif /* defined(__APPLE__) */ - - return uv__stream_open((uv_stream_t*)handle, - fd, - UV_STREAM_READABLE | UV_STREAM_WRITABLE); -} - - -void uv_pipe_connect(uv_connect_t* req, - uv_pipe_t* handle, - const char* name, - uv_connect_cb cb) { - struct sockaddr_un saddr; - int new_sock; - int err; - int r; - - new_sock = (uv__stream_fd(handle) == -1); - - if (new_sock) { - err = uv__socket(AF_UNIX, SOCK_STREAM, 0); - if (err < 0) - goto out; - handle->io_watcher.fd = err; - } - - memset(&saddr, 0, sizeof saddr); - strncpy(saddr.sun_path, name, sizeof(saddr.sun_path) - 1); - saddr.sun_path[sizeof(saddr.sun_path) - 1] = '\0'; - saddr.sun_family = AF_UNIX; - - do { - r = connect(uv__stream_fd(handle), - (struct sockaddr*)&saddr, sizeof saddr); - } - while (r == -1 && errno == EINTR); - - if (r == -1 && errno != EINPROGRESS) { - err = -errno; - goto out; - } - - err = 0; - if (new_sock) { - err = uv__stream_open((uv_stream_t*)handle, - uv__stream_fd(handle), - UV_STREAM_READABLE | UV_STREAM_WRITABLE); - } - - if (err == 0) - uv__io_start(handle->loop, &handle->io_watcher, POLLIN | POLLOUT); - -out: - handle->delayed_error = err; - handle->connect_req = req; - - uv__req_init(handle->loop, req, UV_CONNECT); - req->handle = (uv_stream_t*)handle; - req->cb = cb; - QUEUE_INIT(&req->queue); - - /* Force callback to run on next tick in case of error. */ - if (err) - uv__io_feed(handle->loop, &handle->io_watcher); - -} - - -typedef int (*uv__peersockfunc)(int, struct sockaddr*, socklen_t*); - - -static int uv__pipe_getsockpeername(const uv_pipe_t* handle, - uv__peersockfunc func, - char* buffer, - size_t* size) { - struct sockaddr_un sa; - socklen_t addrlen; - int err; - - addrlen = sizeof(sa); - memset(&sa, 0, addrlen); - err = func(uv__stream_fd(handle), (struct sockaddr*) &sa, &addrlen); - if (err < 0) { - *size = 0; - return -errno; - } - -#if defined(__linux__) - if (sa.sun_path[0] == 0) - /* Linux abstract namespace */ - addrlen -= offsetof(struct sockaddr_un, sun_path); - else -#endif - addrlen = strlen(sa.sun_path); - - - if (addrlen >= *size) { - *size = addrlen + 1; - return UV_ENOBUFS; - } - - memcpy(buffer, sa.sun_path, addrlen); - *size = addrlen; - - /* only null-terminate if it's not an abstract socket */ - if (buffer[0] != '\0') - buffer[addrlen] = '\0'; - - return 0; -} - - -int uv_pipe_getsockname(const uv_pipe_t* handle, char* buffer, size_t* size) { - return uv__pipe_getsockpeername(handle, getsockname, buffer, size); -} - - -int uv_pipe_getpeername(const uv_pipe_t* handle, char* buffer, size_t* size) { - return uv__pipe_getsockpeername(handle, getpeername, buffer, size); -} - - -void uv_pipe_pending_instances(uv_pipe_t* handle, int count) { -} - - -int uv_pipe_pending_count(uv_pipe_t* handle) { - uv__stream_queued_fds_t* queued_fds; - - if (!handle->ipc) - return 0; - - if (handle->accepted_fd == -1) - return 0; - - if (handle->queued_fds == NULL) - return 1; - - queued_fds = handle->queued_fds; - return queued_fds->offset + 1; -} - - -uv_handle_type uv_pipe_pending_type(uv_pipe_t* handle) { - if (!handle->ipc) - return UV_UNKNOWN_HANDLE; - - if (handle->accepted_fd == -1) - return UV_UNKNOWN_HANDLE; - else - return uv__handle_type(handle->accepted_fd); -} diff --git a/vendor/libuv/src/unix/poll.c b/vendor/libuv/src/unix/poll.c deleted file mode 100644 index 370994bd5..000000000 --- a/vendor/libuv/src/unix/poll.c +++ /dev/null @@ -1,130 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "internal.h" - -#include -#include -#include - - -static void uv__poll_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) { - uv_poll_t* handle; - int pevents; - - handle = container_of(w, uv_poll_t, io_watcher); - - if (events & POLLERR) { - uv__io_stop(loop, w, POLLIN | POLLOUT | UV__POLLRDHUP); - uv__handle_stop(handle); - handle->poll_cb(handle, -EBADF, 0); - return; - } - - pevents = 0; - if (events & POLLIN) - pevents |= UV_READABLE; - if (events & POLLOUT) - pevents |= UV_WRITABLE; - if (events & UV__POLLRDHUP) - pevents |= UV_DISCONNECT; - - handle->poll_cb(handle, 0, pevents); -} - - -int uv_poll_init(uv_loop_t* loop, uv_poll_t* handle, int fd) { - int err; - - err = uv__io_check_fd(loop, fd); - if (err) - return err; - - /* If ioctl(FIONBIO) reports ENOTTY, try fcntl(F_GETFL) + fcntl(F_SETFL). - * Workaround for e.g. kqueue fds not supporting ioctls. - */ - err = uv__nonblock(fd, 1); - if (err == -ENOTTY) - if (uv__nonblock == uv__nonblock_ioctl) - err = uv__nonblock_fcntl(fd, 1); - - if (err) - return err; - - uv__handle_init(loop, (uv_handle_t*) handle, UV_POLL); - uv__io_init(&handle->io_watcher, uv__poll_io, fd); - handle->poll_cb = NULL; - return 0; -} - - -int uv_poll_init_socket(uv_loop_t* loop, uv_poll_t* handle, - uv_os_sock_t socket) { - return uv_poll_init(loop, handle, socket); -} - - -static void uv__poll_stop(uv_poll_t* handle) { - uv__io_stop(handle->loop, - &handle->io_watcher, - POLLIN | POLLOUT | UV__POLLRDHUP); - uv__handle_stop(handle); -} - - -int uv_poll_stop(uv_poll_t* handle) { - assert(!uv__is_closing(handle)); - uv__poll_stop(handle); - return 0; -} - - -int uv_poll_start(uv_poll_t* handle, int pevents, uv_poll_cb poll_cb) { - int events; - - assert((pevents & ~(UV_READABLE | UV_WRITABLE | UV_DISCONNECT)) == 0); - assert(!uv__is_closing(handle)); - - uv__poll_stop(handle); - - if (pevents == 0) - return 0; - - events = 0; - if (pevents & UV_READABLE) - events |= POLLIN; - if (pevents & UV_WRITABLE) - events |= POLLOUT; - if (pevents & UV_DISCONNECT) - events |= UV__POLLRDHUP; - - uv__io_start(handle->loop, &handle->io_watcher, events); - uv__handle_start(handle); - handle->poll_cb = poll_cb; - - return 0; -} - - -void uv__poll_close(uv_poll_t* handle) { - uv__poll_stop(handle); -} diff --git a/vendor/libuv/src/unix/process.c b/vendor/libuv/src/unix/process.c deleted file mode 100644 index f2fe30521..000000000 --- a/vendor/libuv/src/unix/process.c +++ /dev/null @@ -1,563 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "internal.h" - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#if defined(__APPLE__) && !TARGET_OS_IPHONE -# include -# define environ (*_NSGetEnviron()) -#else -extern char **environ; -#endif - -#if defined(__linux__) || defined(__GLIBC__) -# include -#endif - - -static void uv__chld(uv_signal_t* handle, int signum) { - uv_process_t* process; - uv_loop_t* loop; - int exit_status; - int term_signal; - int status; - pid_t pid; - QUEUE pending; - QUEUE* q; - QUEUE* h; - - assert(signum == SIGCHLD); - - QUEUE_INIT(&pending); - loop = handle->loop; - - h = &loop->process_handles; - q = QUEUE_HEAD(h); - while (q != h) { - process = QUEUE_DATA(q, uv_process_t, queue); - q = QUEUE_NEXT(q); - - do - pid = waitpid(process->pid, &status, WNOHANG); - while (pid == -1 && errno == EINTR); - - if (pid == 0) - continue; - - if (pid == -1) { - if (errno != ECHILD) - abort(); - continue; - } - - process->status = status; - QUEUE_REMOVE(&process->queue); - QUEUE_INSERT_TAIL(&pending, &process->queue); - } - - h = &pending; - q = QUEUE_HEAD(h); - while (q != h) { - process = QUEUE_DATA(q, uv_process_t, queue); - q = QUEUE_NEXT(q); - - QUEUE_REMOVE(&process->queue); - QUEUE_INIT(&process->queue); - uv__handle_stop(process); - - if (process->exit_cb == NULL) - continue; - - exit_status = 0; - if (WIFEXITED(process->status)) - exit_status = WEXITSTATUS(process->status); - - term_signal = 0; - if (WIFSIGNALED(process->status)) - term_signal = WTERMSIG(process->status); - - process->exit_cb(process, exit_status, term_signal); - } - assert(QUEUE_EMPTY(&pending)); -} - - -int uv__make_socketpair(int fds[2], int flags) { -#if defined(__linux__) - static int no_cloexec; - - if (no_cloexec) - goto skip; - - if (socketpair(AF_UNIX, SOCK_STREAM | UV__SOCK_CLOEXEC | flags, 0, fds) == 0) - return 0; - - /* Retry on EINVAL, it means SOCK_CLOEXEC is not supported. - * Anything else is a genuine error. - */ - if (errno != EINVAL) - return -errno; - - no_cloexec = 1; - -skip: -#endif - - if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds)) - return -errno; - - uv__cloexec(fds[0], 1); - uv__cloexec(fds[1], 1); - - if (flags & UV__F_NONBLOCK) { - uv__nonblock(fds[0], 1); - uv__nonblock(fds[1], 1); - } - - return 0; -} - - -int uv__make_pipe(int fds[2], int flags) { -#if defined(__linux__) - static int no_pipe2; - - if (no_pipe2) - goto skip; - - if (uv__pipe2(fds, flags | UV__O_CLOEXEC) == 0) - return 0; - - if (errno != ENOSYS) - return -errno; - - no_pipe2 = 1; - -skip: -#endif - - if (pipe(fds)) - return -errno; - - uv__cloexec(fds[0], 1); - uv__cloexec(fds[1], 1); - - if (flags & UV__F_NONBLOCK) { - uv__nonblock(fds[0], 1); - uv__nonblock(fds[1], 1); - } - - return 0; -} - - -/* - * Used for initializing stdio streams like options.stdin_stream. Returns - * zero on success. See also the cleanup section in uv_spawn(). - */ -static int uv__process_init_stdio(uv_stdio_container_t* container, int fds[2]) { - int mask; - int fd; - - mask = UV_IGNORE | UV_CREATE_PIPE | UV_INHERIT_FD | UV_INHERIT_STREAM; - - switch (container->flags & mask) { - case UV_IGNORE: - return 0; - - case UV_CREATE_PIPE: - assert(container->data.stream != NULL); - if (container->data.stream->type != UV_NAMED_PIPE) - return -EINVAL; - else - return uv__make_socketpair(fds, 0); - - case UV_INHERIT_FD: - case UV_INHERIT_STREAM: - if (container->flags & UV_INHERIT_FD) - fd = container->data.fd; - else - fd = uv__stream_fd(container->data.stream); - - if (fd == -1) - return -EINVAL; - - fds[1] = fd; - return 0; - - default: - assert(0 && "Unexpected flags"); - return -EINVAL; - } -} - - -static int uv__process_open_stream(uv_stdio_container_t* container, - int pipefds[2], - int writable) { - int flags; - int err; - - if (!(container->flags & UV_CREATE_PIPE) || pipefds[0] < 0) - return 0; - - err = uv__close(pipefds[1]); - if (err != 0) - abort(); - - pipefds[1] = -1; - uv__nonblock(pipefds[0], 1); - - if (container->data.stream->type == UV_NAMED_PIPE && - ((uv_pipe_t*)container->data.stream)->ipc) - flags = UV_STREAM_READABLE | UV_STREAM_WRITABLE; - else if (writable) - flags = UV_STREAM_WRITABLE; - else - flags = UV_STREAM_READABLE; - - return uv__stream_open(container->data.stream, pipefds[0], flags); -} - - -static void uv__process_close_stream(uv_stdio_container_t* container) { - if (!(container->flags & UV_CREATE_PIPE)) return; - uv__stream_close((uv_stream_t*)container->data.stream); -} - - -static void uv__write_int(int fd, int val) { - ssize_t n; - - do - n = write(fd, &val, sizeof(val)); - while (n == -1 && errno == EINTR); - - if (n == -1 && errno == EPIPE) - return; /* parent process has quit */ - - assert(n == sizeof(val)); -} - - -#if !(defined(__APPLE__) && (TARGET_OS_TV || TARGET_OS_WATCH)) -/* execvp is marked __WATCHOS_PROHIBITED __TVOS_PROHIBITED, so must be - * avoided. Since this isn't called on those targets, the function - * doesn't even need to be defined for them. - */ -static void uv__process_child_init(const uv_process_options_t* options, - int stdio_count, - int (*pipes)[2], - int error_fd) { - int close_fd; - int use_fd; - int fd; - - if (options->flags & UV_PROCESS_DETACHED) - setsid(); - - /* First duplicate low numbered fds, since it's not safe to duplicate them, - * they could get replaced. Example: swapping stdout and stderr; without - * this fd 2 (stderr) would be duplicated into fd 1, thus making both - * stdout and stderr go to the same fd, which was not the intention. */ - for (fd = 0; fd < stdio_count; fd++) { - use_fd = pipes[fd][1]; - if (use_fd < 0 || use_fd >= fd) - continue; - pipes[fd][1] = fcntl(use_fd, F_DUPFD, stdio_count); - if (pipes[fd][1] == -1) { - uv__write_int(error_fd, -errno); - _exit(127); - } - } - - for (fd = 0; fd < stdio_count; fd++) { - close_fd = pipes[fd][0]; - use_fd = pipes[fd][1]; - - if (use_fd < 0) { - if (fd >= 3) - continue; - else { - /* redirect stdin, stdout and stderr to /dev/null even if UV_IGNORE is - * set - */ - use_fd = open("/dev/null", fd == 0 ? O_RDONLY : O_RDWR); - close_fd = use_fd; - - if (use_fd == -1) { - uv__write_int(error_fd, -errno); - _exit(127); - } - } - } - - if (fd == use_fd) - uv__cloexec_fcntl(use_fd, 0); - else - fd = dup2(use_fd, fd); - - if (fd == -1) { - uv__write_int(error_fd, -errno); - _exit(127); - } - - if (fd <= 2) - uv__nonblock_fcntl(fd, 0); - - if (close_fd >= stdio_count) - uv__close(close_fd); - } - - for (fd = 0; fd < stdio_count; fd++) { - use_fd = pipes[fd][1]; - - if (use_fd >= stdio_count) - uv__close(use_fd); - } - - if (options->cwd != NULL && chdir(options->cwd)) { - uv__write_int(error_fd, -errno); - _exit(127); - } - - if (options->flags & (UV_PROCESS_SETUID | UV_PROCESS_SETGID)) { - /* When dropping privileges from root, the `setgroups` call will - * remove any extraneous groups. If we don't call this, then - * even though our uid has dropped, we may still have groups - * that enable us to do super-user things. This will fail if we - * aren't root, so don't bother checking the return value, this - * is just done as an optimistic privilege dropping function. - */ - SAVE_ERRNO(setgroups(0, NULL)); - } - - if ((options->flags & UV_PROCESS_SETGID) && setgid(options->gid)) { - uv__write_int(error_fd, -errno); - _exit(127); - } - - if ((options->flags & UV_PROCESS_SETUID) && setuid(options->uid)) { - uv__write_int(error_fd, -errno); - _exit(127); - } - - if (options->env != NULL) { - environ = options->env; - } - - execvp(options->file, options->args); - uv__write_int(error_fd, -errno); - _exit(127); -} -#endif - - -int uv_spawn(uv_loop_t* loop, - uv_process_t* process, - const uv_process_options_t* options) { -#if defined(__APPLE__) && (TARGET_OS_TV || TARGET_OS_WATCH) - /* fork is marked __WATCHOS_PROHIBITED __TVOS_PROHIBITED. */ - return -ENOSYS; -#else - int signal_pipe[2] = { -1, -1 }; - int (*pipes)[2]; - int stdio_count; - ssize_t r; - pid_t pid; - int err; - int exec_errorno; - int i; - int status; - - assert(options->file != NULL); - assert(!(options->flags & ~(UV_PROCESS_DETACHED | - UV_PROCESS_SETGID | - UV_PROCESS_SETUID | - UV_PROCESS_WINDOWS_HIDE | - UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS))); - - uv__handle_init(loop, (uv_handle_t*)process, UV_PROCESS); - QUEUE_INIT(&process->queue); - - stdio_count = options->stdio_count; - if (stdio_count < 3) - stdio_count = 3; - - err = -ENOMEM; - pipes = uv__malloc(stdio_count * sizeof(*pipes)); - if (pipes == NULL) - goto error; - - for (i = 0; i < stdio_count; i++) { - pipes[i][0] = -1; - pipes[i][1] = -1; - } - - for (i = 0; i < options->stdio_count; i++) { - err = uv__process_init_stdio(options->stdio + i, pipes[i]); - if (err) - goto error; - } - - /* This pipe is used by the parent to wait until - * the child has called `execve()`. We need this - * to avoid the following race condition: - * - * if ((pid = fork()) > 0) { - * kill(pid, SIGTERM); - * } - * else if (pid == 0) { - * execve("/bin/cat", argp, envp); - * } - * - * The parent sends a signal immediately after forking. - * Since the child may not have called `execve()` yet, - * there is no telling what process receives the signal, - * our fork or /bin/cat. - * - * To avoid ambiguity, we create a pipe with both ends - * marked close-on-exec. Then, after the call to `fork()`, - * the parent polls the read end until it EOFs or errors with EPIPE. - */ - err = uv__make_pipe(signal_pipe, 0); - if (err) - goto error; - - uv_signal_start(&loop->child_watcher, uv__chld, SIGCHLD); - - /* Acquire write lock to prevent opening new fds in worker threads */ - uv_rwlock_wrlock(&loop->cloexec_lock); - pid = fork(); - - if (pid == -1) { - err = -errno; - uv_rwlock_wrunlock(&loop->cloexec_lock); - uv__close(signal_pipe[0]); - uv__close(signal_pipe[1]); - goto error; - } - - if (pid == 0) { - uv__process_child_init(options, stdio_count, pipes, signal_pipe[1]); - abort(); - } - - /* Release lock in parent process */ - uv_rwlock_wrunlock(&loop->cloexec_lock); - uv__close(signal_pipe[1]); - - process->status = 0; - exec_errorno = 0; - do - r = read(signal_pipe[0], &exec_errorno, sizeof(exec_errorno)); - while (r == -1 && errno == EINTR); - - if (r == 0) - ; /* okay, EOF */ - else if (r == sizeof(exec_errorno)) { - do - err = waitpid(pid, &status, 0); /* okay, read errorno */ - while (err == -1 && errno == EINTR); - assert(err == pid); - } else if (r == -1 && errno == EPIPE) { - do - err = waitpid(pid, &status, 0); /* okay, got EPIPE */ - while (err == -1 && errno == EINTR); - assert(err == pid); - } else - abort(); - - uv__close_nocheckstdio(signal_pipe[0]); - - for (i = 0; i < options->stdio_count; i++) { - err = uv__process_open_stream(options->stdio + i, pipes[i], i == 0); - if (err == 0) - continue; - - while (i--) - uv__process_close_stream(options->stdio + i); - - goto error; - } - - /* Only activate this handle if exec() happened successfully */ - if (exec_errorno == 0) { - QUEUE_INSERT_TAIL(&loop->process_handles, &process->queue); - uv__handle_start(process); - } - - process->pid = pid; - process->exit_cb = options->exit_cb; - - uv__free(pipes); - return exec_errorno; - -error: - if (pipes != NULL) { - for (i = 0; i < stdio_count; i++) { - if (i < options->stdio_count) - if (options->stdio[i].flags & (UV_INHERIT_FD | UV_INHERIT_STREAM)) - continue; - if (pipes[i][0] != -1) - uv__close_nocheckstdio(pipes[i][0]); - if (pipes[i][1] != -1) - uv__close_nocheckstdio(pipes[i][1]); - } - uv__free(pipes); - } - - return err; -#endif -} - - -int uv_process_kill(uv_process_t* process, int signum) { - return uv_kill(process->pid, signum); -} - - -int uv_kill(int pid, int signum) { - if (kill(pid, signum)) - return -errno; - else - return 0; -} - - -void uv__process_close(uv_process_t* handle) { - QUEUE_REMOVE(&handle->queue); - uv__handle_stop(handle); - if (QUEUE_EMPTY(&handle->loop->process_handles)) - uv_signal_stop(&handle->loop->child_watcher); -} diff --git a/vendor/libuv/src/unix/proctitle.c b/vendor/libuv/src/unix/proctitle.c deleted file mode 100644 index 9160f7eaf..000000000 --- a/vendor/libuv/src/unix/proctitle.c +++ /dev/null @@ -1,111 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "internal.h" - -#include -#include - -extern void uv__set_process_title(const char* title); - -static void* args_mem; - -static struct { - char* str; - size_t len; -} process_title; - - -char** uv_setup_args(int argc, char** argv) { - char** new_argv; - size_t size; - char* s; - int i; - - if (argc <= 0) - return argv; - - /* Calculate how much memory we need for the argv strings. */ - size = 0; - for (i = 0; i < argc; i++) - size += strlen(argv[i]) + 1; - -#if defined(__MVS__) - /* argv is not adjacent. So just use argv[0] */ - process_title.str = argv[0]; - process_title.len = strlen(argv[0]); -#else - process_title.str = argv[0]; - process_title.len = argv[argc - 1] + strlen(argv[argc - 1]) - argv[0]; - assert(process_title.len + 1 == size); /* argv memory should be adjacent. */ -#endif - - /* Add space for the argv pointers. */ - size += (argc + 1) * sizeof(char*); - - new_argv = uv__malloc(size); - if (new_argv == NULL) - return argv; - args_mem = new_argv; - - /* Copy over the strings and set up the pointer table. */ - s = (char*) &new_argv[argc + 1]; - for (i = 0; i < argc; i++) { - size = strlen(argv[i]) + 1; - memcpy(s, argv[i], size); - new_argv[i] = s; - s += size; - } - new_argv[i] = NULL; - - return new_argv; -} - - -int uv_set_process_title(const char* title) { - if (process_title.len == 0) - return 0; - - /* No need to terminate, byte after is always '\0'. */ - strncpy(process_title.str, title, process_title.len); - uv__set_process_title(title); - - return 0; -} - - -int uv_get_process_title(char* buffer, size_t size) { - if (buffer == NULL || size == 0) - return -EINVAL; - else if (size <= process_title.len) - return -ENOBUFS; - - memcpy(buffer, process_title.str, process_title.len + 1); - buffer[process_title.len] = '\0'; - - return 0; -} - - -UV_DESTRUCTOR(static void free_args_mem(void)) { - uv__free(args_mem); /* Keep valgrind happy. */ - args_mem = NULL; -} diff --git a/vendor/libuv/src/unix/pthread-barrier.c b/vendor/libuv/src/unix/pthread-barrier.c deleted file mode 100644 index b6e604d46..000000000 --- a/vendor/libuv/src/unix/pthread-barrier.c +++ /dev/null @@ -1,121 +0,0 @@ -/* -Copyright (c) 2016, Kari Tristan Helgason - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ -#include "uv-common.h" -#include "pthread-barrier.h" - -#include -#include - -/* TODO: support barrier_attr */ -int pthread_barrier_init(pthread_barrier_t* barrier, - const void* barrier_attr, - unsigned count) { - int rc; - _uv_barrier* b; - - if (barrier == NULL || count == 0) - return EINVAL; - - if (barrier_attr != NULL) - return ENOTSUP; - - b = uv__malloc(sizeof(*b)); - if (b == NULL) - return ENOMEM; - - b->in = 0; - b->out = 0; - b->threshold = count; - - if ((rc = pthread_mutex_init(&b->mutex, NULL)) != 0) - goto error2; - if ((rc = pthread_cond_init(&b->cond, NULL)) != 0) - goto error; - - barrier->b = b; - return 0; - -error: - pthread_mutex_destroy(&b->mutex); -error2: - uv__free(b); - return rc; -} - -int pthread_barrier_wait(pthread_barrier_t* barrier) { - int rc; - _uv_barrier* b; - - if (barrier == NULL || barrier->b == NULL) - return EINVAL; - - b = barrier->b; - /* Lock the mutex*/ - if ((rc = pthread_mutex_lock(&b->mutex)) != 0) - return rc; - - /* Increment the count. If this is the first thread to reach the threshold, - wake up waiters, unlock the mutex, then return - PTHREAD_BARRIER_SERIAL_THREAD. */ - if (++b->in == b->threshold) { - b->in = 0; - b->out = b->threshold - 1; - rc = pthread_cond_signal(&b->cond); - assert(rc == 0); - - pthread_mutex_unlock(&b->mutex); - return PTHREAD_BARRIER_SERIAL_THREAD; - } - /* Otherwise, wait for other threads until in is set to 0, - then return 0 to indicate this is not the first thread. */ - do { - if ((rc = pthread_cond_wait(&b->cond, &b->mutex)) != 0) - break; - } while (b->in != 0); - - /* mark thread exit */ - b->out--; - pthread_cond_signal(&b->cond); - pthread_mutex_unlock(&b->mutex); - return rc; -} - -int pthread_barrier_destroy(pthread_barrier_t* barrier) { - int rc; - _uv_barrier* b; - - if (barrier == NULL || barrier->b == NULL) - return EINVAL; - - b = barrier->b; - - if ((rc = pthread_mutex_lock(&b->mutex)) != 0) - return rc; - - if (b->in > 0 || b->out > 0) - rc = EBUSY; - - pthread_mutex_unlock(&b->mutex); - - if (rc) - return rc; - - pthread_cond_destroy(&b->cond); - pthread_mutex_destroy(&b->mutex); - uv__free(barrier->b); - barrier->b = NULL; - return 0; -} diff --git a/vendor/libuv/src/unix/pthread-fixes.c b/vendor/libuv/src/unix/pthread-fixes.c deleted file mode 100644 index fb1799584..000000000 --- a/vendor/libuv/src/unix/pthread-fixes.c +++ /dev/null @@ -1,56 +0,0 @@ -/* Copyright (c) 2013, Sony Mobile Communications AB - * Copyright (c) 2012, Google Inc. - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -/* Android versions < 4.1 have a broken pthread_sigmask. */ -#include -#include -#include - -int uv__pthread_sigmask(int how, const sigset_t* set, sigset_t* oset) { - static int workaround; - int err; - - if (workaround) { - return sigprocmask(how, set, oset); - } else { - err = pthread_sigmask(how, set, oset); - if (err) { - if (err == EINVAL && sigprocmask(how, set, oset) == 0) { - workaround = 1; - return 0; - } else { - return -1; - } - } - } - - return 0; -} diff --git a/vendor/libuv/src/unix/signal.c b/vendor/libuv/src/unix/signal.c deleted file mode 100644 index dbd8f8644..000000000 --- a/vendor/libuv/src/unix/signal.c +++ /dev/null @@ -1,467 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "internal.h" - -#include -#include -#include -#include -#include -#include - - -typedef struct { - uv_signal_t* handle; - int signum; -} uv__signal_msg_t; - -RB_HEAD(uv__signal_tree_s, uv_signal_s); - - -static int uv__signal_unlock(void); -static void uv__signal_event(uv_loop_t* loop, uv__io_t* w, unsigned int events); -static int uv__signal_compare(uv_signal_t* w1, uv_signal_t* w2); -static void uv__signal_stop(uv_signal_t* handle); - - -static uv_once_t uv__signal_global_init_guard = UV_ONCE_INIT; -static struct uv__signal_tree_s uv__signal_tree = - RB_INITIALIZER(uv__signal_tree); -static int uv__signal_lock_pipefd[2]; - - -RB_GENERATE_STATIC(uv__signal_tree_s, - uv_signal_s, tree_entry, - uv__signal_compare) - - -static void uv__signal_global_init(void) { - if (uv__make_pipe(uv__signal_lock_pipefd, 0)) - abort(); - - if (uv__signal_unlock()) - abort(); -} - - -void uv__signal_global_once_init(void) { - uv_once(&uv__signal_global_init_guard, uv__signal_global_init); -} - - - -static int uv__signal_lock(void) { - int r; - char data; - - do { - r = read(uv__signal_lock_pipefd[0], &data, sizeof data); - } while (r < 0 && errno == EINTR); - - return (r < 0) ? -1 : 0; -} - - -static int uv__signal_unlock(void) { - int r; - char data = 42; - - do { - r = write(uv__signal_lock_pipefd[1], &data, sizeof data); - } while (r < 0 && errno == EINTR); - - return (r < 0) ? -1 : 0; -} - - -static void uv__signal_block_and_lock(sigset_t* saved_sigmask) { - sigset_t new_mask; - - if (sigfillset(&new_mask)) - abort(); - - if (pthread_sigmask(SIG_SETMASK, &new_mask, saved_sigmask)) - abort(); - - if (uv__signal_lock()) - abort(); -} - - -static void uv__signal_unlock_and_unblock(sigset_t* saved_sigmask) { - if (uv__signal_unlock()) - abort(); - - if (pthread_sigmask(SIG_SETMASK, saved_sigmask, NULL)) - abort(); -} - - -static uv_signal_t* uv__signal_first_handle(int signum) { - /* This function must be called with the signal lock held. */ - uv_signal_t lookup; - uv_signal_t* handle; - - lookup.signum = signum; - lookup.loop = NULL; - - handle = RB_NFIND(uv__signal_tree_s, &uv__signal_tree, &lookup); - - if (handle != NULL && handle->signum == signum) - return handle; - - return NULL; -} - - -static void uv__signal_handler(int signum) { - uv__signal_msg_t msg; - uv_signal_t* handle; - int saved_errno; - - saved_errno = errno; - memset(&msg, 0, sizeof msg); - - if (uv__signal_lock()) { - errno = saved_errno; - return; - } - - for (handle = uv__signal_first_handle(signum); - handle != NULL && handle->signum == signum; - handle = RB_NEXT(uv__signal_tree_s, &uv__signal_tree, handle)) { - int r; - - msg.signum = signum; - msg.handle = handle; - - /* write() should be atomic for small data chunks, so the entire message - * should be written at once. In theory the pipe could become full, in - * which case the user is out of luck. - */ - do { - r = write(handle->loop->signal_pipefd[1], &msg, sizeof msg); - } while (r == -1 && errno == EINTR); - - assert(r == sizeof msg || - (r == -1 && (errno == EAGAIN || errno == EWOULDBLOCK))); - - if (r != -1) - handle->caught_signals++; - } - - uv__signal_unlock(); - errno = saved_errno; -} - - -static int uv__signal_register_handler(int signum) { - /* When this function is called, the signal lock must be held. */ - struct sigaction sa; - - /* XXX use a separate signal stack? */ - memset(&sa, 0, sizeof(sa)); - if (sigfillset(&sa.sa_mask)) - abort(); - sa.sa_handler = uv__signal_handler; - - /* XXX save old action so we can restore it later on? */ - if (sigaction(signum, &sa, NULL)) - return -errno; - - return 0; -} - - -static void uv__signal_unregister_handler(int signum) { - /* When this function is called, the signal lock must be held. */ - struct sigaction sa; - - memset(&sa, 0, sizeof(sa)); - sa.sa_handler = SIG_DFL; - - /* sigaction can only fail with EINVAL or EFAULT; an attempt to deregister a - * signal implies that it was successfully registered earlier, so EINVAL - * should never happen. - */ - if (sigaction(signum, &sa, NULL)) - abort(); -} - - -static int uv__signal_loop_once_init(uv_loop_t* loop) { - int err; - - /* Return if already initialized. */ - if (loop->signal_pipefd[0] != -1) - return 0; - - err = uv__make_pipe(loop->signal_pipefd, UV__F_NONBLOCK); - if (err) - return err; - - uv__io_init(&loop->signal_io_watcher, - uv__signal_event, - loop->signal_pipefd[0]); - uv__io_start(loop, &loop->signal_io_watcher, POLLIN); - - return 0; -} - - -void uv__signal_loop_cleanup(uv_loop_t* loop) { - QUEUE* q; - - /* Stop all the signal watchers that are still attached to this loop. This - * ensures that the (shared) signal tree doesn't contain any invalid entries - * entries, and that signal handlers are removed when appropriate. - * It's safe to use QUEUE_FOREACH here because the handles and the handle - * queue are not modified by uv__signal_stop(). - */ - QUEUE_FOREACH(q, &loop->handle_queue) { - uv_handle_t* handle = QUEUE_DATA(q, uv_handle_t, handle_queue); - - if (handle->type == UV_SIGNAL) - uv__signal_stop((uv_signal_t*) handle); - } - - if (loop->signal_pipefd[0] != -1) { - uv__close(loop->signal_pipefd[0]); - loop->signal_pipefd[0] = -1; - } - - if (loop->signal_pipefd[1] != -1) { - uv__close(loop->signal_pipefd[1]); - loop->signal_pipefd[1] = -1; - } -} - - -int uv_signal_init(uv_loop_t* loop, uv_signal_t* handle) { - int err; - - err = uv__signal_loop_once_init(loop); - if (err) - return err; - - uv__handle_init(loop, (uv_handle_t*) handle, UV_SIGNAL); - handle->signum = 0; - handle->caught_signals = 0; - handle->dispatched_signals = 0; - - return 0; -} - - -void uv__signal_close(uv_signal_t* handle) { - - uv__signal_stop(handle); - - /* If there are any caught signals "trapped" in the signal pipe, we can't - * call the close callback yet. Otherwise, add the handle to the finish_close - * queue. - */ - if (handle->caught_signals == handle->dispatched_signals) { - uv__make_close_pending((uv_handle_t*) handle); - } -} - - -int uv_signal_start(uv_signal_t* handle, uv_signal_cb signal_cb, int signum) { - sigset_t saved_sigmask; - int err; - - assert(!uv__is_closing(handle)); - - /* If the user supplies signum == 0, then return an error already. If the - * signum is otherwise invalid then uv__signal_register will find out - * eventually. - */ - if (signum == 0) - return -EINVAL; - - /* Short circuit: if the signal watcher is already watching {signum} don't - * go through the process of deregistering and registering the handler. - * Additionally, this avoids pending signals getting lost in the small time - * time frame that handle->signum == 0. - */ - if (signum == handle->signum) { - handle->signal_cb = signal_cb; - return 0; - } - - /* If the signal handler was already active, stop it first. */ - if (handle->signum != 0) { - uv__signal_stop(handle); - } - - uv__signal_block_and_lock(&saved_sigmask); - - /* If at this point there are no active signal watchers for this signum (in - * any of the loops), it's time to try and register a handler for it here. - */ - if (uv__signal_first_handle(signum) == NULL) { - err = uv__signal_register_handler(signum); - if (err) { - /* Registering the signal handler failed. Must be an invalid signal. */ - uv__signal_unlock_and_unblock(&saved_sigmask); - return err; - } - } - - handle->signum = signum; - RB_INSERT(uv__signal_tree_s, &uv__signal_tree, handle); - - uv__signal_unlock_and_unblock(&saved_sigmask); - - handle->signal_cb = signal_cb; - uv__handle_start(handle); - - return 0; -} - - -static void uv__signal_event(uv_loop_t* loop, - uv__io_t* w, - unsigned int events) { - uv__signal_msg_t* msg; - uv_signal_t* handle; - char buf[sizeof(uv__signal_msg_t) * 32]; - size_t bytes, end, i; - int r; - - bytes = 0; - end = 0; - - do { - r = read(loop->signal_pipefd[0], buf + bytes, sizeof(buf) - bytes); - - if (r == -1 && errno == EINTR) - continue; - - if (r == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) { - /* If there are bytes in the buffer already (which really is extremely - * unlikely if possible at all) we can't exit the function here. We'll - * spin until more bytes are read instead. - */ - if (bytes > 0) - continue; - - /* Otherwise, there was nothing there. */ - return; - } - - /* Other errors really should never happen. */ - if (r == -1) - abort(); - - bytes += r; - - /* `end` is rounded down to a multiple of sizeof(uv__signal_msg_t). */ - end = (bytes / sizeof(uv__signal_msg_t)) * sizeof(uv__signal_msg_t); - - for (i = 0; i < end; i += sizeof(uv__signal_msg_t)) { - msg = (uv__signal_msg_t*) (buf + i); - handle = msg->handle; - - if (msg->signum == handle->signum) { - assert(!(handle->flags & UV_CLOSING)); - handle->signal_cb(handle, handle->signum); - } - - handle->dispatched_signals++; - - /* If uv_close was called while there were caught signals that were not - * yet dispatched, the uv__finish_close was deferred. Make close pending - * now if this has happened. - */ - if ((handle->flags & UV_CLOSING) && - (handle->caught_signals == handle->dispatched_signals)) { - uv__make_close_pending((uv_handle_t*) handle); - } - } - - bytes -= end; - - /* If there are any "partial" messages left, move them to the start of the - * the buffer, and spin. This should not happen. - */ - if (bytes) { - memmove(buf, buf + end, bytes); - continue; - } - } while (end == sizeof buf); -} - - -static int uv__signal_compare(uv_signal_t* w1, uv_signal_t* w2) { - /* Compare signums first so all watchers with the same signnum end up - * adjacent. - */ - if (w1->signum < w2->signum) return -1; - if (w1->signum > w2->signum) return 1; - - /* Sort by loop pointer, so we can easily look up the first item after - * { .signum = x, .loop = NULL }. - */ - if (w1->loop < w2->loop) return -1; - if (w1->loop > w2->loop) return 1; - - if (w1 < w2) return -1; - if (w1 > w2) return 1; - - return 0; -} - - -int uv_signal_stop(uv_signal_t* handle) { - assert(!uv__is_closing(handle)); - uv__signal_stop(handle); - return 0; -} - - -static void uv__signal_stop(uv_signal_t* handle) { - uv_signal_t* removed_handle; - sigset_t saved_sigmask; - - /* If the watcher wasn't started, this is a no-op. */ - if (handle->signum == 0) - return; - - uv__signal_block_and_lock(&saved_sigmask); - - removed_handle = RB_REMOVE(uv__signal_tree_s, &uv__signal_tree, handle); - assert(removed_handle == handle); - (void) removed_handle; - - /* Check if there are other active signal watchers observing this signal. If - * not, unregister the signal handler. - */ - if (uv__signal_first_handle(handle->signum) == NULL) - uv__signal_unregister_handler(handle->signum); - - uv__signal_unlock_and_unblock(&saved_sigmask); - - handle->signum = 0; - uv__handle_stop(handle); -} diff --git a/vendor/libuv/src/unix/spinlock.h b/vendor/libuv/src/unix/spinlock.h deleted file mode 100644 index a20c83cc6..000000000 --- a/vendor/libuv/src/unix/spinlock.h +++ /dev/null @@ -1,53 +0,0 @@ -/* Copyright (c) 2013, Ben Noordhuis - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef UV_SPINLOCK_H_ -#define UV_SPINLOCK_H_ - -#include "internal.h" /* ACCESS_ONCE, UV_UNUSED */ -#include "atomic-ops.h" - -#define UV_SPINLOCK_INITIALIZER { 0 } - -typedef struct { - int lock; -} uv_spinlock_t; - -UV_UNUSED(static void uv_spinlock_init(uv_spinlock_t* spinlock)); -UV_UNUSED(static void uv_spinlock_lock(uv_spinlock_t* spinlock)); -UV_UNUSED(static void uv_spinlock_unlock(uv_spinlock_t* spinlock)); -UV_UNUSED(static int uv_spinlock_trylock(uv_spinlock_t* spinlock)); - -UV_UNUSED(static void uv_spinlock_init(uv_spinlock_t* spinlock)) { - ACCESS_ONCE(int, spinlock->lock) = 0; -} - -UV_UNUSED(static void uv_spinlock_lock(uv_spinlock_t* spinlock)) { - while (!uv_spinlock_trylock(spinlock)) cpu_relax(); -} - -UV_UNUSED(static void uv_spinlock_unlock(uv_spinlock_t* spinlock)) { - ACCESS_ONCE(int, spinlock->lock) = 0; -} - -UV_UNUSED(static int uv_spinlock_trylock(uv_spinlock_t* spinlock)) { - /* TODO(bnoordhuis) Maybe change to a ticket lock to guarantee fair queueing. - * Not really critical until we have locks that are (frequently) contended - * for by several threads. - */ - return 0 == cmpxchgi(&spinlock->lock, 0, 1); -} - -#endif /* UV_SPINLOCK_H_ */ diff --git a/vendor/libuv/src/unix/stream.c b/vendor/libuv/src/unix/stream.c deleted file mode 100644 index 7059df16a..000000000 --- a/vendor/libuv/src/unix/stream.c +++ /dev/null @@ -1,1661 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "internal.h" - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include /* IOV_MAX */ - -#if defined(__APPLE__) -# include -# include -# include - -/* Forward declaration */ -typedef struct uv__stream_select_s uv__stream_select_t; - -struct uv__stream_select_s { - uv_stream_t* stream; - uv_thread_t thread; - uv_sem_t close_sem; - uv_sem_t async_sem; - uv_async_t async; - int events; - int fake_fd; - int int_fd; - int fd; - fd_set* sread; - size_t sread_sz; - fd_set* swrite; - size_t swrite_sz; -}; -#endif /* defined(__APPLE__) */ - -static void uv__stream_connect(uv_stream_t*); -static void uv__write(uv_stream_t* stream); -static void uv__read(uv_stream_t* stream); -static void uv__stream_io(uv_loop_t* loop, uv__io_t* w, unsigned int events); -static void uv__write_callbacks(uv_stream_t* stream); -static size_t uv__write_req_size(uv_write_t* req); - - -void uv__stream_init(uv_loop_t* loop, - uv_stream_t* stream, - uv_handle_type type) { - int err; - - uv__handle_init(loop, (uv_handle_t*)stream, type); - stream->read_cb = NULL; - stream->alloc_cb = NULL; - stream->close_cb = NULL; - stream->connection_cb = NULL; - stream->connect_req = NULL; - stream->shutdown_req = NULL; - stream->accepted_fd = -1; - stream->queued_fds = NULL; - stream->delayed_error = 0; - QUEUE_INIT(&stream->write_queue); - QUEUE_INIT(&stream->write_completed_queue); - stream->write_queue_size = 0; - - if (loop->emfile_fd == -1) { - err = uv__open_cloexec("/dev/null", O_RDONLY); - if (err < 0) - /* In the rare case that "/dev/null" isn't mounted open "/" - * instead. - */ - err = uv__open_cloexec("/", O_RDONLY); - if (err >= 0) - loop->emfile_fd = err; - } - -#if defined(__APPLE__) - stream->select = NULL; -#endif /* defined(__APPLE_) */ - - uv__io_init(&stream->io_watcher, uv__stream_io, -1); -} - - -static void uv__stream_osx_interrupt_select(uv_stream_t* stream) { -#if defined(__APPLE__) - /* Notify select() thread about state change */ - uv__stream_select_t* s; - int r; - - s = stream->select; - if (s == NULL) - return; - - /* Interrupt select() loop - * NOTE: fake_fd and int_fd are socketpair(), thus writing to one will - * emit read event on other side - */ - do - r = write(s->fake_fd, "x", 1); - while (r == -1 && errno == EINTR); - - assert(r == 1); -#else /* !defined(__APPLE__) */ - /* No-op on any other platform */ -#endif /* !defined(__APPLE__) */ -} - - -#if defined(__APPLE__) -static void uv__stream_osx_select(void* arg) { - uv_stream_t* stream; - uv__stream_select_t* s; - char buf[1024]; - int events; - int fd; - int r; - int max_fd; - - stream = arg; - s = stream->select; - fd = s->fd; - - if (fd > s->int_fd) - max_fd = fd; - else - max_fd = s->int_fd; - - while (1) { - /* Terminate on semaphore */ - if (uv_sem_trywait(&s->close_sem) == 0) - break; - - /* Watch fd using select(2) */ - memset(s->sread, 0, s->sread_sz); - memset(s->swrite, 0, s->swrite_sz); - - if (uv__io_active(&stream->io_watcher, POLLIN)) - FD_SET(fd, s->sread); - if (uv__io_active(&stream->io_watcher, POLLOUT)) - FD_SET(fd, s->swrite); - FD_SET(s->int_fd, s->sread); - - /* Wait indefinitely for fd events */ - r = select(max_fd + 1, s->sread, s->swrite, NULL, NULL); - if (r == -1) { - if (errno == EINTR) - continue; - - /* XXX: Possible?! */ - abort(); - } - - /* Ignore timeouts */ - if (r == 0) - continue; - - /* Empty socketpair's buffer in case of interruption */ - if (FD_ISSET(s->int_fd, s->sread)) - while (1) { - r = read(s->int_fd, buf, sizeof(buf)); - - if (r == sizeof(buf)) - continue; - - if (r != -1) - break; - - if (errno == EAGAIN || errno == EWOULDBLOCK) - break; - - if (errno == EINTR) - continue; - - abort(); - } - - /* Handle events */ - events = 0; - if (FD_ISSET(fd, s->sread)) - events |= POLLIN; - if (FD_ISSET(fd, s->swrite)) - events |= POLLOUT; - - assert(events != 0 || FD_ISSET(s->int_fd, s->sread)); - if (events != 0) { - ACCESS_ONCE(int, s->events) = events; - - uv_async_send(&s->async); - uv_sem_wait(&s->async_sem); - - /* Should be processed at this stage */ - assert((s->events == 0) || (stream->flags & UV_CLOSING)); - } - } -} - - -static void uv__stream_osx_select_cb(uv_async_t* handle) { - uv__stream_select_t* s; - uv_stream_t* stream; - int events; - - s = container_of(handle, uv__stream_select_t, async); - stream = s->stream; - - /* Get and reset stream's events */ - events = s->events; - ACCESS_ONCE(int, s->events) = 0; - - assert(events != 0); - assert(events == (events & (POLLIN | POLLOUT))); - - /* Invoke callback on event-loop */ - if ((events & POLLIN) && uv__io_active(&stream->io_watcher, POLLIN)) - uv__stream_io(stream->loop, &stream->io_watcher, POLLIN); - - if ((events & POLLOUT) && uv__io_active(&stream->io_watcher, POLLOUT)) - uv__stream_io(stream->loop, &stream->io_watcher, POLLOUT); - - if (stream->flags & UV_CLOSING) - return; - - /* NOTE: It is important to do it here, otherwise `select()` might be called - * before the actual `uv__read()`, leading to the blocking syscall - */ - uv_sem_post(&s->async_sem); -} - - -static void uv__stream_osx_cb_close(uv_handle_t* async) { - uv__stream_select_t* s; - - s = container_of(async, uv__stream_select_t, async); - uv__free(s); -} - - -int uv__stream_try_select(uv_stream_t* stream, int* fd) { - /* - * kqueue doesn't work with some files from /dev mount on osx. - * select(2) in separate thread for those fds - */ - - struct kevent filter[1]; - struct kevent events[1]; - struct timespec timeout; - uv__stream_select_t* s; - int fds[2]; - int err; - int ret; - int kq; - int old_fd; - int max_fd; - size_t sread_sz; - size_t swrite_sz; - - kq = kqueue(); - if (kq == -1) { - perror("(libuv) kqueue()"); - return -errno; - } - - EV_SET(&filter[0], *fd, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, 0); - - /* Use small timeout, because we only want to capture EINVALs */ - timeout.tv_sec = 0; - timeout.tv_nsec = 1; - - do - ret = kevent(kq, filter, 1, events, 1, &timeout); - while (ret == -1 && errno == EINTR); - - uv__close(kq); - - if (ret == -1) - return -errno; - - if (ret == 0 || (events[0].flags & EV_ERROR) == 0 || events[0].data != EINVAL) - return 0; - - /* At this point we definitely know that this fd won't work with kqueue */ - - /* - * Create fds for io watcher and to interrupt the select() loop. - * NOTE: do it ahead of malloc below to allocate enough space for fd_sets - */ - if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds)) - return -errno; - - max_fd = *fd; - if (fds[1] > max_fd) - max_fd = fds[1]; - - sread_sz = ROUND_UP(max_fd + 1, sizeof(uint32_t) * NBBY) / NBBY; - swrite_sz = sread_sz; - - s = uv__malloc(sizeof(*s) + sread_sz + swrite_sz); - if (s == NULL) { - err = -ENOMEM; - goto failed_malloc; - } - - s->events = 0; - s->fd = *fd; - s->sread = (fd_set*) ((char*) s + sizeof(*s)); - s->sread_sz = sread_sz; - s->swrite = (fd_set*) ((char*) s->sread + sread_sz); - s->swrite_sz = swrite_sz; - - err = uv_async_init(stream->loop, &s->async, uv__stream_osx_select_cb); - if (err) - goto failed_async_init; - - s->async.flags |= UV__HANDLE_INTERNAL; - uv__handle_unref(&s->async); - - err = uv_sem_init(&s->close_sem, 0); - if (err != 0) - goto failed_close_sem_init; - - err = uv_sem_init(&s->async_sem, 0); - if (err != 0) - goto failed_async_sem_init; - - s->fake_fd = fds[0]; - s->int_fd = fds[1]; - - old_fd = *fd; - s->stream = stream; - stream->select = s; - *fd = s->fake_fd; - - err = uv_thread_create(&s->thread, uv__stream_osx_select, stream); - if (err != 0) - goto failed_thread_create; - - return 0; - -failed_thread_create: - s->stream = NULL; - stream->select = NULL; - *fd = old_fd; - - uv_sem_destroy(&s->async_sem); - -failed_async_sem_init: - uv_sem_destroy(&s->close_sem); - -failed_close_sem_init: - uv__close(fds[0]); - uv__close(fds[1]); - uv_close((uv_handle_t*) &s->async, uv__stream_osx_cb_close); - return err; - -failed_async_init: - uv__free(s); - -failed_malloc: - uv__close(fds[0]); - uv__close(fds[1]); - - return err; -} -#endif /* defined(__APPLE__) */ - - -int uv__stream_open(uv_stream_t* stream, int fd, int flags) { -#if defined(__APPLE__) || defined(__MVS__) - int enable; -#endif - - if (!(stream->io_watcher.fd == -1 || stream->io_watcher.fd == fd)) - return -EBUSY; - - assert(fd >= 0); - stream->flags |= flags; - - if (stream->type == UV_TCP) { - if ((stream->flags & UV_TCP_NODELAY) && uv__tcp_nodelay(fd, 1)) - return -errno; - - /* TODO Use delay the user passed in. */ - if ((stream->flags & UV_TCP_KEEPALIVE) && uv__tcp_keepalive(fd, 1, 60)) - return -errno; - } - -#if defined(__APPLE__) || defined(__MVS__) - enable = 1; - if (setsockopt(fd, SOL_SOCKET, SO_OOBINLINE, &enable, sizeof(enable)) && - errno != ENOTSOCK && - errno != EINVAL) { - return -errno; - } -#endif - - stream->io_watcher.fd = fd; - - return 0; -} - - -void uv__stream_flush_write_queue(uv_stream_t* stream, int error) { - uv_write_t* req; - QUEUE* q; - while (!QUEUE_EMPTY(&stream->write_queue)) { - q = QUEUE_HEAD(&stream->write_queue); - QUEUE_REMOVE(q); - - req = QUEUE_DATA(q, uv_write_t, queue); - req->error = error; - - QUEUE_INSERT_TAIL(&stream->write_completed_queue, &req->queue); - } -} - - -void uv__stream_destroy(uv_stream_t* stream) { - assert(!uv__io_active(&stream->io_watcher, POLLIN | POLLOUT)); - assert(stream->flags & UV_CLOSED); - - if (stream->connect_req) { - uv__req_unregister(stream->loop, stream->connect_req); - stream->connect_req->cb(stream->connect_req, -ECANCELED); - stream->connect_req = NULL; - } - - uv__stream_flush_write_queue(stream, -ECANCELED); - uv__write_callbacks(stream); - - if (stream->shutdown_req) { - /* The ECANCELED error code is a lie, the shutdown(2) syscall is a - * fait accompli at this point. Maybe we should revisit this in v0.11. - * A possible reason for leaving it unchanged is that it informs the - * callee that the handle has been destroyed. - */ - uv__req_unregister(stream->loop, stream->shutdown_req); - stream->shutdown_req->cb(stream->shutdown_req, -ECANCELED); - stream->shutdown_req = NULL; - } - - assert(stream->write_queue_size == 0); -} - - -/* Implements a best effort approach to mitigating accept() EMFILE errors. - * We have a spare file descriptor stashed away that we close to get below - * the EMFILE limit. Next, we accept all pending connections and close them - * immediately to signal the clients that we're overloaded - and we are, but - * we still keep on trucking. - * - * There is one caveat: it's not reliable in a multi-threaded environment. - * The file descriptor limit is per process. Our party trick fails if another - * thread opens a file or creates a socket in the time window between us - * calling close() and accept(). - */ -static int uv__emfile_trick(uv_loop_t* loop, int accept_fd) { - int err; - int emfile_fd; - - if (loop->emfile_fd == -1) - return -EMFILE; - - uv__close(loop->emfile_fd); - loop->emfile_fd = -1; - - do { - err = uv__accept(accept_fd); - if (err >= 0) - uv__close(err); - } while (err >= 0 || err == -EINTR); - - emfile_fd = uv__open_cloexec("/", O_RDONLY); - if (emfile_fd >= 0) - loop->emfile_fd = emfile_fd; - - return err; -} - - -#if defined(UV_HAVE_KQUEUE) -# define UV_DEC_BACKLOG(w) w->rcount--; -#else -# define UV_DEC_BACKLOG(w) /* no-op */ -#endif /* defined(UV_HAVE_KQUEUE) */ - - -void uv__server_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) { - uv_stream_t* stream; - int err; - - stream = container_of(w, uv_stream_t, io_watcher); - assert(events == POLLIN); - assert(stream->accepted_fd == -1); - assert(!(stream->flags & UV_CLOSING)); - - uv__io_start(stream->loop, &stream->io_watcher, POLLIN); - - /* connection_cb can close the server socket while we're - * in the loop so check it on each iteration. - */ - while (uv__stream_fd(stream) != -1) { - assert(stream->accepted_fd == -1); - -#if defined(UV_HAVE_KQUEUE) - if (w->rcount <= 0) - return; -#endif /* defined(UV_HAVE_KQUEUE) */ - - err = uv__accept(uv__stream_fd(stream)); - if (err < 0) { - if (err == -EAGAIN || err == -EWOULDBLOCK) - return; /* Not an error. */ - - if (err == -ECONNABORTED) - continue; /* Ignore. Nothing we can do about that. */ - - if (err == -EMFILE || err == -ENFILE) { - err = uv__emfile_trick(loop, uv__stream_fd(stream)); - if (err == -EAGAIN || err == -EWOULDBLOCK) - break; - } - - stream->connection_cb(stream, err); - continue; - } - - UV_DEC_BACKLOG(w) - stream->accepted_fd = err; - stream->connection_cb(stream, 0); - - if (stream->accepted_fd != -1) { - /* The user hasn't yet accepted called uv_accept() */ - uv__io_stop(loop, &stream->io_watcher, POLLIN); - return; - } - - if (stream->type == UV_TCP && (stream->flags & UV_TCP_SINGLE_ACCEPT)) { - /* Give other processes a chance to accept connections. */ - struct timespec timeout = { 0, 1 }; - nanosleep(&timeout, NULL); - } - } -} - - -#undef UV_DEC_BACKLOG - - -int uv_accept(uv_stream_t* server, uv_stream_t* client) { - int err; - - assert(server->loop == client->loop); - - if (server->accepted_fd == -1) - return -EAGAIN; - - switch (client->type) { - case UV_NAMED_PIPE: - case UV_TCP: - err = uv__stream_open(client, - server->accepted_fd, - UV_STREAM_READABLE | UV_STREAM_WRITABLE); - if (err) { - /* TODO handle error */ - uv__close(server->accepted_fd); - goto done; - } - break; - - case UV_UDP: - err = uv_udp_open((uv_udp_t*) client, server->accepted_fd); - if (err) { - uv__close(server->accepted_fd); - goto done; - } - break; - - default: - return -EINVAL; - } - - client->flags |= UV_HANDLE_BOUND; - -done: - /* Process queued fds */ - if (server->queued_fds != NULL) { - uv__stream_queued_fds_t* queued_fds; - - queued_fds = server->queued_fds; - - /* Read first */ - server->accepted_fd = queued_fds->fds[0]; - - /* All read, free */ - assert(queued_fds->offset > 0); - if (--queued_fds->offset == 0) { - uv__free(queued_fds); - server->queued_fds = NULL; - } else { - /* Shift rest */ - memmove(queued_fds->fds, - queued_fds->fds + 1, - queued_fds->offset * sizeof(*queued_fds->fds)); - } - } else { - server->accepted_fd = -1; - if (err == 0) - uv__io_start(server->loop, &server->io_watcher, POLLIN); - } - return err; -} - - -int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb) { - int err; - - switch (stream->type) { - case UV_TCP: - err = uv_tcp_listen((uv_tcp_t*)stream, backlog, cb); - break; - - case UV_NAMED_PIPE: - err = uv_pipe_listen((uv_pipe_t*)stream, backlog, cb); - break; - - default: - err = -EINVAL; - } - - if (err == 0) - uv__handle_start(stream); - - return err; -} - - -static void uv__drain(uv_stream_t* stream) { - uv_shutdown_t* req; - int err; - - assert(QUEUE_EMPTY(&stream->write_queue)); - uv__io_stop(stream->loop, &stream->io_watcher, POLLOUT); - uv__stream_osx_interrupt_select(stream); - - /* Shutdown? */ - if ((stream->flags & UV_STREAM_SHUTTING) && - !(stream->flags & UV_CLOSING) && - !(stream->flags & UV_STREAM_SHUT)) { - assert(stream->shutdown_req); - - req = stream->shutdown_req; - stream->shutdown_req = NULL; - stream->flags &= ~UV_STREAM_SHUTTING; - uv__req_unregister(stream->loop, req); - - err = 0; - if (shutdown(uv__stream_fd(stream), SHUT_WR)) - err = -errno; - - if (err == 0) - stream->flags |= UV_STREAM_SHUT; - - if (req->cb != NULL) - req->cb(req, err); - } -} - - -static size_t uv__write_req_size(uv_write_t* req) { - size_t size; - - assert(req->bufs != NULL); - size = uv__count_bufs(req->bufs + req->write_index, - req->nbufs - req->write_index); - assert(req->handle->write_queue_size >= size); - - return size; -} - - -static void uv__write_req_finish(uv_write_t* req) { - uv_stream_t* stream = req->handle; - - /* Pop the req off tcp->write_queue. */ - QUEUE_REMOVE(&req->queue); - - /* Only free when there was no error. On error, we touch up write_queue_size - * right before making the callback. The reason we don't do that right away - * is that a write_queue_size > 0 is our only way to signal to the user that - * they should stop writing - which they should if we got an error. Something - * to revisit in future revisions of the libuv API. - */ - if (req->error == 0) { - if (req->bufs != req->bufsml) - uv__free(req->bufs); - req->bufs = NULL; - } - - /* Add it to the write_completed_queue where it will have its - * callback called in the near future. - */ - QUEUE_INSERT_TAIL(&stream->write_completed_queue, &req->queue); - uv__io_feed(stream->loop, &stream->io_watcher); -} - - -static int uv__handle_fd(uv_handle_t* handle) { - switch (handle->type) { - case UV_NAMED_PIPE: - case UV_TCP: - return ((uv_stream_t*) handle)->io_watcher.fd; - - case UV_UDP: - return ((uv_udp_t*) handle)->io_watcher.fd; - - default: - return -1; - } -} - -static void uv__write(uv_stream_t* stream) { - struct iovec* iov; - QUEUE* q; - uv_write_t* req; - int iovmax; - int iovcnt; - ssize_t n; - -start: - - assert(uv__stream_fd(stream) >= 0); - - if (QUEUE_EMPTY(&stream->write_queue)) - return; - - q = QUEUE_HEAD(&stream->write_queue); - req = QUEUE_DATA(q, uv_write_t, queue); - assert(req->handle == stream); - - /* - * Cast to iovec. We had to have our own uv_buf_t instead of iovec - * because Windows's WSABUF is not an iovec. - */ - assert(sizeof(uv_buf_t) == sizeof(struct iovec)); - iov = (struct iovec*) &(req->bufs[req->write_index]); - iovcnt = req->nbufs - req->write_index; - - iovmax = uv__getiovmax(); - - /* Limit iov count to avoid EINVALs from writev() */ - if (iovcnt > iovmax) - iovcnt = iovmax; - - /* - * Now do the actual writev. Note that we've been updating the pointers - * inside the iov each time we write. So there is no need to offset it. - */ - - if (req->send_handle) { - struct msghdr msg; - struct cmsghdr *cmsg; - int fd_to_send = uv__handle_fd((uv_handle_t*) req->send_handle); - char scratch[64] = {0}; - - assert(fd_to_send >= 0); - - msg.msg_name = NULL; - msg.msg_namelen = 0; - msg.msg_iov = iov; - msg.msg_iovlen = iovcnt; - msg.msg_flags = 0; - - msg.msg_control = (void*) scratch; - msg.msg_controllen = CMSG_SPACE(sizeof(fd_to_send)); - - cmsg = CMSG_FIRSTHDR(&msg); - cmsg->cmsg_level = SOL_SOCKET; - cmsg->cmsg_type = SCM_RIGHTS; - cmsg->cmsg_len = CMSG_LEN(sizeof(fd_to_send)); - - /* silence aliasing warning */ - { - void* pv = CMSG_DATA(cmsg); - int* pi = pv; - *pi = fd_to_send; - } - - do { - n = sendmsg(uv__stream_fd(stream), &msg, 0); - } -#if defined(__APPLE__) - /* - * Due to a possible kernel bug at least in OS X 10.10 "Yosemite", - * EPROTOTYPE can be returned while trying to write to a socket that is - * shutting down. If we retry the write, we should get the expected EPIPE - * instead. - */ - while (n == -1 && (errno == EINTR || errno == EPROTOTYPE)); -#else - while (n == -1 && errno == EINTR); -#endif - } else { - do { - if (iovcnt == 1) { - n = write(uv__stream_fd(stream), iov[0].iov_base, iov[0].iov_len); - } else { - n = writev(uv__stream_fd(stream), iov, iovcnt); - } - } -#if defined(__APPLE__) - /* - * Due to a possible kernel bug at least in OS X 10.10 "Yosemite", - * EPROTOTYPE can be returned while trying to write to a socket that is - * shutting down. If we retry the write, we should get the expected EPIPE - * instead. - */ - while (n == -1 && (errno == EINTR || errno == EPROTOTYPE)); -#else - while (n == -1 && errno == EINTR); -#endif - } - - if (n < 0) { - if (errno != EAGAIN && errno != EWOULDBLOCK) { - /* Error */ - req->error = -errno; - uv__write_req_finish(req); - uv__io_stop(stream->loop, &stream->io_watcher, POLLOUT); - if (!uv__io_active(&stream->io_watcher, POLLIN)) - uv__handle_stop(stream); - uv__stream_osx_interrupt_select(stream); - return; - } else if (stream->flags & UV_STREAM_BLOCKING) { - /* If this is a blocking stream, try again. */ - goto start; - } - } else { - /* Successful write */ - - while (n >= 0) { - uv_buf_t* buf = &(req->bufs[req->write_index]); - size_t len = buf->len; - - assert(req->write_index < req->nbufs); - - if ((size_t)n < len) { - buf->base += n; - buf->len -= n; - stream->write_queue_size -= n; - n = 0; - - /* There is more to write. */ - if (stream->flags & UV_STREAM_BLOCKING) { - /* - * If we're blocking then we should not be enabling the write - * watcher - instead we need to try again. - */ - goto start; - } else { - /* Break loop and ensure the watcher is pending. */ - break; - } - - } else { - /* Finished writing the buf at index req->write_index. */ - req->write_index++; - - assert((size_t)n >= len); - n -= len; - - assert(stream->write_queue_size >= len); - stream->write_queue_size -= len; - - if (req->write_index == req->nbufs) { - /* Then we're done! */ - assert(n == 0); - uv__write_req_finish(req); - /* TODO: start trying to write the next request. */ - return; - } - } - } - } - - /* Either we've counted n down to zero or we've got EAGAIN. */ - assert(n == 0 || n == -1); - - /* Only non-blocking streams should use the write_watcher. */ - assert(!(stream->flags & UV_STREAM_BLOCKING)); - - /* We're not done. */ - uv__io_start(stream->loop, &stream->io_watcher, POLLOUT); - - /* Notify select() thread about state change */ - uv__stream_osx_interrupt_select(stream); -} - - -static void uv__write_callbacks(uv_stream_t* stream) { - uv_write_t* req; - QUEUE* q; - - while (!QUEUE_EMPTY(&stream->write_completed_queue)) { - /* Pop a req off write_completed_queue. */ - q = QUEUE_HEAD(&stream->write_completed_queue); - req = QUEUE_DATA(q, uv_write_t, queue); - QUEUE_REMOVE(q); - uv__req_unregister(stream->loop, req); - - if (req->bufs != NULL) { - stream->write_queue_size -= uv__write_req_size(req); - if (req->bufs != req->bufsml) - uv__free(req->bufs); - req->bufs = NULL; - } - - /* NOTE: call callback AFTER freeing the request data. */ - if (req->cb) - req->cb(req, req->error); - } - - assert(QUEUE_EMPTY(&stream->write_completed_queue)); -} - - -uv_handle_type uv__handle_type(int fd) { - struct sockaddr_storage ss; - socklen_t sslen; - socklen_t len; - int type; - - memset(&ss, 0, sizeof(ss)); - sslen = sizeof(ss); - - if (getsockname(fd, (struct sockaddr*)&ss, &sslen)) - return UV_UNKNOWN_HANDLE; - - len = sizeof type; - - if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &type, &len)) - return UV_UNKNOWN_HANDLE; - - if (type == SOCK_STREAM) { -#if defined(_AIX) || defined(__DragonFly__) - /* on AIX/DragonFly the getsockname call returns an empty sa structure - * for sockets of type AF_UNIX. For all other types it will - * return a properly filled in structure. - */ - if (sslen == 0) - return UV_NAMED_PIPE; -#endif - switch (ss.ss_family) { - case AF_UNIX: - return UV_NAMED_PIPE; - case AF_INET: - case AF_INET6: - return UV_TCP; - } - } - - if (type == SOCK_DGRAM && - (ss.ss_family == AF_INET || ss.ss_family == AF_INET6)) - return UV_UDP; - - return UV_UNKNOWN_HANDLE; -} - - -static void uv__stream_eof(uv_stream_t* stream, const uv_buf_t* buf) { - stream->flags |= UV_STREAM_READ_EOF; - uv__io_stop(stream->loop, &stream->io_watcher, POLLIN); - if (!uv__io_active(&stream->io_watcher, POLLOUT)) - uv__handle_stop(stream); - uv__stream_osx_interrupt_select(stream); - stream->read_cb(stream, UV_EOF, buf); - stream->flags &= ~UV_STREAM_READING; -} - - -static int uv__stream_queue_fd(uv_stream_t* stream, int fd) { - uv__stream_queued_fds_t* queued_fds; - unsigned int queue_size; - - queued_fds = stream->queued_fds; - if (queued_fds == NULL) { - queue_size = 8; - queued_fds = uv__malloc((queue_size - 1) * sizeof(*queued_fds->fds) + - sizeof(*queued_fds)); - if (queued_fds == NULL) - return -ENOMEM; - queued_fds->size = queue_size; - queued_fds->offset = 0; - stream->queued_fds = queued_fds; - - /* Grow */ - } else if (queued_fds->size == queued_fds->offset) { - queue_size = queued_fds->size + 8; - queued_fds = uv__realloc(queued_fds, - (queue_size - 1) * sizeof(*queued_fds->fds) + - sizeof(*queued_fds)); - - /* - * Allocation failure, report back. - * NOTE: if it is fatal - sockets will be closed in uv__stream_close - */ - if (queued_fds == NULL) - return -ENOMEM; - queued_fds->size = queue_size; - stream->queued_fds = queued_fds; - } - - /* Put fd in a queue */ - queued_fds->fds[queued_fds->offset++] = fd; - - return 0; -} - - -#define UV__CMSG_FD_COUNT 64 -#define UV__CMSG_FD_SIZE (UV__CMSG_FD_COUNT * sizeof(int)) - - -static int uv__stream_recv_cmsg(uv_stream_t* stream, struct msghdr* msg) { - struct cmsghdr* cmsg; - - for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL; cmsg = CMSG_NXTHDR(msg, cmsg)) { - char* start; - char* end; - int err; - void* pv; - int* pi; - unsigned int i; - unsigned int count; - - if (cmsg->cmsg_type != SCM_RIGHTS) { - fprintf(stderr, "ignoring non-SCM_RIGHTS ancillary data: %d\n", - cmsg->cmsg_type); - continue; - } - - /* silence aliasing warning */ - pv = CMSG_DATA(cmsg); - pi = pv; - - /* Count available fds */ - start = (char*) cmsg; - end = (char*) cmsg + cmsg->cmsg_len; - count = 0; - while (start + CMSG_LEN(count * sizeof(*pi)) < end) - count++; - assert(start + CMSG_LEN(count * sizeof(*pi)) == end); - - for (i = 0; i < count; i++) { - /* Already has accepted fd, queue now */ - if (stream->accepted_fd != -1) { - err = uv__stream_queue_fd(stream, pi[i]); - if (err != 0) { - /* Close rest */ - for (; i < count; i++) - uv__close(pi[i]); - return err; - } - } else { - stream->accepted_fd = pi[i]; - } - } - } - - return 0; -} - - -#ifdef __clang__ -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wgnu-folding-constant" -#endif - -static void uv__read(uv_stream_t* stream) { - uv_buf_t buf; - ssize_t nread; - struct msghdr msg; - char cmsg_space[CMSG_SPACE(UV__CMSG_FD_SIZE)]; - int count; - int err; - int is_ipc; - - stream->flags &= ~UV_STREAM_READ_PARTIAL; - - /* Prevent loop starvation when the data comes in as fast as (or faster than) - * we can read it. XXX Need to rearm fd if we switch to edge-triggered I/O. - */ - count = 32; - - is_ipc = stream->type == UV_NAMED_PIPE && ((uv_pipe_t*) stream)->ipc; - - /* XXX: Maybe instead of having UV_STREAM_READING we just test if - * tcp->read_cb is NULL or not? - */ - while (stream->read_cb - && (stream->flags & UV_STREAM_READING) - && (count-- > 0)) { - assert(stream->alloc_cb != NULL); - - buf = uv_buf_init(NULL, 0); - stream->alloc_cb((uv_handle_t*)stream, 64 * 1024, &buf); - if (buf.base == NULL || buf.len == 0) { - /* User indicates it can't or won't handle the read. */ - stream->read_cb(stream, UV_ENOBUFS, &buf); - return; - } - - assert(buf.base != NULL); - assert(uv__stream_fd(stream) >= 0); - - if (!is_ipc) { - do { - nread = read(uv__stream_fd(stream), buf.base, buf.len); - } - while (nread < 0 && errno == EINTR); - } else { - /* ipc uses recvmsg */ - msg.msg_flags = 0; - msg.msg_iov = (struct iovec*) &buf; - msg.msg_iovlen = 1; - msg.msg_name = NULL; - msg.msg_namelen = 0; - /* Set up to receive a descriptor even if one isn't in the message */ - msg.msg_controllen = sizeof(cmsg_space); - msg.msg_control = cmsg_space; - - do { - nread = uv__recvmsg(uv__stream_fd(stream), &msg, 0); - } - while (nread < 0 && errno == EINTR); - } - - if (nread < 0) { - /* Error */ - if (errno == EAGAIN || errno == EWOULDBLOCK) { - /* Wait for the next one. */ - if (stream->flags & UV_STREAM_READING) { - uv__io_start(stream->loop, &stream->io_watcher, POLLIN); - uv__stream_osx_interrupt_select(stream); - } - stream->read_cb(stream, 0, &buf); - } else { - /* Error. User should call uv_close(). */ - stream->read_cb(stream, -errno, &buf); - if (stream->flags & UV_STREAM_READING) { - stream->flags &= ~UV_STREAM_READING; - uv__io_stop(stream->loop, &stream->io_watcher, POLLIN); - if (!uv__io_active(&stream->io_watcher, POLLOUT)) - uv__handle_stop(stream); - uv__stream_osx_interrupt_select(stream); - } - } - return; - } else if (nread == 0) { - uv__stream_eof(stream, &buf); - return; - } else { - /* Successful read */ - ssize_t buflen = buf.len; - - if (is_ipc) { - err = uv__stream_recv_cmsg(stream, &msg); - if (err != 0) { - stream->read_cb(stream, err, &buf); - return; - } - } - -#if defined(__MVS__) - if (is_ipc && msg.msg_controllen > 0) { - uv_buf_t blankbuf; - int nread; - struct iovec *old; - - blankbuf.base = 0; - blankbuf.len = 0; - old = msg.msg_iov; - msg.msg_iov = (struct iovec*) &blankbuf; - nread = 0; - do { - nread = uv__recvmsg(uv__stream_fd(stream), &msg, 0); - err = uv__stream_recv_cmsg(stream, &msg); - if (err != 0) { - stream->read_cb(stream, err, &buf); - msg.msg_iov = old; - return; - } - } while (nread == 0 && msg.msg_controllen > 0); - msg.msg_iov = old; - } -#endif - stream->read_cb(stream, nread, &buf); - - /* Return if we didn't fill the buffer, there is no more data to read. */ - if (nread < buflen) { - stream->flags |= UV_STREAM_READ_PARTIAL; - return; - } - } - } -} - - -#ifdef __clang__ -# pragma clang diagnostic pop -#endif - -#undef UV__CMSG_FD_COUNT -#undef UV__CMSG_FD_SIZE - - -int uv_shutdown(uv_shutdown_t* req, uv_stream_t* stream, uv_shutdown_cb cb) { - assert((stream->type == UV_TCP || stream->type == UV_NAMED_PIPE) && - "uv_shutdown (unix) only supports uv_handle_t right now"); - - if (!(stream->flags & UV_STREAM_WRITABLE) || - stream->flags & UV_STREAM_SHUT || - stream->flags & UV_STREAM_SHUTTING || - uv__is_closing(stream)) { - return -ENOTCONN; - } - - assert(uv__stream_fd(stream) >= 0); - - /* Initialize request */ - uv__req_init(stream->loop, req, UV_SHUTDOWN); - req->handle = stream; - req->cb = cb; - stream->shutdown_req = req; - stream->flags |= UV_STREAM_SHUTTING; - - uv__io_start(stream->loop, &stream->io_watcher, POLLOUT); - uv__stream_osx_interrupt_select(stream); - - return 0; -} - - -static void uv__stream_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) { - uv_stream_t* stream; - - stream = container_of(w, uv_stream_t, io_watcher); - - assert(stream->type == UV_TCP || - stream->type == UV_NAMED_PIPE || - stream->type == UV_TTY); - assert(!(stream->flags & UV_CLOSING)); - - if (stream->connect_req) { - uv__stream_connect(stream); - return; - } - - assert(uv__stream_fd(stream) >= 0); - - /* Ignore POLLHUP here. Even it it's set, there may still be data to read. */ - if (events & (POLLIN | POLLERR | POLLHUP)) - uv__read(stream); - - if (uv__stream_fd(stream) == -1) - return; /* read_cb closed stream. */ - - /* Short-circuit iff POLLHUP is set, the user is still interested in read - * events and uv__read() reported a partial read but not EOF. If the EOF - * flag is set, uv__read() called read_cb with err=UV_EOF and we don't - * have to do anything. If the partial read flag is not set, we can't - * report the EOF yet because there is still data to read. - */ - if ((events & POLLHUP) && - (stream->flags & UV_STREAM_READING) && - (stream->flags & UV_STREAM_READ_PARTIAL) && - !(stream->flags & UV_STREAM_READ_EOF)) { - uv_buf_t buf = { NULL, 0 }; - uv__stream_eof(stream, &buf); - } - - if (uv__stream_fd(stream) == -1) - return; /* read_cb closed stream. */ - - if (events & (POLLOUT | POLLERR | POLLHUP)) { - uv__write(stream); - uv__write_callbacks(stream); - - /* Write queue drained. */ - if (QUEUE_EMPTY(&stream->write_queue)) - uv__drain(stream); - } -} - - -/** - * We get called here from directly following a call to connect(2). - * In order to determine if we've errored out or succeeded must call - * getsockopt. - */ -static void uv__stream_connect(uv_stream_t* stream) { - int error; - uv_connect_t* req = stream->connect_req; - socklen_t errorsize = sizeof(int); - - assert(stream->type == UV_TCP || stream->type == UV_NAMED_PIPE); - assert(req); - - if (stream->delayed_error) { - /* To smooth over the differences between unixes errors that - * were reported synchronously on the first connect can be delayed - * until the next tick--which is now. - */ - error = stream->delayed_error; - stream->delayed_error = 0; - } else { - /* Normal situation: we need to get the socket error from the kernel. */ - assert(uv__stream_fd(stream) >= 0); - getsockopt(uv__stream_fd(stream), - SOL_SOCKET, - SO_ERROR, - &error, - &errorsize); - error = -error; - } - - if (error == -EINPROGRESS) - return; - - stream->connect_req = NULL; - uv__req_unregister(stream->loop, req); - - if (error < 0 || QUEUE_EMPTY(&stream->write_queue)) { - uv__io_stop(stream->loop, &stream->io_watcher, POLLOUT); - } - - if (req->cb) - req->cb(req, error); - - if (uv__stream_fd(stream) == -1) - return; - - if (error < 0) { - uv__stream_flush_write_queue(stream, -ECANCELED); - uv__write_callbacks(stream); - } -} - - -int uv_write2(uv_write_t* req, - uv_stream_t* stream, - const uv_buf_t bufs[], - unsigned int nbufs, - uv_stream_t* send_handle, - uv_write_cb cb) { - int empty_queue; - - assert(nbufs > 0); - assert((stream->type == UV_TCP || - stream->type == UV_NAMED_PIPE || - stream->type == UV_TTY) && - "uv_write (unix) does not yet support other types of streams"); - - if (uv__stream_fd(stream) < 0) - return -EBADF; - - if (send_handle) { - if (stream->type != UV_NAMED_PIPE || !((uv_pipe_t*)stream)->ipc) - return -EINVAL; - - /* XXX We abuse uv_write2() to send over UDP handles to child processes. - * Don't call uv__stream_fd() on those handles, it's a macro that on OS X - * evaluates to a function that operates on a uv_stream_t with a couple of - * OS X specific fields. On other Unices it does (handle)->io_watcher.fd, - * which works but only by accident. - */ - if (uv__handle_fd((uv_handle_t*) send_handle) < 0) - return -EBADF; - } - - /* It's legal for write_queue_size > 0 even when the write_queue is empty; - * it means there are error-state requests in the write_completed_queue that - * will touch up write_queue_size later, see also uv__write_req_finish(). - * We could check that write_queue is empty instead but that implies making - * a write() syscall when we know that the handle is in error mode. - */ - empty_queue = (stream->write_queue_size == 0); - - /* Initialize the req */ - uv__req_init(stream->loop, req, UV_WRITE); - req->cb = cb; - req->handle = stream; - req->error = 0; - req->send_handle = send_handle; - QUEUE_INIT(&req->queue); - - req->bufs = req->bufsml; - if (nbufs > ARRAY_SIZE(req->bufsml)) - req->bufs = uv__malloc(nbufs * sizeof(bufs[0])); - - if (req->bufs == NULL) - return -ENOMEM; - - memcpy(req->bufs, bufs, nbufs * sizeof(bufs[0])); - req->nbufs = nbufs; - req->write_index = 0; - stream->write_queue_size += uv__count_bufs(bufs, nbufs); - - /* Append the request to write_queue. */ - QUEUE_INSERT_TAIL(&stream->write_queue, &req->queue); - - /* If the queue was empty when this function began, we should attempt to - * do the write immediately. Otherwise start the write_watcher and wait - * for the fd to become writable. - */ - if (stream->connect_req) { - /* Still connecting, do nothing. */ - } - else if (empty_queue) { - uv__write(stream); - } - else { - /* - * blocking streams should never have anything in the queue. - * if this assert fires then somehow the blocking stream isn't being - * sufficiently flushed in uv__write. - */ - assert(!(stream->flags & UV_STREAM_BLOCKING)); - uv__io_start(stream->loop, &stream->io_watcher, POLLOUT); - uv__stream_osx_interrupt_select(stream); - } - - return 0; -} - - -/* The buffers to be written must remain valid until the callback is called. - * This is not required for the uv_buf_t array. - */ -int uv_write(uv_write_t* req, - uv_stream_t* handle, - const uv_buf_t bufs[], - unsigned int nbufs, - uv_write_cb cb) { - return uv_write2(req, handle, bufs, nbufs, NULL, cb); -} - - -void uv_try_write_cb(uv_write_t* req, int status) { - /* Should not be called */ - abort(); -} - - -int uv_try_write(uv_stream_t* stream, - const uv_buf_t bufs[], - unsigned int nbufs) { - int r; - int has_pollout; - size_t written; - size_t req_size; - uv_write_t req; - - /* Connecting or already writing some data */ - if (stream->connect_req != NULL || stream->write_queue_size != 0) - return -EAGAIN; - - has_pollout = uv__io_active(&stream->io_watcher, POLLOUT); - - r = uv_write(&req, stream, bufs, nbufs, uv_try_write_cb); - if (r != 0) - return r; - - /* Remove not written bytes from write queue size */ - written = uv__count_bufs(bufs, nbufs); - if (req.bufs != NULL) - req_size = uv__write_req_size(&req); - else - req_size = 0; - written -= req_size; - stream->write_queue_size -= req_size; - - /* Unqueue request, regardless of immediateness */ - QUEUE_REMOVE(&req.queue); - uv__req_unregister(stream->loop, &req); - if (req.bufs != req.bufsml) - uv__free(req.bufs); - req.bufs = NULL; - - /* Do not poll for writable, if we wasn't before calling this */ - if (!has_pollout) { - uv__io_stop(stream->loop, &stream->io_watcher, POLLOUT); - uv__stream_osx_interrupt_select(stream); - } - - if (written == 0 && req_size != 0) - return -EAGAIN; - else - return written; -} - - -int uv_read_start(uv_stream_t* stream, - uv_alloc_cb alloc_cb, - uv_read_cb read_cb) { - assert(stream->type == UV_TCP || stream->type == UV_NAMED_PIPE || - stream->type == UV_TTY); - - if (stream->flags & UV_CLOSING) - return -EINVAL; - - /* The UV_STREAM_READING flag is irrelevant of the state of the tcp - it just - * expresses the desired state of the user. - */ - stream->flags |= UV_STREAM_READING; - - /* TODO: try to do the read inline? */ - /* TODO: keep track of tcp state. If we've gotten a EOF then we should - * not start the IO watcher. - */ - assert(uv__stream_fd(stream) >= 0); - assert(alloc_cb); - - stream->read_cb = read_cb; - stream->alloc_cb = alloc_cb; - - uv__io_start(stream->loop, &stream->io_watcher, POLLIN); - uv__handle_start(stream); - uv__stream_osx_interrupt_select(stream); - - return 0; -} - - -int uv_read_stop(uv_stream_t* stream) { - if (!(stream->flags & UV_STREAM_READING)) - return 0; - - stream->flags &= ~UV_STREAM_READING; - uv__io_stop(stream->loop, &stream->io_watcher, POLLIN); - if (!uv__io_active(&stream->io_watcher, POLLOUT)) - uv__handle_stop(stream); - uv__stream_osx_interrupt_select(stream); - - stream->read_cb = NULL; - stream->alloc_cb = NULL; - return 0; -} - - -int uv_is_readable(const uv_stream_t* stream) { - return !!(stream->flags & UV_STREAM_READABLE); -} - - -int uv_is_writable(const uv_stream_t* stream) { - return !!(stream->flags & UV_STREAM_WRITABLE); -} - - -#if defined(__APPLE__) -int uv___stream_fd(const uv_stream_t* handle) { - const uv__stream_select_t* s; - - assert(handle->type == UV_TCP || - handle->type == UV_TTY || - handle->type == UV_NAMED_PIPE); - - s = handle->select; - if (s != NULL) - return s->fd; - - return handle->io_watcher.fd; -} -#endif /* defined(__APPLE__) */ - - -void uv__stream_close(uv_stream_t* handle) { - unsigned int i; - uv__stream_queued_fds_t* queued_fds; - -#if defined(__APPLE__) - /* Terminate select loop first */ - if (handle->select != NULL) { - uv__stream_select_t* s; - - s = handle->select; - - uv_sem_post(&s->close_sem); - uv_sem_post(&s->async_sem); - uv__stream_osx_interrupt_select(handle); - uv_thread_join(&s->thread); - uv_sem_destroy(&s->close_sem); - uv_sem_destroy(&s->async_sem); - uv__close(s->fake_fd); - uv__close(s->int_fd); - uv_close((uv_handle_t*) &s->async, uv__stream_osx_cb_close); - - handle->select = NULL; - } -#endif /* defined(__APPLE__) */ - - uv__io_close(handle->loop, &handle->io_watcher); - uv_read_stop(handle); - uv__handle_stop(handle); - - if (handle->io_watcher.fd != -1) { - /* Don't close stdio file descriptors. Nothing good comes from it. */ - if (handle->io_watcher.fd > STDERR_FILENO) - uv__close(handle->io_watcher.fd); - handle->io_watcher.fd = -1; - } - - if (handle->accepted_fd != -1) { - uv__close(handle->accepted_fd); - handle->accepted_fd = -1; - } - - /* Close all queued fds */ - if (handle->queued_fds != NULL) { - queued_fds = handle->queued_fds; - for (i = 0; i < queued_fds->offset; i++) - uv__close(queued_fds->fds[i]); - uv__free(handle->queued_fds); - handle->queued_fds = NULL; - } - - assert(!uv__io_active(&handle->io_watcher, POLLIN | POLLOUT)); -} - - -int uv_stream_set_blocking(uv_stream_t* handle, int blocking) { - /* Don't need to check the file descriptor, uv__nonblock() - * will fail with EBADF if it's not valid. - */ - return uv__nonblock(uv__stream_fd(handle), !blocking); -} diff --git a/vendor/libuv/src/unix/sunos.c b/vendor/libuv/src/unix/sunos.c deleted file mode 100644 index a43f7f1b1..000000000 --- a/vendor/libuv/src/unix/sunos.c +++ /dev/null @@ -1,822 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "internal.h" - -#include -#include -#include -#include -#include -#include - -#ifndef SUNOS_NO_IFADDRS -# include -#endif -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include - -#define PORT_FIRED 0x69 -#define PORT_UNUSED 0x0 -#define PORT_LOADED 0x99 -#define PORT_DELETED -1 - -#if (!defined(_LP64)) && (_FILE_OFFSET_BITS - 0 == 64) -#define PROCFS_FILE_OFFSET_BITS_HACK 1 -#undef _FILE_OFFSET_BITS -#else -#define PROCFS_FILE_OFFSET_BITS_HACK 0 -#endif - -#include - -#if (PROCFS_FILE_OFFSET_BITS_HACK - 0 == 1) -#define _FILE_OFFSET_BITS 64 -#endif - - -int uv__platform_loop_init(uv_loop_t* loop) { - int err; - int fd; - - loop->fs_fd = -1; - loop->backend_fd = -1; - - fd = port_create(); - if (fd == -1) - return -errno; - - err = uv__cloexec(fd, 1); - if (err) { - uv__close(fd); - return err; - } - loop->backend_fd = fd; - - return 0; -} - - -void uv__platform_loop_delete(uv_loop_t* loop) { - if (loop->fs_fd != -1) { - uv__close(loop->fs_fd); - loop->fs_fd = -1; - } - - if (loop->backend_fd != -1) { - uv__close(loop->backend_fd); - loop->backend_fd = -1; - } -} - - -void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) { - struct port_event* events; - uintptr_t i; - uintptr_t nfds; - - assert(loop->watchers != NULL); - - events = (struct port_event*) loop->watchers[loop->nwatchers]; - nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1]; - if (events == NULL) - return; - - /* Invalidate events with same file descriptor */ - for (i = 0; i < nfds; i++) - if ((int) events[i].portev_object == fd) - events[i].portev_object = -1; -} - - -int uv__io_check_fd(uv_loop_t* loop, int fd) { - if (port_associate(loop->backend_fd, PORT_SOURCE_FD, fd, POLLIN, 0)) - return -errno; - - if (port_dissociate(loop->backend_fd, PORT_SOURCE_FD, fd)) - abort(); - - return 0; -} - - -void uv__io_poll(uv_loop_t* loop, int timeout) { - struct port_event events[1024]; - struct port_event* pe; - struct timespec spec; - QUEUE* q; - uv__io_t* w; - sigset_t* pset; - sigset_t set; - uint64_t base; - uint64_t diff; - unsigned int nfds; - unsigned int i; - int saved_errno; - int have_signals; - int nevents; - int count; - int err; - int fd; - - if (loop->nfds == 0) { - assert(QUEUE_EMPTY(&loop->watcher_queue)); - return; - } - - while (!QUEUE_EMPTY(&loop->watcher_queue)) { - q = QUEUE_HEAD(&loop->watcher_queue); - QUEUE_REMOVE(q); - QUEUE_INIT(q); - - w = QUEUE_DATA(q, uv__io_t, watcher_queue); - assert(w->pevents != 0); - - if (port_associate(loop->backend_fd, PORT_SOURCE_FD, w->fd, w->pevents, 0)) - abort(); - - w->events = w->pevents; - } - - pset = NULL; - if (loop->flags & UV_LOOP_BLOCK_SIGPROF) { - pset = &set; - sigemptyset(pset); - sigaddset(pset, SIGPROF); - } - - assert(timeout >= -1); - base = loop->time; - count = 48; /* Benchmarks suggest this gives the best throughput. */ - - for (;;) { - if (timeout != -1) { - spec.tv_sec = timeout / 1000; - spec.tv_nsec = (timeout % 1000) * 1000000; - } - - /* Work around a kernel bug where nfds is not updated. */ - events[0].portev_source = 0; - - nfds = 1; - saved_errno = 0; - - if (pset != NULL) - pthread_sigmask(SIG_BLOCK, pset, NULL); - - err = port_getn(loop->backend_fd, - events, - ARRAY_SIZE(events), - &nfds, - timeout == -1 ? NULL : &spec); - - if (pset != NULL) - pthread_sigmask(SIG_UNBLOCK, pset, NULL); - - if (err) { - /* Work around another kernel bug: port_getn() may return events even - * on error. - */ - if (errno == EINTR || errno == ETIME) - saved_errno = errno; - else - abort(); - } - - /* Update loop->time unconditionally. It's tempting to skip the update when - * timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the - * operating system didn't reschedule our process while in the syscall. - */ - SAVE_ERRNO(uv__update_time(loop)); - - if (events[0].portev_source == 0) { - if (timeout == 0) - return; - - if (timeout == -1) - continue; - - goto update_timeout; - } - - if (nfds == 0) { - assert(timeout != -1); - return; - } - - have_signals = 0; - nevents = 0; - - assert(loop->watchers != NULL); - loop->watchers[loop->nwatchers] = (void*) events; - loop->watchers[loop->nwatchers + 1] = (void*) (uintptr_t) nfds; - for (i = 0; i < nfds; i++) { - pe = events + i; - fd = pe->portev_object; - - /* Skip invalidated events, see uv__platform_invalidate_fd */ - if (fd == -1) - continue; - - assert(fd >= 0); - assert((unsigned) fd < loop->nwatchers); - - w = loop->watchers[fd]; - - /* File descriptor that we've stopped watching, ignore. */ - if (w == NULL) - continue; - - /* Run signal watchers last. This also affects child process watchers - * because those are implemented in terms of signal watchers. - */ - if (w == &loop->signal_io_watcher) - have_signals = 1; - else - w->cb(loop, w, pe->portev_events); - - nevents++; - - if (w != loop->watchers[fd]) - continue; /* Disabled by callback. */ - - /* Events Ports operates in oneshot mode, rearm timer on next run. */ - if (w->pevents != 0 && QUEUE_EMPTY(&w->watcher_queue)) - QUEUE_INSERT_TAIL(&loop->watcher_queue, &w->watcher_queue); - } - - if (have_signals != 0) - loop->signal_io_watcher.cb(loop, &loop->signal_io_watcher, POLLIN); - - loop->watchers[loop->nwatchers] = NULL; - loop->watchers[loop->nwatchers + 1] = NULL; - - if (have_signals != 0) - return; /* Event loop should cycle now so don't poll again. */ - - if (nevents != 0) { - if (nfds == ARRAY_SIZE(events) && --count != 0) { - /* Poll for more events but don't block this time. */ - timeout = 0; - continue; - } - return; - } - - if (saved_errno == ETIME) { - assert(timeout != -1); - return; - } - - if (timeout == 0) - return; - - if (timeout == -1) - continue; - -update_timeout: - assert(timeout > 0); - - diff = loop->time - base; - if (diff >= (uint64_t) timeout) - return; - - timeout -= diff; - } -} - - -uint64_t uv__hrtime(uv_clocktype_t type) { - return gethrtime(); -} - - -/* - * We could use a static buffer for the path manipulations that we need outside - * of the function, but this function could be called by multiple consumers and - * we don't want to potentially create a race condition in the use of snprintf. - */ -int uv_exepath(char* buffer, size_t* size) { - ssize_t res; - char buf[128]; - - if (buffer == NULL || size == NULL || *size == 0) - return -EINVAL; - - snprintf(buf, sizeof(buf), "/proc/%lu/path/a.out", (unsigned long) getpid()); - - res = *size - 1; - if (res > 0) - res = readlink(buf, buffer, res); - - if (res == -1) - return -errno; - - buffer[res] = '\0'; - *size = res; - return 0; -} - - -uint64_t uv_get_free_memory(void) { - return (uint64_t) sysconf(_SC_PAGESIZE) * sysconf(_SC_AVPHYS_PAGES); -} - - -uint64_t uv_get_total_memory(void) { - return (uint64_t) sysconf(_SC_PAGESIZE) * sysconf(_SC_PHYS_PAGES); -} - - -void uv_loadavg(double avg[3]) { - (void) getloadavg(avg, 3); -} - - -#if defined(PORT_SOURCE_FILE) - -static int uv__fs_event_rearm(uv_fs_event_t *handle) { - if (handle->fd == -1) - return -EBADF; - - if (port_associate(handle->loop->fs_fd, - PORT_SOURCE_FILE, - (uintptr_t) &handle->fo, - FILE_ATTRIB | FILE_MODIFIED, - handle) == -1) { - return -errno; - } - handle->fd = PORT_LOADED; - - return 0; -} - - -static void uv__fs_event_read(uv_loop_t* loop, - uv__io_t* w, - unsigned int revents) { - uv_fs_event_t *handle = NULL; - timespec_t timeout; - port_event_t pe; - int events; - int r; - - (void) w; - (void) revents; - - do { - uint_t n = 1; - - /* - * Note that our use of port_getn() here (and not port_get()) is deliberate: - * there is a bug in event ports (Sun bug 6456558) whereby a zeroed timeout - * causes port_get() to return success instead of ETIME when there aren't - * actually any events (!); by using port_getn() in lieu of port_get(), - * we can at least workaround the bug by checking for zero returned events - * and treating it as we would ETIME. - */ - do { - memset(&timeout, 0, sizeof timeout); - r = port_getn(loop->fs_fd, &pe, 1, &n, &timeout); - } - while (r == -1 && errno == EINTR); - - if ((r == -1 && errno == ETIME) || n == 0) - break; - - handle = (uv_fs_event_t*) pe.portev_user; - assert((r == 0) && "unexpected port_get() error"); - - events = 0; - if (pe.portev_events & (FILE_ATTRIB | FILE_MODIFIED)) - events |= UV_CHANGE; - if (pe.portev_events & ~(FILE_ATTRIB | FILE_MODIFIED)) - events |= UV_RENAME; - assert(events != 0); - handle->fd = PORT_FIRED; - handle->cb(handle, NULL, events, 0); - - if (handle->fd != PORT_DELETED) { - r = uv__fs_event_rearm(handle); - if (r != 0) - handle->cb(handle, NULL, 0, r); - } - } - while (handle->fd != PORT_DELETED); -} - - -int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) { - uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_EVENT); - return 0; -} - - -int uv_fs_event_start(uv_fs_event_t* handle, - uv_fs_event_cb cb, - const char* path, - unsigned int flags) { - int portfd; - int first_run; - int err; - - if (uv__is_active(handle)) - return -EINVAL; - - first_run = 0; - if (handle->loop->fs_fd == -1) { - portfd = port_create(); - if (portfd == -1) - return -errno; - handle->loop->fs_fd = portfd; - first_run = 1; - } - - uv__handle_start(handle); - handle->path = uv__strdup(path); - handle->fd = PORT_UNUSED; - handle->cb = cb; - - memset(&handle->fo, 0, sizeof handle->fo); - handle->fo.fo_name = handle->path; - err = uv__fs_event_rearm(handle); - if (err != 0) - return err; - - if (first_run) { - uv__io_init(&handle->loop->fs_event_watcher, uv__fs_event_read, portfd); - uv__io_start(handle->loop, &handle->loop->fs_event_watcher, POLLIN); - } - - return 0; -} - - -int uv_fs_event_stop(uv_fs_event_t* handle) { - if (!uv__is_active(handle)) - return 0; - - if (handle->fd == PORT_FIRED || handle->fd == PORT_LOADED) { - port_dissociate(handle->loop->fs_fd, - PORT_SOURCE_FILE, - (uintptr_t) &handle->fo); - } - - handle->fd = PORT_DELETED; - uv__free(handle->path); - handle->path = NULL; - handle->fo.fo_name = NULL; - uv__handle_stop(handle); - - return 0; -} - -void uv__fs_event_close(uv_fs_event_t* handle) { - uv_fs_event_stop(handle); -} - -#else /* !defined(PORT_SOURCE_FILE) */ - -int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) { - return -ENOSYS; -} - - -int uv_fs_event_start(uv_fs_event_t* handle, - uv_fs_event_cb cb, - const char* filename, - unsigned int flags) { - return -ENOSYS; -} - - -int uv_fs_event_stop(uv_fs_event_t* handle) { - return -ENOSYS; -} - - -void uv__fs_event_close(uv_fs_event_t* handle) { - UNREACHABLE(); -} - -#endif /* defined(PORT_SOURCE_FILE) */ - - -char** uv_setup_args(int argc, char** argv) { - return argv; -} - - -int uv_set_process_title(const char* title) { - return 0; -} - - -int uv_get_process_title(char* buffer, size_t size) { - if (buffer == NULL || size == 0) - return -EINVAL; - - buffer[0] = '\0'; - return 0; -} - - -int uv_resident_set_memory(size_t* rss) { - psinfo_t psinfo; - int err; - int fd; - - fd = open("/proc/self/psinfo", O_RDONLY); - if (fd == -1) - return -errno; - - /* FIXME(bnoordhuis) Handle EINTR. */ - err = -EINVAL; - if (read(fd, &psinfo, sizeof(psinfo)) == sizeof(psinfo)) { - *rss = (size_t)psinfo.pr_rssize * 1024; - err = 0; - } - uv__close(fd); - - return err; -} - - -int uv_uptime(double* uptime) { - kstat_ctl_t *kc; - kstat_t *ksp; - kstat_named_t *knp; - - long hz = sysconf(_SC_CLK_TCK); - - kc = kstat_open(); - if (kc == NULL) - return -EPERM; - - ksp = kstat_lookup(kc, (char*) "unix", 0, (char*) "system_misc"); - if (kstat_read(kc, ksp, NULL) == -1) { - *uptime = -1; - } else { - knp = (kstat_named_t*) kstat_data_lookup(ksp, (char*) "clk_intr"); - *uptime = knp->value.ul / hz; - } - kstat_close(kc); - - return 0; -} - - -int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { - int lookup_instance; - kstat_ctl_t *kc; - kstat_t *ksp; - kstat_named_t *knp; - uv_cpu_info_t* cpu_info; - - kc = kstat_open(); - if (kc == NULL) - return -EPERM; - - /* Get count of cpus */ - lookup_instance = 0; - while ((ksp = kstat_lookup(kc, (char*) "cpu_info", lookup_instance, NULL))) { - lookup_instance++; - } - - *cpu_infos = uv__malloc(lookup_instance * sizeof(**cpu_infos)); - if (!(*cpu_infos)) { - kstat_close(kc); - return -ENOMEM; - } - - *count = lookup_instance; - - cpu_info = *cpu_infos; - lookup_instance = 0; - while ((ksp = kstat_lookup(kc, (char*) "cpu_info", lookup_instance, NULL))) { - if (kstat_read(kc, ksp, NULL) == -1) { - cpu_info->speed = 0; - cpu_info->model = NULL; - } else { - knp = kstat_data_lookup(ksp, (char*) "clock_MHz"); - assert(knp->data_type == KSTAT_DATA_INT32 || - knp->data_type == KSTAT_DATA_INT64); - cpu_info->speed = (knp->data_type == KSTAT_DATA_INT32) ? knp->value.i32 - : knp->value.i64; - - knp = kstat_data_lookup(ksp, (char*) "brand"); - assert(knp->data_type == KSTAT_DATA_STRING); - cpu_info->model = uv__strdup(KSTAT_NAMED_STR_PTR(knp)); - } - - lookup_instance++; - cpu_info++; - } - - cpu_info = *cpu_infos; - lookup_instance = 0; - for (;;) { - ksp = kstat_lookup(kc, (char*) "cpu", lookup_instance, (char*) "sys"); - - if (ksp == NULL) - break; - - if (kstat_read(kc, ksp, NULL) == -1) { - cpu_info->cpu_times.user = 0; - cpu_info->cpu_times.nice = 0; - cpu_info->cpu_times.sys = 0; - cpu_info->cpu_times.idle = 0; - cpu_info->cpu_times.irq = 0; - } else { - knp = kstat_data_lookup(ksp, (char*) "cpu_ticks_user"); - assert(knp->data_type == KSTAT_DATA_UINT64); - cpu_info->cpu_times.user = knp->value.ui64; - - knp = kstat_data_lookup(ksp, (char*) "cpu_ticks_kernel"); - assert(knp->data_type == KSTAT_DATA_UINT64); - cpu_info->cpu_times.sys = knp->value.ui64; - - knp = kstat_data_lookup(ksp, (char*) "cpu_ticks_idle"); - assert(knp->data_type == KSTAT_DATA_UINT64); - cpu_info->cpu_times.idle = knp->value.ui64; - - knp = kstat_data_lookup(ksp, (char*) "intr"); - assert(knp->data_type == KSTAT_DATA_UINT64); - cpu_info->cpu_times.irq = knp->value.ui64; - cpu_info->cpu_times.nice = 0; - } - - lookup_instance++; - cpu_info++; - } - - kstat_close(kc); - - return 0; -} - - -void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { - int i; - - for (i = 0; i < count; i++) { - uv__free(cpu_infos[i].model); - } - - uv__free(cpu_infos); -} - -#ifdef SUNOS_NO_IFADDRS -int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { - return -ENOSYS; -} -#else /* SUNOS_NO_IFADDRS */ -/* - * Inspired By: - * https://blogs.oracle.com/paulie/entry/retrieving_mac_address_in_solaris - * http://www.pauliesworld.org/project/getmac.c - */ -static int uv__set_phys_addr(uv_interface_address_t* address, - struct ifaddrs* ent) { - - struct sockaddr_dl* sa_addr; - int sockfd; - int i; - struct arpreq arpreq; - - /* This appears to only work as root */ - sa_addr = (struct sockaddr_dl*)(ent->ifa_addr); - memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr)); - for (i = 0; i < sizeof(address->phys_addr); i++) { - if (address->phys_addr[i] != 0) - return 0; - } - memset(&arpreq, 0, sizeof(arpreq)); - if (address->address.address4.sin_family == AF_INET) { - struct sockaddr_in* sin = ((struct sockaddr_in*)&arpreq.arp_pa); - sin->sin_addr.s_addr = address->address.address4.sin_addr.s_addr; - } else if (address->address.address4.sin_family == AF_INET6) { - struct sockaddr_in6* sin = ((struct sockaddr_in6*)&arpreq.arp_pa); - memcpy(sin->sin6_addr.s6_addr, - address->address.address6.sin6_addr.s6_addr, - sizeof(address->address.address6.sin6_addr.s6_addr)); - } else { - return 0; - } - - sockfd = socket(AF_INET, SOCK_DGRAM, 0); - if (sockfd < 0) - return -errno; - - if (ioctl(sockfd, SIOCGARP, (char*)&arpreq) == -1) { - uv__close(sockfd); - return -errno; - } - memcpy(address->phys_addr, arpreq.arp_ha.sa_data, sizeof(address->phys_addr)); - uv__close(sockfd); - return 0; -} - -int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { - uv_interface_address_t* address; - struct ifaddrs* addrs; - struct ifaddrs* ent; - int i; - - if (getifaddrs(&addrs)) - return -errno; - - *count = 0; - - /* Count the number of interfaces */ - for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)) || - (ent->ifa_addr == NULL) || - (ent->ifa_addr->sa_family == PF_PACKET)) { - continue; - } - - (*count)++; - } - - *addresses = uv__malloc(*count * sizeof(**addresses)); - if (!(*addresses)) { - freeifaddrs(addrs); - return -ENOMEM; - } - - address = *addresses; - - for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING))) - continue; - - if (ent->ifa_addr == NULL) - continue; - - address->name = uv__strdup(ent->ifa_name); - - if (ent->ifa_addr->sa_family == AF_INET6) { - address->address.address6 = *((struct sockaddr_in6*) ent->ifa_addr); - } else { - address->address.address4 = *((struct sockaddr_in*) ent->ifa_addr); - } - - if (ent->ifa_netmask->sa_family == AF_INET6) { - address->netmask.netmask6 = *((struct sockaddr_in6*) ent->ifa_netmask); - } else { - address->netmask.netmask4 = *((struct sockaddr_in*) ent->ifa_netmask); - } - - address->is_internal = !!((ent->ifa_flags & IFF_PRIVATE) || - (ent->ifa_flags & IFF_LOOPBACK)); - - uv__set_phys_addr(address, ent); - address++; - } - - freeifaddrs(addrs); - - return 0; -} -#endif /* SUNOS_NO_IFADDRS */ - -void uv_free_interface_addresses(uv_interface_address_t* addresses, - int count) { - int i; - - for (i = 0; i < count; i++) { - uv__free(addresses[i].name); - } - - uv__free(addresses); -} diff --git a/vendor/libuv/src/unix/tcp.c b/vendor/libuv/src/unix/tcp.c deleted file mode 100644 index c423dcb15..000000000 --- a/vendor/libuv/src/unix/tcp.c +++ /dev/null @@ -1,395 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "internal.h" - -#include -#include -#include -#include - - -static int maybe_new_socket(uv_tcp_t* handle, int domain, int flags) { - int sockfd; - int err; - - if (domain == AF_UNSPEC || uv__stream_fd(handle) != -1) { - handle->flags |= flags; - return 0; - } - - err = uv__socket(domain, SOCK_STREAM, 0); - if (err < 0) - return err; - sockfd = err; - - err = uv__stream_open((uv_stream_t*) handle, sockfd, flags); - if (err) { - uv__close(sockfd); - return err; - } - - return 0; -} - - -int uv_tcp_init_ex(uv_loop_t* loop, uv_tcp_t* tcp, unsigned int flags) { - int domain; - - /* Use the lower 8 bits for the domain */ - domain = flags & 0xFF; - if (domain != AF_INET && domain != AF_INET6 && domain != AF_UNSPEC) - return -EINVAL; - - if (flags & ~0xFF) - return -EINVAL; - - uv__stream_init(loop, (uv_stream_t*)tcp, UV_TCP); - - /* If anything fails beyond this point we need to remove the handle from - * the handle queue, since it was added by uv__handle_init in uv_stream_init. - */ - - if (domain != AF_UNSPEC) { - int err = maybe_new_socket(tcp, domain, 0); - if (err) { - QUEUE_REMOVE(&tcp->handle_queue); - return err; - } - } - - return 0; -} - - -int uv_tcp_init(uv_loop_t* loop, uv_tcp_t* tcp) { - return uv_tcp_init_ex(loop, tcp, AF_UNSPEC); -} - - -int uv__tcp_bind(uv_tcp_t* tcp, - const struct sockaddr* addr, - unsigned int addrlen, - unsigned int flags) { - int err; - int on; - - /* Cannot set IPv6-only mode on non-IPv6 socket. */ - if ((flags & UV_TCP_IPV6ONLY) && addr->sa_family != AF_INET6) - return -EINVAL; - - err = maybe_new_socket(tcp, - addr->sa_family, - UV_STREAM_READABLE | UV_STREAM_WRITABLE); - if (err) - return err; - - on = 1; - if (setsockopt(tcp->io_watcher.fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))) - return -errno; - -#ifdef IPV6_V6ONLY - if (addr->sa_family == AF_INET6) { - on = (flags & UV_TCP_IPV6ONLY) != 0; - if (setsockopt(tcp->io_watcher.fd, - IPPROTO_IPV6, - IPV6_V6ONLY, - &on, - sizeof on) == -1) { -#if defined(__MVS__) - if (errno == EOPNOTSUPP) - return -EINVAL; -#endif - return -errno; - } - } -#endif - - errno = 0; - if (bind(tcp->io_watcher.fd, addr, addrlen) && errno != EADDRINUSE) { - if (errno == EAFNOSUPPORT) - /* OSX, other BSDs and SunoS fail with EAFNOSUPPORT when binding a - * socket created with AF_INET to an AF_INET6 address or vice versa. */ - return -EINVAL; - return -errno; - } - tcp->delayed_error = -errno; - - tcp->flags |= UV_HANDLE_BOUND; - if (addr->sa_family == AF_INET6) - tcp->flags |= UV_HANDLE_IPV6; - - return 0; -} - - -int uv__tcp_connect(uv_connect_t* req, - uv_tcp_t* handle, - const struct sockaddr* addr, - unsigned int addrlen, - uv_connect_cb cb) { - int err; - int r; - - assert(handle->type == UV_TCP); - - if (handle->connect_req != NULL) - return -EALREADY; /* FIXME(bnoordhuis) -EINVAL or maybe -EBUSY. */ - - err = maybe_new_socket(handle, - addr->sa_family, - UV_STREAM_READABLE | UV_STREAM_WRITABLE); - if (err) - return err; - - handle->delayed_error = 0; - - do { - errno = 0; - r = connect(uv__stream_fd(handle), addr, addrlen); - } while (r == -1 && errno == EINTR); - - /* We not only check the return value, but also check the errno != 0. - * Because in rare cases connect() will return -1 but the errno - * is 0 (for example, on Android 4.3, OnePlus phone A0001_12_150227) - * and actually the tcp three-way handshake is completed. - */ - if (r == -1 && errno != 0) { - if (errno == EINPROGRESS) - ; /* not an error */ - else if (errno == ECONNREFUSED) - /* If we get a ECONNREFUSED wait until the next tick to report the - * error. Solaris wants to report immediately--other unixes want to - * wait. - */ - handle->delayed_error = -errno; - else - return -errno; - } - - uv__req_init(handle->loop, req, UV_CONNECT); - req->cb = cb; - req->handle = (uv_stream_t*) handle; - QUEUE_INIT(&req->queue); - handle->connect_req = req; - - uv__io_start(handle->loop, &handle->io_watcher, POLLOUT); - - if (handle->delayed_error) - uv__io_feed(handle->loop, &handle->io_watcher); - - return 0; -} - - -int uv_tcp_open(uv_tcp_t* handle, uv_os_sock_t sock) { - int err; - - err = uv__nonblock(sock, 1); - if (err) - return err; - - return uv__stream_open((uv_stream_t*)handle, - sock, - UV_STREAM_READABLE | UV_STREAM_WRITABLE); -} - - -int uv_tcp_getsockname(const uv_tcp_t* handle, - struct sockaddr* name, - int* namelen) { - socklen_t socklen; - - if (handle->delayed_error) - return handle->delayed_error; - - if (uv__stream_fd(handle) < 0) - return -EINVAL; /* FIXME(bnoordhuis) -EBADF */ - - /* sizeof(socklen_t) != sizeof(int) on some systems. */ - socklen = (socklen_t) *namelen; - - if (getsockname(uv__stream_fd(handle), name, &socklen)) - return -errno; - - *namelen = (int) socklen; - return 0; -} - - -int uv_tcp_getpeername(const uv_tcp_t* handle, - struct sockaddr* name, - int* namelen) { - socklen_t socklen; - - if (handle->delayed_error) - return handle->delayed_error; - - if (uv__stream_fd(handle) < 0) - return -EINVAL; /* FIXME(bnoordhuis) -EBADF */ - - /* sizeof(socklen_t) != sizeof(int) on some systems. */ - socklen = (socklen_t) *namelen; - - if (getpeername(uv__stream_fd(handle), name, &socklen)) - return -errno; - - *namelen = (int) socklen; - return 0; -} - - -int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb) { - static int single_accept = -1; - int err; - - if (tcp->delayed_error) - return tcp->delayed_error; - - if (single_accept == -1) { - const char* val = getenv("UV_TCP_SINGLE_ACCEPT"); - single_accept = (val != NULL && atoi(val) != 0); /* Off by default. */ - } - - if (single_accept) - tcp->flags |= UV_TCP_SINGLE_ACCEPT; - - err = maybe_new_socket(tcp, AF_INET, UV_STREAM_READABLE); - if (err) - return err; - -#ifdef __MVS__ - /* on zOS the listen call does not bind automatically - if the socket is unbound. Hence the manual binding to - an arbitrary port is required to be done manually - */ - - if (!(tcp->flags & UV_HANDLE_BOUND)) { - struct sockaddr_storage saddr; - socklen_t slen = sizeof(saddr); - memset(&saddr, 0, sizeof(saddr)); - - if (getsockname(tcp->io_watcher.fd, (struct sockaddr*) &saddr, &slen)) - return -errno; - - if (bind(tcp->io_watcher.fd, (struct sockaddr*) &saddr, slen)) - return -errno; - - tcp->flags |= UV_HANDLE_BOUND; - } -#endif - - if (listen(tcp->io_watcher.fd, backlog)) - return -errno; - - tcp->connection_cb = cb; - tcp->flags |= UV_HANDLE_BOUND; - - /* Start listening for connections. */ - tcp->io_watcher.cb = uv__server_io; - uv__io_start(tcp->loop, &tcp->io_watcher, POLLIN); - - return 0; -} - - -int uv__tcp_nodelay(int fd, int on) { - if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on))) - return -errno; - return 0; -} - - -int uv__tcp_keepalive(int fd, int on, unsigned int delay) { - if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on))) - return -errno; - -#ifdef TCP_KEEPIDLE - if (on && setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &delay, sizeof(delay))) - return -errno; -#endif - - /* Solaris/SmartOS, if you don't support keep-alive, - * then don't advertise it in your system headers... - */ - /* FIXME(bnoordhuis) That's possibly because sizeof(delay) should be 1. */ -#if defined(TCP_KEEPALIVE) && !defined(__sun) - if (on && setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, &delay, sizeof(delay))) - return -errno; -#endif - - return 0; -} - - -int uv_tcp_nodelay(uv_tcp_t* handle, int on) { - int err; - - if (uv__stream_fd(handle) != -1) { - err = uv__tcp_nodelay(uv__stream_fd(handle), on); - if (err) - return err; - } - - if (on) - handle->flags |= UV_TCP_NODELAY; - else - handle->flags &= ~UV_TCP_NODELAY; - - return 0; -} - - -int uv_tcp_keepalive(uv_tcp_t* handle, int on, unsigned int delay) { - int err; - - if (uv__stream_fd(handle) != -1) { - err =uv__tcp_keepalive(uv__stream_fd(handle), on, delay); - if (err) - return err; - } - - if (on) - handle->flags |= UV_TCP_KEEPALIVE; - else - handle->flags &= ~UV_TCP_KEEPALIVE; - - /* TODO Store delay if uv__stream_fd(handle) == -1 but don't want to enlarge - * uv_tcp_t with an int that's almost never used... - */ - - return 0; -} - - -int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable) { - if (enable) - handle->flags &= ~UV_TCP_SINGLE_ACCEPT; - else - handle->flags |= UV_TCP_SINGLE_ACCEPT; - return 0; -} - - -void uv__tcp_close(uv_tcp_t* handle) { - uv__stream_close((uv_stream_t*)handle); -} diff --git a/vendor/libuv/src/unix/thread.c b/vendor/libuv/src/unix/thread.c deleted file mode 100644 index a9b5e4c02..000000000 --- a/vendor/libuv/src/unix/thread.c +++ /dev/null @@ -1,575 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "internal.h" - -#include -#include -#include - -#include -#include /* getrlimit() */ -#include /* getpagesize() */ - -#include - -#ifdef __MVS__ -#include -#include -#endif - -#undef NANOSEC -#define NANOSEC ((uint64_t) 1e9) - - -int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) { - int err; - pthread_attr_t* attr; -#if defined(__APPLE__) - pthread_attr_t attr_storage; - struct rlimit lim; -#endif - - /* On OSX threads other than the main thread are created with a reduced stack - * size by default, adjust it to RLIMIT_STACK. - */ -#if defined(__APPLE__) - if (getrlimit(RLIMIT_STACK, &lim)) - abort(); - - attr = &attr_storage; - if (pthread_attr_init(attr)) - abort(); - - if (lim.rlim_cur != RLIM_INFINITY) { - /* pthread_attr_setstacksize() expects page-aligned values. */ - lim.rlim_cur -= lim.rlim_cur % (rlim_t) getpagesize(); - - if (lim.rlim_cur >= PTHREAD_STACK_MIN) - if (pthread_attr_setstacksize(attr, lim.rlim_cur)) - abort(); - } -#else - attr = NULL; -#endif - - err = pthread_create(tid, attr, (void*(*)(void*)) entry, arg); - - if (attr != NULL) - pthread_attr_destroy(attr); - - return -err; -} - - -uv_thread_t uv_thread_self(void) { - return pthread_self(); -} - -int uv_thread_join(uv_thread_t *tid) { - return -pthread_join(*tid, NULL); -} - - -int uv_thread_equal(const uv_thread_t* t1, const uv_thread_t* t2) { - return pthread_equal(*t1, *t2); -} - - -int uv_mutex_init(uv_mutex_t* mutex) { -#if defined(NDEBUG) || !defined(PTHREAD_MUTEX_ERRORCHECK) - return -pthread_mutex_init(mutex, NULL); -#else - pthread_mutexattr_t attr; - int err; - - if (pthread_mutexattr_init(&attr)) - abort(); - - if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK)) - abort(); - - err = pthread_mutex_init(mutex, &attr); - - if (pthread_mutexattr_destroy(&attr)) - abort(); - - return -err; -#endif -} - - -void uv_mutex_destroy(uv_mutex_t* mutex) { - if (pthread_mutex_destroy(mutex)) - abort(); -} - - -void uv_mutex_lock(uv_mutex_t* mutex) { - if (pthread_mutex_lock(mutex)) - abort(); -} - - -int uv_mutex_trylock(uv_mutex_t* mutex) { - int err; - - err = pthread_mutex_trylock(mutex); - if (err) { - if (err != EBUSY && err != EAGAIN) - abort(); - return -EBUSY; - } - - return 0; -} - - -void uv_mutex_unlock(uv_mutex_t* mutex) { - if (pthread_mutex_unlock(mutex)) - abort(); -} - - -int uv_rwlock_init(uv_rwlock_t* rwlock) { - return -pthread_rwlock_init(rwlock, NULL); -} - - -void uv_rwlock_destroy(uv_rwlock_t* rwlock) { - if (pthread_rwlock_destroy(rwlock)) - abort(); -} - - -void uv_rwlock_rdlock(uv_rwlock_t* rwlock) { - if (pthread_rwlock_rdlock(rwlock)) - abort(); -} - - -int uv_rwlock_tryrdlock(uv_rwlock_t* rwlock) { - int err; - - err = pthread_rwlock_tryrdlock(rwlock); - if (err) { - if (err != EBUSY && err != EAGAIN) - abort(); - return -EBUSY; - } - - return 0; -} - - -void uv_rwlock_rdunlock(uv_rwlock_t* rwlock) { - if (pthread_rwlock_unlock(rwlock)) - abort(); -} - - -void uv_rwlock_wrlock(uv_rwlock_t* rwlock) { - if (pthread_rwlock_wrlock(rwlock)) - abort(); -} - - -int uv_rwlock_trywrlock(uv_rwlock_t* rwlock) { - int err; - - err = pthread_rwlock_trywrlock(rwlock); - if (err) { - if (err != EBUSY && err != EAGAIN) - abort(); - return -EBUSY; - } - - return 0; -} - - -void uv_rwlock_wrunlock(uv_rwlock_t* rwlock) { - if (pthread_rwlock_unlock(rwlock)) - abort(); -} - - -void uv_once(uv_once_t* guard, void (*callback)(void)) { - if (pthread_once(guard, callback)) - abort(); -} - -#if defined(__APPLE__) && defined(__MACH__) - -int uv_sem_init(uv_sem_t* sem, unsigned int value) { - kern_return_t err; - - err = semaphore_create(mach_task_self(), sem, SYNC_POLICY_FIFO, value); - if (err == KERN_SUCCESS) - return 0; - if (err == KERN_INVALID_ARGUMENT) - return -EINVAL; - if (err == KERN_RESOURCE_SHORTAGE) - return -ENOMEM; - - abort(); - return -EINVAL; /* Satisfy the compiler. */ -} - - -void uv_sem_destroy(uv_sem_t* sem) { - if (semaphore_destroy(mach_task_self(), *sem)) - abort(); -} - - -void uv_sem_post(uv_sem_t* sem) { - if (semaphore_signal(*sem)) - abort(); -} - - -void uv_sem_wait(uv_sem_t* sem) { - int r; - - do - r = semaphore_wait(*sem); - while (r == KERN_ABORTED); - - if (r != KERN_SUCCESS) - abort(); -} - - -int uv_sem_trywait(uv_sem_t* sem) { - mach_timespec_t interval; - kern_return_t err; - - interval.tv_sec = 0; - interval.tv_nsec = 0; - - err = semaphore_timedwait(*sem, interval); - if (err == KERN_SUCCESS) - return 0; - if (err == KERN_OPERATION_TIMED_OUT) - return -EAGAIN; - - abort(); - return -EINVAL; /* Satisfy the compiler. */ -} - -#elif defined(__MVS__) - -int uv_sem_init(uv_sem_t* sem, unsigned int value) { - uv_sem_t semid; - struct sembuf buf; - int err; - - buf.sem_num = 0; - buf.sem_op = value; - buf.sem_flg = 0; - - semid = semget(IPC_PRIVATE, 1, S_IRUSR | S_IWUSR); - if (semid == -1) - return -errno; - - if (-1 == semop(semid, &buf, 1)) { - err = errno; - if (-1 == semctl(*sem, 0, IPC_RMID)) - abort(); - return -err; - } - - *sem = semid; - return 0; -} - -void uv_sem_destroy(uv_sem_t* sem) { - if (-1 == semctl(*sem, 0, IPC_RMID)) - abort(); -} - -void uv_sem_post(uv_sem_t* sem) { - struct sembuf buf; - - buf.sem_num = 0; - buf.sem_op = 1; - buf.sem_flg = 0; - - if (-1 == semop(*sem, &buf, 1)) - abort(); -} - -void uv_sem_wait(uv_sem_t* sem) { - struct sembuf buf; - int op_status; - - buf.sem_num = 0; - buf.sem_op = -1; - buf.sem_flg = 0; - - do - op_status = semop(*sem, &buf, 1); - while (op_status == -1 && errno == EINTR); - - if (op_status) - abort(); -} - -int uv_sem_trywait(uv_sem_t* sem) { - struct sembuf buf; - int op_status; - - buf.sem_num = 0; - buf.sem_op = -1; - buf.sem_flg = IPC_NOWAIT; - - do - op_status = semop(*sem, &buf, 1); - while (op_status == -1 && errno == EINTR); - - if (op_status) { - if (errno == EAGAIN) - return -EAGAIN; - abort(); - } - - return 0; -} - -#else /* !(defined(__APPLE__) && defined(__MACH__)) */ - -int uv_sem_init(uv_sem_t* sem, unsigned int value) { - if (sem_init(sem, 0, value)) - return -errno; - return 0; -} - - -void uv_sem_destroy(uv_sem_t* sem) { - if (sem_destroy(sem)) - abort(); -} - - -void uv_sem_post(uv_sem_t* sem) { - if (sem_post(sem)) - abort(); -} - - -void uv_sem_wait(uv_sem_t* sem) { - int r; - - do - r = sem_wait(sem); - while (r == -1 && errno == EINTR); - - if (r) - abort(); -} - - -int uv_sem_trywait(uv_sem_t* sem) { - int r; - - do - r = sem_trywait(sem); - while (r == -1 && errno == EINTR); - - if (r) { - if (errno == EAGAIN) - return -EAGAIN; - abort(); - } - - return 0; -} - -#endif /* defined(__APPLE__) && defined(__MACH__) */ - - -#if defined(__APPLE__) && defined(__MACH__) || defined(__MVS__) - -int uv_cond_init(uv_cond_t* cond) { - return -pthread_cond_init(cond, NULL); -} - -#else /* !(defined(__APPLE__) && defined(__MACH__)) */ - -int uv_cond_init(uv_cond_t* cond) { - pthread_condattr_t attr; - int err; - - err = pthread_condattr_init(&attr); - if (err) - return -err; - -#if !(defined(__ANDROID__) && defined(HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC)) - err = pthread_condattr_setclock(&attr, CLOCK_MONOTONIC); - if (err) - goto error2; -#endif - - err = pthread_cond_init(cond, &attr); - if (err) - goto error2; - - err = pthread_condattr_destroy(&attr); - if (err) - goto error; - - return 0; - -error: - pthread_cond_destroy(cond); -error2: - pthread_condattr_destroy(&attr); - return -err; -} - -#endif /* defined(__APPLE__) && defined(__MACH__) */ - -void uv_cond_destroy(uv_cond_t* cond) { -#if defined(__APPLE__) && defined(__MACH__) - /* It has been reported that destroying condition variables that have been - * signalled but not waited on can sometimes result in application crashes. - * See https://codereview.chromium.org/1323293005. - */ - pthread_mutex_t mutex; - struct timespec ts; - int err; - - if (pthread_mutex_init(&mutex, NULL)) - abort(); - - if (pthread_mutex_lock(&mutex)) - abort(); - - ts.tv_sec = 0; - ts.tv_nsec = 1; - - err = pthread_cond_timedwait_relative_np(cond, &mutex, &ts); - if (err != 0 && err != ETIMEDOUT) - abort(); - - if (pthread_mutex_unlock(&mutex)) - abort(); - - if (pthread_mutex_destroy(&mutex)) - abort(); -#endif /* defined(__APPLE__) && defined(__MACH__) */ - - if (pthread_cond_destroy(cond)) - abort(); -} - -void uv_cond_signal(uv_cond_t* cond) { - if (pthread_cond_signal(cond)) - abort(); -} - -void uv_cond_broadcast(uv_cond_t* cond) { - if (pthread_cond_broadcast(cond)) - abort(); -} - -void uv_cond_wait(uv_cond_t* cond, uv_mutex_t* mutex) { - if (pthread_cond_wait(cond, mutex)) - abort(); -} - - -int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, uint64_t timeout) { - int r; - struct timespec ts; - -#if defined(__APPLE__) && defined(__MACH__) - ts.tv_sec = timeout / NANOSEC; - ts.tv_nsec = timeout % NANOSEC; - r = pthread_cond_timedwait_relative_np(cond, mutex, &ts); -#else - timeout += uv__hrtime(UV_CLOCK_PRECISE); - ts.tv_sec = timeout / NANOSEC; - ts.tv_nsec = timeout % NANOSEC; -#if defined(__ANDROID__) && defined(HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC) - /* - * The bionic pthread implementation doesn't support CLOCK_MONOTONIC, - * but has this alternative function instead. - */ - r = pthread_cond_timedwait_monotonic_np(cond, mutex, &ts); -#else - r = pthread_cond_timedwait(cond, mutex, &ts); -#endif /* __ANDROID__ */ -#endif - - - if (r == 0) - return 0; - - if (r == ETIMEDOUT) - return -ETIMEDOUT; - - abort(); - return -EINVAL; /* Satisfy the compiler. */ -} - - -int uv_barrier_init(uv_barrier_t* barrier, unsigned int count) { - return -pthread_barrier_init(barrier, NULL, count); -} - - -void uv_barrier_destroy(uv_barrier_t* barrier) { - if (pthread_barrier_destroy(barrier)) - abort(); -} - - -int uv_barrier_wait(uv_barrier_t* barrier) { - int r = pthread_barrier_wait(barrier); - if (r && r != PTHREAD_BARRIER_SERIAL_THREAD) - abort(); - return r == PTHREAD_BARRIER_SERIAL_THREAD; -} - - -int uv_key_create(uv_key_t* key) { - return -pthread_key_create(key, NULL); -} - - -void uv_key_delete(uv_key_t* key) { - if (pthread_key_delete(*key)) - abort(); -} - - -void* uv_key_get(uv_key_t* key) { - return pthread_getspecific(*key); -} - - -void uv_key_set(uv_key_t* key, void* value) { - if (pthread_setspecific(*key, value)) - abort(); -} diff --git a/vendor/libuv/src/unix/timer.c b/vendor/libuv/src/unix/timer.c deleted file mode 100644 index f46bdf4bf..000000000 --- a/vendor/libuv/src/unix/timer.c +++ /dev/null @@ -1,172 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "internal.h" -#include "heap-inl.h" - -#include -#include - - -static int timer_less_than(const struct heap_node* ha, - const struct heap_node* hb) { - const uv_timer_t* a; - const uv_timer_t* b; - - a = container_of(ha, uv_timer_t, heap_node); - b = container_of(hb, uv_timer_t, heap_node); - - if (a->timeout < b->timeout) - return 1; - if (b->timeout < a->timeout) - return 0; - - /* Compare start_id when both have the same timeout. start_id is - * allocated with loop->timer_counter in uv_timer_start(). - */ - if (a->start_id < b->start_id) - return 1; - if (b->start_id < a->start_id) - return 0; - - return 0; -} - - -int uv_timer_init(uv_loop_t* loop, uv_timer_t* handle) { - uv__handle_init(loop, (uv_handle_t*)handle, UV_TIMER); - handle->timer_cb = NULL; - handle->repeat = 0; - return 0; -} - - -int uv_timer_start(uv_timer_t* handle, - uv_timer_cb cb, - uint64_t timeout, - uint64_t repeat) { - uint64_t clamped_timeout; - - if (cb == NULL) - return -EINVAL; - - if (uv__is_active(handle)) - uv_timer_stop(handle); - - clamped_timeout = handle->loop->time + timeout; - if (clamped_timeout < timeout) - clamped_timeout = (uint64_t) -1; - - handle->timer_cb = cb; - handle->timeout = clamped_timeout; - handle->repeat = repeat; - /* start_id is the second index to be compared in uv__timer_cmp() */ - handle->start_id = handle->loop->timer_counter++; - - heap_insert((struct heap*) &handle->loop->timer_heap, - (struct heap_node*) &handle->heap_node, - timer_less_than); - uv__handle_start(handle); - - return 0; -} - - -int uv_timer_stop(uv_timer_t* handle) { - if (!uv__is_active(handle)) - return 0; - - heap_remove((struct heap*) &handle->loop->timer_heap, - (struct heap_node*) &handle->heap_node, - timer_less_than); - uv__handle_stop(handle); - - return 0; -} - - -int uv_timer_again(uv_timer_t* handle) { - if (handle->timer_cb == NULL) - return -EINVAL; - - if (handle->repeat) { - uv_timer_stop(handle); - uv_timer_start(handle, handle->timer_cb, handle->repeat, handle->repeat); - } - - return 0; -} - - -void uv_timer_set_repeat(uv_timer_t* handle, uint64_t repeat) { - handle->repeat = repeat; -} - - -uint64_t uv_timer_get_repeat(const uv_timer_t* handle) { - return handle->repeat; -} - - -int uv__next_timeout(const uv_loop_t* loop) { - const struct heap_node* heap_node; - const uv_timer_t* handle; - uint64_t diff; - - heap_node = heap_min((const struct heap*) &loop->timer_heap); - if (heap_node == NULL) - return -1; /* block indefinitely */ - - handle = container_of(heap_node, uv_timer_t, heap_node); - if (handle->timeout <= loop->time) - return 0; - - diff = handle->timeout - loop->time; - if (diff > INT_MAX) - diff = INT_MAX; - - return diff; -} - - -void uv__run_timers(uv_loop_t* loop) { - struct heap_node* heap_node; - uv_timer_t* handle; - - for (;;) { - heap_node = heap_min((struct heap*) &loop->timer_heap); - if (heap_node == NULL) - break; - - handle = container_of(heap_node, uv_timer_t, heap_node); - if (handle->timeout > loop->time) - break; - - uv_timer_stop(handle); - uv_timer_again(handle); - handle->timer_cb(handle); - } -} - - -void uv__timer_close(uv_timer_t* handle) { - uv_timer_stop(handle); -} diff --git a/vendor/libuv/src/unix/tty.c b/vendor/libuv/src/unix/tty.c deleted file mode 100644 index b2d37f4c2..000000000 --- a/vendor/libuv/src/unix/tty.c +++ /dev/null @@ -1,336 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "internal.h" -#include "spinlock.h" - -#include -#include -#include -#include -#include -#include - -#if defined(__MVS__) && !defined(IMAXBEL) -#define IMAXBEL 0 -#endif - -static int orig_termios_fd = -1; -static struct termios orig_termios; -static uv_spinlock_t termios_spinlock = UV_SPINLOCK_INITIALIZER; - -static int uv__tty_is_slave(const int fd) { - int result; -#if defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) - int dummy; - - result = ioctl(fd, TIOCGPTN, &dummy) != 0; -#elif defined(__APPLE__) - char dummy[256]; - - result = ioctl(fd, TIOCPTYGNAME, &dummy) != 0; -#else - /* Fallback to ptsname - */ - result = ptsname(fd) == NULL; -#endif - return result; -} - -int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) { - uv_handle_type type; - int flags; - int newfd; - int r; - int saved_flags; - char path[256]; - - /* File descriptors that refer to files cannot be monitored with epoll. - * That restriction also applies to character devices like /dev/random - * (but obviously not /dev/tty.) - */ - type = uv_guess_handle(fd); - if (type == UV_FILE || type == UV_UNKNOWN_HANDLE) - return -EINVAL; - - flags = 0; - newfd = -1; - - /* Reopen the file descriptor when it refers to a tty. This lets us put the - * tty in non-blocking mode without affecting other processes that share it - * with us. - * - * Example: `node | cat` - if we put our fd 0 in non-blocking mode, it also - * affects fd 1 of `cat` because both file descriptors refer to the same - * struct file in the kernel. When we reopen our fd 0, it points to a - * different struct file, hence changing its properties doesn't affect - * other processes. - */ - if (type == UV_TTY) { - /* Reopening a pty in master mode won't work either because the reopened - * pty will be in slave mode (*BSD) or reopening will allocate a new - * master/slave pair (Linux). Therefore check if the fd points to a - * slave device. - */ - if (uv__tty_is_slave(fd) && ttyname_r(fd, path, sizeof(path)) == 0) - r = uv__open_cloexec(path, O_RDWR); - else - r = -1; - - if (r < 0) { - /* fallback to using blocking writes */ - if (!readable) - flags |= UV_STREAM_BLOCKING; - goto skip; - } - - newfd = r; - - r = uv__dup2_cloexec(newfd, fd); - if (r < 0 && r != -EINVAL) { - /* EINVAL means newfd == fd which could conceivably happen if another - * thread called close(fd) between our calls to isatty() and open(). - * That's a rather unlikely event but let's handle it anyway. - */ - uv__close(newfd); - return r; - } - - fd = newfd; - } - -#if defined(__APPLE__) - /* Save the fd flags in case we need to restore them due to an error. */ - do - saved_flags = fcntl(fd, F_GETFL); - while (saved_flags == -1 && errno == EINTR); - - if (saved_flags == -1) { - if (newfd != -1) - uv__close(newfd); - return -errno; - } -#endif - - /* Pacify the compiler. */ - (void) &saved_flags; - -skip: - uv__stream_init(loop, (uv_stream_t*) tty, UV_TTY); - - /* If anything fails beyond this point we need to remove the handle from - * the handle queue, since it was added by uv__handle_init in uv_stream_init. - */ - - if (!(flags & UV_STREAM_BLOCKING)) - uv__nonblock(fd, 1); - -#if defined(__APPLE__) - r = uv__stream_try_select((uv_stream_t*) tty, &fd); - if (r) { - int rc = r; - if (newfd != -1) - uv__close(newfd); - QUEUE_REMOVE(&tty->handle_queue); - do - r = fcntl(fd, F_SETFL, saved_flags); - while (r == -1 && errno == EINTR); - return rc; - } -#endif - - if (readable) - flags |= UV_STREAM_READABLE; - else - flags |= UV_STREAM_WRITABLE; - - uv__stream_open((uv_stream_t*) tty, fd, flags); - tty->mode = UV_TTY_MODE_NORMAL; - - return 0; -} - -static void uv__tty_make_raw(struct termios* tio) { - assert(tio != NULL); - -#if defined __sun || defined __MVS__ - /* - * This implementation of cfmakeraw for Solaris and derivatives is taken from - * http://www.perkin.org.uk/posts/solaris-portability-cfmakeraw.html. - */ - tio->c_iflag &= ~(IMAXBEL | IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | - IGNCR | ICRNL | IXON); - tio->c_oflag &= ~OPOST; - tio->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); - tio->c_cflag &= ~(CSIZE | PARENB); - tio->c_cflag |= CS8; -#else - cfmakeraw(tio); -#endif /* #ifdef __sun */ -} - -int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) { - struct termios tmp; - int fd; - - if (tty->mode == (int) mode) - return 0; - - fd = uv__stream_fd(tty); - if (tty->mode == UV_TTY_MODE_NORMAL && mode != UV_TTY_MODE_NORMAL) { - if (tcgetattr(fd, &tty->orig_termios)) - return -errno; - - /* This is used for uv_tty_reset_mode() */ - uv_spinlock_lock(&termios_spinlock); - if (orig_termios_fd == -1) { - orig_termios = tty->orig_termios; - orig_termios_fd = fd; - } - uv_spinlock_unlock(&termios_spinlock); - } - - tmp = tty->orig_termios; - switch (mode) { - case UV_TTY_MODE_NORMAL: - break; - case UV_TTY_MODE_RAW: - tmp.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); - tmp.c_oflag |= (ONLCR); - tmp.c_cflag |= (CS8); - tmp.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG); - tmp.c_cc[VMIN] = 1; - tmp.c_cc[VTIME] = 0; - break; - case UV_TTY_MODE_IO: - uv__tty_make_raw(&tmp); - break; - } - - /* Apply changes after draining */ - if (tcsetattr(fd, TCSADRAIN, &tmp)) - return -errno; - - tty->mode = mode; - return 0; -} - - -int uv_tty_get_winsize(uv_tty_t* tty, int* width, int* height) { - struct winsize ws; - int err; - - do - err = ioctl(uv__stream_fd(tty), TIOCGWINSZ, &ws); - while (err == -1 && errno == EINTR); - - if (err == -1) - return -errno; - - *width = ws.ws_col; - *height = ws.ws_row; - - return 0; -} - - -uv_handle_type uv_guess_handle(uv_file file) { - struct sockaddr sa; - struct stat s; - socklen_t len; - int type; - - if (file < 0) - return UV_UNKNOWN_HANDLE; - - if (isatty(file)) - return UV_TTY; - - if (fstat(file, &s)) - return UV_UNKNOWN_HANDLE; - - if (S_ISREG(s.st_mode)) - return UV_FILE; - - if (S_ISCHR(s.st_mode)) - return UV_FILE; /* XXX UV_NAMED_PIPE? */ - - if (S_ISFIFO(s.st_mode)) - return UV_NAMED_PIPE; - - if (!S_ISSOCK(s.st_mode)) - return UV_UNKNOWN_HANDLE; - - len = sizeof(type); - if (getsockopt(file, SOL_SOCKET, SO_TYPE, &type, &len)) - return UV_UNKNOWN_HANDLE; - - len = sizeof(sa); - if (getsockname(file, &sa, &len)) - return UV_UNKNOWN_HANDLE; - - if (type == SOCK_DGRAM) - if (sa.sa_family == AF_INET || sa.sa_family == AF_INET6) - return UV_UDP; - - if (type == SOCK_STREAM) { -#if defined(_AIX) || defined(__DragonFly__) - /* on AIX/DragonFly the getsockname call returns an empty sa structure - * for sockets of type AF_UNIX. For all other types it will - * return a properly filled in structure. - */ - if (len == 0) - return UV_NAMED_PIPE; -#endif /* defined(_AIX) || defined(__DragonFly__) */ - - if (sa.sa_family == AF_INET || sa.sa_family == AF_INET6) - return UV_TCP; - if (sa.sa_family == AF_UNIX) - return UV_NAMED_PIPE; - } - - return UV_UNKNOWN_HANDLE; -} - - -/* This function is async signal-safe, meaning that it's safe to call from - * inside a signal handler _unless_ execution was inside uv_tty_set_mode()'s - * critical section when the signal was raised. - */ -int uv_tty_reset_mode(void) { - int saved_errno; - int err; - - saved_errno = errno; - if (!uv_spinlock_trylock(&termios_spinlock)) - return -EBUSY; /* In uv_tty_set_mode(). */ - - err = 0; - if (orig_termios_fd != -1) - if (tcsetattr(orig_termios_fd, TCSANOW, &orig_termios)) - err = -errno; - - uv_spinlock_unlock(&termios_spinlock); - errno = saved_errno; - - return err; -} diff --git a/vendor/libuv/src/unix/udp.c b/vendor/libuv/src/unix/udp.c deleted file mode 100644 index 1cd492578..000000000 --- a/vendor/libuv/src/unix/udp.c +++ /dev/null @@ -1,895 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "internal.h" - -#include -#include -#include -#include -#include -#if defined(__MVS__) -#include -#endif - -#if defined(IPV6_JOIN_GROUP) && !defined(IPV6_ADD_MEMBERSHIP) -# define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP -#endif - -#if defined(IPV6_LEAVE_GROUP) && !defined(IPV6_DROP_MEMBERSHIP) -# define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP -#endif - - -static void uv__udp_run_completed(uv_udp_t* handle); -static void uv__udp_io(uv_loop_t* loop, uv__io_t* w, unsigned int revents); -static void uv__udp_recvmsg(uv_udp_t* handle); -static void uv__udp_sendmsg(uv_udp_t* handle); -static int uv__udp_maybe_deferred_bind(uv_udp_t* handle, - int domain, - unsigned int flags); - - -void uv__udp_close(uv_udp_t* handle) { - uv__io_close(handle->loop, &handle->io_watcher); - uv__handle_stop(handle); - - if (handle->io_watcher.fd != -1) { - uv__close(handle->io_watcher.fd); - handle->io_watcher.fd = -1; - } -} - - -void uv__udp_finish_close(uv_udp_t* handle) { - uv_udp_send_t* req; - QUEUE* q; - - assert(!uv__io_active(&handle->io_watcher, POLLIN | POLLOUT)); - assert(handle->io_watcher.fd == -1); - - while (!QUEUE_EMPTY(&handle->write_queue)) { - q = QUEUE_HEAD(&handle->write_queue); - QUEUE_REMOVE(q); - - req = QUEUE_DATA(q, uv_udp_send_t, queue); - req->status = -ECANCELED; - QUEUE_INSERT_TAIL(&handle->write_completed_queue, &req->queue); - } - - uv__udp_run_completed(handle); - - assert(handle->send_queue_size == 0); - assert(handle->send_queue_count == 0); - - /* Now tear down the handle. */ - handle->recv_cb = NULL; - handle->alloc_cb = NULL; - /* but _do not_ touch close_cb */ -} - - -static void uv__udp_run_completed(uv_udp_t* handle) { - uv_udp_send_t* req; - QUEUE* q; - - assert(!(handle->flags & UV_UDP_PROCESSING)); - handle->flags |= UV_UDP_PROCESSING; - - while (!QUEUE_EMPTY(&handle->write_completed_queue)) { - q = QUEUE_HEAD(&handle->write_completed_queue); - QUEUE_REMOVE(q); - - req = QUEUE_DATA(q, uv_udp_send_t, queue); - uv__req_unregister(handle->loop, req); - - handle->send_queue_size -= uv__count_bufs(req->bufs, req->nbufs); - handle->send_queue_count--; - - if (req->bufs != req->bufsml) - uv__free(req->bufs); - req->bufs = NULL; - - if (req->send_cb == NULL) - continue; - - /* req->status >= 0 == bytes written - * req->status < 0 == errno - */ - if (req->status >= 0) - req->send_cb(req, 0); - else - req->send_cb(req, req->status); - } - - if (QUEUE_EMPTY(&handle->write_queue)) { - /* Pending queue and completion queue empty, stop watcher. */ - uv__io_stop(handle->loop, &handle->io_watcher, POLLOUT); - if (!uv__io_active(&handle->io_watcher, POLLIN)) - uv__handle_stop(handle); - } - - handle->flags &= ~UV_UDP_PROCESSING; -} - - -static void uv__udp_io(uv_loop_t* loop, uv__io_t* w, unsigned int revents) { - uv_udp_t* handle; - - handle = container_of(w, uv_udp_t, io_watcher); - assert(handle->type == UV_UDP); - - if (revents & POLLIN) - uv__udp_recvmsg(handle); - - if (revents & POLLOUT) { - uv__udp_sendmsg(handle); - uv__udp_run_completed(handle); - } -} - - -static void uv__udp_recvmsg(uv_udp_t* handle) { - struct sockaddr_storage peer; - struct msghdr h; - ssize_t nread; - uv_buf_t buf; - int flags; - int count; - - assert(handle->recv_cb != NULL); - assert(handle->alloc_cb != NULL); - - /* Prevent loop starvation when the data comes in as fast as (or faster than) - * we can read it. XXX Need to rearm fd if we switch to edge-triggered I/O. - */ - count = 32; - - memset(&h, 0, sizeof(h)); - h.msg_name = &peer; - - do { - buf = uv_buf_init(NULL, 0); - handle->alloc_cb((uv_handle_t*) handle, 64 * 1024, &buf); - if (buf.base == NULL || buf.len == 0) { - handle->recv_cb(handle, UV_ENOBUFS, &buf, NULL, 0); - return; - } - assert(buf.base != NULL); - - h.msg_namelen = sizeof(peer); - h.msg_iov = (void*) &buf; - h.msg_iovlen = 1; - - do { - nread = recvmsg(handle->io_watcher.fd, &h, 0); - } - while (nread == -1 && errno == EINTR); - - if (nread == -1) { - if (errno == EAGAIN || errno == EWOULDBLOCK) - handle->recv_cb(handle, 0, &buf, NULL, 0); - else - handle->recv_cb(handle, -errno, &buf, NULL, 0); - } - else { - const struct sockaddr *addr; - if (h.msg_namelen == 0) - addr = NULL; - else - addr = (const struct sockaddr*) &peer; - - flags = 0; - if (h.msg_flags & MSG_TRUNC) - flags |= UV_UDP_PARTIAL; - - handle->recv_cb(handle, nread, &buf, addr, flags); - } - } - /* recv_cb callback may decide to pause or close the handle */ - while (nread != -1 - && count-- > 0 - && handle->io_watcher.fd != -1 - && handle->recv_cb != NULL); -} - - -static void uv__udp_sendmsg(uv_udp_t* handle) { - uv_udp_send_t* req; - QUEUE* q; - struct msghdr h; - ssize_t size; - - while (!QUEUE_EMPTY(&handle->write_queue)) { - q = QUEUE_HEAD(&handle->write_queue); - assert(q != NULL); - - req = QUEUE_DATA(q, uv_udp_send_t, queue); - assert(req != NULL); - - memset(&h, 0, sizeof h); - h.msg_name = &req->addr; - h.msg_namelen = (req->addr.ss_family == AF_INET6 ? - sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)); - h.msg_iov = (struct iovec*) req->bufs; - h.msg_iovlen = req->nbufs; - - do { - size = sendmsg(handle->io_watcher.fd, &h, 0); - } while (size == -1 && errno == EINTR); - - if (size == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) - break; - - req->status = (size == -1 ? -errno : size); - - /* Sending a datagram is an atomic operation: either all data - * is written or nothing is (and EMSGSIZE is raised). That is - * why we don't handle partial writes. Just pop the request - * off the write queue and onto the completed queue, done. - */ - QUEUE_REMOVE(&req->queue); - QUEUE_INSERT_TAIL(&handle->write_completed_queue, &req->queue); - uv__io_feed(handle->loop, &handle->io_watcher); - } -} - - -/* On the BSDs, SO_REUSEPORT implies SO_REUSEADDR but with some additional - * refinements for programs that use multicast. - * - * Linux as of 3.9 has a SO_REUSEPORT socket option but with semantics that - * are different from the BSDs: it _shares_ the port rather than steal it - * from the current listener. While useful, it's not something we can emulate - * on other platforms so we don't enable it. - */ -static int uv__set_reuse(int fd) { - int yes; - -#if defined(SO_REUSEPORT) && !defined(__linux__) - yes = 1; - if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof(yes))) - return -errno; -#else - yes = 1; - if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes))) - return -errno; -#endif - - return 0; -} - - -int uv__udp_bind(uv_udp_t* handle, - const struct sockaddr* addr, - unsigned int addrlen, - unsigned int flags) { - int err; - int yes; - int fd; - - /* Check for bad flags. */ - if (flags & ~(UV_UDP_IPV6ONLY | UV_UDP_REUSEADDR)) - return -EINVAL; - - /* Cannot set IPv6-only mode on non-IPv6 socket. */ - if ((flags & UV_UDP_IPV6ONLY) && addr->sa_family != AF_INET6) - return -EINVAL; - - fd = handle->io_watcher.fd; - if (fd == -1) { - err = uv__socket(addr->sa_family, SOCK_DGRAM, 0); - if (err < 0) - return err; - fd = err; - handle->io_watcher.fd = fd; - } - - if (flags & UV_UDP_REUSEADDR) { - err = uv__set_reuse(fd); - if (err) - goto out; - } - - if (flags & UV_UDP_IPV6ONLY) { -#ifdef IPV6_V6ONLY - yes = 1; - if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &yes, sizeof yes) == -1) { - err = -errno; - goto out; - } -#else - err = -ENOTSUP; - goto out; -#endif - } - - if (bind(fd, addr, addrlen)) { - err = -errno; - if (errno == EAFNOSUPPORT) - /* OSX, other BSDs and SunoS fail with EAFNOSUPPORT when binding a - * socket created with AF_INET to an AF_INET6 address or vice versa. */ - err = -EINVAL; - goto out; - } - - if (addr->sa_family == AF_INET6) - handle->flags |= UV_HANDLE_IPV6; - - handle->flags |= UV_HANDLE_BOUND; - - return 0; - -out: - uv__close(handle->io_watcher.fd); - handle->io_watcher.fd = -1; - return err; -} - - -static int uv__udp_maybe_deferred_bind(uv_udp_t* handle, - int domain, - unsigned int flags) { - unsigned char taddr[sizeof(struct sockaddr_in6)]; - socklen_t addrlen; - - if (handle->io_watcher.fd != -1) - return 0; - - switch (domain) { - case AF_INET: - { - struct sockaddr_in* addr = (void*)&taddr; - memset(addr, 0, sizeof *addr); - addr->sin_family = AF_INET; - addr->sin_addr.s_addr = INADDR_ANY; - addrlen = sizeof *addr; - break; - } - case AF_INET6: - { - struct sockaddr_in6* addr = (void*)&taddr; - memset(addr, 0, sizeof *addr); - addr->sin6_family = AF_INET6; - addr->sin6_addr = in6addr_any; - addrlen = sizeof *addr; - break; - } - default: - assert(0 && "unsupported address family"); - abort(); - } - - return uv__udp_bind(handle, (const struct sockaddr*) &taddr, addrlen, flags); -} - - -int uv__udp_send(uv_udp_send_t* req, - uv_udp_t* handle, - const uv_buf_t bufs[], - unsigned int nbufs, - const struct sockaddr* addr, - unsigned int addrlen, - uv_udp_send_cb send_cb) { - int err; - int empty_queue; - - assert(nbufs > 0); - - err = uv__udp_maybe_deferred_bind(handle, addr->sa_family, 0); - if (err) - return err; - - /* It's legal for send_queue_count > 0 even when the write_queue is empty; - * it means there are error-state requests in the write_completed_queue that - * will touch up send_queue_size/count later. - */ - empty_queue = (handle->send_queue_count == 0); - - uv__req_init(handle->loop, req, UV_UDP_SEND); - assert(addrlen <= sizeof(req->addr)); - memcpy(&req->addr, addr, addrlen); - req->send_cb = send_cb; - req->handle = handle; - req->nbufs = nbufs; - - req->bufs = req->bufsml; - if (nbufs > ARRAY_SIZE(req->bufsml)) - req->bufs = uv__malloc(nbufs * sizeof(bufs[0])); - - if (req->bufs == NULL) { - uv__req_unregister(handle->loop, req); - return -ENOMEM; - } - - memcpy(req->bufs, bufs, nbufs * sizeof(bufs[0])); - handle->send_queue_size += uv__count_bufs(req->bufs, req->nbufs); - handle->send_queue_count++; - QUEUE_INSERT_TAIL(&handle->write_queue, &req->queue); - uv__handle_start(handle); - - if (empty_queue && !(handle->flags & UV_UDP_PROCESSING)) { - uv__udp_sendmsg(handle); - } else { - uv__io_start(handle->loop, &handle->io_watcher, POLLOUT); - } - - return 0; -} - - -int uv__udp_try_send(uv_udp_t* handle, - const uv_buf_t bufs[], - unsigned int nbufs, - const struct sockaddr* addr, - unsigned int addrlen) { - int err; - struct msghdr h; - ssize_t size; - - assert(nbufs > 0); - - /* already sending a message */ - if (handle->send_queue_count != 0) - return -EAGAIN; - - err = uv__udp_maybe_deferred_bind(handle, addr->sa_family, 0); - if (err) - return err; - - memset(&h, 0, sizeof h); - h.msg_name = (struct sockaddr*) addr; - h.msg_namelen = addrlen; - h.msg_iov = (struct iovec*) bufs; - h.msg_iovlen = nbufs; - - do { - size = sendmsg(handle->io_watcher.fd, &h, 0); - } while (size == -1 && errno == EINTR); - - if (size == -1) { - if (errno == EAGAIN || errno == EWOULDBLOCK) - return -EAGAIN; - else - return -errno; - } - - return size; -} - - -static int uv__udp_set_membership4(uv_udp_t* handle, - const struct sockaddr_in* multicast_addr, - const char* interface_addr, - uv_membership membership) { - struct ip_mreq mreq; - int optname; - int err; - - memset(&mreq, 0, sizeof mreq); - - if (interface_addr) { - err = uv_inet_pton(AF_INET, interface_addr, &mreq.imr_interface.s_addr); - if (err) - return err; - } else { - mreq.imr_interface.s_addr = htonl(INADDR_ANY); - } - - mreq.imr_multiaddr.s_addr = multicast_addr->sin_addr.s_addr; - - switch (membership) { - case UV_JOIN_GROUP: - optname = IP_ADD_MEMBERSHIP; - break; - case UV_LEAVE_GROUP: - optname = IP_DROP_MEMBERSHIP; - break; - default: - return -EINVAL; - } - - if (setsockopt(handle->io_watcher.fd, - IPPROTO_IP, - optname, - &mreq, - sizeof(mreq))) { -#if defined(__MVS__) - if (errno == ENXIO) - return -ENODEV; -#endif - return -errno; - } - - return 0; -} - - -static int uv__udp_set_membership6(uv_udp_t* handle, - const struct sockaddr_in6* multicast_addr, - const char* interface_addr, - uv_membership membership) { - int optname; - struct ipv6_mreq mreq; - struct sockaddr_in6 addr6; - - memset(&mreq, 0, sizeof mreq); - - if (interface_addr) { - if (uv_ip6_addr(interface_addr, 0, &addr6)) - return -EINVAL; - mreq.ipv6mr_interface = addr6.sin6_scope_id; - } else { - mreq.ipv6mr_interface = 0; - } - - mreq.ipv6mr_multiaddr = multicast_addr->sin6_addr; - - switch (membership) { - case UV_JOIN_GROUP: - optname = IPV6_ADD_MEMBERSHIP; - break; - case UV_LEAVE_GROUP: - optname = IPV6_DROP_MEMBERSHIP; - break; - default: - return -EINVAL; - } - - if (setsockopt(handle->io_watcher.fd, - IPPROTO_IPV6, - optname, - &mreq, - sizeof(mreq))) { -#if defined(__MVS__) - if (errno == ENXIO) - return -ENODEV; -#endif - return -errno; - } - - return 0; -} - - -int uv_udp_init_ex(uv_loop_t* loop, uv_udp_t* handle, unsigned int flags) { - int domain; - int err; - int fd; - - /* Use the lower 8 bits for the domain */ - domain = flags & 0xFF; - if (domain != AF_INET && domain != AF_INET6 && domain != AF_UNSPEC) - return -EINVAL; - - if (flags & ~0xFF) - return -EINVAL; - - if (domain != AF_UNSPEC) { - err = uv__socket(domain, SOCK_DGRAM, 0); - if (err < 0) - return err; - fd = err; - } else { - fd = -1; - } - - uv__handle_init(loop, (uv_handle_t*)handle, UV_UDP); - handle->alloc_cb = NULL; - handle->recv_cb = NULL; - handle->send_queue_size = 0; - handle->send_queue_count = 0; - uv__io_init(&handle->io_watcher, uv__udp_io, fd); - QUEUE_INIT(&handle->write_queue); - QUEUE_INIT(&handle->write_completed_queue); - return 0; -} - - -int uv_udp_init(uv_loop_t* loop, uv_udp_t* handle) { - return uv_udp_init_ex(loop, handle, AF_UNSPEC); -} - - -int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) { - int err; - - /* Check for already active socket. */ - if (handle->io_watcher.fd != -1) - return -EBUSY; - - err = uv__nonblock(sock, 1); - if (err) - return err; - - err = uv__set_reuse(sock); - if (err) - return err; - - handle->io_watcher.fd = sock; - return 0; -} - - -int uv_udp_set_membership(uv_udp_t* handle, - const char* multicast_addr, - const char* interface_addr, - uv_membership membership) { - int err; - struct sockaddr_in addr4; - struct sockaddr_in6 addr6; - - if (uv_ip4_addr(multicast_addr, 0, &addr4) == 0) { - err = uv__udp_maybe_deferred_bind(handle, AF_INET, UV_UDP_REUSEADDR); - if (err) - return err; - return uv__udp_set_membership4(handle, &addr4, interface_addr, membership); - } else if (uv_ip6_addr(multicast_addr, 0, &addr6) == 0) { - err = uv__udp_maybe_deferred_bind(handle, AF_INET6, UV_UDP_REUSEADDR); - if (err) - return err; - return uv__udp_set_membership6(handle, &addr6, interface_addr, membership); - } else { - return -EINVAL; - } -} - -static int uv__setsockopt(uv_udp_t* handle, - int option4, - int option6, - const void* val, - size_t size) { - int r; - - if (handle->flags & UV_HANDLE_IPV6) - r = setsockopt(handle->io_watcher.fd, - IPPROTO_IPV6, - option6, - val, - size); - else - r = setsockopt(handle->io_watcher.fd, - IPPROTO_IP, - option4, - val, - size); - if (r) - return -errno; - - return 0; -} - -static int uv__setsockopt_maybe_char(uv_udp_t* handle, - int option4, - int option6, - int val) { -#if defined(__sun) || defined(_AIX) || defined(__MVS__) - char arg = val; -#elif defined(__OpenBSD__) - unsigned char arg = val; -#else - int arg = val; -#endif - - if (val < 0 || val > 255) - return -EINVAL; - - return uv__setsockopt(handle, option4, option6, &arg, sizeof(arg)); -} - - -int uv_udp_set_broadcast(uv_udp_t* handle, int on) { - if (setsockopt(handle->io_watcher.fd, - SOL_SOCKET, - SO_BROADCAST, - &on, - sizeof(on))) { - return -errno; - } - - return 0; -} - - -int uv_udp_set_ttl(uv_udp_t* handle, int ttl) { - if (ttl < 1 || ttl > 255) - return -EINVAL; - -#if defined(__MVS__) - if (!(handle->flags & UV_HANDLE_IPV6)) - return -ENOTSUP; /* zOS does not support setting ttl for IPv4 */ -#endif - -/* - * On Solaris and derivatives such as SmartOS, the length of socket options - * is sizeof(int) for IP_TTL and IPV6_UNICAST_HOPS, - * so hardcode the size of these options on this platform, - * and use the general uv__setsockopt_maybe_char call on other platforms. - */ -#if defined(__sun) || defined(_AIX) || defined(__OpenBSD__) || \ - defined(__MVS__) - - return uv__setsockopt(handle, - IP_TTL, - IPV6_UNICAST_HOPS, - &ttl, - sizeof(ttl)); -#endif /* defined(__sun) || defined(_AIX) || defined (__OpenBSD__) || - defined(__MVS__) */ - - return uv__setsockopt_maybe_char(handle, - IP_TTL, - IPV6_UNICAST_HOPS, - ttl); -} - - -int uv_udp_set_multicast_ttl(uv_udp_t* handle, int ttl) { -/* - * On Solaris and derivatives such as SmartOS, the length of socket options - * is sizeof(int) for IPV6_MULTICAST_HOPS and sizeof(char) for - * IP_MULTICAST_TTL, so hardcode the size of the option in the IPv6 case, - * and use the general uv__setsockopt_maybe_char call otherwise. - */ -#if defined(__sun) || defined(_AIX) || defined(__MVS__) - if (handle->flags & UV_HANDLE_IPV6) - return uv__setsockopt(handle, - IP_MULTICAST_TTL, - IPV6_MULTICAST_HOPS, - &ttl, - sizeof(ttl)); -#endif /* defined(__sun) || defined(_AIX) || defined(__MVS__) */ - - return uv__setsockopt_maybe_char(handle, - IP_MULTICAST_TTL, - IPV6_MULTICAST_HOPS, - ttl); -} - - -int uv_udp_set_multicast_loop(uv_udp_t* handle, int on) { -/* - * On Solaris and derivatives such as SmartOS, the length of socket options - * is sizeof(int) for IPV6_MULTICAST_LOOP and sizeof(char) for - * IP_MULTICAST_LOOP, so hardcode the size of the option in the IPv6 case, - * and use the general uv__setsockopt_maybe_char call otherwise. - */ -#if defined(__sun) || defined(_AIX) || defined(__MVS__) - if (handle->flags & UV_HANDLE_IPV6) - return uv__setsockopt(handle, - IP_MULTICAST_LOOP, - IPV6_MULTICAST_LOOP, - &on, - sizeof(on)); -#endif /* defined(__sun) || defined(_AIX) || defined(__MVS__) */ - - return uv__setsockopt_maybe_char(handle, - IP_MULTICAST_LOOP, - IPV6_MULTICAST_LOOP, - on); -} - -int uv_udp_set_multicast_interface(uv_udp_t* handle, const char* interface_addr) { - struct sockaddr_storage addr_st; - struct sockaddr_in* addr4; - struct sockaddr_in6* addr6; - - addr4 = (struct sockaddr_in*) &addr_st; - addr6 = (struct sockaddr_in6*) &addr_st; - - if (!interface_addr) { - memset(&addr_st, 0, sizeof addr_st); - if (handle->flags & UV_HANDLE_IPV6) { - addr_st.ss_family = AF_INET6; - addr6->sin6_scope_id = 0; - } else { - addr_st.ss_family = AF_INET; - addr4->sin_addr.s_addr = htonl(INADDR_ANY); - } - } else if (uv_ip4_addr(interface_addr, 0, addr4) == 0) { - /* nothing, address was parsed */ - } else if (uv_ip6_addr(interface_addr, 0, addr6) == 0) { - /* nothing, address was parsed */ - } else { - return -EINVAL; - } - - if (addr_st.ss_family == AF_INET) { - if (setsockopt(handle->io_watcher.fd, - IPPROTO_IP, - IP_MULTICAST_IF, - (void*) &addr4->sin_addr, - sizeof(addr4->sin_addr)) == -1) { - return -errno; - } - } else if (addr_st.ss_family == AF_INET6) { - if (setsockopt(handle->io_watcher.fd, - IPPROTO_IPV6, - IPV6_MULTICAST_IF, - &addr6->sin6_scope_id, - sizeof(addr6->sin6_scope_id)) == -1) { - return -errno; - } - } else { - assert(0 && "unexpected address family"); - abort(); - } - - return 0; -} - - -int uv_udp_getsockname(const uv_udp_t* handle, - struct sockaddr* name, - int* namelen) { - socklen_t socklen; - - if (handle->io_watcher.fd == -1) - return -EINVAL; /* FIXME(bnoordhuis) -EBADF */ - - /* sizeof(socklen_t) != sizeof(int) on some systems. */ - socklen = (socklen_t) *namelen; - - if (getsockname(handle->io_watcher.fd, name, &socklen)) - return -errno; - - *namelen = (int) socklen; - return 0; -} - - -int uv__udp_recv_start(uv_udp_t* handle, - uv_alloc_cb alloc_cb, - uv_udp_recv_cb recv_cb) { - int err; - - if (alloc_cb == NULL || recv_cb == NULL) - return -EINVAL; - - if (uv__io_active(&handle->io_watcher, POLLIN)) - return -EALREADY; /* FIXME(bnoordhuis) Should be -EBUSY. */ - - err = uv__udp_maybe_deferred_bind(handle, AF_INET, 0); - if (err) - return err; - - handle->alloc_cb = alloc_cb; - handle->recv_cb = recv_cb; - - uv__io_start(handle->loop, &handle->io_watcher, POLLIN); - uv__handle_start(handle); - - return 0; -} - - -int uv__udp_recv_stop(uv_udp_t* handle) { - uv__io_stop(handle->loop, &handle->io_watcher, POLLIN); - - if (!uv__io_active(&handle->io_watcher, POLLOUT)) - uv__handle_stop(handle); - - handle->alloc_cb = NULL; - handle->recv_cb = NULL; - - return 0; -} diff --git a/vendor/libuv/src/uv-common.c b/vendor/libuv/src/uv-common.c deleted file mode 100644 index bc7d1379d..000000000 --- a/vendor/libuv/src/uv-common.c +++ /dev/null @@ -1,664 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "uv-common.h" - -#include -#include -#include -#include /* NULL */ -#include -#include /* malloc */ -#include /* memset */ - -#if defined(_WIN32) -# include /* malloc */ -#else -# include /* if_nametoindex */ -#endif - - -typedef struct { - uv_malloc_func local_malloc; - uv_realloc_func local_realloc; - uv_calloc_func local_calloc; - uv_free_func local_free; -} uv__allocator_t; - -static uv__allocator_t uv__allocator = { - malloc, - realloc, - calloc, - free, -}; - -char* uv__strdup(const char* s) { - size_t len = strlen(s) + 1; - char* m = uv__malloc(len); - if (m == NULL) - return NULL; - return memcpy(m, s, len); -} - -char* uv__strndup(const char* s, size_t n) { - char* m; - size_t len = strlen(s); - if (n < len) - len = n; - m = uv__malloc(len + 1); - if (m == NULL) - return NULL; - m[len] = '\0'; - return memcpy(m, s, len); -} - -void* uv__malloc(size_t size) { - return uv__allocator.local_malloc(size); -} - -void uv__free(void* ptr) { - int saved_errno; - - /* Libuv expects that free() does not clobber errno. The system allocator - * honors that assumption but custom allocators may not be so careful. - */ - saved_errno = errno; - uv__allocator.local_free(ptr); - errno = saved_errno; -} - -void* uv__calloc(size_t count, size_t size) { - return uv__allocator.local_calloc(count, size); -} - -void* uv__realloc(void* ptr, size_t size) { - return uv__allocator.local_realloc(ptr, size); -} - -int uv_replace_allocator(uv_malloc_func malloc_func, - uv_realloc_func realloc_func, - uv_calloc_func calloc_func, - uv_free_func free_func) { - if (malloc_func == NULL || realloc_func == NULL || - calloc_func == NULL || free_func == NULL) { - return UV_EINVAL; - } - - uv__allocator.local_malloc = malloc_func; - uv__allocator.local_realloc = realloc_func; - uv__allocator.local_calloc = calloc_func; - uv__allocator.local_free = free_func; - - return 0; -} - -#define XX(uc, lc) case UV_##uc: return sizeof(uv_##lc##_t); - -size_t uv_handle_size(uv_handle_type type) { - switch (type) { - UV_HANDLE_TYPE_MAP(XX) - default: - return -1; - } -} - -size_t uv_req_size(uv_req_type type) { - switch(type) { - UV_REQ_TYPE_MAP(XX) - default: - return -1; - } -} - -#undef XX - - -size_t uv_loop_size(void) { - return sizeof(uv_loop_t); -} - - -uv_buf_t uv_buf_init(char* base, unsigned int len) { - uv_buf_t buf; - buf.base = base; - buf.len = len; - return buf; -} - - -static const char* uv__unknown_err_code(int err) { - char buf[32]; - char* copy; - - snprintf(buf, sizeof(buf), "Unknown system error %d", err); - copy = uv__strdup(buf); - - return copy != NULL ? copy : "Unknown system error"; -} - - -#define UV_ERR_NAME_GEN(name, _) case UV_ ## name: return #name; -const char* uv_err_name(int err) { - switch (err) { - UV_ERRNO_MAP(UV_ERR_NAME_GEN) - } - return uv__unknown_err_code(err); -} -#undef UV_ERR_NAME_GEN - - -#define UV_STRERROR_GEN(name, msg) case UV_ ## name: return msg; -const char* uv_strerror(int err) { - switch (err) { - UV_ERRNO_MAP(UV_STRERROR_GEN) - } - return uv__unknown_err_code(err); -} -#undef UV_STRERROR_GEN - - -int uv_ip4_addr(const char* ip, int port, struct sockaddr_in* addr) { - memset(addr, 0, sizeof(*addr)); - addr->sin_family = AF_INET; - addr->sin_port = htons(port); - return uv_inet_pton(AF_INET, ip, &(addr->sin_addr.s_addr)); -} - - -int uv_ip6_addr(const char* ip, int port, struct sockaddr_in6* addr) { - char address_part[40]; - size_t address_part_size; - const char* zone_index; - - memset(addr, 0, sizeof(*addr)); - addr->sin6_family = AF_INET6; - addr->sin6_port = htons(port); - - zone_index = strchr(ip, '%'); - if (zone_index != NULL) { - address_part_size = zone_index - ip; - if (address_part_size >= sizeof(address_part)) - address_part_size = sizeof(address_part) - 1; - - memcpy(address_part, ip, address_part_size); - address_part[address_part_size] = '\0'; - ip = address_part; - - zone_index++; /* skip '%' */ - /* NOTE: unknown interface (id=0) is silently ignored */ -#ifdef _WIN32 - addr->sin6_scope_id = atoi(zone_index); -#else - addr->sin6_scope_id = if_nametoindex(zone_index); -#endif - } - - return uv_inet_pton(AF_INET6, ip, &addr->sin6_addr); -} - - -int uv_ip4_name(const struct sockaddr_in* src, char* dst, size_t size) { - return uv_inet_ntop(AF_INET, &src->sin_addr, dst, size); -} - - -int uv_ip6_name(const struct sockaddr_in6* src, char* dst, size_t size) { - return uv_inet_ntop(AF_INET6, &src->sin6_addr, dst, size); -} - - -int uv_tcp_bind(uv_tcp_t* handle, - const struct sockaddr* addr, - unsigned int flags) { - unsigned int addrlen; - - if (handle->type != UV_TCP) - return UV_EINVAL; - - if (addr->sa_family == AF_INET) - addrlen = sizeof(struct sockaddr_in); - else if (addr->sa_family == AF_INET6) - addrlen = sizeof(struct sockaddr_in6); - else - return UV_EINVAL; - - return uv__tcp_bind(handle, addr, addrlen, flags); -} - - -int uv_udp_bind(uv_udp_t* handle, - const struct sockaddr* addr, - unsigned int flags) { - unsigned int addrlen; - - if (handle->type != UV_UDP) - return UV_EINVAL; - - if (addr->sa_family == AF_INET) - addrlen = sizeof(struct sockaddr_in); - else if (addr->sa_family == AF_INET6) - addrlen = sizeof(struct sockaddr_in6); - else - return UV_EINVAL; - - return uv__udp_bind(handle, addr, addrlen, flags); -} - - -int uv_tcp_connect(uv_connect_t* req, - uv_tcp_t* handle, - const struct sockaddr* addr, - uv_connect_cb cb) { - unsigned int addrlen; - - if (handle->type != UV_TCP) - return UV_EINVAL; - - if (addr->sa_family == AF_INET) - addrlen = sizeof(struct sockaddr_in); - else if (addr->sa_family == AF_INET6) - addrlen = sizeof(struct sockaddr_in6); - else - return UV_EINVAL; - - return uv__tcp_connect(req, handle, addr, addrlen, cb); -} - - -int uv_udp_send(uv_udp_send_t* req, - uv_udp_t* handle, - const uv_buf_t bufs[], - unsigned int nbufs, - const struct sockaddr* addr, - uv_udp_send_cb send_cb) { - unsigned int addrlen; - - if (handle->type != UV_UDP) - return UV_EINVAL; - - if (addr->sa_family == AF_INET) - addrlen = sizeof(struct sockaddr_in); - else if (addr->sa_family == AF_INET6) - addrlen = sizeof(struct sockaddr_in6); - else - return UV_EINVAL; - - return uv__udp_send(req, handle, bufs, nbufs, addr, addrlen, send_cb); -} - - -int uv_udp_try_send(uv_udp_t* handle, - const uv_buf_t bufs[], - unsigned int nbufs, - const struct sockaddr* addr) { - unsigned int addrlen; - - if (handle->type != UV_UDP) - return UV_EINVAL; - - if (addr->sa_family == AF_INET) - addrlen = sizeof(struct sockaddr_in); - else if (addr->sa_family == AF_INET6) - addrlen = sizeof(struct sockaddr_in6); - else - return UV_EINVAL; - - return uv__udp_try_send(handle, bufs, nbufs, addr, addrlen); -} - - -int uv_udp_recv_start(uv_udp_t* handle, - uv_alloc_cb alloc_cb, - uv_udp_recv_cb recv_cb) { - if (handle->type != UV_UDP || alloc_cb == NULL || recv_cb == NULL) - return UV_EINVAL; - else - return uv__udp_recv_start(handle, alloc_cb, recv_cb); -} - - -int uv_udp_recv_stop(uv_udp_t* handle) { - if (handle->type != UV_UDP) - return UV_EINVAL; - else - return uv__udp_recv_stop(handle); -} - - -void uv_walk(uv_loop_t* loop, uv_walk_cb walk_cb, void* arg) { - QUEUE queue; - QUEUE* q; - uv_handle_t* h; - - QUEUE_MOVE(&loop->handle_queue, &queue); - while (!QUEUE_EMPTY(&queue)) { - q = QUEUE_HEAD(&queue); - h = QUEUE_DATA(q, uv_handle_t, handle_queue); - - QUEUE_REMOVE(q); - QUEUE_INSERT_TAIL(&loop->handle_queue, q); - - if (h->flags & UV__HANDLE_INTERNAL) continue; - walk_cb(h, arg); - } -} - - -static void uv__print_handles(uv_loop_t* loop, int only_active, FILE* stream) { - const char* type; - QUEUE* q; - uv_handle_t* h; - - if (loop == NULL) - loop = uv_default_loop(); - - QUEUE_FOREACH(q, &loop->handle_queue) { - h = QUEUE_DATA(q, uv_handle_t, handle_queue); - - if (only_active && !uv__is_active(h)) - continue; - - switch (h->type) { -#define X(uc, lc) case UV_##uc: type = #lc; break; - UV_HANDLE_TYPE_MAP(X) -#undef X - default: type = ""; - } - - fprintf(stream, - "[%c%c%c] %-8s %p\n", - "R-"[!(h->flags & UV__HANDLE_REF)], - "A-"[!(h->flags & UV__HANDLE_ACTIVE)], - "I-"[!(h->flags & UV__HANDLE_INTERNAL)], - type, - (void*)h); - } -} - - -void uv_print_all_handles(uv_loop_t* loop, FILE* stream) { - uv__print_handles(loop, 0, stream); -} - - -void uv_print_active_handles(uv_loop_t* loop, FILE* stream) { - uv__print_handles(loop, 1, stream); -} - - -void uv_ref(uv_handle_t* handle) { - uv__handle_ref(handle); -} - - -void uv_unref(uv_handle_t* handle) { - uv__handle_unref(handle); -} - - -int uv_has_ref(const uv_handle_t* handle) { - return uv__has_ref(handle); -} - - -void uv_stop(uv_loop_t* loop) { - loop->stop_flag = 1; -} - - -uint64_t uv_now(const uv_loop_t* loop) { - return loop->time; -} - - - -size_t uv__count_bufs(const uv_buf_t bufs[], unsigned int nbufs) { - unsigned int i; - size_t bytes; - - bytes = 0; - for (i = 0; i < nbufs; i++) - bytes += (size_t) bufs[i].len; - - return bytes; -} - -int uv_recv_buffer_size(uv_handle_t* handle, int* value) { - return uv__socket_sockopt(handle, SO_RCVBUF, value); -} - -int uv_send_buffer_size(uv_handle_t* handle, int *value) { - return uv__socket_sockopt(handle, SO_SNDBUF, value); -} - -int uv_fs_event_getpath(uv_fs_event_t* handle, char* buffer, size_t* size) { - size_t required_len; - - if (!uv__is_active(handle)) { - *size = 0; - return UV_EINVAL; - } - - required_len = strlen(handle->path); - if (required_len >= *size) { - *size = required_len + 1; - return UV_ENOBUFS; - } - - memcpy(buffer, handle->path, required_len); - *size = required_len; - buffer[required_len] = '\0'; - - return 0; -} - -/* The windows implementation does not have the same structure layout as - * the unix implementation (nbufs is not directly inside req but is - * contained in a nested union/struct) so this function locates it. -*/ -static unsigned int* uv__get_nbufs(uv_fs_t* req) { -#ifdef _WIN32 - return &req->fs.info.nbufs; -#else - return &req->nbufs; -#endif -} - -/* uv_fs_scandir() uses the system allocator to allocate memory on non-Windows - * systems. So, the memory should be released using free(). On Windows, - * uv__malloc() is used, so use uv__free() to free memory. -*/ -#ifdef _WIN32 -# define uv__fs_scandir_free uv__free -#else -# define uv__fs_scandir_free free -#endif - -void uv__fs_scandir_cleanup(uv_fs_t* req) { - uv__dirent_t** dents; - - unsigned int* nbufs = uv__get_nbufs(req); - - dents = req->ptr; - if (*nbufs > 0 && *nbufs != (unsigned int) req->result) - (*nbufs)--; - for (; *nbufs < (unsigned int) req->result; (*nbufs)++) - uv__fs_scandir_free(dents[*nbufs]); - - uv__fs_scandir_free(req->ptr); - req->ptr = NULL; -} - - -int uv_fs_scandir_next(uv_fs_t* req, uv_dirent_t* ent) { - uv__dirent_t** dents; - uv__dirent_t* dent; - unsigned int* nbufs; - - /* Check to see if req passed */ - if (req->result < 0) - return req->result; - - /* Ptr will be null if req was canceled or no files found */ - if (!req->ptr) - return UV_EOF; - - nbufs = uv__get_nbufs(req); - assert(nbufs); - - dents = req->ptr; - - /* Free previous entity */ - if (*nbufs > 0) - uv__fs_scandir_free(dents[*nbufs - 1]); - - /* End was already reached */ - if (*nbufs == (unsigned int) req->result) { - uv__fs_scandir_free(dents); - req->ptr = NULL; - return UV_EOF; - } - - dent = dents[(*nbufs)++]; - - ent->name = dent->d_name; -#ifdef HAVE_DIRENT_TYPES - switch (dent->d_type) { - case UV__DT_DIR: - ent->type = UV_DIRENT_DIR; - break; - case UV__DT_FILE: - ent->type = UV_DIRENT_FILE; - break; - case UV__DT_LINK: - ent->type = UV_DIRENT_LINK; - break; - case UV__DT_FIFO: - ent->type = UV_DIRENT_FIFO; - break; - case UV__DT_SOCKET: - ent->type = UV_DIRENT_SOCKET; - break; - case UV__DT_CHAR: - ent->type = UV_DIRENT_CHAR; - break; - case UV__DT_BLOCK: - ent->type = UV_DIRENT_BLOCK; - break; - default: - ent->type = UV_DIRENT_UNKNOWN; - } -#else - ent->type = UV_DIRENT_UNKNOWN; -#endif - - return 0; -} - - -int uv_loop_configure(uv_loop_t* loop, uv_loop_option option, ...) { - va_list ap; - int err; - - va_start(ap, option); - /* Any platform-agnostic options should be handled here. */ - err = uv__loop_configure(loop, option, ap); - va_end(ap); - - return err; -} - - -static uv_loop_t default_loop_struct; -static uv_loop_t* default_loop_ptr; - - -uv_loop_t* uv_default_loop(void) { - if (default_loop_ptr != NULL) - return default_loop_ptr; - - if (uv_loop_init(&default_loop_struct)) - return NULL; - - default_loop_ptr = &default_loop_struct; - return default_loop_ptr; -} - - -uv_loop_t* uv_loop_new(void) { - uv_loop_t* loop; - - loop = uv__malloc(sizeof(*loop)); - if (loop == NULL) - return NULL; - - if (uv_loop_init(loop)) { - uv__free(loop); - return NULL; - } - - return loop; -} - - -int uv_loop_close(uv_loop_t* loop) { - QUEUE* q; - uv_handle_t* h; -#ifndef NDEBUG - void* saved_data; -#endif - - if (!QUEUE_EMPTY(&(loop)->active_reqs)) - return UV_EBUSY; - - QUEUE_FOREACH(q, &loop->handle_queue) { - h = QUEUE_DATA(q, uv_handle_t, handle_queue); - if (!(h->flags & UV__HANDLE_INTERNAL)) - return UV_EBUSY; - } - - uv__loop_close(loop); - -#ifndef NDEBUG - saved_data = loop->data; - memset(loop, -1, sizeof(*loop)); - loop->data = saved_data; -#endif - if (loop == default_loop_ptr) - default_loop_ptr = NULL; - - return 0; -} - - -void uv_loop_delete(uv_loop_t* loop) { - uv_loop_t* default_loop; - int err; - - default_loop = default_loop_ptr; - - err = uv_loop_close(loop); - (void) err; /* Squelch compiler warnings. */ - assert(err == 0); - if (loop != default_loop) - uv__free(loop); -} diff --git a/vendor/libuv/src/uv-common.h b/vendor/libuv/src/uv-common.h deleted file mode 100644 index 27902fdf8..000000000 --- a/vendor/libuv/src/uv-common.h +++ /dev/null @@ -1,227 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -/* - * This file is private to libuv. It provides common functionality to both - * Windows and Unix backends. - */ - -#ifndef UV_COMMON_H_ -#define UV_COMMON_H_ - -#include -#include -#include - -#if defined(_MSC_VER) && _MSC_VER < 1600 -# include "stdint-msvc2008.h" -#else -# include -#endif - -#include "uv.h" -#include "tree.h" -#include "queue.h" - -#if !defined(snprintf) && defined(_MSC_VER) && _MSC_VER < 1900 -extern int snprintf(char*, size_t, const char*, ...); -#endif - -#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) - -#define container_of(ptr, type, member) \ - ((type *) ((char *) (ptr) - offsetof(type, member))) - -#define STATIC_ASSERT(expr) \ - void uv__static_assert(int static_assert_failed[1 - 2 * !(expr)]) - -#ifndef _WIN32 -enum { - UV__HANDLE_INTERNAL = 0x8000, - UV__HANDLE_ACTIVE = 0x4000, - UV__HANDLE_REF = 0x2000, - UV__HANDLE_CLOSING = 0 /* no-op on unix */ -}; -#else -# define UV__HANDLE_INTERNAL 0x80 -# define UV__HANDLE_ACTIVE 0x40 -# define UV__HANDLE_REF 0x20 -# define UV__HANDLE_CLOSING 0x01 -#endif - -int uv__loop_configure(uv_loop_t* loop, uv_loop_option option, va_list ap); - -void uv__loop_close(uv_loop_t* loop); - -int uv__tcp_bind(uv_tcp_t* tcp, - const struct sockaddr* addr, - unsigned int addrlen, - unsigned int flags); - -int uv__tcp_connect(uv_connect_t* req, - uv_tcp_t* handle, - const struct sockaddr* addr, - unsigned int addrlen, - uv_connect_cb cb); - -int uv__udp_bind(uv_udp_t* handle, - const struct sockaddr* addr, - unsigned int addrlen, - unsigned int flags); - -int uv__udp_send(uv_udp_send_t* req, - uv_udp_t* handle, - const uv_buf_t bufs[], - unsigned int nbufs, - const struct sockaddr* addr, - unsigned int addrlen, - uv_udp_send_cb send_cb); - -int uv__udp_try_send(uv_udp_t* handle, - const uv_buf_t bufs[], - unsigned int nbufs, - const struct sockaddr* addr, - unsigned int addrlen); - -int uv__udp_recv_start(uv_udp_t* handle, uv_alloc_cb alloccb, - uv_udp_recv_cb recv_cb); - -int uv__udp_recv_stop(uv_udp_t* handle); - -void uv__fs_poll_close(uv_fs_poll_t* handle); - -int uv__getaddrinfo_translate_error(int sys_err); /* EAI_* error. */ - -void uv__work_submit(uv_loop_t* loop, - struct uv__work *w, - void (*work)(struct uv__work *w), - void (*done)(struct uv__work *w, int status)); - -void uv__work_done(uv_async_t* handle); - -size_t uv__count_bufs(const uv_buf_t bufs[], unsigned int nbufs); - -int uv__socket_sockopt(uv_handle_t* handle, int optname, int* value); - -void uv__fs_scandir_cleanup(uv_fs_t* req); - -#define uv__has_active_reqs(loop) \ - (QUEUE_EMPTY(&(loop)->active_reqs) == 0) - -#define uv__req_register(loop, req) \ - do { \ - QUEUE_INSERT_TAIL(&(loop)->active_reqs, &(req)->active_queue); \ - } \ - while (0) - -#define uv__req_unregister(loop, req) \ - do { \ - assert(uv__has_active_reqs(loop)); \ - QUEUE_REMOVE(&(req)->active_queue); \ - } \ - while (0) - -#define uv__has_active_handles(loop) \ - ((loop)->active_handles > 0) - -#define uv__active_handle_add(h) \ - do { \ - (h)->loop->active_handles++; \ - } \ - while (0) - -#define uv__active_handle_rm(h) \ - do { \ - (h)->loop->active_handles--; \ - } \ - while (0) - -#define uv__is_active(h) \ - (((h)->flags & UV__HANDLE_ACTIVE) != 0) - -#define uv__is_closing(h) \ - (((h)->flags & (UV_CLOSING | UV_CLOSED)) != 0) - -#define uv__handle_start(h) \ - do { \ - assert(((h)->flags & UV__HANDLE_CLOSING) == 0); \ - if (((h)->flags & UV__HANDLE_ACTIVE) != 0) break; \ - (h)->flags |= UV__HANDLE_ACTIVE; \ - if (((h)->flags & UV__HANDLE_REF) != 0) uv__active_handle_add(h); \ - } \ - while (0) - -#define uv__handle_stop(h) \ - do { \ - assert(((h)->flags & UV__HANDLE_CLOSING) == 0); \ - if (((h)->flags & UV__HANDLE_ACTIVE) == 0) break; \ - (h)->flags &= ~UV__HANDLE_ACTIVE; \ - if (((h)->flags & UV__HANDLE_REF) != 0) uv__active_handle_rm(h); \ - } \ - while (0) - -#define uv__handle_ref(h) \ - do { \ - if (((h)->flags & UV__HANDLE_REF) != 0) break; \ - (h)->flags |= UV__HANDLE_REF; \ - if (((h)->flags & UV__HANDLE_CLOSING) != 0) break; \ - if (((h)->flags & UV__HANDLE_ACTIVE) != 0) uv__active_handle_add(h); \ - } \ - while (0) - -#define uv__handle_unref(h) \ - do { \ - if (((h)->flags & UV__HANDLE_REF) == 0) break; \ - (h)->flags &= ~UV__HANDLE_REF; \ - if (((h)->flags & UV__HANDLE_CLOSING) != 0) break; \ - if (((h)->flags & UV__HANDLE_ACTIVE) != 0) uv__active_handle_rm(h); \ - } \ - while (0) - -#define uv__has_ref(h) \ - (((h)->flags & UV__HANDLE_REF) != 0) - -#if defined(_WIN32) -# define uv__handle_platform_init(h) ((h)->u.fd = -1) -#else -# define uv__handle_platform_init(h) ((h)->next_closing = NULL) -#endif - -#define uv__handle_init(loop_, h, type_) \ - do { \ - (h)->loop = (loop_); \ - (h)->type = (type_); \ - (h)->flags = UV__HANDLE_REF; /* Ref the loop when active. */ \ - QUEUE_INSERT_TAIL(&(loop_)->handle_queue, &(h)->handle_queue); \ - uv__handle_platform_init(h); \ - } \ - while (0) - - -/* Allocator prototypes */ -void *uv__calloc(size_t count, size_t size); -char *uv__strdup(const char* s); -char *uv__strndup(const char* s, size_t n); -void* uv__malloc(size_t size); -void uv__free(void* ptr); -void* uv__realloc(void* ptr, size_t size); - -#endif /* UV_COMMON_H_ */ diff --git a/vendor/libuv/src/version.c b/vendor/libuv/src/version.c deleted file mode 100644 index 686dedd98..000000000 --- a/vendor/libuv/src/version.c +++ /dev/null @@ -1,45 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" - -#define UV_STRINGIFY(v) UV_STRINGIFY_HELPER(v) -#define UV_STRINGIFY_HELPER(v) #v - -#define UV_VERSION_STRING_BASE UV_STRINGIFY(UV_VERSION_MAJOR) "." \ - UV_STRINGIFY(UV_VERSION_MINOR) "." \ - UV_STRINGIFY(UV_VERSION_PATCH) - -#if UV_VERSION_IS_RELEASE -# define UV_VERSION_STRING UV_VERSION_STRING_BASE -#else -# define UV_VERSION_STRING UV_VERSION_STRING_BASE "-" UV_VERSION_SUFFIX -#endif - - -unsigned int uv_version(void) { - return UV_VERSION_HEX; -} - - -const char* uv_version_string(void) { - return UV_VERSION_STRING; -} diff --git a/vendor/libuv/src/win/async.c b/vendor/libuv/src/win/async.c deleted file mode 100644 index ad240ab89..000000000 --- a/vendor/libuv/src/win/async.c +++ /dev/null @@ -1,99 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include - -#include "uv.h" -#include "internal.h" -#include "atomicops-inl.h" -#include "handle-inl.h" -#include "req-inl.h" - - -void uv_async_endgame(uv_loop_t* loop, uv_async_t* handle) { - if (handle->flags & UV__HANDLE_CLOSING && - !handle->async_sent) { - assert(!(handle->flags & UV_HANDLE_CLOSED)); - uv__handle_close(handle); - } -} - - -int uv_async_init(uv_loop_t* loop, uv_async_t* handle, uv_async_cb async_cb) { - uv_req_t* req; - - uv__handle_init(loop, (uv_handle_t*) handle, UV_ASYNC); - handle->async_sent = 0; - handle->async_cb = async_cb; - - req = &handle->async_req; - uv_req_init(loop, req); - req->type = UV_WAKEUP; - req->data = handle; - - uv__handle_start(handle); - - return 0; -} - - -void uv_async_close(uv_loop_t* loop, uv_async_t* handle) { - if (!((uv_async_t*)handle)->async_sent) { - uv_want_endgame(loop, (uv_handle_t*) handle); - } - - uv__handle_closing(handle); -} - - -int uv_async_send(uv_async_t* handle) { - uv_loop_t* loop = handle->loop; - - if (handle->type != UV_ASYNC) { - /* Can't set errno because that's not thread-safe. */ - return -1; - } - - /* The user should make sure never to call uv_async_send to a closing */ - /* or closed handle. */ - assert(!(handle->flags & UV__HANDLE_CLOSING)); - - if (!uv__atomic_exchange_set(&handle->async_sent)) { - POST_COMPLETION_FOR_REQ(loop, &handle->async_req); - } - - return 0; -} - - -void uv_process_async_wakeup_req(uv_loop_t* loop, uv_async_t* handle, - uv_req_t* req) { - assert(handle->type == UV_ASYNC); - assert(req->type == UV_WAKEUP); - - handle->async_sent = 0; - - if (handle->flags & UV__HANDLE_CLOSING) { - uv_want_endgame(loop, (uv_handle_t*)handle); - } else if (handle->async_cb != NULL) { - handle->async_cb(handle); - } -} diff --git a/vendor/libuv/src/win/atomicops-inl.h b/vendor/libuv/src/win/atomicops-inl.h deleted file mode 100644 index 61e006026..000000000 --- a/vendor/libuv/src/win/atomicops-inl.h +++ /dev/null @@ -1,56 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef UV_WIN_ATOMICOPS_INL_H_ -#define UV_WIN_ATOMICOPS_INL_H_ - -#include "uv.h" - - -/* Atomic set operation on char */ -#ifdef _MSC_VER /* MSVC */ - -/* _InterlockedOr8 is supported by MSVC on x32 and x64. It is slightly less */ -/* efficient than InterlockedExchange, but InterlockedExchange8 does not */ -/* exist, and interlocked operations on larger targets might require the */ -/* target to be aligned. */ -#pragma intrinsic(_InterlockedOr8) - -static char __declspec(inline) uv__atomic_exchange_set(char volatile* target) { - return _InterlockedOr8(target, 1); -} - -#else /* GCC */ - -/* Mingw-32 version, hopefully this works for 64-bit gcc as well. */ -static inline char uv__atomic_exchange_set(char volatile* target) { - const char one = 1; - char old_value; - __asm__ __volatile__ ("lock xchgb %0, %1\n\t" - : "=r"(old_value), "=m"(*target) - : "0"(one), "m"(*target) - : "memory"); - return old_value; -} - -#endif - -#endif /* UV_WIN_ATOMICOPS_INL_H_ */ diff --git a/vendor/libuv/src/win/core.c b/vendor/libuv/src/win/core.c deleted file mode 100644 index e84186d4e..000000000 --- a/vendor/libuv/src/win/core.c +++ /dev/null @@ -1,598 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include -#if defined(_MSC_VER) || defined(__MINGW64_VERSION_MAJOR) -#include -#endif - -#include "uv.h" -#include "internal.h" -#include "queue.h" -#include "handle-inl.h" -#include "req-inl.h" - -/* uv_once initialization guards */ -static uv_once_t uv_init_guard_ = UV_ONCE_INIT; - - -#if defined(_DEBUG) && (defined(_MSC_VER) || defined(__MINGW64_VERSION_MAJOR)) -/* Our crt debug report handler allows us to temporarily disable asserts - * just for the current thread. - */ - -UV_THREAD_LOCAL int uv__crt_assert_enabled = TRUE; - -static int uv__crt_dbg_report_handler(int report_type, char *message, int *ret_val) { - if (uv__crt_assert_enabled || report_type != _CRT_ASSERT) - return FALSE; - - if (ret_val) { - /* Set ret_val to 0 to continue with normal execution. - * Set ret_val to 1 to trigger a breakpoint. - */ - - if(IsDebuggerPresent()) - *ret_val = 1; - else - *ret_val = 0; - } - - /* Don't call _CrtDbgReport. */ - return TRUE; -} -#else -UV_THREAD_LOCAL int uv__crt_assert_enabled = FALSE; -#endif - - -#if !defined(__MINGW32__) || __MSVCRT_VERSION__ >= 0x800 -static void uv__crt_invalid_parameter_handler(const wchar_t* expression, - const wchar_t* function, const wchar_t * file, unsigned int line, - uintptr_t reserved) { - /* No-op. */ -} -#endif - -static uv_loop_t** uv__loops; -static int uv__loops_size; -static int uv__loops_capacity; -#define UV__LOOPS_CHUNK_SIZE 8 -static uv_mutex_t uv__loops_lock; - -static void uv__loops_init() { - uv_mutex_init(&uv__loops_lock); - uv__loops = uv__calloc(UV__LOOPS_CHUNK_SIZE, sizeof(uv_loop_t*)); - if (!uv__loops) - uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc"); - uv__loops_size = 0; - uv__loops_capacity = UV__LOOPS_CHUNK_SIZE; -} - -static int uv__loops_add(uv_loop_t* loop) { - uv_loop_t** new_loops; - int new_capacity, i; - - uv_mutex_lock(&uv__loops_lock); - - if (uv__loops_size == uv__loops_capacity) { - new_capacity = uv__loops_capacity + UV__LOOPS_CHUNK_SIZE; - new_loops = uv__realloc(uv__loops, sizeof(uv_loop_t*) * new_capacity); - if (!new_loops) - goto failed_loops_realloc; - uv__loops = new_loops; - for (i = uv__loops_capacity; i < new_capacity; ++i) - uv__loops[i] = NULL; - uv__loops_capacity = new_capacity; - } - uv__loops[uv__loops_size] = loop; - ++uv__loops_size; - - uv_mutex_unlock(&uv__loops_lock); - return 0; - -failed_loops_realloc: - uv_mutex_unlock(&uv__loops_lock); - return ERROR_OUTOFMEMORY; -} - -static void uv__loops_remove(uv_loop_t* loop) { - int loop_index; - int smaller_capacity; - uv_loop_t** new_loops; - - uv_mutex_lock(&uv__loops_lock); - - for (loop_index = 0; loop_index < uv__loops_size; ++loop_index) { - if (uv__loops[loop_index] == loop) - break; - } - /* If loop was not found, ignore */ - if (loop_index == uv__loops_size) - goto loop_removed; - - uv__loops[loop_index] = uv__loops[uv__loops_size - 1]; - uv__loops[uv__loops_size - 1] = NULL; - --uv__loops_size; - - /* If we didn't grow to big skip downsizing */ - if (uv__loops_capacity < 4 * UV__LOOPS_CHUNK_SIZE) - goto loop_removed; - - /* Downsize only if more than half of buffer is free */ - smaller_capacity = uv__loops_capacity / 2; - if (uv__loops_size >= smaller_capacity) - goto loop_removed; - new_loops = uv__realloc(uv__loops, sizeof(uv_loop_t*) * smaller_capacity); - if (!new_loops) - goto loop_removed; - uv__loops = new_loops; - uv__loops_capacity = smaller_capacity; - -loop_removed: - uv_mutex_unlock(&uv__loops_lock); -} - -void uv__wake_all_loops() { - int i; - uv_loop_t* loop; - - uv_mutex_lock(&uv__loops_lock); - for (i = 0; i < uv__loops_size; ++i) { - loop = uv__loops[i]; - assert(loop); - if (loop->iocp != INVALID_HANDLE_VALUE) - PostQueuedCompletionStatus(loop->iocp, 0, 0, NULL); - } - uv_mutex_unlock(&uv__loops_lock); -} - -static void uv_init(void) { - /* Tell Windows that we will handle critical errors. */ - SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | - SEM_NOOPENFILEERRORBOX); - - /* Tell the CRT to not exit the application when an invalid parameter is - * passed. The main issue is that invalid FDs will trigger this behavior. - */ -#if !defined(__MINGW32__) || __MSVCRT_VERSION__ >= 0x800 - _set_invalid_parameter_handler(uv__crt_invalid_parameter_handler); -#endif - - /* We also need to setup our debug report handler because some CRT - * functions (eg _get_osfhandle) raise an assert when called with invalid - * FDs even though they return the proper error code in the release build. - */ -#if defined(_DEBUG) && (defined(_MSC_VER) || defined(__MINGW64_VERSION_MAJOR)) - _CrtSetReportHook(uv__crt_dbg_report_handler); -#endif - - /* Initialize tracking of all uv loops */ - uv__loops_init(); - - /* Fetch winapi function pointers. This must be done first because other - * initialization code might need these function pointers to be loaded. - */ - uv_winapi_init(); - - /* Initialize winsock */ - uv_winsock_init(); - - /* Initialize FS */ - uv_fs_init(); - - /* Initialize signal stuff */ - uv_signals_init(); - - /* Initialize console */ - uv_console_init(); - - /* Initialize utilities */ - uv__util_init(); - - /* Initialize system wakeup detection */ - uv__init_detect_system_wakeup(); -} - - -int uv_loop_init(uv_loop_t* loop) { - int err; - - /* Initialize libuv itself first */ - uv__once_init(); - - /* Create an I/O completion port */ - loop->iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 1); - if (loop->iocp == NULL) - return uv_translate_sys_error(GetLastError()); - - /* To prevent uninitialized memory access, loop->time must be initialized - * to zero before calling uv_update_time for the first time. - */ - loop->time = 0; - uv_update_time(loop); - - QUEUE_INIT(&loop->wq); - QUEUE_INIT(&loop->handle_queue); - QUEUE_INIT(&loop->active_reqs); - loop->active_handles = 0; - - loop->pending_reqs_tail = NULL; - - loop->endgame_handles = NULL; - - RB_INIT(&loop->timers); - - loop->check_handles = NULL; - loop->prepare_handles = NULL; - loop->idle_handles = NULL; - - loop->next_prepare_handle = NULL; - loop->next_check_handle = NULL; - loop->next_idle_handle = NULL; - - memset(&loop->poll_peer_sockets, 0, sizeof loop->poll_peer_sockets); - - loop->active_tcp_streams = 0; - loop->active_udp_streams = 0; - - loop->timer_counter = 0; - loop->stop_flag = 0; - - err = uv_mutex_init(&loop->wq_mutex); - if (err) - goto fail_mutex_init; - - err = uv_async_init(loop, &loop->wq_async, uv__work_done); - if (err) - goto fail_async_init; - - uv__handle_unref(&loop->wq_async); - loop->wq_async.flags |= UV__HANDLE_INTERNAL; - - err = uv__loops_add(loop); - if (err) - goto fail_async_init; - - return 0; - -fail_async_init: - uv_mutex_destroy(&loop->wq_mutex); - -fail_mutex_init: - CloseHandle(loop->iocp); - loop->iocp = INVALID_HANDLE_VALUE; - - return err; -} - - -void uv__once_init(void) { - uv_once(&uv_init_guard_, uv_init); -} - - -void uv__loop_close(uv_loop_t* loop) { - size_t i; - - uv__loops_remove(loop); - - /* close the async handle without needing an extra loop iteration */ - assert(!loop->wq_async.async_sent); - loop->wq_async.close_cb = NULL; - uv__handle_closing(&loop->wq_async); - uv__handle_close(&loop->wq_async); - - for (i = 0; i < ARRAY_SIZE(loop->poll_peer_sockets); i++) { - SOCKET sock = loop->poll_peer_sockets[i]; - if (sock != 0 && sock != INVALID_SOCKET) - closesocket(sock); - } - - uv_mutex_lock(&loop->wq_mutex); - assert(QUEUE_EMPTY(&loop->wq) && "thread pool work queue not empty!"); - assert(!uv__has_active_reqs(loop)); - uv_mutex_unlock(&loop->wq_mutex); - uv_mutex_destroy(&loop->wq_mutex); - - CloseHandle(loop->iocp); -} - - -int uv__loop_configure(uv_loop_t* loop, uv_loop_option option, va_list ap) { - return UV_ENOSYS; -} - - -int uv_backend_fd(const uv_loop_t* loop) { - return -1; -} - - -int uv_backend_timeout(const uv_loop_t* loop) { - if (loop->stop_flag != 0) - return 0; - - if (!uv__has_active_handles(loop) && !uv__has_active_reqs(loop)) - return 0; - - if (loop->pending_reqs_tail) - return 0; - - if (loop->endgame_handles) - return 0; - - if (loop->idle_handles) - return 0; - - return uv__next_timeout(loop); -} - - -static void uv_poll(uv_loop_t* loop, DWORD timeout) { - DWORD bytes; - ULONG_PTR key; - OVERLAPPED* overlapped; - uv_req_t* req; - int repeat; - uint64_t timeout_time; - - timeout_time = loop->time + timeout; - - for (repeat = 0; ; repeat++) { - GetQueuedCompletionStatus(loop->iocp, - &bytes, - &key, - &overlapped, - timeout); - - if (overlapped) { - /* Package was dequeued */ - req = uv_overlapped_to_req(overlapped); - uv_insert_pending_req(loop, req); - - /* Some time might have passed waiting for I/O, - * so update the loop time here. - */ - uv_update_time(loop); - } else if (GetLastError() != WAIT_TIMEOUT) { - /* Serious error */ - uv_fatal_error(GetLastError(), "GetQueuedCompletionStatus"); - } else if (timeout > 0) { - /* GetQueuedCompletionStatus can occasionally return a little early. - * Make sure that the desired timeout target time is reached. - */ - uv_update_time(loop); - if (timeout_time > loop->time) { - timeout = (DWORD)(timeout_time - loop->time); - /* The first call to GetQueuedCompletionStatus should return very - * close to the target time and the second should reach it, but - * this is not stated in the documentation. To make sure a busy - * loop cannot happen, the timeout is increased exponentially - * starting on the third round. - */ - timeout += repeat ? (1 << (repeat - 1)) : 0; - continue; - } - } - break; - } -} - - -static void uv_poll_ex(uv_loop_t* loop, DWORD timeout) { - BOOL success; - uv_req_t* req; - OVERLAPPED_ENTRY overlappeds[128]; - ULONG count; - ULONG i; - int repeat; - uint64_t timeout_time; - - timeout_time = loop->time + timeout; - - for (repeat = 0; ; repeat++) { - success = pGetQueuedCompletionStatusEx(loop->iocp, - overlappeds, - ARRAY_SIZE(overlappeds), - &count, - timeout, - FALSE); - - if (success) { - for (i = 0; i < count; i++) { - /* Package was dequeued, but see if it is not a empty package - * meant only to wake us up. - */ - if (overlappeds[i].lpOverlapped) { - req = uv_overlapped_to_req(overlappeds[i].lpOverlapped); - uv_insert_pending_req(loop, req); - } - } - - /* Some time might have passed waiting for I/O, - * so update the loop time here. - */ - uv_update_time(loop); - } else if (GetLastError() != WAIT_TIMEOUT) { - /* Serious error */ - uv_fatal_error(GetLastError(), "GetQueuedCompletionStatusEx"); - } else if (timeout > 0) { - /* GetQueuedCompletionStatus can occasionally return a little early. - * Make sure that the desired timeout target time is reached. - */ - uv_update_time(loop); - if (timeout_time > loop->time) { - timeout = (DWORD)(timeout_time - loop->time); - /* The first call to GetQueuedCompletionStatus should return very - * close to the target time and the second should reach it, but - * this is not stated in the documentation. To make sure a busy - * loop cannot happen, the timeout is increased exponentially - * starting on the third round. - */ - timeout += repeat ? (1 << (repeat - 1)) : 0; - continue; - } - } - break; - } -} - - -static int uv__loop_alive(const uv_loop_t* loop) { - return loop->active_handles > 0 || - !QUEUE_EMPTY(&loop->active_reqs) || - loop->endgame_handles != NULL; -} - - -int uv_loop_alive(const uv_loop_t* loop) { - return uv__loop_alive(loop); -} - - -int uv_run(uv_loop_t *loop, uv_run_mode mode) { - DWORD timeout; - int r; - int ran_pending; - void (*poll)(uv_loop_t* loop, DWORD timeout); - - if (pGetQueuedCompletionStatusEx) - poll = &uv_poll_ex; - else - poll = &uv_poll; - - r = uv__loop_alive(loop); - if (!r) - uv_update_time(loop); - - while (r != 0 && loop->stop_flag == 0) { - uv_update_time(loop); - uv_process_timers(loop); - - ran_pending = uv_process_reqs(loop); - uv_idle_invoke(loop); - uv_prepare_invoke(loop); - - timeout = 0; - if ((mode == UV_RUN_ONCE && !ran_pending) || mode == UV_RUN_DEFAULT) - timeout = uv_backend_timeout(loop); - - (*poll)(loop, timeout); - - uv_check_invoke(loop); - uv_process_endgames(loop); - - if (mode == UV_RUN_ONCE) { - /* UV_RUN_ONCE implies forward progress: at least one callback must have - * been invoked when it returns. uv__io_poll() can return without doing - * I/O (meaning: no callbacks) when its timeout expires - which means we - * have pending timers that satisfy the forward progress constraint. - * - * UV_RUN_NOWAIT makes no guarantees about progress so it's omitted from - * the check. - */ - uv_process_timers(loop); - } - - r = uv__loop_alive(loop); - if (mode == UV_RUN_ONCE || mode == UV_RUN_NOWAIT) - break; - } - - /* The if statement lets the compiler compile it to a conditional store. - * Avoids dirtying a cache line. - */ - if (loop->stop_flag != 0) - loop->stop_flag = 0; - - return r; -} - - -int uv_fileno(const uv_handle_t* handle, uv_os_fd_t* fd) { - uv_os_fd_t fd_out; - - switch (handle->type) { - case UV_TCP: - fd_out = (uv_os_fd_t)((uv_tcp_t*) handle)->socket; - break; - - case UV_NAMED_PIPE: - fd_out = ((uv_pipe_t*) handle)->handle; - break; - - case UV_TTY: - fd_out = ((uv_tty_t*) handle)->handle; - break; - - case UV_UDP: - fd_out = (uv_os_fd_t)((uv_udp_t*) handle)->socket; - break; - - case UV_POLL: - fd_out = (uv_os_fd_t)((uv_poll_t*) handle)->socket; - break; - - default: - return UV_EINVAL; - } - - if (uv_is_closing(handle) || fd_out == INVALID_HANDLE_VALUE) - return UV_EBADF; - - *fd = fd_out; - return 0; -} - - -int uv__socket_sockopt(uv_handle_t* handle, int optname, int* value) { - int r; - int len; - SOCKET socket; - - if (handle == NULL || value == NULL) - return UV_EINVAL; - - if (handle->type == UV_TCP) - socket = ((uv_tcp_t*) handle)->socket; - else if (handle->type == UV_UDP) - socket = ((uv_udp_t*) handle)->socket; - else - return UV_ENOTSUP; - - len = sizeof(*value); - - if (*value == 0) - r = getsockopt(socket, SOL_SOCKET, optname, (char*) value, &len); - else - r = setsockopt(socket, SOL_SOCKET, optname, (const char*) value, len); - - if (r == SOCKET_ERROR) - return uv_translate_sys_error(WSAGetLastError()); - - return 0; -} diff --git a/vendor/libuv/src/win/detect-wakeup.c b/vendor/libuv/src/win/detect-wakeup.c deleted file mode 100644 index a12179f79..000000000 --- a/vendor/libuv/src/win/detect-wakeup.c +++ /dev/null @@ -1,35 +0,0 @@ -#include "uv.h" -#include "internal.h" -#include "winapi.h" - -static void uv__register_system_resume_callback(); - -void uv__init_detect_system_wakeup() { - /* Try registering system power event callback. This is the cleanest - * method, but it will only work on Win8 and above. - */ - uv__register_system_resume_callback(); -} - -static ULONG CALLBACK uv__system_resume_callback(PVOID Context, - ULONG Type, - PVOID Setting) { - if (Type == PBT_APMRESUMESUSPEND || Type == PBT_APMRESUMEAUTOMATIC) - uv__wake_all_loops(); - - return 0; -} - -static void uv__register_system_resume_callback() { - _DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS recipient; - _HPOWERNOTIFY registration_handle; - - if (pPowerRegisterSuspendResumeNotification == NULL) - return; - - recipient.Callback = uv__system_resume_callback; - recipient.Context = NULL; - (*pPowerRegisterSuspendResumeNotification)(DEVICE_NOTIFY_CALLBACK, - &recipient, - ®istration_handle); -} diff --git a/vendor/libuv/src/win/dl.c b/vendor/libuv/src/win/dl.c deleted file mode 100644 index 39e400ab2..000000000 --- a/vendor/libuv/src/win/dl.c +++ /dev/null @@ -1,118 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "internal.h" - -static int uv__dlerror(uv_lib_t* lib, int errorno); - - -int uv_dlopen(const char* filename, uv_lib_t* lib) { - WCHAR filename_w[32768]; - - lib->handle = NULL; - lib->errmsg = NULL; - - if (!MultiByteToWideChar(CP_UTF8, - 0, - filename, - -1, - filename_w, - ARRAY_SIZE(filename_w))) { - return uv__dlerror(lib, GetLastError()); - } - - lib->handle = LoadLibraryExW(filename_w, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); - if (lib->handle == NULL) { - return uv__dlerror(lib, GetLastError()); - } - - return 0; -} - - -void uv_dlclose(uv_lib_t* lib) { - if (lib->errmsg) { - LocalFree((void*)lib->errmsg); - lib->errmsg = NULL; - } - - if (lib->handle) { - /* Ignore errors. No good way to signal them without leaking memory. */ - FreeLibrary(lib->handle); - lib->handle = NULL; - } -} - - -int uv_dlsym(uv_lib_t* lib, const char* name, void** ptr) { - *ptr = (void*) GetProcAddress(lib->handle, name); - return uv__dlerror(lib, *ptr ? 0 : GetLastError()); -} - - -const char* uv_dlerror(const uv_lib_t* lib) { - return lib->errmsg ? lib->errmsg : "no error"; -} - - -static void uv__format_fallback_error(uv_lib_t* lib, int errorno){ - DWORD_PTR args[1] = { (DWORD_PTR) errorno }; - LPSTR fallback_error = "error: %1!d!"; - - FormatMessageA(FORMAT_MESSAGE_FROM_STRING | - FORMAT_MESSAGE_ARGUMENT_ARRAY | - FORMAT_MESSAGE_ALLOCATE_BUFFER, - fallback_error, 0, 0, - (LPSTR) &lib->errmsg, - 0, (va_list*) args); -} - - - -static int uv__dlerror(uv_lib_t* lib, int errorno) { - DWORD res; - - if (lib->errmsg) { - LocalFree((void*)lib->errmsg); - lib->errmsg = NULL; - } - - if (errorno) { - res = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorno, - MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), - (LPSTR) &lib->errmsg, 0, NULL); - if (!res && GetLastError() == ERROR_MUI_FILE_NOT_FOUND) { - res = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorno, - 0, (LPSTR) &lib->errmsg, 0, NULL); - } - - if (!res) { - uv__format_fallback_error(lib, errorno); - } - } - - return errorno ? -1 : 0; -} diff --git a/vendor/libuv/src/win/error.c b/vendor/libuv/src/win/error.c deleted file mode 100644 index 642d1112e..000000000 --- a/vendor/libuv/src/win/error.c +++ /dev/null @@ -1,171 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include -#include -#include -#include -#include - -#include "uv.h" -#include "internal.h" - - -/* - * Display an error message and abort the event loop. - */ -void uv_fatal_error(const int errorno, const char* syscall) { - char* buf = NULL; - const char* errmsg; - - FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorno, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&buf, 0, NULL); - - if (buf) { - errmsg = buf; - } else { - errmsg = "Unknown error"; - } - - /* FormatMessage messages include a newline character already, */ - /* so don't add another. */ - if (syscall) { - fprintf(stderr, "%s: (%d) %s", syscall, errorno, errmsg); - } else { - fprintf(stderr, "(%d) %s", errorno, errmsg); - } - - if (buf) { - LocalFree(buf); - } - - *((char*)NULL) = 0xff; /* Force debug break */ - abort(); -} - - -int uv_translate_sys_error(int sys_errno) { - if (sys_errno <= 0) { - return sys_errno; /* If < 0 then it's already a libuv error. */ - } - - switch (sys_errno) { - case ERROR_NOACCESS: return UV_EACCES; - case WSAEACCES: return UV_EACCES; - case ERROR_ELEVATION_REQUIRED: return UV_EACCES; - case ERROR_ADDRESS_ALREADY_ASSOCIATED: return UV_EADDRINUSE; - case WSAEADDRINUSE: return UV_EADDRINUSE; - case WSAEADDRNOTAVAIL: return UV_EADDRNOTAVAIL; - case WSAEAFNOSUPPORT: return UV_EAFNOSUPPORT; - case WSAEWOULDBLOCK: return UV_EAGAIN; - case WSAEALREADY: return UV_EALREADY; - case ERROR_INVALID_FLAGS: return UV_EBADF; - case ERROR_INVALID_HANDLE: return UV_EBADF; - case ERROR_LOCK_VIOLATION: return UV_EBUSY; - case ERROR_PIPE_BUSY: return UV_EBUSY; - case ERROR_SHARING_VIOLATION: return UV_EBUSY; - case ERROR_OPERATION_ABORTED: return UV_ECANCELED; - case WSAEINTR: return UV_ECANCELED; - case ERROR_NO_UNICODE_TRANSLATION: return UV_ECHARSET; - case ERROR_CONNECTION_ABORTED: return UV_ECONNABORTED; - case WSAECONNABORTED: return UV_ECONNABORTED; - case ERROR_CONNECTION_REFUSED: return UV_ECONNREFUSED; - case WSAECONNREFUSED: return UV_ECONNREFUSED; - case ERROR_NETNAME_DELETED: return UV_ECONNRESET; - case WSAECONNRESET: return UV_ECONNRESET; - case ERROR_ALREADY_EXISTS: return UV_EEXIST; - case ERROR_FILE_EXISTS: return UV_EEXIST; - case ERROR_BUFFER_OVERFLOW: return UV_EFAULT; - case WSAEFAULT: return UV_EFAULT; - case ERROR_HOST_UNREACHABLE: return UV_EHOSTUNREACH; - case WSAEHOSTUNREACH: return UV_EHOSTUNREACH; - case ERROR_INSUFFICIENT_BUFFER: return UV_EINVAL; - case ERROR_INVALID_DATA: return UV_EINVAL; - case ERROR_INVALID_PARAMETER: return UV_EINVAL; - case ERROR_SYMLINK_NOT_SUPPORTED: return UV_EINVAL; - case WSAEINVAL: return UV_EINVAL; - case WSAEPFNOSUPPORT: return UV_EINVAL; - case WSAESOCKTNOSUPPORT: return UV_EINVAL; - case ERROR_BEGINNING_OF_MEDIA: return UV_EIO; - case ERROR_BUS_RESET: return UV_EIO; - case ERROR_CRC: return UV_EIO; - case ERROR_DEVICE_DOOR_OPEN: return UV_EIO; - case ERROR_DEVICE_REQUIRES_CLEANING: return UV_EIO; - case ERROR_DISK_CORRUPT: return UV_EIO; - case ERROR_EOM_OVERFLOW: return UV_EIO; - case ERROR_FILEMARK_DETECTED: return UV_EIO; - case ERROR_GEN_FAILURE: return UV_EIO; - case ERROR_INVALID_BLOCK_LENGTH: return UV_EIO; - case ERROR_IO_DEVICE: return UV_EIO; - case ERROR_NO_DATA_DETECTED: return UV_EIO; - case ERROR_NO_SIGNAL_SENT: return UV_EIO; - case ERROR_OPEN_FAILED: return UV_EIO; - case ERROR_SETMARK_DETECTED: return UV_EIO; - case ERROR_SIGNAL_REFUSED: return UV_EIO; - case WSAEISCONN: return UV_EISCONN; - case ERROR_CANT_RESOLVE_FILENAME: return UV_ELOOP; - case ERROR_TOO_MANY_OPEN_FILES: return UV_EMFILE; - case WSAEMFILE: return UV_EMFILE; - case WSAEMSGSIZE: return UV_EMSGSIZE; - case ERROR_FILENAME_EXCED_RANGE: return UV_ENAMETOOLONG; - case ERROR_NETWORK_UNREACHABLE: return UV_ENETUNREACH; - case WSAENETUNREACH: return UV_ENETUNREACH; - case WSAENOBUFS: return UV_ENOBUFS; - case ERROR_BAD_PATHNAME: return UV_ENOENT; - case ERROR_DIRECTORY: return UV_ENOENT; - case ERROR_FILE_NOT_FOUND: return UV_ENOENT; - case ERROR_INVALID_NAME: return UV_ENOENT; - case ERROR_INVALID_DRIVE: return UV_ENOENT; - case ERROR_INVALID_REPARSE_DATA: return UV_ENOENT; - case ERROR_MOD_NOT_FOUND: return UV_ENOENT; - case ERROR_PATH_NOT_FOUND: return UV_ENOENT; - case WSAHOST_NOT_FOUND: return UV_ENOENT; - case WSANO_DATA: return UV_ENOENT; - case ERROR_NOT_ENOUGH_MEMORY: return UV_ENOMEM; - case ERROR_OUTOFMEMORY: return UV_ENOMEM; - case ERROR_CANNOT_MAKE: return UV_ENOSPC; - case ERROR_DISK_FULL: return UV_ENOSPC; - case ERROR_EA_TABLE_FULL: return UV_ENOSPC; - case ERROR_END_OF_MEDIA: return UV_ENOSPC; - case ERROR_HANDLE_DISK_FULL: return UV_ENOSPC; - case ERROR_NOT_CONNECTED: return UV_ENOTCONN; - case WSAENOTCONN: return UV_ENOTCONN; - case ERROR_DIR_NOT_EMPTY: return UV_ENOTEMPTY; - case WSAENOTSOCK: return UV_ENOTSOCK; - case ERROR_NOT_SUPPORTED: return UV_ENOTSUP; - case ERROR_BROKEN_PIPE: return UV_EOF; - case ERROR_ACCESS_DENIED: return UV_EPERM; - case ERROR_PRIVILEGE_NOT_HELD: return UV_EPERM; - case ERROR_BAD_PIPE: return UV_EPIPE; - case ERROR_NO_DATA: return UV_EPIPE; - case ERROR_PIPE_NOT_CONNECTED: return UV_EPIPE; - case WSAESHUTDOWN: return UV_EPIPE; - case WSAEPROTONOSUPPORT: return UV_EPROTONOSUPPORT; - case ERROR_WRITE_PROTECT: return UV_EROFS; - case ERROR_SEM_TIMEOUT: return UV_ETIMEDOUT; - case WSAETIMEDOUT: return UV_ETIMEDOUT; - case ERROR_NOT_SAME_DEVICE: return UV_EXDEV; - case ERROR_INVALID_FUNCTION: return UV_EISDIR; - case ERROR_META_EXPANSION_TOO_LONG: return UV_E2BIG; - default: return UV_UNKNOWN; - } -} diff --git a/vendor/libuv/src/win/fs-event.c b/vendor/libuv/src/win/fs-event.c deleted file mode 100644 index 03e4adc05..000000000 --- a/vendor/libuv/src/win/fs-event.c +++ /dev/null @@ -1,545 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include -#include -#include -#include - -#include "uv.h" -#include "internal.h" -#include "handle-inl.h" -#include "req-inl.h" - - -const unsigned int uv_directory_watcher_buffer_size = 4096; - - -static void uv_fs_event_queue_readdirchanges(uv_loop_t* loop, - uv_fs_event_t* handle) { - assert(handle->dir_handle != INVALID_HANDLE_VALUE); - assert(!handle->req_pending); - - memset(&(handle->req.u.io.overlapped), 0, - sizeof(handle->req.u.io.overlapped)); - if (!ReadDirectoryChangesW(handle->dir_handle, - handle->buffer, - uv_directory_watcher_buffer_size, - (handle->flags & UV_FS_EVENT_RECURSIVE) ? TRUE : FALSE, - FILE_NOTIFY_CHANGE_FILE_NAME | - FILE_NOTIFY_CHANGE_DIR_NAME | - FILE_NOTIFY_CHANGE_ATTRIBUTES | - FILE_NOTIFY_CHANGE_SIZE | - FILE_NOTIFY_CHANGE_LAST_WRITE | - FILE_NOTIFY_CHANGE_LAST_ACCESS | - FILE_NOTIFY_CHANGE_CREATION | - FILE_NOTIFY_CHANGE_SECURITY, - NULL, - &handle->req.u.io.overlapped, - NULL)) { - /* Make this req pending reporting an error. */ - SET_REQ_ERROR(&handle->req, GetLastError()); - uv_insert_pending_req(loop, (uv_req_t*)&handle->req); - } - - handle->req_pending = 1; -} - -static void uv_relative_path(const WCHAR* filename, - const WCHAR* dir, - WCHAR** relpath) { - size_t relpathlen; - size_t filenamelen = wcslen(filename); - size_t dirlen = wcslen(dir); - if (dirlen > 0 && dir[dirlen - 1] == '\\') - dirlen--; - relpathlen = filenamelen - dirlen - 1; - *relpath = uv__malloc((relpathlen + 1) * sizeof(WCHAR)); - if (!*relpath) - uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc"); - wcsncpy(*relpath, filename + dirlen + 1, relpathlen); - (*relpath)[relpathlen] = L'\0'; -} - -static int uv_split_path(const WCHAR* filename, WCHAR** dir, - WCHAR** file) { - int len = wcslen(filename); - int i = len; - while (i > 0 && filename[--i] != '\\' && filename[i] != '/'); - - if (i == 0) { - if (dir) { - *dir = (WCHAR*)uv__malloc((MAX_PATH + 1) * sizeof(WCHAR)); - if (!*dir) { - uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc"); - } - - if (!GetCurrentDirectoryW(MAX_PATH, *dir)) { - uv__free(*dir); - *dir = NULL; - return -1; - } - } - - *file = wcsdup(filename); - } else { - if (dir) { - *dir = (WCHAR*)uv__malloc((i + 2) * sizeof(WCHAR)); - if (!*dir) { - uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc"); - } - wcsncpy(*dir, filename, i + 1); - (*dir)[i + 1] = L'\0'; - } - - *file = (WCHAR*)uv__malloc((len - i) * sizeof(WCHAR)); - if (!*file) { - uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc"); - } - wcsncpy(*file, filename + i + 1, len - i - 1); - (*file)[len - i - 1] = L'\0'; - } - - return 0; -} - - -int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) { - uv__handle_init(loop, (uv_handle_t*) handle, UV_FS_EVENT); - handle->dir_handle = INVALID_HANDLE_VALUE; - handle->buffer = NULL; - handle->req_pending = 0; - handle->filew = NULL; - handle->short_filew = NULL; - handle->dirw = NULL; - - uv_req_init(loop, (uv_req_t*)&handle->req); - handle->req.type = UV_FS_EVENT_REQ; - handle->req.data = handle; - - return 0; -} - - -int uv_fs_event_start(uv_fs_event_t* handle, - uv_fs_event_cb cb, - const char* path, - unsigned int flags) { - int name_size, is_path_dir; - DWORD attr, last_error; - WCHAR* dir = NULL, *dir_to_watch, *pathw = NULL; - WCHAR short_path[MAX_PATH]; - - if (uv__is_active(handle)) - return UV_EINVAL; - - handle->cb = cb; - handle->path = uv__strdup(path); - if (!handle->path) { - uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc"); - } - - uv__handle_start(handle); - - /* Convert name to UTF16. */ - - name_size = MultiByteToWideChar(CP_UTF8, 0, path, -1, NULL, 0) * - sizeof(WCHAR); - pathw = (WCHAR*)uv__malloc(name_size); - if (!pathw) { - uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc"); - } - - if (!MultiByteToWideChar(CP_UTF8, - 0, - path, - -1, - pathw, - name_size / sizeof(WCHAR))) { - return uv_translate_sys_error(GetLastError()); - } - - /* Determine whether path is a file or a directory. */ - attr = GetFileAttributesW(pathw); - if (attr == INVALID_FILE_ATTRIBUTES) { - last_error = GetLastError(); - goto error; - } - - is_path_dir = (attr & FILE_ATTRIBUTE_DIRECTORY) ? 1 : 0; - - if (is_path_dir) { - /* path is a directory, so that's the directory that we will watch. */ - handle->dirw = pathw; - dir_to_watch = pathw; - } else { - /* - * path is a file. So we split path into dir & file parts, and - * watch the dir directory. - */ - - /* Convert to short path. */ - if (!GetShortPathNameW(pathw, short_path, ARRAY_SIZE(short_path))) { - last_error = GetLastError(); - goto error; - } - - if (uv_split_path(pathw, &dir, &handle->filew) != 0) { - last_error = GetLastError(); - goto error; - } - - if (uv_split_path(short_path, NULL, &handle->short_filew) != 0) { - last_error = GetLastError(); - goto error; - } - - dir_to_watch = dir; - uv__free(pathw); - pathw = NULL; - } - - handle->dir_handle = CreateFileW(dir_to_watch, - FILE_LIST_DIRECTORY, - FILE_SHARE_READ | FILE_SHARE_DELETE | - FILE_SHARE_WRITE, - NULL, - OPEN_EXISTING, - FILE_FLAG_BACKUP_SEMANTICS | - FILE_FLAG_OVERLAPPED, - NULL); - - if (dir) { - uv__free(dir); - dir = NULL; - } - - if (handle->dir_handle == INVALID_HANDLE_VALUE) { - last_error = GetLastError(); - goto error; - } - - if (CreateIoCompletionPort(handle->dir_handle, - handle->loop->iocp, - (ULONG_PTR)handle, - 0) == NULL) { - last_error = GetLastError(); - goto error; - } - - if (!handle->buffer) { - handle->buffer = (char*)uv__malloc(uv_directory_watcher_buffer_size); - } - if (!handle->buffer) { - uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc"); - } - - memset(&(handle->req.u.io.overlapped), 0, - sizeof(handle->req.u.io.overlapped)); - - if (!ReadDirectoryChangesW(handle->dir_handle, - handle->buffer, - uv_directory_watcher_buffer_size, - (flags & UV_FS_EVENT_RECURSIVE) ? TRUE : FALSE, - FILE_NOTIFY_CHANGE_FILE_NAME | - FILE_NOTIFY_CHANGE_DIR_NAME | - FILE_NOTIFY_CHANGE_ATTRIBUTES | - FILE_NOTIFY_CHANGE_SIZE | - FILE_NOTIFY_CHANGE_LAST_WRITE | - FILE_NOTIFY_CHANGE_LAST_ACCESS | - FILE_NOTIFY_CHANGE_CREATION | - FILE_NOTIFY_CHANGE_SECURITY, - NULL, - &handle->req.u.io.overlapped, - NULL)) { - last_error = GetLastError(); - goto error; - } - - handle->req_pending = 1; - return 0; - -error: - if (handle->path) { - uv__free(handle->path); - handle->path = NULL; - } - - if (handle->filew) { - uv__free(handle->filew); - handle->filew = NULL; - } - - if (handle->short_filew) { - uv__free(handle->short_filew); - handle->short_filew = NULL; - } - - uv__free(pathw); - - if (handle->dir_handle != INVALID_HANDLE_VALUE) { - CloseHandle(handle->dir_handle); - handle->dir_handle = INVALID_HANDLE_VALUE; - } - - if (handle->buffer) { - uv__free(handle->buffer); - handle->buffer = NULL; - } - - return uv_translate_sys_error(last_error); -} - - -int uv_fs_event_stop(uv_fs_event_t* handle) { - if (!uv__is_active(handle)) - return 0; - - if (handle->dir_handle != INVALID_HANDLE_VALUE) { - CloseHandle(handle->dir_handle); - handle->dir_handle = INVALID_HANDLE_VALUE; - } - - uv__handle_stop(handle); - - if (handle->filew) { - uv__free(handle->filew); - handle->filew = NULL; - } - - if (handle->short_filew) { - uv__free(handle->short_filew); - handle->short_filew = NULL; - } - - if (handle->path) { - uv__free(handle->path); - handle->path = NULL; - } - - if (handle->dirw) { - uv__free(handle->dirw); - handle->dirw = NULL; - } - - return 0; -} - - -static int file_info_cmp(WCHAR* str, WCHAR* file_name, int file_name_len) { - int str_len; - - str_len = wcslen(str); - - /* - Since we only care about equality, return early if the strings - aren't the same length - */ - if (str_len != (file_name_len / sizeof(WCHAR))) - return -1; - - return _wcsnicmp(str, file_name, str_len); -} - - -void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req, - uv_fs_event_t* handle) { - FILE_NOTIFY_INFORMATION* file_info; - int err, sizew, size; - char* filename = NULL; - WCHAR* filenamew = NULL; - WCHAR* long_filenamew = NULL; - DWORD offset = 0; - - assert(req->type == UV_FS_EVENT_REQ); - assert(handle->req_pending); - handle->req_pending = 0; - - /* Don't report any callbacks if: - * - We're closing, just push the handle onto the endgame queue - * - We are not active, just ignore the callback - */ - if (!uv__is_active(handle)) { - if (handle->flags & UV__HANDLE_CLOSING) { - uv_want_endgame(loop, (uv_handle_t*) handle); - } - return; - } - - file_info = (FILE_NOTIFY_INFORMATION*)(handle->buffer + offset); - - if (REQ_SUCCESS(req)) { - if (req->u.io.overlapped.InternalHigh > 0) { - do { - file_info = (FILE_NOTIFY_INFORMATION*)((char*)file_info + offset); - assert(!filename); - assert(!filenamew); - assert(!long_filenamew); - - /* - * Fire the event only if we were asked to watch a directory, - * or if the filename filter matches. - */ - if (handle->dirw || - file_info_cmp(handle->filew, - file_info->FileName, - file_info->FileNameLength) == 0 || - file_info_cmp(handle->short_filew, - file_info->FileName, - file_info->FileNameLength) == 0) { - - if (handle->dirw) { - /* - * We attempt to resolve the long form of the file name explicitly. - * We only do this for file names that might still exist on disk. - * If this fails, we use the name given by ReadDirectoryChangesW. - * This may be the long form or the 8.3 short name in some cases. - */ - if (file_info->Action != FILE_ACTION_REMOVED && - file_info->Action != FILE_ACTION_RENAMED_OLD_NAME) { - /* Construct a full path to the file. */ - size = wcslen(handle->dirw) + - file_info->FileNameLength / sizeof(WCHAR) + 2; - - filenamew = (WCHAR*)uv__malloc(size * sizeof(WCHAR)); - if (!filenamew) { - uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc"); - } - - _snwprintf(filenamew, size, L"%s\\%.*s", handle->dirw, - file_info->FileNameLength / (DWORD)sizeof(WCHAR), - file_info->FileName); - - filenamew[size - 1] = L'\0'; - - /* Convert to long name. */ - size = GetLongPathNameW(filenamew, NULL, 0); - - if (size) { - long_filenamew = (WCHAR*)uv__malloc(size * sizeof(WCHAR)); - if (!long_filenamew) { - uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc"); - } - - size = GetLongPathNameW(filenamew, long_filenamew, size); - if (size) { - long_filenamew[size] = '\0'; - } else { - uv__free(long_filenamew); - long_filenamew = NULL; - } - } - - uv__free(filenamew); - - if (long_filenamew) { - /* Get the file name out of the long path. */ - uv_relative_path(long_filenamew, - handle->dirw, - &filenamew); - uv__free(long_filenamew); - long_filenamew = filenamew; - sizew = -1; - } else { - /* We couldn't get the long filename, use the one reported. */ - filenamew = file_info->FileName; - sizew = file_info->FileNameLength / sizeof(WCHAR); - } - } else { - /* - * Removed or renamed events cannot be resolved to the long form. - * We therefore use the name given by ReadDirectoryChangesW. - * This may be the long form or the 8.3 short name in some cases. - */ - filenamew = file_info->FileName; - sizew = file_info->FileNameLength / sizeof(WCHAR); - } - } else { - /* We already have the long name of the file, so just use it. */ - filenamew = handle->filew; - sizew = -1; - } - - /* Convert the filename to utf8. */ - uv__convert_utf16_to_utf8(filenamew, sizew, &filename); - - switch (file_info->Action) { - case FILE_ACTION_ADDED: - case FILE_ACTION_REMOVED: - case FILE_ACTION_RENAMED_OLD_NAME: - case FILE_ACTION_RENAMED_NEW_NAME: - handle->cb(handle, filename, UV_RENAME, 0); - break; - - case FILE_ACTION_MODIFIED: - handle->cb(handle, filename, UV_CHANGE, 0); - break; - } - - uv__free(filename); - filename = NULL; - uv__free(long_filenamew); - long_filenamew = NULL; - filenamew = NULL; - } - - offset = file_info->NextEntryOffset; - } while (offset && !(handle->flags & UV__HANDLE_CLOSING)); - } else { - handle->cb(handle, NULL, UV_CHANGE, 0); - } - } else { - err = GET_REQ_ERROR(req); - handle->cb(handle, NULL, 0, uv_translate_sys_error(err)); - } - - if (!(handle->flags & UV__HANDLE_CLOSING)) { - uv_fs_event_queue_readdirchanges(loop, handle); - } else { - uv_want_endgame(loop, (uv_handle_t*)handle); - } -} - - -void uv_fs_event_close(uv_loop_t* loop, uv_fs_event_t* handle) { - uv_fs_event_stop(handle); - - uv__handle_closing(handle); - - if (!handle->req_pending) { - uv_want_endgame(loop, (uv_handle_t*)handle); - } - -} - - -void uv_fs_event_endgame(uv_loop_t* loop, uv_fs_event_t* handle) { - if ((handle->flags & UV__HANDLE_CLOSING) && !handle->req_pending) { - assert(!(handle->flags & UV_HANDLE_CLOSED)); - - if (handle->buffer) { - uv__free(handle->buffer); - handle->buffer = NULL; - } - - uv__handle_close(handle); - } -} diff --git a/vendor/libuv/src/win/fs.c b/vendor/libuv/src/win/fs.c deleted file mode 100644 index 6902d4f1a..000000000 --- a/vendor/libuv/src/win/fs.c +++ /dev/null @@ -1,2494 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "uv.h" -#include "internal.h" -#include "req-inl.h" -#include "handle-inl.h" - -#include - - -#define UV_FS_FREE_PATHS 0x0002 -#define UV_FS_FREE_PTR 0x0008 -#define UV_FS_CLEANEDUP 0x0010 - - -#define QUEUE_FS_TP_JOB(loop, req) \ - do { \ - uv__req_register(loop, req); \ - uv__work_submit((loop), &(req)->work_req, uv__fs_work, uv__fs_done); \ - } while (0) - -#define SET_REQ_RESULT(req, result_value) \ - do { \ - req->result = (result_value); \ - if (req->result == -1) { \ - req->sys_errno_ = _doserrno; \ - req->result = uv_translate_sys_error(req->sys_errno_); \ - } \ - } while (0) - -#define SET_REQ_WIN32_ERROR(req, sys_errno) \ - do { \ - req->sys_errno_ = (sys_errno); \ - req->result = uv_translate_sys_error(req->sys_errno_); \ - } while (0) - -#define SET_REQ_UV_ERROR(req, uv_errno, sys_errno) \ - do { \ - req->result = (uv_errno); \ - req->sys_errno_ = (sys_errno); \ - } while (0) - -#define VERIFY_FD(fd, req) \ - if (fd == -1) { \ - req->result = UV_EBADF; \ - req->sys_errno_ = ERROR_INVALID_HANDLE; \ - return; \ - } - -#define FILETIME_TO_UINT(filetime) \ - (*((uint64_t*) &(filetime)) - 116444736000000000ULL) - -#define FILETIME_TO_TIME_T(filetime) \ - (FILETIME_TO_UINT(filetime) / 10000000ULL) - -#define FILETIME_TO_TIME_NS(filetime, secs) \ - ((FILETIME_TO_UINT(filetime) - (secs * 10000000ULL)) * 100) - -#define FILETIME_TO_TIMESPEC(ts, filetime) \ - do { \ - (ts).tv_sec = (long) FILETIME_TO_TIME_T(filetime); \ - (ts).tv_nsec = (long) FILETIME_TO_TIME_NS(filetime, (ts).tv_sec); \ - } while(0) - -#define TIME_T_TO_FILETIME(time, filetime_ptr) \ - do { \ - uint64_t bigtime = ((uint64_t) ((time) * 10000000ULL)) + \ - 116444736000000000ULL; \ - (filetime_ptr)->dwLowDateTime = bigtime & 0xFFFFFFFF; \ - (filetime_ptr)->dwHighDateTime = bigtime >> 32; \ - } while(0) - -#define IS_SLASH(c) ((c) == L'\\' || (c) == L'/') -#define IS_LETTER(c) (((c) >= L'a' && (c) <= L'z') || \ - ((c) >= L'A' && (c) <= L'Z')) - -const WCHAR JUNCTION_PREFIX[] = L"\\??\\"; -const WCHAR JUNCTION_PREFIX_LEN = 4; - -const WCHAR LONG_PATH_PREFIX[] = L"\\\\?\\"; -const WCHAR LONG_PATH_PREFIX_LEN = 4; - -const WCHAR UNC_PATH_PREFIX[] = L"\\\\?\\UNC\\"; -const WCHAR UNC_PATH_PREFIX_LEN = 8; - - -void uv_fs_init() { - _fmode = _O_BINARY; -} - - -INLINE static int fs__capture_path(uv_fs_t* req, const char* path, - const char* new_path, const int copy_path) { - char* buf; - char* pos; - ssize_t buf_sz = 0, path_len = 0, pathw_len = 0, new_pathw_len = 0; - - /* new_path can only be set if path is also set. */ - assert(new_path == NULL || path != NULL); - - if (path != NULL) { - pathw_len = MultiByteToWideChar(CP_UTF8, - 0, - path, - -1, - NULL, - 0); - if (pathw_len == 0) { - return GetLastError(); - } - - buf_sz += pathw_len * sizeof(WCHAR); - } - - if (path != NULL && copy_path) { - path_len = 1 + strlen(path); - buf_sz += path_len; - } - - if (new_path != NULL) { - new_pathw_len = MultiByteToWideChar(CP_UTF8, - 0, - new_path, - -1, - NULL, - 0); - if (new_pathw_len == 0) { - return GetLastError(); - } - - buf_sz += new_pathw_len * sizeof(WCHAR); - } - - - if (buf_sz == 0) { - req->file.pathw = NULL; - req->fs.info.new_pathw = NULL; - req->path = NULL; - return 0; - } - - buf = (char*) uv__malloc(buf_sz); - if (buf == NULL) { - return ERROR_OUTOFMEMORY; - } - - pos = buf; - - if (path != NULL) { - DWORD r = MultiByteToWideChar(CP_UTF8, - 0, - path, - -1, - (WCHAR*) pos, - pathw_len); - assert(r == (DWORD) pathw_len); - req->file.pathw = (WCHAR*) pos; - pos += r * sizeof(WCHAR); - } else { - req->file.pathw = NULL; - } - - if (new_path != NULL) { - DWORD r = MultiByteToWideChar(CP_UTF8, - 0, - new_path, - -1, - (WCHAR*) pos, - new_pathw_len); - assert(r == (DWORD) new_pathw_len); - req->fs.info.new_pathw = (WCHAR*) pos; - pos += r * sizeof(WCHAR); - } else { - req->fs.info.new_pathw = NULL; - } - - req->path = path; - if (path != NULL && copy_path) { - memcpy(pos, path, path_len); - assert(path_len == buf_sz - (pos - buf)); - req->path = pos; - } - - req->flags |= UV_FS_FREE_PATHS; - - return 0; -} - - - -INLINE static void uv_fs_req_init(uv_loop_t* loop, uv_fs_t* req, - uv_fs_type fs_type, const uv_fs_cb cb) { - uv_req_init(loop, (uv_req_t*) req); - - req->type = UV_FS; - req->loop = loop; - req->flags = 0; - req->fs_type = fs_type; - req->result = 0; - req->ptr = NULL; - req->path = NULL; - req->cb = cb; - memset(&req->fs, 0, sizeof(req->fs)); -} - - -static int fs__wide_to_utf8(WCHAR* w_source_ptr, - DWORD w_source_len, - char** target_ptr, - uint64_t* target_len_ptr) { - int r; - int target_len; - char* target; - target_len = WideCharToMultiByte(CP_UTF8, - 0, - w_source_ptr, - w_source_len, - NULL, - 0, - NULL, - NULL); - - if (target_len == 0) { - return -1; - } - - if (target_len_ptr != NULL) { - *target_len_ptr = target_len; - } - - if (target_ptr == NULL) { - return 0; - } - - target = uv__malloc(target_len + 1); - if (target == NULL) { - SetLastError(ERROR_OUTOFMEMORY); - return -1; - } - - r = WideCharToMultiByte(CP_UTF8, - 0, - w_source_ptr, - w_source_len, - target, - target_len, - NULL, - NULL); - assert(r == target_len); - target[target_len] = '\0'; - *target_ptr = target; - return 0; -} - - -INLINE static int fs__readlink_handle(HANDLE handle, char** target_ptr, - uint64_t* target_len_ptr) { - char buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; - REPARSE_DATA_BUFFER* reparse_data = (REPARSE_DATA_BUFFER*) buffer; - WCHAR* w_target; - DWORD w_target_len; - DWORD bytes; - - if (!DeviceIoControl(handle, - FSCTL_GET_REPARSE_POINT, - NULL, - 0, - buffer, - sizeof buffer, - &bytes, - NULL)) { - return -1; - } - - if (reparse_data->ReparseTag == IO_REPARSE_TAG_SYMLINK) { - /* Real symlink */ - w_target = reparse_data->SymbolicLinkReparseBuffer.PathBuffer + - (reparse_data->SymbolicLinkReparseBuffer.SubstituteNameOffset / - sizeof(WCHAR)); - w_target_len = - reparse_data->SymbolicLinkReparseBuffer.SubstituteNameLength / - sizeof(WCHAR); - - /* Real symlinks can contain pretty much everything, but the only thing */ - /* we really care about is undoing the implicit conversion to an NT */ - /* namespaced path that CreateSymbolicLink will perform on absolute */ - /* paths. If the path is win32-namespaced then the user must have */ - /* explicitly made it so, and we better just return the unmodified */ - /* reparse data. */ - if (w_target_len >= 4 && - w_target[0] == L'\\' && - w_target[1] == L'?' && - w_target[2] == L'?' && - w_target[3] == L'\\') { - /* Starts with \??\ */ - if (w_target_len >= 6 && - ((w_target[4] >= L'A' && w_target[4] <= L'Z') || - (w_target[4] >= L'a' && w_target[4] <= L'z')) && - w_target[5] == L':' && - (w_target_len == 6 || w_target[6] == L'\\')) { - /* \??\:\ */ - w_target += 4; - w_target_len -= 4; - - } else if (w_target_len >= 8 && - (w_target[4] == L'U' || w_target[4] == L'u') && - (w_target[5] == L'N' || w_target[5] == L'n') && - (w_target[6] == L'C' || w_target[6] == L'c') && - w_target[7] == L'\\') { - /* \??\UNC\\\ - make sure the final path looks like */ - /* \\\\ */ - w_target += 6; - w_target[0] = L'\\'; - w_target_len -= 6; - } - } - - } else if (reparse_data->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) { - /* Junction. */ - w_target = reparse_data->MountPointReparseBuffer.PathBuffer + - (reparse_data->MountPointReparseBuffer.SubstituteNameOffset / - sizeof(WCHAR)); - w_target_len = reparse_data->MountPointReparseBuffer.SubstituteNameLength / - sizeof(WCHAR); - - /* Only treat junctions that look like \??\:\ as symlink. */ - /* Junctions can also be used as mount points, like \??\Volume{}, */ - /* but that's confusing for programs since they wouldn't be able to */ - /* actually understand such a path when returned by uv_readlink(). */ - /* UNC paths are never valid for junctions so we don't care about them. */ - if (!(w_target_len >= 6 && - w_target[0] == L'\\' && - w_target[1] == L'?' && - w_target[2] == L'?' && - w_target[3] == L'\\' && - ((w_target[4] >= L'A' && w_target[4] <= L'Z') || - (w_target[4] >= L'a' && w_target[4] <= L'z')) && - w_target[5] == L':' && - (w_target_len == 6 || w_target[6] == L'\\'))) { - SetLastError(ERROR_SYMLINK_NOT_SUPPORTED); - return -1; - } - - /* Remove leading \??\ */ - w_target += 4; - w_target_len -= 4; - - } else { - /* Reparse tag does not indicate a symlink. */ - SetLastError(ERROR_SYMLINK_NOT_SUPPORTED); - return -1; - } - - return fs__wide_to_utf8(w_target, w_target_len, target_ptr, target_len_ptr); -} - - -void fs__open(uv_fs_t* req) { - DWORD access; - DWORD share; - DWORD disposition; - DWORD attributes = 0; - HANDLE file; - int fd, current_umask; - int flags = req->fs.info.file_flags; - - /* Obtain the active umask. umask() never fails and returns the previous */ - /* umask. */ - current_umask = umask(0); - umask(current_umask); - - /* convert flags and mode to CreateFile parameters */ - switch (flags & (_O_RDONLY | _O_WRONLY | _O_RDWR)) { - case _O_RDONLY: - access = FILE_GENERIC_READ; - break; - case _O_WRONLY: - access = FILE_GENERIC_WRITE; - break; - case _O_RDWR: - access = FILE_GENERIC_READ | FILE_GENERIC_WRITE; - break; - default: - goto einval; - } - - if (flags & _O_APPEND) { - access &= ~FILE_WRITE_DATA; - access |= FILE_APPEND_DATA; - } - - /* - * Here is where we deviate significantly from what CRT's _open() - * does. We indiscriminately use all the sharing modes, to match - * UNIX semantics. In particular, this ensures that the file can - * be deleted even whilst it's open, fixing issue #1449. - */ - share = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; - - switch (flags & (_O_CREAT | _O_EXCL | _O_TRUNC)) { - case 0: - case _O_EXCL: - disposition = OPEN_EXISTING; - break; - case _O_CREAT: - disposition = OPEN_ALWAYS; - break; - case _O_CREAT | _O_EXCL: - case _O_CREAT | _O_TRUNC | _O_EXCL: - disposition = CREATE_NEW; - break; - case _O_TRUNC: - case _O_TRUNC | _O_EXCL: - disposition = TRUNCATE_EXISTING; - break; - case _O_CREAT | _O_TRUNC: - disposition = CREATE_ALWAYS; - break; - default: - goto einval; - } - - attributes |= FILE_ATTRIBUTE_NORMAL; - if (flags & _O_CREAT) { - if (!((req->fs.info.mode & ~current_umask) & _S_IWRITE)) { - attributes |= FILE_ATTRIBUTE_READONLY; - } - } - - if (flags & _O_TEMPORARY ) { - attributes |= FILE_FLAG_DELETE_ON_CLOSE | FILE_ATTRIBUTE_TEMPORARY; - access |= DELETE; - } - - if (flags & _O_SHORT_LIVED) { - attributes |= FILE_ATTRIBUTE_TEMPORARY; - } - - switch (flags & (_O_SEQUENTIAL | _O_RANDOM)) { - case 0: - break; - case _O_SEQUENTIAL: - attributes |= FILE_FLAG_SEQUENTIAL_SCAN; - break; - case _O_RANDOM: - attributes |= FILE_FLAG_RANDOM_ACCESS; - break; - default: - goto einval; - } - - /* Setting this flag makes it possible to open a directory. */ - attributes |= FILE_FLAG_BACKUP_SEMANTICS; - - file = CreateFileW(req->file.pathw, - access, - share, - NULL, - disposition, - attributes, - NULL); - if (file == INVALID_HANDLE_VALUE) { - DWORD error = GetLastError(); - if (error == ERROR_FILE_EXISTS && (flags & _O_CREAT) && - !(flags & _O_EXCL)) { - /* Special case: when ERROR_FILE_EXISTS happens and O_CREAT was */ - /* specified, it means the path referred to a directory. */ - SET_REQ_UV_ERROR(req, UV_EISDIR, error); - } else { - SET_REQ_WIN32_ERROR(req, GetLastError()); - } - return; - } - - fd = _open_osfhandle((intptr_t) file, flags); - if (fd < 0) { - /* The only known failure mode for _open_osfhandle() is EMFILE, in which - * case GetLastError() will return zero. However we'll try to handle other - * errors as well, should they ever occur. - */ - if (errno == EMFILE) - SET_REQ_UV_ERROR(req, UV_EMFILE, ERROR_TOO_MANY_OPEN_FILES); - else if (GetLastError() != ERROR_SUCCESS) - SET_REQ_WIN32_ERROR(req, GetLastError()); - else - SET_REQ_WIN32_ERROR(req, UV_UNKNOWN); - CloseHandle(file); - return; - } - - SET_REQ_RESULT(req, fd); - return; - - einval: - SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_INVALID_PARAMETER); -} - -void fs__close(uv_fs_t* req) { - int fd = req->file.fd; - int result; - - VERIFY_FD(fd, req); - - if (fd > 2) - result = _close(fd); - else - result = 0; - - /* _close doesn't set _doserrno on failure, but it does always set errno - * to EBADF on failure. - */ - if (result == -1) { - assert(errno == EBADF); - SET_REQ_UV_ERROR(req, UV_EBADF, ERROR_INVALID_HANDLE); - } else { - req->result = 0; - } -} - - -void fs__read(uv_fs_t* req) { - int fd = req->file.fd; - int64_t offset = req->fs.info.offset; - HANDLE handle; - OVERLAPPED overlapped, *overlapped_ptr; - LARGE_INTEGER offset_; - DWORD bytes; - DWORD error; - int result; - unsigned int index; - - VERIFY_FD(fd, req); - - handle = uv__get_osfhandle(fd); - - if (handle == INVALID_HANDLE_VALUE) { - SET_REQ_WIN32_ERROR(req, ERROR_INVALID_HANDLE); - return; - } - - if (offset != -1) { - memset(&overlapped, 0, sizeof overlapped); - overlapped_ptr = &overlapped; - } else { - overlapped_ptr = NULL; - } - - index = 0; - bytes = 0; - do { - DWORD incremental_bytes; - - if (offset != -1) { - offset_.QuadPart = offset + bytes; - overlapped.Offset = offset_.LowPart; - overlapped.OffsetHigh = offset_.HighPart; - } - - result = ReadFile(handle, - req->fs.info.bufs[index].base, - req->fs.info.bufs[index].len, - &incremental_bytes, - overlapped_ptr); - bytes += incremental_bytes; - ++index; - } while (result && index < req->fs.info.nbufs); - - if (result || bytes > 0) { - SET_REQ_RESULT(req, bytes); - } else { - error = GetLastError(); - if (error == ERROR_HANDLE_EOF) { - SET_REQ_RESULT(req, bytes); - } else { - SET_REQ_WIN32_ERROR(req, error); - } - } -} - - -void fs__write(uv_fs_t* req) { - int fd = req->file.fd; - int64_t offset = req->fs.info.offset; - HANDLE handle; - OVERLAPPED overlapped, *overlapped_ptr; - LARGE_INTEGER offset_; - DWORD bytes; - int result; - unsigned int index; - - VERIFY_FD(fd, req); - - handle = uv__get_osfhandle(fd); - if (handle == INVALID_HANDLE_VALUE) { - SET_REQ_WIN32_ERROR(req, ERROR_INVALID_HANDLE); - return; - } - - if (offset != -1) { - memset(&overlapped, 0, sizeof overlapped); - overlapped_ptr = &overlapped; - } else { - overlapped_ptr = NULL; - } - - index = 0; - bytes = 0; - do { - DWORD incremental_bytes; - - if (offset != -1) { - offset_.QuadPart = offset + bytes; - overlapped.Offset = offset_.LowPart; - overlapped.OffsetHigh = offset_.HighPart; - } - - result = WriteFile(handle, - req->fs.info.bufs[index].base, - req->fs.info.bufs[index].len, - &incremental_bytes, - overlapped_ptr); - bytes += incremental_bytes; - ++index; - } while (result && index < req->fs.info.nbufs); - - if (result || bytes > 0) { - SET_REQ_RESULT(req, bytes); - } else { - SET_REQ_WIN32_ERROR(req, GetLastError()); - } -} - - -void fs__rmdir(uv_fs_t* req) { - int result = _wrmdir(req->file.pathw); - SET_REQ_RESULT(req, result); -} - - -void fs__unlink(uv_fs_t* req) { - const WCHAR* pathw = req->file.pathw; - HANDLE handle; - BY_HANDLE_FILE_INFORMATION info; - FILE_DISPOSITION_INFORMATION disposition; - IO_STATUS_BLOCK iosb; - NTSTATUS status; - - handle = CreateFileW(pathw, - FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES | DELETE, - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - NULL, - OPEN_EXISTING, - FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, - NULL); - - if (handle == INVALID_HANDLE_VALUE) { - SET_REQ_WIN32_ERROR(req, GetLastError()); - return; - } - - if (!GetFileInformationByHandle(handle, &info)) { - SET_REQ_WIN32_ERROR(req, GetLastError()); - CloseHandle(handle); - return; - } - - if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - /* Do not allow deletion of directories, unless it is a symlink. When */ - /* the path refers to a non-symlink directory, report EPERM as mandated */ - /* by POSIX.1. */ - - /* Check if it is a reparse point. If it's not, it's a normal directory. */ - if (!(info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) { - SET_REQ_WIN32_ERROR(req, ERROR_ACCESS_DENIED); - CloseHandle(handle); - return; - } - - /* Read the reparse point and check if it is a valid symlink. */ - /* If not, don't unlink. */ - if (fs__readlink_handle(handle, NULL, NULL) < 0) { - DWORD error = GetLastError(); - if (error == ERROR_SYMLINK_NOT_SUPPORTED) - error = ERROR_ACCESS_DENIED; - SET_REQ_WIN32_ERROR(req, error); - CloseHandle(handle); - return; - } - } - - if (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY) { - /* Remove read-only attribute */ - FILE_BASIC_INFORMATION basic = { 0 }; - - basic.FileAttributes = info.dwFileAttributes & ~(FILE_ATTRIBUTE_READONLY); - - status = pNtSetInformationFile(handle, - &iosb, - &basic, - sizeof basic, - FileBasicInformation); - if (!NT_SUCCESS(status)) { - SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(status)); - CloseHandle(handle); - return; - } - } - - /* Try to set the delete flag. */ - disposition.DeleteFile = TRUE; - status = pNtSetInformationFile(handle, - &iosb, - &disposition, - sizeof disposition, - FileDispositionInformation); - if (NT_SUCCESS(status)) { - SET_REQ_SUCCESS(req); - } else { - SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(status)); - } - - CloseHandle(handle); -} - - -void fs__mkdir(uv_fs_t* req) { - /* TODO: use req->mode. */ - int result = _wmkdir(req->file.pathw); - SET_REQ_RESULT(req, result); -} - - -/* OpenBSD original: lib/libc/stdio/mktemp.c */ -void fs__mkdtemp(uv_fs_t* req) { - static const WCHAR *tempchars = - L"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; - static const size_t num_chars = 62; - static const size_t num_x = 6; - WCHAR *cp, *ep; - unsigned int tries, i; - size_t len; - HCRYPTPROV h_crypt_prov; - uint64_t v; - BOOL released; - - len = wcslen(req->file.pathw); - ep = req->file.pathw + len; - if (len < num_x || wcsncmp(ep - num_x, L"XXXXXX", num_x)) { - SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_INVALID_PARAMETER); - return; - } - - if (!CryptAcquireContext(&h_crypt_prov, NULL, NULL, PROV_RSA_FULL, - CRYPT_VERIFYCONTEXT)) { - SET_REQ_WIN32_ERROR(req, GetLastError()); - return; - } - - tries = TMP_MAX; - do { - if (!CryptGenRandom(h_crypt_prov, sizeof(v), (BYTE*) &v)) { - SET_REQ_WIN32_ERROR(req, GetLastError()); - break; - } - - cp = ep - num_x; - for (i = 0; i < num_x; i++) { - *cp++ = tempchars[v % num_chars]; - v /= num_chars; - } - - if (_wmkdir(req->file.pathw) == 0) { - len = strlen(req->path); - wcstombs((char*) req->path + len - num_x, ep - num_x, num_x); - SET_REQ_RESULT(req, 0); - break; - } else if (errno != EEXIST) { - SET_REQ_RESULT(req, -1); - break; - } - } while (--tries); - - released = CryptReleaseContext(h_crypt_prov, 0); - assert(released); - if (tries == 0) { - SET_REQ_RESULT(req, -1); - } -} - - -void fs__scandir(uv_fs_t* req) { - static const size_t dirents_initial_size = 32; - - HANDLE dir_handle = INVALID_HANDLE_VALUE; - - uv__dirent_t** dirents = NULL; - size_t dirents_size = 0; - size_t dirents_used = 0; - - IO_STATUS_BLOCK iosb; - NTSTATUS status; - - /* Buffer to hold directory entries returned by NtQueryDirectoryFile. - * It's important that this buffer can hold at least one entry, regardless - * of the length of the file names present in the enumerated directory. - * A file name is at most 256 WCHARs long. - * According to MSDN, the buffer must be aligned at an 8-byte boundary. - */ -#if _MSC_VER - __declspec(align(8)) char buffer[8192]; -#else - __attribute__ ((aligned (8))) char buffer[8192]; -#endif - - STATIC_ASSERT(sizeof buffer >= - sizeof(FILE_DIRECTORY_INFORMATION) + 256 * sizeof(WCHAR)); - - /* Open the directory. */ - dir_handle = - CreateFileW(req->file.pathw, - FILE_LIST_DIRECTORY | SYNCHRONIZE, - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - NULL, - OPEN_EXISTING, - FILE_FLAG_BACKUP_SEMANTICS, - NULL); - if (dir_handle == INVALID_HANDLE_VALUE) - goto win32_error; - - /* Read the first chunk. */ - status = pNtQueryDirectoryFile(dir_handle, - NULL, - NULL, - NULL, - &iosb, - &buffer, - sizeof buffer, - FileDirectoryInformation, - FALSE, - NULL, - TRUE); - - /* If the handle is not a directory, we'll get STATUS_INVALID_PARAMETER. - * This should be reported back as UV_ENOTDIR. - */ - if (status == STATUS_INVALID_PARAMETER) - goto not_a_directory_error; - - while (NT_SUCCESS(status)) { - char* position = buffer; - size_t next_entry_offset = 0; - - do { - FILE_DIRECTORY_INFORMATION* info; - uv__dirent_t* dirent; - - size_t wchar_len; - size_t utf8_len; - - /* Obtain a pointer to the current directory entry. */ - position += next_entry_offset; - info = (FILE_DIRECTORY_INFORMATION*) position; - - /* Fetch the offset to the next directory entry. */ - next_entry_offset = info->NextEntryOffset; - - /* Compute the length of the filename in WCHARs. */ - wchar_len = info->FileNameLength / sizeof info->FileName[0]; - - /* Skip over '.' and '..' entries. It has been reported that - * the SharePoint driver includes the terminating zero byte in - * the filename length. Strip those first. - */ - while (wchar_len > 0 && info->FileName[wchar_len - 1] == L'\0') - wchar_len -= 1; - - if (wchar_len == 0) - continue; - if (wchar_len == 1 && info->FileName[0] == L'.') - continue; - if (wchar_len == 2 && info->FileName[0] == L'.' && - info->FileName[1] == L'.') - continue; - - /* Compute the space required to store the filename as UTF-8. */ - utf8_len = WideCharToMultiByte( - CP_UTF8, 0, &info->FileName[0], wchar_len, NULL, 0, NULL, NULL); - if (utf8_len == 0) - goto win32_error; - - /* Resize the dirent array if needed. */ - if (dirents_used >= dirents_size) { - size_t new_dirents_size = - dirents_size == 0 ? dirents_initial_size : dirents_size << 1; - uv__dirent_t** new_dirents = - uv__realloc(dirents, new_dirents_size * sizeof *dirents); - - if (new_dirents == NULL) - goto out_of_memory_error; - - dirents_size = new_dirents_size; - dirents = new_dirents; - } - - /* Allocate space for the uv dirent structure. The dirent structure - * includes room for the first character of the filename, but `utf8_len` - * doesn't count the NULL terminator at this point. - */ - dirent = uv__malloc(sizeof *dirent + utf8_len); - if (dirent == NULL) - goto out_of_memory_error; - - dirents[dirents_used++] = dirent; - - /* Convert file name to UTF-8. */ - if (WideCharToMultiByte(CP_UTF8, - 0, - &info->FileName[0], - wchar_len, - &dirent->d_name[0], - utf8_len, - NULL, - NULL) == 0) - goto win32_error; - - /* Add a null terminator to the filename. */ - dirent->d_name[utf8_len] = '\0'; - - /* Fill out the type field. */ - if (info->FileAttributes & FILE_ATTRIBUTE_DEVICE) - dirent->d_type = UV__DT_CHAR; - else if (info->FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) - dirent->d_type = UV__DT_LINK; - else if (info->FileAttributes & FILE_ATTRIBUTE_DIRECTORY) - dirent->d_type = UV__DT_DIR; - else - dirent->d_type = UV__DT_FILE; - } while (next_entry_offset != 0); - - /* Read the next chunk. */ - status = pNtQueryDirectoryFile(dir_handle, - NULL, - NULL, - NULL, - &iosb, - &buffer, - sizeof buffer, - FileDirectoryInformation, - FALSE, - NULL, - FALSE); - - /* After the first pNtQueryDirectoryFile call, the function may return - * STATUS_SUCCESS even if the buffer was too small to hold at least one - * directory entry. - */ - if (status == STATUS_SUCCESS && iosb.Information == 0) - status = STATUS_BUFFER_OVERFLOW; - } - - if (status != STATUS_NO_MORE_FILES) - goto nt_error; - - CloseHandle(dir_handle); - - /* Store the result in the request object. */ - req->ptr = dirents; - if (dirents != NULL) - req->flags |= UV_FS_FREE_PTR; - - SET_REQ_RESULT(req, dirents_used); - - /* `nbufs` will be used as index by uv_fs_scandir_next. */ - req->fs.info.nbufs = 0; - - return; - -nt_error: - SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(status)); - goto cleanup; - -win32_error: - SET_REQ_WIN32_ERROR(req, GetLastError()); - goto cleanup; - -not_a_directory_error: - SET_REQ_UV_ERROR(req, UV_ENOTDIR, ERROR_DIRECTORY); - goto cleanup; - -out_of_memory_error: - SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY); - goto cleanup; - -cleanup: - if (dir_handle != INVALID_HANDLE_VALUE) - CloseHandle(dir_handle); - while (dirents_used > 0) - uv__free(dirents[--dirents_used]); - if (dirents != NULL) - uv__free(dirents); -} - - -INLINE static int fs__stat_handle(HANDLE handle, uv_stat_t* statbuf) { - FILE_ALL_INFORMATION file_info; - FILE_FS_VOLUME_INFORMATION volume_info; - NTSTATUS nt_status; - IO_STATUS_BLOCK io_status; - - nt_status = pNtQueryInformationFile(handle, - &io_status, - &file_info, - sizeof file_info, - FileAllInformation); - - /* Buffer overflow (a warning status code) is expected here. */ - if (NT_ERROR(nt_status)) { - SetLastError(pRtlNtStatusToDosError(nt_status)); - return -1; - } - - nt_status = pNtQueryVolumeInformationFile(handle, - &io_status, - &volume_info, - sizeof volume_info, - FileFsVolumeInformation); - - /* Buffer overflow (a warning status code) is expected here. */ - if (io_status.Status == STATUS_NOT_IMPLEMENTED) { - statbuf->st_dev = 0; - } else if (NT_ERROR(nt_status)) { - SetLastError(pRtlNtStatusToDosError(nt_status)); - return -1; - } else { - statbuf->st_dev = volume_info.VolumeSerialNumber; - } - - /* Todo: st_mode should probably always be 0666 for everyone. We might also - * want to report 0777 if the file is a .exe or a directory. - * - * Currently it's based on whether the 'readonly' attribute is set, which - * makes little sense because the semantics are so different: the 'read-only' - * flag is just a way for a user to protect against accidental deletion, and - * serves no security purpose. Windows uses ACLs for that. - * - * Also people now use uv_fs_chmod() to take away the writable bit for good - * reasons. Windows however just makes the file read-only, which makes it - * impossible to delete the file afterwards, since read-only files can't be - * deleted. - * - * IOW it's all just a clusterfuck and we should think of something that - * makes slightly more sense. - * - * And uv_fs_chmod should probably just fail on windows or be a total no-op. - * There's nothing sensible it can do anyway. - */ - statbuf->st_mode = 0; - - if (file_info.BasicInformation.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { - /* - * It is possible for a file to have FILE_ATTRIBUTE_REPARSE_POINT but not have - * any link data. In that case DeviceIoControl() in fs__readlink_handle() sets - * the last error to ERROR_NOT_A_REPARSE_POINT. Then the stat result mode - * calculated below will indicate a normal directory or file, as if - * FILE_ATTRIBUTE_REPARSE_POINT was not present. - */ - if (fs__readlink_handle(handle, NULL, &statbuf->st_size) == 0) { - statbuf->st_mode |= S_IFLNK; - } else if (GetLastError() != ERROR_NOT_A_REPARSE_POINT) { - return -1; - } - } - - if (statbuf->st_mode == 0) { - if (file_info.BasicInformation.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - statbuf->st_mode |= _S_IFDIR; - statbuf->st_size = 0; - } else { - statbuf->st_mode |= _S_IFREG; - statbuf->st_size = file_info.StandardInformation.EndOfFile.QuadPart; - } - } - - if (file_info.BasicInformation.FileAttributes & FILE_ATTRIBUTE_READONLY) - statbuf->st_mode |= _S_IREAD | (_S_IREAD >> 3) | (_S_IREAD >> 6); - else - statbuf->st_mode |= (_S_IREAD | _S_IWRITE) | ((_S_IREAD | _S_IWRITE) >> 3) | - ((_S_IREAD | _S_IWRITE) >> 6); - - FILETIME_TO_TIMESPEC(statbuf->st_atim, file_info.BasicInformation.LastAccessTime); - FILETIME_TO_TIMESPEC(statbuf->st_ctim, file_info.BasicInformation.ChangeTime); - FILETIME_TO_TIMESPEC(statbuf->st_mtim, file_info.BasicInformation.LastWriteTime); - FILETIME_TO_TIMESPEC(statbuf->st_birthtim, file_info.BasicInformation.CreationTime); - - statbuf->st_ino = file_info.InternalInformation.IndexNumber.QuadPart; - - /* st_blocks contains the on-disk allocation size in 512-byte units. */ - statbuf->st_blocks = - file_info.StandardInformation.AllocationSize.QuadPart >> 9ULL; - - statbuf->st_nlink = file_info.StandardInformation.NumberOfLinks; - - /* The st_blksize is supposed to be the 'optimal' number of bytes for reading - * and writing to the disk. That is, for any definition of 'optimal' - it's - * supposed to at least avoid read-update-write behavior when writing to the - * disk. - * - * However nobody knows this and even fewer people actually use this value, - * and in order to fill it out we'd have to make another syscall to query the - * volume for FILE_FS_SECTOR_SIZE_INFORMATION. - * - * Therefore we'll just report a sensible value that's quite commonly okay - * on modern hardware. - */ - statbuf->st_blksize = 2048; - - /* Todo: set st_flags to something meaningful. Also provide a wrapper for - * chattr(2). - */ - statbuf->st_flags = 0; - - /* Windows has nothing sensible to say about these values, so they'll just - * remain empty. - */ - statbuf->st_gid = 0; - statbuf->st_uid = 0; - statbuf->st_rdev = 0; - statbuf->st_gen = 0; - - return 0; -} - - -INLINE static void fs__stat_prepare_path(WCHAR* pathw) { - size_t len = wcslen(pathw); - - /* TODO: ignore namespaced paths. */ - if (len > 1 && pathw[len - 2] != L':' && - (pathw[len - 1] == L'\\' || pathw[len - 1] == L'/')) { - pathw[len - 1] = '\0'; - } -} - - -INLINE static void fs__stat_impl(uv_fs_t* req, int do_lstat) { - HANDLE handle; - DWORD flags; - - flags = FILE_FLAG_BACKUP_SEMANTICS; - if (do_lstat) { - flags |= FILE_FLAG_OPEN_REPARSE_POINT; - } - - handle = CreateFileW(req->file.pathw, - FILE_READ_ATTRIBUTES, - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - NULL, - OPEN_EXISTING, - flags, - NULL); - if (handle == INVALID_HANDLE_VALUE) { - SET_REQ_WIN32_ERROR(req, GetLastError()); - return; - } - - if (fs__stat_handle(handle, &req->statbuf) != 0) { - DWORD error = GetLastError(); - if (do_lstat && error == ERROR_SYMLINK_NOT_SUPPORTED) { - /* We opened a reparse point but it was not a symlink. Try again. */ - fs__stat_impl(req, 0); - - } else { - /* Stat failed. */ - SET_REQ_WIN32_ERROR(req, GetLastError()); - } - - CloseHandle(handle); - return; - } - - req->ptr = &req->statbuf; - req->result = 0; - CloseHandle(handle); -} - - -static void fs__stat(uv_fs_t* req) { - fs__stat_prepare_path(req->file.pathw); - fs__stat_impl(req, 0); -} - - -static void fs__lstat(uv_fs_t* req) { - fs__stat_prepare_path(req->file.pathw); - fs__stat_impl(req, 1); -} - - -static void fs__fstat(uv_fs_t* req) { - int fd = req->file.fd; - HANDLE handle; - - VERIFY_FD(fd, req); - - handle = uv__get_osfhandle(fd); - - if (handle == INVALID_HANDLE_VALUE) { - SET_REQ_WIN32_ERROR(req, ERROR_INVALID_HANDLE); - return; - } - - if (fs__stat_handle(handle, &req->statbuf) != 0) { - SET_REQ_WIN32_ERROR(req, GetLastError()); - return; - } - - req->ptr = &req->statbuf; - req->result = 0; -} - - -static void fs__rename(uv_fs_t* req) { - if (!MoveFileExW(req->file.pathw, req->fs.info.new_pathw, MOVEFILE_REPLACE_EXISTING)) { - SET_REQ_WIN32_ERROR(req, GetLastError()); - return; - } - - SET_REQ_RESULT(req, 0); -} - - -INLINE static void fs__sync_impl(uv_fs_t* req) { - int fd = req->file.fd; - int result; - - VERIFY_FD(fd, req); - - result = FlushFileBuffers(uv__get_osfhandle(fd)) ? 0 : -1; - if (result == -1) { - SET_REQ_WIN32_ERROR(req, GetLastError()); - } else { - SET_REQ_RESULT(req, result); - } -} - - -static void fs__fsync(uv_fs_t* req) { - fs__sync_impl(req); -} - - -static void fs__fdatasync(uv_fs_t* req) { - fs__sync_impl(req); -} - - -static void fs__ftruncate(uv_fs_t* req) { - int fd = req->file.fd; - HANDLE handle; - NTSTATUS status; - IO_STATUS_BLOCK io_status; - FILE_END_OF_FILE_INFORMATION eof_info; - - VERIFY_FD(fd, req); - - handle = uv__get_osfhandle(fd); - - eof_info.EndOfFile.QuadPart = req->fs.info.offset; - - status = pNtSetInformationFile(handle, - &io_status, - &eof_info, - sizeof eof_info, - FileEndOfFileInformation); - - if (NT_SUCCESS(status)) { - SET_REQ_RESULT(req, 0); - } else { - SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(status)); - } -} - - -static void fs__sendfile(uv_fs_t* req) { - int fd_in = req->file.fd, fd_out = req->fs.info.fd_out; - size_t length = req->fs.info.bufsml[0].len; - int64_t offset = req->fs.info.offset; - const size_t max_buf_size = 65536; - size_t buf_size = length < max_buf_size ? length : max_buf_size; - int n, result = 0; - int64_t result_offset = 0; - char* buf = (char*) uv__malloc(buf_size); - if (!buf) { - uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc"); - } - - if (offset != -1) { - result_offset = _lseeki64(fd_in, offset, SEEK_SET); - } - - if (result_offset == -1) { - result = -1; - } else { - while (length > 0) { - n = _read(fd_in, buf, length < buf_size ? length : buf_size); - if (n == 0) { - break; - } else if (n == -1) { - result = -1; - break; - } - - length -= n; - - n = _write(fd_out, buf, n); - if (n == -1) { - result = -1; - break; - } - - result += n; - } - } - - uv__free(buf); - - SET_REQ_RESULT(req, result); -} - - -static void fs__access(uv_fs_t* req) { - DWORD attr = GetFileAttributesW(req->file.pathw); - - if (attr == INVALID_FILE_ATTRIBUTES) { - SET_REQ_WIN32_ERROR(req, GetLastError()); - return; - } - - /* - * Access is possible if - * - write access wasn't requested, - * - or the file isn't read-only, - * - or it's a directory. - * (Directories cannot be read-only on Windows.) - */ - if (!(req->flags & W_OK) || - !(attr & FILE_ATTRIBUTE_READONLY) || - (attr & FILE_ATTRIBUTE_DIRECTORY)) { - SET_REQ_RESULT(req, 0); - } else { - SET_REQ_WIN32_ERROR(req, UV_EPERM); - } - -} - - -static void fs__chmod(uv_fs_t* req) { - int result = _wchmod(req->file.pathw, req->fs.info.mode); - SET_REQ_RESULT(req, result); -} - - -static void fs__fchmod(uv_fs_t* req) { - int fd = req->file.fd; - HANDLE handle; - NTSTATUS nt_status; - IO_STATUS_BLOCK io_status; - FILE_BASIC_INFORMATION file_info; - - VERIFY_FD(fd, req); - - handle = uv__get_osfhandle(fd); - - nt_status = pNtQueryInformationFile(handle, - &io_status, - &file_info, - sizeof file_info, - FileBasicInformation); - - if (!NT_SUCCESS(nt_status)) { - SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(nt_status)); - return; - } - - if (req->fs.info.mode & _S_IWRITE) { - file_info.FileAttributes &= ~FILE_ATTRIBUTE_READONLY; - } else { - file_info.FileAttributes |= FILE_ATTRIBUTE_READONLY; - } - - nt_status = pNtSetInformationFile(handle, - &io_status, - &file_info, - sizeof file_info, - FileBasicInformation); - - if (!NT_SUCCESS(nt_status)) { - SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(nt_status)); - return; - } - - SET_REQ_SUCCESS(req); -} - - -INLINE static int fs__utime_handle(HANDLE handle, double atime, double mtime) { - FILETIME filetime_a, filetime_m; - - TIME_T_TO_FILETIME(atime, &filetime_a); - TIME_T_TO_FILETIME(mtime, &filetime_m); - - if (!SetFileTime(handle, NULL, &filetime_a, &filetime_m)) { - return -1; - } - - return 0; -} - - -static void fs__utime(uv_fs_t* req) { - HANDLE handle; - - handle = CreateFileW(req->file.pathw, - FILE_WRITE_ATTRIBUTES, - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - NULL, - OPEN_EXISTING, - FILE_FLAG_BACKUP_SEMANTICS, - NULL); - - if (handle == INVALID_HANDLE_VALUE) { - SET_REQ_WIN32_ERROR(req, GetLastError()); - return; - } - - if (fs__utime_handle(handle, req->fs.time.atime, req->fs.time.mtime) != 0) { - SET_REQ_WIN32_ERROR(req, GetLastError()); - CloseHandle(handle); - return; - } - - CloseHandle(handle); - - req->result = 0; -} - - -static void fs__futime(uv_fs_t* req) { - int fd = req->file.fd; - HANDLE handle; - VERIFY_FD(fd, req); - - handle = uv__get_osfhandle(fd); - - if (handle == INVALID_HANDLE_VALUE) { - SET_REQ_WIN32_ERROR(req, ERROR_INVALID_HANDLE); - return; - } - - if (fs__utime_handle(handle, req->fs.time.atime, req->fs.time.mtime) != 0) { - SET_REQ_WIN32_ERROR(req, GetLastError()); - return; - } - - req->result = 0; -} - - -static void fs__link(uv_fs_t* req) { - DWORD r = CreateHardLinkW(req->fs.info.new_pathw, req->file.pathw, NULL); - if (r == 0) { - SET_REQ_WIN32_ERROR(req, GetLastError()); - } else { - req->result = 0; - } -} - - -static void fs__create_junction(uv_fs_t* req, const WCHAR* path, - const WCHAR* new_path) { - HANDLE handle = INVALID_HANDLE_VALUE; - REPARSE_DATA_BUFFER *buffer = NULL; - int created = 0; - int target_len; - int is_absolute, is_long_path; - int needed_buf_size, used_buf_size, used_data_size, path_buf_len; - int start, len, i; - int add_slash; - DWORD bytes; - WCHAR* path_buf; - - target_len = wcslen(path); - is_long_path = wcsncmp(path, LONG_PATH_PREFIX, LONG_PATH_PREFIX_LEN) == 0; - - if (is_long_path) { - is_absolute = 1; - } else { - is_absolute = target_len >= 3 && IS_LETTER(path[0]) && - path[1] == L':' && IS_SLASH(path[2]); - } - - if (!is_absolute) { - /* Not supporting relative paths */ - SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_NOT_SUPPORTED); - return; - } - - /* Do a pessimistic calculation of the required buffer size */ - needed_buf_size = - FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer.PathBuffer) + - JUNCTION_PREFIX_LEN * sizeof(WCHAR) + - 2 * (target_len + 2) * sizeof(WCHAR); - - /* Allocate the buffer */ - buffer = (REPARSE_DATA_BUFFER*)uv__malloc(needed_buf_size); - if (!buffer) { - uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc"); - } - - /* Grab a pointer to the part of the buffer where filenames go */ - path_buf = (WCHAR*)&(buffer->MountPointReparseBuffer.PathBuffer); - path_buf_len = 0; - - /* Copy the substitute (internal) target path */ - start = path_buf_len; - - wcsncpy((WCHAR*)&path_buf[path_buf_len], JUNCTION_PREFIX, - JUNCTION_PREFIX_LEN); - path_buf_len += JUNCTION_PREFIX_LEN; - - add_slash = 0; - for (i = is_long_path ? LONG_PATH_PREFIX_LEN : 0; path[i] != L'\0'; i++) { - if (IS_SLASH(path[i])) { - add_slash = 1; - continue; - } - - if (add_slash) { - path_buf[path_buf_len++] = L'\\'; - add_slash = 0; - } - - path_buf[path_buf_len++] = path[i]; - } - path_buf[path_buf_len++] = L'\\'; - len = path_buf_len - start; - - /* Set the info about the substitute name */ - buffer->MountPointReparseBuffer.SubstituteNameOffset = start * sizeof(WCHAR); - buffer->MountPointReparseBuffer.SubstituteNameLength = len * sizeof(WCHAR); - - /* Insert null terminator */ - path_buf[path_buf_len++] = L'\0'; - - /* Copy the print name of the target path */ - start = path_buf_len; - add_slash = 0; - for (i = is_long_path ? LONG_PATH_PREFIX_LEN : 0; path[i] != L'\0'; i++) { - if (IS_SLASH(path[i])) { - add_slash = 1; - continue; - } - - if (add_slash) { - path_buf[path_buf_len++] = L'\\'; - add_slash = 0; - } - - path_buf[path_buf_len++] = path[i]; - } - len = path_buf_len - start; - if (len == 2) { - path_buf[path_buf_len++] = L'\\'; - len++; - } - - /* Set the info about the print name */ - buffer->MountPointReparseBuffer.PrintNameOffset = start * sizeof(WCHAR); - buffer->MountPointReparseBuffer.PrintNameLength = len * sizeof(WCHAR); - - /* Insert another null terminator */ - path_buf[path_buf_len++] = L'\0'; - - /* Calculate how much buffer space was actually used */ - used_buf_size = FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer.PathBuffer) + - path_buf_len * sizeof(WCHAR); - used_data_size = used_buf_size - - FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer); - - /* Put general info in the data buffer */ - buffer->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT; - buffer->ReparseDataLength = used_data_size; - buffer->Reserved = 0; - - /* Create a new directory */ - if (!CreateDirectoryW(new_path, NULL)) { - SET_REQ_WIN32_ERROR(req, GetLastError()); - goto error; - } - created = 1; - - /* Open the directory */ - handle = CreateFileW(new_path, - GENERIC_WRITE, - 0, - NULL, - OPEN_EXISTING, - FILE_FLAG_BACKUP_SEMANTICS | - FILE_FLAG_OPEN_REPARSE_POINT, - NULL); - if (handle == INVALID_HANDLE_VALUE) { - SET_REQ_WIN32_ERROR(req, GetLastError()); - goto error; - } - - /* Create the actual reparse point */ - if (!DeviceIoControl(handle, - FSCTL_SET_REPARSE_POINT, - buffer, - used_buf_size, - NULL, - 0, - &bytes, - NULL)) { - SET_REQ_WIN32_ERROR(req, GetLastError()); - goto error; - } - - /* Clean up */ - CloseHandle(handle); - uv__free(buffer); - - SET_REQ_RESULT(req, 0); - return; - -error: - uv__free(buffer); - - if (handle != INVALID_HANDLE_VALUE) { - CloseHandle(handle); - } - - if (created) { - RemoveDirectoryW(new_path); - } -} - - -static void fs__symlink(uv_fs_t* req) { - WCHAR* pathw = req->file.pathw; - WCHAR* new_pathw = req->fs.info.new_pathw; - int flags = req->fs.info.file_flags; - int result; - - - if (flags & UV_FS_SYMLINK_JUNCTION) { - fs__create_junction(req, pathw, new_pathw); - } else if (pCreateSymbolicLinkW) { - result = pCreateSymbolicLinkW(new_pathw, - pathw, - flags & UV_FS_SYMLINK_DIR ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0) ? 0 : -1; - if (result == -1) { - SET_REQ_WIN32_ERROR(req, GetLastError()); - } else { - SET_REQ_RESULT(req, result); - } - } else { - SET_REQ_UV_ERROR(req, UV_ENOSYS, ERROR_NOT_SUPPORTED); - } -} - - -static void fs__readlink(uv_fs_t* req) { - HANDLE handle; - - handle = CreateFileW(req->file.pathw, - 0, - 0, - NULL, - OPEN_EXISTING, - FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, - NULL); - - if (handle == INVALID_HANDLE_VALUE) { - SET_REQ_WIN32_ERROR(req, GetLastError()); - return; - } - - if (fs__readlink_handle(handle, (char**) &req->ptr, NULL) != 0) { - SET_REQ_WIN32_ERROR(req, GetLastError()); - CloseHandle(handle); - return; - } - - req->flags |= UV_FS_FREE_PTR; - SET_REQ_RESULT(req, 0); - - CloseHandle(handle); -} - - -static size_t fs__realpath_handle(HANDLE handle, char** realpath_ptr) { - int r; - DWORD w_realpath_len; - WCHAR* w_realpath_ptr = NULL; - WCHAR* w_realpath_buf; - - w_realpath_len = pGetFinalPathNameByHandleW(handle, NULL, 0, VOLUME_NAME_DOS); - if (w_realpath_len == 0) { - return -1; - } - - w_realpath_buf = uv__malloc((w_realpath_len + 1) * sizeof(WCHAR)); - if (w_realpath_buf == NULL) { - SetLastError(ERROR_OUTOFMEMORY); - return -1; - } - w_realpath_ptr = w_realpath_buf; - - if (pGetFinalPathNameByHandleW(handle, - w_realpath_ptr, - w_realpath_len, - VOLUME_NAME_DOS) == 0) { - uv__free(w_realpath_buf); - SetLastError(ERROR_INVALID_HANDLE); - return -1; - } - - /* convert UNC path to long path */ - if (wcsncmp(w_realpath_ptr, - UNC_PATH_PREFIX, - UNC_PATH_PREFIX_LEN) == 0) { - w_realpath_ptr += 6; - *w_realpath_ptr = L'\\'; - w_realpath_len -= 6; - } else if (wcsncmp(w_realpath_ptr, - LONG_PATH_PREFIX, - LONG_PATH_PREFIX_LEN) == 0) { - w_realpath_ptr += 4; - w_realpath_len -= 4; - } else { - uv__free(w_realpath_buf); - SetLastError(ERROR_INVALID_HANDLE); - return -1; - } - - r = fs__wide_to_utf8(w_realpath_ptr, w_realpath_len, realpath_ptr, NULL); - uv__free(w_realpath_buf); - return r; -} - -static void fs__realpath(uv_fs_t* req) { - HANDLE handle; - - if (!pGetFinalPathNameByHandleW) { - SET_REQ_UV_ERROR(req, UV_ENOSYS, ERROR_NOT_SUPPORTED); - return; - } - - handle = CreateFileW(req->file.pathw, - 0, - 0, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, - NULL); - if (handle == INVALID_HANDLE_VALUE) { - SET_REQ_WIN32_ERROR(req, GetLastError()); - return; - } - - if (fs__realpath_handle(handle, (char**) &req->ptr) == -1) { - CloseHandle(handle); - SET_REQ_WIN32_ERROR(req, GetLastError()); - return; - } - - CloseHandle(handle); - req->flags |= UV_FS_FREE_PTR; - SET_REQ_RESULT(req, 0); -} - - -static void fs__chown(uv_fs_t* req) { - req->result = 0; -} - - -static void fs__fchown(uv_fs_t* req) { - req->result = 0; -} - - -static void uv__fs_work(struct uv__work* w) { - uv_fs_t* req; - - req = container_of(w, uv_fs_t, work_req); - assert(req->type == UV_FS); - -#define XX(uc, lc) case UV_FS_##uc: fs__##lc(req); break; - switch (req->fs_type) { - XX(OPEN, open) - XX(CLOSE, close) - XX(READ, read) - XX(WRITE, write) - XX(SENDFILE, sendfile) - XX(STAT, stat) - XX(LSTAT, lstat) - XX(FSTAT, fstat) - XX(FTRUNCATE, ftruncate) - XX(UTIME, utime) - XX(FUTIME, futime) - XX(ACCESS, access) - XX(CHMOD, chmod) - XX(FCHMOD, fchmod) - XX(FSYNC, fsync) - XX(FDATASYNC, fdatasync) - XX(UNLINK, unlink) - XX(RMDIR, rmdir) - XX(MKDIR, mkdir) - XX(MKDTEMP, mkdtemp) - XX(RENAME, rename) - XX(SCANDIR, scandir) - XX(LINK, link) - XX(SYMLINK, symlink) - XX(READLINK, readlink) - XX(REALPATH, realpath) - XX(CHOWN, chown) - XX(FCHOWN, fchown); - default: - assert(!"bad uv_fs_type"); - } -} - - -static void uv__fs_done(struct uv__work* w, int status) { - uv_fs_t* req; - - req = container_of(w, uv_fs_t, work_req); - uv__req_unregister(req->loop, req); - - if (status == UV_ECANCELED) { - assert(req->result == 0); - req->result = UV_ECANCELED; - } - - req->cb(req); -} - - -void uv_fs_req_cleanup(uv_fs_t* req) { - if (req->flags & UV_FS_CLEANEDUP) - return; - - if (req->flags & UV_FS_FREE_PATHS) - uv__free(req->file.pathw); - - if (req->flags & UV_FS_FREE_PTR) { - if (req->fs_type == UV_FS_SCANDIR && req->ptr != NULL) - uv__fs_scandir_cleanup(req); - else - uv__free(req->ptr); - } - - if (req->fs.info.bufs != req->fs.info.bufsml) - uv__free(req->fs.info.bufs); - - req->path = NULL; - req->file.pathw = NULL; - req->fs.info.new_pathw = NULL; - req->fs.info.bufs = NULL; - req->ptr = NULL; - - req->flags |= UV_FS_CLEANEDUP; -} - - -int uv_fs_open(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, - int mode, uv_fs_cb cb) { - int err; - - uv_fs_req_init(loop, req, UV_FS_OPEN, cb); - - err = fs__capture_path(req, path, NULL, cb != NULL); - if (err) { - return uv_translate_sys_error(err); - } - - req->fs.info.file_flags = flags; - req->fs.info.mode = mode; - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__open(req); - return req->result; - } -} - - -int uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file fd, uv_fs_cb cb) { - uv_fs_req_init(loop, req, UV_FS_CLOSE, cb); - req->file.fd = fd; - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__close(req); - return req->result; - } -} - - -int uv_fs_read(uv_loop_t* loop, - uv_fs_t* req, - uv_file fd, - const uv_buf_t bufs[], - unsigned int nbufs, - int64_t offset, - uv_fs_cb cb) { - if (bufs == NULL || nbufs == 0) - return UV_EINVAL; - - uv_fs_req_init(loop, req, UV_FS_READ, cb); - - req->file.fd = fd; - - req->fs.info.nbufs = nbufs; - req->fs.info.bufs = req->fs.info.bufsml; - if (nbufs > ARRAY_SIZE(req->fs.info.bufsml)) - req->fs.info.bufs = uv__malloc(nbufs * sizeof(*bufs)); - - if (req->fs.info.bufs == NULL) - return UV_ENOMEM; - - memcpy(req->fs.info.bufs, bufs, nbufs * sizeof(*bufs)); - - req->fs.info.offset = offset; - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__read(req); - return req->result; - } -} - - -int uv_fs_write(uv_loop_t* loop, - uv_fs_t* req, - uv_file fd, - const uv_buf_t bufs[], - unsigned int nbufs, - int64_t offset, - uv_fs_cb cb) { - if (bufs == NULL || nbufs == 0) - return UV_EINVAL; - - uv_fs_req_init(loop, req, UV_FS_WRITE, cb); - - req->file.fd = fd; - - req->fs.info.nbufs = nbufs; - req->fs.info.bufs = req->fs.info.bufsml; - if (nbufs > ARRAY_SIZE(req->fs.info.bufsml)) - req->fs.info.bufs = uv__malloc(nbufs * sizeof(*bufs)); - - if (req->fs.info.bufs == NULL) - return UV_ENOMEM; - - memcpy(req->fs.info.bufs, bufs, nbufs * sizeof(*bufs)); - - req->fs.info.offset = offset; - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__write(req); - return req->result; - } -} - - -int uv_fs_unlink(uv_loop_t* loop, uv_fs_t* req, const char* path, - uv_fs_cb cb) { - int err; - - uv_fs_req_init(loop, req, UV_FS_UNLINK, cb); - - err = fs__capture_path(req, path, NULL, cb != NULL); - if (err) { - return uv_translate_sys_error(err); - } - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__unlink(req); - return req->result; - } -} - - -int uv_fs_mkdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, - uv_fs_cb cb) { - int err; - - uv_fs_req_init(loop, req, UV_FS_MKDIR, cb); - - err = fs__capture_path(req, path, NULL, cb != NULL); - if (err) { - return uv_translate_sys_error(err); - } - - req->fs.info.mode = mode; - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__mkdir(req); - return req->result; - } -} - - -int uv_fs_mkdtemp(uv_loop_t* loop, uv_fs_t* req, const char* tpl, - uv_fs_cb cb) { - int err; - - uv_fs_req_init(loop, req, UV_FS_MKDTEMP, cb); - - err = fs__capture_path(req, tpl, NULL, TRUE); - if (err) - return uv_translate_sys_error(err); - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__mkdtemp(req); - return req->result; - } -} - - -int uv_fs_rmdir(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) { - int err; - - uv_fs_req_init(loop, req, UV_FS_RMDIR, cb); - - err = fs__capture_path(req, path, NULL, cb != NULL); - if (err) { - return uv_translate_sys_error(err); - } - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__rmdir(req); - return req->result; - } -} - - -int uv_fs_scandir(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, - uv_fs_cb cb) { - int err; - - uv_fs_req_init(loop, req, UV_FS_SCANDIR, cb); - - err = fs__capture_path(req, path, NULL, cb != NULL); - if (err) { - return uv_translate_sys_error(err); - } - - req->fs.info.file_flags = flags; - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__scandir(req); - return req->result; - } -} - - -int uv_fs_link(uv_loop_t* loop, uv_fs_t* req, const char* path, - const char* new_path, uv_fs_cb cb) { - int err; - - uv_fs_req_init(loop, req, UV_FS_LINK, cb); - - err = fs__capture_path(req, path, new_path, cb != NULL); - if (err) { - return uv_translate_sys_error(err); - } - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__link(req); - return req->result; - } -} - - -int uv_fs_symlink(uv_loop_t* loop, uv_fs_t* req, const char* path, - const char* new_path, int flags, uv_fs_cb cb) { - int err; - - uv_fs_req_init(loop, req, UV_FS_SYMLINK, cb); - - err = fs__capture_path(req, path, new_path, cb != NULL); - if (err) { - return uv_translate_sys_error(err); - } - - req->fs.info.file_flags = flags; - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__symlink(req); - return req->result; - } -} - - -int uv_fs_readlink(uv_loop_t* loop, uv_fs_t* req, const char* path, - uv_fs_cb cb) { - int err; - - uv_fs_req_init(loop, req, UV_FS_READLINK, cb); - - err = fs__capture_path(req, path, NULL, cb != NULL); - if (err) { - return uv_translate_sys_error(err); - } - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__readlink(req); - return req->result; - } -} - - -int uv_fs_realpath(uv_loop_t* loop, uv_fs_t* req, const char* path, - uv_fs_cb cb) { - int err; - - if (!req || !path) { - return UV_EINVAL; - } - - uv_fs_req_init(loop, req, UV_FS_REALPATH, cb); - - err = fs__capture_path(req, path, NULL, cb != NULL); - if (err) { - return uv_translate_sys_error(err); - } - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__realpath(req); - return req->result; - } -} - - -int uv_fs_chown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid, - uv_gid_t gid, uv_fs_cb cb) { - int err; - - uv_fs_req_init(loop, req, UV_FS_CHOWN, cb); - - err = fs__capture_path(req, path, NULL, cb != NULL); - if (err) { - return uv_translate_sys_error(err); - } - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__chown(req); - return req->result; - } -} - - -int uv_fs_fchown(uv_loop_t* loop, uv_fs_t* req, uv_file fd, uv_uid_t uid, - uv_gid_t gid, uv_fs_cb cb) { - uv_fs_req_init(loop, req, UV_FS_FCHOWN, cb); - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__fchown(req); - return req->result; - } -} - - -int uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) { - int err; - - uv_fs_req_init(loop, req, UV_FS_STAT, cb); - - err = fs__capture_path(req, path, NULL, cb != NULL); - if (err) { - return uv_translate_sys_error(err); - } - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__stat(req); - return req->result; - } -} - - -int uv_fs_lstat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) { - int err; - - uv_fs_req_init(loop, req, UV_FS_LSTAT, cb); - - err = fs__capture_path(req, path, NULL, cb != NULL); - if (err) { - return uv_translate_sys_error(err); - } - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__lstat(req); - return req->result; - } -} - - -int uv_fs_fstat(uv_loop_t* loop, uv_fs_t* req, uv_file fd, uv_fs_cb cb) { - uv_fs_req_init(loop, req, UV_FS_FSTAT, cb); - req->file.fd = fd; - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__fstat(req); - return req->result; - } -} - - -int uv_fs_rename(uv_loop_t* loop, uv_fs_t* req, const char* path, - const char* new_path, uv_fs_cb cb) { - int err; - - uv_fs_req_init(loop, req, UV_FS_RENAME, cb); - - err = fs__capture_path(req, path, new_path, cb != NULL); - if (err) { - return uv_translate_sys_error(err); - } - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__rename(req); - return req->result; - } -} - - -int uv_fs_fsync(uv_loop_t* loop, uv_fs_t* req, uv_file fd, uv_fs_cb cb) { - uv_fs_req_init(loop, req, UV_FS_FSYNC, cb); - req->file.fd = fd; - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__fsync(req); - return req->result; - } -} - - -int uv_fs_fdatasync(uv_loop_t* loop, uv_fs_t* req, uv_file fd, uv_fs_cb cb) { - uv_fs_req_init(loop, req, UV_FS_FDATASYNC, cb); - req->file.fd = fd; - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__fdatasync(req); - return req->result; - } -} - - -int uv_fs_ftruncate(uv_loop_t* loop, uv_fs_t* req, uv_file fd, - int64_t offset, uv_fs_cb cb) { - uv_fs_req_init(loop, req, UV_FS_FTRUNCATE, cb); - - req->file.fd = fd; - req->fs.info.offset = offset; - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__ftruncate(req); - return req->result; - } -} - - - -int uv_fs_sendfile(uv_loop_t* loop, uv_fs_t* req, uv_file fd_out, - uv_file fd_in, int64_t in_offset, size_t length, uv_fs_cb cb) { - uv_fs_req_init(loop, req, UV_FS_SENDFILE, cb); - - req->file.fd = fd_in; - req->fs.info.fd_out = fd_out; - req->fs.info.offset = in_offset; - req->fs.info.bufsml[0].len = length; - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__sendfile(req); - return req->result; - } -} - - -int uv_fs_access(uv_loop_t* loop, - uv_fs_t* req, - const char* path, - int flags, - uv_fs_cb cb) { - int err; - - uv_fs_req_init(loop, req, UV_FS_ACCESS, cb); - - err = fs__capture_path(req, path, NULL, cb != NULL); - if (err) - return uv_translate_sys_error(err); - - req->flags = flags; - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } - - fs__access(req); - return req->result; -} - - -int uv_fs_chmod(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, - uv_fs_cb cb) { - int err; - - uv_fs_req_init(loop, req, UV_FS_CHMOD, cb); - - err = fs__capture_path(req, path, NULL, cb != NULL); - if (err) { - return uv_translate_sys_error(err); - } - - req->fs.info.mode = mode; - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__chmod(req); - return req->result; - } -} - - -int uv_fs_fchmod(uv_loop_t* loop, uv_fs_t* req, uv_file fd, int mode, - uv_fs_cb cb) { - uv_fs_req_init(loop, req, UV_FS_FCHMOD, cb); - - req->file.fd = fd; - req->fs.info.mode = mode; - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__fchmod(req); - return req->result; - } -} - - -int uv_fs_utime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime, - double mtime, uv_fs_cb cb) { - int err; - - uv_fs_req_init(loop, req, UV_FS_UTIME, cb); - - err = fs__capture_path(req, path, NULL, cb != NULL); - if (err) { - return uv_translate_sys_error(err); - } - - req->fs.time.atime = atime; - req->fs.time.mtime = mtime; - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__utime(req); - return req->result; - } -} - - -int uv_fs_futime(uv_loop_t* loop, uv_fs_t* req, uv_file fd, double atime, - double mtime, uv_fs_cb cb) { - uv_fs_req_init(loop, req, UV_FS_FUTIME, cb); - - req->file.fd = fd; - req->fs.time.atime = atime; - req->fs.time.mtime = mtime; - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__futime(req); - return req->result; - } -} diff --git a/vendor/libuv/src/win/getaddrinfo.c b/vendor/libuv/src/win/getaddrinfo.c deleted file mode 100644 index c13bfec35..000000000 --- a/vendor/libuv/src/win/getaddrinfo.c +++ /dev/null @@ -1,384 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include - -#include "uv.h" -#include "internal.h" -#include "req-inl.h" - -/* EAI_* constants. */ -#include - - -int uv__getaddrinfo_translate_error(int sys_err) { - switch (sys_err) { - case 0: return 0; - case WSATRY_AGAIN: return UV_EAI_AGAIN; - case WSAEINVAL: return UV_EAI_BADFLAGS; - case WSANO_RECOVERY: return UV_EAI_FAIL; - case WSAEAFNOSUPPORT: return UV_EAI_FAMILY; - case WSA_NOT_ENOUGH_MEMORY: return UV_EAI_MEMORY; - case WSAHOST_NOT_FOUND: return UV_EAI_NONAME; - case WSATYPE_NOT_FOUND: return UV_EAI_SERVICE; - case WSAESOCKTNOSUPPORT: return UV_EAI_SOCKTYPE; - default: return uv_translate_sys_error(sys_err); - } -} - - -/* - * MinGW is missing this - */ -#if !defined(_MSC_VER) && !defined(__MINGW64_VERSION_MAJOR) - typedef struct addrinfoW { - int ai_flags; - int ai_family; - int ai_socktype; - int ai_protocol; - size_t ai_addrlen; - WCHAR* ai_canonname; - struct sockaddr* ai_addr; - struct addrinfoW* ai_next; - } ADDRINFOW, *PADDRINFOW; - - DECLSPEC_IMPORT int WSAAPI GetAddrInfoW(const WCHAR* node, - const WCHAR* service, - const ADDRINFOW* hints, - PADDRINFOW* result); - - DECLSPEC_IMPORT void WSAAPI FreeAddrInfoW(PADDRINFOW pAddrInfo); -#endif - - -/* adjust size value to be multiple of 4. Use to keep pointer aligned */ -/* Do we need different versions of this for different architectures? */ -#define ALIGNED_SIZE(X) ((((X) + 3) >> 2) << 2) - - -static void uv__getaddrinfo_work(struct uv__work* w) { - uv_getaddrinfo_t* req; - struct addrinfoW* hints; - int err; - - req = container_of(w, uv_getaddrinfo_t, work_req); - hints = req->addrinfow; - req->addrinfow = NULL; - err = GetAddrInfoW(req->node, req->service, hints, &req->addrinfow); - req->retcode = uv__getaddrinfo_translate_error(err); -} - - -/* - * Called from uv_run when complete. Call user specified callback - * then free returned addrinfo - * Returned addrinfo strings are converted from UTF-16 to UTF-8. - * - * To minimize allocation we calculate total size required, - * and copy all structs and referenced strings into the one block. - * Each size calculation is adjusted to avoid unaligned pointers. - */ -static void uv__getaddrinfo_done(struct uv__work* w, int status) { - uv_getaddrinfo_t* req; - int addrinfo_len = 0; - int name_len = 0; - size_t addrinfo_struct_len = ALIGNED_SIZE(sizeof(struct addrinfo)); - struct addrinfoW* addrinfow_ptr; - struct addrinfo* addrinfo_ptr; - char* alloc_ptr = NULL; - char* cur_ptr = NULL; - - req = container_of(w, uv_getaddrinfo_t, work_req); - - /* release input parameter memory */ - uv__free(req->alloc); - req->alloc = NULL; - - if (status == UV_ECANCELED) { - assert(req->retcode == 0); - req->retcode = UV_EAI_CANCELED; - goto complete; - } - - if (req->retcode == 0) { - /* convert addrinfoW to addrinfo */ - /* first calculate required length */ - addrinfow_ptr = req->addrinfow; - while (addrinfow_ptr != NULL) { - addrinfo_len += addrinfo_struct_len + - ALIGNED_SIZE(addrinfow_ptr->ai_addrlen); - if (addrinfow_ptr->ai_canonname != NULL) { - name_len = WideCharToMultiByte(CP_UTF8, - 0, - addrinfow_ptr->ai_canonname, - -1, - NULL, - 0, - NULL, - NULL); - if (name_len == 0) { - req->retcode = uv_translate_sys_error(GetLastError()); - goto complete; - } - addrinfo_len += ALIGNED_SIZE(name_len); - } - addrinfow_ptr = addrinfow_ptr->ai_next; - } - - /* allocate memory for addrinfo results */ - alloc_ptr = (char*)uv__malloc(addrinfo_len); - - /* do conversions */ - if (alloc_ptr != NULL) { - cur_ptr = alloc_ptr; - addrinfow_ptr = req->addrinfow; - - while (addrinfow_ptr != NULL) { - /* copy addrinfo struct data */ - assert(cur_ptr + addrinfo_struct_len <= alloc_ptr + addrinfo_len); - addrinfo_ptr = (struct addrinfo*)cur_ptr; - addrinfo_ptr->ai_family = addrinfow_ptr->ai_family; - addrinfo_ptr->ai_socktype = addrinfow_ptr->ai_socktype; - addrinfo_ptr->ai_protocol = addrinfow_ptr->ai_protocol; - addrinfo_ptr->ai_flags = addrinfow_ptr->ai_flags; - addrinfo_ptr->ai_addrlen = addrinfow_ptr->ai_addrlen; - addrinfo_ptr->ai_canonname = NULL; - addrinfo_ptr->ai_addr = NULL; - addrinfo_ptr->ai_next = NULL; - - cur_ptr += addrinfo_struct_len; - - /* copy sockaddr */ - if (addrinfo_ptr->ai_addrlen > 0) { - assert(cur_ptr + addrinfo_ptr->ai_addrlen <= - alloc_ptr + addrinfo_len); - memcpy(cur_ptr, addrinfow_ptr->ai_addr, addrinfo_ptr->ai_addrlen); - addrinfo_ptr->ai_addr = (struct sockaddr*)cur_ptr; - cur_ptr += ALIGNED_SIZE(addrinfo_ptr->ai_addrlen); - } - - /* convert canonical name to UTF-8 */ - if (addrinfow_ptr->ai_canonname != NULL) { - name_len = WideCharToMultiByte(CP_UTF8, - 0, - addrinfow_ptr->ai_canonname, - -1, - NULL, - 0, - NULL, - NULL); - assert(name_len > 0); - assert(cur_ptr + name_len <= alloc_ptr + addrinfo_len); - name_len = WideCharToMultiByte(CP_UTF8, - 0, - addrinfow_ptr->ai_canonname, - -1, - cur_ptr, - name_len, - NULL, - NULL); - assert(name_len > 0); - addrinfo_ptr->ai_canonname = cur_ptr; - cur_ptr += ALIGNED_SIZE(name_len); - } - assert(cur_ptr <= alloc_ptr + addrinfo_len); - - /* set next ptr */ - addrinfow_ptr = addrinfow_ptr->ai_next; - if (addrinfow_ptr != NULL) { - addrinfo_ptr->ai_next = (struct addrinfo*)cur_ptr; - } - } - req->addrinfo = (struct addrinfo*)alloc_ptr; - } else { - req->retcode = UV_EAI_MEMORY; - } - } - - /* return memory to system */ - if (req->addrinfow != NULL) { - FreeAddrInfoW(req->addrinfow); - req->addrinfow = NULL; - } - -complete: - uv__req_unregister(req->loop, req); - - /* finally do callback with converted result */ - if (req->getaddrinfo_cb) - req->getaddrinfo_cb(req, req->retcode, req->addrinfo); -} - - -void uv_freeaddrinfo(struct addrinfo* ai) { - char* alloc_ptr = (char*)ai; - - /* release copied result memory */ - uv__free(alloc_ptr); -} - - -/* - * Entry point for getaddrinfo - * we convert the UTF-8 strings to UNICODE - * and save the UNICODE string pointers in the req - * We also copy hints so that caller does not need to keep memory until the - * callback. - * return 0 if a callback will be made - * return error code if validation fails - * - * To minimize allocation we calculate total size required, - * and copy all structs and referenced strings into the one block. - * Each size calculation is adjusted to avoid unaligned pointers. - */ -int uv_getaddrinfo(uv_loop_t* loop, - uv_getaddrinfo_t* req, - uv_getaddrinfo_cb getaddrinfo_cb, - const char* node, - const char* service, - const struct addrinfo* hints) { - int nodesize = 0; - int servicesize = 0; - int hintssize = 0; - char* alloc_ptr = NULL; - int err; - - if (req == NULL || (node == NULL && service == NULL)) { - return UV_EINVAL; - } - - uv_req_init(loop, (uv_req_t*)req); - - req->getaddrinfo_cb = getaddrinfo_cb; - req->addrinfo = NULL; - req->type = UV_GETADDRINFO; - req->loop = loop; - req->retcode = 0; - - /* calculate required memory size for all input values */ - if (node != NULL) { - nodesize = ALIGNED_SIZE(MultiByteToWideChar(CP_UTF8, 0, node, -1, NULL, 0) * - sizeof(WCHAR)); - if (nodesize == 0) { - err = GetLastError(); - goto error; - } - } - - if (service != NULL) { - servicesize = ALIGNED_SIZE(MultiByteToWideChar(CP_UTF8, - 0, - service, - -1, - NULL, - 0) * - sizeof(WCHAR)); - if (servicesize == 0) { - err = GetLastError(); - goto error; - } - } - if (hints != NULL) { - hintssize = ALIGNED_SIZE(sizeof(struct addrinfoW)); - } - - /* allocate memory for inputs, and partition it as needed */ - alloc_ptr = (char*)uv__malloc(nodesize + servicesize + hintssize); - if (!alloc_ptr) { - err = WSAENOBUFS; - goto error; - } - - /* save alloc_ptr now so we can free if error */ - req->alloc = (void*)alloc_ptr; - - /* convert node string to UTF16 into allocated memory and save pointer in */ - /* the request. */ - if (node != NULL) { - req->node = (WCHAR*)alloc_ptr; - if (MultiByteToWideChar(CP_UTF8, - 0, - node, - -1, - (WCHAR*) alloc_ptr, - nodesize / sizeof(WCHAR)) == 0) { - err = GetLastError(); - goto error; - } - alloc_ptr += nodesize; - } else { - req->node = NULL; - } - - /* convert service string to UTF16 into allocated memory and save pointer */ - /* in the req. */ - if (service != NULL) { - req->service = (WCHAR*)alloc_ptr; - if (MultiByteToWideChar(CP_UTF8, - 0, - service, - -1, - (WCHAR*) alloc_ptr, - servicesize / sizeof(WCHAR)) == 0) { - err = GetLastError(); - goto error; - } - alloc_ptr += servicesize; - } else { - req->service = NULL; - } - - /* copy hints to allocated memory and save pointer in req */ - if (hints != NULL) { - req->addrinfow = (struct addrinfoW*)alloc_ptr; - req->addrinfow->ai_family = hints->ai_family; - req->addrinfow->ai_socktype = hints->ai_socktype; - req->addrinfow->ai_protocol = hints->ai_protocol; - req->addrinfow->ai_flags = hints->ai_flags; - req->addrinfow->ai_addrlen = 0; - req->addrinfow->ai_canonname = NULL; - req->addrinfow->ai_addr = NULL; - req->addrinfow->ai_next = NULL; - } else { - req->addrinfow = NULL; - } - - uv__req_register(loop, req); - - if (getaddrinfo_cb) { - uv__work_submit(loop, - &req->work_req, - uv__getaddrinfo_work, - uv__getaddrinfo_done); - return 0; - } else { - uv__getaddrinfo_work(&req->work_req); - uv__getaddrinfo_done(&req->work_req, 0); - return req->retcode; - } - -error: - if (req != NULL) { - uv__free(req->alloc); - req->alloc = NULL; - } - return uv_translate_sys_error(err); -} diff --git a/vendor/libuv/src/win/getnameinfo.c b/vendor/libuv/src/win/getnameinfo.c deleted file mode 100644 index 66b64b883..000000000 --- a/vendor/libuv/src/win/getnameinfo.c +++ /dev/null @@ -1,150 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to -* deal in the Software without restriction, including without limitation the -* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -* sell copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -* IN THE SOFTWARE. -*/ - -#include -#include - -#include "uv.h" -#include "internal.h" -#include "req-inl.h" - -#ifndef GetNameInfo -int WSAAPI GetNameInfoW( - const SOCKADDR *pSockaddr, - socklen_t SockaddrLength, - PWCHAR pNodeBuffer, - DWORD NodeBufferSize, - PWCHAR pServiceBuffer, - DWORD ServiceBufferSize, - INT Flags -); -#endif - -static void uv__getnameinfo_work(struct uv__work* w) { - uv_getnameinfo_t* req; - WCHAR host[NI_MAXHOST]; - WCHAR service[NI_MAXSERV]; - int ret = 0; - - req = container_of(w, uv_getnameinfo_t, work_req); - if (GetNameInfoW((struct sockaddr*)&req->storage, - sizeof(req->storage), - host, - ARRAY_SIZE(host), - service, - ARRAY_SIZE(service), - req->flags)) { - ret = WSAGetLastError(); - } - req->retcode = uv__getaddrinfo_translate_error(ret); - - /* convert results to UTF-8 */ - WideCharToMultiByte(CP_UTF8, - 0, - host, - -1, - req->host, - sizeof(req->host), - NULL, - NULL); - - WideCharToMultiByte(CP_UTF8, - 0, - service, - -1, - req->service, - sizeof(req->service), - NULL, - NULL); -} - - -/* -* Called from uv_run when complete. -*/ -static void uv__getnameinfo_done(struct uv__work* w, int status) { - uv_getnameinfo_t* req; - char* host; - char* service; - - req = container_of(w, uv_getnameinfo_t, work_req); - uv__req_unregister(req->loop, req); - host = service = NULL; - - if (status == UV_ECANCELED) { - assert(req->retcode == 0); - req->retcode = UV_EAI_CANCELED; - } else if (req->retcode == 0) { - host = req->host; - service = req->service; - } - - if (req->getnameinfo_cb) - req->getnameinfo_cb(req, req->retcode, host, service); -} - - -/* -* Entry point for getnameinfo -* return 0 if a callback will be made -* return error code if validation fails -*/ -int uv_getnameinfo(uv_loop_t* loop, - uv_getnameinfo_t* req, - uv_getnameinfo_cb getnameinfo_cb, - const struct sockaddr* addr, - int flags) { - if (req == NULL || addr == NULL) - return UV_EINVAL; - - if (addr->sa_family == AF_INET) { - memcpy(&req->storage, - addr, - sizeof(struct sockaddr_in)); - } else if (addr->sa_family == AF_INET6) { - memcpy(&req->storage, - addr, - sizeof(struct sockaddr_in6)); - } else { - return UV_EINVAL; - } - - uv_req_init(loop, (uv_req_t*)req); - uv__req_register(loop, req); - - req->getnameinfo_cb = getnameinfo_cb; - req->flags = flags; - req->type = UV_GETNAMEINFO; - req->loop = loop; - req->retcode = 0; - - if (getnameinfo_cb) { - uv__work_submit(loop, - &req->work_req, - uv__getnameinfo_work, - uv__getnameinfo_done); - return 0; - } else { - uv__getnameinfo_work(&req->work_req); - uv__getnameinfo_done(&req->work_req, 0); - return req->retcode; - } -} diff --git a/vendor/libuv/src/win/handle-inl.h b/vendor/libuv/src/win/handle-inl.h deleted file mode 100644 index 8d0334cc5..000000000 --- a/vendor/libuv/src/win/handle-inl.h +++ /dev/null @@ -1,179 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef UV_WIN_HANDLE_INL_H_ -#define UV_WIN_HANDLE_INL_H_ - -#include -#include - -#include "uv.h" -#include "internal.h" - - -#define DECREASE_ACTIVE_COUNT(loop, handle) \ - do { \ - if (--(handle)->activecnt == 0 && \ - !((handle)->flags & UV__HANDLE_CLOSING)) { \ - uv__handle_stop((handle)); \ - } \ - assert((handle)->activecnt >= 0); \ - } while (0) - - -#define INCREASE_ACTIVE_COUNT(loop, handle) \ - do { \ - if ((handle)->activecnt++ == 0) { \ - uv__handle_start((handle)); \ - } \ - assert((handle)->activecnt > 0); \ - } while (0) - - -#define DECREASE_PENDING_REQ_COUNT(handle) \ - do { \ - assert(handle->reqs_pending > 0); \ - handle->reqs_pending--; \ - \ - if (handle->flags & UV__HANDLE_CLOSING && \ - handle->reqs_pending == 0) { \ - uv_want_endgame(loop, (uv_handle_t*)handle); \ - } \ - } while (0) - - -#define uv__handle_closing(handle) \ - do { \ - assert(!((handle)->flags & UV__HANDLE_CLOSING)); \ - \ - if (!(((handle)->flags & UV__HANDLE_ACTIVE) && \ - ((handle)->flags & UV__HANDLE_REF))) \ - uv__active_handle_add((uv_handle_t*) (handle)); \ - \ - (handle)->flags |= UV__HANDLE_CLOSING; \ - (handle)->flags &= ~UV__HANDLE_ACTIVE; \ - } while (0) - - -#define uv__handle_close(handle) \ - do { \ - QUEUE_REMOVE(&(handle)->handle_queue); \ - uv__active_handle_rm((uv_handle_t*) (handle)); \ - \ - (handle)->flags |= UV_HANDLE_CLOSED; \ - \ - if ((handle)->close_cb) \ - (handle)->close_cb((uv_handle_t*) (handle)); \ - } while (0) - - -INLINE static void uv_want_endgame(uv_loop_t* loop, uv_handle_t* handle) { - if (!(handle->flags & UV_HANDLE_ENDGAME_QUEUED)) { - handle->flags |= UV_HANDLE_ENDGAME_QUEUED; - - handle->endgame_next = loop->endgame_handles; - loop->endgame_handles = handle; - } -} - - -INLINE static void uv_process_endgames(uv_loop_t* loop) { - uv_handle_t* handle; - - while (loop->endgame_handles) { - handle = loop->endgame_handles; - loop->endgame_handles = handle->endgame_next; - - handle->flags &= ~UV_HANDLE_ENDGAME_QUEUED; - - switch (handle->type) { - case UV_TCP: - uv_tcp_endgame(loop, (uv_tcp_t*) handle); - break; - - case UV_NAMED_PIPE: - uv_pipe_endgame(loop, (uv_pipe_t*) handle); - break; - - case UV_TTY: - uv_tty_endgame(loop, (uv_tty_t*) handle); - break; - - case UV_UDP: - uv_udp_endgame(loop, (uv_udp_t*) handle); - break; - - case UV_POLL: - uv_poll_endgame(loop, (uv_poll_t*) handle); - break; - - case UV_TIMER: - uv_timer_endgame(loop, (uv_timer_t*) handle); - break; - - case UV_PREPARE: - case UV_CHECK: - case UV_IDLE: - uv_loop_watcher_endgame(loop, handle); - break; - - case UV_ASYNC: - uv_async_endgame(loop, (uv_async_t*) handle); - break; - - case UV_SIGNAL: - uv_signal_endgame(loop, (uv_signal_t*) handle); - break; - - case UV_PROCESS: - uv_process_endgame(loop, (uv_process_t*) handle); - break; - - case UV_FS_EVENT: - uv_fs_event_endgame(loop, (uv_fs_event_t*) handle); - break; - - case UV_FS_POLL: - uv__fs_poll_endgame(loop, (uv_fs_poll_t*) handle); - break; - - default: - assert(0); - break; - } - } -} - -INLINE static HANDLE uv__get_osfhandle(int fd) -{ - /* _get_osfhandle() raises an assert in debug builds if the FD is invalid. */ - /* But it also correctly checks the FD and returns INVALID_HANDLE_VALUE */ - /* for invalid FDs in release builds (or if you let the assert continue). */ - /* So this wrapper function disables asserts when calling _get_osfhandle. */ - - HANDLE handle; - UV_BEGIN_DISABLE_CRT_ASSERT(); - handle = (HANDLE) _get_osfhandle(fd); - UV_END_DISABLE_CRT_ASSERT(); - return handle; -} - -#endif /* UV_WIN_HANDLE_INL_H_ */ diff --git a/vendor/libuv/src/win/handle.c b/vendor/libuv/src/win/handle.c deleted file mode 100644 index 72b49d979..000000000 --- a/vendor/libuv/src/win/handle.c +++ /dev/null @@ -1,154 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include -#include -#include - -#include "uv.h" -#include "internal.h" -#include "handle-inl.h" - - -uv_handle_type uv_guess_handle(uv_file file) { - HANDLE handle; - DWORD mode; - - if (file < 0) { - return UV_UNKNOWN_HANDLE; - } - - handle = uv__get_osfhandle(file); - - switch (GetFileType(handle)) { - case FILE_TYPE_CHAR: - if (GetConsoleMode(handle, &mode)) { - return UV_TTY; - } else { - return UV_FILE; - } - - case FILE_TYPE_PIPE: - return UV_NAMED_PIPE; - - case FILE_TYPE_DISK: - return UV_FILE; - - default: - return UV_UNKNOWN_HANDLE; - } -} - - -int uv_is_active(const uv_handle_t* handle) { - return (handle->flags & UV__HANDLE_ACTIVE) && - !(handle->flags & UV__HANDLE_CLOSING); -} - - -void uv_close(uv_handle_t* handle, uv_close_cb cb) { - uv_loop_t* loop = handle->loop; - - if (handle->flags & UV__HANDLE_CLOSING) { - assert(0); - return; - } - - handle->close_cb = cb; - - /* Handle-specific close actions */ - switch (handle->type) { - case UV_TCP: - uv_tcp_close(loop, (uv_tcp_t*)handle); - return; - - case UV_NAMED_PIPE: - uv_pipe_close(loop, (uv_pipe_t*) handle); - return; - - case UV_TTY: - uv_tty_close((uv_tty_t*) handle); - return; - - case UV_UDP: - uv_udp_close(loop, (uv_udp_t*) handle); - return; - - case UV_POLL: - uv_poll_close(loop, (uv_poll_t*) handle); - return; - - case UV_TIMER: - uv_timer_stop((uv_timer_t*)handle); - uv__handle_closing(handle); - uv_want_endgame(loop, handle); - return; - - case UV_PREPARE: - uv_prepare_stop((uv_prepare_t*)handle); - uv__handle_closing(handle); - uv_want_endgame(loop, handle); - return; - - case UV_CHECK: - uv_check_stop((uv_check_t*)handle); - uv__handle_closing(handle); - uv_want_endgame(loop, handle); - return; - - case UV_IDLE: - uv_idle_stop((uv_idle_t*)handle); - uv__handle_closing(handle); - uv_want_endgame(loop, handle); - return; - - case UV_ASYNC: - uv_async_close(loop, (uv_async_t*) handle); - return; - - case UV_SIGNAL: - uv_signal_close(loop, (uv_signal_t*) handle); - return; - - case UV_PROCESS: - uv_process_close(loop, (uv_process_t*) handle); - return; - - case UV_FS_EVENT: - uv_fs_event_close(loop, (uv_fs_event_t*) handle); - return; - - case UV_FS_POLL: - uv__fs_poll_close((uv_fs_poll_t*) handle); - uv__handle_closing(handle); - uv_want_endgame(loop, handle); - return; - - default: - /* Not supported */ - abort(); - } -} - - -int uv_is_closing(const uv_handle_t* handle) { - return !!(handle->flags & (UV__HANDLE_CLOSING | UV_HANDLE_CLOSED)); -} diff --git a/vendor/libuv/src/win/internal.h b/vendor/libuv/src/win/internal.h deleted file mode 100644 index b8cfde90e..000000000 --- a/vendor/libuv/src/win/internal.h +++ /dev/null @@ -1,394 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef UV_WIN_INTERNAL_H_ -#define UV_WIN_INTERNAL_H_ - -#include "uv.h" -#include "../uv-common.h" - -#include "tree.h" -#include "winapi.h" -#include "winsock.h" - -#ifdef _MSC_VER -# define INLINE __inline -# define UV_THREAD_LOCAL __declspec( thread ) -#else -# define INLINE inline -# define UV_THREAD_LOCAL __thread -#endif - - -#ifdef _DEBUG - -extern UV_THREAD_LOCAL int uv__crt_assert_enabled; - -#define UV_BEGIN_DISABLE_CRT_ASSERT() \ - { \ - int uv__saved_crt_assert_enabled = uv__crt_assert_enabled; \ - uv__crt_assert_enabled = FALSE; - - -#define UV_END_DISABLE_CRT_ASSERT() \ - uv__crt_assert_enabled = uv__saved_crt_assert_enabled; \ - } - -#else -#define UV_BEGIN_DISABLE_CRT_ASSERT() -#define UV_END_DISABLE_CRT_ASSERT() -#endif - -/* - * Handles - * (also see handle-inl.h) - */ - -/* Used by all handles. */ -#define UV_HANDLE_CLOSED 0x00000002 -#define UV_HANDLE_ENDGAME_QUEUED 0x00000008 - -/* uv-common.h: #define UV__HANDLE_CLOSING 0x00000001 */ -/* uv-common.h: #define UV__HANDLE_ACTIVE 0x00000040 */ -/* uv-common.h: #define UV__HANDLE_REF 0x00000020 */ -/* uv-common.h: #define UV_HANDLE_INTERNAL 0x00000080 */ - -/* Used by streams and UDP handles. */ -#define UV_HANDLE_READING 0x00000100 -#define UV_HANDLE_BOUND 0x00000200 -#define UV_HANDLE_LISTENING 0x00000800 -#define UV_HANDLE_CONNECTION 0x00001000 -#define UV_HANDLE_READABLE 0x00008000 -#define UV_HANDLE_WRITABLE 0x00010000 -#define UV_HANDLE_READ_PENDING 0x00020000 -#define UV_HANDLE_SYNC_BYPASS_IOCP 0x00040000 -#define UV_HANDLE_ZERO_READ 0x00080000 -#define UV_HANDLE_EMULATE_IOCP 0x00100000 -#define UV_HANDLE_BLOCKING_WRITES 0x00200000 -#define UV_HANDLE_CANCELLATION_PENDING 0x00400000 - -/* Used by uv_tcp_t and uv_udp_t handles */ -#define UV_HANDLE_IPV6 0x01000000 - -/* Only used by uv_tcp_t handles. */ -#define UV_HANDLE_TCP_NODELAY 0x02000000 -#define UV_HANDLE_TCP_KEEPALIVE 0x04000000 -#define UV_HANDLE_TCP_SINGLE_ACCEPT 0x08000000 -#define UV_HANDLE_TCP_ACCEPT_STATE_CHANGING 0x10000000 -#define UV_HANDLE_TCP_SOCKET_CLOSED 0x20000000 -#define UV_HANDLE_SHARED_TCP_SOCKET 0x40000000 - -/* Only used by uv_pipe_t handles. */ -#define UV_HANDLE_NON_OVERLAPPED_PIPE 0x01000000 -#define UV_HANDLE_PIPESERVER 0x02000000 -#define UV_HANDLE_PIPE_READ_CANCELABLE 0x04000000 - -/* Only used by uv_tty_t handles. */ -#define UV_HANDLE_TTY_READABLE 0x01000000 -#define UV_HANDLE_TTY_RAW 0x02000000 -#define UV_HANDLE_TTY_SAVED_POSITION 0x04000000 -#define UV_HANDLE_TTY_SAVED_ATTRIBUTES 0x08000000 - -/* Only used by uv_poll_t handles. */ -#define UV_HANDLE_POLL_SLOW 0x02000000 - - -/* - * Requests: see req-inl.h - */ - - -/* - * Streams: see stream-inl.h - */ - - -/* - * TCP - */ - -typedef struct { - WSAPROTOCOL_INFOW socket_info; - int delayed_error; -} uv__ipc_socket_info_ex; - -int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb); -int uv_tcp_accept(uv_tcp_t* server, uv_tcp_t* client); -int uv_tcp_read_start(uv_tcp_t* handle, uv_alloc_cb alloc_cb, - uv_read_cb read_cb); -int uv_tcp_write(uv_loop_t* loop, uv_write_t* req, uv_tcp_t* handle, - const uv_buf_t bufs[], unsigned int nbufs, uv_write_cb cb); -int uv__tcp_try_write(uv_tcp_t* handle, const uv_buf_t bufs[], - unsigned int nbufs); - -void uv_process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle, uv_req_t* req); -void uv_process_tcp_write_req(uv_loop_t* loop, uv_tcp_t* handle, - uv_write_t* req); -void uv_process_tcp_accept_req(uv_loop_t* loop, uv_tcp_t* handle, - uv_req_t* req); -void uv_process_tcp_connect_req(uv_loop_t* loop, uv_tcp_t* handle, - uv_connect_t* req); - -void uv_tcp_close(uv_loop_t* loop, uv_tcp_t* tcp); -void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle); - -int uv_tcp_import(uv_tcp_t* tcp, uv__ipc_socket_info_ex* socket_info_ex, - int tcp_connection); - -int uv_tcp_duplicate_socket(uv_tcp_t* handle, int pid, - LPWSAPROTOCOL_INFOW protocol_info); - - -/* - * UDP - */ -void uv_process_udp_recv_req(uv_loop_t* loop, uv_udp_t* handle, uv_req_t* req); -void uv_process_udp_send_req(uv_loop_t* loop, uv_udp_t* handle, - uv_udp_send_t* req); - -void uv_udp_close(uv_loop_t* loop, uv_udp_t* handle); -void uv_udp_endgame(uv_loop_t* loop, uv_udp_t* handle); - - -/* - * Pipes - */ -int uv_stdio_pipe_server(uv_loop_t* loop, uv_pipe_t* handle, DWORD access, - char* name, size_t nameSize); - -int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb); -int uv_pipe_accept(uv_pipe_t* server, uv_stream_t* client); -int uv_pipe_read_start(uv_pipe_t* handle, uv_alloc_cb alloc_cb, - uv_read_cb read_cb); -int uv_pipe_write(uv_loop_t* loop, uv_write_t* req, uv_pipe_t* handle, - const uv_buf_t bufs[], unsigned int nbufs, uv_write_cb cb); -int uv_pipe_write2(uv_loop_t* loop, uv_write_t* req, uv_pipe_t* handle, - const uv_buf_t bufs[], unsigned int nbufs, uv_stream_t* send_handle, - uv_write_cb cb); -void uv__pipe_pause_read(uv_pipe_t* handle); -void uv__pipe_unpause_read(uv_pipe_t* handle); -void uv__pipe_stop_read(uv_pipe_t* handle); - -void uv_process_pipe_read_req(uv_loop_t* loop, uv_pipe_t* handle, - uv_req_t* req); -void uv_process_pipe_write_req(uv_loop_t* loop, uv_pipe_t* handle, - uv_write_t* req); -void uv_process_pipe_accept_req(uv_loop_t* loop, uv_pipe_t* handle, - uv_req_t* raw_req); -void uv_process_pipe_connect_req(uv_loop_t* loop, uv_pipe_t* handle, - uv_connect_t* req); -void uv_process_pipe_shutdown_req(uv_loop_t* loop, uv_pipe_t* handle, - uv_shutdown_t* req); - -void uv_pipe_close(uv_loop_t* loop, uv_pipe_t* handle); -void uv_pipe_cleanup(uv_loop_t* loop, uv_pipe_t* handle); -void uv_pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle); - - -/* - * TTY - */ -void uv_console_init(); - -int uv_tty_read_start(uv_tty_t* handle, uv_alloc_cb alloc_cb, - uv_read_cb read_cb); -int uv_tty_read_stop(uv_tty_t* handle); -int uv_tty_write(uv_loop_t* loop, uv_write_t* req, uv_tty_t* handle, - const uv_buf_t bufs[], unsigned int nbufs, uv_write_cb cb); -int uv__tty_try_write(uv_tty_t* handle, const uv_buf_t bufs[], - unsigned int nbufs); -void uv_tty_close(uv_tty_t* handle); - -void uv_process_tty_read_req(uv_loop_t* loop, uv_tty_t* handle, - uv_req_t* req); -void uv_process_tty_write_req(uv_loop_t* loop, uv_tty_t* handle, - uv_write_t* req); -/* TODO: remove me */ -void uv_process_tty_accept_req(uv_loop_t* loop, uv_tty_t* handle, - uv_req_t* raw_req); -/* TODO: remove me */ -void uv_process_tty_connect_req(uv_loop_t* loop, uv_tty_t* handle, - uv_connect_t* req); - -void uv_tty_endgame(uv_loop_t* loop, uv_tty_t* handle); - - -/* - * Poll watchers - */ -void uv_process_poll_req(uv_loop_t* loop, uv_poll_t* handle, - uv_req_t* req); - -int uv_poll_close(uv_loop_t* loop, uv_poll_t* handle); -void uv_poll_endgame(uv_loop_t* loop, uv_poll_t* handle); - - -/* - * Timers - */ -void uv_timer_endgame(uv_loop_t* loop, uv_timer_t* handle); - -DWORD uv__next_timeout(const uv_loop_t* loop); -void uv_process_timers(uv_loop_t* loop); - - -/* - * Loop watchers - */ -void uv_loop_watcher_endgame(uv_loop_t* loop, uv_handle_t* handle); - -void uv_prepare_invoke(uv_loop_t* loop); -void uv_check_invoke(uv_loop_t* loop); -void uv_idle_invoke(uv_loop_t* loop); - -void uv__once_init(); - - -/* - * Async watcher - */ -void uv_async_close(uv_loop_t* loop, uv_async_t* handle); -void uv_async_endgame(uv_loop_t* loop, uv_async_t* handle); - -void uv_process_async_wakeup_req(uv_loop_t* loop, uv_async_t* handle, - uv_req_t* req); - - -/* - * Signal watcher - */ -void uv_signals_init(); -int uv__signal_dispatch(int signum); - -void uv_signal_close(uv_loop_t* loop, uv_signal_t* handle); -void uv_signal_endgame(uv_loop_t* loop, uv_signal_t* handle); - -void uv_process_signal_req(uv_loop_t* loop, uv_signal_t* handle, - uv_req_t* req); - - -/* - * Spawn - */ -void uv_process_proc_exit(uv_loop_t* loop, uv_process_t* handle); -void uv_process_close(uv_loop_t* loop, uv_process_t* handle); -void uv_process_endgame(uv_loop_t* loop, uv_process_t* handle); - - -/* - * Error - */ -int uv_translate_sys_error(int sys_errno); - - -/* - * FS - */ -void uv_fs_init(); - - -/* - * FS Event - */ -void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req, - uv_fs_event_t* handle); -void uv_fs_event_close(uv_loop_t* loop, uv_fs_event_t* handle); -void uv_fs_event_endgame(uv_loop_t* loop, uv_fs_event_t* handle); - - -/* - * Stat poller. - */ -void uv__fs_poll_endgame(uv_loop_t* loop, uv_fs_poll_t* handle); - - -/* - * Utilities. - */ -void uv__util_init(); - -uint64_t uv__hrtime(double scale); -int uv_parent_pid(); -int uv_current_pid(); -__declspec(noreturn) void uv_fatal_error(const int errorno, const char* syscall); -int uv__getpwuid_r(uv_passwd_t* pwd); -int uv__convert_utf16_to_utf8(const WCHAR* utf16, int utf16len, char** utf8); - - -/* - * Process stdio handles. - */ -int uv__stdio_create(uv_loop_t* loop, - const uv_process_options_t* options, - BYTE** buffer_ptr); -void uv__stdio_destroy(BYTE* buffer); -void uv__stdio_noinherit(BYTE* buffer); -int uv__stdio_verify(BYTE* buffer, WORD size); -WORD uv__stdio_size(BYTE* buffer); -HANDLE uv__stdio_handle(BYTE* buffer, int fd); - - -/* - * Winapi and ntapi utility functions - */ -void uv_winapi_init(); - - -/* - * Winsock utility functions - */ -void uv_winsock_init(); - -int uv_ntstatus_to_winsock_error(NTSTATUS status); - -BOOL uv_get_acceptex_function(SOCKET socket, LPFN_ACCEPTEX* target); -BOOL uv_get_connectex_function(SOCKET socket, LPFN_CONNECTEX* target); - -int WSAAPI uv_wsarecv_workaround(SOCKET socket, WSABUF* buffers, - DWORD buffer_count, DWORD* bytes, DWORD* flags, WSAOVERLAPPED *overlapped, - LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_routine); -int WSAAPI uv_wsarecvfrom_workaround(SOCKET socket, WSABUF* buffers, - DWORD buffer_count, DWORD* bytes, DWORD* flags, struct sockaddr* addr, - int* addr_len, WSAOVERLAPPED *overlapped, - LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_routine); - -int WSAAPI uv_msafd_poll(SOCKET socket, AFD_POLL_INFO* info_in, - AFD_POLL_INFO* info_out, OVERLAPPED* overlapped); - -/* Whether there are any non-IFS LSPs stacked on TCP */ -extern int uv_tcp_non_ifs_lsp_ipv4; -extern int uv_tcp_non_ifs_lsp_ipv6; - -/* Ip address used to bind to any port at any interface */ -extern struct sockaddr_in uv_addr_ip4_any_; -extern struct sockaddr_in6 uv_addr_ip6_any_; - -/* - * Wake all loops with fake message - */ -void uv__wake_all_loops(); - -/* - * Init system wake-up detection - */ -void uv__init_detect_system_wakeup(); - -#endif /* UV_WIN_INTERNAL_H_ */ diff --git a/vendor/libuv/src/win/loop-watcher.c b/vendor/libuv/src/win/loop-watcher.c deleted file mode 100644 index 20e4509f8..000000000 --- a/vendor/libuv/src/win/loop-watcher.c +++ /dev/null @@ -1,122 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include - -#include "uv.h" -#include "internal.h" -#include "handle-inl.h" - - -void uv_loop_watcher_endgame(uv_loop_t* loop, uv_handle_t* handle) { - if (handle->flags & UV__HANDLE_CLOSING) { - assert(!(handle->flags & UV_HANDLE_CLOSED)); - handle->flags |= UV_HANDLE_CLOSED; - uv__handle_close(handle); - } -} - - -#define UV_LOOP_WATCHER_DEFINE(name, NAME) \ - int uv_##name##_init(uv_loop_t* loop, uv_##name##_t* handle) { \ - uv__handle_init(loop, (uv_handle_t*) handle, UV_##NAME); \ - \ - return 0; \ - } \ - \ - \ - int uv_##name##_start(uv_##name##_t* handle, uv_##name##_cb cb) { \ - uv_loop_t* loop = handle->loop; \ - uv_##name##_t* old_head; \ - \ - assert(handle->type == UV_##NAME); \ - \ - if (uv__is_active(handle)) \ - return 0; \ - \ - if (cb == NULL) \ - return UV_EINVAL; \ - \ - old_head = loop->name##_handles; \ - \ - handle->name##_next = old_head; \ - handle->name##_prev = NULL; \ - \ - if (old_head) { \ - old_head->name##_prev = handle; \ - } \ - \ - loop->name##_handles = handle; \ - \ - handle->name##_cb = cb; \ - uv__handle_start(handle); \ - \ - return 0; \ - } \ - \ - \ - int uv_##name##_stop(uv_##name##_t* handle) { \ - uv_loop_t* loop = handle->loop; \ - \ - assert(handle->type == UV_##NAME); \ - \ - if (!uv__is_active(handle)) \ - return 0; \ - \ - /* Update loop head if needed */ \ - if (loop->name##_handles == handle) { \ - loop->name##_handles = handle->name##_next; \ - } \ - \ - /* Update the iterator-next pointer of needed */ \ - if (loop->next_##name##_handle == handle) { \ - loop->next_##name##_handle = handle->name##_next; \ - } \ - \ - if (handle->name##_prev) { \ - handle->name##_prev->name##_next = handle->name##_next; \ - } \ - if (handle->name##_next) { \ - handle->name##_next->name##_prev = handle->name##_prev; \ - } \ - \ - uv__handle_stop(handle); \ - \ - return 0; \ - } \ - \ - \ - void uv_##name##_invoke(uv_loop_t* loop) { \ - uv_##name##_t* handle; \ - \ - (loop)->next_##name##_handle = (loop)->name##_handles; \ - \ - while ((loop)->next_##name##_handle != NULL) { \ - handle = (loop)->next_##name##_handle; \ - (loop)->next_##name##_handle = handle->name##_next; \ - \ - handle->name##_cb(handle); \ - } \ - } - -UV_LOOP_WATCHER_DEFINE(prepare, PREPARE) -UV_LOOP_WATCHER_DEFINE(check, CHECK) -UV_LOOP_WATCHER_DEFINE(idle, IDLE) diff --git a/vendor/libuv/src/win/pipe.c b/vendor/libuv/src/win/pipe.c deleted file mode 100644 index 2442be730..000000000 --- a/vendor/libuv/src/win/pipe.c +++ /dev/null @@ -1,2130 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include -#include -#include -#include -#include - -#include "uv.h" -#include "internal.h" -#include "handle-inl.h" -#include "stream-inl.h" -#include "req-inl.h" - -typedef struct uv__ipc_queue_item_s uv__ipc_queue_item_t; - -struct uv__ipc_queue_item_s { - /* - * NOTE: It is important for socket_info_ex to be the first field, - * because we will we assigning it to the pending_ipc_info.socket_info - */ - uv__ipc_socket_info_ex socket_info_ex; - QUEUE member; - int tcp_connection; -}; - -/* A zero-size buffer for use by uv_pipe_read */ -static char uv_zero_[] = ""; - -/* Null uv_buf_t */ -static const uv_buf_t uv_null_buf_ = { 0, NULL }; - -/* The timeout that the pipe will wait for the remote end to write data */ -/* when the local ends wants to shut it down. */ -static const int64_t eof_timeout = 50; /* ms */ - -static const int default_pending_pipe_instances = 4; - -/* Pipe prefix */ -static char pipe_prefix[] = "\\\\?\\pipe"; -static const int pipe_prefix_len = sizeof(pipe_prefix) - 1; - -/* IPC protocol flags. */ -#define UV_IPC_RAW_DATA 0x0001 -#define UV_IPC_TCP_SERVER 0x0002 -#define UV_IPC_TCP_CONNECTION 0x0004 - -/* IPC frame header. */ -typedef struct { - int flags; - uint64_t raw_data_length; -} uv_ipc_frame_header_t; - -/* IPC frame, which contains an imported TCP socket stream. */ -typedef struct { - uv_ipc_frame_header_t header; - uv__ipc_socket_info_ex socket_info_ex; -} uv_ipc_frame_uv_stream; - -static void eof_timer_init(uv_pipe_t* pipe); -static void eof_timer_start(uv_pipe_t* pipe); -static void eof_timer_stop(uv_pipe_t* pipe); -static void eof_timer_cb(uv_timer_t* timer); -static void eof_timer_destroy(uv_pipe_t* pipe); -static void eof_timer_close_cb(uv_handle_t* handle); - - -static void uv_unique_pipe_name(char* ptr, char* name, size_t size) { - snprintf(name, size, "\\\\?\\pipe\\uv\\%p-%lu", ptr, GetCurrentProcessId()); -} - - -int uv_pipe_init(uv_loop_t* loop, uv_pipe_t* handle, int ipc) { - uv_stream_init(loop, (uv_stream_t*)handle, UV_NAMED_PIPE); - - handle->reqs_pending = 0; - handle->handle = INVALID_HANDLE_VALUE; - handle->name = NULL; - handle->pipe.conn.ipc_pid = 0; - handle->pipe.conn.remaining_ipc_rawdata_bytes = 0; - QUEUE_INIT(&handle->pipe.conn.pending_ipc_info.queue); - handle->pipe.conn.pending_ipc_info.queue_len = 0; - handle->ipc = ipc; - handle->pipe.conn.non_overlapped_writes_tail = NULL; - handle->pipe.conn.readfile_thread = NULL; - - uv_req_init(loop, (uv_req_t*) &handle->pipe.conn.ipc_header_write_req); - - return 0; -} - - -static void uv_pipe_connection_init(uv_pipe_t* handle) { - uv_connection_init((uv_stream_t*) handle); - handle->read_req.data = handle; - handle->pipe.conn.eof_timer = NULL; - assert(!(handle->flags & UV_HANDLE_PIPESERVER)); - if (pCancelSynchronousIo && - handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) { - uv_mutex_init(&handle->pipe.conn.readfile_mutex); - handle->flags |= UV_HANDLE_PIPE_READ_CANCELABLE; - } -} - - -static HANDLE open_named_pipe(const WCHAR* name, DWORD* duplex_flags) { - HANDLE pipeHandle; - - /* - * Assume that we have a duplex pipe first, so attempt to - * connect with GENERIC_READ | GENERIC_WRITE. - */ - pipeHandle = CreateFileW(name, - GENERIC_READ | GENERIC_WRITE, - 0, - NULL, - OPEN_EXISTING, - FILE_FLAG_OVERLAPPED, - NULL); - if (pipeHandle != INVALID_HANDLE_VALUE) { - *duplex_flags = UV_HANDLE_READABLE | UV_HANDLE_WRITABLE; - return pipeHandle; - } - - /* - * If the pipe is not duplex CreateFileW fails with - * ERROR_ACCESS_DENIED. In that case try to connect - * as a read-only or write-only. - */ - if (GetLastError() == ERROR_ACCESS_DENIED) { - pipeHandle = CreateFileW(name, - GENERIC_READ | FILE_WRITE_ATTRIBUTES, - 0, - NULL, - OPEN_EXISTING, - FILE_FLAG_OVERLAPPED, - NULL); - - if (pipeHandle != INVALID_HANDLE_VALUE) { - *duplex_flags = UV_HANDLE_READABLE; - return pipeHandle; - } - } - - if (GetLastError() == ERROR_ACCESS_DENIED) { - pipeHandle = CreateFileW(name, - GENERIC_WRITE | FILE_READ_ATTRIBUTES, - 0, - NULL, - OPEN_EXISTING, - FILE_FLAG_OVERLAPPED, - NULL); - - if (pipeHandle != INVALID_HANDLE_VALUE) { - *duplex_flags = UV_HANDLE_WRITABLE; - return pipeHandle; - } - } - - return INVALID_HANDLE_VALUE; -} - - -static void close_pipe(uv_pipe_t* pipe) { - assert(pipe->u.fd == -1 || pipe->u.fd > 2); - if (pipe->u.fd == -1) - CloseHandle(pipe->handle); - else - close(pipe->u.fd); - - pipe->u.fd = -1; - pipe->handle = INVALID_HANDLE_VALUE; -} - - -int uv_stdio_pipe_server(uv_loop_t* loop, uv_pipe_t* handle, DWORD access, - char* name, size_t nameSize) { - HANDLE pipeHandle; - int err; - char* ptr = (char*)handle; - - for (;;) { - uv_unique_pipe_name(ptr, name, nameSize); - - pipeHandle = CreateNamedPipeA(name, - access | FILE_FLAG_OVERLAPPED | FILE_FLAG_FIRST_PIPE_INSTANCE, - PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1, 65536, 65536, 0, - NULL); - - if (pipeHandle != INVALID_HANDLE_VALUE) { - /* No name collisions. We're done. */ - break; - } - - err = GetLastError(); - if (err != ERROR_PIPE_BUSY && err != ERROR_ACCESS_DENIED) { - goto error; - } - - /* Pipe name collision. Increment the pointer and try again. */ - ptr++; - } - - if (CreateIoCompletionPort(pipeHandle, - loop->iocp, - (ULONG_PTR)handle, - 0) == NULL) { - err = GetLastError(); - goto error; - } - - uv_pipe_connection_init(handle); - handle->handle = pipeHandle; - - return 0; - - error: - if (pipeHandle != INVALID_HANDLE_VALUE) { - CloseHandle(pipeHandle); - } - - return err; -} - - -static int uv_set_pipe_handle(uv_loop_t* loop, - uv_pipe_t* handle, - HANDLE pipeHandle, - int fd, - DWORD duplex_flags) { - NTSTATUS nt_status; - IO_STATUS_BLOCK io_status; - FILE_MODE_INFORMATION mode_info; - DWORD mode = PIPE_READMODE_BYTE | PIPE_WAIT; - DWORD current_mode = 0; - DWORD err = 0; - - if (!(handle->flags & UV_HANDLE_PIPESERVER) && - handle->handle != INVALID_HANDLE_VALUE) - return UV_EBUSY; - - if (!SetNamedPipeHandleState(pipeHandle, &mode, NULL, NULL)) { - err = GetLastError(); - if (err == ERROR_ACCESS_DENIED) { - /* - * SetNamedPipeHandleState can fail if the handle doesn't have either - * GENERIC_WRITE or FILE_WRITE_ATTRIBUTES. - * But if the handle already has the desired wait and blocking modes - * we can continue. - */ - if (!GetNamedPipeHandleState(pipeHandle, ¤t_mode, NULL, NULL, - NULL, NULL, 0)) { - return -1; - } else if (current_mode & PIPE_NOWAIT) { - SetLastError(ERROR_ACCESS_DENIED); - return -1; - } - } else { - /* If this returns ERROR_INVALID_PARAMETER we probably opened - * something that is not a pipe. */ - if (err == ERROR_INVALID_PARAMETER) { - SetLastError(WSAENOTSOCK); - } - return -1; - } - } - - /* Check if the pipe was created with FILE_FLAG_OVERLAPPED. */ - nt_status = pNtQueryInformationFile(pipeHandle, - &io_status, - &mode_info, - sizeof(mode_info), - FileModeInformation); - if (nt_status != STATUS_SUCCESS) { - return -1; - } - - if (mode_info.Mode & FILE_SYNCHRONOUS_IO_ALERT || - mode_info.Mode & FILE_SYNCHRONOUS_IO_NONALERT) { - /* Non-overlapped pipe. */ - handle->flags |= UV_HANDLE_NON_OVERLAPPED_PIPE; - } else { - /* Overlapped pipe. Try to associate with IOCP. */ - if (CreateIoCompletionPort(pipeHandle, - loop->iocp, - (ULONG_PTR)handle, - 0) == NULL) { - handle->flags |= UV_HANDLE_EMULATE_IOCP; - } - } - - handle->handle = pipeHandle; - handle->u.fd = fd; - handle->flags |= duplex_flags; - - return 0; -} - - -static DWORD WINAPI pipe_shutdown_thread_proc(void* parameter) { - uv_loop_t* loop; - uv_pipe_t* handle; - uv_shutdown_t* req; - - req = (uv_shutdown_t*) parameter; - assert(req); - handle = (uv_pipe_t*) req->handle; - assert(handle); - loop = handle->loop; - assert(loop); - - FlushFileBuffers(handle->handle); - - /* Post completed */ - POST_COMPLETION_FOR_REQ(loop, req); - - return 0; -} - - -void uv_pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle) { - int err; - DWORD result; - uv_shutdown_t* req; - NTSTATUS nt_status; - IO_STATUS_BLOCK io_status; - FILE_PIPE_LOCAL_INFORMATION pipe_info; - uv__ipc_queue_item_t* item; - - if (handle->flags & UV_HANDLE_PIPE_READ_CANCELABLE) { - handle->flags &= ~UV_HANDLE_PIPE_READ_CANCELABLE; - uv_mutex_destroy(&handle->pipe.conn.readfile_mutex); - } - - if ((handle->flags & UV_HANDLE_CONNECTION) && - handle->stream.conn.shutdown_req != NULL && - handle->stream.conn.write_reqs_pending == 0) { - req = handle->stream.conn.shutdown_req; - - /* Clear the shutdown_req field so we don't go here again. */ - handle->stream.conn.shutdown_req = NULL; - - if (handle->flags & UV__HANDLE_CLOSING) { - UNREGISTER_HANDLE_REQ(loop, handle, req); - - /* Already closing. Cancel the shutdown. */ - if (req->cb) { - req->cb(req, UV_ECANCELED); - } - - DECREASE_PENDING_REQ_COUNT(handle); - return; - } - - /* Try to avoid flushing the pipe buffer in the thread pool. */ - nt_status = pNtQueryInformationFile(handle->handle, - &io_status, - &pipe_info, - sizeof pipe_info, - FilePipeLocalInformation); - - if (nt_status != STATUS_SUCCESS) { - /* Failure */ - UNREGISTER_HANDLE_REQ(loop, handle, req); - - handle->flags |= UV_HANDLE_WRITABLE; /* Questionable */ - if (req->cb) { - err = pRtlNtStatusToDosError(nt_status); - req->cb(req, uv_translate_sys_error(err)); - } - - DECREASE_PENDING_REQ_COUNT(handle); - return; - } - - if (pipe_info.OutboundQuota == pipe_info.WriteQuotaAvailable) { - /* Short-circuit, no need to call FlushFileBuffers. */ - uv_insert_pending_req(loop, (uv_req_t*) req); - return; - } - - /* Run FlushFileBuffers in the thread pool. */ - result = QueueUserWorkItem(pipe_shutdown_thread_proc, - req, - WT_EXECUTELONGFUNCTION); - if (result) { - return; - - } else { - /* Failure. */ - UNREGISTER_HANDLE_REQ(loop, handle, req); - - handle->flags |= UV_HANDLE_WRITABLE; /* Questionable */ - if (req->cb) { - err = GetLastError(); - req->cb(req, uv_translate_sys_error(err)); - } - - DECREASE_PENDING_REQ_COUNT(handle); - return; - } - } - - if (handle->flags & UV__HANDLE_CLOSING && - handle->reqs_pending == 0) { - assert(!(handle->flags & UV_HANDLE_CLOSED)); - - if (handle->flags & UV_HANDLE_CONNECTION) { - /* Free pending sockets */ - while (!QUEUE_EMPTY(&handle->pipe.conn.pending_ipc_info.queue)) { - QUEUE* q; - SOCKET socket; - - q = QUEUE_HEAD(&handle->pipe.conn.pending_ipc_info.queue); - QUEUE_REMOVE(q); - item = QUEUE_DATA(q, uv__ipc_queue_item_t, member); - - /* Materialize socket and close it */ - socket = WSASocketW(FROM_PROTOCOL_INFO, - FROM_PROTOCOL_INFO, - FROM_PROTOCOL_INFO, - &item->socket_info_ex.socket_info, - 0, - WSA_FLAG_OVERLAPPED); - uv__free(item); - - if (socket != INVALID_SOCKET) - closesocket(socket); - } - handle->pipe.conn.pending_ipc_info.queue_len = 0; - - if (handle->flags & UV_HANDLE_EMULATE_IOCP) { - if (handle->read_req.wait_handle != INVALID_HANDLE_VALUE) { - UnregisterWait(handle->read_req.wait_handle); - handle->read_req.wait_handle = INVALID_HANDLE_VALUE; - } - if (handle->read_req.event_handle) { - CloseHandle(handle->read_req.event_handle); - handle->read_req.event_handle = NULL; - } - } - } - - if (handle->flags & UV_HANDLE_PIPESERVER) { - assert(handle->pipe.serv.accept_reqs); - uv__free(handle->pipe.serv.accept_reqs); - handle->pipe.serv.accept_reqs = NULL; - } - - uv__handle_close(handle); - } -} - - -void uv_pipe_pending_instances(uv_pipe_t* handle, int count) { - if (handle->flags & UV_HANDLE_BOUND) - return; - handle->pipe.serv.pending_instances = count; - handle->flags |= UV_HANDLE_PIPESERVER; -} - - -/* Creates a pipe server. */ -int uv_pipe_bind(uv_pipe_t* handle, const char* name) { - uv_loop_t* loop = handle->loop; - int i, err, nameSize; - uv_pipe_accept_t* req; - - if (handle->flags & UV_HANDLE_BOUND) { - return UV_EINVAL; - } - - if (!name) { - return UV_EINVAL; - } - - if (!(handle->flags & UV_HANDLE_PIPESERVER)) { - handle->pipe.serv.pending_instances = default_pending_pipe_instances; - } - - handle->pipe.serv.accept_reqs = (uv_pipe_accept_t*) - uv__malloc(sizeof(uv_pipe_accept_t) * handle->pipe.serv.pending_instances); - if (!handle->pipe.serv.accept_reqs) { - uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc"); - } - - for (i = 0; i < handle->pipe.serv.pending_instances; i++) { - req = &handle->pipe.serv.accept_reqs[i]; - uv_req_init(loop, (uv_req_t*) req); - req->type = UV_ACCEPT; - req->data = handle; - req->pipeHandle = INVALID_HANDLE_VALUE; - req->next_pending = NULL; - } - - /* Convert name to UTF16. */ - nameSize = MultiByteToWideChar(CP_UTF8, 0, name, -1, NULL, 0) * sizeof(WCHAR); - handle->name = (WCHAR*)uv__malloc(nameSize); - if (!handle->name) { - uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc"); - } - - if (!MultiByteToWideChar(CP_UTF8, - 0, - name, - -1, - handle->name, - nameSize / sizeof(WCHAR))) { - err = GetLastError(); - goto error; - } - - /* - * Attempt to create the first pipe with FILE_FLAG_FIRST_PIPE_INSTANCE. - * If this fails then there's already a pipe server for the given pipe name. - */ - handle->pipe.serv.accept_reqs[0].pipeHandle = CreateNamedPipeW(handle->name, - PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | - FILE_FLAG_FIRST_PIPE_INSTANCE, - PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, - PIPE_UNLIMITED_INSTANCES, 65536, 65536, 0, NULL); - - if (handle->pipe.serv.accept_reqs[0].pipeHandle == INVALID_HANDLE_VALUE) { - err = GetLastError(); - if (err == ERROR_ACCESS_DENIED) { - err = WSAEADDRINUSE; /* Translates to UV_EADDRINUSE. */ - } else if (err == ERROR_PATH_NOT_FOUND || err == ERROR_INVALID_NAME) { - err = WSAEACCES; /* Translates to UV_EACCES. */ - } - goto error; - } - - if (uv_set_pipe_handle(loop, - handle, - handle->pipe.serv.accept_reqs[0].pipeHandle, - -1, - 0)) { - err = GetLastError(); - goto error; - } - - handle->pipe.serv.pending_accepts = NULL; - handle->flags |= UV_HANDLE_PIPESERVER; - handle->flags |= UV_HANDLE_BOUND; - - return 0; - -error: - if (handle->name) { - uv__free(handle->name); - handle->name = NULL; - } - - if (handle->pipe.serv.accept_reqs[0].pipeHandle != INVALID_HANDLE_VALUE) { - CloseHandle(handle->pipe.serv.accept_reqs[0].pipeHandle); - handle->pipe.serv.accept_reqs[0].pipeHandle = INVALID_HANDLE_VALUE; - } - - return uv_translate_sys_error(err); -} - - -static DWORD WINAPI pipe_connect_thread_proc(void* parameter) { - uv_loop_t* loop; - uv_pipe_t* handle; - uv_connect_t* req; - HANDLE pipeHandle = INVALID_HANDLE_VALUE; - DWORD duplex_flags; - - req = (uv_connect_t*) parameter; - assert(req); - handle = (uv_pipe_t*) req->handle; - assert(handle); - loop = handle->loop; - assert(loop); - - /* We're here because CreateFile on a pipe returned ERROR_PIPE_BUSY. */ - /* We wait for the pipe to become available with WaitNamedPipe. */ - while (WaitNamedPipeW(handle->name, 30000)) { - /* The pipe is now available, try to connect. */ - pipeHandle = open_named_pipe(handle->name, &duplex_flags); - if (pipeHandle != INVALID_HANDLE_VALUE) { - break; - } - - SwitchToThread(); - } - - if (pipeHandle != INVALID_HANDLE_VALUE && - !uv_set_pipe_handle(loop, handle, pipeHandle, -1, duplex_flags)) { - SET_REQ_SUCCESS(req); - } else { - SET_REQ_ERROR(req, GetLastError()); - } - - /* Post completed */ - POST_COMPLETION_FOR_REQ(loop, req); - - return 0; -} - - -void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle, - const char* name, uv_connect_cb cb) { - uv_loop_t* loop = handle->loop; - int err, nameSize; - HANDLE pipeHandle = INVALID_HANDLE_VALUE; - DWORD duplex_flags; - - uv_req_init(loop, (uv_req_t*) req); - req->type = UV_CONNECT; - req->handle = (uv_stream_t*) handle; - req->cb = cb; - - /* Convert name to UTF16. */ - nameSize = MultiByteToWideChar(CP_UTF8, 0, name, -1, NULL, 0) * sizeof(WCHAR); - handle->name = (WCHAR*)uv__malloc(nameSize); - if (!handle->name) { - uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc"); - } - - if (!MultiByteToWideChar(CP_UTF8, - 0, - name, - -1, - handle->name, - nameSize / sizeof(WCHAR))) { - err = GetLastError(); - goto error; - } - - pipeHandle = open_named_pipe(handle->name, &duplex_flags); - if (pipeHandle == INVALID_HANDLE_VALUE) { - if (GetLastError() == ERROR_PIPE_BUSY) { - /* Wait for the server to make a pipe instance available. */ - if (!QueueUserWorkItem(&pipe_connect_thread_proc, - req, - WT_EXECUTELONGFUNCTION)) { - err = GetLastError(); - goto error; - } - - REGISTER_HANDLE_REQ(loop, handle, req); - handle->reqs_pending++; - - return; - } - - err = GetLastError(); - goto error; - } - - assert(pipeHandle != INVALID_HANDLE_VALUE); - - if (uv_set_pipe_handle(loop, - (uv_pipe_t*) req->handle, - pipeHandle, - -1, - duplex_flags)) { - err = GetLastError(); - goto error; - } - - SET_REQ_SUCCESS(req); - uv_insert_pending_req(loop, (uv_req_t*) req); - handle->reqs_pending++; - REGISTER_HANDLE_REQ(loop, handle, req); - return; - -error: - if (handle->name) { - uv__free(handle->name); - handle->name = NULL; - } - - if (pipeHandle != INVALID_HANDLE_VALUE) { - CloseHandle(pipeHandle); - } - - /* Make this req pending reporting an error. */ - SET_REQ_ERROR(req, err); - uv_insert_pending_req(loop, (uv_req_t*) req); - handle->reqs_pending++; - REGISTER_HANDLE_REQ(loop, handle, req); - return; -} - - -void uv__pipe_pause_read(uv_pipe_t* handle) { - if (handle->flags & UV_HANDLE_PIPE_READ_CANCELABLE) { - /* Pause the ReadFile task briefly, to work - around the Windows kernel bug that causes - any access to a NamedPipe to deadlock if - any process has called ReadFile */ - HANDLE h; - uv_mutex_lock(&handle->pipe.conn.readfile_mutex); - h = handle->pipe.conn.readfile_thread; - while (h) { - /* spinlock: we expect this to finish quickly, - or we are probably about to deadlock anyways - (in the kernel), so it doesn't matter */ - pCancelSynchronousIo(h); - SwitchToThread(); /* yield thread control briefly */ - h = handle->pipe.conn.readfile_thread; - } - } -} - - -void uv__pipe_unpause_read(uv_pipe_t* handle) { - if (handle->flags & UV_HANDLE_PIPE_READ_CANCELABLE) { - uv_mutex_unlock(&handle->pipe.conn.readfile_mutex); - } -} - - -void uv__pipe_stop_read(uv_pipe_t* handle) { - handle->flags &= ~UV_HANDLE_READING; - uv__pipe_pause_read((uv_pipe_t*)handle); - uv__pipe_unpause_read((uv_pipe_t*)handle); -} - - -/* Cleans up uv_pipe_t (server or connection) and all resources associated */ -/* with it. */ -void uv_pipe_cleanup(uv_loop_t* loop, uv_pipe_t* handle) { - int i; - HANDLE pipeHandle; - - uv__pipe_stop_read(handle); - - if (handle->name) { - uv__free(handle->name); - handle->name = NULL; - } - - if (handle->flags & UV_HANDLE_PIPESERVER) { - for (i = 0; i < handle->pipe.serv.pending_instances; i++) { - pipeHandle = handle->pipe.serv.accept_reqs[i].pipeHandle; - if (pipeHandle != INVALID_HANDLE_VALUE) { - CloseHandle(pipeHandle); - handle->pipe.serv.accept_reqs[i].pipeHandle = INVALID_HANDLE_VALUE; - } - } - handle->handle = INVALID_HANDLE_VALUE; - } - - if (handle->flags & UV_HANDLE_CONNECTION) { - handle->flags &= ~UV_HANDLE_WRITABLE; - eof_timer_destroy(handle); - } - - if ((handle->flags & UV_HANDLE_CONNECTION) - && handle->handle != INVALID_HANDLE_VALUE) - close_pipe(handle); -} - - -void uv_pipe_close(uv_loop_t* loop, uv_pipe_t* handle) { - if (handle->flags & UV_HANDLE_READING) { - handle->flags &= ~UV_HANDLE_READING; - DECREASE_ACTIVE_COUNT(loop, handle); - } - - if (handle->flags & UV_HANDLE_LISTENING) { - handle->flags &= ~UV_HANDLE_LISTENING; - DECREASE_ACTIVE_COUNT(loop, handle); - } - - uv_pipe_cleanup(loop, handle); - - if (handle->reqs_pending == 0) { - uv_want_endgame(loop, (uv_handle_t*) handle); - } - - handle->flags &= ~(UV_HANDLE_READABLE | UV_HANDLE_WRITABLE); - uv__handle_closing(handle); -} - - -static void uv_pipe_queue_accept(uv_loop_t* loop, uv_pipe_t* handle, - uv_pipe_accept_t* req, BOOL firstInstance) { - assert(handle->flags & UV_HANDLE_LISTENING); - - if (!firstInstance) { - assert(req->pipeHandle == INVALID_HANDLE_VALUE); - - req->pipeHandle = CreateNamedPipeW(handle->name, - PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, - PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, - PIPE_UNLIMITED_INSTANCES, 65536, 65536, 0, NULL); - - if (req->pipeHandle == INVALID_HANDLE_VALUE) { - SET_REQ_ERROR(req, GetLastError()); - uv_insert_pending_req(loop, (uv_req_t*) req); - handle->reqs_pending++; - return; - } - - if (uv_set_pipe_handle(loop, handle, req->pipeHandle, -1, 0)) { - CloseHandle(req->pipeHandle); - req->pipeHandle = INVALID_HANDLE_VALUE; - SET_REQ_ERROR(req, GetLastError()); - uv_insert_pending_req(loop, (uv_req_t*) req); - handle->reqs_pending++; - return; - } - } - - assert(req->pipeHandle != INVALID_HANDLE_VALUE); - - /* Prepare the overlapped structure. */ - memset(&(req->u.io.overlapped), 0, sizeof(req->u.io.overlapped)); - - if (!ConnectNamedPipe(req->pipeHandle, &req->u.io.overlapped) && - GetLastError() != ERROR_IO_PENDING) { - if (GetLastError() == ERROR_PIPE_CONNECTED) { - SET_REQ_SUCCESS(req); - } else { - CloseHandle(req->pipeHandle); - req->pipeHandle = INVALID_HANDLE_VALUE; - /* Make this req pending reporting an error. */ - SET_REQ_ERROR(req, GetLastError()); - } - uv_insert_pending_req(loop, (uv_req_t*) req); - handle->reqs_pending++; - return; - } - - handle->reqs_pending++; -} - - -int uv_pipe_accept(uv_pipe_t* server, uv_stream_t* client) { - uv_loop_t* loop = server->loop; - uv_pipe_t* pipe_client; - uv_pipe_accept_t* req; - QUEUE* q; - uv__ipc_queue_item_t* item; - int err; - - if (server->ipc) { - if (QUEUE_EMPTY(&server->pipe.conn.pending_ipc_info.queue)) { - /* No valid pending sockets. */ - return WSAEWOULDBLOCK; - } - - q = QUEUE_HEAD(&server->pipe.conn.pending_ipc_info.queue); - QUEUE_REMOVE(q); - server->pipe.conn.pending_ipc_info.queue_len--; - item = QUEUE_DATA(q, uv__ipc_queue_item_t, member); - - err = uv_tcp_import((uv_tcp_t*)client, - &item->socket_info_ex, - item->tcp_connection); - if (err != 0) - return err; - - uv__free(item); - - } else { - pipe_client = (uv_pipe_t*)client; - - /* Find a connection instance that has been connected, but not yet */ - /* accepted. */ - req = server->pipe.serv.pending_accepts; - - if (!req) { - /* No valid connections found, so we error out. */ - return WSAEWOULDBLOCK; - } - - /* Initialize the client handle and copy the pipeHandle to the client */ - uv_pipe_connection_init(pipe_client); - pipe_client->handle = req->pipeHandle; - pipe_client->flags |= UV_HANDLE_READABLE | UV_HANDLE_WRITABLE; - - /* Prepare the req to pick up a new connection */ - server->pipe.serv.pending_accepts = req->next_pending; - req->next_pending = NULL; - req->pipeHandle = INVALID_HANDLE_VALUE; - - if (!(server->flags & UV__HANDLE_CLOSING)) { - uv_pipe_queue_accept(loop, server, req, FALSE); - } - } - - return 0; -} - - -/* Starts listening for connections for the given pipe. */ -int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) { - uv_loop_t* loop = handle->loop; - int i; - - if (handle->flags & UV_HANDLE_LISTENING) { - handle->stream.serv.connection_cb = cb; - } - - if (!(handle->flags & UV_HANDLE_BOUND)) { - return WSAEINVAL; - } - - if (handle->flags & UV_HANDLE_READING) { - return WSAEISCONN; - } - - if (!(handle->flags & UV_HANDLE_PIPESERVER)) { - return ERROR_NOT_SUPPORTED; - } - - handle->flags |= UV_HANDLE_LISTENING; - INCREASE_ACTIVE_COUNT(loop, handle); - handle->stream.serv.connection_cb = cb; - - /* First pipe handle should have already been created in uv_pipe_bind */ - assert(handle->pipe.serv.accept_reqs[0].pipeHandle != INVALID_HANDLE_VALUE); - - for (i = 0; i < handle->pipe.serv.pending_instances; i++) { - uv_pipe_queue_accept(loop, handle, &handle->pipe.serv.accept_reqs[i], i == 0); - } - - return 0; -} - - -static DWORD WINAPI uv_pipe_zero_readfile_thread_proc(void* parameter) { - int result; - DWORD bytes; - uv_read_t* req = (uv_read_t*) parameter; - uv_pipe_t* handle = (uv_pipe_t*) req->data; - uv_loop_t* loop = handle->loop; - HANDLE hThread = NULL; - DWORD err; - uv_mutex_t *m = &handle->pipe.conn.readfile_mutex; - - assert(req != NULL); - assert(req->type == UV_READ); - assert(handle->type == UV_NAMED_PIPE); - - if (handle->flags & UV_HANDLE_PIPE_READ_CANCELABLE) { - uv_mutex_lock(m); /* mutex controls *setting* of readfile_thread */ - if (DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), - GetCurrentProcess(), &hThread, - 0, TRUE, DUPLICATE_SAME_ACCESS)) { - handle->pipe.conn.readfile_thread = hThread; - } else { - hThread = NULL; - } - uv_mutex_unlock(m); - } -restart_readfile: - result = ReadFile(handle->handle, - &uv_zero_, - 0, - &bytes, - NULL); - if (!result) { - err = GetLastError(); - if (err == ERROR_OPERATION_ABORTED && - handle->flags & UV_HANDLE_PIPE_READ_CANCELABLE) { - if (handle->flags & UV_HANDLE_READING) { - /* just a brief break to do something else */ - handle->pipe.conn.readfile_thread = NULL; - /* resume after it is finished */ - uv_mutex_lock(m); - handle->pipe.conn.readfile_thread = hThread; - uv_mutex_unlock(m); - goto restart_readfile; - } else { - result = 1; /* successfully stopped reading */ - } - } - } - if (hThread) { - assert(hThread == handle->pipe.conn.readfile_thread); - /* mutex does not control clearing readfile_thread */ - handle->pipe.conn.readfile_thread = NULL; - uv_mutex_lock(m); - /* only when we hold the mutex lock is it safe to - open or close the handle */ - CloseHandle(hThread); - uv_mutex_unlock(m); - } - - if (!result) { - SET_REQ_ERROR(req, err); - } - - POST_COMPLETION_FOR_REQ(loop, req); - return 0; -} - - -static DWORD WINAPI uv_pipe_writefile_thread_proc(void* parameter) { - int result; - DWORD bytes; - uv_write_t* req = (uv_write_t*) parameter; - uv_pipe_t* handle = (uv_pipe_t*) req->handle; - uv_loop_t* loop = handle->loop; - - assert(req != NULL); - assert(req->type == UV_WRITE); - assert(handle->type == UV_NAMED_PIPE); - assert(req->write_buffer.base); - - result = WriteFile(handle->handle, - req->write_buffer.base, - req->write_buffer.len, - &bytes, - NULL); - - if (!result) { - SET_REQ_ERROR(req, GetLastError()); - } - - POST_COMPLETION_FOR_REQ(loop, req); - return 0; -} - - -static void CALLBACK post_completion_read_wait(void* context, BOOLEAN timed_out) { - uv_read_t* req; - uv_tcp_t* handle; - - req = (uv_read_t*) context; - assert(req != NULL); - handle = (uv_tcp_t*)req->data; - assert(handle != NULL); - assert(!timed_out); - - if (!PostQueuedCompletionStatus(handle->loop->iocp, - req->u.io.overlapped.InternalHigh, - 0, - &req->u.io.overlapped)) { - uv_fatal_error(GetLastError(), "PostQueuedCompletionStatus"); - } -} - - -static void CALLBACK post_completion_write_wait(void* context, BOOLEAN timed_out) { - uv_write_t* req; - uv_tcp_t* handle; - - req = (uv_write_t*) context; - assert(req != NULL); - handle = (uv_tcp_t*)req->handle; - assert(handle != NULL); - assert(!timed_out); - - if (!PostQueuedCompletionStatus(handle->loop->iocp, - req->u.io.overlapped.InternalHigh, - 0, - &req->u.io.overlapped)) { - uv_fatal_error(GetLastError(), "PostQueuedCompletionStatus"); - } -} - - -static void uv_pipe_queue_read(uv_loop_t* loop, uv_pipe_t* handle) { - uv_read_t* req; - int result; - - assert(handle->flags & UV_HANDLE_READING); - assert(!(handle->flags & UV_HANDLE_READ_PENDING)); - - assert(handle->handle != INVALID_HANDLE_VALUE); - - req = &handle->read_req; - - if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) { - if (!QueueUserWorkItem(&uv_pipe_zero_readfile_thread_proc, - req, - WT_EXECUTELONGFUNCTION)) { - /* Make this req pending reporting an error. */ - SET_REQ_ERROR(req, GetLastError()); - goto error; - } - } else { - memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped)); - if (handle->flags & UV_HANDLE_EMULATE_IOCP) { - req->u.io.overlapped.hEvent = (HANDLE) ((uintptr_t) req->event_handle | 1); - } - - /* Do 0-read */ - result = ReadFile(handle->handle, - &uv_zero_, - 0, - NULL, - &req->u.io.overlapped); - - if (!result && GetLastError() != ERROR_IO_PENDING) { - /* Make this req pending reporting an error. */ - SET_REQ_ERROR(req, GetLastError()); - goto error; - } - - if (handle->flags & UV_HANDLE_EMULATE_IOCP) { - if (!req->event_handle) { - req->event_handle = CreateEvent(NULL, 0, 0, NULL); - if (!req->event_handle) { - uv_fatal_error(GetLastError(), "CreateEvent"); - } - } - if (req->wait_handle == INVALID_HANDLE_VALUE) { - if (!RegisterWaitForSingleObject(&req->wait_handle, - req->u.io.overlapped.hEvent, post_completion_read_wait, (void*) req, - INFINITE, WT_EXECUTEINWAITTHREAD)) { - SET_REQ_ERROR(req, GetLastError()); - goto error; - } - } - } - } - - /* Start the eof timer if there is one */ - eof_timer_start(handle); - handle->flags |= UV_HANDLE_READ_PENDING; - handle->reqs_pending++; - return; - -error: - uv_insert_pending_req(loop, (uv_req_t*)req); - handle->flags |= UV_HANDLE_READ_PENDING; - handle->reqs_pending++; -} - - -int uv_pipe_read_start(uv_pipe_t* handle, - uv_alloc_cb alloc_cb, - uv_read_cb read_cb) { - uv_loop_t* loop = handle->loop; - - handle->flags |= UV_HANDLE_READING; - INCREASE_ACTIVE_COUNT(loop, handle); - handle->read_cb = read_cb; - handle->alloc_cb = alloc_cb; - - /* If reading was stopped and then started again, there could still be a */ - /* read request pending. */ - if (!(handle->flags & UV_HANDLE_READ_PENDING)) - uv_pipe_queue_read(loop, handle); - - return 0; -} - - -static void uv_insert_non_overlapped_write_req(uv_pipe_t* handle, - uv_write_t* req) { - req->next_req = NULL; - if (handle->pipe.conn.non_overlapped_writes_tail) { - req->next_req = - handle->pipe.conn.non_overlapped_writes_tail->next_req; - handle->pipe.conn.non_overlapped_writes_tail->next_req = (uv_req_t*)req; - handle->pipe.conn.non_overlapped_writes_tail = req; - } else { - req->next_req = (uv_req_t*)req; - handle->pipe.conn.non_overlapped_writes_tail = req; - } -} - - -static uv_write_t* uv_remove_non_overlapped_write_req(uv_pipe_t* handle) { - uv_write_t* req; - - if (handle->pipe.conn.non_overlapped_writes_tail) { - req = (uv_write_t*)handle->pipe.conn.non_overlapped_writes_tail->next_req; - - if (req == handle->pipe.conn.non_overlapped_writes_tail) { - handle->pipe.conn.non_overlapped_writes_tail = NULL; - } else { - handle->pipe.conn.non_overlapped_writes_tail->next_req = - req->next_req; - } - - return req; - } else { - /* queue empty */ - return NULL; - } -} - - -static void uv_queue_non_overlapped_write(uv_pipe_t* handle) { - uv_write_t* req = uv_remove_non_overlapped_write_req(handle); - if (req) { - if (!QueueUserWorkItem(&uv_pipe_writefile_thread_proc, - req, - WT_EXECUTELONGFUNCTION)) { - uv_fatal_error(GetLastError(), "QueueUserWorkItem"); - } - } -} - - -static int uv_pipe_write_impl(uv_loop_t* loop, - uv_write_t* req, - uv_pipe_t* handle, - const uv_buf_t bufs[], - unsigned int nbufs, - uv_stream_t* send_handle, - uv_write_cb cb) { - int err; - int result; - uv_tcp_t* tcp_send_handle; - uv_write_t* ipc_header_req = NULL; - uv_ipc_frame_uv_stream ipc_frame; - - if (nbufs != 1 && (nbufs != 0 || !send_handle)) { - return ERROR_NOT_SUPPORTED; - } - - /* Only TCP handles are supported for sharing. */ - if (send_handle && ((send_handle->type != UV_TCP) || - (!(send_handle->flags & UV_HANDLE_BOUND) && - !(send_handle->flags & UV_HANDLE_CONNECTION)))) { - return ERROR_NOT_SUPPORTED; - } - - assert(handle->handle != INVALID_HANDLE_VALUE); - - uv_req_init(loop, (uv_req_t*) req); - req->type = UV_WRITE; - req->handle = (uv_stream_t*) handle; - req->cb = cb; - req->ipc_header = 0; - req->event_handle = NULL; - req->wait_handle = INVALID_HANDLE_VALUE; - memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped)); - - if (handle->ipc) { - assert(!(handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE)); - ipc_frame.header.flags = 0; - - /* Use the IPC framing protocol. */ - if (send_handle) { - tcp_send_handle = (uv_tcp_t*)send_handle; - - if (handle->pipe.conn.ipc_pid == 0) { - handle->pipe.conn.ipc_pid = uv_current_pid(); - } - - err = uv_tcp_duplicate_socket(tcp_send_handle, handle->pipe.conn.ipc_pid, - &ipc_frame.socket_info_ex.socket_info); - if (err) { - return err; - } - - ipc_frame.socket_info_ex.delayed_error = tcp_send_handle->delayed_error; - - ipc_frame.header.flags |= UV_IPC_TCP_SERVER; - - if (tcp_send_handle->flags & UV_HANDLE_CONNECTION) { - ipc_frame.header.flags |= UV_IPC_TCP_CONNECTION; - } - } - - if (nbufs == 1) { - ipc_frame.header.flags |= UV_IPC_RAW_DATA; - ipc_frame.header.raw_data_length = bufs[0].len; - } - - /* - * Use the provided req if we're only doing a single write. - * If we're doing multiple writes, use ipc_header_write_req to do - * the first write, and then use the provided req for the second write. - */ - if (!(ipc_frame.header.flags & UV_IPC_RAW_DATA)) { - ipc_header_req = req; - } else { - /* - * Try to use the preallocated write req if it's available. - * Otherwise allocate a new one. - */ - if (handle->pipe.conn.ipc_header_write_req.type != UV_WRITE) { - ipc_header_req = (uv_write_t*)&handle->pipe.conn.ipc_header_write_req; - } else { - ipc_header_req = (uv_write_t*)uv__malloc(sizeof(uv_write_t)); - if (!ipc_header_req) { - uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc"); - } - } - - uv_req_init(loop, (uv_req_t*) ipc_header_req); - ipc_header_req->type = UV_WRITE; - ipc_header_req->handle = (uv_stream_t*) handle; - ipc_header_req->cb = NULL; - ipc_header_req->ipc_header = 1; - } - - /* Write the header or the whole frame. */ - memset(&ipc_header_req->u.io.overlapped, 0, - sizeof(ipc_header_req->u.io.overlapped)); - - /* Using overlapped IO, but wait for completion before returning. - This write is blocking because ipc_frame is on stack. */ - ipc_header_req->u.io.overlapped.hEvent = CreateEvent(NULL, 1, 0, NULL); - if (!ipc_header_req->u.io.overlapped.hEvent) { - uv_fatal_error(GetLastError(), "CreateEvent"); - } - - result = WriteFile(handle->handle, - &ipc_frame, - ipc_frame.header.flags & UV_IPC_TCP_SERVER ? - sizeof(ipc_frame) : sizeof(ipc_frame.header), - NULL, - &ipc_header_req->u.io.overlapped); - if (!result && GetLastError() != ERROR_IO_PENDING) { - err = GetLastError(); - CloseHandle(ipc_header_req->u.io.overlapped.hEvent); - return err; - } - - if (!result) { - /* Request not completed immediately. Wait for it.*/ - if (WaitForSingleObject(ipc_header_req->u.io.overlapped.hEvent, INFINITE) != - WAIT_OBJECT_0) { - err = GetLastError(); - CloseHandle(ipc_header_req->u.io.overlapped.hEvent); - return err; - } - } - ipc_header_req->u.io.queued_bytes = 0; - CloseHandle(ipc_header_req->u.io.overlapped.hEvent); - ipc_header_req->u.io.overlapped.hEvent = NULL; - - REGISTER_HANDLE_REQ(loop, handle, ipc_header_req); - handle->reqs_pending++; - handle->stream.conn.write_reqs_pending++; - - /* If we don't have any raw data to write - we're done. */ - if (!(ipc_frame.header.flags & UV_IPC_RAW_DATA)) { - return 0; - } - } - - if ((handle->flags & - (UV_HANDLE_BLOCKING_WRITES | UV_HANDLE_NON_OVERLAPPED_PIPE)) == - (UV_HANDLE_BLOCKING_WRITES | UV_HANDLE_NON_OVERLAPPED_PIPE)) { - DWORD bytes; - result = WriteFile(handle->handle, - bufs[0].base, - bufs[0].len, - &bytes, - NULL); - - if (!result) { - err = GetLastError(); - return err; - } else { - /* Request completed immediately. */ - req->u.io.queued_bytes = 0; - } - - REGISTER_HANDLE_REQ(loop, handle, req); - handle->reqs_pending++; - handle->stream.conn.write_reqs_pending++; - POST_COMPLETION_FOR_REQ(loop, req); - return 0; - } else if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) { - req->write_buffer = bufs[0]; - uv_insert_non_overlapped_write_req(handle, req); - if (handle->stream.conn.write_reqs_pending == 0) { - uv_queue_non_overlapped_write(handle); - } - - /* Request queued by the kernel. */ - req->u.io.queued_bytes = bufs[0].len; - handle->write_queue_size += req->u.io.queued_bytes; - } else if (handle->flags & UV_HANDLE_BLOCKING_WRITES) { - /* Using overlapped IO, but wait for completion before returning */ - req->u.io.overlapped.hEvent = CreateEvent(NULL, 1, 0, NULL); - if (!req->u.io.overlapped.hEvent) { - uv_fatal_error(GetLastError(), "CreateEvent"); - } - - result = WriteFile(handle->handle, - bufs[0].base, - bufs[0].len, - NULL, - &req->u.io.overlapped); - - if (!result && GetLastError() != ERROR_IO_PENDING) { - err = GetLastError(); - CloseHandle(req->u.io.overlapped.hEvent); - return err; - } - - if (result) { - /* Request completed immediately. */ - req->u.io.queued_bytes = 0; - } else { - /* Request queued by the kernel. */ - req->u.io.queued_bytes = bufs[0].len; - handle->write_queue_size += req->u.io.queued_bytes; - if (WaitForSingleObject(req->u.io.overlapped.hEvent, INFINITE) != - WAIT_OBJECT_0) { - err = GetLastError(); - CloseHandle(req->u.io.overlapped.hEvent); - return uv_translate_sys_error(err); - } - } - CloseHandle(req->u.io.overlapped.hEvent); - - REGISTER_HANDLE_REQ(loop, handle, req); - handle->reqs_pending++; - handle->stream.conn.write_reqs_pending++; - return 0; - } else { - result = WriteFile(handle->handle, - bufs[0].base, - bufs[0].len, - NULL, - &req->u.io.overlapped); - - if (!result && GetLastError() != ERROR_IO_PENDING) { - return GetLastError(); - } - - if (result) { - /* Request completed immediately. */ - req->u.io.queued_bytes = 0; - } else { - /* Request queued by the kernel. */ - req->u.io.queued_bytes = bufs[0].len; - handle->write_queue_size += req->u.io.queued_bytes; - } - - if (handle->flags & UV_HANDLE_EMULATE_IOCP) { - req->event_handle = CreateEvent(NULL, 0, 0, NULL); - if (!req->event_handle) { - uv_fatal_error(GetLastError(), "CreateEvent"); - } - if (!RegisterWaitForSingleObject(&req->wait_handle, - req->u.io.overlapped.hEvent, post_completion_write_wait, (void*) req, - INFINITE, WT_EXECUTEINWAITTHREAD)) { - return GetLastError(); - } - } - } - - REGISTER_HANDLE_REQ(loop, handle, req); - handle->reqs_pending++; - handle->stream.conn.write_reqs_pending++; - - return 0; -} - - -int uv_pipe_write(uv_loop_t* loop, - uv_write_t* req, - uv_pipe_t* handle, - const uv_buf_t bufs[], - unsigned int nbufs, - uv_write_cb cb) { - return uv_pipe_write_impl(loop, req, handle, bufs, nbufs, NULL, cb); -} - - -int uv_pipe_write2(uv_loop_t* loop, - uv_write_t* req, - uv_pipe_t* handle, - const uv_buf_t bufs[], - unsigned int nbufs, - uv_stream_t* send_handle, - uv_write_cb cb) { - if (!handle->ipc) { - return WSAEINVAL; - } - - return uv_pipe_write_impl(loop, req, handle, bufs, nbufs, send_handle, cb); -} - - -static void uv_pipe_read_eof(uv_loop_t* loop, uv_pipe_t* handle, - uv_buf_t buf) { - /* If there is an eof timer running, we don't need it any more, */ - /* so discard it. */ - eof_timer_destroy(handle); - - handle->flags &= ~UV_HANDLE_READABLE; - uv_read_stop((uv_stream_t*) handle); - - handle->read_cb((uv_stream_t*) handle, UV_EOF, &buf); -} - - -static void uv_pipe_read_error(uv_loop_t* loop, uv_pipe_t* handle, int error, - uv_buf_t buf) { - /* If there is an eof timer running, we don't need it any more, */ - /* so discard it. */ - eof_timer_destroy(handle); - - uv_read_stop((uv_stream_t*) handle); - - handle->read_cb((uv_stream_t*)handle, uv_translate_sys_error(error), &buf); -} - - -static void uv_pipe_read_error_or_eof(uv_loop_t* loop, uv_pipe_t* handle, - int error, uv_buf_t buf) { - if (error == ERROR_BROKEN_PIPE) { - uv_pipe_read_eof(loop, handle, buf); - } else { - uv_pipe_read_error(loop, handle, error, buf); - } -} - - -void uv__pipe_insert_pending_socket(uv_pipe_t* handle, - uv__ipc_socket_info_ex* info, - int tcp_connection) { - uv__ipc_queue_item_t* item; - - item = (uv__ipc_queue_item_t*) uv__malloc(sizeof(*item)); - if (item == NULL) - uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc"); - - memcpy(&item->socket_info_ex, info, sizeof(item->socket_info_ex)); - item->tcp_connection = tcp_connection; - QUEUE_INSERT_TAIL(&handle->pipe.conn.pending_ipc_info.queue, &item->member); - handle->pipe.conn.pending_ipc_info.queue_len++; -} - - -void uv_process_pipe_read_req(uv_loop_t* loop, uv_pipe_t* handle, - uv_req_t* req) { - DWORD bytes, avail; - uv_buf_t buf; - uv_ipc_frame_uv_stream ipc_frame; - - assert(handle->type == UV_NAMED_PIPE); - - handle->flags &= ~UV_HANDLE_READ_PENDING; - eof_timer_stop(handle); - - if (!REQ_SUCCESS(req)) { - /* An error occurred doing the 0-read. */ - if (handle->flags & UV_HANDLE_READING) { - uv_pipe_read_error_or_eof(loop, - handle, - GET_REQ_ERROR(req), - uv_null_buf_); - } - } else { - /* Do non-blocking reads until the buffer is empty */ - while (handle->flags & UV_HANDLE_READING) { - if (!PeekNamedPipe(handle->handle, - NULL, - 0, - NULL, - &avail, - NULL)) { - uv_pipe_read_error_or_eof(loop, handle, GetLastError(), uv_null_buf_); - break; - } - - if (avail == 0) { - /* There is nothing to read after all. */ - break; - } - - if (handle->ipc) { - /* Use the IPC framing protocol to read the incoming data. */ - if (handle->pipe.conn.remaining_ipc_rawdata_bytes == 0) { - /* We're reading a new frame. First, read the header. */ - assert(avail >= sizeof(ipc_frame.header)); - - if (!ReadFile(handle->handle, - &ipc_frame.header, - sizeof(ipc_frame.header), - &bytes, - NULL)) { - uv_pipe_read_error_or_eof(loop, handle, GetLastError(), - uv_null_buf_); - break; - } - - assert(bytes == sizeof(ipc_frame.header)); - assert(ipc_frame.header.flags <= (UV_IPC_TCP_SERVER | UV_IPC_RAW_DATA | - UV_IPC_TCP_CONNECTION)); - - if (ipc_frame.header.flags & UV_IPC_TCP_SERVER) { - assert(avail - sizeof(ipc_frame.header) >= - sizeof(ipc_frame.socket_info_ex)); - - /* Read the TCP socket info. */ - if (!ReadFile(handle->handle, - &ipc_frame.socket_info_ex, - sizeof(ipc_frame) - sizeof(ipc_frame.header), - &bytes, - NULL)) { - uv_pipe_read_error_or_eof(loop, handle, GetLastError(), - uv_null_buf_); - break; - } - - assert(bytes == sizeof(ipc_frame) - sizeof(ipc_frame.header)); - - /* Store the pending socket info. */ - uv__pipe_insert_pending_socket( - handle, - &ipc_frame.socket_info_ex, - ipc_frame.header.flags & UV_IPC_TCP_CONNECTION); - } - - if (ipc_frame.header.flags & UV_IPC_RAW_DATA) { - handle->pipe.conn.remaining_ipc_rawdata_bytes = - ipc_frame.header.raw_data_length; - continue; - } - } else { - avail = min(avail, (DWORD)handle->pipe.conn.remaining_ipc_rawdata_bytes); - } - } - - buf = uv_buf_init(NULL, 0); - handle->alloc_cb((uv_handle_t*) handle, avail, &buf); - if (buf.base == NULL || buf.len == 0) { - handle->read_cb((uv_stream_t*) handle, UV_ENOBUFS, &buf); - break; - } - assert(buf.base != NULL); - - if (ReadFile(handle->handle, - buf.base, - min(buf.len, avail), - &bytes, - NULL)) { - /* Successful read */ - if (handle->ipc) { - assert(handle->pipe.conn.remaining_ipc_rawdata_bytes >= bytes); - handle->pipe.conn.remaining_ipc_rawdata_bytes = - handle->pipe.conn.remaining_ipc_rawdata_bytes - bytes; - } - handle->read_cb((uv_stream_t*)handle, bytes, &buf); - - /* Read again only if bytes == buf.len */ - if (bytes <= buf.len) { - break; - } - } else { - uv_pipe_read_error_or_eof(loop, handle, GetLastError(), buf); - break; - } - } - - /* Post another 0-read if still reading and not closing. */ - if ((handle->flags & UV_HANDLE_READING) && - !(handle->flags & UV_HANDLE_READ_PENDING)) { - uv_pipe_queue_read(loop, handle); - } - } - - DECREASE_PENDING_REQ_COUNT(handle); -} - - -void uv_process_pipe_write_req(uv_loop_t* loop, uv_pipe_t* handle, - uv_write_t* req) { - int err; - - assert(handle->type == UV_NAMED_PIPE); - - assert(handle->write_queue_size >= req->u.io.queued_bytes); - handle->write_queue_size -= req->u.io.queued_bytes; - - UNREGISTER_HANDLE_REQ(loop, handle, req); - - if (handle->flags & UV_HANDLE_EMULATE_IOCP) { - if (req->wait_handle != INVALID_HANDLE_VALUE) { - UnregisterWait(req->wait_handle); - req->wait_handle = INVALID_HANDLE_VALUE; - } - if (req->event_handle) { - CloseHandle(req->event_handle); - req->event_handle = NULL; - } - } - - if (req->ipc_header) { - if (req == &handle->pipe.conn.ipc_header_write_req) { - req->type = UV_UNKNOWN_REQ; - } else { - uv__free(req); - } - } else { - if (req->cb) { - err = GET_REQ_ERROR(req); - req->cb(req, uv_translate_sys_error(err)); - } - } - - handle->stream.conn.write_reqs_pending--; - - if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE && - handle->pipe.conn.non_overlapped_writes_tail) { - assert(handle->stream.conn.write_reqs_pending > 0); - uv_queue_non_overlapped_write(handle); - } - - if (handle->stream.conn.shutdown_req != NULL && - handle->stream.conn.write_reqs_pending == 0) { - uv_want_endgame(loop, (uv_handle_t*)handle); - } - - DECREASE_PENDING_REQ_COUNT(handle); -} - - -void uv_process_pipe_accept_req(uv_loop_t* loop, uv_pipe_t* handle, - uv_req_t* raw_req) { - uv_pipe_accept_t* req = (uv_pipe_accept_t*) raw_req; - - assert(handle->type == UV_NAMED_PIPE); - - if (handle->flags & UV__HANDLE_CLOSING) { - /* The req->pipeHandle should be freed already in uv_pipe_cleanup(). */ - assert(req->pipeHandle == INVALID_HANDLE_VALUE); - DECREASE_PENDING_REQ_COUNT(handle); - return; - } - - if (REQ_SUCCESS(req)) { - assert(req->pipeHandle != INVALID_HANDLE_VALUE); - req->next_pending = handle->pipe.serv.pending_accepts; - handle->pipe.serv.pending_accepts = req; - - if (handle->stream.serv.connection_cb) { - handle->stream.serv.connection_cb((uv_stream_t*)handle, 0); - } - } else { - if (req->pipeHandle != INVALID_HANDLE_VALUE) { - CloseHandle(req->pipeHandle); - req->pipeHandle = INVALID_HANDLE_VALUE; - } - if (!(handle->flags & UV__HANDLE_CLOSING)) { - uv_pipe_queue_accept(loop, handle, req, FALSE); - } - } - - DECREASE_PENDING_REQ_COUNT(handle); -} - - -void uv_process_pipe_connect_req(uv_loop_t* loop, uv_pipe_t* handle, - uv_connect_t* req) { - int err; - - assert(handle->type == UV_NAMED_PIPE); - - UNREGISTER_HANDLE_REQ(loop, handle, req); - - if (req->cb) { - err = 0; - if (REQ_SUCCESS(req)) { - uv_pipe_connection_init(handle); - } else { - err = GET_REQ_ERROR(req); - } - req->cb(req, uv_translate_sys_error(err)); - } - - DECREASE_PENDING_REQ_COUNT(handle); -} - - -void uv_process_pipe_shutdown_req(uv_loop_t* loop, uv_pipe_t* handle, - uv_shutdown_t* req) { - assert(handle->type == UV_NAMED_PIPE); - - UNREGISTER_HANDLE_REQ(loop, handle, req); - - if (handle->flags & UV_HANDLE_READABLE) { - /* Initialize and optionally start the eof timer. Only do this if the */ - /* pipe is readable and we haven't seen EOF come in ourselves. */ - eof_timer_init(handle); - - /* If reading start the timer right now. */ - /* Otherwise uv_pipe_queue_read will start it. */ - if (handle->flags & UV_HANDLE_READ_PENDING) { - eof_timer_start(handle); - } - - } else { - /* This pipe is not readable. We can just close it to let the other end */ - /* know that we're done writing. */ - close_pipe(handle); - } - - if (req->cb) { - req->cb(req, 0); - } - - DECREASE_PENDING_REQ_COUNT(handle); -} - - -static void eof_timer_init(uv_pipe_t* pipe) { - int r; - - assert(pipe->pipe.conn.eof_timer == NULL); - assert(pipe->flags & UV_HANDLE_CONNECTION); - - pipe->pipe.conn.eof_timer = (uv_timer_t*) uv__malloc(sizeof *pipe->pipe.conn.eof_timer); - - r = uv_timer_init(pipe->loop, pipe->pipe.conn.eof_timer); - assert(r == 0); /* timers can't fail */ - pipe->pipe.conn.eof_timer->data = pipe; - uv_unref((uv_handle_t*) pipe->pipe.conn.eof_timer); -} - - -static void eof_timer_start(uv_pipe_t* pipe) { - assert(pipe->flags & UV_HANDLE_CONNECTION); - - if (pipe->pipe.conn.eof_timer != NULL) { - uv_timer_start(pipe->pipe.conn.eof_timer, eof_timer_cb, eof_timeout, 0); - } -} - - -static void eof_timer_stop(uv_pipe_t* pipe) { - assert(pipe->flags & UV_HANDLE_CONNECTION); - - if (pipe->pipe.conn.eof_timer != NULL) { - uv_timer_stop(pipe->pipe.conn.eof_timer); - } -} - - -static void eof_timer_cb(uv_timer_t* timer) { - uv_pipe_t* pipe = (uv_pipe_t*) timer->data; - uv_loop_t* loop = timer->loop; - - assert(pipe->type == UV_NAMED_PIPE); - - /* This should always be true, since we start the timer only */ - /* in uv_pipe_queue_read after successfully calling ReadFile, */ - /* or in uv_process_pipe_shutdown_req if a read is pending, */ - /* and we always immediately stop the timer in */ - /* uv_process_pipe_read_req. */ - assert(pipe->flags & UV_HANDLE_READ_PENDING); - - /* If there are many packets coming off the iocp then the timer callback */ - /* may be called before the read request is coming off the queue. */ - /* Therefore we check here if the read request has completed but will */ - /* be processed later. */ - if ((pipe->flags & UV_HANDLE_READ_PENDING) && - HasOverlappedIoCompleted(&pipe->read_req.u.io.overlapped)) { - return; - } - - /* Force both ends off the pipe. */ - close_pipe(pipe); - - /* Stop reading, so the pending read that is going to fail will */ - /* not be reported to the user. */ - uv_read_stop((uv_stream_t*) pipe); - - /* Report the eof and update flags. This will get reported even if the */ - /* user stopped reading in the meantime. TODO: is that okay? */ - uv_pipe_read_eof(loop, pipe, uv_null_buf_); -} - - -static void eof_timer_destroy(uv_pipe_t* pipe) { - assert(pipe->flags & UV_HANDLE_CONNECTION); - - if (pipe->pipe.conn.eof_timer) { - uv_close((uv_handle_t*) pipe->pipe.conn.eof_timer, eof_timer_close_cb); - pipe->pipe.conn.eof_timer = NULL; - } -} - - -static void eof_timer_close_cb(uv_handle_t* handle) { - assert(handle->type == UV_TIMER); - uv__free(handle); -} - - -int uv_pipe_open(uv_pipe_t* pipe, uv_file file) { - HANDLE os_handle = uv__get_osfhandle(file); - NTSTATUS nt_status; - IO_STATUS_BLOCK io_status; - FILE_ACCESS_INFORMATION access; - DWORD duplex_flags = 0; - - if (os_handle == INVALID_HANDLE_VALUE) - return UV_EBADF; - - /* In order to avoid closing a stdio file descriptor 0-2, duplicate the - * underlying OS handle and forget about the original fd. - * We could also opt to use the original OS handle and just never close it, - * but then there would be no reliable way to cancel pending read operations - * upon close. - */ - if (file <= 2) { - if (!DuplicateHandle(INVALID_HANDLE_VALUE, - os_handle, - INVALID_HANDLE_VALUE, - &os_handle, - 0, - FALSE, - DUPLICATE_SAME_ACCESS)) - return uv_translate_sys_error(GetLastError()); - file = -1; - } - - /* Determine what kind of permissions we have on this handle. - * Cygwin opens the pipe in message mode, but we can support it, - * just query the access flags and set the stream flags accordingly. - */ - nt_status = pNtQueryInformationFile(os_handle, - &io_status, - &access, - sizeof(access), - FileAccessInformation); - if (nt_status != STATUS_SUCCESS) - return UV_EINVAL; - - if (pipe->ipc) { - if (!(access.AccessFlags & FILE_WRITE_DATA) || - !(access.AccessFlags & FILE_READ_DATA)) { - return UV_EINVAL; - } - } - - if (access.AccessFlags & FILE_WRITE_DATA) - duplex_flags |= UV_HANDLE_WRITABLE; - if (access.AccessFlags & FILE_READ_DATA) - duplex_flags |= UV_HANDLE_READABLE; - - if (os_handle == INVALID_HANDLE_VALUE || - uv_set_pipe_handle(pipe->loop, - pipe, - os_handle, - file, - duplex_flags) == -1) { - return UV_EINVAL; - } - - uv_pipe_connection_init(pipe); - - if (pipe->ipc) { - assert(!(pipe->flags & UV_HANDLE_NON_OVERLAPPED_PIPE)); - pipe->pipe.conn.ipc_pid = uv_parent_pid(); - assert(pipe->pipe.conn.ipc_pid != -1); - } - return 0; -} - - -static int uv__pipe_getname(const uv_pipe_t* handle, char* buffer, size_t* size) { - NTSTATUS nt_status; - IO_STATUS_BLOCK io_status; - FILE_NAME_INFORMATION tmp_name_info; - FILE_NAME_INFORMATION* name_info; - WCHAR* name_buf; - unsigned int addrlen; - unsigned int name_size; - unsigned int name_len; - int err; - - name_info = NULL; - - if (handle->handle == INVALID_HANDLE_VALUE) { - *size = 0; - return UV_EINVAL; - } - - uv__pipe_pause_read((uv_pipe_t*)handle); /* cast away const warning */ - - nt_status = pNtQueryInformationFile(handle->handle, - &io_status, - &tmp_name_info, - sizeof tmp_name_info, - FileNameInformation); - if (nt_status == STATUS_BUFFER_OVERFLOW) { - name_size = sizeof(*name_info) + tmp_name_info.FileNameLength; - name_info = uv__malloc(name_size); - if (!name_info) { - *size = 0; - err = UV_ENOMEM; - goto cleanup; - } - - nt_status = pNtQueryInformationFile(handle->handle, - &io_status, - name_info, - name_size, - FileNameInformation); - } - - if (nt_status != STATUS_SUCCESS) { - *size = 0; - err = uv_translate_sys_error(pRtlNtStatusToDosError(nt_status)); - goto error; - } - - if (!name_info) { - /* the struct on stack was used */ - name_buf = tmp_name_info.FileName; - name_len = tmp_name_info.FileNameLength; - } else { - name_buf = name_info->FileName; - name_len = name_info->FileNameLength; - } - - if (name_len == 0) { - *size = 0; - err = 0; - goto error; - } - - name_len /= sizeof(WCHAR); - - /* check how much space we need */ - addrlen = WideCharToMultiByte(CP_UTF8, - 0, - name_buf, - name_len, - NULL, - 0, - NULL, - NULL); - if (!addrlen) { - *size = 0; - err = uv_translate_sys_error(GetLastError()); - goto error; - } else if (pipe_prefix_len + addrlen >= *size) { - /* "\\\\.\\pipe" + name */ - *size = pipe_prefix_len + addrlen + 1; - err = UV_ENOBUFS; - goto error; - } - - memcpy(buffer, pipe_prefix, pipe_prefix_len); - addrlen = WideCharToMultiByte(CP_UTF8, - 0, - name_buf, - name_len, - buffer+pipe_prefix_len, - *size-pipe_prefix_len, - NULL, - NULL); - if (!addrlen) { - *size = 0; - err = uv_translate_sys_error(GetLastError()); - goto error; - } - - addrlen += pipe_prefix_len; - *size = addrlen; - buffer[addrlen] = '\0'; - - err = 0; - goto cleanup; - -error: - uv__free(name_info); - -cleanup: - uv__pipe_unpause_read((uv_pipe_t*)handle); /* cast away const warning */ - return err; -} - - -int uv_pipe_pending_count(uv_pipe_t* handle) { - if (!handle->ipc) - return 0; - return handle->pipe.conn.pending_ipc_info.queue_len; -} - - -int uv_pipe_getsockname(const uv_pipe_t* handle, char* buffer, size_t* size) { - if (handle->flags & UV_HANDLE_BOUND) - return uv__pipe_getname(handle, buffer, size); - - if (handle->flags & UV_HANDLE_CONNECTION || - handle->handle != INVALID_HANDLE_VALUE) { - *size = 0; - return 0; - } - - return UV_EBADF; -} - - -int uv_pipe_getpeername(const uv_pipe_t* handle, char* buffer, size_t* size) { - /* emulate unix behaviour */ - if (handle->flags & UV_HANDLE_BOUND) - return UV_ENOTCONN; - - if (handle->handle != INVALID_HANDLE_VALUE) - return uv__pipe_getname(handle, buffer, size); - - return UV_EBADF; -} - - -uv_handle_type uv_pipe_pending_type(uv_pipe_t* handle) { - if (!handle->ipc) - return UV_UNKNOWN_HANDLE; - if (handle->pipe.conn.pending_ipc_info.queue_len == 0) - return UV_UNKNOWN_HANDLE; - else - return UV_TCP; -} diff --git a/vendor/libuv/src/win/poll.c b/vendor/libuv/src/win/poll.c deleted file mode 100644 index d479e521e..000000000 --- a/vendor/libuv/src/win/poll.c +++ /dev/null @@ -1,646 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include -#include - -#include "uv.h" -#include "internal.h" -#include "handle-inl.h" -#include "req-inl.h" - - -static const GUID uv_msafd_provider_ids[UV_MSAFD_PROVIDER_COUNT] = { - {0xe70f1aa0, 0xab8b, 0x11cf, - {0x8c, 0xa3, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}}, - {0xf9eab0c0, 0x26d4, 0x11d0, - {0xbb, 0xbf, 0x00, 0xaa, 0x00, 0x6c, 0x34, 0xe4}}, - {0x9fc48064, 0x7298, 0x43e4, - {0xb7, 0xbd, 0x18, 0x1f, 0x20, 0x89, 0x79, 0x2a}} -}; - -typedef struct uv_single_fd_set_s { - unsigned int fd_count; - SOCKET fd_array[1]; -} uv_single_fd_set_t; - - -static OVERLAPPED overlapped_dummy_; -static uv_once_t overlapped_dummy_init_guard_ = UV_ONCE_INIT; - -static AFD_POLL_INFO afd_poll_info_dummy_; - - -static void uv__init_overlapped_dummy(void) { - HANDLE event; - - event = CreateEvent(NULL, TRUE, TRUE, NULL); - if (event == NULL) - uv_fatal_error(GetLastError(), "CreateEvent"); - - memset(&overlapped_dummy_, 0, sizeof overlapped_dummy_); - overlapped_dummy_.hEvent = (HANDLE) ((uintptr_t) event | 1); -} - - -static OVERLAPPED* uv__get_overlapped_dummy() { - uv_once(&overlapped_dummy_init_guard_, uv__init_overlapped_dummy); - return &overlapped_dummy_; -} - - -static AFD_POLL_INFO* uv__get_afd_poll_info_dummy() { - return &afd_poll_info_dummy_; -} - - -static void uv__fast_poll_submit_poll_req(uv_loop_t* loop, uv_poll_t* handle) { - uv_req_t* req; - AFD_POLL_INFO* afd_poll_info; - DWORD result; - - /* Find a yet unsubmitted req to submit. */ - if (handle->submitted_events_1 == 0) { - req = &handle->poll_req_1; - afd_poll_info = &handle->afd_poll_info_1; - handle->submitted_events_1 = handle->events; - handle->mask_events_1 = 0; - handle->mask_events_2 = handle->events; - } else if (handle->submitted_events_2 == 0) { - req = &handle->poll_req_2; - afd_poll_info = &handle->afd_poll_info_2; - handle->submitted_events_2 = handle->events; - handle->mask_events_1 = handle->events; - handle->mask_events_2 = 0; - } else { - /* Just wait until there's an unsubmitted req. */ - /* This will happen almost immediately as one of the 2 outstanding */ - /* requests is about to return. When this happens, */ - /* uv__fast_poll_process_poll_req will be called, and the pending */ - /* events, if needed, will be processed in a subsequent request. */ - return; - } - - /* Setting Exclusive to TRUE makes the other poll request return if there */ - /* is any. */ - afd_poll_info->Exclusive = TRUE; - afd_poll_info->NumberOfHandles = 1; - afd_poll_info->Timeout.QuadPart = INT64_MAX; - afd_poll_info->Handles[0].Handle = (HANDLE) handle->socket; - afd_poll_info->Handles[0].Status = 0; - afd_poll_info->Handles[0].Events = 0; - - if (handle->events & UV_READABLE) { - afd_poll_info->Handles[0].Events |= AFD_POLL_RECEIVE | - AFD_POLL_DISCONNECT | AFD_POLL_ACCEPT | AFD_POLL_ABORT; - } else { - if (handle->events & UV_DISCONNECT) { - afd_poll_info->Handles[0].Events |= AFD_POLL_DISCONNECT; - } - } - if (handle->events & UV_WRITABLE) { - afd_poll_info->Handles[0].Events |= AFD_POLL_SEND | AFD_POLL_CONNECT_FAIL; - } - - memset(&req->u.io.overlapped, 0, sizeof req->u.io.overlapped); - - result = uv_msafd_poll((SOCKET) handle->peer_socket, - afd_poll_info, - afd_poll_info, - &req->u.io.overlapped); - if (result != 0 && WSAGetLastError() != WSA_IO_PENDING) { - /* Queue this req, reporting an error. */ - SET_REQ_ERROR(req, WSAGetLastError()); - uv_insert_pending_req(loop, req); - } -} - - -static int uv__fast_poll_cancel_poll_req(uv_loop_t* loop, uv_poll_t* handle) { - AFD_POLL_INFO afd_poll_info; - DWORD result; - - afd_poll_info.Exclusive = TRUE; - afd_poll_info.NumberOfHandles = 1; - afd_poll_info.Timeout.QuadPart = INT64_MAX; - afd_poll_info.Handles[0].Handle = (HANDLE) handle->socket; - afd_poll_info.Handles[0].Status = 0; - afd_poll_info.Handles[0].Events = AFD_POLL_ALL; - - result = uv_msafd_poll(handle->socket, - &afd_poll_info, - uv__get_afd_poll_info_dummy(), - uv__get_overlapped_dummy()); - - if (result == SOCKET_ERROR) { - DWORD error = WSAGetLastError(); - if (error != WSA_IO_PENDING) - return error; - } - - return 0; -} - - -static void uv__fast_poll_process_poll_req(uv_loop_t* loop, uv_poll_t* handle, - uv_req_t* req) { - unsigned char mask_events; - AFD_POLL_INFO* afd_poll_info; - - if (req == &handle->poll_req_1) { - afd_poll_info = &handle->afd_poll_info_1; - handle->submitted_events_1 = 0; - mask_events = handle->mask_events_1; - } else if (req == &handle->poll_req_2) { - afd_poll_info = &handle->afd_poll_info_2; - handle->submitted_events_2 = 0; - mask_events = handle->mask_events_2; - } else { - assert(0); - return; - } - - /* Report an error unless the select was just interrupted. */ - if (!REQ_SUCCESS(req)) { - DWORD error = GET_REQ_SOCK_ERROR(req); - if (error != WSAEINTR && handle->events != 0) { - handle->events = 0; /* Stop the watcher */ - handle->poll_cb(handle, uv_translate_sys_error(error), 0); - } - - } else if (afd_poll_info->NumberOfHandles >= 1) { - unsigned char events = 0; - - if ((afd_poll_info->Handles[0].Events & (AFD_POLL_RECEIVE | - AFD_POLL_DISCONNECT | AFD_POLL_ACCEPT | AFD_POLL_ABORT)) != 0) { - events |= UV_READABLE; - if ((afd_poll_info->Handles[0].Events & AFD_POLL_DISCONNECT) != 0) { - events |= UV_DISCONNECT; - } - } - if ((afd_poll_info->Handles[0].Events & (AFD_POLL_SEND | - AFD_POLL_CONNECT_FAIL)) != 0) { - events |= UV_WRITABLE; - } - - events &= handle->events & ~mask_events; - - if (afd_poll_info->Handles[0].Events & AFD_POLL_LOCAL_CLOSE) { - /* Stop polling. */ - handle->events = 0; - if (uv__is_active(handle)) - uv__handle_stop(handle); - } - - if (events != 0) { - handle->poll_cb(handle, 0, events); - } - } - - if ((handle->events & ~(handle->submitted_events_1 | - handle->submitted_events_2)) != 0) { - uv__fast_poll_submit_poll_req(loop, handle); - } else if ((handle->flags & UV__HANDLE_CLOSING) && - handle->submitted_events_1 == 0 && - handle->submitted_events_2 == 0) { - uv_want_endgame(loop, (uv_handle_t*) handle); - } -} - - -static int uv__fast_poll_set(uv_loop_t* loop, uv_poll_t* handle, int events) { - assert(handle->type == UV_POLL); - assert(!(handle->flags & UV__HANDLE_CLOSING)); - assert((events & ~(UV_READABLE | UV_WRITABLE | UV_DISCONNECT)) == 0); - - handle->events = events; - - if (handle->events != 0) { - uv__handle_start(handle); - } else { - uv__handle_stop(handle); - } - - if ((handle->events & ~(handle->submitted_events_1 | - handle->submitted_events_2)) != 0) { - uv__fast_poll_submit_poll_req(handle->loop, handle); - } - - return 0; -} - - -static int uv__fast_poll_close(uv_loop_t* loop, uv_poll_t* handle) { - handle->events = 0; - uv__handle_closing(handle); - - if (handle->submitted_events_1 == 0 && - handle->submitted_events_2 == 0) { - uv_want_endgame(loop, (uv_handle_t*) handle); - return 0; - } else { - /* Cancel outstanding poll requests by executing another, unique poll */ - /* request that forces the outstanding ones to return. */ - return uv__fast_poll_cancel_poll_req(loop, handle); - } -} - - -static SOCKET uv__fast_poll_create_peer_socket(HANDLE iocp, - WSAPROTOCOL_INFOW* protocol_info) { - SOCKET sock = 0; - - sock = WSASocketW(protocol_info->iAddressFamily, - protocol_info->iSocketType, - protocol_info->iProtocol, - protocol_info, - 0, - WSA_FLAG_OVERLAPPED); - if (sock == INVALID_SOCKET) { - return INVALID_SOCKET; - } - - if (!SetHandleInformation((HANDLE) sock, HANDLE_FLAG_INHERIT, 0)) { - goto error; - }; - - if (CreateIoCompletionPort((HANDLE) sock, - iocp, - (ULONG_PTR) sock, - 0) == NULL) { - goto error; - } - - return sock; - - error: - closesocket(sock); - return INVALID_SOCKET; -} - - -static SOCKET uv__fast_poll_get_peer_socket(uv_loop_t* loop, - WSAPROTOCOL_INFOW* protocol_info) { - int index, i; - SOCKET peer_socket; - - index = -1; - for (i = 0; (size_t) i < ARRAY_SIZE(uv_msafd_provider_ids); i++) { - if (memcmp((void*) &protocol_info->ProviderId, - (void*) &uv_msafd_provider_ids[i], - sizeof protocol_info->ProviderId) == 0) { - index = i; - } - } - - /* Check if the protocol uses an msafd socket. */ - if (index < 0) { - return INVALID_SOCKET; - } - - /* If we didn't (try) to create a peer socket yet, try to make one. Don't */ - /* try again if the peer socket creation failed earlier for the same */ - /* protocol. */ - peer_socket = loop->poll_peer_sockets[index]; - if (peer_socket == 0) { - peer_socket = uv__fast_poll_create_peer_socket(loop->iocp, protocol_info); - loop->poll_peer_sockets[index] = peer_socket; - } - - return peer_socket; -} - - -static DWORD WINAPI uv__slow_poll_thread_proc(void* arg) { - uv_req_t* req = (uv_req_t*) arg; - uv_poll_t* handle = (uv_poll_t*) req->data; - unsigned char reported_events; - int r; - uv_single_fd_set_t rfds, wfds, efds; - struct timeval timeout; - - assert(handle->type == UV_POLL); - assert(req->type == UV_POLL_REQ); - - if (handle->events & UV_READABLE) { - rfds.fd_count = 1; - rfds.fd_array[0] = handle->socket; - } else { - rfds.fd_count = 0; - } - - if (handle->events & UV_WRITABLE) { - wfds.fd_count = 1; - wfds.fd_array[0] = handle->socket; - efds.fd_count = 1; - efds.fd_array[0] = handle->socket; - } else { - wfds.fd_count = 0; - efds.fd_count = 0; - } - - /* Make the select() time out after 3 minutes. If select() hangs because */ - /* the user closed the socket, we will at least not hang indefinitely. */ - timeout.tv_sec = 3 * 60; - timeout.tv_usec = 0; - - r = select(1, (fd_set*) &rfds, (fd_set*) &wfds, (fd_set*) &efds, &timeout); - if (r == SOCKET_ERROR) { - /* Queue this req, reporting an error. */ - SET_REQ_ERROR(&handle->poll_req_1, WSAGetLastError()); - POST_COMPLETION_FOR_REQ(handle->loop, req); - return 0; - } - - reported_events = 0; - - if (r > 0) { - if (rfds.fd_count > 0) { - assert(rfds.fd_count == 1); - assert(rfds.fd_array[0] == handle->socket); - reported_events |= UV_READABLE; - } - - if (wfds.fd_count > 0) { - assert(wfds.fd_count == 1); - assert(wfds.fd_array[0] == handle->socket); - reported_events |= UV_WRITABLE; - } else if (efds.fd_count > 0) { - assert(efds.fd_count == 1); - assert(efds.fd_array[0] == handle->socket); - reported_events |= UV_WRITABLE; - } - } - - SET_REQ_SUCCESS(req); - req->u.io.overlapped.InternalHigh = (DWORD) reported_events; - POST_COMPLETION_FOR_REQ(handle->loop, req); - - return 0; -} - - -static void uv__slow_poll_submit_poll_req(uv_loop_t* loop, uv_poll_t* handle) { - uv_req_t* req; - - /* Find a yet unsubmitted req to submit. */ - if (handle->submitted_events_1 == 0) { - req = &handle->poll_req_1; - handle->submitted_events_1 = handle->events; - handle->mask_events_1 = 0; - handle->mask_events_2 = handle->events; - } else if (handle->submitted_events_2 == 0) { - req = &handle->poll_req_2; - handle->submitted_events_2 = handle->events; - handle->mask_events_1 = handle->events; - handle->mask_events_2 = 0; - } else { - assert(0); - return; - } - - if (!QueueUserWorkItem(uv__slow_poll_thread_proc, - (void*) req, - WT_EXECUTELONGFUNCTION)) { - /* Make this req pending, reporting an error. */ - SET_REQ_ERROR(req, GetLastError()); - uv_insert_pending_req(loop, req); - } -} - - - -static void uv__slow_poll_process_poll_req(uv_loop_t* loop, uv_poll_t* handle, - uv_req_t* req) { - unsigned char mask_events; - int err; - - if (req == &handle->poll_req_1) { - handle->submitted_events_1 = 0; - mask_events = handle->mask_events_1; - } else if (req == &handle->poll_req_2) { - handle->submitted_events_2 = 0; - mask_events = handle->mask_events_2; - } else { - assert(0); - return; - } - - if (!REQ_SUCCESS(req)) { - /* Error. */ - if (handle->events != 0) { - err = GET_REQ_ERROR(req); - handle->events = 0; /* Stop the watcher */ - handle->poll_cb(handle, uv_translate_sys_error(err), 0); - } - } else { - /* Got some events. */ - int events = req->u.io.overlapped.InternalHigh & handle->events & ~mask_events; - if (events != 0) { - handle->poll_cb(handle, 0, events); - } - } - - if ((handle->events & ~(handle->submitted_events_1 | - handle->submitted_events_2)) != 0) { - uv__slow_poll_submit_poll_req(loop, handle); - } else if ((handle->flags & UV__HANDLE_CLOSING) && - handle->submitted_events_1 == 0 && - handle->submitted_events_2 == 0) { - uv_want_endgame(loop, (uv_handle_t*) handle); - } -} - - -static int uv__slow_poll_set(uv_loop_t* loop, uv_poll_t* handle, int events) { - assert(handle->type == UV_POLL); - assert(!(handle->flags & UV__HANDLE_CLOSING)); - assert((events & ~(UV_READABLE | UV_WRITABLE)) == 0); - - handle->events = events; - - if (handle->events != 0) { - uv__handle_start(handle); - } else { - uv__handle_stop(handle); - } - - if ((handle->events & - ~(handle->submitted_events_1 | handle->submitted_events_2)) != 0) { - uv__slow_poll_submit_poll_req(handle->loop, handle); - } - - return 0; -} - - -static int uv__slow_poll_close(uv_loop_t* loop, uv_poll_t* handle) { - handle->events = 0; - uv__handle_closing(handle); - - if (handle->submitted_events_1 == 0 && - handle->submitted_events_2 == 0) { - uv_want_endgame(loop, (uv_handle_t*) handle); - } - - return 0; -} - - -int uv_poll_init(uv_loop_t* loop, uv_poll_t* handle, int fd) { - return uv_poll_init_socket(loop, handle, (SOCKET) uv__get_osfhandle(fd)); -} - - -int uv_poll_init_socket(uv_loop_t* loop, uv_poll_t* handle, - uv_os_sock_t socket) { - WSAPROTOCOL_INFOW protocol_info; - int len; - SOCKET peer_socket, base_socket; - DWORD bytes; - DWORD yes = 1; - - /* Set the socket to nonblocking mode */ - if (ioctlsocket(socket, FIONBIO, &yes) == SOCKET_ERROR) - return uv_translate_sys_error(WSAGetLastError()); - - /* Try to obtain a base handle for the socket. This increases this chances */ - /* that we find an AFD handle and are able to use the fast poll mechanism. */ - /* This will always fail on windows XP/2k3, since they don't support the */ - /* SIO_BASE_HANDLE ioctl. */ -#ifndef NDEBUG - base_socket = INVALID_SOCKET; -#endif - - if (WSAIoctl(socket, - SIO_BASE_HANDLE, - NULL, - 0, - &base_socket, - sizeof base_socket, - &bytes, - NULL, - NULL) == 0) { - assert(base_socket != 0 && base_socket != INVALID_SOCKET); - socket = base_socket; - } - - uv__handle_init(loop, (uv_handle_t*) handle, UV_POLL); - handle->socket = socket; - handle->events = 0; - - /* Obtain protocol information about the socket. */ - len = sizeof protocol_info; - if (getsockopt(socket, - SOL_SOCKET, - SO_PROTOCOL_INFOW, - (char*) &protocol_info, - &len) != 0) { - return uv_translate_sys_error(WSAGetLastError()); - } - - /* Get the peer socket that is needed to enable fast poll. If the returned */ - /* value is NULL, the protocol is not implemented by MSAFD and we'll have */ - /* to use slow mode. */ - peer_socket = uv__fast_poll_get_peer_socket(loop, &protocol_info); - - if (peer_socket != INVALID_SOCKET) { - /* Initialize fast poll specific fields. */ - handle->peer_socket = peer_socket; - } else { - /* Initialize slow poll specific fields. */ - handle->flags |= UV_HANDLE_POLL_SLOW; - } - - /* Initialize 2 poll reqs. */ - handle->submitted_events_1 = 0; - uv_req_init(loop, (uv_req_t*) &(handle->poll_req_1)); - handle->poll_req_1.type = UV_POLL_REQ; - handle->poll_req_1.data = handle; - - handle->submitted_events_2 = 0; - uv_req_init(loop, (uv_req_t*) &(handle->poll_req_2)); - handle->poll_req_2.type = UV_POLL_REQ; - handle->poll_req_2.data = handle; - - return 0; -} - - -int uv_poll_start(uv_poll_t* handle, int events, uv_poll_cb cb) { - int err; - - if (!(handle->flags & UV_HANDLE_POLL_SLOW)) { - err = uv__fast_poll_set(handle->loop, handle, events); - } else { - err = uv__slow_poll_set(handle->loop, handle, events); - } - - if (err) { - return uv_translate_sys_error(err); - } - - handle->poll_cb = cb; - - return 0; -} - - -int uv_poll_stop(uv_poll_t* handle) { - int err; - - if (!(handle->flags & UV_HANDLE_POLL_SLOW)) { - err = uv__fast_poll_set(handle->loop, handle, 0); - } else { - err = uv__slow_poll_set(handle->loop, handle, 0); - } - - return uv_translate_sys_error(err); -} - - -void uv_process_poll_req(uv_loop_t* loop, uv_poll_t* handle, uv_req_t* req) { - if (!(handle->flags & UV_HANDLE_POLL_SLOW)) { - uv__fast_poll_process_poll_req(loop, handle, req); - } else { - uv__slow_poll_process_poll_req(loop, handle, req); - } -} - - -int uv_poll_close(uv_loop_t* loop, uv_poll_t* handle) { - if (!(handle->flags & UV_HANDLE_POLL_SLOW)) { - return uv__fast_poll_close(loop, handle); - } else { - return uv__slow_poll_close(loop, handle); - } -} - - -void uv_poll_endgame(uv_loop_t* loop, uv_poll_t* handle) { - assert(handle->flags & UV__HANDLE_CLOSING); - assert(!(handle->flags & UV_HANDLE_CLOSED)); - - assert(handle->submitted_events_1 == 0); - assert(handle->submitted_events_2 == 0); - - uv__handle_close(handle); -} diff --git a/vendor/libuv/src/win/process-stdio.c b/vendor/libuv/src/win/process-stdio.c deleted file mode 100644 index 032e30935..000000000 --- a/vendor/libuv/src/win/process-stdio.c +++ /dev/null @@ -1,511 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include -#include -#include -#include - -#include "uv.h" -#include "internal.h" -#include "handle-inl.h" - - -/* - * The `child_stdio_buffer` buffer has the following layout: - * int number_of_fds - * unsigned char crt_flags[number_of_fds] - * HANDLE os_handle[number_of_fds] - */ -#define CHILD_STDIO_SIZE(count) \ - (sizeof(int) + \ - sizeof(unsigned char) * (count) + \ - sizeof(uintptr_t) * (count)) - -#define CHILD_STDIO_COUNT(buffer) \ - *((unsigned int*) (buffer)) - -#define CHILD_STDIO_CRT_FLAGS(buffer, fd) \ - *((unsigned char*) (buffer) + sizeof(int) + fd) - -#define CHILD_STDIO_HANDLE(buffer, fd) \ - *((HANDLE*) ((unsigned char*) (buffer) + \ - sizeof(int) + \ - sizeof(unsigned char) * \ - CHILD_STDIO_COUNT((buffer)) + \ - sizeof(HANDLE) * (fd))) - - -/* CRT file descriptor mode flags */ -#define FOPEN 0x01 -#define FEOFLAG 0x02 -#define FCRLF 0x04 -#define FPIPE 0x08 -#define FNOINHERIT 0x10 -#define FAPPEND 0x20 -#define FDEV 0x40 -#define FTEXT 0x80 - - -/* - * Clear the HANDLE_FLAG_INHERIT flag from all HANDLEs that were inherited - * the parent process. Don't check for errors - the stdio handles may not be - * valid, or may be closed already. There is no guarantee that this function - * does a perfect job. - */ -void uv_disable_stdio_inheritance(void) { - HANDLE handle; - STARTUPINFOW si; - - /* Make the windows stdio handles non-inheritable. */ - handle = GetStdHandle(STD_INPUT_HANDLE); - if (handle != NULL && handle != INVALID_HANDLE_VALUE) - SetHandleInformation(handle, HANDLE_FLAG_INHERIT, 0); - - handle = GetStdHandle(STD_OUTPUT_HANDLE); - if (handle != NULL && handle != INVALID_HANDLE_VALUE) - SetHandleInformation(handle, HANDLE_FLAG_INHERIT, 0); - - handle = GetStdHandle(STD_ERROR_HANDLE); - if (handle != NULL && handle != INVALID_HANDLE_VALUE) - SetHandleInformation(handle, HANDLE_FLAG_INHERIT, 0); - - /* Make inherited CRT FDs non-inheritable. */ - GetStartupInfoW(&si); - if (uv__stdio_verify(si.lpReserved2, si.cbReserved2)) - uv__stdio_noinherit(si.lpReserved2); -} - - -static int uv__create_stdio_pipe_pair(uv_loop_t* loop, - uv_pipe_t* server_pipe, HANDLE* child_pipe_ptr, unsigned int flags) { - char pipe_name[64]; - SECURITY_ATTRIBUTES sa; - DWORD server_access = 0; - DWORD client_access = 0; - HANDLE child_pipe = INVALID_HANDLE_VALUE; - int err; - - if (flags & UV_READABLE_PIPE) { - /* The server needs inbound access too, otherwise CreateNamedPipe() */ - /* won't give us the FILE_READ_ATTRIBUTES permission. We need that to */ - /* probe the state of the write buffer when we're trying to shutdown */ - /* the pipe. */ - server_access |= PIPE_ACCESS_OUTBOUND | PIPE_ACCESS_INBOUND; - client_access |= GENERIC_READ | FILE_WRITE_ATTRIBUTES; - } - if (flags & UV_WRITABLE_PIPE) { - server_access |= PIPE_ACCESS_INBOUND; - client_access |= GENERIC_WRITE | FILE_READ_ATTRIBUTES; - } - - /* Create server pipe handle. */ - err = uv_stdio_pipe_server(loop, - server_pipe, - server_access, - pipe_name, - sizeof(pipe_name)); - if (err) - goto error; - - /* Create child pipe handle. */ - sa.nLength = sizeof sa; - sa.lpSecurityDescriptor = NULL; - sa.bInheritHandle = TRUE; - - child_pipe = CreateFileA(pipe_name, - client_access, - 0, - &sa, - OPEN_EXISTING, - server_pipe->ipc ? FILE_FLAG_OVERLAPPED : 0, - NULL); - if (child_pipe == INVALID_HANDLE_VALUE) { - err = GetLastError(); - goto error; - } - -#ifndef NDEBUG - /* Validate that the pipe was opened in the right mode. */ - { - DWORD mode; - BOOL r = GetNamedPipeHandleState(child_pipe, - &mode, - NULL, - NULL, - NULL, - NULL, - 0); - assert(r == TRUE); - assert(mode == (PIPE_READMODE_BYTE | PIPE_WAIT)); - } -#endif - - /* Do a blocking ConnectNamedPipe. This should not block because we have */ - /* both ends of the pipe created. */ - if (!ConnectNamedPipe(server_pipe->handle, NULL)) { - if (GetLastError() != ERROR_PIPE_CONNECTED) { - err = GetLastError(); - goto error; - } - } - - /* The server end is now readable and/or writable. */ - if (flags & UV_READABLE_PIPE) - server_pipe->flags |= UV_HANDLE_WRITABLE; - if (flags & UV_WRITABLE_PIPE) - server_pipe->flags |= UV_HANDLE_READABLE; - - *child_pipe_ptr = child_pipe; - return 0; - - error: - if (server_pipe->handle != INVALID_HANDLE_VALUE) { - uv_pipe_cleanup(loop, server_pipe); - } - - if (child_pipe != INVALID_HANDLE_VALUE) { - CloseHandle(child_pipe); - } - - return err; -} - - -static int uv__duplicate_handle(uv_loop_t* loop, HANDLE handle, HANDLE* dup) { - HANDLE current_process; - - - /* _get_osfhandle will sometimes return -2 in case of an error. This seems */ - /* to happen when fd <= 2 and the process' corresponding stdio handle is */ - /* set to NULL. Unfortunately DuplicateHandle will happily duplicate */ - /* (HANDLE) -2, so this situation goes unnoticed until someone tries to */ - /* use the duplicate. Therefore we filter out known-invalid handles here. */ - if (handle == INVALID_HANDLE_VALUE || - handle == NULL || - handle == (HANDLE) -2) { - *dup = INVALID_HANDLE_VALUE; - return ERROR_INVALID_HANDLE; - } - - current_process = GetCurrentProcess(); - - if (!DuplicateHandle(current_process, - handle, - current_process, - dup, - 0, - TRUE, - DUPLICATE_SAME_ACCESS)) { - *dup = INVALID_HANDLE_VALUE; - return GetLastError(); - } - - return 0; -} - - -static int uv__duplicate_fd(uv_loop_t* loop, int fd, HANDLE* dup) { - HANDLE handle; - - if (fd == -1) { - *dup = INVALID_HANDLE_VALUE; - return ERROR_INVALID_HANDLE; - } - - handle = uv__get_osfhandle(fd); - return uv__duplicate_handle(loop, handle, dup); -} - - -int uv__create_nul_handle(HANDLE* handle_ptr, - DWORD access) { - HANDLE handle; - SECURITY_ATTRIBUTES sa; - - sa.nLength = sizeof sa; - sa.lpSecurityDescriptor = NULL; - sa.bInheritHandle = TRUE; - - handle = CreateFileW(L"NUL", - access, - FILE_SHARE_READ | FILE_SHARE_WRITE, - &sa, - OPEN_EXISTING, - 0, - NULL); - if (handle == INVALID_HANDLE_VALUE) { - return GetLastError(); - } - - *handle_ptr = handle; - return 0; -} - - -int uv__stdio_create(uv_loop_t* loop, - const uv_process_options_t* options, - BYTE** buffer_ptr) { - BYTE* buffer; - int count, i; - int err; - - count = options->stdio_count; - - if (count < 0 || count > 255) { - /* Only support FDs 0-255 */ - return ERROR_NOT_SUPPORTED; - } else if (count < 3) { - /* There should always be at least 3 stdio handles. */ - count = 3; - } - - /* Allocate the child stdio buffer */ - buffer = (BYTE*) uv__malloc(CHILD_STDIO_SIZE(count)); - if (buffer == NULL) { - return ERROR_OUTOFMEMORY; - } - - /* Prepopulate the buffer with INVALID_HANDLE_VALUE handles so we can */ - /* clean up on failure. */ - CHILD_STDIO_COUNT(buffer) = count; - for (i = 0; i < count; i++) { - CHILD_STDIO_CRT_FLAGS(buffer, i) = 0; - CHILD_STDIO_HANDLE(buffer, i) = INVALID_HANDLE_VALUE; - } - - for (i = 0; i < count; i++) { - uv_stdio_container_t fdopt; - if (i < options->stdio_count) { - fdopt = options->stdio[i]; - } else { - fdopt.flags = UV_IGNORE; - } - - switch (fdopt.flags & (UV_IGNORE | UV_CREATE_PIPE | UV_INHERIT_FD | - UV_INHERIT_STREAM)) { - case UV_IGNORE: - /* Starting a process with no stdin/stout/stderr can confuse it. */ - /* So no matter what the user specified, we make sure the first */ - /* three FDs are always open in their typical modes, e.g. stdin */ - /* be readable and stdout/err should be writable. For FDs > 2, don't */ - /* do anything - all handles in the stdio buffer are initialized with */ - /* INVALID_HANDLE_VALUE, which should be okay. */ - if (i <= 2) { - DWORD access = (i == 0) ? FILE_GENERIC_READ : - FILE_GENERIC_WRITE | FILE_READ_ATTRIBUTES; - - err = uv__create_nul_handle(&CHILD_STDIO_HANDLE(buffer, i), - access); - if (err) - goto error; - - CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN | FDEV; - } - break; - - case UV_CREATE_PIPE: { - /* Create a pair of two connected pipe ends; one end is turned into */ - /* an uv_pipe_t for use by the parent. The other one is given to */ - /* the child. */ - uv_pipe_t* parent_pipe = (uv_pipe_t*) fdopt.data.stream; - HANDLE child_pipe = INVALID_HANDLE_VALUE; - - /* Create a new, connected pipe pair. stdio[i].stream should point */ - /* to an uninitialized, but not connected pipe handle. */ - assert(fdopt.data.stream->type == UV_NAMED_PIPE); - assert(!(fdopt.data.stream->flags & UV_HANDLE_CONNECTION)); - assert(!(fdopt.data.stream->flags & UV_HANDLE_PIPESERVER)); - - err = uv__create_stdio_pipe_pair(loop, - parent_pipe, - &child_pipe, - fdopt.flags); - if (err) - goto error; - - CHILD_STDIO_HANDLE(buffer, i) = child_pipe; - CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN | FPIPE; - break; - } - - case UV_INHERIT_FD: { - /* Inherit a raw FD. */ - HANDLE child_handle; - - /* Make an inheritable duplicate of the handle. */ - err = uv__duplicate_fd(loop, fdopt.data.fd, &child_handle); - if (err) { - /* If fdopt.data.fd is not valid and fd fd <= 2, then ignore the */ - /* error. */ - if (fdopt.data.fd <= 2 && err == ERROR_INVALID_HANDLE) { - CHILD_STDIO_CRT_FLAGS(buffer, i) = 0; - CHILD_STDIO_HANDLE(buffer, i) = INVALID_HANDLE_VALUE; - break; - } - goto error; - } - - /* Figure out what the type is. */ - switch (GetFileType(child_handle)) { - case FILE_TYPE_DISK: - CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN; - break; - - case FILE_TYPE_PIPE: - CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN | FPIPE; - break; - - case FILE_TYPE_CHAR: - case FILE_TYPE_REMOTE: - CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN | FDEV; - break; - - case FILE_TYPE_UNKNOWN: - if (GetLastError() != 0) { - err = GetLastError(); - CloseHandle(child_handle); - goto error; - } - CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN | FDEV; - break; - - default: - assert(0); - return -1; - } - - CHILD_STDIO_HANDLE(buffer, i) = child_handle; - break; - } - - case UV_INHERIT_STREAM: { - /* Use an existing stream as the stdio handle for the child. */ - HANDLE stream_handle, child_handle; - unsigned char crt_flags; - uv_stream_t* stream = fdopt.data.stream; - - /* Leech the handle out of the stream. */ - if (stream->type == UV_TTY) { - stream_handle = ((uv_tty_t*) stream)->handle; - crt_flags = FOPEN | FDEV; - } else if (stream->type == UV_NAMED_PIPE && - stream->flags & UV_HANDLE_CONNECTION) { - stream_handle = ((uv_pipe_t*) stream)->handle; - crt_flags = FOPEN | FPIPE; - } else { - stream_handle = INVALID_HANDLE_VALUE; - crt_flags = 0; - } - - if (stream_handle == NULL || - stream_handle == INVALID_HANDLE_VALUE) { - /* The handle is already closed, or not yet created, or the */ - /* stream type is not supported. */ - err = ERROR_NOT_SUPPORTED; - goto error; - } - - /* Make an inheritable copy of the handle. */ - err = uv__duplicate_handle(loop, stream_handle, &child_handle); - if (err) - goto error; - - CHILD_STDIO_HANDLE(buffer, i) = child_handle; - CHILD_STDIO_CRT_FLAGS(buffer, i) = crt_flags; - break; - } - - default: - assert(0); - return -1; - } - } - - *buffer_ptr = buffer; - return 0; - - error: - uv__stdio_destroy(buffer); - return err; -} - - -void uv__stdio_destroy(BYTE* buffer) { - int i, count; - - count = CHILD_STDIO_COUNT(buffer); - for (i = 0; i < count; i++) { - HANDLE handle = CHILD_STDIO_HANDLE(buffer, i); - if (handle != INVALID_HANDLE_VALUE) { - CloseHandle(handle); - } - } - - uv__free(buffer); -} - - -void uv__stdio_noinherit(BYTE* buffer) { - int i, count; - - count = CHILD_STDIO_COUNT(buffer); - for (i = 0; i < count; i++) { - HANDLE handle = CHILD_STDIO_HANDLE(buffer, i); - if (handle != INVALID_HANDLE_VALUE) { - SetHandleInformation(handle, HANDLE_FLAG_INHERIT, 0); - } - } -} - - -int uv__stdio_verify(BYTE* buffer, WORD size) { - unsigned int count; - - /* Check the buffer pointer. */ - if (buffer == NULL) - return 0; - - /* Verify that the buffer is at least big enough to hold the count. */ - if (size < CHILD_STDIO_SIZE(0)) - return 0; - - /* Verify if the count is within range. */ - count = CHILD_STDIO_COUNT(buffer); - if (count > 256) - return 0; - - /* Verify that the buffer size is big enough to hold info for N FDs. */ - if (size < CHILD_STDIO_SIZE(count)) - return 0; - - return 1; -} - - -WORD uv__stdio_size(BYTE* buffer) { - return (WORD) CHILD_STDIO_SIZE(CHILD_STDIO_COUNT((buffer))); -} - - -HANDLE uv__stdio_handle(BYTE* buffer, int fd) { - return CHILD_STDIO_HANDLE(buffer, fd); -} diff --git a/vendor/libuv/src/win/process.c b/vendor/libuv/src/win/process.c deleted file mode 100644 index bdf88d2cd..000000000 --- a/vendor/libuv/src/win/process.c +++ /dev/null @@ -1,1247 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include /* alloca */ - -#include "uv.h" -#include "internal.h" -#include "handle-inl.h" -#include "req-inl.h" - - -#define SIGKILL 9 - - -typedef struct env_var { - const WCHAR* const wide; - const WCHAR* const wide_eq; - const size_t len; /* including null or '=' */ -} env_var_t; - -#define E_V(str) { L##str, L##str L"=", sizeof(str) } - -static const env_var_t required_vars[] = { /* keep me sorted */ - E_V("HOMEDRIVE"), - E_V("HOMEPATH"), - E_V("LOGONSERVER"), - E_V("PATH"), - E_V("SYSTEMDRIVE"), - E_V("SYSTEMROOT"), - E_V("TEMP"), - E_V("USERDOMAIN"), - E_V("USERNAME"), - E_V("USERPROFILE"), - E_V("WINDIR"), -}; -static size_t n_required_vars = ARRAY_SIZE(required_vars); - - -static HANDLE uv_global_job_handle_; -static uv_once_t uv_global_job_handle_init_guard_ = UV_ONCE_INIT; - - -static void uv__init_global_job_handle(void) { - /* Create a job object and set it up to kill all contained processes when - * it's closed. Since this handle is made non-inheritable and we're not - * giving it to anyone, we're the only process holding a reference to it. - * That means that if this process exits it is closed and all the processes - * it contains are killed. All processes created with uv_spawn that are not - * spawned with the UV_PROCESS_DETACHED flag are assigned to this job. - * - * We're setting the JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK flag so only the - * processes that we explicitly add are affected, and *their* subprocesses - * are not. This ensures that our child processes are not limited in their - * ability to use job control on Windows versions that don't deal with - * nested jobs (prior to Windows 8 / Server 2012). It also lets our child - * processes created detached processes without explicitly breaking away - * from job control (which uv_spawn doesn't, either). - */ - SECURITY_ATTRIBUTES attr; - JOBOBJECT_EXTENDED_LIMIT_INFORMATION info; - - memset(&attr, 0, sizeof attr); - attr.bInheritHandle = FALSE; - - memset(&info, 0, sizeof info); - info.BasicLimitInformation.LimitFlags = - JOB_OBJECT_LIMIT_BREAKAWAY_OK | - JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK | - JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION | - JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE; - - uv_global_job_handle_ = CreateJobObjectW(&attr, NULL); - if (uv_global_job_handle_ == NULL) - uv_fatal_error(GetLastError(), "CreateJobObjectW"); - - if (!SetInformationJobObject(uv_global_job_handle_, - JobObjectExtendedLimitInformation, - &info, - sizeof info)) - uv_fatal_error(GetLastError(), "SetInformationJobObject"); -} - - -static int uv_utf8_to_utf16_alloc(const char* s, WCHAR** ws_ptr) { - int ws_len, r; - WCHAR* ws; - - ws_len = MultiByteToWideChar(CP_UTF8, - 0, - s, - -1, - NULL, - 0); - if (ws_len <= 0) { - return GetLastError(); - } - - ws = (WCHAR*) uv__malloc(ws_len * sizeof(WCHAR)); - if (ws == NULL) { - return ERROR_OUTOFMEMORY; - } - - r = MultiByteToWideChar(CP_UTF8, - 0, - s, - -1, - ws, - ws_len); - assert(r == ws_len); - - *ws_ptr = ws; - return 0; -} - - -static void uv_process_init(uv_loop_t* loop, uv_process_t* handle) { - uv__handle_init(loop, (uv_handle_t*) handle, UV_PROCESS); - handle->exit_cb = NULL; - handle->pid = 0; - handle->exit_signal = 0; - handle->wait_handle = INVALID_HANDLE_VALUE; - handle->process_handle = INVALID_HANDLE_VALUE; - handle->child_stdio_buffer = NULL; - handle->exit_cb_pending = 0; - - uv_req_init(loop, (uv_req_t*)&handle->exit_req); - handle->exit_req.type = UV_PROCESS_EXIT; - handle->exit_req.data = handle; -} - - -/* - * Path search functions - */ - -/* - * Helper function for search_path - */ -static WCHAR* search_path_join_test(const WCHAR* dir, - size_t dir_len, - const WCHAR* name, - size_t name_len, - const WCHAR* ext, - size_t ext_len, - const WCHAR* cwd, - size_t cwd_len) { - WCHAR *result, *result_pos; - DWORD attrs; - if (dir_len > 2 && dir[0] == L'\\' && dir[1] == L'\\') { - /* It's a UNC path so ignore cwd */ - cwd_len = 0; - } else if (dir_len >= 1 && (dir[0] == L'/' || dir[0] == L'\\')) { - /* It's a full path without drive letter, use cwd's drive letter only */ - cwd_len = 2; - } else if (dir_len >= 2 && dir[1] == L':' && - (dir_len < 3 || (dir[2] != L'/' && dir[2] != L'\\'))) { - /* It's a relative path with drive letter (ext.g. D:../some/file) - * Replace drive letter in dir by full cwd if it points to the same drive, - * otherwise use the dir only. - */ - if (cwd_len < 2 || _wcsnicmp(cwd, dir, 2) != 0) { - cwd_len = 0; - } else { - dir += 2; - dir_len -= 2; - } - } else if (dir_len > 2 && dir[1] == L':') { - /* It's an absolute path with drive letter - * Don't use the cwd at all - */ - cwd_len = 0; - } - - /* Allocate buffer for output */ - result = result_pos = (WCHAR*)uv__malloc(sizeof(WCHAR) * - (cwd_len + 1 + dir_len + 1 + name_len + 1 + ext_len + 1)); - - /* Copy cwd */ - wcsncpy(result_pos, cwd, cwd_len); - result_pos += cwd_len; - - /* Add a path separator if cwd didn't end with one */ - if (cwd_len && wcsrchr(L"\\/:", result_pos[-1]) == NULL) { - result_pos[0] = L'\\'; - result_pos++; - } - - /* Copy dir */ - wcsncpy(result_pos, dir, dir_len); - result_pos += dir_len; - - /* Add a separator if the dir didn't end with one */ - if (dir_len && wcsrchr(L"\\/:", result_pos[-1]) == NULL) { - result_pos[0] = L'\\'; - result_pos++; - } - - /* Copy filename */ - wcsncpy(result_pos, name, name_len); - result_pos += name_len; - - if (ext_len) { - /* Add a dot if the filename didn't end with one */ - if (name_len && result_pos[-1] != '.') { - result_pos[0] = L'.'; - result_pos++; - } - - /* Copy extension */ - wcsncpy(result_pos, ext, ext_len); - result_pos += ext_len; - } - - /* Null terminator */ - result_pos[0] = L'\0'; - - attrs = GetFileAttributesW(result); - - if (attrs != INVALID_FILE_ATTRIBUTES && - !(attrs & FILE_ATTRIBUTE_DIRECTORY)) { - return result; - } - - uv__free(result); - return NULL; -} - - -/* - * Helper function for search_path - */ -static WCHAR* path_search_walk_ext(const WCHAR *dir, - size_t dir_len, - const WCHAR *name, - size_t name_len, - WCHAR *cwd, - size_t cwd_len, - int name_has_ext) { - WCHAR* result; - - /* If the name itself has a nonempty extension, try this extension first */ - if (name_has_ext) { - result = search_path_join_test(dir, dir_len, - name, name_len, - L"", 0, - cwd, cwd_len); - if (result != NULL) { - return result; - } - } - - /* Try .com extension */ - result = search_path_join_test(dir, dir_len, - name, name_len, - L"com", 3, - cwd, cwd_len); - if (result != NULL) { - return result; - } - - /* Try .exe extension */ - result = search_path_join_test(dir, dir_len, - name, name_len, - L"exe", 3, - cwd, cwd_len); - if (result != NULL) { - return result; - } - - return NULL; -} - - -/* - * search_path searches the system path for an executable filename - - * the windows API doesn't provide this as a standalone function nor as an - * option to CreateProcess. - * - * It tries to return an absolute filename. - * - * Furthermore, it tries to follow the semantics that cmd.exe, with this - * exception that PATHEXT environment variable isn't used. Since CreateProcess - * can start only .com and .exe files, only those extensions are tried. This - * behavior equals that of msvcrt's spawn functions. - * - * - Do not search the path if the filename already contains a path (either - * relative or absolute). - * - * - If there's really only a filename, check the current directory for file, - * then search all path directories. - * - * - If filename specified has *any* extension, search for the file with the - * specified extension first. - * - * - If the literal filename is not found in a directory, try *appending* - * (not replacing) .com first and then .exe. - * - * - The path variable may contain relative paths; relative paths are relative - * to the cwd. - * - * - Directories in path may or may not end with a trailing backslash. - * - * - CMD does not trim leading/trailing whitespace from path/pathex entries - * nor from the environment variables as a whole. - * - * - When cmd.exe cannot read a directory, it will just skip it and go on - * searching. However, unlike posix-y systems, it will happily try to run a - * file that is not readable/executable; if the spawn fails it will not - * continue searching. - * - * UNC path support: we are dealing with UNC paths in both the path and the - * filename. This is a deviation from what cmd.exe does (it does not let you - * start a program by specifying an UNC path on the command line) but this is - * really a pointless restriction. - * - */ -static WCHAR* search_path(const WCHAR *file, - WCHAR *cwd, - const WCHAR *path) { - int file_has_dir; - WCHAR* result = NULL; - WCHAR *file_name_start; - WCHAR *dot; - const WCHAR *dir_start, *dir_end, *dir_path; - size_t dir_len; - int name_has_ext; - - size_t file_len = wcslen(file); - size_t cwd_len = wcslen(cwd); - - /* If the caller supplies an empty filename, - * we're not gonna return c:\windows\.exe -- GFY! - */ - if (file_len == 0 - || (file_len == 1 && file[0] == L'.')) { - return NULL; - } - - /* Find the start of the filename so we can split the directory from the */ - /* name. */ - for (file_name_start = (WCHAR*)file + file_len; - file_name_start > file - && file_name_start[-1] != L'\\' - && file_name_start[-1] != L'/' - && file_name_start[-1] != L':'; - file_name_start--); - - file_has_dir = file_name_start != file; - - /* Check if the filename includes an extension */ - dot = wcschr(file_name_start, L'.'); - name_has_ext = (dot != NULL && dot[1] != L'\0'); - - if (file_has_dir) { - /* The file has a path inside, don't use path */ - result = path_search_walk_ext( - file, file_name_start - file, - file_name_start, file_len - (file_name_start - file), - cwd, cwd_len, - name_has_ext); - - } else { - dir_end = path; - - /* The file is really only a name; look in cwd first, then scan path */ - result = path_search_walk_ext(L"", 0, - file, file_len, - cwd, cwd_len, - name_has_ext); - - while (result == NULL) { - if (*dir_end == L'\0') { - break; - } - - /* Skip the separator that dir_end now points to */ - if (dir_end != path || *path == L';') { - dir_end++; - } - - /* Next slice starts just after where the previous one ended */ - dir_start = dir_end; - - /* Slice until the next ; or \0 is found */ - dir_end = wcschr(dir_start, L';'); - if (dir_end == NULL) { - dir_end = wcschr(dir_start, L'\0'); - } - - /* If the slice is zero-length, don't bother */ - if (dir_end - dir_start == 0) { - continue; - } - - dir_path = dir_start; - dir_len = dir_end - dir_start; - - /* Adjust if the path is quoted. */ - if (dir_path[0] == '"' || dir_path[0] == '\'') { - ++dir_path; - --dir_len; - } - - if (dir_path[dir_len - 1] == '"' || dir_path[dir_len - 1] == '\'') { - --dir_len; - } - - result = path_search_walk_ext(dir_path, dir_len, - file, file_len, - cwd, cwd_len, - name_has_ext); - } - } - - return result; -} - - -/* - * Quotes command line arguments - * Returns a pointer to the end (next char to be written) of the buffer - */ -WCHAR* quote_cmd_arg(const WCHAR *source, WCHAR *target) { - size_t len = wcslen(source); - size_t i; - int quote_hit; - WCHAR* start; - - if (len == 0) { - /* Need double quotation for empty argument */ - *(target++) = L'"'; - *(target++) = L'"'; - return target; - } - - if (NULL == wcspbrk(source, L" \t\"")) { - /* No quotation needed */ - wcsncpy(target, source, len); - target += len; - return target; - } - - if (NULL == wcspbrk(source, L"\"\\")) { - /* - * No embedded double quotes or backlashes, so I can just wrap - * quote marks around the whole thing. - */ - *(target++) = L'"'; - wcsncpy(target, source, len); - target += len; - *(target++) = L'"'; - return target; - } - - /* - * Expected input/output: - * input : hello"world - * output: "hello\"world" - * input : hello""world - * output: "hello\"\"world" - * input : hello\world - * output: hello\world - * input : hello\\world - * output: hello\\world - * input : hello\"world - * output: "hello\\\"world" - * input : hello\\"world - * output: "hello\\\\\"world" - * input : hello world\ - * output: "hello world\\" - */ - - *(target++) = L'"'; - start = target; - quote_hit = 1; - - for (i = len; i > 0; --i) { - *(target++) = source[i - 1]; - - if (quote_hit && source[i - 1] == L'\\') { - *(target++) = L'\\'; - } else if(source[i - 1] == L'"') { - quote_hit = 1; - *(target++) = L'\\'; - } else { - quote_hit = 0; - } - } - target[0] = L'\0'; - wcsrev(start); - *(target++) = L'"'; - return target; -} - - -int make_program_args(char** args, int verbatim_arguments, WCHAR** dst_ptr) { - char** arg; - WCHAR* dst = NULL; - WCHAR* temp_buffer = NULL; - size_t dst_len = 0; - size_t temp_buffer_len = 0; - WCHAR* pos; - int arg_count = 0; - int err = 0; - - /* Count the required size. */ - for (arg = args; *arg; arg++) { - DWORD arg_len; - - arg_len = MultiByteToWideChar(CP_UTF8, - 0, - *arg, - -1, - NULL, - 0); - if (arg_len == 0) { - return GetLastError(); - } - - dst_len += arg_len; - - if (arg_len > temp_buffer_len) - temp_buffer_len = arg_len; - - arg_count++; - } - - /* Adjust for potential quotes. Also assume the worst-case scenario */ - /* that every character needs escaping, so we need twice as much space. */ - dst_len = dst_len * 2 + arg_count * 2; - - /* Allocate buffer for the final command line. */ - dst = (WCHAR*) uv__malloc(dst_len * sizeof(WCHAR)); - if (dst == NULL) { - err = ERROR_OUTOFMEMORY; - goto error; - } - - /* Allocate temporary working buffer. */ - temp_buffer = (WCHAR*) uv__malloc(temp_buffer_len * sizeof(WCHAR)); - if (temp_buffer == NULL) { - err = ERROR_OUTOFMEMORY; - goto error; - } - - pos = dst; - for (arg = args; *arg; arg++) { - DWORD arg_len; - - /* Convert argument to wide char. */ - arg_len = MultiByteToWideChar(CP_UTF8, - 0, - *arg, - -1, - temp_buffer, - (int) (dst + dst_len - pos)); - if (arg_len == 0) { - err = GetLastError(); - goto error; - } - - if (verbatim_arguments) { - /* Copy verbatim. */ - wcscpy(pos, temp_buffer); - pos += arg_len - 1; - } else { - /* Quote/escape, if needed. */ - pos = quote_cmd_arg(temp_buffer, pos); - } - - *pos++ = *(arg + 1) ? L' ' : L'\0'; - } - - uv__free(temp_buffer); - - *dst_ptr = dst; - return 0; - -error: - uv__free(dst); - uv__free(temp_buffer); - return err; -} - - -int env_strncmp(const wchar_t* a, int na, const wchar_t* b) { - wchar_t* a_eq; - wchar_t* b_eq; - wchar_t* A; - wchar_t* B; - int nb; - int r; - - if (na < 0) { - a_eq = wcschr(a, L'='); - assert(a_eq); - na = (int)(long)(a_eq - a); - } else { - na--; - } - b_eq = wcschr(b, L'='); - assert(b_eq); - nb = b_eq - b; - - A = alloca((na+1) * sizeof(wchar_t)); - B = alloca((nb+1) * sizeof(wchar_t)); - - r = LCMapStringW(LOCALE_INVARIANT, LCMAP_UPPERCASE, a, na, A, na); - assert(r==na); - A[na] = L'\0'; - r = LCMapStringW(LOCALE_INVARIANT, LCMAP_UPPERCASE, b, nb, B, nb); - assert(r==nb); - B[nb] = L'\0'; - - while (1) { - wchar_t AA = *A++; - wchar_t BB = *B++; - if (AA < BB) { - return -1; - } else if (AA > BB) { - return 1; - } else if (!AA && !BB) { - return 0; - } - } -} - - -static int qsort_wcscmp(const void *a, const void *b) { - wchar_t* astr = *(wchar_t* const*)a; - wchar_t* bstr = *(wchar_t* const*)b; - return env_strncmp(astr, -1, bstr); -} - - -/* - * The way windows takes environment variables is different than what C does; - * Windows wants a contiguous block of null-terminated strings, terminated - * with an additional null. - * - * Windows has a few "essential" environment variables. winsock will fail - * to initialize if SYSTEMROOT is not defined; some APIs make reference to - * TEMP. SYSTEMDRIVE is probably also important. We therefore ensure that - * these get defined if the input environment block does not contain any - * values for them. - * - * Also add variables known to Cygwin to be required for correct - * subprocess operation in many cases: - * https://github.com/Alexpux/Cygwin/blob/b266b04fbbd3a595f02ea149e4306d3ab9b1fe3d/winsup/cygwin/environ.cc#L955 - * - */ -int make_program_env(char* env_block[], WCHAR** dst_ptr) { - WCHAR* dst; - WCHAR* ptr; - char** env; - size_t env_len = 0; - int len; - size_t i; - DWORD var_size; - size_t env_block_count = 1; /* 1 for null-terminator */ - WCHAR* dst_copy; - WCHAR** ptr_copy; - WCHAR** env_copy; - DWORD* required_vars_value_len = alloca(n_required_vars * sizeof(DWORD*)); - - /* first pass: determine size in UTF-16 */ - for (env = env_block; *env; env++) { - int len; - if (strchr(*env, '=')) { - len = MultiByteToWideChar(CP_UTF8, - 0, - *env, - -1, - NULL, - 0); - if (len <= 0) { - return GetLastError(); - } - env_len += len; - env_block_count++; - } - } - - /* second pass: copy to UTF-16 environment block */ - dst_copy = (WCHAR*)uv__malloc(env_len * sizeof(WCHAR)); - if (!dst_copy) { - return ERROR_OUTOFMEMORY; - } - env_copy = alloca(env_block_count * sizeof(WCHAR*)); - - ptr = dst_copy; - ptr_copy = env_copy; - for (env = env_block; *env; env++) { - if (strchr(*env, '=')) { - len = MultiByteToWideChar(CP_UTF8, - 0, - *env, - -1, - ptr, - (int) (env_len - (ptr - dst_copy))); - if (len <= 0) { - DWORD err = GetLastError(); - uv__free(dst_copy); - return err; - } - *ptr_copy++ = ptr; - ptr += len; - } - } - *ptr_copy = NULL; - assert(env_len == ptr - dst_copy); - - /* sort our (UTF-16) copy */ - qsort(env_copy, env_block_count-1, sizeof(wchar_t*), qsort_wcscmp); - - /* third pass: check for required variables */ - for (ptr_copy = env_copy, i = 0; i < n_required_vars; ) { - int cmp; - if (!*ptr_copy) { - cmp = -1; - } else { - cmp = env_strncmp(required_vars[i].wide_eq, - required_vars[i].len, - *ptr_copy); - } - if (cmp < 0) { - /* missing required var */ - var_size = GetEnvironmentVariableW(required_vars[i].wide, NULL, 0); - required_vars_value_len[i] = var_size; - if (var_size != 0) { - env_len += required_vars[i].len; - env_len += var_size; - } - i++; - } else { - ptr_copy++; - if (cmp == 0) - i++; - } - } - - /* final pass: copy, in sort order, and inserting required variables */ - dst = uv__malloc((1+env_len) * sizeof(WCHAR)); - if (!dst) { - uv__free(dst_copy); - return ERROR_OUTOFMEMORY; - } - - for (ptr = dst, ptr_copy = env_copy, i = 0; - *ptr_copy || i < n_required_vars; - ptr += len) { - int cmp; - if (i >= n_required_vars) { - cmp = 1; - } else if (!*ptr_copy) { - cmp = -1; - } else { - cmp = env_strncmp(required_vars[i].wide_eq, - required_vars[i].len, - *ptr_copy); - } - if (cmp < 0) { - /* missing required var */ - len = required_vars_value_len[i]; - if (len) { - wcscpy(ptr, required_vars[i].wide_eq); - ptr += required_vars[i].len; - var_size = GetEnvironmentVariableW(required_vars[i].wide, - ptr, - (int) (env_len - (ptr - dst))); - if (var_size != len-1) { /* race condition? */ - uv_fatal_error(GetLastError(), "GetEnvironmentVariableW"); - } - } - i++; - } else { - /* copy var from env_block */ - len = wcslen(*ptr_copy) + 1; - wmemcpy(ptr, *ptr_copy, len); - ptr_copy++; - if (cmp == 0) - i++; - } - } - - /* Terminate with an extra NULL. */ - assert(env_len == (ptr - dst)); - *ptr = L'\0'; - - uv__free(dst_copy); - *dst_ptr = dst; - return 0; -} - -/* - * Attempt to find the value of the PATH environment variable in the child's - * preprocessed environment. - * - * If found, a pointer into `env` is returned. If not found, NULL is returned. - */ -static WCHAR* find_path(WCHAR *env) { - for (; env != NULL && *env != 0; env += wcslen(env) + 1) { - if (wcsncmp(env, L"PATH=", 5) == 0) - return &env[5]; - } - - return NULL; -} - -/* - * Called on Windows thread-pool thread to indicate that - * a child process has exited. - */ -static void CALLBACK exit_wait_callback(void* data, BOOLEAN didTimeout) { - uv_process_t* process = (uv_process_t*) data; - uv_loop_t* loop = process->loop; - - assert(didTimeout == FALSE); - assert(process); - assert(!process->exit_cb_pending); - - process->exit_cb_pending = 1; - - /* Post completed */ - POST_COMPLETION_FOR_REQ(loop, &process->exit_req); -} - - -/* Called on main thread after a child process has exited. */ -void uv_process_proc_exit(uv_loop_t* loop, uv_process_t* handle) { - int64_t exit_code; - DWORD status; - - assert(handle->exit_cb_pending); - handle->exit_cb_pending = 0; - - /* If we're closing, don't call the exit callback. Just schedule a close */ - /* callback now. */ - if (handle->flags & UV__HANDLE_CLOSING) { - uv_want_endgame(loop, (uv_handle_t*) handle); - return; - } - - /* Unregister from process notification. */ - if (handle->wait_handle != INVALID_HANDLE_VALUE) { - UnregisterWait(handle->wait_handle); - handle->wait_handle = INVALID_HANDLE_VALUE; - } - - /* Set the handle to inactive: no callbacks will be made after the exit */ - /* callback.*/ - uv__handle_stop(handle); - - if (GetExitCodeProcess(handle->process_handle, &status)) { - exit_code = status; - } else { - /* Unable to to obtain the exit code. This should never happen. */ - exit_code = uv_translate_sys_error(GetLastError()); - } - - /* Fire the exit callback. */ - if (handle->exit_cb) { - handle->exit_cb(handle, exit_code, handle->exit_signal); - } -} - - -void uv_process_close(uv_loop_t* loop, uv_process_t* handle) { - uv__handle_closing(handle); - - if (handle->wait_handle != INVALID_HANDLE_VALUE) { - /* This blocks until either the wait was cancelled, or the callback has */ - /* completed. */ - BOOL r = UnregisterWaitEx(handle->wait_handle, INVALID_HANDLE_VALUE); - if (!r) { - /* This should never happen, and if it happens, we can't recover... */ - uv_fatal_error(GetLastError(), "UnregisterWaitEx"); - } - - handle->wait_handle = INVALID_HANDLE_VALUE; - } - - if (!handle->exit_cb_pending) { - uv_want_endgame(loop, (uv_handle_t*)handle); - } -} - - -void uv_process_endgame(uv_loop_t* loop, uv_process_t* handle) { - assert(!handle->exit_cb_pending); - assert(handle->flags & UV__HANDLE_CLOSING); - assert(!(handle->flags & UV_HANDLE_CLOSED)); - - /* Clean-up the process handle. */ - CloseHandle(handle->process_handle); - - uv__handle_close(handle); -} - - -int uv_spawn(uv_loop_t* loop, - uv_process_t* process, - const uv_process_options_t* options) { - int i; - int err = 0; - WCHAR* path = NULL, *alloc_path = NULL; - BOOL result; - WCHAR* application_path = NULL, *application = NULL, *arguments = NULL, - *env = NULL, *cwd = NULL; - STARTUPINFOW startup; - PROCESS_INFORMATION info; - DWORD process_flags; - - uv_process_init(loop, process); - process->exit_cb = options->exit_cb; - - if (options->flags & (UV_PROCESS_SETGID | UV_PROCESS_SETUID)) { - return UV_ENOTSUP; - } - - if (options->file == NULL || - options->args == NULL) { - return UV_EINVAL; - } - - assert(options->file != NULL); - assert(!(options->flags & ~(UV_PROCESS_DETACHED | - UV_PROCESS_SETGID | - UV_PROCESS_SETUID | - UV_PROCESS_WINDOWS_HIDE | - UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS))); - - err = uv_utf8_to_utf16_alloc(options->file, &application); - if (err) - goto done; - - err = make_program_args( - options->args, - options->flags & UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS, - &arguments); - if (err) - goto done; - - if (options->env) { - err = make_program_env(options->env, &env); - if (err) - goto done; - } - - if (options->cwd) { - /* Explicit cwd */ - err = uv_utf8_to_utf16_alloc(options->cwd, &cwd); - if (err) - goto done; - - } else { - /* Inherit cwd */ - DWORD cwd_len, r; - - cwd_len = GetCurrentDirectoryW(0, NULL); - if (!cwd_len) { - err = GetLastError(); - goto done; - } - - cwd = (WCHAR*) uv__malloc(cwd_len * sizeof(WCHAR)); - if (cwd == NULL) { - err = ERROR_OUTOFMEMORY; - goto done; - } - - r = GetCurrentDirectoryW(cwd_len, cwd); - if (r == 0 || r >= cwd_len) { - err = GetLastError(); - goto done; - } - } - - /* Get PATH environment variable. */ - path = find_path(env); - if (path == NULL) { - DWORD path_len, r; - - path_len = GetEnvironmentVariableW(L"PATH", NULL, 0); - if (path_len == 0) { - err = GetLastError(); - goto done; - } - - alloc_path = (WCHAR*) uv__malloc(path_len * sizeof(WCHAR)); - if (alloc_path == NULL) { - err = ERROR_OUTOFMEMORY; - goto done; - } - path = alloc_path; - - r = GetEnvironmentVariableW(L"PATH", path, path_len); - if (r == 0 || r >= path_len) { - err = GetLastError(); - goto done; - } - } - - err = uv__stdio_create(loop, options, &process->child_stdio_buffer); - if (err) - goto done; - - application_path = search_path(application, - cwd, - path); - if (application_path == NULL) { - /* Not found. */ - err = ERROR_FILE_NOT_FOUND; - goto done; - } - - startup.cb = sizeof(startup); - startup.lpReserved = NULL; - startup.lpDesktop = NULL; - startup.lpTitle = NULL; - startup.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; - - startup.cbReserved2 = uv__stdio_size(process->child_stdio_buffer); - startup.lpReserved2 = (BYTE*) process->child_stdio_buffer; - - startup.hStdInput = uv__stdio_handle(process->child_stdio_buffer, 0); - startup.hStdOutput = uv__stdio_handle(process->child_stdio_buffer, 1); - startup.hStdError = uv__stdio_handle(process->child_stdio_buffer, 2); - - if (options->flags & UV_PROCESS_WINDOWS_HIDE) { - /* Use SW_HIDE to avoid any potential process window. */ - startup.wShowWindow = SW_HIDE; - } else { - startup.wShowWindow = SW_SHOWDEFAULT; - } - - process_flags = CREATE_UNICODE_ENVIRONMENT; - - if (options->flags & UV_PROCESS_DETACHED) { - /* Note that we're not setting the CREATE_BREAKAWAY_FROM_JOB flag. That - * means that libuv might not let you create a fully daemonized process - * when run under job control. However the type of job control that libuv - * itself creates doesn't trickle down to subprocesses so they can still - * daemonize. - * - * A reason to not do this is that CREATE_BREAKAWAY_FROM_JOB makes the - * CreateProcess call fail if we're under job control that doesn't allow - * breakaway. - */ - process_flags |= DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP; - } - - if (!CreateProcessW(application_path, - arguments, - NULL, - NULL, - 1, - process_flags, - env, - cwd, - &startup, - &info)) { - /* CreateProcessW failed. */ - err = GetLastError(); - goto done; - } - - /* Spawn succeeded */ - /* Beyond this point, failure is reported asynchronously. */ - - process->process_handle = info.hProcess; - process->pid = info.dwProcessId; - - /* If the process isn't spawned as detached, assign to the global job */ - /* object so windows will kill it when the parent process dies. */ - if (!(options->flags & UV_PROCESS_DETACHED)) { - uv_once(&uv_global_job_handle_init_guard_, uv__init_global_job_handle); - - if (!AssignProcessToJobObject(uv_global_job_handle_, info.hProcess)) { - /* AssignProcessToJobObject might fail if this process is under job - * control and the job doesn't have the - * JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK flag set, on a Windows version - * that doesn't support nested jobs. - * - * When that happens we just swallow the error and continue without - * establishing a kill-child-on-parent-exit relationship, otherwise - * there would be no way for libuv applications run under job control - * to spawn processes at all. - */ - DWORD err = GetLastError(); - if (err != ERROR_ACCESS_DENIED) - uv_fatal_error(err, "AssignProcessToJobObject"); - } - } - - /* Set IPC pid to all IPC pipes. */ - for (i = 0; i < options->stdio_count; i++) { - const uv_stdio_container_t* fdopt = &options->stdio[i]; - if (fdopt->flags & UV_CREATE_PIPE && - fdopt->data.stream->type == UV_NAMED_PIPE && - ((uv_pipe_t*) fdopt->data.stream)->ipc) { - ((uv_pipe_t*) fdopt->data.stream)->pipe.conn.ipc_pid = info.dwProcessId; - } - } - - /* Setup notifications for when the child process exits. */ - result = RegisterWaitForSingleObject(&process->wait_handle, - process->process_handle, exit_wait_callback, (void*)process, INFINITE, - WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE); - if (!result) { - uv_fatal_error(GetLastError(), "RegisterWaitForSingleObject"); - } - - CloseHandle(info.hThread); - - assert(!err); - - /* Make the handle active. It will remain active until the exit callback */ - /* is made or the handle is closed, whichever happens first. */ - uv__handle_start(process); - - /* Cleanup, whether we succeeded or failed. */ - done: - uv__free(application); - uv__free(application_path); - uv__free(arguments); - uv__free(cwd); - uv__free(env); - uv__free(alloc_path); - - if (process->child_stdio_buffer != NULL) { - /* Clean up child stdio handles. */ - uv__stdio_destroy(process->child_stdio_buffer); - process->child_stdio_buffer = NULL; - } - - return uv_translate_sys_error(err); -} - - -static int uv__kill(HANDLE process_handle, int signum) { - switch (signum) { - case SIGTERM: - case SIGKILL: - case SIGINT: { - /* Unconditionally terminate the process. On Windows, killed processes */ - /* normally return 1. */ - DWORD status; - int err; - - if (TerminateProcess(process_handle, 1)) - return 0; - - /* If the process already exited before TerminateProcess was called, */ - /* TerminateProcess will fail with ERROR_ACCESS_DENIED. */ - err = GetLastError(); - if (err == ERROR_ACCESS_DENIED && - GetExitCodeProcess(process_handle, &status) && - status != STILL_ACTIVE) { - return UV_ESRCH; - } - - return uv_translate_sys_error(err); - } - - case 0: { - /* Health check: is the process still alive? */ - DWORD status; - - if (!GetExitCodeProcess(process_handle, &status)) - return uv_translate_sys_error(GetLastError()); - - if (status != STILL_ACTIVE) - return UV_ESRCH; - - return 0; - } - - default: - /* Unsupported signal. */ - return UV_ENOSYS; - } -} - - -int uv_process_kill(uv_process_t* process, int signum) { - int err; - - if (process->process_handle == INVALID_HANDLE_VALUE) { - return UV_EINVAL; - } - - err = uv__kill(process->process_handle, signum); - if (err) { - return err; /* err is already translated. */ - } - - process->exit_signal = signum; - - return 0; -} - - -int uv_kill(int pid, int signum) { - int err; - HANDLE process_handle = OpenProcess(PROCESS_TERMINATE | - PROCESS_QUERY_INFORMATION, FALSE, pid); - - if (process_handle == NULL) { - err = GetLastError(); - if (err == ERROR_INVALID_PARAMETER) { - return UV_ESRCH; - } else { - return uv_translate_sys_error(err); - } - } - - err = uv__kill(process_handle, signum); - CloseHandle(process_handle); - - return err; /* err is already translated. */ -} diff --git a/vendor/libuv/src/win/req-inl.h b/vendor/libuv/src/win/req-inl.h deleted file mode 100644 index b5e502eef..000000000 --- a/vendor/libuv/src/win/req-inl.h +++ /dev/null @@ -1,224 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef UV_WIN_REQ_INL_H_ -#define UV_WIN_REQ_INL_H_ - -#include - -#include "uv.h" -#include "internal.h" - - -#define SET_REQ_STATUS(req, status) \ - (req)->u.io.overlapped.Internal = (ULONG_PTR) (status) - -#define SET_REQ_ERROR(req, error) \ - SET_REQ_STATUS((req), NTSTATUS_FROM_WIN32((error))) - -#define SET_REQ_SUCCESS(req) \ - SET_REQ_STATUS((req), STATUS_SUCCESS) - -#define GET_REQ_STATUS(req) \ - ((NTSTATUS) (req)->u.io.overlapped.Internal) - -#define REQ_SUCCESS(req) \ - (NT_SUCCESS(GET_REQ_STATUS((req)))) - -#define GET_REQ_ERROR(req) \ - (pRtlNtStatusToDosError(GET_REQ_STATUS((req)))) - -#define GET_REQ_SOCK_ERROR(req) \ - (uv_ntstatus_to_winsock_error(GET_REQ_STATUS((req)))) - - -#define REGISTER_HANDLE_REQ(loop, handle, req) \ - do { \ - INCREASE_ACTIVE_COUNT((loop), (handle)); \ - uv__req_register((loop), (req)); \ - } while (0) - -#define UNREGISTER_HANDLE_REQ(loop, handle, req) \ - do { \ - DECREASE_ACTIVE_COUNT((loop), (handle)); \ - uv__req_unregister((loop), (req)); \ - } while (0) - - -#define UV_SUCCEEDED_WITHOUT_IOCP(result) \ - ((result) && (handle->flags & UV_HANDLE_SYNC_BYPASS_IOCP)) - -#define UV_SUCCEEDED_WITH_IOCP(result) \ - ((result) || (GetLastError() == ERROR_IO_PENDING)) - - -#define POST_COMPLETION_FOR_REQ(loop, req) \ - if (!PostQueuedCompletionStatus((loop)->iocp, \ - 0, \ - 0, \ - &((req)->u.io.overlapped))) { \ - uv_fatal_error(GetLastError(), "PostQueuedCompletionStatus"); \ - } - - -INLINE static void uv_req_init(uv_loop_t* loop, uv_req_t* req) { - req->type = UV_UNKNOWN_REQ; - SET_REQ_SUCCESS(req); -} - - -INLINE static uv_req_t* uv_overlapped_to_req(OVERLAPPED* overlapped) { - return CONTAINING_RECORD(overlapped, uv_req_t, u.io.overlapped); -} - - -INLINE static void uv_insert_pending_req(uv_loop_t* loop, uv_req_t* req) { - req->next_req = NULL; - if (loop->pending_reqs_tail) { -#ifdef _DEBUG - /* Ensure the request is not already in the queue, or the queue - * will get corrupted. - */ - uv_req_t* current = loop->pending_reqs_tail; - do { - assert(req != current); - current = current->next_req; - } while(current != loop->pending_reqs_tail); -#endif - - req->next_req = loop->pending_reqs_tail->next_req; - loop->pending_reqs_tail->next_req = req; - loop->pending_reqs_tail = req; - } else { - req->next_req = req; - loop->pending_reqs_tail = req; - } -} - - -#define DELEGATE_STREAM_REQ(loop, req, method, handle_at) \ - do { \ - switch (((uv_handle_t*) (req)->handle_at)->type) { \ - case UV_TCP: \ - uv_process_tcp_##method##_req(loop, \ - (uv_tcp_t*) ((req)->handle_at), \ - req); \ - break; \ - \ - case UV_NAMED_PIPE: \ - uv_process_pipe_##method##_req(loop, \ - (uv_pipe_t*) ((req)->handle_at), \ - req); \ - break; \ - \ - case UV_TTY: \ - uv_process_tty_##method##_req(loop, \ - (uv_tty_t*) ((req)->handle_at), \ - req); \ - break; \ - \ - default: \ - assert(0); \ - } \ - } while (0) - - -INLINE static int uv_process_reqs(uv_loop_t* loop) { - uv_req_t* req; - uv_req_t* first; - uv_req_t* next; - - if (loop->pending_reqs_tail == NULL) - return 0; - - first = loop->pending_reqs_tail->next_req; - next = first; - loop->pending_reqs_tail = NULL; - - while (next != NULL) { - req = next; - next = req->next_req != first ? req->next_req : NULL; - - switch (req->type) { - case UV_READ: - DELEGATE_STREAM_REQ(loop, req, read, data); - break; - - case UV_WRITE: - DELEGATE_STREAM_REQ(loop, (uv_write_t*) req, write, handle); - break; - - case UV_ACCEPT: - DELEGATE_STREAM_REQ(loop, req, accept, data); - break; - - case UV_CONNECT: - DELEGATE_STREAM_REQ(loop, (uv_connect_t*) req, connect, handle); - break; - - case UV_SHUTDOWN: - /* Tcp shutdown requests don't come here. */ - assert(((uv_shutdown_t*) req)->handle->type == UV_NAMED_PIPE); - uv_process_pipe_shutdown_req( - loop, - (uv_pipe_t*) ((uv_shutdown_t*) req)->handle, - (uv_shutdown_t*) req); - break; - - case UV_UDP_RECV: - uv_process_udp_recv_req(loop, (uv_udp_t*) req->data, req); - break; - - case UV_UDP_SEND: - uv_process_udp_send_req(loop, - ((uv_udp_send_t*) req)->handle, - (uv_udp_send_t*) req); - break; - - case UV_WAKEUP: - uv_process_async_wakeup_req(loop, (uv_async_t*) req->data, req); - break; - - case UV_SIGNAL_REQ: - uv_process_signal_req(loop, (uv_signal_t*) req->data, req); - break; - - case UV_POLL_REQ: - uv_process_poll_req(loop, (uv_poll_t*) req->data, req); - break; - - case UV_PROCESS_EXIT: - uv_process_proc_exit(loop, (uv_process_t*) req->data); - break; - - case UV_FS_EVENT_REQ: - uv_process_fs_event_req(loop, req, (uv_fs_event_t*) req->data); - break; - - default: - assert(0); - } - } - - return 1; -} - -#endif /* UV_WIN_REQ_INL_H_ */ diff --git a/vendor/libuv/src/win/req.c b/vendor/libuv/src/win/req.c deleted file mode 100644 index 111cc5e28..000000000 --- a/vendor/libuv/src/win/req.c +++ /dev/null @@ -1,25 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include - -#include "uv.h" -#include "internal.h" diff --git a/vendor/libuv/src/win/signal.c b/vendor/libuv/src/win/signal.c deleted file mode 100644 index af7974c36..000000000 --- a/vendor/libuv/src/win/signal.c +++ /dev/null @@ -1,248 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include -#include - -#include "uv.h" -#include "internal.h" -#include "handle-inl.h" -#include "req-inl.h" - - -RB_HEAD(uv_signal_tree_s, uv_signal_s); - -static struct uv_signal_tree_s uv__signal_tree = RB_INITIALIZER(uv__signal_tree); -static CRITICAL_SECTION uv__signal_lock; - -static BOOL WINAPI uv__signal_control_handler(DWORD type); - -void uv_signals_init() { - InitializeCriticalSection(&uv__signal_lock); - if (!SetConsoleCtrlHandler(uv__signal_control_handler, TRUE)) - abort(); -} - - -static int uv__signal_compare(uv_signal_t* w1, uv_signal_t* w2) { - /* Compare signums first so all watchers with the same signnum end up */ - /* adjacent. */ - if (w1->signum < w2->signum) return -1; - if (w1->signum > w2->signum) return 1; - - /* Sort by loop pointer, so we can easily look up the first item after */ - /* { .signum = x, .loop = NULL } */ - if ((uintptr_t) w1->loop < (uintptr_t) w2->loop) return -1; - if ((uintptr_t) w1->loop > (uintptr_t) w2->loop) return 1; - - if ((uintptr_t) w1 < (uintptr_t) w2) return -1; - if ((uintptr_t) w1 > (uintptr_t) w2) return 1; - - return 0; -} - - -RB_GENERATE_STATIC(uv_signal_tree_s, uv_signal_s, tree_entry, uv__signal_compare); - - -/* - * Dispatches signal {signum} to all active uv_signal_t watchers in all loops. - * Returns 1 if the signal was dispatched to any watcher, or 0 if there were - * no active signal watchers observing this signal. - */ -int uv__signal_dispatch(int signum) { - uv_signal_t lookup; - uv_signal_t* handle; - int dispatched = 0; - - EnterCriticalSection(&uv__signal_lock); - - lookup.signum = signum; - lookup.loop = NULL; - - for (handle = RB_NFIND(uv_signal_tree_s, &uv__signal_tree, &lookup); - handle != NULL && handle->signum == signum; - handle = RB_NEXT(uv_signal_tree_s, &uv__signal_tree, handle)) { - unsigned long previous = InterlockedExchange( - (volatile LONG*) &handle->pending_signum, signum); - - if (!previous) { - POST_COMPLETION_FOR_REQ(handle->loop, &handle->signal_req); - } - - dispatched = 1; - } - - LeaveCriticalSection(&uv__signal_lock); - - return dispatched; -} - - -static BOOL WINAPI uv__signal_control_handler(DWORD type) { - switch (type) { - case CTRL_C_EVENT: - return uv__signal_dispatch(SIGINT); - - case CTRL_BREAK_EVENT: - return uv__signal_dispatch(SIGBREAK); - - case CTRL_CLOSE_EVENT: - if (uv__signal_dispatch(SIGHUP)) { - /* Windows will terminate the process after the control handler */ - /* returns. After that it will just terminate our process. Therefore */ - /* block the signal handler so the main loop has some time to pick */ - /* up the signal and do something for a few seconds. */ - Sleep(INFINITE); - return TRUE; - } - return FALSE; - - case CTRL_LOGOFF_EVENT: - case CTRL_SHUTDOWN_EVENT: - /* These signals are only sent to services. Services have their own */ - /* notification mechanism, so there's no point in handling these. */ - - default: - /* We don't handle these. */ - return FALSE; - } -} - - -int uv_signal_init(uv_loop_t* loop, uv_signal_t* handle) { - uv_req_t* req; - - uv__handle_init(loop, (uv_handle_t*) handle, UV_SIGNAL); - handle->pending_signum = 0; - handle->signum = 0; - handle->signal_cb = NULL; - - req = &handle->signal_req; - uv_req_init(loop, req); - req->type = UV_SIGNAL_REQ; - req->data = handle; - - return 0; -} - - -int uv_signal_stop(uv_signal_t* handle) { - uv_signal_t* removed_handle; - - /* If the watcher wasn't started, this is a no-op. */ - if (handle->signum == 0) - return 0; - - EnterCriticalSection(&uv__signal_lock); - - removed_handle = RB_REMOVE(uv_signal_tree_s, &uv__signal_tree, handle); - assert(removed_handle == handle); - - LeaveCriticalSection(&uv__signal_lock); - - handle->signum = 0; - uv__handle_stop(handle); - - return 0; -} - - -int uv_signal_start(uv_signal_t* handle, uv_signal_cb signal_cb, int signum) { - /* Test for invalid signal values. */ - if (signum != SIGWINCH && (signum <= 0 || signum >= NSIG)) - return UV_EINVAL; - - /* Short circuit: if the signal watcher is already watching {signum} don't */ - /* go through the process of deregistering and registering the handler. */ - /* Additionally, this avoids pending signals getting lost in the (small) */ - /* time frame that handle->signum == 0. */ - if (signum == handle->signum) { - handle->signal_cb = signal_cb; - return 0; - } - - /* If the signal handler was already active, stop it first. */ - if (handle->signum != 0) { - int r = uv_signal_stop(handle); - /* uv_signal_stop is infallible. */ - assert(r == 0); - } - - EnterCriticalSection(&uv__signal_lock); - - handle->signum = signum; - RB_INSERT(uv_signal_tree_s, &uv__signal_tree, handle); - - LeaveCriticalSection(&uv__signal_lock); - - handle->signal_cb = signal_cb; - uv__handle_start(handle); - - return 0; -} - - -void uv_process_signal_req(uv_loop_t* loop, uv_signal_t* handle, - uv_req_t* req) { - long dispatched_signum; - - assert(handle->type == UV_SIGNAL); - assert(req->type == UV_SIGNAL_REQ); - - dispatched_signum = InterlockedExchange( - (volatile LONG*) &handle->pending_signum, 0); - assert(dispatched_signum != 0); - - /* Check if the pending signal equals the signum that we are watching for. */ - /* These can get out of sync when the handler is stopped and restarted */ - /* while the signal_req is pending. */ - if (dispatched_signum == handle->signum) - handle->signal_cb(handle, dispatched_signum); - - if (handle->flags & UV__HANDLE_CLOSING) { - /* When it is closing, it must be stopped at this point. */ - assert(handle->signum == 0); - uv_want_endgame(loop, (uv_handle_t*) handle); - } -} - - -void uv_signal_close(uv_loop_t* loop, uv_signal_t* handle) { - uv_signal_stop(handle); - uv__handle_closing(handle); - - if (handle->pending_signum == 0) { - uv_want_endgame(loop, (uv_handle_t*) handle); - } -} - - -void uv_signal_endgame(uv_loop_t* loop, uv_signal_t* handle) { - assert(handle->flags & UV__HANDLE_CLOSING); - assert(!(handle->flags & UV_HANDLE_CLOSED)); - - assert(handle->signum == 0); - assert(handle->pending_signum == 0); - - handle->flags |= UV_HANDLE_CLOSED; - - uv__handle_close(handle); -} diff --git a/vendor/libuv/src/win/snprintf.c b/vendor/libuv/src/win/snprintf.c deleted file mode 100644 index 776c0e392..000000000 --- a/vendor/libuv/src/win/snprintf.c +++ /dev/null @@ -1,42 +0,0 @@ -/* Copyright the libuv project contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#if defined(_MSC_VER) && _MSC_VER < 1900 - -#include -#include - -/* Emulate snprintf() on MSVC<2015, _snprintf() doesn't zero-terminate the buffer - * on overflow... - */ -int snprintf(char* buf, size_t len, const char* fmt, ...) { - int n; - va_list ap; - va_start(ap, fmt); - - n = _vscprintf(fmt, ap); - vsnprintf_s(buf, len, _TRUNCATE, fmt, ap); - - va_end(ap); - return n; -} - -#endif diff --git a/vendor/libuv/src/win/stream-inl.h b/vendor/libuv/src/win/stream-inl.h deleted file mode 100644 index b7a3c1195..000000000 --- a/vendor/libuv/src/win/stream-inl.h +++ /dev/null @@ -1,56 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef UV_WIN_STREAM_INL_H_ -#define UV_WIN_STREAM_INL_H_ - -#include - -#include "uv.h" -#include "internal.h" -#include "handle-inl.h" -#include "req-inl.h" - - -INLINE static void uv_stream_init(uv_loop_t* loop, - uv_stream_t* handle, - uv_handle_type type) { - uv__handle_init(loop, (uv_handle_t*) handle, type); - handle->write_queue_size = 0; - handle->activecnt = 0; -} - - -INLINE static void uv_connection_init(uv_stream_t* handle) { - handle->flags |= UV_HANDLE_CONNECTION; - handle->stream.conn.write_reqs_pending = 0; - - uv_req_init(handle->loop, (uv_req_t*) &(handle->read_req)); - handle->read_req.event_handle = NULL; - handle->read_req.wait_handle = INVALID_HANDLE_VALUE; - handle->read_req.type = UV_READ; - handle->read_req.data = handle; - - handle->stream.conn.shutdown_req = NULL; -} - - -#endif /* UV_WIN_STREAM_INL_H_ */ diff --git a/vendor/libuv/src/win/stream.c b/vendor/libuv/src/win/stream.c deleted file mode 100644 index a2466e5e9..000000000 --- a/vendor/libuv/src/win/stream.c +++ /dev/null @@ -1,249 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include - -#include "uv.h" -#include "internal.h" -#include "handle-inl.h" -#include "req-inl.h" - - -int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb) { - int err; - - err = ERROR_INVALID_PARAMETER; - switch (stream->type) { - case UV_TCP: - err = uv_tcp_listen((uv_tcp_t*)stream, backlog, cb); - break; - case UV_NAMED_PIPE: - err = uv_pipe_listen((uv_pipe_t*)stream, backlog, cb); - break; - default: - assert(0); - } - - return uv_translate_sys_error(err); -} - - -int uv_accept(uv_stream_t* server, uv_stream_t* client) { - int err; - - err = ERROR_INVALID_PARAMETER; - switch (server->type) { - case UV_TCP: - err = uv_tcp_accept((uv_tcp_t*)server, (uv_tcp_t*)client); - break; - case UV_NAMED_PIPE: - err = uv_pipe_accept((uv_pipe_t*)server, client); - break; - default: - assert(0); - } - - return uv_translate_sys_error(err); -} - - -int uv_read_start(uv_stream_t* handle, uv_alloc_cb alloc_cb, - uv_read_cb read_cb) { - int err; - - if (handle->flags & UV_HANDLE_READING) { - return UV_EALREADY; - } - - if (!(handle->flags & UV_HANDLE_READABLE)) { - return UV_ENOTCONN; - } - - err = ERROR_INVALID_PARAMETER; - switch (handle->type) { - case UV_TCP: - err = uv_tcp_read_start((uv_tcp_t*)handle, alloc_cb, read_cb); - break; - case UV_NAMED_PIPE: - err = uv_pipe_read_start((uv_pipe_t*)handle, alloc_cb, read_cb); - break; - case UV_TTY: - err = uv_tty_read_start((uv_tty_t*) handle, alloc_cb, read_cb); - break; - default: - assert(0); - } - - return uv_translate_sys_error(err); -} - - -int uv_read_stop(uv_stream_t* handle) { - int err; - - if (!(handle->flags & UV_HANDLE_READING)) - return 0; - - err = 0; - if (handle->type == UV_TTY) { - err = uv_tty_read_stop((uv_tty_t*) handle); - } else { - if (handle->type == UV_NAMED_PIPE) { - uv__pipe_stop_read((uv_pipe_t*) handle); - } else { - handle->flags &= ~UV_HANDLE_READING; - } - DECREASE_ACTIVE_COUNT(handle->loop, handle); - } - - return uv_translate_sys_error(err); -} - - -int uv_write(uv_write_t* req, - uv_stream_t* handle, - const uv_buf_t bufs[], - unsigned int nbufs, - uv_write_cb cb) { - uv_loop_t* loop = handle->loop; - int err; - - if (!(handle->flags & UV_HANDLE_WRITABLE)) { - return UV_EPIPE; - } - - err = ERROR_INVALID_PARAMETER; - switch (handle->type) { - case UV_TCP: - err = uv_tcp_write(loop, req, (uv_tcp_t*) handle, bufs, nbufs, cb); - break; - case UV_NAMED_PIPE: - err = uv_pipe_write(loop, req, (uv_pipe_t*) handle, bufs, nbufs, cb); - break; - case UV_TTY: - err = uv_tty_write(loop, req, (uv_tty_t*) handle, bufs, nbufs, cb); - break; - default: - assert(0); - } - - return uv_translate_sys_error(err); -} - - -int uv_write2(uv_write_t* req, - uv_stream_t* handle, - const uv_buf_t bufs[], - unsigned int nbufs, - uv_stream_t* send_handle, - uv_write_cb cb) { - uv_loop_t* loop = handle->loop; - int err; - - if (!(handle->flags & UV_HANDLE_WRITABLE)) { - return UV_EPIPE; - } - - err = ERROR_INVALID_PARAMETER; - switch (handle->type) { - case UV_NAMED_PIPE: - err = uv_pipe_write2(loop, - req, - (uv_pipe_t*) handle, - bufs, - nbufs, - send_handle, - cb); - break; - default: - assert(0); - } - - return uv_translate_sys_error(err); -} - - -int uv_try_write(uv_stream_t* stream, - const uv_buf_t bufs[], - unsigned int nbufs) { - if (stream->flags & UV__HANDLE_CLOSING) - return UV_EBADF; - if (!(stream->flags & UV_HANDLE_WRITABLE)) - return UV_EPIPE; - - switch (stream->type) { - case UV_TCP: - return uv__tcp_try_write((uv_tcp_t*) stream, bufs, nbufs); - case UV_TTY: - return uv__tty_try_write((uv_tty_t*) stream, bufs, nbufs); - case UV_NAMED_PIPE: - return UV_EAGAIN; - default: - assert(0); - return UV_ENOSYS; - } -} - - -int uv_shutdown(uv_shutdown_t* req, uv_stream_t* handle, uv_shutdown_cb cb) { - uv_loop_t* loop = handle->loop; - - if (!(handle->flags & UV_HANDLE_WRITABLE)) { - return UV_EPIPE; - } - - uv_req_init(loop, (uv_req_t*) req); - req->type = UV_SHUTDOWN; - req->handle = handle; - req->cb = cb; - - handle->flags &= ~UV_HANDLE_WRITABLE; - handle->stream.conn.shutdown_req = req; - handle->reqs_pending++; - REGISTER_HANDLE_REQ(loop, handle, req); - - uv_want_endgame(loop, (uv_handle_t*)handle); - - return 0; -} - - -int uv_is_readable(const uv_stream_t* handle) { - return !!(handle->flags & UV_HANDLE_READABLE); -} - - -int uv_is_writable(const uv_stream_t* handle) { - return !!(handle->flags & UV_HANDLE_WRITABLE); -} - - -int uv_stream_set_blocking(uv_stream_t* handle, int blocking) { - if (handle->type != UV_NAMED_PIPE) - return UV_EINVAL; - - if (blocking != 0) - handle->flags |= UV_HANDLE_BLOCKING_WRITES; - else - handle->flags &= ~UV_HANDLE_BLOCKING_WRITES; - - return 0; -} diff --git a/vendor/libuv/src/win/tcp.c b/vendor/libuv/src/win/tcp.c deleted file mode 100644 index 0709696ff..000000000 --- a/vendor/libuv/src/win/tcp.c +++ /dev/null @@ -1,1510 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include -#include - -#include "uv.h" -#include "internal.h" -#include "handle-inl.h" -#include "stream-inl.h" -#include "req-inl.h" - - -/* - * Threshold of active tcp streams for which to preallocate tcp read buffers. - * (Due to node slab allocator performing poorly under this pattern, - * the optimization is temporarily disabled (threshold=0). This will be - * revisited once node allocator is improved.) - */ -const unsigned int uv_active_tcp_streams_threshold = 0; - -/* - * Number of simultaneous pending AcceptEx calls. - */ -const unsigned int uv_simultaneous_server_accepts = 32; - -/* A zero-size buffer for use by uv_tcp_read */ -static char uv_zero_[] = ""; - -static int uv__tcp_nodelay(uv_tcp_t* handle, SOCKET socket, int enable) { - if (setsockopt(socket, - IPPROTO_TCP, - TCP_NODELAY, - (const char*)&enable, - sizeof enable) == -1) { - return WSAGetLastError(); - } - return 0; -} - - -static int uv__tcp_keepalive(uv_tcp_t* handle, SOCKET socket, int enable, unsigned int delay) { - if (setsockopt(socket, - SOL_SOCKET, - SO_KEEPALIVE, - (const char*)&enable, - sizeof enable) == -1) { - return WSAGetLastError(); - } - - if (enable && setsockopt(socket, - IPPROTO_TCP, - TCP_KEEPALIVE, - (const char*)&delay, - sizeof delay) == -1) { - return WSAGetLastError(); - } - - return 0; -} - - -static int uv_tcp_set_socket(uv_loop_t* loop, - uv_tcp_t* handle, - SOCKET socket, - int family, - int imported) { - DWORD yes = 1; - int non_ifs_lsp; - int err; - - if (handle->socket != INVALID_SOCKET) - return UV_EBUSY; - - /* Set the socket to nonblocking mode */ - if (ioctlsocket(socket, FIONBIO, &yes) == SOCKET_ERROR) { - return WSAGetLastError(); - } - - /* Make the socket non-inheritable */ - if (!SetHandleInformation((HANDLE) socket, HANDLE_FLAG_INHERIT, 0)) - return GetLastError(); - - /* Associate it with the I/O completion port. */ - /* Use uv_handle_t pointer as completion key. */ - if (CreateIoCompletionPort((HANDLE)socket, - loop->iocp, - (ULONG_PTR)socket, - 0) == NULL) { - if (imported) { - handle->flags |= UV_HANDLE_EMULATE_IOCP; - } else { - return GetLastError(); - } - } - - if (family == AF_INET6) { - non_ifs_lsp = uv_tcp_non_ifs_lsp_ipv6; - } else { - non_ifs_lsp = uv_tcp_non_ifs_lsp_ipv4; - } - - if (pSetFileCompletionNotificationModes && - !(handle->flags & UV_HANDLE_EMULATE_IOCP) && !non_ifs_lsp) { - if (pSetFileCompletionNotificationModes((HANDLE) socket, - FILE_SKIP_SET_EVENT_ON_HANDLE | - FILE_SKIP_COMPLETION_PORT_ON_SUCCESS)) { - handle->flags |= UV_HANDLE_SYNC_BYPASS_IOCP; - } else if (GetLastError() != ERROR_INVALID_FUNCTION) { - return GetLastError(); - } - } - - if (handle->flags & UV_HANDLE_TCP_NODELAY) { - err = uv__tcp_nodelay(handle, socket, 1); - if (err) - return err; - } - - /* TODO: Use stored delay. */ - if (handle->flags & UV_HANDLE_TCP_KEEPALIVE) { - err = uv__tcp_keepalive(handle, socket, 1, 60); - if (err) - return err; - } - - handle->socket = socket; - - if (family == AF_INET6) { - handle->flags |= UV_HANDLE_IPV6; - } else { - assert(!(handle->flags & UV_HANDLE_IPV6)); - } - - return 0; -} - - -int uv_tcp_init_ex(uv_loop_t* loop, uv_tcp_t* handle, unsigned int flags) { - int domain; - - /* Use the lower 8 bits for the domain */ - domain = flags & 0xFF; - if (domain != AF_INET && domain != AF_INET6 && domain != AF_UNSPEC) - return UV_EINVAL; - - if (flags & ~0xFF) - return UV_EINVAL; - - uv_stream_init(loop, (uv_stream_t*) handle, UV_TCP); - handle->tcp.serv.accept_reqs = NULL; - handle->tcp.serv.pending_accepts = NULL; - handle->socket = INVALID_SOCKET; - handle->reqs_pending = 0; - handle->tcp.serv.func_acceptex = NULL; - handle->tcp.conn.func_connectex = NULL; - handle->tcp.serv.processed_accepts = 0; - handle->delayed_error = 0; - - /* If anything fails beyond this point we need to remove the handle from - * the handle queue, since it was added by uv__handle_init in uv_stream_init. - */ - - if (domain != AF_UNSPEC) { - SOCKET sock; - DWORD err; - - sock = socket(domain, SOCK_STREAM, 0); - if (sock == INVALID_SOCKET) { - err = WSAGetLastError(); - QUEUE_REMOVE(&handle->handle_queue); - return uv_translate_sys_error(err); - } - - err = uv_tcp_set_socket(handle->loop, handle, sock, domain, 0); - if (err) { - closesocket(sock); - QUEUE_REMOVE(&handle->handle_queue); - return uv_translate_sys_error(err); - } - - } - - return 0; -} - - -int uv_tcp_init(uv_loop_t* loop, uv_tcp_t* handle) { - return uv_tcp_init_ex(loop, handle, AF_UNSPEC); -} - - -void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle) { - int err; - unsigned int i; - uv_tcp_accept_t* req; - - if (handle->flags & UV_HANDLE_CONNECTION && - handle->stream.conn.shutdown_req != NULL && - handle->stream.conn.write_reqs_pending == 0) { - - UNREGISTER_HANDLE_REQ(loop, handle, handle->stream.conn.shutdown_req); - - err = 0; - if (handle->flags & UV__HANDLE_CLOSING) { - err = ERROR_OPERATION_ABORTED; - } else if (shutdown(handle->socket, SD_SEND) == SOCKET_ERROR) { - err = WSAGetLastError(); - } - - if (handle->stream.conn.shutdown_req->cb) { - handle->stream.conn.shutdown_req->cb(handle->stream.conn.shutdown_req, - uv_translate_sys_error(err)); - } - - handle->stream.conn.shutdown_req = NULL; - DECREASE_PENDING_REQ_COUNT(handle); - return; - } - - if (handle->flags & UV__HANDLE_CLOSING && - handle->reqs_pending == 0) { - assert(!(handle->flags & UV_HANDLE_CLOSED)); - - if (!(handle->flags & UV_HANDLE_TCP_SOCKET_CLOSED)) { - closesocket(handle->socket); - handle->socket = INVALID_SOCKET; - handle->flags |= UV_HANDLE_TCP_SOCKET_CLOSED; - } - - if (!(handle->flags & UV_HANDLE_CONNECTION) && handle->tcp.serv.accept_reqs) { - if (handle->flags & UV_HANDLE_EMULATE_IOCP) { - for (i = 0; i < uv_simultaneous_server_accepts; i++) { - req = &handle->tcp.serv.accept_reqs[i]; - if (req->wait_handle != INVALID_HANDLE_VALUE) { - UnregisterWait(req->wait_handle); - req->wait_handle = INVALID_HANDLE_VALUE; - } - if (req->event_handle) { - CloseHandle(req->event_handle); - req->event_handle = NULL; - } - } - } - - uv__free(handle->tcp.serv.accept_reqs); - handle->tcp.serv.accept_reqs = NULL; - } - - if (handle->flags & UV_HANDLE_CONNECTION && - handle->flags & UV_HANDLE_EMULATE_IOCP) { - if (handle->read_req.wait_handle != INVALID_HANDLE_VALUE) { - UnregisterWait(handle->read_req.wait_handle); - handle->read_req.wait_handle = INVALID_HANDLE_VALUE; - } - if (handle->read_req.event_handle) { - CloseHandle(handle->read_req.event_handle); - handle->read_req.event_handle = NULL; - } - } - - uv__handle_close(handle); - loop->active_tcp_streams--; - } -} - - -/* Unlike on Unix, here we don't set SO_REUSEADDR, because it doesn't just - * allow binding to addresses that are in use by sockets in TIME_WAIT, it - * effectively allows 'stealing' a port which is in use by another application. - * - * SO_EXCLUSIVEADDRUSE is also not good here because it does check all sockets, - * regardless of state, so we'd get an error even if the port is in use by a - * socket in TIME_WAIT state. - * - * See issue #1360. - * - */ -static int uv_tcp_try_bind(uv_tcp_t* handle, - const struct sockaddr* addr, - unsigned int addrlen, - unsigned int flags) { - DWORD err; - int r; - - if (handle->socket == INVALID_SOCKET) { - SOCKET sock; - - /* Cannot set IPv6-only mode on non-IPv6 socket. */ - if ((flags & UV_TCP_IPV6ONLY) && addr->sa_family != AF_INET6) - return ERROR_INVALID_PARAMETER; - - sock = socket(addr->sa_family, SOCK_STREAM, 0); - if (sock == INVALID_SOCKET) { - return WSAGetLastError(); - } - - err = uv_tcp_set_socket(handle->loop, handle, sock, addr->sa_family, 0); - if (err) { - closesocket(sock); - return err; - } - } - -#ifdef IPV6_V6ONLY - if (addr->sa_family == AF_INET6) { - int on; - - on = (flags & UV_TCP_IPV6ONLY) != 0; - - /* TODO: how to handle errors? This may fail if there is no ipv4 stack */ - /* available, or when run on XP/2003 which have no support for dualstack */ - /* sockets. For now we're silently ignoring the error. */ - setsockopt(handle->socket, - IPPROTO_IPV6, - IPV6_V6ONLY, - (const char*)&on, - sizeof on); - } -#endif - - r = bind(handle->socket, addr, addrlen); - - if (r == SOCKET_ERROR) { - err = WSAGetLastError(); - if (err == WSAEADDRINUSE) { - /* Some errors are not to be reported until connect() or listen() */ - handle->delayed_error = err; - } else { - return err; - } - } - - handle->flags |= UV_HANDLE_BOUND; - - return 0; -} - - -static void CALLBACK post_completion(void* context, BOOLEAN timed_out) { - uv_req_t* req; - uv_tcp_t* handle; - - req = (uv_req_t*) context; - assert(req != NULL); - handle = (uv_tcp_t*)req->data; - assert(handle != NULL); - assert(!timed_out); - - if (!PostQueuedCompletionStatus(handle->loop->iocp, - req->u.io.overlapped.InternalHigh, - 0, - &req->u.io.overlapped)) { - uv_fatal_error(GetLastError(), "PostQueuedCompletionStatus"); - } -} - - -static void CALLBACK post_write_completion(void* context, BOOLEAN timed_out) { - uv_write_t* req; - uv_tcp_t* handle; - - req = (uv_write_t*) context; - assert(req != NULL); - handle = (uv_tcp_t*)req->handle; - assert(handle != NULL); - assert(!timed_out); - - if (!PostQueuedCompletionStatus(handle->loop->iocp, - req->u.io.overlapped.InternalHigh, - 0, - &req->u.io.overlapped)) { - uv_fatal_error(GetLastError(), "PostQueuedCompletionStatus"); - } -} - - -static void uv_tcp_queue_accept(uv_tcp_t* handle, uv_tcp_accept_t* req) { - uv_loop_t* loop = handle->loop; - BOOL success; - DWORD bytes; - SOCKET accept_socket; - short family; - - assert(handle->flags & UV_HANDLE_LISTENING); - assert(req->accept_socket == INVALID_SOCKET); - - /* choose family and extension function */ - if (handle->flags & UV_HANDLE_IPV6) { - family = AF_INET6; - } else { - family = AF_INET; - } - - /* Open a socket for the accepted connection. */ - accept_socket = socket(family, SOCK_STREAM, 0); - if (accept_socket == INVALID_SOCKET) { - SET_REQ_ERROR(req, WSAGetLastError()); - uv_insert_pending_req(loop, (uv_req_t*)req); - handle->reqs_pending++; - return; - } - - /* Make the socket non-inheritable */ - if (!SetHandleInformation((HANDLE) accept_socket, HANDLE_FLAG_INHERIT, 0)) { - SET_REQ_ERROR(req, GetLastError()); - uv_insert_pending_req(loop, (uv_req_t*)req); - handle->reqs_pending++; - closesocket(accept_socket); - return; - } - - /* Prepare the overlapped structure. */ - memset(&(req->u.io.overlapped), 0, sizeof(req->u.io.overlapped)); - if (handle->flags & UV_HANDLE_EMULATE_IOCP) { - req->u.io.overlapped.hEvent = (HANDLE) ((ULONG_PTR) req->event_handle | 1); - } - - success = handle->tcp.serv.func_acceptex(handle->socket, - accept_socket, - (void*)req->accept_buffer, - 0, - sizeof(struct sockaddr_storage), - sizeof(struct sockaddr_storage), - &bytes, - &req->u.io.overlapped); - - if (UV_SUCCEEDED_WITHOUT_IOCP(success)) { - /* Process the req without IOCP. */ - req->accept_socket = accept_socket; - handle->reqs_pending++; - uv_insert_pending_req(loop, (uv_req_t*)req); - } else if (UV_SUCCEEDED_WITH_IOCP(success)) { - /* The req will be processed with IOCP. */ - req->accept_socket = accept_socket; - handle->reqs_pending++; - if (handle->flags & UV_HANDLE_EMULATE_IOCP && - req->wait_handle == INVALID_HANDLE_VALUE && - !RegisterWaitForSingleObject(&req->wait_handle, - req->event_handle, post_completion, (void*) req, - INFINITE, WT_EXECUTEINWAITTHREAD)) { - SET_REQ_ERROR(req, GetLastError()); - uv_insert_pending_req(loop, (uv_req_t*)req); - handle->reqs_pending++; - return; - } - } else { - /* Make this req pending reporting an error. */ - SET_REQ_ERROR(req, WSAGetLastError()); - uv_insert_pending_req(loop, (uv_req_t*)req); - handle->reqs_pending++; - /* Destroy the preallocated client socket. */ - closesocket(accept_socket); - /* Destroy the event handle */ - if (handle->flags & UV_HANDLE_EMULATE_IOCP) { - CloseHandle(req->u.io.overlapped.hEvent); - req->event_handle = NULL; - } - } -} - - -static void uv_tcp_queue_read(uv_loop_t* loop, uv_tcp_t* handle) { - uv_read_t* req; - uv_buf_t buf; - int result; - DWORD bytes, flags; - - assert(handle->flags & UV_HANDLE_READING); - assert(!(handle->flags & UV_HANDLE_READ_PENDING)); - - req = &handle->read_req; - memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped)); - - /* - * Preallocate a read buffer if the number of active streams is below - * the threshold. - */ - if (loop->active_tcp_streams < uv_active_tcp_streams_threshold) { - handle->flags &= ~UV_HANDLE_ZERO_READ; - handle->tcp.conn.read_buffer = uv_buf_init(NULL, 0); - handle->alloc_cb((uv_handle_t*) handle, 65536, &handle->tcp.conn.read_buffer); - if (handle->tcp.conn.read_buffer.base == NULL || - handle->tcp.conn.read_buffer.len == 0) { - handle->read_cb((uv_stream_t*) handle, UV_ENOBUFS, &handle->tcp.conn.read_buffer); - return; - } - assert(handle->tcp.conn.read_buffer.base != NULL); - buf = handle->tcp.conn.read_buffer; - } else { - handle->flags |= UV_HANDLE_ZERO_READ; - buf.base = (char*) &uv_zero_; - buf.len = 0; - } - - /* Prepare the overlapped structure. */ - memset(&(req->u.io.overlapped), 0, sizeof(req->u.io.overlapped)); - if (handle->flags & UV_HANDLE_EMULATE_IOCP) { - assert(req->event_handle); - req->u.io.overlapped.hEvent = (HANDLE) ((ULONG_PTR) req->event_handle | 1); - } - - flags = 0; - result = WSARecv(handle->socket, - (WSABUF*)&buf, - 1, - &bytes, - &flags, - &req->u.io.overlapped, - NULL); - - if (UV_SUCCEEDED_WITHOUT_IOCP(result == 0)) { - /* Process the req without IOCP. */ - handle->flags |= UV_HANDLE_READ_PENDING; - req->u.io.overlapped.InternalHigh = bytes; - handle->reqs_pending++; - uv_insert_pending_req(loop, (uv_req_t*)req); - } else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) { - /* The req will be processed with IOCP. */ - handle->flags |= UV_HANDLE_READ_PENDING; - handle->reqs_pending++; - if (handle->flags & UV_HANDLE_EMULATE_IOCP && - req->wait_handle == INVALID_HANDLE_VALUE && - !RegisterWaitForSingleObject(&req->wait_handle, - req->event_handle, post_completion, (void*) req, - INFINITE, WT_EXECUTEINWAITTHREAD)) { - SET_REQ_ERROR(req, GetLastError()); - uv_insert_pending_req(loop, (uv_req_t*)req); - } - } else { - /* Make this req pending reporting an error. */ - SET_REQ_ERROR(req, WSAGetLastError()); - uv_insert_pending_req(loop, (uv_req_t*)req); - handle->reqs_pending++; - } -} - - -int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) { - uv_loop_t* loop = handle->loop; - unsigned int i, simultaneous_accepts; - uv_tcp_accept_t* req; - int err; - - assert(backlog > 0); - - if (handle->flags & UV_HANDLE_LISTENING) { - handle->stream.serv.connection_cb = cb; - } - - if (handle->flags & UV_HANDLE_READING) { - return WSAEISCONN; - } - - if (handle->delayed_error) { - return handle->delayed_error; - } - - if (!(handle->flags & UV_HANDLE_BOUND)) { - err = uv_tcp_try_bind(handle, - (const struct sockaddr*) &uv_addr_ip4_any_, - sizeof(uv_addr_ip4_any_), - 0); - if (err) - return err; - if (handle->delayed_error) - return handle->delayed_error; - } - - if (!handle->tcp.serv.func_acceptex) { - if (!uv_get_acceptex_function(handle->socket, &handle->tcp.serv.func_acceptex)) { - return WSAEAFNOSUPPORT; - } - } - - if (!(handle->flags & UV_HANDLE_SHARED_TCP_SOCKET) && - listen(handle->socket, backlog) == SOCKET_ERROR) { - return WSAGetLastError(); - } - - handle->flags |= UV_HANDLE_LISTENING; - handle->stream.serv.connection_cb = cb; - INCREASE_ACTIVE_COUNT(loop, handle); - - simultaneous_accepts = handle->flags & UV_HANDLE_TCP_SINGLE_ACCEPT ? 1 - : uv_simultaneous_server_accepts; - - if(!handle->tcp.serv.accept_reqs) { - handle->tcp.serv.accept_reqs = (uv_tcp_accept_t*) - uv__malloc(uv_simultaneous_server_accepts * sizeof(uv_tcp_accept_t)); - if (!handle->tcp.serv.accept_reqs) { - uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc"); - } - - for (i = 0; i < simultaneous_accepts; i++) { - req = &handle->tcp.serv.accept_reqs[i]; - uv_req_init(loop, (uv_req_t*)req); - req->type = UV_ACCEPT; - req->accept_socket = INVALID_SOCKET; - req->data = handle; - - req->wait_handle = INVALID_HANDLE_VALUE; - if (handle->flags & UV_HANDLE_EMULATE_IOCP) { - req->event_handle = CreateEvent(NULL, 0, 0, NULL); - if (!req->event_handle) { - uv_fatal_error(GetLastError(), "CreateEvent"); - } - } else { - req->event_handle = NULL; - } - - uv_tcp_queue_accept(handle, req); - } - - /* Initialize other unused requests too, because uv_tcp_endgame */ - /* doesn't know how how many requests were initialized, so it will */ - /* try to clean up {uv_simultaneous_server_accepts} requests. */ - for (i = simultaneous_accepts; i < uv_simultaneous_server_accepts; i++) { - req = &handle->tcp.serv.accept_reqs[i]; - uv_req_init(loop, (uv_req_t*) req); - req->type = UV_ACCEPT; - req->accept_socket = INVALID_SOCKET; - req->data = handle; - req->wait_handle = INVALID_HANDLE_VALUE; - req->event_handle = NULL; - } - } - - return 0; -} - - -int uv_tcp_accept(uv_tcp_t* server, uv_tcp_t* client) { - uv_loop_t* loop = server->loop; - int err = 0; - int family; - - uv_tcp_accept_t* req = server->tcp.serv.pending_accepts; - - if (!req) { - /* No valid connections found, so we error out. */ - return WSAEWOULDBLOCK; - } - - if (req->accept_socket == INVALID_SOCKET) { - return WSAENOTCONN; - } - - if (server->flags & UV_HANDLE_IPV6) { - family = AF_INET6; - } else { - family = AF_INET; - } - - err = uv_tcp_set_socket(client->loop, - client, - req->accept_socket, - family, - 0); - if (err) { - closesocket(req->accept_socket); - } else { - uv_connection_init((uv_stream_t*) client); - /* AcceptEx() implicitly binds the accepted socket. */ - client->flags |= UV_HANDLE_BOUND | UV_HANDLE_READABLE | UV_HANDLE_WRITABLE; - } - - /* Prepare the req to pick up a new connection */ - server->tcp.serv.pending_accepts = req->next_pending; - req->next_pending = NULL; - req->accept_socket = INVALID_SOCKET; - - if (!(server->flags & UV__HANDLE_CLOSING)) { - /* Check if we're in a middle of changing the number of pending accepts. */ - if (!(server->flags & UV_HANDLE_TCP_ACCEPT_STATE_CHANGING)) { - uv_tcp_queue_accept(server, req); - } else { - /* We better be switching to a single pending accept. */ - assert(server->flags & UV_HANDLE_TCP_SINGLE_ACCEPT); - - server->tcp.serv.processed_accepts++; - - if (server->tcp.serv.processed_accepts >= uv_simultaneous_server_accepts) { - server->tcp.serv.processed_accepts = 0; - /* - * All previously queued accept requests are now processed. - * We now switch to queueing just a single accept. - */ - uv_tcp_queue_accept(server, &server->tcp.serv.accept_reqs[0]); - server->flags &= ~UV_HANDLE_TCP_ACCEPT_STATE_CHANGING; - server->flags |= UV_HANDLE_TCP_SINGLE_ACCEPT; - } - } - } - - loop->active_tcp_streams++; - - return err; -} - - -int uv_tcp_read_start(uv_tcp_t* handle, uv_alloc_cb alloc_cb, - uv_read_cb read_cb) { - uv_loop_t* loop = handle->loop; - - handle->flags |= UV_HANDLE_READING; - handle->read_cb = read_cb; - handle->alloc_cb = alloc_cb; - INCREASE_ACTIVE_COUNT(loop, handle); - - /* If reading was stopped and then started again, there could still be a */ - /* read request pending. */ - if (!(handle->flags & UV_HANDLE_READ_PENDING)) { - if (handle->flags & UV_HANDLE_EMULATE_IOCP && - !handle->read_req.event_handle) { - handle->read_req.event_handle = CreateEvent(NULL, 0, 0, NULL); - if (!handle->read_req.event_handle) { - uv_fatal_error(GetLastError(), "CreateEvent"); - } - } - uv_tcp_queue_read(loop, handle); - } - - return 0; -} - - -static int uv_tcp_try_connect(uv_connect_t* req, - uv_tcp_t* handle, - const struct sockaddr* addr, - unsigned int addrlen, - uv_connect_cb cb) { - uv_loop_t* loop = handle->loop; - const struct sockaddr* bind_addr; - BOOL success; - DWORD bytes; - int err; - - if (handle->delayed_error) { - return handle->delayed_error; - } - - if (!(handle->flags & UV_HANDLE_BOUND)) { - if (addrlen == sizeof(uv_addr_ip4_any_)) { - bind_addr = (const struct sockaddr*) &uv_addr_ip4_any_; - } else if (addrlen == sizeof(uv_addr_ip6_any_)) { - bind_addr = (const struct sockaddr*) &uv_addr_ip6_any_; - } else { - abort(); - } - err = uv_tcp_try_bind(handle, bind_addr, addrlen, 0); - if (err) - return err; - if (handle->delayed_error) - return handle->delayed_error; - } - - if (!handle->tcp.conn.func_connectex) { - if (!uv_get_connectex_function(handle->socket, &handle->tcp.conn.func_connectex)) { - return WSAEAFNOSUPPORT; - } - } - - uv_req_init(loop, (uv_req_t*) req); - req->type = UV_CONNECT; - req->handle = (uv_stream_t*) handle; - req->cb = cb; - memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped)); - - success = handle->tcp.conn.func_connectex(handle->socket, - addr, - addrlen, - NULL, - 0, - &bytes, - &req->u.io.overlapped); - - if (UV_SUCCEEDED_WITHOUT_IOCP(success)) { - /* Process the req without IOCP. */ - handle->reqs_pending++; - REGISTER_HANDLE_REQ(loop, handle, req); - uv_insert_pending_req(loop, (uv_req_t*)req); - } else if (UV_SUCCEEDED_WITH_IOCP(success)) { - /* The req will be processed with IOCP. */ - handle->reqs_pending++; - REGISTER_HANDLE_REQ(loop, handle, req); - } else { - return WSAGetLastError(); - } - - return 0; -} - - -int uv_tcp_getsockname(const uv_tcp_t* handle, - struct sockaddr* name, - int* namelen) { - int result; - - if (handle->socket == INVALID_SOCKET) { - return UV_EINVAL; - } - - if (handle->delayed_error) { - return uv_translate_sys_error(handle->delayed_error); - } - - result = getsockname(handle->socket, name, namelen); - if (result != 0) { - return uv_translate_sys_error(WSAGetLastError()); - } - - return 0; -} - - -int uv_tcp_getpeername(const uv_tcp_t* handle, - struct sockaddr* name, - int* namelen) { - int result; - - if (handle->socket == INVALID_SOCKET) { - return UV_EINVAL; - } - - if (handle->delayed_error) { - return uv_translate_sys_error(handle->delayed_error); - } - - result = getpeername(handle->socket, name, namelen); - if (result != 0) { - return uv_translate_sys_error(WSAGetLastError()); - } - - return 0; -} - - -int uv_tcp_write(uv_loop_t* loop, - uv_write_t* req, - uv_tcp_t* handle, - const uv_buf_t bufs[], - unsigned int nbufs, - uv_write_cb cb) { - int result; - DWORD bytes; - - uv_req_init(loop, (uv_req_t*) req); - req->type = UV_WRITE; - req->handle = (uv_stream_t*) handle; - req->cb = cb; - - /* Prepare the overlapped structure. */ - memset(&(req->u.io.overlapped), 0, sizeof(req->u.io.overlapped)); - if (handle->flags & UV_HANDLE_EMULATE_IOCP) { - req->event_handle = CreateEvent(NULL, 0, 0, NULL); - if (!req->event_handle) { - uv_fatal_error(GetLastError(), "CreateEvent"); - } - req->u.io.overlapped.hEvent = (HANDLE) ((ULONG_PTR) req->event_handle | 1); - req->wait_handle = INVALID_HANDLE_VALUE; - } - - result = WSASend(handle->socket, - (WSABUF*) bufs, - nbufs, - &bytes, - 0, - &req->u.io.overlapped, - NULL); - - if (UV_SUCCEEDED_WITHOUT_IOCP(result == 0)) { - /* Request completed immediately. */ - req->u.io.queued_bytes = 0; - handle->reqs_pending++; - handle->stream.conn.write_reqs_pending++; - REGISTER_HANDLE_REQ(loop, handle, req); - uv_insert_pending_req(loop, (uv_req_t*) req); - } else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) { - /* Request queued by the kernel. */ - req->u.io.queued_bytes = uv__count_bufs(bufs, nbufs); - handle->reqs_pending++; - handle->stream.conn.write_reqs_pending++; - REGISTER_HANDLE_REQ(loop, handle, req); - handle->write_queue_size += req->u.io.queued_bytes; - if (handle->flags & UV_HANDLE_EMULATE_IOCP && - !RegisterWaitForSingleObject(&req->wait_handle, - req->event_handle, post_write_completion, (void*) req, - INFINITE, WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE)) { - SET_REQ_ERROR(req, GetLastError()); - uv_insert_pending_req(loop, (uv_req_t*)req); - } - } else { - /* Send failed due to an error, report it later */ - req->u.io.queued_bytes = 0; - handle->reqs_pending++; - handle->stream.conn.write_reqs_pending++; - REGISTER_HANDLE_REQ(loop, handle, req); - SET_REQ_ERROR(req, WSAGetLastError()); - uv_insert_pending_req(loop, (uv_req_t*) req); - } - - return 0; -} - - -int uv__tcp_try_write(uv_tcp_t* handle, - const uv_buf_t bufs[], - unsigned int nbufs) { - int result; - DWORD bytes; - - if (handle->stream.conn.write_reqs_pending > 0) - return UV_EAGAIN; - - result = WSASend(handle->socket, - (WSABUF*) bufs, - nbufs, - &bytes, - 0, - NULL, - NULL); - - if (result == SOCKET_ERROR) - return uv_translate_sys_error(WSAGetLastError()); - else - return bytes; -} - - -void uv_process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle, - uv_req_t* req) { - DWORD bytes, flags, err; - uv_buf_t buf; - - assert(handle->type == UV_TCP); - - handle->flags &= ~UV_HANDLE_READ_PENDING; - - if (!REQ_SUCCESS(req)) { - /* An error occurred doing the read. */ - if ((handle->flags & UV_HANDLE_READING) || - !(handle->flags & UV_HANDLE_ZERO_READ)) { - handle->flags &= ~UV_HANDLE_READING; - DECREASE_ACTIVE_COUNT(loop, handle); - buf = (handle->flags & UV_HANDLE_ZERO_READ) ? - uv_buf_init(NULL, 0) : handle->tcp.conn.read_buffer; - - err = GET_REQ_SOCK_ERROR(req); - - if (err == WSAECONNABORTED) { - /* - * Turn WSAECONNABORTED into UV_ECONNRESET to be consistent with Unix. - */ - err = WSAECONNRESET; - } - - handle->read_cb((uv_stream_t*)handle, - uv_translate_sys_error(err), - &buf); - } - } else { - if (!(handle->flags & UV_HANDLE_ZERO_READ)) { - /* The read was done with a non-zero buffer length. */ - if (req->u.io.overlapped.InternalHigh > 0) { - /* Successful read */ - handle->read_cb((uv_stream_t*)handle, - req->u.io.overlapped.InternalHigh, - &handle->tcp.conn.read_buffer); - /* Read again only if bytes == buf.len */ - if (req->u.io.overlapped.InternalHigh < handle->tcp.conn.read_buffer.len) { - goto done; - } - } else { - /* Connection closed */ - if (handle->flags & UV_HANDLE_READING) { - handle->flags &= ~UV_HANDLE_READING; - DECREASE_ACTIVE_COUNT(loop, handle); - } - handle->flags &= ~UV_HANDLE_READABLE; - - buf.base = 0; - buf.len = 0; - handle->read_cb((uv_stream_t*)handle, UV_EOF, &handle->tcp.conn.read_buffer); - goto done; - } - } - - /* Do nonblocking reads until the buffer is empty */ - while (handle->flags & UV_HANDLE_READING) { - buf = uv_buf_init(NULL, 0); - handle->alloc_cb((uv_handle_t*) handle, 65536, &buf); - if (buf.base == NULL || buf.len == 0) { - handle->read_cb((uv_stream_t*) handle, UV_ENOBUFS, &buf); - break; - } - assert(buf.base != NULL); - - flags = 0; - if (WSARecv(handle->socket, - (WSABUF*)&buf, - 1, - &bytes, - &flags, - NULL, - NULL) != SOCKET_ERROR) { - if (bytes > 0) { - /* Successful read */ - handle->read_cb((uv_stream_t*)handle, bytes, &buf); - /* Read again only if bytes == buf.len */ - if (bytes < buf.len) { - break; - } - } else { - /* Connection closed */ - handle->flags &= ~(UV_HANDLE_READING | UV_HANDLE_READABLE); - DECREASE_ACTIVE_COUNT(loop, handle); - - handle->read_cb((uv_stream_t*)handle, UV_EOF, &buf); - break; - } - } else { - err = WSAGetLastError(); - if (err == WSAEWOULDBLOCK) { - /* Read buffer was completely empty, report a 0-byte read. */ - handle->read_cb((uv_stream_t*)handle, 0, &buf); - } else { - /* Ouch! serious error. */ - handle->flags &= ~UV_HANDLE_READING; - DECREASE_ACTIVE_COUNT(loop, handle); - - if (err == WSAECONNABORTED) { - /* Turn WSAECONNABORTED into UV_ECONNRESET to be consistent with */ - /* Unix. */ - err = WSAECONNRESET; - } - - handle->read_cb((uv_stream_t*)handle, - uv_translate_sys_error(err), - &buf); - } - break; - } - } - -done: - /* Post another read if still reading and not closing. */ - if ((handle->flags & UV_HANDLE_READING) && - !(handle->flags & UV_HANDLE_READ_PENDING)) { - uv_tcp_queue_read(loop, handle); - } - } - - DECREASE_PENDING_REQ_COUNT(handle); -} - - -void uv_process_tcp_write_req(uv_loop_t* loop, uv_tcp_t* handle, - uv_write_t* req) { - int err; - - assert(handle->type == UV_TCP); - - assert(handle->write_queue_size >= req->u.io.queued_bytes); - handle->write_queue_size -= req->u.io.queued_bytes; - - UNREGISTER_HANDLE_REQ(loop, handle, req); - - if (handle->flags & UV_HANDLE_EMULATE_IOCP) { - if (req->wait_handle != INVALID_HANDLE_VALUE) { - UnregisterWait(req->wait_handle); - req->wait_handle = INVALID_HANDLE_VALUE; - } - if (req->event_handle) { - CloseHandle(req->event_handle); - req->event_handle = NULL; - } - } - - if (req->cb) { - err = uv_translate_sys_error(GET_REQ_SOCK_ERROR(req)); - if (err == UV_ECONNABORTED) { - /* use UV_ECANCELED for consistency with Unix */ - err = UV_ECANCELED; - } - req->cb(req, err); - } - - handle->stream.conn.write_reqs_pending--; - if (handle->stream.conn.shutdown_req != NULL && - handle->stream.conn.write_reqs_pending == 0) { - uv_want_endgame(loop, (uv_handle_t*)handle); - } - - DECREASE_PENDING_REQ_COUNT(handle); -} - - -void uv_process_tcp_accept_req(uv_loop_t* loop, uv_tcp_t* handle, - uv_req_t* raw_req) { - uv_tcp_accept_t* req = (uv_tcp_accept_t*) raw_req; - int err; - - assert(handle->type == UV_TCP); - - /* If handle->accepted_socket is not a valid socket, then */ - /* uv_queue_accept must have failed. This is a serious error. We stop */ - /* accepting connections and report this error to the connection */ - /* callback. */ - if (req->accept_socket == INVALID_SOCKET) { - if (handle->flags & UV_HANDLE_LISTENING) { - handle->flags &= ~UV_HANDLE_LISTENING; - DECREASE_ACTIVE_COUNT(loop, handle); - if (handle->stream.serv.connection_cb) { - err = GET_REQ_SOCK_ERROR(req); - handle->stream.serv.connection_cb((uv_stream_t*)handle, - uv_translate_sys_error(err)); - } - } - } else if (REQ_SUCCESS(req) && - setsockopt(req->accept_socket, - SOL_SOCKET, - SO_UPDATE_ACCEPT_CONTEXT, - (char*)&handle->socket, - sizeof(handle->socket)) == 0) { - req->next_pending = handle->tcp.serv.pending_accepts; - handle->tcp.serv.pending_accepts = req; - - /* Accept and SO_UPDATE_ACCEPT_CONTEXT were successful. */ - if (handle->stream.serv.connection_cb) { - handle->stream.serv.connection_cb((uv_stream_t*)handle, 0); - } - } else { - /* Error related to accepted socket is ignored because the server */ - /* socket may still be healthy. If the server socket is broken */ - /* uv_queue_accept will detect it. */ - closesocket(req->accept_socket); - req->accept_socket = INVALID_SOCKET; - if (handle->flags & UV_HANDLE_LISTENING) { - uv_tcp_queue_accept(handle, req); - } - } - - DECREASE_PENDING_REQ_COUNT(handle); -} - - -void uv_process_tcp_connect_req(uv_loop_t* loop, uv_tcp_t* handle, - uv_connect_t* req) { - int err; - - assert(handle->type == UV_TCP); - - UNREGISTER_HANDLE_REQ(loop, handle, req); - - err = 0; - if (REQ_SUCCESS(req)) { - if (setsockopt(handle->socket, - SOL_SOCKET, - SO_UPDATE_CONNECT_CONTEXT, - NULL, - 0) == 0) { - uv_connection_init((uv_stream_t*)handle); - handle->flags |= UV_HANDLE_READABLE | UV_HANDLE_WRITABLE; - loop->active_tcp_streams++; - } else { - err = WSAGetLastError(); - } - } else { - err = GET_REQ_SOCK_ERROR(req); - } - req->cb(req, uv_translate_sys_error(err)); - - DECREASE_PENDING_REQ_COUNT(handle); -} - - -int uv_tcp_import(uv_tcp_t* tcp, uv__ipc_socket_info_ex* socket_info_ex, - int tcp_connection) { - int err; - SOCKET socket = WSASocketW(FROM_PROTOCOL_INFO, - FROM_PROTOCOL_INFO, - FROM_PROTOCOL_INFO, - &socket_info_ex->socket_info, - 0, - WSA_FLAG_OVERLAPPED); - - if (socket == INVALID_SOCKET) { - return WSAGetLastError(); - } - - err = uv_tcp_set_socket(tcp->loop, - tcp, - socket, - socket_info_ex->socket_info.iAddressFamily, - 1); - if (err) { - closesocket(socket); - return err; - } - - if (tcp_connection) { - uv_connection_init((uv_stream_t*)tcp); - tcp->flags |= UV_HANDLE_READABLE | UV_HANDLE_WRITABLE; - } - - tcp->flags |= UV_HANDLE_BOUND; - tcp->flags |= UV_HANDLE_SHARED_TCP_SOCKET; - - tcp->delayed_error = socket_info_ex->delayed_error; - - tcp->loop->active_tcp_streams++; - return 0; -} - - -int uv_tcp_nodelay(uv_tcp_t* handle, int enable) { - int err; - - if (handle->socket != INVALID_SOCKET) { - err = uv__tcp_nodelay(handle, handle->socket, enable); - if (err) - return err; - } - - if (enable) { - handle->flags |= UV_HANDLE_TCP_NODELAY; - } else { - handle->flags &= ~UV_HANDLE_TCP_NODELAY; - } - - return 0; -} - - -int uv_tcp_keepalive(uv_tcp_t* handle, int enable, unsigned int delay) { - int err; - - if (handle->socket != INVALID_SOCKET) { - err = uv__tcp_keepalive(handle, handle->socket, enable, delay); - if (err) - return err; - } - - if (enable) { - handle->flags |= UV_HANDLE_TCP_KEEPALIVE; - } else { - handle->flags &= ~UV_HANDLE_TCP_KEEPALIVE; - } - - /* TODO: Store delay if handle->socket isn't created yet. */ - - return 0; -} - - -int uv_tcp_duplicate_socket(uv_tcp_t* handle, int pid, - LPWSAPROTOCOL_INFOW protocol_info) { - if (!(handle->flags & UV_HANDLE_CONNECTION)) { - /* - * We're about to share the socket with another process. Because - * this is a listening socket, we assume that the other process will - * be accepting connections on it. So, before sharing the socket - * with another process, we call listen here in the parent process. - */ - - if (!(handle->flags & UV_HANDLE_LISTENING)) { - if (!(handle->flags & UV_HANDLE_BOUND)) { - return ERROR_INVALID_PARAMETER; - } - - if (!(handle->delayed_error)) { - if (listen(handle->socket, SOMAXCONN) == SOCKET_ERROR) { - handle->delayed_error = WSAGetLastError(); - } - } - } - } - - if (WSADuplicateSocketW(handle->socket, pid, protocol_info)) { - return WSAGetLastError(); - } - - handle->flags |= UV_HANDLE_SHARED_TCP_SOCKET; - - return 0; -} - - -int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable) { - if (handle->flags & UV_HANDLE_CONNECTION) { - return UV_EINVAL; - } - - /* Check if we're already in the desired mode. */ - if ((enable && !(handle->flags & UV_HANDLE_TCP_SINGLE_ACCEPT)) || - (!enable && handle->flags & UV_HANDLE_TCP_SINGLE_ACCEPT)) { - return 0; - } - - /* Don't allow switching from single pending accept to many. */ - if (enable) { - return UV_ENOTSUP; - } - - /* Check if we're in a middle of changing the number of pending accepts. */ - if (handle->flags & UV_HANDLE_TCP_ACCEPT_STATE_CHANGING) { - return 0; - } - - handle->flags |= UV_HANDLE_TCP_SINGLE_ACCEPT; - - /* Flip the changing flag if we have already queued multiple accepts. */ - if (handle->flags & UV_HANDLE_LISTENING) { - handle->flags |= UV_HANDLE_TCP_ACCEPT_STATE_CHANGING; - } - - return 0; -} - - -static int uv_tcp_try_cancel_io(uv_tcp_t* tcp) { - SOCKET socket = tcp->socket; - int non_ifs_lsp; - - /* Check if we have any non-IFS LSPs stacked on top of TCP */ - non_ifs_lsp = (tcp->flags & UV_HANDLE_IPV6) ? uv_tcp_non_ifs_lsp_ipv6 : - uv_tcp_non_ifs_lsp_ipv4; - - /* If there are non-ifs LSPs then try to obtain a base handle for the */ - /* socket. This will always fail on Windows XP/3k. */ - if (non_ifs_lsp) { - DWORD bytes; - if (WSAIoctl(socket, - SIO_BASE_HANDLE, - NULL, - 0, - &socket, - sizeof socket, - &bytes, - NULL, - NULL) != 0) { - /* Failed. We can't do CancelIo. */ - return -1; - } - } - - assert(socket != 0 && socket != INVALID_SOCKET); - - if (!CancelIo((HANDLE) socket)) { - return GetLastError(); - } - - /* It worked. */ - return 0; -} - - -void uv_tcp_close(uv_loop_t* loop, uv_tcp_t* tcp) { - int close_socket = 1; - - if (tcp->flags & UV_HANDLE_READ_PENDING) { - /* In order for winsock to do a graceful close there must not be any */ - /* any pending reads, or the socket must be shut down for writing */ - if (!(tcp->flags & UV_HANDLE_SHARED_TCP_SOCKET)) { - /* Just do shutdown on non-shared sockets, which ensures graceful close. */ - shutdown(tcp->socket, SD_SEND); - - } else if (uv_tcp_try_cancel_io(tcp) == 0) { - /* In case of a shared socket, we try to cancel all outstanding I/O, */ - /* If that works, don't close the socket yet - wait for the read req to */ - /* return and close the socket in uv_tcp_endgame. */ - close_socket = 0; - - } else { - /* When cancelling isn't possible - which could happen when an LSP is */ - /* present on an old Windows version, we will have to close the socket */ - /* with a read pending. That is not nice because trailing sent bytes */ - /* may not make it to the other side. */ - } - - } else if ((tcp->flags & UV_HANDLE_SHARED_TCP_SOCKET) && - tcp->tcp.serv.accept_reqs != NULL) { - /* Under normal circumstances closesocket() will ensure that all pending */ - /* accept reqs are canceled. However, when the socket is shared the */ - /* presence of another reference to the socket in another process will */ - /* keep the accept reqs going, so we have to ensure that these are */ - /* canceled. */ - if (uv_tcp_try_cancel_io(tcp) != 0) { - /* When cancellation is not possible, there is another option: we can */ - /* close the incoming sockets, which will also cancel the accept */ - /* operations. However this is not cool because we might inadvertently */ - /* close a socket that just accepted a new connection, which will */ - /* cause the connection to be aborted. */ - unsigned int i; - for (i = 0; i < uv_simultaneous_server_accepts; i++) { - uv_tcp_accept_t* req = &tcp->tcp.serv.accept_reqs[i]; - if (req->accept_socket != INVALID_SOCKET && - !HasOverlappedIoCompleted(&req->u.io.overlapped)) { - closesocket(req->accept_socket); - req->accept_socket = INVALID_SOCKET; - } - } - } - } - - if (tcp->flags & UV_HANDLE_READING) { - tcp->flags &= ~UV_HANDLE_READING; - DECREASE_ACTIVE_COUNT(loop, tcp); - } - - if (tcp->flags & UV_HANDLE_LISTENING) { - tcp->flags &= ~UV_HANDLE_LISTENING; - DECREASE_ACTIVE_COUNT(loop, tcp); - } - - if (close_socket) { - closesocket(tcp->socket); - tcp->socket = INVALID_SOCKET; - tcp->flags |= UV_HANDLE_TCP_SOCKET_CLOSED; - } - - tcp->flags &= ~(UV_HANDLE_READABLE | UV_HANDLE_WRITABLE); - uv__handle_closing(tcp); - - if (tcp->reqs_pending == 0) { - uv_want_endgame(tcp->loop, (uv_handle_t*)tcp); - } -} - - -int uv_tcp_open(uv_tcp_t* handle, uv_os_sock_t sock) { - WSAPROTOCOL_INFOW protocol_info; - int opt_len; - int err; - - /* Detect the address family of the socket. */ - opt_len = (int) sizeof protocol_info; - if (getsockopt(sock, - SOL_SOCKET, - SO_PROTOCOL_INFOW, - (char*) &protocol_info, - &opt_len) == SOCKET_ERROR) { - return uv_translate_sys_error(GetLastError()); - } - - err = uv_tcp_set_socket(handle->loop, - handle, - sock, - protocol_info.iAddressFamily, - 1); - if (err) { - return uv_translate_sys_error(err); - } - - return 0; -} - - -/* This function is an egress point, i.e. it returns libuv errors rather than - * system errors. - */ -int uv__tcp_bind(uv_tcp_t* handle, - const struct sockaddr* addr, - unsigned int addrlen, - unsigned int flags) { - int err; - - err = uv_tcp_try_bind(handle, addr, addrlen, flags); - if (err) - return uv_translate_sys_error(err); - - return 0; -} - - -/* This function is an egress point, i.e. it returns libuv errors rather than - * system errors. - */ -int uv__tcp_connect(uv_connect_t* req, - uv_tcp_t* handle, - const struct sockaddr* addr, - unsigned int addrlen, - uv_connect_cb cb) { - int err; - - err = uv_tcp_try_connect(req, handle, addr, addrlen, cb); - if (err) - return uv_translate_sys_error(err); - - return 0; -} diff --git a/vendor/libuv/src/win/thread.c b/vendor/libuv/src/win/thread.c deleted file mode 100644 index 91684e938..000000000 --- a/vendor/libuv/src/win/thread.c +++ /dev/null @@ -1,697 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include -#include -#include - -#include "uv.h" -#include "internal.h" - - -#define HAVE_CONDVAR_API() (pInitializeConditionVariable != NULL) - -static int uv_cond_fallback_init(uv_cond_t* cond); -static void uv_cond_fallback_destroy(uv_cond_t* cond); -static void uv_cond_fallback_signal(uv_cond_t* cond); -static void uv_cond_fallback_broadcast(uv_cond_t* cond); -static void uv_cond_fallback_wait(uv_cond_t* cond, uv_mutex_t* mutex); -static int uv_cond_fallback_timedwait(uv_cond_t* cond, - uv_mutex_t* mutex, uint64_t timeout); - -static int uv_cond_condvar_init(uv_cond_t* cond); -static void uv_cond_condvar_destroy(uv_cond_t* cond); -static void uv_cond_condvar_signal(uv_cond_t* cond); -static void uv_cond_condvar_broadcast(uv_cond_t* cond); -static void uv_cond_condvar_wait(uv_cond_t* cond, uv_mutex_t* mutex); -static int uv_cond_condvar_timedwait(uv_cond_t* cond, - uv_mutex_t* mutex, uint64_t timeout); - - -static void uv__once_inner(uv_once_t* guard, void (*callback)(void)) { - DWORD result; - HANDLE existing_event, created_event; - - created_event = CreateEvent(NULL, 1, 0, NULL); - if (created_event == 0) { - /* Could fail in a low-memory situation? */ - uv_fatal_error(GetLastError(), "CreateEvent"); - } - - existing_event = InterlockedCompareExchangePointer(&guard->event, - created_event, - NULL); - - if (existing_event == NULL) { - /* We won the race */ - callback(); - - result = SetEvent(created_event); - assert(result); - guard->ran = 1; - - } else { - /* We lost the race. Destroy the event we created and wait for the */ - /* existing one to become signaled. */ - CloseHandle(created_event); - result = WaitForSingleObject(existing_event, INFINITE); - assert(result == WAIT_OBJECT_0); - } -} - - -void uv_once(uv_once_t* guard, void (*callback)(void)) { - /* Fast case - avoid WaitForSingleObject. */ - if (guard->ran) { - return; - } - - uv__once_inner(guard, callback); -} - - -/* Verify that uv_thread_t can be stored in a TLS slot. */ -STATIC_ASSERT(sizeof(uv_thread_t) <= sizeof(void*)); - -static uv_key_t uv__current_thread_key; -static uv_once_t uv__current_thread_init_guard = UV_ONCE_INIT; - - -static void uv__init_current_thread_key(void) { - if (uv_key_create(&uv__current_thread_key)) - abort(); -} - - -struct thread_ctx { - void (*entry)(void* arg); - void* arg; - uv_thread_t self; -}; - - -static UINT __stdcall uv__thread_start(void* arg) { - struct thread_ctx *ctx_p; - struct thread_ctx ctx; - - ctx_p = arg; - ctx = *ctx_p; - uv__free(ctx_p); - - uv_once(&uv__current_thread_init_guard, uv__init_current_thread_key); - uv_key_set(&uv__current_thread_key, (void*) ctx.self); - - ctx.entry(ctx.arg); - - return 0; -} - - -int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) { - struct thread_ctx* ctx; - int err; - HANDLE thread; - - ctx = uv__malloc(sizeof(*ctx)); - if (ctx == NULL) - return UV_ENOMEM; - - ctx->entry = entry; - ctx->arg = arg; - - /* Create the thread in suspended state so we have a chance to pass - * its own creation handle to it */ - thread = (HANDLE) _beginthreadex(NULL, - 0, - uv__thread_start, - ctx, - CREATE_SUSPENDED, - NULL); - if (thread == NULL) { - err = errno; - uv__free(ctx); - } else { - err = 0; - *tid = thread; - ctx->self = thread; - ResumeThread(thread); - } - - switch (err) { - case 0: - return 0; - case EACCES: - return UV_EACCES; - case EAGAIN: - return UV_EAGAIN; - case EINVAL: - return UV_EINVAL; - } - - return UV_EIO; -} - - -uv_thread_t uv_thread_self(void) { - uv_once(&uv__current_thread_init_guard, uv__init_current_thread_key); - return (uv_thread_t) uv_key_get(&uv__current_thread_key); -} - - -int uv_thread_join(uv_thread_t *tid) { - if (WaitForSingleObject(*tid, INFINITE)) - return uv_translate_sys_error(GetLastError()); - else { - CloseHandle(*tid); - *tid = 0; - return 0; - } -} - - -int uv_thread_equal(const uv_thread_t* t1, const uv_thread_t* t2) { - return *t1 == *t2; -} - - -int uv_mutex_init(uv_mutex_t* mutex) { - InitializeCriticalSection(mutex); - return 0; -} - - -void uv_mutex_destroy(uv_mutex_t* mutex) { - DeleteCriticalSection(mutex); -} - - -void uv_mutex_lock(uv_mutex_t* mutex) { - EnterCriticalSection(mutex); -} - - -int uv_mutex_trylock(uv_mutex_t* mutex) { - if (TryEnterCriticalSection(mutex)) - return 0; - else - return UV_EBUSY; -} - - -void uv_mutex_unlock(uv_mutex_t* mutex) { - LeaveCriticalSection(mutex); -} - - -int uv_rwlock_init(uv_rwlock_t* rwlock) { - /* Initialize the semaphore that acts as the write lock. */ - HANDLE handle = CreateSemaphoreW(NULL, 1, 1, NULL); - if (handle == NULL) - return uv_translate_sys_error(GetLastError()); - rwlock->state_.write_semaphore_ = handle; - - /* Initialize the critical section protecting the reader count. */ - InitializeCriticalSection(&rwlock->state_.num_readers_lock_); - - /* Initialize the reader count. */ - rwlock->state_.num_readers_ = 0; - - return 0; -} - - -void uv_rwlock_destroy(uv_rwlock_t* rwlock) { - DeleteCriticalSection(&rwlock->state_.num_readers_lock_); - CloseHandle(rwlock->state_.write_semaphore_); -} - - -void uv_rwlock_rdlock(uv_rwlock_t* rwlock) { - /* Acquire the lock that protects the reader count. */ - EnterCriticalSection(&rwlock->state_.num_readers_lock_); - - /* Increase the reader count, and lock for write if this is the first - * reader. - */ - if (++rwlock->state_.num_readers_ == 1) { - DWORD r = WaitForSingleObject(rwlock->state_.write_semaphore_, INFINITE); - if (r != WAIT_OBJECT_0) - uv_fatal_error(GetLastError(), "WaitForSingleObject"); - } - - /* Release the lock that protects the reader count. */ - LeaveCriticalSection(&rwlock->state_.num_readers_lock_); -} - - -int uv_rwlock_tryrdlock(uv_rwlock_t* rwlock) { - int err; - - if (!TryEnterCriticalSection(&rwlock->state_.num_readers_lock_)) - return UV_EBUSY; - - err = 0; - - if (rwlock->state_.num_readers_ == 0) { - /* Currently there are no other readers, which means that the write lock - * needs to be acquired. - */ - DWORD r = WaitForSingleObject(rwlock->state_.write_semaphore_, 0); - if (r == WAIT_OBJECT_0) - rwlock->state_.num_readers_++; - else if (r == WAIT_TIMEOUT) - err = UV_EBUSY; - else if (r == WAIT_FAILED) - uv_fatal_error(GetLastError(), "WaitForSingleObject"); - - } else { - /* The write lock has already been acquired because there are other - * active readers. - */ - rwlock->state_.num_readers_++; - } - - LeaveCriticalSection(&rwlock->state_.num_readers_lock_); - return err; -} - - -void uv_rwlock_rdunlock(uv_rwlock_t* rwlock) { - EnterCriticalSection(&rwlock->state_.num_readers_lock_); - - if (--rwlock->state_.num_readers_ == 0) { - if (!ReleaseSemaphore(rwlock->state_.write_semaphore_, 1, NULL)) - uv_fatal_error(GetLastError(), "ReleaseSemaphore"); - } - - LeaveCriticalSection(&rwlock->state_.num_readers_lock_); -} - - -void uv_rwlock_wrlock(uv_rwlock_t* rwlock) { - DWORD r = WaitForSingleObject(rwlock->state_.write_semaphore_, INFINITE); - if (r != WAIT_OBJECT_0) - uv_fatal_error(GetLastError(), "WaitForSingleObject"); -} - - -int uv_rwlock_trywrlock(uv_rwlock_t* rwlock) { - DWORD r = WaitForSingleObject(rwlock->state_.write_semaphore_, 0); - if (r == WAIT_OBJECT_0) - return 0; - else if (r == WAIT_TIMEOUT) - return UV_EBUSY; - else - uv_fatal_error(GetLastError(), "WaitForSingleObject"); -} - - -void uv_rwlock_wrunlock(uv_rwlock_t* rwlock) { - if (!ReleaseSemaphore(rwlock->state_.write_semaphore_, 1, NULL)) - uv_fatal_error(GetLastError(), "ReleaseSemaphore"); -} - - -int uv_sem_init(uv_sem_t* sem, unsigned int value) { - *sem = CreateSemaphore(NULL, value, INT_MAX, NULL); - if (*sem == NULL) - return uv_translate_sys_error(GetLastError()); - else - return 0; -} - - -void uv_sem_destroy(uv_sem_t* sem) { - if (!CloseHandle(*sem)) - abort(); -} - - -void uv_sem_post(uv_sem_t* sem) { - if (!ReleaseSemaphore(*sem, 1, NULL)) - abort(); -} - - -void uv_sem_wait(uv_sem_t* sem) { - if (WaitForSingleObject(*sem, INFINITE) != WAIT_OBJECT_0) - abort(); -} - - -int uv_sem_trywait(uv_sem_t* sem) { - DWORD r = WaitForSingleObject(*sem, 0); - - if (r == WAIT_OBJECT_0) - return 0; - - if (r == WAIT_TIMEOUT) - return UV_EAGAIN; - - abort(); - return -1; /* Satisfy the compiler. */ -} - - -/* This condition variable implementation is based on the SetEvent solution - * (section 3.2) at http://www.cs.wustl.edu/~schmidt/win32-cv-1.html - * We could not use the SignalObjectAndWait solution (section 3.4) because - * it want the 2nd argument (type uv_mutex_t) of uv_cond_wait() and - * uv_cond_timedwait() to be HANDLEs, but we use CRITICAL_SECTIONs. - */ - -static int uv_cond_fallback_init(uv_cond_t* cond) { - int err; - - /* Initialize the count to 0. */ - cond->fallback.waiters_count = 0; - - InitializeCriticalSection(&cond->fallback.waiters_count_lock); - - /* Create an auto-reset event. */ - cond->fallback.signal_event = CreateEvent(NULL, /* no security */ - FALSE, /* auto-reset event */ - FALSE, /* non-signaled initially */ - NULL); /* unnamed */ - if (!cond->fallback.signal_event) { - err = GetLastError(); - goto error2; - } - - /* Create a manual-reset event. */ - cond->fallback.broadcast_event = CreateEvent(NULL, /* no security */ - TRUE, /* manual-reset */ - FALSE, /* non-signaled */ - NULL); /* unnamed */ - if (!cond->fallback.broadcast_event) { - err = GetLastError(); - goto error; - } - - return 0; - -error: - CloseHandle(cond->fallback.signal_event); -error2: - DeleteCriticalSection(&cond->fallback.waiters_count_lock); - return uv_translate_sys_error(err); -} - - -static int uv_cond_condvar_init(uv_cond_t* cond) { - pInitializeConditionVariable(&cond->cond_var); - return 0; -} - - -int uv_cond_init(uv_cond_t* cond) { - uv__once_init(); - - if (HAVE_CONDVAR_API()) - return uv_cond_condvar_init(cond); - else - return uv_cond_fallback_init(cond); -} - - -static void uv_cond_fallback_destroy(uv_cond_t* cond) { - if (!CloseHandle(cond->fallback.broadcast_event)) - abort(); - if (!CloseHandle(cond->fallback.signal_event)) - abort(); - DeleteCriticalSection(&cond->fallback.waiters_count_lock); -} - - -static void uv_cond_condvar_destroy(uv_cond_t* cond) { - /* nothing to do */ -} - - -void uv_cond_destroy(uv_cond_t* cond) { - if (HAVE_CONDVAR_API()) - uv_cond_condvar_destroy(cond); - else - uv_cond_fallback_destroy(cond); -} - - -static void uv_cond_fallback_signal(uv_cond_t* cond) { - int have_waiters; - - /* Avoid race conditions. */ - EnterCriticalSection(&cond->fallback.waiters_count_lock); - have_waiters = cond->fallback.waiters_count > 0; - LeaveCriticalSection(&cond->fallback.waiters_count_lock); - - if (have_waiters) - SetEvent(cond->fallback.signal_event); -} - - -static void uv_cond_condvar_signal(uv_cond_t* cond) { - pWakeConditionVariable(&cond->cond_var); -} - - -void uv_cond_signal(uv_cond_t* cond) { - if (HAVE_CONDVAR_API()) - uv_cond_condvar_signal(cond); - else - uv_cond_fallback_signal(cond); -} - - -static void uv_cond_fallback_broadcast(uv_cond_t* cond) { - int have_waiters; - - /* Avoid race conditions. */ - EnterCriticalSection(&cond->fallback.waiters_count_lock); - have_waiters = cond->fallback.waiters_count > 0; - LeaveCriticalSection(&cond->fallback.waiters_count_lock); - - if (have_waiters) - SetEvent(cond->fallback.broadcast_event); -} - - -static void uv_cond_condvar_broadcast(uv_cond_t* cond) { - pWakeAllConditionVariable(&cond->cond_var); -} - - -void uv_cond_broadcast(uv_cond_t* cond) { - if (HAVE_CONDVAR_API()) - uv_cond_condvar_broadcast(cond); - else - uv_cond_fallback_broadcast(cond); -} - - -static int uv_cond_wait_helper(uv_cond_t* cond, uv_mutex_t* mutex, - DWORD dwMilliseconds) { - DWORD result; - int last_waiter; - HANDLE handles[2] = { - cond->fallback.signal_event, - cond->fallback.broadcast_event - }; - - /* Avoid race conditions. */ - EnterCriticalSection(&cond->fallback.waiters_count_lock); - cond->fallback.waiters_count++; - LeaveCriticalSection(&cond->fallback.waiters_count_lock); - - /* It's ok to release the here since Win32 manual-reset events */ - /* maintain state when used with . This avoids the "lost wakeup" */ - /* bug. */ - uv_mutex_unlock(mutex); - - /* Wait for either event to become signaled due to being */ - /* called or being called. */ - result = WaitForMultipleObjects(2, handles, FALSE, dwMilliseconds); - - EnterCriticalSection(&cond->fallback.waiters_count_lock); - cond->fallback.waiters_count--; - last_waiter = result == WAIT_OBJECT_0 + 1 - && cond->fallback.waiters_count == 0; - LeaveCriticalSection(&cond->fallback.waiters_count_lock); - - /* Some thread called . */ - if (last_waiter) { - /* We're the last waiter to be notified or to stop waiting, so reset the */ - /* the manual-reset event. */ - ResetEvent(cond->fallback.broadcast_event); - } - - /* Reacquire the . */ - uv_mutex_lock(mutex); - - if (result == WAIT_OBJECT_0 || result == WAIT_OBJECT_0 + 1) - return 0; - - if (result == WAIT_TIMEOUT) - return UV_ETIMEDOUT; - - abort(); - return -1; /* Satisfy the compiler. */ -} - - -static void uv_cond_fallback_wait(uv_cond_t* cond, uv_mutex_t* mutex) { - if (uv_cond_wait_helper(cond, mutex, INFINITE)) - abort(); -} - - -static void uv_cond_condvar_wait(uv_cond_t* cond, uv_mutex_t* mutex) { - if (!pSleepConditionVariableCS(&cond->cond_var, mutex, INFINITE)) - abort(); -} - - -void uv_cond_wait(uv_cond_t* cond, uv_mutex_t* mutex) { - if (HAVE_CONDVAR_API()) - uv_cond_condvar_wait(cond, mutex); - else - uv_cond_fallback_wait(cond, mutex); -} - - -static int uv_cond_fallback_timedwait(uv_cond_t* cond, - uv_mutex_t* mutex, uint64_t timeout) { - return uv_cond_wait_helper(cond, mutex, (DWORD)(timeout / 1e6)); -} - - -static int uv_cond_condvar_timedwait(uv_cond_t* cond, - uv_mutex_t* mutex, uint64_t timeout) { - if (pSleepConditionVariableCS(&cond->cond_var, mutex, (DWORD)(timeout / 1e6))) - return 0; - if (GetLastError() != ERROR_TIMEOUT) - abort(); - return UV_ETIMEDOUT; -} - - -int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, - uint64_t timeout) { - if (HAVE_CONDVAR_API()) - return uv_cond_condvar_timedwait(cond, mutex, timeout); - else - return uv_cond_fallback_timedwait(cond, mutex, timeout); -} - - -int uv_barrier_init(uv_barrier_t* barrier, unsigned int count) { - int err; - - barrier->n = count; - barrier->count = 0; - - err = uv_mutex_init(&barrier->mutex); - if (err) - return err; - - err = uv_sem_init(&barrier->turnstile1, 0); - if (err) - goto error2; - - err = uv_sem_init(&barrier->turnstile2, 1); - if (err) - goto error; - - return 0; - -error: - uv_sem_destroy(&barrier->turnstile1); -error2: - uv_mutex_destroy(&barrier->mutex); - return err; - -} - - -void uv_barrier_destroy(uv_barrier_t* barrier) { - uv_sem_destroy(&barrier->turnstile2); - uv_sem_destroy(&barrier->turnstile1); - uv_mutex_destroy(&barrier->mutex); -} - - -int uv_barrier_wait(uv_barrier_t* barrier) { - int serial_thread; - - uv_mutex_lock(&barrier->mutex); - if (++barrier->count == barrier->n) { - uv_sem_wait(&barrier->turnstile2); - uv_sem_post(&barrier->turnstile1); - } - uv_mutex_unlock(&barrier->mutex); - - uv_sem_wait(&barrier->turnstile1); - uv_sem_post(&barrier->turnstile1); - - uv_mutex_lock(&barrier->mutex); - serial_thread = (--barrier->count == 0); - if (serial_thread) { - uv_sem_wait(&barrier->turnstile1); - uv_sem_post(&barrier->turnstile2); - } - uv_mutex_unlock(&barrier->mutex); - - uv_sem_wait(&barrier->turnstile2); - uv_sem_post(&barrier->turnstile2); - return serial_thread; -} - - -int uv_key_create(uv_key_t* key) { - key->tls_index = TlsAlloc(); - if (key->tls_index == TLS_OUT_OF_INDEXES) - return UV_ENOMEM; - return 0; -} - - -void uv_key_delete(uv_key_t* key) { - if (TlsFree(key->tls_index) == FALSE) - abort(); - key->tls_index = TLS_OUT_OF_INDEXES; -} - - -void* uv_key_get(uv_key_t* key) { - void* value; - - value = TlsGetValue(key->tls_index); - if (value == NULL) - if (GetLastError() != ERROR_SUCCESS) - abort(); - - return value; -} - - -void uv_key_set(uv_key_t* key, void* value) { - if (TlsSetValue(key->tls_index, value) == FALSE) - abort(); -} diff --git a/vendor/libuv/src/win/timer.c b/vendor/libuv/src/win/timer.c deleted file mode 100644 index 27ca7716a..000000000 --- a/vendor/libuv/src/win/timer.c +++ /dev/null @@ -1,195 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include -#include - -#include "uv.h" -#include "internal.h" -#include "tree.h" -#include "handle-inl.h" - - -/* The number of milliseconds in one second. */ -#define UV__MILLISEC 1000 - - -void uv_update_time(uv_loop_t* loop) { - uint64_t new_time = uv__hrtime(UV__MILLISEC); - assert(new_time >= loop->time); - loop->time = new_time; -} - - -static int uv_timer_compare(uv_timer_t* a, uv_timer_t* b) { - if (a->due < b->due) - return -1; - if (a->due > b->due) - return 1; - /* - * compare start_id when both has the same due. start_id is - * allocated with loop->timer_counter in uv_timer_start(). - */ - if (a->start_id < b->start_id) - return -1; - if (a->start_id > b->start_id) - return 1; - return 0; -} - - -RB_GENERATE_STATIC(uv_timer_tree_s, uv_timer_s, tree_entry, uv_timer_compare); - - -int uv_timer_init(uv_loop_t* loop, uv_timer_t* handle) { - uv__handle_init(loop, (uv_handle_t*) handle, UV_TIMER); - handle->timer_cb = NULL; - handle->repeat = 0; - - return 0; -} - - -void uv_timer_endgame(uv_loop_t* loop, uv_timer_t* handle) { - if (handle->flags & UV__HANDLE_CLOSING) { - assert(!(handle->flags & UV_HANDLE_CLOSED)); - uv__handle_close(handle); - } -} - - -static uint64_t get_clamped_due_time(uint64_t loop_time, uint64_t timeout) { - uint64_t clamped_timeout; - - clamped_timeout = loop_time + timeout; - if (clamped_timeout < timeout) - clamped_timeout = (uint64_t) -1; - - return clamped_timeout; -} - - -int uv_timer_start(uv_timer_t* handle, uv_timer_cb timer_cb, uint64_t timeout, - uint64_t repeat) { - uv_loop_t* loop = handle->loop; - uv_timer_t* old; - - if (timer_cb == NULL) - return UV_EINVAL; - - if (uv__is_active(handle)) - uv_timer_stop(handle); - - handle->timer_cb = timer_cb; - handle->due = get_clamped_due_time(loop->time, timeout); - handle->repeat = repeat; - uv__handle_start(handle); - - /* start_id is the second index to be compared in uv__timer_cmp() */ - handle->start_id = handle->loop->timer_counter++; - - old = RB_INSERT(uv_timer_tree_s, &loop->timers, handle); - assert(old == NULL); - - return 0; -} - - -int uv_timer_stop(uv_timer_t* handle) { - uv_loop_t* loop = handle->loop; - - if (!uv__is_active(handle)) - return 0; - - RB_REMOVE(uv_timer_tree_s, &loop->timers, handle); - uv__handle_stop(handle); - - return 0; -} - - -int uv_timer_again(uv_timer_t* handle) { - /* If timer_cb is NULL that means that the timer was never started. */ - if (!handle->timer_cb) { - return UV_EINVAL; - } - - if (handle->repeat) { - uv_timer_stop(handle); - uv_timer_start(handle, handle->timer_cb, handle->repeat, handle->repeat); - } - - return 0; -} - - -void uv_timer_set_repeat(uv_timer_t* handle, uint64_t repeat) { - assert(handle->type == UV_TIMER); - handle->repeat = repeat; -} - - -uint64_t uv_timer_get_repeat(const uv_timer_t* handle) { - assert(handle->type == UV_TIMER); - return handle->repeat; -} - - -DWORD uv__next_timeout(const uv_loop_t* loop) { - uv_timer_t* timer; - int64_t delta; - - /* Check if there are any running timers - * Need to cast away const first, since RB_MIN doesn't know what we are - * going to do with this return value, it can't be marked const - */ - timer = RB_MIN(uv_timer_tree_s, &((uv_loop_t*)loop)->timers); - if (timer) { - delta = timer->due - loop->time; - if (delta >= UINT_MAX - 1) { - /* A timeout value of UINT_MAX means infinite, so that's no good. */ - return UINT_MAX - 1; - } else if (delta < 0) { - /* Negative timeout values are not allowed */ - return 0; - } else { - return (DWORD)delta; - } - } else { - /* No timers */ - return INFINITE; - } -} - - -void uv_process_timers(uv_loop_t* loop) { - uv_timer_t* timer; - - /* Call timer callbacks */ - for (timer = RB_MIN(uv_timer_tree_s, &loop->timers); - timer != NULL && timer->due <= loop->time; - timer = RB_MIN(uv_timer_tree_s, &loop->timers)) { - - uv_timer_stop(timer); - uv_timer_again(timer); - timer->timer_cb((uv_timer_t*) timer); - } -} diff --git a/vendor/libuv/src/win/tty.c b/vendor/libuv/src/win/tty.c deleted file mode 100644 index 1b7adf64f..000000000 --- a/vendor/libuv/src/win/tty.c +++ /dev/null @@ -1,2282 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include -#include -#include -#include - -#if defined(_MSC_VER) && _MSC_VER < 1600 -# include "stdint-msvc2008.h" -#else -# include -#endif - -#ifndef COMMON_LVB_REVERSE_VIDEO -# define COMMON_LVB_REVERSE_VIDEO 0x4000 -#endif - -#include "uv.h" -#include "internal.h" -#include "handle-inl.h" -#include "stream-inl.h" -#include "req-inl.h" - -#ifndef InterlockedOr -# define InterlockedOr _InterlockedOr -#endif - -#define UNICODE_REPLACEMENT_CHARACTER (0xfffd) - -#define ANSI_NORMAL 0x00 -#define ANSI_ESCAPE_SEEN 0x02 -#define ANSI_CSI 0x04 -#define ANSI_ST_CONTROL 0x08 -#define ANSI_IGNORE 0x10 -#define ANSI_IN_ARG 0x20 -#define ANSI_IN_STRING 0x40 -#define ANSI_BACKSLASH_SEEN 0x80 - -#define MAX_INPUT_BUFFER_LENGTH 8192 -#define MAX_CONSOLE_CHAR 8192 - -#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING -#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004 -#endif - -static void uv_tty_capture_initial_style(CONSOLE_SCREEN_BUFFER_INFO* info); -static void uv_tty_update_virtual_window(CONSOLE_SCREEN_BUFFER_INFO* info); -static int uv__cancel_read_console(uv_tty_t* handle); - - -/* Null uv_buf_t */ -static const uv_buf_t uv_null_buf_ = { 0, NULL }; - -enum uv__read_console_status_e { - NOT_STARTED, - IN_PROGRESS, - TRAP_REQUESTED, - COMPLETED -}; - -static volatile LONG uv__read_console_status = NOT_STARTED; -static volatile LONG uv__restore_screen_state; -static CONSOLE_SCREEN_BUFFER_INFO uv__saved_screen_state; - - -/* - * The console virtual window. - * - * Normally cursor movement in windows is relative to the console screen buffer, - * e.g. the application is allowed to overwrite the 'history'. This is very - * inconvenient, it makes absolute cursor movement pretty useless. There is - * also the concept of 'client rect' which is defined by the actual size of - * the console window and the scroll position of the screen buffer, but it's - * very volatile because it changes when the user scrolls. - * - * To make cursor movement behave sensibly we define a virtual window to which - * cursor movement is confined. The virtual window is always as wide as the - * console screen buffer, but it's height is defined by the size of the - * console window. The top of the virtual window aligns with the position - * of the caret when the first stdout/err handle is created, unless that would - * mean that it would extend beyond the bottom of the screen buffer - in that - * that case it's located as far down as possible. - * - * When the user writes a long text or many newlines, such that the output - * reaches beyond the bottom of the virtual window, the virtual window is - * shifted downwards, but not resized. - * - * Since all tty i/o happens on the same console, this window is shared - * between all stdout/stderr handles. - */ - -static int uv_tty_virtual_offset = -1; -static int uv_tty_virtual_height = -1; -static int uv_tty_virtual_width = -1; - -/* We use a semaphore rather than a mutex or critical section because in some - cases (uv__cancel_read_console) we need take the lock in the main thread and - release it in another thread. Using a semaphore ensures that in such - scenario the main thread will still block when trying to acquire the lock. */ -static uv_sem_t uv_tty_output_lock; - -static HANDLE uv_tty_output_handle = INVALID_HANDLE_VALUE; - -static WORD uv_tty_default_text_attributes = - FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; - -static char uv_tty_default_fg_color = 7; -static char uv_tty_default_bg_color = 0; -static char uv_tty_default_fg_bright = 0; -static char uv_tty_default_bg_bright = 0; -static char uv_tty_default_inverse = 0; - -typedef enum { - UV_SUPPORTED, - UV_UNCHECKED, - UV_UNSUPPORTED -} uv_vtermstate_t; -/* Determine whether or not ANSI support is enabled. */ -static uv_vtermstate_t uv__vterm_state = UV_UNCHECKED; -static void uv__determine_vterm_state(HANDLE handle); - -void uv_console_init() { - if (uv_sem_init(&uv_tty_output_lock, 1)) - abort(); -} - - -int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, uv_file fd, int readable) { - HANDLE handle; - CONSOLE_SCREEN_BUFFER_INFO screen_buffer_info; - - handle = (HANDLE) uv__get_osfhandle(fd); - if (handle == INVALID_HANDLE_VALUE) - return UV_EBADF; - - if (fd <= 2) { - /* In order to avoid closing a stdio file descriptor 0-2, duplicate the - * underlying OS handle and forget about the original fd. - * We could also opt to use the original OS handle and just never close it, - * but then there would be no reliable way to cancel pending read operations - * upon close. - */ - if (!DuplicateHandle(INVALID_HANDLE_VALUE, - handle, - INVALID_HANDLE_VALUE, - &handle, - 0, - FALSE, - DUPLICATE_SAME_ACCESS)) - return uv_translate_sys_error(GetLastError()); - fd = -1; - } - - if (!readable) { - /* Obtain the screen buffer info with the output handle. */ - if (!GetConsoleScreenBufferInfo(handle, &screen_buffer_info)) { - return uv_translate_sys_error(GetLastError()); - } - - /* Obtain the the tty_output_lock because the virtual window state is */ - /* shared between all uv_tty_t handles. */ - uv_sem_wait(&uv_tty_output_lock); - - if (uv__vterm_state == UV_UNCHECKED) - uv__determine_vterm_state(handle); - - /* Store the global tty output handle. This handle is used by TTY read */ - /* streams to update the virtual window when a CONSOLE_BUFFER_SIZE_EVENT */ - /* is received. */ - uv_tty_output_handle = handle; - - /* Remember the original console text attributes. */ - uv_tty_capture_initial_style(&screen_buffer_info); - - uv_tty_update_virtual_window(&screen_buffer_info); - - uv_sem_post(&uv_tty_output_lock); - } - - - uv_stream_init(loop, (uv_stream_t*) tty, UV_TTY); - uv_connection_init((uv_stream_t*) tty); - - tty->handle = handle; - tty->u.fd = fd; - tty->reqs_pending = 0; - tty->flags |= UV_HANDLE_BOUND; - - if (readable) { - /* Initialize TTY input specific fields. */ - tty->flags |= UV_HANDLE_TTY_READABLE | UV_HANDLE_READABLE; - /* TODO: remove me in v2.x. */ - tty->tty.rd.unused_ = NULL; - tty->tty.rd.read_line_buffer = uv_null_buf_; - tty->tty.rd.read_raw_wait = NULL; - - /* Init keycode-to-vt100 mapper state. */ - tty->tty.rd.last_key_len = 0; - tty->tty.rd.last_key_offset = 0; - tty->tty.rd.last_utf16_high_surrogate = 0; - memset(&tty->tty.rd.last_input_record, 0, sizeof tty->tty.rd.last_input_record); - } else { - /* TTY output specific fields. */ - tty->flags |= UV_HANDLE_WRITABLE; - - /* Init utf8-to-utf16 conversion state. */ - tty->tty.wr.utf8_bytes_left = 0; - tty->tty.wr.utf8_codepoint = 0; - - /* Initialize eol conversion state */ - tty->tty.wr.previous_eol = 0; - - /* Init ANSI parser state. */ - tty->tty.wr.ansi_parser_state = ANSI_NORMAL; - } - - return 0; -} - - -/* Set the default console text attributes based on how the console was - * configured when libuv started. - */ -static void uv_tty_capture_initial_style(CONSOLE_SCREEN_BUFFER_INFO* info) { - static int style_captured = 0; - - /* Only do this once. - Assumption: Caller has acquired uv_tty_output_lock. */ - if (style_captured) - return; - - /* Save raw win32 attributes. */ - uv_tty_default_text_attributes = info->wAttributes; - - /* Convert black text on black background to use white text. */ - if (uv_tty_default_text_attributes == 0) - uv_tty_default_text_attributes = 7; - - /* Convert Win32 attributes to ANSI colors. */ - uv_tty_default_fg_color = 0; - uv_tty_default_bg_color = 0; - uv_tty_default_fg_bright = 0; - uv_tty_default_bg_bright = 0; - uv_tty_default_inverse = 0; - - if (uv_tty_default_text_attributes & FOREGROUND_RED) - uv_tty_default_fg_color |= 1; - - if (uv_tty_default_text_attributes & FOREGROUND_GREEN) - uv_tty_default_fg_color |= 2; - - if (uv_tty_default_text_attributes & FOREGROUND_BLUE) - uv_tty_default_fg_color |= 4; - - if (uv_tty_default_text_attributes & BACKGROUND_RED) - uv_tty_default_bg_color |= 1; - - if (uv_tty_default_text_attributes & BACKGROUND_GREEN) - uv_tty_default_bg_color |= 2; - - if (uv_tty_default_text_attributes & BACKGROUND_BLUE) - uv_tty_default_bg_color |= 4; - - if (uv_tty_default_text_attributes & FOREGROUND_INTENSITY) - uv_tty_default_fg_bright = 1; - - if (uv_tty_default_text_attributes & BACKGROUND_INTENSITY) - uv_tty_default_bg_bright = 1; - - if (uv_tty_default_text_attributes & COMMON_LVB_REVERSE_VIDEO) - uv_tty_default_inverse = 1; - - style_captured = 1; -} - - -int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) { - DWORD flags; - unsigned char was_reading; - uv_alloc_cb alloc_cb; - uv_read_cb read_cb; - int err; - - if (!(tty->flags & UV_HANDLE_TTY_READABLE)) { - return UV_EINVAL; - } - - if (!!mode == !!(tty->flags & UV_HANDLE_TTY_RAW)) { - return 0; - } - - switch (mode) { - case UV_TTY_MODE_NORMAL: - flags = ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT; - break; - case UV_TTY_MODE_RAW: - flags = ENABLE_WINDOW_INPUT; - break; - case UV_TTY_MODE_IO: - return UV_ENOTSUP; - default: - return UV_EINVAL; - } - - /* If currently reading, stop, and restart reading. */ - if (tty->flags & UV_HANDLE_READING) { - was_reading = 1; - alloc_cb = tty->alloc_cb; - read_cb = tty->read_cb; - err = uv_tty_read_stop(tty); - if (err) { - return uv_translate_sys_error(err); - } - } else { - was_reading = 0; - } - - uv_sem_wait(&uv_tty_output_lock); - if (!SetConsoleMode(tty->handle, flags)) { - err = uv_translate_sys_error(GetLastError()); - uv_sem_post(&uv_tty_output_lock); - return err; - } - uv_sem_post(&uv_tty_output_lock); - - /* Update flag. */ - tty->flags &= ~UV_HANDLE_TTY_RAW; - tty->flags |= mode ? UV_HANDLE_TTY_RAW : 0; - - /* If we just stopped reading, restart. */ - if (was_reading) { - err = uv_tty_read_start(tty, alloc_cb, read_cb); - if (err) { - return uv_translate_sys_error(err); - } - } - - return 0; -} - - -int uv_is_tty(uv_file file) { - DWORD result; - return GetConsoleMode((HANDLE) _get_osfhandle(file), &result) != 0; -} - - -int uv_tty_get_winsize(uv_tty_t* tty, int* width, int* height) { - CONSOLE_SCREEN_BUFFER_INFO info; - - if (!GetConsoleScreenBufferInfo(tty->handle, &info)) { - return uv_translate_sys_error(GetLastError()); - } - - uv_sem_wait(&uv_tty_output_lock); - uv_tty_update_virtual_window(&info); - uv_sem_post(&uv_tty_output_lock); - - *width = uv_tty_virtual_width; - *height = uv_tty_virtual_height; - - return 0; -} - - -static void CALLBACK uv_tty_post_raw_read(void* data, BOOLEAN didTimeout) { - uv_loop_t* loop; - uv_tty_t* handle; - uv_req_t* req; - - assert(data); - assert(!didTimeout); - - req = (uv_req_t*) data; - handle = (uv_tty_t*) req->data; - loop = handle->loop; - - UnregisterWait(handle->tty.rd.read_raw_wait); - handle->tty.rd.read_raw_wait = NULL; - - SET_REQ_SUCCESS(req); - POST_COMPLETION_FOR_REQ(loop, req); -} - - -static void uv_tty_queue_read_raw(uv_loop_t* loop, uv_tty_t* handle) { - uv_read_t* req; - BOOL r; - - assert(handle->flags & UV_HANDLE_READING); - assert(!(handle->flags & UV_HANDLE_READ_PENDING)); - - assert(handle->handle && handle->handle != INVALID_HANDLE_VALUE); - - handle->tty.rd.read_line_buffer = uv_null_buf_; - - req = &handle->read_req; - memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped)); - - r = RegisterWaitForSingleObject(&handle->tty.rd.read_raw_wait, - handle->handle, - uv_tty_post_raw_read, - (void*) req, - INFINITE, - WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE); - if (!r) { - handle->tty.rd.read_raw_wait = NULL; - SET_REQ_ERROR(req, GetLastError()); - uv_insert_pending_req(loop, (uv_req_t*)req); - } - - handle->flags |= UV_HANDLE_READ_PENDING; - handle->reqs_pending++; -} - - -static DWORD CALLBACK uv_tty_line_read_thread(void* data) { - uv_loop_t* loop; - uv_tty_t* handle; - uv_req_t* req; - DWORD bytes, read_bytes; - WCHAR utf16[MAX_INPUT_BUFFER_LENGTH / 3]; - DWORD chars, read_chars; - LONG status; - COORD pos; - BOOL read_console_success; - - assert(data); - - req = (uv_req_t*) data; - handle = (uv_tty_t*) req->data; - loop = handle->loop; - - assert(handle->tty.rd.read_line_buffer.base != NULL); - assert(handle->tty.rd.read_line_buffer.len > 0); - - /* ReadConsole can't handle big buffers. */ - if (handle->tty.rd.read_line_buffer.len < MAX_INPUT_BUFFER_LENGTH) { - bytes = handle->tty.rd.read_line_buffer.len; - } else { - bytes = MAX_INPUT_BUFFER_LENGTH; - } - - /* At last, unicode! */ - /* One utf-16 codeunit never takes more than 3 utf-8 codeunits to encode */ - chars = bytes / 3; - - status = InterlockedExchange(&uv__read_console_status, IN_PROGRESS); - if (status == TRAP_REQUESTED) { - SET_REQ_SUCCESS(req); - req->u.io.overlapped.InternalHigh = 0; - POST_COMPLETION_FOR_REQ(loop, req); - return 0; - } - - read_console_success = ReadConsoleW(handle->handle, - (void*) utf16, - chars, - &read_chars, - NULL); - - if (read_console_success) { - read_bytes = WideCharToMultiByte(CP_UTF8, - 0, - utf16, - read_chars, - handle->tty.rd.read_line_buffer.base, - bytes, - NULL, - NULL); - SET_REQ_SUCCESS(req); - req->u.io.overlapped.InternalHigh = read_bytes; - } else { - SET_REQ_ERROR(req, GetLastError()); - } - - status = InterlockedExchange(&uv__read_console_status, COMPLETED); - - if (status == TRAP_REQUESTED) { - /* If we canceled the read by sending a VK_RETURN event, restore the - screen state to undo the visual effect of the VK_RETURN */ - if (read_console_success && InterlockedOr(&uv__restore_screen_state, 0)) { - HANDLE active_screen_buffer; - active_screen_buffer = CreateFileA("conout$", - GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL); - if (active_screen_buffer != INVALID_HANDLE_VALUE) { - pos = uv__saved_screen_state.dwCursorPosition; - - /* If the cursor was at the bottom line of the screen buffer, the - VK_RETURN would have caused the buffer contents to scroll up by one - line. The right position to reset the cursor to is therefore one line - higher */ - if (pos.Y == uv__saved_screen_state.dwSize.Y - 1) - pos.Y--; - - SetConsoleCursorPosition(active_screen_buffer, pos); - CloseHandle(active_screen_buffer); - } - } - uv_sem_post(&uv_tty_output_lock); - } - POST_COMPLETION_FOR_REQ(loop, req); - return 0; -} - - -static void uv_tty_queue_read_line(uv_loop_t* loop, uv_tty_t* handle) { - uv_read_t* req; - BOOL r; - - assert(handle->flags & UV_HANDLE_READING); - assert(!(handle->flags & UV_HANDLE_READ_PENDING)); - assert(handle->handle && handle->handle != INVALID_HANDLE_VALUE); - - req = &handle->read_req; - memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped)); - - handle->tty.rd.read_line_buffer = uv_buf_init(NULL, 0); - handle->alloc_cb((uv_handle_t*) handle, 8192, &handle->tty.rd.read_line_buffer); - if (handle->tty.rd.read_line_buffer.base == NULL || - handle->tty.rd.read_line_buffer.len == 0) { - handle->read_cb((uv_stream_t*) handle, - UV_ENOBUFS, - &handle->tty.rd.read_line_buffer); - return; - } - assert(handle->tty.rd.read_line_buffer.base != NULL); - - /* Reset flags No locking is required since there cannot be a line read - in progress. We are also relying on the memory barrier provided by - QueueUserWorkItem*/ - uv__restore_screen_state = FALSE; - uv__read_console_status = NOT_STARTED; - r = QueueUserWorkItem(uv_tty_line_read_thread, - (void*) req, - WT_EXECUTELONGFUNCTION); - if (!r) { - SET_REQ_ERROR(req, GetLastError()); - uv_insert_pending_req(loop, (uv_req_t*)req); - } - - handle->flags |= UV_HANDLE_READ_PENDING; - handle->reqs_pending++; -} - - -static void uv_tty_queue_read(uv_loop_t* loop, uv_tty_t* handle) { - if (handle->flags & UV_HANDLE_TTY_RAW) { - uv_tty_queue_read_raw(loop, handle); - } else { - uv_tty_queue_read_line(loop, handle); - } -} - - -static const char* get_vt100_fn_key(DWORD code, char shift, char ctrl, - size_t* len) { -#define VK_CASE(vk, normal_str, shift_str, ctrl_str, shift_ctrl_str) \ - case (vk): \ - if (shift && ctrl) { \ - *len = sizeof shift_ctrl_str; \ - return "\033" shift_ctrl_str; \ - } else if (shift) { \ - *len = sizeof shift_str ; \ - return "\033" shift_str; \ - } else if (ctrl) { \ - *len = sizeof ctrl_str; \ - return "\033" ctrl_str; \ - } else { \ - *len = sizeof normal_str; \ - return "\033" normal_str; \ - } - - switch (code) { - /* These mappings are the same as Cygwin's. Unmodified and alt-modified */ - /* keypad keys comply with linux console, modifiers comply with xterm */ - /* modifier usage. F1..f12 and shift-f1..f10 comply with linux console, */ - /* f6..f12 with and without modifiers comply with rxvt. */ - VK_CASE(VK_INSERT, "[2~", "[2;2~", "[2;5~", "[2;6~") - VK_CASE(VK_END, "[4~", "[4;2~", "[4;5~", "[4;6~") - VK_CASE(VK_DOWN, "[B", "[1;2B", "[1;5B", "[1;6B") - VK_CASE(VK_NEXT, "[6~", "[6;2~", "[6;5~", "[6;6~") - VK_CASE(VK_LEFT, "[D", "[1;2D", "[1;5D", "[1;6D") - VK_CASE(VK_CLEAR, "[G", "[1;2G", "[1;5G", "[1;6G") - VK_CASE(VK_RIGHT, "[C", "[1;2C", "[1;5C", "[1;6C") - VK_CASE(VK_UP, "[A", "[1;2A", "[1;5A", "[1;6A") - VK_CASE(VK_HOME, "[1~", "[1;2~", "[1;5~", "[1;6~") - VK_CASE(VK_PRIOR, "[5~", "[5;2~", "[5;5~", "[5;6~") - VK_CASE(VK_DELETE, "[3~", "[3;2~", "[3;5~", "[3;6~") - VK_CASE(VK_NUMPAD0, "[2~", "[2;2~", "[2;5~", "[2;6~") - VK_CASE(VK_NUMPAD1, "[4~", "[4;2~", "[4;5~", "[4;6~") - VK_CASE(VK_NUMPAD2, "[B", "[1;2B", "[1;5B", "[1;6B") - VK_CASE(VK_NUMPAD3, "[6~", "[6;2~", "[6;5~", "[6;6~") - VK_CASE(VK_NUMPAD4, "[D", "[1;2D", "[1;5D", "[1;6D") - VK_CASE(VK_NUMPAD5, "[G", "[1;2G", "[1;5G", "[1;6G") - VK_CASE(VK_NUMPAD6, "[C", "[1;2C", "[1;5C", "[1;6C") - VK_CASE(VK_NUMPAD7, "[A", "[1;2A", "[1;5A", "[1;6A") - VK_CASE(VK_NUMPAD8, "[1~", "[1;2~", "[1;5~", "[1;6~") - VK_CASE(VK_NUMPAD9, "[5~", "[5;2~", "[5;5~", "[5;6~") - VK_CASE(VK_DECIMAL, "[3~", "[3;2~", "[3;5~", "[3;6~") - VK_CASE(VK_F1, "[[A", "[23~", "[11^", "[23^" ) - VK_CASE(VK_F2, "[[B", "[24~", "[12^", "[24^" ) - VK_CASE(VK_F3, "[[C", "[25~", "[13^", "[25^" ) - VK_CASE(VK_F4, "[[D", "[26~", "[14^", "[26^" ) - VK_CASE(VK_F5, "[[E", "[28~", "[15^", "[28^" ) - VK_CASE(VK_F6, "[17~", "[29~", "[17^", "[29^" ) - VK_CASE(VK_F7, "[18~", "[31~", "[18^", "[31^" ) - VK_CASE(VK_F8, "[19~", "[32~", "[19^", "[32^" ) - VK_CASE(VK_F9, "[20~", "[33~", "[20^", "[33^" ) - VK_CASE(VK_F10, "[21~", "[34~", "[21^", "[34^" ) - VK_CASE(VK_F11, "[23~", "[23$", "[23^", "[23@" ) - VK_CASE(VK_F12, "[24~", "[24$", "[24^", "[24@" ) - - default: - *len = 0; - return NULL; - } -#undef VK_CASE -} - - -void uv_process_tty_read_raw_req(uv_loop_t* loop, uv_tty_t* handle, - uv_req_t* req) { - /* Shortcut for handle->tty.rd.last_input_record.Event.KeyEvent. */ -#define KEV handle->tty.rd.last_input_record.Event.KeyEvent - - DWORD records_left, records_read; - uv_buf_t buf; - off_t buf_used; - - assert(handle->type == UV_TTY); - assert(handle->flags & UV_HANDLE_TTY_READABLE); - handle->flags &= ~UV_HANDLE_READ_PENDING; - - if (!(handle->flags & UV_HANDLE_READING) || - !(handle->flags & UV_HANDLE_TTY_RAW)) { - goto out; - } - - if (!REQ_SUCCESS(req)) { - /* An error occurred while waiting for the event. */ - if ((handle->flags & UV_HANDLE_READING)) { - handle->flags &= ~UV_HANDLE_READING; - handle->read_cb((uv_stream_t*)handle, - uv_translate_sys_error(GET_REQ_ERROR(req)), - &uv_null_buf_); - } - goto out; - } - - /* Fetch the number of events */ - if (!GetNumberOfConsoleInputEvents(handle->handle, &records_left)) { - handle->flags &= ~UV_HANDLE_READING; - DECREASE_ACTIVE_COUNT(loop, handle); - handle->read_cb((uv_stream_t*)handle, - uv_translate_sys_error(GetLastError()), - &uv_null_buf_); - goto out; - } - - /* Windows sends a lot of events that we're not interested in, so buf */ - /* will be allocated on demand, when there's actually something to emit. */ - buf = uv_null_buf_; - buf_used = 0; - - while ((records_left > 0 || handle->tty.rd.last_key_len > 0) && - (handle->flags & UV_HANDLE_READING)) { - if (handle->tty.rd.last_key_len == 0) { - /* Read the next input record */ - if (!ReadConsoleInputW(handle->handle, - &handle->tty.rd.last_input_record, - 1, - &records_read)) { - handle->flags &= ~UV_HANDLE_READING; - DECREASE_ACTIVE_COUNT(loop, handle); - handle->read_cb((uv_stream_t*) handle, - uv_translate_sys_error(GetLastError()), - &buf); - goto out; - } - records_left--; - - /* If the window was resized, recompute the virtual window size. This */ - /* will trigger a SIGWINCH signal if the window size changed in an */ - /* way that matters to libuv. */ - if (handle->tty.rd.last_input_record.EventType == WINDOW_BUFFER_SIZE_EVENT) { - CONSOLE_SCREEN_BUFFER_INFO info; - - uv_sem_wait(&uv_tty_output_lock); - - if (uv_tty_output_handle != INVALID_HANDLE_VALUE && - GetConsoleScreenBufferInfo(uv_tty_output_handle, &info)) { - uv_tty_update_virtual_window(&info); - } - - uv_sem_post(&uv_tty_output_lock); - - continue; - } - - /* Ignore other events that are not key or resize events. */ - if (handle->tty.rd.last_input_record.EventType != KEY_EVENT) { - continue; - } - - /* Ignore keyup events, unless the left alt key was held and a valid */ - /* unicode character was emitted. */ - if (!KEV.bKeyDown && !(((KEV.dwControlKeyState & LEFT_ALT_PRESSED) || - KEV.wVirtualKeyCode==VK_MENU) && KEV.uChar.UnicodeChar != 0)) { - continue; - } - - /* Ignore keypresses to numpad number keys if the left alt is held */ - /* because the user is composing a character, or windows simulating */ - /* this. */ - if ((KEV.dwControlKeyState & LEFT_ALT_PRESSED) && - !(KEV.dwControlKeyState & ENHANCED_KEY) && - (KEV.wVirtualKeyCode == VK_INSERT || - KEV.wVirtualKeyCode == VK_END || - KEV.wVirtualKeyCode == VK_DOWN || - KEV.wVirtualKeyCode == VK_NEXT || - KEV.wVirtualKeyCode == VK_LEFT || - KEV.wVirtualKeyCode == VK_CLEAR || - KEV.wVirtualKeyCode == VK_RIGHT || - KEV.wVirtualKeyCode == VK_HOME || - KEV.wVirtualKeyCode == VK_UP || - KEV.wVirtualKeyCode == VK_PRIOR || - KEV.wVirtualKeyCode == VK_NUMPAD0 || - KEV.wVirtualKeyCode == VK_NUMPAD1 || - KEV.wVirtualKeyCode == VK_NUMPAD2 || - KEV.wVirtualKeyCode == VK_NUMPAD3 || - KEV.wVirtualKeyCode == VK_NUMPAD4 || - KEV.wVirtualKeyCode == VK_NUMPAD5 || - KEV.wVirtualKeyCode == VK_NUMPAD6 || - KEV.wVirtualKeyCode == VK_NUMPAD7 || - KEV.wVirtualKeyCode == VK_NUMPAD8 || - KEV.wVirtualKeyCode == VK_NUMPAD9)) { - continue; - } - - if (KEV.uChar.UnicodeChar != 0) { - int prefix_len, char_len; - - /* Character key pressed */ - if (KEV.uChar.UnicodeChar >= 0xD800 && - KEV.uChar.UnicodeChar < 0xDC00) { - /* UTF-16 high surrogate */ - handle->tty.rd.last_utf16_high_surrogate = KEV.uChar.UnicodeChar; - continue; - } - - /* Prefix with \u033 if alt was held, but alt was not used as part */ - /* a compose sequence. */ - if ((KEV.dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) - && !(KEV.dwControlKeyState & (LEFT_CTRL_PRESSED | - RIGHT_CTRL_PRESSED)) && KEV.bKeyDown) { - handle->tty.rd.last_key[0] = '\033'; - prefix_len = 1; - } else { - prefix_len = 0; - } - - if (KEV.uChar.UnicodeChar >= 0xDC00 && - KEV.uChar.UnicodeChar < 0xE000) { - /* UTF-16 surrogate pair */ - WCHAR utf16_buffer[2] = { handle->tty.rd.last_utf16_high_surrogate, - KEV.uChar.UnicodeChar}; - char_len = WideCharToMultiByte(CP_UTF8, - 0, - utf16_buffer, - 2, - &handle->tty.rd.last_key[prefix_len], - sizeof handle->tty.rd.last_key, - NULL, - NULL); - } else { - /* Single UTF-16 character */ - char_len = WideCharToMultiByte(CP_UTF8, - 0, - &KEV.uChar.UnicodeChar, - 1, - &handle->tty.rd.last_key[prefix_len], - sizeof handle->tty.rd.last_key, - NULL, - NULL); - } - - /* Whatever happened, the last character wasn't a high surrogate. */ - handle->tty.rd.last_utf16_high_surrogate = 0; - - /* If the utf16 character(s) couldn't be converted something must */ - /* be wrong. */ - if (!char_len) { - handle->flags &= ~UV_HANDLE_READING; - DECREASE_ACTIVE_COUNT(loop, handle); - handle->read_cb((uv_stream_t*) handle, - uv_translate_sys_error(GetLastError()), - &buf); - goto out; - } - - handle->tty.rd.last_key_len = (unsigned char) (prefix_len + char_len); - handle->tty.rd.last_key_offset = 0; - continue; - - } else { - /* Function key pressed */ - const char* vt100; - size_t prefix_len, vt100_len; - - vt100 = get_vt100_fn_key(KEV.wVirtualKeyCode, - !!(KEV.dwControlKeyState & SHIFT_PRESSED), - !!(KEV.dwControlKeyState & ( - LEFT_CTRL_PRESSED | - RIGHT_CTRL_PRESSED)), - &vt100_len); - - /* If we were unable to map to a vt100 sequence, just ignore. */ - if (!vt100) { - continue; - } - - /* Prefix with \x033 when the alt key was held. */ - if (KEV.dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) { - handle->tty.rd.last_key[0] = '\033'; - prefix_len = 1; - } else { - prefix_len = 0; - } - - /* Copy the vt100 sequence to the handle buffer. */ - assert(prefix_len + vt100_len < sizeof handle->tty.rd.last_key); - memcpy(&handle->tty.rd.last_key[prefix_len], vt100, vt100_len); - - handle->tty.rd.last_key_len = (unsigned char) (prefix_len + vt100_len); - handle->tty.rd.last_key_offset = 0; - continue; - } - } else { - /* Copy any bytes left from the last keypress to the user buffer. */ - if (handle->tty.rd.last_key_offset < handle->tty.rd.last_key_len) { - /* Allocate a buffer if needed */ - if (buf_used == 0) { - buf = uv_buf_init(NULL, 0); - handle->alloc_cb((uv_handle_t*) handle, 1024, &buf); - if (buf.base == NULL || buf.len == 0) { - handle->read_cb((uv_stream_t*) handle, UV_ENOBUFS, &buf); - goto out; - } - assert(buf.base != NULL); - } - - buf.base[buf_used++] = handle->tty.rd.last_key[handle->tty.rd.last_key_offset++]; - - /* If the buffer is full, emit it */ - if ((size_t) buf_used == buf.len) { - handle->read_cb((uv_stream_t*) handle, buf_used, &buf); - buf = uv_null_buf_; - buf_used = 0; - } - - continue; - } - - /* Apply dwRepeat from the last input record. */ - if (--KEV.wRepeatCount > 0) { - handle->tty.rd.last_key_offset = 0; - continue; - } - - handle->tty.rd.last_key_len = 0; - continue; - } - } - - /* Send the buffer back to the user */ - if (buf_used > 0) { - handle->read_cb((uv_stream_t*) handle, buf_used, &buf); - } - - out: - /* Wait for more input events. */ - if ((handle->flags & UV_HANDLE_READING) && - !(handle->flags & UV_HANDLE_READ_PENDING)) { - uv_tty_queue_read(loop, handle); - } - - DECREASE_PENDING_REQ_COUNT(handle); - -#undef KEV -} - - - -void uv_process_tty_read_line_req(uv_loop_t* loop, uv_tty_t* handle, - uv_req_t* req) { - uv_buf_t buf; - - assert(handle->type == UV_TTY); - assert(handle->flags & UV_HANDLE_TTY_READABLE); - - buf = handle->tty.rd.read_line_buffer; - - handle->flags &= ~UV_HANDLE_READ_PENDING; - handle->tty.rd.read_line_buffer = uv_null_buf_; - - if (!REQ_SUCCESS(req)) { - /* Read was not successful */ - if (handle->flags & UV_HANDLE_READING) { - /* Real error */ - handle->flags &= ~UV_HANDLE_READING; - DECREASE_ACTIVE_COUNT(loop, handle); - handle->read_cb((uv_stream_t*) handle, - uv_translate_sys_error(GET_REQ_ERROR(req)), - &buf); - } else { - /* The read was cancelled, or whatever we don't care */ - handle->read_cb((uv_stream_t*) handle, 0, &buf); - } - - } else { - if (!(handle->flags & UV_HANDLE_CANCELLATION_PENDING)) { - /* Read successful */ - /* TODO: read unicode, convert to utf-8 */ - DWORD bytes = req->u.io.overlapped.InternalHigh; - handle->read_cb((uv_stream_t*) handle, bytes, &buf); - } else { - handle->flags &= ~UV_HANDLE_CANCELLATION_PENDING; - handle->read_cb((uv_stream_t*) handle, 0, &buf); - } - } - - /* Wait for more input events. */ - if ((handle->flags & UV_HANDLE_READING) && - !(handle->flags & UV_HANDLE_READ_PENDING)) { - uv_tty_queue_read(loop, handle); - } - - DECREASE_PENDING_REQ_COUNT(handle); -} - - -void uv_process_tty_read_req(uv_loop_t* loop, uv_tty_t* handle, - uv_req_t* req) { - assert(handle->type == UV_TTY); - assert(handle->flags & UV_HANDLE_TTY_READABLE); - - /* If the read_line_buffer member is zero, it must have been an raw read. */ - /* Otherwise it was a line-buffered read. */ - /* FIXME: This is quite obscure. Use a flag or something. */ - if (handle->tty.rd.read_line_buffer.len == 0) { - uv_process_tty_read_raw_req(loop, handle, req); - } else { - uv_process_tty_read_line_req(loop, handle, req); - } -} - - -int uv_tty_read_start(uv_tty_t* handle, uv_alloc_cb alloc_cb, - uv_read_cb read_cb) { - uv_loop_t* loop = handle->loop; - - if (!(handle->flags & UV_HANDLE_TTY_READABLE)) { - return ERROR_INVALID_PARAMETER; - } - - handle->flags |= UV_HANDLE_READING; - INCREASE_ACTIVE_COUNT(loop, handle); - handle->read_cb = read_cb; - handle->alloc_cb = alloc_cb; - - /* If reading was stopped and then started again, there could still be a */ - /* read request pending. */ - if (handle->flags & UV_HANDLE_READ_PENDING) { - return 0; - } - - /* Maybe the user stopped reading half-way while processing key events. */ - /* Short-circuit if this could be the case. */ - if (handle->tty.rd.last_key_len > 0) { - SET_REQ_SUCCESS(&handle->read_req); - uv_insert_pending_req(handle->loop, (uv_req_t*) &handle->read_req); - /* Make sure no attempt is made to insert it again until it's handled. */ - handle->flags |= UV_HANDLE_READ_PENDING; - handle->reqs_pending++; - return 0; - } - - uv_tty_queue_read(loop, handle); - - return 0; -} - - -int uv_tty_read_stop(uv_tty_t* handle) { - INPUT_RECORD record; - DWORD written, err; - - handle->flags &= ~UV_HANDLE_READING; - DECREASE_ACTIVE_COUNT(handle->loop, handle); - - if (!(handle->flags & UV_HANDLE_READ_PENDING)) - return 0; - - if (handle->flags & UV_HANDLE_TTY_RAW) { - /* Cancel raw read */ - /* Write some bullshit event to force the console wait to return. */ - memset(&record, 0, sizeof record); - if (!WriteConsoleInputW(handle->handle, &record, 1, &written)) { - return GetLastError(); - } - } else if (!(handle->flags & UV_HANDLE_CANCELLATION_PENDING)) { - /* Cancel line-buffered read if not already pending */ - err = uv__cancel_read_console(handle); - if (err) - return err; - - handle->flags |= UV_HANDLE_CANCELLATION_PENDING; - } - - return 0; -} - -static int uv__cancel_read_console(uv_tty_t* handle) { - HANDLE active_screen_buffer = INVALID_HANDLE_VALUE; - INPUT_RECORD record; - DWORD written; - DWORD err = 0; - LONG status; - - assert(!(handle->flags & UV_HANDLE_CANCELLATION_PENDING)); - - /* Hold the output lock during the cancellation, to ensure that further - writes don't interfere with the screen state. It will be the ReadConsole - thread's responsibility to release the lock. */ - uv_sem_wait(&uv_tty_output_lock); - status = InterlockedExchange(&uv__read_console_status, TRAP_REQUESTED); - if (status != IN_PROGRESS) { - /* Either we have managed to set a trap for the other thread before - ReadConsole is called, or ReadConsole has returned because the user - has pressed ENTER. In either case, there is nothing else to do. */ - uv_sem_post(&uv_tty_output_lock); - return 0; - } - - /* Save screen state before sending the VK_RETURN event */ - active_screen_buffer = CreateFileA("conout$", - GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL); - - if (active_screen_buffer != INVALID_HANDLE_VALUE && - GetConsoleScreenBufferInfo(active_screen_buffer, - &uv__saved_screen_state)) { - InterlockedOr(&uv__restore_screen_state, 1); - } - - /* Write enter key event to force the console wait to return. */ - record.EventType = KEY_EVENT; - record.Event.KeyEvent.bKeyDown = TRUE; - record.Event.KeyEvent.wRepeatCount = 1; - record.Event.KeyEvent.wVirtualKeyCode = VK_RETURN; - record.Event.KeyEvent.wVirtualScanCode = - MapVirtualKeyW(VK_RETURN, MAPVK_VK_TO_VSC); - record.Event.KeyEvent.uChar.UnicodeChar = L'\r'; - record.Event.KeyEvent.dwControlKeyState = 0; - if (!WriteConsoleInputW(handle->handle, &record, 1, &written)) - err = GetLastError(); - - if (active_screen_buffer != INVALID_HANDLE_VALUE) - CloseHandle(active_screen_buffer); - - return err; -} - - -static void uv_tty_update_virtual_window(CONSOLE_SCREEN_BUFFER_INFO* info) { - int old_virtual_width = uv_tty_virtual_width; - int old_virtual_height = uv_tty_virtual_height; - - uv_tty_virtual_width = info->dwSize.X; - uv_tty_virtual_height = info->srWindow.Bottom - info->srWindow.Top + 1; - - /* Recompute virtual window offset row. */ - if (uv_tty_virtual_offset == -1) { - uv_tty_virtual_offset = info->dwCursorPosition.Y; - } else if (uv_tty_virtual_offset < info->dwCursorPosition.Y - - uv_tty_virtual_height + 1) { - /* If suddenly find the cursor outside of the virtual window, it must */ - /* have somehow scrolled. Update the virtual window offset. */ - uv_tty_virtual_offset = info->dwCursorPosition.Y - - uv_tty_virtual_height + 1; - } - if (uv_tty_virtual_offset + uv_tty_virtual_height > info->dwSize.Y) { - uv_tty_virtual_offset = info->dwSize.Y - uv_tty_virtual_height; - } - if (uv_tty_virtual_offset < 0) { - uv_tty_virtual_offset = 0; - } - - /* If the virtual window size changed, emit a SIGWINCH signal. Don't emit */ - /* if this was the first time the virtual window size was computed. */ - if (old_virtual_width != -1 && old_virtual_height != -1 && - (uv_tty_virtual_width != old_virtual_width || - uv_tty_virtual_height != old_virtual_height)) { - uv__signal_dispatch(SIGWINCH); - } -} - - -static COORD uv_tty_make_real_coord(uv_tty_t* handle, - CONSOLE_SCREEN_BUFFER_INFO* info, int x, unsigned char x_relative, int y, - unsigned char y_relative) { - COORD result; - - uv_tty_update_virtual_window(info); - - /* Adjust y position */ - if (y_relative) { - y = info->dwCursorPosition.Y + y; - } else { - y = uv_tty_virtual_offset + y; - } - /* Clip y to virtual client rectangle */ - if (y < uv_tty_virtual_offset) { - y = uv_tty_virtual_offset; - } else if (y >= uv_tty_virtual_offset + uv_tty_virtual_height) { - y = uv_tty_virtual_offset + uv_tty_virtual_height - 1; - } - - /* Adjust x */ - if (x_relative) { - x = info->dwCursorPosition.X + x; - } - /* Clip x */ - if (x < 0) { - x = 0; - } else if (x >= uv_tty_virtual_width) { - x = uv_tty_virtual_width - 1; - } - - result.X = (unsigned short) x; - result.Y = (unsigned short) y; - return result; -} - - -static int uv_tty_emit_text(uv_tty_t* handle, WCHAR buffer[], DWORD length, - DWORD* error) { - DWORD written; - - if (*error != ERROR_SUCCESS) { - return -1; - } - - if (!WriteConsoleW(handle->handle, - (void*) buffer, - length, - &written, - NULL)) { - *error = GetLastError(); - return -1; - } - - return 0; -} - - -static int uv_tty_move_caret(uv_tty_t* handle, int x, unsigned char x_relative, - int y, unsigned char y_relative, DWORD* error) { - CONSOLE_SCREEN_BUFFER_INFO info; - COORD pos; - - if (*error != ERROR_SUCCESS) { - return -1; - } - - retry: - if (!GetConsoleScreenBufferInfo(handle->handle, &info)) { - *error = GetLastError(); - } - - pos = uv_tty_make_real_coord(handle, &info, x, x_relative, y, y_relative); - - if (!SetConsoleCursorPosition(handle->handle, pos)) { - if (GetLastError() == ERROR_INVALID_PARAMETER) { - /* The console may be resized - retry */ - goto retry; - } else { - *error = GetLastError(); - return -1; - } - } - - return 0; -} - - -static int uv_tty_reset(uv_tty_t* handle, DWORD* error) { - const COORD origin = {0, 0}; - const WORD char_attrs = uv_tty_default_text_attributes; - CONSOLE_SCREEN_BUFFER_INFO info; - DWORD count, written; - - if (*error != ERROR_SUCCESS) { - return -1; - } - - /* Reset original text attributes. */ - if (!SetConsoleTextAttribute(handle->handle, char_attrs)) { - *error = GetLastError(); - return -1; - } - - /* Move the cursor position to (0, 0). */ - if (!SetConsoleCursorPosition(handle->handle, origin)) { - *error = GetLastError(); - return -1; - } - - /* Clear the screen buffer. */ - retry: - if (!GetConsoleScreenBufferInfo(handle->handle, &info)) { - *error = GetLastError(); - return -1; - } - - count = info.dwSize.X * info.dwSize.Y; - - if (!(FillConsoleOutputCharacterW(handle->handle, - L'\x20', - count, - origin, - &written) && - FillConsoleOutputAttribute(handle->handle, - char_attrs, - written, - origin, - &written))) { - if (GetLastError() == ERROR_INVALID_PARAMETER) { - /* The console may be resized - retry */ - goto retry; - } else { - *error = GetLastError(); - return -1; - } - } - - /* Move the virtual window up to the top. */ - uv_tty_virtual_offset = 0; - uv_tty_update_virtual_window(&info); - - return 0; -} - - -static int uv_tty_clear(uv_tty_t* handle, int dir, char entire_screen, - DWORD* error) { - CONSOLE_SCREEN_BUFFER_INFO info; - COORD start, end; - DWORD count, written; - - int x1, x2, y1, y2; - int x1r, x2r, y1r, y2r; - - if (*error != ERROR_SUCCESS) { - return -1; - } - - if (dir == 0) { - /* Clear from current position */ - x1 = 0; - x1r = 1; - } else { - /* Clear from column 0 */ - x1 = 0; - x1r = 0; - } - - if (dir == 1) { - /* Clear to current position */ - x2 = 0; - x2r = 1; - } else { - /* Clear to end of row. We pretend the console is 65536 characters wide, */ - /* uv_tty_make_real_coord will clip it to the actual console width. */ - x2 = 0xffff; - x2r = 0; - } - - if (!entire_screen) { - /* Stay on our own row */ - y1 = y2 = 0; - y1r = y2r = 1; - } else { - /* Apply columns direction to row */ - y1 = x1; - y1r = x1r; - y2 = x2; - y2r = x2r; - } - - retry: - if (!GetConsoleScreenBufferInfo(handle->handle, &info)) { - *error = GetLastError(); - return -1; - } - - start = uv_tty_make_real_coord(handle, &info, x1, x1r, y1, y1r); - end = uv_tty_make_real_coord(handle, &info, x2, x2r, y2, y2r); - count = (end.Y * info.dwSize.X + end.X) - - (start.Y * info.dwSize.X + start.X) + 1; - - if (!(FillConsoleOutputCharacterW(handle->handle, - L'\x20', - count, - start, - &written) && - FillConsoleOutputAttribute(handle->handle, - info.wAttributes, - written, - start, - &written))) { - if (GetLastError() == ERROR_INVALID_PARAMETER) { - /* The console may be resized - retry */ - goto retry; - } else { - *error = GetLastError(); - return -1; - } - } - - return 0; -} - -#define FLIP_FGBG \ - do { \ - WORD fg = info.wAttributes & 0xF; \ - WORD bg = info.wAttributes & 0xF0; \ - info.wAttributes &= 0xFF00; \ - info.wAttributes |= fg << 4; \ - info.wAttributes |= bg >> 4; \ - } while (0) - -static int uv_tty_set_style(uv_tty_t* handle, DWORD* error) { - unsigned short argc = handle->tty.wr.ansi_csi_argc; - unsigned short* argv = handle->tty.wr.ansi_csi_argv; - int i; - CONSOLE_SCREEN_BUFFER_INFO info; - - char fg_color = -1, bg_color = -1; - char fg_bright = -1, bg_bright = -1; - char inverse = -1; - - if (argc == 0) { - /* Reset mode */ - fg_color = uv_tty_default_fg_color; - bg_color = uv_tty_default_bg_color; - fg_bright = uv_tty_default_fg_bright; - bg_bright = uv_tty_default_bg_bright; - inverse = uv_tty_default_inverse; - } - - for (i = 0; i < argc; i++) { - short arg = argv[i]; - - if (arg == 0) { - /* Reset mode */ - fg_color = uv_tty_default_fg_color; - bg_color = uv_tty_default_bg_color; - fg_bright = uv_tty_default_fg_bright; - bg_bright = uv_tty_default_bg_bright; - inverse = uv_tty_default_inverse; - - } else if (arg == 1) { - /* Foreground bright on */ - fg_bright = 1; - - } else if (arg == 2) { - /* Both bright off */ - fg_bright = 0; - bg_bright = 0; - - } else if (arg == 5) { - /* Background bright on */ - bg_bright = 1; - - } else if (arg == 7) { - /* Inverse: on */ - inverse = 1; - - } else if (arg == 21 || arg == 22) { - /* Foreground bright off */ - fg_bright = 0; - - } else if (arg == 25) { - /* Background bright off */ - bg_bright = 0; - - } else if (arg == 27) { - /* Inverse: off */ - inverse = 0; - - } else if (arg >= 30 && arg <= 37) { - /* Set foreground color */ - fg_color = arg - 30; - - } else if (arg == 39) { - /* Default text color */ - fg_color = uv_tty_default_fg_color; - fg_bright = uv_tty_default_fg_bright; - - } else if (arg >= 40 && arg <= 47) { - /* Set background color */ - bg_color = arg - 40; - - } else if (arg == 49) { - /* Default background color */ - bg_color = uv_tty_default_bg_color; - bg_bright = uv_tty_default_bg_bright; - - } else if (arg >= 90 && arg <= 97) { - /* Set bold foreground color */ - fg_bright = 1; - fg_color = arg - 90; - - } else if (arg >= 100 && arg <= 107) { - /* Set bold background color */ - bg_bright = 1; - bg_color = arg - 100; - - } - } - - if (fg_color == -1 && bg_color == -1 && fg_bright == -1 && - bg_bright == -1 && inverse == -1) { - /* Nothing changed */ - return 0; - } - - if (!GetConsoleScreenBufferInfo(handle->handle, &info)) { - *error = GetLastError(); - return -1; - } - - if ((info.wAttributes & COMMON_LVB_REVERSE_VIDEO) > 0) { - FLIP_FGBG; - } - - if (fg_color != -1) { - info.wAttributes &= ~(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); - if (fg_color & 1) info.wAttributes |= FOREGROUND_RED; - if (fg_color & 2) info.wAttributes |= FOREGROUND_GREEN; - if (fg_color & 4) info.wAttributes |= FOREGROUND_BLUE; - } - - if (fg_bright != -1) { - if (fg_bright) { - info.wAttributes |= FOREGROUND_INTENSITY; - } else { - info.wAttributes &= ~FOREGROUND_INTENSITY; - } - } - - if (bg_color != -1) { - info.wAttributes &= ~(BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE); - if (bg_color & 1) info.wAttributes |= BACKGROUND_RED; - if (bg_color & 2) info.wAttributes |= BACKGROUND_GREEN; - if (bg_color & 4) info.wAttributes |= BACKGROUND_BLUE; - } - - if (bg_bright != -1) { - if (bg_bright) { - info.wAttributes |= BACKGROUND_INTENSITY; - } else { - info.wAttributes &= ~BACKGROUND_INTENSITY; - } - } - - if (inverse != -1) { - if (inverse) { - info.wAttributes |= COMMON_LVB_REVERSE_VIDEO; - } else { - info.wAttributes &= ~COMMON_LVB_REVERSE_VIDEO; - } - } - - if ((info.wAttributes & COMMON_LVB_REVERSE_VIDEO) > 0) { - FLIP_FGBG; - } - - if (!SetConsoleTextAttribute(handle->handle, info.wAttributes)) { - *error = GetLastError(); - return -1; - } - - return 0; -} - - -static int uv_tty_save_state(uv_tty_t* handle, unsigned char save_attributes, - DWORD* error) { - CONSOLE_SCREEN_BUFFER_INFO info; - - if (*error != ERROR_SUCCESS) { - return -1; - } - - if (!GetConsoleScreenBufferInfo(handle->handle, &info)) { - *error = GetLastError(); - return -1; - } - - uv_tty_update_virtual_window(&info); - - handle->tty.wr.saved_position.X = info.dwCursorPosition.X; - handle->tty.wr.saved_position.Y = info.dwCursorPosition.Y - uv_tty_virtual_offset; - handle->flags |= UV_HANDLE_TTY_SAVED_POSITION; - - if (save_attributes) { - handle->tty.wr.saved_attributes = info.wAttributes & - (FOREGROUND_INTENSITY | BACKGROUND_INTENSITY); - handle->flags |= UV_HANDLE_TTY_SAVED_ATTRIBUTES; - } - - return 0; -} - - -static int uv_tty_restore_state(uv_tty_t* handle, - unsigned char restore_attributes, DWORD* error) { - CONSOLE_SCREEN_BUFFER_INFO info; - WORD new_attributes; - - if (*error != ERROR_SUCCESS) { - return -1; - } - - if (handle->flags & UV_HANDLE_TTY_SAVED_POSITION) { - if (uv_tty_move_caret(handle, - handle->tty.wr.saved_position.X, - 0, - handle->tty.wr.saved_position.Y, - 0, - error) != 0) { - return -1; - } - } - - if (restore_attributes && - (handle->flags & UV_HANDLE_TTY_SAVED_ATTRIBUTES)) { - if (!GetConsoleScreenBufferInfo(handle->handle, &info)) { - *error = GetLastError(); - return -1; - } - - new_attributes = info.wAttributes; - new_attributes &= ~(FOREGROUND_INTENSITY | BACKGROUND_INTENSITY); - new_attributes |= handle->tty.wr.saved_attributes; - - if (!SetConsoleTextAttribute(handle->handle, new_attributes)) { - *error = GetLastError(); - return -1; - } - } - - return 0; -} - -static int uv_tty_set_cursor_visibility(uv_tty_t* handle, - BOOL visible, - DWORD* error) { - CONSOLE_CURSOR_INFO cursor_info; - - if (!GetConsoleCursorInfo(handle->handle, &cursor_info)) { - *error = GetLastError(); - return -1; - } - - cursor_info.bVisible = visible; - - if (!SetConsoleCursorInfo(handle->handle, &cursor_info)) { - *error = GetLastError(); - return -1; - } - - return 0; -} - -static int uv_tty_write_bufs(uv_tty_t* handle, - const uv_buf_t bufs[], - unsigned int nbufs, - DWORD* error) { - /* We can only write 8k characters at a time. Windows can't handle */ - /* much more characters in a single console write anyway. */ - WCHAR utf16_buf[MAX_CONSOLE_CHAR]; - WCHAR* utf16_buffer; - DWORD utf16_buf_used = 0; - unsigned int i, len, max_len, pos; - int allocate = 0; - -#define FLUSH_TEXT() \ - do { \ - pos = 0; \ - do { \ - len = utf16_buf_used - pos; \ - if (len > MAX_CONSOLE_CHAR) \ - len = MAX_CONSOLE_CHAR; \ - uv_tty_emit_text(handle, &utf16_buffer[pos], len, error); \ - pos += len; \ - } while (pos < utf16_buf_used); \ - if (allocate) { \ - uv__free(utf16_buffer); \ - allocate = 0; \ - utf16_buffer = utf16_buf; \ - } \ - utf16_buf_used = 0; \ - } while (0) - -#define ENSURE_BUFFER_SPACE(wchars_needed) \ - if (wchars_needed > ARRAY_SIZE(utf16_buf) - utf16_buf_used) { \ - FLUSH_TEXT(); \ - } - - /* Cache for fast access */ - unsigned char utf8_bytes_left = handle->tty.wr.utf8_bytes_left; - unsigned int utf8_codepoint = handle->tty.wr.utf8_codepoint; - unsigned char previous_eol = handle->tty.wr.previous_eol; - unsigned char ansi_parser_state = handle->tty.wr.ansi_parser_state; - - /* Store the error here. If we encounter an error, stop trying to do i/o */ - /* but keep parsing the buffer so we leave the parser in a consistent */ - /* state. */ - *error = ERROR_SUCCESS; - - utf16_buffer = utf16_buf; - - uv_sem_wait(&uv_tty_output_lock); - - for (i = 0; i < nbufs; i++) { - uv_buf_t buf = bufs[i]; - unsigned int j; - - if (uv__vterm_state == UV_SUPPORTED && buf.len > 0) { - utf16_buf_used = MultiByteToWideChar(CP_UTF8, - 0, - buf.base, - buf.len, - NULL, - 0); - - if (utf16_buf_used == 0) { - *error = GetLastError(); - break; - } - - max_len = (utf16_buf_used + 1) * sizeof(WCHAR); - allocate = max_len > MAX_CONSOLE_CHAR; - if (allocate) - utf16_buffer = uv__malloc(max_len); - if (!MultiByteToWideChar(CP_UTF8, - 0, - buf.base, - buf.len, - utf16_buffer, - utf16_buf_used)) { - if (allocate) - uv__free(utf16_buffer); - *error = GetLastError(); - break; - } - - FLUSH_TEXT(); - - continue; - } - - for (j = 0; j < buf.len; j++) { - unsigned char c = buf.base[j]; - - /* Run the character through the utf8 decoder We happily accept non */ - /* shortest form encodings and invalid code points - there's no real */ - /* harm that can be done. */ - if (utf8_bytes_left == 0) { - /* Read utf-8 start byte */ - DWORD first_zero_bit; - unsigned char not_c = ~c; -#ifdef _MSC_VER /* msvc */ - if (_BitScanReverse(&first_zero_bit, not_c)) { -#else /* assume gcc */ - if (c != 0) { - first_zero_bit = (sizeof(int) * 8) - 1 - __builtin_clz(not_c); -#endif - if (first_zero_bit == 7) { - /* Ascii - pass right through */ - utf8_codepoint = (unsigned int) c; - - } else if (first_zero_bit <= 5) { - /* Multibyte sequence */ - utf8_codepoint = (0xff >> (8 - first_zero_bit)) & c; - utf8_bytes_left = (char) (6 - first_zero_bit); - - } else { - /* Invalid continuation */ - utf8_codepoint = UNICODE_REPLACEMENT_CHARACTER; - } - - } else { - /* 0xff -- invalid */ - utf8_codepoint = UNICODE_REPLACEMENT_CHARACTER; - } - - } else if ((c & 0xc0) == 0x80) { - /* Valid continuation of utf-8 multibyte sequence */ - utf8_bytes_left--; - utf8_codepoint <<= 6; - utf8_codepoint |= ((unsigned int) c & 0x3f); - - } else { - /* Start byte where continuation was expected. */ - utf8_bytes_left = 0; - utf8_codepoint = UNICODE_REPLACEMENT_CHARACTER; - /* Patch buf offset so this character will be parsed again as a */ - /* start byte. */ - j--; - } - - /* Maybe we need to parse more bytes to find a character. */ - if (utf8_bytes_left != 0) { - continue; - } - - /* Parse vt100/ansi escape codes */ - if (ansi_parser_state == ANSI_NORMAL) { - switch (utf8_codepoint) { - case '\033': - ansi_parser_state = ANSI_ESCAPE_SEEN; - continue; - - case 0233: - ansi_parser_state = ANSI_CSI; - handle->tty.wr.ansi_csi_argc = 0; - continue; - } - - } else if (ansi_parser_state == ANSI_ESCAPE_SEEN) { - switch (utf8_codepoint) { - case '[': - ansi_parser_state = ANSI_CSI; - handle->tty.wr.ansi_csi_argc = 0; - continue; - - case '^': - case '_': - case 'P': - case ']': - /* Not supported, but we'll have to parse until we see a stop */ - /* code, e.g. ESC \ or BEL. */ - ansi_parser_state = ANSI_ST_CONTROL; - continue; - - case '\033': - /* Ignore double escape. */ - continue; - - case 'c': - /* Full console reset. */ - FLUSH_TEXT(); - uv_tty_reset(handle, error); - ansi_parser_state = ANSI_NORMAL; - continue; - - case '7': - /* Save the cursor position and text attributes. */ - FLUSH_TEXT(); - uv_tty_save_state(handle, 1, error); - ansi_parser_state = ANSI_NORMAL; - continue; - - case '8': - /* Restore the cursor position and text attributes */ - FLUSH_TEXT(); - uv_tty_restore_state(handle, 1, error); - ansi_parser_state = ANSI_NORMAL; - continue; - - default: - if (utf8_codepoint >= '@' && utf8_codepoint <= '_') { - /* Single-char control. */ - ansi_parser_state = ANSI_NORMAL; - continue; - } else { - /* Invalid - proceed as normal, */ - ansi_parser_state = ANSI_NORMAL; - } - } - - } else if (ansi_parser_state & ANSI_CSI) { - if (!(ansi_parser_state & ANSI_IGNORE)) { - if (utf8_codepoint >= '0' && utf8_codepoint <= '9') { - /* Parsing a numerical argument */ - - if (!(ansi_parser_state & ANSI_IN_ARG)) { - /* We were not currently parsing a number */ - - /* Check for too many arguments */ - if (handle->tty.wr.ansi_csi_argc >= ARRAY_SIZE(handle->tty.wr.ansi_csi_argv)) { - ansi_parser_state |= ANSI_IGNORE; - continue; - } - - ansi_parser_state |= ANSI_IN_ARG; - handle->tty.wr.ansi_csi_argc++; - handle->tty.wr.ansi_csi_argv[handle->tty.wr.ansi_csi_argc - 1] = - (unsigned short) utf8_codepoint - '0'; - continue; - } else { - /* We were already parsing a number. Parse next digit. */ - uint32_t value = 10 * - handle->tty.wr.ansi_csi_argv[handle->tty.wr.ansi_csi_argc - 1]; - - /* Check for overflow. */ - if (value > UINT16_MAX) { - ansi_parser_state |= ANSI_IGNORE; - continue; - } - - handle->tty.wr.ansi_csi_argv[handle->tty.wr.ansi_csi_argc - 1] = - (unsigned short) value + (utf8_codepoint - '0'); - continue; - } - - } else if (utf8_codepoint == ';') { - /* Denotes the end of an argument. */ - if (ansi_parser_state & ANSI_IN_ARG) { - ansi_parser_state &= ~ANSI_IN_ARG; - continue; - - } else { - /* If ANSI_IN_ARG is not set, add another argument and */ - /* default it to 0. */ - /* Check for too many arguments */ - if (handle->tty.wr.ansi_csi_argc >= ARRAY_SIZE(handle->tty.wr.ansi_csi_argv)) { - ansi_parser_state |= ANSI_IGNORE; - continue; - } - - handle->tty.wr.ansi_csi_argc++; - handle->tty.wr.ansi_csi_argv[handle->tty.wr.ansi_csi_argc - 1] = 0; - continue; - } - - } else if (utf8_codepoint == '?' && !(ansi_parser_state & ANSI_IN_ARG) && - handle->tty.wr.ansi_csi_argc == 0) { - /* Ignores '?' if it is the first character after CSI[ */ - /* This is an extension character from the VT100 codeset */ - /* that is supported and used by most ANSI terminals today. */ - continue; - - } else if (utf8_codepoint >= '@' && utf8_codepoint <= '~' && - (handle->tty.wr.ansi_csi_argc > 0 || utf8_codepoint != '[')) { - int x, y, d; - - /* Command byte */ - switch (utf8_codepoint) { - case 'A': - /* cursor up */ - FLUSH_TEXT(); - y = -(handle->tty.wr.ansi_csi_argc ? handle->tty.wr.ansi_csi_argv[0] : 1); - uv_tty_move_caret(handle, 0, 1, y, 1, error); - break; - - case 'B': - /* cursor down */ - FLUSH_TEXT(); - y = handle->tty.wr.ansi_csi_argc ? handle->tty.wr.ansi_csi_argv[0] : 1; - uv_tty_move_caret(handle, 0, 1, y, 1, error); - break; - - case 'C': - /* cursor forward */ - FLUSH_TEXT(); - x = handle->tty.wr.ansi_csi_argc ? handle->tty.wr.ansi_csi_argv[0] : 1; - uv_tty_move_caret(handle, x, 1, 0, 1, error); - break; - - case 'D': - /* cursor back */ - FLUSH_TEXT(); - x = -(handle->tty.wr.ansi_csi_argc ? handle->tty.wr.ansi_csi_argv[0] : 1); - uv_tty_move_caret(handle, x, 1, 0, 1, error); - break; - - case 'E': - /* cursor next line */ - FLUSH_TEXT(); - y = handle->tty.wr.ansi_csi_argc ? handle->tty.wr.ansi_csi_argv[0] : 1; - uv_tty_move_caret(handle, 0, 0, y, 1, error); - break; - - case 'F': - /* cursor previous line */ - FLUSH_TEXT(); - y = -(handle->tty.wr.ansi_csi_argc ? handle->tty.wr.ansi_csi_argv[0] : 1); - uv_tty_move_caret(handle, 0, 0, y, 1, error); - break; - - case 'G': - /* cursor horizontal move absolute */ - FLUSH_TEXT(); - x = (handle->tty.wr.ansi_csi_argc >= 1 && handle->tty.wr.ansi_csi_argv[0]) - ? handle->tty.wr.ansi_csi_argv[0] - 1 : 0; - uv_tty_move_caret(handle, x, 0, 0, 1, error); - break; - - case 'H': - case 'f': - /* cursor move absolute */ - FLUSH_TEXT(); - y = (handle->tty.wr.ansi_csi_argc >= 1 && handle->tty.wr.ansi_csi_argv[0]) - ? handle->tty.wr.ansi_csi_argv[0] - 1 : 0; - x = (handle->tty.wr.ansi_csi_argc >= 2 && handle->tty.wr.ansi_csi_argv[1]) - ? handle->tty.wr.ansi_csi_argv[1] - 1 : 0; - uv_tty_move_caret(handle, x, 0, y, 0, error); - break; - - case 'J': - /* Erase screen */ - FLUSH_TEXT(); - d = handle->tty.wr.ansi_csi_argc ? handle->tty.wr.ansi_csi_argv[0] : 0; - if (d >= 0 && d <= 2) { - uv_tty_clear(handle, d, 1, error); - } - break; - - case 'K': - /* Erase line */ - FLUSH_TEXT(); - d = handle->tty.wr.ansi_csi_argc ? handle->tty.wr.ansi_csi_argv[0] : 0; - if (d >= 0 && d <= 2) { - uv_tty_clear(handle, d, 0, error); - } - break; - - case 'm': - /* Set style */ - FLUSH_TEXT(); - uv_tty_set_style(handle, error); - break; - - case 's': - /* Save the cursor position. */ - FLUSH_TEXT(); - uv_tty_save_state(handle, 0, error); - break; - - case 'u': - /* Restore the cursor position */ - FLUSH_TEXT(); - uv_tty_restore_state(handle, 0, error); - break; - - case 'l': - /* Hide the cursor */ - if (handle->tty.wr.ansi_csi_argc == 1 && - handle->tty.wr.ansi_csi_argv[0] == 25) { - FLUSH_TEXT(); - uv_tty_set_cursor_visibility(handle, 0, error); - } - break; - - case 'h': - /* Show the cursor */ - if (handle->tty.wr.ansi_csi_argc == 1 && - handle->tty.wr.ansi_csi_argv[0] == 25) { - FLUSH_TEXT(); - uv_tty_set_cursor_visibility(handle, 1, error); - } - break; - } - - /* Sequence ended - go back to normal state. */ - ansi_parser_state = ANSI_NORMAL; - continue; - - } else { - /* We don't support commands that use private mode characters or */ - /* intermediaries. Ignore the rest of the sequence. */ - ansi_parser_state |= ANSI_IGNORE; - continue; - } - } else { - /* We're ignoring this command. Stop only on command character. */ - if (utf8_codepoint >= '@' && utf8_codepoint <= '~') { - ansi_parser_state = ANSI_NORMAL; - } - continue; - } - - } else if (ansi_parser_state & ANSI_ST_CONTROL) { - /* Unsupported control code */ - /* Ignore everything until we see BEL or ESC \ */ - if (ansi_parser_state & ANSI_IN_STRING) { - if (!(ansi_parser_state & ANSI_BACKSLASH_SEEN)) { - if (utf8_codepoint == '"') { - ansi_parser_state &= ~ANSI_IN_STRING; - } else if (utf8_codepoint == '\\') { - ansi_parser_state |= ANSI_BACKSLASH_SEEN; - } - } else { - ansi_parser_state &= ~ANSI_BACKSLASH_SEEN; - } - } else { - if (utf8_codepoint == '\007' || (utf8_codepoint == '\\' && - (ansi_parser_state & ANSI_ESCAPE_SEEN))) { - /* End of sequence */ - ansi_parser_state = ANSI_NORMAL; - } else if (utf8_codepoint == '\033') { - /* Escape character */ - ansi_parser_state |= ANSI_ESCAPE_SEEN; - } else if (utf8_codepoint == '"') { - /* String starting */ - ansi_parser_state |= ANSI_IN_STRING; - ansi_parser_state &= ~ANSI_ESCAPE_SEEN; - ansi_parser_state &= ~ANSI_BACKSLASH_SEEN; - } else { - ansi_parser_state &= ~ANSI_ESCAPE_SEEN; - } - } - continue; - } else { - /* Inconsistent state */ - abort(); - } - - /* We wouldn't mind emitting utf-16 surrogate pairs. Too bad, the */ - /* windows console doesn't really support UTF-16, so just emit the */ - /* replacement character. */ - if (utf8_codepoint > 0xffff) { - utf8_codepoint = UNICODE_REPLACEMENT_CHARACTER; - } - - if (utf8_codepoint == 0x0a || utf8_codepoint == 0x0d) { - /* EOL conversion - emit \r\n when we see \n. */ - - if (utf8_codepoint == 0x0a && previous_eol != 0x0d) { - /* \n was not preceded by \r; print \r\n. */ - ENSURE_BUFFER_SPACE(2); - utf16_buf[utf16_buf_used++] = L'\r'; - utf16_buf[utf16_buf_used++] = L'\n'; - } else if (utf8_codepoint == 0x0d && previous_eol == 0x0a) { - /* \n was followed by \r; do not print the \r, since */ - /* the source was either \r\n\r (so the second \r is */ - /* redundant) or was \n\r (so the \n was processed */ - /* by the last case and an \r automatically inserted). */ - } else { - /* \r without \n; print \r as-is. */ - ENSURE_BUFFER_SPACE(1); - utf16_buf[utf16_buf_used++] = (WCHAR) utf8_codepoint; - } - - previous_eol = (char) utf8_codepoint; - - } else if (utf8_codepoint <= 0xffff) { - /* Encode character into utf-16 buffer. */ - ENSURE_BUFFER_SPACE(1); - utf16_buf[utf16_buf_used++] = (WCHAR) utf8_codepoint; - previous_eol = 0; - } - } - } - - /* Flush remaining characters */ - FLUSH_TEXT(); - - /* Copy cached values back to struct. */ - handle->tty.wr.utf8_bytes_left = utf8_bytes_left; - handle->tty.wr.utf8_codepoint = utf8_codepoint; - handle->tty.wr.previous_eol = previous_eol; - handle->tty.wr.ansi_parser_state = ansi_parser_state; - - uv_sem_post(&uv_tty_output_lock); - - if (*error == STATUS_SUCCESS) { - return 0; - } else { - return -1; - } - -#undef FLUSH_TEXT -} - - -int uv_tty_write(uv_loop_t* loop, - uv_write_t* req, - uv_tty_t* handle, - const uv_buf_t bufs[], - unsigned int nbufs, - uv_write_cb cb) { - DWORD error; - - uv_req_init(loop, (uv_req_t*) req); - req->type = UV_WRITE; - req->handle = (uv_stream_t*) handle; - req->cb = cb; - - handle->reqs_pending++; - handle->stream.conn.write_reqs_pending++; - REGISTER_HANDLE_REQ(loop, handle, req); - - req->u.io.queued_bytes = 0; - - if (!uv_tty_write_bufs(handle, bufs, nbufs, &error)) { - SET_REQ_SUCCESS(req); - } else { - SET_REQ_ERROR(req, error); - } - - uv_insert_pending_req(loop, (uv_req_t*) req); - - return 0; -} - - -int uv__tty_try_write(uv_tty_t* handle, - const uv_buf_t bufs[], - unsigned int nbufs) { - DWORD error; - - if (handle->stream.conn.write_reqs_pending > 0) - return UV_EAGAIN; - - if (uv_tty_write_bufs(handle, bufs, nbufs, &error)) - return uv_translate_sys_error(error); - - return uv__count_bufs(bufs, nbufs); -} - - -void uv_process_tty_write_req(uv_loop_t* loop, uv_tty_t* handle, - uv_write_t* req) { - int err; - - handle->write_queue_size -= req->u.io.queued_bytes; - UNREGISTER_HANDLE_REQ(loop, handle, req); - - if (req->cb) { - err = GET_REQ_ERROR(req); - req->cb(req, uv_translate_sys_error(err)); - } - - handle->stream.conn.write_reqs_pending--; - if (handle->stream.conn.shutdown_req != NULL && - handle->stream.conn.write_reqs_pending == 0) { - uv_want_endgame(loop, (uv_handle_t*)handle); - } - - DECREASE_PENDING_REQ_COUNT(handle); -} - - -void uv_tty_close(uv_tty_t* handle) { - assert(handle->u.fd == -1 || handle->u.fd > 2); - if (handle->u.fd == -1) - CloseHandle(handle->handle); - else - close(handle->u.fd); - - if (handle->flags & UV_HANDLE_READING) - uv_tty_read_stop(handle); - - handle->u.fd = -1; - handle->handle = INVALID_HANDLE_VALUE; - handle->flags &= ~(UV_HANDLE_READABLE | UV_HANDLE_WRITABLE); - uv__handle_closing(handle); - - if (handle->reqs_pending == 0) { - uv_want_endgame(handle->loop, (uv_handle_t*) handle); - } -} - - -void uv_tty_endgame(uv_loop_t* loop, uv_tty_t* handle) { - if (!(handle->flags & UV_HANDLE_TTY_READABLE) && - handle->stream.conn.shutdown_req != NULL && - handle->stream.conn.write_reqs_pending == 0) { - UNREGISTER_HANDLE_REQ(loop, handle, handle->stream.conn.shutdown_req); - - /* TTY shutdown is really just a no-op */ - if (handle->stream.conn.shutdown_req->cb) { - if (handle->flags & UV__HANDLE_CLOSING) { - handle->stream.conn.shutdown_req->cb(handle->stream.conn.shutdown_req, UV_ECANCELED); - } else { - handle->stream.conn.shutdown_req->cb(handle->stream.conn.shutdown_req, 0); - } - } - - handle->stream.conn.shutdown_req = NULL; - - DECREASE_PENDING_REQ_COUNT(handle); - return; - } - - if (handle->flags & UV__HANDLE_CLOSING && - handle->reqs_pending == 0) { - /* The wait handle used for raw reading should be unregistered when the */ - /* wait callback runs. */ - assert(!(handle->flags & UV_HANDLE_TTY_READABLE) || - handle->tty.rd.read_raw_wait == NULL); - - assert(!(handle->flags & UV_HANDLE_CLOSED)); - uv__handle_close(handle); - } -} - - -/* TODO: remove me */ -void uv_process_tty_accept_req(uv_loop_t* loop, uv_tty_t* handle, - uv_req_t* raw_req) { - abort(); -} - - -/* TODO: remove me */ -void uv_process_tty_connect_req(uv_loop_t* loop, uv_tty_t* handle, - uv_connect_t* req) { - abort(); -} - - -int uv_tty_reset_mode(void) { - /* Not necessary to do anything. */ - return 0; -} - -/* Determine whether or not this version of windows supports - * proper ANSI color codes. Should be supported as of windows - * 10 version 1511, build number 10.0.10586. - */ -static void uv__determine_vterm_state(HANDLE handle) { - DWORD dwMode = 0; - - if (!GetConsoleMode(handle, &dwMode)) { - uv__vterm_state = UV_UNSUPPORTED; - return; - } - - dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING; - if (!SetConsoleMode(handle, dwMode)) { - uv__vterm_state = UV_UNSUPPORTED; - return; - } - - uv__vterm_state = UV_SUPPORTED; -} diff --git a/vendor/libuv/src/win/udp.c b/vendor/libuv/src/win/udp.c deleted file mode 100644 index 9bf1453e5..000000000 --- a/vendor/libuv/src/win/udp.c +++ /dev/null @@ -1,928 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include -#include - -#include "uv.h" -#include "internal.h" -#include "handle-inl.h" -#include "stream-inl.h" -#include "req-inl.h" - - -/* - * Threshold of active udp streams for which to preallocate udp read buffers. - */ -const unsigned int uv_active_udp_streams_threshold = 0; - -/* A zero-size buffer for use by uv_udp_read */ -static char uv_zero_[] = ""; - -int uv_udp_getsockname(const uv_udp_t* handle, - struct sockaddr* name, - int* namelen) { - int result; - - if (handle->socket == INVALID_SOCKET) { - return UV_EINVAL; - } - - result = getsockname(handle->socket, name, namelen); - if (result != 0) { - return uv_translate_sys_error(WSAGetLastError()); - } - - return 0; -} - - -static int uv_udp_set_socket(uv_loop_t* loop, uv_udp_t* handle, SOCKET socket, - int family) { - DWORD yes = 1; - WSAPROTOCOL_INFOW info; - int opt_len; - - if (handle->socket != INVALID_SOCKET) - return UV_EBUSY; - - /* Set the socket to nonblocking mode */ - if (ioctlsocket(socket, FIONBIO, &yes) == SOCKET_ERROR) { - return WSAGetLastError(); - } - - /* Make the socket non-inheritable */ - if (!SetHandleInformation((HANDLE)socket, HANDLE_FLAG_INHERIT, 0)) { - return GetLastError(); - } - - /* Associate it with the I/O completion port. */ - /* Use uv_handle_t pointer as completion key. */ - if (CreateIoCompletionPort((HANDLE)socket, - loop->iocp, - (ULONG_PTR)socket, - 0) == NULL) { - return GetLastError(); - } - - if (pSetFileCompletionNotificationModes) { - /* All known Windows that support SetFileCompletionNotificationModes */ - /* have a bug that makes it impossible to use this function in */ - /* conjunction with datagram sockets. We can work around that but only */ - /* if the user is using the default UDP driver (AFD) and has no other */ - /* LSPs stacked on top. Here we check whether that is the case. */ - opt_len = (int) sizeof info; - if (getsockopt(socket, - SOL_SOCKET, - SO_PROTOCOL_INFOW, - (char*) &info, - &opt_len) == SOCKET_ERROR) { - return GetLastError(); - } - - if (info.ProtocolChain.ChainLen == 1) { - if (pSetFileCompletionNotificationModes((HANDLE)socket, - FILE_SKIP_SET_EVENT_ON_HANDLE | - FILE_SKIP_COMPLETION_PORT_ON_SUCCESS)) { - handle->flags |= UV_HANDLE_SYNC_BYPASS_IOCP; - handle->func_wsarecv = uv_wsarecv_workaround; - handle->func_wsarecvfrom = uv_wsarecvfrom_workaround; - } else if (GetLastError() != ERROR_INVALID_FUNCTION) { - return GetLastError(); - } - } - } - - handle->socket = socket; - - if (family == AF_INET6) { - handle->flags |= UV_HANDLE_IPV6; - } else { - assert(!(handle->flags & UV_HANDLE_IPV6)); - } - - return 0; -} - - -int uv_udp_init_ex(uv_loop_t* loop, uv_udp_t* handle, unsigned int flags) { - int domain; - - /* Use the lower 8 bits for the domain */ - domain = flags & 0xFF; - if (domain != AF_INET && domain != AF_INET6 && domain != AF_UNSPEC) - return UV_EINVAL; - - if (flags & ~0xFF) - return UV_EINVAL; - - uv__handle_init(loop, (uv_handle_t*) handle, UV_UDP); - handle->socket = INVALID_SOCKET; - handle->reqs_pending = 0; - handle->activecnt = 0; - handle->func_wsarecv = WSARecv; - handle->func_wsarecvfrom = WSARecvFrom; - handle->send_queue_size = 0; - handle->send_queue_count = 0; - uv_req_init(loop, (uv_req_t*) &(handle->recv_req)); - handle->recv_req.type = UV_UDP_RECV; - handle->recv_req.data = handle; - - /* If anything fails beyond this point we need to remove the handle from - * the handle queue, since it was added by uv__handle_init. - */ - - if (domain != AF_UNSPEC) { - SOCKET sock; - DWORD err; - - sock = socket(domain, SOCK_DGRAM, 0); - if (sock == INVALID_SOCKET) { - err = WSAGetLastError(); - QUEUE_REMOVE(&handle->handle_queue); - return uv_translate_sys_error(err); - } - - err = uv_udp_set_socket(handle->loop, handle, sock, domain); - if (err) { - closesocket(sock); - QUEUE_REMOVE(&handle->handle_queue); - return uv_translate_sys_error(err); - } - } - - return 0; -} - - -int uv_udp_init(uv_loop_t* loop, uv_udp_t* handle) { - return uv_udp_init_ex(loop, handle, AF_UNSPEC); -} - - -void uv_udp_close(uv_loop_t* loop, uv_udp_t* handle) { - uv_udp_recv_stop(handle); - closesocket(handle->socket); - handle->socket = INVALID_SOCKET; - - uv__handle_closing(handle); - - if (handle->reqs_pending == 0) { - uv_want_endgame(loop, (uv_handle_t*) handle); - } -} - - -void uv_udp_endgame(uv_loop_t* loop, uv_udp_t* handle) { - if (handle->flags & UV__HANDLE_CLOSING && - handle->reqs_pending == 0) { - assert(!(handle->flags & UV_HANDLE_CLOSED)); - uv__handle_close(handle); - } -} - - -static int uv_udp_maybe_bind(uv_udp_t* handle, - const struct sockaddr* addr, - unsigned int addrlen, - unsigned int flags) { - int r; - int err; - DWORD no = 0; - - if (handle->flags & UV_HANDLE_BOUND) - return 0; - - if ((flags & UV_UDP_IPV6ONLY) && addr->sa_family != AF_INET6) { - /* UV_UDP_IPV6ONLY is supported only for IPV6 sockets */ - return ERROR_INVALID_PARAMETER; - } - - if (handle->socket == INVALID_SOCKET) { - SOCKET sock = socket(addr->sa_family, SOCK_DGRAM, 0); - if (sock == INVALID_SOCKET) { - return WSAGetLastError(); - } - - err = uv_udp_set_socket(handle->loop, handle, sock, addr->sa_family); - if (err) { - closesocket(sock); - return err; - } - } - - if (flags & UV_UDP_REUSEADDR) { - DWORD yes = 1; - /* Set SO_REUSEADDR on the socket. */ - if (setsockopt(handle->socket, - SOL_SOCKET, - SO_REUSEADDR, - (char*) &yes, - sizeof yes) == SOCKET_ERROR) { - err = WSAGetLastError(); - return err; - } - } - - if (addr->sa_family == AF_INET6) - handle->flags |= UV_HANDLE_IPV6; - - if (addr->sa_family == AF_INET6 && !(flags & UV_UDP_IPV6ONLY)) { - /* On windows IPV6ONLY is on by default. */ - /* If the user doesn't specify it libuv turns it off. */ - - /* TODO: how to handle errors? This may fail if there is no ipv4 stack */ - /* available, or when run on XP/2003 which have no support for dualstack */ - /* sockets. For now we're silently ignoring the error. */ - setsockopt(handle->socket, - IPPROTO_IPV6, - IPV6_V6ONLY, - (char*) &no, - sizeof no); - } - - r = bind(handle->socket, addr, addrlen); - if (r == SOCKET_ERROR) { - return WSAGetLastError(); - } - - handle->flags |= UV_HANDLE_BOUND; - - return 0; -} - - -static void uv_udp_queue_recv(uv_loop_t* loop, uv_udp_t* handle) { - uv_req_t* req; - uv_buf_t buf; - DWORD bytes, flags; - int result; - - assert(handle->flags & UV_HANDLE_READING); - assert(!(handle->flags & UV_HANDLE_READ_PENDING)); - - req = &handle->recv_req; - memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped)); - - /* - * Preallocate a read buffer if the number of active streams is below - * the threshold. - */ - if (loop->active_udp_streams < uv_active_udp_streams_threshold) { - handle->flags &= ~UV_HANDLE_ZERO_READ; - - handle->recv_buffer = uv_buf_init(NULL, 0); - handle->alloc_cb((uv_handle_t*) handle, 65536, &handle->recv_buffer); - if (handle->recv_buffer.base == NULL || handle->recv_buffer.len == 0) { - handle->recv_cb(handle, UV_ENOBUFS, &handle->recv_buffer, NULL, 0); - return; - } - assert(handle->recv_buffer.base != NULL); - - buf = handle->recv_buffer; - memset(&handle->recv_from, 0, sizeof handle->recv_from); - handle->recv_from_len = sizeof handle->recv_from; - flags = 0; - - result = handle->func_wsarecvfrom(handle->socket, - (WSABUF*) &buf, - 1, - &bytes, - &flags, - (struct sockaddr*) &handle->recv_from, - &handle->recv_from_len, - &req->u.io.overlapped, - NULL); - - if (UV_SUCCEEDED_WITHOUT_IOCP(result == 0)) { - /* Process the req without IOCP. */ - handle->flags |= UV_HANDLE_READ_PENDING; - req->u.io.overlapped.InternalHigh = bytes; - handle->reqs_pending++; - uv_insert_pending_req(loop, req); - } else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) { - /* The req will be processed with IOCP. */ - handle->flags |= UV_HANDLE_READ_PENDING; - handle->reqs_pending++; - } else { - /* Make this req pending reporting an error. */ - SET_REQ_ERROR(req, WSAGetLastError()); - uv_insert_pending_req(loop, req); - handle->reqs_pending++; - } - - } else { - handle->flags |= UV_HANDLE_ZERO_READ; - - buf.base = (char*) uv_zero_; - buf.len = 0; - flags = MSG_PEEK; - - result = handle->func_wsarecv(handle->socket, - (WSABUF*) &buf, - 1, - &bytes, - &flags, - &req->u.io.overlapped, - NULL); - - if (UV_SUCCEEDED_WITHOUT_IOCP(result == 0)) { - /* Process the req without IOCP. */ - handle->flags |= UV_HANDLE_READ_PENDING; - req->u.io.overlapped.InternalHigh = bytes; - handle->reqs_pending++; - uv_insert_pending_req(loop, req); - } else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) { - /* The req will be processed with IOCP. */ - handle->flags |= UV_HANDLE_READ_PENDING; - handle->reqs_pending++; - } else { - /* Make this req pending reporting an error. */ - SET_REQ_ERROR(req, WSAGetLastError()); - uv_insert_pending_req(loop, req); - handle->reqs_pending++; - } - } -} - - -int uv__udp_recv_start(uv_udp_t* handle, uv_alloc_cb alloc_cb, - uv_udp_recv_cb recv_cb) { - uv_loop_t* loop = handle->loop; - int err; - - if (handle->flags & UV_HANDLE_READING) { - return WSAEALREADY; - } - - err = uv_udp_maybe_bind(handle, - (const struct sockaddr*) &uv_addr_ip4_any_, - sizeof(uv_addr_ip4_any_), - 0); - if (err) - return err; - - handle->flags |= UV_HANDLE_READING; - INCREASE_ACTIVE_COUNT(loop, handle); - loop->active_udp_streams++; - - handle->recv_cb = recv_cb; - handle->alloc_cb = alloc_cb; - - /* If reading was stopped and then started again, there could still be a */ - /* recv request pending. */ - if (!(handle->flags & UV_HANDLE_READ_PENDING)) - uv_udp_queue_recv(loop, handle); - - return 0; -} - - -int uv__udp_recv_stop(uv_udp_t* handle) { - if (handle->flags & UV_HANDLE_READING) { - handle->flags &= ~UV_HANDLE_READING; - handle->loop->active_udp_streams--; - DECREASE_ACTIVE_COUNT(loop, handle); - } - - return 0; -} - - -static int uv__send(uv_udp_send_t* req, - uv_udp_t* handle, - const uv_buf_t bufs[], - unsigned int nbufs, - const struct sockaddr* addr, - unsigned int addrlen, - uv_udp_send_cb cb) { - uv_loop_t* loop = handle->loop; - DWORD result, bytes; - - uv_req_init(loop, (uv_req_t*) req); - req->type = UV_UDP_SEND; - req->handle = handle; - req->cb = cb; - memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped)); - - result = WSASendTo(handle->socket, - (WSABUF*)bufs, - nbufs, - &bytes, - 0, - addr, - addrlen, - &req->u.io.overlapped, - NULL); - - if (UV_SUCCEEDED_WITHOUT_IOCP(result == 0)) { - /* Request completed immediately. */ - req->u.io.queued_bytes = 0; - handle->reqs_pending++; - handle->send_queue_size += req->u.io.queued_bytes; - handle->send_queue_count++; - REGISTER_HANDLE_REQ(loop, handle, req); - uv_insert_pending_req(loop, (uv_req_t*)req); - } else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) { - /* Request queued by the kernel. */ - req->u.io.queued_bytes = uv__count_bufs(bufs, nbufs); - handle->reqs_pending++; - handle->send_queue_size += req->u.io.queued_bytes; - handle->send_queue_count++; - REGISTER_HANDLE_REQ(loop, handle, req); - } else { - /* Send failed due to an error. */ - return WSAGetLastError(); - } - - return 0; -} - - -void uv_process_udp_recv_req(uv_loop_t* loop, uv_udp_t* handle, - uv_req_t* req) { - uv_buf_t buf; - int partial; - - assert(handle->type == UV_UDP); - - handle->flags &= ~UV_HANDLE_READ_PENDING; - - if (!REQ_SUCCESS(req)) { - DWORD err = GET_REQ_SOCK_ERROR(req); - if (err == WSAEMSGSIZE) { - /* Not a real error, it just indicates that the received packet */ - /* was bigger than the receive buffer. */ - } else if (err == WSAECONNRESET || err == WSAENETRESET) { - /* A previous sendto operation failed; ignore this error. If */ - /* zero-reading we need to call WSARecv/WSARecvFrom _without_ the */ - /* MSG_PEEK flag to clear out the error queue. For nonzero reads, */ - /* immediately queue a new receive. */ - if (!(handle->flags & UV_HANDLE_ZERO_READ)) { - goto done; - } - } else { - /* A real error occurred. Report the error to the user only if we're */ - /* currently reading. */ - if (handle->flags & UV_HANDLE_READING) { - uv_udp_recv_stop(handle); - buf = (handle->flags & UV_HANDLE_ZERO_READ) ? - uv_buf_init(NULL, 0) : handle->recv_buffer; - handle->recv_cb(handle, uv_translate_sys_error(err), &buf, NULL, 0); - } - goto done; - } - } - - if (!(handle->flags & UV_HANDLE_ZERO_READ)) { - /* Successful read */ - partial = !REQ_SUCCESS(req); - handle->recv_cb(handle, - req->u.io.overlapped.InternalHigh, - &handle->recv_buffer, - (const struct sockaddr*) &handle->recv_from, - partial ? UV_UDP_PARTIAL : 0); - } else if (handle->flags & UV_HANDLE_READING) { - DWORD bytes, err, flags; - struct sockaddr_storage from; - int from_len; - - /* Do a nonblocking receive */ - /* TODO: try to read multiple datagrams at once. FIONREAD maybe? */ - buf = uv_buf_init(NULL, 0); - handle->alloc_cb((uv_handle_t*) handle, 65536, &buf); - if (buf.base == NULL || buf.len == 0) { - handle->recv_cb(handle, UV_ENOBUFS, &buf, NULL, 0); - goto done; - } - assert(buf.base != NULL); - - memset(&from, 0, sizeof from); - from_len = sizeof from; - - flags = 0; - - if (WSARecvFrom(handle->socket, - (WSABUF*)&buf, - 1, - &bytes, - &flags, - (struct sockaddr*) &from, - &from_len, - NULL, - NULL) != SOCKET_ERROR) { - - /* Message received */ - handle->recv_cb(handle, bytes, &buf, (const struct sockaddr*) &from, 0); - } else { - err = WSAGetLastError(); - if (err == WSAEMSGSIZE) { - /* Message truncated */ - handle->recv_cb(handle, - bytes, - &buf, - (const struct sockaddr*) &from, - UV_UDP_PARTIAL); - } else if (err == WSAEWOULDBLOCK) { - /* Kernel buffer empty */ - handle->recv_cb(handle, 0, &buf, NULL, 0); - } else if (err == WSAECONNRESET || err == WSAENETRESET) { - /* WSAECONNRESET/WSANETRESET is ignored because this just indicates - * that a previous sendto operation failed. - */ - handle->recv_cb(handle, 0, &buf, NULL, 0); - } else { - /* Any other error that we want to report back to the user. */ - uv_udp_recv_stop(handle); - handle->recv_cb(handle, uv_translate_sys_error(err), &buf, NULL, 0); - } - } - } - -done: - /* Post another read if still reading and not closing. */ - if ((handle->flags & UV_HANDLE_READING) && - !(handle->flags & UV_HANDLE_READ_PENDING)) { - uv_udp_queue_recv(loop, handle); - } - - DECREASE_PENDING_REQ_COUNT(handle); -} - - -void uv_process_udp_send_req(uv_loop_t* loop, uv_udp_t* handle, - uv_udp_send_t* req) { - int err; - - assert(handle->type == UV_UDP); - - assert(handle->send_queue_size >= req->u.io.queued_bytes); - assert(handle->send_queue_count >= 1); - handle->send_queue_size -= req->u.io.queued_bytes; - handle->send_queue_count--; - - UNREGISTER_HANDLE_REQ(loop, handle, req); - - if (req->cb) { - err = 0; - if (!REQ_SUCCESS(req)) { - err = GET_REQ_SOCK_ERROR(req); - } - req->cb(req, uv_translate_sys_error(err)); - } - - DECREASE_PENDING_REQ_COUNT(handle); -} - - -static int uv__udp_set_membership4(uv_udp_t* handle, - const struct sockaddr_in* multicast_addr, - const char* interface_addr, - uv_membership membership) { - int err; - int optname; - struct ip_mreq mreq; - - if (handle->flags & UV_HANDLE_IPV6) - return UV_EINVAL; - - /* If the socket is unbound, bind to inaddr_any. */ - err = uv_udp_maybe_bind(handle, - (const struct sockaddr*) &uv_addr_ip4_any_, - sizeof(uv_addr_ip4_any_), - UV_UDP_REUSEADDR); - if (err) - return uv_translate_sys_error(err); - - memset(&mreq, 0, sizeof mreq); - - if (interface_addr) { - err = uv_inet_pton(AF_INET, interface_addr, &mreq.imr_interface.s_addr); - if (err) - return err; - } else { - mreq.imr_interface.s_addr = htonl(INADDR_ANY); - } - - mreq.imr_multiaddr.s_addr = multicast_addr->sin_addr.s_addr; - - switch (membership) { - case UV_JOIN_GROUP: - optname = IP_ADD_MEMBERSHIP; - break; - case UV_LEAVE_GROUP: - optname = IP_DROP_MEMBERSHIP; - break; - default: - return UV_EINVAL; - } - - if (setsockopt(handle->socket, - IPPROTO_IP, - optname, - (char*) &mreq, - sizeof mreq) == SOCKET_ERROR) { - return uv_translate_sys_error(WSAGetLastError()); - } - - return 0; -} - - -int uv__udp_set_membership6(uv_udp_t* handle, - const struct sockaddr_in6* multicast_addr, - const char* interface_addr, - uv_membership membership) { - int optname; - int err; - struct ipv6_mreq mreq; - struct sockaddr_in6 addr6; - - if ((handle->flags & UV_HANDLE_BOUND) && !(handle->flags & UV_HANDLE_IPV6)) - return UV_EINVAL; - - err = uv_udp_maybe_bind(handle, - (const struct sockaddr*) &uv_addr_ip6_any_, - sizeof(uv_addr_ip6_any_), - UV_UDP_REUSEADDR); - - if (err) - return uv_translate_sys_error(err); - - memset(&mreq, 0, sizeof(mreq)); - - if (interface_addr) { - if (uv_ip6_addr(interface_addr, 0, &addr6)) - return UV_EINVAL; - mreq.ipv6mr_interface = addr6.sin6_scope_id; - } else { - mreq.ipv6mr_interface = 0; - } - - mreq.ipv6mr_multiaddr = multicast_addr->sin6_addr; - - switch (membership) { - case UV_JOIN_GROUP: - optname = IPV6_ADD_MEMBERSHIP; - break; - case UV_LEAVE_GROUP: - optname = IPV6_DROP_MEMBERSHIP; - break; - default: - return UV_EINVAL; - } - - if (setsockopt(handle->socket, - IPPROTO_IPV6, - optname, - (char*) &mreq, - sizeof mreq) == SOCKET_ERROR) { - return uv_translate_sys_error(WSAGetLastError()); - } - - return 0; -} - - -int uv_udp_set_membership(uv_udp_t* handle, - const char* multicast_addr, - const char* interface_addr, - uv_membership membership) { - struct sockaddr_in addr4; - struct sockaddr_in6 addr6; - - if (uv_ip4_addr(multicast_addr, 0, &addr4) == 0) - return uv__udp_set_membership4(handle, &addr4, interface_addr, membership); - else if (uv_ip6_addr(multicast_addr, 0, &addr6) == 0) - return uv__udp_set_membership6(handle, &addr6, interface_addr, membership); - else - return UV_EINVAL; -} - - -int uv_udp_set_multicast_interface(uv_udp_t* handle, const char* interface_addr) { - struct sockaddr_storage addr_st; - struct sockaddr_in* addr4; - struct sockaddr_in6* addr6; - - addr4 = (struct sockaddr_in*) &addr_st; - addr6 = (struct sockaddr_in6*) &addr_st; - - if (!interface_addr) { - memset(&addr_st, 0, sizeof addr_st); - if (handle->flags & UV_HANDLE_IPV6) { - addr_st.ss_family = AF_INET6; - addr6->sin6_scope_id = 0; - } else { - addr_st.ss_family = AF_INET; - addr4->sin_addr.s_addr = htonl(INADDR_ANY); - } - } else if (uv_ip4_addr(interface_addr, 0, addr4) == 0) { - /* nothing, address was parsed */ - } else if (uv_ip6_addr(interface_addr, 0, addr6) == 0) { - /* nothing, address was parsed */ - } else { - return UV_EINVAL; - } - - if (!(handle->flags & UV_HANDLE_BOUND)) - return UV_EBADF; - - if (addr_st.ss_family == AF_INET) { - if (setsockopt(handle->socket, - IPPROTO_IP, - IP_MULTICAST_IF, - (char*) &addr4->sin_addr, - sizeof(addr4->sin_addr)) == SOCKET_ERROR) { - return uv_translate_sys_error(WSAGetLastError()); - } - } else if (addr_st.ss_family == AF_INET6) { - if (setsockopt(handle->socket, - IPPROTO_IPV6, - IPV6_MULTICAST_IF, - (char*) &addr6->sin6_scope_id, - sizeof(addr6->sin6_scope_id)) == SOCKET_ERROR) { - return uv_translate_sys_error(WSAGetLastError()); - } - } else { - assert(0 && "unexpected address family"); - abort(); - } - - return 0; -} - - -int uv_udp_set_broadcast(uv_udp_t* handle, int value) { - BOOL optval = (BOOL) value; - - if (!(handle->flags & UV_HANDLE_BOUND)) - return UV_EBADF; - - if (setsockopt(handle->socket, - SOL_SOCKET, - SO_BROADCAST, - (char*) &optval, - sizeof optval)) { - return uv_translate_sys_error(WSAGetLastError()); - } - - return 0; -} - - -int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) { - WSAPROTOCOL_INFOW protocol_info; - int opt_len; - int err; - - /* Detect the address family of the socket. */ - opt_len = (int) sizeof protocol_info; - if (getsockopt(sock, - SOL_SOCKET, - SO_PROTOCOL_INFOW, - (char*) &protocol_info, - &opt_len) == SOCKET_ERROR) { - return uv_translate_sys_error(GetLastError()); - } - - err = uv_udp_set_socket(handle->loop, - handle, - sock, - protocol_info.iAddressFamily); - return uv_translate_sys_error(err); -} - - -#define SOCKOPT_SETTER(name, option4, option6, validate) \ - int uv_udp_set_##name(uv_udp_t* handle, int value) { \ - DWORD optval = (DWORD) value; \ - \ - if (!(validate(value))) { \ - return UV_EINVAL; \ - } \ - \ - if (!(handle->flags & UV_HANDLE_BOUND)) \ - return UV_EBADF; \ - \ - if (!(handle->flags & UV_HANDLE_IPV6)) { \ - /* Set IPv4 socket option */ \ - if (setsockopt(handle->socket, \ - IPPROTO_IP, \ - option4, \ - (char*) &optval, \ - sizeof optval)) { \ - return uv_translate_sys_error(WSAGetLastError()); \ - } \ - } else { \ - /* Set IPv6 socket option */ \ - if (setsockopt(handle->socket, \ - IPPROTO_IPV6, \ - option6, \ - (char*) &optval, \ - sizeof optval)) { \ - return uv_translate_sys_error(WSAGetLastError()); \ - } \ - } \ - return 0; \ - } - -#define VALIDATE_TTL(value) ((value) >= 1 && (value) <= 255) -#define VALIDATE_MULTICAST_TTL(value) ((value) >= -1 && (value) <= 255) -#define VALIDATE_MULTICAST_LOOP(value) (1) - -SOCKOPT_SETTER(ttl, - IP_TTL, - IPV6_HOPLIMIT, - VALIDATE_TTL) -SOCKOPT_SETTER(multicast_ttl, - IP_MULTICAST_TTL, - IPV6_MULTICAST_HOPS, - VALIDATE_MULTICAST_TTL) -SOCKOPT_SETTER(multicast_loop, - IP_MULTICAST_LOOP, - IPV6_MULTICAST_LOOP, - VALIDATE_MULTICAST_LOOP) - -#undef SOCKOPT_SETTER -#undef VALIDATE_TTL -#undef VALIDATE_MULTICAST_TTL -#undef VALIDATE_MULTICAST_LOOP - - -/* This function is an egress point, i.e. it returns libuv errors rather than - * system errors. - */ -int uv__udp_bind(uv_udp_t* handle, - const struct sockaddr* addr, - unsigned int addrlen, - unsigned int flags) { - int err; - - err = uv_udp_maybe_bind(handle, addr, addrlen, flags); - if (err) - return uv_translate_sys_error(err); - - return 0; -} - - -/* This function is an egress point, i.e. it returns libuv errors rather than - * system errors. - */ -int uv__udp_send(uv_udp_send_t* req, - uv_udp_t* handle, - const uv_buf_t bufs[], - unsigned int nbufs, - const struct sockaddr* addr, - unsigned int addrlen, - uv_udp_send_cb send_cb) { - const struct sockaddr* bind_addr; - int err; - - if (!(handle->flags & UV_HANDLE_BOUND)) { - if (addrlen == sizeof(uv_addr_ip4_any_)) { - bind_addr = (const struct sockaddr*) &uv_addr_ip4_any_; - } else if (addrlen == sizeof(uv_addr_ip6_any_)) { - bind_addr = (const struct sockaddr*) &uv_addr_ip6_any_; - } else { - abort(); - } - err = uv_udp_maybe_bind(handle, bind_addr, addrlen, 0); - if (err) - return uv_translate_sys_error(err); - } - - err = uv__send(req, handle, bufs, nbufs, addr, addrlen, send_cb); - if (err) - return uv_translate_sys_error(err); - - return 0; -} - - -int uv__udp_try_send(uv_udp_t* handle, - const uv_buf_t bufs[], - unsigned int nbufs, - const struct sockaddr* addr, - unsigned int addrlen) { - return UV_ENOSYS; -} diff --git a/vendor/libuv/src/win/util.c b/vendor/libuv/src/win/util.c deleted file mode 100644 index 050058afa..000000000 --- a/vendor/libuv/src/win/util.c +++ /dev/null @@ -1,1389 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "uv.h" -#include "internal.h" - -#include -#include -#include -#include -#include -#include -#include - - -/* - * Max title length; the only thing MSDN tells us about the maximum length - * of the console title is that it is smaller than 64K. However in practice - * it is much smaller, and there is no way to figure out what the exact length - * of the title is or can be, at least not on XP. To make it even more - * annoying, GetConsoleTitle fails when the buffer to be read into is bigger - * than the actual maximum length. So we make a conservative guess here; - * just don't put the novel you're writing in the title, unless the plot - * survives truncation. - */ -#define MAX_TITLE_LENGTH 8192 - -/* The number of nanoseconds in one second. */ -#define UV__NANOSEC 1000000000 - -/* Max user name length, from iphlpapi.h */ -#ifndef UNLEN -# define UNLEN 256 -#endif - -/* Cached copy of the process title, plus a mutex guarding it. */ -static char *process_title; -static CRITICAL_SECTION process_title_lock; - -/* Cached copy of the process id, written once. */ -static DWORD current_pid = 0; - - -/* Interval (in seconds) of the high-resolution clock. */ -static double hrtime_interval_ = 0; - - -/* - * One-time initialization code for functionality defined in util.c. - */ -void uv__util_init() { - LARGE_INTEGER perf_frequency; - - /* Initialize process title access mutex. */ - InitializeCriticalSection(&process_title_lock); - - /* Retrieve high-resolution timer frequency - * and precompute its reciprocal. - */ - if (QueryPerformanceFrequency(&perf_frequency)) { - hrtime_interval_ = 1.0 / perf_frequency.QuadPart; - } else { - hrtime_interval_= 0; - } -} - - -int uv_exepath(char* buffer, size_t* size_ptr) { - int utf8_len, utf16_buffer_len, utf16_len; - WCHAR* utf16_buffer; - int err; - - if (buffer == NULL || size_ptr == NULL || *size_ptr == 0) { - return UV_EINVAL; - } - - if (*size_ptr > 32768) { - /* Windows paths can never be longer than this. */ - utf16_buffer_len = 32768; - } else { - utf16_buffer_len = (int) *size_ptr; - } - - utf16_buffer = (WCHAR*) uv__malloc(sizeof(WCHAR) * utf16_buffer_len); - if (!utf16_buffer) { - return UV_ENOMEM; - } - - /* Get the path as UTF-16. */ - utf16_len = GetModuleFileNameW(NULL, utf16_buffer, utf16_buffer_len); - if (utf16_len <= 0) { - err = GetLastError(); - goto error; - } - - /* utf16_len contains the length, *not* including the terminating null. */ - utf16_buffer[utf16_len] = L'\0'; - - /* Convert to UTF-8 */ - utf8_len = WideCharToMultiByte(CP_UTF8, - 0, - utf16_buffer, - -1, - buffer, - (int) *size_ptr, - NULL, - NULL); - if (utf8_len == 0) { - err = GetLastError(); - goto error; - } - - uv__free(utf16_buffer); - - /* utf8_len *does* include the terminating null at this point, but the */ - /* returned size shouldn't. */ - *size_ptr = utf8_len - 1; - return 0; - - error: - uv__free(utf16_buffer); - return uv_translate_sys_error(err); -} - - -int uv_cwd(char* buffer, size_t* size) { - DWORD utf16_len; - WCHAR utf16_buffer[MAX_PATH]; - int r; - - if (buffer == NULL || size == NULL) { - return UV_EINVAL; - } - - utf16_len = GetCurrentDirectoryW(MAX_PATH, utf16_buffer); - if (utf16_len == 0) { - return uv_translate_sys_error(GetLastError()); - } else if (utf16_len > MAX_PATH) { - /* This should be impossible; however the CRT has a code path to deal */ - /* with this scenario, so I added a check anyway. */ - return UV_EIO; - } - - /* utf16_len contains the length, *not* including the terminating null. */ - utf16_buffer[utf16_len] = L'\0'; - - /* The returned directory should not have a trailing slash, unless it */ - /* points at a drive root, like c:\. Remove it if needed.*/ - if (utf16_buffer[utf16_len - 1] == L'\\' && - !(utf16_len == 3 && utf16_buffer[1] == L':')) { - utf16_len--; - utf16_buffer[utf16_len] = L'\0'; - } - - /* Check how much space we need */ - r = WideCharToMultiByte(CP_UTF8, - 0, - utf16_buffer, - -1, - NULL, - 0, - NULL, - NULL); - if (r == 0) { - return uv_translate_sys_error(GetLastError()); - } else if (r > (int) *size) { - *size = r; - return UV_ENOBUFS; - } - - /* Convert to UTF-8 */ - r = WideCharToMultiByte(CP_UTF8, - 0, - utf16_buffer, - -1, - buffer, - *size > INT_MAX ? INT_MAX : (int) *size, - NULL, - NULL); - if (r == 0) { - return uv_translate_sys_error(GetLastError()); - } - - *size = r - 1; - return 0; -} - - -int uv_chdir(const char* dir) { - WCHAR utf16_buffer[MAX_PATH]; - size_t utf16_len; - WCHAR drive_letter, env_var[4]; - - if (dir == NULL) { - return UV_EINVAL; - } - - if (MultiByteToWideChar(CP_UTF8, - 0, - dir, - -1, - utf16_buffer, - MAX_PATH) == 0) { - DWORD error = GetLastError(); - /* The maximum length of the current working directory is 260 chars, */ - /* including terminating null. If it doesn't fit, the path name must be */ - /* too long. */ - if (error == ERROR_INSUFFICIENT_BUFFER) { - return UV_ENAMETOOLONG; - } else { - return uv_translate_sys_error(error); - } - } - - if (!SetCurrentDirectoryW(utf16_buffer)) { - return uv_translate_sys_error(GetLastError()); - } - - /* Windows stores the drive-local path in an "hidden" environment variable, */ - /* which has the form "=C:=C:\Windows". SetCurrentDirectory does not */ - /* update this, so we'll have to do it. */ - utf16_len = GetCurrentDirectoryW(MAX_PATH, utf16_buffer); - if (utf16_len == 0) { - return uv_translate_sys_error(GetLastError()); - } else if (utf16_len > MAX_PATH) { - return UV_EIO; - } - - /* The returned directory should not have a trailing slash, unless it */ - /* points at a drive root, like c:\. Remove it if needed. */ - if (utf16_buffer[utf16_len - 1] == L'\\' && - !(utf16_len == 3 && utf16_buffer[1] == L':')) { - utf16_len--; - utf16_buffer[utf16_len] = L'\0'; - } - - if (utf16_len < 2 || utf16_buffer[1] != L':') { - /* Doesn't look like a drive letter could be there - probably an UNC */ - /* path. TODO: Need to handle win32 namespaces like \\?\C:\ ? */ - drive_letter = 0; - } else if (utf16_buffer[0] >= L'A' && utf16_buffer[0] <= L'Z') { - drive_letter = utf16_buffer[0]; - } else if (utf16_buffer[0] >= L'a' && utf16_buffer[0] <= L'z') { - /* Convert to uppercase. */ - drive_letter = utf16_buffer[0] - L'a' + L'A'; - } else { - /* Not valid. */ - drive_letter = 0; - } - - if (drive_letter != 0) { - /* Construct the environment variable name and set it. */ - env_var[0] = L'='; - env_var[1] = drive_letter; - env_var[2] = L':'; - env_var[3] = L'\0'; - - if (!SetEnvironmentVariableW(env_var, utf16_buffer)) { - return uv_translate_sys_error(GetLastError()); - } - } - - return 0; -} - - -void uv_loadavg(double avg[3]) { - /* Can't be implemented */ - avg[0] = avg[1] = avg[2] = 0; -} - - -uint64_t uv_get_free_memory(void) { - MEMORYSTATUSEX memory_status; - memory_status.dwLength = sizeof(memory_status); - - if (!GlobalMemoryStatusEx(&memory_status)) { - return -1; - } - - return (uint64_t)memory_status.ullAvailPhys; -} - - -uint64_t uv_get_total_memory(void) { - MEMORYSTATUSEX memory_status; - memory_status.dwLength = sizeof(memory_status); - - if (!GlobalMemoryStatusEx(&memory_status)) { - return -1; - } - - return (uint64_t)memory_status.ullTotalPhys; -} - - -int uv_parent_pid() { - int parent_pid = -1; - HANDLE handle; - PROCESSENTRY32 pe; - DWORD current_pid = GetCurrentProcessId(); - - pe.dwSize = sizeof(PROCESSENTRY32); - handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); - - if (Process32First(handle, &pe)) { - do { - if (pe.th32ProcessID == current_pid) { - parent_pid = pe.th32ParentProcessID; - break; - } - } while( Process32Next(handle, &pe)); - } - - CloseHandle(handle); - return parent_pid; -} - - -int uv_current_pid() { - if (current_pid == 0) { - current_pid = GetCurrentProcessId(); - } - return current_pid; -} - - -char** uv_setup_args(int argc, char** argv) { - return argv; -} - - -int uv_set_process_title(const char* title) { - int err; - int length; - WCHAR* title_w = NULL; - - uv__once_init(); - - /* Find out how big the buffer for the wide-char title must be */ - length = MultiByteToWideChar(CP_UTF8, 0, title, -1, NULL, 0); - if (!length) { - err = GetLastError(); - goto done; - } - - /* Convert to wide-char string */ - title_w = (WCHAR*)uv__malloc(sizeof(WCHAR) * length); - if (!title_w) { - uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc"); - } - - length = MultiByteToWideChar(CP_UTF8, 0, title, -1, title_w, length); - if (!length) { - err = GetLastError(); - goto done; - } - - /* If the title must be truncated insert a \0 terminator there */ - if (length > MAX_TITLE_LENGTH) { - title_w[MAX_TITLE_LENGTH - 1] = L'\0'; - } - - if (!SetConsoleTitleW(title_w)) { - err = GetLastError(); - goto done; - } - - EnterCriticalSection(&process_title_lock); - uv__free(process_title); - process_title = uv__strdup(title); - LeaveCriticalSection(&process_title_lock); - - err = 0; - -done: - uv__free(title_w); - return uv_translate_sys_error(err); -} - - -static int uv__get_process_title() { - WCHAR title_w[MAX_TITLE_LENGTH]; - - if (!GetConsoleTitleW(title_w, sizeof(title_w) / sizeof(WCHAR))) { - return -1; - } - - if (uv__convert_utf16_to_utf8(title_w, -1, &process_title) != 0) - return -1; - - return 0; -} - - -int uv_get_process_title(char* buffer, size_t size) { - size_t len; - - if (buffer == NULL || size == 0) - return UV_EINVAL; - - uv__once_init(); - - EnterCriticalSection(&process_title_lock); - /* - * If the process_title was never read before nor explicitly set, - * we must query it with getConsoleTitleW - */ - if (!process_title && uv__get_process_title() == -1) { - LeaveCriticalSection(&process_title_lock); - return uv_translate_sys_error(GetLastError()); - } - - assert(process_title); - len = strlen(process_title) + 1; - - if (size < len) { - LeaveCriticalSection(&process_title_lock); - return UV_ENOBUFS; - } - - memcpy(buffer, process_title, len); - LeaveCriticalSection(&process_title_lock); - - return 0; -} - - -uint64_t uv_hrtime(void) { - uv__once_init(); - return uv__hrtime(UV__NANOSEC); -} - -uint64_t uv__hrtime(double scale) { - LARGE_INTEGER counter; - - /* If the performance interval is zero, there's no support. */ - if (hrtime_interval_ == 0) { - return 0; - } - - if (!QueryPerformanceCounter(&counter)) { - return 0; - } - - /* Because we have no guarantee about the order of magnitude of the - * performance counter interval, integer math could cause this computation - * to overflow. Therefore we resort to floating point math. - */ - return (uint64_t) ((double) counter.QuadPart * hrtime_interval_ * scale); -} - - -int uv_resident_set_memory(size_t* rss) { - HANDLE current_process; - PROCESS_MEMORY_COUNTERS pmc; - - current_process = GetCurrentProcess(); - - if (!GetProcessMemoryInfo(current_process, &pmc, sizeof(pmc))) { - return uv_translate_sys_error(GetLastError()); - } - - *rss = pmc.WorkingSetSize; - - return 0; -} - - -int uv_uptime(double* uptime) { - BYTE stack_buffer[4096]; - BYTE* malloced_buffer = NULL; - BYTE* buffer = (BYTE*) stack_buffer; - size_t buffer_size = sizeof(stack_buffer); - DWORD data_size; - - PERF_DATA_BLOCK* data_block; - PERF_OBJECT_TYPE* object_type; - PERF_COUNTER_DEFINITION* counter_definition; - - DWORD i; - - for (;;) { - LONG result; - - data_size = (DWORD) buffer_size; - result = RegQueryValueExW(HKEY_PERFORMANCE_DATA, - L"2", - NULL, - NULL, - buffer, - &data_size); - if (result == ERROR_SUCCESS) { - break; - } else if (result != ERROR_MORE_DATA) { - *uptime = 0; - return uv_translate_sys_error(result); - } - - buffer_size *= 2; - /* Don't let the buffer grow infinitely. */ - if (buffer_size > 1 << 20) { - goto internalError; - } - - uv__free(malloced_buffer); - - buffer = malloced_buffer = (BYTE*) uv__malloc(buffer_size); - if (malloced_buffer == NULL) { - *uptime = 0; - return UV_ENOMEM; - } - } - - if (data_size < sizeof(*data_block)) - goto internalError; - - data_block = (PERF_DATA_BLOCK*) buffer; - - if (wmemcmp(data_block->Signature, L"PERF", 4) != 0) - goto internalError; - - if (data_size < data_block->HeaderLength + sizeof(*object_type)) - goto internalError; - - object_type = (PERF_OBJECT_TYPE*) (buffer + data_block->HeaderLength); - - if (object_type->NumInstances != PERF_NO_INSTANCES) - goto internalError; - - counter_definition = (PERF_COUNTER_DEFINITION*) (buffer + - data_block->HeaderLength + object_type->HeaderLength); - for (i = 0; i < object_type->NumCounters; i++) { - if ((BYTE*) counter_definition + sizeof(*counter_definition) > - buffer + data_size) { - break; - } - - if (counter_definition->CounterNameTitleIndex == 674 && - counter_definition->CounterSize == sizeof(uint64_t)) { - if (counter_definition->CounterOffset + sizeof(uint64_t) > data_size || - !(counter_definition->CounterType & PERF_OBJECT_TIMER)) { - goto internalError; - } else { - BYTE* address = (BYTE*) object_type + object_type->DefinitionLength + - counter_definition->CounterOffset; - uint64_t value = *((uint64_t*) address); - *uptime = (double) (object_type->PerfTime.QuadPart - value) / - (double) object_type->PerfFreq.QuadPart; - uv__free(malloced_buffer); - return 0; - } - } - - counter_definition = (PERF_COUNTER_DEFINITION*) - ((BYTE*) counter_definition + counter_definition->ByteLength); - } - - /* If we get here, the uptime value was not found. */ - uv__free(malloced_buffer); - *uptime = 0; - return UV_ENOSYS; - - internalError: - uv__free(malloced_buffer); - *uptime = 0; - return UV_EIO; -} - - -int uv_cpu_info(uv_cpu_info_t** cpu_infos_ptr, int* cpu_count_ptr) { - uv_cpu_info_t* cpu_infos; - SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION* sppi; - DWORD sppi_size; - SYSTEM_INFO system_info; - DWORD cpu_count, r, i; - NTSTATUS status; - ULONG result_size; - int err; - uv_cpu_info_t* cpu_info; - - cpu_infos = NULL; - cpu_count = 0; - sppi = NULL; - - uv__once_init(); - - GetSystemInfo(&system_info); - cpu_count = system_info.dwNumberOfProcessors; - - cpu_infos = uv__calloc(cpu_count, sizeof *cpu_infos); - if (cpu_infos == NULL) { - err = ERROR_OUTOFMEMORY; - goto error; - } - - sppi_size = cpu_count * sizeof(*sppi); - sppi = uv__malloc(sppi_size); - if (sppi == NULL) { - err = ERROR_OUTOFMEMORY; - goto error; - } - - status = pNtQuerySystemInformation(SystemProcessorPerformanceInformation, - sppi, - sppi_size, - &result_size); - if (!NT_SUCCESS(status)) { - err = pRtlNtStatusToDosError(status); - goto error; - } - - assert(result_size == sppi_size); - - for (i = 0; i < cpu_count; i++) { - WCHAR key_name[128]; - HKEY processor_key; - DWORD cpu_speed; - DWORD cpu_speed_size = sizeof(cpu_speed); - WCHAR cpu_brand[256]; - DWORD cpu_brand_size = sizeof(cpu_brand); - size_t len; - - len = _snwprintf(key_name, - ARRAY_SIZE(key_name), - L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\%d", - i); - - assert(len > 0 && len < ARRAY_SIZE(key_name)); - - r = RegOpenKeyExW(HKEY_LOCAL_MACHINE, - key_name, - 0, - KEY_QUERY_VALUE, - &processor_key); - if (r != ERROR_SUCCESS) { - err = GetLastError(); - goto error; - } - - if (RegQueryValueExW(processor_key, - L"~MHz", - NULL, - NULL, - (BYTE*) &cpu_speed, - &cpu_speed_size) != ERROR_SUCCESS) { - err = GetLastError(); - RegCloseKey(processor_key); - goto error; - } - - if (RegQueryValueExW(processor_key, - L"ProcessorNameString", - NULL, - NULL, - (BYTE*) &cpu_brand, - &cpu_brand_size) != ERROR_SUCCESS) { - err = GetLastError(); - RegCloseKey(processor_key); - goto error; - } - - RegCloseKey(processor_key); - - cpu_info = &cpu_infos[i]; - cpu_info->speed = cpu_speed; - cpu_info->cpu_times.user = sppi[i].UserTime.QuadPart / 10000; - cpu_info->cpu_times.sys = (sppi[i].KernelTime.QuadPart - - sppi[i].IdleTime.QuadPart) / 10000; - cpu_info->cpu_times.idle = sppi[i].IdleTime.QuadPart / 10000; - cpu_info->cpu_times.irq = sppi[i].InterruptTime.QuadPart / 10000; - cpu_info->cpu_times.nice = 0; - - uv__convert_utf16_to_utf8(cpu_brand, - cpu_brand_size / sizeof(WCHAR), - &(cpu_info->model)); - } - - uv__free(sppi); - - *cpu_count_ptr = cpu_count; - *cpu_infos_ptr = cpu_infos; - - return 0; - - error: - /* This is safe because the cpu_infos array is zeroed on allocation. */ - for (i = 0; i < cpu_count; i++) - uv__free(cpu_infos[i].model); - - uv__free(cpu_infos); - uv__free(sppi); - - return uv_translate_sys_error(err); -} - - -void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { - int i; - - for (i = 0; i < count; i++) { - uv__free(cpu_infos[i].model); - } - - uv__free(cpu_infos); -} - - -static int is_windows_version_or_greater(DWORD os_major, - DWORD os_minor, - WORD service_pack_major, - WORD service_pack_minor) { - OSVERSIONINFOEX osvi; - DWORDLONG condition_mask = 0; - int op = VER_GREATER_EQUAL; - - /* Initialize the OSVERSIONINFOEX structure. */ - ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); - osvi.dwMajorVersion = os_major; - osvi.dwMinorVersion = os_minor; - osvi.wServicePackMajor = service_pack_major; - osvi.wServicePackMinor = service_pack_minor; - - /* Initialize the condition mask. */ - VER_SET_CONDITION(condition_mask, VER_MAJORVERSION, op); - VER_SET_CONDITION(condition_mask, VER_MINORVERSION, op); - VER_SET_CONDITION(condition_mask, VER_SERVICEPACKMAJOR, op); - VER_SET_CONDITION(condition_mask, VER_SERVICEPACKMINOR, op); - - /* Perform the test. */ - return (int) VerifyVersionInfo( - &osvi, - VER_MAJORVERSION | VER_MINORVERSION | - VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR, - condition_mask); -} - - -static int address_prefix_match(int family, - struct sockaddr* address, - struct sockaddr* prefix_address, - int prefix_len) { - uint8_t* address_data; - uint8_t* prefix_address_data; - int i; - - assert(address->sa_family == family); - assert(prefix_address->sa_family == family); - - if (family == AF_INET6) { - address_data = (uint8_t*) &(((struct sockaddr_in6 *) address)->sin6_addr); - prefix_address_data = - (uint8_t*) &(((struct sockaddr_in6 *) prefix_address)->sin6_addr); - } else { - address_data = (uint8_t*) &(((struct sockaddr_in *) address)->sin_addr); - prefix_address_data = - (uint8_t*) &(((struct sockaddr_in *) prefix_address)->sin_addr); - } - - for (i = 0; i < prefix_len >> 3; i++) { - if (address_data[i] != prefix_address_data[i]) - return 0; - } - - if (prefix_len % 8) - return prefix_address_data[i] == - (address_data[i] & (0xff << (8 - prefix_len % 8))); - - return 1; -} - - -int uv_interface_addresses(uv_interface_address_t** addresses_ptr, - int* count_ptr) { - IP_ADAPTER_ADDRESSES* win_address_buf; - ULONG win_address_buf_size; - IP_ADAPTER_ADDRESSES* adapter; - - uv_interface_address_t* uv_address_buf; - char* name_buf; - size_t uv_address_buf_size; - uv_interface_address_t* uv_address; - - int count; - - int is_vista_or_greater; - ULONG flags; - - is_vista_or_greater = is_windows_version_or_greater(6, 0, 0, 0); - if (is_vista_or_greater) { - flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | - GAA_FLAG_SKIP_DNS_SERVER; - } else { - /* We need at least XP SP1. */ - if (!is_windows_version_or_greater(5, 1, 1, 0)) - return UV_ENOTSUP; - - flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | - GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_INCLUDE_PREFIX; - } - - - /* Fetch the size of the adapters reported by windows, and then get the */ - /* list itself. */ - win_address_buf_size = 0; - win_address_buf = NULL; - - for (;;) { - ULONG r; - - /* If win_address_buf is 0, then GetAdaptersAddresses will fail with */ - /* ERROR_BUFFER_OVERFLOW, and the required buffer size will be stored in */ - /* win_address_buf_size. */ - r = GetAdaptersAddresses(AF_UNSPEC, - flags, - NULL, - win_address_buf, - &win_address_buf_size); - - if (r == ERROR_SUCCESS) - break; - - uv__free(win_address_buf); - - switch (r) { - case ERROR_BUFFER_OVERFLOW: - /* This happens when win_address_buf is NULL or too small to hold */ - /* all adapters. */ - win_address_buf = uv__malloc(win_address_buf_size); - if (win_address_buf == NULL) - return UV_ENOMEM; - - continue; - - case ERROR_NO_DATA: { - /* No adapters were found. */ - uv_address_buf = uv__malloc(1); - if (uv_address_buf == NULL) - return UV_ENOMEM; - - *count_ptr = 0; - *addresses_ptr = uv_address_buf; - - return 0; - } - - case ERROR_ADDRESS_NOT_ASSOCIATED: - return UV_EAGAIN; - - case ERROR_INVALID_PARAMETER: - /* MSDN says: - * "This error is returned for any of the following conditions: the - * SizePointer parameter is NULL, the Address parameter is not - * AF_INET, AF_INET6, or AF_UNSPEC, or the address information for - * the parameters requested is greater than ULONG_MAX." - * Since the first two conditions are not met, it must be that the - * adapter data is too big. - */ - return UV_ENOBUFS; - - default: - /* Other (unspecified) errors can happen, but we don't have any */ - /* special meaning for them. */ - assert(r != ERROR_SUCCESS); - return uv_translate_sys_error(r); - } - } - - /* Count the number of enabled interfaces and compute how much space is */ - /* needed to store their info. */ - count = 0; - uv_address_buf_size = 0; - - for (adapter = win_address_buf; - adapter != NULL; - adapter = adapter->Next) { - IP_ADAPTER_UNICAST_ADDRESS* unicast_address; - int name_size; - - /* Interfaces that are not 'up' should not be reported. Also skip */ - /* interfaces that have no associated unicast address, as to avoid */ - /* allocating space for the name for this interface. */ - if (adapter->OperStatus != IfOperStatusUp || - adapter->FirstUnicastAddress == NULL) - continue; - - /* Compute the size of the interface name. */ - name_size = WideCharToMultiByte(CP_UTF8, - 0, - adapter->FriendlyName, - -1, - NULL, - 0, - NULL, - FALSE); - if (name_size <= 0) { - uv__free(win_address_buf); - return uv_translate_sys_error(GetLastError()); - } - uv_address_buf_size += name_size; - - /* Count the number of addresses associated with this interface, and */ - /* compute the size. */ - for (unicast_address = (IP_ADAPTER_UNICAST_ADDRESS*) - adapter->FirstUnicastAddress; - unicast_address != NULL; - unicast_address = unicast_address->Next) { - count++; - uv_address_buf_size += sizeof(uv_interface_address_t); - } - } - - /* Allocate space to store interface data plus adapter names. */ - uv_address_buf = uv__malloc(uv_address_buf_size); - if (uv_address_buf == NULL) { - uv__free(win_address_buf); - return UV_ENOMEM; - } - - /* Compute the start of the uv_interface_address_t array, and the place in */ - /* the buffer where the interface names will be stored. */ - uv_address = uv_address_buf; - name_buf = (char*) (uv_address_buf + count); - - /* Fill out the output buffer. */ - for (adapter = win_address_buf; - adapter != NULL; - adapter = adapter->Next) { - IP_ADAPTER_UNICAST_ADDRESS* unicast_address; - int name_size; - size_t max_name_size; - - if (adapter->OperStatus != IfOperStatusUp || - adapter->FirstUnicastAddress == NULL) - continue; - - /* Convert the interface name to UTF8. */ - max_name_size = (char*) uv_address_buf + uv_address_buf_size - name_buf; - if (max_name_size > (size_t) INT_MAX) - max_name_size = INT_MAX; - name_size = WideCharToMultiByte(CP_UTF8, - 0, - adapter->FriendlyName, - -1, - name_buf, - (int) max_name_size, - NULL, - FALSE); - if (name_size <= 0) { - uv__free(win_address_buf); - uv__free(uv_address_buf); - return uv_translate_sys_error(GetLastError()); - } - - /* Add an uv_interface_address_t element for every unicast address. */ - for (unicast_address = (IP_ADAPTER_UNICAST_ADDRESS*) - adapter->FirstUnicastAddress; - unicast_address != NULL; - unicast_address = unicast_address->Next) { - struct sockaddr* sa; - ULONG prefix_len; - - sa = unicast_address->Address.lpSockaddr; - - /* XP has no OnLinkPrefixLength field. */ - if (is_vista_or_greater) { - prefix_len = - ((IP_ADAPTER_UNICAST_ADDRESS_LH*) unicast_address)->OnLinkPrefixLength; - } else { - /* Prior to Windows Vista the FirstPrefix pointed to the list with - * single prefix for each IP address assigned to the adapter. - * Order of FirstPrefix does not match order of FirstUnicastAddress, - * so we need to find corresponding prefix. - */ - IP_ADAPTER_PREFIX* prefix; - prefix_len = 0; - - for (prefix = adapter->FirstPrefix; prefix; prefix = prefix->Next) { - /* We want the longest matching prefix. */ - if (prefix->Address.lpSockaddr->sa_family != sa->sa_family || - prefix->PrefixLength <= prefix_len) - continue; - - if (address_prefix_match(sa->sa_family, sa, - prefix->Address.lpSockaddr, prefix->PrefixLength)) { - prefix_len = prefix->PrefixLength; - } - } - - /* If there is no matching prefix information, return a single-host - * subnet mask (e.g. 255.255.255.255 for IPv4). - */ - if (!prefix_len) - prefix_len = (sa->sa_family == AF_INET6) ? 128 : 32; - } - - memset(uv_address, 0, sizeof *uv_address); - - uv_address->name = name_buf; - - if (adapter->PhysicalAddressLength == sizeof(uv_address->phys_addr)) { - memcpy(uv_address->phys_addr, - adapter->PhysicalAddress, - sizeof(uv_address->phys_addr)); - } - - uv_address->is_internal = - (adapter->IfType == IF_TYPE_SOFTWARE_LOOPBACK); - - if (sa->sa_family == AF_INET6) { - uv_address->address.address6 = *((struct sockaddr_in6 *) sa); - - uv_address->netmask.netmask6.sin6_family = AF_INET6; - memset(uv_address->netmask.netmask6.sin6_addr.s6_addr, 0xff, prefix_len >> 3); - /* This check ensures that we don't write past the size of the data. */ - if (prefix_len % 8) { - uv_address->netmask.netmask6.sin6_addr.s6_addr[prefix_len >> 3] = - 0xff << (8 - prefix_len % 8); - } - - } else { - uv_address->address.address4 = *((struct sockaddr_in *) sa); - - uv_address->netmask.netmask4.sin_family = AF_INET; - uv_address->netmask.netmask4.sin_addr.s_addr = (prefix_len > 0) ? - htonl(0xffffffff << (32 - prefix_len)) : 0; - } - - uv_address++; - } - - name_buf += name_size; - } - - uv__free(win_address_buf); - - *addresses_ptr = uv_address_buf; - *count_ptr = count; - - return 0; -} - - -void uv_free_interface_addresses(uv_interface_address_t* addresses, - int count) { - uv__free(addresses); -} - - -int uv_getrusage(uv_rusage_t *uv_rusage) { - FILETIME createTime, exitTime, kernelTime, userTime; - SYSTEMTIME kernelSystemTime, userSystemTime; - PROCESS_MEMORY_COUNTERS memCounters; - IO_COUNTERS ioCounters; - int ret; - - ret = GetProcessTimes(GetCurrentProcess(), &createTime, &exitTime, &kernelTime, &userTime); - if (ret == 0) { - return uv_translate_sys_error(GetLastError()); - } - - ret = FileTimeToSystemTime(&kernelTime, &kernelSystemTime); - if (ret == 0) { - return uv_translate_sys_error(GetLastError()); - } - - ret = FileTimeToSystemTime(&userTime, &userSystemTime); - if (ret == 0) { - return uv_translate_sys_error(GetLastError()); - } - - ret = GetProcessMemoryInfo(GetCurrentProcess(), - &memCounters, - sizeof(memCounters)); - if (ret == 0) { - return uv_translate_sys_error(GetLastError()); - } - - ret = GetProcessIoCounters(GetCurrentProcess(), &ioCounters); - if (ret == 0) { - return uv_translate_sys_error(GetLastError()); - } - - memset(uv_rusage, 0, sizeof(*uv_rusage)); - - uv_rusage->ru_utime.tv_sec = userSystemTime.wHour * 3600 + - userSystemTime.wMinute * 60 + - userSystemTime.wSecond; - uv_rusage->ru_utime.tv_usec = userSystemTime.wMilliseconds * 1000; - - uv_rusage->ru_stime.tv_sec = kernelSystemTime.wHour * 3600 + - kernelSystemTime.wMinute * 60 + - kernelSystemTime.wSecond; - uv_rusage->ru_stime.tv_usec = kernelSystemTime.wMilliseconds * 1000; - - uv_rusage->ru_majflt = (uint64_t) memCounters.PageFaultCount; - uv_rusage->ru_maxrss = (uint64_t) memCounters.PeakWorkingSetSize / 1024; - - uv_rusage->ru_oublock = (uint64_t) ioCounters.WriteOperationCount; - uv_rusage->ru_inblock = (uint64_t) ioCounters.ReadOperationCount; - - return 0; -} - - -int uv_os_homedir(char* buffer, size_t* size) { - uv_passwd_t pwd; - wchar_t path[MAX_PATH]; - DWORD bufsize; - size_t len; - int r; - - if (buffer == NULL || size == NULL || *size == 0) - return UV_EINVAL; - - /* Check if the USERPROFILE environment variable is set first */ - len = GetEnvironmentVariableW(L"USERPROFILE", path, MAX_PATH); - - if (len == 0) { - r = GetLastError(); - - /* Don't return an error if USERPROFILE was not found */ - if (r != ERROR_ENVVAR_NOT_FOUND) - return uv_translate_sys_error(r); - } else if (len > MAX_PATH) { - /* This should not be possible */ - return UV_EIO; - } else { - /* Check how much space we need */ - bufsize = WideCharToMultiByte(CP_UTF8, 0, path, -1, NULL, 0, NULL, NULL); - - if (bufsize == 0) { - return uv_translate_sys_error(GetLastError()); - } else if (bufsize > *size) { - *size = bufsize; - return UV_ENOBUFS; - } - - /* Convert to UTF-8 */ - bufsize = WideCharToMultiByte(CP_UTF8, - 0, - path, - -1, - buffer, - *size, - NULL, - NULL); - - if (bufsize == 0) - return uv_translate_sys_error(GetLastError()); - - *size = bufsize - 1; - return 0; - } - - /* USERPROFILE is not set, so call uv__getpwuid_r() */ - r = uv__getpwuid_r(&pwd); - - if (r != 0) { - return r; - } - - len = strlen(pwd.homedir); - - if (len >= *size) { - *size = len + 1; - uv_os_free_passwd(&pwd); - return UV_ENOBUFS; - } - - memcpy(buffer, pwd.homedir, len + 1); - *size = len; - uv_os_free_passwd(&pwd); - - return 0; -} - - -int uv_os_tmpdir(char* buffer, size_t* size) { - wchar_t path[MAX_PATH + 1]; - DWORD bufsize; - size_t len; - - if (buffer == NULL || size == NULL || *size == 0) - return UV_EINVAL; - - len = GetTempPathW(MAX_PATH + 1, path); - - if (len == 0) { - return uv_translate_sys_error(GetLastError()); - } else if (len > MAX_PATH + 1) { - /* This should not be possible */ - return UV_EIO; - } - - /* The returned directory should not have a trailing slash, unless it */ - /* points at a drive root, like c:\. Remove it if needed.*/ - if (path[len - 1] == L'\\' && - !(len == 3 && path[1] == L':')) { - len--; - path[len] = L'\0'; - } - - /* Check how much space we need */ - bufsize = WideCharToMultiByte(CP_UTF8, 0, path, -1, NULL, 0, NULL, NULL); - - if (bufsize == 0) { - return uv_translate_sys_error(GetLastError()); - } else if (bufsize > *size) { - *size = bufsize; - return UV_ENOBUFS; - } - - /* Convert to UTF-8 */ - bufsize = WideCharToMultiByte(CP_UTF8, - 0, - path, - -1, - buffer, - *size, - NULL, - NULL); - - if (bufsize == 0) - return uv_translate_sys_error(GetLastError()); - - *size = bufsize - 1; - return 0; -} - - -void uv_os_free_passwd(uv_passwd_t* pwd) { - if (pwd == NULL) - return; - - uv__free(pwd->username); - uv__free(pwd->homedir); - pwd->username = NULL; - pwd->homedir = NULL; -} - - -/* - * Converts a UTF-16 string into a UTF-8 one. The resulting string is - * null-terminated. - * - * If utf16 is null terminated, utf16len can be set to -1, otherwise it must - * be specified. - */ -int uv__convert_utf16_to_utf8(const WCHAR* utf16, int utf16len, char** utf8) { - DWORD bufsize; - - if (utf16 == NULL) - return UV_EINVAL; - - /* Check how much space we need */ - bufsize = WideCharToMultiByte(CP_UTF8, - 0, - utf16, - utf16len, - NULL, - 0, - NULL, - NULL); - - if (bufsize == 0) - return uv_translate_sys_error(GetLastError()); - - /* Allocate the destination buffer adding an extra byte for the terminating - * NULL. If utf16len is not -1 WideCharToMultiByte will not add it, so - * we do it ourselves always, just in case. */ - *utf8 = uv__malloc(bufsize + 1); - - if (*utf8 == NULL) - return UV_ENOMEM; - - /* Convert to UTF-8 */ - bufsize = WideCharToMultiByte(CP_UTF8, - 0, - utf16, - utf16len, - *utf8, - bufsize, - NULL, - NULL); - - if (bufsize == 0) { - uv__free(*utf8); - *utf8 = NULL; - return uv_translate_sys_error(GetLastError()); - } - - (*utf8)[bufsize] = '\0'; - return 0; -} - - -int uv__getpwuid_r(uv_passwd_t* pwd) { - HANDLE token; - wchar_t username[UNLEN + 1]; - wchar_t path[MAX_PATH]; - DWORD bufsize; - int r; - - if (pwd == NULL) - return UV_EINVAL; - - /* Get the home directory using GetUserProfileDirectoryW() */ - if (OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &token) == 0) - return uv_translate_sys_error(GetLastError()); - - bufsize = sizeof(path); - if (!GetUserProfileDirectoryW(token, path, &bufsize)) { - r = GetLastError(); - CloseHandle(token); - - /* This should not be possible */ - if (r == ERROR_INSUFFICIENT_BUFFER) - return UV_ENOMEM; - - return uv_translate_sys_error(r); - } - - CloseHandle(token); - - /* Get the username using GetUserNameW() */ - bufsize = sizeof(username); - if (!GetUserNameW(username, &bufsize)) { - r = GetLastError(); - - /* This should not be possible */ - if (r == ERROR_INSUFFICIENT_BUFFER) - return UV_ENOMEM; - - return uv_translate_sys_error(r); - } - - pwd->homedir = NULL; - r = uv__convert_utf16_to_utf8(path, -1, &pwd->homedir); - - if (r != 0) - return r; - - pwd->username = NULL; - r = uv__convert_utf16_to_utf8(username, -1, &pwd->username); - - if (r != 0) { - uv__free(pwd->homedir); - return r; - } - - pwd->shell = NULL; - pwd->uid = -1; - pwd->gid = -1; - - return 0; -} - - -int uv_os_get_passwd(uv_passwd_t* pwd) { - return uv__getpwuid_r(pwd); -} diff --git a/vendor/libuv/src/win/winapi.c b/vendor/libuv/src/win/winapi.c deleted file mode 100644 index 1fa179b57..000000000 --- a/vendor/libuv/src/win/winapi.c +++ /dev/null @@ -1,159 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include - -#include "uv.h" -#include "internal.h" - - -/* Ntdll function pointers */ -sRtlNtStatusToDosError pRtlNtStatusToDosError; -sNtDeviceIoControlFile pNtDeviceIoControlFile; -sNtQueryInformationFile pNtQueryInformationFile; -sNtSetInformationFile pNtSetInformationFile; -sNtQueryVolumeInformationFile pNtQueryVolumeInformationFile; -sNtQueryDirectoryFile pNtQueryDirectoryFile; -sNtQuerySystemInformation pNtQuerySystemInformation; - - -/* Kernel32 function pointers */ -sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx; -sSetFileCompletionNotificationModes pSetFileCompletionNotificationModes; -sCreateSymbolicLinkW pCreateSymbolicLinkW; -sCancelIoEx pCancelIoEx; -sInitializeConditionVariable pInitializeConditionVariable; -sSleepConditionVariableCS pSleepConditionVariableCS; -sSleepConditionVariableSRW pSleepConditionVariableSRW; -sWakeAllConditionVariable pWakeAllConditionVariable; -sWakeConditionVariable pWakeConditionVariable; -sCancelSynchronousIo pCancelSynchronousIo; -sGetFinalPathNameByHandleW pGetFinalPathNameByHandleW; - - -/* Powrprof.dll function pointer */ -sPowerRegisterSuspendResumeNotification pPowerRegisterSuspendResumeNotification; - - -void uv_winapi_init() { - HMODULE ntdll_module; - HMODULE kernel32_module; - HMODULE powrprof_module; - - ntdll_module = GetModuleHandleA("ntdll.dll"); - if (ntdll_module == NULL) { - uv_fatal_error(GetLastError(), "GetModuleHandleA"); - } - - pRtlNtStatusToDosError = (sRtlNtStatusToDosError) GetProcAddress( - ntdll_module, - "RtlNtStatusToDosError"); - if (pRtlNtStatusToDosError == NULL) { - uv_fatal_error(GetLastError(), "GetProcAddress"); - } - - pNtDeviceIoControlFile = (sNtDeviceIoControlFile) GetProcAddress( - ntdll_module, - "NtDeviceIoControlFile"); - if (pNtDeviceIoControlFile == NULL) { - uv_fatal_error(GetLastError(), "GetProcAddress"); - } - - pNtQueryInformationFile = (sNtQueryInformationFile) GetProcAddress( - ntdll_module, - "NtQueryInformationFile"); - if (pNtQueryInformationFile == NULL) { - uv_fatal_error(GetLastError(), "GetProcAddress"); - } - - pNtSetInformationFile = (sNtSetInformationFile) GetProcAddress( - ntdll_module, - "NtSetInformationFile"); - if (pNtSetInformationFile == NULL) { - uv_fatal_error(GetLastError(), "GetProcAddress"); - } - - pNtQueryVolumeInformationFile = (sNtQueryVolumeInformationFile) - GetProcAddress(ntdll_module, "NtQueryVolumeInformationFile"); - if (pNtQueryVolumeInformationFile == NULL) { - uv_fatal_error(GetLastError(), "GetProcAddress"); - } - - pNtQueryDirectoryFile = (sNtQueryDirectoryFile) - GetProcAddress(ntdll_module, "NtQueryDirectoryFile"); - if (pNtQueryVolumeInformationFile == NULL) { - uv_fatal_error(GetLastError(), "GetProcAddress"); - } - - pNtQuerySystemInformation = (sNtQuerySystemInformation) GetProcAddress( - ntdll_module, - "NtQuerySystemInformation"); - if (pNtQuerySystemInformation == NULL) { - uv_fatal_error(GetLastError(), "GetProcAddress"); - } - - kernel32_module = GetModuleHandleA("kernel32.dll"); - if (kernel32_module == NULL) { - uv_fatal_error(GetLastError(), "GetModuleHandleA"); - } - - pGetQueuedCompletionStatusEx = (sGetQueuedCompletionStatusEx) GetProcAddress( - kernel32_module, - "GetQueuedCompletionStatusEx"); - - pSetFileCompletionNotificationModes = (sSetFileCompletionNotificationModes) - GetProcAddress(kernel32_module, "SetFileCompletionNotificationModes"); - - pCreateSymbolicLinkW = (sCreateSymbolicLinkW) - GetProcAddress(kernel32_module, "CreateSymbolicLinkW"); - - pCancelIoEx = (sCancelIoEx) - GetProcAddress(kernel32_module, "CancelIoEx"); - - pInitializeConditionVariable = (sInitializeConditionVariable) - GetProcAddress(kernel32_module, "InitializeConditionVariable"); - - pSleepConditionVariableCS = (sSleepConditionVariableCS) - GetProcAddress(kernel32_module, "SleepConditionVariableCS"); - - pSleepConditionVariableSRW = (sSleepConditionVariableSRW) - GetProcAddress(kernel32_module, "SleepConditionVariableSRW"); - - pWakeAllConditionVariable = (sWakeAllConditionVariable) - GetProcAddress(kernel32_module, "WakeAllConditionVariable"); - - pWakeConditionVariable = (sWakeConditionVariable) - GetProcAddress(kernel32_module, "WakeConditionVariable"); - - pCancelSynchronousIo = (sCancelSynchronousIo) - GetProcAddress(kernel32_module, "CancelSynchronousIo"); - - pGetFinalPathNameByHandleW = (sGetFinalPathNameByHandleW) - GetProcAddress(kernel32_module, "GetFinalPathNameByHandleW"); - - - powrprof_module = LoadLibraryA("powrprof.dll"); - if (powrprof_module != NULL) { - pPowerRegisterSuspendResumeNotification = (sPowerRegisterSuspendResumeNotification) - GetProcAddress(powrprof_module, "PowerRegisterSuspendResumeNotification"); - } - -} diff --git a/vendor/libuv/src/win/winapi.h b/vendor/libuv/src/win/winapi.h deleted file mode 100644 index 9401676fb..000000000 --- a/vendor/libuv/src/win/winapi.h +++ /dev/null @@ -1,4752 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef UV_WIN_WINAPI_H_ -#define UV_WIN_WINAPI_H_ - -#include - - -/* - * Ntdll headers - */ -#ifndef STATUS_SEVERITY_SUCCESS -# define STATUS_SEVERITY_SUCCESS 0x0 -#endif - -#ifndef STATUS_SEVERITY_INFORMATIONAL -# define STATUS_SEVERITY_INFORMATIONAL 0x1 -#endif - -#ifndef STATUS_SEVERITY_WARNING -# define STATUS_SEVERITY_WARNING 0x2 -#endif - -#ifndef STATUS_SEVERITY_ERROR -# define STATUS_SEVERITY_ERROR 0x3 -#endif - -#ifndef FACILITY_NTWIN32 -# define FACILITY_NTWIN32 0x7 -#endif - -#ifndef NT_SUCCESS -# define NT_SUCCESS(status) (((NTSTATUS) (status)) >= 0) -#endif - -#ifndef NT_INFORMATION -# define NT_INFORMATION(status) ((((ULONG) (status)) >> 30) == 1) -#endif - -#ifndef NT_WARNING -# define NT_WARNING(status) ((((ULONG) (status)) >> 30) == 2) -#endif - -#ifndef NT_ERROR -# define NT_ERROR(status) ((((ULONG) (status)) >> 30) == 3) -#endif - -#ifndef STATUS_SUCCESS -# define STATUS_SUCCESS ((NTSTATUS) 0x00000000L) -#endif - -#ifndef STATUS_WAIT_0 -# define STATUS_WAIT_0 ((NTSTATUS) 0x00000000L) -#endif - -#ifndef STATUS_WAIT_1 -# define STATUS_WAIT_1 ((NTSTATUS) 0x00000001L) -#endif - -#ifndef STATUS_WAIT_2 -# define STATUS_WAIT_2 ((NTSTATUS) 0x00000002L) -#endif - -#ifndef STATUS_WAIT_3 -# define STATUS_WAIT_3 ((NTSTATUS) 0x00000003L) -#endif - -#ifndef STATUS_WAIT_63 -# define STATUS_WAIT_63 ((NTSTATUS) 0x0000003FL) -#endif - -#ifndef STATUS_ABANDONED -# define STATUS_ABANDONED ((NTSTATUS) 0x00000080L) -#endif - -#ifndef STATUS_ABANDONED_WAIT_0 -# define STATUS_ABANDONED_WAIT_0 ((NTSTATUS) 0x00000080L) -#endif - -#ifndef STATUS_ABANDONED_WAIT_63 -# define STATUS_ABANDONED_WAIT_63 ((NTSTATUS) 0x000000BFL) -#endif - -#ifndef STATUS_USER_APC -# define STATUS_USER_APC ((NTSTATUS) 0x000000C0L) -#endif - -#ifndef STATUS_KERNEL_APC -# define STATUS_KERNEL_APC ((NTSTATUS) 0x00000100L) -#endif - -#ifndef STATUS_ALERTED -# define STATUS_ALERTED ((NTSTATUS) 0x00000101L) -#endif - -#ifndef STATUS_TIMEOUT -# define STATUS_TIMEOUT ((NTSTATUS) 0x00000102L) -#endif - -#ifndef STATUS_PENDING -# define STATUS_PENDING ((NTSTATUS) 0x00000103L) -#endif - -#ifndef STATUS_REPARSE -# define STATUS_REPARSE ((NTSTATUS) 0x00000104L) -#endif - -#ifndef STATUS_MORE_ENTRIES -# define STATUS_MORE_ENTRIES ((NTSTATUS) 0x00000105L) -#endif - -#ifndef STATUS_NOT_ALL_ASSIGNED -# define STATUS_NOT_ALL_ASSIGNED ((NTSTATUS) 0x00000106L) -#endif - -#ifndef STATUS_SOME_NOT_MAPPED -# define STATUS_SOME_NOT_MAPPED ((NTSTATUS) 0x00000107L) -#endif - -#ifndef STATUS_OPLOCK_BREAK_IN_PROGRESS -# define STATUS_OPLOCK_BREAK_IN_PROGRESS ((NTSTATUS) 0x00000108L) -#endif - -#ifndef STATUS_VOLUME_MOUNTED -# define STATUS_VOLUME_MOUNTED ((NTSTATUS) 0x00000109L) -#endif - -#ifndef STATUS_RXACT_COMMITTED -# define STATUS_RXACT_COMMITTED ((NTSTATUS) 0x0000010AL) -#endif - -#ifndef STATUS_NOTIFY_CLEANUP -# define STATUS_NOTIFY_CLEANUP ((NTSTATUS) 0x0000010BL) -#endif - -#ifndef STATUS_NOTIFY_ENUM_DIR -# define STATUS_NOTIFY_ENUM_DIR ((NTSTATUS) 0x0000010CL) -#endif - -#ifndef STATUS_NO_QUOTAS_FOR_ACCOUNT -# define STATUS_NO_QUOTAS_FOR_ACCOUNT ((NTSTATUS) 0x0000010DL) -#endif - -#ifndef STATUS_PRIMARY_TRANSPORT_CONNECT_FAILED -# define STATUS_PRIMARY_TRANSPORT_CONNECT_FAILED ((NTSTATUS) 0x0000010EL) -#endif - -#ifndef STATUS_PAGE_FAULT_TRANSITION -# define STATUS_PAGE_FAULT_TRANSITION ((NTSTATUS) 0x00000110L) -#endif - -#ifndef STATUS_PAGE_FAULT_DEMAND_ZERO -# define STATUS_PAGE_FAULT_DEMAND_ZERO ((NTSTATUS) 0x00000111L) -#endif - -#ifndef STATUS_PAGE_FAULT_COPY_ON_WRITE -# define STATUS_PAGE_FAULT_COPY_ON_WRITE ((NTSTATUS) 0x00000112L) -#endif - -#ifndef STATUS_PAGE_FAULT_GUARD_PAGE -# define STATUS_PAGE_FAULT_GUARD_PAGE ((NTSTATUS) 0x00000113L) -#endif - -#ifndef STATUS_PAGE_FAULT_PAGING_FILE -# define STATUS_PAGE_FAULT_PAGING_FILE ((NTSTATUS) 0x00000114L) -#endif - -#ifndef STATUS_CACHE_PAGE_LOCKED -# define STATUS_CACHE_PAGE_LOCKED ((NTSTATUS) 0x00000115L) -#endif - -#ifndef STATUS_CRASH_DUMP -# define STATUS_CRASH_DUMP ((NTSTATUS) 0x00000116L) -#endif - -#ifndef STATUS_BUFFER_ALL_ZEROS -# define STATUS_BUFFER_ALL_ZEROS ((NTSTATUS) 0x00000117L) -#endif - -#ifndef STATUS_REPARSE_OBJECT -# define STATUS_REPARSE_OBJECT ((NTSTATUS) 0x00000118L) -#endif - -#ifndef STATUS_RESOURCE_REQUIREMENTS_CHANGED -# define STATUS_RESOURCE_REQUIREMENTS_CHANGED ((NTSTATUS) 0x00000119L) -#endif - -#ifndef STATUS_TRANSLATION_COMPLETE -# define STATUS_TRANSLATION_COMPLETE ((NTSTATUS) 0x00000120L) -#endif - -#ifndef STATUS_DS_MEMBERSHIP_EVALUATED_LOCALLY -# define STATUS_DS_MEMBERSHIP_EVALUATED_LOCALLY ((NTSTATUS) 0x00000121L) -#endif - -#ifndef STATUS_NOTHING_TO_TERMINATE -# define STATUS_NOTHING_TO_TERMINATE ((NTSTATUS) 0x00000122L) -#endif - -#ifndef STATUS_PROCESS_NOT_IN_JOB -# define STATUS_PROCESS_NOT_IN_JOB ((NTSTATUS) 0x00000123L) -#endif - -#ifndef STATUS_PROCESS_IN_JOB -# define STATUS_PROCESS_IN_JOB ((NTSTATUS) 0x00000124L) -#endif - -#ifndef STATUS_VOLSNAP_HIBERNATE_READY -# define STATUS_VOLSNAP_HIBERNATE_READY ((NTSTATUS) 0x00000125L) -#endif - -#ifndef STATUS_FSFILTER_OP_COMPLETED_SUCCESSFULLY -# define STATUS_FSFILTER_OP_COMPLETED_SUCCESSFULLY ((NTSTATUS) 0x00000126L) -#endif - -#ifndef STATUS_INTERRUPT_VECTOR_ALREADY_CONNECTED -# define STATUS_INTERRUPT_VECTOR_ALREADY_CONNECTED ((NTSTATUS) 0x00000127L) -#endif - -#ifndef STATUS_INTERRUPT_STILL_CONNECTED -# define STATUS_INTERRUPT_STILL_CONNECTED ((NTSTATUS) 0x00000128L) -#endif - -#ifndef STATUS_PROCESS_CLONED -# define STATUS_PROCESS_CLONED ((NTSTATUS) 0x00000129L) -#endif - -#ifndef STATUS_FILE_LOCKED_WITH_ONLY_READERS -# define STATUS_FILE_LOCKED_WITH_ONLY_READERS ((NTSTATUS) 0x0000012AL) -#endif - -#ifndef STATUS_FILE_LOCKED_WITH_WRITERS -# define STATUS_FILE_LOCKED_WITH_WRITERS ((NTSTATUS) 0x0000012BL) -#endif - -#ifndef STATUS_RESOURCEMANAGER_READ_ONLY -# define STATUS_RESOURCEMANAGER_READ_ONLY ((NTSTATUS) 0x00000202L) -#endif - -#ifndef STATUS_RING_PREVIOUSLY_EMPTY -# define STATUS_RING_PREVIOUSLY_EMPTY ((NTSTATUS) 0x00000210L) -#endif - -#ifndef STATUS_RING_PREVIOUSLY_FULL -# define STATUS_RING_PREVIOUSLY_FULL ((NTSTATUS) 0x00000211L) -#endif - -#ifndef STATUS_RING_PREVIOUSLY_ABOVE_QUOTA -# define STATUS_RING_PREVIOUSLY_ABOVE_QUOTA ((NTSTATUS) 0x00000212L) -#endif - -#ifndef STATUS_RING_NEWLY_EMPTY -# define STATUS_RING_NEWLY_EMPTY ((NTSTATUS) 0x00000213L) -#endif - -#ifndef STATUS_RING_SIGNAL_OPPOSITE_ENDPOINT -# define STATUS_RING_SIGNAL_OPPOSITE_ENDPOINT ((NTSTATUS) 0x00000214L) -#endif - -#ifndef STATUS_OPLOCK_SWITCHED_TO_NEW_HANDLE -# define STATUS_OPLOCK_SWITCHED_TO_NEW_HANDLE ((NTSTATUS) 0x00000215L) -#endif - -#ifndef STATUS_OPLOCK_HANDLE_CLOSED -# define STATUS_OPLOCK_HANDLE_CLOSED ((NTSTATUS) 0x00000216L) -#endif - -#ifndef STATUS_WAIT_FOR_OPLOCK -# define STATUS_WAIT_FOR_OPLOCK ((NTSTATUS) 0x00000367L) -#endif - -#ifndef STATUS_OBJECT_NAME_EXISTS -# define STATUS_OBJECT_NAME_EXISTS ((NTSTATUS) 0x40000000L) -#endif - -#ifndef STATUS_THREAD_WAS_SUSPENDED -# define STATUS_THREAD_WAS_SUSPENDED ((NTSTATUS) 0x40000001L) -#endif - -#ifndef STATUS_WORKING_SET_LIMIT_RANGE -# define STATUS_WORKING_SET_LIMIT_RANGE ((NTSTATUS) 0x40000002L) -#endif - -#ifndef STATUS_IMAGE_NOT_AT_BASE -# define STATUS_IMAGE_NOT_AT_BASE ((NTSTATUS) 0x40000003L) -#endif - -#ifndef STATUS_RXACT_STATE_CREATED -# define STATUS_RXACT_STATE_CREATED ((NTSTATUS) 0x40000004L) -#endif - -#ifndef STATUS_SEGMENT_NOTIFICATION -# define STATUS_SEGMENT_NOTIFICATION ((NTSTATUS) 0x40000005L) -#endif - -#ifndef STATUS_LOCAL_USER_SESSION_KEY -# define STATUS_LOCAL_USER_SESSION_KEY ((NTSTATUS) 0x40000006L) -#endif - -#ifndef STATUS_BAD_CURRENT_DIRECTORY -# define STATUS_BAD_CURRENT_DIRECTORY ((NTSTATUS) 0x40000007L) -#endif - -#ifndef STATUS_SERIAL_MORE_WRITES -# define STATUS_SERIAL_MORE_WRITES ((NTSTATUS) 0x40000008L) -#endif - -#ifndef STATUS_REGISTRY_RECOVERED -# define STATUS_REGISTRY_RECOVERED ((NTSTATUS) 0x40000009L) -#endif - -#ifndef STATUS_FT_READ_RECOVERY_FROM_BACKUP -# define STATUS_FT_READ_RECOVERY_FROM_BACKUP ((NTSTATUS) 0x4000000AL) -#endif - -#ifndef STATUS_FT_WRITE_RECOVERY -# define STATUS_FT_WRITE_RECOVERY ((NTSTATUS) 0x4000000BL) -#endif - -#ifndef STATUS_SERIAL_COUNTER_TIMEOUT -# define STATUS_SERIAL_COUNTER_TIMEOUT ((NTSTATUS) 0x4000000CL) -#endif - -#ifndef STATUS_NULL_LM_PASSWORD -# define STATUS_NULL_LM_PASSWORD ((NTSTATUS) 0x4000000DL) -#endif - -#ifndef STATUS_IMAGE_MACHINE_TYPE_MISMATCH -# define STATUS_IMAGE_MACHINE_TYPE_MISMATCH ((NTSTATUS) 0x4000000EL) -#endif - -#ifndef STATUS_RECEIVE_PARTIAL -# define STATUS_RECEIVE_PARTIAL ((NTSTATUS) 0x4000000FL) -#endif - -#ifndef STATUS_RECEIVE_EXPEDITED -# define STATUS_RECEIVE_EXPEDITED ((NTSTATUS) 0x40000010L) -#endif - -#ifndef STATUS_RECEIVE_PARTIAL_EXPEDITED -# define STATUS_RECEIVE_PARTIAL_EXPEDITED ((NTSTATUS) 0x40000011L) -#endif - -#ifndef STATUS_EVENT_DONE -# define STATUS_EVENT_DONE ((NTSTATUS) 0x40000012L) -#endif - -#ifndef STATUS_EVENT_PENDING -# define STATUS_EVENT_PENDING ((NTSTATUS) 0x40000013L) -#endif - -#ifndef STATUS_CHECKING_FILE_SYSTEM -# define STATUS_CHECKING_FILE_SYSTEM ((NTSTATUS) 0x40000014L) -#endif - -#ifndef STATUS_FATAL_APP_EXIT -# define STATUS_FATAL_APP_EXIT ((NTSTATUS) 0x40000015L) -#endif - -#ifndef STATUS_PREDEFINED_HANDLE -# define STATUS_PREDEFINED_HANDLE ((NTSTATUS) 0x40000016L) -#endif - -#ifndef STATUS_WAS_UNLOCKED -# define STATUS_WAS_UNLOCKED ((NTSTATUS) 0x40000017L) -#endif - -#ifndef STATUS_SERVICE_NOTIFICATION -# define STATUS_SERVICE_NOTIFICATION ((NTSTATUS) 0x40000018L) -#endif - -#ifndef STATUS_WAS_LOCKED -# define STATUS_WAS_LOCKED ((NTSTATUS) 0x40000019L) -#endif - -#ifndef STATUS_LOG_HARD_ERROR -# define STATUS_LOG_HARD_ERROR ((NTSTATUS) 0x4000001AL) -#endif - -#ifndef STATUS_ALREADY_WIN32 -# define STATUS_ALREADY_WIN32 ((NTSTATUS) 0x4000001BL) -#endif - -#ifndef STATUS_WX86_UNSIMULATE -# define STATUS_WX86_UNSIMULATE ((NTSTATUS) 0x4000001CL) -#endif - -#ifndef STATUS_WX86_CONTINUE -# define STATUS_WX86_CONTINUE ((NTSTATUS) 0x4000001DL) -#endif - -#ifndef STATUS_WX86_SINGLE_STEP -# define STATUS_WX86_SINGLE_STEP ((NTSTATUS) 0x4000001EL) -#endif - -#ifndef STATUS_WX86_BREAKPOINT -# define STATUS_WX86_BREAKPOINT ((NTSTATUS) 0x4000001FL) -#endif - -#ifndef STATUS_WX86_EXCEPTION_CONTINUE -# define STATUS_WX86_EXCEPTION_CONTINUE ((NTSTATUS) 0x40000020L) -#endif - -#ifndef STATUS_WX86_EXCEPTION_LASTCHANCE -# define STATUS_WX86_EXCEPTION_LASTCHANCE ((NTSTATUS) 0x40000021L) -#endif - -#ifndef STATUS_WX86_EXCEPTION_CHAIN -# define STATUS_WX86_EXCEPTION_CHAIN ((NTSTATUS) 0x40000022L) -#endif - -#ifndef STATUS_IMAGE_MACHINE_TYPE_MISMATCH_EXE -# define STATUS_IMAGE_MACHINE_TYPE_MISMATCH_EXE ((NTSTATUS) 0x40000023L) -#endif - -#ifndef STATUS_NO_YIELD_PERFORMED -# define STATUS_NO_YIELD_PERFORMED ((NTSTATUS) 0x40000024L) -#endif - -#ifndef STATUS_TIMER_RESUME_IGNORED -# define STATUS_TIMER_RESUME_IGNORED ((NTSTATUS) 0x40000025L) -#endif - -#ifndef STATUS_ARBITRATION_UNHANDLED -# define STATUS_ARBITRATION_UNHANDLED ((NTSTATUS) 0x40000026L) -#endif - -#ifndef STATUS_CARDBUS_NOT_SUPPORTED -# define STATUS_CARDBUS_NOT_SUPPORTED ((NTSTATUS) 0x40000027L) -#endif - -#ifndef STATUS_WX86_CREATEWX86TIB -# define STATUS_WX86_CREATEWX86TIB ((NTSTATUS) 0x40000028L) -#endif - -#ifndef STATUS_MP_PROCESSOR_MISMATCH -# define STATUS_MP_PROCESSOR_MISMATCH ((NTSTATUS) 0x40000029L) -#endif - -#ifndef STATUS_HIBERNATED -# define STATUS_HIBERNATED ((NTSTATUS) 0x4000002AL) -#endif - -#ifndef STATUS_RESUME_HIBERNATION -# define STATUS_RESUME_HIBERNATION ((NTSTATUS) 0x4000002BL) -#endif - -#ifndef STATUS_FIRMWARE_UPDATED -# define STATUS_FIRMWARE_UPDATED ((NTSTATUS) 0x4000002CL) -#endif - -#ifndef STATUS_DRIVERS_LEAKING_LOCKED_PAGES -# define STATUS_DRIVERS_LEAKING_LOCKED_PAGES ((NTSTATUS) 0x4000002DL) -#endif - -#ifndef STATUS_MESSAGE_RETRIEVED -# define STATUS_MESSAGE_RETRIEVED ((NTSTATUS) 0x4000002EL) -#endif - -#ifndef STATUS_SYSTEM_POWERSTATE_TRANSITION -# define STATUS_SYSTEM_POWERSTATE_TRANSITION ((NTSTATUS) 0x4000002FL) -#endif - -#ifndef STATUS_ALPC_CHECK_COMPLETION_LIST -# define STATUS_ALPC_CHECK_COMPLETION_LIST ((NTSTATUS) 0x40000030L) -#endif - -#ifndef STATUS_SYSTEM_POWERSTATE_COMPLEX_TRANSITION -# define STATUS_SYSTEM_POWERSTATE_COMPLEX_TRANSITION ((NTSTATUS) 0x40000031L) -#endif - -#ifndef STATUS_ACCESS_AUDIT_BY_POLICY -# define STATUS_ACCESS_AUDIT_BY_POLICY ((NTSTATUS) 0x40000032L) -#endif - -#ifndef STATUS_ABANDON_HIBERFILE -# define STATUS_ABANDON_HIBERFILE ((NTSTATUS) 0x40000033L) -#endif - -#ifndef STATUS_BIZRULES_NOT_ENABLED -# define STATUS_BIZRULES_NOT_ENABLED ((NTSTATUS) 0x40000034L) -#endif - -#ifndef STATUS_GUARD_PAGE_VIOLATION -# define STATUS_GUARD_PAGE_VIOLATION ((NTSTATUS) 0x80000001L) -#endif - -#ifndef STATUS_DATATYPE_MISALIGNMENT -# define STATUS_DATATYPE_MISALIGNMENT ((NTSTATUS) 0x80000002L) -#endif - -#ifndef STATUS_BREAKPOINT -# define STATUS_BREAKPOINT ((NTSTATUS) 0x80000003L) -#endif - -#ifndef STATUS_SINGLE_STEP -# define STATUS_SINGLE_STEP ((NTSTATUS) 0x80000004L) -#endif - -#ifndef STATUS_BUFFER_OVERFLOW -# define STATUS_BUFFER_OVERFLOW ((NTSTATUS) 0x80000005L) -#endif - -#ifndef STATUS_NO_MORE_FILES -# define STATUS_NO_MORE_FILES ((NTSTATUS) 0x80000006L) -#endif - -#ifndef STATUS_WAKE_SYSTEM_DEBUGGER -# define STATUS_WAKE_SYSTEM_DEBUGGER ((NTSTATUS) 0x80000007L) -#endif - -#ifndef STATUS_HANDLES_CLOSED -# define STATUS_HANDLES_CLOSED ((NTSTATUS) 0x8000000AL) -#endif - -#ifndef STATUS_NO_INHERITANCE -# define STATUS_NO_INHERITANCE ((NTSTATUS) 0x8000000BL) -#endif - -#ifndef STATUS_GUID_SUBSTITUTION_MADE -# define STATUS_GUID_SUBSTITUTION_MADE ((NTSTATUS) 0x8000000CL) -#endif - -#ifndef STATUS_PARTIAL_COPY -# define STATUS_PARTIAL_COPY ((NTSTATUS) 0x8000000DL) -#endif - -#ifndef STATUS_DEVICE_PAPER_EMPTY -# define STATUS_DEVICE_PAPER_EMPTY ((NTSTATUS) 0x8000000EL) -#endif - -#ifndef STATUS_DEVICE_POWERED_OFF -# define STATUS_DEVICE_POWERED_OFF ((NTSTATUS) 0x8000000FL) -#endif - -#ifndef STATUS_DEVICE_OFF_LINE -# define STATUS_DEVICE_OFF_LINE ((NTSTATUS) 0x80000010L) -#endif - -#ifndef STATUS_DEVICE_BUSY -# define STATUS_DEVICE_BUSY ((NTSTATUS) 0x80000011L) -#endif - -#ifndef STATUS_NO_MORE_EAS -# define STATUS_NO_MORE_EAS ((NTSTATUS) 0x80000012L) -#endif - -#ifndef STATUS_INVALID_EA_NAME -# define STATUS_INVALID_EA_NAME ((NTSTATUS) 0x80000013L) -#endif - -#ifndef STATUS_EA_LIST_INCONSISTENT -# define STATUS_EA_LIST_INCONSISTENT ((NTSTATUS) 0x80000014L) -#endif - -#ifndef STATUS_INVALID_EA_FLAG -# define STATUS_INVALID_EA_FLAG ((NTSTATUS) 0x80000015L) -#endif - -#ifndef STATUS_VERIFY_REQUIRED -# define STATUS_VERIFY_REQUIRED ((NTSTATUS) 0x80000016L) -#endif - -#ifndef STATUS_EXTRANEOUS_INFORMATION -# define STATUS_EXTRANEOUS_INFORMATION ((NTSTATUS) 0x80000017L) -#endif - -#ifndef STATUS_RXACT_COMMIT_NECESSARY -# define STATUS_RXACT_COMMIT_NECESSARY ((NTSTATUS) 0x80000018L) -#endif - -#ifndef STATUS_NO_MORE_ENTRIES -# define STATUS_NO_MORE_ENTRIES ((NTSTATUS) 0x8000001AL) -#endif - -#ifndef STATUS_FILEMARK_DETECTED -# define STATUS_FILEMARK_DETECTED ((NTSTATUS) 0x8000001BL) -#endif - -#ifndef STATUS_MEDIA_CHANGED -# define STATUS_MEDIA_CHANGED ((NTSTATUS) 0x8000001CL) -#endif - -#ifndef STATUS_BUS_RESET -# define STATUS_BUS_RESET ((NTSTATUS) 0x8000001DL) -#endif - -#ifndef STATUS_END_OF_MEDIA -# define STATUS_END_OF_MEDIA ((NTSTATUS) 0x8000001EL) -#endif - -#ifndef STATUS_BEGINNING_OF_MEDIA -# define STATUS_BEGINNING_OF_MEDIA ((NTSTATUS) 0x8000001FL) -#endif - -#ifndef STATUS_MEDIA_CHECK -# define STATUS_MEDIA_CHECK ((NTSTATUS) 0x80000020L) -#endif - -#ifndef STATUS_SETMARK_DETECTED -# define STATUS_SETMARK_DETECTED ((NTSTATUS) 0x80000021L) -#endif - -#ifndef STATUS_NO_DATA_DETECTED -# define STATUS_NO_DATA_DETECTED ((NTSTATUS) 0x80000022L) -#endif - -#ifndef STATUS_REDIRECTOR_HAS_OPEN_HANDLES -# define STATUS_REDIRECTOR_HAS_OPEN_HANDLES ((NTSTATUS) 0x80000023L) -#endif - -#ifndef STATUS_SERVER_HAS_OPEN_HANDLES -# define STATUS_SERVER_HAS_OPEN_HANDLES ((NTSTATUS) 0x80000024L) -#endif - -#ifndef STATUS_ALREADY_DISCONNECTED -# define STATUS_ALREADY_DISCONNECTED ((NTSTATUS) 0x80000025L) -#endif - -#ifndef STATUS_LONGJUMP -# define STATUS_LONGJUMP ((NTSTATUS) 0x80000026L) -#endif - -#ifndef STATUS_CLEANER_CARTRIDGE_INSTALLED -# define STATUS_CLEANER_CARTRIDGE_INSTALLED ((NTSTATUS) 0x80000027L) -#endif - -#ifndef STATUS_PLUGPLAY_QUERY_VETOED -# define STATUS_PLUGPLAY_QUERY_VETOED ((NTSTATUS) 0x80000028L) -#endif - -#ifndef STATUS_UNWIND_CONSOLIDATE -# define STATUS_UNWIND_CONSOLIDATE ((NTSTATUS) 0x80000029L) -#endif - -#ifndef STATUS_REGISTRY_HIVE_RECOVERED -# define STATUS_REGISTRY_HIVE_RECOVERED ((NTSTATUS) 0x8000002AL) -#endif - -#ifndef STATUS_DLL_MIGHT_BE_INSECURE -# define STATUS_DLL_MIGHT_BE_INSECURE ((NTSTATUS) 0x8000002BL) -#endif - -#ifndef STATUS_DLL_MIGHT_BE_INCOMPATIBLE -# define STATUS_DLL_MIGHT_BE_INCOMPATIBLE ((NTSTATUS) 0x8000002CL) -#endif - -#ifndef STATUS_STOPPED_ON_SYMLINK -# define STATUS_STOPPED_ON_SYMLINK ((NTSTATUS) 0x8000002DL) -#endif - -#ifndef STATUS_CANNOT_GRANT_REQUESTED_OPLOCK -# define STATUS_CANNOT_GRANT_REQUESTED_OPLOCK ((NTSTATUS) 0x8000002EL) -#endif - -#ifndef STATUS_NO_ACE_CONDITION -# define STATUS_NO_ACE_CONDITION ((NTSTATUS) 0x8000002FL) -#endif - -#ifndef STATUS_UNSUCCESSFUL -# define STATUS_UNSUCCESSFUL ((NTSTATUS) 0xC0000001L) -#endif - -#ifndef STATUS_NOT_IMPLEMENTED -# define STATUS_NOT_IMPLEMENTED ((NTSTATUS) 0xC0000002L) -#endif - -#ifndef STATUS_INVALID_INFO_CLASS -# define STATUS_INVALID_INFO_CLASS ((NTSTATUS) 0xC0000003L) -#endif - -#ifndef STATUS_INFO_LENGTH_MISMATCH -# define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS) 0xC0000004L) -#endif - -#ifndef STATUS_ACCESS_VIOLATION -# define STATUS_ACCESS_VIOLATION ((NTSTATUS) 0xC0000005L) -#endif - -#ifndef STATUS_IN_PAGE_ERROR -# define STATUS_IN_PAGE_ERROR ((NTSTATUS) 0xC0000006L) -#endif - -#ifndef STATUS_PAGEFILE_QUOTA -# define STATUS_PAGEFILE_QUOTA ((NTSTATUS) 0xC0000007L) -#endif - -#ifndef STATUS_INVALID_HANDLE -# define STATUS_INVALID_HANDLE ((NTSTATUS) 0xC0000008L) -#endif - -#ifndef STATUS_BAD_INITIAL_STACK -# define STATUS_BAD_INITIAL_STACK ((NTSTATUS) 0xC0000009L) -#endif - -#ifndef STATUS_BAD_INITIAL_PC -# define STATUS_BAD_INITIAL_PC ((NTSTATUS) 0xC000000AL) -#endif - -#ifndef STATUS_INVALID_CID -# define STATUS_INVALID_CID ((NTSTATUS) 0xC000000BL) -#endif - -#ifndef STATUS_TIMER_NOT_CANCELED -# define STATUS_TIMER_NOT_CANCELED ((NTSTATUS) 0xC000000CL) -#endif - -#ifndef STATUS_INVALID_PARAMETER -# define STATUS_INVALID_PARAMETER ((NTSTATUS) 0xC000000DL) -#endif - -#ifndef STATUS_NO_SUCH_DEVICE -# define STATUS_NO_SUCH_DEVICE ((NTSTATUS) 0xC000000EL) -#endif - -#ifndef STATUS_NO_SUCH_FILE -# define STATUS_NO_SUCH_FILE ((NTSTATUS) 0xC000000FL) -#endif - -#ifndef STATUS_INVALID_DEVICE_REQUEST -# define STATUS_INVALID_DEVICE_REQUEST ((NTSTATUS) 0xC0000010L) -#endif - -#ifndef STATUS_END_OF_FILE -# define STATUS_END_OF_FILE ((NTSTATUS) 0xC0000011L) -#endif - -#ifndef STATUS_WRONG_VOLUME -# define STATUS_WRONG_VOLUME ((NTSTATUS) 0xC0000012L) -#endif - -#ifndef STATUS_NO_MEDIA_IN_DEVICE -# define STATUS_NO_MEDIA_IN_DEVICE ((NTSTATUS) 0xC0000013L) -#endif - -#ifndef STATUS_UNRECOGNIZED_MEDIA -# define STATUS_UNRECOGNIZED_MEDIA ((NTSTATUS) 0xC0000014L) -#endif - -#ifndef STATUS_NONEXISTENT_SECTOR -# define STATUS_NONEXISTENT_SECTOR ((NTSTATUS) 0xC0000015L) -#endif - -#ifndef STATUS_MORE_PROCESSING_REQUIRED -# define STATUS_MORE_PROCESSING_REQUIRED ((NTSTATUS) 0xC0000016L) -#endif - -#ifndef STATUS_NO_MEMORY -# define STATUS_NO_MEMORY ((NTSTATUS) 0xC0000017L) -#endif - -#ifndef STATUS_CONFLICTING_ADDRESSES -# define STATUS_CONFLICTING_ADDRESSES ((NTSTATUS) 0xC0000018L) -#endif - -#ifndef STATUS_NOT_MAPPED_VIEW -# define STATUS_NOT_MAPPED_VIEW ((NTSTATUS) 0xC0000019L) -#endif - -#ifndef STATUS_UNABLE_TO_FREE_VM -# define STATUS_UNABLE_TO_FREE_VM ((NTSTATUS) 0xC000001AL) -#endif - -#ifndef STATUS_UNABLE_TO_DELETE_SECTION -# define STATUS_UNABLE_TO_DELETE_SECTION ((NTSTATUS) 0xC000001BL) -#endif - -#ifndef STATUS_INVALID_SYSTEM_SERVICE -# define STATUS_INVALID_SYSTEM_SERVICE ((NTSTATUS) 0xC000001CL) -#endif - -#ifndef STATUS_ILLEGAL_INSTRUCTION -# define STATUS_ILLEGAL_INSTRUCTION ((NTSTATUS) 0xC000001DL) -#endif - -#ifndef STATUS_INVALID_LOCK_SEQUENCE -# define STATUS_INVALID_LOCK_SEQUENCE ((NTSTATUS) 0xC000001EL) -#endif - -#ifndef STATUS_INVALID_VIEW_SIZE -# define STATUS_INVALID_VIEW_SIZE ((NTSTATUS) 0xC000001FL) -#endif - -#ifndef STATUS_INVALID_FILE_FOR_SECTION -# define STATUS_INVALID_FILE_FOR_SECTION ((NTSTATUS) 0xC0000020L) -#endif - -#ifndef STATUS_ALREADY_COMMITTED -# define STATUS_ALREADY_COMMITTED ((NTSTATUS) 0xC0000021L) -#endif - -#ifndef STATUS_ACCESS_DENIED -# define STATUS_ACCESS_DENIED ((NTSTATUS) 0xC0000022L) -#endif - -#ifndef STATUS_BUFFER_TOO_SMALL -# define STATUS_BUFFER_TOO_SMALL ((NTSTATUS) 0xC0000023L) -#endif - -#ifndef STATUS_OBJECT_TYPE_MISMATCH -# define STATUS_OBJECT_TYPE_MISMATCH ((NTSTATUS) 0xC0000024L) -#endif - -#ifndef STATUS_NONCONTINUABLE_EXCEPTION -# define STATUS_NONCONTINUABLE_EXCEPTION ((NTSTATUS) 0xC0000025L) -#endif - -#ifndef STATUS_INVALID_DISPOSITION -# define STATUS_INVALID_DISPOSITION ((NTSTATUS) 0xC0000026L) -#endif - -#ifndef STATUS_UNWIND -# define STATUS_UNWIND ((NTSTATUS) 0xC0000027L) -#endif - -#ifndef STATUS_BAD_STACK -# define STATUS_BAD_STACK ((NTSTATUS) 0xC0000028L) -#endif - -#ifndef STATUS_INVALID_UNWIND_TARGET -# define STATUS_INVALID_UNWIND_TARGET ((NTSTATUS) 0xC0000029L) -#endif - -#ifndef STATUS_NOT_LOCKED -# define STATUS_NOT_LOCKED ((NTSTATUS) 0xC000002AL) -#endif - -#ifndef STATUS_PARITY_ERROR -# define STATUS_PARITY_ERROR ((NTSTATUS) 0xC000002BL) -#endif - -#ifndef STATUS_UNABLE_TO_DECOMMIT_VM -# define STATUS_UNABLE_TO_DECOMMIT_VM ((NTSTATUS) 0xC000002CL) -#endif - -#ifndef STATUS_NOT_COMMITTED -# define STATUS_NOT_COMMITTED ((NTSTATUS) 0xC000002DL) -#endif - -#ifndef STATUS_INVALID_PORT_ATTRIBUTES -# define STATUS_INVALID_PORT_ATTRIBUTES ((NTSTATUS) 0xC000002EL) -#endif - -#ifndef STATUS_PORT_MESSAGE_TOO_LONG -# define STATUS_PORT_MESSAGE_TOO_LONG ((NTSTATUS) 0xC000002FL) -#endif - -#ifndef STATUS_INVALID_PARAMETER_MIX -# define STATUS_INVALID_PARAMETER_MIX ((NTSTATUS) 0xC0000030L) -#endif - -#ifndef STATUS_INVALID_QUOTA_LOWER -# define STATUS_INVALID_QUOTA_LOWER ((NTSTATUS) 0xC0000031L) -#endif - -#ifndef STATUS_DISK_CORRUPT_ERROR -# define STATUS_DISK_CORRUPT_ERROR ((NTSTATUS) 0xC0000032L) -#endif - -#ifndef STATUS_OBJECT_NAME_INVALID -# define STATUS_OBJECT_NAME_INVALID ((NTSTATUS) 0xC0000033L) -#endif - -#ifndef STATUS_OBJECT_NAME_NOT_FOUND -# define STATUS_OBJECT_NAME_NOT_FOUND ((NTSTATUS) 0xC0000034L) -#endif - -#ifndef STATUS_OBJECT_NAME_COLLISION -# define STATUS_OBJECT_NAME_COLLISION ((NTSTATUS) 0xC0000035L) -#endif - -#ifndef STATUS_PORT_DISCONNECTED -# define STATUS_PORT_DISCONNECTED ((NTSTATUS) 0xC0000037L) -#endif - -#ifndef STATUS_DEVICE_ALREADY_ATTACHED -# define STATUS_DEVICE_ALREADY_ATTACHED ((NTSTATUS) 0xC0000038L) -#endif - -#ifndef STATUS_OBJECT_PATH_INVALID -# define STATUS_OBJECT_PATH_INVALID ((NTSTATUS) 0xC0000039L) -#endif - -#ifndef STATUS_OBJECT_PATH_NOT_FOUND -# define STATUS_OBJECT_PATH_NOT_FOUND ((NTSTATUS) 0xC000003AL) -#endif - -#ifndef STATUS_OBJECT_PATH_SYNTAX_BAD -# define STATUS_OBJECT_PATH_SYNTAX_BAD ((NTSTATUS) 0xC000003BL) -#endif - -#ifndef STATUS_DATA_OVERRUN -# define STATUS_DATA_OVERRUN ((NTSTATUS) 0xC000003CL) -#endif - -#ifndef STATUS_DATA_LATE_ERROR -# define STATUS_DATA_LATE_ERROR ((NTSTATUS) 0xC000003DL) -#endif - -#ifndef STATUS_DATA_ERROR -# define STATUS_DATA_ERROR ((NTSTATUS) 0xC000003EL) -#endif - -#ifndef STATUS_CRC_ERROR -# define STATUS_CRC_ERROR ((NTSTATUS) 0xC000003FL) -#endif - -#ifndef STATUS_SECTION_TOO_BIG -# define STATUS_SECTION_TOO_BIG ((NTSTATUS) 0xC0000040L) -#endif - -#ifndef STATUS_PORT_CONNECTION_REFUSED -# define STATUS_PORT_CONNECTION_REFUSED ((NTSTATUS) 0xC0000041L) -#endif - -#ifndef STATUS_INVALID_PORT_HANDLE -# define STATUS_INVALID_PORT_HANDLE ((NTSTATUS) 0xC0000042L) -#endif - -#ifndef STATUS_SHARING_VIOLATION -# define STATUS_SHARING_VIOLATION ((NTSTATUS) 0xC0000043L) -#endif - -#ifndef STATUS_QUOTA_EXCEEDED -# define STATUS_QUOTA_EXCEEDED ((NTSTATUS) 0xC0000044L) -#endif - -#ifndef STATUS_INVALID_PAGE_PROTECTION -# define STATUS_INVALID_PAGE_PROTECTION ((NTSTATUS) 0xC0000045L) -#endif - -#ifndef STATUS_MUTANT_NOT_OWNED -# define STATUS_MUTANT_NOT_OWNED ((NTSTATUS) 0xC0000046L) -#endif - -#ifndef STATUS_SEMAPHORE_LIMIT_EXCEEDED -# define STATUS_SEMAPHORE_LIMIT_EXCEEDED ((NTSTATUS) 0xC0000047L) -#endif - -#ifndef STATUS_PORT_ALREADY_SET -# define STATUS_PORT_ALREADY_SET ((NTSTATUS) 0xC0000048L) -#endif - -#ifndef STATUS_SECTION_NOT_IMAGE -# define STATUS_SECTION_NOT_IMAGE ((NTSTATUS) 0xC0000049L) -#endif - -#ifndef STATUS_SUSPEND_COUNT_EXCEEDED -# define STATUS_SUSPEND_COUNT_EXCEEDED ((NTSTATUS) 0xC000004AL) -#endif - -#ifndef STATUS_THREAD_IS_TERMINATING -# define STATUS_THREAD_IS_TERMINATING ((NTSTATUS) 0xC000004BL) -#endif - -#ifndef STATUS_BAD_WORKING_SET_LIMIT -# define STATUS_BAD_WORKING_SET_LIMIT ((NTSTATUS) 0xC000004CL) -#endif - -#ifndef STATUS_INCOMPATIBLE_FILE_MAP -# define STATUS_INCOMPATIBLE_FILE_MAP ((NTSTATUS) 0xC000004DL) -#endif - -#ifndef STATUS_SECTION_PROTECTION -# define STATUS_SECTION_PROTECTION ((NTSTATUS) 0xC000004EL) -#endif - -#ifndef STATUS_EAS_NOT_SUPPORTED -# define STATUS_EAS_NOT_SUPPORTED ((NTSTATUS) 0xC000004FL) -#endif - -#ifndef STATUS_EA_TOO_LARGE -# define STATUS_EA_TOO_LARGE ((NTSTATUS) 0xC0000050L) -#endif - -#ifndef STATUS_NONEXISTENT_EA_ENTRY -# define STATUS_NONEXISTENT_EA_ENTRY ((NTSTATUS) 0xC0000051L) -#endif - -#ifndef STATUS_NO_EAS_ON_FILE -# define STATUS_NO_EAS_ON_FILE ((NTSTATUS) 0xC0000052L) -#endif - -#ifndef STATUS_EA_CORRUPT_ERROR -# define STATUS_EA_CORRUPT_ERROR ((NTSTATUS) 0xC0000053L) -#endif - -#ifndef STATUS_FILE_LOCK_CONFLICT -# define STATUS_FILE_LOCK_CONFLICT ((NTSTATUS) 0xC0000054L) -#endif - -#ifndef STATUS_LOCK_NOT_GRANTED -# define STATUS_LOCK_NOT_GRANTED ((NTSTATUS) 0xC0000055L) -#endif - -#ifndef STATUS_DELETE_PENDING -# define STATUS_DELETE_PENDING ((NTSTATUS) 0xC0000056L) -#endif - -#ifndef STATUS_CTL_FILE_NOT_SUPPORTED -# define STATUS_CTL_FILE_NOT_SUPPORTED ((NTSTATUS) 0xC0000057L) -#endif - -#ifndef STATUS_UNKNOWN_REVISION -# define STATUS_UNKNOWN_REVISION ((NTSTATUS) 0xC0000058L) -#endif - -#ifndef STATUS_REVISION_MISMATCH -# define STATUS_REVISION_MISMATCH ((NTSTATUS) 0xC0000059L) -#endif - -#ifndef STATUS_INVALID_OWNER -# define STATUS_INVALID_OWNER ((NTSTATUS) 0xC000005AL) -#endif - -#ifndef STATUS_INVALID_PRIMARY_GROUP -# define STATUS_INVALID_PRIMARY_GROUP ((NTSTATUS) 0xC000005BL) -#endif - -#ifndef STATUS_NO_IMPERSONATION_TOKEN -# define STATUS_NO_IMPERSONATION_TOKEN ((NTSTATUS) 0xC000005CL) -#endif - -#ifndef STATUS_CANT_DISABLE_MANDATORY -# define STATUS_CANT_DISABLE_MANDATORY ((NTSTATUS) 0xC000005DL) -#endif - -#ifndef STATUS_NO_LOGON_SERVERS -# define STATUS_NO_LOGON_SERVERS ((NTSTATUS) 0xC000005EL) -#endif - -#ifndef STATUS_NO_SUCH_LOGON_SESSION -# define STATUS_NO_SUCH_LOGON_SESSION ((NTSTATUS) 0xC000005FL) -#endif - -#ifndef STATUS_NO_SUCH_PRIVILEGE -# define STATUS_NO_SUCH_PRIVILEGE ((NTSTATUS) 0xC0000060L) -#endif - -#ifndef STATUS_PRIVILEGE_NOT_HELD -# define STATUS_PRIVILEGE_NOT_HELD ((NTSTATUS) 0xC0000061L) -#endif - -#ifndef STATUS_INVALID_ACCOUNT_NAME -# define STATUS_INVALID_ACCOUNT_NAME ((NTSTATUS) 0xC0000062L) -#endif - -#ifndef STATUS_USER_EXISTS -# define STATUS_USER_EXISTS ((NTSTATUS) 0xC0000063L) -#endif - -#ifndef STATUS_NO_SUCH_USER -# define STATUS_NO_SUCH_USER ((NTSTATUS) 0xC0000064L) -#endif - -#ifndef STATUS_GROUP_EXISTS -# define STATUS_GROUP_EXISTS ((NTSTATUS) 0xC0000065L) -#endif - -#ifndef STATUS_NO_SUCH_GROUP -# define STATUS_NO_SUCH_GROUP ((NTSTATUS) 0xC0000066L) -#endif - -#ifndef STATUS_MEMBER_IN_GROUP -# define STATUS_MEMBER_IN_GROUP ((NTSTATUS) 0xC0000067L) -#endif - -#ifndef STATUS_MEMBER_NOT_IN_GROUP -# define STATUS_MEMBER_NOT_IN_GROUP ((NTSTATUS) 0xC0000068L) -#endif - -#ifndef STATUS_LAST_ADMIN -# define STATUS_LAST_ADMIN ((NTSTATUS) 0xC0000069L) -#endif - -#ifndef STATUS_WRONG_PASSWORD -# define STATUS_WRONG_PASSWORD ((NTSTATUS) 0xC000006AL) -#endif - -#ifndef STATUS_ILL_FORMED_PASSWORD -# define STATUS_ILL_FORMED_PASSWORD ((NTSTATUS) 0xC000006BL) -#endif - -#ifndef STATUS_PASSWORD_RESTRICTION -# define STATUS_PASSWORD_RESTRICTION ((NTSTATUS) 0xC000006CL) -#endif - -#ifndef STATUS_LOGON_FAILURE -# define STATUS_LOGON_FAILURE ((NTSTATUS) 0xC000006DL) -#endif - -#ifndef STATUS_ACCOUNT_RESTRICTION -# define STATUS_ACCOUNT_RESTRICTION ((NTSTATUS) 0xC000006EL) -#endif - -#ifndef STATUS_INVALID_LOGON_HOURS -# define STATUS_INVALID_LOGON_HOURS ((NTSTATUS) 0xC000006FL) -#endif - -#ifndef STATUS_INVALID_WORKSTATION -# define STATUS_INVALID_WORKSTATION ((NTSTATUS) 0xC0000070L) -#endif - -#ifndef STATUS_PASSWORD_EXPIRED -# define STATUS_PASSWORD_EXPIRED ((NTSTATUS) 0xC0000071L) -#endif - -#ifndef STATUS_ACCOUNT_DISABLED -# define STATUS_ACCOUNT_DISABLED ((NTSTATUS) 0xC0000072L) -#endif - -#ifndef STATUS_NONE_MAPPED -# define STATUS_NONE_MAPPED ((NTSTATUS) 0xC0000073L) -#endif - -#ifndef STATUS_TOO_MANY_LUIDS_REQUESTED -# define STATUS_TOO_MANY_LUIDS_REQUESTED ((NTSTATUS) 0xC0000074L) -#endif - -#ifndef STATUS_LUIDS_EXHAUSTED -# define STATUS_LUIDS_EXHAUSTED ((NTSTATUS) 0xC0000075L) -#endif - -#ifndef STATUS_INVALID_SUB_AUTHORITY -# define STATUS_INVALID_SUB_AUTHORITY ((NTSTATUS) 0xC0000076L) -#endif - -#ifndef STATUS_INVALID_ACL -# define STATUS_INVALID_ACL ((NTSTATUS) 0xC0000077L) -#endif - -#ifndef STATUS_INVALID_SID -# define STATUS_INVALID_SID ((NTSTATUS) 0xC0000078L) -#endif - -#ifndef STATUS_INVALID_SECURITY_DESCR -# define STATUS_INVALID_SECURITY_DESCR ((NTSTATUS) 0xC0000079L) -#endif - -#ifndef STATUS_PROCEDURE_NOT_FOUND -# define STATUS_PROCEDURE_NOT_FOUND ((NTSTATUS) 0xC000007AL) -#endif - -#ifndef STATUS_INVALID_IMAGE_FORMAT -# define STATUS_INVALID_IMAGE_FORMAT ((NTSTATUS) 0xC000007BL) -#endif - -#ifndef STATUS_NO_TOKEN -# define STATUS_NO_TOKEN ((NTSTATUS) 0xC000007CL) -#endif - -#ifndef STATUS_BAD_INHERITANCE_ACL -# define STATUS_BAD_INHERITANCE_ACL ((NTSTATUS) 0xC000007DL) -#endif - -#ifndef STATUS_RANGE_NOT_LOCKED -# define STATUS_RANGE_NOT_LOCKED ((NTSTATUS) 0xC000007EL) -#endif - -#ifndef STATUS_DISK_FULL -# define STATUS_DISK_FULL ((NTSTATUS) 0xC000007FL) -#endif - -#ifndef STATUS_SERVER_DISABLED -# define STATUS_SERVER_DISABLED ((NTSTATUS) 0xC0000080L) -#endif - -#ifndef STATUS_SERVER_NOT_DISABLED -# define STATUS_SERVER_NOT_DISABLED ((NTSTATUS) 0xC0000081L) -#endif - -#ifndef STATUS_TOO_MANY_GUIDS_REQUESTED -# define STATUS_TOO_MANY_GUIDS_REQUESTED ((NTSTATUS) 0xC0000082L) -#endif - -#ifndef STATUS_GUIDS_EXHAUSTED -# define STATUS_GUIDS_EXHAUSTED ((NTSTATUS) 0xC0000083L) -#endif - -#ifndef STATUS_INVALID_ID_AUTHORITY -# define STATUS_INVALID_ID_AUTHORITY ((NTSTATUS) 0xC0000084L) -#endif - -#ifndef STATUS_AGENTS_EXHAUSTED -# define STATUS_AGENTS_EXHAUSTED ((NTSTATUS) 0xC0000085L) -#endif - -#ifndef STATUS_INVALID_VOLUME_LABEL -# define STATUS_INVALID_VOLUME_LABEL ((NTSTATUS) 0xC0000086L) -#endif - -#ifndef STATUS_SECTION_NOT_EXTENDED -# define STATUS_SECTION_NOT_EXTENDED ((NTSTATUS) 0xC0000087L) -#endif - -#ifndef STATUS_NOT_MAPPED_DATA -# define STATUS_NOT_MAPPED_DATA ((NTSTATUS) 0xC0000088L) -#endif - -#ifndef STATUS_RESOURCE_DATA_NOT_FOUND -# define STATUS_RESOURCE_DATA_NOT_FOUND ((NTSTATUS) 0xC0000089L) -#endif - -#ifndef STATUS_RESOURCE_TYPE_NOT_FOUND -# define STATUS_RESOURCE_TYPE_NOT_FOUND ((NTSTATUS) 0xC000008AL) -#endif - -#ifndef STATUS_RESOURCE_NAME_NOT_FOUND -# define STATUS_RESOURCE_NAME_NOT_FOUND ((NTSTATUS) 0xC000008BL) -#endif - -#ifndef STATUS_ARRAY_BOUNDS_EXCEEDED -# define STATUS_ARRAY_BOUNDS_EXCEEDED ((NTSTATUS) 0xC000008CL) -#endif - -#ifndef STATUS_FLOAT_DENORMAL_OPERAND -# define STATUS_FLOAT_DENORMAL_OPERAND ((NTSTATUS) 0xC000008DL) -#endif - -#ifndef STATUS_FLOAT_DIVIDE_BY_ZERO -# define STATUS_FLOAT_DIVIDE_BY_ZERO ((NTSTATUS) 0xC000008EL) -#endif - -#ifndef STATUS_FLOAT_INEXACT_RESULT -# define STATUS_FLOAT_INEXACT_RESULT ((NTSTATUS) 0xC000008FL) -#endif - -#ifndef STATUS_FLOAT_INVALID_OPERATION -# define STATUS_FLOAT_INVALID_OPERATION ((NTSTATUS) 0xC0000090L) -#endif - -#ifndef STATUS_FLOAT_OVERFLOW -# define STATUS_FLOAT_OVERFLOW ((NTSTATUS) 0xC0000091L) -#endif - -#ifndef STATUS_FLOAT_STACK_CHECK -# define STATUS_FLOAT_STACK_CHECK ((NTSTATUS) 0xC0000092L) -#endif - -#ifndef STATUS_FLOAT_UNDERFLOW -# define STATUS_FLOAT_UNDERFLOW ((NTSTATUS) 0xC0000093L) -#endif - -#ifndef STATUS_INTEGER_DIVIDE_BY_ZERO -# define STATUS_INTEGER_DIVIDE_BY_ZERO ((NTSTATUS) 0xC0000094L) -#endif - -#ifndef STATUS_INTEGER_OVERFLOW -# define STATUS_INTEGER_OVERFLOW ((NTSTATUS) 0xC0000095L) -#endif - -#ifndef STATUS_PRIVILEGED_INSTRUCTION -# define STATUS_PRIVILEGED_INSTRUCTION ((NTSTATUS) 0xC0000096L) -#endif - -#ifndef STATUS_TOO_MANY_PAGING_FILES -# define STATUS_TOO_MANY_PAGING_FILES ((NTSTATUS) 0xC0000097L) -#endif - -#ifndef STATUS_FILE_INVALID -# define STATUS_FILE_INVALID ((NTSTATUS) 0xC0000098L) -#endif - -#ifndef STATUS_ALLOTTED_SPACE_EXCEEDED -# define STATUS_ALLOTTED_SPACE_EXCEEDED ((NTSTATUS) 0xC0000099L) -#endif - -#ifndef STATUS_INSUFFICIENT_RESOURCES -# define STATUS_INSUFFICIENT_RESOURCES ((NTSTATUS) 0xC000009AL) -#endif - -#ifndef STATUS_DFS_EXIT_PATH_FOUND -# define STATUS_DFS_EXIT_PATH_FOUND ((NTSTATUS) 0xC000009BL) -#endif - -#ifndef STATUS_DEVICE_DATA_ERROR -# define STATUS_DEVICE_DATA_ERROR ((NTSTATUS) 0xC000009CL) -#endif - -#ifndef STATUS_DEVICE_NOT_CONNECTED -# define STATUS_DEVICE_NOT_CONNECTED ((NTSTATUS) 0xC000009DL) -#endif - -#ifndef STATUS_DEVICE_POWER_FAILURE -# define STATUS_DEVICE_POWER_FAILURE ((NTSTATUS) 0xC000009EL) -#endif - -#ifndef STATUS_FREE_VM_NOT_AT_BASE -# define STATUS_FREE_VM_NOT_AT_BASE ((NTSTATUS) 0xC000009FL) -#endif - -#ifndef STATUS_MEMORY_NOT_ALLOCATED -# define STATUS_MEMORY_NOT_ALLOCATED ((NTSTATUS) 0xC00000A0L) -#endif - -#ifndef STATUS_WORKING_SET_QUOTA -# define STATUS_WORKING_SET_QUOTA ((NTSTATUS) 0xC00000A1L) -#endif - -#ifndef STATUS_MEDIA_WRITE_PROTECTED -# define STATUS_MEDIA_WRITE_PROTECTED ((NTSTATUS) 0xC00000A2L) -#endif - -#ifndef STATUS_DEVICE_NOT_READY -# define STATUS_DEVICE_NOT_READY ((NTSTATUS) 0xC00000A3L) -#endif - -#ifndef STATUS_INVALID_GROUP_ATTRIBUTES -# define STATUS_INVALID_GROUP_ATTRIBUTES ((NTSTATUS) 0xC00000A4L) -#endif - -#ifndef STATUS_BAD_IMPERSONATION_LEVEL -# define STATUS_BAD_IMPERSONATION_LEVEL ((NTSTATUS) 0xC00000A5L) -#endif - -#ifndef STATUS_CANT_OPEN_ANONYMOUS -# define STATUS_CANT_OPEN_ANONYMOUS ((NTSTATUS) 0xC00000A6L) -#endif - -#ifndef STATUS_BAD_VALIDATION_CLASS -# define STATUS_BAD_VALIDATION_CLASS ((NTSTATUS) 0xC00000A7L) -#endif - -#ifndef STATUS_BAD_TOKEN_TYPE -# define STATUS_BAD_TOKEN_TYPE ((NTSTATUS) 0xC00000A8L) -#endif - -#ifndef STATUS_BAD_MASTER_BOOT_RECORD -# define STATUS_BAD_MASTER_BOOT_RECORD ((NTSTATUS) 0xC00000A9L) -#endif - -#ifndef STATUS_INSTRUCTION_MISALIGNMENT -# define STATUS_INSTRUCTION_MISALIGNMENT ((NTSTATUS) 0xC00000AAL) -#endif - -#ifndef STATUS_INSTANCE_NOT_AVAILABLE -# define STATUS_INSTANCE_NOT_AVAILABLE ((NTSTATUS) 0xC00000ABL) -#endif - -#ifndef STATUS_PIPE_NOT_AVAILABLE -# define STATUS_PIPE_NOT_AVAILABLE ((NTSTATUS) 0xC00000ACL) -#endif - -#ifndef STATUS_INVALID_PIPE_STATE -# define STATUS_INVALID_PIPE_STATE ((NTSTATUS) 0xC00000ADL) -#endif - -#ifndef STATUS_PIPE_BUSY -# define STATUS_PIPE_BUSY ((NTSTATUS) 0xC00000AEL) -#endif - -#ifndef STATUS_ILLEGAL_FUNCTION -# define STATUS_ILLEGAL_FUNCTION ((NTSTATUS) 0xC00000AFL) -#endif - -#ifndef STATUS_PIPE_DISCONNECTED -# define STATUS_PIPE_DISCONNECTED ((NTSTATUS) 0xC00000B0L) -#endif - -#ifndef STATUS_PIPE_CLOSING -# define STATUS_PIPE_CLOSING ((NTSTATUS) 0xC00000B1L) -#endif - -#ifndef STATUS_PIPE_CONNECTED -# define STATUS_PIPE_CONNECTED ((NTSTATUS) 0xC00000B2L) -#endif - -#ifndef STATUS_PIPE_LISTENING -# define STATUS_PIPE_LISTENING ((NTSTATUS) 0xC00000B3L) -#endif - -#ifndef STATUS_INVALID_READ_MODE -# define STATUS_INVALID_READ_MODE ((NTSTATUS) 0xC00000B4L) -#endif - -#ifndef STATUS_IO_TIMEOUT -# define STATUS_IO_TIMEOUT ((NTSTATUS) 0xC00000B5L) -#endif - -#ifndef STATUS_FILE_FORCED_CLOSED -# define STATUS_FILE_FORCED_CLOSED ((NTSTATUS) 0xC00000B6L) -#endif - -#ifndef STATUS_PROFILING_NOT_STARTED -# define STATUS_PROFILING_NOT_STARTED ((NTSTATUS) 0xC00000B7L) -#endif - -#ifndef STATUS_PROFILING_NOT_STOPPED -# define STATUS_PROFILING_NOT_STOPPED ((NTSTATUS) 0xC00000B8L) -#endif - -#ifndef STATUS_COULD_NOT_INTERPRET -# define STATUS_COULD_NOT_INTERPRET ((NTSTATUS) 0xC00000B9L) -#endif - -#ifndef STATUS_FILE_IS_A_DIRECTORY -# define STATUS_FILE_IS_A_DIRECTORY ((NTSTATUS) 0xC00000BAL) -#endif - -#ifndef STATUS_NOT_SUPPORTED -# define STATUS_NOT_SUPPORTED ((NTSTATUS) 0xC00000BBL) -#endif - -#ifndef STATUS_REMOTE_NOT_LISTENING -# define STATUS_REMOTE_NOT_LISTENING ((NTSTATUS) 0xC00000BCL) -#endif - -#ifndef STATUS_DUPLICATE_NAME -# define STATUS_DUPLICATE_NAME ((NTSTATUS) 0xC00000BDL) -#endif - -#ifndef STATUS_BAD_NETWORK_PATH -# define STATUS_BAD_NETWORK_PATH ((NTSTATUS) 0xC00000BEL) -#endif - -#ifndef STATUS_NETWORK_BUSY -# define STATUS_NETWORK_BUSY ((NTSTATUS) 0xC00000BFL) -#endif - -#ifndef STATUS_DEVICE_DOES_NOT_EXIST -# define STATUS_DEVICE_DOES_NOT_EXIST ((NTSTATUS) 0xC00000C0L) -#endif - -#ifndef STATUS_TOO_MANY_COMMANDS -# define STATUS_TOO_MANY_COMMANDS ((NTSTATUS) 0xC00000C1L) -#endif - -#ifndef STATUS_ADAPTER_HARDWARE_ERROR -# define STATUS_ADAPTER_HARDWARE_ERROR ((NTSTATUS) 0xC00000C2L) -#endif - -#ifndef STATUS_INVALID_NETWORK_RESPONSE -# define STATUS_INVALID_NETWORK_RESPONSE ((NTSTATUS) 0xC00000C3L) -#endif - -#ifndef STATUS_UNEXPECTED_NETWORK_ERROR -# define STATUS_UNEXPECTED_NETWORK_ERROR ((NTSTATUS) 0xC00000C4L) -#endif - -#ifndef STATUS_BAD_REMOTE_ADAPTER -# define STATUS_BAD_REMOTE_ADAPTER ((NTSTATUS) 0xC00000C5L) -#endif - -#ifndef STATUS_PRINT_QUEUE_FULL -# define STATUS_PRINT_QUEUE_FULL ((NTSTATUS) 0xC00000C6L) -#endif - -#ifndef STATUS_NO_SPOOL_SPACE -# define STATUS_NO_SPOOL_SPACE ((NTSTATUS) 0xC00000C7L) -#endif - -#ifndef STATUS_PRINT_CANCELLED -# define STATUS_PRINT_CANCELLED ((NTSTATUS) 0xC00000C8L) -#endif - -#ifndef STATUS_NETWORK_NAME_DELETED -# define STATUS_NETWORK_NAME_DELETED ((NTSTATUS) 0xC00000C9L) -#endif - -#ifndef STATUS_NETWORK_ACCESS_DENIED -# define STATUS_NETWORK_ACCESS_DENIED ((NTSTATUS) 0xC00000CAL) -#endif - -#ifndef STATUS_BAD_DEVICE_TYPE -# define STATUS_BAD_DEVICE_TYPE ((NTSTATUS) 0xC00000CBL) -#endif - -#ifndef STATUS_BAD_NETWORK_NAME -# define STATUS_BAD_NETWORK_NAME ((NTSTATUS) 0xC00000CCL) -#endif - -#ifndef STATUS_TOO_MANY_NAMES -# define STATUS_TOO_MANY_NAMES ((NTSTATUS) 0xC00000CDL) -#endif - -#ifndef STATUS_TOO_MANY_SESSIONS -# define STATUS_TOO_MANY_SESSIONS ((NTSTATUS) 0xC00000CEL) -#endif - -#ifndef STATUS_SHARING_PAUSED -# define STATUS_SHARING_PAUSED ((NTSTATUS) 0xC00000CFL) -#endif - -#ifndef STATUS_REQUEST_NOT_ACCEPTED -# define STATUS_REQUEST_NOT_ACCEPTED ((NTSTATUS) 0xC00000D0L) -#endif - -#ifndef STATUS_REDIRECTOR_PAUSED -# define STATUS_REDIRECTOR_PAUSED ((NTSTATUS) 0xC00000D1L) -#endif - -#ifndef STATUS_NET_WRITE_FAULT -# define STATUS_NET_WRITE_FAULT ((NTSTATUS) 0xC00000D2L) -#endif - -#ifndef STATUS_PROFILING_AT_LIMIT -# define STATUS_PROFILING_AT_LIMIT ((NTSTATUS) 0xC00000D3L) -#endif - -#ifndef STATUS_NOT_SAME_DEVICE -# define STATUS_NOT_SAME_DEVICE ((NTSTATUS) 0xC00000D4L) -#endif - -#ifndef STATUS_FILE_RENAMED -# define STATUS_FILE_RENAMED ((NTSTATUS) 0xC00000D5L) -#endif - -#ifndef STATUS_VIRTUAL_CIRCUIT_CLOSED -# define STATUS_VIRTUAL_CIRCUIT_CLOSED ((NTSTATUS) 0xC00000D6L) -#endif - -#ifndef STATUS_NO_SECURITY_ON_OBJECT -# define STATUS_NO_SECURITY_ON_OBJECT ((NTSTATUS) 0xC00000D7L) -#endif - -#ifndef STATUS_CANT_WAIT -# define STATUS_CANT_WAIT ((NTSTATUS) 0xC00000D8L) -#endif - -#ifndef STATUS_PIPE_EMPTY -# define STATUS_PIPE_EMPTY ((NTSTATUS) 0xC00000D9L) -#endif - -#ifndef STATUS_CANT_ACCESS_DOMAIN_INFO -# define STATUS_CANT_ACCESS_DOMAIN_INFO ((NTSTATUS) 0xC00000DAL) -#endif - -#ifndef STATUS_CANT_TERMINATE_SELF -# define STATUS_CANT_TERMINATE_SELF ((NTSTATUS) 0xC00000DBL) -#endif - -#ifndef STATUS_INVALID_SERVER_STATE -# define STATUS_INVALID_SERVER_STATE ((NTSTATUS) 0xC00000DCL) -#endif - -#ifndef STATUS_INVALID_DOMAIN_STATE -# define STATUS_INVALID_DOMAIN_STATE ((NTSTATUS) 0xC00000DDL) -#endif - -#ifndef STATUS_INVALID_DOMAIN_ROLE -# define STATUS_INVALID_DOMAIN_ROLE ((NTSTATUS) 0xC00000DEL) -#endif - -#ifndef STATUS_NO_SUCH_DOMAIN -# define STATUS_NO_SUCH_DOMAIN ((NTSTATUS) 0xC00000DFL) -#endif - -#ifndef STATUS_DOMAIN_EXISTS -# define STATUS_DOMAIN_EXISTS ((NTSTATUS) 0xC00000E0L) -#endif - -#ifndef STATUS_DOMAIN_LIMIT_EXCEEDED -# define STATUS_DOMAIN_LIMIT_EXCEEDED ((NTSTATUS) 0xC00000E1L) -#endif - -#ifndef STATUS_OPLOCK_NOT_GRANTED -# define STATUS_OPLOCK_NOT_GRANTED ((NTSTATUS) 0xC00000E2L) -#endif - -#ifndef STATUS_INVALID_OPLOCK_PROTOCOL -# define STATUS_INVALID_OPLOCK_PROTOCOL ((NTSTATUS) 0xC00000E3L) -#endif - -#ifndef STATUS_INTERNAL_DB_CORRUPTION -# define STATUS_INTERNAL_DB_CORRUPTION ((NTSTATUS) 0xC00000E4L) -#endif - -#ifndef STATUS_INTERNAL_ERROR -# define STATUS_INTERNAL_ERROR ((NTSTATUS) 0xC00000E5L) -#endif - -#ifndef STATUS_GENERIC_NOT_MAPPED -# define STATUS_GENERIC_NOT_MAPPED ((NTSTATUS) 0xC00000E6L) -#endif - -#ifndef STATUS_BAD_DESCRIPTOR_FORMAT -# define STATUS_BAD_DESCRIPTOR_FORMAT ((NTSTATUS) 0xC00000E7L) -#endif - -#ifndef STATUS_INVALID_USER_BUFFER -# define STATUS_INVALID_USER_BUFFER ((NTSTATUS) 0xC00000E8L) -#endif - -#ifndef STATUS_UNEXPECTED_IO_ERROR -# define STATUS_UNEXPECTED_IO_ERROR ((NTSTATUS) 0xC00000E9L) -#endif - -#ifndef STATUS_UNEXPECTED_MM_CREATE_ERR -# define STATUS_UNEXPECTED_MM_CREATE_ERR ((NTSTATUS) 0xC00000EAL) -#endif - -#ifndef STATUS_UNEXPECTED_MM_MAP_ERROR -# define STATUS_UNEXPECTED_MM_MAP_ERROR ((NTSTATUS) 0xC00000EBL) -#endif - -#ifndef STATUS_UNEXPECTED_MM_EXTEND_ERR -# define STATUS_UNEXPECTED_MM_EXTEND_ERR ((NTSTATUS) 0xC00000ECL) -#endif - -#ifndef STATUS_NOT_LOGON_PROCESS -# define STATUS_NOT_LOGON_PROCESS ((NTSTATUS) 0xC00000EDL) -#endif - -#ifndef STATUS_LOGON_SESSION_EXISTS -# define STATUS_LOGON_SESSION_EXISTS ((NTSTATUS) 0xC00000EEL) -#endif - -#ifndef STATUS_INVALID_PARAMETER_1 -# define STATUS_INVALID_PARAMETER_1 ((NTSTATUS) 0xC00000EFL) -#endif - -#ifndef STATUS_INVALID_PARAMETER_2 -# define STATUS_INVALID_PARAMETER_2 ((NTSTATUS) 0xC00000F0L) -#endif - -#ifndef STATUS_INVALID_PARAMETER_3 -# define STATUS_INVALID_PARAMETER_3 ((NTSTATUS) 0xC00000F1L) -#endif - -#ifndef STATUS_INVALID_PARAMETER_4 -# define STATUS_INVALID_PARAMETER_4 ((NTSTATUS) 0xC00000F2L) -#endif - -#ifndef STATUS_INVALID_PARAMETER_5 -# define STATUS_INVALID_PARAMETER_5 ((NTSTATUS) 0xC00000F3L) -#endif - -#ifndef STATUS_INVALID_PARAMETER_6 -# define STATUS_INVALID_PARAMETER_6 ((NTSTATUS) 0xC00000F4L) -#endif - -#ifndef STATUS_INVALID_PARAMETER_7 -# define STATUS_INVALID_PARAMETER_7 ((NTSTATUS) 0xC00000F5L) -#endif - -#ifndef STATUS_INVALID_PARAMETER_8 -# define STATUS_INVALID_PARAMETER_8 ((NTSTATUS) 0xC00000F6L) -#endif - -#ifndef STATUS_INVALID_PARAMETER_9 -# define STATUS_INVALID_PARAMETER_9 ((NTSTATUS) 0xC00000F7L) -#endif - -#ifndef STATUS_INVALID_PARAMETER_10 -# define STATUS_INVALID_PARAMETER_10 ((NTSTATUS) 0xC00000F8L) -#endif - -#ifndef STATUS_INVALID_PARAMETER_11 -# define STATUS_INVALID_PARAMETER_11 ((NTSTATUS) 0xC00000F9L) -#endif - -#ifndef STATUS_INVALID_PARAMETER_12 -# define STATUS_INVALID_PARAMETER_12 ((NTSTATUS) 0xC00000FAL) -#endif - -#ifndef STATUS_REDIRECTOR_NOT_STARTED -# define STATUS_REDIRECTOR_NOT_STARTED ((NTSTATUS) 0xC00000FBL) -#endif - -#ifndef STATUS_REDIRECTOR_STARTED -# define STATUS_REDIRECTOR_STARTED ((NTSTATUS) 0xC00000FCL) -#endif - -#ifndef STATUS_STACK_OVERFLOW -# define STATUS_STACK_OVERFLOW ((NTSTATUS) 0xC00000FDL) -#endif - -#ifndef STATUS_NO_SUCH_PACKAGE -# define STATUS_NO_SUCH_PACKAGE ((NTSTATUS) 0xC00000FEL) -#endif - -#ifndef STATUS_BAD_FUNCTION_TABLE -# define STATUS_BAD_FUNCTION_TABLE ((NTSTATUS) 0xC00000FFL) -#endif - -#ifndef STATUS_VARIABLE_NOT_FOUND -# define STATUS_VARIABLE_NOT_FOUND ((NTSTATUS) 0xC0000100L) -#endif - -#ifndef STATUS_DIRECTORY_NOT_EMPTY -# define STATUS_DIRECTORY_NOT_EMPTY ((NTSTATUS) 0xC0000101L) -#endif - -#ifndef STATUS_FILE_CORRUPT_ERROR -# define STATUS_FILE_CORRUPT_ERROR ((NTSTATUS) 0xC0000102L) -#endif - -#ifndef STATUS_NOT_A_DIRECTORY -# define STATUS_NOT_A_DIRECTORY ((NTSTATUS) 0xC0000103L) -#endif - -#ifndef STATUS_BAD_LOGON_SESSION_STATE -# define STATUS_BAD_LOGON_SESSION_STATE ((NTSTATUS) 0xC0000104L) -#endif - -#ifndef STATUS_LOGON_SESSION_COLLISION -# define STATUS_LOGON_SESSION_COLLISION ((NTSTATUS) 0xC0000105L) -#endif - -#ifndef STATUS_NAME_TOO_LONG -# define STATUS_NAME_TOO_LONG ((NTSTATUS) 0xC0000106L) -#endif - -#ifndef STATUS_FILES_OPEN -# define STATUS_FILES_OPEN ((NTSTATUS) 0xC0000107L) -#endif - -#ifndef STATUS_CONNECTION_IN_USE -# define STATUS_CONNECTION_IN_USE ((NTSTATUS) 0xC0000108L) -#endif - -#ifndef STATUS_MESSAGE_NOT_FOUND -# define STATUS_MESSAGE_NOT_FOUND ((NTSTATUS) 0xC0000109L) -#endif - -#ifndef STATUS_PROCESS_IS_TERMINATING -# define STATUS_PROCESS_IS_TERMINATING ((NTSTATUS) 0xC000010AL) -#endif - -#ifndef STATUS_INVALID_LOGON_TYPE -# define STATUS_INVALID_LOGON_TYPE ((NTSTATUS) 0xC000010BL) -#endif - -#ifndef STATUS_NO_GUID_TRANSLATION -# define STATUS_NO_GUID_TRANSLATION ((NTSTATUS) 0xC000010CL) -#endif - -#ifndef STATUS_CANNOT_IMPERSONATE -# define STATUS_CANNOT_IMPERSONATE ((NTSTATUS) 0xC000010DL) -#endif - -#ifndef STATUS_IMAGE_ALREADY_LOADED -# define STATUS_IMAGE_ALREADY_LOADED ((NTSTATUS) 0xC000010EL) -#endif - -#ifndef STATUS_ABIOS_NOT_PRESENT -# define STATUS_ABIOS_NOT_PRESENT ((NTSTATUS) 0xC000010FL) -#endif - -#ifndef STATUS_ABIOS_LID_NOT_EXIST -# define STATUS_ABIOS_LID_NOT_EXIST ((NTSTATUS) 0xC0000110L) -#endif - -#ifndef STATUS_ABIOS_LID_ALREADY_OWNED -# define STATUS_ABIOS_LID_ALREADY_OWNED ((NTSTATUS) 0xC0000111L) -#endif - -#ifndef STATUS_ABIOS_NOT_LID_OWNER -# define STATUS_ABIOS_NOT_LID_OWNER ((NTSTATUS) 0xC0000112L) -#endif - -#ifndef STATUS_ABIOS_INVALID_COMMAND -# define STATUS_ABIOS_INVALID_COMMAND ((NTSTATUS) 0xC0000113L) -#endif - -#ifndef STATUS_ABIOS_INVALID_LID -# define STATUS_ABIOS_INVALID_LID ((NTSTATUS) 0xC0000114L) -#endif - -#ifndef STATUS_ABIOS_SELECTOR_NOT_AVAILABLE -# define STATUS_ABIOS_SELECTOR_NOT_AVAILABLE ((NTSTATUS) 0xC0000115L) -#endif - -#ifndef STATUS_ABIOS_INVALID_SELECTOR -# define STATUS_ABIOS_INVALID_SELECTOR ((NTSTATUS) 0xC0000116L) -#endif - -#ifndef STATUS_NO_LDT -# define STATUS_NO_LDT ((NTSTATUS) 0xC0000117L) -#endif - -#ifndef STATUS_INVALID_LDT_SIZE -# define STATUS_INVALID_LDT_SIZE ((NTSTATUS) 0xC0000118L) -#endif - -#ifndef STATUS_INVALID_LDT_OFFSET -# define STATUS_INVALID_LDT_OFFSET ((NTSTATUS) 0xC0000119L) -#endif - -#ifndef STATUS_INVALID_LDT_DESCRIPTOR -# define STATUS_INVALID_LDT_DESCRIPTOR ((NTSTATUS) 0xC000011AL) -#endif - -#ifndef STATUS_INVALID_IMAGE_NE_FORMAT -# define STATUS_INVALID_IMAGE_NE_FORMAT ((NTSTATUS) 0xC000011BL) -#endif - -#ifndef STATUS_RXACT_INVALID_STATE -# define STATUS_RXACT_INVALID_STATE ((NTSTATUS) 0xC000011CL) -#endif - -#ifndef STATUS_RXACT_COMMIT_FAILURE -# define STATUS_RXACT_COMMIT_FAILURE ((NTSTATUS) 0xC000011DL) -#endif - -#ifndef STATUS_MAPPED_FILE_SIZE_ZERO -# define STATUS_MAPPED_FILE_SIZE_ZERO ((NTSTATUS) 0xC000011EL) -#endif - -#ifndef STATUS_TOO_MANY_OPENED_FILES -# define STATUS_TOO_MANY_OPENED_FILES ((NTSTATUS) 0xC000011FL) -#endif - -#ifndef STATUS_CANCELLED -# define STATUS_CANCELLED ((NTSTATUS) 0xC0000120L) -#endif - -#ifndef STATUS_CANNOT_DELETE -# define STATUS_CANNOT_DELETE ((NTSTATUS) 0xC0000121L) -#endif - -#ifndef STATUS_INVALID_COMPUTER_NAME -# define STATUS_INVALID_COMPUTER_NAME ((NTSTATUS) 0xC0000122L) -#endif - -#ifndef STATUS_FILE_DELETED -# define STATUS_FILE_DELETED ((NTSTATUS) 0xC0000123L) -#endif - -#ifndef STATUS_SPECIAL_ACCOUNT -# define STATUS_SPECIAL_ACCOUNT ((NTSTATUS) 0xC0000124L) -#endif - -#ifndef STATUS_SPECIAL_GROUP -# define STATUS_SPECIAL_GROUP ((NTSTATUS) 0xC0000125L) -#endif - -#ifndef STATUS_SPECIAL_USER -# define STATUS_SPECIAL_USER ((NTSTATUS) 0xC0000126L) -#endif - -#ifndef STATUS_MEMBERS_PRIMARY_GROUP -# define STATUS_MEMBERS_PRIMARY_GROUP ((NTSTATUS) 0xC0000127L) -#endif - -#ifndef STATUS_FILE_CLOSED -# define STATUS_FILE_CLOSED ((NTSTATUS) 0xC0000128L) -#endif - -#ifndef STATUS_TOO_MANY_THREADS -# define STATUS_TOO_MANY_THREADS ((NTSTATUS) 0xC0000129L) -#endif - -#ifndef STATUS_THREAD_NOT_IN_PROCESS -# define STATUS_THREAD_NOT_IN_PROCESS ((NTSTATUS) 0xC000012AL) -#endif - -#ifndef STATUS_TOKEN_ALREADY_IN_USE -# define STATUS_TOKEN_ALREADY_IN_USE ((NTSTATUS) 0xC000012BL) -#endif - -#ifndef STATUS_PAGEFILE_QUOTA_EXCEEDED -# define STATUS_PAGEFILE_QUOTA_EXCEEDED ((NTSTATUS) 0xC000012CL) -#endif - -#ifndef STATUS_COMMITMENT_LIMIT -# define STATUS_COMMITMENT_LIMIT ((NTSTATUS) 0xC000012DL) -#endif - -#ifndef STATUS_INVALID_IMAGE_LE_FORMAT -# define STATUS_INVALID_IMAGE_LE_FORMAT ((NTSTATUS) 0xC000012EL) -#endif - -#ifndef STATUS_INVALID_IMAGE_NOT_MZ -# define STATUS_INVALID_IMAGE_NOT_MZ ((NTSTATUS) 0xC000012FL) -#endif - -#ifndef STATUS_INVALID_IMAGE_PROTECT -# define STATUS_INVALID_IMAGE_PROTECT ((NTSTATUS) 0xC0000130L) -#endif - -#ifndef STATUS_INVALID_IMAGE_WIN_16 -# define STATUS_INVALID_IMAGE_WIN_16 ((NTSTATUS) 0xC0000131L) -#endif - -#ifndef STATUS_LOGON_SERVER_CONFLICT -# define STATUS_LOGON_SERVER_CONFLICT ((NTSTATUS) 0xC0000132L) -#endif - -#ifndef STATUS_TIME_DIFFERENCE_AT_DC -# define STATUS_TIME_DIFFERENCE_AT_DC ((NTSTATUS) 0xC0000133L) -#endif - -#ifndef STATUS_SYNCHRONIZATION_REQUIRED -# define STATUS_SYNCHRONIZATION_REQUIRED ((NTSTATUS) 0xC0000134L) -#endif - -#ifndef STATUS_DLL_NOT_FOUND -# define STATUS_DLL_NOT_FOUND ((NTSTATUS) 0xC0000135L) -#endif - -#ifndef STATUS_OPEN_FAILED -# define STATUS_OPEN_FAILED ((NTSTATUS) 0xC0000136L) -#endif - -#ifndef STATUS_IO_PRIVILEGE_FAILED -# define STATUS_IO_PRIVILEGE_FAILED ((NTSTATUS) 0xC0000137L) -#endif - -#ifndef STATUS_ORDINAL_NOT_FOUND -# define STATUS_ORDINAL_NOT_FOUND ((NTSTATUS) 0xC0000138L) -#endif - -#ifndef STATUS_ENTRYPOINT_NOT_FOUND -# define STATUS_ENTRYPOINT_NOT_FOUND ((NTSTATUS) 0xC0000139L) -#endif - -#ifndef STATUS_CONTROL_C_EXIT -# define STATUS_CONTROL_C_EXIT ((NTSTATUS) 0xC000013AL) -#endif - -#ifndef STATUS_LOCAL_DISCONNECT -# define STATUS_LOCAL_DISCONNECT ((NTSTATUS) 0xC000013BL) -#endif - -#ifndef STATUS_REMOTE_DISCONNECT -# define STATUS_REMOTE_DISCONNECT ((NTSTATUS) 0xC000013CL) -#endif - -#ifndef STATUS_REMOTE_RESOURCES -# define STATUS_REMOTE_RESOURCES ((NTSTATUS) 0xC000013DL) -#endif - -#ifndef STATUS_LINK_FAILED -# define STATUS_LINK_FAILED ((NTSTATUS) 0xC000013EL) -#endif - -#ifndef STATUS_LINK_TIMEOUT -# define STATUS_LINK_TIMEOUT ((NTSTATUS) 0xC000013FL) -#endif - -#ifndef STATUS_INVALID_CONNECTION -# define STATUS_INVALID_CONNECTION ((NTSTATUS) 0xC0000140L) -#endif - -#ifndef STATUS_INVALID_ADDRESS -# define STATUS_INVALID_ADDRESS ((NTSTATUS) 0xC0000141L) -#endif - -#ifndef STATUS_DLL_INIT_FAILED -# define STATUS_DLL_INIT_FAILED ((NTSTATUS) 0xC0000142L) -#endif - -#ifndef STATUS_MISSING_SYSTEMFILE -# define STATUS_MISSING_SYSTEMFILE ((NTSTATUS) 0xC0000143L) -#endif - -#ifndef STATUS_UNHANDLED_EXCEPTION -# define STATUS_UNHANDLED_EXCEPTION ((NTSTATUS) 0xC0000144L) -#endif - -#ifndef STATUS_APP_INIT_FAILURE -# define STATUS_APP_INIT_FAILURE ((NTSTATUS) 0xC0000145L) -#endif - -#ifndef STATUS_PAGEFILE_CREATE_FAILED -# define STATUS_PAGEFILE_CREATE_FAILED ((NTSTATUS) 0xC0000146L) -#endif - -#ifndef STATUS_NO_PAGEFILE -# define STATUS_NO_PAGEFILE ((NTSTATUS) 0xC0000147L) -#endif - -#ifndef STATUS_INVALID_LEVEL -# define STATUS_INVALID_LEVEL ((NTSTATUS) 0xC0000148L) -#endif - -#ifndef STATUS_WRONG_PASSWORD_CORE -# define STATUS_WRONG_PASSWORD_CORE ((NTSTATUS) 0xC0000149L) -#endif - -#ifndef STATUS_ILLEGAL_FLOAT_CONTEXT -# define STATUS_ILLEGAL_FLOAT_CONTEXT ((NTSTATUS) 0xC000014AL) -#endif - -#ifndef STATUS_PIPE_BROKEN -# define STATUS_PIPE_BROKEN ((NTSTATUS) 0xC000014BL) -#endif - -#ifndef STATUS_REGISTRY_CORRUPT -# define STATUS_REGISTRY_CORRUPT ((NTSTATUS) 0xC000014CL) -#endif - -#ifndef STATUS_REGISTRY_IO_FAILED -# define STATUS_REGISTRY_IO_FAILED ((NTSTATUS) 0xC000014DL) -#endif - -#ifndef STATUS_NO_EVENT_PAIR -# define STATUS_NO_EVENT_PAIR ((NTSTATUS) 0xC000014EL) -#endif - -#ifndef STATUS_UNRECOGNIZED_VOLUME -# define STATUS_UNRECOGNIZED_VOLUME ((NTSTATUS) 0xC000014FL) -#endif - -#ifndef STATUS_SERIAL_NO_DEVICE_INITED -# define STATUS_SERIAL_NO_DEVICE_INITED ((NTSTATUS) 0xC0000150L) -#endif - -#ifndef STATUS_NO_SUCH_ALIAS -# define STATUS_NO_SUCH_ALIAS ((NTSTATUS) 0xC0000151L) -#endif - -#ifndef STATUS_MEMBER_NOT_IN_ALIAS -# define STATUS_MEMBER_NOT_IN_ALIAS ((NTSTATUS) 0xC0000152L) -#endif - -#ifndef STATUS_MEMBER_IN_ALIAS -# define STATUS_MEMBER_IN_ALIAS ((NTSTATUS) 0xC0000153L) -#endif - -#ifndef STATUS_ALIAS_EXISTS -# define STATUS_ALIAS_EXISTS ((NTSTATUS) 0xC0000154L) -#endif - -#ifndef STATUS_LOGON_NOT_GRANTED -# define STATUS_LOGON_NOT_GRANTED ((NTSTATUS) 0xC0000155L) -#endif - -#ifndef STATUS_TOO_MANY_SECRETS -# define STATUS_TOO_MANY_SECRETS ((NTSTATUS) 0xC0000156L) -#endif - -#ifndef STATUS_SECRET_TOO_LONG -# define STATUS_SECRET_TOO_LONG ((NTSTATUS) 0xC0000157L) -#endif - -#ifndef STATUS_INTERNAL_DB_ERROR -# define STATUS_INTERNAL_DB_ERROR ((NTSTATUS) 0xC0000158L) -#endif - -#ifndef STATUS_FULLSCREEN_MODE -# define STATUS_FULLSCREEN_MODE ((NTSTATUS) 0xC0000159L) -#endif - -#ifndef STATUS_TOO_MANY_CONTEXT_IDS -# define STATUS_TOO_MANY_CONTEXT_IDS ((NTSTATUS) 0xC000015AL) -#endif - -#ifndef STATUS_LOGON_TYPE_NOT_GRANTED -# define STATUS_LOGON_TYPE_NOT_GRANTED ((NTSTATUS) 0xC000015BL) -#endif - -#ifndef STATUS_NOT_REGISTRY_FILE -# define STATUS_NOT_REGISTRY_FILE ((NTSTATUS) 0xC000015CL) -#endif - -#ifndef STATUS_NT_CROSS_ENCRYPTION_REQUIRED -# define STATUS_NT_CROSS_ENCRYPTION_REQUIRED ((NTSTATUS) 0xC000015DL) -#endif - -#ifndef STATUS_DOMAIN_CTRLR_CONFIG_ERROR -# define STATUS_DOMAIN_CTRLR_CONFIG_ERROR ((NTSTATUS) 0xC000015EL) -#endif - -#ifndef STATUS_FT_MISSING_MEMBER -# define STATUS_FT_MISSING_MEMBER ((NTSTATUS) 0xC000015FL) -#endif - -#ifndef STATUS_ILL_FORMED_SERVICE_ENTRY -# define STATUS_ILL_FORMED_SERVICE_ENTRY ((NTSTATUS) 0xC0000160L) -#endif - -#ifndef STATUS_ILLEGAL_CHARACTER -# define STATUS_ILLEGAL_CHARACTER ((NTSTATUS) 0xC0000161L) -#endif - -#ifndef STATUS_UNMAPPABLE_CHARACTER -# define STATUS_UNMAPPABLE_CHARACTER ((NTSTATUS) 0xC0000162L) -#endif - -#ifndef STATUS_UNDEFINED_CHARACTER -# define STATUS_UNDEFINED_CHARACTER ((NTSTATUS) 0xC0000163L) -#endif - -#ifndef STATUS_FLOPPY_VOLUME -# define STATUS_FLOPPY_VOLUME ((NTSTATUS) 0xC0000164L) -#endif - -#ifndef STATUS_FLOPPY_ID_MARK_NOT_FOUND -# define STATUS_FLOPPY_ID_MARK_NOT_FOUND ((NTSTATUS) 0xC0000165L) -#endif - -#ifndef STATUS_FLOPPY_WRONG_CYLINDER -# define STATUS_FLOPPY_WRONG_CYLINDER ((NTSTATUS) 0xC0000166L) -#endif - -#ifndef STATUS_FLOPPY_UNKNOWN_ERROR -# define STATUS_FLOPPY_UNKNOWN_ERROR ((NTSTATUS) 0xC0000167L) -#endif - -#ifndef STATUS_FLOPPY_BAD_REGISTERS -# define STATUS_FLOPPY_BAD_REGISTERS ((NTSTATUS) 0xC0000168L) -#endif - -#ifndef STATUS_DISK_RECALIBRATE_FAILED -# define STATUS_DISK_RECALIBRATE_FAILED ((NTSTATUS) 0xC0000169L) -#endif - -#ifndef STATUS_DISK_OPERATION_FAILED -# define STATUS_DISK_OPERATION_FAILED ((NTSTATUS) 0xC000016AL) -#endif - -#ifndef STATUS_DISK_RESET_FAILED -# define STATUS_DISK_RESET_FAILED ((NTSTATUS) 0xC000016BL) -#endif - -#ifndef STATUS_SHARED_IRQ_BUSY -# define STATUS_SHARED_IRQ_BUSY ((NTSTATUS) 0xC000016CL) -#endif - -#ifndef STATUS_FT_ORPHANING -# define STATUS_FT_ORPHANING ((NTSTATUS) 0xC000016DL) -#endif - -#ifndef STATUS_BIOS_FAILED_TO_CONNECT_INTERRUPT -# define STATUS_BIOS_FAILED_TO_CONNECT_INTERRUPT ((NTSTATUS) 0xC000016EL) -#endif - -#ifndef STATUS_PARTITION_FAILURE -# define STATUS_PARTITION_FAILURE ((NTSTATUS) 0xC0000172L) -#endif - -#ifndef STATUS_INVALID_BLOCK_LENGTH -# define STATUS_INVALID_BLOCK_LENGTH ((NTSTATUS) 0xC0000173L) -#endif - -#ifndef STATUS_DEVICE_NOT_PARTITIONED -# define STATUS_DEVICE_NOT_PARTITIONED ((NTSTATUS) 0xC0000174L) -#endif - -#ifndef STATUS_UNABLE_TO_LOCK_MEDIA -# define STATUS_UNABLE_TO_LOCK_MEDIA ((NTSTATUS) 0xC0000175L) -#endif - -#ifndef STATUS_UNABLE_TO_UNLOAD_MEDIA -# define STATUS_UNABLE_TO_UNLOAD_MEDIA ((NTSTATUS) 0xC0000176L) -#endif - -#ifndef STATUS_EOM_OVERFLOW -# define STATUS_EOM_OVERFLOW ((NTSTATUS) 0xC0000177L) -#endif - -#ifndef STATUS_NO_MEDIA -# define STATUS_NO_MEDIA ((NTSTATUS) 0xC0000178L) -#endif - -#ifndef STATUS_NO_SUCH_MEMBER -# define STATUS_NO_SUCH_MEMBER ((NTSTATUS) 0xC000017AL) -#endif - -#ifndef STATUS_INVALID_MEMBER -# define STATUS_INVALID_MEMBER ((NTSTATUS) 0xC000017BL) -#endif - -#ifndef STATUS_KEY_DELETED -# define STATUS_KEY_DELETED ((NTSTATUS) 0xC000017CL) -#endif - -#ifndef STATUS_NO_LOG_SPACE -# define STATUS_NO_LOG_SPACE ((NTSTATUS) 0xC000017DL) -#endif - -#ifndef STATUS_TOO_MANY_SIDS -# define STATUS_TOO_MANY_SIDS ((NTSTATUS) 0xC000017EL) -#endif - -#ifndef STATUS_LM_CROSS_ENCRYPTION_REQUIRED -# define STATUS_LM_CROSS_ENCRYPTION_REQUIRED ((NTSTATUS) 0xC000017FL) -#endif - -#ifndef STATUS_KEY_HAS_CHILDREN -# define STATUS_KEY_HAS_CHILDREN ((NTSTATUS) 0xC0000180L) -#endif - -#ifndef STATUS_CHILD_MUST_BE_VOLATILE -# define STATUS_CHILD_MUST_BE_VOLATILE ((NTSTATUS) 0xC0000181L) -#endif - -#ifndef STATUS_DEVICE_CONFIGURATION_ERROR -# define STATUS_DEVICE_CONFIGURATION_ERROR ((NTSTATUS) 0xC0000182L) -#endif - -#ifndef STATUS_DRIVER_INTERNAL_ERROR -# define STATUS_DRIVER_INTERNAL_ERROR ((NTSTATUS) 0xC0000183L) -#endif - -#ifndef STATUS_INVALID_DEVICE_STATE -# define STATUS_INVALID_DEVICE_STATE ((NTSTATUS) 0xC0000184L) -#endif - -#ifndef STATUS_IO_DEVICE_ERROR -# define STATUS_IO_DEVICE_ERROR ((NTSTATUS) 0xC0000185L) -#endif - -#ifndef STATUS_DEVICE_PROTOCOL_ERROR -# define STATUS_DEVICE_PROTOCOL_ERROR ((NTSTATUS) 0xC0000186L) -#endif - -#ifndef STATUS_BACKUP_CONTROLLER -# define STATUS_BACKUP_CONTROLLER ((NTSTATUS) 0xC0000187L) -#endif - -#ifndef STATUS_LOG_FILE_FULL -# define STATUS_LOG_FILE_FULL ((NTSTATUS) 0xC0000188L) -#endif - -#ifndef STATUS_TOO_LATE -# define STATUS_TOO_LATE ((NTSTATUS) 0xC0000189L) -#endif - -#ifndef STATUS_NO_TRUST_LSA_SECRET -# define STATUS_NO_TRUST_LSA_SECRET ((NTSTATUS) 0xC000018AL) -#endif - -#ifndef STATUS_NO_TRUST_SAM_ACCOUNT -# define STATUS_NO_TRUST_SAM_ACCOUNT ((NTSTATUS) 0xC000018BL) -#endif - -#ifndef STATUS_TRUSTED_DOMAIN_FAILURE -# define STATUS_TRUSTED_DOMAIN_FAILURE ((NTSTATUS) 0xC000018CL) -#endif - -#ifndef STATUS_TRUSTED_RELATIONSHIP_FAILURE -# define STATUS_TRUSTED_RELATIONSHIP_FAILURE ((NTSTATUS) 0xC000018DL) -#endif - -#ifndef STATUS_EVENTLOG_FILE_CORRUPT -# define STATUS_EVENTLOG_FILE_CORRUPT ((NTSTATUS) 0xC000018EL) -#endif - -#ifndef STATUS_EVENTLOG_CANT_START -# define STATUS_EVENTLOG_CANT_START ((NTSTATUS) 0xC000018FL) -#endif - -#ifndef STATUS_TRUST_FAILURE -# define STATUS_TRUST_FAILURE ((NTSTATUS) 0xC0000190L) -#endif - -#ifndef STATUS_MUTANT_LIMIT_EXCEEDED -# define STATUS_MUTANT_LIMIT_EXCEEDED ((NTSTATUS) 0xC0000191L) -#endif - -#ifndef STATUS_NETLOGON_NOT_STARTED -# define STATUS_NETLOGON_NOT_STARTED ((NTSTATUS) 0xC0000192L) -#endif - -#ifndef STATUS_ACCOUNT_EXPIRED -# define STATUS_ACCOUNT_EXPIRED ((NTSTATUS) 0xC0000193L) -#endif - -#ifndef STATUS_POSSIBLE_DEADLOCK -# define STATUS_POSSIBLE_DEADLOCK ((NTSTATUS) 0xC0000194L) -#endif - -#ifndef STATUS_NETWORK_CREDENTIAL_CONFLICT -# define STATUS_NETWORK_CREDENTIAL_CONFLICT ((NTSTATUS) 0xC0000195L) -#endif - -#ifndef STATUS_REMOTE_SESSION_LIMIT -# define STATUS_REMOTE_SESSION_LIMIT ((NTSTATUS) 0xC0000196L) -#endif - -#ifndef STATUS_EVENTLOG_FILE_CHANGED -# define STATUS_EVENTLOG_FILE_CHANGED ((NTSTATUS) 0xC0000197L) -#endif - -#ifndef STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT -# define STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT ((NTSTATUS) 0xC0000198L) -#endif - -#ifndef STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT -# define STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT ((NTSTATUS) 0xC0000199L) -#endif - -#ifndef STATUS_NOLOGON_SERVER_TRUST_ACCOUNT -# define STATUS_NOLOGON_SERVER_TRUST_ACCOUNT ((NTSTATUS) 0xC000019AL) -#endif - -#ifndef STATUS_DOMAIN_TRUST_INCONSISTENT -# define STATUS_DOMAIN_TRUST_INCONSISTENT ((NTSTATUS) 0xC000019BL) -#endif - -#ifndef STATUS_FS_DRIVER_REQUIRED -# define STATUS_FS_DRIVER_REQUIRED ((NTSTATUS) 0xC000019CL) -#endif - -#ifndef STATUS_IMAGE_ALREADY_LOADED_AS_DLL -# define STATUS_IMAGE_ALREADY_LOADED_AS_DLL ((NTSTATUS) 0xC000019DL) -#endif - -#ifndef STATUS_INCOMPATIBLE_WITH_GLOBAL_SHORT_NAME_REGISTRY_SETTING -# define STATUS_INCOMPATIBLE_WITH_GLOBAL_SHORT_NAME_REGISTRY_SETTING ((NTSTATUS) 0xC000019EL) -#endif - -#ifndef STATUS_SHORT_NAMES_NOT_ENABLED_ON_VOLUME -# define STATUS_SHORT_NAMES_NOT_ENABLED_ON_VOLUME ((NTSTATUS) 0xC000019FL) -#endif - -#ifndef STATUS_SECURITY_STREAM_IS_INCONSISTENT -# define STATUS_SECURITY_STREAM_IS_INCONSISTENT ((NTSTATUS) 0xC00001A0L) -#endif - -#ifndef STATUS_INVALID_LOCK_RANGE -# define STATUS_INVALID_LOCK_RANGE ((NTSTATUS) 0xC00001A1L) -#endif - -#ifndef STATUS_INVALID_ACE_CONDITION -# define STATUS_INVALID_ACE_CONDITION ((NTSTATUS) 0xC00001A2L) -#endif - -#ifndef STATUS_IMAGE_SUBSYSTEM_NOT_PRESENT -# define STATUS_IMAGE_SUBSYSTEM_NOT_PRESENT ((NTSTATUS) 0xC00001A3L) -#endif - -#ifndef STATUS_NOTIFICATION_GUID_ALREADY_DEFINED -# define STATUS_NOTIFICATION_GUID_ALREADY_DEFINED ((NTSTATUS) 0xC00001A4L) -#endif - -#ifndef STATUS_NETWORK_OPEN_RESTRICTION -# define STATUS_NETWORK_OPEN_RESTRICTION ((NTSTATUS) 0xC0000201L) -#endif - -#ifndef STATUS_NO_USER_SESSION_KEY -# define STATUS_NO_USER_SESSION_KEY ((NTSTATUS) 0xC0000202L) -#endif - -#ifndef STATUS_USER_SESSION_DELETED -# define STATUS_USER_SESSION_DELETED ((NTSTATUS) 0xC0000203L) -#endif - -#ifndef STATUS_RESOURCE_LANG_NOT_FOUND -# define STATUS_RESOURCE_LANG_NOT_FOUND ((NTSTATUS) 0xC0000204L) -#endif - -#ifndef STATUS_INSUFF_SERVER_RESOURCES -# define STATUS_INSUFF_SERVER_RESOURCES ((NTSTATUS) 0xC0000205L) -#endif - -#ifndef STATUS_INVALID_BUFFER_SIZE -# define STATUS_INVALID_BUFFER_SIZE ((NTSTATUS) 0xC0000206L) -#endif - -#ifndef STATUS_INVALID_ADDRESS_COMPONENT -# define STATUS_INVALID_ADDRESS_COMPONENT ((NTSTATUS) 0xC0000207L) -#endif - -#ifndef STATUS_INVALID_ADDRESS_WILDCARD -# define STATUS_INVALID_ADDRESS_WILDCARD ((NTSTATUS) 0xC0000208L) -#endif - -#ifndef STATUS_TOO_MANY_ADDRESSES -# define STATUS_TOO_MANY_ADDRESSES ((NTSTATUS) 0xC0000209L) -#endif - -#ifndef STATUS_ADDRESS_ALREADY_EXISTS -# define STATUS_ADDRESS_ALREADY_EXISTS ((NTSTATUS) 0xC000020AL) -#endif - -#ifndef STATUS_ADDRESS_CLOSED -# define STATUS_ADDRESS_CLOSED ((NTSTATUS) 0xC000020BL) -#endif - -#ifndef STATUS_CONNECTION_DISCONNECTED -# define STATUS_CONNECTION_DISCONNECTED ((NTSTATUS) 0xC000020CL) -#endif - -#ifndef STATUS_CONNECTION_RESET -# define STATUS_CONNECTION_RESET ((NTSTATUS) 0xC000020DL) -#endif - -#ifndef STATUS_TOO_MANY_NODES -# define STATUS_TOO_MANY_NODES ((NTSTATUS) 0xC000020EL) -#endif - -#ifndef STATUS_TRANSACTION_ABORTED -# define STATUS_TRANSACTION_ABORTED ((NTSTATUS) 0xC000020FL) -#endif - -#ifndef STATUS_TRANSACTION_TIMED_OUT -# define STATUS_TRANSACTION_TIMED_OUT ((NTSTATUS) 0xC0000210L) -#endif - -#ifndef STATUS_TRANSACTION_NO_RELEASE -# define STATUS_TRANSACTION_NO_RELEASE ((NTSTATUS) 0xC0000211L) -#endif - -#ifndef STATUS_TRANSACTION_NO_MATCH -# define STATUS_TRANSACTION_NO_MATCH ((NTSTATUS) 0xC0000212L) -#endif - -#ifndef STATUS_TRANSACTION_RESPONDED -# define STATUS_TRANSACTION_RESPONDED ((NTSTATUS) 0xC0000213L) -#endif - -#ifndef STATUS_TRANSACTION_INVALID_ID -# define STATUS_TRANSACTION_INVALID_ID ((NTSTATUS) 0xC0000214L) -#endif - -#ifndef STATUS_TRANSACTION_INVALID_TYPE -# define STATUS_TRANSACTION_INVALID_TYPE ((NTSTATUS) 0xC0000215L) -#endif - -#ifndef STATUS_NOT_SERVER_SESSION -# define STATUS_NOT_SERVER_SESSION ((NTSTATUS) 0xC0000216L) -#endif - -#ifndef STATUS_NOT_CLIENT_SESSION -# define STATUS_NOT_CLIENT_SESSION ((NTSTATUS) 0xC0000217L) -#endif - -#ifndef STATUS_CANNOT_LOAD_REGISTRY_FILE -# define STATUS_CANNOT_LOAD_REGISTRY_FILE ((NTSTATUS) 0xC0000218L) -#endif - -#ifndef STATUS_DEBUG_ATTACH_FAILED -# define STATUS_DEBUG_ATTACH_FAILED ((NTSTATUS) 0xC0000219L) -#endif - -#ifndef STATUS_SYSTEM_PROCESS_TERMINATED -# define STATUS_SYSTEM_PROCESS_TERMINATED ((NTSTATUS) 0xC000021AL) -#endif - -#ifndef STATUS_DATA_NOT_ACCEPTED -# define STATUS_DATA_NOT_ACCEPTED ((NTSTATUS) 0xC000021BL) -#endif - -#ifndef STATUS_NO_BROWSER_SERVERS_FOUND -# define STATUS_NO_BROWSER_SERVERS_FOUND ((NTSTATUS) 0xC000021CL) -#endif - -#ifndef STATUS_VDM_HARD_ERROR -# define STATUS_VDM_HARD_ERROR ((NTSTATUS) 0xC000021DL) -#endif - -#ifndef STATUS_DRIVER_CANCEL_TIMEOUT -# define STATUS_DRIVER_CANCEL_TIMEOUT ((NTSTATUS) 0xC000021EL) -#endif - -#ifndef STATUS_REPLY_MESSAGE_MISMATCH -# define STATUS_REPLY_MESSAGE_MISMATCH ((NTSTATUS) 0xC000021FL) -#endif - -#ifndef STATUS_MAPPED_ALIGNMENT -# define STATUS_MAPPED_ALIGNMENT ((NTSTATUS) 0xC0000220L) -#endif - -#ifndef STATUS_IMAGE_CHECKSUM_MISMATCH -# define STATUS_IMAGE_CHECKSUM_MISMATCH ((NTSTATUS) 0xC0000221L) -#endif - -#ifndef STATUS_LOST_WRITEBEHIND_DATA -# define STATUS_LOST_WRITEBEHIND_DATA ((NTSTATUS) 0xC0000222L) -#endif - -#ifndef STATUS_CLIENT_SERVER_PARAMETERS_INVALID -# define STATUS_CLIENT_SERVER_PARAMETERS_INVALID ((NTSTATUS) 0xC0000223L) -#endif - -#ifndef STATUS_PASSWORD_MUST_CHANGE -# define STATUS_PASSWORD_MUST_CHANGE ((NTSTATUS) 0xC0000224L) -#endif - -#ifndef STATUS_NOT_FOUND -# define STATUS_NOT_FOUND ((NTSTATUS) 0xC0000225L) -#endif - -#ifndef STATUS_NOT_TINY_STREAM -# define STATUS_NOT_TINY_STREAM ((NTSTATUS) 0xC0000226L) -#endif - -#ifndef STATUS_RECOVERY_FAILURE -# define STATUS_RECOVERY_FAILURE ((NTSTATUS) 0xC0000227L) -#endif - -#ifndef STATUS_STACK_OVERFLOW_READ -# define STATUS_STACK_OVERFLOW_READ ((NTSTATUS) 0xC0000228L) -#endif - -#ifndef STATUS_FAIL_CHECK -# define STATUS_FAIL_CHECK ((NTSTATUS) 0xC0000229L) -#endif - -#ifndef STATUS_DUPLICATE_OBJECTID -# define STATUS_DUPLICATE_OBJECTID ((NTSTATUS) 0xC000022AL) -#endif - -#ifndef STATUS_OBJECTID_EXISTS -# define STATUS_OBJECTID_EXISTS ((NTSTATUS) 0xC000022BL) -#endif - -#ifndef STATUS_CONVERT_TO_LARGE -# define STATUS_CONVERT_TO_LARGE ((NTSTATUS) 0xC000022CL) -#endif - -#ifndef STATUS_RETRY -# define STATUS_RETRY ((NTSTATUS) 0xC000022DL) -#endif - -#ifndef STATUS_FOUND_OUT_OF_SCOPE -# define STATUS_FOUND_OUT_OF_SCOPE ((NTSTATUS) 0xC000022EL) -#endif - -#ifndef STATUS_ALLOCATE_BUCKET -# define STATUS_ALLOCATE_BUCKET ((NTSTATUS) 0xC000022FL) -#endif - -#ifndef STATUS_PROPSET_NOT_FOUND -# define STATUS_PROPSET_NOT_FOUND ((NTSTATUS) 0xC0000230L) -#endif - -#ifndef STATUS_MARSHALL_OVERFLOW -# define STATUS_MARSHALL_OVERFLOW ((NTSTATUS) 0xC0000231L) -#endif - -#ifndef STATUS_INVALID_VARIANT -# define STATUS_INVALID_VARIANT ((NTSTATUS) 0xC0000232L) -#endif - -#ifndef STATUS_DOMAIN_CONTROLLER_NOT_FOUND -# define STATUS_DOMAIN_CONTROLLER_NOT_FOUND ((NTSTATUS) 0xC0000233L) -#endif - -#ifndef STATUS_ACCOUNT_LOCKED_OUT -# define STATUS_ACCOUNT_LOCKED_OUT ((NTSTATUS) 0xC0000234L) -#endif - -#ifndef STATUS_HANDLE_NOT_CLOSABLE -# define STATUS_HANDLE_NOT_CLOSABLE ((NTSTATUS) 0xC0000235L) -#endif - -#ifndef STATUS_CONNECTION_REFUSED -# define STATUS_CONNECTION_REFUSED ((NTSTATUS) 0xC0000236L) -#endif - -#ifndef STATUS_GRACEFUL_DISCONNECT -# define STATUS_GRACEFUL_DISCONNECT ((NTSTATUS) 0xC0000237L) -#endif - -#ifndef STATUS_ADDRESS_ALREADY_ASSOCIATED -# define STATUS_ADDRESS_ALREADY_ASSOCIATED ((NTSTATUS) 0xC0000238L) -#endif - -#ifndef STATUS_ADDRESS_NOT_ASSOCIATED -# define STATUS_ADDRESS_NOT_ASSOCIATED ((NTSTATUS) 0xC0000239L) -#endif - -#ifndef STATUS_CONNECTION_INVALID -# define STATUS_CONNECTION_INVALID ((NTSTATUS) 0xC000023AL) -#endif - -#ifndef STATUS_CONNECTION_ACTIVE -# define STATUS_CONNECTION_ACTIVE ((NTSTATUS) 0xC000023BL) -#endif - -#ifndef STATUS_NETWORK_UNREACHABLE -# define STATUS_NETWORK_UNREACHABLE ((NTSTATUS) 0xC000023CL) -#endif - -#ifndef STATUS_HOST_UNREACHABLE -# define STATUS_HOST_UNREACHABLE ((NTSTATUS) 0xC000023DL) -#endif - -#ifndef STATUS_PROTOCOL_UNREACHABLE -# define STATUS_PROTOCOL_UNREACHABLE ((NTSTATUS) 0xC000023EL) -#endif - -#ifndef STATUS_PORT_UNREACHABLE -# define STATUS_PORT_UNREACHABLE ((NTSTATUS) 0xC000023FL) -#endif - -#ifndef STATUS_REQUEST_ABORTED -# define STATUS_REQUEST_ABORTED ((NTSTATUS) 0xC0000240L) -#endif - -#ifndef STATUS_CONNECTION_ABORTED -# define STATUS_CONNECTION_ABORTED ((NTSTATUS) 0xC0000241L) -#endif - -#ifndef STATUS_BAD_COMPRESSION_BUFFER -# define STATUS_BAD_COMPRESSION_BUFFER ((NTSTATUS) 0xC0000242L) -#endif - -#ifndef STATUS_USER_MAPPED_FILE -# define STATUS_USER_MAPPED_FILE ((NTSTATUS) 0xC0000243L) -#endif - -#ifndef STATUS_AUDIT_FAILED -# define STATUS_AUDIT_FAILED ((NTSTATUS) 0xC0000244L) -#endif - -#ifndef STATUS_TIMER_RESOLUTION_NOT_SET -# define STATUS_TIMER_RESOLUTION_NOT_SET ((NTSTATUS) 0xC0000245L) -#endif - -#ifndef STATUS_CONNECTION_COUNT_LIMIT -# define STATUS_CONNECTION_COUNT_LIMIT ((NTSTATUS) 0xC0000246L) -#endif - -#ifndef STATUS_LOGIN_TIME_RESTRICTION -# define STATUS_LOGIN_TIME_RESTRICTION ((NTSTATUS) 0xC0000247L) -#endif - -#ifndef STATUS_LOGIN_WKSTA_RESTRICTION -# define STATUS_LOGIN_WKSTA_RESTRICTION ((NTSTATUS) 0xC0000248L) -#endif - -#ifndef STATUS_IMAGE_MP_UP_MISMATCH -# define STATUS_IMAGE_MP_UP_MISMATCH ((NTSTATUS) 0xC0000249L) -#endif - -#ifndef STATUS_INSUFFICIENT_LOGON_INFO -# define STATUS_INSUFFICIENT_LOGON_INFO ((NTSTATUS) 0xC0000250L) -#endif - -#ifndef STATUS_BAD_DLL_ENTRYPOINT -# define STATUS_BAD_DLL_ENTRYPOINT ((NTSTATUS) 0xC0000251L) -#endif - -#ifndef STATUS_BAD_SERVICE_ENTRYPOINT -# define STATUS_BAD_SERVICE_ENTRYPOINT ((NTSTATUS) 0xC0000252L) -#endif - -#ifndef STATUS_LPC_REPLY_LOST -# define STATUS_LPC_REPLY_LOST ((NTSTATUS) 0xC0000253L) -#endif - -#ifndef STATUS_IP_ADDRESS_CONFLICT1 -# define STATUS_IP_ADDRESS_CONFLICT1 ((NTSTATUS) 0xC0000254L) -#endif - -#ifndef STATUS_IP_ADDRESS_CONFLICT2 -# define STATUS_IP_ADDRESS_CONFLICT2 ((NTSTATUS) 0xC0000255L) -#endif - -#ifndef STATUS_REGISTRY_QUOTA_LIMIT -# define STATUS_REGISTRY_QUOTA_LIMIT ((NTSTATUS) 0xC0000256L) -#endif - -#ifndef STATUS_PATH_NOT_COVERED -# define STATUS_PATH_NOT_COVERED ((NTSTATUS) 0xC0000257L) -#endif - -#ifndef STATUS_NO_CALLBACK_ACTIVE -# define STATUS_NO_CALLBACK_ACTIVE ((NTSTATUS) 0xC0000258L) -#endif - -#ifndef STATUS_LICENSE_QUOTA_EXCEEDED -# define STATUS_LICENSE_QUOTA_EXCEEDED ((NTSTATUS) 0xC0000259L) -#endif - -#ifndef STATUS_PWD_TOO_SHORT -# define STATUS_PWD_TOO_SHORT ((NTSTATUS) 0xC000025AL) -#endif - -#ifndef STATUS_PWD_TOO_RECENT -# define STATUS_PWD_TOO_RECENT ((NTSTATUS) 0xC000025BL) -#endif - -#ifndef STATUS_PWD_HISTORY_CONFLICT -# define STATUS_PWD_HISTORY_CONFLICT ((NTSTATUS) 0xC000025CL) -#endif - -#ifndef STATUS_PLUGPLAY_NO_DEVICE -# define STATUS_PLUGPLAY_NO_DEVICE ((NTSTATUS) 0xC000025EL) -#endif - -#ifndef STATUS_UNSUPPORTED_COMPRESSION -# define STATUS_UNSUPPORTED_COMPRESSION ((NTSTATUS) 0xC000025FL) -#endif - -#ifndef STATUS_INVALID_HW_PROFILE -# define STATUS_INVALID_HW_PROFILE ((NTSTATUS) 0xC0000260L) -#endif - -#ifndef STATUS_INVALID_PLUGPLAY_DEVICE_PATH -# define STATUS_INVALID_PLUGPLAY_DEVICE_PATH ((NTSTATUS) 0xC0000261L) -#endif - -#ifndef STATUS_DRIVER_ORDINAL_NOT_FOUND -# define STATUS_DRIVER_ORDINAL_NOT_FOUND ((NTSTATUS) 0xC0000262L) -#endif - -#ifndef STATUS_DRIVER_ENTRYPOINT_NOT_FOUND -# define STATUS_DRIVER_ENTRYPOINT_NOT_FOUND ((NTSTATUS) 0xC0000263L) -#endif - -#ifndef STATUS_RESOURCE_NOT_OWNED -# define STATUS_RESOURCE_NOT_OWNED ((NTSTATUS) 0xC0000264L) -#endif - -#ifndef STATUS_TOO_MANY_LINKS -# define STATUS_TOO_MANY_LINKS ((NTSTATUS) 0xC0000265L) -#endif - -#ifndef STATUS_QUOTA_LIST_INCONSISTENT -# define STATUS_QUOTA_LIST_INCONSISTENT ((NTSTATUS) 0xC0000266L) -#endif - -#ifndef STATUS_FILE_IS_OFFLINE -# define STATUS_FILE_IS_OFFLINE ((NTSTATUS) 0xC0000267L) -#endif - -#ifndef STATUS_EVALUATION_EXPIRATION -# define STATUS_EVALUATION_EXPIRATION ((NTSTATUS) 0xC0000268L) -#endif - -#ifndef STATUS_ILLEGAL_DLL_RELOCATION -# define STATUS_ILLEGAL_DLL_RELOCATION ((NTSTATUS) 0xC0000269L) -#endif - -#ifndef STATUS_LICENSE_VIOLATION -# define STATUS_LICENSE_VIOLATION ((NTSTATUS) 0xC000026AL) -#endif - -#ifndef STATUS_DLL_INIT_FAILED_LOGOFF -# define STATUS_DLL_INIT_FAILED_LOGOFF ((NTSTATUS) 0xC000026BL) -#endif - -#ifndef STATUS_DRIVER_UNABLE_TO_LOAD -# define STATUS_DRIVER_UNABLE_TO_LOAD ((NTSTATUS) 0xC000026CL) -#endif - -#ifndef STATUS_DFS_UNAVAILABLE -# define STATUS_DFS_UNAVAILABLE ((NTSTATUS) 0xC000026DL) -#endif - -#ifndef STATUS_VOLUME_DISMOUNTED -# define STATUS_VOLUME_DISMOUNTED ((NTSTATUS) 0xC000026EL) -#endif - -#ifndef STATUS_WX86_INTERNAL_ERROR -# define STATUS_WX86_INTERNAL_ERROR ((NTSTATUS) 0xC000026FL) -#endif - -#ifndef STATUS_WX86_FLOAT_STACK_CHECK -# define STATUS_WX86_FLOAT_STACK_CHECK ((NTSTATUS) 0xC0000270L) -#endif - -#ifndef STATUS_VALIDATE_CONTINUE -# define STATUS_VALIDATE_CONTINUE ((NTSTATUS) 0xC0000271L) -#endif - -#ifndef STATUS_NO_MATCH -# define STATUS_NO_MATCH ((NTSTATUS) 0xC0000272L) -#endif - -#ifndef STATUS_NO_MORE_MATCHES -# define STATUS_NO_MORE_MATCHES ((NTSTATUS) 0xC0000273L) -#endif - -#ifndef STATUS_NOT_A_REPARSE_POINT -# define STATUS_NOT_A_REPARSE_POINT ((NTSTATUS) 0xC0000275L) -#endif - -#ifndef STATUS_IO_REPARSE_TAG_INVALID -# define STATUS_IO_REPARSE_TAG_INVALID ((NTSTATUS) 0xC0000276L) -#endif - -#ifndef STATUS_IO_REPARSE_TAG_MISMATCH -# define STATUS_IO_REPARSE_TAG_MISMATCH ((NTSTATUS) 0xC0000277L) -#endif - -#ifndef STATUS_IO_REPARSE_DATA_INVALID -# define STATUS_IO_REPARSE_DATA_INVALID ((NTSTATUS) 0xC0000278L) -#endif - -#ifndef STATUS_IO_REPARSE_TAG_NOT_HANDLED -# define STATUS_IO_REPARSE_TAG_NOT_HANDLED ((NTSTATUS) 0xC0000279L) -#endif - -#ifndef STATUS_REPARSE_POINT_NOT_RESOLVED -# define STATUS_REPARSE_POINT_NOT_RESOLVED ((NTSTATUS) 0xC0000280L) -#endif - -#ifndef STATUS_DIRECTORY_IS_A_REPARSE_POINT -# define STATUS_DIRECTORY_IS_A_REPARSE_POINT ((NTSTATUS) 0xC0000281L) -#endif - -#ifndef STATUS_RANGE_LIST_CONFLICT -# define STATUS_RANGE_LIST_CONFLICT ((NTSTATUS) 0xC0000282L) -#endif - -#ifndef STATUS_SOURCE_ELEMENT_EMPTY -# define STATUS_SOURCE_ELEMENT_EMPTY ((NTSTATUS) 0xC0000283L) -#endif - -#ifndef STATUS_DESTINATION_ELEMENT_FULL -# define STATUS_DESTINATION_ELEMENT_FULL ((NTSTATUS) 0xC0000284L) -#endif - -#ifndef STATUS_ILLEGAL_ELEMENT_ADDRESS -# define STATUS_ILLEGAL_ELEMENT_ADDRESS ((NTSTATUS) 0xC0000285L) -#endif - -#ifndef STATUS_MAGAZINE_NOT_PRESENT -# define STATUS_MAGAZINE_NOT_PRESENT ((NTSTATUS) 0xC0000286L) -#endif - -#ifndef STATUS_REINITIALIZATION_NEEDED -# define STATUS_REINITIALIZATION_NEEDED ((NTSTATUS) 0xC0000287L) -#endif - -#ifndef STATUS_DEVICE_REQUIRES_CLEANING -# define STATUS_DEVICE_REQUIRES_CLEANING ((NTSTATUS) 0x80000288L) -#endif - -#ifndef STATUS_DEVICE_DOOR_OPEN -# define STATUS_DEVICE_DOOR_OPEN ((NTSTATUS) 0x80000289L) -#endif - -#ifndef STATUS_ENCRYPTION_FAILED -# define STATUS_ENCRYPTION_FAILED ((NTSTATUS) 0xC000028AL) -#endif - -#ifndef STATUS_DECRYPTION_FAILED -# define STATUS_DECRYPTION_FAILED ((NTSTATUS) 0xC000028BL) -#endif - -#ifndef STATUS_RANGE_NOT_FOUND -# define STATUS_RANGE_NOT_FOUND ((NTSTATUS) 0xC000028CL) -#endif - -#ifndef STATUS_NO_RECOVERY_POLICY -# define STATUS_NO_RECOVERY_POLICY ((NTSTATUS) 0xC000028DL) -#endif - -#ifndef STATUS_NO_EFS -# define STATUS_NO_EFS ((NTSTATUS) 0xC000028EL) -#endif - -#ifndef STATUS_WRONG_EFS -# define STATUS_WRONG_EFS ((NTSTATUS) 0xC000028FL) -#endif - -#ifndef STATUS_NO_USER_KEYS -# define STATUS_NO_USER_KEYS ((NTSTATUS) 0xC0000290L) -#endif - -#ifndef STATUS_FILE_NOT_ENCRYPTED -# define STATUS_FILE_NOT_ENCRYPTED ((NTSTATUS) 0xC0000291L) -#endif - -#ifndef STATUS_NOT_EXPORT_FORMAT -# define STATUS_NOT_EXPORT_FORMAT ((NTSTATUS) 0xC0000292L) -#endif - -#ifndef STATUS_FILE_ENCRYPTED -# define STATUS_FILE_ENCRYPTED ((NTSTATUS) 0xC0000293L) -#endif - -#ifndef STATUS_WAKE_SYSTEM -# define STATUS_WAKE_SYSTEM ((NTSTATUS) 0x40000294L) -#endif - -#ifndef STATUS_WMI_GUID_NOT_FOUND -# define STATUS_WMI_GUID_NOT_FOUND ((NTSTATUS) 0xC0000295L) -#endif - -#ifndef STATUS_WMI_INSTANCE_NOT_FOUND -# define STATUS_WMI_INSTANCE_NOT_FOUND ((NTSTATUS) 0xC0000296L) -#endif - -#ifndef STATUS_WMI_ITEMID_NOT_FOUND -# define STATUS_WMI_ITEMID_NOT_FOUND ((NTSTATUS) 0xC0000297L) -#endif - -#ifndef STATUS_WMI_TRY_AGAIN -# define STATUS_WMI_TRY_AGAIN ((NTSTATUS) 0xC0000298L) -#endif - -#ifndef STATUS_SHARED_POLICY -# define STATUS_SHARED_POLICY ((NTSTATUS) 0xC0000299L) -#endif - -#ifndef STATUS_POLICY_OBJECT_NOT_FOUND -# define STATUS_POLICY_OBJECT_NOT_FOUND ((NTSTATUS) 0xC000029AL) -#endif - -#ifndef STATUS_POLICY_ONLY_IN_DS -# define STATUS_POLICY_ONLY_IN_DS ((NTSTATUS) 0xC000029BL) -#endif - -#ifndef STATUS_VOLUME_NOT_UPGRADED -# define STATUS_VOLUME_NOT_UPGRADED ((NTSTATUS) 0xC000029CL) -#endif - -#ifndef STATUS_REMOTE_STORAGE_NOT_ACTIVE -# define STATUS_REMOTE_STORAGE_NOT_ACTIVE ((NTSTATUS) 0xC000029DL) -#endif - -#ifndef STATUS_REMOTE_STORAGE_MEDIA_ERROR -# define STATUS_REMOTE_STORAGE_MEDIA_ERROR ((NTSTATUS) 0xC000029EL) -#endif - -#ifndef STATUS_NO_TRACKING_SERVICE -# define STATUS_NO_TRACKING_SERVICE ((NTSTATUS) 0xC000029FL) -#endif - -#ifndef STATUS_SERVER_SID_MISMATCH -# define STATUS_SERVER_SID_MISMATCH ((NTSTATUS) 0xC00002A0L) -#endif - -#ifndef STATUS_DS_NO_ATTRIBUTE_OR_VALUE -# define STATUS_DS_NO_ATTRIBUTE_OR_VALUE ((NTSTATUS) 0xC00002A1L) -#endif - -#ifndef STATUS_DS_INVALID_ATTRIBUTE_SYNTAX -# define STATUS_DS_INVALID_ATTRIBUTE_SYNTAX ((NTSTATUS) 0xC00002A2L) -#endif - -#ifndef STATUS_DS_ATTRIBUTE_TYPE_UNDEFINED -# define STATUS_DS_ATTRIBUTE_TYPE_UNDEFINED ((NTSTATUS) 0xC00002A3L) -#endif - -#ifndef STATUS_DS_ATTRIBUTE_OR_VALUE_EXISTS -# define STATUS_DS_ATTRIBUTE_OR_VALUE_EXISTS ((NTSTATUS) 0xC00002A4L) -#endif - -#ifndef STATUS_DS_BUSY -# define STATUS_DS_BUSY ((NTSTATUS) 0xC00002A5L) -#endif - -#ifndef STATUS_DS_UNAVAILABLE -# define STATUS_DS_UNAVAILABLE ((NTSTATUS) 0xC00002A6L) -#endif - -#ifndef STATUS_DS_NO_RIDS_ALLOCATED -# define STATUS_DS_NO_RIDS_ALLOCATED ((NTSTATUS) 0xC00002A7L) -#endif - -#ifndef STATUS_DS_NO_MORE_RIDS -# define STATUS_DS_NO_MORE_RIDS ((NTSTATUS) 0xC00002A8L) -#endif - -#ifndef STATUS_DS_INCORRECT_ROLE_OWNER -# define STATUS_DS_INCORRECT_ROLE_OWNER ((NTSTATUS) 0xC00002A9L) -#endif - -#ifndef STATUS_DS_RIDMGR_INIT_ERROR -# define STATUS_DS_RIDMGR_INIT_ERROR ((NTSTATUS) 0xC00002AAL) -#endif - -#ifndef STATUS_DS_OBJ_CLASS_VIOLATION -# define STATUS_DS_OBJ_CLASS_VIOLATION ((NTSTATUS) 0xC00002ABL) -#endif - -#ifndef STATUS_DS_CANT_ON_NON_LEAF -# define STATUS_DS_CANT_ON_NON_LEAF ((NTSTATUS) 0xC00002ACL) -#endif - -#ifndef STATUS_DS_CANT_ON_RDN -# define STATUS_DS_CANT_ON_RDN ((NTSTATUS) 0xC00002ADL) -#endif - -#ifndef STATUS_DS_CANT_MOD_OBJ_CLASS -# define STATUS_DS_CANT_MOD_OBJ_CLASS ((NTSTATUS) 0xC00002AEL) -#endif - -#ifndef STATUS_DS_CROSS_DOM_MOVE_FAILED -# define STATUS_DS_CROSS_DOM_MOVE_FAILED ((NTSTATUS) 0xC00002AFL) -#endif - -#ifndef STATUS_DS_GC_NOT_AVAILABLE -# define STATUS_DS_GC_NOT_AVAILABLE ((NTSTATUS) 0xC00002B0L) -#endif - -#ifndef STATUS_DIRECTORY_SERVICE_REQUIRED -# define STATUS_DIRECTORY_SERVICE_REQUIRED ((NTSTATUS) 0xC00002B1L) -#endif - -#ifndef STATUS_REPARSE_ATTRIBUTE_CONFLICT -# define STATUS_REPARSE_ATTRIBUTE_CONFLICT ((NTSTATUS) 0xC00002B2L) -#endif - -#ifndef STATUS_CANT_ENABLE_DENY_ONLY -# define STATUS_CANT_ENABLE_DENY_ONLY ((NTSTATUS) 0xC00002B3L) -#endif - -#ifndef STATUS_FLOAT_MULTIPLE_FAULTS -# define STATUS_FLOAT_MULTIPLE_FAULTS ((NTSTATUS) 0xC00002B4L) -#endif - -#ifndef STATUS_FLOAT_MULTIPLE_TRAPS -# define STATUS_FLOAT_MULTIPLE_TRAPS ((NTSTATUS) 0xC00002B5L) -#endif - -#ifndef STATUS_DEVICE_REMOVED -# define STATUS_DEVICE_REMOVED ((NTSTATUS) 0xC00002B6L) -#endif - -#ifndef STATUS_JOURNAL_DELETE_IN_PROGRESS -# define STATUS_JOURNAL_DELETE_IN_PROGRESS ((NTSTATUS) 0xC00002B7L) -#endif - -#ifndef STATUS_JOURNAL_NOT_ACTIVE -# define STATUS_JOURNAL_NOT_ACTIVE ((NTSTATUS) 0xC00002B8L) -#endif - -#ifndef STATUS_NOINTERFACE -# define STATUS_NOINTERFACE ((NTSTATUS) 0xC00002B9L) -#endif - -#ifndef STATUS_DS_ADMIN_LIMIT_EXCEEDED -# define STATUS_DS_ADMIN_LIMIT_EXCEEDED ((NTSTATUS) 0xC00002C1L) -#endif - -#ifndef STATUS_DRIVER_FAILED_SLEEP -# define STATUS_DRIVER_FAILED_SLEEP ((NTSTATUS) 0xC00002C2L) -#endif - -#ifndef STATUS_MUTUAL_AUTHENTICATION_FAILED -# define STATUS_MUTUAL_AUTHENTICATION_FAILED ((NTSTATUS) 0xC00002C3L) -#endif - -#ifndef STATUS_CORRUPT_SYSTEM_FILE -# define STATUS_CORRUPT_SYSTEM_FILE ((NTSTATUS) 0xC00002C4L) -#endif - -#ifndef STATUS_DATATYPE_MISALIGNMENT_ERROR -# define STATUS_DATATYPE_MISALIGNMENT_ERROR ((NTSTATUS) 0xC00002C5L) -#endif - -#ifndef STATUS_WMI_READ_ONLY -# define STATUS_WMI_READ_ONLY ((NTSTATUS) 0xC00002C6L) -#endif - -#ifndef STATUS_WMI_SET_FAILURE -# define STATUS_WMI_SET_FAILURE ((NTSTATUS) 0xC00002C7L) -#endif - -#ifndef STATUS_COMMITMENT_MINIMUM -# define STATUS_COMMITMENT_MINIMUM ((NTSTATUS) 0xC00002C8L) -#endif - -#ifndef STATUS_REG_NAT_CONSUMPTION -# define STATUS_REG_NAT_CONSUMPTION ((NTSTATUS) 0xC00002C9L) -#endif - -#ifndef STATUS_TRANSPORT_FULL -# define STATUS_TRANSPORT_FULL ((NTSTATUS) 0xC00002CAL) -#endif - -#ifndef STATUS_DS_SAM_INIT_FAILURE -# define STATUS_DS_SAM_INIT_FAILURE ((NTSTATUS) 0xC00002CBL) -#endif - -#ifndef STATUS_ONLY_IF_CONNECTED -# define STATUS_ONLY_IF_CONNECTED ((NTSTATUS) 0xC00002CCL) -#endif - -#ifndef STATUS_DS_SENSITIVE_GROUP_VIOLATION -# define STATUS_DS_SENSITIVE_GROUP_VIOLATION ((NTSTATUS) 0xC00002CDL) -#endif - -#ifndef STATUS_PNP_RESTART_ENUMERATION -# define STATUS_PNP_RESTART_ENUMERATION ((NTSTATUS) 0xC00002CEL) -#endif - -#ifndef STATUS_JOURNAL_ENTRY_DELETED -# define STATUS_JOURNAL_ENTRY_DELETED ((NTSTATUS) 0xC00002CFL) -#endif - -#ifndef STATUS_DS_CANT_MOD_PRIMARYGROUPID -# define STATUS_DS_CANT_MOD_PRIMARYGROUPID ((NTSTATUS) 0xC00002D0L) -#endif - -#ifndef STATUS_SYSTEM_IMAGE_BAD_SIGNATURE -# define STATUS_SYSTEM_IMAGE_BAD_SIGNATURE ((NTSTATUS) 0xC00002D1L) -#endif - -#ifndef STATUS_PNP_REBOOT_REQUIRED -# define STATUS_PNP_REBOOT_REQUIRED ((NTSTATUS) 0xC00002D2L) -#endif - -#ifndef STATUS_POWER_STATE_INVALID -# define STATUS_POWER_STATE_INVALID ((NTSTATUS) 0xC00002D3L) -#endif - -#ifndef STATUS_DS_INVALID_GROUP_TYPE -# define STATUS_DS_INVALID_GROUP_TYPE ((NTSTATUS) 0xC00002D4L) -#endif - -#ifndef STATUS_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN -# define STATUS_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN ((NTSTATUS) 0xC00002D5L) -#endif - -#ifndef STATUS_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN -# define STATUS_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN ((NTSTATUS) 0xC00002D6L) -#endif - -#ifndef STATUS_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER -# define STATUS_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER ((NTSTATUS) 0xC00002D7L) -#endif - -#ifndef STATUS_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER -# define STATUS_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER ((NTSTATUS) 0xC00002D8L) -#endif - -#ifndef STATUS_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER -# define STATUS_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER ((NTSTATUS) 0xC00002D9L) -#endif - -#ifndef STATUS_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER -# define STATUS_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER ((NTSTATUS) 0xC00002DAL) -#endif - -#ifndef STATUS_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER -# define STATUS_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER ((NTSTATUS) 0xC00002DBL) -#endif - -#ifndef STATUS_DS_HAVE_PRIMARY_MEMBERS -# define STATUS_DS_HAVE_PRIMARY_MEMBERS ((NTSTATUS) 0xC00002DCL) -#endif - -#ifndef STATUS_WMI_NOT_SUPPORTED -# define STATUS_WMI_NOT_SUPPORTED ((NTSTATUS) 0xC00002DDL) -#endif - -#ifndef STATUS_INSUFFICIENT_POWER -# define STATUS_INSUFFICIENT_POWER ((NTSTATUS) 0xC00002DEL) -#endif - -#ifndef STATUS_SAM_NEED_BOOTKEY_PASSWORD -# define STATUS_SAM_NEED_BOOTKEY_PASSWORD ((NTSTATUS) 0xC00002DFL) -#endif - -#ifndef STATUS_SAM_NEED_BOOTKEY_FLOPPY -# define STATUS_SAM_NEED_BOOTKEY_FLOPPY ((NTSTATUS) 0xC00002E0L) -#endif - -#ifndef STATUS_DS_CANT_START -# define STATUS_DS_CANT_START ((NTSTATUS) 0xC00002E1L) -#endif - -#ifndef STATUS_DS_INIT_FAILURE -# define STATUS_DS_INIT_FAILURE ((NTSTATUS) 0xC00002E2L) -#endif - -#ifndef STATUS_SAM_INIT_FAILURE -# define STATUS_SAM_INIT_FAILURE ((NTSTATUS) 0xC00002E3L) -#endif - -#ifndef STATUS_DS_GC_REQUIRED -# define STATUS_DS_GC_REQUIRED ((NTSTATUS) 0xC00002E4L) -#endif - -#ifndef STATUS_DS_LOCAL_MEMBER_OF_LOCAL_ONLY -# define STATUS_DS_LOCAL_MEMBER_OF_LOCAL_ONLY ((NTSTATUS) 0xC00002E5L) -#endif - -#ifndef STATUS_DS_NO_FPO_IN_UNIVERSAL_GROUPS -# define STATUS_DS_NO_FPO_IN_UNIVERSAL_GROUPS ((NTSTATUS) 0xC00002E6L) -#endif - -#ifndef STATUS_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED -# define STATUS_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED ((NTSTATUS) 0xC00002E7L) -#endif - -#ifndef STATUS_MULTIPLE_FAULT_VIOLATION -# define STATUS_MULTIPLE_FAULT_VIOLATION ((NTSTATUS) 0xC00002E8L) -#endif - -#ifndef STATUS_CURRENT_DOMAIN_NOT_ALLOWED -# define STATUS_CURRENT_DOMAIN_NOT_ALLOWED ((NTSTATUS) 0xC00002E9L) -#endif - -#ifndef STATUS_CANNOT_MAKE -# define STATUS_CANNOT_MAKE ((NTSTATUS) 0xC00002EAL) -#endif - -#ifndef STATUS_SYSTEM_SHUTDOWN -# define STATUS_SYSTEM_SHUTDOWN ((NTSTATUS) 0xC00002EBL) -#endif - -#ifndef STATUS_DS_INIT_FAILURE_CONSOLE -# define STATUS_DS_INIT_FAILURE_CONSOLE ((NTSTATUS) 0xC00002ECL) -#endif - -#ifndef STATUS_DS_SAM_INIT_FAILURE_CONSOLE -# define STATUS_DS_SAM_INIT_FAILURE_CONSOLE ((NTSTATUS) 0xC00002EDL) -#endif - -#ifndef STATUS_UNFINISHED_CONTEXT_DELETED -# define STATUS_UNFINISHED_CONTEXT_DELETED ((NTSTATUS) 0xC00002EEL) -#endif - -#ifndef STATUS_NO_TGT_REPLY -# define STATUS_NO_TGT_REPLY ((NTSTATUS) 0xC00002EFL) -#endif - -#ifndef STATUS_OBJECTID_NOT_FOUND -# define STATUS_OBJECTID_NOT_FOUND ((NTSTATUS) 0xC00002F0L) -#endif - -#ifndef STATUS_NO_IP_ADDRESSES -# define STATUS_NO_IP_ADDRESSES ((NTSTATUS) 0xC00002F1L) -#endif - -#ifndef STATUS_WRONG_CREDENTIAL_HANDLE -# define STATUS_WRONG_CREDENTIAL_HANDLE ((NTSTATUS) 0xC00002F2L) -#endif - -#ifndef STATUS_CRYPTO_SYSTEM_INVALID -# define STATUS_CRYPTO_SYSTEM_INVALID ((NTSTATUS) 0xC00002F3L) -#endif - -#ifndef STATUS_MAX_REFERRALS_EXCEEDED -# define STATUS_MAX_REFERRALS_EXCEEDED ((NTSTATUS) 0xC00002F4L) -#endif - -#ifndef STATUS_MUST_BE_KDC -# define STATUS_MUST_BE_KDC ((NTSTATUS) 0xC00002F5L) -#endif - -#ifndef STATUS_STRONG_CRYPTO_NOT_SUPPORTED -# define STATUS_STRONG_CRYPTO_NOT_SUPPORTED ((NTSTATUS) 0xC00002F6L) -#endif - -#ifndef STATUS_TOO_MANY_PRINCIPALS -# define STATUS_TOO_MANY_PRINCIPALS ((NTSTATUS) 0xC00002F7L) -#endif - -#ifndef STATUS_NO_PA_DATA -# define STATUS_NO_PA_DATA ((NTSTATUS) 0xC00002F8L) -#endif - -#ifndef STATUS_PKINIT_NAME_MISMATCH -# define STATUS_PKINIT_NAME_MISMATCH ((NTSTATUS) 0xC00002F9L) -#endif - -#ifndef STATUS_SMARTCARD_LOGON_REQUIRED -# define STATUS_SMARTCARD_LOGON_REQUIRED ((NTSTATUS) 0xC00002FAL) -#endif - -#ifndef STATUS_KDC_INVALID_REQUEST -# define STATUS_KDC_INVALID_REQUEST ((NTSTATUS) 0xC00002FBL) -#endif - -#ifndef STATUS_KDC_UNABLE_TO_REFER -# define STATUS_KDC_UNABLE_TO_REFER ((NTSTATUS) 0xC00002FCL) -#endif - -#ifndef STATUS_KDC_UNKNOWN_ETYPE -# define STATUS_KDC_UNKNOWN_ETYPE ((NTSTATUS) 0xC00002FDL) -#endif - -#ifndef STATUS_SHUTDOWN_IN_PROGRESS -# define STATUS_SHUTDOWN_IN_PROGRESS ((NTSTATUS) 0xC00002FEL) -#endif - -#ifndef STATUS_SERVER_SHUTDOWN_IN_PROGRESS -# define STATUS_SERVER_SHUTDOWN_IN_PROGRESS ((NTSTATUS) 0xC00002FFL) -#endif - -#ifndef STATUS_NOT_SUPPORTED_ON_SBS -# define STATUS_NOT_SUPPORTED_ON_SBS ((NTSTATUS) 0xC0000300L) -#endif - -#ifndef STATUS_WMI_GUID_DISCONNECTED -# define STATUS_WMI_GUID_DISCONNECTED ((NTSTATUS) 0xC0000301L) -#endif - -#ifndef STATUS_WMI_ALREADY_DISABLED -# define STATUS_WMI_ALREADY_DISABLED ((NTSTATUS) 0xC0000302L) -#endif - -#ifndef STATUS_WMI_ALREADY_ENABLED -# define STATUS_WMI_ALREADY_ENABLED ((NTSTATUS) 0xC0000303L) -#endif - -#ifndef STATUS_MFT_TOO_FRAGMENTED -# define STATUS_MFT_TOO_FRAGMENTED ((NTSTATUS) 0xC0000304L) -#endif - -#ifndef STATUS_COPY_PROTECTION_FAILURE -# define STATUS_COPY_PROTECTION_FAILURE ((NTSTATUS) 0xC0000305L) -#endif - -#ifndef STATUS_CSS_AUTHENTICATION_FAILURE -# define STATUS_CSS_AUTHENTICATION_FAILURE ((NTSTATUS) 0xC0000306L) -#endif - -#ifndef STATUS_CSS_KEY_NOT_PRESENT -# define STATUS_CSS_KEY_NOT_PRESENT ((NTSTATUS) 0xC0000307L) -#endif - -#ifndef STATUS_CSS_KEY_NOT_ESTABLISHED -# define STATUS_CSS_KEY_NOT_ESTABLISHED ((NTSTATUS) 0xC0000308L) -#endif - -#ifndef STATUS_CSS_SCRAMBLED_SECTOR -# define STATUS_CSS_SCRAMBLED_SECTOR ((NTSTATUS) 0xC0000309L) -#endif - -#ifndef STATUS_CSS_REGION_MISMATCH -# define STATUS_CSS_REGION_MISMATCH ((NTSTATUS) 0xC000030AL) -#endif - -#ifndef STATUS_CSS_RESETS_EXHAUSTED -# define STATUS_CSS_RESETS_EXHAUSTED ((NTSTATUS) 0xC000030BL) -#endif - -#ifndef STATUS_PKINIT_FAILURE -# define STATUS_PKINIT_FAILURE ((NTSTATUS) 0xC0000320L) -#endif - -#ifndef STATUS_SMARTCARD_SUBSYSTEM_FAILURE -# define STATUS_SMARTCARD_SUBSYSTEM_FAILURE ((NTSTATUS) 0xC0000321L) -#endif - -#ifndef STATUS_NO_KERB_KEY -# define STATUS_NO_KERB_KEY ((NTSTATUS) 0xC0000322L) -#endif - -#ifndef STATUS_HOST_DOWN -# define STATUS_HOST_DOWN ((NTSTATUS) 0xC0000350L) -#endif - -#ifndef STATUS_UNSUPPORTED_PREAUTH -# define STATUS_UNSUPPORTED_PREAUTH ((NTSTATUS) 0xC0000351L) -#endif - -#ifndef STATUS_EFS_ALG_BLOB_TOO_BIG -# define STATUS_EFS_ALG_BLOB_TOO_BIG ((NTSTATUS) 0xC0000352L) -#endif - -#ifndef STATUS_PORT_NOT_SET -# define STATUS_PORT_NOT_SET ((NTSTATUS) 0xC0000353L) -#endif - -#ifndef STATUS_DEBUGGER_INACTIVE -# define STATUS_DEBUGGER_INACTIVE ((NTSTATUS) 0xC0000354L) -#endif - -#ifndef STATUS_DS_VERSION_CHECK_FAILURE -# define STATUS_DS_VERSION_CHECK_FAILURE ((NTSTATUS) 0xC0000355L) -#endif - -#ifndef STATUS_AUDITING_DISABLED -# define STATUS_AUDITING_DISABLED ((NTSTATUS) 0xC0000356L) -#endif - -#ifndef STATUS_PRENT4_MACHINE_ACCOUNT -# define STATUS_PRENT4_MACHINE_ACCOUNT ((NTSTATUS) 0xC0000357L) -#endif - -#ifndef STATUS_DS_AG_CANT_HAVE_UNIVERSAL_MEMBER -# define STATUS_DS_AG_CANT_HAVE_UNIVERSAL_MEMBER ((NTSTATUS) 0xC0000358L) -#endif - -#ifndef STATUS_INVALID_IMAGE_WIN_32 -# define STATUS_INVALID_IMAGE_WIN_32 ((NTSTATUS) 0xC0000359L) -#endif - -#ifndef STATUS_INVALID_IMAGE_WIN_64 -# define STATUS_INVALID_IMAGE_WIN_64 ((NTSTATUS) 0xC000035AL) -#endif - -#ifndef STATUS_BAD_BINDINGS -# define STATUS_BAD_BINDINGS ((NTSTATUS) 0xC000035BL) -#endif - -#ifndef STATUS_NETWORK_SESSION_EXPIRED -# define STATUS_NETWORK_SESSION_EXPIRED ((NTSTATUS) 0xC000035CL) -#endif - -#ifndef STATUS_APPHELP_BLOCK -# define STATUS_APPHELP_BLOCK ((NTSTATUS) 0xC000035DL) -#endif - -#ifndef STATUS_ALL_SIDS_FILTERED -# define STATUS_ALL_SIDS_FILTERED ((NTSTATUS) 0xC000035EL) -#endif - -#ifndef STATUS_NOT_SAFE_MODE_DRIVER -# define STATUS_NOT_SAFE_MODE_DRIVER ((NTSTATUS) 0xC000035FL) -#endif - -#ifndef STATUS_ACCESS_DISABLED_BY_POLICY_DEFAULT -# define STATUS_ACCESS_DISABLED_BY_POLICY_DEFAULT ((NTSTATUS) 0xC0000361L) -#endif - -#ifndef STATUS_ACCESS_DISABLED_BY_POLICY_PATH -# define STATUS_ACCESS_DISABLED_BY_POLICY_PATH ((NTSTATUS) 0xC0000362L) -#endif - -#ifndef STATUS_ACCESS_DISABLED_BY_POLICY_PUBLISHER -# define STATUS_ACCESS_DISABLED_BY_POLICY_PUBLISHER ((NTSTATUS) 0xC0000363L) -#endif - -#ifndef STATUS_ACCESS_DISABLED_BY_POLICY_OTHER -# define STATUS_ACCESS_DISABLED_BY_POLICY_OTHER ((NTSTATUS) 0xC0000364L) -#endif - -#ifndef STATUS_FAILED_DRIVER_ENTRY -# define STATUS_FAILED_DRIVER_ENTRY ((NTSTATUS) 0xC0000365L) -#endif - -#ifndef STATUS_DEVICE_ENUMERATION_ERROR -# define STATUS_DEVICE_ENUMERATION_ERROR ((NTSTATUS) 0xC0000366L) -#endif - -#ifndef STATUS_MOUNT_POINT_NOT_RESOLVED -# define STATUS_MOUNT_POINT_NOT_RESOLVED ((NTSTATUS) 0xC0000368L) -#endif - -#ifndef STATUS_INVALID_DEVICE_OBJECT_PARAMETER -# define STATUS_INVALID_DEVICE_OBJECT_PARAMETER ((NTSTATUS) 0xC0000369L) -#endif - -#ifndef STATUS_MCA_OCCURED -# define STATUS_MCA_OCCURED ((NTSTATUS) 0xC000036AL) -#endif - -#ifndef STATUS_DRIVER_BLOCKED_CRITICAL -# define STATUS_DRIVER_BLOCKED_CRITICAL ((NTSTATUS) 0xC000036BL) -#endif - -#ifndef STATUS_DRIVER_BLOCKED -# define STATUS_DRIVER_BLOCKED ((NTSTATUS) 0xC000036CL) -#endif - -#ifndef STATUS_DRIVER_DATABASE_ERROR -# define STATUS_DRIVER_DATABASE_ERROR ((NTSTATUS) 0xC000036DL) -#endif - -#ifndef STATUS_SYSTEM_HIVE_TOO_LARGE -# define STATUS_SYSTEM_HIVE_TOO_LARGE ((NTSTATUS) 0xC000036EL) -#endif - -#ifndef STATUS_INVALID_IMPORT_OF_NON_DLL -# define STATUS_INVALID_IMPORT_OF_NON_DLL ((NTSTATUS) 0xC000036FL) -#endif - -#ifndef STATUS_DS_SHUTTING_DOWN -# define STATUS_DS_SHUTTING_DOWN ((NTSTATUS) 0x40000370L) -#endif - -#ifndef STATUS_NO_SECRETS -# define STATUS_NO_SECRETS ((NTSTATUS) 0xC0000371L) -#endif - -#ifndef STATUS_ACCESS_DISABLED_NO_SAFER_UI_BY_POLICY -# define STATUS_ACCESS_DISABLED_NO_SAFER_UI_BY_POLICY ((NTSTATUS) 0xC0000372L) -#endif - -#ifndef STATUS_FAILED_STACK_SWITCH -# define STATUS_FAILED_STACK_SWITCH ((NTSTATUS) 0xC0000373L) -#endif - -#ifndef STATUS_HEAP_CORRUPTION -# define STATUS_HEAP_CORRUPTION ((NTSTATUS) 0xC0000374L) -#endif - -#ifndef STATUS_SMARTCARD_WRONG_PIN -# define STATUS_SMARTCARD_WRONG_PIN ((NTSTATUS) 0xC0000380L) -#endif - -#ifndef STATUS_SMARTCARD_CARD_BLOCKED -# define STATUS_SMARTCARD_CARD_BLOCKED ((NTSTATUS) 0xC0000381L) -#endif - -#ifndef STATUS_SMARTCARD_CARD_NOT_AUTHENTICATED -# define STATUS_SMARTCARD_CARD_NOT_AUTHENTICATED ((NTSTATUS) 0xC0000382L) -#endif - -#ifndef STATUS_SMARTCARD_NO_CARD -# define STATUS_SMARTCARD_NO_CARD ((NTSTATUS) 0xC0000383L) -#endif - -#ifndef STATUS_SMARTCARD_NO_KEY_CONTAINER -# define STATUS_SMARTCARD_NO_KEY_CONTAINER ((NTSTATUS) 0xC0000384L) -#endif - -#ifndef STATUS_SMARTCARD_NO_CERTIFICATE -# define STATUS_SMARTCARD_NO_CERTIFICATE ((NTSTATUS) 0xC0000385L) -#endif - -#ifndef STATUS_SMARTCARD_NO_KEYSET -# define STATUS_SMARTCARD_NO_KEYSET ((NTSTATUS) 0xC0000386L) -#endif - -#ifndef STATUS_SMARTCARD_IO_ERROR -# define STATUS_SMARTCARD_IO_ERROR ((NTSTATUS) 0xC0000387L) -#endif - -#ifndef STATUS_DOWNGRADE_DETECTED -# define STATUS_DOWNGRADE_DETECTED ((NTSTATUS) 0xC0000388L) -#endif - -#ifndef STATUS_SMARTCARD_CERT_REVOKED -# define STATUS_SMARTCARD_CERT_REVOKED ((NTSTATUS) 0xC0000389L) -#endif - -#ifndef STATUS_ISSUING_CA_UNTRUSTED -# define STATUS_ISSUING_CA_UNTRUSTED ((NTSTATUS) 0xC000038AL) -#endif - -#ifndef STATUS_REVOCATION_OFFLINE_C -# define STATUS_REVOCATION_OFFLINE_C ((NTSTATUS) 0xC000038BL) -#endif - -#ifndef STATUS_PKINIT_CLIENT_FAILURE -# define STATUS_PKINIT_CLIENT_FAILURE ((NTSTATUS) 0xC000038CL) -#endif - -#ifndef STATUS_SMARTCARD_CERT_EXPIRED -# define STATUS_SMARTCARD_CERT_EXPIRED ((NTSTATUS) 0xC000038DL) -#endif - -#ifndef STATUS_DRIVER_FAILED_PRIOR_UNLOAD -# define STATUS_DRIVER_FAILED_PRIOR_UNLOAD ((NTSTATUS) 0xC000038EL) -#endif - -#ifndef STATUS_SMARTCARD_SILENT_CONTEXT -# define STATUS_SMARTCARD_SILENT_CONTEXT ((NTSTATUS) 0xC000038FL) -#endif - -#ifndef STATUS_PER_USER_TRUST_QUOTA_EXCEEDED -# define STATUS_PER_USER_TRUST_QUOTA_EXCEEDED ((NTSTATUS) 0xC0000401L) -#endif - -#ifndef STATUS_ALL_USER_TRUST_QUOTA_EXCEEDED -# define STATUS_ALL_USER_TRUST_QUOTA_EXCEEDED ((NTSTATUS) 0xC0000402L) -#endif - -#ifndef STATUS_USER_DELETE_TRUST_QUOTA_EXCEEDED -# define STATUS_USER_DELETE_TRUST_QUOTA_EXCEEDED ((NTSTATUS) 0xC0000403L) -#endif - -#ifndef STATUS_DS_NAME_NOT_UNIQUE -# define STATUS_DS_NAME_NOT_UNIQUE ((NTSTATUS) 0xC0000404L) -#endif - -#ifndef STATUS_DS_DUPLICATE_ID_FOUND -# define STATUS_DS_DUPLICATE_ID_FOUND ((NTSTATUS) 0xC0000405L) -#endif - -#ifndef STATUS_DS_GROUP_CONVERSION_ERROR -# define STATUS_DS_GROUP_CONVERSION_ERROR ((NTSTATUS) 0xC0000406L) -#endif - -#ifndef STATUS_VOLSNAP_PREPARE_HIBERNATE -# define STATUS_VOLSNAP_PREPARE_HIBERNATE ((NTSTATUS) 0xC0000407L) -#endif - -#ifndef STATUS_USER2USER_REQUIRED -# define STATUS_USER2USER_REQUIRED ((NTSTATUS) 0xC0000408L) -#endif - -#ifndef STATUS_STACK_BUFFER_OVERRUN -# define STATUS_STACK_BUFFER_OVERRUN ((NTSTATUS) 0xC0000409L) -#endif - -#ifndef STATUS_NO_S4U_PROT_SUPPORT -# define STATUS_NO_S4U_PROT_SUPPORT ((NTSTATUS) 0xC000040AL) -#endif - -#ifndef STATUS_CROSSREALM_DELEGATION_FAILURE -# define STATUS_CROSSREALM_DELEGATION_FAILURE ((NTSTATUS) 0xC000040BL) -#endif - -#ifndef STATUS_REVOCATION_OFFLINE_KDC -# define STATUS_REVOCATION_OFFLINE_KDC ((NTSTATUS) 0xC000040CL) -#endif - -#ifndef STATUS_ISSUING_CA_UNTRUSTED_KDC -# define STATUS_ISSUING_CA_UNTRUSTED_KDC ((NTSTATUS) 0xC000040DL) -#endif - -#ifndef STATUS_KDC_CERT_EXPIRED -# define STATUS_KDC_CERT_EXPIRED ((NTSTATUS) 0xC000040EL) -#endif - -#ifndef STATUS_KDC_CERT_REVOKED -# define STATUS_KDC_CERT_REVOKED ((NTSTATUS) 0xC000040FL) -#endif - -#ifndef STATUS_PARAMETER_QUOTA_EXCEEDED -# define STATUS_PARAMETER_QUOTA_EXCEEDED ((NTSTATUS) 0xC0000410L) -#endif - -#ifndef STATUS_HIBERNATION_FAILURE -# define STATUS_HIBERNATION_FAILURE ((NTSTATUS) 0xC0000411L) -#endif - -#ifndef STATUS_DELAY_LOAD_FAILED -# define STATUS_DELAY_LOAD_FAILED ((NTSTATUS) 0xC0000412L) -#endif - -#ifndef STATUS_AUTHENTICATION_FIREWALL_FAILED -# define STATUS_AUTHENTICATION_FIREWALL_FAILED ((NTSTATUS) 0xC0000413L) -#endif - -#ifndef STATUS_VDM_DISALLOWED -# define STATUS_VDM_DISALLOWED ((NTSTATUS) 0xC0000414L) -#endif - -#ifndef STATUS_HUNG_DISPLAY_DRIVER_THREAD -# define STATUS_HUNG_DISPLAY_DRIVER_THREAD ((NTSTATUS) 0xC0000415L) -#endif - -#ifndef STATUS_INSUFFICIENT_RESOURCE_FOR_SPECIFIED_SHARED_SECTION_SIZE -# define STATUS_INSUFFICIENT_RESOURCE_FOR_SPECIFIED_SHARED_SECTION_SIZE ((NTSTATUS) 0xC0000416L) -#endif - -#ifndef STATUS_INVALID_CRUNTIME_PARAMETER -# define STATUS_INVALID_CRUNTIME_PARAMETER ((NTSTATUS) 0xC0000417L) -#endif - -#ifndef STATUS_NTLM_BLOCKED -# define STATUS_NTLM_BLOCKED ((NTSTATUS) 0xC0000418L) -#endif - -#ifndef STATUS_DS_SRC_SID_EXISTS_IN_FOREST -# define STATUS_DS_SRC_SID_EXISTS_IN_FOREST ((NTSTATUS) 0xC0000419L) -#endif - -#ifndef STATUS_DS_DOMAIN_NAME_EXISTS_IN_FOREST -# define STATUS_DS_DOMAIN_NAME_EXISTS_IN_FOREST ((NTSTATUS) 0xC000041AL) -#endif - -#ifndef STATUS_DS_FLAT_NAME_EXISTS_IN_FOREST -# define STATUS_DS_FLAT_NAME_EXISTS_IN_FOREST ((NTSTATUS) 0xC000041BL) -#endif - -#ifndef STATUS_INVALID_USER_PRINCIPAL_NAME -# define STATUS_INVALID_USER_PRINCIPAL_NAME ((NTSTATUS) 0xC000041CL) -#endif - -#ifndef STATUS_FATAL_USER_CALLBACK_EXCEPTION -# define STATUS_FATAL_USER_CALLBACK_EXCEPTION ((NTSTATUS) 0xC000041DL) -#endif - -#ifndef STATUS_ASSERTION_FAILURE -# define STATUS_ASSERTION_FAILURE ((NTSTATUS) 0xC0000420L) -#endif - -#ifndef STATUS_VERIFIER_STOP -# define STATUS_VERIFIER_STOP ((NTSTATUS) 0xC0000421L) -#endif - -#ifndef STATUS_CALLBACK_POP_STACK -# define STATUS_CALLBACK_POP_STACK ((NTSTATUS) 0xC0000423L) -#endif - -#ifndef STATUS_INCOMPATIBLE_DRIVER_BLOCKED -# define STATUS_INCOMPATIBLE_DRIVER_BLOCKED ((NTSTATUS) 0xC0000424L) -#endif - -#ifndef STATUS_HIVE_UNLOADED -# define STATUS_HIVE_UNLOADED ((NTSTATUS) 0xC0000425L) -#endif - -#ifndef STATUS_COMPRESSION_DISABLED -# define STATUS_COMPRESSION_DISABLED ((NTSTATUS) 0xC0000426L) -#endif - -#ifndef STATUS_FILE_SYSTEM_LIMITATION -# define STATUS_FILE_SYSTEM_LIMITATION ((NTSTATUS) 0xC0000427L) -#endif - -#ifndef STATUS_INVALID_IMAGE_HASH -# define STATUS_INVALID_IMAGE_HASH ((NTSTATUS) 0xC0000428L) -#endif - -#ifndef STATUS_NOT_CAPABLE -# define STATUS_NOT_CAPABLE ((NTSTATUS) 0xC0000429L) -#endif - -#ifndef STATUS_REQUEST_OUT_OF_SEQUENCE -# define STATUS_REQUEST_OUT_OF_SEQUENCE ((NTSTATUS) 0xC000042AL) -#endif - -#ifndef STATUS_IMPLEMENTATION_LIMIT -# define STATUS_IMPLEMENTATION_LIMIT ((NTSTATUS) 0xC000042BL) -#endif - -#ifndef STATUS_ELEVATION_REQUIRED -# define STATUS_ELEVATION_REQUIRED ((NTSTATUS) 0xC000042CL) -#endif - -#ifndef STATUS_NO_SECURITY_CONTEXT -# define STATUS_NO_SECURITY_CONTEXT ((NTSTATUS) 0xC000042DL) -#endif - -#ifndef STATUS_PKU2U_CERT_FAILURE -# define STATUS_PKU2U_CERT_FAILURE ((NTSTATUS) 0xC000042FL) -#endif - -#ifndef STATUS_BEYOND_VDL -# define STATUS_BEYOND_VDL ((NTSTATUS) 0xC0000432L) -#endif - -#ifndef STATUS_ENCOUNTERED_WRITE_IN_PROGRESS -# define STATUS_ENCOUNTERED_WRITE_IN_PROGRESS ((NTSTATUS) 0xC0000433L) -#endif - -#ifndef STATUS_PTE_CHANGED -# define STATUS_PTE_CHANGED ((NTSTATUS) 0xC0000434L) -#endif - -#ifndef STATUS_PURGE_FAILED -# define STATUS_PURGE_FAILED ((NTSTATUS) 0xC0000435L) -#endif - -#ifndef STATUS_CRED_REQUIRES_CONFIRMATION -# define STATUS_CRED_REQUIRES_CONFIRMATION ((NTSTATUS) 0xC0000440L) -#endif - -#ifndef STATUS_CS_ENCRYPTION_INVALID_SERVER_RESPONSE -# define STATUS_CS_ENCRYPTION_INVALID_SERVER_RESPONSE ((NTSTATUS) 0xC0000441L) -#endif - -#ifndef STATUS_CS_ENCRYPTION_UNSUPPORTED_SERVER -# define STATUS_CS_ENCRYPTION_UNSUPPORTED_SERVER ((NTSTATUS) 0xC0000442L) -#endif - -#ifndef STATUS_CS_ENCRYPTION_EXISTING_ENCRYPTED_FILE -# define STATUS_CS_ENCRYPTION_EXISTING_ENCRYPTED_FILE ((NTSTATUS) 0xC0000443L) -#endif - -#ifndef STATUS_CS_ENCRYPTION_NEW_ENCRYPTED_FILE -# define STATUS_CS_ENCRYPTION_NEW_ENCRYPTED_FILE ((NTSTATUS) 0xC0000444L) -#endif - -#ifndef STATUS_CS_ENCRYPTION_FILE_NOT_CSE -# define STATUS_CS_ENCRYPTION_FILE_NOT_CSE ((NTSTATUS) 0xC0000445L) -#endif - -#ifndef STATUS_INVALID_LABEL -# define STATUS_INVALID_LABEL ((NTSTATUS) 0xC0000446L) -#endif - -#ifndef STATUS_DRIVER_PROCESS_TERMINATED -# define STATUS_DRIVER_PROCESS_TERMINATED ((NTSTATUS) 0xC0000450L) -#endif - -#ifndef STATUS_AMBIGUOUS_SYSTEM_DEVICE -# define STATUS_AMBIGUOUS_SYSTEM_DEVICE ((NTSTATUS) 0xC0000451L) -#endif - -#ifndef STATUS_SYSTEM_DEVICE_NOT_FOUND -# define STATUS_SYSTEM_DEVICE_NOT_FOUND ((NTSTATUS) 0xC0000452L) -#endif - -#ifndef STATUS_RESTART_BOOT_APPLICATION -# define STATUS_RESTART_BOOT_APPLICATION ((NTSTATUS) 0xC0000453L) -#endif - -#ifndef STATUS_INSUFFICIENT_NVRAM_RESOURCES -# define STATUS_INSUFFICIENT_NVRAM_RESOURCES ((NTSTATUS) 0xC0000454L) -#endif - -#ifndef STATUS_INVALID_TASK_NAME -# define STATUS_INVALID_TASK_NAME ((NTSTATUS) 0xC0000500L) -#endif - -#ifndef STATUS_INVALID_TASK_INDEX -# define STATUS_INVALID_TASK_INDEX ((NTSTATUS) 0xC0000501L) -#endif - -#ifndef STATUS_THREAD_ALREADY_IN_TASK -# define STATUS_THREAD_ALREADY_IN_TASK ((NTSTATUS) 0xC0000502L) -#endif - -#ifndef STATUS_CALLBACK_BYPASS -# define STATUS_CALLBACK_BYPASS ((NTSTATUS) 0xC0000503L) -#endif - -#ifndef STATUS_FAIL_FAST_EXCEPTION -# define STATUS_FAIL_FAST_EXCEPTION ((NTSTATUS) 0xC0000602L) -#endif - -#ifndef STATUS_IMAGE_CERT_REVOKED -# define STATUS_IMAGE_CERT_REVOKED ((NTSTATUS) 0xC0000603L) -#endif - -#ifndef STATUS_PORT_CLOSED -# define STATUS_PORT_CLOSED ((NTSTATUS) 0xC0000700L) -#endif - -#ifndef STATUS_MESSAGE_LOST -# define STATUS_MESSAGE_LOST ((NTSTATUS) 0xC0000701L) -#endif - -#ifndef STATUS_INVALID_MESSAGE -# define STATUS_INVALID_MESSAGE ((NTSTATUS) 0xC0000702L) -#endif - -#ifndef STATUS_REQUEST_CANCELED -# define STATUS_REQUEST_CANCELED ((NTSTATUS) 0xC0000703L) -#endif - -#ifndef STATUS_RECURSIVE_DISPATCH -# define STATUS_RECURSIVE_DISPATCH ((NTSTATUS) 0xC0000704L) -#endif - -#ifndef STATUS_LPC_RECEIVE_BUFFER_EXPECTED -# define STATUS_LPC_RECEIVE_BUFFER_EXPECTED ((NTSTATUS) 0xC0000705L) -#endif - -#ifndef STATUS_LPC_INVALID_CONNECTION_USAGE -# define STATUS_LPC_INVALID_CONNECTION_USAGE ((NTSTATUS) 0xC0000706L) -#endif - -#ifndef STATUS_LPC_REQUESTS_NOT_ALLOWED -# define STATUS_LPC_REQUESTS_NOT_ALLOWED ((NTSTATUS) 0xC0000707L) -#endif - -#ifndef STATUS_RESOURCE_IN_USE -# define STATUS_RESOURCE_IN_USE ((NTSTATUS) 0xC0000708L) -#endif - -#ifndef STATUS_HARDWARE_MEMORY_ERROR -# define STATUS_HARDWARE_MEMORY_ERROR ((NTSTATUS) 0xC0000709L) -#endif - -#ifndef STATUS_THREADPOOL_HANDLE_EXCEPTION -# define STATUS_THREADPOOL_HANDLE_EXCEPTION ((NTSTATUS) 0xC000070AL) -#endif - -#ifndef STATUS_THREADPOOL_SET_EVENT_ON_COMPLETION_FAILED -# define STATUS_THREADPOOL_SET_EVENT_ON_COMPLETION_FAILED ((NTSTATUS) 0xC000070BL) -#endif - -#ifndef STATUS_THREADPOOL_RELEASE_SEMAPHORE_ON_COMPLETION_FAILED -# define STATUS_THREADPOOL_RELEASE_SEMAPHORE_ON_COMPLETION_FAILED ((NTSTATUS) 0xC000070CL) -#endif - -#ifndef STATUS_THREADPOOL_RELEASE_MUTEX_ON_COMPLETION_FAILED -# define STATUS_THREADPOOL_RELEASE_MUTEX_ON_COMPLETION_FAILED ((NTSTATUS) 0xC000070DL) -#endif - -#ifndef STATUS_THREADPOOL_FREE_LIBRARY_ON_COMPLETION_FAILED -# define STATUS_THREADPOOL_FREE_LIBRARY_ON_COMPLETION_FAILED ((NTSTATUS) 0xC000070EL) -#endif - -#ifndef STATUS_THREADPOOL_RELEASED_DURING_OPERATION -# define STATUS_THREADPOOL_RELEASED_DURING_OPERATION ((NTSTATUS) 0xC000070FL) -#endif - -#ifndef STATUS_CALLBACK_RETURNED_WHILE_IMPERSONATING -# define STATUS_CALLBACK_RETURNED_WHILE_IMPERSONATING ((NTSTATUS) 0xC0000710L) -#endif - -#ifndef STATUS_APC_RETURNED_WHILE_IMPERSONATING -# define STATUS_APC_RETURNED_WHILE_IMPERSONATING ((NTSTATUS) 0xC0000711L) -#endif - -#ifndef STATUS_PROCESS_IS_PROTECTED -# define STATUS_PROCESS_IS_PROTECTED ((NTSTATUS) 0xC0000712L) -#endif - -#ifndef STATUS_MCA_EXCEPTION -# define STATUS_MCA_EXCEPTION ((NTSTATUS) 0xC0000713L) -#endif - -#ifndef STATUS_CERTIFICATE_MAPPING_NOT_UNIQUE -# define STATUS_CERTIFICATE_MAPPING_NOT_UNIQUE ((NTSTATUS) 0xC0000714L) -#endif - -#ifndef STATUS_SYMLINK_CLASS_DISABLED -# define STATUS_SYMLINK_CLASS_DISABLED ((NTSTATUS) 0xC0000715L) -#endif - -#ifndef STATUS_INVALID_IDN_NORMALIZATION -# define STATUS_INVALID_IDN_NORMALIZATION ((NTSTATUS) 0xC0000716L) -#endif - -#ifndef STATUS_NO_UNICODE_TRANSLATION -# define STATUS_NO_UNICODE_TRANSLATION ((NTSTATUS) 0xC0000717L) -#endif - -#ifndef STATUS_ALREADY_REGISTERED -# define STATUS_ALREADY_REGISTERED ((NTSTATUS) 0xC0000718L) -#endif - -#ifndef STATUS_CONTEXT_MISMATCH -# define STATUS_CONTEXT_MISMATCH ((NTSTATUS) 0xC0000719L) -#endif - -#ifndef STATUS_PORT_ALREADY_HAS_COMPLETION_LIST -# define STATUS_PORT_ALREADY_HAS_COMPLETION_LIST ((NTSTATUS) 0xC000071AL) -#endif - -#ifndef STATUS_CALLBACK_RETURNED_THREAD_PRIORITY -# define STATUS_CALLBACK_RETURNED_THREAD_PRIORITY ((NTSTATUS) 0xC000071BL) -#endif - -#ifndef STATUS_INVALID_THREAD -# define STATUS_INVALID_THREAD ((NTSTATUS) 0xC000071CL) -#endif - -#ifndef STATUS_CALLBACK_RETURNED_TRANSACTION -# define STATUS_CALLBACK_RETURNED_TRANSACTION ((NTSTATUS) 0xC000071DL) -#endif - -#ifndef STATUS_CALLBACK_RETURNED_LDR_LOCK -# define STATUS_CALLBACK_RETURNED_LDR_LOCK ((NTSTATUS) 0xC000071EL) -#endif - -#ifndef STATUS_CALLBACK_RETURNED_LANG -# define STATUS_CALLBACK_RETURNED_LANG ((NTSTATUS) 0xC000071FL) -#endif - -#ifndef STATUS_CALLBACK_RETURNED_PRI_BACK -# define STATUS_CALLBACK_RETURNED_PRI_BACK ((NTSTATUS) 0xC0000720L) -#endif - -#ifndef STATUS_CALLBACK_RETURNED_THREAD_AFFINITY -# define STATUS_CALLBACK_RETURNED_THREAD_AFFINITY ((NTSTATUS) 0xC0000721L) -#endif - -#ifndef STATUS_DISK_REPAIR_DISABLED -# define STATUS_DISK_REPAIR_DISABLED ((NTSTATUS) 0xC0000800L) -#endif - -#ifndef STATUS_DS_DOMAIN_RENAME_IN_PROGRESS -# define STATUS_DS_DOMAIN_RENAME_IN_PROGRESS ((NTSTATUS) 0xC0000801L) -#endif - -#ifndef STATUS_DISK_QUOTA_EXCEEDED -# define STATUS_DISK_QUOTA_EXCEEDED ((NTSTATUS) 0xC0000802L) -#endif - -#ifndef STATUS_DATA_LOST_REPAIR -# define STATUS_DATA_LOST_REPAIR ((NTSTATUS) 0x80000803L) -#endif - -#ifndef STATUS_CONTENT_BLOCKED -# define STATUS_CONTENT_BLOCKED ((NTSTATUS) 0xC0000804L) -#endif - -#ifndef STATUS_BAD_CLUSTERS -# define STATUS_BAD_CLUSTERS ((NTSTATUS) 0xC0000805L) -#endif - -#ifndef STATUS_VOLUME_DIRTY -# define STATUS_VOLUME_DIRTY ((NTSTATUS) 0xC0000806L) -#endif - -#ifndef STATUS_FILE_CHECKED_OUT -# define STATUS_FILE_CHECKED_OUT ((NTSTATUS) 0xC0000901L) -#endif - -#ifndef STATUS_CHECKOUT_REQUIRED -# define STATUS_CHECKOUT_REQUIRED ((NTSTATUS) 0xC0000902L) -#endif - -#ifndef STATUS_BAD_FILE_TYPE -# define STATUS_BAD_FILE_TYPE ((NTSTATUS) 0xC0000903L) -#endif - -#ifndef STATUS_FILE_TOO_LARGE -# define STATUS_FILE_TOO_LARGE ((NTSTATUS) 0xC0000904L) -#endif - -#ifndef STATUS_FORMS_AUTH_REQUIRED -# define STATUS_FORMS_AUTH_REQUIRED ((NTSTATUS) 0xC0000905L) -#endif - -#ifndef STATUS_VIRUS_INFECTED -# define STATUS_VIRUS_INFECTED ((NTSTATUS) 0xC0000906L) -#endif - -#ifndef STATUS_VIRUS_DELETED -# define STATUS_VIRUS_DELETED ((NTSTATUS) 0xC0000907L) -#endif - -#ifndef STATUS_BAD_MCFG_TABLE -# define STATUS_BAD_MCFG_TABLE ((NTSTATUS) 0xC0000908L) -#endif - -#ifndef STATUS_CANNOT_BREAK_OPLOCK -# define STATUS_CANNOT_BREAK_OPLOCK ((NTSTATUS) 0xC0000909L) -#endif - -#ifndef STATUS_WOW_ASSERTION -# define STATUS_WOW_ASSERTION ((NTSTATUS) 0xC0009898L) -#endif - -#ifndef STATUS_INVALID_SIGNATURE -# define STATUS_INVALID_SIGNATURE ((NTSTATUS) 0xC000A000L) -#endif - -#ifndef STATUS_HMAC_NOT_SUPPORTED -# define STATUS_HMAC_NOT_SUPPORTED ((NTSTATUS) 0xC000A001L) -#endif - -#ifndef STATUS_AUTH_TAG_MISMATCH -# define STATUS_AUTH_TAG_MISMATCH ((NTSTATUS) 0xC000A002L) -#endif - -#ifndef STATUS_IPSEC_QUEUE_OVERFLOW -# define STATUS_IPSEC_QUEUE_OVERFLOW ((NTSTATUS) 0xC000A010L) -#endif - -#ifndef STATUS_ND_QUEUE_OVERFLOW -# define STATUS_ND_QUEUE_OVERFLOW ((NTSTATUS) 0xC000A011L) -#endif - -#ifndef STATUS_HOPLIMIT_EXCEEDED -# define STATUS_HOPLIMIT_EXCEEDED ((NTSTATUS) 0xC000A012L) -#endif - -#ifndef STATUS_PROTOCOL_NOT_SUPPORTED -# define STATUS_PROTOCOL_NOT_SUPPORTED ((NTSTATUS) 0xC000A013L) -#endif - -#ifndef STATUS_FASTPATH_REJECTED -# define STATUS_FASTPATH_REJECTED ((NTSTATUS) 0xC000A014L) -#endif - -#ifndef STATUS_LOST_WRITEBEHIND_DATA_NETWORK_DISCONNECTED -# define STATUS_LOST_WRITEBEHIND_DATA_NETWORK_DISCONNECTED ((NTSTATUS) 0xC000A080L) -#endif - -#ifndef STATUS_LOST_WRITEBEHIND_DATA_NETWORK_SERVER_ERROR -# define STATUS_LOST_WRITEBEHIND_DATA_NETWORK_SERVER_ERROR ((NTSTATUS) 0xC000A081L) -#endif - -#ifndef STATUS_LOST_WRITEBEHIND_DATA_LOCAL_DISK_ERROR -# define STATUS_LOST_WRITEBEHIND_DATA_LOCAL_DISK_ERROR ((NTSTATUS) 0xC000A082L) -#endif - -#ifndef STATUS_XML_PARSE_ERROR -# define STATUS_XML_PARSE_ERROR ((NTSTATUS) 0xC000A083L) -#endif - -#ifndef STATUS_XMLDSIG_ERROR -# define STATUS_XMLDSIG_ERROR ((NTSTATUS) 0xC000A084L) -#endif - -#ifndef STATUS_WRONG_COMPARTMENT -# define STATUS_WRONG_COMPARTMENT ((NTSTATUS) 0xC000A085L) -#endif - -#ifndef STATUS_AUTHIP_FAILURE -# define STATUS_AUTHIP_FAILURE ((NTSTATUS) 0xC000A086L) -#endif - -#ifndef STATUS_DS_OID_MAPPED_GROUP_CANT_HAVE_MEMBERS -# define STATUS_DS_OID_MAPPED_GROUP_CANT_HAVE_MEMBERS ((NTSTATUS) 0xC000A087L) -#endif - -#ifndef STATUS_DS_OID_NOT_FOUND -# define STATUS_DS_OID_NOT_FOUND ((NTSTATUS) 0xC000A088L) -#endif - -#ifndef STATUS_HASH_NOT_SUPPORTED -# define STATUS_HASH_NOT_SUPPORTED ((NTSTATUS) 0xC000A100L) -#endif - -#ifndef STATUS_HASH_NOT_PRESENT -# define STATUS_HASH_NOT_PRESENT ((NTSTATUS) 0xC000A101L) -#endif - -/* This is not the NTSTATUS_FROM_WIN32 that the DDK provides, because the */ -/* DDK got it wrong! */ -#ifdef NTSTATUS_FROM_WIN32 -# undef NTSTATUS_FROM_WIN32 -#endif -#define NTSTATUS_FROM_WIN32(error) ((NTSTATUS) (error) <= 0 ? \ - ((NTSTATUS) (error)) : ((NTSTATUS) (((error) & 0x0000FFFF) | \ - (FACILITY_NTWIN32 << 16) | ERROR_SEVERITY_WARNING))) - -#ifndef JOB_OBJECT_LIMIT_PROCESS_MEMORY -# define JOB_OBJECT_LIMIT_PROCESS_MEMORY 0x00000100 -#endif -#ifndef JOB_OBJECT_LIMIT_JOB_MEMORY -# define JOB_OBJECT_LIMIT_JOB_MEMORY 0x00000200 -#endif -#ifndef JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION -# define JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION 0x00000400 -#endif -#ifndef JOB_OBJECT_LIMIT_BREAKAWAY_OK -# define JOB_OBJECT_LIMIT_BREAKAWAY_OK 0x00000800 -#endif -#ifndef JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK -# define JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK 0x00001000 -#endif -#ifndef JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE -# define JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE 0x00002000 -#endif - -/* from winternl.h */ -typedef struct _UNICODE_STRING { - USHORT Length; - USHORT MaximumLength; - PWSTR Buffer; -} UNICODE_STRING, *PUNICODE_STRING; - -typedef const UNICODE_STRING *PCUNICODE_STRING; - -/* from ntifs.h */ -#ifndef DEVICE_TYPE -# define DEVICE_TYPE DWORD -#endif - -/* MinGW already has a definition for REPARSE_DATA_BUFFER, but mingw-w64 does - * not. - */ -#if defined(_MSC_VER) || defined(__MINGW64_VERSION_MAJOR) - typedef struct _REPARSE_DATA_BUFFER { - ULONG ReparseTag; - USHORT ReparseDataLength; - USHORT Reserved; - union { - struct { - USHORT SubstituteNameOffset; - USHORT SubstituteNameLength; - USHORT PrintNameOffset; - USHORT PrintNameLength; - ULONG Flags; - WCHAR PathBuffer[1]; - } SymbolicLinkReparseBuffer; - struct { - USHORT SubstituteNameOffset; - USHORT SubstituteNameLength; - USHORT PrintNameOffset; - USHORT PrintNameLength; - WCHAR PathBuffer[1]; - } MountPointReparseBuffer; - struct { - UCHAR DataBuffer[1]; - } GenericReparseBuffer; - }; - } REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER; -#endif - -typedef struct _IO_STATUS_BLOCK { - union { - NTSTATUS Status; - PVOID Pointer; - }; - ULONG_PTR Information; -} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK; - -typedef enum _FILE_INFORMATION_CLASS { - FileDirectoryInformation = 1, - FileFullDirectoryInformation, - FileBothDirectoryInformation, - FileBasicInformation, - FileStandardInformation, - FileInternalInformation, - FileEaInformation, - FileAccessInformation, - FileNameInformation, - FileRenameInformation, - FileLinkInformation, - FileNamesInformation, - FileDispositionInformation, - FilePositionInformation, - FileFullEaInformation, - FileModeInformation, - FileAlignmentInformation, - FileAllInformation, - FileAllocationInformation, - FileEndOfFileInformation, - FileAlternateNameInformation, - FileStreamInformation, - FilePipeInformation, - FilePipeLocalInformation, - FilePipeRemoteInformation, - FileMailslotQueryInformation, - FileMailslotSetInformation, - FileCompressionInformation, - FileObjectIdInformation, - FileCompletionInformation, - FileMoveClusterInformation, - FileQuotaInformation, - FileReparsePointInformation, - FileNetworkOpenInformation, - FileAttributeTagInformation, - FileTrackingInformation, - FileIdBothDirectoryInformation, - FileIdFullDirectoryInformation, - FileValidDataLengthInformation, - FileShortNameInformation, - FileIoCompletionNotificationInformation, - FileIoStatusBlockRangeInformation, - FileIoPriorityHintInformation, - FileSfioReserveInformation, - FileSfioVolumeInformation, - FileHardLinkInformation, - FileProcessIdsUsingFileInformation, - FileNormalizedNameInformation, - FileNetworkPhysicalNameInformation, - FileIdGlobalTxDirectoryInformation, - FileIsRemoteDeviceInformation, - FileAttributeCacheInformation, - FileNumaNodeInformation, - FileStandardLinkInformation, - FileRemoteProtocolInformation, - FileMaximumInformation -} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS; - -typedef struct _FILE_DIRECTORY_INFORMATION { - ULONG NextEntryOffset; - ULONG FileIndex; - LARGE_INTEGER CreationTime; - LARGE_INTEGER LastAccessTime; - LARGE_INTEGER LastWriteTime; - LARGE_INTEGER ChangeTime; - LARGE_INTEGER EndOfFile; - LARGE_INTEGER AllocationSize; - ULONG FileAttributes; - ULONG FileNameLength; - WCHAR FileName[1]; -} FILE_DIRECTORY_INFORMATION, *PFILE_DIRECTORY_INFORMATION; - -typedef struct _FILE_BOTH_DIR_INFORMATION { - ULONG NextEntryOffset; - ULONG FileIndex; - LARGE_INTEGER CreationTime; - LARGE_INTEGER LastAccessTime; - LARGE_INTEGER LastWriteTime; - LARGE_INTEGER ChangeTime; - LARGE_INTEGER EndOfFile; - LARGE_INTEGER AllocationSize; - ULONG FileAttributes; - ULONG FileNameLength; - ULONG EaSize; - CCHAR ShortNameLength; - WCHAR ShortName[12]; - WCHAR FileName[1]; -} FILE_BOTH_DIR_INFORMATION, *PFILE_BOTH_DIR_INFORMATION; - -typedef struct _FILE_BASIC_INFORMATION { - LARGE_INTEGER CreationTime; - LARGE_INTEGER LastAccessTime; - LARGE_INTEGER LastWriteTime; - LARGE_INTEGER ChangeTime; - DWORD FileAttributes; -} FILE_BASIC_INFORMATION, *PFILE_BASIC_INFORMATION; - -typedef struct _FILE_STANDARD_INFORMATION { - LARGE_INTEGER AllocationSize; - LARGE_INTEGER EndOfFile; - ULONG NumberOfLinks; - BOOLEAN DeletePending; - BOOLEAN Directory; -} FILE_STANDARD_INFORMATION, *PFILE_STANDARD_INFORMATION; - -typedef struct _FILE_INTERNAL_INFORMATION { - LARGE_INTEGER IndexNumber; -} FILE_INTERNAL_INFORMATION, *PFILE_INTERNAL_INFORMATION; - -typedef struct _FILE_EA_INFORMATION { - ULONG EaSize; -} FILE_EA_INFORMATION, *PFILE_EA_INFORMATION; - -typedef struct _FILE_ACCESS_INFORMATION { - ACCESS_MASK AccessFlags; -} FILE_ACCESS_INFORMATION, *PFILE_ACCESS_INFORMATION; - -typedef struct _FILE_POSITION_INFORMATION { - LARGE_INTEGER CurrentByteOffset; -} FILE_POSITION_INFORMATION, *PFILE_POSITION_INFORMATION; - -typedef struct _FILE_MODE_INFORMATION { - ULONG Mode; -} FILE_MODE_INFORMATION, *PFILE_MODE_INFORMATION; - -typedef struct _FILE_ALIGNMENT_INFORMATION { - ULONG AlignmentRequirement; -} FILE_ALIGNMENT_INFORMATION, *PFILE_ALIGNMENT_INFORMATION; - -typedef struct _FILE_NAME_INFORMATION { - ULONG FileNameLength; - WCHAR FileName[1]; -} FILE_NAME_INFORMATION, *PFILE_NAME_INFORMATION; - -typedef struct _FILE_END_OF_FILE_INFORMATION { - LARGE_INTEGER EndOfFile; -} FILE_END_OF_FILE_INFORMATION, *PFILE_END_OF_FILE_INFORMATION; - -typedef struct _FILE_ALL_INFORMATION { - FILE_BASIC_INFORMATION BasicInformation; - FILE_STANDARD_INFORMATION StandardInformation; - FILE_INTERNAL_INFORMATION InternalInformation; - FILE_EA_INFORMATION EaInformation; - FILE_ACCESS_INFORMATION AccessInformation; - FILE_POSITION_INFORMATION PositionInformation; - FILE_MODE_INFORMATION ModeInformation; - FILE_ALIGNMENT_INFORMATION AlignmentInformation; - FILE_NAME_INFORMATION NameInformation; -} FILE_ALL_INFORMATION, *PFILE_ALL_INFORMATION; - -typedef struct _FILE_DISPOSITION_INFORMATION { - BOOLEAN DeleteFile; -} FILE_DISPOSITION_INFORMATION, *PFILE_DISPOSITION_INFORMATION; - -typedef struct _FILE_PIPE_LOCAL_INFORMATION { - ULONG NamedPipeType; - ULONG NamedPipeConfiguration; - ULONG MaximumInstances; - ULONG CurrentInstances; - ULONG InboundQuota; - ULONG ReadDataAvailable; - ULONG OutboundQuota; - ULONG WriteQuotaAvailable; - ULONG NamedPipeState; - ULONG NamedPipeEnd; -} FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION; - -#define FILE_SYNCHRONOUS_IO_ALERT 0x00000010 -#define FILE_SYNCHRONOUS_IO_NONALERT 0x00000020 - -typedef enum _FS_INFORMATION_CLASS { - FileFsVolumeInformation = 1, - FileFsLabelInformation = 2, - FileFsSizeInformation = 3, - FileFsDeviceInformation = 4, - FileFsAttributeInformation = 5, - FileFsControlInformation = 6, - FileFsFullSizeInformation = 7, - FileFsObjectIdInformation = 8, - FileFsDriverPathInformation = 9, - FileFsVolumeFlagsInformation = 10, - FileFsSectorSizeInformation = 11 -} FS_INFORMATION_CLASS, *PFS_INFORMATION_CLASS; - -typedef struct _FILE_FS_VOLUME_INFORMATION { - LARGE_INTEGER VolumeCreationTime; - ULONG VolumeSerialNumber; - ULONG VolumeLabelLength; - BOOLEAN SupportsObjects; - WCHAR VolumeLabel[1]; -} FILE_FS_VOLUME_INFORMATION, *PFILE_FS_VOLUME_INFORMATION; - -typedef struct _FILE_FS_LABEL_INFORMATION { - ULONG VolumeLabelLength; - WCHAR VolumeLabel[1]; -} FILE_FS_LABEL_INFORMATION, *PFILE_FS_LABEL_INFORMATION; - -typedef struct _FILE_FS_SIZE_INFORMATION { - LARGE_INTEGER TotalAllocationUnits; - LARGE_INTEGER AvailableAllocationUnits; - ULONG SectorsPerAllocationUnit; - ULONG BytesPerSector; -} FILE_FS_SIZE_INFORMATION, *PFILE_FS_SIZE_INFORMATION; - -typedef struct _FILE_FS_DEVICE_INFORMATION { - DEVICE_TYPE DeviceType; - ULONG Characteristics; -} FILE_FS_DEVICE_INFORMATION, *PFILE_FS_DEVICE_INFORMATION; - -typedef struct _FILE_FS_ATTRIBUTE_INFORMATION { - ULONG FileSystemAttributes; - LONG MaximumComponentNameLength; - ULONG FileSystemNameLength; - WCHAR FileSystemName[1]; -} FILE_FS_ATTRIBUTE_INFORMATION, *PFILE_FS_ATTRIBUTE_INFORMATION; - -typedef struct _FILE_FS_CONTROL_INFORMATION { - LARGE_INTEGER FreeSpaceStartFiltering; - LARGE_INTEGER FreeSpaceThreshold; - LARGE_INTEGER FreeSpaceStopFiltering; - LARGE_INTEGER DefaultQuotaThreshold; - LARGE_INTEGER DefaultQuotaLimit; - ULONG FileSystemControlFlags; -} FILE_FS_CONTROL_INFORMATION, *PFILE_FS_CONTROL_INFORMATION; - -typedef struct _FILE_FS_FULL_SIZE_INFORMATION { - LARGE_INTEGER TotalAllocationUnits; - LARGE_INTEGER CallerAvailableAllocationUnits; - LARGE_INTEGER ActualAvailableAllocationUnits; - ULONG SectorsPerAllocationUnit; - ULONG BytesPerSector; -} FILE_FS_FULL_SIZE_INFORMATION, *PFILE_FS_FULL_SIZE_INFORMATION; - -typedef struct _FILE_FS_OBJECTID_INFORMATION { - UCHAR ObjectId[16]; - UCHAR ExtendedInfo[48]; -} FILE_FS_OBJECTID_INFORMATION, *PFILE_FS_OBJECTID_INFORMATION; - -typedef struct _FILE_FS_DRIVER_PATH_INFORMATION { - BOOLEAN DriverInPath; - ULONG DriverNameLength; - WCHAR DriverName[1]; -} FILE_FS_DRIVER_PATH_INFORMATION, *PFILE_FS_DRIVER_PATH_INFORMATION; - -typedef struct _FILE_FS_VOLUME_FLAGS_INFORMATION { - ULONG Flags; -} FILE_FS_VOLUME_FLAGS_INFORMATION, *PFILE_FS_VOLUME_FLAGS_INFORMATION; - -typedef struct _FILE_FS_SECTOR_SIZE_INFORMATION { - ULONG LogicalBytesPerSector; - ULONG PhysicalBytesPerSectorForAtomicity; - ULONG PhysicalBytesPerSectorForPerformance; - ULONG FileSystemEffectivePhysicalBytesPerSectorForAtomicity; - ULONG Flags; - ULONG ByteOffsetForSectorAlignment; - ULONG ByteOffsetForPartitionAlignment; -} FILE_FS_SECTOR_SIZE_INFORMATION, *PFILE_FS_SECTOR_SIZE_INFORMATION; - -typedef struct _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION { - LARGE_INTEGER IdleTime; - LARGE_INTEGER KernelTime; - LARGE_INTEGER UserTime; - LARGE_INTEGER DpcTime; - LARGE_INTEGER InterruptTime; - ULONG InterruptCount; -} SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION, *PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION; - -#ifndef SystemProcessorPerformanceInformation -# define SystemProcessorPerformanceInformation 8 -#endif - -#ifndef FILE_DEVICE_FILE_SYSTEM -# define FILE_DEVICE_FILE_SYSTEM 0x00000009 -#endif - -#ifndef FILE_DEVICE_NETWORK -# define FILE_DEVICE_NETWORK 0x00000012 -#endif - -#ifndef METHOD_BUFFERED -# define METHOD_BUFFERED 0 -#endif - -#ifndef METHOD_IN_DIRECT -# define METHOD_IN_DIRECT 1 -#endif - -#ifndef METHOD_OUT_DIRECT -# define METHOD_OUT_DIRECT 2 -#endif - -#ifndef METHOD_NEITHER -#define METHOD_NEITHER 3 -#endif - -#ifndef METHOD_DIRECT_TO_HARDWARE -# define METHOD_DIRECT_TO_HARDWARE METHOD_IN_DIRECT -#endif - -#ifndef METHOD_DIRECT_FROM_HARDWARE -# define METHOD_DIRECT_FROM_HARDWARE METHOD_OUT_DIRECT -#endif - -#ifndef FILE_ANY_ACCESS -# define FILE_ANY_ACCESS 0 -#endif - -#ifndef FILE_SPECIAL_ACCESS -# define FILE_SPECIAL_ACCESS (FILE_ANY_ACCESS) -#endif - -#ifndef FILE_READ_ACCESS -# define FILE_READ_ACCESS 0x0001 -#endif - -#ifndef FILE_WRITE_ACCESS -# define FILE_WRITE_ACCESS 0x0002 -#endif - -#ifndef CTL_CODE -# define CTL_CODE(device_type, function, method, access) \ - (((device_type) << 16) | ((access) << 14) | ((function) << 2) | (method)) -#endif - -#ifndef FSCTL_SET_REPARSE_POINT -# define FSCTL_SET_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, \ - 41, \ - METHOD_BUFFERED, \ - FILE_SPECIAL_ACCESS) -#endif - -#ifndef FSCTL_GET_REPARSE_POINT -# define FSCTL_GET_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, \ - 42, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) -#endif - -#ifndef FSCTL_DELETE_REPARSE_POINT -# define FSCTL_DELETE_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, \ - 43, \ - METHOD_BUFFERED, \ - FILE_SPECIAL_ACCESS) -#endif - -#ifndef IO_REPARSE_TAG_SYMLINK -# define IO_REPARSE_TAG_SYMLINK (0xA000000CL) -#endif - -typedef VOID (NTAPI *PIO_APC_ROUTINE) - (PVOID ApcContext, - PIO_STATUS_BLOCK IoStatusBlock, - ULONG Reserved); - -typedef ULONG (NTAPI *sRtlNtStatusToDosError) - (NTSTATUS Status); - -typedef NTSTATUS (NTAPI *sNtDeviceIoControlFile) - (HANDLE FileHandle, - HANDLE Event, - PIO_APC_ROUTINE ApcRoutine, - PVOID ApcContext, - PIO_STATUS_BLOCK IoStatusBlock, - ULONG IoControlCode, - PVOID InputBuffer, - ULONG InputBufferLength, - PVOID OutputBuffer, - ULONG OutputBufferLength); - -typedef NTSTATUS (NTAPI *sNtQueryInformationFile) - (HANDLE FileHandle, - PIO_STATUS_BLOCK IoStatusBlock, - PVOID FileInformation, - ULONG Length, - FILE_INFORMATION_CLASS FileInformationClass); - -typedef NTSTATUS (NTAPI *sNtSetInformationFile) - (HANDLE FileHandle, - PIO_STATUS_BLOCK IoStatusBlock, - PVOID FileInformation, - ULONG Length, - FILE_INFORMATION_CLASS FileInformationClass); - -typedef NTSTATUS (NTAPI *sNtQueryVolumeInformationFile) - (HANDLE FileHandle, - PIO_STATUS_BLOCK IoStatusBlock, - PVOID FsInformation, - ULONG Length, - FS_INFORMATION_CLASS FsInformationClass); - -typedef NTSTATUS (NTAPI *sNtQuerySystemInformation) - (UINT SystemInformationClass, - PVOID SystemInformation, - ULONG SystemInformationLength, - PULONG ReturnLength); - -typedef NTSTATUS (NTAPI *sNtQueryDirectoryFile) - (HANDLE FileHandle, - HANDLE Event, - PIO_APC_ROUTINE ApcRoutine, - PVOID ApcContext, - PIO_STATUS_BLOCK IoStatusBlock, - PVOID FileInformation, - ULONG Length, - FILE_INFORMATION_CLASS FileInformationClass, - BOOLEAN ReturnSingleEntry, - PUNICODE_STRING FileName, - BOOLEAN RestartScan - ); - -/* - * Kernel32 headers - */ -#ifndef FILE_SKIP_COMPLETION_PORT_ON_SUCCESS -# define FILE_SKIP_COMPLETION_PORT_ON_SUCCESS 0x1 -#endif - -#ifndef FILE_SKIP_SET_EVENT_ON_HANDLE -# define FILE_SKIP_SET_EVENT_ON_HANDLE 0x2 -#endif - -#ifndef SYMBOLIC_LINK_FLAG_DIRECTORY -# define SYMBOLIC_LINK_FLAG_DIRECTORY 0x1 -#endif - -#if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR) - typedef struct _OVERLAPPED_ENTRY { - ULONG_PTR lpCompletionKey; - LPOVERLAPPED lpOverlapped; - ULONG_PTR Internal; - DWORD dwNumberOfBytesTransferred; - } OVERLAPPED_ENTRY, *LPOVERLAPPED_ENTRY; -#endif - -/* from wincon.h */ -#ifndef ENABLE_INSERT_MODE -# define ENABLE_INSERT_MODE 0x20 -#endif - -#ifndef ENABLE_QUICK_EDIT_MODE -# define ENABLE_QUICK_EDIT_MODE 0x40 -#endif - -#ifndef ENABLE_EXTENDED_FLAGS -# define ENABLE_EXTENDED_FLAGS 0x80 -#endif - -/* from winerror.h */ -#ifndef ERROR_ELEVATION_REQUIRED -# define ERROR_ELEVATION_REQUIRED 740 -#endif - -#ifndef ERROR_SYMLINK_NOT_SUPPORTED -# define ERROR_SYMLINK_NOT_SUPPORTED 1464 -#endif - -#ifndef ERROR_MUI_FILE_NOT_FOUND -# define ERROR_MUI_FILE_NOT_FOUND 15100 -#endif - -#ifndef ERROR_MUI_INVALID_FILE -# define ERROR_MUI_INVALID_FILE 15101 -#endif - -#ifndef ERROR_MUI_INVALID_RC_CONFIG -# define ERROR_MUI_INVALID_RC_CONFIG 15102 -#endif - -#ifndef ERROR_MUI_INVALID_LOCALE_NAME -# define ERROR_MUI_INVALID_LOCALE_NAME 15103 -#endif - -#ifndef ERROR_MUI_INVALID_ULTIMATEFALLBACK_NAME -# define ERROR_MUI_INVALID_ULTIMATEFALLBACK_NAME 15104 -#endif - -#ifndef ERROR_MUI_FILE_NOT_LOADED -# define ERROR_MUI_FILE_NOT_LOADED 15105 -#endif - -typedef BOOL (WINAPI *sGetQueuedCompletionStatusEx) - (HANDLE CompletionPort, - LPOVERLAPPED_ENTRY lpCompletionPortEntries, - ULONG ulCount, - PULONG ulNumEntriesRemoved, - DWORD dwMilliseconds, - BOOL fAlertable); - -typedef BOOL (WINAPI* sSetFileCompletionNotificationModes) - (HANDLE FileHandle, - UCHAR Flags); - -typedef BOOLEAN (WINAPI* sCreateSymbolicLinkW) - (LPCWSTR lpSymlinkFileName, - LPCWSTR lpTargetFileName, - DWORD dwFlags); - -typedef BOOL (WINAPI* sCancelIoEx) - (HANDLE hFile, - LPOVERLAPPED lpOverlapped); - -typedef VOID (WINAPI* sInitializeConditionVariable) - (PCONDITION_VARIABLE ConditionVariable); - -typedef BOOL (WINAPI* sSleepConditionVariableCS) - (PCONDITION_VARIABLE ConditionVariable, - PCRITICAL_SECTION CriticalSection, - DWORD dwMilliseconds); - -typedef BOOL (WINAPI* sSleepConditionVariableSRW) - (PCONDITION_VARIABLE ConditionVariable, - PSRWLOCK SRWLock, - DWORD dwMilliseconds, - ULONG Flags); - -typedef VOID (WINAPI* sWakeAllConditionVariable) - (PCONDITION_VARIABLE ConditionVariable); - -typedef VOID (WINAPI* sWakeConditionVariable) - (PCONDITION_VARIABLE ConditionVariable); - -typedef BOOL (WINAPI* sCancelSynchronousIo) - (HANDLE hThread); - -typedef DWORD (WINAPI* sGetFinalPathNameByHandleW) - (HANDLE hFile, - LPWSTR lpszFilePath, - DWORD cchFilePath, - DWORD dwFlags); - -/* from powerbase.h */ -#ifndef DEVICE_NOTIFY_CALLBACK -# define DEVICE_NOTIFY_CALLBACK 2 -#endif - -#ifndef PBT_APMRESUMEAUTOMATIC -# define PBT_APMRESUMEAUTOMATIC 18 -#endif - -#ifndef PBT_APMRESUMESUSPEND -# define PBT_APMRESUMESUSPEND 7 -#endif - -typedef ULONG CALLBACK _DEVICE_NOTIFY_CALLBACK_ROUTINE( - PVOID Context, - ULONG Type, - PVOID Setting -); -typedef _DEVICE_NOTIFY_CALLBACK_ROUTINE* _PDEVICE_NOTIFY_CALLBACK_ROUTINE; - -typedef struct _DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS { - _PDEVICE_NOTIFY_CALLBACK_ROUTINE Callback; - PVOID Context; -} _DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS, *_PDEVICE_NOTIFY_SUBSCRIBE_PARAMETERS; - -typedef PVOID _HPOWERNOTIFY; -typedef _HPOWERNOTIFY *_PHPOWERNOTIFY; - -typedef DWORD (WINAPI *sPowerRegisterSuspendResumeNotification) - (DWORD Flags, - HANDLE Recipient, - _PHPOWERNOTIFY RegistrationHandle); - - -/* Ntdll function pointers */ -extern sRtlNtStatusToDosError pRtlNtStatusToDosError; -extern sNtDeviceIoControlFile pNtDeviceIoControlFile; -extern sNtQueryInformationFile pNtQueryInformationFile; -extern sNtSetInformationFile pNtSetInformationFile; -extern sNtQueryVolumeInformationFile pNtQueryVolumeInformationFile; -extern sNtQueryDirectoryFile pNtQueryDirectoryFile; -extern sNtQuerySystemInformation pNtQuerySystemInformation; - - -/* Kernel32 function pointers */ -extern sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx; -extern sSetFileCompletionNotificationModes pSetFileCompletionNotificationModes; -extern sCreateSymbolicLinkW pCreateSymbolicLinkW; -extern sCancelIoEx pCancelIoEx; -extern sInitializeConditionVariable pInitializeConditionVariable; -extern sSleepConditionVariableCS pSleepConditionVariableCS; -extern sSleepConditionVariableSRW pSleepConditionVariableSRW; -extern sWakeAllConditionVariable pWakeAllConditionVariable; -extern sWakeConditionVariable pWakeConditionVariable; -extern sCancelSynchronousIo pCancelSynchronousIo; -extern sGetFinalPathNameByHandleW pGetFinalPathNameByHandleW; - - -/* Powrprof.dll function pointer */ -extern sPowerRegisterSuspendResumeNotification pPowerRegisterSuspendResumeNotification; - -#endif /* UV_WIN_WINAPI_H_ */ diff --git a/vendor/libuv/src/win/winsock.c b/vendor/libuv/src/win/winsock.c deleted file mode 100644 index d2e667e9f..000000000 --- a/vendor/libuv/src/win/winsock.c +++ /dev/null @@ -1,561 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include -#include - -#include "uv.h" -#include "internal.h" - - -/* Whether there are any non-IFS LSPs stacked on TCP */ -int uv_tcp_non_ifs_lsp_ipv4; -int uv_tcp_non_ifs_lsp_ipv6; - -/* Ip address used to bind to any port at any interface */ -struct sockaddr_in uv_addr_ip4_any_; -struct sockaddr_in6 uv_addr_ip6_any_; - - -/* - * Retrieves the pointer to a winsock extension function. - */ -static BOOL uv_get_extension_function(SOCKET socket, GUID guid, - void **target) { - int result; - DWORD bytes; - - result = WSAIoctl(socket, - SIO_GET_EXTENSION_FUNCTION_POINTER, - &guid, - sizeof(guid), - (void*)target, - sizeof(*target), - &bytes, - NULL, - NULL); - - if (result == SOCKET_ERROR) { - *target = NULL; - return FALSE; - } else { - return TRUE; - } -} - - -BOOL uv_get_acceptex_function(SOCKET socket, LPFN_ACCEPTEX* target) { - const GUID wsaid_acceptex = WSAID_ACCEPTEX; - return uv_get_extension_function(socket, wsaid_acceptex, (void**)target); -} - - -BOOL uv_get_connectex_function(SOCKET socket, LPFN_CONNECTEX* target) { - const GUID wsaid_connectex = WSAID_CONNECTEX; - return uv_get_extension_function(socket, wsaid_connectex, (void**)target); -} - - -static int error_means_no_support(DWORD error) { - return error == WSAEPROTONOSUPPORT || error == WSAESOCKTNOSUPPORT || - error == WSAEPFNOSUPPORT || error == WSAEAFNOSUPPORT; -} - - -void uv_winsock_init() { - WSADATA wsa_data; - int errorno; - SOCKET dummy; - WSAPROTOCOL_INFOW protocol_info; - int opt_len; - - /* Initialize winsock */ - errorno = WSAStartup(MAKEWORD(2, 2), &wsa_data); - if (errorno != 0) { - uv_fatal_error(errorno, "WSAStartup"); - } - - /* Set implicit binding address used by connectEx */ - if (uv_ip4_addr("0.0.0.0", 0, &uv_addr_ip4_any_)) { - abort(); - } - - if (uv_ip6_addr("::", 0, &uv_addr_ip6_any_)) { - abort(); - } - - /* Detect non-IFS LSPs */ - dummy = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); - - if (dummy != INVALID_SOCKET) { - opt_len = (int) sizeof protocol_info; - if (getsockopt(dummy, - SOL_SOCKET, - SO_PROTOCOL_INFOW, - (char*) &protocol_info, - &opt_len) == SOCKET_ERROR) - uv_fatal_error(WSAGetLastError(), "getsockopt"); - - if (!(protocol_info.dwServiceFlags1 & XP1_IFS_HANDLES)) - uv_tcp_non_ifs_lsp_ipv4 = 1; - - if (closesocket(dummy) == SOCKET_ERROR) - uv_fatal_error(WSAGetLastError(), "closesocket"); - - } else if (!error_means_no_support(WSAGetLastError())) { - /* Any error other than "socket type not supported" is fatal. */ - uv_fatal_error(WSAGetLastError(), "socket"); - } - - /* Detect IPV6 support and non-IFS LSPs */ - dummy = socket(AF_INET6, SOCK_STREAM, IPPROTO_IP); - - if (dummy != INVALID_SOCKET) { - opt_len = (int) sizeof protocol_info; - if (getsockopt(dummy, - SOL_SOCKET, - SO_PROTOCOL_INFOW, - (char*) &protocol_info, - &opt_len) == SOCKET_ERROR) - uv_fatal_error(WSAGetLastError(), "getsockopt"); - - if (!(protocol_info.dwServiceFlags1 & XP1_IFS_HANDLES)) - uv_tcp_non_ifs_lsp_ipv6 = 1; - - if (closesocket(dummy) == SOCKET_ERROR) - uv_fatal_error(WSAGetLastError(), "closesocket"); - - } else if (!error_means_no_support(WSAGetLastError())) { - /* Any error other than "socket type not supported" is fatal. */ - uv_fatal_error(WSAGetLastError(), "socket"); - } -} - - -int uv_ntstatus_to_winsock_error(NTSTATUS status) { - switch (status) { - case STATUS_SUCCESS: - return ERROR_SUCCESS; - - case STATUS_PENDING: - return ERROR_IO_PENDING; - - case STATUS_INVALID_HANDLE: - case STATUS_OBJECT_TYPE_MISMATCH: - return WSAENOTSOCK; - - case STATUS_INSUFFICIENT_RESOURCES: - case STATUS_PAGEFILE_QUOTA: - case STATUS_COMMITMENT_LIMIT: - case STATUS_WORKING_SET_QUOTA: - case STATUS_NO_MEMORY: - case STATUS_QUOTA_EXCEEDED: - case STATUS_TOO_MANY_PAGING_FILES: - case STATUS_REMOTE_RESOURCES: - return WSAENOBUFS; - - case STATUS_TOO_MANY_ADDRESSES: - case STATUS_SHARING_VIOLATION: - case STATUS_ADDRESS_ALREADY_EXISTS: - return WSAEADDRINUSE; - - case STATUS_LINK_TIMEOUT: - case STATUS_IO_TIMEOUT: - case STATUS_TIMEOUT: - return WSAETIMEDOUT; - - case STATUS_GRACEFUL_DISCONNECT: - return WSAEDISCON; - - case STATUS_REMOTE_DISCONNECT: - case STATUS_CONNECTION_RESET: - case STATUS_LINK_FAILED: - case STATUS_CONNECTION_DISCONNECTED: - case STATUS_PORT_UNREACHABLE: - case STATUS_HOPLIMIT_EXCEEDED: - return WSAECONNRESET; - - case STATUS_LOCAL_DISCONNECT: - case STATUS_TRANSACTION_ABORTED: - case STATUS_CONNECTION_ABORTED: - return WSAECONNABORTED; - - case STATUS_BAD_NETWORK_PATH: - case STATUS_NETWORK_UNREACHABLE: - case STATUS_PROTOCOL_UNREACHABLE: - return WSAENETUNREACH; - - case STATUS_HOST_UNREACHABLE: - return WSAEHOSTUNREACH; - - case STATUS_CANCELLED: - case STATUS_REQUEST_ABORTED: - return WSAEINTR; - - case STATUS_BUFFER_OVERFLOW: - case STATUS_INVALID_BUFFER_SIZE: - return WSAEMSGSIZE; - - case STATUS_BUFFER_TOO_SMALL: - case STATUS_ACCESS_VIOLATION: - return WSAEFAULT; - - case STATUS_DEVICE_NOT_READY: - case STATUS_REQUEST_NOT_ACCEPTED: - return WSAEWOULDBLOCK; - - case STATUS_INVALID_NETWORK_RESPONSE: - case STATUS_NETWORK_BUSY: - case STATUS_NO_SUCH_DEVICE: - case STATUS_NO_SUCH_FILE: - case STATUS_OBJECT_PATH_NOT_FOUND: - case STATUS_OBJECT_NAME_NOT_FOUND: - case STATUS_UNEXPECTED_NETWORK_ERROR: - return WSAENETDOWN; - - case STATUS_INVALID_CONNECTION: - return WSAENOTCONN; - - case STATUS_REMOTE_NOT_LISTENING: - case STATUS_CONNECTION_REFUSED: - return WSAECONNREFUSED; - - case STATUS_PIPE_DISCONNECTED: - return WSAESHUTDOWN; - - case STATUS_CONFLICTING_ADDRESSES: - case STATUS_INVALID_ADDRESS: - case STATUS_INVALID_ADDRESS_COMPONENT: - return WSAEADDRNOTAVAIL; - - case STATUS_NOT_SUPPORTED: - case STATUS_NOT_IMPLEMENTED: - return WSAEOPNOTSUPP; - - case STATUS_ACCESS_DENIED: - return WSAEACCES; - - default: - if ((status & (FACILITY_NTWIN32 << 16)) == (FACILITY_NTWIN32 << 16) && - (status & (ERROR_SEVERITY_ERROR | ERROR_SEVERITY_WARNING))) { - /* It's a windows error that has been previously mapped to an */ - /* ntstatus code. */ - return (DWORD) (status & 0xffff); - } else { - /* The default fallback for unmappable ntstatus codes. */ - return WSAEINVAL; - } - } -} - - -/* - * This function provides a workaround for a bug in the winsock implementation - * of WSARecv. The problem is that when SetFileCompletionNotificationModes is - * used to avoid IOCP notifications of completed reads, WSARecv does not - * reliably indicate whether we can expect a completion package to be posted - * when the receive buffer is smaller than the received datagram. - * - * However it is desirable to use SetFileCompletionNotificationModes because - * it yields a massive performance increase. - * - * This function provides a workaround for that bug, but it only works for the - * specific case that we need it for. E.g. it assumes that the "avoid iocp" - * bit has been set, and supports only overlapped operation. It also requires - * the user to use the default msafd driver, doesn't work when other LSPs are - * stacked on top of it. - */ -int WSAAPI uv_wsarecv_workaround(SOCKET socket, WSABUF* buffers, - DWORD buffer_count, DWORD* bytes, DWORD* flags, WSAOVERLAPPED *overlapped, - LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_routine) { - NTSTATUS status; - void* apc_context; - IO_STATUS_BLOCK* iosb = (IO_STATUS_BLOCK*) &overlapped->Internal; - AFD_RECV_INFO info; - DWORD error; - - if (overlapped == NULL || completion_routine != NULL) { - WSASetLastError(WSAEINVAL); - return SOCKET_ERROR; - } - - info.BufferArray = buffers; - info.BufferCount = buffer_count; - info.AfdFlags = AFD_OVERLAPPED; - info.TdiFlags = TDI_RECEIVE_NORMAL; - - if (*flags & MSG_PEEK) { - info.TdiFlags |= TDI_RECEIVE_PEEK; - } - - if (*flags & MSG_PARTIAL) { - info.TdiFlags |= TDI_RECEIVE_PARTIAL; - } - - if (!((intptr_t) overlapped->hEvent & 1)) { - apc_context = (void*) overlapped; - } else { - apc_context = NULL; - } - - iosb->Status = STATUS_PENDING; - iosb->Pointer = 0; - - status = pNtDeviceIoControlFile((HANDLE) socket, - overlapped->hEvent, - NULL, - apc_context, - iosb, - IOCTL_AFD_RECEIVE, - &info, - sizeof(info), - NULL, - 0); - - *flags = 0; - *bytes = (DWORD) iosb->Information; - - switch (status) { - case STATUS_SUCCESS: - error = ERROR_SUCCESS; - break; - - case STATUS_PENDING: - error = WSA_IO_PENDING; - break; - - case STATUS_BUFFER_OVERFLOW: - error = WSAEMSGSIZE; - break; - - case STATUS_RECEIVE_EXPEDITED: - error = ERROR_SUCCESS; - *flags = MSG_OOB; - break; - - case STATUS_RECEIVE_PARTIAL_EXPEDITED: - error = ERROR_SUCCESS; - *flags = MSG_PARTIAL | MSG_OOB; - break; - - case STATUS_RECEIVE_PARTIAL: - error = ERROR_SUCCESS; - *flags = MSG_PARTIAL; - break; - - default: - error = uv_ntstatus_to_winsock_error(status); - break; - } - - WSASetLastError(error); - - if (error == ERROR_SUCCESS) { - return 0; - } else { - return SOCKET_ERROR; - } -} - - -/* See description of uv_wsarecv_workaround. */ -int WSAAPI uv_wsarecvfrom_workaround(SOCKET socket, WSABUF* buffers, - DWORD buffer_count, DWORD* bytes, DWORD* flags, struct sockaddr* addr, - int* addr_len, WSAOVERLAPPED *overlapped, - LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_routine) { - NTSTATUS status; - void* apc_context; - IO_STATUS_BLOCK* iosb = (IO_STATUS_BLOCK*) &overlapped->Internal; - AFD_RECV_DATAGRAM_INFO info; - DWORD error; - - if (overlapped == NULL || addr == NULL || addr_len == NULL || - completion_routine != NULL) { - WSASetLastError(WSAEINVAL); - return SOCKET_ERROR; - } - - info.BufferArray = buffers; - info.BufferCount = buffer_count; - info.AfdFlags = AFD_OVERLAPPED; - info.TdiFlags = TDI_RECEIVE_NORMAL; - info.Address = addr; - info.AddressLength = addr_len; - - if (*flags & MSG_PEEK) { - info.TdiFlags |= TDI_RECEIVE_PEEK; - } - - if (*flags & MSG_PARTIAL) { - info.TdiFlags |= TDI_RECEIVE_PARTIAL; - } - - if (!((intptr_t) overlapped->hEvent & 1)) { - apc_context = (void*) overlapped; - } else { - apc_context = NULL; - } - - iosb->Status = STATUS_PENDING; - iosb->Pointer = 0; - - status = pNtDeviceIoControlFile((HANDLE) socket, - overlapped->hEvent, - NULL, - apc_context, - iosb, - IOCTL_AFD_RECEIVE_DATAGRAM, - &info, - sizeof(info), - NULL, - 0); - - *flags = 0; - *bytes = (DWORD) iosb->Information; - - switch (status) { - case STATUS_SUCCESS: - error = ERROR_SUCCESS; - break; - - case STATUS_PENDING: - error = WSA_IO_PENDING; - break; - - case STATUS_BUFFER_OVERFLOW: - error = WSAEMSGSIZE; - break; - - case STATUS_RECEIVE_EXPEDITED: - error = ERROR_SUCCESS; - *flags = MSG_OOB; - break; - - case STATUS_RECEIVE_PARTIAL_EXPEDITED: - error = ERROR_SUCCESS; - *flags = MSG_PARTIAL | MSG_OOB; - break; - - case STATUS_RECEIVE_PARTIAL: - error = ERROR_SUCCESS; - *flags = MSG_PARTIAL; - break; - - default: - error = uv_ntstatus_to_winsock_error(status); - break; - } - - WSASetLastError(error); - - if (error == ERROR_SUCCESS) { - return 0; - } else { - return SOCKET_ERROR; - } -} - - -int WSAAPI uv_msafd_poll(SOCKET socket, AFD_POLL_INFO* info_in, - AFD_POLL_INFO* info_out, OVERLAPPED* overlapped) { - IO_STATUS_BLOCK iosb; - IO_STATUS_BLOCK* iosb_ptr; - HANDLE event = NULL; - void* apc_context; - NTSTATUS status; - DWORD error; - - if (overlapped != NULL) { - /* Overlapped operation. */ - iosb_ptr = (IO_STATUS_BLOCK*) &overlapped->Internal; - event = overlapped->hEvent; - - /* Do not report iocp completion if hEvent is tagged. */ - if ((uintptr_t) event & 1) { - event = (HANDLE)((uintptr_t) event & ~(uintptr_t) 1); - apc_context = NULL; - } else { - apc_context = overlapped; - } - - } else { - /* Blocking operation. */ - iosb_ptr = &iosb; - event = CreateEvent(NULL, FALSE, FALSE, NULL); - if (event == NULL) { - return SOCKET_ERROR; - } - apc_context = NULL; - } - - iosb_ptr->Status = STATUS_PENDING; - status = pNtDeviceIoControlFile((HANDLE) socket, - event, - NULL, - apc_context, - iosb_ptr, - IOCTL_AFD_POLL, - info_in, - sizeof *info_in, - info_out, - sizeof *info_out); - - if (overlapped == NULL) { - /* If this is a blocking operation, wait for the event to become */ - /* signaled, and then grab the real status from the io status block. */ - if (status == STATUS_PENDING) { - DWORD r = WaitForSingleObject(event, INFINITE); - - if (r == WAIT_FAILED) { - DWORD saved_error = GetLastError(); - CloseHandle(event); - WSASetLastError(saved_error); - return SOCKET_ERROR; - } - - status = iosb.Status; - } - - CloseHandle(event); - } - - switch (status) { - case STATUS_SUCCESS: - error = ERROR_SUCCESS; - break; - - case STATUS_PENDING: - error = WSA_IO_PENDING; - break; - - default: - error = uv_ntstatus_to_winsock_error(status); - break; - } - - WSASetLastError(error); - - if (error == ERROR_SUCCESS) { - return 0; - } else { - return SOCKET_ERROR; - } -} diff --git a/vendor/libuv/src/win/winsock.h b/vendor/libuv/src/win/winsock.h deleted file mode 100644 index 7c007ab49..000000000 --- a/vendor/libuv/src/win/winsock.h +++ /dev/null @@ -1,190 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef UV_WIN_WINSOCK_H_ -#define UV_WIN_WINSOCK_H_ - -#include -#include -#include -#include -#include - -#include "winapi.h" - - -/* - * MinGW is missing these too - */ -#ifndef SO_UPDATE_CONNECT_CONTEXT -# define SO_UPDATE_CONNECT_CONTEXT 0x7010 -#endif - -#ifndef TCP_KEEPALIVE -# define TCP_KEEPALIVE 3 -#endif - -#ifndef IPV6_V6ONLY -# define IPV6_V6ONLY 27 -#endif - -#ifndef IPV6_HOPLIMIT -# define IPV6_HOPLIMIT 21 -#endif - -#ifndef SIO_BASE_HANDLE -# define SIO_BASE_HANDLE 0x48000022 -#endif - -/* - * TDI defines that are only in the DDK. - * We only need receive flags so far. - */ -#ifndef TDI_RECEIVE_NORMAL - #define TDI_RECEIVE_BROADCAST 0x00000004 - #define TDI_RECEIVE_MULTICAST 0x00000008 - #define TDI_RECEIVE_PARTIAL 0x00000010 - #define TDI_RECEIVE_NORMAL 0x00000020 - #define TDI_RECEIVE_EXPEDITED 0x00000040 - #define TDI_RECEIVE_PEEK 0x00000080 - #define TDI_RECEIVE_NO_RESPONSE_EXP 0x00000100 - #define TDI_RECEIVE_COPY_LOOKAHEAD 0x00000200 - #define TDI_RECEIVE_ENTIRE_MESSAGE 0x00000400 - #define TDI_RECEIVE_AT_DISPATCH_LEVEL 0x00000800 - #define TDI_RECEIVE_CONTROL_INFO 0x00001000 - #define TDI_RECEIVE_FORCE_INDICATION 0x00002000 - #define TDI_RECEIVE_NO_PUSH 0x00004000 -#endif - -/* - * The "Auxiliary Function Driver" is the windows kernel-mode driver that does - * TCP, UDP etc. Winsock is just a layer that dispatches requests to it. - * Having these definitions allows us to bypass winsock and make an AFD kernel - * call directly, avoiding a bug in winsock's recvfrom implementation. - */ - -#define AFD_NO_FAST_IO 0x00000001 -#define AFD_OVERLAPPED 0x00000002 -#define AFD_IMMEDIATE 0x00000004 - -#define AFD_POLL_RECEIVE_BIT 0 -#define AFD_POLL_RECEIVE (1 << AFD_POLL_RECEIVE_BIT) -#define AFD_POLL_RECEIVE_EXPEDITED_BIT 1 -#define AFD_POLL_RECEIVE_EXPEDITED (1 << AFD_POLL_RECEIVE_EXPEDITED_BIT) -#define AFD_POLL_SEND_BIT 2 -#define AFD_POLL_SEND (1 << AFD_POLL_SEND_BIT) -#define AFD_POLL_DISCONNECT_BIT 3 -#define AFD_POLL_DISCONNECT (1 << AFD_POLL_DISCONNECT_BIT) -#define AFD_POLL_ABORT_BIT 4 -#define AFD_POLL_ABORT (1 << AFD_POLL_ABORT_BIT) -#define AFD_POLL_LOCAL_CLOSE_BIT 5 -#define AFD_POLL_LOCAL_CLOSE (1 << AFD_POLL_LOCAL_CLOSE_BIT) -#define AFD_POLL_CONNECT_BIT 6 -#define AFD_POLL_CONNECT (1 << AFD_POLL_CONNECT_BIT) -#define AFD_POLL_ACCEPT_BIT 7 -#define AFD_POLL_ACCEPT (1 << AFD_POLL_ACCEPT_BIT) -#define AFD_POLL_CONNECT_FAIL_BIT 8 -#define AFD_POLL_CONNECT_FAIL (1 << AFD_POLL_CONNECT_FAIL_BIT) -#define AFD_POLL_QOS_BIT 9 -#define AFD_POLL_QOS (1 << AFD_POLL_QOS_BIT) -#define AFD_POLL_GROUP_QOS_BIT 10 -#define AFD_POLL_GROUP_QOS (1 << AFD_POLL_GROUP_QOS_BIT) - -#define AFD_NUM_POLL_EVENTS 11 -#define AFD_POLL_ALL ((1 << AFD_NUM_POLL_EVENTS) - 1) - -typedef struct _AFD_RECV_DATAGRAM_INFO { - LPWSABUF BufferArray; - ULONG BufferCount; - ULONG AfdFlags; - ULONG TdiFlags; - struct sockaddr* Address; - int* AddressLength; -} AFD_RECV_DATAGRAM_INFO, *PAFD_RECV_DATAGRAM_INFO; - -typedef struct _AFD_RECV_INFO { - LPWSABUF BufferArray; - ULONG BufferCount; - ULONG AfdFlags; - ULONG TdiFlags; -} AFD_RECV_INFO, *PAFD_RECV_INFO; - - -#define _AFD_CONTROL_CODE(operation, method) \ - ((FSCTL_AFD_BASE) << 12 | (operation << 2) | method) - -#define FSCTL_AFD_BASE FILE_DEVICE_NETWORK - -#define AFD_RECEIVE 5 -#define AFD_RECEIVE_DATAGRAM 6 -#define AFD_POLL 9 - -#define IOCTL_AFD_RECEIVE \ - _AFD_CONTROL_CODE(AFD_RECEIVE, METHOD_NEITHER) - -#define IOCTL_AFD_RECEIVE_DATAGRAM \ - _AFD_CONTROL_CODE(AFD_RECEIVE_DATAGRAM, METHOD_NEITHER) - -#define IOCTL_AFD_POLL \ - _AFD_CONTROL_CODE(AFD_POLL, METHOD_BUFFERED) - -#if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR) -typedef struct _IP_ADAPTER_UNICAST_ADDRESS_XP { - /* FIXME: __C89_NAMELESS was removed */ - /* __C89_NAMELESS */ union { - ULONGLONG Alignment; - /* __C89_NAMELESS */ struct { - ULONG Length; - DWORD Flags; - }; - }; - struct _IP_ADAPTER_UNICAST_ADDRESS_XP *Next; - SOCKET_ADDRESS Address; - IP_PREFIX_ORIGIN PrefixOrigin; - IP_SUFFIX_ORIGIN SuffixOrigin; - IP_DAD_STATE DadState; - ULONG ValidLifetime; - ULONG PreferredLifetime; - ULONG LeaseLifetime; -} IP_ADAPTER_UNICAST_ADDRESS_XP,*PIP_ADAPTER_UNICAST_ADDRESS_XP; - -typedef struct _IP_ADAPTER_UNICAST_ADDRESS_LH { - union { - ULONGLONG Alignment; - struct { - ULONG Length; - DWORD Flags; - }; - }; - struct _IP_ADAPTER_UNICAST_ADDRESS_LH *Next; - SOCKET_ADDRESS Address; - IP_PREFIX_ORIGIN PrefixOrigin; - IP_SUFFIX_ORIGIN SuffixOrigin; - IP_DAD_STATE DadState; - ULONG ValidLifetime; - ULONG PreferredLifetime; - ULONG LeaseLifetime; - UINT8 OnLinkPrefixLength; -} IP_ADAPTER_UNICAST_ADDRESS_LH,*PIP_ADAPTER_UNICAST_ADDRESS_LH; - -#endif - -#endif /* UV_WIN_WINSOCK_H_ */ diff --git a/vendor/libuv/uv.gyp b/vendor/libuv/uv.gyp deleted file mode 100644 index 49d5d22f9..000000000 --- a/vendor/libuv/uv.gyp +++ /dev/null @@ -1,577 +0,0 @@ -{ - 'target_defaults': { - 'conditions': [ - ['OS != "win"', { - 'defines': [ - '_LARGEFILE_SOURCE', - '_FILE_OFFSET_BITS=64', - ], - 'conditions': [ - ['OS=="solaris"', { - 'cflags': [ '-pthreads' ], - }], - ['OS not in "solaris android os390"', { - 'cflags': [ '-pthread' ], - }], - ['OS in "os390"', { - 'defines': [ - '_UNIX03_THREADS', - '_UNIX03_SOURCE', - '_UNIX03_WITHDRAWN', - '_OPEN_SYS_IF_EXT', - '_OPEN_SYS_SOCK_IPV6', - '_OPEN_MSGQ_EXT', - '_XOPEN_SOURCE_EXTENDED', - '_ALL_SOURCE', - '_LARGE_TIME_API', - '_OPEN_SYS_FILE_EXT', - '_AE_BIMODAL', - 'PATH_MAX=255' - ], - 'cflags': [ '-qxplink' ], - 'ldflags': [ '-qxplink' ], - }] - ], - }], - ], - 'xcode_settings': { - 'GCC_SYMBOLS_PRIVATE_EXTERN': 'YES', # -fvisibility=hidden - 'WARNING_CFLAGS': [ '-Wall', '-Wextra', '-Wno-unused-parameter' ], - 'OTHER_CFLAGS': [ '-g', '--std=gnu89', '-pedantic' ], - } - }, - - 'targets': [ - { - 'target_name': 'libuv', - 'type': '<(uv_library)', - 'include_dirs': [ - 'include', - 'src/', - ], - 'direct_dependent_settings': { - 'include_dirs': [ 'include' ], - 'conditions': [ - ['OS != "win"', { - 'defines': [ - '_LARGEFILE_SOURCE', - '_FILE_OFFSET_BITS=64', - ], - }], - ['OS in "mac ios"', { - 'defines': [ '_DARWIN_USE_64_BIT_INODE=1' ], - }], - ['OS == "linux"', { - 'defines': [ '_POSIX_C_SOURCE=200112' ], - }], - ], - }, - 'sources': [ - 'common.gypi', - 'include/uv.h', - 'include/tree.h', - 'include/uv-errno.h', - 'include/uv-threadpool.h', - 'include/uv-version.h', - 'src/fs-poll.c', - 'src/heap-inl.h', - 'src/inet.c', - 'src/queue.h', - 'src/threadpool.c', - 'src/uv-common.c', - 'src/uv-common.h', - 'src/version.c' - ], - 'conditions': [ - [ 'OS=="win"', { - 'defines': [ - '_WIN32_WINNT=0x0600', - '_GNU_SOURCE', - ], - 'sources': [ - 'include/uv-win.h', - 'src/win/async.c', - 'src/win/atomicops-inl.h', - 'src/win/core.c', - 'src/win/detect-wakeup.c', - 'src/win/dl.c', - 'src/win/error.c', - 'src/win/fs.c', - 'src/win/fs-event.c', - 'src/win/getaddrinfo.c', - 'src/win/getnameinfo.c', - 'src/win/handle.c', - 'src/win/handle-inl.h', - 'src/win/internal.h', - 'src/win/loop-watcher.c', - 'src/win/pipe.c', - 'src/win/thread.c', - 'src/win/poll.c', - 'src/win/process.c', - 'src/win/process-stdio.c', - 'src/win/req.c', - 'src/win/req-inl.h', - 'src/win/signal.c', - 'src/win/snprintf.c', - 'src/win/stream.c', - 'src/win/stream-inl.h', - 'src/win/tcp.c', - 'src/win/tty.c', - 'src/win/timer.c', - 'src/win/udp.c', - 'src/win/util.c', - 'src/win/winapi.c', - 'src/win/winapi.h', - 'src/win/winsock.c', - 'src/win/winsock.h', - ], - 'link_settings': { - 'libraries': [ - '-ladvapi32', - '-liphlpapi', - '-lpsapi', - '-lshell32', - '-luser32', - '-luserenv', - '-lws2_32' - ], - }, - }, { # Not Windows i.e. POSIX - 'sources': [ - 'include/uv-unix.h', - 'include/uv-linux.h', - 'include/uv-sunos.h', - 'include/uv-darwin.h', - 'include/uv-bsd.h', - 'include/uv-aix.h', - 'src/unix/async.c', - 'src/unix/atomic-ops.h', - 'src/unix/core.c', - 'src/unix/dl.c', - 'src/unix/fs.c', - 'src/unix/getaddrinfo.c', - 'src/unix/getnameinfo.c', - 'src/unix/internal.h', - 'src/unix/loop.c', - 'src/unix/loop-watcher.c', - 'src/unix/pipe.c', - 'src/unix/poll.c', - 'src/unix/process.c', - 'src/unix/signal.c', - 'src/unix/spinlock.h', - 'src/unix/stream.c', - 'src/unix/tcp.c', - 'src/unix/thread.c', - 'src/unix/timer.c', - 'src/unix/tty.c', - 'src/unix/udp.c', - ], - 'link_settings': { - 'libraries': [ '-lm' ], - 'conditions': [ - ['OS=="solaris"', { - 'ldflags': [ '-pthreads' ], - }], - [ 'OS=="os390" and uv_library=="shared_library"', { - 'ldflags': [ '-Wl,DLL' ], - }], - ['OS != "solaris" and OS != "android" and OS != "os390"', { - 'ldflags': [ '-pthread' ], - }], - ], - }, - 'conditions': [ - ['uv_library=="shared_library"', { - 'conditions': [ - ['OS=="os390"', { - 'cflags': [ '-qexportall' ], - }, { - 'cflags': [ '-fPIC' ], - }], - ], - }], - ['uv_library=="shared_library" and OS!="mac" and OS!="os390"', { - # This will cause gyp to set soname - # Must correspond with UV_VERSION_MAJOR - # in include/uv-version.h - 'product_extension': 'so.1', - }], - ], - }], - [ 'OS in "linux mac ios android os390"', { - 'sources': [ 'src/unix/proctitle.c' ], - }], - [ 'OS != "os390"', { - 'cflags': [ - '-fvisibility=hidden', - '-g', - '--std=gnu89', - '-pedantic', - '-Wall', - '-Wextra', - '-Wno-unused-parameter', - ], - }], - [ 'OS in "mac ios"', { - 'sources': [ - 'src/unix/darwin.c', - 'src/unix/fsevents.c', - 'src/unix/darwin-proctitle.c', - 'src/unix/pthread-barrier.c' - ], - 'defines': [ - '_DARWIN_USE_64_BIT_INODE=1', - '_DARWIN_UNLIMITED_SELECT=1', - ] - }], - [ 'OS!="mac" and OS!="os390"', { - # Enable on all platforms except OS X. The antique gcc/clang that - # ships with Xcode emits waaaay too many false positives. - 'cflags': [ '-Wstrict-aliasing' ], - }], - [ 'OS=="linux"', { - 'defines': [ '_GNU_SOURCE' ], - 'sources': [ - 'src/unix/linux-core.c', - 'src/unix/linux-inotify.c', - 'src/unix/linux-syscalls.c', - 'src/unix/linux-syscalls.h', - ], - 'link_settings': { - 'libraries': [ '-ldl', '-lrt' ], - }, - }], - [ 'OS=="android"', { - 'sources': [ - 'src/unix/linux-core.c', - 'src/unix/linux-inotify.c', - 'src/unix/linux-syscalls.c', - 'src/unix/linux-syscalls.h', - 'src/unix/pthread-fixes.c', - 'src/unix/android-ifaddrs.c', - 'src/unix/pthread-barrier.c' - ], - 'link_settings': { - 'libraries': [ '-ldl' ], - }, - }], - [ 'OS=="solaris"', { - 'sources': [ 'src/unix/sunos.c' ], - 'defines': [ - '__EXTENSIONS__', - '_XOPEN_SOURCE=500', - ], - 'link_settings': { - 'libraries': [ - '-lkstat', - '-lnsl', - '-lsendfile', - '-lsocket', - ], - }, - }], - [ 'OS=="aix"', { - 'sources': [ 'src/unix/aix.c' ], - 'defines': [ - '_ALL_SOURCE', - '_XOPEN_SOURCE=500', - '_LINUX_SOURCE_COMPAT', - '_THREAD_SAFE', - 'HAVE_SYS_AHAFS_EVPRODS_H', - ], - 'link_settings': { - 'libraries': [ - '-lperfstat', - ], - }, - }], - [ 'OS=="freebsd" or OS=="dragonflybsd"', { - 'sources': [ 'src/unix/freebsd.c' ], - }], - [ 'OS=="openbsd"', { - 'sources': [ 'src/unix/openbsd.c' ], - }], - [ 'OS=="netbsd"', { - 'sources': [ 'src/unix/netbsd.c' ], - }], - [ 'OS in "freebsd dragonflybsd openbsd netbsd".split()', { - 'link_settings': { - 'libraries': [ '-lkvm' ], - }, - }], - [ 'OS in "ios mac freebsd dragonflybsd openbsd netbsd".split()', { - 'sources': [ 'src/unix/kqueue.c' ], - }], - ['uv_library=="shared_library"', { - 'defines': [ 'BUILDING_UV_SHARED=1' ] - }], - ['OS=="os390"', { - 'sources': [ - 'src/unix/pthread-fixes.c', - 'src/unix/pthread-barrier.c', - 'src/unix/os390.c', - 'src/unix/os390-syscalls.c' - ] - }], - ] - }, - - { - 'target_name': 'run-tests', - 'type': 'executable', - 'dependencies': [ 'libuv' ], - 'sources': [ - 'test/blackhole-server.c', - 'test/echo-server.c', - 'test/run-tests.c', - 'test/runner.c', - 'test/runner.h', - 'test/test-get-loadavg.c', - 'test/task.h', - 'test/test-active.c', - 'test/test-async.c', - 'test/test-async-null-cb.c', - 'test/test-callback-stack.c', - 'test/test-callback-order.c', - 'test/test-close-fd.c', - 'test/test-close-order.c', - 'test/test-connection-fail.c', - 'test/test-cwd-and-chdir.c', - 'test/test-default-loop-close.c', - 'test/test-delayed-accept.c', - 'test/test-eintr-handling.c', - 'test/test-error.c', - 'test/test-embed.c', - 'test/test-emfile.c', - 'test/test-fail-always.c', - 'test/test-fs.c', - 'test/test-fs-event.c', - 'test/test-get-currentexe.c', - 'test/test-get-memory.c', - 'test/test-get-passwd.c', - 'test/test-getaddrinfo.c', - 'test/test-getnameinfo.c', - 'test/test-getsockname.c', - 'test/test-handle-fileno.c', - 'test/test-homedir.c', - 'test/test-hrtime.c', - 'test/test-idle.c', - 'test/test-ip6-addr.c', - 'test/test-ipc.c', - 'test/test-ipc-send-recv.c', - 'test/test-list.h', - 'test/test-loop-handles.c', - 'test/test-loop-alive.c', - 'test/test-loop-close.c', - 'test/test-loop-stop.c', - 'test/test-loop-time.c', - 'test/test-loop-configure.c', - 'test/test-walk-handles.c', - 'test/test-watcher-cross-stop.c', - 'test/test-multiple-listen.c', - 'test/test-osx-select.c', - 'test/test-pass-always.c', - 'test/test-ping-pong.c', - 'test/test-pipe-bind-error.c', - 'test/test-pipe-connect-error.c', - 'test/test-pipe-connect-multiple.c', - 'test/test-pipe-connect-prepare.c', - 'test/test-pipe-getsockname.c', - 'test/test-pipe-pending-instances.c', - 'test/test-pipe-sendmsg.c', - 'test/test-pipe-server-close.c', - 'test/test-pipe-close-stdout-read-stdin.c', - 'test/test-pipe-set-non-blocking.c', - 'test/test-platform-output.c', - 'test/test-poll.c', - 'test/test-poll-close.c', - 'test/test-poll-close-doesnt-corrupt-stack.c', - 'test/test-poll-closesocket.c', - 'test/test-process-title.c', - 'test/test-queue-foreach-delete.c', - 'test/test-ref.c', - 'test/test-run-nowait.c', - 'test/test-run-once.c', - 'test/test-semaphore.c', - 'test/test-shutdown-close.c', - 'test/test-shutdown-eof.c', - 'test/test-shutdown-twice.c', - 'test/test-signal.c', - 'test/test-signal-multiple-loops.c', - 'test/test-socket-buffer-size.c', - 'test/test-spawn.c', - 'test/test-fs-poll.c', - 'test/test-stdio-over-pipes.c', - 'test/test-tcp-alloc-cb-fail.c', - 'test/test-tcp-bind-error.c', - 'test/test-tcp-bind6-error.c', - 'test/test-tcp-close.c', - 'test/test-tcp-close-accept.c', - 'test/test-tcp-close-while-connecting.c', - 'test/test-tcp-create-socket-early.c', - 'test/test-tcp-connect-error-after-write.c', - 'test/test-tcp-shutdown-after-write.c', - 'test/test-tcp-flags.c', - 'test/test-tcp-connect-error.c', - 'test/test-tcp-connect-timeout.c', - 'test/test-tcp-connect6-error.c', - 'test/test-tcp-open.c', - 'test/test-tcp-write-to-half-open-connection.c', - 'test/test-tcp-write-after-connect.c', - 'test/test-tcp-writealot.c', - 'test/test-tcp-write-fail.c', - 'test/test-tcp-try-write.c', - 'test/test-tcp-unexpected-read.c', - 'test/test-tcp-oob.c', - 'test/test-tcp-read-stop.c', - 'test/test-tcp-write-queue-order.c', - 'test/test-threadpool.c', - 'test/test-threadpool-cancel.c', - 'test/test-thread-equal.c', - 'test/test-tmpdir.c', - 'test/test-mutexes.c', - 'test/test-thread.c', - 'test/test-barrier.c', - 'test/test-condvar.c', - 'test/test-timer-again.c', - 'test/test-timer-from-check.c', - 'test/test-timer.c', - 'test/test-tty.c', - 'test/test-udp-alloc-cb-fail.c', - 'test/test-udp-bind.c', - 'test/test-udp-create-socket-early.c', - 'test/test-udp-dgram-too-big.c', - 'test/test-udp-ipv6.c', - 'test/test-udp-open.c', - 'test/test-udp-options.c', - 'test/test-udp-send-and-recv.c', - 'test/test-udp-send-immediate.c', - 'test/test-udp-send-unreachable.c', - 'test/test-udp-multicast-join.c', - 'test/test-udp-multicast-join6.c', - 'test/test-dlerror.c', - 'test/test-udp-multicast-ttl.c', - 'test/test-ip4-addr.c', - 'test/test-ip6-addr.c', - 'test/test-udp-multicast-interface.c', - 'test/test-udp-multicast-interface6.c', - 'test/test-udp-try-send.c', - ], - 'conditions': [ - [ 'OS=="win"', { - 'sources': [ - 'test/runner-win.c', - 'test/runner-win.h', - 'src/win/snprintf.c', - ], - 'libraries': [ '-lws2_32' ] - }, { # POSIX - 'sources': [ - 'test/runner-unix.c', - 'test/runner-unix.h', - ], - 'conditions': [ - [ 'OS != "os390"', { - 'defines': [ '_GNU_SOURCE' ], - 'cflags': [ '-Wno-long-long' ], - 'xcode_settings': { - 'WARNING_CFLAGS': [ '-Wno-long-long' ] - } - }], - ]}, - ], - [ 'OS in "mac dragonflybsd freebsd linux netbsd openbsd".split()', { - 'link_settings': { - 'libraries': [ '-lutil' ], - }, - }], - [ 'OS=="solaris"', { # make test-fs.c compile, needs _POSIX_C_SOURCE - 'defines': [ - '__EXTENSIONS__', - '_XOPEN_SOURCE=500', - ], - }], - [ 'OS=="aix"', { # make test-fs.c compile, needs _POSIX_C_SOURCE - 'defines': [ - '_ALL_SOURCE', - '_XOPEN_SOURCE=500', - ], - }], - ['uv_library=="shared_library"', { - 'defines': [ 'USING_UV_SHARED=1' ], - 'conditions': [ - [ 'OS == "os390"', { - 'cflags': [ '-Wc,DLL' ], - }], - ], - }], - ], - 'msvs-settings': { - 'VCLinkerTool': { - 'SubSystem': 1, # /subsystem:console - }, - }, - }, - - { - 'target_name': 'run-benchmarks', - 'type': 'executable', - 'dependencies': [ 'libuv' ], - 'sources': [ - 'test/benchmark-async.c', - 'test/benchmark-async-pummel.c', - 'test/benchmark-fs-stat.c', - 'test/benchmark-getaddrinfo.c', - 'test/benchmark-list.h', - 'test/benchmark-loop-count.c', - 'test/benchmark-million-async.c', - 'test/benchmark-million-timers.c', - 'test/benchmark-multi-accept.c', - 'test/benchmark-ping-pongs.c', - 'test/benchmark-pound.c', - 'test/benchmark-pump.c', - 'test/benchmark-sizes.c', - 'test/benchmark-spawn.c', - 'test/benchmark-thread.c', - 'test/benchmark-tcp-write-batch.c', - 'test/benchmark-udp-pummel.c', - 'test/dns-server.c', - 'test/echo-server.c', - 'test/blackhole-server.c', - 'test/run-benchmarks.c', - 'test/runner.c', - 'test/runner.h', - 'test/task.h', - ], - 'conditions': [ - [ 'OS=="win"', { - 'sources': [ - 'test/runner-win.c', - 'test/runner-win.h', - 'src/win/snprintf.c', - ], - 'libraries': [ '-lws2_32' ] - }, { # POSIX - 'defines': [ '_GNU_SOURCE' ], - 'sources': [ - 'test/runner-unix.c', - 'test/runner-unix.h', - ] - }], - ['uv_library=="shared_library"', { - 'defines': [ 'USING_UV_SHARED=1' ], - 'conditions': [ - [ 'OS == "os390"', { - 'cflags': [ '-Wc,DLL' ], - }], - ], - }], - ], - 'msvs-settings': { - 'VCLinkerTool': { - 'SubSystem': 1, # /subsystem:console - }, - }, - }, - ] -} diff --git a/vendor/libuv/vcbuild.bat b/vendor/libuv/vcbuild.bat deleted file mode 100644 index 91f45b721..000000000 --- a/vendor/libuv/vcbuild.bat +++ /dev/null @@ -1,158 +0,0 @@ -@echo off - -cd %~dp0 - -if /i "%1"=="help" goto help -if /i "%1"=="--help" goto help -if /i "%1"=="-help" goto help -if /i "%1"=="/help" goto help -if /i "%1"=="?" goto help -if /i "%1"=="-?" goto help -if /i "%1"=="--?" goto help -if /i "%1"=="/?" goto help - -@rem Process arguments. -set config= -set target=Build -set noprojgen= -set nobuild= -set run= -set target_arch=ia32 -set vs_toolset=x86 -set msbuild_platform=WIN32 -set library=static_library - -:next-arg -if "%1"=="" goto args-done -if /i "%1"=="debug" set config=Debug&goto arg-ok -if /i "%1"=="release" set config=Release&goto arg-ok -if /i "%1"=="test" set run=run-tests.exe&goto arg-ok -if /i "%1"=="bench" set run=run-benchmarks.exe&goto arg-ok -if /i "%1"=="clean" set target=Clean&goto arg-ok -if /i "%1"=="noprojgen" set noprojgen=1&goto arg-ok -if /i "%1"=="nobuild" set nobuild=1&goto arg-ok -if /i "%1"=="x86" set target_arch=ia32&set msbuild_platform=WIN32&set vs_toolset=x86&goto arg-ok -if /i "%1"=="ia32" set target_arch=ia32&set msbuild_platform=WIN32&set vs_toolset=x86&goto arg-ok -if /i "%1"=="x64" set target_arch=x64&set msbuild_platform=x64&set vs_toolset=x64&goto arg-ok -if /i "%1"=="shared" set library=shared_library&goto arg-ok -if /i "%1"=="static" set library=static_library&goto arg-ok -:arg-ok -shift -goto next-arg -:args-done - -if defined WindowsSDKDir goto select-target -if defined VCINSTALLDIR goto select-target - -@rem Look for Visual Studio 2015 -if not defined VS140COMNTOOLS goto vc-set-2013 -if not exist "%VS140COMNTOOLS%\..\..\vc\vcvarsall.bat" goto vc-set-2013 -call "%VS140COMNTOOLS%\..\..\vc\vcvarsall.bat" %vs_toolset% -set GYP_MSVS_VERSION=2015 -echo Using Visual Studio 2015 -goto select-target - -:vc-set-2013 -@rem Look for Visual Studio 2013 -if not defined VS120COMNTOOLS goto vc-set-2012 -if not exist "%VS120COMNTOOLS%\..\..\vc\vcvarsall.bat" goto vc-set-2012 -call "%VS120COMNTOOLS%\..\..\vc\vcvarsall.bat" %vs_toolset% -set GYP_MSVS_VERSION=2013 -echo Using Visual Studio 2013 -goto select-target - -:vc-set-2012 -@rem Look for Visual Studio 2012 -if not defined VS110COMNTOOLS goto vc-set-2010 -if not exist "%VS110COMNTOOLS%\..\..\vc\vcvarsall.bat" goto vc-set-2010 -call "%VS110COMNTOOLS%\..\..\vc\vcvarsall.bat" %vs_toolset% -set GYP_MSVS_VERSION=2012 -echo Using Visual Studio 2012 -goto select-target - -:vc-set-2010 -@rem Look for Visual Studio 2010 -if not defined VS100COMNTOOLS goto vc-set-2008 -if not exist "%VS100COMNTOOLS%\..\..\vc\vcvarsall.bat" goto vc-set-2008 -call "%VS100COMNTOOLS%\..\..\vc\vcvarsall.bat" %vs_toolset% -set GYP_MSVS_VERSION=2010 -echo Using Visual Studio 2010 -goto select-target - -:vc-set-2008 -@rem Look for Visual Studio 2008 -if not defined VS90COMNTOOLS goto vc-set-notfound -if not exist "%VS90COMNTOOLS%\..\..\vc\vcvarsall.bat" goto vc-set-notfound -call "%VS90COMNTOOLS%\..\..\vc\vcvarsall.bat" %vs_toolset% -set GYP_MSVS_VERSION=2008 -echo Using Visual Studio 2008 -goto select-target - -:vc-set-notfound -echo Warning: Visual Studio not found - -:select-target -if not "%config%"=="" goto project-gen -if "%run%"=="run-tests.exe" set config=Debug& goto project-gen -if "%run%"=="run-benchmarks.exe" set config=Release& goto project-gen -set config=Debug - -:project-gen -@rem Skip project generation if requested. -if defined noprojgen goto msbuild - -@rem Generate the VS project. -if exist build\gyp goto have_gyp -echo git clone https://chromium.googlesource.com/external/gyp build/gyp -git clone https://chromium.googlesource.com/external/gyp build/gyp -if errorlevel 1 goto gyp_install_failed -goto have_gyp - -:gyp_install_failed -echo Failed to download gyp. Make sure you have git installed, or -echo manually install gyp into %~dp0build\gyp. -exit /b 1 - -:have_gyp -if not defined PYTHON set PYTHON=python -"%PYTHON%" gyp_uv.py -Dtarget_arch=%target_arch% -Duv_library=%library% -if errorlevel 1 goto create-msvs-files-failed -if not exist uv.sln goto create-msvs-files-failed -echo Project files generated. - -:msbuild -@rem Skip project generation if requested. -if defined nobuild goto run - -@rem Check if VS build env is available -if defined VCINSTALLDIR goto msbuild-found -if defined WindowsSDKDir goto msbuild-found -echo Build skipped. To build, this file needs to run from VS cmd prompt. -goto run - -@rem Build the sln with msbuild. -:msbuild-found -msbuild uv.sln /t:%target% /p:Configuration=%config% /p:Platform="%msbuild_platform%" /clp:NoSummary;NoItemAndPropertyList;Verbosity=minimal /nologo -if errorlevel 1 exit /b 1 - -:run -@rem Run tests if requested. -if "%run%"=="" goto exit -if not exist %config%\%run% goto exit -echo running '%config%\%run%' -%config%\%run% -goto exit - -:create-msvs-files-failed -echo Failed to create vc project files. -exit /b 1 - -:help -echo vcbuild.bat [debug/release] [test/bench] [clean] [noprojgen] [nobuild] [x86/x64] [static/shared] -echo Examples: -echo vcbuild.bat : builds debug build -echo vcbuild.bat test : builds debug build and runs tests -echo vcbuild.bat release bench: builds release build and runs benchmarks -goto exit - -:exit diff --git a/vendor/minizip/CMakeLists.txt b/vendor/minizip/CMakeLists.txt deleted file mode 100644 index 8d2c0a458..000000000 --- a/vendor/minizip/CMakeLists.txt +++ /dev/null @@ -1,25 +0,0 @@ -include_directories("${LibSourcey_VENDOR_BUILD_DIR}/zlib") # for zconf.h -include_directories("${CMAKE_CURRENT_SOURCE_DIR}/../zlib") # for zlib.h - -# Include source files: -set(minizip_SOURCE_FILES - ioapi.c - mztools.c - unzip.c - zip.c) - -set(minizip_HEADER_FILES - crypt.h - ioapi.h - mztools.h - unzip.h - zip.h) - -if(WIN32) - # iowin32.h iowin32.c - set(minizip_SOURCE_FILES ${minizip_SOURCE_FILES} iowin32.c) -endif() - -set(minizip_DEPENDENCIES zlib) - -define_sourcey_dependency(minizip) diff --git a/vendor/minizip/Makefile b/vendor/minizip/Makefile deleted file mode 100644 index 84eaad20d..000000000 --- a/vendor/minizip/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -CC=cc -CFLAGS=-O -I../.. - -UNZ_OBJS = miniunz.o unzip.o ioapi.o ../../libz.a -ZIP_OBJS = minizip.o zip.o ioapi.o ../../libz.a - -.c.o: - $(CC) -c $(CFLAGS) $*.c - -all: miniunz minizip - -miniunz: $(UNZ_OBJS) - $(CC) $(CFLAGS) -o $@ $(UNZ_OBJS) - -minizip: $(ZIP_OBJS) - $(CC) $(CFLAGS) -o $@ $(ZIP_OBJS) - -test: miniunz minizip - ./minizip test readme.txt - ./miniunz -l test.zip - mv readme.txt readme.old - ./miniunz test.zip - -clean: - /bin/rm -f *.o *~ minizip miniunz diff --git a/vendor/minizip/Makefile.am b/vendor/minizip/Makefile.am deleted file mode 100644 index d343011eb..000000000 --- a/vendor/minizip/Makefile.am +++ /dev/null @@ -1,45 +0,0 @@ -lib_LTLIBRARIES = libminizip.la - -if COND_DEMOS -bin_PROGRAMS = miniunzip minizip -endif - -zlib_top_srcdir = $(top_srcdir)/../.. -zlib_top_builddir = $(top_builddir)/../.. - -AM_CPPFLAGS = -I$(zlib_top_srcdir) -AM_LDFLAGS = -L$(zlib_top_builddir) - -if WIN32 -iowin32_src = iowin32.c -iowin32_h = iowin32.h -endif - -libminizip_la_SOURCES = \ - ioapi.c \ - mztools.c \ - unzip.c \ - zip.c \ - ${iowin32_src} - -libminizip_la_LDFLAGS = $(AM_LDFLAGS) -version-info 1:0:0 -lz - -minizip_includedir = $(includedir)/minizip -minizip_include_HEADERS = \ - crypt.h \ - ioapi.h \ - mztools.h \ - unzip.h \ - zip.h \ - ${iowin32_h} - -pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = minizip.pc - -EXTRA_PROGRAMS = miniunzip minizip - -miniunzip_SOURCES = miniunz.c -miniunzip_LDADD = libminizip.la - -minizip_SOURCES = minizip.c -minizip_LDADD = libminizip.la -lz diff --git a/vendor/minizip/MiniZip64_Changes.txt b/vendor/minizip/MiniZip64_Changes.txt deleted file mode 100644 index 13a1bd91a..000000000 --- a/vendor/minizip/MiniZip64_Changes.txt +++ /dev/null @@ -1,6 +0,0 @@ - -MiniZip 1.1 was derrived from MiniZip at version 1.01f - -Change in 1.0 (Okt 2009) - - **TODO - Add history** - diff --git a/vendor/minizip/MiniZip64_info.txt b/vendor/minizip/MiniZip64_info.txt deleted file mode 100644 index 57d715242..000000000 --- a/vendor/minizip/MiniZip64_info.txt +++ /dev/null @@ -1,74 +0,0 @@ -MiniZip - Copyright (c) 1998-2010 - by Gilles Vollant - version 1.1 64 bits from Mathias Svensson - -Introduction ---------------------- -MiniZip 1.1 is built from MiniZip 1.0 by Gilles Vollant ( http://www.winimage.com/zLibDll/minizip.html ) - -When adding ZIP64 support into minizip it would result into risk of breaking compatibility with minizip 1.0. -All possible work was done for compatibility. - - -Background ---------------------- -When adding ZIP64 support Mathias Svensson found that Even Rouault have added ZIP64 -support for unzip.c into minizip for a open source project called gdal ( http://www.gdal.org/ ) - -That was used as a starting point. And after that ZIP64 support was added to zip.c -some refactoring and code cleanup was also done. - - -Changed from MiniZip 1.0 to MiniZip 1.1 ---------------------------------------- -* Added ZIP64 support for unzip ( by Even Rouault ) -* Added ZIP64 support for zip ( by Mathias Svensson ) -* Reverted some changed that Even Rouault did. -* Bunch of patches received from Gulles Vollant that he received for MiniZip from various users. -* Added unzip patch for BZIP Compression method (patch create by Daniel Borca) -* Added BZIP Compress method for zip -* Did some refactoring and code cleanup - - -Credits - - Gilles Vollant - Original MiniZip author - Even Rouault - ZIP64 unzip Support - Daniel Borca - BZip Compression method support in unzip - Mathias Svensson - ZIP64 zip support - Mathias Svensson - BZip Compression method support in zip - - Resources - - ZipLayout http://result42.com/projects/ZipFileLayout - Command line tool for Windows that shows the layout and information of the headers in a zip archive. - Used when debugging and validating the creation of zip files using MiniZip64 - - - ZIP App Note http://www.pkware.com/documents/casestudies/APPNOTE.TXT - Zip File specification - - -Notes. - * To be able to use BZip compression method in zip64.c or unzip64.c the BZIP2 lib is needed and HAVE_BZIP2 need to be defined. - -License ----------------------------------------------------------- - Condition of use and distribution are the same than zlib : - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - ----------------------------------------------------------- - diff --git a/vendor/minizip/configure.ac b/vendor/minizip/configure.ac deleted file mode 100644 index 827a4e057..000000000 --- a/vendor/minizip/configure.ac +++ /dev/null @@ -1,32 +0,0 @@ -# -*- Autoconf -*- -# Process this file with autoconf to produce a configure script. - -AC_INIT([minizip], [1.2.8], [bugzilla.redhat.com]) -AC_CONFIG_SRCDIR([minizip.c]) -AM_INIT_AUTOMAKE([foreign]) -LT_INIT - -AC_MSG_CHECKING([whether to build example programs]) -AC_ARG_ENABLE([demos], AC_HELP_STRING([--enable-demos], [build example programs])) -AM_CONDITIONAL([COND_DEMOS], [test "$enable_demos" = yes]) -if test "$enable_demos" = yes -then - AC_MSG_RESULT([yes]) -else - AC_MSG_RESULT([no]) -fi - -case "${host}" in - *-mingw* | mingw*) - WIN32="yes" - ;; - *) - ;; -esac -AM_CONDITIONAL([WIN32], [test "${WIN32}" = "yes"]) - - -AC_SUBST([HAVE_UNISTD_H], [0]) -AC_CHECK_HEADER([unistd.h], [HAVE_UNISTD_H=1], []) -AC_CONFIG_FILES([Makefile minizip.pc]) -AC_OUTPUT diff --git a/vendor/minizip/crypt.h b/vendor/minizip/crypt.h deleted file mode 100644 index 1e9e8200b..000000000 --- a/vendor/minizip/crypt.h +++ /dev/null @@ -1,131 +0,0 @@ -/* crypt.h -- base code for crypt/uncrypt ZIPfile - - - Version 1.01e, February 12th, 2005 - - Copyright (C) 1998-2005 Gilles Vollant - - This code is a modified version of crypting code in Infozip distribution - - The encryption/decryption parts of this source code (as opposed to the - non-echoing password parts) were originally written in Europe. The - whole source package can be freely distributed, including from the USA. - (Prior to January 2000, re-export from the US was a violation of US law.) - - This encryption code is a direct transcription of the algorithm from - Roger Schlafly, described by Phil Katz in the file appnote.txt. This - file (appnote.txt) is distributed with the PKZIP program (even in the - version without encryption capabilities). - - If you don't need crypting in your application, just define symbols - NOCRYPT and NOUNCRYPT. - - This code support the "Traditional PKWARE Encryption". - - The new AES encryption added on Zip format by Winzip (see the page - http://www.winzip.com/aes_info.htm ) and PKWare PKZip 5.x Strong - Encryption is not supported. -*/ - -#define CRC32(c, b) ((*(pcrc_32_tab+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8)) - -/*********************************************************************** - * Return the next byte in the pseudo-random sequence - */ -static int decrypt_byte(unsigned long* pkeys, const z_crc_t* pcrc_32_tab) -{ - unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an - * unpredictable manner on 16-bit systems; not a problem - * with any known compiler so far, though */ - - temp = ((unsigned)(*(pkeys+2)) & 0xffff) | 2; - return (int)(((temp * (temp ^ 1)) >> 8) & 0xff); -} - -/*********************************************************************** - * Update the encryption keys with the next byte of plain text - */ -static int update_keys(unsigned long* pkeys,const z_crc_t* pcrc_32_tab,int c) -{ - (*(pkeys+0)) = CRC32((*(pkeys+0)), c); - (*(pkeys+1)) += (*(pkeys+0)) & 0xff; - (*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1; - { - register int keyshift = (int)((*(pkeys+1)) >> 24); - (*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift); - } - return c; -} - - -/*********************************************************************** - * Initialize the encryption keys and the random header according to - * the given password. - */ -static void init_keys(const char* passwd,unsigned long* pkeys,const z_crc_t* pcrc_32_tab) -{ - *(pkeys+0) = 305419896L; - *(pkeys+1) = 591751049L; - *(pkeys+2) = 878082192L; - while (*passwd != '\0') { - update_keys(pkeys,pcrc_32_tab,(int)*passwd); - passwd++; - } -} - -#define zdecode(pkeys,pcrc_32_tab,c) \ - (update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys,pcrc_32_tab))) - -#define zencode(pkeys,pcrc_32_tab,c,t) \ - (t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), t^(c)) - -#ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED - -#define RAND_HEAD_LEN 12 - /* "last resort" source for second part of crypt seed pattern */ -# ifndef ZCR_SEED2 -# define ZCR_SEED2 3141592654UL /* use PI as default pattern */ -# endif - -static int crypthead(const char* passwd, /* password string */ - unsigned char* buf, /* where to write header */ - int bufSize, - unsigned long* pkeys, - const z_crc_t* pcrc_32_tab, - unsigned long crcForCrypting) -{ - int n; /* index in random header */ - int t; /* temporary */ - int c; /* random byte */ - unsigned char header[RAND_HEAD_LEN-2]; /* random header */ - static unsigned calls = 0; /* ensure different random header each time */ - - if (bufSize> 7) & 0xff; - header[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, c, t); - } - /* Encrypt random header (last two bytes is high word of crc) */ - init_keys(passwd, pkeys, pcrc_32_tab); - for (n = 0; n < RAND_HEAD_LEN-2; n++) - { - buf[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, header[n], t); - } - buf[n++] = (unsigned char)zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 16) & 0xff, t); - buf[n++] = (unsigned char)zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 24) & 0xff, t); - return n; -} - -#endif diff --git a/vendor/minizip/ioapi.c b/vendor/minizip/ioapi.c deleted file mode 100644 index 7f5c191b2..000000000 --- a/vendor/minizip/ioapi.c +++ /dev/null @@ -1,247 +0,0 @@ -/* ioapi.h -- IO base function header for compress/uncompress .zip - part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) - - Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) - - Modifications for Zip64 support - Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) - - For more info read MiniZip_info.txt - -*/ - -#if defined(_WIN32) && (!(defined(_CRT_SECURE_NO_WARNINGS))) - #define _CRT_SECURE_NO_WARNINGS -#endif - -#if defined(__APPLE__) || defined(IOAPI_NO_64) -// In darwin and perhaps other BSD variants off_t is a 64 bit value, hence no need for specific 64 bit functions -#define FOPEN_FUNC(filename, mode) fopen(filename, mode) -#define FTELLO_FUNC(stream) ftello(stream) -#define FSEEKO_FUNC(stream, offset, origin) fseeko(stream, offset, origin) -#else -#define FOPEN_FUNC(filename, mode) fopen64(filename, mode) -#define FTELLO_FUNC(stream) ftello64(stream) -#define FSEEKO_FUNC(stream, offset, origin) fseeko64(stream, offset, origin) -#endif - - -#include "ioapi.h" - -voidpf call_zopen64 (const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode) -{ - if (pfilefunc->zfile_func64.zopen64_file != NULL) - return (*(pfilefunc->zfile_func64.zopen64_file)) (pfilefunc->zfile_func64.opaque,filename,mode); - else - { - return (*(pfilefunc->zopen32_file))(pfilefunc->zfile_func64.opaque,(const char*)filename,mode); - } -} - -long call_zseek64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin) -{ - if (pfilefunc->zfile_func64.zseek64_file != NULL) - return (*(pfilefunc->zfile_func64.zseek64_file)) (pfilefunc->zfile_func64.opaque,filestream,offset,origin); - else - { - uLong offsetTruncated = (uLong)offset; - if (offsetTruncated != offset) - return -1; - else - return (*(pfilefunc->zseek32_file))(pfilefunc->zfile_func64.opaque,filestream,offsetTruncated,origin); - } -} - -ZPOS64_T call_ztell64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream) -{ - if (pfilefunc->zfile_func64.zseek64_file != NULL) - return (*(pfilefunc->zfile_func64.ztell64_file)) (pfilefunc->zfile_func64.opaque,filestream); - else - { - uLong tell_uLong = (*(pfilefunc->ztell32_file))(pfilefunc->zfile_func64.opaque,filestream); - if ((tell_uLong) == MAXU32) - return (ZPOS64_T)-1; - else - return tell_uLong; - } -} - -void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32) -{ - p_filefunc64_32->zfile_func64.zopen64_file = NULL; - p_filefunc64_32->zopen32_file = p_filefunc32->zopen_file; - p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file; - p_filefunc64_32->zfile_func64.zread_file = p_filefunc32->zread_file; - p_filefunc64_32->zfile_func64.zwrite_file = p_filefunc32->zwrite_file; - p_filefunc64_32->zfile_func64.ztell64_file = NULL; - p_filefunc64_32->zfile_func64.zseek64_file = NULL; - p_filefunc64_32->zfile_func64.zclose_file = p_filefunc32->zclose_file; - p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file; - p_filefunc64_32->zfile_func64.opaque = p_filefunc32->opaque; - p_filefunc64_32->zseek32_file = p_filefunc32->zseek_file; - p_filefunc64_32->ztell32_file = p_filefunc32->ztell_file; -} - - - -static voidpf ZCALLBACK fopen_file_func OF((voidpf opaque, const char* filename, int mode)); -static uLong ZCALLBACK fread_file_func OF((voidpf opaque, voidpf stream, void* buf, uLong size)); -static uLong ZCALLBACK fwrite_file_func OF((voidpf opaque, voidpf stream, const void* buf,uLong size)); -static ZPOS64_T ZCALLBACK ftell64_file_func OF((voidpf opaque, voidpf stream)); -static long ZCALLBACK fseek64_file_func OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin)); -static int ZCALLBACK fclose_file_func OF((voidpf opaque, voidpf stream)); -static int ZCALLBACK ferror_file_func OF((voidpf opaque, voidpf stream)); - -static voidpf ZCALLBACK fopen_file_func (voidpf opaque, const char* filename, int mode) -{ - FILE* file = NULL; - const char* mode_fopen = NULL; - if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) - mode_fopen = "rb"; - else - if (mode & ZLIB_FILEFUNC_MODE_EXISTING) - mode_fopen = "r+b"; - else - if (mode & ZLIB_FILEFUNC_MODE_CREATE) - mode_fopen = "wb"; - - if ((filename!=NULL) && (mode_fopen != NULL)) - file = fopen(filename, mode_fopen); - return file; -} - -static voidpf ZCALLBACK fopen64_file_func (voidpf opaque, const void* filename, int mode) -{ - FILE* file = NULL; - const char* mode_fopen = NULL; - if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) - mode_fopen = "rb"; - else - if (mode & ZLIB_FILEFUNC_MODE_EXISTING) - mode_fopen = "r+b"; - else - if (mode & ZLIB_FILEFUNC_MODE_CREATE) - mode_fopen = "wb"; - - if ((filename!=NULL) && (mode_fopen != NULL)) - file = FOPEN_FUNC((const char*)filename, mode_fopen); - return file; -} - - -static uLong ZCALLBACK fread_file_func (voidpf opaque, voidpf stream, void* buf, uLong size) -{ - uLong ret; - ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream); - return ret; -} - -static uLong ZCALLBACK fwrite_file_func (voidpf opaque, voidpf stream, const void* buf, uLong size) -{ - uLong ret; - ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream); - return ret; -} - -static long ZCALLBACK ftell_file_func (voidpf opaque, voidpf stream) -{ - long ret; - ret = ftell((FILE *)stream); - return ret; -} - - -static ZPOS64_T ZCALLBACK ftell64_file_func (voidpf opaque, voidpf stream) -{ - ZPOS64_T ret; - ret = FTELLO_FUNC((FILE *)stream); - return ret; -} - -static long ZCALLBACK fseek_file_func (voidpf opaque, voidpf stream, uLong offset, int origin) -{ - int fseek_origin=0; - long ret; - switch (origin) - { - case ZLIB_FILEFUNC_SEEK_CUR : - fseek_origin = SEEK_CUR; - break; - case ZLIB_FILEFUNC_SEEK_END : - fseek_origin = SEEK_END; - break; - case ZLIB_FILEFUNC_SEEK_SET : - fseek_origin = SEEK_SET; - break; - default: return -1; - } - ret = 0; - if (fseek((FILE *)stream, offset, fseek_origin) != 0) - ret = -1; - return ret; -} - -static long ZCALLBACK fseek64_file_func (voidpf opaque, voidpf stream, ZPOS64_T offset, int origin) -{ - int fseek_origin=0; - long ret; - switch (origin) - { - case ZLIB_FILEFUNC_SEEK_CUR : - fseek_origin = SEEK_CUR; - break; - case ZLIB_FILEFUNC_SEEK_END : - fseek_origin = SEEK_END; - break; - case ZLIB_FILEFUNC_SEEK_SET : - fseek_origin = SEEK_SET; - break; - default: return -1; - } - ret = 0; - - if(FSEEKO_FUNC((FILE *)stream, offset, fseek_origin) != 0) - ret = -1; - - return ret; -} - - -static int ZCALLBACK fclose_file_func (voidpf opaque, voidpf stream) -{ - int ret; - ret = fclose((FILE *)stream); - return ret; -} - -static int ZCALLBACK ferror_file_func (voidpf opaque, voidpf stream) -{ - int ret; - ret = ferror((FILE *)stream); - return ret; -} - -void fill_fopen_filefunc (pzlib_filefunc_def) - zlib_filefunc_def* pzlib_filefunc_def; -{ - pzlib_filefunc_def->zopen_file = fopen_file_func; - pzlib_filefunc_def->zread_file = fread_file_func; - pzlib_filefunc_def->zwrite_file = fwrite_file_func; - pzlib_filefunc_def->ztell_file = ftell_file_func; - pzlib_filefunc_def->zseek_file = fseek_file_func; - pzlib_filefunc_def->zclose_file = fclose_file_func; - pzlib_filefunc_def->zerror_file = ferror_file_func; - pzlib_filefunc_def->opaque = NULL; -} - -void fill_fopen64_filefunc (zlib_filefunc64_def* pzlib_filefunc_def) -{ - pzlib_filefunc_def->zopen64_file = fopen64_file_func; - pzlib_filefunc_def->zread_file = fread_file_func; - pzlib_filefunc_def->zwrite_file = fwrite_file_func; - pzlib_filefunc_def->ztell64_file = ftell64_file_func; - pzlib_filefunc_def->zseek64_file = fseek64_file_func; - pzlib_filefunc_def->zclose_file = fclose_file_func; - pzlib_filefunc_def->zerror_file = ferror_file_func; - pzlib_filefunc_def->opaque = NULL; -} diff --git a/vendor/minizip/ioapi.h b/vendor/minizip/ioapi.h deleted file mode 100644 index 8dcbdb06e..000000000 --- a/vendor/minizip/ioapi.h +++ /dev/null @@ -1,208 +0,0 @@ -/* ioapi.h -- IO base function header for compress/uncompress .zip - part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) - - Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) - - Modifications for Zip64 support - Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) - - For more info read MiniZip_info.txt - - Changes - - Oct-2009 - Defined ZPOS64_T to fpos_t on windows and u_int64_t on linux. (might need to find a better why for this) - Oct-2009 - Change to fseeko64, ftello64 and fopen64 so large files would work on linux. - More if/def section may be needed to support other platforms - Oct-2009 - Defined fxxxx64 calls to normal fopen/ftell/fseek so they would compile on windows. - (but you should use iowin32.c for windows instead) - -*/ - -#ifndef _ZLIBIOAPI64_H -#define _ZLIBIOAPI64_H - -#if (!defined(_WIN32)) && (!defined(WIN32)) && (!defined(__APPLE__)) - - // Linux needs this to support file operation on files larger then 4+GB - // But might need better if/def to select just the platforms that needs them. - - #ifndef __USE_FILE_OFFSET64 - #define __USE_FILE_OFFSET64 - #endif - #ifndef __USE_LARGEFILE64 - #define __USE_LARGEFILE64 - #endif - #ifndef _LARGEFILE64_SOURCE - #define _LARGEFILE64_SOURCE - #endif - #ifndef _FILE_OFFSET_BIT - #define _FILE_OFFSET_BIT 64 - #endif - -#endif - -#include -#include -#include "zlib.h" - -#if defined(USE_FILE32API) -#define fopen64 fopen -#define ftello64 ftell -#define fseeko64 fseek -#else -#ifdef __FreeBSD__ -#define fopen64 fopen -#define ftello64 ftello -#define fseeko64 fseeko -#endif -#ifdef _MSC_VER - #define fopen64 fopen - #if (_MSC_VER >= 1400) && (!(defined(NO_MSCVER_FILE64_FUNC))) - #define ftello64 _ftelli64 - #define fseeko64 _fseeki64 - #else // old MSC - #define ftello64 ftell - #define fseeko64 fseek - #endif -#endif -#endif - -/* -#ifndef ZPOS64_T - #ifdef _WIN32 - #define ZPOS64_T fpos_t - #else - #include - #define ZPOS64_T uint64_t - #endif -#endif -*/ - -#ifdef HAVE_MINIZIP64_CONF_H -#include "mz64conf.h" -#endif - -/* a type choosen by DEFINE */ -#ifdef HAVE_64BIT_INT_CUSTOM -typedef 64BIT_INT_CUSTOM_TYPE ZPOS64_T; -#else -#ifdef HAS_STDINT_H -#include "stdint.h" -typedef uint64_t ZPOS64_T; -#else - -/* Maximum unsigned 32-bit value used as placeholder for zip64 */ -#define MAXU32 0xffffffff - -#if defined(_MSC_VER) || defined(__BORLANDC__) -typedef unsigned __int64 ZPOS64_T; -#else -typedef unsigned long long int ZPOS64_T; -#endif -#endif -#endif - - - -#ifdef __cplusplus -extern "C" { -#endif - - -#define ZLIB_FILEFUNC_SEEK_CUR (1) -#define ZLIB_FILEFUNC_SEEK_END (2) -#define ZLIB_FILEFUNC_SEEK_SET (0) - -#define ZLIB_FILEFUNC_MODE_READ (1) -#define ZLIB_FILEFUNC_MODE_WRITE (2) -#define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3) - -#define ZLIB_FILEFUNC_MODE_EXISTING (4) -#define ZLIB_FILEFUNC_MODE_CREATE (8) - - -#ifndef ZCALLBACK - #if (defined(WIN32) || defined(_WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK) - #define ZCALLBACK CALLBACK - #else - #define ZCALLBACK - #endif -#endif - - - - -typedef voidpf (ZCALLBACK *open_file_func) OF((voidpf opaque, const char* filename, int mode)); -typedef uLong (ZCALLBACK *read_file_func) OF((voidpf opaque, voidpf stream, void* buf, uLong size)); -typedef uLong (ZCALLBACK *write_file_func) OF((voidpf opaque, voidpf stream, const void* buf, uLong size)); -typedef int (ZCALLBACK *close_file_func) OF((voidpf opaque, voidpf stream)); -typedef int (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream)); - -typedef long (ZCALLBACK *tell_file_func) OF((voidpf opaque, voidpf stream)); -typedef long (ZCALLBACK *seek_file_func) OF((voidpf opaque, voidpf stream, uLong offset, int origin)); - - -/* here is the "old" 32 bits structure structure */ -typedef struct zlib_filefunc_def_s -{ - open_file_func zopen_file; - read_file_func zread_file; - write_file_func zwrite_file; - tell_file_func ztell_file; - seek_file_func zseek_file; - close_file_func zclose_file; - testerror_file_func zerror_file; - voidpf opaque; -} zlib_filefunc_def; - -typedef ZPOS64_T (ZCALLBACK *tell64_file_func) OF((voidpf opaque, voidpf stream)); -typedef long (ZCALLBACK *seek64_file_func) OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin)); -typedef voidpf (ZCALLBACK *open64_file_func) OF((voidpf opaque, const void* filename, int mode)); - -typedef struct zlib_filefunc64_def_s -{ - open64_file_func zopen64_file; - read_file_func zread_file; - write_file_func zwrite_file; - tell64_file_func ztell64_file; - seek64_file_func zseek64_file; - close_file_func zclose_file; - testerror_file_func zerror_file; - voidpf opaque; -} zlib_filefunc64_def; - -void fill_fopen64_filefunc OF((zlib_filefunc64_def* pzlib_filefunc_def)); -void fill_fopen_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def)); - -/* now internal definition, only for zip.c and unzip.h */ -typedef struct zlib_filefunc64_32_def_s -{ - zlib_filefunc64_def zfile_func64; - open_file_func zopen32_file; - tell_file_func ztell32_file; - seek_file_func zseek32_file; -} zlib_filefunc64_32_def; - - -#define ZREAD64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zread_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size)) -#define ZWRITE64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zwrite_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size)) -//#define ZTELL64(filefunc,filestream) ((*((filefunc).ztell64_file)) ((filefunc).opaque,filestream)) -//#define ZSEEK64(filefunc,filestream,pos,mode) ((*((filefunc).zseek64_file)) ((filefunc).opaque,filestream,pos,mode)) -#define ZCLOSE64(filefunc,filestream) ((*((filefunc).zfile_func64.zclose_file)) ((filefunc).zfile_func64.opaque,filestream)) -#define ZERROR64(filefunc,filestream) ((*((filefunc).zfile_func64.zerror_file)) ((filefunc).zfile_func64.opaque,filestream)) - -voidpf call_zopen64 OF((const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode)); -long call_zseek64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin)); -ZPOS64_T call_ztell64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream)); - -void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32); - -#define ZOPEN64(filefunc,filename,mode) (call_zopen64((&(filefunc)),(filename),(mode))) -#define ZTELL64(filefunc,filestream) (call_ztell64((&(filefunc)),(filestream))) -#define ZSEEK64(filefunc,filestream,pos,mode) (call_zseek64((&(filefunc)),(filestream),(pos),(mode))) - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/vendor/minizip/iowin32.c b/vendor/minizip/iowin32.c deleted file mode 100644 index a46d96c7f..000000000 --- a/vendor/minizip/iowin32.c +++ /dev/null @@ -1,461 +0,0 @@ -/* iowin32.c -- IO base function header for compress/uncompress .zip - Version 1.1, February 14h, 2010 - part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) - - Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) - - Modifications for Zip64 support - Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) - - For more info read MiniZip_info.txt - -*/ - -#include - -#include "zlib.h" -#include "ioapi.h" -#include "iowin32.h" - -#ifndef INVALID_HANDLE_VALUE -#define INVALID_HANDLE_VALUE (0xFFFFFFFF) -#endif - -#ifndef INVALID_SET_FILE_POINTER -#define INVALID_SET_FILE_POINTER ((DWORD)-1) -#endif - - -#if defined(WINAPI_FAMILY_PARTITION) && (!(defined(IOWIN32_USING_WINRT_API))) -#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) -#define IOWIN32_USING_WINRT_API 1 -#endif -#endif - -voidpf ZCALLBACK win32_open_file_func OF((voidpf opaque, const char* filename, int mode)); -uLong ZCALLBACK win32_read_file_func OF((voidpf opaque, voidpf stream, void* buf, uLong size)); -uLong ZCALLBACK win32_write_file_func OF((voidpf opaque, voidpf stream, const void* buf, uLong size)); -ZPOS64_T ZCALLBACK win32_tell64_file_func OF((voidpf opaque, voidpf stream)); -long ZCALLBACK win32_seek64_file_func OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin)); -int ZCALLBACK win32_close_file_func OF((voidpf opaque, voidpf stream)); -int ZCALLBACK win32_error_file_func OF((voidpf opaque, voidpf stream)); - -typedef struct -{ - HANDLE hf; - int error; -} WIN32FILE_IOWIN; - - -static void win32_translate_open_mode(int mode, - DWORD* lpdwDesiredAccess, - DWORD* lpdwCreationDisposition, - DWORD* lpdwShareMode, - DWORD* lpdwFlagsAndAttributes) -{ - *lpdwDesiredAccess = *lpdwShareMode = *lpdwFlagsAndAttributes = *lpdwCreationDisposition = 0; - - if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) - { - *lpdwDesiredAccess = GENERIC_READ; - *lpdwCreationDisposition = OPEN_EXISTING; - *lpdwShareMode = FILE_SHARE_READ; - } - else if (mode & ZLIB_FILEFUNC_MODE_EXISTING) - { - *lpdwDesiredAccess = GENERIC_WRITE | GENERIC_READ; - *lpdwCreationDisposition = OPEN_EXISTING; - } - else if (mode & ZLIB_FILEFUNC_MODE_CREATE) - { - *lpdwDesiredAccess = GENERIC_WRITE | GENERIC_READ; - *lpdwCreationDisposition = CREATE_ALWAYS; - } -} - -static voidpf win32_build_iowin(HANDLE hFile) -{ - voidpf ret=NULL; - - if ((hFile != NULL) && (hFile != INVALID_HANDLE_VALUE)) - { - WIN32FILE_IOWIN w32fiow; - w32fiow.hf = hFile; - w32fiow.error = 0; - ret = malloc(sizeof(WIN32FILE_IOWIN)); - - if (ret==NULL) - CloseHandle(hFile); - else - *((WIN32FILE_IOWIN*)ret) = w32fiow; - } - return ret; -} - -voidpf ZCALLBACK win32_open64_file_func (voidpf opaque,const void* filename,int mode) -{ - const char* mode_fopen = NULL; - DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ; - HANDLE hFile = NULL; - - win32_translate_open_mode(mode,&dwDesiredAccess,&dwCreationDisposition,&dwShareMode,&dwFlagsAndAttributes); - -#ifdef IOWIN32_USING_WINRT_API -#ifdef UNICODE - if ((filename!=NULL) && (dwDesiredAccess != 0)) - hFile = CreateFile2((LPCTSTR)filename, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL); -#else - if ((filename!=NULL) && (dwDesiredAccess != 0)) - { - WCHAR filenameW[FILENAME_MAX + 0x200 + 1]; - MultiByteToWideChar(CP_ACP,0,(const char*)filename,-1,filenameW,FILENAME_MAX + 0x200); - hFile = CreateFile2(filenameW, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL); - } -#endif -#else - if ((filename!=NULL) && (dwDesiredAccess != 0)) - hFile = CreateFile((LPCTSTR)filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL); -#endif - - return win32_build_iowin(hFile); -} - - -voidpf ZCALLBACK win32_open64_file_funcA (voidpf opaque,const void* filename,int mode) -{ - const char* mode_fopen = NULL; - DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ; - HANDLE hFile = NULL; - - win32_translate_open_mode(mode,&dwDesiredAccess,&dwCreationDisposition,&dwShareMode,&dwFlagsAndAttributes); - -#ifdef IOWIN32_USING_WINRT_API - if ((filename!=NULL) && (dwDesiredAccess != 0)) - { - WCHAR filenameW[FILENAME_MAX + 0x200 + 1]; - MultiByteToWideChar(CP_ACP,0,(const char*)filename,-1,filenameW,FILENAME_MAX + 0x200); - hFile = CreateFile2(filenameW, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL); - } -#else - if ((filename!=NULL) && (dwDesiredAccess != 0)) - hFile = CreateFileA((LPCSTR)filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL); -#endif - - return win32_build_iowin(hFile); -} - - -voidpf ZCALLBACK win32_open64_file_funcW (voidpf opaque,const void* filename,int mode) -{ - const char* mode_fopen = NULL; - DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ; - HANDLE hFile = NULL; - - win32_translate_open_mode(mode,&dwDesiredAccess,&dwCreationDisposition,&dwShareMode,&dwFlagsAndAttributes); - -#ifdef IOWIN32_USING_WINRT_API - if ((filename!=NULL) && (dwDesiredAccess != 0)) - hFile = CreateFile2((LPCWSTR)filename, dwDesiredAccess, dwShareMode, dwCreationDisposition,NULL); -#else - if ((filename!=NULL) && (dwDesiredAccess != 0)) - hFile = CreateFileW((LPCWSTR)filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL); -#endif - - return win32_build_iowin(hFile); -} - - -voidpf ZCALLBACK win32_open_file_func (voidpf opaque,const char* filename,int mode) -{ - const char* mode_fopen = NULL; - DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ; - HANDLE hFile = NULL; - - win32_translate_open_mode(mode,&dwDesiredAccess,&dwCreationDisposition,&dwShareMode,&dwFlagsAndAttributes); - -#ifdef IOWIN32_USING_WINRT_API -#ifdef UNICODE - if ((filename!=NULL) && (dwDesiredAccess != 0)) - hFile = CreateFile2((LPCTSTR)filename, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL); -#else - if ((filename!=NULL) && (dwDesiredAccess != 0)) - { - WCHAR filenameW[FILENAME_MAX + 0x200 + 1]; - MultiByteToWideChar(CP_ACP,0,(const char*)filename,-1,filenameW,FILENAME_MAX + 0x200); - hFile = CreateFile2(filenameW, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL); - } -#endif -#else - if ((filename!=NULL) && (dwDesiredAccess != 0)) - hFile = CreateFile((LPCTSTR)filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL); -#endif - - return win32_build_iowin(hFile); -} - - -uLong ZCALLBACK win32_read_file_func (voidpf opaque, voidpf stream, void* buf,uLong size) -{ - uLong ret=0; - HANDLE hFile = NULL; - if (stream!=NULL) - hFile = ((WIN32FILE_IOWIN*)stream) -> hf; - - if (hFile != NULL) - { - if (!ReadFile(hFile, buf, size, &ret, NULL)) - { - DWORD dwErr = GetLastError(); - if (dwErr == ERROR_HANDLE_EOF) - dwErr = 0; - ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; - } - } - - return ret; -} - - -uLong ZCALLBACK win32_write_file_func (voidpf opaque,voidpf stream,const void* buf,uLong size) -{ - uLong ret=0; - HANDLE hFile = NULL; - if (stream!=NULL) - hFile = ((WIN32FILE_IOWIN*)stream) -> hf; - - if (hFile != NULL) - { - if (!WriteFile(hFile, buf, size, &ret, NULL)) - { - DWORD dwErr = GetLastError(); - if (dwErr == ERROR_HANDLE_EOF) - dwErr = 0; - ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; - } - } - - return ret; -} - -static BOOL MySetFilePointerEx(HANDLE hFile, LARGE_INTEGER pos, LARGE_INTEGER *newPos, DWORD dwMoveMethod) -{ -#ifdef IOWIN32_USING_WINRT_API - return SetFilePointerEx(hFile, pos, newPos, dwMoveMethod); -#else - LONG lHigh = pos.HighPart; - DWORD dwNewPos = SetFilePointer(hFile, pos.LowPart, &lHigh, FILE_CURRENT); - BOOL fOk = TRUE; - if (dwNewPos == 0xFFFFFFFF) - if (GetLastError() != NO_ERROR) - fOk = FALSE; - if ((newPos != NULL) && (fOk)) - { - newPos->LowPart = dwNewPos; - newPos->HighPart = lHigh; - } - return fOk; -#endif -} - -long ZCALLBACK win32_tell_file_func (voidpf opaque,voidpf stream) -{ - long ret=-1; - HANDLE hFile = NULL; - if (stream!=NULL) - hFile = ((WIN32FILE_IOWIN*)stream) -> hf; - if (hFile != NULL) - { - LARGE_INTEGER pos; - pos.QuadPart = 0; - - if (!MySetFilePointerEx(hFile, pos, &pos, FILE_CURRENT)) - { - DWORD dwErr = GetLastError(); - ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; - ret = -1; - } - else - ret=(long)pos.LowPart; - } - return ret; -} - -ZPOS64_T ZCALLBACK win32_tell64_file_func (voidpf opaque, voidpf stream) -{ - ZPOS64_T ret= (ZPOS64_T)-1; - HANDLE hFile = NULL; - if (stream!=NULL) - hFile = ((WIN32FILE_IOWIN*)stream)->hf; - - if (hFile) - { - LARGE_INTEGER pos; - pos.QuadPart = 0; - - if (!MySetFilePointerEx(hFile, pos, &pos, FILE_CURRENT)) - { - DWORD dwErr = GetLastError(); - ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; - ret = (ZPOS64_T)-1; - } - else - ret=pos.QuadPart; - } - return ret; -} - - -long ZCALLBACK win32_seek_file_func (voidpf opaque,voidpf stream,uLong offset,int origin) -{ - DWORD dwMoveMethod=0xFFFFFFFF; - HANDLE hFile = NULL; - - long ret=-1; - if (stream!=NULL) - hFile = ((WIN32FILE_IOWIN*)stream) -> hf; - switch (origin) - { - case ZLIB_FILEFUNC_SEEK_CUR : - dwMoveMethod = FILE_CURRENT; - break; - case ZLIB_FILEFUNC_SEEK_END : - dwMoveMethod = FILE_END; - break; - case ZLIB_FILEFUNC_SEEK_SET : - dwMoveMethod = FILE_BEGIN; - break; - default: return -1; - } - - if (hFile != NULL) - { - LARGE_INTEGER pos; - pos.QuadPart = offset; - if (!MySetFilePointerEx(hFile, pos, NULL, dwMoveMethod)) - { - DWORD dwErr = GetLastError(); - ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; - ret = -1; - } - else - ret=0; - } - return ret; -} - -long ZCALLBACK win32_seek64_file_func (voidpf opaque, voidpf stream,ZPOS64_T offset,int origin) -{ - DWORD dwMoveMethod=0xFFFFFFFF; - HANDLE hFile = NULL; - long ret=-1; - - if (stream!=NULL) - hFile = ((WIN32FILE_IOWIN*)stream)->hf; - - switch (origin) - { - case ZLIB_FILEFUNC_SEEK_CUR : - dwMoveMethod = FILE_CURRENT; - break; - case ZLIB_FILEFUNC_SEEK_END : - dwMoveMethod = FILE_END; - break; - case ZLIB_FILEFUNC_SEEK_SET : - dwMoveMethod = FILE_BEGIN; - break; - default: return -1; - } - - if (hFile) - { - LARGE_INTEGER pos; - pos.QuadPart = offset; - if (!MySetFilePointerEx(hFile, pos, NULL, FILE_CURRENT)) - { - DWORD dwErr = GetLastError(); - ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; - ret = -1; - } - else - ret=0; - } - return ret; -} - -int ZCALLBACK win32_close_file_func (voidpf opaque, voidpf stream) -{ - int ret=-1; - - if (stream!=NULL) - { - HANDLE hFile; - hFile = ((WIN32FILE_IOWIN*)stream) -> hf; - if (hFile != NULL) - { - CloseHandle(hFile); - ret=0; - } - free(stream); - } - return ret; -} - -int ZCALLBACK win32_error_file_func (voidpf opaque,voidpf stream) -{ - int ret=-1; - if (stream!=NULL) - { - ret = ((WIN32FILE_IOWIN*)stream) -> error; - } - return ret; -} - -void fill_win32_filefunc (zlib_filefunc_def* pzlib_filefunc_def) -{ - pzlib_filefunc_def->zopen_file = win32_open_file_func; - pzlib_filefunc_def->zread_file = win32_read_file_func; - pzlib_filefunc_def->zwrite_file = win32_write_file_func; - pzlib_filefunc_def->ztell_file = win32_tell_file_func; - pzlib_filefunc_def->zseek_file = win32_seek_file_func; - pzlib_filefunc_def->zclose_file = win32_close_file_func; - pzlib_filefunc_def->zerror_file = win32_error_file_func; - pzlib_filefunc_def->opaque = NULL; -} - -void fill_win32_filefunc64(zlib_filefunc64_def* pzlib_filefunc_def) -{ - pzlib_filefunc_def->zopen64_file = win32_open64_file_func; - pzlib_filefunc_def->zread_file = win32_read_file_func; - pzlib_filefunc_def->zwrite_file = win32_write_file_func; - pzlib_filefunc_def->ztell64_file = win32_tell64_file_func; - pzlib_filefunc_def->zseek64_file = win32_seek64_file_func; - pzlib_filefunc_def->zclose_file = win32_close_file_func; - pzlib_filefunc_def->zerror_file = win32_error_file_func; - pzlib_filefunc_def->opaque = NULL; -} - - -void fill_win32_filefunc64A(zlib_filefunc64_def* pzlib_filefunc_def) -{ - pzlib_filefunc_def->zopen64_file = win32_open64_file_funcA; - pzlib_filefunc_def->zread_file = win32_read_file_func; - pzlib_filefunc_def->zwrite_file = win32_write_file_func; - pzlib_filefunc_def->ztell64_file = win32_tell64_file_func; - pzlib_filefunc_def->zseek64_file = win32_seek64_file_func; - pzlib_filefunc_def->zclose_file = win32_close_file_func; - pzlib_filefunc_def->zerror_file = win32_error_file_func; - pzlib_filefunc_def->opaque = NULL; -} - - -void fill_win32_filefunc64W(zlib_filefunc64_def* pzlib_filefunc_def) -{ - pzlib_filefunc_def->zopen64_file = win32_open64_file_funcW; - pzlib_filefunc_def->zread_file = win32_read_file_func; - pzlib_filefunc_def->zwrite_file = win32_write_file_func; - pzlib_filefunc_def->ztell64_file = win32_tell64_file_func; - pzlib_filefunc_def->zseek64_file = win32_seek64_file_func; - pzlib_filefunc_def->zclose_file = win32_close_file_func; - pzlib_filefunc_def->zerror_file = win32_error_file_func; - pzlib_filefunc_def->opaque = NULL; -} diff --git a/vendor/minizip/iowin32.h b/vendor/minizip/iowin32.h deleted file mode 100644 index 0ca0969a7..000000000 --- a/vendor/minizip/iowin32.h +++ /dev/null @@ -1,28 +0,0 @@ -/* iowin32.h -- IO base function header for compress/uncompress .zip - Version 1.1, February 14h, 2010 - part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) - - Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) - - Modifications for Zip64 support - Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) - - For more info read MiniZip_info.txt - -*/ - -#include - - -#ifdef __cplusplus -extern "C" { -#endif - -void fill_win32_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def)); -void fill_win32_filefunc64 OF((zlib_filefunc64_def* pzlib_filefunc_def)); -void fill_win32_filefunc64A OF((zlib_filefunc64_def* pzlib_filefunc_def)); -void fill_win32_filefunc64W OF((zlib_filefunc64_def* pzlib_filefunc_def)); - -#ifdef __cplusplus -} -#endif diff --git a/vendor/minizip/make_vms.com b/vendor/minizip/make_vms.com deleted file mode 100644 index 9ac13a98f..000000000 --- a/vendor/minizip/make_vms.com +++ /dev/null @@ -1,25 +0,0 @@ -$ if f$search("ioapi.h_orig") .eqs. "" then copy ioapi.h ioapi.h_orig -$ open/write zdef vmsdefs.h -$ copy sys$input: zdef -$ deck -#define unix -#define fill_zlib_filefunc64_32_def_from_filefunc32 fillzffunc64from -#define Write_Zip64EndOfCentralDirectoryLocator Write_Zip64EoDLocator -#define Write_Zip64EndOfCentralDirectoryRecord Write_Zip64EoDRecord -#define Write_EndOfCentralDirectoryRecord Write_EoDRecord -$ eod -$ close zdef -$ copy vmsdefs.h,ioapi.h_orig ioapi.h -$ cc/include=[--]/prefix=all ioapi.c -$ cc/include=[--]/prefix=all miniunz.c -$ cc/include=[--]/prefix=all unzip.c -$ cc/include=[--]/prefix=all minizip.c -$ cc/include=[--]/prefix=all zip.c -$ link miniunz,unzip,ioapi,[--]libz.olb/lib -$ link minizip,zip,ioapi,[--]libz.olb/lib -$ mcr []minizip test minizip_info.txt -$ mcr []miniunz -l test.zip -$ rename minizip_info.txt; minizip_info.txt_old -$ mcr []miniunz test.zip -$ delete test.zip;* -$exit diff --git a/vendor/minizip/miniunz.c b/vendor/minizip/miniunz.c deleted file mode 100644 index 3d65401be..000000000 --- a/vendor/minizip/miniunz.c +++ /dev/null @@ -1,660 +0,0 @@ -/* - miniunz.c - Version 1.1, February 14h, 2010 - sample part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) - - Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) - - Modifications of Unzip for Zip64 - Copyright (C) 2007-2008 Even Rouault - - Modifications for Zip64 support on both zip and unzip - Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) -*/ - -#if (!defined(_WIN32)) && (!defined(WIN32)) && (!defined(__APPLE__)) - #ifndef __USE_FILE_OFFSET64 - #define __USE_FILE_OFFSET64 - #endif - #ifndef __USE_LARGEFILE64 - #define __USE_LARGEFILE64 - #endif - #ifndef _LARGEFILE64_SOURCE - #define _LARGEFILE64_SOURCE - #endif - #ifndef _FILE_OFFSET_BIT - #define _FILE_OFFSET_BIT 64 - #endif -#endif - -#ifdef __APPLE__ -// In darwin and perhaps other BSD variants off_t is a 64 bit value, hence no need for specific 64 bit functions -#define FOPEN_FUNC(filename, mode) fopen(filename, mode) -#define FTELLO_FUNC(stream) ftello(stream) -#define FSEEKO_FUNC(stream, offset, origin) fseeko(stream, offset, origin) -#else -#define FOPEN_FUNC(filename, mode) fopen64(filename, mode) -#define FTELLO_FUNC(stream) ftello64(stream) -#define FSEEKO_FUNC(stream, offset, origin) fseeko64(stream, offset, origin) -#endif - - -#include -#include -#include -#include -#include -#include - -#ifdef _WIN32 -# include -# include -#else -# include -# include -#endif - - -#include "unzip.h" - -#define CASESENSITIVITY (0) -#define WRITEBUFFERSIZE (8192) -#define MAXFILENAME (256) - -#ifdef _WIN32 -#define USEWIN32IOAPI -#include "iowin32.h" -#endif -/* - mini unzip, demo of unzip package - - usage : - Usage : miniunz [-exvlo] file.zip [file_to_extract] [-d extractdir] - - list the file in the zipfile, and print the content of FILE_ID.ZIP or README.TXT - if it exists -*/ - - -/* change_file_date : change the date/time of a file - filename : the filename of the file where date/time must be modified - dosdate : the new date at the MSDos format (4 bytes) - tmu_date : the SAME new date at the tm_unz format */ -void change_file_date(filename,dosdate,tmu_date) - const char *filename; - uLong dosdate; - tm_unz tmu_date; -{ -#ifdef _WIN32 - HANDLE hFile; - FILETIME ftm,ftLocal,ftCreate,ftLastAcc,ftLastWrite; - - hFile = CreateFileA(filename,GENERIC_READ | GENERIC_WRITE, - 0,NULL,OPEN_EXISTING,0,NULL); - GetFileTime(hFile,&ftCreate,&ftLastAcc,&ftLastWrite); - DosDateTimeToFileTime((WORD)(dosdate>>16),(WORD)dosdate,&ftLocal); - LocalFileTimeToFileTime(&ftLocal,&ftm); - SetFileTime(hFile,&ftm,&ftLastAcc,&ftm); - CloseHandle(hFile); -#else -#ifdef unix || __APPLE__ - struct utimbuf ut; - struct tm newdate; - newdate.tm_sec = tmu_date.tm_sec; - newdate.tm_min=tmu_date.tm_min; - newdate.tm_hour=tmu_date.tm_hour; - newdate.tm_mday=tmu_date.tm_mday; - newdate.tm_mon=tmu_date.tm_mon; - if (tmu_date.tm_year > 1900) - newdate.tm_year=tmu_date.tm_year - 1900; - else - newdate.tm_year=tmu_date.tm_year ; - newdate.tm_isdst=-1; - - ut.actime=ut.modtime=mktime(&newdate); - utime(filename,&ut); -#endif -#endif -} - - -/* mymkdir and change_file_date are not 100 % portable - As I don't know well Unix, I wait feedback for the unix portion */ - -int mymkdir(dirname) - const char* dirname; -{ - int ret=0; -#ifdef _WIN32 - ret = _mkdir(dirname); -#elif unix - ret = mkdir (dirname,0775); -#elif __APPLE__ - ret = mkdir (dirname,0775); -#endif - return ret; -} - -int makedir (newdir) - char *newdir; -{ - char *buffer ; - char *p; - int len = (int)strlen(newdir); - - if (len <= 0) - return 0; - - buffer = (char*)malloc(len+1); - if (buffer==NULL) - { - printf("Error allocating memory\n"); - return UNZ_INTERNALERROR; - } - strcpy(buffer,newdir); - - if (buffer[len-1] == '/') { - buffer[len-1] = '\0'; - } - if (mymkdir(buffer) == 0) - { - free(buffer); - return 1; - } - - p = buffer+1; - while (1) - { - char hold; - - while(*p && *p != '\\' && *p != '/') - p++; - hold = *p; - *p = 0; - if ((mymkdir(buffer) == -1) && (errno == ENOENT)) - { - printf("couldn't create directory %s\n",buffer); - free(buffer); - return 0; - } - if (hold == 0) - break; - *p++ = hold; - } - free(buffer); - return 1; -} - -void do_banner() -{ - printf("MiniUnz 1.01b, demo of zLib + Unz package written by Gilles Vollant\n"); - printf("more info at http://www.winimage.com/zLibDll/unzip.html\n\n"); -} - -void do_help() -{ - printf("Usage : miniunz [-e] [-x] [-v] [-l] [-o] [-p password] file.zip [file_to_extr.] [-d extractdir]\n\n" \ - " -e Extract without pathname (junk paths)\n" \ - " -x Extract with pathname\n" \ - " -v list files\n" \ - " -l list files\n" \ - " -d directory to extract into\n" \ - " -o overwrite files without prompting\n" \ - " -p extract crypted file using password\n\n"); -} - -void Display64BitsSize(ZPOS64_T n, int size_char) -{ - /* to avoid compatibility problem , we do here the conversion */ - char number[21]; - int offset=19; - int pos_string = 19; - number[20]=0; - for (;;) { - number[offset]=(char)((n%10)+'0'); - if (number[offset] != '0') - pos_string=offset; - n/=10; - if (offset==0) - break; - offset--; - } - { - int size_display_string = 19-pos_string; - while (size_char > size_display_string) - { - size_char--; - printf(" "); - } - } - - printf("%s",&number[pos_string]); -} - -int do_list(uf) - unzFile uf; -{ - uLong i; - unz_global_info64 gi; - int err; - - err = unzGetGlobalInfo64(uf,&gi); - if (err!=UNZ_OK) - printf("error %d with zipfile in unzGetGlobalInfo \n",err); - printf(" Length Method Size Ratio Date Time CRC-32 Name\n"); - printf(" ------ ------ ---- ----- ---- ---- ------ ----\n"); - for (i=0;i0) - ratio = (uLong)((file_info.compressed_size*100)/file_info.uncompressed_size); - - /* display a '*' if the file is crypted */ - if ((file_info.flag & 1) != 0) - charCrypt='*'; - - if (file_info.compression_method==0) - string_method="Stored"; - else - if (file_info.compression_method==Z_DEFLATED) - { - uInt iLevel=(uInt)((file_info.flag & 0x6)/2); - if (iLevel==0) - string_method="Defl:N"; - else if (iLevel==1) - string_method="Defl:X"; - else if ((iLevel==2) || (iLevel==3)) - string_method="Defl:F"; /* 2:fast , 3 : extra fast*/ - } - else - if (file_info.compression_method==Z_BZIP2ED) - { - string_method="BZip2 "; - } - else - string_method="Unkn. "; - - Display64BitsSize(file_info.uncompressed_size,7); - printf(" %6s%c",string_method,charCrypt); - Display64BitsSize(file_info.compressed_size,7); - printf(" %3lu%% %2.2lu-%2.2lu-%2.2lu %2.2lu:%2.2lu %8.8lx %s\n", - ratio, - (uLong)file_info.tmu_date.tm_mon + 1, - (uLong)file_info.tmu_date.tm_mday, - (uLong)file_info.tmu_date.tm_year % 100, - (uLong)file_info.tmu_date.tm_hour,(uLong)file_info.tmu_date.tm_min, - (uLong)file_info.crc,filename_inzip); - if ((i+1)='a') && (rep<='z')) - rep -= 0x20; - } - while ((rep!='Y') && (rep!='N') && (rep!='A')); - } - - if (rep == 'N') - skip = 1; - - if (rep == 'A') - *popt_overwrite=1; - } - - if ((skip==0) && (err==UNZ_OK)) - { - fout=FOPEN_FUNC(write_filename,"wb"); - /* some zipfile don't contain directory alone before file */ - if ((fout==NULL) && ((*popt_extract_without_path)==0) && - (filename_withoutpath!=(char*)filename_inzip)) - { - char c=*(filename_withoutpath-1); - *(filename_withoutpath-1)='\0'; - makedir(write_filename); - *(filename_withoutpath-1)=c; - fout=FOPEN_FUNC(write_filename,"wb"); - } - - if (fout==NULL) - { - printf("error opening %s\n",write_filename); - } - } - - if (fout!=NULL) - { - printf(" extracting: %s\n",write_filename); - - do - { - err = unzReadCurrentFile(uf,buf,size_buf); - if (err<0) - { - printf("error %d with zipfile in unzReadCurrentFile\n",err); - break; - } - if (err>0) - if (fwrite(buf,err,1,fout)!=1) - { - printf("error in writing extracted file\n"); - err=UNZ_ERRNO; - break; - } - } - while (err>0); - if (fout) - fclose(fout); - - if (err==0) - change_file_date(write_filename,file_info.dosDate, - file_info.tmu_date); - } - - if (err==UNZ_OK) - { - err = unzCloseCurrentFile (uf); - if (err!=UNZ_OK) - { - printf("error %d with zipfile in unzCloseCurrentFile\n",err); - } - } - else - unzCloseCurrentFile(uf); /* don't lose the error */ - } - - free(buf); - return err; -} - - -int do_extract(uf,opt_extract_without_path,opt_overwrite,password) - unzFile uf; - int opt_extract_without_path; - int opt_overwrite; - const char* password; -{ - uLong i; - unz_global_info64 gi; - int err; - FILE* fout=NULL; - - err = unzGetGlobalInfo64(uf,&gi); - if (err!=UNZ_OK) - printf("error %d with zipfile in unzGetGlobalInfo \n",err); - - for (i=0;i insert n+1 empty lines -.\" for manpage-specific macros, see man(7) -.SH NAME -miniunzip - uncompress and examine ZIP archives -.SH SYNOPSIS -.B miniunzip -.RI [ -exvlo ] -zipfile [ files_to_extract ] [-d tempdir] -.SH DESCRIPTION -.B minizip -is a simple tool which allows the extraction of compressed file -archives in the ZIP format used by the MS-DOS utility PKZIP. It was -written as a demonstration of the -.IR zlib (3) -library and therefore lack many of the features of the -.IR unzip (1) -program. -.SH OPTIONS -A number of options are supported. With the exception of -.BI \-d\ tempdir -these must be supplied before any -other arguments and are: -.TP -.BI \-l\ ,\ \-\-v -List the files in the archive without extracting them. -.TP -.B \-o -Overwrite files without prompting for confirmation. -.TP -.B \-x -Extract files (default). -.PP -The -.I zipfile -argument is the name of the archive to process. The next argument can be used -to specify a single file to extract from the archive. - -Lastly, the following option can be specified at the end of the command-line: -.TP -.BI \-d\ tempdir -Extract the archive in the directory -.I tempdir -rather than the current directory. -.SH SEE ALSO -.BR minizip (1), -.BR zlib (3), -.BR unzip (1). -.SH AUTHOR -This program was written by Gilles Vollant. This manual page was -written by Mark Brown . The -d tempdir option -was added by Dirk Eddelbuettel . diff --git a/vendor/minizip/minizip.1 b/vendor/minizip/minizip.1 deleted file mode 100644 index 1154484c1..000000000 --- a/vendor/minizip/minizip.1 +++ /dev/null @@ -1,46 +0,0 @@ -.\" Hey, EMACS: -*- nroff -*- -.TH minizip 1 "May 2, 2001" -.\" Please adjust this date whenever revising the manpage. -.\" -.\" Some roff macros, for reference: -.\" .nh disable hyphenation -.\" .hy enable hyphenation -.\" .ad l left justify -.\" .ad b justify to both left and right margins -.\" .nf disable filling -.\" .fi enable filling -.\" .br insert line break -.\" .sp insert n+1 empty lines -.\" for manpage-specific macros, see man(7) -.SH NAME -minizip - create ZIP archives -.SH SYNOPSIS -.B minizip -.RI [ -o ] -zipfile [ " files" ... ] -.SH DESCRIPTION -.B minizip -is a simple tool which allows the creation of compressed file archives -in the ZIP format used by the MS-DOS utility PKZIP. It was written as -a demonstration of the -.IR zlib (3) -library and therefore lack many of the features of the -.IR zip (1) -program. -.SH OPTIONS -The first argument supplied is the name of the ZIP archive to create or -.RI -o -in which case it is ignored and the second argument treated as the -name of the ZIP file. If the ZIP file already exists it will be -overwritten. -.PP -Subsequent arguments specify a list of files to place in the ZIP -archive. If none are specified then an empty archive will be created. -.SH SEE ALSO -.BR miniunzip (1), -.BR zlib (3), -.BR zip (1). -.SH AUTHOR -This program was written by Gilles Vollant. This manual page was -written by Mark Brown . - diff --git a/vendor/minizip/minizip.c b/vendor/minizip/minizip.c deleted file mode 100644 index 4288962ec..000000000 --- a/vendor/minizip/minizip.c +++ /dev/null @@ -1,520 +0,0 @@ -/* - minizip.c - Version 1.1, February 14h, 2010 - sample part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) - - Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) - - Modifications of Unzip for Zip64 - Copyright (C) 2007-2008 Even Rouault - - Modifications for Zip64 support on both zip and unzip - Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) -*/ - - -#if (!defined(_WIN32)) && (!defined(WIN32)) && (!defined(__APPLE__)) - #ifndef __USE_FILE_OFFSET64 - #define __USE_FILE_OFFSET64 - #endif - #ifndef __USE_LARGEFILE64 - #define __USE_LARGEFILE64 - #endif - #ifndef _LARGEFILE64_SOURCE - #define _LARGEFILE64_SOURCE - #endif - #ifndef _FILE_OFFSET_BIT - #define _FILE_OFFSET_BIT 64 - #endif -#endif - -#ifdef __APPLE__ -// In darwin and perhaps other BSD variants off_t is a 64 bit value, hence no need for specific 64 bit functions -#define FOPEN_FUNC(filename, mode) fopen(filename, mode) -#define FTELLO_FUNC(stream) ftello(stream) -#define FSEEKO_FUNC(stream, offset, origin) fseeko(stream, offset, origin) -#else -#define FOPEN_FUNC(filename, mode) fopen64(filename, mode) -#define FTELLO_FUNC(stream) ftello64(stream) -#define FSEEKO_FUNC(stream, offset, origin) fseeko64(stream, offset, origin) -#endif - - - -#include -#include -#include -#include -#include -#include - -#ifdef _WIN32 -# include -# include -#else -# include -# include -# include -# include -#endif - -#include "zip.h" - -#ifdef _WIN32 - #define USEWIN32IOAPI - #include "iowin32.h" -#endif - - - -#define WRITEBUFFERSIZE (16384) -#define MAXFILENAME (256) - -#ifdef _WIN32 -uLong filetime(f, tmzip, dt) - char *f; /* name of file to get info on */ - tm_zip *tmzip; /* return value: access, modific. and creation times */ - uLong *dt; /* dostime */ -{ - int ret = 0; - { - FILETIME ftLocal; - HANDLE hFind; - WIN32_FIND_DATAA ff32; - - hFind = FindFirstFileA(f,&ff32); - if (hFind != INVALID_HANDLE_VALUE) - { - FileTimeToLocalFileTime(&(ff32.ftLastWriteTime),&ftLocal); - FileTimeToDosDateTime(&ftLocal,((LPWORD)dt)+1,((LPWORD)dt)+0); - FindClose(hFind); - ret = 1; - } - } - return ret; -} -#else -#ifdef unix || __APPLE__ -uLong filetime(f, tmzip, dt) - char *f; /* name of file to get info on */ - tm_zip *tmzip; /* return value: access, modific. and creation times */ - uLong *dt; /* dostime */ -{ - int ret=0; - struct stat s; /* results of stat() */ - struct tm* filedate; - time_t tm_t=0; - - if (strcmp(f,"-")!=0) - { - char name[MAXFILENAME+1]; - int len = strlen(f); - if (len > MAXFILENAME) - len = MAXFILENAME; - - strncpy(name, f,MAXFILENAME-1); - /* strncpy doesnt append the trailing NULL, of the string is too long. */ - name[ MAXFILENAME ] = '\0'; - - if (name[len - 1] == '/') - name[len - 1] = '\0'; - /* not all systems allow stat'ing a file with / appended */ - if (stat(name,&s)==0) - { - tm_t = s.st_mtime; - ret = 1; - } - } - filedate = localtime(&tm_t); - - tmzip->tm_sec = filedate->tm_sec; - tmzip->tm_min = filedate->tm_min; - tmzip->tm_hour = filedate->tm_hour; - tmzip->tm_mday = filedate->tm_mday; - tmzip->tm_mon = filedate->tm_mon ; - tmzip->tm_year = filedate->tm_year; - - return ret; -} -#else -uLong filetime(f, tmzip, dt) - char *f; /* name of file to get info on */ - tm_zip *tmzip; /* return value: access, modific. and creation times */ - uLong *dt; /* dostime */ -{ - return 0; -} -#endif -#endif - - - - -int check_exist_file(filename) - const char* filename; -{ - FILE* ftestexist; - int ret = 1; - ftestexist = FOPEN_FUNC(filename,"rb"); - if (ftestexist==NULL) - ret = 0; - else - fclose(ftestexist); - return ret; -} - -void do_banner() -{ - printf("MiniZip 1.1, demo of zLib + MiniZip64 package, written by Gilles Vollant\n"); - printf("more info on MiniZip at http://www.winimage.com/zLibDll/minizip.html\n\n"); -} - -void do_help() -{ - printf("Usage : minizip [-o] [-a] [-0 to -9] [-p password] [-j] file.zip [files_to_add]\n\n" \ - " -o Overwrite existing file.zip\n" \ - " -a Append to existing file.zip\n" \ - " -0 Store only\n" \ - " -1 Compress faster\n" \ - " -9 Compress better\n\n" \ - " -j exclude path. store only the file name.\n\n"); -} - -/* calculate the CRC32 of a file, - because to encrypt a file, we need known the CRC32 of the file before */ -int getFileCrc(const char* filenameinzip,void*buf,unsigned long size_buf,unsigned long* result_crc) -{ - unsigned long calculate_crc=0; - int err=ZIP_OK; - FILE * fin = FOPEN_FUNC(filenameinzip,"rb"); - - unsigned long size_read = 0; - unsigned long total_read = 0; - if (fin==NULL) - { - err = ZIP_ERRNO; - } - - if (err == ZIP_OK) - do - { - err = ZIP_OK; - size_read = (int)fread(buf,1,size_buf,fin); - if (size_read < size_buf) - if (feof(fin)==0) - { - printf("error in reading %s\n",filenameinzip); - err = ZIP_ERRNO; - } - - if (size_read>0) - calculate_crc = crc32(calculate_crc,buf,size_read); - total_read += size_read; - - } while ((err == ZIP_OK) && (size_read>0)); - - if (fin) - fclose(fin); - - *result_crc=calculate_crc; - printf("file %s crc %lx\n", filenameinzip, calculate_crc); - return err; -} - -int isLargeFile(const char* filename) -{ - int largeFile = 0; - ZPOS64_T pos = 0; - FILE* pFile = FOPEN_FUNC(filename, "rb"); - - if(pFile != NULL) - { - int n = FSEEKO_FUNC(pFile, 0, SEEK_END); - pos = FTELLO_FUNC(pFile); - - printf("File : %s is %lld bytes\n", filename, pos); - - if(pos >= 0xffffffff) - largeFile = 1; - - fclose(pFile); - } - - return largeFile; -} - -int main(argc,argv) - int argc; - char *argv[]; -{ - int i; - int opt_overwrite=0; - int opt_compress_level=Z_DEFAULT_COMPRESSION; - int opt_exclude_path=0; - int zipfilenamearg = 0; - char filename_try[MAXFILENAME+16]; - int zipok; - int err=0; - int size_buf=0; - void* buf=NULL; - const char* password=NULL; - - - do_banner(); - if (argc==1) - { - do_help(); - return 0; - } - else - { - for (i=1;i='0') && (c<='9')) - opt_compress_level = c-'0'; - if ((c=='j') || (c=='J')) - opt_exclude_path = 1; - - if (((c=='p') || (c=='P')) && (i+1='a') && (rep<='z')) - rep -= 0x20; - } - while ((rep!='Y') && (rep!='N') && (rep!='A')); - if (rep=='N') - zipok = 0; - if (rep=='A') - opt_overwrite = 2; - } - } - - if (zipok==1) - { - zipFile zf; - int errclose; -# ifdef USEWIN32IOAPI - zlib_filefunc64_def ffunc; - fill_win32_filefunc64A(&ffunc); - zf = zipOpen2_64(filename_try,(opt_overwrite==2) ? 2 : 0,NULL,&ffunc); -# else - zf = zipOpen64(filename_try,(opt_overwrite==2) ? 2 : 0); -# endif - - if (zf == NULL) - { - printf("error opening %s\n",filename_try); - err= ZIP_ERRNO; - } - else - printf("creating %s\n",filename_try); - - for (i=zipfilenamearg+1;(i='0') || (argv[i][1]<='9'))) && - (strlen(argv[i]) == 2))) - { - FILE * fin; - int size_read; - const char* filenameinzip = argv[i]; - const char *savefilenameinzip; - zip_fileinfo zi; - unsigned long crcFile=0; - int zip64 = 0; - - zi.tmz_date.tm_sec = zi.tmz_date.tm_min = zi.tmz_date.tm_hour = - zi.tmz_date.tm_mday = zi.tmz_date.tm_mon = zi.tmz_date.tm_year = 0; - zi.dosDate = 0; - zi.internal_fa = 0; - zi.external_fa = 0; - filetime(filenameinzip,&zi.tmz_date,&zi.dosDate); - -/* - err = zipOpenNewFileInZip(zf,filenameinzip,&zi, - NULL,0,NULL,0,NULL / * comment * /, - (opt_compress_level != 0) ? Z_DEFLATED : 0, - opt_compress_level); -*/ - if ((password != NULL) && (err==ZIP_OK)) - err = getFileCrc(filenameinzip,buf,size_buf,&crcFile); - - zip64 = isLargeFile(filenameinzip); - - /* The path name saved, should not include a leading slash. */ - /*if it did, windows/xp and dynazip couldn't read the zip file. */ - savefilenameinzip = filenameinzip; - while( savefilenameinzip[0] == '\\' || savefilenameinzip[0] == '/' ) - { - savefilenameinzip++; - } - - /*should the zip file contain any path at all?*/ - if( opt_exclude_path ) - { - const char *tmpptr; - const char *lastslash = 0; - for( tmpptr = savefilenameinzip; *tmpptr; tmpptr++) - { - if( *tmpptr == '\\' || *tmpptr == '/') - { - lastslash = tmpptr; - } - } - if( lastslash != NULL ) - { - savefilenameinzip = lastslash+1; // base filename follows last slash. - } - } - - /**/ - err = zipOpenNewFileInZip3_64(zf,savefilenameinzip,&zi, - NULL,0,NULL,0,NULL /* comment*/, - (opt_compress_level != 0) ? Z_DEFLATED : 0, - opt_compress_level,0, - /* -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, */ - -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, - password,crcFile, zip64); - - if (err != ZIP_OK) - printf("error in opening %s in zipfile\n",filenameinzip); - else - { - fin = FOPEN_FUNC(filenameinzip,"rb"); - if (fin==NULL) - { - err=ZIP_ERRNO; - printf("error in opening %s for reading\n",filenameinzip); - } - } - - if (err == ZIP_OK) - do - { - err = ZIP_OK; - size_read = (int)fread(buf,1,size_buf,fin); - if (size_read < size_buf) - if (feof(fin)==0) - { - printf("error in reading %s\n",filenameinzip); - err = ZIP_ERRNO; - } - - if (size_read>0) - { - err = zipWriteInFileInZip (zf,buf,size_read); - if (err<0) - { - printf("error in writing %s in the zipfile\n", - filenameinzip); - } - - } - } while ((err == ZIP_OK) && (size_read>0)); - - if (fin) - fclose(fin); - - if (err<0) - err=ZIP_ERRNO; - else - { - err = zipCloseFileInZip(zf); - if (err!=ZIP_OK) - printf("error in closing %s in the zipfile\n", - filenameinzip); - } - } - } - errclose = zipClose(zf,NULL); - if (errclose != ZIP_OK) - printf("error in closing %s\n",filename_try); - } - else - { - do_help(); - } - - free(buf); - return 0; -} diff --git a/vendor/minizip/minizip.pc.in b/vendor/minizip/minizip.pc.in deleted file mode 100644 index 69b5b7fdc..000000000 --- a/vendor/minizip/minizip.pc.in +++ /dev/null @@ -1,12 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@/minizip - -Name: minizip -Description: Minizip zip file manipulation library -Requires: -Version: @PACKAGE_VERSION@ -Libs: -L${libdir} -lminizip -Libs.private: -lz -Cflags: -I${includedir} diff --git a/vendor/minizip/mztools.c b/vendor/minizip/mztools.c deleted file mode 100644 index 96891c2e0..000000000 --- a/vendor/minizip/mztools.c +++ /dev/null @@ -1,291 +0,0 @@ -/* - Additional tools for Minizip - Code: Xavier Roche '2004 - License: Same as ZLIB (www.gzip.org) -*/ - -/* Code */ -#include -#include -#include -#include "zlib.h" -#include "unzip.h" - -#define READ_8(adr) ((unsigned char)*(adr)) -#define READ_16(adr) ( READ_8(adr) | (READ_8(adr+1) << 8) ) -#define READ_32(adr) ( READ_16(adr) | (READ_16((adr)+2) << 16) ) - -#define WRITE_8(buff, n) do { \ - *((unsigned char*)(buff)) = (unsigned char) ((n) & 0xff); \ -} while(0) -#define WRITE_16(buff, n) do { \ - WRITE_8((unsigned char*)(buff), n); \ - WRITE_8(((unsigned char*)(buff)) + 1, (n) >> 8); \ -} while(0) -#define WRITE_32(buff, n) do { \ - WRITE_16((unsigned char*)(buff), (n) & 0xffff); \ - WRITE_16((unsigned char*)(buff) + 2, (n) >> 16); \ -} while(0) - -extern int ZEXPORT unzRepair(file, fileOut, fileOutTmp, nRecovered, bytesRecovered) -const char* file; -const char* fileOut; -const char* fileOutTmp; -uLong* nRecovered; -uLong* bytesRecovered; -{ - int err = Z_OK; - FILE* fpZip = fopen(file, "rb"); - FILE* fpOut = fopen(fileOut, "wb"); - FILE* fpOutCD = fopen(fileOutTmp, "wb"); - if (fpZip != NULL && fpOut != NULL) { - int entries = 0; - uLong totalBytes = 0; - char header[30]; - char filename[1024]; - char extra[1024]; - int offset = 0; - int offsetCD = 0; - while ( fread(header, 1, 30, fpZip) == 30 ) { - int currentOffset = offset; - - /* File entry */ - if (READ_32(header) == 0x04034b50) { - unsigned int version = READ_16(header + 4); - unsigned int gpflag = READ_16(header + 6); - unsigned int method = READ_16(header + 8); - unsigned int filetime = READ_16(header + 10); - unsigned int filedate = READ_16(header + 12); - unsigned int crc = READ_32(header + 14); /* crc */ - unsigned int cpsize = READ_32(header + 18); /* compressed size */ - unsigned int uncpsize = READ_32(header + 22); /* uncompressed sz */ - unsigned int fnsize = READ_16(header + 26); /* file name length */ - unsigned int extsize = READ_16(header + 28); /* extra field length */ - filename[0] = extra[0] = '\0'; - - /* Header */ - if (fwrite(header, 1, 30, fpOut) == 30) { - offset += 30; - } else { - err = Z_ERRNO; - break; - } - - /* Filename */ - if (fnsize > 0) { - if (fnsize < sizeof(filename)) { - if (fread(filename, 1, fnsize, fpZip) == fnsize) { - if (fwrite(filename, 1, fnsize, fpOut) == fnsize) { - offset += fnsize; - } else { - err = Z_ERRNO; - break; - } - } else { - err = Z_ERRNO; - break; - } - } else { - err = Z_ERRNO; - break; - } - } else { - err = Z_STREAM_ERROR; - break; - } - - /* Extra field */ - if (extsize > 0) { - if (extsize < sizeof(extra)) { - if (fread(extra, 1, extsize, fpZip) == extsize) { - if (fwrite(extra, 1, extsize, fpOut) == extsize) { - offset += extsize; - } else { - err = Z_ERRNO; - break; - } - } else { - err = Z_ERRNO; - break; - } - } else { - err = Z_ERRNO; - break; - } - } - - /* Data */ - { - int dataSize = cpsize; - if (dataSize == 0) { - dataSize = uncpsize; - } - if (dataSize > 0) { - char* data = malloc(dataSize); - if (data != NULL) { - if ((int)fread(data, 1, dataSize, fpZip) == dataSize) { - if ((int)fwrite(data, 1, dataSize, fpOut) == dataSize) { - offset += dataSize; - totalBytes += dataSize; - } else { - err = Z_ERRNO; - } - } else { - err = Z_ERRNO; - } - free(data); - if (err != Z_OK) { - break; - } - } else { - err = Z_MEM_ERROR; - break; - } - } - } - - /* Central directory entry */ - { - char header[46]; - char* comment = ""; - int comsize = (int) strlen(comment); - WRITE_32(header, 0x02014b50); - WRITE_16(header + 4, version); - WRITE_16(header + 6, version); - WRITE_16(header + 8, gpflag); - WRITE_16(header + 10, method); - WRITE_16(header + 12, filetime); - WRITE_16(header + 14, filedate); - WRITE_32(header + 16, crc); - WRITE_32(header + 20, cpsize); - WRITE_32(header + 24, uncpsize); - WRITE_16(header + 28, fnsize); - WRITE_16(header + 30, extsize); - WRITE_16(header + 32, comsize); - WRITE_16(header + 34, 0); /* disk # */ - WRITE_16(header + 36, 0); /* int attrb */ - WRITE_32(header + 38, 0); /* ext attrb */ - WRITE_32(header + 42, currentOffset); - /* Header */ - if (fwrite(header, 1, 46, fpOutCD) == 46) { - offsetCD += 46; - - /* Filename */ - if (fnsize > 0) { - if (fwrite(filename, 1, fnsize, fpOutCD) == fnsize) { - offsetCD += fnsize; - } else { - err = Z_ERRNO; - break; - } - } else { - err = Z_STREAM_ERROR; - break; - } - - /* Extra field */ - if (extsize > 0) { - if (fwrite(extra, 1, extsize, fpOutCD) == extsize) { - offsetCD += extsize; - } else { - err = Z_ERRNO; - break; - } - } - - /* Comment field */ - if (comsize > 0) { - if ((int)fwrite(comment, 1, comsize, fpOutCD) == comsize) { - offsetCD += comsize; - } else { - err = Z_ERRNO; - break; - } - } - - - } else { - err = Z_ERRNO; - break; - } - } - - /* Success */ - entries++; - - } else { - break; - } - } - - /* Final central directory */ - { - int entriesZip = entries; - char header[22]; - char* comment = ""; // "ZIP File recovered by zlib/minizip/mztools"; - int comsize = (int) strlen(comment); - if (entriesZip > 0xffff) { - entriesZip = 0xffff; - } - WRITE_32(header, 0x06054b50); - WRITE_16(header + 4, 0); /* disk # */ - WRITE_16(header + 6, 0); /* disk # */ - WRITE_16(header + 8, entriesZip); /* hack */ - WRITE_16(header + 10, entriesZip); /* hack */ - WRITE_32(header + 12, offsetCD); /* size of CD */ - WRITE_32(header + 16, offset); /* offset to CD */ - WRITE_16(header + 20, comsize); /* comment */ - - /* Header */ - if (fwrite(header, 1, 22, fpOutCD) == 22) { - - /* Comment field */ - if (comsize > 0) { - if ((int)fwrite(comment, 1, comsize, fpOutCD) != comsize) { - err = Z_ERRNO; - } - } - - } else { - err = Z_ERRNO; - } - } - - /* Final merge (file + central directory) */ - fclose(fpOutCD); - if (err == Z_OK) { - fpOutCD = fopen(fileOutTmp, "rb"); - if (fpOutCD != NULL) { - int nRead; - char buffer[8192]; - while ( (nRead = (int)fread(buffer, 1, sizeof(buffer), fpOutCD)) > 0) { - if ((int)fwrite(buffer, 1, nRead, fpOut) != nRead) { - err = Z_ERRNO; - break; - } - } - fclose(fpOutCD); - } - } - - /* Close */ - fclose(fpZip); - fclose(fpOut); - - /* Wipe temporary file */ - (void)remove(fileOutTmp); - - /* Number of recovered entries */ - if (err == Z_OK) { - if (nRecovered != NULL) { - *nRecovered = entries; - } - if (bytesRecovered != NULL) { - *bytesRecovered = totalBytes; - } - } - } else { - err = Z_STREAM_ERROR; - } - return err; -} diff --git a/vendor/minizip/mztools.h b/vendor/minizip/mztools.h deleted file mode 100644 index a49a426ec..000000000 --- a/vendor/minizip/mztools.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - Additional tools for Minizip - Code: Xavier Roche '2004 - License: Same as ZLIB (www.gzip.org) -*/ - -#ifndef _zip_tools_H -#define _zip_tools_H - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef _ZLIB_H -#include "zlib.h" -#endif - -#include "unzip.h" - -/* Repair a ZIP file (missing central directory) - file: file to recover - fileOut: output file after recovery - fileOutTmp: temporary file name used for recovery -*/ -extern int ZEXPORT unzRepair(const char* file, - const char* fileOut, - const char* fileOutTmp, - uLong* nRecovered, - uLong* bytesRecovered); - - -#ifdef __cplusplus -} -#endif - - -#endif diff --git a/vendor/minizip/unzip.c b/vendor/minizip/unzip.c deleted file mode 100644 index 909350435..000000000 --- a/vendor/minizip/unzip.c +++ /dev/null @@ -1,2125 +0,0 @@ -/* unzip.c -- IO for uncompress .zip files using zlib - Version 1.1, February 14h, 2010 - part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) - - Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) - - Modifications of Unzip for Zip64 - Copyright (C) 2007-2008 Even Rouault - - Modifications for Zip64 support on both zip and unzip - Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) - - For more info read MiniZip_info.txt - - - ------------------------------------------------------------------------------------ - Decryption code comes from crypt.c by Info-ZIP but has been greatly reduced in terms of - compatibility with older software. The following is from the original crypt.c. - Code woven in by Terry Thorsen 1/2003. - - Copyright (c) 1990-2000 Info-ZIP. All rights reserved. - - See the accompanying file LICENSE, version 2000-Apr-09 or later - (the contents of which are also included in zip.h) for terms of use. - If, for some reason, all these files are missing, the Info-ZIP license - also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html - - crypt.c (full version) by Info-ZIP. Last revised: [see crypt.h] - - The encryption/decryption parts of this source code (as opposed to the - non-echoing password parts) were originally written in Europe. The - whole source package can be freely distributed, including from the USA. - (Prior to January 2000, re-export from the US was a violation of US law.) - - This encryption code is a direct transcription of the algorithm from - Roger Schlafly, described by Phil Katz in the file appnote.txt. This - file (appnote.txt) is distributed with the PKZIP program (even in the - version without encryption capabilities). - - ------------------------------------------------------------------------------------ - - Changes in unzip.c - - 2007-2008 - Even Rouault - Addition of cpl_unzGetCurrentFileZStreamPos - 2007-2008 - Even Rouault - Decoration of symbol names unz* -> cpl_unz* - 2007-2008 - Even Rouault - Remove old C style function prototypes - 2007-2008 - Even Rouault - Add unzip support for ZIP64 - - Copyright (C) 2007-2008 Even Rouault - - - Oct-2009 - Mathias Svensson - Removed cpl_* from symbol names (Even Rouault added them but since this is now moved to a new project (minizip64) I renamed them again). - Oct-2009 - Mathias Svensson - Fixed problem if uncompressed size was > 4G and compressed size was <4G - should only read the compressed/uncompressed size from the Zip64 format if - the size from normal header was 0xFFFFFFFF - Oct-2009 - Mathias Svensson - Applied some bug fixes from paches recived from Gilles Vollant - Oct-2009 - Mathias Svensson - Applied support to unzip files with compression mathod BZIP2 (bzip2 lib is required) - Patch created by Daniel Borca - - Jan-2010 - back to unzip and minizip 1.0 name scheme, with compatibility layer - - Copyright (C) 1998 - 2010 Gilles Vollant, Even Rouault, Mathias Svensson - -*/ - - -#include -#include -#include - -#ifndef NOUNCRYPT - #define NOUNCRYPT -#endif - -#include "zlib.h" -#include "unzip.h" - -#ifdef STDC -# include -# include -# include -#endif -#ifdef NO_ERRNO_H - extern int errno; -#else -# include -#endif - - -#ifndef local -# define local static -#endif -/* compile with -Dlocal if your debugger can't find static symbols */ - - -#ifndef CASESENSITIVITYDEFAULT_NO -# if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES) -# define CASESENSITIVITYDEFAULT_NO -# endif -#endif - - -#ifndef UNZ_BUFSIZE -#define UNZ_BUFSIZE (16384) -#endif - -#ifndef UNZ_MAXFILENAMEINZIP -#define UNZ_MAXFILENAMEINZIP (256) -#endif - -#ifndef ALLOC -# define ALLOC(size) (malloc(size)) -#endif -#ifndef TRYFREE -# define TRYFREE(p) {if (p) free(p);} -#endif - -#define SIZECENTRALDIRITEM (0x2e) -#define SIZEZIPLOCALHEADER (0x1e) - - -const char unz_copyright[] = - " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll"; - -/* unz_file_info_interntal contain internal info about a file in zipfile*/ -typedef struct unz_file_info64_internal_s -{ - ZPOS64_T offset_curfile;/* relative offset of local header 8 bytes */ -} unz_file_info64_internal; - - -/* file_in_zip_read_info_s contain internal information about a file in zipfile, - when reading and decompress it */ -typedef struct -{ - char *read_buffer; /* internal buffer for compressed data */ - z_stream stream; /* zLib stream structure for inflate */ - -#ifdef HAVE_BZIP2 - bz_stream bstream; /* bzLib stream structure for bziped */ -#endif - - ZPOS64_T pos_in_zipfile; /* position in byte on the zipfile, for fseek*/ - uLong stream_initialised; /* flag set if stream structure is initialised*/ - - ZPOS64_T offset_local_extrafield;/* offset of the local extra field */ - uInt size_local_extrafield;/* size of the local extra field */ - ZPOS64_T pos_local_extrafield; /* position in the local extra field in read*/ - ZPOS64_T total_out_64; - - uLong crc32; /* crc32 of all data uncompressed */ - uLong crc32_wait; /* crc32 we must obtain after decompress all */ - ZPOS64_T rest_read_compressed; /* number of byte to be decompressed */ - ZPOS64_T rest_read_uncompressed;/*number of byte to be obtained after decomp*/ - zlib_filefunc64_32_def z_filefunc; - voidpf filestream; /* io structore of the zipfile */ - uLong compression_method; /* compression method (0==store) */ - ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ - int raw; -} file_in_zip64_read_info_s; - - -/* unz64_s contain internal information about the zipfile -*/ -typedef struct -{ - zlib_filefunc64_32_def z_filefunc; - int is64bitOpenFunction; - voidpf filestream; /* io structore of the zipfile */ - unz_global_info64 gi; /* public global information */ - ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ - ZPOS64_T num_file; /* number of the current file in the zipfile*/ - ZPOS64_T pos_in_central_dir; /* pos of the current file in the central dir*/ - ZPOS64_T current_file_ok; /* flag about the usability of the current file*/ - ZPOS64_T central_pos; /* position of the beginning of the central dir*/ - - ZPOS64_T size_central_dir; /* size of the central directory */ - ZPOS64_T offset_central_dir; /* offset of start of central directory with - respect to the starting disk number */ - - unz_file_info64 cur_file_info; /* public info about the current file in zip*/ - unz_file_info64_internal cur_file_info_internal; /* private info about it*/ - file_in_zip64_read_info_s* pfile_in_zip_read; /* structure about the current - file if we are decompressing it */ - int encrypted; - - int isZip64; - -# ifndef NOUNCRYPT - unsigned long keys[3]; /* keys defining the pseudo-random sequence */ - const z_crc_t* pcrc_32_tab; -# endif -} unz64_s; - - -#ifndef NOUNCRYPT -#include "crypt.h" -#endif - -/* =========================================================================== - Read a byte from a gz_stream; update next_in and avail_in. Return EOF - for end of file. - IN assertion: the stream s has been sucessfully opened for reading. -*/ - - -local int unz64local_getByte OF(( - const zlib_filefunc64_32_def* pzlib_filefunc_def, - voidpf filestream, - int *pi)); - -local int unz64local_getByte(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, int *pi) -{ - unsigned char c; - int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,&c,1); - if (err==1) - { - *pi = (int)c; - return UNZ_OK; - } - else - { - if (ZERROR64(*pzlib_filefunc_def,filestream)) - return UNZ_ERRNO; - else - return UNZ_EOF; - } -} - - -/* =========================================================================== - Reads a long in LSB order from the given gz_stream. Sets -*/ -local int unz64local_getShort OF(( - const zlib_filefunc64_32_def* pzlib_filefunc_def, - voidpf filestream, - uLong *pX)); - -local int unz64local_getShort (const zlib_filefunc64_32_def* pzlib_filefunc_def, - voidpf filestream, - uLong *pX) -{ - uLong x ; - int i = 0; - int err; - - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x = (uLong)i; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x |= ((uLong)i)<<8; - - if (err==UNZ_OK) - *pX = x; - else - *pX = 0; - return err; -} - -local int unz64local_getLong OF(( - const zlib_filefunc64_32_def* pzlib_filefunc_def, - voidpf filestream, - uLong *pX)); - -local int unz64local_getLong (const zlib_filefunc64_32_def* pzlib_filefunc_def, - voidpf filestream, - uLong *pX) -{ - uLong x ; - int i = 0; - int err; - - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x = (uLong)i; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x |= ((uLong)i)<<8; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x |= ((uLong)i)<<16; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x += ((uLong)i)<<24; - - if (err==UNZ_OK) - *pX = x; - else - *pX = 0; - return err; -} - -local int unz64local_getLong64 OF(( - const zlib_filefunc64_32_def* pzlib_filefunc_def, - voidpf filestream, - ZPOS64_T *pX)); - - -local int unz64local_getLong64 (const zlib_filefunc64_32_def* pzlib_filefunc_def, - voidpf filestream, - ZPOS64_T *pX) -{ - ZPOS64_T x ; - int i = 0; - int err; - - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x = (ZPOS64_T)i; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x |= ((ZPOS64_T)i)<<8; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x |= ((ZPOS64_T)i)<<16; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x |= ((ZPOS64_T)i)<<24; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x |= ((ZPOS64_T)i)<<32; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x |= ((ZPOS64_T)i)<<40; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x |= ((ZPOS64_T)i)<<48; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x |= ((ZPOS64_T)i)<<56; - - if (err==UNZ_OK) - *pX = x; - else - *pX = 0; - return err; -} - -/* My own strcmpi / strcasecmp */ -local int strcmpcasenosensitive_internal (const char* fileName1, const char* fileName2) -{ - for (;;) - { - char c1=*(fileName1++); - char c2=*(fileName2++); - if ((c1>='a') && (c1<='z')) - c1 -= 0x20; - if ((c2>='a') && (c2<='z')) - c2 -= 0x20; - if (c1=='\0') - return ((c2=='\0') ? 0 : -1); - if (c2=='\0') - return 1; - if (c1c2) - return 1; - } -} - - -#ifdef CASESENSITIVITYDEFAULT_NO -#define CASESENSITIVITYDEFAULTVALUE 2 -#else -#define CASESENSITIVITYDEFAULTVALUE 1 -#endif - -#ifndef STRCMPCASENOSENTIVEFUNCTION -#define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal -#endif - -/* - Compare two filename (fileName1,fileName2). - If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) - If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi - or strcasecmp) - If iCaseSenisivity = 0, case sensitivity is defaut of your operating system - (like 1 on Unix, 2 on Windows) - -*/ -extern int ZEXPORT unzStringFileNameCompare (const char* fileName1, - const char* fileName2, - int iCaseSensitivity) - -{ - if (iCaseSensitivity==0) - iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE; - - if (iCaseSensitivity==1) - return strcmp(fileName1,fileName2); - - return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2); -} - -#ifndef BUFREADCOMMENT -#define BUFREADCOMMENT (0x400) -#endif - -/* - Locate the Central directory of a zipfile (at the end, just before - the global comment) -*/ -local ZPOS64_T unz64local_SearchCentralDir OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)); -local ZPOS64_T unz64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) -{ - unsigned char* buf; - ZPOS64_T uSizeFile; - ZPOS64_T uBackRead; - ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */ - ZPOS64_T uPosFound=0; - - if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) - return 0; - - - uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream); - - if (uMaxBack>uSizeFile) - uMaxBack = uSizeFile; - - buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); - if (buf==NULL) - return 0; - - uBackRead = 4; - while (uBackReaduMaxBack) - uBackRead = uMaxBack; - else - uBackRead+=BUFREADCOMMENT; - uReadPos = uSizeFile-uBackRead ; - - uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? - (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos); - if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) - break; - - if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) - break; - - for (i=(int)uReadSize-3; (i--)>0;) - if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && - ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06)) - { - uPosFound = uReadPos+i; - break; - } - - if (uPosFound!=0) - break; - } - TRYFREE(buf); - return uPosFound; -} - - -/* - Locate the Central directory 64 of a zipfile (at the end, just before - the global comment) -*/ -local ZPOS64_T unz64local_SearchCentralDir64 OF(( - const zlib_filefunc64_32_def* pzlib_filefunc_def, - voidpf filestream)); - -local ZPOS64_T unz64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib_filefunc_def, - voidpf filestream) -{ - unsigned char* buf; - ZPOS64_T uSizeFile; - ZPOS64_T uBackRead; - ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */ - ZPOS64_T uPosFound=0; - uLong uL; - ZPOS64_T relativeOffset; - - if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) - return 0; - - - uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream); - - if (uMaxBack>uSizeFile) - uMaxBack = uSizeFile; - - buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); - if (buf==NULL) - return 0; - - uBackRead = 4; - while (uBackReaduMaxBack) - uBackRead = uMaxBack; - else - uBackRead+=BUFREADCOMMENT; - uReadPos = uSizeFile-uBackRead ; - - uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? - (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos); - if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) - break; - - if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) - break; - - for (i=(int)uReadSize-3; (i--)>0;) - if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && - ((*(buf+i+2))==0x06) && ((*(buf+i+3))==0x07)) - { - uPosFound = uReadPos+i; - break; - } - - if (uPosFound!=0) - break; - } - TRYFREE(buf); - if (uPosFound == 0) - return 0; - - /* Zip64 end of central directory locator */ - if (ZSEEK64(*pzlib_filefunc_def,filestream, uPosFound,ZLIB_FILEFUNC_SEEK_SET)!=0) - return 0; - - /* the signature, already checked */ - if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK) - return 0; - - /* number of the disk with the start of the zip64 end of central directory */ - if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK) - return 0; - if (uL != 0) - return 0; - - /* relative offset of the zip64 end of central directory record */ - if (unz64local_getLong64(pzlib_filefunc_def,filestream,&relativeOffset)!=UNZ_OK) - return 0; - - /* total number of disks */ - if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK) - return 0; - if (uL != 1) - return 0; - - /* Goto end of central directory record */ - if (ZSEEK64(*pzlib_filefunc_def,filestream, relativeOffset,ZLIB_FILEFUNC_SEEK_SET)!=0) - return 0; - - /* the signature */ - if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK) - return 0; - - if (uL != 0x06064b50) - return 0; - - return relativeOffset; -} - -/* - Open a Zip file. path contain the full pathname (by example, - on a Windows NT computer "c:\\test\\zlib114.zip" or on an Unix computer - "zlib/zlib114.zip". - If the zipfile cannot be opened (file doesn't exist or in not valid), the - return value is NULL. - Else, the return value is a unzFile Handle, usable with other function - of this unzip package. -*/ -local unzFile unzOpenInternal (const void *path, - zlib_filefunc64_32_def* pzlib_filefunc64_32_def, - int is64bitOpenFunction) -{ - unz64_s us; - unz64_s *s; - ZPOS64_T central_pos; - uLong uL; - - uLong number_disk; /* number of the current dist, used for - spaning ZIP, unsupported, always 0*/ - uLong number_disk_with_CD; /* number the the disk with central dir, used - for spaning ZIP, unsupported, always 0*/ - ZPOS64_T number_entry_CD; /* total number of entries in - the central dir - (same than number_entry on nospan) */ - - int err=UNZ_OK; - - if (unz_copyright[0]!=' ') - return NULL; - - us.z_filefunc.zseek32_file = NULL; - us.z_filefunc.ztell32_file = NULL; - if (pzlib_filefunc64_32_def==NULL) - fill_fopen64_filefunc(&us.z_filefunc.zfile_func64); - else - us.z_filefunc = *pzlib_filefunc64_32_def; - us.is64bitOpenFunction = is64bitOpenFunction; - - - - us.filestream = ZOPEN64(us.z_filefunc, - path, - ZLIB_FILEFUNC_MODE_READ | - ZLIB_FILEFUNC_MODE_EXISTING); - if (us.filestream==NULL) - return NULL; - - central_pos = unz64local_SearchCentralDir64(&us.z_filefunc,us.filestream); - if (central_pos) - { - uLong uS; - ZPOS64_T uL64; - - us.isZip64 = 1; - - if (ZSEEK64(us.z_filefunc, us.filestream, - central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0) - err=UNZ_ERRNO; - - /* the signature, already checked */ - if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) - err=UNZ_ERRNO; - - /* size of zip64 end of central directory record */ - if (unz64local_getLong64(&us.z_filefunc, us.filestream,&uL64)!=UNZ_OK) - err=UNZ_ERRNO; - - /* version made by */ - if (unz64local_getShort(&us.z_filefunc, us.filestream,&uS)!=UNZ_OK) - err=UNZ_ERRNO; - - /* version needed to extract */ - if (unz64local_getShort(&us.z_filefunc, us.filestream,&uS)!=UNZ_OK) - err=UNZ_ERRNO; - - /* number of this disk */ - if (unz64local_getLong(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK) - err=UNZ_ERRNO; - - /* number of the disk with the start of the central directory */ - if (unz64local_getLong(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK) - err=UNZ_ERRNO; - - /* total number of entries in the central directory on this disk */ - if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK) - err=UNZ_ERRNO; - - /* total number of entries in the central directory */ - if (unz64local_getLong64(&us.z_filefunc, us.filestream,&number_entry_CD)!=UNZ_OK) - err=UNZ_ERRNO; - - if ((number_entry_CD!=us.gi.number_entry) || - (number_disk_with_CD!=0) || - (number_disk!=0)) - err=UNZ_BADZIPFILE; - - /* size of the central directory */ - if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.size_central_dir)!=UNZ_OK) - err=UNZ_ERRNO; - - /* offset of start of central directory with respect to the - starting disk number */ - if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK) - err=UNZ_ERRNO; - - us.gi.size_comment = 0; - } - else - { - central_pos = unz64local_SearchCentralDir(&us.z_filefunc,us.filestream); - if (central_pos==0) - err=UNZ_ERRNO; - - us.isZip64 = 0; - - if (ZSEEK64(us.z_filefunc, us.filestream, - central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0) - err=UNZ_ERRNO; - - /* the signature, already checked */ - if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) - err=UNZ_ERRNO; - - /* number of this disk */ - if (unz64local_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK) - err=UNZ_ERRNO; - - /* number of the disk with the start of the central directory */ - if (unz64local_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK) - err=UNZ_ERRNO; - - /* total number of entries in the central dir on this disk */ - if (unz64local_getShort(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) - err=UNZ_ERRNO; - us.gi.number_entry = uL; - - /* total number of entries in the central dir */ - if (unz64local_getShort(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) - err=UNZ_ERRNO; - number_entry_CD = uL; - - if ((number_entry_CD!=us.gi.number_entry) || - (number_disk_with_CD!=0) || - (number_disk!=0)) - err=UNZ_BADZIPFILE; - - /* size of the central directory */ - if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) - err=UNZ_ERRNO; - us.size_central_dir = uL; - - /* offset of start of central directory with respect to the - starting disk number */ - if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) - err=UNZ_ERRNO; - us.offset_central_dir = uL; - - /* zipfile comment length */ - if (unz64local_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK) - err=UNZ_ERRNO; - } - - if ((central_pospfile_in_zip_read!=NULL) - unzCloseCurrentFile(file); - - ZCLOSE64(s->z_filefunc, s->filestream); - TRYFREE(s); - return UNZ_OK; -} - - -/* - Write info about the ZipFile in the *pglobal_info structure. - No preparation of the structure is needed - return UNZ_OK if there is no problem. */ -extern int ZEXPORT unzGetGlobalInfo64 (unzFile file, unz_global_info64* pglobal_info) -{ - unz64_s* s; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz64_s*)file; - *pglobal_info=s->gi; - return UNZ_OK; -} - -extern int ZEXPORT unzGetGlobalInfo (unzFile file, unz_global_info* pglobal_info32) -{ - unz64_s* s; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz64_s*)file; - /* to do : check if number_entry is not truncated */ - pglobal_info32->number_entry = (uLong)s->gi.number_entry; - pglobal_info32->size_comment = s->gi.size_comment; - return UNZ_OK; -} -/* - Translate date/time from Dos format to tm_unz (readable more easilty) -*/ -local void unz64local_DosDateToTmuDate (ZPOS64_T ulDosDate, tm_unz* ptm) -{ - ZPOS64_T uDate; - uDate = (ZPOS64_T)(ulDosDate>>16); - ptm->tm_mday = (uInt)(uDate&0x1f) ; - ptm->tm_mon = (uInt)((((uDate)&0x1E0)/0x20)-1) ; - ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ; - - ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800); - ptm->tm_min = (uInt) ((ulDosDate&0x7E0)/0x20) ; - ptm->tm_sec = (uInt) (2*(ulDosDate&0x1f)) ; -} - -/* - Get Info about the current file in the zipfile, with internal only info -*/ -local int unz64local_GetCurrentFileInfoInternal OF((unzFile file, - unz_file_info64 *pfile_info, - unz_file_info64_internal - *pfile_info_internal, - char *szFileName, - uLong fileNameBufferSize, - void *extraField, - uLong extraFieldBufferSize, - char *szComment, - uLong commentBufferSize)); - -local int unz64local_GetCurrentFileInfoInternal (unzFile file, - unz_file_info64 *pfile_info, - unz_file_info64_internal - *pfile_info_internal, - char *szFileName, - uLong fileNameBufferSize, - void *extraField, - uLong extraFieldBufferSize, - char *szComment, - uLong commentBufferSize) -{ - unz64_s* s; - unz_file_info64 file_info; - unz_file_info64_internal file_info_internal; - int err=UNZ_OK; - uLong uMagic; - long lSeek=0; - uLong uL; - - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz64_s*)file; - if (ZSEEK64(s->z_filefunc, s->filestream, - s->pos_in_central_dir+s->byte_before_the_zipfile, - ZLIB_FILEFUNC_SEEK_SET)!=0) - err=UNZ_ERRNO; - - - /* we check the magic */ - if (err==UNZ_OK) - { - if (unz64local_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK) - err=UNZ_ERRNO; - else if (uMagic!=0x02014b50) - err=UNZ_BADZIPFILE; - } - - if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK) - err=UNZ_ERRNO; - - if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK) - err=UNZ_ERRNO; - - if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK) - err=UNZ_ERRNO; - - if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK) - err=UNZ_ERRNO; - - if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK) - err=UNZ_ERRNO; - - unz64local_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date); - - if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK) - err=UNZ_ERRNO; - - if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK) - err=UNZ_ERRNO; - file_info.compressed_size = uL; - - if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK) - err=UNZ_ERRNO; - file_info.uncompressed_size = uL; - - if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK) - err=UNZ_ERRNO; - - if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK) - err=UNZ_ERRNO; - - if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK) - err=UNZ_ERRNO; - - if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK) - err=UNZ_ERRNO; - - if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK) - err=UNZ_ERRNO; - - if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK) - err=UNZ_ERRNO; - - // relative offset of local header - if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK) - err=UNZ_ERRNO; - file_info_internal.offset_curfile = uL; - - lSeek+=file_info.size_filename; - if ((err==UNZ_OK) && (szFileName!=NULL)) - { - uLong uSizeRead ; - if (file_info.size_filename0) && (fileNameBufferSize>0)) - if (ZREAD64(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead) - err=UNZ_ERRNO; - lSeek -= uSizeRead; - } - - // Read extrafield - if ((err==UNZ_OK) && (extraField!=NULL)) - { - ZPOS64_T uSizeRead ; - if (file_info.size_file_extraz_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) - lSeek=0; - else - err=UNZ_ERRNO; - } - - if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0)) - if (ZREAD64(s->z_filefunc, s->filestream,extraField,(uLong)uSizeRead)!=uSizeRead) - err=UNZ_ERRNO; - - lSeek += file_info.size_file_extra - (uLong)uSizeRead; - } - else - lSeek += file_info.size_file_extra; - - - if ((err==UNZ_OK) && (file_info.size_file_extra != 0)) - { - uLong acc = 0; - - // since lSeek now points to after the extra field we need to move back - lSeek -= file_info.size_file_extra; - - if (lSeek!=0) - { - if (ZSEEK64(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) - lSeek=0; - else - err=UNZ_ERRNO; - } - - while(acc < file_info.size_file_extra) - { - uLong headerId; - uLong dataSize; - - if (unz64local_getShort(&s->z_filefunc, s->filestream,&headerId) != UNZ_OK) - err=UNZ_ERRNO; - - if (unz64local_getShort(&s->z_filefunc, s->filestream,&dataSize) != UNZ_OK) - err=UNZ_ERRNO; - - /* ZIP64 extra fields */ - if (headerId == 0x0001) - { - uLong uL; - - if(file_info.uncompressed_size == MAXU32) - { - if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK) - err=UNZ_ERRNO; - } - - if(file_info.compressed_size == MAXU32) - { - if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK) - err=UNZ_ERRNO; - } - - if(file_info_internal.offset_curfile == MAXU32) - { - /* Relative Header offset */ - if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK) - err=UNZ_ERRNO; - } - - if(file_info.disk_num_start == MAXU32) - { - /* Disk Start Number */ - if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK) - err=UNZ_ERRNO; - } - - } - else - { - if (ZSEEK64(s->z_filefunc, s->filestream,dataSize,ZLIB_FILEFUNC_SEEK_CUR)!=0) - err=UNZ_ERRNO; - } - - acc += 2 + 2 + dataSize; - } - } - - if ((err==UNZ_OK) && (szComment!=NULL)) - { - uLong uSizeRead ; - if (file_info.size_file_commentz_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) - lSeek=0; - else - err=UNZ_ERRNO; - } - - if ((file_info.size_file_comment>0) && (commentBufferSize>0)) - if (ZREAD64(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead) - err=UNZ_ERRNO; - lSeek+=file_info.size_file_comment - uSizeRead; - } - else - lSeek+=file_info.size_file_comment; - - - if ((err==UNZ_OK) && (pfile_info!=NULL)) - *pfile_info=file_info; - - if ((err==UNZ_OK) && (pfile_info_internal!=NULL)) - *pfile_info_internal=file_info_internal; - - return err; -} - - - -/* - Write info about the ZipFile in the *pglobal_info structure. - No preparation of the structure is needed - return UNZ_OK if there is no problem. -*/ -extern int ZEXPORT unzGetCurrentFileInfo64 (unzFile file, - unz_file_info64 * pfile_info, - char * szFileName, uLong fileNameBufferSize, - void *extraField, uLong extraFieldBufferSize, - char* szComment, uLong commentBufferSize) -{ - return unz64local_GetCurrentFileInfoInternal(file,pfile_info,NULL, - szFileName,fileNameBufferSize, - extraField,extraFieldBufferSize, - szComment,commentBufferSize); -} - -extern int ZEXPORT unzGetCurrentFileInfo (unzFile file, - unz_file_info * pfile_info, - char * szFileName, uLong fileNameBufferSize, - void *extraField, uLong extraFieldBufferSize, - char* szComment, uLong commentBufferSize) -{ - int err; - unz_file_info64 file_info64; - err = unz64local_GetCurrentFileInfoInternal(file,&file_info64,NULL, - szFileName,fileNameBufferSize, - extraField,extraFieldBufferSize, - szComment,commentBufferSize); - if ((err==UNZ_OK) && (pfile_info != NULL)) - { - pfile_info->version = file_info64.version; - pfile_info->version_needed = file_info64.version_needed; - pfile_info->flag = file_info64.flag; - pfile_info->compression_method = file_info64.compression_method; - pfile_info->dosDate = file_info64.dosDate; - pfile_info->crc = file_info64.crc; - - pfile_info->size_filename = file_info64.size_filename; - pfile_info->size_file_extra = file_info64.size_file_extra; - pfile_info->size_file_comment = file_info64.size_file_comment; - - pfile_info->disk_num_start = file_info64.disk_num_start; - pfile_info->internal_fa = file_info64.internal_fa; - pfile_info->external_fa = file_info64.external_fa; - - pfile_info->tmu_date = file_info64.tmu_date, - - - pfile_info->compressed_size = (uLong)file_info64.compressed_size; - pfile_info->uncompressed_size = (uLong)file_info64.uncompressed_size; - - } - return err; -} -/* - Set the current file of the zipfile to the first file. - return UNZ_OK if there is no problem -*/ -extern int ZEXPORT unzGoToFirstFile (unzFile file) -{ - int err=UNZ_OK; - unz64_s* s; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz64_s*)file; - s->pos_in_central_dir=s->offset_central_dir; - s->num_file=0; - err=unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info, - &s->cur_file_info_internal, - NULL,0,NULL,0,NULL,0); - s->current_file_ok = (err == UNZ_OK); - return err; -} - -/* - Set the current file of the zipfile to the next file. - return UNZ_OK if there is no problem - return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. -*/ -extern int ZEXPORT unzGoToNextFile (unzFile file) -{ - unz64_s* s; - int err; - - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz64_s*)file; - if (!s->current_file_ok) - return UNZ_END_OF_LIST_OF_FILE; - if (s->gi.number_entry != 0xffff) /* 2^16 files overflow hack */ - if (s->num_file+1==s->gi.number_entry) - return UNZ_END_OF_LIST_OF_FILE; - - s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename + - s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ; - s->num_file++; - err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info, - &s->cur_file_info_internal, - NULL,0,NULL,0,NULL,0); - s->current_file_ok = (err == UNZ_OK); - return err; -} - - -/* - Try locate the file szFileName in the zipfile. - For the iCaseSensitivity signification, see unzStringFileNameCompare - - return value : - UNZ_OK if the file is found. It becomes the current file. - UNZ_END_OF_LIST_OF_FILE if the file is not found -*/ -extern int ZEXPORT unzLocateFile (unzFile file, const char *szFileName, int iCaseSensitivity) -{ - unz64_s* s; - int err; - - /* We remember the 'current' position in the file so that we can jump - * back there if we fail. - */ - unz_file_info64 cur_file_infoSaved; - unz_file_info64_internal cur_file_info_internalSaved; - ZPOS64_T num_fileSaved; - ZPOS64_T pos_in_central_dirSaved; - - - if (file==NULL) - return UNZ_PARAMERROR; - - if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP) - return UNZ_PARAMERROR; - - s=(unz64_s*)file; - if (!s->current_file_ok) - return UNZ_END_OF_LIST_OF_FILE; - - /* Save the current state */ - num_fileSaved = s->num_file; - pos_in_central_dirSaved = s->pos_in_central_dir; - cur_file_infoSaved = s->cur_file_info; - cur_file_info_internalSaved = s->cur_file_info_internal; - - err = unzGoToFirstFile(file); - - while (err == UNZ_OK) - { - char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1]; - err = unzGetCurrentFileInfo64(file,NULL, - szCurrentFileName,sizeof(szCurrentFileName)-1, - NULL,0,NULL,0); - if (err == UNZ_OK) - { - if (unzStringFileNameCompare(szCurrentFileName, - szFileName,iCaseSensitivity)==0) - return UNZ_OK; - err = unzGoToNextFile(file); - } - } - - /* We failed, so restore the state of the 'current file' to where we - * were. - */ - s->num_file = num_fileSaved ; - s->pos_in_central_dir = pos_in_central_dirSaved ; - s->cur_file_info = cur_file_infoSaved; - s->cur_file_info_internal = cur_file_info_internalSaved; - return err; -} - - -/* -/////////////////////////////////////////// -// Contributed by Ryan Haksi (mailto://cryogen@infoserve.net) -// I need random access -// -// Further optimization could be realized by adding an ability -// to cache the directory in memory. The goal being a single -// comprehensive file read to put the file I need in a memory. -*/ - -/* -typedef struct unz_file_pos_s -{ - ZPOS64_T pos_in_zip_directory; // offset in file - ZPOS64_T num_of_file; // # of file -} unz_file_pos; -*/ - -extern int ZEXPORT unzGetFilePos64(unzFile file, unz64_file_pos* file_pos) -{ - unz64_s* s; - - if (file==NULL || file_pos==NULL) - return UNZ_PARAMERROR; - s=(unz64_s*)file; - if (!s->current_file_ok) - return UNZ_END_OF_LIST_OF_FILE; - - file_pos->pos_in_zip_directory = s->pos_in_central_dir; - file_pos->num_of_file = s->num_file; - - return UNZ_OK; -} - -extern int ZEXPORT unzGetFilePos( - unzFile file, - unz_file_pos* file_pos) -{ - unz64_file_pos file_pos64; - int err = unzGetFilePos64(file,&file_pos64); - if (err==UNZ_OK) - { - file_pos->pos_in_zip_directory = (uLong)file_pos64.pos_in_zip_directory; - file_pos->num_of_file = (uLong)file_pos64.num_of_file; - } - return err; -} - -extern int ZEXPORT unzGoToFilePos64(unzFile file, const unz64_file_pos* file_pos) -{ - unz64_s* s; - int err; - - if (file==NULL || file_pos==NULL) - return UNZ_PARAMERROR; - s=(unz64_s*)file; - - /* jump to the right spot */ - s->pos_in_central_dir = file_pos->pos_in_zip_directory; - s->num_file = file_pos->num_of_file; - - /* set the current file */ - err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info, - &s->cur_file_info_internal, - NULL,0,NULL,0,NULL,0); - /* return results */ - s->current_file_ok = (err == UNZ_OK); - return err; -} - -extern int ZEXPORT unzGoToFilePos( - unzFile file, - unz_file_pos* file_pos) -{ - unz64_file_pos file_pos64; - if (file_pos == NULL) - return UNZ_PARAMERROR; - - file_pos64.pos_in_zip_directory = file_pos->pos_in_zip_directory; - file_pos64.num_of_file = file_pos->num_of_file; - return unzGoToFilePos64(file,&file_pos64); -} - -/* -// Unzip Helper Functions - should be here? -/////////////////////////////////////////// -*/ - -/* - Read the local header of the current zipfile - Check the coherency of the local header and info in the end of central - directory about this file - store in *piSizeVar the size of extra info in local header - (filename and size of extra field data) -*/ -local int unz64local_CheckCurrentFileCoherencyHeader (unz64_s* s, uInt* piSizeVar, - ZPOS64_T * poffset_local_extrafield, - uInt * psize_local_extrafield) -{ - uLong uMagic,uData,uFlags; - uLong size_filename; - uLong size_extra_field; - int err=UNZ_OK; - - *piSizeVar = 0; - *poffset_local_extrafield = 0; - *psize_local_extrafield = 0; - - if (ZSEEK64(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile + - s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0) - return UNZ_ERRNO; - - - if (err==UNZ_OK) - { - if (unz64local_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK) - err=UNZ_ERRNO; - else if (uMagic!=0x04034b50) - err=UNZ_BADZIPFILE; - } - - if (unz64local_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) - err=UNZ_ERRNO; -/* - else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion)) - err=UNZ_BADZIPFILE; -*/ - if (unz64local_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK) - err=UNZ_ERRNO; - - if (unz64local_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) - err=UNZ_ERRNO; - else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method)) - err=UNZ_BADZIPFILE; - - if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) && -/* #ifdef HAVE_BZIP2 */ - (s->cur_file_info.compression_method!=Z_BZIP2ED) && -/* #endif */ - (s->cur_file_info.compression_method!=Z_DEFLATED)) - err=UNZ_BADZIPFILE; - - if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */ - err=UNZ_ERRNO; - - if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* crc */ - err=UNZ_ERRNO; - else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) && ((uFlags & 8)==0)) - err=UNZ_BADZIPFILE; - - if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size compr */ - err=UNZ_ERRNO; - else if (uData != 0xFFFFFFFF && (err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) && ((uFlags & 8)==0)) - err=UNZ_BADZIPFILE; - - if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size uncompr */ - err=UNZ_ERRNO; - else if (uData != 0xFFFFFFFF && (err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) && ((uFlags & 8)==0)) - err=UNZ_BADZIPFILE; - - if (unz64local_getShort(&s->z_filefunc, s->filestream,&size_filename) != UNZ_OK) - err=UNZ_ERRNO; - else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename)) - err=UNZ_BADZIPFILE; - - *piSizeVar += (uInt)size_filename; - - if (unz64local_getShort(&s->z_filefunc, s->filestream,&size_extra_field) != UNZ_OK) - err=UNZ_ERRNO; - *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile + - SIZEZIPLOCALHEADER + size_filename; - *psize_local_extrafield = (uInt)size_extra_field; - - *piSizeVar += (uInt)size_extra_field; - - return err; -} - -/* - Open for reading data the current file in the zipfile. - If there is no error and the file is opened, the return value is UNZ_OK. -*/ -extern int ZEXPORT unzOpenCurrentFile3 (unzFile file, int* method, - int* level, int raw, const char* password) -{ - int err=UNZ_OK; - uInt iSizeVar; - unz64_s* s; - file_in_zip64_read_info_s* pfile_in_zip_read_info; - ZPOS64_T offset_local_extrafield; /* offset of the local extra field */ - uInt size_local_extrafield; /* size of the local extra field */ -# ifndef NOUNCRYPT - char source[12]; -# else - if (password != NULL) - return UNZ_PARAMERROR; -# endif - - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz64_s*)file; - if (!s->current_file_ok) - return UNZ_PARAMERROR; - - if (s->pfile_in_zip_read != NULL) - unzCloseCurrentFile(file); - - if (unz64local_CheckCurrentFileCoherencyHeader(s,&iSizeVar, &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK) - return UNZ_BADZIPFILE; - - pfile_in_zip_read_info = (file_in_zip64_read_info_s*)ALLOC(sizeof(file_in_zip64_read_info_s)); - if (pfile_in_zip_read_info==NULL) - return UNZ_INTERNALERROR; - - pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE); - pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield; - pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield; - pfile_in_zip_read_info->pos_local_extrafield=0; - pfile_in_zip_read_info->raw=raw; - - if (pfile_in_zip_read_info->read_buffer==NULL) - { - TRYFREE(pfile_in_zip_read_info); - return UNZ_INTERNALERROR; - } - - pfile_in_zip_read_info->stream_initialised=0; - - if (method!=NULL) - *method = (int)s->cur_file_info.compression_method; - - if (level!=NULL) - { - *level = 6; - switch (s->cur_file_info.flag & 0x06) - { - case 6 : *level = 1; break; - case 4 : *level = 2; break; - case 2 : *level = 9; break; - } - } - - if ((s->cur_file_info.compression_method!=0) && -/* #ifdef HAVE_BZIP2 */ - (s->cur_file_info.compression_method!=Z_BZIP2ED) && -/* #endif */ - (s->cur_file_info.compression_method!=Z_DEFLATED)) - - err=UNZ_BADZIPFILE; - - pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc; - pfile_in_zip_read_info->crc32=0; - pfile_in_zip_read_info->total_out_64=0; - pfile_in_zip_read_info->compression_method = s->cur_file_info.compression_method; - pfile_in_zip_read_info->filestream=s->filestream; - pfile_in_zip_read_info->z_filefunc=s->z_filefunc; - pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile; - - pfile_in_zip_read_info->stream.total_out = 0; - - if ((s->cur_file_info.compression_method==Z_BZIP2ED) && (!raw)) - { -#ifdef HAVE_BZIP2 - pfile_in_zip_read_info->bstream.bzalloc = (void *(*) (void *, int, int))0; - pfile_in_zip_read_info->bstream.bzfree = (free_func)0; - pfile_in_zip_read_info->bstream.opaque = (voidpf)0; - pfile_in_zip_read_info->bstream.state = (voidpf)0; - - pfile_in_zip_read_info->stream.zalloc = (alloc_func)0; - pfile_in_zip_read_info->stream.zfree = (free_func)0; - pfile_in_zip_read_info->stream.opaque = (voidpf)0; - pfile_in_zip_read_info->stream.next_in = (voidpf)0; - pfile_in_zip_read_info->stream.avail_in = 0; - - err=BZ2_bzDecompressInit(&pfile_in_zip_read_info->bstream, 0, 0); - if (err == Z_OK) - pfile_in_zip_read_info->stream_initialised=Z_BZIP2ED; - else - { - TRYFREE(pfile_in_zip_read_info); - return err; - } -#else - pfile_in_zip_read_info->raw=1; -#endif - } - else if ((s->cur_file_info.compression_method==Z_DEFLATED) && (!raw)) - { - pfile_in_zip_read_info->stream.zalloc = (alloc_func)0; - pfile_in_zip_read_info->stream.zfree = (free_func)0; - pfile_in_zip_read_info->stream.opaque = (voidpf)0; - pfile_in_zip_read_info->stream.next_in = 0; - pfile_in_zip_read_info->stream.avail_in = 0; - - err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS); - if (err == Z_OK) - pfile_in_zip_read_info->stream_initialised=Z_DEFLATED; - else - { - TRYFREE(pfile_in_zip_read_info); - return err; - } - /* windowBits is passed < 0 to tell that there is no zlib header. - * Note that in this case inflate *requires* an extra "dummy" byte - * after the compressed stream in order to complete decompression and - * return Z_STREAM_END. - * In unzip, i don't wait absolutely Z_STREAM_END because I known the - * size of both compressed and uncompressed data - */ - } - pfile_in_zip_read_info->rest_read_compressed = - s->cur_file_info.compressed_size ; - pfile_in_zip_read_info->rest_read_uncompressed = - s->cur_file_info.uncompressed_size ; - - - pfile_in_zip_read_info->pos_in_zipfile = - s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + - iSizeVar; - - pfile_in_zip_read_info->stream.avail_in = (uInt)0; - - s->pfile_in_zip_read = pfile_in_zip_read_info; - s->encrypted = 0; - -# ifndef NOUNCRYPT - if (password != NULL) - { - int i; - s->pcrc_32_tab = get_crc_table(); - init_keys(password,s->keys,s->pcrc_32_tab); - if (ZSEEK64(s->z_filefunc, s->filestream, - s->pfile_in_zip_read->pos_in_zipfile + - s->pfile_in_zip_read->byte_before_the_zipfile, - SEEK_SET)!=0) - return UNZ_INTERNALERROR; - if(ZREAD64(s->z_filefunc, s->filestream,source, 12)<12) - return UNZ_INTERNALERROR; - - for (i = 0; i<12; i++) - zdecode(s->keys,s->pcrc_32_tab,source[i]); - - s->pfile_in_zip_read->pos_in_zipfile+=12; - s->encrypted=1; - } -# endif - - - return UNZ_OK; -} - -extern int ZEXPORT unzOpenCurrentFile (unzFile file) -{ - return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL); -} - -extern int ZEXPORT unzOpenCurrentFilePassword (unzFile file, const char* password) -{ - return unzOpenCurrentFile3(file, NULL, NULL, 0, password); -} - -extern int ZEXPORT unzOpenCurrentFile2 (unzFile file, int* method, int* level, int raw) -{ - return unzOpenCurrentFile3(file, method, level, raw, NULL); -} - -/** Addition for GDAL : START */ - -extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64( unzFile file) -{ - unz64_s* s; - file_in_zip64_read_info_s* pfile_in_zip_read_info; - s=(unz64_s*)file; - if (file==NULL) - return 0; //UNZ_PARAMERROR; - pfile_in_zip_read_info=s->pfile_in_zip_read; - if (pfile_in_zip_read_info==NULL) - return 0; //UNZ_PARAMERROR; - return pfile_in_zip_read_info->pos_in_zipfile + - pfile_in_zip_read_info->byte_before_the_zipfile; -} - -/** Addition for GDAL : END */ - -/* - Read bytes from the current file. - buf contain buffer where data must be copied - len the size of buf. - - return the number of byte copied if somes bytes are copied - return 0 if the end of file was reached - return <0 with error code if there is an error - (UNZ_ERRNO for IO error, or zLib error for uncompress error) -*/ -extern int ZEXPORT unzReadCurrentFile (unzFile file, voidp buf, unsigned len) -{ - int err=UNZ_OK; - uInt iRead = 0; - unz64_s* s; - file_in_zip64_read_info_s* pfile_in_zip_read_info; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz64_s*)file; - pfile_in_zip_read_info=s->pfile_in_zip_read; - - if (pfile_in_zip_read_info==NULL) - return UNZ_PARAMERROR; - - - if (pfile_in_zip_read_info->read_buffer == NULL) - return UNZ_END_OF_LIST_OF_FILE; - if (len==0) - return 0; - - pfile_in_zip_read_info->stream.next_out = (Bytef*)buf; - - pfile_in_zip_read_info->stream.avail_out = (uInt)len; - - if ((len>pfile_in_zip_read_info->rest_read_uncompressed) && - (!(pfile_in_zip_read_info->raw))) - pfile_in_zip_read_info->stream.avail_out = - (uInt)pfile_in_zip_read_info->rest_read_uncompressed; - - if ((len>pfile_in_zip_read_info->rest_read_compressed+ - pfile_in_zip_read_info->stream.avail_in) && - (pfile_in_zip_read_info->raw)) - pfile_in_zip_read_info->stream.avail_out = - (uInt)pfile_in_zip_read_info->rest_read_compressed+ - pfile_in_zip_read_info->stream.avail_in; - - while (pfile_in_zip_read_info->stream.avail_out>0) - { - if ((pfile_in_zip_read_info->stream.avail_in==0) && - (pfile_in_zip_read_info->rest_read_compressed>0)) - { - uInt uReadThis = UNZ_BUFSIZE; - if (pfile_in_zip_read_info->rest_read_compressedrest_read_compressed; - if (uReadThis == 0) - return UNZ_EOF; - if (ZSEEK64(pfile_in_zip_read_info->z_filefunc, - pfile_in_zip_read_info->filestream, - pfile_in_zip_read_info->pos_in_zipfile + - pfile_in_zip_read_info->byte_before_the_zipfile, - ZLIB_FILEFUNC_SEEK_SET)!=0) - return UNZ_ERRNO; - if (ZREAD64(pfile_in_zip_read_info->z_filefunc, - pfile_in_zip_read_info->filestream, - pfile_in_zip_read_info->read_buffer, - uReadThis)!=uReadThis) - return UNZ_ERRNO; - - -# ifndef NOUNCRYPT - if(s->encrypted) - { - uInt i; - for(i=0;iread_buffer[i] = - zdecode(s->keys,s->pcrc_32_tab, - pfile_in_zip_read_info->read_buffer[i]); - } -# endif - - - pfile_in_zip_read_info->pos_in_zipfile += uReadThis; - - pfile_in_zip_read_info->rest_read_compressed-=uReadThis; - - pfile_in_zip_read_info->stream.next_in = - (Bytef*)pfile_in_zip_read_info->read_buffer; - pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis; - } - - if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw)) - { - uInt uDoCopy,i ; - - if ((pfile_in_zip_read_info->stream.avail_in == 0) && - (pfile_in_zip_read_info->rest_read_compressed == 0)) - return (iRead==0) ? UNZ_EOF : iRead; - - if (pfile_in_zip_read_info->stream.avail_out < - pfile_in_zip_read_info->stream.avail_in) - uDoCopy = pfile_in_zip_read_info->stream.avail_out ; - else - uDoCopy = pfile_in_zip_read_info->stream.avail_in ; - - for (i=0;istream.next_out+i) = - *(pfile_in_zip_read_info->stream.next_in+i); - - pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uDoCopy; - - pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32, - pfile_in_zip_read_info->stream.next_out, - uDoCopy); - pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy; - pfile_in_zip_read_info->stream.avail_in -= uDoCopy; - pfile_in_zip_read_info->stream.avail_out -= uDoCopy; - pfile_in_zip_read_info->stream.next_out += uDoCopy; - pfile_in_zip_read_info->stream.next_in += uDoCopy; - pfile_in_zip_read_info->stream.total_out += uDoCopy; - iRead += uDoCopy; - } - else if (pfile_in_zip_read_info->compression_method==Z_BZIP2ED) - { -#ifdef HAVE_BZIP2 - uLong uTotalOutBefore,uTotalOutAfter; - const Bytef *bufBefore; - uLong uOutThis; - - pfile_in_zip_read_info->bstream.next_in = (char*)pfile_in_zip_read_info->stream.next_in; - pfile_in_zip_read_info->bstream.avail_in = pfile_in_zip_read_info->stream.avail_in; - pfile_in_zip_read_info->bstream.total_in_lo32 = pfile_in_zip_read_info->stream.total_in; - pfile_in_zip_read_info->bstream.total_in_hi32 = 0; - pfile_in_zip_read_info->bstream.next_out = (char*)pfile_in_zip_read_info->stream.next_out; - pfile_in_zip_read_info->bstream.avail_out = pfile_in_zip_read_info->stream.avail_out; - pfile_in_zip_read_info->bstream.total_out_lo32 = pfile_in_zip_read_info->stream.total_out; - pfile_in_zip_read_info->bstream.total_out_hi32 = 0; - - uTotalOutBefore = pfile_in_zip_read_info->bstream.total_out_lo32; - bufBefore = (const Bytef *)pfile_in_zip_read_info->bstream.next_out; - - err=BZ2_bzDecompress(&pfile_in_zip_read_info->bstream); - - uTotalOutAfter = pfile_in_zip_read_info->bstream.total_out_lo32; - uOutThis = uTotalOutAfter-uTotalOutBefore; - - pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uOutThis; - - pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,bufBefore, (uInt)(uOutThis)); - pfile_in_zip_read_info->rest_read_uncompressed -= uOutThis; - iRead += (uInt)(uTotalOutAfter - uTotalOutBefore); - - pfile_in_zip_read_info->stream.next_in = (Bytef*)pfile_in_zip_read_info->bstream.next_in; - pfile_in_zip_read_info->stream.avail_in = pfile_in_zip_read_info->bstream.avail_in; - pfile_in_zip_read_info->stream.total_in = pfile_in_zip_read_info->bstream.total_in_lo32; - pfile_in_zip_read_info->stream.next_out = (Bytef*)pfile_in_zip_read_info->bstream.next_out; - pfile_in_zip_read_info->stream.avail_out = pfile_in_zip_read_info->bstream.avail_out; - pfile_in_zip_read_info->stream.total_out = pfile_in_zip_read_info->bstream.total_out_lo32; - - if (err==BZ_STREAM_END) - return (iRead==0) ? UNZ_EOF : iRead; - if (err!=BZ_OK) - break; -#endif - } // end Z_BZIP2ED - else - { - ZPOS64_T uTotalOutBefore,uTotalOutAfter; - const Bytef *bufBefore; - ZPOS64_T uOutThis; - int flush=Z_SYNC_FLUSH; - - uTotalOutBefore = pfile_in_zip_read_info->stream.total_out; - bufBefore = pfile_in_zip_read_info->stream.next_out; - - /* - if ((pfile_in_zip_read_info->rest_read_uncompressed == - pfile_in_zip_read_info->stream.avail_out) && - (pfile_in_zip_read_info->rest_read_compressed == 0)) - flush = Z_FINISH; - */ - err=inflate(&pfile_in_zip_read_info->stream,flush); - - if ((err>=0) && (pfile_in_zip_read_info->stream.msg!=NULL)) - err = Z_DATA_ERROR; - - uTotalOutAfter = pfile_in_zip_read_info->stream.total_out; - uOutThis = uTotalOutAfter-uTotalOutBefore; - - pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uOutThis; - - pfile_in_zip_read_info->crc32 = - crc32(pfile_in_zip_read_info->crc32,bufBefore, - (uInt)(uOutThis)); - - pfile_in_zip_read_info->rest_read_uncompressed -= - uOutThis; - - iRead += (uInt)(uTotalOutAfter - uTotalOutBefore); - - if (err==Z_STREAM_END) - return (iRead==0) ? UNZ_EOF : iRead; - if (err!=Z_OK) - break; - } - } - - if (err==Z_OK) - return iRead; - return err; -} - - -/* - Give the current position in uncompressed data -*/ -extern z_off_t ZEXPORT unztell (unzFile file) -{ - unz64_s* s; - file_in_zip64_read_info_s* pfile_in_zip_read_info; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz64_s*)file; - pfile_in_zip_read_info=s->pfile_in_zip_read; - - if (pfile_in_zip_read_info==NULL) - return UNZ_PARAMERROR; - - return (z_off_t)pfile_in_zip_read_info->stream.total_out; -} - -extern ZPOS64_T ZEXPORT unztell64 (unzFile file) -{ - - unz64_s* s; - file_in_zip64_read_info_s* pfile_in_zip_read_info; - if (file==NULL) - return (ZPOS64_T)-1; - s=(unz64_s*)file; - pfile_in_zip_read_info=s->pfile_in_zip_read; - - if (pfile_in_zip_read_info==NULL) - return (ZPOS64_T)-1; - - return pfile_in_zip_read_info->total_out_64; -} - - -/* - return 1 if the end of file was reached, 0 elsewhere -*/ -extern int ZEXPORT unzeof (unzFile file) -{ - unz64_s* s; - file_in_zip64_read_info_s* pfile_in_zip_read_info; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz64_s*)file; - pfile_in_zip_read_info=s->pfile_in_zip_read; - - if (pfile_in_zip_read_info==NULL) - return UNZ_PARAMERROR; - - if (pfile_in_zip_read_info->rest_read_uncompressed == 0) - return 1; - else - return 0; -} - - - -/* -Read extra field from the current file (opened by unzOpenCurrentFile) -This is the local-header version of the extra field (sometimes, there is -more info in the local-header version than in the central-header) - - if buf==NULL, it return the size of the local extra field that can be read - - if buf!=NULL, len is the size of the buffer, the extra header is copied in - buf. - the return value is the number of bytes copied in buf, or (if <0) - the error code -*/ -extern int ZEXPORT unzGetLocalExtrafield (unzFile file, voidp buf, unsigned len) -{ - unz64_s* s; - file_in_zip64_read_info_s* pfile_in_zip_read_info; - uInt read_now; - ZPOS64_T size_to_read; - - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz64_s*)file; - pfile_in_zip_read_info=s->pfile_in_zip_read; - - if (pfile_in_zip_read_info==NULL) - return UNZ_PARAMERROR; - - size_to_read = (pfile_in_zip_read_info->size_local_extrafield - - pfile_in_zip_read_info->pos_local_extrafield); - - if (buf==NULL) - return (int)size_to_read; - - if (len>size_to_read) - read_now = (uInt)size_to_read; - else - read_now = (uInt)len ; - - if (read_now==0) - return 0; - - if (ZSEEK64(pfile_in_zip_read_info->z_filefunc, - pfile_in_zip_read_info->filestream, - pfile_in_zip_read_info->offset_local_extrafield + - pfile_in_zip_read_info->pos_local_extrafield, - ZLIB_FILEFUNC_SEEK_SET)!=0) - return UNZ_ERRNO; - - if (ZREAD64(pfile_in_zip_read_info->z_filefunc, - pfile_in_zip_read_info->filestream, - buf,read_now)!=read_now) - return UNZ_ERRNO; - - return (int)read_now; -} - -/* - Close the file in zip opened with unzOpenCurrentFile - Return UNZ_CRCERROR if all the file was read but the CRC is not good -*/ -extern int ZEXPORT unzCloseCurrentFile (unzFile file) -{ - int err=UNZ_OK; - - unz64_s* s; - file_in_zip64_read_info_s* pfile_in_zip_read_info; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz64_s*)file; - pfile_in_zip_read_info=s->pfile_in_zip_read; - - if (pfile_in_zip_read_info==NULL) - return UNZ_PARAMERROR; - - - if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) && - (!pfile_in_zip_read_info->raw)) - { - if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait) - err=UNZ_CRCERROR; - } - - - TRYFREE(pfile_in_zip_read_info->read_buffer); - pfile_in_zip_read_info->read_buffer = NULL; - if (pfile_in_zip_read_info->stream_initialised == Z_DEFLATED) - inflateEnd(&pfile_in_zip_read_info->stream); -#ifdef HAVE_BZIP2 - else if (pfile_in_zip_read_info->stream_initialised == Z_BZIP2ED) - BZ2_bzDecompressEnd(&pfile_in_zip_read_info->bstream); -#endif - - - pfile_in_zip_read_info->stream_initialised = 0; - TRYFREE(pfile_in_zip_read_info); - - s->pfile_in_zip_read=NULL; - - return err; -} - - -/* - Get the global comment string of the ZipFile, in the szComment buffer. - uSizeBuf is the size of the szComment buffer. - return the number of byte copied or an error code <0 -*/ -extern int ZEXPORT unzGetGlobalComment (unzFile file, char * szComment, uLong uSizeBuf) -{ - unz64_s* s; - uLong uReadThis ; - if (file==NULL) - return (int)UNZ_PARAMERROR; - s=(unz64_s*)file; - - uReadThis = uSizeBuf; - if (uReadThis>s->gi.size_comment) - uReadThis = s->gi.size_comment; - - if (ZSEEK64(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0) - return UNZ_ERRNO; - - if (uReadThis>0) - { - *szComment='\0'; - if (ZREAD64(s->z_filefunc,s->filestream,szComment,uReadThis)!=uReadThis) - return UNZ_ERRNO; - } - - if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment)) - *(szComment+s->gi.size_comment)='\0'; - return (int)uReadThis; -} - -/* Additions by RX '2004 */ -extern ZPOS64_T ZEXPORT unzGetOffset64(unzFile file) -{ - unz64_s* s; - - if (file==NULL) - return 0; //UNZ_PARAMERROR; - s=(unz64_s*)file; - if (!s->current_file_ok) - return 0; - if (s->gi.number_entry != 0 && s->gi.number_entry != 0xffff) - if (s->num_file==s->gi.number_entry) - return 0; - return s->pos_in_central_dir; -} - -extern uLong ZEXPORT unzGetOffset (unzFile file) -{ - ZPOS64_T offset64; - - if (file==NULL) - return 0; //UNZ_PARAMERROR; - offset64 = unzGetOffset64(file); - return (uLong)offset64; -} - -extern int ZEXPORT unzSetOffset64(unzFile file, ZPOS64_T pos) -{ - unz64_s* s; - int err; - - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz64_s*)file; - - s->pos_in_central_dir = pos; - s->num_file = s->gi.number_entry; /* hack */ - err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info, - &s->cur_file_info_internal, - NULL,0,NULL,0,NULL,0); - s->current_file_ok = (err == UNZ_OK); - return err; -} - -extern int ZEXPORT unzSetOffset (unzFile file, uLong pos) -{ - return unzSetOffset64(file,pos); -} diff --git a/vendor/minizip/unzip.h b/vendor/minizip/unzip.h deleted file mode 100644 index 2104e3915..000000000 --- a/vendor/minizip/unzip.h +++ /dev/null @@ -1,437 +0,0 @@ -/* unzip.h -- IO for uncompress .zip files using zlib - Version 1.1, February 14h, 2010 - part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) - - Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) - - Modifications of Unzip for Zip64 - Copyright (C) 2007-2008 Even Rouault - - Modifications for Zip64 support on both zip and unzip - Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) - - For more info read MiniZip_info.txt - - --------------------------------------------------------------------------------- - - Condition of use and distribution are the same than zlib : - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - --------------------------------------------------------------------------------- - - Changes - - See header of unzip64.c - -*/ - -#ifndef _unz64_H -#define _unz64_H - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef _ZLIB_H -#include "zlib.h" -#endif - -#ifndef _ZLIBIOAPI_H -#include "ioapi.h" -#endif - -#ifdef HAVE_BZIP2 -#include "bzlib.h" -#endif - -#define Z_BZIP2ED 12 - -#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP) -/* like the STRICT of WIN32, we define a pointer that cannot be converted - from (void*) without cast */ -typedef struct TagunzFile__ { int unused; } unzFile__; -typedef unzFile__ *unzFile; -#else -typedef voidp unzFile; -#endif - - -#define UNZ_OK (0) -#define UNZ_END_OF_LIST_OF_FILE (-100) -#define UNZ_ERRNO (Z_ERRNO) -#define UNZ_EOF (0) -#define UNZ_PARAMERROR (-102) -#define UNZ_BADZIPFILE (-103) -#define UNZ_INTERNALERROR (-104) -#define UNZ_CRCERROR (-105) - -/* tm_unz contain date/time info */ -typedef struct tm_unz_s -{ - uInt tm_sec; /* seconds after the minute - [0,59] */ - uInt tm_min; /* minutes after the hour - [0,59] */ - uInt tm_hour; /* hours since midnight - [0,23] */ - uInt tm_mday; /* day of the month - [1,31] */ - uInt tm_mon; /* months since January - [0,11] */ - uInt tm_year; /* years - [1980..2044] */ -} tm_unz; - -/* unz_global_info structure contain global data about the ZIPfile - These data comes from the end of central dir */ -typedef struct unz_global_info64_s -{ - ZPOS64_T number_entry; /* total number of entries in - the central dir on this disk */ - uLong size_comment; /* size of the global comment of the zipfile */ -} unz_global_info64; - -typedef struct unz_global_info_s -{ - uLong number_entry; /* total number of entries in - the central dir on this disk */ - uLong size_comment; /* size of the global comment of the zipfile */ -} unz_global_info; - -/* unz_file_info contain information about a file in the zipfile */ -typedef struct unz_file_info64_s -{ - uLong version; /* version made by 2 bytes */ - uLong version_needed; /* version needed to extract 2 bytes */ - uLong flag; /* general purpose bit flag 2 bytes */ - uLong compression_method; /* compression method 2 bytes */ - uLong dosDate; /* last mod file date in Dos fmt 4 bytes */ - uLong crc; /* crc-32 4 bytes */ - ZPOS64_T compressed_size; /* compressed size 8 bytes */ - ZPOS64_T uncompressed_size; /* uncompressed size 8 bytes */ - uLong size_filename; /* filename length 2 bytes */ - uLong size_file_extra; /* extra field length 2 bytes */ - uLong size_file_comment; /* file comment length 2 bytes */ - - uLong disk_num_start; /* disk number start 2 bytes */ - uLong internal_fa; /* internal file attributes 2 bytes */ - uLong external_fa; /* external file attributes 4 bytes */ - - tm_unz tmu_date; -} unz_file_info64; - -typedef struct unz_file_info_s -{ - uLong version; /* version made by 2 bytes */ - uLong version_needed; /* version needed to extract 2 bytes */ - uLong flag; /* general purpose bit flag 2 bytes */ - uLong compression_method; /* compression method 2 bytes */ - uLong dosDate; /* last mod file date in Dos fmt 4 bytes */ - uLong crc; /* crc-32 4 bytes */ - uLong compressed_size; /* compressed size 4 bytes */ - uLong uncompressed_size; /* uncompressed size 4 bytes */ - uLong size_filename; /* filename length 2 bytes */ - uLong size_file_extra; /* extra field length 2 bytes */ - uLong size_file_comment; /* file comment length 2 bytes */ - - uLong disk_num_start; /* disk number start 2 bytes */ - uLong internal_fa; /* internal file attributes 2 bytes */ - uLong external_fa; /* external file attributes 4 bytes */ - - tm_unz tmu_date; -} unz_file_info; - -extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1, - const char* fileName2, - int iCaseSensitivity)); -/* - Compare two filename (fileName1,fileName2). - If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) - If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi - or strcasecmp) - If iCaseSenisivity = 0, case sensitivity is defaut of your operating system - (like 1 on Unix, 2 on Windows) -*/ - - -extern unzFile ZEXPORT unzOpen OF((const char *path)); -extern unzFile ZEXPORT unzOpen64 OF((const void *path)); -/* - Open a Zip file. path contain the full pathname (by example, - on a Windows XP computer "c:\\zlib\\zlib113.zip" or on an Unix computer - "zlib/zlib113.zip". - If the zipfile cannot be opened (file don't exist or in not valid), the - return value is NULL. - Else, the return value is a unzFile Handle, usable with other function - of this unzip package. - the "64" function take a const void* pointer, because the path is just the - value passed to the open64_file_func callback. - Under Windows, if UNICODE is defined, using fill_fopen64_filefunc, the path - is a pointer to a wide unicode string (LPCTSTR is LPCWSTR), so const char* - does not describe the reality -*/ - - -extern unzFile ZEXPORT unzOpen2 OF((const char *path, - zlib_filefunc_def* pzlib_filefunc_def)); -/* - Open a Zip file, like unzOpen, but provide a set of file low level API - for read/write the zip file (see ioapi.h) -*/ - -extern unzFile ZEXPORT unzOpen2_64 OF((const void *path, - zlib_filefunc64_def* pzlib_filefunc_def)); -/* - Open a Zip file, like unz64Open, but provide a set of file low level API - for read/write the zip file (see ioapi.h) -*/ - -extern int ZEXPORT unzClose OF((unzFile file)); -/* - Close a ZipFile opened with unzOpen. - If there is files inside the .Zip opened with unzOpenCurrentFile (see later), - these files MUST be closed with unzCloseCurrentFile before call unzClose. - return UNZ_OK if there is no problem. */ - -extern int ZEXPORT unzGetGlobalInfo OF((unzFile file, - unz_global_info *pglobal_info)); - -extern int ZEXPORT unzGetGlobalInfo64 OF((unzFile file, - unz_global_info64 *pglobal_info)); -/* - Write info about the ZipFile in the *pglobal_info structure. - No preparation of the structure is needed - return UNZ_OK if there is no problem. */ - - -extern int ZEXPORT unzGetGlobalComment OF((unzFile file, - char *szComment, - uLong uSizeBuf)); -/* - Get the global comment string of the ZipFile, in the szComment buffer. - uSizeBuf is the size of the szComment buffer. - return the number of byte copied or an error code <0 -*/ - - -/***************************************************************************/ -/* Unzip package allow you browse the directory of the zipfile */ - -extern int ZEXPORT unzGoToFirstFile OF((unzFile file)); -/* - Set the current file of the zipfile to the first file. - return UNZ_OK if there is no problem -*/ - -extern int ZEXPORT unzGoToNextFile OF((unzFile file)); -/* - Set the current file of the zipfile to the next file. - return UNZ_OK if there is no problem - return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. -*/ - -extern int ZEXPORT unzLocateFile OF((unzFile file, - const char *szFileName, - int iCaseSensitivity)); -/* - Try locate the file szFileName in the zipfile. - For the iCaseSensitivity signification, see unzStringFileNameCompare - - return value : - UNZ_OK if the file is found. It becomes the current file. - UNZ_END_OF_LIST_OF_FILE if the file is not found -*/ - - -/* ****************************************** */ -/* Ryan supplied functions */ -/* unz_file_info contain information about a file in the zipfile */ -typedef struct unz_file_pos_s -{ - uLong pos_in_zip_directory; /* offset in zip file directory */ - uLong num_of_file; /* # of file */ -} unz_file_pos; - -extern int ZEXPORT unzGetFilePos( - unzFile file, - unz_file_pos* file_pos); - -extern int ZEXPORT unzGoToFilePos( - unzFile file, - unz_file_pos* file_pos); - -typedef struct unz64_file_pos_s -{ - ZPOS64_T pos_in_zip_directory; /* offset in zip file directory */ - ZPOS64_T num_of_file; /* # of file */ -} unz64_file_pos; - -extern int ZEXPORT unzGetFilePos64( - unzFile file, - unz64_file_pos* file_pos); - -extern int ZEXPORT unzGoToFilePos64( - unzFile file, - const unz64_file_pos* file_pos); - -/* ****************************************** */ - -extern int ZEXPORT unzGetCurrentFileInfo64 OF((unzFile file, - unz_file_info64 *pfile_info, - char *szFileName, - uLong fileNameBufferSize, - void *extraField, - uLong extraFieldBufferSize, - char *szComment, - uLong commentBufferSize)); - -extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file, - unz_file_info *pfile_info, - char *szFileName, - uLong fileNameBufferSize, - void *extraField, - uLong extraFieldBufferSize, - char *szComment, - uLong commentBufferSize)); -/* - Get Info about the current file - if pfile_info!=NULL, the *pfile_info structure will contain somes info about - the current file - if szFileName!=NULL, the filemane string will be copied in szFileName - (fileNameBufferSize is the size of the buffer) - if extraField!=NULL, the extra field information will be copied in extraField - (extraFieldBufferSize is the size of the buffer). - This is the Central-header version of the extra field - if szComment!=NULL, the comment string of the file will be copied in szComment - (commentBufferSize is the size of the buffer) -*/ - - -/** Addition for GDAL : START */ - -extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64 OF((unzFile file)); - -/** Addition for GDAL : END */ - - -/***************************************************************************/ -/* for reading the content of the current zipfile, you can open it, read data - from it, and close it (you can close it before reading all the file) - */ - -extern int ZEXPORT unzOpenCurrentFile OF((unzFile file)); -/* - Open for reading data the current file in the zipfile. - If there is no error, the return value is UNZ_OK. -*/ - -extern int ZEXPORT unzOpenCurrentFilePassword OF((unzFile file, - const char* password)); -/* - Open for reading data the current file in the zipfile. - password is a crypting password - If there is no error, the return value is UNZ_OK. -*/ - -extern int ZEXPORT unzOpenCurrentFile2 OF((unzFile file, - int* method, - int* level, - int raw)); -/* - Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) - if raw==1 - *method will receive method of compression, *level will receive level of - compression - note : you can set level parameter as NULL (if you did not want known level, - but you CANNOT set method parameter as NULL -*/ - -extern int ZEXPORT unzOpenCurrentFile3 OF((unzFile file, - int* method, - int* level, - int raw, - const char* password)); -/* - Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) - if raw==1 - *method will receive method of compression, *level will receive level of - compression - note : you can set level parameter as NULL (if you did not want known level, - but you CANNOT set method parameter as NULL -*/ - - -extern int ZEXPORT unzCloseCurrentFile OF((unzFile file)); -/* - Close the file in zip opened with unzOpenCurrentFile - Return UNZ_CRCERROR if all the file was read but the CRC is not good -*/ - -extern int ZEXPORT unzReadCurrentFile OF((unzFile file, - voidp buf, - unsigned len)); -/* - Read bytes from the current file (opened by unzOpenCurrentFile) - buf contain buffer where data must be copied - len the size of buf. - - return the number of byte copied if somes bytes are copied - return 0 if the end of file was reached - return <0 with error code if there is an error - (UNZ_ERRNO for IO error, or zLib error for uncompress error) -*/ - -extern z_off_t ZEXPORT unztell OF((unzFile file)); - -extern ZPOS64_T ZEXPORT unztell64 OF((unzFile file)); -/* - Give the current position in uncompressed data -*/ - -extern int ZEXPORT unzeof OF((unzFile file)); -/* - return 1 if the end of file was reached, 0 elsewhere -*/ - -extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file, - voidp buf, - unsigned len)); -/* - Read extra field from the current file (opened by unzOpenCurrentFile) - This is the local-header version of the extra field (sometimes, there is - more info in the local-header version than in the central-header) - - if buf==NULL, it return the size of the local extra field - - if buf!=NULL, len is the size of the buffer, the extra header is copied in - buf. - the return value is the number of bytes copied in buf, or (if <0) - the error code -*/ - -/***************************************************************************/ - -/* Get the current file offset */ -extern ZPOS64_T ZEXPORT unzGetOffset64 (unzFile file); -extern uLong ZEXPORT unzGetOffset (unzFile file); - -/* Set the current file offset */ -extern int ZEXPORT unzSetOffset64 (unzFile file, ZPOS64_T pos); -extern int ZEXPORT unzSetOffset (unzFile file, uLong pos); - - - -#ifdef __cplusplus -} -#endif - -#endif /* _unz64_H */ diff --git a/vendor/minizip/zip.c b/vendor/minizip/zip.c deleted file mode 100644 index ea54853e8..000000000 --- a/vendor/minizip/zip.c +++ /dev/null @@ -1,2007 +0,0 @@ -/* zip.c -- IO on .zip files using zlib - Version 1.1, February 14h, 2010 - part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) - - Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) - - Modifications for Zip64 support - Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) - - For more info read MiniZip_info.txt - - Changes - Oct-2009 - Mathias Svensson - Remove old C style function prototypes - Oct-2009 - Mathias Svensson - Added Zip64 Support when creating new file archives - Oct-2009 - Mathias Svensson - Did some code cleanup and refactoring to get better overview of some functions. - Oct-2009 - Mathias Svensson - Added zipRemoveExtraInfoBlock to strip extra field data from its ZIP64 data - It is used when recreting zip archive with RAW when deleting items from a zip. - ZIP64 data is automaticly added to items that needs it, and existing ZIP64 data need to be removed. - Oct-2009 - Mathias Svensson - Added support for BZIP2 as compression mode (bzip2 lib is required) - Jan-2010 - back to unzip and minizip 1.0 name scheme, with compatibility layer - -*/ - - -#include -#include -#include -#include -#include "zlib.h" -#include "zip.h" - -#ifdef STDC -# include -# include -# include -#endif -#ifdef NO_ERRNO_H - extern int errno; -#else -# include -#endif - - -#ifndef local -# define local static -#endif -/* compile with -Dlocal if your debugger can't find static symbols */ - -#ifndef VERSIONMADEBY -# define VERSIONMADEBY (0x0) /* platform depedent */ -#endif - -#ifndef Z_BUFSIZE -#define Z_BUFSIZE (64*1024) //(16384) -#endif - -#ifndef Z_MAXFILENAMEINZIP -#define Z_MAXFILENAMEINZIP (256) -#endif - -#ifndef ALLOC -# define ALLOC(size) (malloc(size)) -#endif -#ifndef TRYFREE -# define TRYFREE(p) {if (p) free(p);} -#endif - -/* -#define SIZECENTRALDIRITEM (0x2e) -#define SIZEZIPLOCALHEADER (0x1e) -*/ - -/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */ - - -// NOT sure that this work on ALL platform -#define MAKEULONG64(a, b) ((ZPOS64_T)(((unsigned long)(a)) | ((ZPOS64_T)((unsigned long)(b))) << 32)) - -#ifndef SEEK_CUR -#define SEEK_CUR 1 -#endif - -#ifndef SEEK_END -#define SEEK_END 2 -#endif - -#ifndef SEEK_SET -#define SEEK_SET 0 -#endif - -#ifndef DEF_MEM_LEVEL -#if MAX_MEM_LEVEL >= 8 -# define DEF_MEM_LEVEL 8 -#else -# define DEF_MEM_LEVEL MAX_MEM_LEVEL -#endif -#endif -const char zip_copyright[] =" zip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll"; - - -#define SIZEDATA_INDATABLOCK (4096-(4*4)) - -#define LOCALHEADERMAGIC (0x04034b50) -#define CENTRALHEADERMAGIC (0x02014b50) -#define ENDHEADERMAGIC (0x06054b50) -#define ZIP64ENDHEADERMAGIC (0x6064b50) -#define ZIP64ENDLOCHEADERMAGIC (0x7064b50) - -#define FLAG_LOCALHEADER_OFFSET (0x06) -#define CRC_LOCALHEADER_OFFSET (0x0e) - -#define SIZECENTRALHEADER (0x2e) /* 46 */ - -typedef struct linkedlist_datablock_internal_s -{ - struct linkedlist_datablock_internal_s* next_datablock; - uLong avail_in_this_block; - uLong filled_in_this_block; - uLong unused; /* for future use and alignement */ - unsigned char data[SIZEDATA_INDATABLOCK]; -} linkedlist_datablock_internal; - -typedef struct linkedlist_data_s -{ - linkedlist_datablock_internal* first_block; - linkedlist_datablock_internal* last_block; -} linkedlist_data; - - -typedef struct -{ - z_stream stream; /* zLib stream structure for inflate */ -#ifdef HAVE_BZIP2 - bz_stream bstream; /* bzLib stream structure for bziped */ -#endif - - int stream_initialised; /* 1 is stream is initialised */ - uInt pos_in_buffered_data; /* last written byte in buffered_data */ - - ZPOS64_T pos_local_header; /* offset of the local header of the file - currenty writing */ - char* central_header; /* central header data for the current file */ - uLong size_centralExtra; - uLong size_centralheader; /* size of the central header for cur file */ - uLong size_centralExtraFree; /* Extra bytes allocated to the centralheader but that are not used */ - uLong flag; /* flag of the file currently writing */ - - int method; /* compression method of file currenty wr.*/ - int raw; /* 1 for directly writing raw data */ - Byte buffered_data[Z_BUFSIZE];/* buffer contain compressed data to be writ*/ - uLong dosDate; - uLong crc32; - int encrypt; - int zip64; /* Add ZIP64 extened information in the extra field */ - ZPOS64_T pos_zip64extrainfo; - ZPOS64_T totalCompressedData; - ZPOS64_T totalUncompressedData; -#ifndef NOCRYPT - unsigned long keys[3]; /* keys defining the pseudo-random sequence */ - const z_crc_t* pcrc_32_tab; - int crypt_header_size; -#endif -} curfile64_info; - -typedef struct -{ - zlib_filefunc64_32_def z_filefunc; - voidpf filestream; /* io structore of the zipfile */ - linkedlist_data central_dir;/* datablock with central dir in construction*/ - int in_opened_file_inzip; /* 1 if a file in the zip is currently writ.*/ - curfile64_info ci; /* info on the file curretly writing */ - - ZPOS64_T begin_pos; /* position of the beginning of the zipfile */ - ZPOS64_T add_position_when_writting_offset; - ZPOS64_T number_entry; - -#ifndef NO_ADDFILEINEXISTINGZIP - char *globalcomment; -#endif - -} zip64_internal; - - -#ifndef NOCRYPT -#define INCLUDECRYPTINGCODE_IFCRYPTALLOWED -#include "crypt.h" -#endif - -local linkedlist_datablock_internal* allocate_new_datablock() -{ - linkedlist_datablock_internal* ldi; - ldi = (linkedlist_datablock_internal*) - ALLOC(sizeof(linkedlist_datablock_internal)); - if (ldi!=NULL) - { - ldi->next_datablock = NULL ; - ldi->filled_in_this_block = 0 ; - ldi->avail_in_this_block = SIZEDATA_INDATABLOCK ; - } - return ldi; -} - -local void free_datablock(linkedlist_datablock_internal* ldi) -{ - while (ldi!=NULL) - { - linkedlist_datablock_internal* ldinext = ldi->next_datablock; - TRYFREE(ldi); - ldi = ldinext; - } -} - -local void init_linkedlist(linkedlist_data* ll) -{ - ll->first_block = ll->last_block = NULL; -} - -local void free_linkedlist(linkedlist_data* ll) -{ - free_datablock(ll->first_block); - ll->first_block = ll->last_block = NULL; -} - - -local int add_data_in_datablock(linkedlist_data* ll, const void* buf, uLong len) -{ - linkedlist_datablock_internal* ldi; - const unsigned char* from_copy; - - if (ll==NULL) - return ZIP_INTERNALERROR; - - if (ll->last_block == NULL) - { - ll->first_block = ll->last_block = allocate_new_datablock(); - if (ll->first_block == NULL) - return ZIP_INTERNALERROR; - } - - ldi = ll->last_block; - from_copy = (unsigned char*)buf; - - while (len>0) - { - uInt copy_this; - uInt i; - unsigned char* to_copy; - - if (ldi->avail_in_this_block==0) - { - ldi->next_datablock = allocate_new_datablock(); - if (ldi->next_datablock == NULL) - return ZIP_INTERNALERROR; - ldi = ldi->next_datablock ; - ll->last_block = ldi; - } - - if (ldi->avail_in_this_block < len) - copy_this = (uInt)ldi->avail_in_this_block; - else - copy_this = (uInt)len; - - to_copy = &(ldi->data[ldi->filled_in_this_block]); - - for (i=0;ifilled_in_this_block += copy_this; - ldi->avail_in_this_block -= copy_this; - from_copy += copy_this ; - len -= copy_this; - } - return ZIP_OK; -} - - - -/****************************************************************************/ - -#ifndef NO_ADDFILEINEXISTINGZIP -/* =========================================================================== - Inputs a long in LSB order to the given file - nbByte == 1, 2 ,4 or 8 (byte, short or long, ZPOS64_T) -*/ - -local int zip64local_putValue OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T x, int nbByte)); -local int zip64local_putValue (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T x, int nbByte) -{ - unsigned char buf[8]; - int n; - for (n = 0; n < nbByte; n++) - { - buf[n] = (unsigned char)(x & 0xff); - x >>= 8; - } - if (x != 0) - { /* data overflow - hack for ZIP64 (X Roche) */ - for (n = 0; n < nbByte; n++) - { - buf[n] = 0xff; - } - } - - if (ZWRITE64(*pzlib_filefunc_def,filestream,buf,nbByte)!=(uLong)nbByte) - return ZIP_ERRNO; - else - return ZIP_OK; -} - -local void zip64local_putValue_inmemory OF((void* dest, ZPOS64_T x, int nbByte)); -local void zip64local_putValue_inmemory (void* dest, ZPOS64_T x, int nbByte) -{ - unsigned char* buf=(unsigned char*)dest; - int n; - for (n = 0; n < nbByte; n++) { - buf[n] = (unsigned char)(x & 0xff); - x >>= 8; - } - - if (x != 0) - { /* data overflow - hack for ZIP64 */ - for (n = 0; n < nbByte; n++) - { - buf[n] = 0xff; - } - } -} - -/****************************************************************************/ - - -local uLong zip64local_TmzDateToDosDate(const tm_zip* ptm) -{ - uLong year = (uLong)ptm->tm_year; - if (year>=1980) - year-=1980; - else if (year>=80) - year-=80; - return - (uLong) (((ptm->tm_mday) + (32 * (ptm->tm_mon+1)) + (512 * year)) << 16) | - ((ptm->tm_sec/2) + (32* ptm->tm_min) + (2048 * (uLong)ptm->tm_hour)); -} - - -/****************************************************************************/ - -local int zip64local_getByte OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, int *pi)); - -local int zip64local_getByte(const zlib_filefunc64_32_def* pzlib_filefunc_def,voidpf filestream,int* pi) -{ - unsigned char c; - int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,&c,1); - if (err==1) - { - *pi = (int)c; - return ZIP_OK; - } - else - { - if (ZERROR64(*pzlib_filefunc_def,filestream)) - return ZIP_ERRNO; - else - return ZIP_EOF; - } -} - - -/* =========================================================================== - Reads a long in LSB order from the given gz_stream. Sets -*/ -local int zip64local_getShort OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong *pX)); - -local int zip64local_getShort (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong* pX) -{ - uLong x ; - int i = 0; - int err; - - err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); - x = (uLong)i; - - if (err==ZIP_OK) - err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); - x += ((uLong)i)<<8; - - if (err==ZIP_OK) - *pX = x; - else - *pX = 0; - return err; -} - -local int zip64local_getLong OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong *pX)); - -local int zip64local_getLong (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong* pX) -{ - uLong x ; - int i = 0; - int err; - - err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); - x = (uLong)i; - - if (err==ZIP_OK) - err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); - x += ((uLong)i)<<8; - - if (err==ZIP_OK) - err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); - x += ((uLong)i)<<16; - - if (err==ZIP_OK) - err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); - x += ((uLong)i)<<24; - - if (err==ZIP_OK) - *pX = x; - else - *pX = 0; - return err; -} - -local int zip64local_getLong64 OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T *pX)); - - -local int zip64local_getLong64 (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T *pX) -{ - ZPOS64_T x; - int i = 0; - int err; - - err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); - x = (ZPOS64_T)i; - - if (err==ZIP_OK) - err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); - x += ((ZPOS64_T)i)<<8; - - if (err==ZIP_OK) - err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); - x += ((ZPOS64_T)i)<<16; - - if (err==ZIP_OK) - err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); - x += ((ZPOS64_T)i)<<24; - - if (err==ZIP_OK) - err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); - x += ((ZPOS64_T)i)<<32; - - if (err==ZIP_OK) - err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); - x += ((ZPOS64_T)i)<<40; - - if (err==ZIP_OK) - err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); - x += ((ZPOS64_T)i)<<48; - - if (err==ZIP_OK) - err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); - x += ((ZPOS64_T)i)<<56; - - if (err==ZIP_OK) - *pX = x; - else - *pX = 0; - - return err; -} - -#ifndef BUFREADCOMMENT -#define BUFREADCOMMENT (0x400) -#endif -/* - Locate the Central directory of a zipfile (at the end, just before - the global comment) -*/ -local ZPOS64_T zip64local_SearchCentralDir OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)); - -local ZPOS64_T zip64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) -{ - unsigned char* buf; - ZPOS64_T uSizeFile; - ZPOS64_T uBackRead; - ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */ - ZPOS64_T uPosFound=0; - - if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) - return 0; - - - uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream); - - if (uMaxBack>uSizeFile) - uMaxBack = uSizeFile; - - buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); - if (buf==NULL) - return 0; - - uBackRead = 4; - while (uBackReaduMaxBack) - uBackRead = uMaxBack; - else - uBackRead+=BUFREADCOMMENT; - uReadPos = uSizeFile-uBackRead ; - - uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? - (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos); - if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) - break; - - if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) - break; - - for (i=(int)uReadSize-3; (i--)>0;) - if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && - ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06)) - { - uPosFound = uReadPos+i; - break; - } - - if (uPosFound!=0) - break; - } - TRYFREE(buf); - return uPosFound; -} - -/* -Locate the End of Zip64 Central directory locator and from there find the CD of a zipfile (at the end, just before -the global comment) -*/ -local ZPOS64_T zip64local_SearchCentralDir64 OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)); - -local ZPOS64_T zip64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) -{ - unsigned char* buf; - ZPOS64_T uSizeFile; - ZPOS64_T uBackRead; - ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */ - ZPOS64_T uPosFound=0; - uLong uL; - ZPOS64_T relativeOffset; - - if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) - return 0; - - uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream); - - if (uMaxBack>uSizeFile) - uMaxBack = uSizeFile; - - buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); - if (buf==NULL) - return 0; - - uBackRead = 4; - while (uBackReaduMaxBack) - uBackRead = uMaxBack; - else - uBackRead+=BUFREADCOMMENT; - uReadPos = uSizeFile-uBackRead ; - - uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? - (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos); - if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) - break; - - if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) - break; - - for (i=(int)uReadSize-3; (i--)>0;) - { - // Signature "0x07064b50" Zip64 end of central directory locater - if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && ((*(buf+i+2))==0x06) && ((*(buf+i+3))==0x07)) - { - uPosFound = uReadPos+i; - break; - } - } - - if (uPosFound!=0) - break; - } - - TRYFREE(buf); - if (uPosFound == 0) - return 0; - - /* Zip64 end of central directory locator */ - if (ZSEEK64(*pzlib_filefunc_def,filestream, uPosFound,ZLIB_FILEFUNC_SEEK_SET)!=0) - return 0; - - /* the signature, already checked */ - if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK) - return 0; - - /* number of the disk with the start of the zip64 end of central directory */ - if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK) - return 0; - if (uL != 0) - return 0; - - /* relative offset of the zip64 end of central directory record */ - if (zip64local_getLong64(pzlib_filefunc_def,filestream,&relativeOffset)!=ZIP_OK) - return 0; - - /* total number of disks */ - if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK) - return 0; - if (uL != 1) - return 0; - - /* Goto Zip64 end of central directory record */ - if (ZSEEK64(*pzlib_filefunc_def,filestream, relativeOffset,ZLIB_FILEFUNC_SEEK_SET)!=0) - return 0; - - /* the signature */ - if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK) - return 0; - - if (uL != 0x06064b50) // signature of 'Zip64 end of central directory' - return 0; - - return relativeOffset; -} - -int LoadCentralDirectoryRecord(zip64_internal* pziinit) -{ - int err=ZIP_OK; - ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ - - ZPOS64_T size_central_dir; /* size of the central directory */ - ZPOS64_T offset_central_dir; /* offset of start of central directory */ - ZPOS64_T central_pos; - uLong uL; - - uLong number_disk; /* number of the current dist, used for - spaning ZIP, unsupported, always 0*/ - uLong number_disk_with_CD; /* number the the disk with central dir, used - for spaning ZIP, unsupported, always 0*/ - ZPOS64_T number_entry; - ZPOS64_T number_entry_CD; /* total number of entries in - the central dir - (same than number_entry on nospan) */ - uLong VersionMadeBy; - uLong VersionNeeded; - uLong size_comment; - - int hasZIP64Record = 0; - - // check first if we find a ZIP64 record - central_pos = zip64local_SearchCentralDir64(&pziinit->z_filefunc,pziinit->filestream); - if(central_pos > 0) - { - hasZIP64Record = 1; - } - else if(central_pos == 0) - { - central_pos = zip64local_SearchCentralDir(&pziinit->z_filefunc,pziinit->filestream); - } - -/* disable to allow appending to empty ZIP archive - if (central_pos==0) - err=ZIP_ERRNO; -*/ - - if(hasZIP64Record) - { - ZPOS64_T sizeEndOfCentralDirectory; - if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, central_pos, ZLIB_FILEFUNC_SEEK_SET) != 0) - err=ZIP_ERRNO; - - /* the signature, already checked */ - if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&uL)!=ZIP_OK) - err=ZIP_ERRNO; - - /* size of zip64 end of central directory record */ - if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream, &sizeEndOfCentralDirectory)!=ZIP_OK) - err=ZIP_ERRNO; - - /* version made by */ - if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &VersionMadeBy)!=ZIP_OK) - err=ZIP_ERRNO; - - /* version needed to extract */ - if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &VersionNeeded)!=ZIP_OK) - err=ZIP_ERRNO; - - /* number of this disk */ - if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&number_disk)!=ZIP_OK) - err=ZIP_ERRNO; - - /* number of the disk with the start of the central directory */ - if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&number_disk_with_CD)!=ZIP_OK) - err=ZIP_ERRNO; - - /* total number of entries in the central directory on this disk */ - if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream, &number_entry)!=ZIP_OK) - err=ZIP_ERRNO; - - /* total number of entries in the central directory */ - if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream,&number_entry_CD)!=ZIP_OK) - err=ZIP_ERRNO; - - if ((number_entry_CD!=number_entry) || (number_disk_with_CD!=0) || (number_disk!=0)) - err=ZIP_BADZIPFILE; - - /* size of the central directory */ - if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream,&size_central_dir)!=ZIP_OK) - err=ZIP_ERRNO; - - /* offset of start of central directory with respect to the - starting disk number */ - if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream,&offset_central_dir)!=ZIP_OK) - err=ZIP_ERRNO; - - // TODO.. - // read the comment from the standard central header. - size_comment = 0; - } - else - { - // Read End of central Directory info - if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0) - err=ZIP_ERRNO; - - /* the signature, already checked */ - if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&uL)!=ZIP_OK) - err=ZIP_ERRNO; - - /* number of this disk */ - if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream,&number_disk)!=ZIP_OK) - err=ZIP_ERRNO; - - /* number of the disk with the start of the central directory */ - if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream,&number_disk_with_CD)!=ZIP_OK) - err=ZIP_ERRNO; - - /* total number of entries in the central dir on this disk */ - number_entry = 0; - if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK) - err=ZIP_ERRNO; - else - number_entry = uL; - - /* total number of entries in the central dir */ - number_entry_CD = 0; - if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK) - err=ZIP_ERRNO; - else - number_entry_CD = uL; - - if ((number_entry_CD!=number_entry) || (number_disk_with_CD!=0) || (number_disk!=0)) - err=ZIP_BADZIPFILE; - - /* size of the central directory */ - size_central_dir = 0; - if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK) - err=ZIP_ERRNO; - else - size_central_dir = uL; - - /* offset of start of central directory with respect to the starting disk number */ - offset_central_dir = 0; - if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK) - err=ZIP_ERRNO; - else - offset_central_dir = uL; - - - /* zipfile global comment length */ - if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &size_comment)!=ZIP_OK) - err=ZIP_ERRNO; - } - - if ((central_posz_filefunc, pziinit->filestream); - return ZIP_ERRNO; - } - - if (size_comment>0) - { - pziinit->globalcomment = (char*)ALLOC(size_comment+1); - if (pziinit->globalcomment) - { - size_comment = ZREAD64(pziinit->z_filefunc, pziinit->filestream, pziinit->globalcomment,size_comment); - pziinit->globalcomment[size_comment]=0; - } - } - - byte_before_the_zipfile = central_pos - (offset_central_dir+size_central_dir); - pziinit->add_position_when_writting_offset = byte_before_the_zipfile; - - { - ZPOS64_T size_central_dir_to_read = size_central_dir; - size_t buf_size = SIZEDATA_INDATABLOCK; - void* buf_read = (void*)ALLOC(buf_size); - if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, offset_central_dir + byte_before_the_zipfile, ZLIB_FILEFUNC_SEEK_SET) != 0) - err=ZIP_ERRNO; - - while ((size_central_dir_to_read>0) && (err==ZIP_OK)) - { - ZPOS64_T read_this = SIZEDATA_INDATABLOCK; - if (read_this > size_central_dir_to_read) - read_this = size_central_dir_to_read; - - if (ZREAD64(pziinit->z_filefunc, pziinit->filestream,buf_read,(uLong)read_this) != read_this) - err=ZIP_ERRNO; - - if (err==ZIP_OK) - err = add_data_in_datablock(&pziinit->central_dir,buf_read, (uLong)read_this); - - size_central_dir_to_read-=read_this; - } - TRYFREE(buf_read); - } - pziinit->begin_pos = byte_before_the_zipfile; - pziinit->number_entry = number_entry_CD; - - if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, offset_central_dir+byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET) != 0) - err=ZIP_ERRNO; - - return err; -} - - -#endif /* !NO_ADDFILEINEXISTINGZIP*/ - - -/************************************************************/ -extern zipFile ZEXPORT zipOpen3 (const void *pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_32_def* pzlib_filefunc64_32_def) -{ - zip64_internal ziinit; - zip64_internal* zi; - int err=ZIP_OK; - - ziinit.z_filefunc.zseek32_file = NULL; - ziinit.z_filefunc.ztell32_file = NULL; - if (pzlib_filefunc64_32_def==NULL) - fill_fopen64_filefunc(&ziinit.z_filefunc.zfile_func64); - else - ziinit.z_filefunc = *pzlib_filefunc64_32_def; - - ziinit.filestream = ZOPEN64(ziinit.z_filefunc, - pathname, - (append == APPEND_STATUS_CREATE) ? - (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_CREATE) : - (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_EXISTING)); - - if (ziinit.filestream == NULL) - return NULL; - - if (append == APPEND_STATUS_CREATEAFTER) - ZSEEK64(ziinit.z_filefunc,ziinit.filestream,0,SEEK_END); - - ziinit.begin_pos = ZTELL64(ziinit.z_filefunc,ziinit.filestream); - ziinit.in_opened_file_inzip = 0; - ziinit.ci.stream_initialised = 0; - ziinit.number_entry = 0; - ziinit.add_position_when_writting_offset = 0; - init_linkedlist(&(ziinit.central_dir)); - - - - zi = (zip64_internal*)ALLOC(sizeof(zip64_internal)); - if (zi==NULL) - { - ZCLOSE64(ziinit.z_filefunc,ziinit.filestream); - return NULL; - } - - /* now we add file in a zipfile */ -# ifndef NO_ADDFILEINEXISTINGZIP - ziinit.globalcomment = NULL; - if (append == APPEND_STATUS_ADDINZIP) - { - // Read and Cache Central Directory Records - err = LoadCentralDirectoryRecord(&ziinit); - } - - if (globalcomment) - { - *globalcomment = ziinit.globalcomment; - } -# endif /* !NO_ADDFILEINEXISTINGZIP*/ - - if (err != ZIP_OK) - { -# ifndef NO_ADDFILEINEXISTINGZIP - TRYFREE(ziinit.globalcomment); -# endif /* !NO_ADDFILEINEXISTINGZIP*/ - TRYFREE(zi); - return NULL; - } - else - { - *zi = ziinit; - return (zipFile)zi; - } -} - -extern zipFile ZEXPORT zipOpen2 (const char *pathname, int append, zipcharpc* globalcomment, zlib_filefunc_def* pzlib_filefunc32_def) -{ - if (pzlib_filefunc32_def != NULL) - { - zlib_filefunc64_32_def zlib_filefunc64_32_def_fill; - fill_zlib_filefunc64_32_def_from_filefunc32(&zlib_filefunc64_32_def_fill,pzlib_filefunc32_def); - return zipOpen3(pathname, append, globalcomment, &zlib_filefunc64_32_def_fill); - } - else - return zipOpen3(pathname, append, globalcomment, NULL); -} - -extern zipFile ZEXPORT zipOpen2_64 (const void *pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_def* pzlib_filefunc_def) -{ - if (pzlib_filefunc_def != NULL) - { - zlib_filefunc64_32_def zlib_filefunc64_32_def_fill; - zlib_filefunc64_32_def_fill.zfile_func64 = *pzlib_filefunc_def; - zlib_filefunc64_32_def_fill.ztell32_file = NULL; - zlib_filefunc64_32_def_fill.zseek32_file = NULL; - return zipOpen3(pathname, append, globalcomment, &zlib_filefunc64_32_def_fill); - } - else - return zipOpen3(pathname, append, globalcomment, NULL); -} - - - -extern zipFile ZEXPORT zipOpen (const char* pathname, int append) -{ - return zipOpen3((const void*)pathname,append,NULL,NULL); -} - -extern zipFile ZEXPORT zipOpen64 (const void* pathname, int append) -{ - return zipOpen3(pathname,append,NULL,NULL); -} - -int Write_LocalFileHeader(zip64_internal* zi, const char* filename, uInt size_extrafield_local, const void* extrafield_local) -{ - /* write the local header */ - int err; - uInt size_filename = (uInt)strlen(filename); - uInt size_extrafield = size_extrafield_local; - - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)LOCALHEADERMAGIC, 4); - - if (err==ZIP_OK) - { - if(zi->ci.zip64) - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)45,2);/* version needed to extract */ - else - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)20,2);/* version needed to extract */ - } - - if (err==ZIP_OK) - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.flag,2); - - if (err==ZIP_OK) - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.method,2); - - if (err==ZIP_OK) - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.dosDate,4); - - // CRC / Compressed size / Uncompressed size will be filled in later and rewritten later - if (err==ZIP_OK) - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* crc 32, unknown */ - if (err==ZIP_OK) - { - if(zi->ci.zip64) - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xFFFFFFFF,4); /* compressed size, unknown */ - else - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* compressed size, unknown */ - } - if (err==ZIP_OK) - { - if(zi->ci.zip64) - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xFFFFFFFF,4); /* uncompressed size, unknown */ - else - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* uncompressed size, unknown */ - } - - if (err==ZIP_OK) - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_filename,2); - - if(zi->ci.zip64) - { - size_extrafield += 20; - } - - if (err==ZIP_OK) - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_extrafield,2); - - if ((err==ZIP_OK) && (size_filename > 0)) - { - if (ZWRITE64(zi->z_filefunc,zi->filestream,filename,size_filename)!=size_filename) - err = ZIP_ERRNO; - } - - if ((err==ZIP_OK) && (size_extrafield_local > 0)) - { - if (ZWRITE64(zi->z_filefunc, zi->filestream, extrafield_local, size_extrafield_local) != size_extrafield_local) - err = ZIP_ERRNO; - } - - - if ((err==ZIP_OK) && (zi->ci.zip64)) - { - // write the Zip64 extended info - short HeaderID = 1; - short DataSize = 16; - ZPOS64_T CompressedSize = 0; - ZPOS64_T UncompressedSize = 0; - - // Remember position of Zip64 extended info for the local file header. (needed when we update size after done with file) - zi->ci.pos_zip64extrainfo = ZTELL64(zi->z_filefunc,zi->filestream); - - err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (short)HeaderID,2); - err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (short)DataSize,2); - - err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)UncompressedSize,8); - err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)CompressedSize,8); - } - - return err; -} - -/* - NOTE. - When writing RAW the ZIP64 extended information in extrafield_local and extrafield_global needs to be stripped - before calling this function it can be done with zipRemoveExtraInfoBlock - - It is not done here because then we need to realloc a new buffer since parameters are 'const' and I want to minimize - unnecessary allocations. - */ -extern int ZEXPORT zipOpenNewFileInZip4_64 (zipFile file, const char* filename, const zip_fileinfo* zipfi, - const void* extrafield_local, uInt size_extrafield_local, - const void* extrafield_global, uInt size_extrafield_global, - const char* comment, int method, int level, int raw, - int windowBits,int memLevel, int strategy, - const char* password, uLong crcForCrypting, - uLong versionMadeBy, uLong flagBase, int zip64) -{ - zip64_internal* zi; - uInt size_filename; - uInt size_comment; - uInt i; - int err = ZIP_OK; - -# ifdef NOCRYPT - (crcForCrypting); - if (password != NULL) - return ZIP_PARAMERROR; -# endif - - if (file == NULL) - return ZIP_PARAMERROR; - -#ifdef HAVE_BZIP2 - if ((method!=0) && (method!=Z_DEFLATED) && (method!=Z_BZIP2ED)) - return ZIP_PARAMERROR; -#else - if ((method!=0) && (method!=Z_DEFLATED)) - return ZIP_PARAMERROR; -#endif - - zi = (zip64_internal*)file; - - if (zi->in_opened_file_inzip == 1) - { - err = zipCloseFileInZip (file); - if (err != ZIP_OK) - return err; - } - - if (filename==NULL) - filename="-"; - - if (comment==NULL) - size_comment = 0; - else - size_comment = (uInt)strlen(comment); - - size_filename = (uInt)strlen(filename); - - if (zipfi == NULL) - zi->ci.dosDate = 0; - else - { - if (zipfi->dosDate != 0) - zi->ci.dosDate = zipfi->dosDate; - else - zi->ci.dosDate = zip64local_TmzDateToDosDate(&zipfi->tmz_date); - } - - zi->ci.flag = flagBase; - if ((level==8) || (level==9)) - zi->ci.flag |= 2; - if (level==2) - zi->ci.flag |= 4; - if (level==1) - zi->ci.flag |= 6; - if (password != NULL) - zi->ci.flag |= 1; - - zi->ci.crc32 = 0; - zi->ci.method = method; - zi->ci.encrypt = 0; - zi->ci.stream_initialised = 0; - zi->ci.pos_in_buffered_data = 0; - zi->ci.raw = raw; - zi->ci.pos_local_header = ZTELL64(zi->z_filefunc,zi->filestream); - - zi->ci.size_centralheader = SIZECENTRALHEADER + size_filename + size_extrafield_global + size_comment; - zi->ci.size_centralExtraFree = 32; // Extra space we have reserved in case we need to add ZIP64 extra info data - - zi->ci.central_header = (char*)ALLOC((uInt)zi->ci.size_centralheader + zi->ci.size_centralExtraFree); - - zi->ci.size_centralExtra = size_extrafield_global; - zip64local_putValue_inmemory(zi->ci.central_header,(uLong)CENTRALHEADERMAGIC,4); - /* version info */ - zip64local_putValue_inmemory(zi->ci.central_header+4,(uLong)versionMadeBy,2); - zip64local_putValue_inmemory(zi->ci.central_header+6,(uLong)20,2); - zip64local_putValue_inmemory(zi->ci.central_header+8,(uLong)zi->ci.flag,2); - zip64local_putValue_inmemory(zi->ci.central_header+10,(uLong)zi->ci.method,2); - zip64local_putValue_inmemory(zi->ci.central_header+12,(uLong)zi->ci.dosDate,4); - zip64local_putValue_inmemory(zi->ci.central_header+16,(uLong)0,4); /*crc*/ - zip64local_putValue_inmemory(zi->ci.central_header+20,(uLong)0,4); /*compr size*/ - zip64local_putValue_inmemory(zi->ci.central_header+24,(uLong)0,4); /*uncompr size*/ - zip64local_putValue_inmemory(zi->ci.central_header+28,(uLong)size_filename,2); - zip64local_putValue_inmemory(zi->ci.central_header+30,(uLong)size_extrafield_global,2); - zip64local_putValue_inmemory(zi->ci.central_header+32,(uLong)size_comment,2); - zip64local_putValue_inmemory(zi->ci.central_header+34,(uLong)0,2); /*disk nm start*/ - - if (zipfi==NULL) - zip64local_putValue_inmemory(zi->ci.central_header+36,(uLong)0,2); - else - zip64local_putValue_inmemory(zi->ci.central_header+36,(uLong)zipfi->internal_fa,2); - - if (zipfi==NULL) - zip64local_putValue_inmemory(zi->ci.central_header+38,(uLong)0,4); - else - zip64local_putValue_inmemory(zi->ci.central_header+38,(uLong)zipfi->external_fa,4); - - if(zi->ci.pos_local_header >= 0xffffffff) - zip64local_putValue_inmemory(zi->ci.central_header+42,(uLong)0xffffffff,4); - else - zip64local_putValue_inmemory(zi->ci.central_header+42,(uLong)zi->ci.pos_local_header - zi->add_position_when_writting_offset,4); - - for (i=0;ici.central_header+SIZECENTRALHEADER+i) = *(filename+i); - - for (i=0;ici.central_header+SIZECENTRALHEADER+size_filename+i) = - *(((const char*)extrafield_global)+i); - - for (i=0;ici.central_header+SIZECENTRALHEADER+size_filename+ - size_extrafield_global+i) = *(comment+i); - if (zi->ci.central_header == NULL) - return ZIP_INTERNALERROR; - - zi->ci.zip64 = zip64; - zi->ci.totalCompressedData = 0; - zi->ci.totalUncompressedData = 0; - zi->ci.pos_zip64extrainfo = 0; - - err = Write_LocalFileHeader(zi, filename, size_extrafield_local, extrafield_local); - -#ifdef HAVE_BZIP2 - zi->ci.bstream.avail_in = (uInt)0; - zi->ci.bstream.avail_out = (uInt)Z_BUFSIZE; - zi->ci.bstream.next_out = (char*)zi->ci.buffered_data; - zi->ci.bstream.total_in_hi32 = 0; - zi->ci.bstream.total_in_lo32 = 0; - zi->ci.bstream.total_out_hi32 = 0; - zi->ci.bstream.total_out_lo32 = 0; -#endif - - zi->ci.stream.avail_in = (uInt)0; - zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; - zi->ci.stream.next_out = zi->ci.buffered_data; - zi->ci.stream.total_in = 0; - zi->ci.stream.total_out = 0; - zi->ci.stream.data_type = Z_BINARY; - -#ifdef HAVE_BZIP2 - if ((err==ZIP_OK) && (zi->ci.method == Z_DEFLATED || zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw)) -#else - if ((err==ZIP_OK) && (zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) -#endif - { - if(zi->ci.method == Z_DEFLATED) - { - zi->ci.stream.zalloc = (alloc_func)0; - zi->ci.stream.zfree = (free_func)0; - zi->ci.stream.opaque = (voidpf)0; - - if (windowBits>0) - windowBits = -windowBits; - - err = deflateInit2(&zi->ci.stream, level, Z_DEFLATED, windowBits, memLevel, strategy); - - if (err==Z_OK) - zi->ci.stream_initialised = Z_DEFLATED; - } - else if(zi->ci.method == Z_BZIP2ED) - { -#ifdef HAVE_BZIP2 - // Init BZip stuff here - zi->ci.bstream.bzalloc = 0; - zi->ci.bstream.bzfree = 0; - zi->ci.bstream.opaque = (voidpf)0; - - err = BZ2_bzCompressInit(&zi->ci.bstream, level, 0,35); - if(err == BZ_OK) - zi->ci.stream_initialised = Z_BZIP2ED; -#endif - } - - } - -# ifndef NOCRYPT - zi->ci.crypt_header_size = 0; - if ((err==Z_OK) && (password != NULL)) - { - unsigned char bufHead[RAND_HEAD_LEN]; - unsigned int sizeHead; - zi->ci.encrypt = 1; - zi->ci.pcrc_32_tab = get_crc_table(); - /*init_keys(password,zi->ci.keys,zi->ci.pcrc_32_tab);*/ - - sizeHead=crypthead(password,bufHead,RAND_HEAD_LEN,zi->ci.keys,zi->ci.pcrc_32_tab,crcForCrypting); - zi->ci.crypt_header_size = sizeHead; - - if (ZWRITE64(zi->z_filefunc,zi->filestream,bufHead,sizeHead) != sizeHead) - err = ZIP_ERRNO; - } -# endif - - if (err==Z_OK) - zi->in_opened_file_inzip = 1; - return err; -} - -extern int ZEXPORT zipOpenNewFileInZip4 (zipFile file, const char* filename, const zip_fileinfo* zipfi, - const void* extrafield_local, uInt size_extrafield_local, - const void* extrafield_global, uInt size_extrafield_global, - const char* comment, int method, int level, int raw, - int windowBits,int memLevel, int strategy, - const char* password, uLong crcForCrypting, - uLong versionMadeBy, uLong flagBase) -{ - return zipOpenNewFileInZip4_64 (file, filename, zipfi, - extrafield_local, size_extrafield_local, - extrafield_global, size_extrafield_global, - comment, method, level, raw, - windowBits, memLevel, strategy, - password, crcForCrypting, versionMadeBy, flagBase, 0); -} - -extern int ZEXPORT zipOpenNewFileInZip3 (zipFile file, const char* filename, const zip_fileinfo* zipfi, - const void* extrafield_local, uInt size_extrafield_local, - const void* extrafield_global, uInt size_extrafield_global, - const char* comment, int method, int level, int raw, - int windowBits,int memLevel, int strategy, - const char* password, uLong crcForCrypting) -{ - return zipOpenNewFileInZip4_64 (file, filename, zipfi, - extrafield_local, size_extrafield_local, - extrafield_global, size_extrafield_global, - comment, method, level, raw, - windowBits, memLevel, strategy, - password, crcForCrypting, VERSIONMADEBY, 0, 0); -} - -extern int ZEXPORT zipOpenNewFileInZip3_64(zipFile file, const char* filename, const zip_fileinfo* zipfi, - const void* extrafield_local, uInt size_extrafield_local, - const void* extrafield_global, uInt size_extrafield_global, - const char* comment, int method, int level, int raw, - int windowBits,int memLevel, int strategy, - const char* password, uLong crcForCrypting, int zip64) -{ - return zipOpenNewFileInZip4_64 (file, filename, zipfi, - extrafield_local, size_extrafield_local, - extrafield_global, size_extrafield_global, - comment, method, level, raw, - windowBits, memLevel, strategy, - password, crcForCrypting, VERSIONMADEBY, 0, zip64); -} - -extern int ZEXPORT zipOpenNewFileInZip2(zipFile file, const char* filename, const zip_fileinfo* zipfi, - const void* extrafield_local, uInt size_extrafield_local, - const void* extrafield_global, uInt size_extrafield_global, - const char* comment, int method, int level, int raw) -{ - return zipOpenNewFileInZip4_64 (file, filename, zipfi, - extrafield_local, size_extrafield_local, - extrafield_global, size_extrafield_global, - comment, method, level, raw, - -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, - NULL, 0, VERSIONMADEBY, 0, 0); -} - -extern int ZEXPORT zipOpenNewFileInZip2_64(zipFile file, const char* filename, const zip_fileinfo* zipfi, - const void* extrafield_local, uInt size_extrafield_local, - const void* extrafield_global, uInt size_extrafield_global, - const char* comment, int method, int level, int raw, int zip64) -{ - return zipOpenNewFileInZip4_64 (file, filename, zipfi, - extrafield_local, size_extrafield_local, - extrafield_global, size_extrafield_global, - comment, method, level, raw, - -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, - NULL, 0, VERSIONMADEBY, 0, zip64); -} - -extern int ZEXPORT zipOpenNewFileInZip64 (zipFile file, const char* filename, const zip_fileinfo* zipfi, - const void* extrafield_local, uInt size_extrafield_local, - const void*extrafield_global, uInt size_extrafield_global, - const char* comment, int method, int level, int zip64) -{ - return zipOpenNewFileInZip4_64 (file, filename, zipfi, - extrafield_local, size_extrafield_local, - extrafield_global, size_extrafield_global, - comment, method, level, 0, - -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, - NULL, 0, VERSIONMADEBY, 0, zip64); -} - -extern int ZEXPORT zipOpenNewFileInZip (zipFile file, const char* filename, const zip_fileinfo* zipfi, - const void* extrafield_local, uInt size_extrafield_local, - const void*extrafield_global, uInt size_extrafield_global, - const char* comment, int method, int level) -{ - return zipOpenNewFileInZip4_64 (file, filename, zipfi, - extrafield_local, size_extrafield_local, - extrafield_global, size_extrafield_global, - comment, method, level, 0, - -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, - NULL, 0, VERSIONMADEBY, 0, 0); -} - -local int zip64FlushWriteBuffer(zip64_internal* zi) -{ - int err=ZIP_OK; - - if (zi->ci.encrypt != 0) - { -#ifndef NOCRYPT - uInt i; - int t; - for (i=0;ici.pos_in_buffered_data;i++) - zi->ci.buffered_data[i] = zencode(zi->ci.keys, zi->ci.pcrc_32_tab, zi->ci.buffered_data[i],t); -#endif - } - - if (ZWRITE64(zi->z_filefunc,zi->filestream,zi->ci.buffered_data,zi->ci.pos_in_buffered_data) != zi->ci.pos_in_buffered_data) - err = ZIP_ERRNO; - - zi->ci.totalCompressedData += zi->ci.pos_in_buffered_data; - -#ifdef HAVE_BZIP2 - if(zi->ci.method == Z_BZIP2ED) - { - zi->ci.totalUncompressedData += zi->ci.bstream.total_in_lo32; - zi->ci.bstream.total_in_lo32 = 0; - zi->ci.bstream.total_in_hi32 = 0; - } - else -#endif - { - zi->ci.totalUncompressedData += zi->ci.stream.total_in; - zi->ci.stream.total_in = 0; - } - - - zi->ci.pos_in_buffered_data = 0; - - return err; -} - -extern int ZEXPORT zipWriteInFileInZip (zipFile file,const void* buf,unsigned int len) -{ - zip64_internal* zi; - int err=ZIP_OK; - - if (file == NULL) - return ZIP_PARAMERROR; - zi = (zip64_internal*)file; - - if (zi->in_opened_file_inzip == 0) - return ZIP_PARAMERROR; - - zi->ci.crc32 = crc32(zi->ci.crc32,buf,(uInt)len); - -#ifdef HAVE_BZIP2 - if(zi->ci.method == Z_BZIP2ED && (!zi->ci.raw)) - { - zi->ci.bstream.next_in = (void*)buf; - zi->ci.bstream.avail_in = len; - err = BZ_RUN_OK; - - while ((err==BZ_RUN_OK) && (zi->ci.bstream.avail_in>0)) - { - if (zi->ci.bstream.avail_out == 0) - { - if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO) - err = ZIP_ERRNO; - zi->ci.bstream.avail_out = (uInt)Z_BUFSIZE; - zi->ci.bstream.next_out = (char*)zi->ci.buffered_data; - } - - - if(err != BZ_RUN_OK) - break; - - if ((zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw)) - { - uLong uTotalOutBefore_lo = zi->ci.bstream.total_out_lo32; -// uLong uTotalOutBefore_hi = zi->ci.bstream.total_out_hi32; - err=BZ2_bzCompress(&zi->ci.bstream, BZ_RUN); - - zi->ci.pos_in_buffered_data += (uInt)(zi->ci.bstream.total_out_lo32 - uTotalOutBefore_lo) ; - } - } - - if(err == BZ_RUN_OK) - err = ZIP_OK; - } - else -#endif - { - zi->ci.stream.next_in = (Bytef*)buf; - zi->ci.stream.avail_in = len; - - while ((err==ZIP_OK) && (zi->ci.stream.avail_in>0)) - { - if (zi->ci.stream.avail_out == 0) - { - if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO) - err = ZIP_ERRNO; - zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; - zi->ci.stream.next_out = zi->ci.buffered_data; - } - - - if(err != ZIP_OK) - break; - - if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) - { - uLong uTotalOutBefore = zi->ci.stream.total_out; - err=deflate(&zi->ci.stream, Z_NO_FLUSH); - if(uTotalOutBefore > zi->ci.stream.total_out) - { - int bBreak = 0; - bBreak++; - } - - zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ; - } - else - { - uInt copy_this,i; - if (zi->ci.stream.avail_in < zi->ci.stream.avail_out) - copy_this = zi->ci.stream.avail_in; - else - copy_this = zi->ci.stream.avail_out; - - for (i = 0; i < copy_this; i++) - *(((char*)zi->ci.stream.next_out)+i) = - *(((const char*)zi->ci.stream.next_in)+i); - { - zi->ci.stream.avail_in -= copy_this; - zi->ci.stream.avail_out-= copy_this; - zi->ci.stream.next_in+= copy_this; - zi->ci.stream.next_out+= copy_this; - zi->ci.stream.total_in+= copy_this; - zi->ci.stream.total_out+= copy_this; - zi->ci.pos_in_buffered_data += copy_this; - } - } - }// while(...) - } - - return err; -} - -extern int ZEXPORT zipCloseFileInZipRaw (zipFile file, uLong uncompressed_size, uLong crc32) -{ - return zipCloseFileInZipRaw64 (file, uncompressed_size, crc32); -} - -extern int ZEXPORT zipCloseFileInZipRaw64 (zipFile file, ZPOS64_T uncompressed_size, uLong crc32) -{ - zip64_internal* zi; - ZPOS64_T compressed_size; - uLong invalidValue = 0xffffffff; - short datasize = 0; - int err=ZIP_OK; - - if (file == NULL) - return ZIP_PARAMERROR; - zi = (zip64_internal*)file; - - if (zi->in_opened_file_inzip == 0) - return ZIP_PARAMERROR; - zi->ci.stream.avail_in = 0; - - if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) - { - while (err==ZIP_OK) - { - uLong uTotalOutBefore; - if (zi->ci.stream.avail_out == 0) - { - if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO) - err = ZIP_ERRNO; - zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; - zi->ci.stream.next_out = zi->ci.buffered_data; - } - uTotalOutBefore = zi->ci.stream.total_out; - err=deflate(&zi->ci.stream, Z_FINISH); - zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ; - } - } - else if ((zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw)) - { -#ifdef HAVE_BZIP2 - err = BZ_FINISH_OK; - while (err==BZ_FINISH_OK) - { - uLong uTotalOutBefore; - if (zi->ci.bstream.avail_out == 0) - { - if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO) - err = ZIP_ERRNO; - zi->ci.bstream.avail_out = (uInt)Z_BUFSIZE; - zi->ci.bstream.next_out = (char*)zi->ci.buffered_data; - } - uTotalOutBefore = zi->ci.bstream.total_out_lo32; - err=BZ2_bzCompress(&zi->ci.bstream, BZ_FINISH); - if(err == BZ_STREAM_END) - err = Z_STREAM_END; - - zi->ci.pos_in_buffered_data += (uInt)(zi->ci.bstream.total_out_lo32 - uTotalOutBefore); - } - - if(err == BZ_FINISH_OK) - err = ZIP_OK; -#endif - } - - if (err==Z_STREAM_END) - err=ZIP_OK; /* this is normal */ - - if ((zi->ci.pos_in_buffered_data>0) && (err==ZIP_OK)) - { - if (zip64FlushWriteBuffer(zi)==ZIP_ERRNO) - err = ZIP_ERRNO; - } - - if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) - { - int tmp_err = deflateEnd(&zi->ci.stream); - if (err == ZIP_OK) - err = tmp_err; - zi->ci.stream_initialised = 0; - } -#ifdef HAVE_BZIP2 - else if((zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw)) - { - int tmperr = BZ2_bzCompressEnd(&zi->ci.bstream); - if (err==ZIP_OK) - err = tmperr; - zi->ci.stream_initialised = 0; - } -#endif - - if (!zi->ci.raw) - { - crc32 = (uLong)zi->ci.crc32; - uncompressed_size = zi->ci.totalUncompressedData; - } - compressed_size = zi->ci.totalCompressedData; - -# ifndef NOCRYPT - compressed_size += zi->ci.crypt_header_size; -# endif - - // update Current Item crc and sizes, - if(compressed_size >= 0xffffffff || uncompressed_size >= 0xffffffff || zi->ci.pos_local_header >= 0xffffffff) - { - /*version Made by*/ - zip64local_putValue_inmemory(zi->ci.central_header+4,(uLong)45,2); - /*version needed*/ - zip64local_putValue_inmemory(zi->ci.central_header+6,(uLong)45,2); - - } - - zip64local_putValue_inmemory(zi->ci.central_header+16,crc32,4); /*crc*/ - - - if(compressed_size >= 0xffffffff) - zip64local_putValue_inmemory(zi->ci.central_header+20, invalidValue,4); /*compr size*/ - else - zip64local_putValue_inmemory(zi->ci.central_header+20, compressed_size,4); /*compr size*/ - - /// set internal file attributes field - if (zi->ci.stream.data_type == Z_ASCII) - zip64local_putValue_inmemory(zi->ci.central_header+36,(uLong)Z_ASCII,2); - - if(uncompressed_size >= 0xffffffff) - zip64local_putValue_inmemory(zi->ci.central_header+24, invalidValue,4); /*uncompr size*/ - else - zip64local_putValue_inmemory(zi->ci.central_header+24, uncompressed_size,4); /*uncompr size*/ - - // Add ZIP64 extra info field for uncompressed size - if(uncompressed_size >= 0xffffffff) - datasize += 8; - - // Add ZIP64 extra info field for compressed size - if(compressed_size >= 0xffffffff) - datasize += 8; - - // Add ZIP64 extra info field for relative offset to local file header of current file - if(zi->ci.pos_local_header >= 0xffffffff) - datasize += 8; - - if(datasize > 0) - { - char* p = NULL; - - if((uLong)(datasize + 4) > zi->ci.size_centralExtraFree) - { - // we can not write more data to the buffer that we have room for. - return ZIP_BADZIPFILE; - } - - p = zi->ci.central_header + zi->ci.size_centralheader; - - // Add Extra Information Header for 'ZIP64 information' - zip64local_putValue_inmemory(p, 0x0001, 2); // HeaderID - p += 2; - zip64local_putValue_inmemory(p, datasize, 2); // DataSize - p += 2; - - if(uncompressed_size >= 0xffffffff) - { - zip64local_putValue_inmemory(p, uncompressed_size, 8); - p += 8; - } - - if(compressed_size >= 0xffffffff) - { - zip64local_putValue_inmemory(p, compressed_size, 8); - p += 8; - } - - if(zi->ci.pos_local_header >= 0xffffffff) - { - zip64local_putValue_inmemory(p, zi->ci.pos_local_header, 8); - p += 8; - } - - // Update how much extra free space we got in the memory buffer - // and increase the centralheader size so the new ZIP64 fields are included - // ( 4 below is the size of HeaderID and DataSize field ) - zi->ci.size_centralExtraFree -= datasize + 4; - zi->ci.size_centralheader += datasize + 4; - - // Update the extra info size field - zi->ci.size_centralExtra += datasize + 4; - zip64local_putValue_inmemory(zi->ci.central_header+30,(uLong)zi->ci.size_centralExtra,2); - } - - if (err==ZIP_OK) - err = add_data_in_datablock(&zi->central_dir, zi->ci.central_header, (uLong)zi->ci.size_centralheader); - - free(zi->ci.central_header); - - if (err==ZIP_OK) - { - // Update the LocalFileHeader with the new values. - - ZPOS64_T cur_pos_inzip = ZTELL64(zi->z_filefunc,zi->filestream); - - if (ZSEEK64(zi->z_filefunc,zi->filestream, zi->ci.pos_local_header + 14,ZLIB_FILEFUNC_SEEK_SET)!=0) - err = ZIP_ERRNO; - - if (err==ZIP_OK) - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,crc32,4); /* crc 32, unknown */ - - if(uncompressed_size >= 0xffffffff || compressed_size >= 0xffffffff ) - { - if(zi->ci.pos_zip64extrainfo > 0) - { - // Update the size in the ZIP64 extended field. - if (ZSEEK64(zi->z_filefunc,zi->filestream, zi->ci.pos_zip64extrainfo + 4,ZLIB_FILEFUNC_SEEK_SET)!=0) - err = ZIP_ERRNO; - - if (err==ZIP_OK) /* compressed size, unknown */ - err = zip64local_putValue(&zi->z_filefunc, zi->filestream, uncompressed_size, 8); - - if (err==ZIP_OK) /* uncompressed size, unknown */ - err = zip64local_putValue(&zi->z_filefunc, zi->filestream, compressed_size, 8); - } - else - err = ZIP_BADZIPFILE; // Caller passed zip64 = 0, so no room for zip64 info -> fatal - } - else - { - if (err==ZIP_OK) /* compressed size, unknown */ - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,compressed_size,4); - - if (err==ZIP_OK) /* uncompressed size, unknown */ - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,uncompressed_size,4); - } - - if (ZSEEK64(zi->z_filefunc,zi->filestream, cur_pos_inzip,ZLIB_FILEFUNC_SEEK_SET)!=0) - err = ZIP_ERRNO; - } - - zi->number_entry ++; - zi->in_opened_file_inzip = 0; - - return err; -} - -extern int ZEXPORT zipCloseFileInZip (zipFile file) -{ - return zipCloseFileInZipRaw (file,0,0); -} - -int Write_Zip64EndOfCentralDirectoryLocator(zip64_internal* zi, ZPOS64_T zip64eocd_pos_inzip) -{ - int err = ZIP_OK; - ZPOS64_T pos = zip64eocd_pos_inzip - zi->add_position_when_writting_offset; - - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)ZIP64ENDLOCHEADERMAGIC,4); - - /*num disks*/ - if (err==ZIP_OK) /* number of the disk with the start of the central directory */ - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); - - /*relative offset*/ - if (err==ZIP_OK) /* Relative offset to the Zip64EndOfCentralDirectory */ - err = zip64local_putValue(&zi->z_filefunc,zi->filestream, pos,8); - - /*total disks*/ /* Do not support spawning of disk so always say 1 here*/ - if (err==ZIP_OK) /* number of the disk with the start of the central directory */ - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)1,4); - - return err; -} - -int Write_Zip64EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip) -{ - int err = ZIP_OK; - - uLong Zip64DataSize = 44; - - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)ZIP64ENDHEADERMAGIC,4); - - if (err==ZIP_OK) /* size of this 'zip64 end of central directory' */ - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(ZPOS64_T)Zip64DataSize,8); // why ZPOS64_T of this ? - - if (err==ZIP_OK) /* version made by */ - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)45,2); - - if (err==ZIP_OK) /* version needed */ - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)45,2); - - if (err==ZIP_OK) /* number of this disk */ - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); - - if (err==ZIP_OK) /* number of the disk with the start of the central directory */ - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); - - if (err==ZIP_OK) /* total number of entries in the central dir on this disk */ - err = zip64local_putValue(&zi->z_filefunc, zi->filestream, zi->number_entry, 8); - - if (err==ZIP_OK) /* total number of entries in the central dir */ - err = zip64local_putValue(&zi->z_filefunc, zi->filestream, zi->number_entry, 8); - - if (err==ZIP_OK) /* size of the central directory */ - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(ZPOS64_T)size_centraldir,8); - - if (err==ZIP_OK) /* offset of start of central directory with respect to the starting disk number */ - { - ZPOS64_T pos = centraldir_pos_inzip - zi->add_position_when_writting_offset; - err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (ZPOS64_T)pos,8); - } - return err; -} -int Write_EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip) -{ - int err = ZIP_OK; - - /*signature*/ - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)ENDHEADERMAGIC,4); - - if (err==ZIP_OK) /* number of this disk */ - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2); - - if (err==ZIP_OK) /* number of the disk with the start of the central directory */ - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2); - - if (err==ZIP_OK) /* total number of entries in the central dir on this disk */ - { - { - if(zi->number_entry >= 0xFFFF) - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xffff,2); // use value in ZIP64 record - else - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2); - } - } - - if (err==ZIP_OK) /* total number of entries in the central dir */ - { - if(zi->number_entry >= 0xFFFF) - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xffff,2); // use value in ZIP64 record - else - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2); - } - - if (err==ZIP_OK) /* size of the central directory */ - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_centraldir,4); - - if (err==ZIP_OK) /* offset of start of central directory with respect to the starting disk number */ - { - ZPOS64_T pos = centraldir_pos_inzip - zi->add_position_when_writting_offset; - if(pos >= 0xffffffff) - { - err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (uLong)0xffffffff,4); - } - else - err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (uLong)(centraldir_pos_inzip - zi->add_position_when_writting_offset),4); - } - - return err; -} - -int Write_GlobalComment(zip64_internal* zi, const char* global_comment) -{ - int err = ZIP_OK; - uInt size_global_comment = 0; - - if(global_comment != NULL) - size_global_comment = (uInt)strlen(global_comment); - - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_global_comment,2); - - if (err == ZIP_OK && size_global_comment > 0) - { - if (ZWRITE64(zi->z_filefunc,zi->filestream, global_comment, size_global_comment) != size_global_comment) - err = ZIP_ERRNO; - } - return err; -} - -extern int ZEXPORT zipClose (zipFile file, const char* global_comment) -{ - zip64_internal* zi; - int err = 0; - uLong size_centraldir = 0; - ZPOS64_T centraldir_pos_inzip; - ZPOS64_T pos; - - if (file == NULL) - return ZIP_PARAMERROR; - - zi = (zip64_internal*)file; - - if (zi->in_opened_file_inzip == 1) - { - err = zipCloseFileInZip (file); - } - -#ifndef NO_ADDFILEINEXISTINGZIP - if (global_comment==NULL) - global_comment = zi->globalcomment; -#endif - - centraldir_pos_inzip = ZTELL64(zi->z_filefunc,zi->filestream); - - if (err==ZIP_OK) - { - linkedlist_datablock_internal* ldi = zi->central_dir.first_block; - while (ldi!=NULL) - { - if ((err==ZIP_OK) && (ldi->filled_in_this_block>0)) - { - if (ZWRITE64(zi->z_filefunc,zi->filestream, ldi->data, ldi->filled_in_this_block) != ldi->filled_in_this_block) - err = ZIP_ERRNO; - } - - size_centraldir += ldi->filled_in_this_block; - ldi = ldi->next_datablock; - } - } - free_linkedlist(&(zi->central_dir)); - - pos = centraldir_pos_inzip - zi->add_position_when_writting_offset; - if(pos >= 0xffffffff || zi->number_entry > 0xFFFF) - { - ZPOS64_T Zip64EOCDpos = ZTELL64(zi->z_filefunc,zi->filestream); - Write_Zip64EndOfCentralDirectoryRecord(zi, size_centraldir, centraldir_pos_inzip); - - Write_Zip64EndOfCentralDirectoryLocator(zi, Zip64EOCDpos); - } - - if (err==ZIP_OK) - err = Write_EndOfCentralDirectoryRecord(zi, size_centraldir, centraldir_pos_inzip); - - if(err == ZIP_OK) - err = Write_GlobalComment(zi, global_comment); - - if (ZCLOSE64(zi->z_filefunc,zi->filestream) != 0) - if (err == ZIP_OK) - err = ZIP_ERRNO; - -#ifndef NO_ADDFILEINEXISTINGZIP - TRYFREE(zi->globalcomment); -#endif - TRYFREE(zi); - - return err; -} - -extern int ZEXPORT zipRemoveExtraInfoBlock (char* pData, int* dataLen, short sHeader) -{ - char* p = pData; - int size = 0; - char* pNewHeader; - char* pTmp; - short header; - short dataSize; - - int retVal = ZIP_OK; - - if(pData == NULL || *dataLen < 4) - return ZIP_PARAMERROR; - - pNewHeader = (char*)ALLOC(*dataLen); - pTmp = pNewHeader; - - while(p < (pData + *dataLen)) - { - header = *(short*)p; - dataSize = *(((short*)p)+1); - - if( header == sHeader ) // Header found. - { - p += dataSize + 4; // skip it. do not copy to temp buffer - } - else - { - // Extra Info block should not be removed, So copy it to the temp buffer. - memcpy(pTmp, p, dataSize + 4); - p += dataSize + 4; - size += dataSize + 4; - } - - } - - if(size < *dataLen) - { - // clean old extra info block. - memset(pData,0, *dataLen); - - // copy the new extra info block over the old - if(size > 0) - memcpy(pData, pNewHeader, size); - - // set the new extra info size - *dataLen = size; - - retVal = ZIP_OK; - } - else - retVal = ZIP_ERRNO; - - TRYFREE(pNewHeader); - - return retVal; -} diff --git a/vendor/minizip/zip.h b/vendor/minizip/zip.h deleted file mode 100644 index 8aaebb623..000000000 --- a/vendor/minizip/zip.h +++ /dev/null @@ -1,362 +0,0 @@ -/* zip.h -- IO on .zip files using zlib - Version 1.1, February 14h, 2010 - part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) - - Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) - - Modifications for Zip64 support - Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) - - For more info read MiniZip_info.txt - - --------------------------------------------------------------------------- - - Condition of use and distribution are the same than zlib : - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - --------------------------------------------------------------------------- - - Changes - - See header of zip.h - -*/ - -#ifndef _zip12_H -#define _zip12_H - -#ifdef __cplusplus -extern "C" { -#endif - -//#define HAVE_BZIP2 - -#ifndef _ZLIB_H -#include "zlib.h" -#endif - -#ifndef _ZLIBIOAPI_H -#include "ioapi.h" -#endif - -#ifdef HAVE_BZIP2 -#include "bzlib.h" -#endif - -#define Z_BZIP2ED 12 - -#if defined(STRICTZIP) || defined(STRICTZIPUNZIP) -/* like the STRICT of WIN32, we define a pointer that cannot be converted - from (void*) without cast */ -typedef struct TagzipFile__ { int unused; } zipFile__; -typedef zipFile__ *zipFile; -#else -typedef voidp zipFile; -#endif - -#define ZIP_OK (0) -#define ZIP_EOF (0) -#define ZIP_ERRNO (Z_ERRNO) -#define ZIP_PARAMERROR (-102) -#define ZIP_BADZIPFILE (-103) -#define ZIP_INTERNALERROR (-104) - -#ifndef DEF_MEM_LEVEL -# if MAX_MEM_LEVEL >= 8 -# define DEF_MEM_LEVEL 8 -# else -# define DEF_MEM_LEVEL MAX_MEM_LEVEL -# endif -#endif -/* default memLevel */ - -/* tm_zip contain date/time info */ -typedef struct tm_zip_s -{ - uInt tm_sec; /* seconds after the minute - [0,59] */ - uInt tm_min; /* minutes after the hour - [0,59] */ - uInt tm_hour; /* hours since midnight - [0,23] */ - uInt tm_mday; /* day of the month - [1,31] */ - uInt tm_mon; /* months since January - [0,11] */ - uInt tm_year; /* years - [1980..2044] */ -} tm_zip; - -typedef struct -{ - tm_zip tmz_date; /* date in understandable format */ - uLong dosDate; /* if dos_date == 0, tmu_date is used */ -/* uLong flag; */ /* general purpose bit flag 2 bytes */ - - uLong internal_fa; /* internal file attributes 2 bytes */ - uLong external_fa; /* external file attributes 4 bytes */ -} zip_fileinfo; - -typedef const char* zipcharpc; - - -#define APPEND_STATUS_CREATE (0) -#define APPEND_STATUS_CREATEAFTER (1) -#define APPEND_STATUS_ADDINZIP (2) - -extern zipFile ZEXPORT zipOpen OF((const char *pathname, int append)); -extern zipFile ZEXPORT zipOpen64 OF((const void *pathname, int append)); -/* - Create a zipfile. - pathname contain on Windows XP a filename like "c:\\zlib\\zlib113.zip" or on - an Unix computer "zlib/zlib113.zip". - if the file pathname exist and append==APPEND_STATUS_CREATEAFTER, the zip - will be created at the end of the file. - (useful if the file contain a self extractor code) - if the file pathname exist and append==APPEND_STATUS_ADDINZIP, we will - add files in existing zip (be sure you don't add file that doesn't exist) - If the zipfile cannot be opened, the return value is NULL. - Else, the return value is a zipFile Handle, usable with other function - of this zip package. -*/ - -/* Note : there is no delete function into a zipfile. - If you want delete file into a zipfile, you must open a zipfile, and create another - Of couse, you can use RAW reading and writing to copy the file you did not want delte -*/ - -extern zipFile ZEXPORT zipOpen2 OF((const char *pathname, - int append, - zipcharpc* globalcomment, - zlib_filefunc_def* pzlib_filefunc_def)); - -extern zipFile ZEXPORT zipOpen2_64 OF((const void *pathname, - int append, - zipcharpc* globalcomment, - zlib_filefunc64_def* pzlib_filefunc_def)); - -extern int ZEXPORT zipOpenNewFileInZip OF((zipFile file, - const char* filename, - const zip_fileinfo* zipfi, - const void* extrafield_local, - uInt size_extrafield_local, - const void* extrafield_global, - uInt size_extrafield_global, - const char* comment, - int method, - int level)); - -extern int ZEXPORT zipOpenNewFileInZip64 OF((zipFile file, - const char* filename, - const zip_fileinfo* zipfi, - const void* extrafield_local, - uInt size_extrafield_local, - const void* extrafield_global, - uInt size_extrafield_global, - const char* comment, - int method, - int level, - int zip64)); - -/* - Open a file in the ZIP for writing. - filename : the filename in zip (if NULL, '-' without quote will be used - *zipfi contain supplemental information - if extrafield_local!=NULL and size_extrafield_local>0, extrafield_local - contains the extrafield data the the local header - if extrafield_global!=NULL and size_extrafield_global>0, extrafield_global - contains the extrafield data the the local header - if comment != NULL, comment contain the comment string - method contain the compression method (0 for store, Z_DEFLATED for deflate) - level contain the level of compression (can be Z_DEFAULT_COMPRESSION) - zip64 is set to 1 if a zip64 extended information block should be added to the local file header. - this MUST be '1' if the uncompressed size is >= 0xffffffff. - -*/ - - -extern int ZEXPORT zipOpenNewFileInZip2 OF((zipFile file, - const char* filename, - const zip_fileinfo* zipfi, - const void* extrafield_local, - uInt size_extrafield_local, - const void* extrafield_global, - uInt size_extrafield_global, - const char* comment, - int method, - int level, - int raw)); - - -extern int ZEXPORT zipOpenNewFileInZip2_64 OF((zipFile file, - const char* filename, - const zip_fileinfo* zipfi, - const void* extrafield_local, - uInt size_extrafield_local, - const void* extrafield_global, - uInt size_extrafield_global, - const char* comment, - int method, - int level, - int raw, - int zip64)); -/* - Same than zipOpenNewFileInZip, except if raw=1, we write raw file - */ - -extern int ZEXPORT zipOpenNewFileInZip3 OF((zipFile file, - const char* filename, - const zip_fileinfo* zipfi, - const void* extrafield_local, - uInt size_extrafield_local, - const void* extrafield_global, - uInt size_extrafield_global, - const char* comment, - int method, - int level, - int raw, - int windowBits, - int memLevel, - int strategy, - const char* password, - uLong crcForCrypting)); - -extern int ZEXPORT zipOpenNewFileInZip3_64 OF((zipFile file, - const char* filename, - const zip_fileinfo* zipfi, - const void* extrafield_local, - uInt size_extrafield_local, - const void* extrafield_global, - uInt size_extrafield_global, - const char* comment, - int method, - int level, - int raw, - int windowBits, - int memLevel, - int strategy, - const char* password, - uLong crcForCrypting, - int zip64 - )); - -/* - Same than zipOpenNewFileInZip2, except - windowBits,memLevel,,strategy : see parameter strategy in deflateInit2 - password : crypting password (NULL for no crypting) - crcForCrypting : crc of file to compress (needed for crypting) - */ - -extern int ZEXPORT zipOpenNewFileInZip4 OF((zipFile file, - const char* filename, - const zip_fileinfo* zipfi, - const void* extrafield_local, - uInt size_extrafield_local, - const void* extrafield_global, - uInt size_extrafield_global, - const char* comment, - int method, - int level, - int raw, - int windowBits, - int memLevel, - int strategy, - const char* password, - uLong crcForCrypting, - uLong versionMadeBy, - uLong flagBase - )); - - -extern int ZEXPORT zipOpenNewFileInZip4_64 OF((zipFile file, - const char* filename, - const zip_fileinfo* zipfi, - const void* extrafield_local, - uInt size_extrafield_local, - const void* extrafield_global, - uInt size_extrafield_global, - const char* comment, - int method, - int level, - int raw, - int windowBits, - int memLevel, - int strategy, - const char* password, - uLong crcForCrypting, - uLong versionMadeBy, - uLong flagBase, - int zip64 - )); -/* - Same than zipOpenNewFileInZip4, except - versionMadeBy : value for Version made by field - flag : value for flag field (compression level info will be added) - */ - - -extern int ZEXPORT zipWriteInFileInZip OF((zipFile file, - const void* buf, - unsigned len)); -/* - Write data in the zipfile -*/ - -extern int ZEXPORT zipCloseFileInZip OF((zipFile file)); -/* - Close the current file in the zipfile -*/ - -extern int ZEXPORT zipCloseFileInZipRaw OF((zipFile file, - uLong uncompressed_size, - uLong crc32)); - -extern int ZEXPORT zipCloseFileInZipRaw64 OF((zipFile file, - ZPOS64_T uncompressed_size, - uLong crc32)); - -/* - Close the current file in the zipfile, for file opened with - parameter raw=1 in zipOpenNewFileInZip2 - uncompressed_size and crc32 are value for the uncompressed size -*/ - -extern int ZEXPORT zipClose OF((zipFile file, - const char* global_comment)); -/* - Close the zipfile -*/ - - -extern int ZEXPORT zipRemoveExtraInfoBlock OF((char* pData, int* dataLen, short sHeader)); -/* - zipRemoveExtraInfoBlock - Added by Mathias Svensson - - Remove extra information block from a extra information data for the local file header or central directory header - - It is needed to remove ZIP64 extra information blocks when before data is written if using RAW mode. - - 0x0001 is the signature header for the ZIP64 extra information blocks - - usage. - Remove ZIP64 Extra information from a central director extra field data - zipRemoveExtraInfoBlock(pCenDirExtraFieldData, &nCenDirExtraFieldDataLen, 0x0001); - - Remove ZIP64 Extra information from a Local File Header extra field data - zipRemoveExtraInfoBlock(pLocalHeaderExtraFieldData, &nLocalHeaderExtraFieldDataLen, 0x0001); -*/ - -#ifdef __cplusplus -} -#endif - -#endif /* _zip64_H */ diff --git a/vendor/msvc/inttypes.h b/vendor/msvc/inttypes.h deleted file mode 100644 index 4b3828a21..000000000 --- a/vendor/msvc/inttypes.h +++ /dev/null @@ -1,305 +0,0 @@ -// ISO C9x compliant inttypes.h for Microsoft Visual Studio -// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 -// -// Copyright (c) 2006 Alexander Chemeris -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// 3. The name of the author may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO -// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; -// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef _MSC_VER // [ -#error "Use this header only with Microsoft Visual C++ compilers!" -#endif // _MSC_VER ] - -#ifndef _MSC_INTTYPES_H_ // [ -#define _MSC_INTTYPES_H_ - -#if _MSC_VER > 1000 -#pragma once -#endif - -#include "stdint.h" - -// 7.8 Format conversion of integer types - -typedef struct { - intmax_t quot; - intmax_t rem; -} imaxdiv_t; - -// 7.8.1 Macros for format specifiers - -#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) // [ See footnote 185 at page 198 - -// The fprintf macros for signed integers are: -#define PRId8 "d" -#define PRIi8 "i" -#define PRIdLEAST8 "d" -#define PRIiLEAST8 "i" -#define PRIdFAST8 "d" -#define PRIiFAST8 "i" - -#define PRId16 "hd" -#define PRIi16 "hi" -#define PRIdLEAST16 "hd" -#define PRIiLEAST16 "hi" -#define PRIdFAST16 "hd" -#define PRIiFAST16 "hi" - -#define PRId32 "I32d" -#define PRIi32 "I32i" -#define PRIdLEAST32 "I32d" -#define PRIiLEAST32 "I32i" -#define PRIdFAST32 "I32d" -#define PRIiFAST32 "I32i" - -#define PRId64 "I64d" -#define PRIi64 "I64i" -#define PRIdLEAST64 "I64d" -#define PRIiLEAST64 "I64i" -#define PRIdFAST64 "I64d" -#define PRIiFAST64 "I64i" - -#define PRIdMAX "I64d" -#define PRIiMAX "I64i" - -#define PRIdPTR "Id" -#define PRIiPTR "Ii" - -// The fprintf macros for unsigned integers are: -#define PRIo8 "o" -#define PRIu8 "u" -#define PRIx8 "x" -#define PRIX8 "X" -#define PRIoLEAST8 "o" -#define PRIuLEAST8 "u" -#define PRIxLEAST8 "x" -#define PRIXLEAST8 "X" -#define PRIoFAST8 "o" -#define PRIuFAST8 "u" -#define PRIxFAST8 "x" -#define PRIXFAST8 "X" - -#define PRIo16 "ho" -#define PRIu16 "hu" -#define PRIx16 "hx" -#define PRIX16 "hX" -#define PRIoLEAST16 "ho" -#define PRIuLEAST16 "hu" -#define PRIxLEAST16 "hx" -#define PRIXLEAST16 "hX" -#define PRIoFAST16 "ho" -#define PRIuFAST16 "hu" -#define PRIxFAST16 "hx" -#define PRIXFAST16 "hX" - -#define PRIo32 "I32o" -#define PRIu32 "I32u" -#define PRIx32 "I32x" -#define PRIX32 "I32X" -#define PRIoLEAST32 "I32o" -#define PRIuLEAST32 "I32u" -#define PRIxLEAST32 "I32x" -#define PRIXLEAST32 "I32X" -#define PRIoFAST32 "I32o" -#define PRIuFAST32 "I32u" -#define PRIxFAST32 "I32x" -#define PRIXFAST32 "I32X" - -#define PRIo64 "I64o" -#define PRIu64 "I64u" -#define PRIx64 "I64x" -#define PRIX64 "I64X" -#define PRIoLEAST64 "I64o" -#define PRIuLEAST64 "I64u" -#define PRIxLEAST64 "I64x" -#define PRIXLEAST64 "I64X" -#define PRIoFAST64 "I64o" -#define PRIuFAST64 "I64u" -#define PRIxFAST64 "I64x" -#define PRIXFAST64 "I64X" - -#define PRIoMAX "I64o" -#define PRIuMAX "I64u" -#define PRIxMAX "I64x" -#define PRIXMAX "I64X" - -#define PRIoPTR "Io" -#define PRIuPTR "Iu" -#define PRIxPTR "Ix" -#define PRIXPTR "IX" - -// The fscanf macros for signed integers are: -#define SCNd8 "d" -#define SCNi8 "i" -#define SCNdLEAST8 "d" -#define SCNiLEAST8 "i" -#define SCNdFAST8 "d" -#define SCNiFAST8 "i" - -#define SCNd16 "hd" -#define SCNi16 "hi" -#define SCNdLEAST16 "hd" -#define SCNiLEAST16 "hi" -#define SCNdFAST16 "hd" -#define SCNiFAST16 "hi" - -#define SCNd32 "ld" -#define SCNi32 "li" -#define SCNdLEAST32 "ld" -#define SCNiLEAST32 "li" -#define SCNdFAST32 "ld" -#define SCNiFAST32 "li" - -#define SCNd64 "I64d" -#define SCNi64 "I64i" -#define SCNdLEAST64 "I64d" -#define SCNiLEAST64 "I64i" -#define SCNdFAST64 "I64d" -#define SCNiFAST64 "I64i" - -#define SCNdMAX "I64d" -#define SCNiMAX "I64i" - -#ifdef _WIN64 // [ -# define SCNdPTR "I64d" -# define SCNiPTR "I64i" -#else // _WIN64 ][ -# define SCNdPTR "ld" -# define SCNiPTR "li" -#endif // _WIN64 ] - -// The fscanf macros for unsigned integers are: -#define SCNo8 "o" -#define SCNu8 "u" -#define SCNx8 "x" -#define SCNX8 "X" -#define SCNoLEAST8 "o" -#define SCNuLEAST8 "u" -#define SCNxLEAST8 "x" -#define SCNXLEAST8 "X" -#define SCNoFAST8 "o" -#define SCNuFAST8 "u" -#define SCNxFAST8 "x" -#define SCNXFAST8 "X" - -#define SCNo16 "ho" -#define SCNu16 "hu" -#define SCNx16 "hx" -#define SCNX16 "hX" -#define SCNoLEAST16 "ho" -#define SCNuLEAST16 "hu" -#define SCNxLEAST16 "hx" -#define SCNXLEAST16 "hX" -#define SCNoFAST16 "ho" -#define SCNuFAST16 "hu" -#define SCNxFAST16 "hx" -#define SCNXFAST16 "hX" - -#define SCNo32 "lo" -#define SCNu32 "lu" -#define SCNx32 "lx" -#define SCNX32 "lX" -#define SCNoLEAST32 "lo" -#define SCNuLEAST32 "lu" -#define SCNxLEAST32 "lx" -#define SCNXLEAST32 "lX" -#define SCNoFAST32 "lo" -#define SCNuFAST32 "lu" -#define SCNxFAST32 "lx" -#define SCNXFAST32 "lX" - -#define SCNo64 "I64o" -#define SCNu64 "I64u" -#define SCNx64 "I64x" -#define SCNX64 "I64X" -#define SCNoLEAST64 "I64o" -#define SCNuLEAST64 "I64u" -#define SCNxLEAST64 "I64x" -#define SCNXLEAST64 "I64X" -#define SCNoFAST64 "I64o" -#define SCNuFAST64 "I64u" -#define SCNxFAST64 "I64x" -#define SCNXFAST64 "I64X" - -#define SCNoMAX "I64o" -#define SCNuMAX "I64u" -#define SCNxMAX "I64x" -#define SCNXMAX "I64X" - -#ifdef _WIN64 // [ -# define SCNoPTR "I64o" -# define SCNuPTR "I64u" -# define SCNxPTR "I64x" -# define SCNXPTR "I64X" -#else // _WIN64 ][ -# define SCNoPTR "lo" -# define SCNuPTR "lu" -# define SCNxPTR "lx" -# define SCNXPTR "lX" -#endif // _WIN64 ] - -#endif // __STDC_FORMAT_MACROS ] - -// 7.8.2 Functions for greatest-width integer types - -// 7.8.2.1 The imaxabs function -#define imaxabs _abs64 - -// 7.8.2.2 The imaxdiv function - -// This is modified version of div() function from Microsoft's div.c found -// in %MSVC.NET%\crt\src\div.c -#ifdef STATIC_IMAXDIV // [ -static -#else // STATIC_IMAXDIV ][ -_inline -#endif // STATIC_IMAXDIV ] -imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom) -{ - imaxdiv_t result; - - result.quot = numer / denom; - result.rem = numer % denom; - - if (numer < 0 && result.rem > 0) { - // did division wrong; must fix up - ++result.quot; - result.rem -= denom; - } - - return result; -} - -// 7.8.2.3 The strtoimax and strtoumax functions -#define strtoimax _strtoi64 -#define strtoumax _strtoui64 - -// 7.8.2.4 The wcstoimax and wcstoumax functions -#define wcstoimax _wcstoi64 -#define wcstoumax _wcstoui64 - - -#endif // _MSC_INTTYPES_H_ ] diff --git a/vendor/msvc/stdint.h b/vendor/msvc/stdint.h deleted file mode 100644 index 53c68200e..000000000 --- a/vendor/msvc/stdint.h +++ /dev/null @@ -1,199 +0,0 @@ -/* stdint.h standard header */ -#pragma once -#ifndef _STDINT -#define _STDINT -#ifndef RC_INVOKED -#include - -/* NB: assumes - byte has 8 bits - long is 32 bits - pointer can convert to and from long long - long long is longest type - */ - -_C_STD_BEGIN - /* TYPE DEFINITIONS */ -typedef signed char int8_t; -typedef short int16_t; -typedef int int32_t; - -typedef unsigned char uint8_t; -typedef unsigned short uint16_t; -typedef unsigned int uint32_t; - -typedef signed char int_least8_t; -typedef short int_least16_t; -typedef int int_least32_t; - -typedef unsigned char uint_least8_t; -typedef unsigned short uint_least16_t; -typedef unsigned int uint_least32_t; - -typedef char int_fast8_t; -typedef int int_fast16_t; -typedef int int_fast32_t; - -typedef unsigned char uint_fast8_t; -typedef unsigned int uint_fast16_t; -typedef unsigned int uint_fast32_t; - -#ifndef _INTPTR_T_DEFINED - #define _INTPTR_T_DEFINED - #ifdef _WIN64 -typedef __int64 intptr_t; - #else /* _WIN64 */ -typedef _W64 int intptr_t; - #endif /* _WIN64 */ -#endif /* _INTPTR_T_DEFINED */ - -#ifndef _UINTPTR_T_DEFINED - #define _UINTPTR_T_DEFINED - #ifdef _WIN64 -typedef unsigned __int64 uintptr_t; - #else /* _WIN64 */ -typedef _W64 unsigned int uintptr_t; - #endif /* _WIN64 */ -#endif /* _UINTPTR_T_DEFINED */ - -typedef _Longlong int64_t; -typedef _ULonglong uint64_t; - -typedef _Longlong int_least64_t; -typedef _ULonglong uint_least64_t; - -typedef _Longlong int_fast64_t; -typedef _ULonglong uint_fast64_t; - -typedef _Longlong intmax_t; -typedef _ULonglong uintmax_t; - - /* LIMIT MACROS */ -#define INT8_MIN (-0x7f - _C2) -#define INT16_MIN (-0x7fff - _C2) -#define INT32_MIN (-0x7fffffff - _C2) - -#define INT8_MAX 0x7f -#define INT16_MAX 0x7fff -#define INT32_MAX 0x7fffffff -#define UINT8_MAX 0xff -#define UINT16_MAX 0xffff -#define UINT32_MAX 0xffffffff - -#define INT_LEAST8_MIN (-0x7f - _C2) -#define INT_LEAST16_MIN (-0x7fff - _C2) -#define INT_LEAST32_MIN (-0x7fffffff - _C2) - -#define INT_LEAST8_MAX 0x7f -#define INT_LEAST16_MAX 0x7fff -#define INT_LEAST32_MAX 0x7fffffff -#define UINT_LEAST8_MAX 0xff -#define UINT_LEAST16_MAX 0xffff -#define UINT_LEAST32_MAX 0xffffffff - -#define INT_FAST8_MIN (-0x7f - _C2) -#define INT_FAST16_MIN (-0x7fff - _C2) -#define INT_FAST32_MIN (-0x7fffffff - _C2) - -#define INT_FAST8_MAX 0x7f -#define INT_FAST16_MAX 0x7fff -#define INT_FAST32_MAX 0x7fffffff -#define UINT_FAST8_MAX 0xff -#define UINT_FAST16_MAX 0xffff -#define UINT_FAST32_MAX 0xffffffff - - #if _INTPTR == 0 || _INTPTR == 1 -#define INTPTR_MAX 0x7fffffff -#define INTPTR_MIN (-INTPTR_MAX - _C2) -#define UINTPTR_MAX 0xffffffff - - #else /* _INTPTR == 2 */ -#define INTPTR_MIN (-_LLONG_MAX - _C2) -#define INTPTR_MAX _LLONG_MAX -#define UINTPTR_MAX _ULLONG_MAX -#endif /* _INTPTR */ - -#define INT8_C(x) (x) -#define INT16_C(x) (x) -#define INT32_C(x) ((x) + (INT32_MAX - INT32_MAX)) - -#define UINT8_C(x) (x) -#define UINT16_C(x) (x) -#define UINT32_C(x) ((x) + (UINT32_MAX - UINT32_MAX)) - -#ifdef _WIN64 - #define PTRDIFF_MIN INT64_MIN - #define PTRDIFF_MAX INT64_MAX -#else /* _WIN64 */ - #define PTRDIFF_MIN INT32_MIN - #define PTRDIFF_MAX INT32_MAX -#endif /* _WIN64 */ - -#define SIG_ATOMIC_MIN INT32_MIN -#define SIG_ATOMIC_MAX INT32_MAX - -#ifndef SIZE_MAX - #ifdef _WIN64 - #define SIZE_MAX UINT64_MAX - #else /* _WIN64 */ - #define SIZE_MAX UINT32_MAX - #endif /* _WIN64 */ -#endif /* SIZE_MAX */ - -#define WCHAR_MIN 0x0000 -#define WCHAR_MAX 0xffff - -#define WINT_MIN 0x0000 -#define WINT_MAX 0xffff - - #define INT64_MIN (-0x7fffffffffffffff - _C2) - #define INT64_MAX 0x7fffffffffffffff - #define UINT64_MAX 0xffffffffffffffffU - - #define INT_LEAST64_MIN (-0x7fffffffffffffff - _C2) - #define INT_LEAST64_MAX 0x7fffffffffffffff - #define UINT_LEAST64_MAX 0xffffffffffffffffU - - #define INT_FAST64_MIN (-0x7fffffffffffffff - _C2) - #define INT_FAST64_MAX 0x7fffffffffffffff - #define UINT_FAST64_MAX 0xffffffffffffffffU - - #define INTMAX_MIN (-0x7fffffffffffffff - _C2) - #define INTMAX_MAX 0x7fffffffffffffff - #define UINTMAX_MAX 0xffffffffffffffffU - -#define INT64_C(x) ((x) + (INT64_MAX - INT64_MAX)) -#define UINT64_C(x) ((x) + (UINT64_MAX - UINT64_MAX)) -#define INTMAX_C(x) INT64_C(x) -#define UINTMAX_C(x) UINT64_C(x) -_C_STD_END -#endif /* RC_INVOKED */ -#endif /* _STDINT */ - - #if defined(_STD_USING) -using _CSTD int8_t; using _CSTD int16_t; -using _CSTD int32_t; using _CSTD int64_t; - -using _CSTD uint8_t; using _CSTD uint16_t; -using _CSTD uint32_t; using _CSTD uint64_t; - -using _CSTD int_least8_t; using _CSTD int_least16_t; -using _CSTD int_least32_t; using _CSTD int_least64_t; -using _CSTD uint_least8_t; using _CSTD uint_least16_t; -using _CSTD uint_least32_t; using _CSTD uint_least64_t; - -using _CSTD intmax_t; using _CSTD uintmax_t; - -using _CSTD uintptr_t; -using _CSTD intptr_t; - -using _CSTD int_fast8_t; using _CSTD int_fast16_t; -using _CSTD int_fast32_t; using _CSTD int_fast64_t; -using _CSTD uint_fast8_t; using _CSTD uint_fast16_t; -using _CSTD uint_fast32_t; using _CSTD uint_fast64_t; - #endif /* defined(_STD_USING) */ - -/* - * Copyright (c) 1992-2009 by P.J. Plauger. ALL RIGHTS RESERVED. - * Consult your license regarding permissions and restrictions. -V5.20:0009 */ \ No newline at end of file diff --git a/vendor/rtaudio/.gitignore b/vendor/rtaudio/.gitignore deleted file mode 100644 index a93909f7b..000000000 --- a/vendor/rtaudio/.gitignore +++ /dev/null @@ -1,11 +0,0 @@ -Makefile -*.o -/config -/configure -/Makefile.in -/aclocal.m4 -/autom4te.cache -/configure -/m4 -/doc/Makefile.in -/tests/Makefile.in diff --git a/vendor/rtaudio/CMakeLists.txt b/vendor/rtaudio/CMakeLists.txt deleted file mode 100644 index 7e1f4c07e..000000000 --- a/vendor/rtaudio/CMakeLists.txt +++ /dev/null @@ -1,125 +0,0 @@ -cmake_minimum_required(VERSION 2.8.10) -project(RtAudio) - -include(CTest) -include(CheckFunctionExists) - -option(BUILD_PYTHON "Build PyRtAudio python bindings" OFF) -option(AUDIO_WINDOWS_DS "Build Windows DirectSound API" OFF) -option(AUDIO_WINDOWS_ASIO "Build Windows ASIO API" OFF) -option(AUDIO_WINDOWS_WASAPI "Build Windows WASAPI API" OFF) -option(AUDIO_LINUX_OSS "Build Linux OSS API" OFF) -option(AUDIO_LINUX_ALSA "Build Linux ALSA API" OFF) -option(AUDIO_LINUX_PULSE "Build Linux PulseAudio API" OFF) -option(AUDIO_UNIX_JACK "Build Unix JACK audio server API" OFF) -option(AUDIO_OSX_CORE "Build Mac OSX CoreAudio API" OFF) - -if (CMAKE_BUILD_TYPE STREQUAL "Debug") - add_definitions(-D__RTAUDIO_DEBUG__) -endif () - -check_function_exists(gettimeofday HAVE_GETTIMEOFDAY) - -if (HAVE_GETTIMEOFDAY) - add_definitions(-DHAVE_GETTIMEOFDAY) -endif () - -if (CMAKE_COMPILER_IS_GNUCXX) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") -endif (CMAKE_COMPILER_IS_GNUCXX) - -set(rtaudio_SOURCES RtAudio.cpp) - -set(LINKLIBS) -if (CMAKE_SYSTEM_NAME MATCHES "kNetBSD.*|NetBSD.*") - message(STATUS "NetBSD detected, using OSS") - find_package(Threads REQUIRED CMAKE_THREAD_PREFER_PTHREAD) - list(APPEND LINKLIBS ossaudio ${CMAKE_THREAD_LIBS_INIT}) - set(AUDIO_LINUX_OSS ON) -elseif (UNIX AND NOT APPLE) - if (NOT AUDIO_LINUX_PULSE AND NOT AUDIO_LINUX_ALSA AND NOT AUDIO_LINUX_OSS AND NOT AUDIO_UNIX_JACK) - set(AUDIO_LINUX_ALSA ON) - endif() - - if (AUDIO_LINUX_PULSE) - find_library(PULSE_LIB pulse) - find_library(PULSESIMPLE_LIB pulse-simple) - list(APPEND LINKLIBS ${PULSE_LIB} ${PULSESIMPLE_LIB}) - add_definitions(-D__LINUX_PULSE__) - message(STATUS "Using Linux PulseAudio") - endif (AUDIO_LINUX_PULSE) - if (AUDIO_LINUX_ALSA) - find_package(ALSA) - find_package(Threads REQUIRED CMAKE_THREAD_PREFER_PTHREAD) - if (NOT ALSA_FOUND) - message(FATAL_ERROR "ALSA API requested but no ALSA dev libraries found") - endif() - include_directories(${ALSA_INCLUDE_DIR}) - list(APPEND LINKLIBS ${ALSA_LIBRARY} ${CMAKE_THREAD_LIBS_INIT}) - add_definitions(-D__LINUX_ALSA__) - message(STATUS "Using Linux ALSA") - endif (AUDIO_LINUX_ALSA) -endif () - -if (APPLE) - if (NOT AUDIO_OSX_CORE AND NOT AUDIO_UNIX_JACK) - set(AUDIO_OSX_CORE ON) - endif() - - if (AUDIO_OSX_CORE) - find_library(COREAUDIO_LIB CoreAudio) - find_library(COREFOUNDATION_LIB CoreFoundation) - list(APPEND LINKLIBS ${COREAUDIO_LIB} ${COREFOUNDATION_LIB}) - add_definitions(-D__MACOSX_CORE__) - message(STATUS "Using OSX CoreAudio") - endif (AUDIO_OSX_CORE) -endif (APPLE) - -# JACK supported on many Unices -if (UNIX) - if (AUDIO_UNIX_JACK) - find_library(JACK_LIB jack) - list(APPEND LINKLIBS ${JACK_LIB}) - add_definitions(-D__UNIX_JACK__) - message(STATUS "Using JACK") - endif (AUDIO_UNIX_JACK) -endif (UNIX) - -if (WIN32) - if (NOT AUDIO_WINDOWS_DS AND NOT AUDIO_WINDOWS_ASIO AND NOT AUDIO_WINDOWS_WASAPI) - set(AUDIO_WINDOWS_WASAPI ON) - endif() - - include_directories(include) - list(APPEND LINKLIBS winmm ole32) - - if (AUDIO_WINDOWS_DS) - add_definitions(-D__WINDOWS_DS__) - message(STATUS "Using Windows DirectSound") - list(APPEND LINKLIBS dsound) - endif (AUDIO_WINDOWS_DS) - if (AUDIO_WINDOWS_WASAPI) - add_definitions(-D__WINDOWS_WASAPI__) - message(STATUS "Using Windows WASAPI") - list(APPEND LINKLIBS uuid ksuser) - endif (AUDIO_WINDOWS_WASAPI) - if (AUDIO_WINDOWS_ASIO) - list(APPEND rtaudio_SOURCES - include/asio.cpp - include/asiodrivers.cpp - include/asiolist.cpp - include/iasiothiscallresolver.cpp) - add_definitions(-D__WINDOWS_ASIO__) - message(STATUS "Using Windows ASIO") - endif (AUDIO_WINDOWS_ASIO) -endif (WIN32) - -#cmake_policy(SET CMP0042 OLD) -add_library(rtaudio SHARED ${rtaudio_SOURCES}) -add_library(rtaudio_static STATIC ${rtaudio_SOURCES}) - -target_link_libraries(rtaudio ${LINKLIBS}) - -if (BUILD_TESTING) - #add_subdirectory(tests) -endif (BUILD_TESTING) diff --git a/vendor/rtaudio/Makefile.am b/vendor/rtaudio/Makefile.am deleted file mode 100644 index 00927e8b1..000000000 --- a/vendor/rtaudio/Makefile.am +++ /dev/null @@ -1,18 +0,0 @@ -SUBDIRS = . tests -if MAKE_DOC -SUBDIRS += doc -endif - -lib_LTLIBRARIES = %D%/librtaudio.la -%C%_librtaudio_la_LDFLAGS = -no-undefined -export-dynamic -version-info @SO_VERSION@ -%C%_librtaudio_la_SOURCES = \ - %D%/RtAudio.cpp - -rtaudio_incdir = $(includedir)/rtaudio -rtaudio_inc_HEADERS = \ - %D%/RtAudio.h - -pkgconfigdatadir = $(libdir)/pkgconfig -pkgconfigdata_DATA = rtaudio.pc - -EXTRA_DIST = autogen.sh readme install.txt contrib include diff --git a/vendor/rtaudio/RtAudio.cpp b/vendor/rtaudio/RtAudio.cpp deleted file mode 100644 index 882fa0e28..000000000 --- a/vendor/rtaudio/RtAudio.cpp +++ /dev/null @@ -1,10229 +0,0 @@ -/************************************************************************/ -/*! \class RtAudio - \brief Realtime audio i/o C++ classes. - - RtAudio provides a common API (Application Programming Interface) - for realtime audio input/output across Linux (native ALSA, Jack, - and OSS), Macintosh OS X (CoreAudio and Jack), and Windows - (DirectSound, ASIO and WASAPI) operating systems. - - RtAudio WWW site: http://www.music.mcgill.ca/~gary/rtaudio/ - - RtAudio: realtime audio i/o C++ classes - Copyright (c) 2001-2016 Gary P. Scavone - - Permission is hereby granted, free of charge, to any person - obtaining a copy of this software and associated documentation files - (the "Software"), to deal in the Software without restriction, - including without limitation the rights to use, copy, modify, merge, - publish, distribute, sublicense, and/or sell copies of the Software, - and to permit persons to whom the Software is furnished to do so, - subject to the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - Any person wishing to distribute modifications to the Software is - asked to send the modifications to the original developer so that - they can be incorporated into the canonical version. This is, - however, not a binding provision of this license. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR - ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ -/************************************************************************/ - -// RtAudio: Version 4.1.2 - -#include "RtAudio.h" -#include -#include -#include -#include -#include - -// Static variable definitions. -const unsigned int RtApi::MAX_SAMPLE_RATES = 14; -const unsigned int RtApi::SAMPLE_RATES[] = { - 4000, 5512, 8000, 9600, 11025, 16000, 22050, - 32000, 44100, 48000, 88200, 96000, 176400, 192000 -}; - -#if defined(__WINDOWS_DS__) || defined(__WINDOWS_ASIO__) || defined(__WINDOWS_WASAPI__) - #define MUTEX_INITIALIZE(A) InitializeCriticalSection(A) - #define MUTEX_DESTROY(A) DeleteCriticalSection(A) - #define MUTEX_LOCK(A) EnterCriticalSection(A) - #define MUTEX_UNLOCK(A) LeaveCriticalSection(A) - - #include "tchar.h" - - static std::string convertCharPointerToStdString(const char *text) - { - return std::string(text); - } - - static std::string convertCharPointerToStdString(const wchar_t *text) - { - int length = WideCharToMultiByte(CP_UTF8, 0, text, -1, NULL, 0, NULL, NULL); - std::string s( length-1, '\0' ); - WideCharToMultiByte(CP_UTF8, 0, text, -1, &s[0], length, NULL, NULL); - return s; - } - -#elif defined(__LINUX_ALSA__) || defined(__LINUX_PULSE__) || defined(__UNIX_JACK__) || defined(__LINUX_OSS__) || defined(__MACOSX_CORE__) - // pthread API - #define MUTEX_INITIALIZE(A) pthread_mutex_init(A, NULL) - #define MUTEX_DESTROY(A) pthread_mutex_destroy(A) - #define MUTEX_LOCK(A) pthread_mutex_lock(A) - #define MUTEX_UNLOCK(A) pthread_mutex_unlock(A) -#else - #define MUTEX_INITIALIZE(A) abs(*A) // dummy definitions - #define MUTEX_DESTROY(A) abs(*A) // dummy definitions -#endif - -// *************************************************** // -// -// RtAudio definitions. -// -// *************************************************** // - -std::string RtAudio :: getVersion( void ) throw() -{ - return RTAUDIO_VERSION; -} - -void RtAudio :: getCompiledApi( std::vector &apis ) throw() -{ - apis.clear(); - - // The order here will control the order of RtAudio's API search in - // the constructor. -#if defined(__UNIX_JACK__) - apis.push_back( UNIX_JACK ); -#endif -#if defined(__LINUX_ALSA__) - apis.push_back( LINUX_ALSA ); -#endif -#if defined(__LINUX_PULSE__) - apis.push_back( LINUX_PULSE ); -#endif -#if defined(__LINUX_OSS__) - apis.push_back( LINUX_OSS ); -#endif -#if defined(__WINDOWS_ASIO__) - apis.push_back( WINDOWS_ASIO ); -#endif -#if defined(__WINDOWS_WASAPI__) - apis.push_back( WINDOWS_WASAPI ); -#endif -#if defined(__WINDOWS_DS__) - apis.push_back( WINDOWS_DS ); -#endif -#if defined(__MACOSX_CORE__) - apis.push_back( MACOSX_CORE ); -#endif -#if defined(__RTAUDIO_DUMMY__) - apis.push_back( RTAUDIO_DUMMY ); -#endif -} - -void RtAudio :: openRtApi( RtAudio::Api api ) -{ - if ( rtapi_ ) - delete rtapi_; - rtapi_ = 0; - -#if defined(__UNIX_JACK__) - if ( api == UNIX_JACK ) - rtapi_ = new RtApiJack(); -#endif -#if defined(__LINUX_ALSA__) - if ( api == LINUX_ALSA ) - rtapi_ = new RtApiAlsa(); -#endif -#if defined(__LINUX_PULSE__) - if ( api == LINUX_PULSE ) - rtapi_ = new RtApiPulse(); -#endif -#if defined(__LINUX_OSS__) - if ( api == LINUX_OSS ) - rtapi_ = new RtApiOss(); -#endif -#if defined(__WINDOWS_ASIO__) - if ( api == WINDOWS_ASIO ) - rtapi_ = new RtApiAsio(); -#endif -#if defined(__WINDOWS_WASAPI__) - if ( api == WINDOWS_WASAPI ) - rtapi_ = new RtApiWasapi(); -#endif -#if defined(__WINDOWS_DS__) - if ( api == WINDOWS_DS ) - rtapi_ = new RtApiDs(); -#endif -#if defined(__MACOSX_CORE__) - if ( api == MACOSX_CORE ) - rtapi_ = new RtApiCore(); -#endif -#if defined(__RTAUDIO_DUMMY__) - if ( api == RTAUDIO_DUMMY ) - rtapi_ = new RtApiDummy(); -#endif -} - -RtAudio :: RtAudio( RtAudio::Api api ) -{ - rtapi_ = 0; - - if ( api != UNSPECIFIED ) { - // Attempt to open the specified API. - openRtApi( api ); - if ( rtapi_ ) return; - - // No compiled support for specified API value. Issue a debug - // warning and continue as if no API was specified. - std::cerr << "\nRtAudio: no compiled support for specified API argument!\n" << std::endl; - } - - // Iterate through the compiled APIs and return as soon as we find - // one with at least one device or we reach the end of the list. - std::vector< RtAudio::Api > apis; - getCompiledApi( apis ); - for ( unsigned int i=0; igetDeviceCount() ) break; - } - - if ( rtapi_ ) return; - - // It should not be possible to get here because the preprocessor - // definition __RTAUDIO_DUMMY__ is automatically defined if no - // API-specific definitions are passed to the compiler. But just in - // case something weird happens, we'll thow an error. - std::string errorText = "\nRtAudio: no compiled API support found ... critical error!!\n\n"; - throw( RtAudioError( errorText, RtAudioError::UNSPECIFIED ) ); -} - -RtAudio :: ~RtAudio() throw() -{ - if ( rtapi_ ) - delete rtapi_; -} - -void RtAudio :: openStream( RtAudio::StreamParameters *outputParameters, - RtAudio::StreamParameters *inputParameters, - RtAudioFormat format, unsigned int sampleRate, - unsigned int *bufferFrames, - RtAudioCallback callback, void *userData, - RtAudio::StreamOptions *options, - RtAudioErrorCallback errorCallback ) -{ - return rtapi_->openStream( outputParameters, inputParameters, format, - sampleRate, bufferFrames, callback, - userData, options, errorCallback ); -} - -// *************************************************** // -// -// Public RtApi definitions (see end of file for -// private or protected utility functions). -// -// *************************************************** // - -RtApi :: RtApi() -{ - stream_.state = STREAM_CLOSED; - stream_.mode = UNINITIALIZED; - stream_.apiHandle = 0; - stream_.userBuffer[0] = 0; - stream_.userBuffer[1] = 0; - MUTEX_INITIALIZE( &stream_.mutex ); - showWarnings_ = true; - firstErrorOccurred_ = false; -} - -RtApi :: ~RtApi() -{ - MUTEX_DESTROY( &stream_.mutex ); -} - -void RtApi :: openStream( RtAudio::StreamParameters *oParams, - RtAudio::StreamParameters *iParams, - RtAudioFormat format, unsigned int sampleRate, - unsigned int *bufferFrames, - RtAudioCallback callback, void *userData, - RtAudio::StreamOptions *options, - RtAudioErrorCallback errorCallback ) -{ - if ( stream_.state != STREAM_CLOSED ) { - errorText_ = "RtApi::openStream: a stream is already open!"; - error( RtAudioError::INVALID_USE ); - return; - } - - // Clear stream information potentially left from a previously open stream. - clearStreamInfo(); - - if ( oParams && oParams->nChannels < 1 ) { - errorText_ = "RtApi::openStream: a non-NULL output StreamParameters structure cannot have an nChannels value less than one."; - error( RtAudioError::INVALID_USE ); - return; - } - - if ( iParams && iParams->nChannels < 1 ) { - errorText_ = "RtApi::openStream: a non-NULL input StreamParameters structure cannot have an nChannels value less than one."; - error( RtAudioError::INVALID_USE ); - return; - } - - if ( oParams == NULL && iParams == NULL ) { - errorText_ = "RtApi::openStream: input and output StreamParameters structures are both NULL!"; - error( RtAudioError::INVALID_USE ); - return; - } - - if ( formatBytes(format) == 0 ) { - errorText_ = "RtApi::openStream: 'format' parameter value is undefined."; - error( RtAudioError::INVALID_USE ); - return; - } - - unsigned int nDevices = getDeviceCount(); - unsigned int oChannels = 0; - if ( oParams ) { - oChannels = oParams->nChannels; - if ( oParams->deviceId >= nDevices ) { - errorText_ = "RtApi::openStream: output device parameter value is invalid."; - error( RtAudioError::INVALID_USE ); - return; - } - } - - unsigned int iChannels = 0; - if ( iParams ) { - iChannels = iParams->nChannels; - if ( iParams->deviceId >= nDevices ) { - errorText_ = "RtApi::openStream: input device parameter value is invalid."; - error( RtAudioError::INVALID_USE ); - return; - } - } - - bool result; - - if ( oChannels > 0 ) { - - result = probeDeviceOpen( oParams->deviceId, OUTPUT, oChannels, oParams->firstChannel, - sampleRate, format, bufferFrames, options ); - if ( result == false ) { - error( RtAudioError::SYSTEM_ERROR ); - return; - } - } - - if ( iChannels > 0 ) { - - result = probeDeviceOpen( iParams->deviceId, INPUT, iChannels, iParams->firstChannel, - sampleRate, format, bufferFrames, options ); - if ( result == false ) { - if ( oChannels > 0 ) closeStream(); - error( RtAudioError::SYSTEM_ERROR ); - return; - } - } - - stream_.callbackInfo.callback = (void *) callback; - stream_.callbackInfo.userData = userData; - stream_.callbackInfo.errorCallback = (void *) errorCallback; - - if ( options ) options->numberOfBuffers = stream_.nBuffers; - stream_.state = STREAM_STOPPED; -} - -unsigned int RtApi :: getDefaultInputDevice( void ) -{ - // Should be implemented in subclasses if possible. - return 0; -} - -unsigned int RtApi :: getDefaultOutputDevice( void ) -{ - // Should be implemented in subclasses if possible. - return 0; -} - -void RtApi :: closeStream( void ) -{ - // MUST be implemented in subclasses! - return; -} - -bool RtApi :: probeDeviceOpen( unsigned int /*device*/, StreamMode /*mode*/, unsigned int /*channels*/, - unsigned int /*firstChannel*/, unsigned int /*sampleRate*/, - RtAudioFormat /*format*/, unsigned int * /*bufferSize*/, - RtAudio::StreamOptions * /*options*/ ) -{ - // MUST be implemented in subclasses! - return FAILURE; -} - -void RtApi :: tickStreamTime( void ) -{ - // Subclasses that do not provide their own implementation of - // getStreamTime should call this function once per buffer I/O to - // provide basic stream time support. - - stream_.streamTime += ( stream_.bufferSize * 1.0 / stream_.sampleRate ); - -#if defined( HAVE_GETTIMEOFDAY ) - gettimeofday( &stream_.lastTickTimestamp, NULL ); -#endif -} - -long RtApi :: getStreamLatency( void ) -{ - verifyStream(); - - long totalLatency = 0; - if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) - totalLatency = stream_.latency[0]; - if ( stream_.mode == INPUT || stream_.mode == DUPLEX ) - totalLatency += stream_.latency[1]; - - return totalLatency; -} - -double RtApi :: getStreamTime( void ) -{ - verifyStream(); - -#if defined( HAVE_GETTIMEOFDAY ) - // Return a very accurate estimate of the stream time by - // adding in the elapsed time since the last tick. - struct timeval then; - struct timeval now; - - if ( stream_.state != STREAM_RUNNING || stream_.streamTime == 0.0 ) - return stream_.streamTime; - - gettimeofday( &now, NULL ); - then = stream_.lastTickTimestamp; - return stream_.streamTime + - ((now.tv_sec + 0.000001 * now.tv_usec) - - (then.tv_sec + 0.000001 * then.tv_usec)); -#else - return stream_.streamTime; -#endif -} - -void RtApi :: setStreamTime( double time ) -{ - verifyStream(); - - if ( time >= 0.0 ) - stream_.streamTime = time; -} - -unsigned int RtApi :: getStreamSampleRate( void ) -{ - verifyStream(); - - return stream_.sampleRate; -} - - -// *************************************************** // -// -// OS/API-specific methods. -// -// *************************************************** // - -#if defined(__MACOSX_CORE__) - -// The OS X CoreAudio API is designed to use a separate callback -// procedure for each of its audio devices. A single RtAudio duplex -// stream using two different devices is supported here, though it -// cannot be guaranteed to always behave correctly because we cannot -// synchronize these two callbacks. -// -// A property listener is installed for over/underrun information. -// However, no functionality is currently provided to allow property -// listeners to trigger user handlers because it is unclear what could -// be done if a critical stream parameter (buffer size, sample rate, -// device disconnect) notification arrived. The listeners entail -// quite a bit of extra code and most likely, a user program wouldn't -// be prepared for the result anyway. However, we do provide a flag -// to the client callback function to inform of an over/underrun. - -// A structure to hold various information related to the CoreAudio API -// implementation. -struct CoreHandle { - AudioDeviceID id[2]; // device ids -#if defined( MAC_OS_X_VERSION_10_5 ) && ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 ) - AudioDeviceIOProcID procId[2]; -#endif - UInt32 iStream[2]; // device stream index (or first if using multiple) - UInt32 nStreams[2]; // number of streams to use - bool xrun[2]; - char *deviceBuffer; - pthread_cond_t condition; - int drainCounter; // Tracks callback counts when draining - bool internalDrain; // Indicates if stop is initiated from callback or not. - - CoreHandle() - :deviceBuffer(0), drainCounter(0), internalDrain(false) { nStreams[0] = 1; nStreams[1] = 1; id[0] = 0; id[1] = 0; xrun[0] = false; xrun[1] = false; } -}; - -RtApiCore:: RtApiCore() -{ -#if defined( AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER ) - // This is a largely undocumented but absolutely necessary - // requirement starting with OS-X 10.6. If not called, queries and - // updates to various audio device properties are not handled - // correctly. - CFRunLoopRef theRunLoop = NULL; - AudioObjectPropertyAddress property = { kAudioHardwarePropertyRunLoop, - kAudioObjectPropertyScopeGlobal, - kAudioObjectPropertyElementMaster }; - OSStatus result = AudioObjectSetPropertyData( kAudioObjectSystemObject, &property, 0, NULL, sizeof(CFRunLoopRef), &theRunLoop); - if ( result != noErr ) { - errorText_ = "RtApiCore::RtApiCore: error setting run loop property!"; - error( RtAudioError::WARNING ); - } -#endif -} - -RtApiCore :: ~RtApiCore() -{ - // The subclass destructor gets called before the base class - // destructor, so close an existing stream before deallocating - // apiDeviceId memory. - if ( stream_.state != STREAM_CLOSED ) closeStream(); -} - -unsigned int RtApiCore :: getDeviceCount( void ) -{ - // Find out how many audio devices there are, if any. - UInt32 dataSize; - AudioObjectPropertyAddress propertyAddress = { kAudioHardwarePropertyDevices, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster }; - OSStatus result = AudioObjectGetPropertyDataSize( kAudioObjectSystemObject, &propertyAddress, 0, NULL, &dataSize ); - if ( result != noErr ) { - errorText_ = "RtApiCore::getDeviceCount: OS-X error getting device info!"; - error( RtAudioError::WARNING ); - return 0; - } - - return dataSize / sizeof( AudioDeviceID ); -} - -unsigned int RtApiCore :: getDefaultInputDevice( void ) -{ - unsigned int nDevices = getDeviceCount(); - if ( nDevices <= 1 ) return 0; - - AudioDeviceID id; - UInt32 dataSize = sizeof( AudioDeviceID ); - AudioObjectPropertyAddress property = { kAudioHardwarePropertyDefaultInputDevice, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster }; - OSStatus result = AudioObjectGetPropertyData( kAudioObjectSystemObject, &property, 0, NULL, &dataSize, &id ); - if ( result != noErr ) { - errorText_ = "RtApiCore::getDefaultInputDevice: OS-X system error getting device."; - error( RtAudioError::WARNING ); - return 0; - } - - dataSize *= nDevices; - AudioDeviceID deviceList[ nDevices ]; - property.mSelector = kAudioHardwarePropertyDevices; - result = AudioObjectGetPropertyData( kAudioObjectSystemObject, &property, 0, NULL, &dataSize, (void *) &deviceList ); - if ( result != noErr ) { - errorText_ = "RtApiCore::getDefaultInputDevice: OS-X system error getting device IDs."; - error( RtAudioError::WARNING ); - return 0; - } - - for ( unsigned int i=0; i= nDevices ) { - errorText_ = "RtApiCore::getDeviceInfo: device ID is invalid!"; - error( RtAudioError::INVALID_USE ); - return info; - } - - AudioDeviceID deviceList[ nDevices ]; - UInt32 dataSize = sizeof( AudioDeviceID ) * nDevices; - AudioObjectPropertyAddress property = { kAudioHardwarePropertyDevices, - kAudioObjectPropertyScopeGlobal, - kAudioObjectPropertyElementMaster }; - OSStatus result = AudioObjectGetPropertyData( kAudioObjectSystemObject, &property, - 0, NULL, &dataSize, (void *) &deviceList ); - if ( result != noErr ) { - errorText_ = "RtApiCore::getDeviceInfo: OS-X system error getting device IDs."; - error( RtAudioError::WARNING ); - return info; - } - - AudioDeviceID id = deviceList[ device ]; - - // Get the device name. - info.name.erase(); - CFStringRef cfname; - dataSize = sizeof( CFStringRef ); - property.mSelector = kAudioObjectPropertyManufacturer; - result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, &cfname ); - if ( result != noErr ) { - errorStream_ << "RtApiCore::probeDeviceInfo: system error (" << getErrorCode( result ) << ") getting device manufacturer."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - return info; - } - - //const char *mname = CFStringGetCStringPtr( cfname, CFStringGetSystemEncoding() ); - int length = CFStringGetLength(cfname); - char *mname = (char *)malloc(length * 3 + 1); -#if defined( UNICODE ) || defined( _UNICODE ) - CFStringGetCString(cfname, mname, length * 3 + 1, kCFStringEncodingUTF8); -#else - CFStringGetCString(cfname, mname, length * 3 + 1, CFStringGetSystemEncoding()); -#endif - info.name.append( (const char *)mname, strlen(mname) ); - info.name.append( ": " ); - CFRelease( cfname ); - free(mname); - - property.mSelector = kAudioObjectPropertyName; - result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, &cfname ); - if ( result != noErr ) { - errorStream_ << "RtApiCore::probeDeviceInfo: system error (" << getErrorCode( result ) << ") getting device name."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - return info; - } - - //const char *name = CFStringGetCStringPtr( cfname, CFStringGetSystemEncoding() ); - length = CFStringGetLength(cfname); - char *name = (char *)malloc(length * 3 + 1); -#if defined( UNICODE ) || defined( _UNICODE ) - CFStringGetCString(cfname, name, length * 3 + 1, kCFStringEncodingUTF8); -#else - CFStringGetCString(cfname, name, length * 3 + 1, CFStringGetSystemEncoding()); -#endif - info.name.append( (const char *)name, strlen(name) ); - CFRelease( cfname ); - free(name); - - // Get the output stream "configuration". - AudioBufferList *bufferList = nil; - property.mSelector = kAudioDevicePropertyStreamConfiguration; - property.mScope = kAudioDevicePropertyScopeOutput; - // property.mElement = kAudioObjectPropertyElementWildcard; - dataSize = 0; - result = AudioObjectGetPropertyDataSize( id, &property, 0, NULL, &dataSize ); - if ( result != noErr || dataSize == 0 ) { - errorStream_ << "RtApiCore::getDeviceInfo: system error (" << getErrorCode( result ) << ") getting output stream configuration info for device (" << device << ")."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - return info; - } - - // Allocate the AudioBufferList. - bufferList = (AudioBufferList *) malloc( dataSize ); - if ( bufferList == NULL ) { - errorText_ = "RtApiCore::getDeviceInfo: memory error allocating output AudioBufferList."; - error( RtAudioError::WARNING ); - return info; - } - - result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, bufferList ); - if ( result != noErr || dataSize == 0 ) { - free( bufferList ); - errorStream_ << "RtApiCore::getDeviceInfo: system error (" << getErrorCode( result ) << ") getting output stream configuration for device (" << device << ")."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - return info; - } - - // Get output channel information. - unsigned int i, nStreams = bufferList->mNumberBuffers; - for ( i=0; imBuffers[i].mNumberChannels; - free( bufferList ); - - // Get the input stream "configuration". - property.mScope = kAudioDevicePropertyScopeInput; - result = AudioObjectGetPropertyDataSize( id, &property, 0, NULL, &dataSize ); - if ( result != noErr || dataSize == 0 ) { - errorStream_ << "RtApiCore::getDeviceInfo: system error (" << getErrorCode( result ) << ") getting input stream configuration info for device (" << device << ")."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - return info; - } - - // Allocate the AudioBufferList. - bufferList = (AudioBufferList *) malloc( dataSize ); - if ( bufferList == NULL ) { - errorText_ = "RtApiCore::getDeviceInfo: memory error allocating input AudioBufferList."; - error( RtAudioError::WARNING ); - return info; - } - - result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, bufferList ); - if (result != noErr || dataSize == 0) { - free( bufferList ); - errorStream_ << "RtApiCore::getDeviceInfo: system error (" << getErrorCode( result ) << ") getting input stream configuration for device (" << device << ")."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - return info; - } - - // Get input channel information. - nStreams = bufferList->mNumberBuffers; - for ( i=0; imBuffers[i].mNumberChannels; - free( bufferList ); - - // If device opens for both playback and capture, we determine the channels. - if ( info.outputChannels > 0 && info.inputChannels > 0 ) - info.duplexChannels = (info.outputChannels > info.inputChannels) ? info.inputChannels : info.outputChannels; - - // Probe the device sample rates. - bool isInput = false; - if ( info.outputChannels == 0 ) isInput = true; - - // Determine the supported sample rates. - property.mSelector = kAudioDevicePropertyAvailableNominalSampleRates; - if ( isInput == false ) property.mScope = kAudioDevicePropertyScopeOutput; - result = AudioObjectGetPropertyDataSize( id, &property, 0, NULL, &dataSize ); - if ( result != kAudioHardwareNoError || dataSize == 0 ) { - errorStream_ << "RtApiCore::getDeviceInfo: system error (" << getErrorCode( result ) << ") getting sample rate info."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - return info; - } - - UInt32 nRanges = dataSize / sizeof( AudioValueRange ); - AudioValueRange rangeList[ nRanges ]; - result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, &rangeList ); - if ( result != kAudioHardwareNoError ) { - errorStream_ << "RtApiCore::getDeviceInfo: system error (" << getErrorCode( result ) << ") getting sample rates."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - return info; - } - - // The sample rate reporting mechanism is a bit of a mystery. It - // seems that it can either return individual rates or a range of - // rates. I assume that if the min / max range values are the same, - // then that represents a single supported rate and if the min / max - // range values are different, the device supports an arbitrary - // range of values (though there might be multiple ranges, so we'll - // use the most conservative range). - Float64 minimumRate = 1.0, maximumRate = 10000000000.0; - bool haveValueRange = false; - info.sampleRates.clear(); - for ( UInt32 i=0; i info.preferredSampleRate ) ) - info.preferredSampleRate = tmpSr; - - } else { - haveValueRange = true; - if ( rangeList[i].mMinimum > minimumRate ) minimumRate = rangeList[i].mMinimum; - if ( rangeList[i].mMaximum < maximumRate ) maximumRate = rangeList[i].mMaximum; - } - } - - if ( haveValueRange ) { - for ( unsigned int k=0; k= (unsigned int) minimumRate && SAMPLE_RATES[k] <= (unsigned int) maximumRate ) { - info.sampleRates.push_back( SAMPLE_RATES[k] ); - - if ( !info.preferredSampleRate || ( SAMPLE_RATES[k] <= 48000 && SAMPLE_RATES[k] > info.preferredSampleRate ) ) - info.preferredSampleRate = SAMPLE_RATES[k]; - } - } - } - - // Sort and remove any redundant values - std::sort( info.sampleRates.begin(), info.sampleRates.end() ); - info.sampleRates.erase( unique( info.sampleRates.begin(), info.sampleRates.end() ), info.sampleRates.end() ); - - if ( info.sampleRates.size() == 0 ) { - errorStream_ << "RtApiCore::probeDeviceInfo: No supported sample rates found for device (" << device << ")."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - return info; - } - - // CoreAudio always uses 32-bit floating point data for PCM streams. - // Thus, any other "physical" formats supported by the device are of - // no interest to the client. - info.nativeFormats = RTAUDIO_FLOAT32; - - if ( info.outputChannels > 0 ) - if ( getDefaultOutputDevice() == device ) info.isDefaultOutput = true; - if ( info.inputChannels > 0 ) - if ( getDefaultInputDevice() == device ) info.isDefaultInput = true; - - info.probed = true; - return info; -} - -static OSStatus callbackHandler( AudioDeviceID inDevice, - const AudioTimeStamp* /*inNow*/, - const AudioBufferList* inInputData, - const AudioTimeStamp* /*inInputTime*/, - AudioBufferList* outOutputData, - const AudioTimeStamp* /*inOutputTime*/, - void* infoPointer ) -{ - CallbackInfo *info = (CallbackInfo *) infoPointer; - - RtApiCore *object = (RtApiCore *) info->object; - if ( object->callbackEvent( inDevice, inInputData, outOutputData ) == false ) - return kAudioHardwareUnspecifiedError; - else - return kAudioHardwareNoError; -} - -static OSStatus xrunListener( AudioObjectID /*inDevice*/, - UInt32 nAddresses, - const AudioObjectPropertyAddress properties[], - void* handlePointer ) -{ - CoreHandle *handle = (CoreHandle *) handlePointer; - for ( UInt32 i=0; ixrun[1] = true; - else - handle->xrun[0] = true; - } - } - - return kAudioHardwareNoError; -} - -static OSStatus rateListener( AudioObjectID inDevice, - UInt32 /*nAddresses*/, - const AudioObjectPropertyAddress /*properties*/[], - void* ratePointer ) -{ - Float64 *rate = (Float64 *) ratePointer; - UInt32 dataSize = sizeof( Float64 ); - AudioObjectPropertyAddress property = { kAudioDevicePropertyNominalSampleRate, - kAudioObjectPropertyScopeGlobal, - kAudioObjectPropertyElementMaster }; - AudioObjectGetPropertyData( inDevice, &property, 0, NULL, &dataSize, rate ); - return kAudioHardwareNoError; -} - -bool RtApiCore :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, - unsigned int firstChannel, unsigned int sampleRate, - RtAudioFormat format, unsigned int *bufferSize, - RtAudio::StreamOptions *options ) -{ - // Get device ID - unsigned int nDevices = getDeviceCount(); - if ( nDevices == 0 ) { - // This should not happen because a check is made before this function is called. - errorText_ = "RtApiCore::probeDeviceOpen: no devices found!"; - return FAILURE; - } - - if ( device >= nDevices ) { - // This should not happen because a check is made before this function is called. - errorText_ = "RtApiCore::probeDeviceOpen: device ID is invalid!"; - return FAILURE; - } - - AudioDeviceID deviceList[ nDevices ]; - UInt32 dataSize = sizeof( AudioDeviceID ) * nDevices; - AudioObjectPropertyAddress property = { kAudioHardwarePropertyDevices, - kAudioObjectPropertyScopeGlobal, - kAudioObjectPropertyElementMaster }; - OSStatus result = AudioObjectGetPropertyData( kAudioObjectSystemObject, &property, - 0, NULL, &dataSize, (void *) &deviceList ); - if ( result != noErr ) { - errorText_ = "RtApiCore::probeDeviceOpen: OS-X system error getting device IDs."; - return FAILURE; - } - - AudioDeviceID id = deviceList[ device ]; - - // Setup for stream mode. - bool isInput = false; - if ( mode == INPUT ) { - isInput = true; - property.mScope = kAudioDevicePropertyScopeInput; - } - else - property.mScope = kAudioDevicePropertyScopeOutput; - - // Get the stream "configuration". - AudioBufferList *bufferList = nil; - dataSize = 0; - property.mSelector = kAudioDevicePropertyStreamConfiguration; - result = AudioObjectGetPropertyDataSize( id, &property, 0, NULL, &dataSize ); - if ( result != noErr || dataSize == 0 ) { - errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") getting stream configuration info for device (" << device << ")."; - errorText_ = errorStream_.str(); - return FAILURE; - } - - // Allocate the AudioBufferList. - bufferList = (AudioBufferList *) malloc( dataSize ); - if ( bufferList == NULL ) { - errorText_ = "RtApiCore::probeDeviceOpen: memory error allocating AudioBufferList."; - return FAILURE; - } - - result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, bufferList ); - if (result != noErr || dataSize == 0) { - free( bufferList ); - errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") getting stream configuration for device (" << device << ")."; - errorText_ = errorStream_.str(); - return FAILURE; - } - - // Search for one or more streams that contain the desired number of - // channels. CoreAudio devices can have an arbitrary number of - // streams and each stream can have an arbitrary number of channels. - // For each stream, a single buffer of interleaved samples is - // provided. RtAudio prefers the use of one stream of interleaved - // data or multiple consecutive single-channel streams. However, we - // now support multiple consecutive multi-channel streams of - // interleaved data as well. - UInt32 iStream, offsetCounter = firstChannel; - UInt32 nStreams = bufferList->mNumberBuffers; - bool monoMode = false; - bool foundStream = false; - - // First check that the device supports the requested number of - // channels. - UInt32 deviceChannels = 0; - for ( iStream=0; iStreammBuffers[iStream].mNumberChannels; - - if ( deviceChannels < ( channels + firstChannel ) ) { - free( bufferList ); - errorStream_ << "RtApiCore::probeDeviceOpen: the device (" << device << ") does not support the requested channel count."; - errorText_ = errorStream_.str(); - return FAILURE; - } - - // Look for a single stream meeting our needs. - UInt32 firstStream, streamCount = 1, streamChannels = 0, channelOffset = 0; - for ( iStream=0; iStreammBuffers[iStream].mNumberChannels; - if ( streamChannels >= channels + offsetCounter ) { - firstStream = iStream; - channelOffset = offsetCounter; - foundStream = true; - break; - } - if ( streamChannels > offsetCounter ) break; - offsetCounter -= streamChannels; - } - - // If we didn't find a single stream above, then we should be able - // to meet the channel specification with multiple streams. - if ( foundStream == false ) { - monoMode = true; - offsetCounter = firstChannel; - for ( iStream=0; iStreammBuffers[iStream].mNumberChannels; - if ( streamChannels > offsetCounter ) break; - offsetCounter -= streamChannels; - } - - firstStream = iStream; - channelOffset = offsetCounter; - Int32 channelCounter = channels + offsetCounter - streamChannels; - - if ( streamChannels > 1 ) monoMode = false; - while ( channelCounter > 0 ) { - streamChannels = bufferList->mBuffers[++iStream].mNumberChannels; - if ( streamChannels > 1 ) monoMode = false; - channelCounter -= streamChannels; - streamCount++; - } - } - - free( bufferList ); - - // Determine the buffer size. - AudioValueRange bufferRange; - dataSize = sizeof( AudioValueRange ); - property.mSelector = kAudioDevicePropertyBufferFrameSizeRange; - result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, &bufferRange ); - - if ( result != noErr ) { - errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") getting buffer size range for device (" << device << ")."; - errorText_ = errorStream_.str(); - return FAILURE; - } - - if ( bufferRange.mMinimum > *bufferSize ) *bufferSize = (unsigned long) bufferRange.mMinimum; - else if ( bufferRange.mMaximum < *bufferSize ) *bufferSize = (unsigned long) bufferRange.mMaximum; - if ( options && options->flags & RTAUDIO_MINIMIZE_LATENCY ) *bufferSize = (unsigned long) bufferRange.mMinimum; - - // Set the buffer size. For multiple streams, I'm assuming we only - // need to make this setting for the master channel. - UInt32 theSize = (UInt32) *bufferSize; - dataSize = sizeof( UInt32 ); - property.mSelector = kAudioDevicePropertyBufferFrameSize; - result = AudioObjectSetPropertyData( id, &property, 0, NULL, dataSize, &theSize ); - - if ( result != noErr ) { - errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") setting the buffer size for device (" << device << ")."; - errorText_ = errorStream_.str(); - return FAILURE; - } - - // If attempting to setup a duplex stream, the bufferSize parameter - // MUST be the same in both directions! - *bufferSize = theSize; - if ( stream_.mode == OUTPUT && mode == INPUT && *bufferSize != stream_.bufferSize ) { - errorStream_ << "RtApiCore::probeDeviceOpen: system error setting buffer size for duplex stream on device (" << device << ")."; - errorText_ = errorStream_.str(); - return FAILURE; - } - - stream_.bufferSize = *bufferSize; - stream_.nBuffers = 1; - - // Try to set "hog" mode ... it's not clear to me this is working. - if ( options && options->flags & RTAUDIO_HOG_DEVICE ) { - pid_t hog_pid; - dataSize = sizeof( hog_pid ); - property.mSelector = kAudioDevicePropertyHogMode; - result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, &hog_pid ); - if ( result != noErr ) { - errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") getting 'hog' state!"; - errorText_ = errorStream_.str(); - return FAILURE; - } - - if ( hog_pid != getpid() ) { - hog_pid = getpid(); - result = AudioObjectSetPropertyData( id, &property, 0, NULL, dataSize, &hog_pid ); - if ( result != noErr ) { - errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") setting 'hog' state!"; - errorText_ = errorStream_.str(); - return FAILURE; - } - } - } - - // Check and if necessary, change the sample rate for the device. - Float64 nominalRate; - dataSize = sizeof( Float64 ); - property.mSelector = kAudioDevicePropertyNominalSampleRate; - result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, &nominalRate ); - if ( result != noErr ) { - errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") getting current sample rate."; - errorText_ = errorStream_.str(); - return FAILURE; - } - - // Only change the sample rate if off by more than 1 Hz. - if ( fabs( nominalRate - (double)sampleRate ) > 1.0 ) { - - // Set a property listener for the sample rate change - Float64 reportedRate = 0.0; - AudioObjectPropertyAddress tmp = { kAudioDevicePropertyNominalSampleRate, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster }; - result = AudioObjectAddPropertyListener( id, &tmp, rateListener, (void *) &reportedRate ); - if ( result != noErr ) { - errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") setting sample rate property listener for device (" << device << ")."; - errorText_ = errorStream_.str(); - return FAILURE; - } - - nominalRate = (Float64) sampleRate; - result = AudioObjectSetPropertyData( id, &property, 0, NULL, dataSize, &nominalRate ); - if ( result != noErr ) { - AudioObjectRemovePropertyListener( id, &tmp, rateListener, (void *) &reportedRate ); - errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") setting sample rate for device (" << device << ")."; - errorText_ = errorStream_.str(); - return FAILURE; - } - - // Now wait until the reported nominal rate is what we just set. - UInt32 microCounter = 0; - while ( reportedRate != nominalRate ) { - microCounter += 5000; - if ( microCounter > 5000000 ) break; - usleep( 5000 ); - } - - // Remove the property listener. - AudioObjectRemovePropertyListener( id, &tmp, rateListener, (void *) &reportedRate ); - - if ( microCounter > 5000000 ) { - errorStream_ << "RtApiCore::probeDeviceOpen: timeout waiting for sample rate update for device (" << device << ")."; - errorText_ = errorStream_.str(); - return FAILURE; - } - } - - // Now set the stream format for all streams. Also, check the - // physical format of the device and change that if necessary. - AudioStreamBasicDescription description; - dataSize = sizeof( AudioStreamBasicDescription ); - property.mSelector = kAudioStreamPropertyVirtualFormat; - result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, &description ); - if ( result != noErr ) { - errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") getting stream format for device (" << device << ")."; - errorText_ = errorStream_.str(); - return FAILURE; - } - - // Set the sample rate and data format id. However, only make the - // change if the sample rate is not within 1.0 of the desired - // rate and the format is not linear pcm. - bool updateFormat = false; - if ( fabs( description.mSampleRate - (Float64)sampleRate ) > 1.0 ) { - description.mSampleRate = (Float64) sampleRate; - updateFormat = true; - } - - if ( description.mFormatID != kAudioFormatLinearPCM ) { - description.mFormatID = kAudioFormatLinearPCM; - updateFormat = true; - } - - if ( updateFormat ) { - result = AudioObjectSetPropertyData( id, &property, 0, NULL, dataSize, &description ); - if ( result != noErr ) { - errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") setting sample rate or data format for device (" << device << ")."; - errorText_ = errorStream_.str(); - return FAILURE; - } - } - - // Now check the physical format. - property.mSelector = kAudioStreamPropertyPhysicalFormat; - result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, &description ); - if ( result != noErr ) { - errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") getting stream physical format for device (" << device << ")."; - errorText_ = errorStream_.str(); - return FAILURE; - } - - //std::cout << "Current physical stream format:" << std::endl; - //std::cout << " mBitsPerChan = " << description.mBitsPerChannel << std::endl; - //std::cout << " aligned high = " << (description.mFormatFlags & kAudioFormatFlagIsAlignedHigh) << ", isPacked = " << (description.mFormatFlags & kAudioFormatFlagIsPacked) << std::endl; - //std::cout << " bytesPerFrame = " << description.mBytesPerFrame << std::endl; - //std::cout << " sample rate = " << description.mSampleRate << std::endl; - - if ( description.mFormatID != kAudioFormatLinearPCM || description.mBitsPerChannel < 16 ) { - description.mFormatID = kAudioFormatLinearPCM; - //description.mSampleRate = (Float64) sampleRate; - AudioStreamBasicDescription testDescription = description; - UInt32 formatFlags; - - // We'll try higher bit rates first and then work our way down. - std::vector< std::pair > physicalFormats; - formatFlags = (description.mFormatFlags | kLinearPCMFormatFlagIsFloat) & ~kLinearPCMFormatFlagIsSignedInteger; - physicalFormats.push_back( std::pair( 32, formatFlags ) ); - formatFlags = (description.mFormatFlags | kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked) & ~kLinearPCMFormatFlagIsFloat; - physicalFormats.push_back( std::pair( 32, formatFlags ) ); - physicalFormats.push_back( std::pair( 24, formatFlags ) ); // 24-bit packed - formatFlags &= ~( kAudioFormatFlagIsPacked | kAudioFormatFlagIsAlignedHigh ); - physicalFormats.push_back( std::pair( 24.2, formatFlags ) ); // 24-bit in 4 bytes, aligned low - formatFlags |= kAudioFormatFlagIsAlignedHigh; - physicalFormats.push_back( std::pair( 24.4, formatFlags ) ); // 24-bit in 4 bytes, aligned high - formatFlags = (description.mFormatFlags | kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked) & ~kLinearPCMFormatFlagIsFloat; - physicalFormats.push_back( std::pair( 16, formatFlags ) ); - physicalFormats.push_back( std::pair( 8, formatFlags ) ); - - bool setPhysicalFormat = false; - for( unsigned int i=0; iflags & RTAUDIO_NONINTERLEAVED ) stream_.userInterleaved = false; - else stream_.userInterleaved = true; - stream_.deviceInterleaved[mode] = true; - if ( monoMode == true ) stream_.deviceInterleaved[mode] = false; - - // Set flags for buffer conversion. - stream_.doConvertBuffer[mode] = false; - if ( stream_.userFormat != stream_.deviceFormat[mode] ) - stream_.doConvertBuffer[mode] = true; - if ( stream_.nUserChannels[mode] < stream_.nDeviceChannels[mode] ) - stream_.doConvertBuffer[mode] = true; - if ( streamCount == 1 ) { - if ( stream_.nUserChannels[mode] > 1 && - stream_.userInterleaved != stream_.deviceInterleaved[mode] ) - stream_.doConvertBuffer[mode] = true; - } - else if ( monoMode && stream_.userInterleaved ) - stream_.doConvertBuffer[mode] = true; - - // Allocate our CoreHandle structure for the stream. - CoreHandle *handle = 0; - if ( stream_.apiHandle == 0 ) { - try { - handle = new CoreHandle; - } - catch ( std::bad_alloc& ) { - errorText_ = "RtApiCore::probeDeviceOpen: error allocating CoreHandle memory."; - goto error; - } - - if ( pthread_cond_init( &handle->condition, NULL ) ) { - errorText_ = "RtApiCore::probeDeviceOpen: error initializing pthread condition variable."; - goto error; - } - stream_.apiHandle = (void *) handle; - } - else - handle = (CoreHandle *) stream_.apiHandle; - handle->iStream[mode] = firstStream; - handle->nStreams[mode] = streamCount; - handle->id[mode] = id; - - // Allocate necessary internal buffers. - unsigned long bufferBytes; - bufferBytes = stream_.nUserChannels[mode] * *bufferSize * formatBytes( stream_.userFormat ); - // stream_.userBuffer[mode] = (char *) calloc( bufferBytes, 1 ); - stream_.userBuffer[mode] = (char *) malloc( bufferBytes * sizeof(char) ); - memset( stream_.userBuffer[mode], 0, bufferBytes * sizeof(char) ); - if ( stream_.userBuffer[mode] == NULL ) { - errorText_ = "RtApiCore::probeDeviceOpen: error allocating user buffer memory."; - goto error; - } - - // If possible, we will make use of the CoreAudio stream buffers as - // "device buffers". However, we can't do this if using multiple - // streams. - if ( stream_.doConvertBuffer[mode] && handle->nStreams[mode] > 1 ) { - - bool makeBuffer = true; - bufferBytes = stream_.nDeviceChannels[mode] * formatBytes( stream_.deviceFormat[mode] ); - if ( mode == INPUT ) { - if ( stream_.mode == OUTPUT && stream_.deviceBuffer ) { - unsigned long bytesOut = stream_.nDeviceChannels[0] * formatBytes( stream_.deviceFormat[0] ); - if ( bufferBytes <= bytesOut ) makeBuffer = false; - } - } - - if ( makeBuffer ) { - bufferBytes *= *bufferSize; - if ( stream_.deviceBuffer ) free( stream_.deviceBuffer ); - stream_.deviceBuffer = (char *) calloc( bufferBytes, 1 ); - if ( stream_.deviceBuffer == NULL ) { - errorText_ = "RtApiCore::probeDeviceOpen: error allocating device buffer memory."; - goto error; - } - } - } - - stream_.sampleRate = sampleRate; - stream_.device[mode] = device; - stream_.state = STREAM_STOPPED; - stream_.callbackInfo.object = (void *) this; - - // Setup the buffer conversion information structure. - if ( stream_.doConvertBuffer[mode] ) { - if ( streamCount > 1 ) setConvertInfo( mode, 0 ); - else setConvertInfo( mode, channelOffset ); - } - - if ( mode == INPUT && stream_.mode == OUTPUT && stream_.device[0] == device ) - // Only one callback procedure per device. - stream_.mode = DUPLEX; - else { -#if defined( MAC_OS_X_VERSION_10_5 ) && ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 ) - result = AudioDeviceCreateIOProcID( id, callbackHandler, (void *) &stream_.callbackInfo, &handle->procId[mode] ); -#else - // deprecated in favor of AudioDeviceCreateIOProcID() - result = AudioDeviceAddIOProc( id, callbackHandler, (void *) &stream_.callbackInfo ); -#endif - if ( result != noErr ) { - errorStream_ << "RtApiCore::probeDeviceOpen: system error setting callback for device (" << device << ")."; - errorText_ = errorStream_.str(); - goto error; - } - if ( stream_.mode == OUTPUT && mode == INPUT ) - stream_.mode = DUPLEX; - else - stream_.mode = mode; - } - - // Setup the device property listener for over/underload. - property.mSelector = kAudioDeviceProcessorOverload; - property.mScope = kAudioObjectPropertyScopeGlobal; - result = AudioObjectAddPropertyListener( id, &property, xrunListener, (void *) handle ); - - return SUCCESS; - - error: - if ( handle ) { - pthread_cond_destroy( &handle->condition ); - delete handle; - stream_.apiHandle = 0; - } - - for ( int i=0; i<2; i++ ) { - if ( stream_.userBuffer[i] ) { - free( stream_.userBuffer[i] ); - stream_.userBuffer[i] = 0; - } - } - - if ( stream_.deviceBuffer ) { - free( stream_.deviceBuffer ); - stream_.deviceBuffer = 0; - } - - stream_.state = STREAM_CLOSED; - return FAILURE; -} - -void RtApiCore :: closeStream( void ) -{ - if ( stream_.state == STREAM_CLOSED ) { - errorText_ = "RtApiCore::closeStream(): no open stream to close!"; - error( RtAudioError::WARNING ); - return; - } - - CoreHandle *handle = (CoreHandle *) stream_.apiHandle; - if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { - if (handle) { - AudioObjectPropertyAddress property = { kAudioHardwarePropertyDevices, - kAudioObjectPropertyScopeGlobal, - kAudioObjectPropertyElementMaster }; - - property.mSelector = kAudioDeviceProcessorOverload; - property.mScope = kAudioObjectPropertyScopeGlobal; - if (AudioObjectRemovePropertyListener( handle->id[0], &property, xrunListener, (void *) handle ) != noErr) { - errorText_ = "RtApiCore::closeStream(): error removing property listener!"; - error( RtAudioError::WARNING ); - } - } - if ( stream_.state == STREAM_RUNNING ) - AudioDeviceStop( handle->id[0], callbackHandler ); -#if defined( MAC_OS_X_VERSION_10_5 ) && ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 ) - AudioDeviceDestroyIOProcID( handle->id[0], handle->procId[0] ); -#else - // deprecated in favor of AudioDeviceDestroyIOProcID() - AudioDeviceRemoveIOProc( handle->id[0], callbackHandler ); -#endif - } - - if ( stream_.mode == INPUT || ( stream_.mode == DUPLEX && stream_.device[0] != stream_.device[1] ) ) { - if (handle) { - AudioObjectPropertyAddress property = { kAudioHardwarePropertyDevices, - kAudioObjectPropertyScopeGlobal, - kAudioObjectPropertyElementMaster }; - - property.mSelector = kAudioDeviceProcessorOverload; - property.mScope = kAudioObjectPropertyScopeGlobal; - if (AudioObjectRemovePropertyListener( handle->id[1], &property, xrunListener, (void *) handle ) != noErr) { - errorText_ = "RtApiCore::closeStream(): error removing property listener!"; - error( RtAudioError::WARNING ); - } - } - if ( stream_.state == STREAM_RUNNING ) - AudioDeviceStop( handle->id[1], callbackHandler ); -#if defined( MAC_OS_X_VERSION_10_5 ) && ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 ) - AudioDeviceDestroyIOProcID( handle->id[1], handle->procId[1] ); -#else - // deprecated in favor of AudioDeviceDestroyIOProcID() - AudioDeviceRemoveIOProc( handle->id[1], callbackHandler ); -#endif - } - - for ( int i=0; i<2; i++ ) { - if ( stream_.userBuffer[i] ) { - free( stream_.userBuffer[i] ); - stream_.userBuffer[i] = 0; - } - } - - if ( stream_.deviceBuffer ) { - free( stream_.deviceBuffer ); - stream_.deviceBuffer = 0; - } - - // Destroy pthread condition variable. - pthread_cond_destroy( &handle->condition ); - delete handle; - stream_.apiHandle = 0; - - stream_.mode = UNINITIALIZED; - stream_.state = STREAM_CLOSED; -} - -void RtApiCore :: startStream( void ) -{ - verifyStream(); - if ( stream_.state == STREAM_RUNNING ) { - errorText_ = "RtApiCore::startStream(): the stream is already running!"; - error( RtAudioError::WARNING ); - return; - } - - OSStatus result = noErr; - CoreHandle *handle = (CoreHandle *) stream_.apiHandle; - if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { - - result = AudioDeviceStart( handle->id[0], callbackHandler ); - if ( result != noErr ) { - errorStream_ << "RtApiCore::startStream: system error (" << getErrorCode( result ) << ") starting callback procedure on device (" << stream_.device[0] << ")."; - errorText_ = errorStream_.str(); - goto unlock; - } - } - - if ( stream_.mode == INPUT || - ( stream_.mode == DUPLEX && stream_.device[0] != stream_.device[1] ) ) { - - result = AudioDeviceStart( handle->id[1], callbackHandler ); - if ( result != noErr ) { - errorStream_ << "RtApiCore::startStream: system error starting input callback procedure on device (" << stream_.device[1] << ")."; - errorText_ = errorStream_.str(); - goto unlock; - } - } - - handle->drainCounter = 0; - handle->internalDrain = false; - stream_.state = STREAM_RUNNING; - - unlock: - if ( result == noErr ) return; - error( RtAudioError::SYSTEM_ERROR ); -} - -void RtApiCore :: stopStream( void ) -{ - verifyStream(); - if ( stream_.state == STREAM_STOPPED ) { - errorText_ = "RtApiCore::stopStream(): the stream is already stopped!"; - error( RtAudioError::WARNING ); - return; - } - - OSStatus result = noErr; - CoreHandle *handle = (CoreHandle *) stream_.apiHandle; - if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { - - if ( handle->drainCounter == 0 ) { - handle->drainCounter = 2; - pthread_cond_wait( &handle->condition, &stream_.mutex ); // block until signaled - } - - result = AudioDeviceStop( handle->id[0], callbackHandler ); - if ( result != noErr ) { - errorStream_ << "RtApiCore::stopStream: system error (" << getErrorCode( result ) << ") stopping callback procedure on device (" << stream_.device[0] << ")."; - errorText_ = errorStream_.str(); - goto unlock; - } - } - - if ( stream_.mode == INPUT || ( stream_.mode == DUPLEX && stream_.device[0] != stream_.device[1] ) ) { - - result = AudioDeviceStop( handle->id[1], callbackHandler ); - if ( result != noErr ) { - errorStream_ << "RtApiCore::stopStream: system error (" << getErrorCode( result ) << ") stopping input callback procedure on device (" << stream_.device[1] << ")."; - errorText_ = errorStream_.str(); - goto unlock; - } - } - - stream_.state = STREAM_STOPPED; - - unlock: - if ( result == noErr ) return; - error( RtAudioError::SYSTEM_ERROR ); -} - -void RtApiCore :: abortStream( void ) -{ - verifyStream(); - if ( stream_.state == STREAM_STOPPED ) { - errorText_ = "RtApiCore::abortStream(): the stream is already stopped!"; - error( RtAudioError::WARNING ); - return; - } - - CoreHandle *handle = (CoreHandle *) stream_.apiHandle; - handle->drainCounter = 2; - - stopStream(); -} - -// This function will be called by a spawned thread when the user -// callback function signals that the stream should be stopped or -// aborted. It is better to handle it this way because the -// callbackEvent() function probably should return before the AudioDeviceStop() -// function is called. -static void *coreStopStream( void *ptr ) -{ - CallbackInfo *info = (CallbackInfo *) ptr; - RtApiCore *object = (RtApiCore *) info->object; - - object->stopStream(); - pthread_exit( NULL ); -} - -bool RtApiCore :: callbackEvent( AudioDeviceID deviceId, - const AudioBufferList *inBufferList, - const AudioBufferList *outBufferList ) -{ - if ( stream_.state == STREAM_STOPPED || stream_.state == STREAM_STOPPING ) return SUCCESS; - if ( stream_.state == STREAM_CLOSED ) { - errorText_ = "RtApiCore::callbackEvent(): the stream is closed ... this shouldn't happen!"; - error( RtAudioError::WARNING ); - return FAILURE; - } - - CallbackInfo *info = (CallbackInfo *) &stream_.callbackInfo; - CoreHandle *handle = (CoreHandle *) stream_.apiHandle; - - // Check if we were draining the stream and signal is finished. - if ( handle->drainCounter > 3 ) { - ThreadHandle threadId; - - stream_.state = STREAM_STOPPING; - if ( handle->internalDrain == true ) - pthread_create( &threadId, NULL, coreStopStream, info ); - else // external call to stopStream() - pthread_cond_signal( &handle->condition ); - return SUCCESS; - } - - AudioDeviceID outputDevice = handle->id[0]; - - // Invoke user callback to get fresh output data UNLESS we are - // draining stream or duplex mode AND the input/output devices are - // different AND this function is called for the input device. - if ( handle->drainCounter == 0 && ( stream_.mode != DUPLEX || deviceId == outputDevice ) ) { - RtAudioCallback callback = (RtAudioCallback) info->callback; - double streamTime = getStreamTime(); - RtAudioStreamStatus status = 0; - if ( stream_.mode != INPUT && handle->xrun[0] == true ) { - status |= RTAUDIO_OUTPUT_UNDERFLOW; - handle->xrun[0] = false; - } - if ( stream_.mode != OUTPUT && handle->xrun[1] == true ) { - status |= RTAUDIO_INPUT_OVERFLOW; - handle->xrun[1] = false; - } - - int cbReturnValue = callback( stream_.userBuffer[0], stream_.userBuffer[1], - stream_.bufferSize, streamTime, status, info->userData ); - if ( cbReturnValue == 2 ) { - stream_.state = STREAM_STOPPING; - handle->drainCounter = 2; - abortStream(); - return SUCCESS; - } - else if ( cbReturnValue == 1 ) { - handle->drainCounter = 1; - handle->internalDrain = true; - } - } - - if ( stream_.mode == OUTPUT || ( stream_.mode == DUPLEX && deviceId == outputDevice ) ) { - - if ( handle->drainCounter > 1 ) { // write zeros to the output stream - - if ( handle->nStreams[0] == 1 ) { - memset( outBufferList->mBuffers[handle->iStream[0]].mData, - 0, - outBufferList->mBuffers[handle->iStream[0]].mDataByteSize ); - } - else { // fill multiple streams with zeros - for ( unsigned int i=0; inStreams[0]; i++ ) { - memset( outBufferList->mBuffers[handle->iStream[0]+i].mData, - 0, - outBufferList->mBuffers[handle->iStream[0]+i].mDataByteSize ); - } - } - } - else if ( handle->nStreams[0] == 1 ) { - if ( stream_.doConvertBuffer[0] ) { // convert directly to CoreAudio stream buffer - convertBuffer( (char *) outBufferList->mBuffers[handle->iStream[0]].mData, - stream_.userBuffer[0], stream_.convertInfo[0] ); - } - else { // copy from user buffer - memcpy( outBufferList->mBuffers[handle->iStream[0]].mData, - stream_.userBuffer[0], - outBufferList->mBuffers[handle->iStream[0]].mDataByteSize ); - } - } - else { // fill multiple streams - Float32 *inBuffer = (Float32 *) stream_.userBuffer[0]; - if ( stream_.doConvertBuffer[0] ) { - convertBuffer( stream_.deviceBuffer, stream_.userBuffer[0], stream_.convertInfo[0] ); - inBuffer = (Float32 *) stream_.deviceBuffer; - } - - if ( stream_.deviceInterleaved[0] == false ) { // mono mode - UInt32 bufferBytes = outBufferList->mBuffers[handle->iStream[0]].mDataByteSize; - for ( unsigned int i=0; imBuffers[handle->iStream[0]+i].mData, - (void *)&inBuffer[i*stream_.bufferSize], bufferBytes ); - } - } - else { // fill multiple multi-channel streams with interleaved data - UInt32 streamChannels, channelsLeft, inJump, outJump, inOffset; - Float32 *out, *in; - - bool inInterleaved = ( stream_.userInterleaved ) ? true : false; - UInt32 inChannels = stream_.nUserChannels[0]; - if ( stream_.doConvertBuffer[0] ) { - inInterleaved = true; // device buffer will always be interleaved for nStreams > 1 and not mono mode - inChannels = stream_.nDeviceChannels[0]; - } - - if ( inInterleaved ) inOffset = 1; - else inOffset = stream_.bufferSize; - - channelsLeft = inChannels; - for ( unsigned int i=0; inStreams[0]; i++ ) { - in = inBuffer; - out = (Float32 *) outBufferList->mBuffers[handle->iStream[0]+i].mData; - streamChannels = outBufferList->mBuffers[handle->iStream[0]+i].mNumberChannels; - - outJump = 0; - // Account for possible channel offset in first stream - if ( i == 0 && stream_.channelOffset[0] > 0 ) { - streamChannels -= stream_.channelOffset[0]; - outJump = stream_.channelOffset[0]; - out += outJump; - } - - // Account for possible unfilled channels at end of the last stream - if ( streamChannels > channelsLeft ) { - outJump = streamChannels - channelsLeft; - streamChannels = channelsLeft; - } - - // Determine input buffer offsets and skips - if ( inInterleaved ) { - inJump = inChannels; - in += inChannels - channelsLeft; - } - else { - inJump = 1; - in += (inChannels - channelsLeft) * inOffset; - } - - for ( unsigned int i=0; idrainCounter ) { - handle->drainCounter++; - goto unlock; - } - - AudioDeviceID inputDevice; - inputDevice = handle->id[1]; - if ( stream_.mode == INPUT || ( stream_.mode == DUPLEX && deviceId == inputDevice ) ) { - - if ( handle->nStreams[1] == 1 ) { - if ( stream_.doConvertBuffer[1] ) { // convert directly from CoreAudio stream buffer - convertBuffer( stream_.userBuffer[1], - (char *) inBufferList->mBuffers[handle->iStream[1]].mData, - stream_.convertInfo[1] ); - } - else { // copy to user buffer - memcpy( stream_.userBuffer[1], - inBufferList->mBuffers[handle->iStream[1]].mData, - inBufferList->mBuffers[handle->iStream[1]].mDataByteSize ); - } - } - else { // read from multiple streams - Float32 *outBuffer = (Float32 *) stream_.userBuffer[1]; - if ( stream_.doConvertBuffer[1] ) outBuffer = (Float32 *) stream_.deviceBuffer; - - if ( stream_.deviceInterleaved[1] == false ) { // mono mode - UInt32 bufferBytes = inBufferList->mBuffers[handle->iStream[1]].mDataByteSize; - for ( unsigned int i=0; imBuffers[handle->iStream[1]+i].mData, bufferBytes ); - } - } - else { // read from multiple multi-channel streams - UInt32 streamChannels, channelsLeft, inJump, outJump, outOffset; - Float32 *out, *in; - - bool outInterleaved = ( stream_.userInterleaved ) ? true : false; - UInt32 outChannels = stream_.nUserChannels[1]; - if ( stream_.doConvertBuffer[1] ) { - outInterleaved = true; // device buffer will always be interleaved for nStreams > 1 and not mono mode - outChannels = stream_.nDeviceChannels[1]; - } - - if ( outInterleaved ) outOffset = 1; - else outOffset = stream_.bufferSize; - - channelsLeft = outChannels; - for ( unsigned int i=0; inStreams[1]; i++ ) { - out = outBuffer; - in = (Float32 *) inBufferList->mBuffers[handle->iStream[1]+i].mData; - streamChannels = inBufferList->mBuffers[handle->iStream[1]+i].mNumberChannels; - - inJump = 0; - // Account for possible channel offset in first stream - if ( i == 0 && stream_.channelOffset[1] > 0 ) { - streamChannels -= stream_.channelOffset[1]; - inJump = stream_.channelOffset[1]; - in += inJump; - } - - // Account for possible unread channels at end of the last stream - if ( streamChannels > channelsLeft ) { - inJump = streamChannels - channelsLeft; - streamChannels = channelsLeft; - } - - // Determine output buffer offsets and skips - if ( outInterleaved ) { - outJump = outChannels; - out += outChannels - channelsLeft; - } - else { - outJump = 1; - out += (outChannels - channelsLeft) * outOffset; - } - - for ( unsigned int i=0; i -#include -#include - -// A structure to hold various information related to the Jack API -// implementation. -struct JackHandle { - jack_client_t *client; - jack_port_t **ports[2]; - std::string deviceName[2]; - bool xrun[2]; - pthread_cond_t condition; - int drainCounter; // Tracks callback counts when draining - bool internalDrain; // Indicates if stop is initiated from callback or not. - - JackHandle() - :client(0), drainCounter(0), internalDrain(false) { ports[0] = 0; ports[1] = 0; xrun[0] = false; xrun[1] = false; } -}; - -static void jackSilentError( const char * ) {}; - -RtApiJack :: RtApiJack() -{ - // Nothing to do here. -#if !defined(__RTAUDIO_DEBUG__) - // Turn off Jack's internal error reporting. - jack_set_error_function( &jackSilentError ); -#endif -} - -RtApiJack :: ~RtApiJack() -{ - if ( stream_.state != STREAM_CLOSED ) closeStream(); -} - -unsigned int RtApiJack :: getDeviceCount( void ) -{ - // See if we can become a jack client. - jack_options_t options = (jack_options_t) ( JackNoStartServer ); //JackNullOption; - jack_status_t *status = NULL; - jack_client_t *client = jack_client_open( "RtApiJackCount", options, status ); - if ( client == 0 ) return 0; - - const char **ports; - std::string port, previousPort; - unsigned int nChannels = 0, nDevices = 0; - ports = jack_get_ports( client, NULL, NULL, 0 ); - if ( ports ) { - // Parse the port names up to the first colon (:). - size_t iColon = 0; - do { - port = (char *) ports[ nChannels ]; - iColon = port.find(":"); - if ( iColon != std::string::npos ) { - port = port.substr( 0, iColon + 1 ); - if ( port != previousPort ) { - nDevices++; - previousPort = port; - } - } - } while ( ports[++nChannels] ); - free( ports ); - } - - jack_client_close( client ); - return nDevices; -} - -RtAudio::DeviceInfo RtApiJack :: getDeviceInfo( unsigned int device ) -{ - RtAudio::DeviceInfo info; - info.probed = false; - - jack_options_t options = (jack_options_t) ( JackNoStartServer ); //JackNullOption - jack_status_t *status = NULL; - jack_client_t *client = jack_client_open( "RtApiJackInfo", options, status ); - if ( client == 0 ) { - errorText_ = "RtApiJack::getDeviceInfo: Jack server not found or connection error!"; - error( RtAudioError::WARNING ); - return info; - } - - const char **ports; - std::string port, previousPort; - unsigned int nPorts = 0, nDevices = 0; - ports = jack_get_ports( client, NULL, NULL, 0 ); - if ( ports ) { - // Parse the port names up to the first colon (:). - size_t iColon = 0; - do { - port = (char *) ports[ nPorts ]; - iColon = port.find(":"); - if ( iColon != std::string::npos ) { - port = port.substr( 0, iColon ); - if ( port != previousPort ) { - if ( nDevices == device ) info.name = port; - nDevices++; - previousPort = port; - } - } - } while ( ports[++nPorts] ); - free( ports ); - } - - if ( device >= nDevices ) { - jack_client_close( client ); - errorText_ = "RtApiJack::getDeviceInfo: device ID is invalid!"; - error( RtAudioError::INVALID_USE ); - return info; - } - - // Get the current jack server sample rate. - info.sampleRates.clear(); - - info.preferredSampleRate = jack_get_sample_rate( client ); - info.sampleRates.push_back( info.preferredSampleRate ); - - // Count the available ports containing the client name as device - // channels. Jack "input ports" equal RtAudio output channels. - unsigned int nChannels = 0; - ports = jack_get_ports( client, info.name.c_str(), NULL, JackPortIsInput ); - if ( ports ) { - while ( ports[ nChannels ] ) nChannels++; - free( ports ); - info.outputChannels = nChannels; - } - - // Jack "output ports" equal RtAudio input channels. - nChannels = 0; - ports = jack_get_ports( client, info.name.c_str(), NULL, JackPortIsOutput ); - if ( ports ) { - while ( ports[ nChannels ] ) nChannels++; - free( ports ); - info.inputChannels = nChannels; - } - - if ( info.outputChannels == 0 && info.inputChannels == 0 ) { - jack_client_close(client); - errorText_ = "RtApiJack::getDeviceInfo: error determining Jack input/output channels!"; - error( RtAudioError::WARNING ); - return info; - } - - // If device opens for both playback and capture, we determine the channels. - if ( info.outputChannels > 0 && info.inputChannels > 0 ) - info.duplexChannels = (info.outputChannels > info.inputChannels) ? info.inputChannels : info.outputChannels; - - // Jack always uses 32-bit floats. - info.nativeFormats = RTAUDIO_FLOAT32; - - // Jack doesn't provide default devices so we'll use the first available one. - if ( device == 0 && info.outputChannels > 0 ) - info.isDefaultOutput = true; - if ( device == 0 && info.inputChannels > 0 ) - info.isDefaultInput = true; - - jack_client_close(client); - info.probed = true; - return info; -} - -static int jackCallbackHandler( jack_nframes_t nframes, void *infoPointer ) -{ - CallbackInfo *info = (CallbackInfo *) infoPointer; - - RtApiJack *object = (RtApiJack *) info->object; - if ( object->callbackEvent( (unsigned long) nframes ) == false ) return 1; - - return 0; -} - -// This function will be called by a spawned thread when the Jack -// server signals that it is shutting down. It is necessary to handle -// it this way because the jackShutdown() function must return before -// the jack_deactivate() function (in closeStream()) will return. -static void *jackCloseStream( void *ptr ) -{ - CallbackInfo *info = (CallbackInfo *) ptr; - RtApiJack *object = (RtApiJack *) info->object; - - object->closeStream(); - - pthread_exit( NULL ); -} -static void jackShutdown( void *infoPointer ) -{ - CallbackInfo *info = (CallbackInfo *) infoPointer; - RtApiJack *object = (RtApiJack *) info->object; - - // Check current stream state. If stopped, then we'll assume this - // was called as a result of a call to RtApiJack::stopStream (the - // deactivation of a client handle causes this function to be called). - // If not, we'll assume the Jack server is shutting down or some - // other problem occurred and we should close the stream. - if ( object->isStreamRunning() == false ) return; - - ThreadHandle threadId; - pthread_create( &threadId, NULL, jackCloseStream, info ); - std::cerr << "\nRtApiJack: the Jack server is shutting down this client ... stream stopped and closed!!\n" << std::endl; -} - -static int jackXrun( void *infoPointer ) -{ - JackHandle *handle = (JackHandle *) infoPointer; - - if ( handle->ports[0] ) handle->xrun[0] = true; - if ( handle->ports[1] ) handle->xrun[1] = true; - - return 0; -} - -bool RtApiJack :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, - unsigned int firstChannel, unsigned int sampleRate, - RtAudioFormat format, unsigned int *bufferSize, - RtAudio::StreamOptions *options ) -{ - JackHandle *handle = (JackHandle *) stream_.apiHandle; - - // Look for jack server and try to become a client (only do once per stream). - jack_client_t *client = 0; - if ( mode == OUTPUT || ( mode == INPUT && stream_.mode != OUTPUT ) ) { - jack_options_t jackoptions = (jack_options_t) ( JackNoStartServer ); //JackNullOption; - jack_status_t *status = NULL; - if ( options && !options->streamName.empty() ) - client = jack_client_open( options->streamName.c_str(), jackoptions, status ); - else - client = jack_client_open( "RtApiJack", jackoptions, status ); - if ( client == 0 ) { - errorText_ = "RtApiJack::probeDeviceOpen: Jack server not found or connection error!"; - error( RtAudioError::WARNING ); - return FAILURE; - } - } - else { - // The handle must have been created on an earlier pass. - client = handle->client; - } - - const char **ports; - std::string port, previousPort, deviceName; - unsigned int nPorts = 0, nDevices = 0; - ports = jack_get_ports( client, NULL, NULL, 0 ); - if ( ports ) { - // Parse the port names up to the first colon (:). - size_t iColon = 0; - do { - port = (char *) ports[ nPorts ]; - iColon = port.find(":"); - if ( iColon != std::string::npos ) { - port = port.substr( 0, iColon ); - if ( port != previousPort ) { - if ( nDevices == device ) deviceName = port; - nDevices++; - previousPort = port; - } - } - } while ( ports[++nPorts] ); - free( ports ); - } - - if ( device >= nDevices ) { - errorText_ = "RtApiJack::probeDeviceOpen: device ID is invalid!"; - return FAILURE; - } - - // Count the available ports containing the client name as device - // channels. Jack "input ports" equal RtAudio output channels. - unsigned int nChannels = 0; - unsigned long flag = JackPortIsInput; - if ( mode == INPUT ) flag = JackPortIsOutput; - ports = jack_get_ports( client, deviceName.c_str(), NULL, flag ); - if ( ports ) { - while ( ports[ nChannels ] ) nChannels++; - free( ports ); - } - - // Compare the jack ports for specified client to the requested number of channels. - if ( nChannels < (channels + firstChannel) ) { - errorStream_ << "RtApiJack::probeDeviceOpen: requested number of channels (" << channels << ") + offset (" << firstChannel << ") not found for specified device (" << device << ":" << deviceName << ")."; - errorText_ = errorStream_.str(); - return FAILURE; - } - - // Check the jack server sample rate. - unsigned int jackRate = jack_get_sample_rate( client ); - if ( sampleRate != jackRate ) { - jack_client_close( client ); - errorStream_ << "RtApiJack::probeDeviceOpen: the requested sample rate (" << sampleRate << ") is different than the JACK server rate (" << jackRate << ")."; - errorText_ = errorStream_.str(); - return FAILURE; - } - stream_.sampleRate = jackRate; - - // Get the latency of the JACK port. - ports = jack_get_ports( client, deviceName.c_str(), NULL, flag ); - if ( ports[ firstChannel ] ) { - // Added by Ge Wang - jack_latency_callback_mode_t cbmode = (mode == INPUT ? JackCaptureLatency : JackPlaybackLatency); - // the range (usually the min and max are equal) - jack_latency_range_t latrange; latrange.min = latrange.max = 0; - // get the latency range - jack_port_get_latency_range( jack_port_by_name( client, ports[firstChannel] ), cbmode, &latrange ); - // be optimistic, use the min! - stream_.latency[mode] = latrange.min; - //stream_.latency[mode] = jack_port_get_latency( jack_port_by_name( client, ports[ firstChannel ] ) ); - } - free( ports ); - - // The jack server always uses 32-bit floating-point data. - stream_.deviceFormat[mode] = RTAUDIO_FLOAT32; - stream_.userFormat = format; - - if ( options && options->flags & RTAUDIO_NONINTERLEAVED ) stream_.userInterleaved = false; - else stream_.userInterleaved = true; - - // Jack always uses non-interleaved buffers. - stream_.deviceInterleaved[mode] = false; - - // Jack always provides host byte-ordered data. - stream_.doByteSwap[mode] = false; - - // Get the buffer size. The buffer size and number of buffers - // (periods) is set when the jack server is started. - stream_.bufferSize = (int) jack_get_buffer_size( client ); - *bufferSize = stream_.bufferSize; - - stream_.nDeviceChannels[mode] = channels; - stream_.nUserChannels[mode] = channels; - - // Set flags for buffer conversion. - stream_.doConvertBuffer[mode] = false; - if ( stream_.userFormat != stream_.deviceFormat[mode] ) - stream_.doConvertBuffer[mode] = true; - if ( stream_.userInterleaved != stream_.deviceInterleaved[mode] && - stream_.nUserChannels[mode] > 1 ) - stream_.doConvertBuffer[mode] = true; - - // Allocate our JackHandle structure for the stream. - if ( handle == 0 ) { - try { - handle = new JackHandle; - } - catch ( std::bad_alloc& ) { - errorText_ = "RtApiJack::probeDeviceOpen: error allocating JackHandle memory."; - goto error; - } - - if ( pthread_cond_init(&handle->condition, NULL) ) { - errorText_ = "RtApiJack::probeDeviceOpen: error initializing pthread condition variable."; - goto error; - } - stream_.apiHandle = (void *) handle; - handle->client = client; - } - handle->deviceName[mode] = deviceName; - - // Allocate necessary internal buffers. - unsigned long bufferBytes; - bufferBytes = stream_.nUserChannels[mode] * *bufferSize * formatBytes( stream_.userFormat ); - stream_.userBuffer[mode] = (char *) calloc( bufferBytes, 1 ); - if ( stream_.userBuffer[mode] == NULL ) { - errorText_ = "RtApiJack::probeDeviceOpen: error allocating user buffer memory."; - goto error; - } - - if ( stream_.doConvertBuffer[mode] ) { - - bool makeBuffer = true; - if ( mode == OUTPUT ) - bufferBytes = stream_.nDeviceChannels[0] * formatBytes( stream_.deviceFormat[0] ); - else { // mode == INPUT - bufferBytes = stream_.nDeviceChannels[1] * formatBytes( stream_.deviceFormat[1] ); - if ( stream_.mode == OUTPUT && stream_.deviceBuffer ) { - unsigned long bytesOut = stream_.nDeviceChannels[0] * formatBytes(stream_.deviceFormat[0]); - if ( bufferBytes < bytesOut ) makeBuffer = false; - } - } - - if ( makeBuffer ) { - bufferBytes *= *bufferSize; - if ( stream_.deviceBuffer ) free( stream_.deviceBuffer ); - stream_.deviceBuffer = (char *) calloc( bufferBytes, 1 ); - if ( stream_.deviceBuffer == NULL ) { - errorText_ = "RtApiJack::probeDeviceOpen: error allocating device buffer memory."; - goto error; - } - } - } - - // Allocate memory for the Jack ports (channels) identifiers. - handle->ports[mode] = (jack_port_t **) malloc ( sizeof (jack_port_t *) * channels ); - if ( handle->ports[mode] == NULL ) { - errorText_ = "RtApiJack::probeDeviceOpen: error allocating port memory."; - goto error; - } - - stream_.device[mode] = device; - stream_.channelOffset[mode] = firstChannel; - stream_.state = STREAM_STOPPED; - stream_.callbackInfo.object = (void *) this; - - if ( stream_.mode == OUTPUT && mode == INPUT ) - // We had already set up the stream for output. - stream_.mode = DUPLEX; - else { - stream_.mode = mode; - jack_set_process_callback( handle->client, jackCallbackHandler, (void *) &stream_.callbackInfo ); - jack_set_xrun_callback( handle->client, jackXrun, (void *) &handle ); - jack_on_shutdown( handle->client, jackShutdown, (void *) &stream_.callbackInfo ); - } - - // Register our ports. - char label[64]; - if ( mode == OUTPUT ) { - for ( unsigned int i=0; iports[0][i] = jack_port_register( handle->client, (const char *)label, - JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0 ); - } - } - else { - for ( unsigned int i=0; iports[1][i] = jack_port_register( handle->client, (const char *)label, - JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0 ); - } - } - - // Setup the buffer conversion information structure. We don't use - // buffers to do channel offsets, so we override that parameter - // here. - if ( stream_.doConvertBuffer[mode] ) setConvertInfo( mode, 0 ); - - return SUCCESS; - - error: - if ( handle ) { - pthread_cond_destroy( &handle->condition ); - jack_client_close( handle->client ); - - if ( handle->ports[0] ) free( handle->ports[0] ); - if ( handle->ports[1] ) free( handle->ports[1] ); - - delete handle; - stream_.apiHandle = 0; - } - - for ( int i=0; i<2; i++ ) { - if ( stream_.userBuffer[i] ) { - free( stream_.userBuffer[i] ); - stream_.userBuffer[i] = 0; - } - } - - if ( stream_.deviceBuffer ) { - free( stream_.deviceBuffer ); - stream_.deviceBuffer = 0; - } - - return FAILURE; -} - -void RtApiJack :: closeStream( void ) -{ - if ( stream_.state == STREAM_CLOSED ) { - errorText_ = "RtApiJack::closeStream(): no open stream to close!"; - error( RtAudioError::WARNING ); - return; - } - - JackHandle *handle = (JackHandle *) stream_.apiHandle; - if ( handle ) { - - if ( stream_.state == STREAM_RUNNING ) - jack_deactivate( handle->client ); - - jack_client_close( handle->client ); - } - - if ( handle ) { - if ( handle->ports[0] ) free( handle->ports[0] ); - if ( handle->ports[1] ) free( handle->ports[1] ); - pthread_cond_destroy( &handle->condition ); - delete handle; - stream_.apiHandle = 0; - } - - for ( int i=0; i<2; i++ ) { - if ( stream_.userBuffer[i] ) { - free( stream_.userBuffer[i] ); - stream_.userBuffer[i] = 0; - } - } - - if ( stream_.deviceBuffer ) { - free( stream_.deviceBuffer ); - stream_.deviceBuffer = 0; - } - - stream_.mode = UNINITIALIZED; - stream_.state = STREAM_CLOSED; -} - -void RtApiJack :: startStream( void ) -{ - verifyStream(); - if ( stream_.state == STREAM_RUNNING ) { - errorText_ = "RtApiJack::startStream(): the stream is already running!"; - error( RtAudioError::WARNING ); - return; - } - - JackHandle *handle = (JackHandle *) stream_.apiHandle; - int result = jack_activate( handle->client ); - if ( result ) { - errorText_ = "RtApiJack::startStream(): unable to activate JACK client!"; - goto unlock; - } - - const char **ports; - - // Get the list of available ports. - if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { - result = 1; - ports = jack_get_ports( handle->client, handle->deviceName[0].c_str(), NULL, JackPortIsInput); - if ( ports == NULL) { - errorText_ = "RtApiJack::startStream(): error determining available JACK input ports!"; - goto unlock; - } - - // Now make the port connections. Since RtAudio wasn't designed to - // allow the user to select particular channels of a device, we'll - // just open the first "nChannels" ports with offset. - for ( unsigned int i=0; iclient, jack_port_name( handle->ports[0][i] ), ports[ stream_.channelOffset[0] + i ] ); - if ( result ) { - free( ports ); - errorText_ = "RtApiJack::startStream(): error connecting output ports!"; - goto unlock; - } - } - free(ports); - } - - if ( stream_.mode == INPUT || stream_.mode == DUPLEX ) { - result = 1; - ports = jack_get_ports( handle->client, handle->deviceName[1].c_str(), NULL, JackPortIsOutput ); - if ( ports == NULL) { - errorText_ = "RtApiJack::startStream(): error determining available JACK output ports!"; - goto unlock; - } - - // Now make the port connections. See note above. - for ( unsigned int i=0; iclient, ports[ stream_.channelOffset[1] + i ], jack_port_name( handle->ports[1][i] ) ); - if ( result ) { - free( ports ); - errorText_ = "RtApiJack::startStream(): error connecting input ports!"; - goto unlock; - } - } - free(ports); - } - - handle->drainCounter = 0; - handle->internalDrain = false; - stream_.state = STREAM_RUNNING; - - unlock: - if ( result == 0 ) return; - error( RtAudioError::SYSTEM_ERROR ); -} - -void RtApiJack :: stopStream( void ) -{ - verifyStream(); - if ( stream_.state == STREAM_STOPPED ) { - errorText_ = "RtApiJack::stopStream(): the stream is already stopped!"; - error( RtAudioError::WARNING ); - return; - } - - JackHandle *handle = (JackHandle *) stream_.apiHandle; - if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { - - if ( handle->drainCounter == 0 ) { - handle->drainCounter = 2; - pthread_cond_wait( &handle->condition, &stream_.mutex ); // block until signaled - } - } - - jack_deactivate( handle->client ); - stream_.state = STREAM_STOPPED; -} - -void RtApiJack :: abortStream( void ) -{ - verifyStream(); - if ( stream_.state == STREAM_STOPPED ) { - errorText_ = "RtApiJack::abortStream(): the stream is already stopped!"; - error( RtAudioError::WARNING ); - return; - } - - JackHandle *handle = (JackHandle *) stream_.apiHandle; - handle->drainCounter = 2; - - stopStream(); -} - -// This function will be called by a spawned thread when the user -// callback function signals that the stream should be stopped or -// aborted. It is necessary to handle it this way because the -// callbackEvent() function must return before the jack_deactivate() -// function will return. -static void *jackStopStream( void *ptr ) -{ - CallbackInfo *info = (CallbackInfo *) ptr; - RtApiJack *object = (RtApiJack *) info->object; - - object->stopStream(); - pthread_exit( NULL ); -} - -bool RtApiJack :: callbackEvent( unsigned long nframes ) -{ - if ( stream_.state == STREAM_STOPPED || stream_.state == STREAM_STOPPING ) return SUCCESS; - if ( stream_.state == STREAM_CLOSED ) { - errorText_ = "RtApiCore::callbackEvent(): the stream is closed ... this shouldn't happen!"; - error( RtAudioError::WARNING ); - return FAILURE; - } - if ( stream_.bufferSize != nframes ) { - errorText_ = "RtApiCore::callbackEvent(): the JACK buffer size has changed ... cannot process!"; - error( RtAudioError::WARNING ); - return FAILURE; - } - - CallbackInfo *info = (CallbackInfo *) &stream_.callbackInfo; - JackHandle *handle = (JackHandle *) stream_.apiHandle; - - // Check if we were draining the stream and signal is finished. - if ( handle->drainCounter > 3 ) { - ThreadHandle threadId; - - stream_.state = STREAM_STOPPING; - if ( handle->internalDrain == true ) - pthread_create( &threadId, NULL, jackStopStream, info ); - else - pthread_cond_signal( &handle->condition ); - return SUCCESS; - } - - // Invoke user callback first, to get fresh output data. - if ( handle->drainCounter == 0 ) { - RtAudioCallback callback = (RtAudioCallback) info->callback; - double streamTime = getStreamTime(); - RtAudioStreamStatus status = 0; - if ( stream_.mode != INPUT && handle->xrun[0] == true ) { - status |= RTAUDIO_OUTPUT_UNDERFLOW; - handle->xrun[0] = false; - } - if ( stream_.mode != OUTPUT && handle->xrun[1] == true ) { - status |= RTAUDIO_INPUT_OVERFLOW; - handle->xrun[1] = false; - } - int cbReturnValue = callback( stream_.userBuffer[0], stream_.userBuffer[1], - stream_.bufferSize, streamTime, status, info->userData ); - if ( cbReturnValue == 2 ) { - stream_.state = STREAM_STOPPING; - handle->drainCounter = 2; - ThreadHandle id; - pthread_create( &id, NULL, jackStopStream, info ); - return SUCCESS; - } - else if ( cbReturnValue == 1 ) { - handle->drainCounter = 1; - handle->internalDrain = true; - } - } - - jack_default_audio_sample_t *jackbuffer; - unsigned long bufferBytes = nframes * sizeof( jack_default_audio_sample_t ); - if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { - - if ( handle->drainCounter > 1 ) { // write zeros to the output stream - - for ( unsigned int i=0; iports[0][i], (jack_nframes_t) nframes ); - memset( jackbuffer, 0, bufferBytes ); - } - - } - else if ( stream_.doConvertBuffer[0] ) { - - convertBuffer( stream_.deviceBuffer, stream_.userBuffer[0], stream_.convertInfo[0] ); - - for ( unsigned int i=0; iports[0][i], (jack_nframes_t) nframes ); - memcpy( jackbuffer, &stream_.deviceBuffer[i*bufferBytes], bufferBytes ); - } - } - else { // no buffer conversion - for ( unsigned int i=0; iports[0][i], (jack_nframes_t) nframes ); - memcpy( jackbuffer, &stream_.userBuffer[0][i*bufferBytes], bufferBytes ); - } - } - } - - // Don't bother draining input - if ( handle->drainCounter ) { - handle->drainCounter++; - goto unlock; - } - - if ( stream_.mode == INPUT || stream_.mode == DUPLEX ) { - - if ( stream_.doConvertBuffer[1] ) { - for ( unsigned int i=0; iports[1][i], (jack_nframes_t) nframes ); - memcpy( &stream_.deviceBuffer[i*bufferBytes], jackbuffer, bufferBytes ); - } - convertBuffer( stream_.userBuffer[1], stream_.deviceBuffer, stream_.convertInfo[1] ); - } - else { // no buffer conversion - for ( unsigned int i=0; iports[1][i], (jack_nframes_t) nframes ); - memcpy( &stream_.userBuffer[1][i*bufferBytes], jackbuffer, bufferBytes ); - } - } - } - - unlock: - RtApi::tickStreamTime(); - return SUCCESS; -} - //******************** End of __UNIX_JACK__ *********************// -#endif - -#if defined(__WINDOWS_ASIO__) // ASIO API on Windows - -// The ASIO API is designed around a callback scheme, so this -// implementation is similar to that used for OS-X CoreAudio and Linux -// Jack. The primary constraint with ASIO is that it only allows -// access to a single driver at a time. Thus, it is not possible to -// have more than one simultaneous RtAudio stream. -// -// This implementation also requires a number of external ASIO files -// and a few global variables. The ASIO callback scheme does not -// allow for the passing of user data, so we must create a global -// pointer to our callbackInfo structure. -// -// On unix systems, we make use of a pthread condition variable. -// Since there is no equivalent in Windows, I hacked something based -// on information found in -// http://www.cs.wustl.edu/~schmidt/win32-cv-1.html. - -#include "asiosys.h" -#include "asio.h" -#include "iasiothiscallresolver.h" -#include "asiodrivers.h" -#include - -static AsioDrivers drivers; -static ASIOCallbacks asioCallbacks; -static ASIODriverInfo driverInfo; -static CallbackInfo *asioCallbackInfo; -static bool asioXRun; - -struct AsioHandle { - int drainCounter; // Tracks callback counts when draining - bool internalDrain; // Indicates if stop is initiated from callback or not. - ASIOBufferInfo *bufferInfos; - HANDLE condition; - - AsioHandle() - :drainCounter(0), internalDrain(false), bufferInfos(0) {} -}; - -// Function declarations (definitions at end of section) -static const char* getAsioErrorString( ASIOError result ); -static void sampleRateChanged( ASIOSampleRate sRate ); -static long asioMessages( long selector, long value, void* message, double* opt ); - -RtApiAsio :: RtApiAsio() -{ - // ASIO cannot run on a multi-threaded appartment. You can call - // CoInitialize beforehand, but it must be for appartment threading - // (in which case, CoInitilialize will return S_FALSE here). - coInitialized_ = false; - HRESULT hr = CoInitialize( NULL ); - if ( FAILED(hr) ) { - errorText_ = "RtApiAsio::ASIO requires a single-threaded appartment. Call CoInitializeEx(0,COINIT_APARTMENTTHREADED)"; - error( RtAudioError::WARNING ); - } - coInitialized_ = true; - - drivers.removeCurrentDriver(); - driverInfo.asioVersion = 2; - - // See note in DirectSound implementation about GetDesktopWindow(). - driverInfo.sysRef = GetForegroundWindow(); -} - -RtApiAsio :: ~RtApiAsio() -{ - if ( stream_.state != STREAM_CLOSED ) closeStream(); - if ( coInitialized_ ) CoUninitialize(); -} - -unsigned int RtApiAsio :: getDeviceCount( void ) -{ - return (unsigned int) drivers.asioGetNumDev(); -} - -RtAudio::DeviceInfo RtApiAsio :: getDeviceInfo( unsigned int device ) -{ - RtAudio::DeviceInfo info; - info.probed = false; - - // Get device ID - unsigned int nDevices = getDeviceCount(); - if ( nDevices == 0 ) { - errorText_ = "RtApiAsio::getDeviceInfo: no devices found!"; - error( RtAudioError::INVALID_USE ); - return info; - } - - if ( device >= nDevices ) { - errorText_ = "RtApiAsio::getDeviceInfo: device ID is invalid!"; - error( RtAudioError::INVALID_USE ); - return info; - } - - // If a stream is already open, we cannot probe other devices. Thus, use the saved results. - if ( stream_.state != STREAM_CLOSED ) { - if ( device >= devices_.size() ) { - errorText_ = "RtApiAsio::getDeviceInfo: device ID was not present before stream was opened."; - error( RtAudioError::WARNING ); - return info; - } - return devices_[ device ]; - } - - char driverName[32]; - ASIOError result = drivers.asioGetDriverName( (int) device, driverName, 32 ); - if ( result != ASE_OK ) { - errorStream_ << "RtApiAsio::getDeviceInfo: unable to get driver name (" << getAsioErrorString( result ) << ")."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - return info; - } - - info.name = driverName; - - if ( !drivers.loadDriver( driverName ) ) { - errorStream_ << "RtApiAsio::getDeviceInfo: unable to load driver (" << driverName << ")."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - return info; - } - - result = ASIOInit( &driverInfo ); - if ( result != ASE_OK ) { - errorStream_ << "RtApiAsio::getDeviceInfo: error (" << getAsioErrorString( result ) << ") initializing driver (" << driverName << ")."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - return info; - } - - // Determine the device channel information. - long inputChannels, outputChannels; - result = ASIOGetChannels( &inputChannels, &outputChannels ); - if ( result != ASE_OK ) { - drivers.removeCurrentDriver(); - errorStream_ << "RtApiAsio::getDeviceInfo: error (" << getAsioErrorString( result ) << ") getting channel count (" << driverName << ")."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - return info; - } - - info.outputChannels = outputChannels; - info.inputChannels = inputChannels; - if ( info.outputChannels > 0 && info.inputChannels > 0 ) - info.duplexChannels = (info.outputChannels > info.inputChannels) ? info.inputChannels : info.outputChannels; - - // Determine the supported sample rates. - info.sampleRates.clear(); - for ( unsigned int i=0; i info.preferredSampleRate ) ) - info.preferredSampleRate = SAMPLE_RATES[i]; - } - } - - // Determine supported data types ... just check first channel and assume rest are the same. - ASIOChannelInfo channelInfo; - channelInfo.channel = 0; - channelInfo.isInput = true; - if ( info.inputChannels <= 0 ) channelInfo.isInput = false; - result = ASIOGetChannelInfo( &channelInfo ); - if ( result != ASE_OK ) { - drivers.removeCurrentDriver(); - errorStream_ << "RtApiAsio::getDeviceInfo: error (" << getAsioErrorString( result ) << ") getting driver channel info (" << driverName << ")."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - return info; - } - - info.nativeFormats = 0; - if ( channelInfo.type == ASIOSTInt16MSB || channelInfo.type == ASIOSTInt16LSB ) - info.nativeFormats |= RTAUDIO_SINT16; - else if ( channelInfo.type == ASIOSTInt32MSB || channelInfo.type == ASIOSTInt32LSB ) - info.nativeFormats |= RTAUDIO_SINT32; - else if ( channelInfo.type == ASIOSTFloat32MSB || channelInfo.type == ASIOSTFloat32LSB ) - info.nativeFormats |= RTAUDIO_FLOAT32; - else if ( channelInfo.type == ASIOSTFloat64MSB || channelInfo.type == ASIOSTFloat64LSB ) - info.nativeFormats |= RTAUDIO_FLOAT64; - else if ( channelInfo.type == ASIOSTInt24MSB || channelInfo.type == ASIOSTInt24LSB ) - info.nativeFormats |= RTAUDIO_SINT24; - - if ( info.outputChannels > 0 ) - if ( getDefaultOutputDevice() == device ) info.isDefaultOutput = true; - if ( info.inputChannels > 0 ) - if ( getDefaultInputDevice() == device ) info.isDefaultInput = true; - - info.probed = true; - drivers.removeCurrentDriver(); - return info; -} - -static void bufferSwitch( long index, ASIOBool /*processNow*/ ) -{ - RtApiAsio *object = (RtApiAsio *) asioCallbackInfo->object; - object->callbackEvent( index ); -} - -void RtApiAsio :: saveDeviceInfo( void ) -{ - devices_.clear(); - - unsigned int nDevices = getDeviceCount(); - devices_.resize( nDevices ); - for ( unsigned int i=0; isaveDeviceInfo(); - - if ( !drivers.loadDriver( driverName ) ) { - errorStream_ << "RtApiAsio::probeDeviceOpen: unable to load driver (" << driverName << ")."; - errorText_ = errorStream_.str(); - return FAILURE; - } - - result = ASIOInit( &driverInfo ); - if ( result != ASE_OK ) { - errorStream_ << "RtApiAsio::probeDeviceOpen: error (" << getAsioErrorString( result ) << ") initializing driver (" << driverName << ")."; - errorText_ = errorStream_.str(); - return FAILURE; - } - } - - // keep them before any "goto error", they are used for error cleanup + goto device boundary checks - bool buffersAllocated = false; - AsioHandle *handle = (AsioHandle *) stream_.apiHandle; - unsigned int nChannels; - - - // Check the device channel count. - long inputChannels, outputChannels; - result = ASIOGetChannels( &inputChannels, &outputChannels ); - if ( result != ASE_OK ) { - errorStream_ << "RtApiAsio::probeDeviceOpen: error (" << getAsioErrorString( result ) << ") getting channel count (" << driverName << ")."; - errorText_ = errorStream_.str(); - goto error; - } - - if ( ( mode == OUTPUT && (channels+firstChannel) > (unsigned int) outputChannels) || - ( mode == INPUT && (channels+firstChannel) > (unsigned int) inputChannels) ) { - errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") does not support requested channel count (" << channels << ") + offset (" << firstChannel << ")."; - errorText_ = errorStream_.str(); - goto error; - } - stream_.nDeviceChannels[mode] = channels; - stream_.nUserChannels[mode] = channels; - stream_.channelOffset[mode] = firstChannel; - - // Verify the sample rate is supported. - result = ASIOCanSampleRate( (ASIOSampleRate) sampleRate ); - if ( result != ASE_OK ) { - errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") does not support requested sample rate (" << sampleRate << ")."; - errorText_ = errorStream_.str(); - goto error; - } - - // Get the current sample rate - ASIOSampleRate currentRate; - result = ASIOGetSampleRate( ¤tRate ); - if ( result != ASE_OK ) { - errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") error getting sample rate."; - errorText_ = errorStream_.str(); - goto error; - } - - // Set the sample rate only if necessary - if ( currentRate != sampleRate ) { - result = ASIOSetSampleRate( (ASIOSampleRate) sampleRate ); - if ( result != ASE_OK ) { - errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") error setting sample rate (" << sampleRate << ")."; - errorText_ = errorStream_.str(); - goto error; - } - } - - // Determine the driver data type. - ASIOChannelInfo channelInfo; - channelInfo.channel = 0; - if ( mode == OUTPUT ) channelInfo.isInput = false; - else channelInfo.isInput = true; - result = ASIOGetChannelInfo( &channelInfo ); - if ( result != ASE_OK ) { - errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") error (" << getAsioErrorString( result ) << ") getting data format."; - errorText_ = errorStream_.str(); - goto error; - } - - // Assuming WINDOWS host is always little-endian. - stream_.doByteSwap[mode] = false; - stream_.userFormat = format; - stream_.deviceFormat[mode] = 0; - if ( channelInfo.type == ASIOSTInt16MSB || channelInfo.type == ASIOSTInt16LSB ) { - stream_.deviceFormat[mode] = RTAUDIO_SINT16; - if ( channelInfo.type == ASIOSTInt16MSB ) stream_.doByteSwap[mode] = true; - } - else if ( channelInfo.type == ASIOSTInt32MSB || channelInfo.type == ASIOSTInt32LSB ) { - stream_.deviceFormat[mode] = RTAUDIO_SINT32; - if ( channelInfo.type == ASIOSTInt32MSB ) stream_.doByteSwap[mode] = true; - } - else if ( channelInfo.type == ASIOSTFloat32MSB || channelInfo.type == ASIOSTFloat32LSB ) { - stream_.deviceFormat[mode] = RTAUDIO_FLOAT32; - if ( channelInfo.type == ASIOSTFloat32MSB ) stream_.doByteSwap[mode] = true; - } - else if ( channelInfo.type == ASIOSTFloat64MSB || channelInfo.type == ASIOSTFloat64LSB ) { - stream_.deviceFormat[mode] = RTAUDIO_FLOAT64; - if ( channelInfo.type == ASIOSTFloat64MSB ) stream_.doByteSwap[mode] = true; - } - else if ( channelInfo.type == ASIOSTInt24MSB || channelInfo.type == ASIOSTInt24LSB ) { - stream_.deviceFormat[mode] = RTAUDIO_SINT24; - if ( channelInfo.type == ASIOSTInt24MSB ) stream_.doByteSwap[mode] = true; - } - - if ( stream_.deviceFormat[mode] == 0 ) { - errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") data format not supported by RtAudio."; - errorText_ = errorStream_.str(); - goto error; - } - - // Set the buffer size. For a duplex stream, this will end up - // setting the buffer size based on the input constraints, which - // should be ok. - long minSize, maxSize, preferSize, granularity; - result = ASIOGetBufferSize( &minSize, &maxSize, &preferSize, &granularity ); - if ( result != ASE_OK ) { - errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") error (" << getAsioErrorString( result ) << ") getting buffer size."; - errorText_ = errorStream_.str(); - goto error; - } - - if ( isDuplexInput ) { - // When this is the duplex input (output was opened before), then we have to use the same - // buffersize as the output, because it might use the preferred buffer size, which most - // likely wasn't passed as input to this. The buffer sizes have to be identically anyway, - // So instead of throwing an error, make them equal. The caller uses the reference - // to the "bufferSize" param as usual to set up processing buffers. - - *bufferSize = stream_.bufferSize; - - } else { - if ( *bufferSize == 0 ) *bufferSize = preferSize; - else if ( *bufferSize < (unsigned int) minSize ) *bufferSize = (unsigned int) minSize; - else if ( *bufferSize > (unsigned int) maxSize ) *bufferSize = (unsigned int) maxSize; - else if ( granularity == -1 ) { - // Make sure bufferSize is a power of two. - int log2_of_min_size = 0; - int log2_of_max_size = 0; - - for ( unsigned int i = 0; i < sizeof(long) * 8; i++ ) { - if ( minSize & ((long)1 << i) ) log2_of_min_size = i; - if ( maxSize & ((long)1 << i) ) log2_of_max_size = i; - } - - long min_delta = std::abs( (long)*bufferSize - ((long)1 << log2_of_min_size) ); - int min_delta_num = log2_of_min_size; - - for (int i = log2_of_min_size + 1; i <= log2_of_max_size; i++) { - long current_delta = std::abs( (long)*bufferSize - ((long)1 << i) ); - if (current_delta < min_delta) { - min_delta = current_delta; - min_delta_num = i; - } - } - - *bufferSize = ( (unsigned int)1 << min_delta_num ); - if ( *bufferSize < (unsigned int) minSize ) *bufferSize = (unsigned int) minSize; - else if ( *bufferSize > (unsigned int) maxSize ) *bufferSize = (unsigned int) maxSize; - } - else if ( granularity != 0 ) { - // Set to an even multiple of granularity, rounding up. - *bufferSize = (*bufferSize + granularity-1) / granularity * granularity; - } - } - - /* - // we don't use it anymore, see above! - // Just left it here for the case... - if ( isDuplexInput && stream_.bufferSize != *bufferSize ) { - errorText_ = "RtApiAsio::probeDeviceOpen: input/output buffersize discrepancy!"; - goto error; - } - */ - - stream_.bufferSize = *bufferSize; - stream_.nBuffers = 2; - - if ( options && options->flags & RTAUDIO_NONINTERLEAVED ) stream_.userInterleaved = false; - else stream_.userInterleaved = true; - - // ASIO always uses non-interleaved buffers. - stream_.deviceInterleaved[mode] = false; - - // Allocate, if necessary, our AsioHandle structure for the stream. - if ( handle == 0 ) { - try { - handle = new AsioHandle; - } - catch ( std::bad_alloc& ) { - errorText_ = "RtApiAsio::probeDeviceOpen: error allocating AsioHandle memory."; - goto error; - } - handle->bufferInfos = 0; - - // Create a manual-reset event. - handle->condition = CreateEvent( NULL, // no security - TRUE, // manual-reset - FALSE, // non-signaled initially - NULL ); // unnamed - stream_.apiHandle = (void *) handle; - } - - // Create the ASIO internal buffers. Since RtAudio sets up input - // and output separately, we'll have to dispose of previously - // created output buffers for a duplex stream. - if ( mode == INPUT && stream_.mode == OUTPUT ) { - ASIODisposeBuffers(); - if ( handle->bufferInfos ) free( handle->bufferInfos ); - } - - // Allocate, initialize, and save the bufferInfos in our stream callbackInfo structure. - unsigned int i; - nChannels = stream_.nDeviceChannels[0] + stream_.nDeviceChannels[1]; - handle->bufferInfos = (ASIOBufferInfo *) malloc( nChannels * sizeof(ASIOBufferInfo) ); - if ( handle->bufferInfos == NULL ) { - errorStream_ << "RtApiAsio::probeDeviceOpen: error allocating bufferInfo memory for driver (" << driverName << ")."; - errorText_ = errorStream_.str(); - goto error; - } - - ASIOBufferInfo *infos; - infos = handle->bufferInfos; - for ( i=0; iisInput = ASIOFalse; - infos->channelNum = i + stream_.channelOffset[0]; - infos->buffers[0] = infos->buffers[1] = 0; - } - for ( i=0; iisInput = ASIOTrue; - infos->channelNum = i + stream_.channelOffset[1]; - infos->buffers[0] = infos->buffers[1] = 0; - } - - // prepare for callbacks - stream_.sampleRate = sampleRate; - stream_.device[mode] = device; - stream_.mode = isDuplexInput ? DUPLEX : mode; - - // store this class instance before registering callbacks, that are going to use it - asioCallbackInfo = &stream_.callbackInfo; - stream_.callbackInfo.object = (void *) this; - - // Set up the ASIO callback structure and create the ASIO data buffers. - asioCallbacks.bufferSwitch = &bufferSwitch; - asioCallbacks.sampleRateDidChange = &sampleRateChanged; - asioCallbacks.asioMessage = &asioMessages; - asioCallbacks.bufferSwitchTimeInfo = NULL; - result = ASIOCreateBuffers( handle->bufferInfos, nChannels, stream_.bufferSize, &asioCallbacks ); - if ( result != ASE_OK ) { - // Standard method failed. This can happen with strict/misbehaving drivers that return valid buffer size ranges - // but only accept the preferred buffer size as parameter for ASIOCreateBuffers. eg. Creatives ASIO driver - // in that case, let's be naïve and try that instead - *bufferSize = preferSize; - stream_.bufferSize = *bufferSize; - result = ASIOCreateBuffers( handle->bufferInfos, nChannels, stream_.bufferSize, &asioCallbacks ); - } - - if ( result != ASE_OK ) { - errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") error (" << getAsioErrorString( result ) << ") creating buffers."; - errorText_ = errorStream_.str(); - goto error; - } - buffersAllocated = true; - stream_.state = STREAM_STOPPED; - - // Set flags for buffer conversion. - stream_.doConvertBuffer[mode] = false; - if ( stream_.userFormat != stream_.deviceFormat[mode] ) - stream_.doConvertBuffer[mode] = true; - if ( stream_.userInterleaved != stream_.deviceInterleaved[mode] && - stream_.nUserChannels[mode] > 1 ) - stream_.doConvertBuffer[mode] = true; - - // Allocate necessary internal buffers - unsigned long bufferBytes; - bufferBytes = stream_.nUserChannels[mode] * *bufferSize * formatBytes( stream_.userFormat ); - stream_.userBuffer[mode] = (char *) calloc( bufferBytes, 1 ); - if ( stream_.userBuffer[mode] == NULL ) { - errorText_ = "RtApiAsio::probeDeviceOpen: error allocating user buffer memory."; - goto error; - } - - if ( stream_.doConvertBuffer[mode] ) { - - bool makeBuffer = true; - bufferBytes = stream_.nDeviceChannels[mode] * formatBytes( stream_.deviceFormat[mode] ); - if ( isDuplexInput && stream_.deviceBuffer ) { - unsigned long bytesOut = stream_.nDeviceChannels[0] * formatBytes( stream_.deviceFormat[0] ); - if ( bufferBytes <= bytesOut ) makeBuffer = false; - } - - if ( makeBuffer ) { - bufferBytes *= *bufferSize; - if ( stream_.deviceBuffer ) free( stream_.deviceBuffer ); - stream_.deviceBuffer = (char *) calloc( bufferBytes, 1 ); - if ( stream_.deviceBuffer == NULL ) { - errorText_ = "RtApiAsio::probeDeviceOpen: error allocating device buffer memory."; - goto error; - } - } - } - - // Determine device latencies - long inputLatency, outputLatency; - result = ASIOGetLatencies( &inputLatency, &outputLatency ); - if ( result != ASE_OK ) { - errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") error (" << getAsioErrorString( result ) << ") getting latency."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING); // warn but don't fail - } - else { - stream_.latency[0] = outputLatency; - stream_.latency[1] = inputLatency; - } - - // Setup the buffer conversion information structure. We don't use - // buffers to do channel offsets, so we override that parameter - // here. - if ( stream_.doConvertBuffer[mode] ) setConvertInfo( mode, 0 ); - - return SUCCESS; - - error: - if ( !isDuplexInput ) { - // the cleanup for error in the duplex input, is done by RtApi::openStream - // So we clean up for single channel only - - if ( buffersAllocated ) - ASIODisposeBuffers(); - - drivers.removeCurrentDriver(); - - if ( handle ) { - CloseHandle( handle->condition ); - if ( handle->bufferInfos ) - free( handle->bufferInfos ); - - delete handle; - stream_.apiHandle = 0; - } - - - if ( stream_.userBuffer[mode] ) { - free( stream_.userBuffer[mode] ); - stream_.userBuffer[mode] = 0; - } - - if ( stream_.deviceBuffer ) { - free( stream_.deviceBuffer ); - stream_.deviceBuffer = 0; - } - } - - return FAILURE; -}//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -void RtApiAsio :: closeStream() -{ - if ( stream_.state == STREAM_CLOSED ) { - errorText_ = "RtApiAsio::closeStream(): no open stream to close!"; - error( RtAudioError::WARNING ); - return; - } - - if ( stream_.state == STREAM_RUNNING ) { - stream_.state = STREAM_STOPPED; - ASIOStop(); - } - ASIODisposeBuffers(); - drivers.removeCurrentDriver(); - - AsioHandle *handle = (AsioHandle *) stream_.apiHandle; - if ( handle ) { - CloseHandle( handle->condition ); - if ( handle->bufferInfos ) - free( handle->bufferInfos ); - delete handle; - stream_.apiHandle = 0; - } - - for ( int i=0; i<2; i++ ) { - if ( stream_.userBuffer[i] ) { - free( stream_.userBuffer[i] ); - stream_.userBuffer[i] = 0; - } - } - - if ( stream_.deviceBuffer ) { - free( stream_.deviceBuffer ); - stream_.deviceBuffer = 0; - } - - stream_.mode = UNINITIALIZED; - stream_.state = STREAM_CLOSED; -} - -bool stopThreadCalled = false; - -void RtApiAsio :: startStream() -{ - verifyStream(); - if ( stream_.state == STREAM_RUNNING ) { - errorText_ = "RtApiAsio::startStream(): the stream is already running!"; - error( RtAudioError::WARNING ); - return; - } - - AsioHandle *handle = (AsioHandle *) stream_.apiHandle; - ASIOError result = ASIOStart(); - if ( result != ASE_OK ) { - errorStream_ << "RtApiAsio::startStream: error (" << getAsioErrorString( result ) << ") starting device."; - errorText_ = errorStream_.str(); - goto unlock; - } - - handle->drainCounter = 0; - handle->internalDrain = false; - ResetEvent( handle->condition ); - stream_.state = STREAM_RUNNING; - asioXRun = false; - - unlock: - stopThreadCalled = false; - - if ( result == ASE_OK ) return; - error( RtAudioError::SYSTEM_ERROR ); -} - -void RtApiAsio :: stopStream() -{ - verifyStream(); - if ( stream_.state == STREAM_STOPPED ) { - errorText_ = "RtApiAsio::stopStream(): the stream is already stopped!"; - error( RtAudioError::WARNING ); - return; - } - - AsioHandle *handle = (AsioHandle *) stream_.apiHandle; - if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { - if ( handle->drainCounter == 0 ) { - handle->drainCounter = 2; - WaitForSingleObject( handle->condition, INFINITE ); // block until signaled - } - } - - stream_.state = STREAM_STOPPED; - - ASIOError result = ASIOStop(); - if ( result != ASE_OK ) { - errorStream_ << "RtApiAsio::stopStream: error (" << getAsioErrorString( result ) << ") stopping device."; - errorText_ = errorStream_.str(); - } - - if ( result == ASE_OK ) return; - error( RtAudioError::SYSTEM_ERROR ); -} - -void RtApiAsio :: abortStream() -{ - verifyStream(); - if ( stream_.state == STREAM_STOPPED ) { - errorText_ = "RtApiAsio::abortStream(): the stream is already stopped!"; - error( RtAudioError::WARNING ); - return; - } - - // The following lines were commented-out because some behavior was - // noted where the device buffers need to be zeroed to avoid - // continuing sound, even when the device buffers are completely - // disposed. So now, calling abort is the same as calling stop. - // AsioHandle *handle = (AsioHandle *) stream_.apiHandle; - // handle->drainCounter = 2; - stopStream(); -} - -// This function will be called by a spawned thread when the user -// callback function signals that the stream should be stopped or -// aborted. It is necessary to handle it this way because the -// callbackEvent() function must return before the ASIOStop() -// function will return. -static unsigned __stdcall asioStopStream( void *ptr ) -{ - CallbackInfo *info = (CallbackInfo *) ptr; - RtApiAsio *object = (RtApiAsio *) info->object; - - object->stopStream(); - _endthreadex( 0 ); - return 0; -} - -bool RtApiAsio :: callbackEvent( long bufferIndex ) -{ - if ( stream_.state == STREAM_STOPPED || stream_.state == STREAM_STOPPING ) return SUCCESS; - if ( stream_.state == STREAM_CLOSED ) { - errorText_ = "RtApiAsio::callbackEvent(): the stream is closed ... this shouldn't happen!"; - error( RtAudioError::WARNING ); - return FAILURE; - } - - CallbackInfo *info = (CallbackInfo *) &stream_.callbackInfo; - AsioHandle *handle = (AsioHandle *) stream_.apiHandle; - - // Check if we were draining the stream and signal if finished. - if ( handle->drainCounter > 3 ) { - - stream_.state = STREAM_STOPPING; - if ( handle->internalDrain == false ) - SetEvent( handle->condition ); - else { // spawn a thread to stop the stream - unsigned threadId; - stream_.callbackInfo.thread = _beginthreadex( NULL, 0, &asioStopStream, - &stream_.callbackInfo, 0, &threadId ); - } - return SUCCESS; - } - - // Invoke user callback to get fresh output data UNLESS we are - // draining stream. - if ( handle->drainCounter == 0 ) { - RtAudioCallback callback = (RtAudioCallback) info->callback; - double streamTime = getStreamTime(); - RtAudioStreamStatus status = 0; - if ( stream_.mode != INPUT && asioXRun == true ) { - status |= RTAUDIO_OUTPUT_UNDERFLOW; - asioXRun = false; - } - if ( stream_.mode != OUTPUT && asioXRun == true ) { - status |= RTAUDIO_INPUT_OVERFLOW; - asioXRun = false; - } - int cbReturnValue = callback( stream_.userBuffer[0], stream_.userBuffer[1], - stream_.bufferSize, streamTime, status, info->userData ); - if ( cbReturnValue == 2 ) { - stream_.state = STREAM_STOPPING; - handle->drainCounter = 2; - unsigned threadId; - stream_.callbackInfo.thread = _beginthreadex( NULL, 0, &asioStopStream, - &stream_.callbackInfo, 0, &threadId ); - return SUCCESS; - } - else if ( cbReturnValue == 1 ) { - handle->drainCounter = 1; - handle->internalDrain = true; - } - } - - unsigned int nChannels, bufferBytes, i, j; - nChannels = stream_.nDeviceChannels[0] + stream_.nDeviceChannels[1]; - if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { - - bufferBytes = stream_.bufferSize * formatBytes( stream_.deviceFormat[0] ); - - if ( handle->drainCounter > 1 ) { // write zeros to the output stream - - for ( i=0, j=0; ibufferInfos[i].isInput != ASIOTrue ) - memset( handle->bufferInfos[i].buffers[bufferIndex], 0, bufferBytes ); - } - - } - else if ( stream_.doConvertBuffer[0] ) { - - convertBuffer( stream_.deviceBuffer, stream_.userBuffer[0], stream_.convertInfo[0] ); - if ( stream_.doByteSwap[0] ) - byteSwapBuffer( stream_.deviceBuffer, - stream_.bufferSize * stream_.nDeviceChannels[0], - stream_.deviceFormat[0] ); - - for ( i=0, j=0; ibufferInfos[i].isInput != ASIOTrue ) - memcpy( handle->bufferInfos[i].buffers[bufferIndex], - &stream_.deviceBuffer[j++*bufferBytes], bufferBytes ); - } - - } - else { - - if ( stream_.doByteSwap[0] ) - byteSwapBuffer( stream_.userBuffer[0], - stream_.bufferSize * stream_.nUserChannels[0], - stream_.userFormat ); - - for ( i=0, j=0; ibufferInfos[i].isInput != ASIOTrue ) - memcpy( handle->bufferInfos[i].buffers[bufferIndex], - &stream_.userBuffer[0][bufferBytes*j++], bufferBytes ); - } - - } - } - - // Don't bother draining input - if ( handle->drainCounter ) { - handle->drainCounter++; - goto unlock; - } - - if ( stream_.mode == INPUT || stream_.mode == DUPLEX ) { - - bufferBytes = stream_.bufferSize * formatBytes(stream_.deviceFormat[1]); - - if (stream_.doConvertBuffer[1]) { - - // Always interleave ASIO input data. - for ( i=0, j=0; ibufferInfos[i].isInput == ASIOTrue ) - memcpy( &stream_.deviceBuffer[j++*bufferBytes], - handle->bufferInfos[i].buffers[bufferIndex], - bufferBytes ); - } - - if ( stream_.doByteSwap[1] ) - byteSwapBuffer( stream_.deviceBuffer, - stream_.bufferSize * stream_.nDeviceChannels[1], - stream_.deviceFormat[1] ); - convertBuffer( stream_.userBuffer[1], stream_.deviceBuffer, stream_.convertInfo[1] ); - - } - else { - for ( i=0, j=0; ibufferInfos[i].isInput == ASIOTrue ) { - memcpy( &stream_.userBuffer[1][bufferBytes*j++], - handle->bufferInfos[i].buffers[bufferIndex], - bufferBytes ); - } - } - - if ( stream_.doByteSwap[1] ) - byteSwapBuffer( stream_.userBuffer[1], - stream_.bufferSize * stream_.nUserChannels[1], - stream_.userFormat ); - } - } - - unlock: - // The following call was suggested by Malte Clasen. While the API - // documentation indicates it should not be required, some device - // drivers apparently do not function correctly without it. - ASIOOutputReady(); - - RtApi::tickStreamTime(); - return SUCCESS; -} - -static void sampleRateChanged( ASIOSampleRate sRate ) -{ - // The ASIO documentation says that this usually only happens during - // external sync. Audio processing is not stopped by the driver, - // actual sample rate might not have even changed, maybe only the - // sample rate status of an AES/EBU or S/PDIF digital input at the - // audio device. - - RtApi *object = (RtApi *) asioCallbackInfo->object; - try { - object->stopStream(); - } - catch ( RtAudioError &exception ) { - std::cerr << "\nRtApiAsio: sampleRateChanged() error (" << exception.getMessage() << ")!\n" << std::endl; - return; - } - - std::cerr << "\nRtApiAsio: driver reports sample rate changed to " << sRate << " ... stream stopped!!!\n" << std::endl; -} - -static long asioMessages( long selector, long value, void* /*message*/, double* /*opt*/ ) -{ - long ret = 0; - - switch( selector ) { - case kAsioSelectorSupported: - if ( value == kAsioResetRequest - || value == kAsioEngineVersion - || value == kAsioResyncRequest - || value == kAsioLatenciesChanged - // The following three were added for ASIO 2.0, you don't - // necessarily have to support them. - || value == kAsioSupportsTimeInfo - || value == kAsioSupportsTimeCode - || value == kAsioSupportsInputMonitor) - ret = 1L; - break; - case kAsioResetRequest: - // Defer the task and perform the reset of the driver during the - // next "safe" situation. You cannot reset the driver right now, - // as this code is called from the driver. Reset the driver is - // done by completely destruct is. I.e. ASIOStop(), - // ASIODisposeBuffers(), Destruction Afterwards you initialize the - // driver again. - std::cerr << "\nRtApiAsio: driver reset requested!!!" << std::endl; - ret = 1L; - break; - case kAsioResyncRequest: - // This informs the application that the driver encountered some - // non-fatal data loss. It is used for synchronization purposes - // of different media. Added mainly to work around the Win16Mutex - // problems in Windows 95/98 with the Windows Multimedia system, - // which could lose data because the Mutex was held too long by - // another thread. However a driver can issue it in other - // situations, too. - // std::cerr << "\nRtApiAsio: driver resync requested!!!" << std::endl; - asioXRun = true; - ret = 1L; - break; - case kAsioLatenciesChanged: - // This will inform the host application that the drivers were - // latencies changed. Beware, it this does not mean that the - // buffer sizes have changed! You might need to update internal - // delay data. - std::cerr << "\nRtApiAsio: driver latency may have changed!!!" << std::endl; - ret = 1L; - break; - case kAsioEngineVersion: - // Return the supported ASIO version of the host application. If - // a host application does not implement this selector, ASIO 1.0 - // is assumed by the driver. - ret = 2L; - break; - case kAsioSupportsTimeInfo: - // Informs the driver whether the - // asioCallbacks.bufferSwitchTimeInfo() callback is supported. - // For compatibility with ASIO 1.0 drivers the host application - // should always support the "old" bufferSwitch method, too. - ret = 0; - break; - case kAsioSupportsTimeCode: - // Informs the driver whether application is interested in time - // code info. If an application does not need to know about time - // code, the driver has less work to do. - ret = 0; - break; - } - return ret; -} - -static const char* getAsioErrorString( ASIOError result ) -{ - struct Messages - { - ASIOError value; - const char*message; - }; - - static const Messages m[] = - { - { ASE_NotPresent, "Hardware input or output is not present or available." }, - { ASE_HWMalfunction, "Hardware is malfunctioning." }, - { ASE_InvalidParameter, "Invalid input parameter." }, - { ASE_InvalidMode, "Invalid mode." }, - { ASE_SPNotAdvancing, "Sample position not advancing." }, - { ASE_NoClock, "Sample clock or rate cannot be determined or is not present." }, - { ASE_NoMemory, "Not enough memory to complete the request." } - }; - - for ( unsigned int i = 0; i < sizeof(m)/sizeof(m[0]); ++i ) - if ( m[i].value == result ) return m[i].message; - - return "Unknown error."; -} - -//******************** End of __WINDOWS_ASIO__ *********************// -#endif - - -#if defined(__WINDOWS_WASAPI__) // Windows WASAPI API - -// Authored by Marcus Tomlinson , April 2014 -// - Introduces support for the Windows WASAPI API -// - Aims to deliver bit streams to and from hardware at the lowest possible latency, via the absolute minimum buffer sizes required -// - Provides flexible stream configuration to an otherwise strict and inflexible WASAPI interface -// - Includes automatic internal conversion of sample rate and buffer size between hardware and the user - -#ifndef INITGUID - #define INITGUID -#endif -#include -#include -#include -#include - -//============================================================================= - -#define SAFE_RELEASE( objectPtr )\ -if ( objectPtr )\ -{\ - objectPtr->Release();\ - objectPtr = NULL;\ -} - -typedef HANDLE ( __stdcall *TAvSetMmThreadCharacteristicsPtr )( LPCWSTR TaskName, LPDWORD TaskIndex ); - -//----------------------------------------------------------------------------- - -// WASAPI dictates stream sample rate, format, channel count, and in some cases, buffer size. -// Therefore we must perform all necessary conversions to user buffers in order to satisfy these -// requirements. WasapiBuffer ring buffers are used between HwIn->UserIn and UserOut->HwOut to -// provide intermediate storage for read / write synchronization. -class WasapiBuffer -{ -public: - WasapiBuffer() - : buffer_( NULL ), - bufferSize_( 0 ), - inIndex_( 0 ), - outIndex_( 0 ) {} - - ~WasapiBuffer() { - free( buffer_ ); - } - - // sets the length of the internal ring buffer - void setBufferSize( unsigned int bufferSize, unsigned int formatBytes ) { - free( buffer_ ); - - buffer_ = ( char* ) calloc( bufferSize, formatBytes ); - - bufferSize_ = bufferSize; - inIndex_ = 0; - outIndex_ = 0; - } - - // attempt to push a buffer into the ring buffer at the current "in" index - bool pushBuffer( char* buffer, unsigned int bufferSize, RtAudioFormat format ) - { - if ( !buffer || // incoming buffer is NULL - bufferSize == 0 || // incoming buffer has no data - bufferSize > bufferSize_ ) // incoming buffer too large - { - return false; - } - - unsigned int relOutIndex = outIndex_; - unsigned int inIndexEnd = inIndex_ + bufferSize; - if ( relOutIndex < inIndex_ && inIndexEnd >= bufferSize_ ) { - relOutIndex += bufferSize_; - } - - // "in" index can end on the "out" index but cannot begin at it - if ( inIndex_ <= relOutIndex && inIndexEnd > relOutIndex ) { - return false; // not enough space between "in" index and "out" index - } - - // copy buffer from external to internal - int fromZeroSize = inIndex_ + bufferSize - bufferSize_; - fromZeroSize = fromZeroSize < 0 ? 0 : fromZeroSize; - int fromInSize = bufferSize - fromZeroSize; - - switch( format ) - { - case RTAUDIO_SINT8: - memcpy( &( ( char* ) buffer_ )[inIndex_], buffer, fromInSize * sizeof( char ) ); - memcpy( buffer_, &( ( char* ) buffer )[fromInSize], fromZeroSize * sizeof( char ) ); - break; - case RTAUDIO_SINT16: - memcpy( &( ( short* ) buffer_ )[inIndex_], buffer, fromInSize * sizeof( short ) ); - memcpy( buffer_, &( ( short* ) buffer )[fromInSize], fromZeroSize * sizeof( short ) ); - break; - case RTAUDIO_SINT24: - memcpy( &( ( S24* ) buffer_ )[inIndex_], buffer, fromInSize * sizeof( S24 ) ); - memcpy( buffer_, &( ( S24* ) buffer )[fromInSize], fromZeroSize * sizeof( S24 ) ); - break; - case RTAUDIO_SINT32: - memcpy( &( ( int* ) buffer_ )[inIndex_], buffer, fromInSize * sizeof( int ) ); - memcpy( buffer_, &( ( int* ) buffer )[fromInSize], fromZeroSize * sizeof( int ) ); - break; - case RTAUDIO_FLOAT32: - memcpy( &( ( float* ) buffer_ )[inIndex_], buffer, fromInSize * sizeof( float ) ); - memcpy( buffer_, &( ( float* ) buffer )[fromInSize], fromZeroSize * sizeof( float ) ); - break; - case RTAUDIO_FLOAT64: - memcpy( &( ( double* ) buffer_ )[inIndex_], buffer, fromInSize * sizeof( double ) ); - memcpy( buffer_, &( ( double* ) buffer )[fromInSize], fromZeroSize * sizeof( double ) ); - break; - } - - // update "in" index - inIndex_ += bufferSize; - inIndex_ %= bufferSize_; - - return true; - } - - // attempt to pull a buffer from the ring buffer from the current "out" index - bool pullBuffer( char* buffer, unsigned int bufferSize, RtAudioFormat format ) - { - if ( !buffer || // incoming buffer is NULL - bufferSize == 0 || // incoming buffer has no data - bufferSize > bufferSize_ ) // incoming buffer too large - { - return false; - } - - unsigned int relInIndex = inIndex_; - unsigned int outIndexEnd = outIndex_ + bufferSize; - if ( relInIndex < outIndex_ && outIndexEnd >= bufferSize_ ) { - relInIndex += bufferSize_; - } - - // "out" index can begin at and end on the "in" index - if ( outIndex_ < relInIndex && outIndexEnd > relInIndex ) { - return false; // not enough space between "out" index and "in" index - } - - // copy buffer from internal to external - int fromZeroSize = outIndex_ + bufferSize - bufferSize_; - fromZeroSize = fromZeroSize < 0 ? 0 : fromZeroSize; - int fromOutSize = bufferSize - fromZeroSize; - - switch( format ) - { - case RTAUDIO_SINT8: - memcpy( buffer, &( ( char* ) buffer_ )[outIndex_], fromOutSize * sizeof( char ) ); - memcpy( &( ( char* ) buffer )[fromOutSize], buffer_, fromZeroSize * sizeof( char ) ); - break; - case RTAUDIO_SINT16: - memcpy( buffer, &( ( short* ) buffer_ )[outIndex_], fromOutSize * sizeof( short ) ); - memcpy( &( ( short* ) buffer )[fromOutSize], buffer_, fromZeroSize * sizeof( short ) ); - break; - case RTAUDIO_SINT24: - memcpy( buffer, &( ( S24* ) buffer_ )[outIndex_], fromOutSize * sizeof( S24 ) ); - memcpy( &( ( S24* ) buffer )[fromOutSize], buffer_, fromZeroSize * sizeof( S24 ) ); - break; - case RTAUDIO_SINT32: - memcpy( buffer, &( ( int* ) buffer_ )[outIndex_], fromOutSize * sizeof( int ) ); - memcpy( &( ( int* ) buffer )[fromOutSize], buffer_, fromZeroSize * sizeof( int ) ); - break; - case RTAUDIO_FLOAT32: - memcpy( buffer, &( ( float* ) buffer_ )[outIndex_], fromOutSize * sizeof( float ) ); - memcpy( &( ( float* ) buffer )[fromOutSize], buffer_, fromZeroSize * sizeof( float ) ); - break; - case RTAUDIO_FLOAT64: - memcpy( buffer, &( ( double* ) buffer_ )[outIndex_], fromOutSize * sizeof( double ) ); - memcpy( &( ( double* ) buffer )[fromOutSize], buffer_, fromZeroSize * sizeof( double ) ); - break; - } - - // update "out" index - outIndex_ += bufferSize; - outIndex_ %= bufferSize_; - - return true; - } - -private: - char* buffer_; - unsigned int bufferSize_; - unsigned int inIndex_; - unsigned int outIndex_; -}; - -//----------------------------------------------------------------------------- - -// In order to satisfy WASAPI's buffer requirements, we need a means of converting sample rate -// between HW and the user. The convertBufferWasapi function is used to perform this conversion -// between HwIn->UserIn and UserOut->HwOut during the stream callback loop. -// This sample rate converter favors speed over quality, and works best with conversions between -// one rate and its multiple. -void convertBufferWasapi( char* outBuffer, - const char* inBuffer, - const unsigned int& channelCount, - const unsigned int& inSampleRate, - const unsigned int& outSampleRate, - const unsigned int& inSampleCount, - unsigned int& outSampleCount, - const RtAudioFormat& format ) -{ - // calculate the new outSampleCount and relative sampleStep - float sampleRatio = ( float ) outSampleRate / inSampleRate; - float sampleStep = 1.0f / sampleRatio; - float inSampleFraction = 0.0f; - - outSampleCount = ( unsigned int ) roundf( inSampleCount * sampleRatio ); - - // frame-by-frame, copy each relative input sample into it's corresponding output sample - for ( unsigned int outSample = 0; outSample < outSampleCount; outSample++ ) - { - unsigned int inSample = ( unsigned int ) inSampleFraction; - - switch ( format ) - { - case RTAUDIO_SINT8: - memcpy( &( ( char* ) outBuffer )[ outSample * channelCount ], &( ( char* ) inBuffer )[ inSample * channelCount ], channelCount * sizeof( char ) ); - break; - case RTAUDIO_SINT16: - memcpy( &( ( short* ) outBuffer )[ outSample * channelCount ], &( ( short* ) inBuffer )[ inSample * channelCount ], channelCount * sizeof( short ) ); - break; - case RTAUDIO_SINT24: - memcpy( &( ( S24* ) outBuffer )[ outSample * channelCount ], &( ( S24* ) inBuffer )[ inSample * channelCount ], channelCount * sizeof( S24 ) ); - break; - case RTAUDIO_SINT32: - memcpy( &( ( int* ) outBuffer )[ outSample * channelCount ], &( ( int* ) inBuffer )[ inSample * channelCount ], channelCount * sizeof( int ) ); - break; - case RTAUDIO_FLOAT32: - memcpy( &( ( float* ) outBuffer )[ outSample * channelCount ], &( ( float* ) inBuffer )[ inSample * channelCount ], channelCount * sizeof( float ) ); - break; - case RTAUDIO_FLOAT64: - memcpy( &( ( double* ) outBuffer )[ outSample * channelCount ], &( ( double* ) inBuffer )[ inSample * channelCount ], channelCount * sizeof( double ) ); - break; - } - - // jump to next in sample - inSampleFraction += sampleStep; - } -} - -//----------------------------------------------------------------------------- - -// A structure to hold various information related to the WASAPI implementation. -struct WasapiHandle -{ - IAudioClient* captureAudioClient; - IAudioClient* renderAudioClient; - IAudioCaptureClient* captureClient; - IAudioRenderClient* renderClient; - HANDLE captureEvent; - HANDLE renderEvent; - - WasapiHandle() - : captureAudioClient( NULL ), - renderAudioClient( NULL ), - captureClient( NULL ), - renderClient( NULL ), - captureEvent( NULL ), - renderEvent( NULL ) {} -}; - -//============================================================================= - -RtApiWasapi::RtApiWasapi() - : coInitialized_( false ), deviceEnumerator_( NULL ) -{ - // WASAPI can run either apartment or multi-threaded - HRESULT hr = CoInitialize( NULL ); - if ( !FAILED( hr ) ) - coInitialized_ = true; - - // Instantiate device enumerator - hr = CoCreateInstance( __uuidof( MMDeviceEnumerator ), NULL, - CLSCTX_ALL, __uuidof( IMMDeviceEnumerator ), - ( void** ) &deviceEnumerator_ ); - - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::RtApiWasapi: Unable to instantiate device enumerator"; - error( RtAudioError::DRIVER_ERROR ); - } -} - -//----------------------------------------------------------------------------- - -RtApiWasapi::~RtApiWasapi() -{ - if ( stream_.state != STREAM_CLOSED ) - closeStream(); - - SAFE_RELEASE( deviceEnumerator_ ); - - // If this object previously called CoInitialize() - if ( coInitialized_ ) - CoUninitialize(); -} - -//============================================================================= - -unsigned int RtApiWasapi::getDeviceCount( void ) -{ - unsigned int captureDeviceCount = 0; - unsigned int renderDeviceCount = 0; - - IMMDeviceCollection* captureDevices = NULL; - IMMDeviceCollection* renderDevices = NULL; - - // Count capture devices - errorText_.clear(); - HRESULT hr = deviceEnumerator_->EnumAudioEndpoints( eCapture, DEVICE_STATE_ACTIVE, &captureDevices ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::getDeviceCount: Unable to retrieve capture device collection."; - goto Exit; - } - - hr = captureDevices->GetCount( &captureDeviceCount ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::getDeviceCount: Unable to retrieve capture device count."; - goto Exit; - } - - // Count render devices - hr = deviceEnumerator_->EnumAudioEndpoints( eRender, DEVICE_STATE_ACTIVE, &renderDevices ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::getDeviceCount: Unable to retrieve render device collection."; - goto Exit; - } - - hr = renderDevices->GetCount( &renderDeviceCount ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::getDeviceCount: Unable to retrieve render device count."; - goto Exit; - } - -Exit: - // release all references - SAFE_RELEASE( captureDevices ); - SAFE_RELEASE( renderDevices ); - - if ( errorText_.empty() ) - return captureDeviceCount + renderDeviceCount; - - error( RtAudioError::DRIVER_ERROR ); - return 0; -} - -//----------------------------------------------------------------------------- - -RtAudio::DeviceInfo RtApiWasapi::getDeviceInfo( unsigned int device ) -{ - RtAudio::DeviceInfo info; - unsigned int captureDeviceCount = 0; - unsigned int renderDeviceCount = 0; - std::string defaultDeviceName; - bool isCaptureDevice = false; - - PROPVARIANT deviceNameProp; - PROPVARIANT defaultDeviceNameProp; - - IMMDeviceCollection* captureDevices = NULL; - IMMDeviceCollection* renderDevices = NULL; - IMMDevice* devicePtr = NULL; - IMMDevice* defaultDevicePtr = NULL; - IAudioClient* audioClient = NULL; - IPropertyStore* devicePropStore = NULL; - IPropertyStore* defaultDevicePropStore = NULL; - - WAVEFORMATEX* deviceFormat = NULL; - WAVEFORMATEX* closestMatchFormat = NULL; - - // probed - info.probed = false; - - // Count capture devices - errorText_.clear(); - RtAudioError::Type errorType = RtAudioError::DRIVER_ERROR; - HRESULT hr = deviceEnumerator_->EnumAudioEndpoints( eCapture, DEVICE_STATE_ACTIVE, &captureDevices ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve capture device collection."; - goto Exit; - } - - hr = captureDevices->GetCount( &captureDeviceCount ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve capture device count."; - goto Exit; - } - - // Count render devices - hr = deviceEnumerator_->EnumAudioEndpoints( eRender, DEVICE_STATE_ACTIVE, &renderDevices ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve render device collection."; - goto Exit; - } - - hr = renderDevices->GetCount( &renderDeviceCount ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve render device count."; - goto Exit; - } - - // validate device index - if ( device >= captureDeviceCount + renderDeviceCount ) { - errorText_ = "RtApiWasapi::getDeviceInfo: Invalid device index."; - errorType = RtAudioError::INVALID_USE; - goto Exit; - } - - // determine whether index falls within capture or render devices - if ( device >= renderDeviceCount ) { - hr = captureDevices->Item( device - renderDeviceCount, &devicePtr ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve capture device handle."; - goto Exit; - } - isCaptureDevice = true; - } - else { - hr = renderDevices->Item( device, &devicePtr ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve render device handle."; - goto Exit; - } - isCaptureDevice = false; - } - - // get default device name - if ( isCaptureDevice ) { - hr = deviceEnumerator_->GetDefaultAudioEndpoint( eCapture, eConsole, &defaultDevicePtr ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve default capture device handle."; - goto Exit; - } - } - else { - hr = deviceEnumerator_->GetDefaultAudioEndpoint( eRender, eConsole, &defaultDevicePtr ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve default render device handle."; - goto Exit; - } - } - - hr = defaultDevicePtr->OpenPropertyStore( STGM_READ, &defaultDevicePropStore ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::getDeviceInfo: Unable to open default device property store."; - goto Exit; - } - PropVariantInit( &defaultDeviceNameProp ); - - hr = defaultDevicePropStore->GetValue( PKEY_Device_FriendlyName, &defaultDeviceNameProp ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve default device property: PKEY_Device_FriendlyName."; - goto Exit; - } - - defaultDeviceName = convertCharPointerToStdString(defaultDeviceNameProp.pwszVal); - - // name - hr = devicePtr->OpenPropertyStore( STGM_READ, &devicePropStore ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::getDeviceInfo: Unable to open device property store."; - goto Exit; - } - - PropVariantInit( &deviceNameProp ); - - hr = devicePropStore->GetValue( PKEY_Device_FriendlyName, &deviceNameProp ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve device property: PKEY_Device_FriendlyName."; - goto Exit; - } - - info.name =convertCharPointerToStdString(deviceNameProp.pwszVal); - - // is default - if ( isCaptureDevice ) { - info.isDefaultInput = info.name == defaultDeviceName; - info.isDefaultOutput = false; - } - else { - info.isDefaultInput = false; - info.isDefaultOutput = info.name == defaultDeviceName; - } - - // channel count - hr = devicePtr->Activate( __uuidof( IAudioClient ), CLSCTX_ALL, NULL, ( void** ) &audioClient ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve device audio client."; - goto Exit; - } - - hr = audioClient->GetMixFormat( &deviceFormat ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve device mix format."; - goto Exit; - } - - if ( isCaptureDevice ) { - info.inputChannels = deviceFormat->nChannels; - info.outputChannels = 0; - info.duplexChannels = 0; - } - else { - info.inputChannels = 0; - info.outputChannels = deviceFormat->nChannels; - info.duplexChannels = 0; - } - - // sample rates - info.sampleRates.clear(); - - // allow support for all sample rates as we have a built-in sample rate converter - for ( unsigned int i = 0; i < MAX_SAMPLE_RATES; i++ ) { - info.sampleRates.push_back( SAMPLE_RATES[i] ); - } - info.preferredSampleRate = deviceFormat->nSamplesPerSec; - - // native format - info.nativeFormats = 0; - - if ( deviceFormat->wFormatTag == WAVE_FORMAT_IEEE_FLOAT || - ( deviceFormat->wFormatTag == WAVE_FORMAT_EXTENSIBLE && - ( ( WAVEFORMATEXTENSIBLE* ) deviceFormat )->SubFormat == KSDATAFORMAT_SUBTYPE_IEEE_FLOAT ) ) - { - if ( deviceFormat->wBitsPerSample == 32 ) { - info.nativeFormats |= RTAUDIO_FLOAT32; - } - else if ( deviceFormat->wBitsPerSample == 64 ) { - info.nativeFormats |= RTAUDIO_FLOAT64; - } - } - else if ( deviceFormat->wFormatTag == WAVE_FORMAT_PCM || - ( deviceFormat->wFormatTag == WAVE_FORMAT_EXTENSIBLE && - ( ( WAVEFORMATEXTENSIBLE* ) deviceFormat )->SubFormat == KSDATAFORMAT_SUBTYPE_PCM ) ) - { - if ( deviceFormat->wBitsPerSample == 8 ) { - info.nativeFormats |= RTAUDIO_SINT8; - } - else if ( deviceFormat->wBitsPerSample == 16 ) { - info.nativeFormats |= RTAUDIO_SINT16; - } - else if ( deviceFormat->wBitsPerSample == 24 ) { - info.nativeFormats |= RTAUDIO_SINT24; - } - else if ( deviceFormat->wBitsPerSample == 32 ) { - info.nativeFormats |= RTAUDIO_SINT32; - } - } - - // probed - info.probed = true; - -Exit: - // release all references - PropVariantClear( &deviceNameProp ); - PropVariantClear( &defaultDeviceNameProp ); - - SAFE_RELEASE( captureDevices ); - SAFE_RELEASE( renderDevices ); - SAFE_RELEASE( devicePtr ); - SAFE_RELEASE( defaultDevicePtr ); - SAFE_RELEASE( audioClient ); - SAFE_RELEASE( devicePropStore ); - SAFE_RELEASE( defaultDevicePropStore ); - - CoTaskMemFree( deviceFormat ); - CoTaskMemFree( closestMatchFormat ); - - if ( !errorText_.empty() ) - error( errorType ); - return info; -} - -//----------------------------------------------------------------------------- - -unsigned int RtApiWasapi::getDefaultOutputDevice( void ) -{ - for ( unsigned int i = 0; i < getDeviceCount(); i++ ) { - if ( getDeviceInfo( i ).isDefaultOutput ) { - return i; - } - } - - return 0; -} - -//----------------------------------------------------------------------------- - -unsigned int RtApiWasapi::getDefaultInputDevice( void ) -{ - for ( unsigned int i = 0; i < getDeviceCount(); i++ ) { - if ( getDeviceInfo( i ).isDefaultInput ) { - return i; - } - } - - return 0; -} - -//----------------------------------------------------------------------------- - -void RtApiWasapi::closeStream( void ) -{ - if ( stream_.state == STREAM_CLOSED ) { - errorText_ = "RtApiWasapi::closeStream: No open stream to close."; - error( RtAudioError::WARNING ); - return; - } - - if ( stream_.state != STREAM_STOPPED ) - stopStream(); - - // clean up stream memory - SAFE_RELEASE( ( ( WasapiHandle* ) stream_.apiHandle )->captureAudioClient ) - SAFE_RELEASE( ( ( WasapiHandle* ) stream_.apiHandle )->renderAudioClient ) - - SAFE_RELEASE( ( ( WasapiHandle* ) stream_.apiHandle )->captureClient ) - SAFE_RELEASE( ( ( WasapiHandle* ) stream_.apiHandle )->renderClient ) - - if ( ( ( WasapiHandle* ) stream_.apiHandle )->captureEvent ) - CloseHandle( ( ( WasapiHandle* ) stream_.apiHandle )->captureEvent ); - - if ( ( ( WasapiHandle* ) stream_.apiHandle )->renderEvent ) - CloseHandle( ( ( WasapiHandle* ) stream_.apiHandle )->renderEvent ); - - delete ( WasapiHandle* ) stream_.apiHandle; - stream_.apiHandle = NULL; - - for ( int i = 0; i < 2; i++ ) { - if ( stream_.userBuffer[i] ) { - free( stream_.userBuffer[i] ); - stream_.userBuffer[i] = 0; - } - } - - if ( stream_.deviceBuffer ) { - free( stream_.deviceBuffer ); - stream_.deviceBuffer = 0; - } - - // update stream state - stream_.state = STREAM_CLOSED; -} - -//----------------------------------------------------------------------------- - -void RtApiWasapi::startStream( void ) -{ - verifyStream(); - - if ( stream_.state == STREAM_RUNNING ) { - errorText_ = "RtApiWasapi::startStream: The stream is already running."; - error( RtAudioError::WARNING ); - return; - } - - // update stream state - stream_.state = STREAM_RUNNING; - - // create WASAPI stream thread - stream_.callbackInfo.thread = ( ThreadHandle ) CreateThread( NULL, 0, runWasapiThread, this, CREATE_SUSPENDED, NULL ); - - if ( !stream_.callbackInfo.thread ) { - errorText_ = "RtApiWasapi::startStream: Unable to instantiate callback thread."; - error( RtAudioError::THREAD_ERROR ); - } - else { - SetThreadPriority( ( void* ) stream_.callbackInfo.thread, stream_.callbackInfo.priority ); - ResumeThread( ( void* ) stream_.callbackInfo.thread ); - } -} - -//----------------------------------------------------------------------------- - -void RtApiWasapi::stopStream( void ) -{ - verifyStream(); - - if ( stream_.state == STREAM_STOPPED ) { - errorText_ = "RtApiWasapi::stopStream: The stream is already stopped."; - error( RtAudioError::WARNING ); - return; - } - - // inform stream thread by setting stream state to STREAM_STOPPING - stream_.state = STREAM_STOPPING; - - // wait until stream thread is stopped - while( stream_.state != STREAM_STOPPED ) { - Sleep( 1 ); - } - - // Wait for the last buffer to play before stopping. - Sleep( 1000 * stream_.bufferSize / stream_.sampleRate ); - - // stop capture client if applicable - if ( ( ( WasapiHandle* ) stream_.apiHandle )->captureAudioClient ) { - HRESULT hr = ( ( WasapiHandle* ) stream_.apiHandle )->captureAudioClient->Stop(); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::stopStream: Unable to stop capture stream."; - error( RtAudioError::DRIVER_ERROR ); - return; - } - } - - // stop render client if applicable - if ( ( ( WasapiHandle* ) stream_.apiHandle )->renderAudioClient ) { - HRESULT hr = ( ( WasapiHandle* ) stream_.apiHandle )->renderAudioClient->Stop(); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::stopStream: Unable to stop render stream."; - error( RtAudioError::DRIVER_ERROR ); - return; - } - } - - // close thread handle - if ( stream_.callbackInfo.thread && !CloseHandle( ( void* ) stream_.callbackInfo.thread ) ) { - errorText_ = "RtApiWasapi::stopStream: Unable to close callback thread."; - error( RtAudioError::THREAD_ERROR ); - return; - } - - stream_.callbackInfo.thread = (ThreadHandle) NULL; -} - -//----------------------------------------------------------------------------- - -void RtApiWasapi::abortStream( void ) -{ - verifyStream(); - - if ( stream_.state == STREAM_STOPPED ) { - errorText_ = "RtApiWasapi::abortStream: The stream is already stopped."; - error( RtAudioError::WARNING ); - return; - } - - // inform stream thread by setting stream state to STREAM_STOPPING - stream_.state = STREAM_STOPPING; - - // wait until stream thread is stopped - while ( stream_.state != STREAM_STOPPED ) { - Sleep( 1 ); - } - - // stop capture client if applicable - if ( ( ( WasapiHandle* ) stream_.apiHandle )->captureAudioClient ) { - HRESULT hr = ( ( WasapiHandle* ) stream_.apiHandle )->captureAudioClient->Stop(); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::abortStream: Unable to stop capture stream."; - error( RtAudioError::DRIVER_ERROR ); - return; - } - } - - // stop render client if applicable - if ( ( ( WasapiHandle* ) stream_.apiHandle )->renderAudioClient ) { - HRESULT hr = ( ( WasapiHandle* ) stream_.apiHandle )->renderAudioClient->Stop(); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::abortStream: Unable to stop render stream."; - error( RtAudioError::DRIVER_ERROR ); - return; - } - } - - // close thread handle - if ( stream_.callbackInfo.thread && !CloseHandle( ( void* ) stream_.callbackInfo.thread ) ) { - errorText_ = "RtApiWasapi::abortStream: Unable to close callback thread."; - error( RtAudioError::THREAD_ERROR ); - return; - } - - stream_.callbackInfo.thread = (ThreadHandle) NULL; -} - -//----------------------------------------------------------------------------- - -bool RtApiWasapi::probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, - unsigned int firstChannel, unsigned int sampleRate, - RtAudioFormat format, unsigned int* bufferSize, - RtAudio::StreamOptions* options ) -{ - bool methodResult = FAILURE; - unsigned int captureDeviceCount = 0; - unsigned int renderDeviceCount = 0; - - IMMDeviceCollection* captureDevices = NULL; - IMMDeviceCollection* renderDevices = NULL; - IMMDevice* devicePtr = NULL; - WAVEFORMATEX* deviceFormat = NULL; - unsigned int bufferBytes; - stream_.state = STREAM_STOPPED; - - // create API Handle if not already created - if ( !stream_.apiHandle ) - stream_.apiHandle = ( void* ) new WasapiHandle(); - - // Count capture devices - errorText_.clear(); - RtAudioError::Type errorType = RtAudioError::DRIVER_ERROR; - HRESULT hr = deviceEnumerator_->EnumAudioEndpoints( eCapture, DEVICE_STATE_ACTIVE, &captureDevices ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve capture device collection."; - goto Exit; - } - - hr = captureDevices->GetCount( &captureDeviceCount ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve capture device count."; - goto Exit; - } - - // Count render devices - hr = deviceEnumerator_->EnumAudioEndpoints( eRender, DEVICE_STATE_ACTIVE, &renderDevices ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve render device collection."; - goto Exit; - } - - hr = renderDevices->GetCount( &renderDeviceCount ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve render device count."; - goto Exit; - } - - // validate device index - if ( device >= captureDeviceCount + renderDeviceCount ) { - errorType = RtAudioError::INVALID_USE; - errorText_ = "RtApiWasapi::probeDeviceOpen: Invalid device index."; - goto Exit; - } - - // determine whether index falls within capture or render devices - if ( device >= renderDeviceCount ) { - if ( mode != INPUT ) { - errorType = RtAudioError::INVALID_USE; - errorText_ = "RtApiWasapi::probeDeviceOpen: Capture device selected as output device."; - goto Exit; - } - - // retrieve captureAudioClient from devicePtr - IAudioClient*& captureAudioClient = ( ( WasapiHandle* ) stream_.apiHandle )->captureAudioClient; - - hr = captureDevices->Item( device - renderDeviceCount, &devicePtr ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve capture device handle."; - goto Exit; - } - - hr = devicePtr->Activate( __uuidof( IAudioClient ), CLSCTX_ALL, - NULL, ( void** ) &captureAudioClient ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve device audio client."; - goto Exit; - } - - hr = captureAudioClient->GetMixFormat( &deviceFormat ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve device mix format."; - goto Exit; - } - - stream_.nDeviceChannels[mode] = deviceFormat->nChannels; - captureAudioClient->GetStreamLatency( ( long long* ) &stream_.latency[mode] ); - } - else { - if ( mode != OUTPUT ) { - errorType = RtAudioError::INVALID_USE; - errorText_ = "RtApiWasapi::probeDeviceOpen: Render device selected as input device."; - goto Exit; - } - - // retrieve renderAudioClient from devicePtr - IAudioClient*& renderAudioClient = ( ( WasapiHandle* ) stream_.apiHandle )->renderAudioClient; - - hr = renderDevices->Item( device, &devicePtr ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve render device handle."; - goto Exit; - } - - hr = devicePtr->Activate( __uuidof( IAudioClient ), CLSCTX_ALL, - NULL, ( void** ) &renderAudioClient ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve device audio client."; - goto Exit; - } - - hr = renderAudioClient->GetMixFormat( &deviceFormat ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve device mix format."; - goto Exit; - } - - stream_.nDeviceChannels[mode] = deviceFormat->nChannels; - renderAudioClient->GetStreamLatency( ( long long* ) &stream_.latency[mode] ); - } - - // fill stream data - if ( ( stream_.mode == OUTPUT && mode == INPUT ) || - ( stream_.mode == INPUT && mode == OUTPUT ) ) { - stream_.mode = DUPLEX; - } - else { - stream_.mode = mode; - } - - stream_.device[mode] = device; - stream_.doByteSwap[mode] = false; - stream_.sampleRate = sampleRate; - stream_.bufferSize = *bufferSize; - stream_.nBuffers = 1; - stream_.nUserChannels[mode] = channels; - stream_.channelOffset[mode] = firstChannel; - stream_.userFormat = format; - stream_.deviceFormat[mode] = getDeviceInfo( device ).nativeFormats; - - if ( options && options->flags & RTAUDIO_NONINTERLEAVED ) - stream_.userInterleaved = false; - else - stream_.userInterleaved = true; - stream_.deviceInterleaved[mode] = true; - - // Set flags for buffer conversion. - stream_.doConvertBuffer[mode] = false; - if ( stream_.userFormat != stream_.deviceFormat[mode] || - stream_.nUserChannels != stream_.nDeviceChannels ) - stream_.doConvertBuffer[mode] = true; - else if ( stream_.userInterleaved != stream_.deviceInterleaved[mode] && - stream_.nUserChannels[mode] > 1 ) - stream_.doConvertBuffer[mode] = true; - - if ( stream_.doConvertBuffer[mode] ) - setConvertInfo( mode, 0 ); - - // Allocate necessary internal buffers - bufferBytes = stream_.nUserChannels[mode] * stream_.bufferSize * formatBytes( stream_.userFormat ); - - stream_.userBuffer[mode] = ( char* ) calloc( bufferBytes, 1 ); - if ( !stream_.userBuffer[mode] ) { - errorType = RtAudioError::MEMORY_ERROR; - errorText_ = "RtApiWasapi::probeDeviceOpen: Error allocating user buffer memory."; - goto Exit; - } - - if ( options && options->flags & RTAUDIO_SCHEDULE_REALTIME ) - stream_.callbackInfo.priority = 15; - else - stream_.callbackInfo.priority = 0; - - ///! TODO: RTAUDIO_MINIMIZE_LATENCY // Provide stream buffers directly to callback - ///! TODO: RTAUDIO_HOG_DEVICE // Exclusive mode - - methodResult = SUCCESS; - -Exit: - //clean up - SAFE_RELEASE( captureDevices ); - SAFE_RELEASE( renderDevices ); - SAFE_RELEASE( devicePtr ); - CoTaskMemFree( deviceFormat ); - - // if method failed, close the stream - if ( methodResult == FAILURE ) - closeStream(); - - if ( !errorText_.empty() ) - error( errorType ); - return methodResult; -} - -//============================================================================= - -DWORD WINAPI RtApiWasapi::runWasapiThread( void* wasapiPtr ) -{ - if ( wasapiPtr ) - ( ( RtApiWasapi* ) wasapiPtr )->wasapiThread(); - - return 0; -} - -DWORD WINAPI RtApiWasapi::stopWasapiThread( void* wasapiPtr ) -{ - if ( wasapiPtr ) - ( ( RtApiWasapi* ) wasapiPtr )->stopStream(); - - return 0; -} - -DWORD WINAPI RtApiWasapi::abortWasapiThread( void* wasapiPtr ) -{ - if ( wasapiPtr ) - ( ( RtApiWasapi* ) wasapiPtr )->abortStream(); - - return 0; -} - -//----------------------------------------------------------------------------- - -void RtApiWasapi::wasapiThread() -{ - // as this is a new thread, we must CoInitialize it - CoInitialize( NULL ); - - HRESULT hr; - - IAudioClient* captureAudioClient = ( ( WasapiHandle* ) stream_.apiHandle )->captureAudioClient; - IAudioClient* renderAudioClient = ( ( WasapiHandle* ) stream_.apiHandle )->renderAudioClient; - IAudioCaptureClient* captureClient = ( ( WasapiHandle* ) stream_.apiHandle )->captureClient; - IAudioRenderClient* renderClient = ( ( WasapiHandle* ) stream_.apiHandle )->renderClient; - HANDLE captureEvent = ( ( WasapiHandle* ) stream_.apiHandle )->captureEvent; - HANDLE renderEvent = ( ( WasapiHandle* ) stream_.apiHandle )->renderEvent; - - WAVEFORMATEX* captureFormat = NULL; - WAVEFORMATEX* renderFormat = NULL; - float captureSrRatio = 0.0f; - float renderSrRatio = 0.0f; - WasapiBuffer captureBuffer; - WasapiBuffer renderBuffer; - - // declare local stream variables - RtAudioCallback callback = ( RtAudioCallback ) stream_.callbackInfo.callback; - BYTE* streamBuffer = NULL; - unsigned long captureFlags = 0; - unsigned int bufferFrameCount = 0; - unsigned int numFramesPadding = 0; - unsigned int convBufferSize = 0; - bool callbackPushed = false; - bool callbackPulled = false; - bool callbackStopped = false; - int callbackResult = 0; - - // convBuffer is used to store converted buffers between WASAPI and the user - char* convBuffer = NULL; - unsigned int convBuffSize = 0; - unsigned int deviceBuffSize = 0; - - errorText_.clear(); - RtAudioError::Type errorType = RtAudioError::DRIVER_ERROR; - - // Attempt to assign "Pro Audio" characteristic to thread - HMODULE AvrtDll = LoadLibrary( (LPCTSTR) "AVRT.dll" ); - if ( AvrtDll ) { - DWORD taskIndex = 0; - TAvSetMmThreadCharacteristicsPtr AvSetMmThreadCharacteristicsPtr = ( TAvSetMmThreadCharacteristicsPtr ) GetProcAddress( AvrtDll, "AvSetMmThreadCharacteristicsW" ); - AvSetMmThreadCharacteristicsPtr( L"Pro Audio", &taskIndex ); - FreeLibrary( AvrtDll ); - } - - // start capture stream if applicable - if ( captureAudioClient ) { - hr = captureAudioClient->GetMixFormat( &captureFormat ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::wasapiThread: Unable to retrieve device mix format."; - goto Exit; - } - - captureSrRatio = ( ( float ) captureFormat->nSamplesPerSec / stream_.sampleRate ); - - // initialize capture stream according to desire buffer size - float desiredBufferSize = stream_.bufferSize * captureSrRatio; - REFERENCE_TIME desiredBufferPeriod = ( REFERENCE_TIME ) ( ( float ) desiredBufferSize * 10000000 / captureFormat->nSamplesPerSec ); - - if ( !captureClient ) { - hr = captureAudioClient->Initialize( AUDCLNT_SHAREMODE_SHARED, - AUDCLNT_STREAMFLAGS_EVENTCALLBACK, - desiredBufferPeriod, - desiredBufferPeriod, - captureFormat, - NULL ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::wasapiThread: Unable to initialize capture audio client."; - goto Exit; - } - - hr = captureAudioClient->GetService( __uuidof( IAudioCaptureClient ), - ( void** ) &captureClient ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::wasapiThread: Unable to retrieve capture client handle."; - goto Exit; - } - - // configure captureEvent to trigger on every available capture buffer - captureEvent = CreateEvent( NULL, FALSE, FALSE, NULL ); - if ( !captureEvent ) { - errorType = RtAudioError::SYSTEM_ERROR; - errorText_ = "RtApiWasapi::wasapiThread: Unable to create capture event."; - goto Exit; - } - - hr = captureAudioClient->SetEventHandle( captureEvent ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::wasapiThread: Unable to set capture event handle."; - goto Exit; - } - - ( ( WasapiHandle* ) stream_.apiHandle )->captureClient = captureClient; - ( ( WasapiHandle* ) stream_.apiHandle )->captureEvent = captureEvent; - } - - unsigned int inBufferSize = 0; - hr = captureAudioClient->GetBufferSize( &inBufferSize ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::wasapiThread: Unable to get capture buffer size."; - goto Exit; - } - - // scale outBufferSize according to stream->user sample rate ratio - unsigned int outBufferSize = ( unsigned int ) ( stream_.bufferSize * captureSrRatio ) * stream_.nDeviceChannels[INPUT]; - inBufferSize *= stream_.nDeviceChannels[INPUT]; - - // set captureBuffer size - captureBuffer.setBufferSize( inBufferSize + outBufferSize, formatBytes( stream_.deviceFormat[INPUT] ) ); - - // reset the capture stream - hr = captureAudioClient->Reset(); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::wasapiThread: Unable to reset capture stream."; - goto Exit; - } - - // start the capture stream - hr = captureAudioClient->Start(); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::wasapiThread: Unable to start capture stream."; - goto Exit; - } - } - - // start render stream if applicable - if ( renderAudioClient ) { - hr = renderAudioClient->GetMixFormat( &renderFormat ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::wasapiThread: Unable to retrieve device mix format."; - goto Exit; - } - - renderSrRatio = ( ( float ) renderFormat->nSamplesPerSec / stream_.sampleRate ); - - // initialize render stream according to desire buffer size - float desiredBufferSize = stream_.bufferSize * renderSrRatio; - REFERENCE_TIME desiredBufferPeriod = ( REFERENCE_TIME ) ( ( float ) desiredBufferSize * 10000000 / renderFormat->nSamplesPerSec ); - - if ( !renderClient ) { - hr = renderAudioClient->Initialize( AUDCLNT_SHAREMODE_SHARED, - AUDCLNT_STREAMFLAGS_EVENTCALLBACK, - desiredBufferPeriod, - desiredBufferPeriod, - renderFormat, - NULL ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::wasapiThread: Unable to initialize render audio client."; - goto Exit; - } - - hr = renderAudioClient->GetService( __uuidof( IAudioRenderClient ), - ( void** ) &renderClient ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::wasapiThread: Unable to retrieve render client handle."; - goto Exit; - } - - // configure renderEvent to trigger on every available render buffer - renderEvent = CreateEvent( NULL, FALSE, FALSE, NULL ); - if ( !renderEvent ) { - errorType = RtAudioError::SYSTEM_ERROR; - errorText_ = "RtApiWasapi::wasapiThread: Unable to create render event."; - goto Exit; - } - - hr = renderAudioClient->SetEventHandle( renderEvent ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::wasapiThread: Unable to set render event handle."; - goto Exit; - } - - ( ( WasapiHandle* ) stream_.apiHandle )->renderClient = renderClient; - ( ( WasapiHandle* ) stream_.apiHandle )->renderEvent = renderEvent; - } - - unsigned int outBufferSize = 0; - hr = renderAudioClient->GetBufferSize( &outBufferSize ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::wasapiThread: Unable to get render buffer size."; - goto Exit; - } - - // scale inBufferSize according to user->stream sample rate ratio - unsigned int inBufferSize = ( unsigned int ) ( stream_.bufferSize * renderSrRatio ) * stream_.nDeviceChannels[OUTPUT]; - outBufferSize *= stream_.nDeviceChannels[OUTPUT]; - - // set renderBuffer size - renderBuffer.setBufferSize( inBufferSize + outBufferSize, formatBytes( stream_.deviceFormat[OUTPUT] ) ); - - // reset the render stream - hr = renderAudioClient->Reset(); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::wasapiThread: Unable to reset render stream."; - goto Exit; - } - - // start the render stream - hr = renderAudioClient->Start(); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::wasapiThread: Unable to start render stream."; - goto Exit; - } - } - - if ( stream_.mode == INPUT ) { - convBuffSize = ( size_t ) ( stream_.bufferSize * captureSrRatio ) * stream_.nDeviceChannels[INPUT] * formatBytes( stream_.deviceFormat[INPUT] ); - deviceBuffSize = stream_.bufferSize * stream_.nDeviceChannels[INPUT] * formatBytes( stream_.deviceFormat[INPUT] ); - } - else if ( stream_.mode == OUTPUT ) { - convBuffSize = ( size_t ) ( stream_.bufferSize * renderSrRatio ) * stream_.nDeviceChannels[OUTPUT] * formatBytes( stream_.deviceFormat[OUTPUT] ); - deviceBuffSize = stream_.bufferSize * stream_.nDeviceChannels[OUTPUT] * formatBytes( stream_.deviceFormat[OUTPUT] ); - } - else if ( stream_.mode == DUPLEX ) { - convBuffSize = std::max( ( size_t ) ( stream_.bufferSize * captureSrRatio ) * stream_.nDeviceChannels[INPUT] * formatBytes( stream_.deviceFormat[INPUT] ), - ( size_t ) ( stream_.bufferSize * renderSrRatio ) * stream_.nDeviceChannels[OUTPUT] * formatBytes( stream_.deviceFormat[OUTPUT] ) ); - deviceBuffSize = std::max( stream_.bufferSize * stream_.nDeviceChannels[INPUT] * formatBytes( stream_.deviceFormat[INPUT] ), - stream_.bufferSize * stream_.nDeviceChannels[OUTPUT] * formatBytes( stream_.deviceFormat[OUTPUT] ) ); - } - - convBuffer = ( char* ) malloc( convBuffSize ); - stream_.deviceBuffer = ( char* ) malloc( deviceBuffSize ); - if ( !convBuffer || !stream_.deviceBuffer ) { - errorType = RtAudioError::MEMORY_ERROR; - errorText_ = "RtApiWasapi::wasapiThread: Error allocating device buffer memory."; - goto Exit; - } - - // stream process loop - while ( stream_.state != STREAM_STOPPING ) { - if ( !callbackPulled ) { - // Callback Input - // ============== - // 1. Pull callback buffer from inputBuffer - // 2. If 1. was successful: Convert callback buffer to user sample rate and channel count - // Convert callback buffer to user format - - if ( captureAudioClient ) { - // Pull callback buffer from inputBuffer - callbackPulled = captureBuffer.pullBuffer( convBuffer, - ( unsigned int ) ( stream_.bufferSize * captureSrRatio ) * stream_.nDeviceChannels[INPUT], - stream_.deviceFormat[INPUT] ); - - if ( callbackPulled ) { - // Convert callback buffer to user sample rate - convertBufferWasapi( stream_.deviceBuffer, - convBuffer, - stream_.nDeviceChannels[INPUT], - captureFormat->nSamplesPerSec, - stream_.sampleRate, - ( unsigned int ) ( stream_.bufferSize * captureSrRatio ), - convBufferSize, - stream_.deviceFormat[INPUT] ); - - if ( stream_.doConvertBuffer[INPUT] ) { - // Convert callback buffer to user format - convertBuffer( stream_.userBuffer[INPUT], - stream_.deviceBuffer, - stream_.convertInfo[INPUT] ); - } - else { - // no further conversion, simple copy deviceBuffer to userBuffer - memcpy( stream_.userBuffer[INPUT], - stream_.deviceBuffer, - stream_.bufferSize * stream_.nUserChannels[INPUT] * formatBytes( stream_.userFormat ) ); - } - } - } - else { - // if there is no capture stream, set callbackPulled flag - callbackPulled = true; - } - - // Execute Callback - // ================ - // 1. Execute user callback method - // 2. Handle return value from callback - - // if callback has not requested the stream to stop - if ( callbackPulled && !callbackStopped ) { - // Execute user callback method - callbackResult = callback( stream_.userBuffer[OUTPUT], - stream_.userBuffer[INPUT], - stream_.bufferSize, - getStreamTime(), - captureFlags & AUDCLNT_BUFFERFLAGS_DATA_DISCONTINUITY ? RTAUDIO_INPUT_OVERFLOW : 0, - stream_.callbackInfo.userData ); - - // Handle return value from callback - if ( callbackResult == 1 ) { - // instantiate a thread to stop this thread - HANDLE threadHandle = CreateThread( NULL, 0, stopWasapiThread, this, 0, NULL ); - if ( !threadHandle ) { - errorType = RtAudioError::THREAD_ERROR; - errorText_ = "RtApiWasapi::wasapiThread: Unable to instantiate stream stop thread."; - goto Exit; - } - else if ( !CloseHandle( threadHandle ) ) { - errorType = RtAudioError::THREAD_ERROR; - errorText_ = "RtApiWasapi::wasapiThread: Unable to close stream stop thread handle."; - goto Exit; - } - - callbackStopped = true; - } - else if ( callbackResult == 2 ) { - // instantiate a thread to stop this thread - HANDLE threadHandle = CreateThread( NULL, 0, abortWasapiThread, this, 0, NULL ); - if ( !threadHandle ) { - errorType = RtAudioError::THREAD_ERROR; - errorText_ = "RtApiWasapi::wasapiThread: Unable to instantiate stream abort thread."; - goto Exit; - } - else if ( !CloseHandle( threadHandle ) ) { - errorType = RtAudioError::THREAD_ERROR; - errorText_ = "RtApiWasapi::wasapiThread: Unable to close stream abort thread handle."; - goto Exit; - } - - callbackStopped = true; - } - } - } - - // Callback Output - // =============== - // 1. Convert callback buffer to stream format - // 2. Convert callback buffer to stream sample rate and channel count - // 3. Push callback buffer into outputBuffer - - if ( renderAudioClient && callbackPulled ) { - if ( stream_.doConvertBuffer[OUTPUT] ) { - // Convert callback buffer to stream format - convertBuffer( stream_.deviceBuffer, - stream_.userBuffer[OUTPUT], - stream_.convertInfo[OUTPUT] ); - - } - - // Convert callback buffer to stream sample rate - convertBufferWasapi( convBuffer, - stream_.deviceBuffer, - stream_.nDeviceChannels[OUTPUT], - stream_.sampleRate, - renderFormat->nSamplesPerSec, - stream_.bufferSize, - convBufferSize, - stream_.deviceFormat[OUTPUT] ); - - // Push callback buffer into outputBuffer - callbackPushed = renderBuffer.pushBuffer( convBuffer, - convBufferSize * stream_.nDeviceChannels[OUTPUT], - stream_.deviceFormat[OUTPUT] ); - } - else { - // if there is no render stream, set callbackPushed flag - callbackPushed = true; - } - - // Stream Capture - // ============== - // 1. Get capture buffer from stream - // 2. Push capture buffer into inputBuffer - // 3. If 2. was successful: Release capture buffer - - if ( captureAudioClient ) { - // if the callback input buffer was not pulled from captureBuffer, wait for next capture event - if ( !callbackPulled ) { - WaitForSingleObject( captureEvent, INFINITE ); - } - - // Get capture buffer from stream - hr = captureClient->GetBuffer( &streamBuffer, - &bufferFrameCount, - &captureFlags, NULL, NULL ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::wasapiThread: Unable to retrieve capture buffer."; - goto Exit; - } - - if ( bufferFrameCount != 0 ) { - // Push capture buffer into inputBuffer - if ( captureBuffer.pushBuffer( ( char* ) streamBuffer, - bufferFrameCount * stream_.nDeviceChannels[INPUT], - stream_.deviceFormat[INPUT] ) ) - { - // Release capture buffer - hr = captureClient->ReleaseBuffer( bufferFrameCount ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::wasapiThread: Unable to release capture buffer."; - goto Exit; - } - } - else - { - // Inform WASAPI that capture was unsuccessful - hr = captureClient->ReleaseBuffer( 0 ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::wasapiThread: Unable to release capture buffer."; - goto Exit; - } - } - } - else - { - // Inform WASAPI that capture was unsuccessful - hr = captureClient->ReleaseBuffer( 0 ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::wasapiThread: Unable to release capture buffer."; - goto Exit; - } - } - } - - // Stream Render - // ============= - // 1. Get render buffer from stream - // 2. Pull next buffer from outputBuffer - // 3. If 2. was successful: Fill render buffer with next buffer - // Release render buffer - - if ( renderAudioClient ) { - // if the callback output buffer was not pushed to renderBuffer, wait for next render event - if ( callbackPulled && !callbackPushed ) { - WaitForSingleObject( renderEvent, INFINITE ); - } - - // Get render buffer from stream - hr = renderAudioClient->GetBufferSize( &bufferFrameCount ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::wasapiThread: Unable to retrieve render buffer size."; - goto Exit; - } - - hr = renderAudioClient->GetCurrentPadding( &numFramesPadding ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::wasapiThread: Unable to retrieve render buffer padding."; - goto Exit; - } - - bufferFrameCount -= numFramesPadding; - - if ( bufferFrameCount != 0 ) { - hr = renderClient->GetBuffer( bufferFrameCount, &streamBuffer ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::wasapiThread: Unable to retrieve render buffer."; - goto Exit; - } - - // Pull next buffer from outputBuffer - // Fill render buffer with next buffer - if ( renderBuffer.pullBuffer( ( char* ) streamBuffer, - bufferFrameCount * stream_.nDeviceChannels[OUTPUT], - stream_.deviceFormat[OUTPUT] ) ) - { - // Release render buffer - hr = renderClient->ReleaseBuffer( bufferFrameCount, 0 ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::wasapiThread: Unable to release render buffer."; - goto Exit; - } - } - else - { - // Inform WASAPI that render was unsuccessful - hr = renderClient->ReleaseBuffer( 0, 0 ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::wasapiThread: Unable to release render buffer."; - goto Exit; - } - } - } - else - { - // Inform WASAPI that render was unsuccessful - hr = renderClient->ReleaseBuffer( 0, 0 ); - if ( FAILED( hr ) ) { - errorText_ = "RtApiWasapi::wasapiThread: Unable to release render buffer."; - goto Exit; - } - } - } - - // if the callback buffer was pushed renderBuffer reset callbackPulled flag - if ( callbackPushed ) { - callbackPulled = false; - // tick stream time - RtApi::tickStreamTime(); - } - - } - -Exit: - // clean up - CoTaskMemFree( captureFormat ); - CoTaskMemFree( renderFormat ); - - free ( convBuffer ); - - CoUninitialize(); - - // update stream state - stream_.state = STREAM_STOPPED; - - if ( errorText_.empty() ) - return; - else - error( errorType ); -} - -//******************** End of __WINDOWS_WASAPI__ *********************// -#endif - - -#if defined(__WINDOWS_DS__) // Windows DirectSound API - -// Modified by Robin Davies, October 2005 -// - Improvements to DirectX pointer chasing. -// - Bug fix for non-power-of-two Asio granularity used by Edirol PCR-A30. -// - Auto-call CoInitialize for DSOUND and ASIO platforms. -// Various revisions for RtAudio 4.0 by Gary Scavone, April 2007 -// Changed device query structure for RtAudio 4.0.7, January 2010 - -#include -#include -#include - -#if defined(__MINGW32__) - // missing from latest mingw winapi -#define WAVE_FORMAT_96M08 0x00010000 /* 96 kHz, Mono, 8-bit */ -#define WAVE_FORMAT_96S08 0x00020000 /* 96 kHz, Stereo, 8-bit */ -#define WAVE_FORMAT_96M16 0x00040000 /* 96 kHz, Mono, 16-bit */ -#define WAVE_FORMAT_96S16 0x00080000 /* 96 kHz, Stereo, 16-bit */ -#endif - -#define MINIMUM_DEVICE_BUFFER_SIZE 32768 - -#ifdef _MSC_VER // if Microsoft Visual C++ -#pragma comment( lib, "winmm.lib" ) // then, auto-link winmm.lib. Otherwise, it has to be added manually. -#endif - -static inline DWORD dsPointerBetween( DWORD pointer, DWORD laterPointer, DWORD earlierPointer, DWORD bufferSize ) -{ - if ( pointer > bufferSize ) pointer -= bufferSize; - if ( laterPointer < earlierPointer ) laterPointer += bufferSize; - if ( pointer < earlierPointer ) pointer += bufferSize; - return pointer >= earlierPointer && pointer < laterPointer; -} - -// A structure to hold various information related to the DirectSound -// API implementation. -struct DsHandle { - unsigned int drainCounter; // Tracks callback counts when draining - bool internalDrain; // Indicates if stop is initiated from callback or not. - void *id[2]; - void *buffer[2]; - bool xrun[2]; - UINT bufferPointer[2]; - DWORD dsBufferSize[2]; - DWORD dsPointerLeadTime[2]; // the number of bytes ahead of the safe pointer to lead by. - HANDLE condition; - - DsHandle() - :drainCounter(0), internalDrain(false) { id[0] = 0; id[1] = 0; buffer[0] = 0; buffer[1] = 0; xrun[0] = false; xrun[1] = false; bufferPointer[0] = 0; bufferPointer[1] = 0; } -}; - -// Declarations for utility functions, callbacks, and structures -// specific to the DirectSound implementation. -static BOOL CALLBACK deviceQueryCallback( LPGUID lpguid, - LPCTSTR description, - LPCTSTR module, - LPVOID lpContext ); - -static const char* getErrorString( int code ); - -static unsigned __stdcall callbackHandler( void *ptr ); - -struct DsDevice { - LPGUID id[2]; - bool validId[2]; - bool found; - std::string name; - - DsDevice() - : found(false) { validId[0] = false; validId[1] = false; } -}; - -struct DsProbeData { - bool isInput; - std::vector* dsDevices; -}; - -RtApiDs :: RtApiDs() -{ - // Dsound will run both-threaded. If CoInitialize fails, then just - // accept whatever the mainline chose for a threading model. - coInitialized_ = false; - HRESULT hr = CoInitialize( NULL ); - if ( !FAILED( hr ) ) coInitialized_ = true; -} - -RtApiDs :: ~RtApiDs() -{ - if ( coInitialized_ ) CoUninitialize(); // balanced call. - if ( stream_.state != STREAM_CLOSED ) closeStream(); -} - -// The DirectSound default output is always the first device. -unsigned int RtApiDs :: getDefaultOutputDevice( void ) -{ - return 0; -} - -// The DirectSound default input is always the first input device, -// which is the first capture device enumerated. -unsigned int RtApiDs :: getDefaultInputDevice( void ) -{ - return 0; -} - -unsigned int RtApiDs :: getDeviceCount( void ) -{ - // Set query flag for previously found devices to false, so that we - // can check for any devices that have disappeared. - for ( unsigned int i=0; i(dsDevices.size()); -} - -RtAudio::DeviceInfo RtApiDs :: getDeviceInfo( unsigned int device ) -{ - RtAudio::DeviceInfo info; - info.probed = false; - - if ( dsDevices.size() == 0 ) { - // Force a query of all devices - getDeviceCount(); - if ( dsDevices.size() == 0 ) { - errorText_ = "RtApiDs::getDeviceInfo: no devices found!"; - error( RtAudioError::INVALID_USE ); - return info; - } - } - - if ( device >= dsDevices.size() ) { - errorText_ = "RtApiDs::getDeviceInfo: device ID is invalid!"; - error( RtAudioError::INVALID_USE ); - return info; - } - - HRESULT result; - if ( dsDevices[ device ].validId[0] == false ) goto probeInput; - - LPDIRECTSOUND output; - DSCAPS outCaps; - result = DirectSoundCreate( dsDevices[ device ].id[0], &output, NULL ); - if ( FAILED( result ) ) { - errorStream_ << "RtApiDs::getDeviceInfo: error (" << getErrorString( result ) << ") opening output device (" << dsDevices[ device ].name << ")!"; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - goto probeInput; - } - - outCaps.dwSize = sizeof( outCaps ); - result = output->GetCaps( &outCaps ); - if ( FAILED( result ) ) { - output->Release(); - errorStream_ << "RtApiDs::getDeviceInfo: error (" << getErrorString( result ) << ") getting capabilities!"; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - goto probeInput; - } - - // Get output channel information. - info.outputChannels = ( outCaps.dwFlags & DSCAPS_PRIMARYSTEREO ) ? 2 : 1; - - // Get sample rate information. - info.sampleRates.clear(); - for ( unsigned int k=0; k= (unsigned int) outCaps.dwMinSecondarySampleRate && - SAMPLE_RATES[k] <= (unsigned int) outCaps.dwMaxSecondarySampleRate ) { - info.sampleRates.push_back( SAMPLE_RATES[k] ); - - if ( !info.preferredSampleRate || ( SAMPLE_RATES[k] <= 48000 && SAMPLE_RATES[k] > info.preferredSampleRate ) ) - info.preferredSampleRate = SAMPLE_RATES[k]; - } - } - - // Get format information. - if ( outCaps.dwFlags & DSCAPS_PRIMARY16BIT ) info.nativeFormats |= RTAUDIO_SINT16; - if ( outCaps.dwFlags & DSCAPS_PRIMARY8BIT ) info.nativeFormats |= RTAUDIO_SINT8; - - output->Release(); - - if ( getDefaultOutputDevice() == device ) - info.isDefaultOutput = true; - - if ( dsDevices[ device ].validId[1] == false ) { - info.name = dsDevices[ device ].name; - info.probed = true; - return info; - } - - probeInput: - - LPDIRECTSOUNDCAPTURE input; - result = DirectSoundCaptureCreate( dsDevices[ device ].id[1], &input, NULL ); - if ( FAILED( result ) ) { - errorStream_ << "RtApiDs::getDeviceInfo: error (" << getErrorString( result ) << ") opening input device (" << dsDevices[ device ].name << ")!"; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - return info; - } - - DSCCAPS inCaps; - inCaps.dwSize = sizeof( inCaps ); - result = input->GetCaps( &inCaps ); - if ( FAILED( result ) ) { - input->Release(); - errorStream_ << "RtApiDs::getDeviceInfo: error (" << getErrorString( result ) << ") getting object capabilities (" << dsDevices[ device ].name << ")!"; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - return info; - } - - // Get input channel information. - info.inputChannels = inCaps.dwChannels; - - // Get sample rate and format information. - std::vector rates; - if ( inCaps.dwChannels >= 2 ) { - if ( inCaps.dwFormats & WAVE_FORMAT_1S16 ) info.nativeFormats |= RTAUDIO_SINT16; - if ( inCaps.dwFormats & WAVE_FORMAT_2S16 ) info.nativeFormats |= RTAUDIO_SINT16; - if ( inCaps.dwFormats & WAVE_FORMAT_4S16 ) info.nativeFormats |= RTAUDIO_SINT16; - if ( inCaps.dwFormats & WAVE_FORMAT_96S16 ) info.nativeFormats |= RTAUDIO_SINT16; - if ( inCaps.dwFormats & WAVE_FORMAT_1S08 ) info.nativeFormats |= RTAUDIO_SINT8; - if ( inCaps.dwFormats & WAVE_FORMAT_2S08 ) info.nativeFormats |= RTAUDIO_SINT8; - if ( inCaps.dwFormats & WAVE_FORMAT_4S08 ) info.nativeFormats |= RTAUDIO_SINT8; - if ( inCaps.dwFormats & WAVE_FORMAT_96S08 ) info.nativeFormats |= RTAUDIO_SINT8; - - if ( info.nativeFormats & RTAUDIO_SINT16 ) { - if ( inCaps.dwFormats & WAVE_FORMAT_1S16 ) rates.push_back( 11025 ); - if ( inCaps.dwFormats & WAVE_FORMAT_2S16 ) rates.push_back( 22050 ); - if ( inCaps.dwFormats & WAVE_FORMAT_4S16 ) rates.push_back( 44100 ); - if ( inCaps.dwFormats & WAVE_FORMAT_96S16 ) rates.push_back( 96000 ); - } - else if ( info.nativeFormats & RTAUDIO_SINT8 ) { - if ( inCaps.dwFormats & WAVE_FORMAT_1S08 ) rates.push_back( 11025 ); - if ( inCaps.dwFormats & WAVE_FORMAT_2S08 ) rates.push_back( 22050 ); - if ( inCaps.dwFormats & WAVE_FORMAT_4S08 ) rates.push_back( 44100 ); - if ( inCaps.dwFormats & WAVE_FORMAT_96S08 ) rates.push_back( 96000 ); - } - } - else if ( inCaps.dwChannels == 1 ) { - if ( inCaps.dwFormats & WAVE_FORMAT_1M16 ) info.nativeFormats |= RTAUDIO_SINT16; - if ( inCaps.dwFormats & WAVE_FORMAT_2M16 ) info.nativeFormats |= RTAUDIO_SINT16; - if ( inCaps.dwFormats & WAVE_FORMAT_4M16 ) info.nativeFormats |= RTAUDIO_SINT16; - if ( inCaps.dwFormats & WAVE_FORMAT_96M16 ) info.nativeFormats |= RTAUDIO_SINT16; - if ( inCaps.dwFormats & WAVE_FORMAT_1M08 ) info.nativeFormats |= RTAUDIO_SINT8; - if ( inCaps.dwFormats & WAVE_FORMAT_2M08 ) info.nativeFormats |= RTAUDIO_SINT8; - if ( inCaps.dwFormats & WAVE_FORMAT_4M08 ) info.nativeFormats |= RTAUDIO_SINT8; - if ( inCaps.dwFormats & WAVE_FORMAT_96M08 ) info.nativeFormats |= RTAUDIO_SINT8; - - if ( info.nativeFormats & RTAUDIO_SINT16 ) { - if ( inCaps.dwFormats & WAVE_FORMAT_1M16 ) rates.push_back( 11025 ); - if ( inCaps.dwFormats & WAVE_FORMAT_2M16 ) rates.push_back( 22050 ); - if ( inCaps.dwFormats & WAVE_FORMAT_4M16 ) rates.push_back( 44100 ); - if ( inCaps.dwFormats & WAVE_FORMAT_96M16 ) rates.push_back( 96000 ); - } - else if ( info.nativeFormats & RTAUDIO_SINT8 ) { - if ( inCaps.dwFormats & WAVE_FORMAT_1M08 ) rates.push_back( 11025 ); - if ( inCaps.dwFormats & WAVE_FORMAT_2M08 ) rates.push_back( 22050 ); - if ( inCaps.dwFormats & WAVE_FORMAT_4M08 ) rates.push_back( 44100 ); - if ( inCaps.dwFormats & WAVE_FORMAT_96M08 ) rates.push_back( 96000 ); - } - } - else info.inputChannels = 0; // technically, this would be an error - - input->Release(); - - if ( info.inputChannels == 0 ) return info; - - // Copy the supported rates to the info structure but avoid duplication. - bool found; - for ( unsigned int i=0; i 0 && info.inputChannels > 0 ) - info.duplexChannels = (info.outputChannels > info.inputChannels) ? info.inputChannels : info.outputChannels; - - if ( device == 0 ) info.isDefaultInput = true; - - // Copy name and return. - info.name = dsDevices[ device ].name; - info.probed = true; - return info; -} - -bool RtApiDs :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, - unsigned int firstChannel, unsigned int sampleRate, - RtAudioFormat format, unsigned int *bufferSize, - RtAudio::StreamOptions *options ) -{ - if ( channels + firstChannel > 2 ) { - errorText_ = "RtApiDs::probeDeviceOpen: DirectSound does not support more than 2 channels per device."; - return FAILURE; - } - - size_t nDevices = dsDevices.size(); - if ( nDevices == 0 ) { - // This should not happen because a check is made before this function is called. - errorText_ = "RtApiDs::probeDeviceOpen: no devices found!"; - return FAILURE; - } - - if ( device >= nDevices ) { - // This should not happen because a check is made before this function is called. - errorText_ = "RtApiDs::probeDeviceOpen: device ID is invalid!"; - return FAILURE; - } - - if ( mode == OUTPUT ) { - if ( dsDevices[ device ].validId[0] == false ) { - errorStream_ << "RtApiDs::probeDeviceOpen: device (" << device << ") does not support output!"; - errorText_ = errorStream_.str(); - return FAILURE; - } - } - else { // mode == INPUT - if ( dsDevices[ device ].validId[1] == false ) { - errorStream_ << "RtApiDs::probeDeviceOpen: device (" << device << ") does not support input!"; - errorText_ = errorStream_.str(); - return FAILURE; - } - } - - // According to a note in PortAudio, using GetDesktopWindow() - // instead of GetForegroundWindow() is supposed to avoid problems - // that occur when the application's window is not the foreground - // window. Also, if the application window closes before the - // DirectSound buffer, DirectSound can crash. In the past, I had - // problems when using GetDesktopWindow() but it seems fine now - // (January 2010). I'll leave it commented here. - // HWND hWnd = GetForegroundWindow(); - HWND hWnd = GetDesktopWindow(); - - // Check the numberOfBuffers parameter and limit the lowest value to - // two. This is a judgement call and a value of two is probably too - // low for capture, but it should work for playback. - int nBuffers = 0; - if ( options ) nBuffers = options->numberOfBuffers; - if ( options && options->flags & RTAUDIO_MINIMIZE_LATENCY ) nBuffers = 2; - if ( nBuffers < 2 ) nBuffers = 3; - - // Check the lower range of the user-specified buffer size and set - // (arbitrarily) to a lower bound of 32. - if ( *bufferSize < 32 ) *bufferSize = 32; - - // Create the wave format structure. The data format setting will - // be determined later. - WAVEFORMATEX waveFormat; - ZeroMemory( &waveFormat, sizeof(WAVEFORMATEX) ); - waveFormat.wFormatTag = WAVE_FORMAT_PCM; - waveFormat.nChannels = channels + firstChannel; - waveFormat.nSamplesPerSec = (unsigned long) sampleRate; - - // Determine the device buffer size. By default, we'll use the value - // defined above (32K), but we will grow it to make allowances for - // very large software buffer sizes. - DWORD dsBufferSize = MINIMUM_DEVICE_BUFFER_SIZE; - DWORD dsPointerLeadTime = 0; - - void *ohandle = 0, *bhandle = 0; - HRESULT result; - if ( mode == OUTPUT ) { - - LPDIRECTSOUND output; - result = DirectSoundCreate( dsDevices[ device ].id[0], &output, NULL ); - if ( FAILED( result ) ) { - errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") opening output device (" << dsDevices[ device ].name << ")!"; - errorText_ = errorStream_.str(); - return FAILURE; - } - - DSCAPS outCaps; - outCaps.dwSize = sizeof( outCaps ); - result = output->GetCaps( &outCaps ); - if ( FAILED( result ) ) { - output->Release(); - errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") getting capabilities (" << dsDevices[ device ].name << ")!"; - errorText_ = errorStream_.str(); - return FAILURE; - } - - // Check channel information. - if ( channels + firstChannel == 2 && !( outCaps.dwFlags & DSCAPS_PRIMARYSTEREO ) ) { - errorStream_ << "RtApiDs::getDeviceInfo: the output device (" << dsDevices[ device ].name << ") does not support stereo playback."; - errorText_ = errorStream_.str(); - return FAILURE; - } - - // Check format information. Use 16-bit format unless not - // supported or user requests 8-bit. - if ( outCaps.dwFlags & DSCAPS_PRIMARY16BIT && - !( format == RTAUDIO_SINT8 && outCaps.dwFlags & DSCAPS_PRIMARY8BIT ) ) { - waveFormat.wBitsPerSample = 16; - stream_.deviceFormat[mode] = RTAUDIO_SINT16; - } - else { - waveFormat.wBitsPerSample = 8; - stream_.deviceFormat[mode] = RTAUDIO_SINT8; - } - stream_.userFormat = format; - - // Update wave format structure and buffer information. - waveFormat.nBlockAlign = waveFormat.nChannels * waveFormat.wBitsPerSample / 8; - waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign; - dsPointerLeadTime = nBuffers * (*bufferSize) * (waveFormat.wBitsPerSample / 8) * channels; - - // If the user wants an even bigger buffer, increase the device buffer size accordingly. - while ( dsPointerLeadTime * 2U > dsBufferSize ) - dsBufferSize *= 2; - - // Set cooperative level to DSSCL_EXCLUSIVE ... sound stops when window focus changes. - // result = output->SetCooperativeLevel( hWnd, DSSCL_EXCLUSIVE ); - // Set cooperative level to DSSCL_PRIORITY ... sound remains when window focus changes. - result = output->SetCooperativeLevel( hWnd, DSSCL_PRIORITY ); - if ( FAILED( result ) ) { - output->Release(); - errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") setting cooperative level (" << dsDevices[ device ].name << ")!"; - errorText_ = errorStream_.str(); - return FAILURE; - } - - // Even though we will write to the secondary buffer, we need to - // access the primary buffer to set the correct output format - // (since the default is 8-bit, 22 kHz!). Setup the DS primary - // buffer description. - DSBUFFERDESC bufferDescription; - ZeroMemory( &bufferDescription, sizeof( DSBUFFERDESC ) ); - bufferDescription.dwSize = sizeof( DSBUFFERDESC ); - bufferDescription.dwFlags = DSBCAPS_PRIMARYBUFFER; - - // Obtain the primary buffer - LPDIRECTSOUNDBUFFER buffer; - result = output->CreateSoundBuffer( &bufferDescription, &buffer, NULL ); - if ( FAILED( result ) ) { - output->Release(); - errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") accessing primary buffer (" << dsDevices[ device ].name << ")!"; - errorText_ = errorStream_.str(); - return FAILURE; - } - - // Set the primary DS buffer sound format. - result = buffer->SetFormat( &waveFormat ); - if ( FAILED( result ) ) { - output->Release(); - errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") setting primary buffer format (" << dsDevices[ device ].name << ")!"; - errorText_ = errorStream_.str(); - return FAILURE; - } - - // Setup the secondary DS buffer description. - ZeroMemory( &bufferDescription, sizeof( DSBUFFERDESC ) ); - bufferDescription.dwSize = sizeof( DSBUFFERDESC ); - bufferDescription.dwFlags = ( DSBCAPS_STICKYFOCUS | - DSBCAPS_GLOBALFOCUS | - DSBCAPS_GETCURRENTPOSITION2 | - DSBCAPS_LOCHARDWARE ); // Force hardware mixing - bufferDescription.dwBufferBytes = dsBufferSize; - bufferDescription.lpwfxFormat = &waveFormat; - - // Try to create the secondary DS buffer. If that doesn't work, - // try to use software mixing. Otherwise, there's a problem. - result = output->CreateSoundBuffer( &bufferDescription, &buffer, NULL ); - if ( FAILED( result ) ) { - bufferDescription.dwFlags = ( DSBCAPS_STICKYFOCUS | - DSBCAPS_GLOBALFOCUS | - DSBCAPS_GETCURRENTPOSITION2 | - DSBCAPS_LOCSOFTWARE ); // Force software mixing - result = output->CreateSoundBuffer( &bufferDescription, &buffer, NULL ); - if ( FAILED( result ) ) { - output->Release(); - errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") creating secondary buffer (" << dsDevices[ device ].name << ")!"; - errorText_ = errorStream_.str(); - return FAILURE; - } - } - - // Get the buffer size ... might be different from what we specified. - DSBCAPS dsbcaps; - dsbcaps.dwSize = sizeof( DSBCAPS ); - result = buffer->GetCaps( &dsbcaps ); - if ( FAILED( result ) ) { - output->Release(); - buffer->Release(); - errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") getting buffer settings (" << dsDevices[ device ].name << ")!"; - errorText_ = errorStream_.str(); - return FAILURE; - } - - dsBufferSize = dsbcaps.dwBufferBytes; - - // Lock the DS buffer - LPVOID audioPtr; - DWORD dataLen; - result = buffer->Lock( 0, dsBufferSize, &audioPtr, &dataLen, NULL, NULL, 0 ); - if ( FAILED( result ) ) { - output->Release(); - buffer->Release(); - errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") locking buffer (" << dsDevices[ device ].name << ")!"; - errorText_ = errorStream_.str(); - return FAILURE; - } - - // Zero the DS buffer - ZeroMemory( audioPtr, dataLen ); - - // Unlock the DS buffer - result = buffer->Unlock( audioPtr, dataLen, NULL, 0 ); - if ( FAILED( result ) ) { - output->Release(); - buffer->Release(); - errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") unlocking buffer (" << dsDevices[ device ].name << ")!"; - errorText_ = errorStream_.str(); - return FAILURE; - } - - ohandle = (void *) output; - bhandle = (void *) buffer; - } - - if ( mode == INPUT ) { - - LPDIRECTSOUNDCAPTURE input; - result = DirectSoundCaptureCreate( dsDevices[ device ].id[1], &input, NULL ); - if ( FAILED( result ) ) { - errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") opening input device (" << dsDevices[ device ].name << ")!"; - errorText_ = errorStream_.str(); - return FAILURE; - } - - DSCCAPS inCaps; - inCaps.dwSize = sizeof( inCaps ); - result = input->GetCaps( &inCaps ); - if ( FAILED( result ) ) { - input->Release(); - errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") getting input capabilities (" << dsDevices[ device ].name << ")!"; - errorText_ = errorStream_.str(); - return FAILURE; - } - - // Check channel information. - if ( inCaps.dwChannels < channels + firstChannel ) { - errorText_ = "RtApiDs::getDeviceInfo: the input device does not support requested input channels."; - return FAILURE; - } - - // Check format information. Use 16-bit format unless user - // requests 8-bit. - DWORD deviceFormats; - if ( channels + firstChannel == 2 ) { - deviceFormats = WAVE_FORMAT_1S08 | WAVE_FORMAT_2S08 | WAVE_FORMAT_4S08 | WAVE_FORMAT_96S08; - if ( format == RTAUDIO_SINT8 && inCaps.dwFormats & deviceFormats ) { - waveFormat.wBitsPerSample = 8; - stream_.deviceFormat[mode] = RTAUDIO_SINT8; - } - else { // assume 16-bit is supported - waveFormat.wBitsPerSample = 16; - stream_.deviceFormat[mode] = RTAUDIO_SINT16; - } - } - else { // channel == 1 - deviceFormats = WAVE_FORMAT_1M08 | WAVE_FORMAT_2M08 | WAVE_FORMAT_4M08 | WAVE_FORMAT_96M08; - if ( format == RTAUDIO_SINT8 && inCaps.dwFormats & deviceFormats ) { - waveFormat.wBitsPerSample = 8; - stream_.deviceFormat[mode] = RTAUDIO_SINT8; - } - else { // assume 16-bit is supported - waveFormat.wBitsPerSample = 16; - stream_.deviceFormat[mode] = RTAUDIO_SINT16; - } - } - stream_.userFormat = format; - - // Update wave format structure and buffer information. - waveFormat.nBlockAlign = waveFormat.nChannels * waveFormat.wBitsPerSample / 8; - waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign; - dsPointerLeadTime = nBuffers * (*bufferSize) * (waveFormat.wBitsPerSample / 8) * channels; - - // If the user wants an even bigger buffer, increase the device buffer size accordingly. - while ( dsPointerLeadTime * 2U > dsBufferSize ) - dsBufferSize *= 2; - - // Setup the secondary DS buffer description. - DSCBUFFERDESC bufferDescription; - ZeroMemory( &bufferDescription, sizeof( DSCBUFFERDESC ) ); - bufferDescription.dwSize = sizeof( DSCBUFFERDESC ); - bufferDescription.dwFlags = 0; - bufferDescription.dwReserved = 0; - bufferDescription.dwBufferBytes = dsBufferSize; - bufferDescription.lpwfxFormat = &waveFormat; - - // Create the capture buffer. - LPDIRECTSOUNDCAPTUREBUFFER buffer; - result = input->CreateCaptureBuffer( &bufferDescription, &buffer, NULL ); - if ( FAILED( result ) ) { - input->Release(); - errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") creating input buffer (" << dsDevices[ device ].name << ")!"; - errorText_ = errorStream_.str(); - return FAILURE; - } - - // Get the buffer size ... might be different from what we specified. - DSCBCAPS dscbcaps; - dscbcaps.dwSize = sizeof( DSCBCAPS ); - result = buffer->GetCaps( &dscbcaps ); - if ( FAILED( result ) ) { - input->Release(); - buffer->Release(); - errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") getting buffer settings (" << dsDevices[ device ].name << ")!"; - errorText_ = errorStream_.str(); - return FAILURE; - } - - dsBufferSize = dscbcaps.dwBufferBytes; - - // NOTE: We could have a problem here if this is a duplex stream - // and the play and capture hardware buffer sizes are different - // (I'm actually not sure if that is a problem or not). - // Currently, we are not verifying that. - - // Lock the capture buffer - LPVOID audioPtr; - DWORD dataLen; - result = buffer->Lock( 0, dsBufferSize, &audioPtr, &dataLen, NULL, NULL, 0 ); - if ( FAILED( result ) ) { - input->Release(); - buffer->Release(); - errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") locking input buffer (" << dsDevices[ device ].name << ")!"; - errorText_ = errorStream_.str(); - return FAILURE; - } - - // Zero the buffer - ZeroMemory( audioPtr, dataLen ); - - // Unlock the buffer - result = buffer->Unlock( audioPtr, dataLen, NULL, 0 ); - if ( FAILED( result ) ) { - input->Release(); - buffer->Release(); - errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") unlocking input buffer (" << dsDevices[ device ].name << ")!"; - errorText_ = errorStream_.str(); - return FAILURE; - } - - ohandle = (void *) input; - bhandle = (void *) buffer; - } - - // Set various stream parameters - DsHandle *handle = 0; - stream_.nDeviceChannels[mode] = channels + firstChannel; - stream_.nUserChannels[mode] = channels; - stream_.bufferSize = *bufferSize; - stream_.channelOffset[mode] = firstChannel; - stream_.deviceInterleaved[mode] = true; - if ( options && options->flags & RTAUDIO_NONINTERLEAVED ) stream_.userInterleaved = false; - else stream_.userInterleaved = true; - - // Set flag for buffer conversion - stream_.doConvertBuffer[mode] = false; - if (stream_.nUserChannels[mode] != stream_.nDeviceChannels[mode]) - stream_.doConvertBuffer[mode] = true; - if (stream_.userFormat != stream_.deviceFormat[mode]) - stream_.doConvertBuffer[mode] = true; - if ( stream_.userInterleaved != stream_.deviceInterleaved[mode] && - stream_.nUserChannels[mode] > 1 ) - stream_.doConvertBuffer[mode] = true; - - // Allocate necessary internal buffers - long bufferBytes = stream_.nUserChannels[mode] * *bufferSize * formatBytes( stream_.userFormat ); - stream_.userBuffer[mode] = (char *) calloc( bufferBytes, 1 ); - if ( stream_.userBuffer[mode] == NULL ) { - errorText_ = "RtApiDs::probeDeviceOpen: error allocating user buffer memory."; - goto error; - } - - if ( stream_.doConvertBuffer[mode] ) { - - bool makeBuffer = true; - bufferBytes = stream_.nDeviceChannels[mode] * formatBytes( stream_.deviceFormat[mode] ); - if ( mode == INPUT ) { - if ( stream_.mode == OUTPUT && stream_.deviceBuffer ) { - unsigned long bytesOut = stream_.nDeviceChannels[0] * formatBytes( stream_.deviceFormat[0] ); - if ( bufferBytes <= (long) bytesOut ) makeBuffer = false; - } - } - - if ( makeBuffer ) { - bufferBytes *= *bufferSize; - if ( stream_.deviceBuffer ) free( stream_.deviceBuffer ); - stream_.deviceBuffer = (char *) calloc( bufferBytes, 1 ); - if ( stream_.deviceBuffer == NULL ) { - errorText_ = "RtApiDs::probeDeviceOpen: error allocating device buffer memory."; - goto error; - } - } - } - - // Allocate our DsHandle structures for the stream. - if ( stream_.apiHandle == 0 ) { - try { - handle = new DsHandle; - } - catch ( std::bad_alloc& ) { - errorText_ = "RtApiDs::probeDeviceOpen: error allocating AsioHandle memory."; - goto error; - } - - // Create a manual-reset event. - handle->condition = CreateEvent( NULL, // no security - TRUE, // manual-reset - FALSE, // non-signaled initially - NULL ); // unnamed - stream_.apiHandle = (void *) handle; - } - else - handle = (DsHandle *) stream_.apiHandle; - handle->id[mode] = ohandle; - handle->buffer[mode] = bhandle; - handle->dsBufferSize[mode] = dsBufferSize; - handle->dsPointerLeadTime[mode] = dsPointerLeadTime; - - stream_.device[mode] = device; - stream_.state = STREAM_STOPPED; - if ( stream_.mode == OUTPUT && mode == INPUT ) - // We had already set up an output stream. - stream_.mode = DUPLEX; - else - stream_.mode = mode; - stream_.nBuffers = nBuffers; - stream_.sampleRate = sampleRate; - - // Setup the buffer conversion information structure. - if ( stream_.doConvertBuffer[mode] ) setConvertInfo( mode, firstChannel ); - - // Setup the callback thread. - if ( stream_.callbackInfo.isRunning == false ) { - unsigned threadId; - stream_.callbackInfo.isRunning = true; - stream_.callbackInfo.object = (void *) this; - stream_.callbackInfo.thread = _beginthreadex( NULL, 0, &callbackHandler, - &stream_.callbackInfo, 0, &threadId ); - if ( stream_.callbackInfo.thread == 0 ) { - errorText_ = "RtApiDs::probeDeviceOpen: error creating callback thread!"; - goto error; - } - - // Boost DS thread priority - SetThreadPriority( (HANDLE) stream_.callbackInfo.thread, THREAD_PRIORITY_HIGHEST ); - } - return SUCCESS; - - error: - if ( handle ) { - if ( handle->buffer[0] ) { // the object pointer can be NULL and valid - LPDIRECTSOUND object = (LPDIRECTSOUND) handle->id[0]; - LPDIRECTSOUNDBUFFER buffer = (LPDIRECTSOUNDBUFFER) handle->buffer[0]; - if ( buffer ) buffer->Release(); - object->Release(); - } - if ( handle->buffer[1] ) { - LPDIRECTSOUNDCAPTURE object = (LPDIRECTSOUNDCAPTURE) handle->id[1]; - LPDIRECTSOUNDCAPTUREBUFFER buffer = (LPDIRECTSOUNDCAPTUREBUFFER) handle->buffer[1]; - if ( buffer ) buffer->Release(); - object->Release(); - } - CloseHandle( handle->condition ); - delete handle; - stream_.apiHandle = 0; - } - - for ( int i=0; i<2; i++ ) { - if ( stream_.userBuffer[i] ) { - free( stream_.userBuffer[i] ); - stream_.userBuffer[i] = 0; - } - } - - if ( stream_.deviceBuffer ) { - free( stream_.deviceBuffer ); - stream_.deviceBuffer = 0; - } - - stream_.state = STREAM_CLOSED; - return FAILURE; -} - -void RtApiDs :: closeStream() -{ - if ( stream_.state == STREAM_CLOSED ) { - errorText_ = "RtApiDs::closeStream(): no open stream to close!"; - error( RtAudioError::WARNING ); - return; - } - - // Stop the callback thread. - stream_.callbackInfo.isRunning = false; - WaitForSingleObject( (HANDLE) stream_.callbackInfo.thread, INFINITE ); - CloseHandle( (HANDLE) stream_.callbackInfo.thread ); - - DsHandle *handle = (DsHandle *) stream_.apiHandle; - if ( handle ) { - if ( handle->buffer[0] ) { // the object pointer can be NULL and valid - LPDIRECTSOUND object = (LPDIRECTSOUND) handle->id[0]; - LPDIRECTSOUNDBUFFER buffer = (LPDIRECTSOUNDBUFFER) handle->buffer[0]; - if ( buffer ) { - buffer->Stop(); - buffer->Release(); - } - object->Release(); - } - if ( handle->buffer[1] ) { - LPDIRECTSOUNDCAPTURE object = (LPDIRECTSOUNDCAPTURE) handle->id[1]; - LPDIRECTSOUNDCAPTUREBUFFER buffer = (LPDIRECTSOUNDCAPTUREBUFFER) handle->buffer[1]; - if ( buffer ) { - buffer->Stop(); - buffer->Release(); - } - object->Release(); - } - CloseHandle( handle->condition ); - delete handle; - stream_.apiHandle = 0; - } - - for ( int i=0; i<2; i++ ) { - if ( stream_.userBuffer[i] ) { - free( stream_.userBuffer[i] ); - stream_.userBuffer[i] = 0; - } - } - - if ( stream_.deviceBuffer ) { - free( stream_.deviceBuffer ); - stream_.deviceBuffer = 0; - } - - stream_.mode = UNINITIALIZED; - stream_.state = STREAM_CLOSED; -} - -void RtApiDs :: startStream() -{ - verifyStream(); - if ( stream_.state == STREAM_RUNNING ) { - errorText_ = "RtApiDs::startStream(): the stream is already running!"; - error( RtAudioError::WARNING ); - return; - } - - DsHandle *handle = (DsHandle *) stream_.apiHandle; - - // Increase scheduler frequency on lesser windows (a side-effect of - // increasing timer accuracy). On greater windows (Win2K or later), - // this is already in effect. - timeBeginPeriod( 1 ); - - buffersRolling = false; - duplexPrerollBytes = 0; - - if ( stream_.mode == DUPLEX ) { - // 0.5 seconds of silence in DUPLEX mode while the devices spin up and synchronize. - duplexPrerollBytes = (int) ( 0.5 * stream_.sampleRate * formatBytes( stream_.deviceFormat[1] ) * stream_.nDeviceChannels[1] ); - } - - HRESULT result = 0; - if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { - - LPDIRECTSOUNDBUFFER buffer = (LPDIRECTSOUNDBUFFER) handle->buffer[0]; - result = buffer->Play( 0, 0, DSBPLAY_LOOPING ); - if ( FAILED( result ) ) { - errorStream_ << "RtApiDs::startStream: error (" << getErrorString( result ) << ") starting output buffer!"; - errorText_ = errorStream_.str(); - goto unlock; - } - } - - if ( stream_.mode == INPUT || stream_.mode == DUPLEX ) { - - LPDIRECTSOUNDCAPTUREBUFFER buffer = (LPDIRECTSOUNDCAPTUREBUFFER) handle->buffer[1]; - result = buffer->Start( DSCBSTART_LOOPING ); - if ( FAILED( result ) ) { - errorStream_ << "RtApiDs::startStream: error (" << getErrorString( result ) << ") starting input buffer!"; - errorText_ = errorStream_.str(); - goto unlock; - } - } - - handle->drainCounter = 0; - handle->internalDrain = false; - ResetEvent( handle->condition ); - stream_.state = STREAM_RUNNING; - - unlock: - if ( FAILED( result ) ) error( RtAudioError::SYSTEM_ERROR ); -} - -void RtApiDs :: stopStream() -{ - verifyStream(); - if ( stream_.state == STREAM_STOPPED ) { - errorText_ = "RtApiDs::stopStream(): the stream is already stopped!"; - error( RtAudioError::WARNING ); - return; - } - - HRESULT result = 0; - LPVOID audioPtr; - DWORD dataLen; - DsHandle *handle = (DsHandle *) stream_.apiHandle; - if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { - if ( handle->drainCounter == 0 ) { - handle->drainCounter = 2; - WaitForSingleObject( handle->condition, INFINITE ); // block until signaled - } - - stream_.state = STREAM_STOPPED; - - MUTEX_LOCK( &stream_.mutex ); - - // Stop the buffer and clear memory - LPDIRECTSOUNDBUFFER buffer = (LPDIRECTSOUNDBUFFER) handle->buffer[0]; - result = buffer->Stop(); - if ( FAILED( result ) ) { - errorStream_ << "RtApiDs::stopStream: error (" << getErrorString( result ) << ") stopping output buffer!"; - errorText_ = errorStream_.str(); - goto unlock; - } - - // Lock the buffer and clear it so that if we start to play again, - // we won't have old data playing. - result = buffer->Lock( 0, handle->dsBufferSize[0], &audioPtr, &dataLen, NULL, NULL, 0 ); - if ( FAILED( result ) ) { - errorStream_ << "RtApiDs::stopStream: error (" << getErrorString( result ) << ") locking output buffer!"; - errorText_ = errorStream_.str(); - goto unlock; - } - - // Zero the DS buffer - ZeroMemory( audioPtr, dataLen ); - - // Unlock the DS buffer - result = buffer->Unlock( audioPtr, dataLen, NULL, 0 ); - if ( FAILED( result ) ) { - errorStream_ << "RtApiDs::stopStream: error (" << getErrorString( result ) << ") unlocking output buffer!"; - errorText_ = errorStream_.str(); - goto unlock; - } - - // If we start playing again, we must begin at beginning of buffer. - handle->bufferPointer[0] = 0; - } - - if ( stream_.mode == INPUT || stream_.mode == DUPLEX ) { - LPDIRECTSOUNDCAPTUREBUFFER buffer = (LPDIRECTSOUNDCAPTUREBUFFER) handle->buffer[1]; - audioPtr = NULL; - dataLen = 0; - - stream_.state = STREAM_STOPPED; - - if ( stream_.mode != DUPLEX ) - MUTEX_LOCK( &stream_.mutex ); - - result = buffer->Stop(); - if ( FAILED( result ) ) { - errorStream_ << "RtApiDs::stopStream: error (" << getErrorString( result ) << ") stopping input buffer!"; - errorText_ = errorStream_.str(); - goto unlock; - } - - // Lock the buffer and clear it so that if we start to play again, - // we won't have old data playing. - result = buffer->Lock( 0, handle->dsBufferSize[1], &audioPtr, &dataLen, NULL, NULL, 0 ); - if ( FAILED( result ) ) { - errorStream_ << "RtApiDs::stopStream: error (" << getErrorString( result ) << ") locking input buffer!"; - errorText_ = errorStream_.str(); - goto unlock; - } - - // Zero the DS buffer - ZeroMemory( audioPtr, dataLen ); - - // Unlock the DS buffer - result = buffer->Unlock( audioPtr, dataLen, NULL, 0 ); - if ( FAILED( result ) ) { - errorStream_ << "RtApiDs::stopStream: error (" << getErrorString( result ) << ") unlocking input buffer!"; - errorText_ = errorStream_.str(); - goto unlock; - } - - // If we start recording again, we must begin at beginning of buffer. - handle->bufferPointer[1] = 0; - } - - unlock: - timeEndPeriod( 1 ); // revert to normal scheduler frequency on lesser windows. - MUTEX_UNLOCK( &stream_.mutex ); - - if ( FAILED( result ) ) error( RtAudioError::SYSTEM_ERROR ); -} - -void RtApiDs :: abortStream() -{ - verifyStream(); - if ( stream_.state == STREAM_STOPPED ) { - errorText_ = "RtApiDs::abortStream(): the stream is already stopped!"; - error( RtAudioError::WARNING ); - return; - } - - DsHandle *handle = (DsHandle *) stream_.apiHandle; - handle->drainCounter = 2; - - stopStream(); -} - -void RtApiDs :: callbackEvent() -{ - if ( stream_.state == STREAM_STOPPED || stream_.state == STREAM_STOPPING ) { - Sleep( 50 ); // sleep 50 milliseconds - return; - } - - if ( stream_.state == STREAM_CLOSED ) { - errorText_ = "RtApiDs::callbackEvent(): the stream is closed ... this shouldn't happen!"; - error( RtAudioError::WARNING ); - return; - } - - CallbackInfo *info = (CallbackInfo *) &stream_.callbackInfo; - DsHandle *handle = (DsHandle *) stream_.apiHandle; - - // Check if we were draining the stream and signal is finished. - if ( handle->drainCounter > stream_.nBuffers + 2 ) { - - stream_.state = STREAM_STOPPING; - if ( handle->internalDrain == false ) - SetEvent( handle->condition ); - else - stopStream(); - return; - } - - // Invoke user callback to get fresh output data UNLESS we are - // draining stream. - if ( handle->drainCounter == 0 ) { - RtAudioCallback callback = (RtAudioCallback) info->callback; - double streamTime = getStreamTime(); - RtAudioStreamStatus status = 0; - if ( stream_.mode != INPUT && handle->xrun[0] == true ) { - status |= RTAUDIO_OUTPUT_UNDERFLOW; - handle->xrun[0] = false; - } - if ( stream_.mode != OUTPUT && handle->xrun[1] == true ) { - status |= RTAUDIO_INPUT_OVERFLOW; - handle->xrun[1] = false; - } - int cbReturnValue = callback( stream_.userBuffer[0], stream_.userBuffer[1], - stream_.bufferSize, streamTime, status, info->userData ); - if ( cbReturnValue == 2 ) { - stream_.state = STREAM_STOPPING; - handle->drainCounter = 2; - abortStream(); - return; - } - else if ( cbReturnValue == 1 ) { - handle->drainCounter = 1; - handle->internalDrain = true; - } - } - - HRESULT result; - DWORD currentWritePointer, safeWritePointer; - DWORD currentReadPointer, safeReadPointer; - UINT nextWritePointer; - - LPVOID buffer1 = NULL; - LPVOID buffer2 = NULL; - DWORD bufferSize1 = 0; - DWORD bufferSize2 = 0; - - char *buffer; - long bufferBytes; - - MUTEX_LOCK( &stream_.mutex ); - if ( stream_.state == STREAM_STOPPED ) { - MUTEX_UNLOCK( &stream_.mutex ); - return; - } - - if ( buffersRolling == false ) { - if ( stream_.mode == DUPLEX ) { - //assert( handle->dsBufferSize[0] == handle->dsBufferSize[1] ); - - // It takes a while for the devices to get rolling. As a result, - // there's no guarantee that the capture and write device pointers - // will move in lockstep. Wait here for both devices to start - // rolling, and then set our buffer pointers accordingly. - // e.g. Crystal Drivers: the capture buffer starts up 5700 to 9600 - // bytes later than the write buffer. - - // Stub: a serious risk of having a pre-emptive scheduling round - // take place between the two GetCurrentPosition calls... but I'm - // really not sure how to solve the problem. Temporarily boost to - // Realtime priority, maybe; but I'm not sure what priority the - // DirectSound service threads run at. We *should* be roughly - // within a ms or so of correct. - - LPDIRECTSOUNDBUFFER dsWriteBuffer = (LPDIRECTSOUNDBUFFER) handle->buffer[0]; - LPDIRECTSOUNDCAPTUREBUFFER dsCaptureBuffer = (LPDIRECTSOUNDCAPTUREBUFFER) handle->buffer[1]; - - DWORD startSafeWritePointer, startSafeReadPointer; - - result = dsWriteBuffer->GetCurrentPosition( NULL, &startSafeWritePointer ); - if ( FAILED( result ) ) { - errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current write position!"; - errorText_ = errorStream_.str(); - MUTEX_UNLOCK( &stream_.mutex ); - error( RtAudioError::SYSTEM_ERROR ); - return; - } - result = dsCaptureBuffer->GetCurrentPosition( NULL, &startSafeReadPointer ); - if ( FAILED( result ) ) { - errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current read position!"; - errorText_ = errorStream_.str(); - MUTEX_UNLOCK( &stream_.mutex ); - error( RtAudioError::SYSTEM_ERROR ); - return; - } - while ( true ) { - result = dsWriteBuffer->GetCurrentPosition( NULL, &safeWritePointer ); - if ( FAILED( result ) ) { - errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current write position!"; - errorText_ = errorStream_.str(); - MUTEX_UNLOCK( &stream_.mutex ); - error( RtAudioError::SYSTEM_ERROR ); - return; - } - result = dsCaptureBuffer->GetCurrentPosition( NULL, &safeReadPointer ); - if ( FAILED( result ) ) { - errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current read position!"; - errorText_ = errorStream_.str(); - MUTEX_UNLOCK( &stream_.mutex ); - error( RtAudioError::SYSTEM_ERROR ); - return; - } - if ( safeWritePointer != startSafeWritePointer && safeReadPointer != startSafeReadPointer ) break; - Sleep( 1 ); - } - - //assert( handle->dsBufferSize[0] == handle->dsBufferSize[1] ); - - handle->bufferPointer[0] = safeWritePointer + handle->dsPointerLeadTime[0]; - if ( handle->bufferPointer[0] >= handle->dsBufferSize[0] ) handle->bufferPointer[0] -= handle->dsBufferSize[0]; - handle->bufferPointer[1] = safeReadPointer; - } - else if ( stream_.mode == OUTPUT ) { - - // Set the proper nextWritePosition after initial startup. - LPDIRECTSOUNDBUFFER dsWriteBuffer = (LPDIRECTSOUNDBUFFER) handle->buffer[0]; - result = dsWriteBuffer->GetCurrentPosition( ¤tWritePointer, &safeWritePointer ); - if ( FAILED( result ) ) { - errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current write position!"; - errorText_ = errorStream_.str(); - MUTEX_UNLOCK( &stream_.mutex ); - error( RtAudioError::SYSTEM_ERROR ); - return; - } - handle->bufferPointer[0] = safeWritePointer + handle->dsPointerLeadTime[0]; - if ( handle->bufferPointer[0] >= handle->dsBufferSize[0] ) handle->bufferPointer[0] -= handle->dsBufferSize[0]; - } - - buffersRolling = true; - } - - if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { - - LPDIRECTSOUNDBUFFER dsBuffer = (LPDIRECTSOUNDBUFFER) handle->buffer[0]; - - if ( handle->drainCounter > 1 ) { // write zeros to the output stream - bufferBytes = stream_.bufferSize * stream_.nUserChannels[0]; - bufferBytes *= formatBytes( stream_.userFormat ); - memset( stream_.userBuffer[0], 0, bufferBytes ); - } - - // Setup parameters and do buffer conversion if necessary. - if ( stream_.doConvertBuffer[0] ) { - buffer = stream_.deviceBuffer; - convertBuffer( buffer, stream_.userBuffer[0], stream_.convertInfo[0] ); - bufferBytes = stream_.bufferSize * stream_.nDeviceChannels[0]; - bufferBytes *= formatBytes( stream_.deviceFormat[0] ); - } - else { - buffer = stream_.userBuffer[0]; - bufferBytes = stream_.bufferSize * stream_.nUserChannels[0]; - bufferBytes *= formatBytes( stream_.userFormat ); - } - - // No byte swapping necessary in DirectSound implementation. - - // Ahhh ... windoze. 16-bit data is signed but 8-bit data is - // unsigned. So, we need to convert our signed 8-bit data here to - // unsigned. - if ( stream_.deviceFormat[0] == RTAUDIO_SINT8 ) - for ( int i=0; idsBufferSize[0]; - nextWritePointer = handle->bufferPointer[0]; - - DWORD endWrite, leadPointer; - while ( true ) { - // Find out where the read and "safe write" pointers are. - result = dsBuffer->GetCurrentPosition( ¤tWritePointer, &safeWritePointer ); - if ( FAILED( result ) ) { - errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current write position!"; - errorText_ = errorStream_.str(); - MUTEX_UNLOCK( &stream_.mutex ); - error( RtAudioError::SYSTEM_ERROR ); - return; - } - - // We will copy our output buffer into the region between - // safeWritePointer and leadPointer. If leadPointer is not - // beyond the next endWrite position, wait until it is. - leadPointer = safeWritePointer + handle->dsPointerLeadTime[0]; - //std::cout << "safeWritePointer = " << safeWritePointer << ", leadPointer = " << leadPointer << ", nextWritePointer = " << nextWritePointer << std::endl; - if ( leadPointer > dsBufferSize ) leadPointer -= dsBufferSize; - if ( leadPointer < nextWritePointer ) leadPointer += dsBufferSize; // unwrap offset - endWrite = nextWritePointer + bufferBytes; - - // Check whether the entire write region is behind the play pointer. - if ( leadPointer >= endWrite ) break; - - // If we are here, then we must wait until the leadPointer advances - // beyond the end of our next write region. We use the - // Sleep() function to suspend operation until that happens. - double millis = ( endWrite - leadPointer ) * 1000.0; - millis /= ( formatBytes( stream_.deviceFormat[0]) * stream_.nDeviceChannels[0] * stream_.sampleRate); - if ( millis < 1.0 ) millis = 1.0; - Sleep( (DWORD) millis ); - } - - if ( dsPointerBetween( nextWritePointer, safeWritePointer, currentWritePointer, dsBufferSize ) - || dsPointerBetween( endWrite, safeWritePointer, currentWritePointer, dsBufferSize ) ) { - // We've strayed into the forbidden zone ... resync the read pointer. - handle->xrun[0] = true; - nextWritePointer = safeWritePointer + handle->dsPointerLeadTime[0] - bufferBytes; - if ( nextWritePointer >= dsBufferSize ) nextWritePointer -= dsBufferSize; - handle->bufferPointer[0] = nextWritePointer; - endWrite = nextWritePointer + bufferBytes; - } - - // Lock free space in the buffer - result = dsBuffer->Lock( nextWritePointer, bufferBytes, &buffer1, - &bufferSize1, &buffer2, &bufferSize2, 0 ); - if ( FAILED( result ) ) { - errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") locking buffer during playback!"; - errorText_ = errorStream_.str(); - MUTEX_UNLOCK( &stream_.mutex ); - error( RtAudioError::SYSTEM_ERROR ); - return; - } - - // Copy our buffer into the DS buffer - CopyMemory( buffer1, buffer, bufferSize1 ); - if ( buffer2 != NULL ) CopyMemory( buffer2, buffer+bufferSize1, bufferSize2 ); - - // Update our buffer offset and unlock sound buffer - dsBuffer->Unlock( buffer1, bufferSize1, buffer2, bufferSize2 ); - if ( FAILED( result ) ) { - errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") unlocking buffer during playback!"; - errorText_ = errorStream_.str(); - MUTEX_UNLOCK( &stream_.mutex ); - error( RtAudioError::SYSTEM_ERROR ); - return; - } - nextWritePointer = ( nextWritePointer + bufferSize1 + bufferSize2 ) % dsBufferSize; - handle->bufferPointer[0] = nextWritePointer; - } - - // Don't bother draining input - if ( handle->drainCounter ) { - handle->drainCounter++; - goto unlock; - } - - if ( stream_.mode == INPUT || stream_.mode == DUPLEX ) { - - // Setup parameters. - if ( stream_.doConvertBuffer[1] ) { - buffer = stream_.deviceBuffer; - bufferBytes = stream_.bufferSize * stream_.nDeviceChannels[1]; - bufferBytes *= formatBytes( stream_.deviceFormat[1] ); - } - else { - buffer = stream_.userBuffer[1]; - bufferBytes = stream_.bufferSize * stream_.nUserChannels[1]; - bufferBytes *= formatBytes( stream_.userFormat ); - } - - LPDIRECTSOUNDCAPTUREBUFFER dsBuffer = (LPDIRECTSOUNDCAPTUREBUFFER) handle->buffer[1]; - long nextReadPointer = handle->bufferPointer[1]; - DWORD dsBufferSize = handle->dsBufferSize[1]; - - // Find out where the write and "safe read" pointers are. - result = dsBuffer->GetCurrentPosition( ¤tReadPointer, &safeReadPointer ); - if ( FAILED( result ) ) { - errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current read position!"; - errorText_ = errorStream_.str(); - MUTEX_UNLOCK( &stream_.mutex ); - error( RtAudioError::SYSTEM_ERROR ); - return; - } - - if ( safeReadPointer < (DWORD)nextReadPointer ) safeReadPointer += dsBufferSize; // unwrap offset - DWORD endRead = nextReadPointer + bufferBytes; - - // Handling depends on whether we are INPUT or DUPLEX. - // If we're in INPUT mode then waiting is a good thing. If we're in DUPLEX mode, - // then a wait here will drag the write pointers into the forbidden zone. - // - // In DUPLEX mode, rather than wait, we will back off the read pointer until - // it's in a safe position. This causes dropouts, but it seems to be the only - // practical way to sync up the read and write pointers reliably, given the - // the very complex relationship between phase and increment of the read and write - // pointers. - // - // In order to minimize audible dropouts in DUPLEX mode, we will - // provide a pre-roll period of 0.5 seconds in which we return - // zeros from the read buffer while the pointers sync up. - - if ( stream_.mode == DUPLEX ) { - if ( safeReadPointer < endRead ) { - if ( duplexPrerollBytes <= 0 ) { - // Pre-roll time over. Be more agressive. - int adjustment = endRead-safeReadPointer; - - handle->xrun[1] = true; - // Two cases: - // - large adjustments: we've probably run out of CPU cycles, so just resync exactly, - // and perform fine adjustments later. - // - small adjustments: back off by twice as much. - if ( adjustment >= 2*bufferBytes ) - nextReadPointer = safeReadPointer-2*bufferBytes; - else - nextReadPointer = safeReadPointer-bufferBytes-adjustment; - - if ( nextReadPointer < 0 ) nextReadPointer += dsBufferSize; - - } - else { - // In pre=roll time. Just do it. - nextReadPointer = safeReadPointer - bufferBytes; - while ( nextReadPointer < 0 ) nextReadPointer += dsBufferSize; - } - endRead = nextReadPointer + bufferBytes; - } - } - else { // mode == INPUT - while ( safeReadPointer < endRead && stream_.callbackInfo.isRunning ) { - // See comments for playback. - double millis = (endRead - safeReadPointer) * 1000.0; - millis /= ( formatBytes(stream_.deviceFormat[1]) * stream_.nDeviceChannels[1] * stream_.sampleRate); - if ( millis < 1.0 ) millis = 1.0; - Sleep( (DWORD) millis ); - - // Wake up and find out where we are now. - result = dsBuffer->GetCurrentPosition( ¤tReadPointer, &safeReadPointer ); - if ( FAILED( result ) ) { - errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current read position!"; - errorText_ = errorStream_.str(); - MUTEX_UNLOCK( &stream_.mutex ); - error( RtAudioError::SYSTEM_ERROR ); - return; - } - - if ( safeReadPointer < (DWORD)nextReadPointer ) safeReadPointer += dsBufferSize; // unwrap offset - } - } - - // Lock free space in the buffer - result = dsBuffer->Lock( nextReadPointer, bufferBytes, &buffer1, - &bufferSize1, &buffer2, &bufferSize2, 0 ); - if ( FAILED( result ) ) { - errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") locking capture buffer!"; - errorText_ = errorStream_.str(); - MUTEX_UNLOCK( &stream_.mutex ); - error( RtAudioError::SYSTEM_ERROR ); - return; - } - - if ( duplexPrerollBytes <= 0 ) { - // Copy our buffer into the DS buffer - CopyMemory( buffer, buffer1, bufferSize1 ); - if ( buffer2 != NULL ) CopyMemory( buffer+bufferSize1, buffer2, bufferSize2 ); - } - else { - memset( buffer, 0, bufferSize1 ); - if ( buffer2 != NULL ) memset( buffer + bufferSize1, 0, bufferSize2 ); - duplexPrerollBytes -= bufferSize1 + bufferSize2; - } - - // Update our buffer offset and unlock sound buffer - nextReadPointer = ( nextReadPointer + bufferSize1 + bufferSize2 ) % dsBufferSize; - dsBuffer->Unlock( buffer1, bufferSize1, buffer2, bufferSize2 ); - if ( FAILED( result ) ) { - errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") unlocking capture buffer!"; - errorText_ = errorStream_.str(); - MUTEX_UNLOCK( &stream_.mutex ); - error( RtAudioError::SYSTEM_ERROR ); - return; - } - handle->bufferPointer[1] = nextReadPointer; - - // No byte swapping necessary in DirectSound implementation. - - // If necessary, convert 8-bit data from unsigned to signed. - if ( stream_.deviceFormat[1] == RTAUDIO_SINT8 ) - for ( int j=0; jobject; - bool* isRunning = &info->isRunning; - - while ( *isRunning == true ) { - object->callbackEvent(); - } - - _endthreadex( 0 ); - return 0; -} - -static BOOL CALLBACK deviceQueryCallback( LPGUID lpguid, - LPCTSTR description, - LPCTSTR /*module*/, - LPVOID lpContext ) -{ - struct DsProbeData& probeInfo = *(struct DsProbeData*) lpContext; - std::vector& dsDevices = *probeInfo.dsDevices; - - HRESULT hr; - bool validDevice = false; - if ( probeInfo.isInput == true ) { - DSCCAPS caps; - LPDIRECTSOUNDCAPTURE object; - - hr = DirectSoundCaptureCreate( lpguid, &object, NULL ); - if ( hr != DS_OK ) return TRUE; - - caps.dwSize = sizeof(caps); - hr = object->GetCaps( &caps ); - if ( hr == DS_OK ) { - if ( caps.dwChannels > 0 && caps.dwFormats > 0 ) - validDevice = true; - } - object->Release(); - } - else { - DSCAPS caps; - LPDIRECTSOUND object; - hr = DirectSoundCreate( lpguid, &object, NULL ); - if ( hr != DS_OK ) return TRUE; - - caps.dwSize = sizeof(caps); - hr = object->GetCaps( &caps ); - if ( hr == DS_OK ) { - if ( caps.dwFlags & DSCAPS_PRIMARYMONO || caps.dwFlags & DSCAPS_PRIMARYSTEREO ) - validDevice = true; - } - object->Release(); - } - - // If good device, then save its name and guid. - std::string name = convertCharPointerToStdString( description ); - //if ( name == "Primary Sound Driver" || name == "Primary Sound Capture Driver" ) - if ( lpguid == NULL ) - name = "Default Device"; - if ( validDevice ) { - for ( unsigned int i=0; i -#include - - // A structure to hold various information related to the ALSA API - // implementation. -struct AlsaHandle { - snd_pcm_t *handles[2]; - bool synchronized; - bool xrun[2]; - pthread_cond_t runnable_cv; - bool runnable; - - AlsaHandle() - :synchronized(false), runnable(false) { xrun[0] = false; xrun[1] = false; } -}; - -static void *alsaCallbackHandler( void * ptr ); - -RtApiAlsa :: RtApiAlsa() -{ - // Nothing to do here. -} - -RtApiAlsa :: ~RtApiAlsa() -{ - if ( stream_.state != STREAM_CLOSED ) closeStream(); -} - -unsigned int RtApiAlsa :: getDeviceCount( void ) -{ - unsigned nDevices = 0; - int result, subdevice, card; - char name[64]; - snd_ctl_t *handle; - - // Count cards and devices - card = -1; - snd_card_next( &card ); - while ( card >= 0 ) { - sprintf( name, "hw:%d", card ); - result = snd_ctl_open( &handle, name, 0 ); - if ( result < 0 ) { - errorStream_ << "RtApiAlsa::getDeviceCount: control open, card = " << card << ", " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - goto nextcard; - } - subdevice = -1; - while( 1 ) { - result = snd_ctl_pcm_next_device( handle, &subdevice ); - if ( result < 0 ) { - errorStream_ << "RtApiAlsa::getDeviceCount: control next device, card = " << card << ", " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - break; - } - if ( subdevice < 0 ) - break; - nDevices++; - } - nextcard: - snd_ctl_close( handle ); - snd_card_next( &card ); - } - - result = snd_ctl_open( &handle, "default", 0 ); - if (result == 0) { - nDevices++; - snd_ctl_close( handle ); - } - - return nDevices; -} - -RtAudio::DeviceInfo RtApiAlsa :: getDeviceInfo( unsigned int device ) -{ - RtAudio::DeviceInfo info; - info.probed = false; - - unsigned nDevices = 0; - int result, subdevice, card; - char name[64]; - snd_ctl_t *chandle; - - // Count cards and devices - card = -1; - subdevice = -1; - snd_card_next( &card ); - while ( card >= 0 ) { - sprintf( name, "hw:%d", card ); - result = snd_ctl_open( &chandle, name, SND_CTL_NONBLOCK ); - if ( result < 0 ) { - errorStream_ << "RtApiAlsa::getDeviceInfo: control open, card = " << card << ", " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - goto nextcard; - } - subdevice = -1; - while( 1 ) { - result = snd_ctl_pcm_next_device( chandle, &subdevice ); - if ( result < 0 ) { - errorStream_ << "RtApiAlsa::getDeviceInfo: control next device, card = " << card << ", " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - break; - } - if ( subdevice < 0 ) break; - if ( nDevices == device ) { - sprintf( name, "hw:%d,%d", card, subdevice ); - goto foundDevice; - } - nDevices++; - } - nextcard: - snd_ctl_close( chandle ); - snd_card_next( &card ); - } - - result = snd_ctl_open( &chandle, "default", SND_CTL_NONBLOCK ); - if ( result == 0 ) { - if ( nDevices == device ) { - strcpy( name, "default" ); - goto foundDevice; - } - nDevices++; - } - - if ( nDevices == 0 ) { - errorText_ = "RtApiAlsa::getDeviceInfo: no devices found!"; - error( RtAudioError::INVALID_USE ); - return info; - } - - if ( device >= nDevices ) { - errorText_ = "RtApiAlsa::getDeviceInfo: device ID is invalid!"; - error( RtAudioError::INVALID_USE ); - return info; - } - - foundDevice: - - // If a stream is already open, we cannot probe the stream devices. - // Thus, use the saved results. - if ( stream_.state != STREAM_CLOSED && - ( stream_.device[0] == device || stream_.device[1] == device ) ) { - snd_ctl_close( chandle ); - if ( device >= devices_.size() ) { - errorText_ = "RtApiAlsa::getDeviceInfo: device ID was not present before stream was opened."; - error( RtAudioError::WARNING ); - return info; - } - return devices_[ device ]; - } - - int openMode = SND_PCM_ASYNC; - snd_pcm_stream_t stream; - snd_pcm_info_t *pcminfo; - snd_pcm_info_alloca( &pcminfo ); - snd_pcm_t *phandle; - snd_pcm_hw_params_t *params; - snd_pcm_hw_params_alloca( ¶ms ); - - // First try for playback unless default device (which has subdev -1) - stream = SND_PCM_STREAM_PLAYBACK; - snd_pcm_info_set_stream( pcminfo, stream ); - if ( subdevice != -1 ) { - snd_pcm_info_set_device( pcminfo, subdevice ); - snd_pcm_info_set_subdevice( pcminfo, 0 ); - - result = snd_ctl_pcm_info( chandle, pcminfo ); - if ( result < 0 ) { - // Device probably doesn't support playback. - goto captureProbe; - } - } - - result = snd_pcm_open( &phandle, name, stream, openMode | SND_PCM_NONBLOCK ); - if ( result < 0 ) { - errorStream_ << "RtApiAlsa::getDeviceInfo: snd_pcm_open error for device (" << name << "), " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - goto captureProbe; - } - - // The device is open ... fill the parameter structure. - result = snd_pcm_hw_params_any( phandle, params ); - if ( result < 0 ) { - snd_pcm_close( phandle ); - errorStream_ << "RtApiAlsa::getDeviceInfo: snd_pcm_hw_params error for device (" << name << "), " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - goto captureProbe; - } - - // Get output channel information. - unsigned int value; - result = snd_pcm_hw_params_get_channels_max( params, &value ); - if ( result < 0 ) { - snd_pcm_close( phandle ); - errorStream_ << "RtApiAlsa::getDeviceInfo: error getting device (" << name << ") output channels, " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - goto captureProbe; - } - info.outputChannels = value; - snd_pcm_close( phandle ); - - captureProbe: - stream = SND_PCM_STREAM_CAPTURE; - snd_pcm_info_set_stream( pcminfo, stream ); - - // Now try for capture unless default device (with subdev = -1) - if ( subdevice != -1 ) { - result = snd_ctl_pcm_info( chandle, pcminfo ); - snd_ctl_close( chandle ); - if ( result < 0 ) { - // Device probably doesn't support capture. - if ( info.outputChannels == 0 ) return info; - goto probeParameters; - } - } - else - snd_ctl_close( chandle ); - - result = snd_pcm_open( &phandle, name, stream, openMode | SND_PCM_NONBLOCK); - if ( result < 0 ) { - errorStream_ << "RtApiAlsa::getDeviceInfo: snd_pcm_open error for device (" << name << "), " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - if ( info.outputChannels == 0 ) return info; - goto probeParameters; - } - - // The device is open ... fill the parameter structure. - result = snd_pcm_hw_params_any( phandle, params ); - if ( result < 0 ) { - snd_pcm_close( phandle ); - errorStream_ << "RtApiAlsa::getDeviceInfo: snd_pcm_hw_params error for device (" << name << "), " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - if ( info.outputChannels == 0 ) return info; - goto probeParameters; - } - - result = snd_pcm_hw_params_get_channels_max( params, &value ); - if ( result < 0 ) { - snd_pcm_close( phandle ); - errorStream_ << "RtApiAlsa::getDeviceInfo: error getting device (" << name << ") input channels, " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - if ( info.outputChannels == 0 ) return info; - goto probeParameters; - } - info.inputChannels = value; - snd_pcm_close( phandle ); - - // If device opens for both playback and capture, we determine the channels. - if ( info.outputChannels > 0 && info.inputChannels > 0 ) - info.duplexChannels = (info.outputChannels > info.inputChannels) ? info.inputChannels : info.outputChannels; - - // ALSA doesn't provide default devices so we'll use the first available one. - if ( device == 0 && info.outputChannels > 0 ) - info.isDefaultOutput = true; - if ( device == 0 && info.inputChannels > 0 ) - info.isDefaultInput = true; - - probeParameters: - // At this point, we just need to figure out the supported data - // formats and sample rates. We'll proceed by opening the device in - // the direction with the maximum number of channels, or playback if - // they are equal. This might limit our sample rate options, but so - // be it. - - if ( info.outputChannels >= info.inputChannels ) - stream = SND_PCM_STREAM_PLAYBACK; - else - stream = SND_PCM_STREAM_CAPTURE; - snd_pcm_info_set_stream( pcminfo, stream ); - - result = snd_pcm_open( &phandle, name, stream, openMode | SND_PCM_NONBLOCK); - if ( result < 0 ) { - errorStream_ << "RtApiAlsa::getDeviceInfo: snd_pcm_open error for device (" << name << "), " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - return info; - } - - // The device is open ... fill the parameter structure. - result = snd_pcm_hw_params_any( phandle, params ); - if ( result < 0 ) { - snd_pcm_close( phandle ); - errorStream_ << "RtApiAlsa::getDeviceInfo: snd_pcm_hw_params error for device (" << name << "), " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - return info; - } - - // Test our discrete set of sample rate values. - info.sampleRates.clear(); - for ( unsigned int i=0; i info.preferredSampleRate ) ) - info.preferredSampleRate = SAMPLE_RATES[i]; - } - } - if ( info.sampleRates.size() == 0 ) { - snd_pcm_close( phandle ); - errorStream_ << "RtApiAlsa::getDeviceInfo: no supported sample rates found for device (" << name << ")."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - return info; - } - - // Probe the supported data formats ... we don't care about endian-ness just yet - snd_pcm_format_t format; - info.nativeFormats = 0; - format = SND_PCM_FORMAT_S8; - if ( snd_pcm_hw_params_test_format( phandle, params, format ) == 0 ) - info.nativeFormats |= RTAUDIO_SINT8; - format = SND_PCM_FORMAT_S16; - if ( snd_pcm_hw_params_test_format( phandle, params, format ) == 0 ) - info.nativeFormats |= RTAUDIO_SINT16; - format = SND_PCM_FORMAT_S24; - if ( snd_pcm_hw_params_test_format( phandle, params, format ) == 0 ) - info.nativeFormats |= RTAUDIO_SINT24; - format = SND_PCM_FORMAT_S32; - if ( snd_pcm_hw_params_test_format( phandle, params, format ) == 0 ) - info.nativeFormats |= RTAUDIO_SINT32; - format = SND_PCM_FORMAT_FLOAT; - if ( snd_pcm_hw_params_test_format( phandle, params, format ) == 0 ) - info.nativeFormats |= RTAUDIO_FLOAT32; - format = SND_PCM_FORMAT_FLOAT64; - if ( snd_pcm_hw_params_test_format( phandle, params, format ) == 0 ) - info.nativeFormats |= RTAUDIO_FLOAT64; - - // Check that we have at least one supported format - if ( info.nativeFormats == 0 ) { - snd_pcm_close( phandle ); - errorStream_ << "RtApiAlsa::getDeviceInfo: pcm device (" << name << ") data format not supported by RtAudio."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - return info; - } - - // Get the device name - char *cardname; - result = snd_card_get_name( card, &cardname ); - if ( result >= 0 ) { - sprintf( name, "hw:%s,%d", cardname, subdevice ); - free( cardname ); - } - info.name = name; - - // That's all ... close the device and return - snd_pcm_close( phandle ); - info.probed = true; - return info; -} - -void RtApiAlsa :: saveDeviceInfo( void ) -{ - devices_.clear(); - - unsigned int nDevices = getDeviceCount(); - devices_.resize( nDevices ); - for ( unsigned int i=0; iflags & RTAUDIO_ALSA_USE_DEFAULT ) - snprintf(name, sizeof(name), "%s", "default"); - else { - // Count cards and devices - card = -1; - snd_card_next( &card ); - while ( card >= 0 ) { - sprintf( name, "hw:%d", card ); - result = snd_ctl_open( &chandle, name, SND_CTL_NONBLOCK ); - if ( result < 0 ) { - errorStream_ << "RtApiAlsa::probeDeviceOpen: control open, card = " << card << ", " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - return FAILURE; - } - subdevice = -1; - while( 1 ) { - result = snd_ctl_pcm_next_device( chandle, &subdevice ); - if ( result < 0 ) break; - if ( subdevice < 0 ) break; - if ( nDevices == device ) { - sprintf( name, "hw:%d,%d", card, subdevice ); - snd_ctl_close( chandle ); - goto foundDevice; - } - nDevices++; - } - snd_ctl_close( chandle ); - snd_card_next( &card ); - } - - result = snd_ctl_open( &chandle, "default", SND_CTL_NONBLOCK ); - if ( result == 0 ) { - if ( nDevices == device ) { - strcpy( name, "default" ); - goto foundDevice; - } - nDevices++; - } - - if ( nDevices == 0 ) { - // This should not happen because a check is made before this function is called. - errorText_ = "RtApiAlsa::probeDeviceOpen: no devices found!"; - return FAILURE; - } - - if ( device >= nDevices ) { - // This should not happen because a check is made before this function is called. - errorText_ = "RtApiAlsa::probeDeviceOpen: device ID is invalid!"; - return FAILURE; - } - } - - foundDevice: - - // The getDeviceInfo() function will not work for a device that is - // already open. Thus, we'll probe the system before opening a - // stream and save the results for use by getDeviceInfo(). - if ( mode == OUTPUT || ( mode == INPUT && stream_.mode != OUTPUT ) ) // only do once - this->saveDeviceInfo(); - - snd_pcm_stream_t stream; - if ( mode == OUTPUT ) - stream = SND_PCM_STREAM_PLAYBACK; - else - stream = SND_PCM_STREAM_CAPTURE; - - snd_pcm_t *phandle; - int openMode = SND_PCM_ASYNC; - result = snd_pcm_open( &phandle, name, stream, openMode ); - if ( result < 0 ) { - if ( mode == OUTPUT ) - errorStream_ << "RtApiAlsa::probeDeviceOpen: pcm device (" << name << ") won't open for output."; - else - errorStream_ << "RtApiAlsa::probeDeviceOpen: pcm device (" << name << ") won't open for input."; - errorText_ = errorStream_.str(); - return FAILURE; - } - - // Fill the parameter structure. - snd_pcm_hw_params_t *hw_params; - snd_pcm_hw_params_alloca( &hw_params ); - result = snd_pcm_hw_params_any( phandle, hw_params ); - if ( result < 0 ) { - snd_pcm_close( phandle ); - errorStream_ << "RtApiAlsa::probeDeviceOpen: error getting pcm device (" << name << ") parameters, " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - return FAILURE; - } - -#if defined(__RTAUDIO_DEBUG__) - fprintf( stderr, "\nRtApiAlsa: dump hardware params just after device open:\n\n" ); - snd_pcm_hw_params_dump( hw_params, out ); -#endif - - // Set access ... check user preference. - if ( options && options->flags & RTAUDIO_NONINTERLEAVED ) { - stream_.userInterleaved = false; - result = snd_pcm_hw_params_set_access( phandle, hw_params, SND_PCM_ACCESS_RW_NONINTERLEAVED ); - if ( result < 0 ) { - result = snd_pcm_hw_params_set_access( phandle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED ); - stream_.deviceInterleaved[mode] = true; - } - else - stream_.deviceInterleaved[mode] = false; - } - else { - stream_.userInterleaved = true; - result = snd_pcm_hw_params_set_access( phandle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED ); - if ( result < 0 ) { - result = snd_pcm_hw_params_set_access( phandle, hw_params, SND_PCM_ACCESS_RW_NONINTERLEAVED ); - stream_.deviceInterleaved[mode] = false; - } - else - stream_.deviceInterleaved[mode] = true; - } - - if ( result < 0 ) { - snd_pcm_close( phandle ); - errorStream_ << "RtApiAlsa::probeDeviceOpen: error setting pcm device (" << name << ") access, " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - return FAILURE; - } - - // Determine how to set the device format. - stream_.userFormat = format; - snd_pcm_format_t deviceFormat = SND_PCM_FORMAT_UNKNOWN; - - if ( format == RTAUDIO_SINT8 ) - deviceFormat = SND_PCM_FORMAT_S8; - else if ( format == RTAUDIO_SINT16 ) - deviceFormat = SND_PCM_FORMAT_S16; - else if ( format == RTAUDIO_SINT24 ) - deviceFormat = SND_PCM_FORMAT_S24; - else if ( format == RTAUDIO_SINT32 ) - deviceFormat = SND_PCM_FORMAT_S32; - else if ( format == RTAUDIO_FLOAT32 ) - deviceFormat = SND_PCM_FORMAT_FLOAT; - else if ( format == RTAUDIO_FLOAT64 ) - deviceFormat = SND_PCM_FORMAT_FLOAT64; - - if ( snd_pcm_hw_params_test_format(phandle, hw_params, deviceFormat) == 0) { - stream_.deviceFormat[mode] = format; - goto setFormat; - } - - // The user requested format is not natively supported by the device. - deviceFormat = SND_PCM_FORMAT_FLOAT64; - if ( snd_pcm_hw_params_test_format( phandle, hw_params, deviceFormat ) == 0 ) { - stream_.deviceFormat[mode] = RTAUDIO_FLOAT64; - goto setFormat; - } - - deviceFormat = SND_PCM_FORMAT_FLOAT; - if ( snd_pcm_hw_params_test_format(phandle, hw_params, deviceFormat ) == 0 ) { - stream_.deviceFormat[mode] = RTAUDIO_FLOAT32; - goto setFormat; - } - - deviceFormat = SND_PCM_FORMAT_S32; - if ( snd_pcm_hw_params_test_format(phandle, hw_params, deviceFormat ) == 0 ) { - stream_.deviceFormat[mode] = RTAUDIO_SINT32; - goto setFormat; - } - - deviceFormat = SND_PCM_FORMAT_S24; - if ( snd_pcm_hw_params_test_format(phandle, hw_params, deviceFormat ) == 0 ) { - stream_.deviceFormat[mode] = RTAUDIO_SINT24; - goto setFormat; - } - - deviceFormat = SND_PCM_FORMAT_S16; - if ( snd_pcm_hw_params_test_format(phandle, hw_params, deviceFormat ) == 0 ) { - stream_.deviceFormat[mode] = RTAUDIO_SINT16; - goto setFormat; - } - - deviceFormat = SND_PCM_FORMAT_S8; - if ( snd_pcm_hw_params_test_format(phandle, hw_params, deviceFormat ) == 0 ) { - stream_.deviceFormat[mode] = RTAUDIO_SINT8; - goto setFormat; - } - - // If we get here, no supported format was found. - snd_pcm_close( phandle ); - errorStream_ << "RtApiAlsa::probeDeviceOpen: pcm device " << device << " data format not supported by RtAudio."; - errorText_ = errorStream_.str(); - return FAILURE; - - setFormat: - result = snd_pcm_hw_params_set_format( phandle, hw_params, deviceFormat ); - if ( result < 0 ) { - snd_pcm_close( phandle ); - errorStream_ << "RtApiAlsa::probeDeviceOpen: error setting pcm device (" << name << ") data format, " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - return FAILURE; - } - - // Determine whether byte-swaping is necessary. - stream_.doByteSwap[mode] = false; - if ( deviceFormat != SND_PCM_FORMAT_S8 ) { - result = snd_pcm_format_cpu_endian( deviceFormat ); - if ( result == 0 ) - stream_.doByteSwap[mode] = true; - else if (result < 0) { - snd_pcm_close( phandle ); - errorStream_ << "RtApiAlsa::probeDeviceOpen: error getting pcm device (" << name << ") endian-ness, " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - return FAILURE; - } - } - - // Set the sample rate. - result = snd_pcm_hw_params_set_rate_near( phandle, hw_params, (unsigned int*) &sampleRate, 0 ); - if ( result < 0 ) { - snd_pcm_close( phandle ); - errorStream_ << "RtApiAlsa::probeDeviceOpen: error setting sample rate on device (" << name << "), " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - return FAILURE; - } - - // Determine the number of channels for this device. We support a possible - // minimum device channel number > than the value requested by the user. - stream_.nUserChannels[mode] = channels; - unsigned int value; - result = snd_pcm_hw_params_get_channels_max( hw_params, &value ); - unsigned int deviceChannels = value; - if ( result < 0 || deviceChannels < channels + firstChannel ) { - snd_pcm_close( phandle ); - errorStream_ << "RtApiAlsa::probeDeviceOpen: requested channel parameters not supported by device (" << name << "), " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - return FAILURE; - } - - result = snd_pcm_hw_params_get_channels_min( hw_params, &value ); - if ( result < 0 ) { - snd_pcm_close( phandle ); - errorStream_ << "RtApiAlsa::probeDeviceOpen: error getting minimum channels for device (" << name << "), " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - return FAILURE; - } - deviceChannels = value; - if ( deviceChannels < channels + firstChannel ) deviceChannels = channels + firstChannel; - stream_.nDeviceChannels[mode] = deviceChannels; - - // Set the device channels. - result = snd_pcm_hw_params_set_channels( phandle, hw_params, deviceChannels ); - if ( result < 0 ) { - snd_pcm_close( phandle ); - errorStream_ << "RtApiAlsa::probeDeviceOpen: error setting channels for device (" << name << "), " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - return FAILURE; - } - - // Set the buffer (or period) size. - int dir = 0; - snd_pcm_uframes_t periodSize = *bufferSize; - result = snd_pcm_hw_params_set_period_size_near( phandle, hw_params, &periodSize, &dir ); - if ( result < 0 ) { - snd_pcm_close( phandle ); - errorStream_ << "RtApiAlsa::probeDeviceOpen: error setting period size for device (" << name << "), " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - return FAILURE; - } - *bufferSize = periodSize; - - // Set the buffer number, which in ALSA is referred to as the "period". - unsigned int periods = 0; - if ( options && options->flags & RTAUDIO_MINIMIZE_LATENCY ) periods = 2; - if ( options && options->numberOfBuffers > 0 ) periods = options->numberOfBuffers; - if ( periods < 2 ) periods = 4; // a fairly safe default value - result = snd_pcm_hw_params_set_periods_near( phandle, hw_params, &periods, &dir ); - if ( result < 0 ) { - snd_pcm_close( phandle ); - errorStream_ << "RtApiAlsa::probeDeviceOpen: error setting periods for device (" << name << "), " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - return FAILURE; - } - - // If attempting to setup a duplex stream, the bufferSize parameter - // MUST be the same in both directions! - if ( stream_.mode == OUTPUT && mode == INPUT && *bufferSize != stream_.bufferSize ) { - snd_pcm_close( phandle ); - errorStream_ << "RtApiAlsa::probeDeviceOpen: system error setting buffer size for duplex stream on device (" << name << ")."; - errorText_ = errorStream_.str(); - return FAILURE; - } - - stream_.bufferSize = *bufferSize; - - // Install the hardware configuration - result = snd_pcm_hw_params( phandle, hw_params ); - if ( result < 0 ) { - snd_pcm_close( phandle ); - errorStream_ << "RtApiAlsa::probeDeviceOpen: error installing hardware configuration on device (" << name << "), " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - return FAILURE; - } - -#if defined(__RTAUDIO_DEBUG__) - fprintf(stderr, "\nRtApiAlsa: dump hardware params after installation:\n\n"); - snd_pcm_hw_params_dump( hw_params, out ); -#endif - - // Set the software configuration to fill buffers with zeros and prevent device stopping on xruns. - snd_pcm_sw_params_t *sw_params = NULL; - snd_pcm_sw_params_alloca( &sw_params ); - snd_pcm_sw_params_current( phandle, sw_params ); - snd_pcm_sw_params_set_start_threshold( phandle, sw_params, *bufferSize ); - snd_pcm_sw_params_set_stop_threshold( phandle, sw_params, ULONG_MAX ); - snd_pcm_sw_params_set_silence_threshold( phandle, sw_params, 0 ); - - // The following two settings were suggested by Theo Veenker - //snd_pcm_sw_params_set_avail_min( phandle, sw_params, *bufferSize ); - //snd_pcm_sw_params_set_xfer_align( phandle, sw_params, 1 ); - - // here are two options for a fix - //snd_pcm_sw_params_set_silence_size( phandle, sw_params, ULONG_MAX ); - snd_pcm_uframes_t val; - snd_pcm_sw_params_get_boundary( sw_params, &val ); - snd_pcm_sw_params_set_silence_size( phandle, sw_params, val ); - - result = snd_pcm_sw_params( phandle, sw_params ); - if ( result < 0 ) { - snd_pcm_close( phandle ); - errorStream_ << "RtApiAlsa::probeDeviceOpen: error installing software configuration on device (" << name << "), " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - return FAILURE; - } - -#if defined(__RTAUDIO_DEBUG__) - fprintf(stderr, "\nRtApiAlsa: dump software params after installation:\n\n"); - snd_pcm_sw_params_dump( sw_params, out ); -#endif - - // Set flags for buffer conversion - stream_.doConvertBuffer[mode] = false; - if ( stream_.userFormat != stream_.deviceFormat[mode] ) - stream_.doConvertBuffer[mode] = true; - if ( stream_.nUserChannels[mode] < stream_.nDeviceChannels[mode] ) - stream_.doConvertBuffer[mode] = true; - if ( stream_.userInterleaved != stream_.deviceInterleaved[mode] && - stream_.nUserChannels[mode] > 1 ) - stream_.doConvertBuffer[mode] = true; - - // Allocate the ApiHandle if necessary and then save. - AlsaHandle *apiInfo = 0; - if ( stream_.apiHandle == 0 ) { - try { - apiInfo = (AlsaHandle *) new AlsaHandle; - } - catch ( std::bad_alloc& ) { - errorText_ = "RtApiAlsa::probeDeviceOpen: error allocating AlsaHandle memory."; - goto error; - } - - if ( pthread_cond_init( &apiInfo->runnable_cv, NULL ) ) { - errorText_ = "RtApiAlsa::probeDeviceOpen: error initializing pthread condition variable."; - goto error; - } - - stream_.apiHandle = (void *) apiInfo; - apiInfo->handles[0] = 0; - apiInfo->handles[1] = 0; - } - else { - apiInfo = (AlsaHandle *) stream_.apiHandle; - } - apiInfo->handles[mode] = phandle; - phandle = 0; - - // Allocate necessary internal buffers. - unsigned long bufferBytes; - bufferBytes = stream_.nUserChannels[mode] * *bufferSize * formatBytes( stream_.userFormat ); - stream_.userBuffer[mode] = (char *) calloc( bufferBytes, 1 ); - if ( stream_.userBuffer[mode] == NULL ) { - errorText_ = "RtApiAlsa::probeDeviceOpen: error allocating user buffer memory."; - goto error; - } - - if ( stream_.doConvertBuffer[mode] ) { - - bool makeBuffer = true; - bufferBytes = stream_.nDeviceChannels[mode] * formatBytes( stream_.deviceFormat[mode] ); - if ( mode == INPUT ) { - if ( stream_.mode == OUTPUT && stream_.deviceBuffer ) { - unsigned long bytesOut = stream_.nDeviceChannels[0] * formatBytes( stream_.deviceFormat[0] ); - if ( bufferBytes <= bytesOut ) makeBuffer = false; - } - } - - if ( makeBuffer ) { - bufferBytes *= *bufferSize; - if ( stream_.deviceBuffer ) free( stream_.deviceBuffer ); - stream_.deviceBuffer = (char *) calloc( bufferBytes, 1 ); - if ( stream_.deviceBuffer == NULL ) { - errorText_ = "RtApiAlsa::probeDeviceOpen: error allocating device buffer memory."; - goto error; - } - } - } - - stream_.sampleRate = sampleRate; - stream_.nBuffers = periods; - stream_.device[mode] = device; - stream_.state = STREAM_STOPPED; - - // Setup the buffer conversion information structure. - if ( stream_.doConvertBuffer[mode] ) setConvertInfo( mode, firstChannel ); - - // Setup thread if necessary. - if ( stream_.mode == OUTPUT && mode == INPUT ) { - // We had already set up an output stream. - stream_.mode = DUPLEX; - // Link the streams if possible. - apiInfo->synchronized = false; - if ( snd_pcm_link( apiInfo->handles[0], apiInfo->handles[1] ) == 0 ) - apiInfo->synchronized = true; - else { - errorText_ = "RtApiAlsa::probeDeviceOpen: unable to synchronize input and output devices."; - error( RtAudioError::WARNING ); - } - } - else { - stream_.mode = mode; - - // Setup callback thread. - stream_.callbackInfo.object = (void *) this; - - // Set the thread attributes for joinable and realtime scheduling - // priority (optional). The higher priority will only take affect - // if the program is run as root or suid. Note, under Linux - // processes with CAP_SYS_NICE privilege, a user can change - // scheduling policy and priority (thus need not be root). See - // POSIX "capabilities". - pthread_attr_t attr; - pthread_attr_init( &attr ); - pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_JOINABLE ); - -#ifdef SCHED_RR // Undefined with some OSes (eg: NetBSD 1.6.x with GNU Pthread) - if ( options && options->flags & RTAUDIO_SCHEDULE_REALTIME ) { - // We previously attempted to increase the audio callback priority - // to SCHED_RR here via the attributes. However, while no errors - // were reported in doing so, it did not work. So, now this is - // done in the alsaCallbackHandler function. - stream_.callbackInfo.doRealtime = true; - int priority = options->priority; - int min = sched_get_priority_min( SCHED_RR ); - int max = sched_get_priority_max( SCHED_RR ); - if ( priority < min ) priority = min; - else if ( priority > max ) priority = max; - stream_.callbackInfo.priority = priority; - } -#endif - - stream_.callbackInfo.isRunning = true; - result = pthread_create( &stream_.callbackInfo.thread, &attr, alsaCallbackHandler, &stream_.callbackInfo ); - pthread_attr_destroy( &attr ); - if ( result ) { - stream_.callbackInfo.isRunning = false; - errorText_ = "RtApiAlsa::error creating callback thread!"; - goto error; - } - } - - return SUCCESS; - - error: - if ( apiInfo ) { - pthread_cond_destroy( &apiInfo->runnable_cv ); - if ( apiInfo->handles[0] ) snd_pcm_close( apiInfo->handles[0] ); - if ( apiInfo->handles[1] ) snd_pcm_close( apiInfo->handles[1] ); - delete apiInfo; - stream_.apiHandle = 0; - } - - if ( phandle) snd_pcm_close( phandle ); - - for ( int i=0; i<2; i++ ) { - if ( stream_.userBuffer[i] ) { - free( stream_.userBuffer[i] ); - stream_.userBuffer[i] = 0; - } - } - - if ( stream_.deviceBuffer ) { - free( stream_.deviceBuffer ); - stream_.deviceBuffer = 0; - } - - stream_.state = STREAM_CLOSED; - return FAILURE; -} - -void RtApiAlsa :: closeStream() -{ - if ( stream_.state == STREAM_CLOSED ) { - errorText_ = "RtApiAlsa::closeStream(): no open stream to close!"; - error( RtAudioError::WARNING ); - return; - } - - AlsaHandle *apiInfo = (AlsaHandle *) stream_.apiHandle; - stream_.callbackInfo.isRunning = false; - MUTEX_LOCK( &stream_.mutex ); - if ( stream_.state == STREAM_STOPPED ) { - apiInfo->runnable = true; - pthread_cond_signal( &apiInfo->runnable_cv ); - } - MUTEX_UNLOCK( &stream_.mutex ); - pthread_join( stream_.callbackInfo.thread, NULL ); - - if ( stream_.state == STREAM_RUNNING ) { - stream_.state = STREAM_STOPPED; - if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) - snd_pcm_drop( apiInfo->handles[0] ); - if ( stream_.mode == INPUT || stream_.mode == DUPLEX ) - snd_pcm_drop( apiInfo->handles[1] ); - } - - if ( apiInfo ) { - pthread_cond_destroy( &apiInfo->runnable_cv ); - if ( apiInfo->handles[0] ) snd_pcm_close( apiInfo->handles[0] ); - if ( apiInfo->handles[1] ) snd_pcm_close( apiInfo->handles[1] ); - delete apiInfo; - stream_.apiHandle = 0; - } - - for ( int i=0; i<2; i++ ) { - if ( stream_.userBuffer[i] ) { - free( stream_.userBuffer[i] ); - stream_.userBuffer[i] = 0; - } - } - - if ( stream_.deviceBuffer ) { - free( stream_.deviceBuffer ); - stream_.deviceBuffer = 0; - } - - stream_.mode = UNINITIALIZED; - stream_.state = STREAM_CLOSED; -} - -void RtApiAlsa :: startStream() -{ - // This method calls snd_pcm_prepare if the device isn't already in that state. - - verifyStream(); - if ( stream_.state == STREAM_RUNNING ) { - errorText_ = "RtApiAlsa::startStream(): the stream is already running!"; - error( RtAudioError::WARNING ); - return; - } - - MUTEX_LOCK( &stream_.mutex ); - - int result = 0; - snd_pcm_state_t state; - AlsaHandle *apiInfo = (AlsaHandle *) stream_.apiHandle; - snd_pcm_t **handle = (snd_pcm_t **) apiInfo->handles; - if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { - state = snd_pcm_state( handle[0] ); - if ( state != SND_PCM_STATE_PREPARED ) { - result = snd_pcm_prepare( handle[0] ); - if ( result < 0 ) { - errorStream_ << "RtApiAlsa::startStream: error preparing output pcm device, " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - goto unlock; - } - } - } - - if ( ( stream_.mode == INPUT || stream_.mode == DUPLEX ) && !apiInfo->synchronized ) { - result = snd_pcm_drop(handle[1]); // fix to remove stale data received since device has been open - state = snd_pcm_state( handle[1] ); - if ( state != SND_PCM_STATE_PREPARED ) { - result = snd_pcm_prepare( handle[1] ); - if ( result < 0 ) { - errorStream_ << "RtApiAlsa::startStream: error preparing input pcm device, " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - goto unlock; - } - } - } - - stream_.state = STREAM_RUNNING; - - unlock: - apiInfo->runnable = true; - pthread_cond_signal( &apiInfo->runnable_cv ); - MUTEX_UNLOCK( &stream_.mutex ); - - if ( result >= 0 ) return; - error( RtAudioError::SYSTEM_ERROR ); -} - -void RtApiAlsa :: stopStream() -{ - verifyStream(); - if ( stream_.state == STREAM_STOPPED ) { - errorText_ = "RtApiAlsa::stopStream(): the stream is already stopped!"; - error( RtAudioError::WARNING ); - return; - } - - stream_.state = STREAM_STOPPED; - MUTEX_LOCK( &stream_.mutex ); - - int result = 0; - AlsaHandle *apiInfo = (AlsaHandle *) stream_.apiHandle; - snd_pcm_t **handle = (snd_pcm_t **) apiInfo->handles; - if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { - if ( apiInfo->synchronized ) - result = snd_pcm_drop( handle[0] ); - else - result = snd_pcm_drain( handle[0] ); - if ( result < 0 ) { - errorStream_ << "RtApiAlsa::stopStream: error draining output pcm device, " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - goto unlock; - } - } - - if ( ( stream_.mode == INPUT || stream_.mode == DUPLEX ) && !apiInfo->synchronized ) { - result = snd_pcm_drop( handle[1] ); - if ( result < 0 ) { - errorStream_ << "RtApiAlsa::stopStream: error stopping input pcm device, " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - goto unlock; - } - } - - unlock: - apiInfo->runnable = false; // fixes high CPU usage when stopped - MUTEX_UNLOCK( &stream_.mutex ); - - if ( result >= 0 ) return; - error( RtAudioError::SYSTEM_ERROR ); -} - -void RtApiAlsa :: abortStream() -{ - verifyStream(); - if ( stream_.state == STREAM_STOPPED ) { - errorText_ = "RtApiAlsa::abortStream(): the stream is already stopped!"; - error( RtAudioError::WARNING ); - return; - } - - stream_.state = STREAM_STOPPED; - MUTEX_LOCK( &stream_.mutex ); - - int result = 0; - AlsaHandle *apiInfo = (AlsaHandle *) stream_.apiHandle; - snd_pcm_t **handle = (snd_pcm_t **) apiInfo->handles; - if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { - result = snd_pcm_drop( handle[0] ); - if ( result < 0 ) { - errorStream_ << "RtApiAlsa::abortStream: error aborting output pcm device, " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - goto unlock; - } - } - - if ( ( stream_.mode == INPUT || stream_.mode == DUPLEX ) && !apiInfo->synchronized ) { - result = snd_pcm_drop( handle[1] ); - if ( result < 0 ) { - errorStream_ << "RtApiAlsa::abortStream: error aborting input pcm device, " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - goto unlock; - } - } - - unlock: - apiInfo->runnable = false; // fixes high CPU usage when stopped - MUTEX_UNLOCK( &stream_.mutex ); - - if ( result >= 0 ) return; - error( RtAudioError::SYSTEM_ERROR ); -} - -void RtApiAlsa :: callbackEvent() -{ - AlsaHandle *apiInfo = (AlsaHandle *) stream_.apiHandle; - if ( stream_.state == STREAM_STOPPED ) { - MUTEX_LOCK( &stream_.mutex ); - while ( !apiInfo->runnable ) - pthread_cond_wait( &apiInfo->runnable_cv, &stream_.mutex ); - - if ( stream_.state != STREAM_RUNNING ) { - MUTEX_UNLOCK( &stream_.mutex ); - return; - } - MUTEX_UNLOCK( &stream_.mutex ); - } - - if ( stream_.state == STREAM_CLOSED ) { - errorText_ = "RtApiAlsa::callbackEvent(): the stream is closed ... this shouldn't happen!"; - error( RtAudioError::WARNING ); - return; - } - - int doStopStream = 0; - RtAudioCallback callback = (RtAudioCallback) stream_.callbackInfo.callback; - double streamTime = getStreamTime(); - RtAudioStreamStatus status = 0; - if ( stream_.mode != INPUT && apiInfo->xrun[0] == true ) { - status |= RTAUDIO_OUTPUT_UNDERFLOW; - apiInfo->xrun[0] = false; - } - if ( stream_.mode != OUTPUT && apiInfo->xrun[1] == true ) { - status |= RTAUDIO_INPUT_OVERFLOW; - apiInfo->xrun[1] = false; - } - doStopStream = callback( stream_.userBuffer[0], stream_.userBuffer[1], - stream_.bufferSize, streamTime, status, stream_.callbackInfo.userData ); - - if ( doStopStream == 2 ) { - abortStream(); - return; - } - - MUTEX_LOCK( &stream_.mutex ); - - // The state might change while waiting on a mutex. - if ( stream_.state == STREAM_STOPPED ) goto unlock; - - int result; - char *buffer; - int channels; - snd_pcm_t **handle; - snd_pcm_sframes_t frames; - RtAudioFormat format; - handle = (snd_pcm_t **) apiInfo->handles; - - if ( stream_.mode == INPUT || stream_.mode == DUPLEX ) { - - // Setup parameters. - if ( stream_.doConvertBuffer[1] ) { - buffer = stream_.deviceBuffer; - channels = stream_.nDeviceChannels[1]; - format = stream_.deviceFormat[1]; - } - else { - buffer = stream_.userBuffer[1]; - channels = stream_.nUserChannels[1]; - format = stream_.userFormat; - } - - // Read samples from device in interleaved/non-interleaved format. - if ( stream_.deviceInterleaved[1] ) - result = snd_pcm_readi( handle[1], buffer, stream_.bufferSize ); - else { - void *bufs[channels]; - size_t offset = stream_.bufferSize * formatBytes( format ); - for ( int i=0; ixrun[1] = true; - result = snd_pcm_prepare( handle[1] ); - if ( result < 0 ) { - errorStream_ << "RtApiAlsa::callbackEvent: error preparing device after overrun, " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - } - } - else { - errorStream_ << "RtApiAlsa::callbackEvent: error, current state is " << snd_pcm_state_name( state ) << ", " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - } - } - else { - errorStream_ << "RtApiAlsa::callbackEvent: audio read error, " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - } - error( RtAudioError::WARNING ); - goto tryOutput; - } - - // Do byte swapping if necessary. - if ( stream_.doByteSwap[1] ) - byteSwapBuffer( buffer, stream_.bufferSize * channels, format ); - - // Do buffer conversion if necessary. - if ( stream_.doConvertBuffer[1] ) - convertBuffer( stream_.userBuffer[1], stream_.deviceBuffer, stream_.convertInfo[1] ); - - // Check stream latency - result = snd_pcm_delay( handle[1], &frames ); - if ( result == 0 && frames > 0 ) stream_.latency[1] = frames; - } - - tryOutput: - - if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { - - // Setup parameters and do buffer conversion if necessary. - if ( stream_.doConvertBuffer[0] ) { - buffer = stream_.deviceBuffer; - convertBuffer( buffer, stream_.userBuffer[0], stream_.convertInfo[0] ); - channels = stream_.nDeviceChannels[0]; - format = stream_.deviceFormat[0]; - } - else { - buffer = stream_.userBuffer[0]; - channels = stream_.nUserChannels[0]; - format = stream_.userFormat; - } - - // Do byte swapping if necessary. - if ( stream_.doByteSwap[0] ) - byteSwapBuffer(buffer, stream_.bufferSize * channels, format); - - // Write samples to device in interleaved/non-interleaved format. - if ( stream_.deviceInterleaved[0] ) - result = snd_pcm_writei( handle[0], buffer, stream_.bufferSize ); - else { - void *bufs[channels]; - size_t offset = stream_.bufferSize * formatBytes( format ); - for ( int i=0; ixrun[0] = true; - result = snd_pcm_prepare( handle[0] ); - if ( result < 0 ) { - errorStream_ << "RtApiAlsa::callbackEvent: error preparing device after underrun, " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - } - else - errorText_ = "RtApiAlsa::callbackEvent: audio write error, underrun."; - } - else { - errorStream_ << "RtApiAlsa::callbackEvent: error, current state is " << snd_pcm_state_name( state ) << ", " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - } - } - else { - errorStream_ << "RtApiAlsa::callbackEvent: audio write error, " << snd_strerror( result ) << "."; - errorText_ = errorStream_.str(); - } - error( RtAudioError::WARNING ); - goto unlock; - } - - // Check stream latency - result = snd_pcm_delay( handle[0], &frames ); - if ( result == 0 && frames > 0 ) stream_.latency[0] = frames; - } - - unlock: - MUTEX_UNLOCK( &stream_.mutex ); - - RtApi::tickStreamTime(); - if ( doStopStream == 1 ) this->stopStream(); -} - -static void *alsaCallbackHandler( void *ptr ) -{ - CallbackInfo *info = (CallbackInfo *) ptr; - RtApiAlsa *object = (RtApiAlsa *) info->object; - bool *isRunning = &info->isRunning; - -#ifdef SCHED_RR // Undefined with some OSes (eg: NetBSD 1.6.x with GNU Pthread) - if ( info->doRealtime ) { - pthread_t tID = pthread_self(); // ID of this thread - sched_param prio = { info->priority }; // scheduling priority of thread - pthread_setschedparam( tID, SCHED_RR, &prio ); - } -#endif - - while ( *isRunning == true ) { - pthread_testcancel(); - object->callbackEvent(); - } - - pthread_exit( NULL ); -} - -//******************** End of __LINUX_ALSA__ *********************// -#endif - -#if defined(__LINUX_PULSE__) - -// Code written by Peter Meerwald, pmeerw@pmeerw.net -// and Tristan Matthews. - -#include -#include -#include - -static const unsigned int SUPPORTED_SAMPLERATES[] = { 8000, 16000, 22050, 32000, - 44100, 48000, 96000, 0}; - -struct rtaudio_pa_format_mapping_t { - RtAudioFormat rtaudio_format; - pa_sample_format_t pa_format; -}; - -static const rtaudio_pa_format_mapping_t supported_sampleformats[] = { - {RTAUDIO_SINT16, PA_SAMPLE_S16LE}, - {RTAUDIO_SINT32, PA_SAMPLE_S32LE}, - {RTAUDIO_FLOAT32, PA_SAMPLE_FLOAT32LE}, - {0, PA_SAMPLE_INVALID}}; - -struct PulseAudioHandle { - pa_simple *s_play; - pa_simple *s_rec; - pthread_t thread; - pthread_cond_t runnable_cv; - bool runnable; - PulseAudioHandle() : s_play(0), s_rec(0), runnable(false) { } -}; - -RtApiPulse::~RtApiPulse() -{ - if ( stream_.state != STREAM_CLOSED ) - closeStream(); -} - -unsigned int RtApiPulse::getDeviceCount( void ) -{ - return 1; -} - -RtAudio::DeviceInfo RtApiPulse::getDeviceInfo( unsigned int /*device*/ ) -{ - RtAudio::DeviceInfo info; - info.probed = true; - info.name = "PulseAudio"; - info.outputChannels = 2; - info.inputChannels = 2; - info.duplexChannels = 2; - info.isDefaultOutput = true; - info.isDefaultInput = true; - - for ( const unsigned int *sr = SUPPORTED_SAMPLERATES; *sr; ++sr ) - info.sampleRates.push_back( *sr ); - - info.preferredSampleRate = 48000; - info.nativeFormats = RTAUDIO_SINT16 | RTAUDIO_SINT32 | RTAUDIO_FLOAT32; - - return info; -} - -static void *pulseaudio_callback( void * user ) -{ - CallbackInfo *cbi = static_cast( user ); - RtApiPulse *context = static_cast( cbi->object ); - volatile bool *isRunning = &cbi->isRunning; - - while ( *isRunning ) { - pthread_testcancel(); - context->callbackEvent(); - } - - pthread_exit( NULL ); -} - -void RtApiPulse::closeStream( void ) -{ - PulseAudioHandle *pah = static_cast( stream_.apiHandle ); - - stream_.callbackInfo.isRunning = false; - if ( pah ) { - MUTEX_LOCK( &stream_.mutex ); - if ( stream_.state == STREAM_STOPPED ) { - pah->runnable = true; - pthread_cond_signal( &pah->runnable_cv ); - } - MUTEX_UNLOCK( &stream_.mutex ); - - pthread_join( pah->thread, 0 ); - if ( pah->s_play ) { - pa_simple_flush( pah->s_play, NULL ); - pa_simple_free( pah->s_play ); - } - if ( pah->s_rec ) - pa_simple_free( pah->s_rec ); - - pthread_cond_destroy( &pah->runnable_cv ); - delete pah; - stream_.apiHandle = 0; - } - - if ( stream_.userBuffer[0] ) { - free( stream_.userBuffer[0] ); - stream_.userBuffer[0] = 0; - } - if ( stream_.userBuffer[1] ) { - free( stream_.userBuffer[1] ); - stream_.userBuffer[1] = 0; - } - - stream_.state = STREAM_CLOSED; - stream_.mode = UNINITIALIZED; -} - -void RtApiPulse::callbackEvent( void ) -{ - PulseAudioHandle *pah = static_cast( stream_.apiHandle ); - - if ( stream_.state == STREAM_STOPPED ) { - MUTEX_LOCK( &stream_.mutex ); - while ( !pah->runnable ) - pthread_cond_wait( &pah->runnable_cv, &stream_.mutex ); - - if ( stream_.state != STREAM_RUNNING ) { - MUTEX_UNLOCK( &stream_.mutex ); - return; - } - MUTEX_UNLOCK( &stream_.mutex ); - } - - if ( stream_.state == STREAM_CLOSED ) { - errorText_ = "RtApiPulse::callbackEvent(): the stream is closed ... " - "this shouldn't happen!"; - error( RtAudioError::WARNING ); - return; - } - - RtAudioCallback callback = (RtAudioCallback) stream_.callbackInfo.callback; - double streamTime = getStreamTime(); - RtAudioStreamStatus status = 0; - int doStopStream = callback( stream_.userBuffer[OUTPUT], stream_.userBuffer[INPUT], - stream_.bufferSize, streamTime, status, - stream_.callbackInfo.userData ); - - if ( doStopStream == 2 ) { - abortStream(); - return; - } - - MUTEX_LOCK( &stream_.mutex ); - void *pulse_in = stream_.doConvertBuffer[INPUT] ? stream_.deviceBuffer : stream_.userBuffer[INPUT]; - void *pulse_out = stream_.doConvertBuffer[OUTPUT] ? stream_.deviceBuffer : stream_.userBuffer[OUTPUT]; - - if ( stream_.state != STREAM_RUNNING ) - goto unlock; - - int pa_error; - size_t bytes; - if (stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { - if ( stream_.doConvertBuffer[OUTPUT] ) { - convertBuffer( stream_.deviceBuffer, - stream_.userBuffer[OUTPUT], - stream_.convertInfo[OUTPUT] ); - bytes = stream_.nDeviceChannels[OUTPUT] * stream_.bufferSize * - formatBytes( stream_.deviceFormat[OUTPUT] ); - } else - bytes = stream_.nUserChannels[OUTPUT] * stream_.bufferSize * - formatBytes( stream_.userFormat ); - - if ( pa_simple_write( pah->s_play, pulse_out, bytes, &pa_error ) < 0 ) { - errorStream_ << "RtApiPulse::callbackEvent: audio write error, " << - pa_strerror( pa_error ) << "."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - } - } - - if ( stream_.mode == INPUT || stream_.mode == DUPLEX) { - if ( stream_.doConvertBuffer[INPUT] ) - bytes = stream_.nDeviceChannels[INPUT] * stream_.bufferSize * - formatBytes( stream_.deviceFormat[INPUT] ); - else - bytes = stream_.nUserChannels[INPUT] * stream_.bufferSize * - formatBytes( stream_.userFormat ); - - if ( pa_simple_read( pah->s_rec, pulse_in, bytes, &pa_error ) < 0 ) { - errorStream_ << "RtApiPulse::callbackEvent: audio read error, " << - pa_strerror( pa_error ) << "."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - } - if ( stream_.doConvertBuffer[INPUT] ) { - convertBuffer( stream_.userBuffer[INPUT], - stream_.deviceBuffer, - stream_.convertInfo[INPUT] ); - } - } - - unlock: - MUTEX_UNLOCK( &stream_.mutex ); - RtApi::tickStreamTime(); - - if ( doStopStream == 1 ) - stopStream(); -} - -void RtApiPulse::startStream( void ) -{ - PulseAudioHandle *pah = static_cast( stream_.apiHandle ); - - if ( stream_.state == STREAM_CLOSED ) { - errorText_ = "RtApiPulse::startStream(): the stream is not open!"; - error( RtAudioError::INVALID_USE ); - return; - } - if ( stream_.state == STREAM_RUNNING ) { - errorText_ = "RtApiPulse::startStream(): the stream is already running!"; - error( RtAudioError::WARNING ); - return; - } - - MUTEX_LOCK( &stream_.mutex ); - - stream_.state = STREAM_RUNNING; - - pah->runnable = true; - pthread_cond_signal( &pah->runnable_cv ); - MUTEX_UNLOCK( &stream_.mutex ); -} - -void RtApiPulse::stopStream( void ) -{ - PulseAudioHandle *pah = static_cast( stream_.apiHandle ); - - if ( stream_.state == STREAM_CLOSED ) { - errorText_ = "RtApiPulse::stopStream(): the stream is not open!"; - error( RtAudioError::INVALID_USE ); - return; - } - if ( stream_.state == STREAM_STOPPED ) { - errorText_ = "RtApiPulse::stopStream(): the stream is already stopped!"; - error( RtAudioError::WARNING ); - return; - } - - stream_.state = STREAM_STOPPED; - MUTEX_LOCK( &stream_.mutex ); - - if ( pah && pah->s_play ) { - int pa_error; - if ( pa_simple_drain( pah->s_play, &pa_error ) < 0 ) { - errorStream_ << "RtApiPulse::stopStream: error draining output device, " << - pa_strerror( pa_error ) << "."; - errorText_ = errorStream_.str(); - MUTEX_UNLOCK( &stream_.mutex ); - error( RtAudioError::SYSTEM_ERROR ); - return; - } - } - - stream_.state = STREAM_STOPPED; - MUTEX_UNLOCK( &stream_.mutex ); -} - -void RtApiPulse::abortStream( void ) -{ - PulseAudioHandle *pah = static_cast( stream_.apiHandle ); - - if ( stream_.state == STREAM_CLOSED ) { - errorText_ = "RtApiPulse::abortStream(): the stream is not open!"; - error( RtAudioError::INVALID_USE ); - return; - } - if ( stream_.state == STREAM_STOPPED ) { - errorText_ = "RtApiPulse::abortStream(): the stream is already stopped!"; - error( RtAudioError::WARNING ); - return; - } - - stream_.state = STREAM_STOPPED; - MUTEX_LOCK( &stream_.mutex ); - - if ( pah && pah->s_play ) { - int pa_error; - if ( pa_simple_flush( pah->s_play, &pa_error ) < 0 ) { - errorStream_ << "RtApiPulse::abortStream: error flushing output device, " << - pa_strerror( pa_error ) << "."; - errorText_ = errorStream_.str(); - MUTEX_UNLOCK( &stream_.mutex ); - error( RtAudioError::SYSTEM_ERROR ); - return; - } - } - - stream_.state = STREAM_STOPPED; - MUTEX_UNLOCK( &stream_.mutex ); -} - -bool RtApiPulse::probeDeviceOpen( unsigned int device, StreamMode mode, - unsigned int channels, unsigned int firstChannel, - unsigned int sampleRate, RtAudioFormat format, - unsigned int *bufferSize, RtAudio::StreamOptions *options ) -{ - PulseAudioHandle *pah = 0; - unsigned long bufferBytes = 0; - pa_sample_spec ss; - - if ( device != 0 ) return false; - if ( mode != INPUT && mode != OUTPUT ) return false; - if ( channels != 1 && channels != 2 ) { - errorText_ = "RtApiPulse::probeDeviceOpen: unsupported number of channels."; - return false; - } - ss.channels = channels; - - if ( firstChannel != 0 ) return false; - - bool sr_found = false; - for ( const unsigned int *sr = SUPPORTED_SAMPLERATES; *sr; ++sr ) { - if ( sampleRate == *sr ) { - sr_found = true; - stream_.sampleRate = sampleRate; - ss.rate = sampleRate; - break; - } - } - if ( !sr_found ) { - errorText_ = "RtApiPulse::probeDeviceOpen: unsupported sample rate."; - return false; - } - - bool sf_found = 0; - for ( const rtaudio_pa_format_mapping_t *sf = supported_sampleformats; - sf->rtaudio_format && sf->pa_format != PA_SAMPLE_INVALID; ++sf ) { - if ( format == sf->rtaudio_format ) { - sf_found = true; - stream_.userFormat = sf->rtaudio_format; - stream_.deviceFormat[mode] = stream_.userFormat; - ss.format = sf->pa_format; - break; - } - } - if ( !sf_found ) { // Use internal data format conversion. - stream_.userFormat = format; - stream_.deviceFormat[mode] = RTAUDIO_FLOAT32; - ss.format = PA_SAMPLE_FLOAT32LE; - } - - // Set other stream parameters. - if ( options && options->flags & RTAUDIO_NONINTERLEAVED ) stream_.userInterleaved = false; - else stream_.userInterleaved = true; - stream_.deviceInterleaved[mode] = true; - stream_.nBuffers = 1; - stream_.doByteSwap[mode] = false; - stream_.nUserChannels[mode] = channels; - stream_.nDeviceChannels[mode] = channels + firstChannel; - stream_.channelOffset[mode] = 0; - std::string streamName = "RtAudio"; - - // Set flags for buffer conversion. - stream_.doConvertBuffer[mode] = false; - if ( stream_.userFormat != stream_.deviceFormat[mode] ) - stream_.doConvertBuffer[mode] = true; - if ( stream_.nUserChannels[mode] < stream_.nDeviceChannels[mode] ) - stream_.doConvertBuffer[mode] = true; - - // Allocate necessary internal buffers. - bufferBytes = stream_.nUserChannels[mode] * *bufferSize * formatBytes( stream_.userFormat ); - stream_.userBuffer[mode] = (char *) calloc( bufferBytes, 1 ); - if ( stream_.userBuffer[mode] == NULL ) { - errorText_ = "RtApiPulse::probeDeviceOpen: error allocating user buffer memory."; - goto error; - } - stream_.bufferSize = *bufferSize; - - if ( stream_.doConvertBuffer[mode] ) { - - bool makeBuffer = true; - bufferBytes = stream_.nDeviceChannels[mode] * formatBytes( stream_.deviceFormat[mode] ); - if ( mode == INPUT ) { - if ( stream_.mode == OUTPUT && stream_.deviceBuffer ) { - unsigned long bytesOut = stream_.nDeviceChannels[0] * formatBytes( stream_.deviceFormat[0] ); - if ( bufferBytes <= bytesOut ) makeBuffer = false; - } - } - - if ( makeBuffer ) { - bufferBytes *= *bufferSize; - if ( stream_.deviceBuffer ) free( stream_.deviceBuffer ); - stream_.deviceBuffer = (char *) calloc( bufferBytes, 1 ); - if ( stream_.deviceBuffer == NULL ) { - errorText_ = "RtApiPulse::probeDeviceOpen: error allocating device buffer memory."; - goto error; - } - } - } - - stream_.device[mode] = device; - - // Setup the buffer conversion information structure. - if ( stream_.doConvertBuffer[mode] ) setConvertInfo( mode, firstChannel ); - - if ( !stream_.apiHandle ) { - PulseAudioHandle *pah = new PulseAudioHandle; - if ( !pah ) { - errorText_ = "RtApiPulse::probeDeviceOpen: error allocating memory for handle."; - goto error; - } - - stream_.apiHandle = pah; - if ( pthread_cond_init( &pah->runnable_cv, NULL ) != 0 ) { - errorText_ = "RtApiPulse::probeDeviceOpen: error creating condition variable."; - goto error; - } - } - pah = static_cast( stream_.apiHandle ); - - int error; - if ( options && !options->streamName.empty() ) streamName = options->streamName; - switch ( mode ) { - case INPUT: - pa_buffer_attr buffer_attr; - buffer_attr.fragsize = bufferBytes; - buffer_attr.maxlength = -1; - - pah->s_rec = pa_simple_new( NULL, streamName.c_str(), PA_STREAM_RECORD, NULL, "Record", &ss, NULL, &buffer_attr, &error ); - if ( !pah->s_rec ) { - errorText_ = "RtApiPulse::probeDeviceOpen: error connecting input to PulseAudio server."; - goto error; - } - break; - case OUTPUT: - pah->s_play = pa_simple_new( NULL, streamName.c_str(), PA_STREAM_PLAYBACK, NULL, "Playback", &ss, NULL, NULL, &error ); - if ( !pah->s_play ) { - errorText_ = "RtApiPulse::probeDeviceOpen: error connecting output to PulseAudio server."; - goto error; - } - break; - default: - goto error; - } - - if ( stream_.mode == UNINITIALIZED ) - stream_.mode = mode; - else if ( stream_.mode == mode ) - goto error; - else - stream_.mode = DUPLEX; - - if ( !stream_.callbackInfo.isRunning ) { - stream_.callbackInfo.object = this; - stream_.callbackInfo.isRunning = true; - if ( pthread_create( &pah->thread, NULL, pulseaudio_callback, (void *)&stream_.callbackInfo) != 0 ) { - errorText_ = "RtApiPulse::probeDeviceOpen: error creating thread."; - goto error; - } - } - - stream_.state = STREAM_STOPPED; - return true; - - error: - if ( pah && stream_.callbackInfo.isRunning ) { - pthread_cond_destroy( &pah->runnable_cv ); - delete pah; - stream_.apiHandle = 0; - } - - for ( int i=0; i<2; i++ ) { - if ( stream_.userBuffer[i] ) { - free( stream_.userBuffer[i] ); - stream_.userBuffer[i] = 0; - } - } - - if ( stream_.deviceBuffer ) { - free( stream_.deviceBuffer ); - stream_.deviceBuffer = 0; - } - - return FAILURE; -} - -//******************** End of __LINUX_PULSE__ *********************// -#endif - -#if defined(__LINUX_OSS__) - -#include -#include -#include -#include -#include -#include -#include - -static void *ossCallbackHandler(void * ptr); - -// A structure to hold various information related to the OSS API -// implementation. -struct OssHandle { - int id[2]; // device ids - bool xrun[2]; - bool triggered; - pthread_cond_t runnable; - - OssHandle() - :triggered(false) { id[0] = 0; id[1] = 0; xrun[0] = false; xrun[1] = false; } -}; - -RtApiOss :: RtApiOss() -{ - // Nothing to do here. -} - -RtApiOss :: ~RtApiOss() -{ - if ( stream_.state != STREAM_CLOSED ) closeStream(); -} - -unsigned int RtApiOss :: getDeviceCount( void ) -{ - int mixerfd = open( "/dev/mixer", O_RDWR, 0 ); - if ( mixerfd == -1 ) { - errorText_ = "RtApiOss::getDeviceCount: error opening '/dev/mixer'."; - error( RtAudioError::WARNING ); - return 0; - } - - oss_sysinfo sysinfo; - if ( ioctl( mixerfd, SNDCTL_SYSINFO, &sysinfo ) == -1 ) { - close( mixerfd ); - errorText_ = "RtApiOss::getDeviceCount: error getting sysinfo, OSS version >= 4.0 is required."; - error( RtAudioError::WARNING ); - return 0; - } - - close( mixerfd ); - return sysinfo.numaudios; -} - -RtAudio::DeviceInfo RtApiOss :: getDeviceInfo( unsigned int device ) -{ - RtAudio::DeviceInfo info; - info.probed = false; - - int mixerfd = open( "/dev/mixer", O_RDWR, 0 ); - if ( mixerfd == -1 ) { - errorText_ = "RtApiOss::getDeviceInfo: error opening '/dev/mixer'."; - error( RtAudioError::WARNING ); - return info; - } - - oss_sysinfo sysinfo; - int result = ioctl( mixerfd, SNDCTL_SYSINFO, &sysinfo ); - if ( result == -1 ) { - close( mixerfd ); - errorText_ = "RtApiOss::getDeviceInfo: error getting sysinfo, OSS version >= 4.0 is required."; - error( RtAudioError::WARNING ); - return info; - } - - unsigned nDevices = sysinfo.numaudios; - if ( nDevices == 0 ) { - close( mixerfd ); - errorText_ = "RtApiOss::getDeviceInfo: no devices found!"; - error( RtAudioError::INVALID_USE ); - return info; - } - - if ( device >= nDevices ) { - close( mixerfd ); - errorText_ = "RtApiOss::getDeviceInfo: device ID is invalid!"; - error( RtAudioError::INVALID_USE ); - return info; - } - - oss_audioinfo ainfo; - ainfo.dev = device; - result = ioctl( mixerfd, SNDCTL_AUDIOINFO, &ainfo ); - close( mixerfd ); - if ( result == -1 ) { - errorStream_ << "RtApiOss::getDeviceInfo: error getting device (" << ainfo.name << ") info."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - return info; - } - - // Probe channels - if ( ainfo.caps & PCM_CAP_OUTPUT ) info.outputChannels = ainfo.max_channels; - if ( ainfo.caps & PCM_CAP_INPUT ) info.inputChannels = ainfo.max_channels; - if ( ainfo.caps & PCM_CAP_DUPLEX ) { - if ( info.outputChannels > 0 && info.inputChannels > 0 && ainfo.caps & PCM_CAP_DUPLEX ) - info.duplexChannels = (info.outputChannels > info.inputChannels) ? info.inputChannels : info.outputChannels; - } - - // Probe data formats ... do for input - unsigned long mask = ainfo.iformats; - if ( mask & AFMT_S16_LE || mask & AFMT_S16_BE ) - info.nativeFormats |= RTAUDIO_SINT16; - if ( mask & AFMT_S8 ) - info.nativeFormats |= RTAUDIO_SINT8; - if ( mask & AFMT_S32_LE || mask & AFMT_S32_BE ) - info.nativeFormats |= RTAUDIO_SINT32; - if ( mask & AFMT_FLOAT ) - info.nativeFormats |= RTAUDIO_FLOAT32; - if ( mask & AFMT_S24_LE || mask & AFMT_S24_BE ) - info.nativeFormats |= RTAUDIO_SINT24; - - // Check that we have at least one supported format - if ( info.nativeFormats == 0 ) { - errorStream_ << "RtApiOss::getDeviceInfo: device (" << ainfo.name << ") data format not supported by RtAudio."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - return info; - } - - // Probe the supported sample rates. - info.sampleRates.clear(); - if ( ainfo.nrates ) { - for ( unsigned int i=0; i info.preferredSampleRate ) ) - info.preferredSampleRate = SAMPLE_RATES[k]; - - break; - } - } - } - } - else { - // Check min and max rate values; - for ( unsigned int k=0; k= (int) SAMPLE_RATES[k] ) { - info.sampleRates.push_back( SAMPLE_RATES[k] ); - - if ( !info.preferredSampleRate || ( SAMPLE_RATES[k] <= 48000 && SAMPLE_RATES[k] > info.preferredSampleRate ) ) - info.preferredSampleRate = SAMPLE_RATES[k]; - } - } - } - - if ( info.sampleRates.size() == 0 ) { - errorStream_ << "RtApiOss::getDeviceInfo: no supported sample rates found for device (" << ainfo.name << ")."; - errorText_ = errorStream_.str(); - error( RtAudioError::WARNING ); - } - else { - info.probed = true; - info.name = ainfo.name; - } - - return info; -} - - -bool RtApiOss :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, - unsigned int firstChannel, unsigned int sampleRate, - RtAudioFormat format, unsigned int *bufferSize, - RtAudio::StreamOptions *options ) -{ - int mixerfd = open( "/dev/mixer", O_RDWR, 0 ); - if ( mixerfd == -1 ) { - errorText_ = "RtApiOss::probeDeviceOpen: error opening '/dev/mixer'."; - return FAILURE; - } - - oss_sysinfo sysinfo; - int result = ioctl( mixerfd, SNDCTL_SYSINFO, &sysinfo ); - if ( result == -1 ) { - close( mixerfd ); - errorText_ = "RtApiOss::probeDeviceOpen: error getting sysinfo, OSS version >= 4.0 is required."; - return FAILURE; - } - - unsigned nDevices = sysinfo.numaudios; - if ( nDevices == 0 ) { - // This should not happen because a check is made before this function is called. - close( mixerfd ); - errorText_ = "RtApiOss::probeDeviceOpen: no devices found!"; - return FAILURE; - } - - if ( device >= nDevices ) { - // This should not happen because a check is made before this function is called. - close( mixerfd ); - errorText_ = "RtApiOss::probeDeviceOpen: device ID is invalid!"; - return FAILURE; - } - - oss_audioinfo ainfo; - ainfo.dev = device; - result = ioctl( mixerfd, SNDCTL_AUDIOINFO, &ainfo ); - close( mixerfd ); - if ( result == -1 ) { - errorStream_ << "RtApiOss::getDeviceInfo: error getting device (" << ainfo.name << ") info."; - errorText_ = errorStream_.str(); - return FAILURE; - } - - // Check if device supports input or output - if ( ( mode == OUTPUT && !( ainfo.caps & PCM_CAP_OUTPUT ) ) || - ( mode == INPUT && !( ainfo.caps & PCM_CAP_INPUT ) ) ) { - if ( mode == OUTPUT ) - errorStream_ << "RtApiOss::probeDeviceOpen: device (" << ainfo.name << ") does not support output."; - else - errorStream_ << "RtApiOss::probeDeviceOpen: device (" << ainfo.name << ") does not support input."; - errorText_ = errorStream_.str(); - return FAILURE; - } - - int flags = 0; - OssHandle *handle = (OssHandle *) stream_.apiHandle; - if ( mode == OUTPUT ) - flags |= O_WRONLY; - else { // mode == INPUT - if (stream_.mode == OUTPUT && stream_.device[0] == device) { - // We just set the same device for playback ... close and reopen for duplex (OSS only). - close( handle->id[0] ); - handle->id[0] = 0; - if ( !( ainfo.caps & PCM_CAP_DUPLEX ) ) { - errorStream_ << "RtApiOss::probeDeviceOpen: device (" << ainfo.name << ") does not support duplex mode."; - errorText_ = errorStream_.str(); - return FAILURE; - } - // Check that the number previously set channels is the same. - if ( stream_.nUserChannels[0] != channels ) { - errorStream_ << "RtApiOss::probeDeviceOpen: input/output channels must be equal for OSS duplex device (" << ainfo.name << ")."; - errorText_ = errorStream_.str(); - return FAILURE; - } - flags |= O_RDWR; - } - else - flags |= O_RDONLY; - } - - // Set exclusive access if specified. - if ( options && options->flags & RTAUDIO_HOG_DEVICE ) flags |= O_EXCL; - - // Try to open the device. - int fd; - fd = open( ainfo.devnode, flags, 0 ); - if ( fd == -1 ) { - if ( errno == EBUSY ) - errorStream_ << "RtApiOss::probeDeviceOpen: device (" << ainfo.name << ") is busy."; - else - errorStream_ << "RtApiOss::probeDeviceOpen: error opening device (" << ainfo.name << ")."; - errorText_ = errorStream_.str(); - return FAILURE; - } - - // For duplex operation, specifically set this mode (this doesn't seem to work). - /* - if ( flags | O_RDWR ) { - result = ioctl( fd, SNDCTL_DSP_SETDUPLEX, NULL ); - if ( result == -1) { - errorStream_ << "RtApiOss::probeDeviceOpen: error setting duplex mode for device (" << ainfo.name << ")."; - errorText_ = errorStream_.str(); - return FAILURE; - } - } - */ - - // Check the device channel support. - stream_.nUserChannels[mode] = channels; - if ( ainfo.max_channels < (int)(channels + firstChannel) ) { - close( fd ); - errorStream_ << "RtApiOss::probeDeviceOpen: the device (" << ainfo.name << ") does not support requested channel parameters."; - errorText_ = errorStream_.str(); - return FAILURE; - } - - // Set the number of channels. - int deviceChannels = channels + firstChannel; - result = ioctl( fd, SNDCTL_DSP_CHANNELS, &deviceChannels ); - if ( result == -1 || deviceChannels < (int)(channels + firstChannel) ) { - close( fd ); - errorStream_ << "RtApiOss::probeDeviceOpen: error setting channel parameters on device (" << ainfo.name << ")."; - errorText_ = errorStream_.str(); - return FAILURE; - } - stream_.nDeviceChannels[mode] = deviceChannels; - - // Get the data format mask - int mask; - result = ioctl( fd, SNDCTL_DSP_GETFMTS, &mask ); - if ( result == -1 ) { - close( fd ); - errorStream_ << "RtApiOss::probeDeviceOpen: error getting device (" << ainfo.name << ") data formats."; - errorText_ = errorStream_.str(); - return FAILURE; - } - - // Determine how to set the device format. - stream_.userFormat = format; - int deviceFormat = -1; - stream_.doByteSwap[mode] = false; - if ( format == RTAUDIO_SINT8 ) { - if ( mask & AFMT_S8 ) { - deviceFormat = AFMT_S8; - stream_.deviceFormat[mode] = RTAUDIO_SINT8; - } - } - else if ( format == RTAUDIO_SINT16 ) { - if ( mask & AFMT_S16_NE ) { - deviceFormat = AFMT_S16_NE; - stream_.deviceFormat[mode] = RTAUDIO_SINT16; - } - else if ( mask & AFMT_S16_OE ) { - deviceFormat = AFMT_S16_OE; - stream_.deviceFormat[mode] = RTAUDIO_SINT16; - stream_.doByteSwap[mode] = true; - } - } - else if ( format == RTAUDIO_SINT24 ) { - if ( mask & AFMT_S24_NE ) { - deviceFormat = AFMT_S24_NE; - stream_.deviceFormat[mode] = RTAUDIO_SINT24; - } - else if ( mask & AFMT_S24_OE ) { - deviceFormat = AFMT_S24_OE; - stream_.deviceFormat[mode] = RTAUDIO_SINT24; - stream_.doByteSwap[mode] = true; - } - } - else if ( format == RTAUDIO_SINT32 ) { - if ( mask & AFMT_S32_NE ) { - deviceFormat = AFMT_S32_NE; - stream_.deviceFormat[mode] = RTAUDIO_SINT32; - } - else if ( mask & AFMT_S32_OE ) { - deviceFormat = AFMT_S32_OE; - stream_.deviceFormat[mode] = RTAUDIO_SINT32; - stream_.doByteSwap[mode] = true; - } - } - - if ( deviceFormat == -1 ) { - // The user requested format is not natively supported by the device. - if ( mask & AFMT_S16_NE ) { - deviceFormat = AFMT_S16_NE; - stream_.deviceFormat[mode] = RTAUDIO_SINT16; - } - else if ( mask & AFMT_S32_NE ) { - deviceFormat = AFMT_S32_NE; - stream_.deviceFormat[mode] = RTAUDIO_SINT32; - } - else if ( mask & AFMT_S24_NE ) { - deviceFormat = AFMT_S24_NE; - stream_.deviceFormat[mode] = RTAUDIO_SINT24; - } - else if ( mask & AFMT_S16_OE ) { - deviceFormat = AFMT_S16_OE; - stream_.deviceFormat[mode] = RTAUDIO_SINT16; - stream_.doByteSwap[mode] = true; - } - else if ( mask & AFMT_S32_OE ) { - deviceFormat = AFMT_S32_OE; - stream_.deviceFormat[mode] = RTAUDIO_SINT32; - stream_.doByteSwap[mode] = true; - } - else if ( mask & AFMT_S24_OE ) { - deviceFormat = AFMT_S24_OE; - stream_.deviceFormat[mode] = RTAUDIO_SINT24; - stream_.doByteSwap[mode] = true; - } - else if ( mask & AFMT_S8) { - deviceFormat = AFMT_S8; - stream_.deviceFormat[mode] = RTAUDIO_SINT8; - } - } - - if ( stream_.deviceFormat[mode] == 0 ) { - // This really shouldn't happen ... - close( fd ); - errorStream_ << "RtApiOss::probeDeviceOpen: device (" << ainfo.name << ") data format not supported by RtAudio."; - errorText_ = errorStream_.str(); - return FAILURE; - } - - // Set the data format. - int temp = deviceFormat; - result = ioctl( fd, SNDCTL_DSP_SETFMT, &deviceFormat ); - if ( result == -1 || deviceFormat != temp ) { - close( fd ); - errorStream_ << "RtApiOss::probeDeviceOpen: error setting data format on device (" << ainfo.name << ")."; - errorText_ = errorStream_.str(); - return FAILURE; - } - - // Attempt to set the buffer size. According to OSS, the minimum - // number of buffers is two. The supposed minimum buffer size is 16 - // bytes, so that will be our lower bound. The argument to this - // call is in the form 0xMMMMSSSS (hex), where the buffer size (in - // bytes) is given as 2^SSSS and the number of buffers as 2^MMMM. - // We'll check the actual value used near the end of the setup - // procedure. - int ossBufferBytes = *bufferSize * formatBytes( stream_.deviceFormat[mode] ) * deviceChannels; - if ( ossBufferBytes < 16 ) ossBufferBytes = 16; - int buffers = 0; - if ( options ) buffers = options->numberOfBuffers; - if ( options && options->flags & RTAUDIO_MINIMIZE_LATENCY ) buffers = 2; - if ( buffers < 2 ) buffers = 3; - temp = ((int) buffers << 16) + (int)( log10( (double)ossBufferBytes ) / log10( 2.0 ) ); - result = ioctl( fd, SNDCTL_DSP_SETFRAGMENT, &temp ); - if ( result == -1 ) { - close( fd ); - errorStream_ << "RtApiOss::probeDeviceOpen: error setting buffer size on device (" << ainfo.name << ")."; - errorText_ = errorStream_.str(); - return FAILURE; - } - stream_.nBuffers = buffers; - - // Save buffer size (in sample frames). - *bufferSize = ossBufferBytes / ( formatBytes(stream_.deviceFormat[mode]) * deviceChannels ); - stream_.bufferSize = *bufferSize; - - // Set the sample rate. - int srate = sampleRate; - result = ioctl( fd, SNDCTL_DSP_SPEED, &srate ); - if ( result == -1 ) { - close( fd ); - errorStream_ << "RtApiOss::probeDeviceOpen: error setting sample rate (" << sampleRate << ") on device (" << ainfo.name << ")."; - errorText_ = errorStream_.str(); - return FAILURE; - } - - // Verify the sample rate setup worked. - if ( abs( srate - sampleRate ) > 100 ) { - close( fd ); - errorStream_ << "RtApiOss::probeDeviceOpen: device (" << ainfo.name << ") does not support sample rate (" << sampleRate << ")."; - errorText_ = errorStream_.str(); - return FAILURE; - } - stream_.sampleRate = sampleRate; - - if ( mode == INPUT && stream_.mode == OUTPUT && stream_.device[0] == device) { - // We're doing duplex setup here. - stream_.deviceFormat[0] = stream_.deviceFormat[1]; - stream_.nDeviceChannels[0] = deviceChannels; - } - - // Set interleaving parameters. - stream_.userInterleaved = true; - stream_.deviceInterleaved[mode] = true; - if ( options && options->flags & RTAUDIO_NONINTERLEAVED ) - stream_.userInterleaved = false; - - // Set flags for buffer conversion - stream_.doConvertBuffer[mode] = false; - if ( stream_.userFormat != stream_.deviceFormat[mode] ) - stream_.doConvertBuffer[mode] = true; - if ( stream_.nUserChannels[mode] < stream_.nDeviceChannels[mode] ) - stream_.doConvertBuffer[mode] = true; - if ( stream_.userInterleaved != stream_.deviceInterleaved[mode] && - stream_.nUserChannels[mode] > 1 ) - stream_.doConvertBuffer[mode] = true; - - // Allocate the stream handles if necessary and then save. - if ( stream_.apiHandle == 0 ) { - try { - handle = new OssHandle; - } - catch ( std::bad_alloc& ) { - errorText_ = "RtApiOss::probeDeviceOpen: error allocating OssHandle memory."; - goto error; - } - - if ( pthread_cond_init( &handle->runnable, NULL ) ) { - errorText_ = "RtApiOss::probeDeviceOpen: error initializing pthread condition variable."; - goto error; - } - - stream_.apiHandle = (void *) handle; - } - else { - handle = (OssHandle *) stream_.apiHandle; - } - handle->id[mode] = fd; - - // Allocate necessary internal buffers. - unsigned long bufferBytes; - bufferBytes = stream_.nUserChannels[mode] * *bufferSize * formatBytes( stream_.userFormat ); - stream_.userBuffer[mode] = (char *) calloc( bufferBytes, 1 ); - if ( stream_.userBuffer[mode] == NULL ) { - errorText_ = "RtApiOss::probeDeviceOpen: error allocating user buffer memory."; - goto error; - } - - if ( stream_.doConvertBuffer[mode] ) { - - bool makeBuffer = true; - bufferBytes = stream_.nDeviceChannels[mode] * formatBytes( stream_.deviceFormat[mode] ); - if ( mode == INPUT ) { - if ( stream_.mode == OUTPUT && stream_.deviceBuffer ) { - unsigned long bytesOut = stream_.nDeviceChannels[0] * formatBytes( stream_.deviceFormat[0] ); - if ( bufferBytes <= bytesOut ) makeBuffer = false; - } - } - - if ( makeBuffer ) { - bufferBytes *= *bufferSize; - if ( stream_.deviceBuffer ) free( stream_.deviceBuffer ); - stream_.deviceBuffer = (char *) calloc( bufferBytes, 1 ); - if ( stream_.deviceBuffer == NULL ) { - errorText_ = "RtApiOss::probeDeviceOpen: error allocating device buffer memory."; - goto error; - } - } - } - - stream_.device[mode] = device; - stream_.state = STREAM_STOPPED; - - // Setup the buffer conversion information structure. - if ( stream_.doConvertBuffer[mode] ) setConvertInfo( mode, firstChannel ); - - // Setup thread if necessary. - if ( stream_.mode == OUTPUT && mode == INPUT ) { - // We had already set up an output stream. - stream_.mode = DUPLEX; - if ( stream_.device[0] == device ) handle->id[0] = fd; - } - else { - stream_.mode = mode; - - // Setup callback thread. - stream_.callbackInfo.object = (void *) this; - - // Set the thread attributes for joinable and realtime scheduling - // priority. The higher priority will only take affect if the - // program is run as root or suid. - pthread_attr_t attr; - pthread_attr_init( &attr ); - pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_JOINABLE ); -#ifdef SCHED_RR // Undefined with some OSes (eg: NetBSD 1.6.x with GNU Pthread) - if ( options && options->flags & RTAUDIO_SCHEDULE_REALTIME ) { - struct sched_param param; - int priority = options->priority; - int min = sched_get_priority_min( SCHED_RR ); - int max = sched_get_priority_max( SCHED_RR ); - if ( priority < min ) priority = min; - else if ( priority > max ) priority = max; - param.sched_priority = priority; - pthread_attr_setschedparam( &attr, ¶m ); - pthread_attr_setschedpolicy( &attr, SCHED_RR ); - } - else - pthread_attr_setschedpolicy( &attr, SCHED_OTHER ); -#else - pthread_attr_setschedpolicy( &attr, SCHED_OTHER ); -#endif - - stream_.callbackInfo.isRunning = true; - result = pthread_create( &stream_.callbackInfo.thread, &attr, ossCallbackHandler, &stream_.callbackInfo ); - pthread_attr_destroy( &attr ); - if ( result ) { - stream_.callbackInfo.isRunning = false; - errorText_ = "RtApiOss::error creating callback thread!"; - goto error; - } - } - - return SUCCESS; - - error: - if ( handle ) { - pthread_cond_destroy( &handle->runnable ); - if ( handle->id[0] ) close( handle->id[0] ); - if ( handle->id[1] ) close( handle->id[1] ); - delete handle; - stream_.apiHandle = 0; - } - - for ( int i=0; i<2; i++ ) { - if ( stream_.userBuffer[i] ) { - free( stream_.userBuffer[i] ); - stream_.userBuffer[i] = 0; - } - } - - if ( stream_.deviceBuffer ) { - free( stream_.deviceBuffer ); - stream_.deviceBuffer = 0; - } - - return FAILURE; -} - -void RtApiOss :: closeStream() -{ - if ( stream_.state == STREAM_CLOSED ) { - errorText_ = "RtApiOss::closeStream(): no open stream to close!"; - error( RtAudioError::WARNING ); - return; - } - - OssHandle *handle = (OssHandle *) stream_.apiHandle; - stream_.callbackInfo.isRunning = false; - MUTEX_LOCK( &stream_.mutex ); - if ( stream_.state == STREAM_STOPPED ) - pthread_cond_signal( &handle->runnable ); - MUTEX_UNLOCK( &stream_.mutex ); - pthread_join( stream_.callbackInfo.thread, NULL ); - - if ( stream_.state == STREAM_RUNNING ) { - if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) - ioctl( handle->id[0], SNDCTL_DSP_HALT, 0 ); - else - ioctl( handle->id[1], SNDCTL_DSP_HALT, 0 ); - stream_.state = STREAM_STOPPED; - } - - if ( handle ) { - pthread_cond_destroy( &handle->runnable ); - if ( handle->id[0] ) close( handle->id[0] ); - if ( handle->id[1] ) close( handle->id[1] ); - delete handle; - stream_.apiHandle = 0; - } - - for ( int i=0; i<2; i++ ) { - if ( stream_.userBuffer[i] ) { - free( stream_.userBuffer[i] ); - stream_.userBuffer[i] = 0; - } - } - - if ( stream_.deviceBuffer ) { - free( stream_.deviceBuffer ); - stream_.deviceBuffer = 0; - } - - stream_.mode = UNINITIALIZED; - stream_.state = STREAM_CLOSED; -} - -void RtApiOss :: startStream() -{ - verifyStream(); - if ( stream_.state == STREAM_RUNNING ) { - errorText_ = "RtApiOss::startStream(): the stream is already running!"; - error( RtAudioError::WARNING ); - return; - } - - MUTEX_LOCK( &stream_.mutex ); - - stream_.state = STREAM_RUNNING; - - // No need to do anything else here ... OSS automatically starts - // when fed samples. - - MUTEX_UNLOCK( &stream_.mutex ); - - OssHandle *handle = (OssHandle *) stream_.apiHandle; - pthread_cond_signal( &handle->runnable ); -} - -void RtApiOss :: stopStream() -{ - verifyStream(); - if ( stream_.state == STREAM_STOPPED ) { - errorText_ = "RtApiOss::stopStream(): the stream is already stopped!"; - error( RtAudioError::WARNING ); - return; - } - - MUTEX_LOCK( &stream_.mutex ); - - // The state might change while waiting on a mutex. - if ( stream_.state == STREAM_STOPPED ) { - MUTEX_UNLOCK( &stream_.mutex ); - return; - } - - int result = 0; - OssHandle *handle = (OssHandle *) stream_.apiHandle; - if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { - - // Flush the output with zeros a few times. - char *buffer; - int samples; - RtAudioFormat format; - - if ( stream_.doConvertBuffer[0] ) { - buffer = stream_.deviceBuffer; - samples = stream_.bufferSize * stream_.nDeviceChannels[0]; - format = stream_.deviceFormat[0]; - } - else { - buffer = stream_.userBuffer[0]; - samples = stream_.bufferSize * stream_.nUserChannels[0]; - format = stream_.userFormat; - } - - memset( buffer, 0, samples * formatBytes(format) ); - for ( unsigned int i=0; iid[0], buffer, samples * formatBytes(format) ); - if ( result == -1 ) { - errorText_ = "RtApiOss::stopStream: audio write error."; - error( RtAudioError::WARNING ); - } - } - - result = ioctl( handle->id[0], SNDCTL_DSP_HALT, 0 ); - if ( result == -1 ) { - errorStream_ << "RtApiOss::stopStream: system error stopping callback procedure on device (" << stream_.device[0] << ")."; - errorText_ = errorStream_.str(); - goto unlock; - } - handle->triggered = false; - } - - if ( stream_.mode == INPUT || ( stream_.mode == DUPLEX && handle->id[0] != handle->id[1] ) ) { - result = ioctl( handle->id[1], SNDCTL_DSP_HALT, 0 ); - if ( result == -1 ) { - errorStream_ << "RtApiOss::stopStream: system error stopping input callback procedure on device (" << stream_.device[0] << ")."; - errorText_ = errorStream_.str(); - goto unlock; - } - } - - unlock: - stream_.state = STREAM_STOPPED; - MUTEX_UNLOCK( &stream_.mutex ); - - if ( result != -1 ) return; - error( RtAudioError::SYSTEM_ERROR ); -} - -void RtApiOss :: abortStream() -{ - verifyStream(); - if ( stream_.state == STREAM_STOPPED ) { - errorText_ = "RtApiOss::abortStream(): the stream is already stopped!"; - error( RtAudioError::WARNING ); - return; - } - - MUTEX_LOCK( &stream_.mutex ); - - // The state might change while waiting on a mutex. - if ( stream_.state == STREAM_STOPPED ) { - MUTEX_UNLOCK( &stream_.mutex ); - return; - } - - int result = 0; - OssHandle *handle = (OssHandle *) stream_.apiHandle; - if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { - result = ioctl( handle->id[0], SNDCTL_DSP_HALT, 0 ); - if ( result == -1 ) { - errorStream_ << "RtApiOss::abortStream: system error stopping callback procedure on device (" << stream_.device[0] << ")."; - errorText_ = errorStream_.str(); - goto unlock; - } - handle->triggered = false; - } - - if ( stream_.mode == INPUT || ( stream_.mode == DUPLEX && handle->id[0] != handle->id[1] ) ) { - result = ioctl( handle->id[1], SNDCTL_DSP_HALT, 0 ); - if ( result == -1 ) { - errorStream_ << "RtApiOss::abortStream: system error stopping input callback procedure on device (" << stream_.device[0] << ")."; - errorText_ = errorStream_.str(); - goto unlock; - } - } - - unlock: - stream_.state = STREAM_STOPPED; - MUTEX_UNLOCK( &stream_.mutex ); - - if ( result != -1 ) return; - error( RtAudioError::SYSTEM_ERROR ); -} - -void RtApiOss :: callbackEvent() -{ - OssHandle *handle = (OssHandle *) stream_.apiHandle; - if ( stream_.state == STREAM_STOPPED ) { - MUTEX_LOCK( &stream_.mutex ); - pthread_cond_wait( &handle->runnable, &stream_.mutex ); - if ( stream_.state != STREAM_RUNNING ) { - MUTEX_UNLOCK( &stream_.mutex ); - return; - } - MUTEX_UNLOCK( &stream_.mutex ); - } - - if ( stream_.state == STREAM_CLOSED ) { - errorText_ = "RtApiOss::callbackEvent(): the stream is closed ... this shouldn't happen!"; - error( RtAudioError::WARNING ); - return; - } - - // Invoke user callback to get fresh output data. - int doStopStream = 0; - RtAudioCallback callback = (RtAudioCallback) stream_.callbackInfo.callback; - double streamTime = getStreamTime(); - RtAudioStreamStatus status = 0; - if ( stream_.mode != INPUT && handle->xrun[0] == true ) { - status |= RTAUDIO_OUTPUT_UNDERFLOW; - handle->xrun[0] = false; - } - if ( stream_.mode != OUTPUT && handle->xrun[1] == true ) { - status |= RTAUDIO_INPUT_OVERFLOW; - handle->xrun[1] = false; - } - doStopStream = callback( stream_.userBuffer[0], stream_.userBuffer[1], - stream_.bufferSize, streamTime, status, stream_.callbackInfo.userData ); - if ( doStopStream == 2 ) { - this->abortStream(); - return; - } - - MUTEX_LOCK( &stream_.mutex ); - - // The state might change while waiting on a mutex. - if ( stream_.state == STREAM_STOPPED ) goto unlock; - - int result; - char *buffer; - int samples; - RtAudioFormat format; - - if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { - - // Setup parameters and do buffer conversion if necessary. - if ( stream_.doConvertBuffer[0] ) { - buffer = stream_.deviceBuffer; - convertBuffer( buffer, stream_.userBuffer[0], stream_.convertInfo[0] ); - samples = stream_.bufferSize * stream_.nDeviceChannels[0]; - format = stream_.deviceFormat[0]; - } - else { - buffer = stream_.userBuffer[0]; - samples = stream_.bufferSize * stream_.nUserChannels[0]; - format = stream_.userFormat; - } - - // Do byte swapping if necessary. - if ( stream_.doByteSwap[0] ) - byteSwapBuffer( buffer, samples, format ); - - if ( stream_.mode == DUPLEX && handle->triggered == false ) { - int trig = 0; - ioctl( handle->id[0], SNDCTL_DSP_SETTRIGGER, &trig ); - result = write( handle->id[0], buffer, samples * formatBytes(format) ); - trig = PCM_ENABLE_INPUT|PCM_ENABLE_OUTPUT; - ioctl( handle->id[0], SNDCTL_DSP_SETTRIGGER, &trig ); - handle->triggered = true; - } - else - // Write samples to device. - result = write( handle->id[0], buffer, samples * formatBytes(format) ); - - if ( result == -1 ) { - // We'll assume this is an underrun, though there isn't a - // specific means for determining that. - handle->xrun[0] = true; - errorText_ = "RtApiOss::callbackEvent: audio write error."; - error( RtAudioError::WARNING ); - // Continue on to input section. - } - } - - if ( stream_.mode == INPUT || stream_.mode == DUPLEX ) { - - // Setup parameters. - if ( stream_.doConvertBuffer[1] ) { - buffer = stream_.deviceBuffer; - samples = stream_.bufferSize * stream_.nDeviceChannels[1]; - format = stream_.deviceFormat[1]; - } - else { - buffer = stream_.userBuffer[1]; - samples = stream_.bufferSize * stream_.nUserChannels[1]; - format = stream_.userFormat; - } - - // Read samples from device. - result = read( handle->id[1], buffer, samples * formatBytes(format) ); - - if ( result == -1 ) { - // We'll assume this is an overrun, though there isn't a - // specific means for determining that. - handle->xrun[1] = true; - errorText_ = "RtApiOss::callbackEvent: audio read error."; - error( RtAudioError::WARNING ); - goto unlock; - } - - // Do byte swapping if necessary. - if ( stream_.doByteSwap[1] ) - byteSwapBuffer( buffer, samples, format ); - - // Do buffer conversion if necessary. - if ( stream_.doConvertBuffer[1] ) - convertBuffer( stream_.userBuffer[1], stream_.deviceBuffer, stream_.convertInfo[1] ); - } - - unlock: - MUTEX_UNLOCK( &stream_.mutex ); - - RtApi::tickStreamTime(); - if ( doStopStream == 1 ) this->stopStream(); -} - -static void *ossCallbackHandler( void *ptr ) -{ - CallbackInfo *info = (CallbackInfo *) ptr; - RtApiOss *object = (RtApiOss *) info->object; - bool *isRunning = &info->isRunning; - - while ( *isRunning == true ) { - pthread_testcancel(); - object->callbackEvent(); - } - - pthread_exit( NULL ); -} - -//******************** End of __LINUX_OSS__ *********************// -#endif - - -// *************************************************** // -// -// Protected common (OS-independent) RtAudio methods. -// -// *************************************************** // - -// This method can be modified to control the behavior of error -// message printing. -void RtApi :: error( RtAudioError::Type type ) -{ - errorStream_.str(""); // clear the ostringstream - - RtAudioErrorCallback errorCallback = (RtAudioErrorCallback) stream_.callbackInfo.errorCallback; - if ( errorCallback ) { - // abortStream() can generate new error messages. Ignore them. Just keep original one. - - if ( firstErrorOccurred_ ) - return; - - firstErrorOccurred_ = true; - const std::string errorMessage = errorText_; - - if ( type != RtAudioError::WARNING && stream_.state != STREAM_STOPPED) { - stream_.callbackInfo.isRunning = false; // exit from the thread - abortStream(); - } - - errorCallback( type, errorMessage ); - firstErrorOccurred_ = false; - return; - } - - if ( type == RtAudioError::WARNING && showWarnings_ == true ) - std::cerr << '\n' << errorText_ << "\n\n"; - else if ( type != RtAudioError::WARNING ) - throw( RtAudioError( errorText_, type ) ); -} - -void RtApi :: verifyStream() -{ - if ( stream_.state == STREAM_CLOSED ) { - errorText_ = "RtApi:: a stream is not open!"; - error( RtAudioError::INVALID_USE ); - } -} - -void RtApi :: clearStreamInfo() -{ - stream_.mode = UNINITIALIZED; - stream_.state = STREAM_CLOSED; - stream_.sampleRate = 0; - stream_.bufferSize = 0; - stream_.nBuffers = 0; - stream_.userFormat = 0; - stream_.userInterleaved = true; - stream_.streamTime = 0.0; - stream_.apiHandle = 0; - stream_.deviceBuffer = 0; - stream_.callbackInfo.callback = 0; - stream_.callbackInfo.userData = 0; - stream_.callbackInfo.isRunning = false; - stream_.callbackInfo.errorCallback = 0; - for ( int i=0; i<2; i++ ) { - stream_.device[i] = 11111; - stream_.doConvertBuffer[i] = false; - stream_.deviceInterleaved[i] = true; - stream_.doByteSwap[i] = false; - stream_.nUserChannels[i] = 0; - stream_.nDeviceChannels[i] = 0; - stream_.channelOffset[i] = 0; - stream_.deviceFormat[i] = 0; - stream_.latency[i] = 0; - stream_.userBuffer[i] = 0; - stream_.convertInfo[i].channels = 0; - stream_.convertInfo[i].inJump = 0; - stream_.convertInfo[i].outJump = 0; - stream_.convertInfo[i].inFormat = 0; - stream_.convertInfo[i].outFormat = 0; - stream_.convertInfo[i].inOffset.clear(); - stream_.convertInfo[i].outOffset.clear(); - } -} - -unsigned int RtApi :: formatBytes( RtAudioFormat format ) -{ - if ( format == RTAUDIO_SINT16 ) - return 2; - else if ( format == RTAUDIO_SINT32 || format == RTAUDIO_FLOAT32 ) - return 4; - else if ( format == RTAUDIO_FLOAT64 ) - return 8; - else if ( format == RTAUDIO_SINT24 ) - return 3; - else if ( format == RTAUDIO_SINT8 ) - return 1; - - errorText_ = "RtApi::formatBytes: undefined format."; - error( RtAudioError::WARNING ); - - return 0; -} - -void RtApi :: setConvertInfo( StreamMode mode, unsigned int firstChannel ) -{ - if ( mode == INPUT ) { // convert device to user buffer - stream_.convertInfo[mode].inJump = stream_.nDeviceChannels[1]; - stream_.convertInfo[mode].outJump = stream_.nUserChannels[1]; - stream_.convertInfo[mode].inFormat = stream_.deviceFormat[1]; - stream_.convertInfo[mode].outFormat = stream_.userFormat; - } - else { // convert user to device buffer - stream_.convertInfo[mode].inJump = stream_.nUserChannels[0]; - stream_.convertInfo[mode].outJump = stream_.nDeviceChannels[0]; - stream_.convertInfo[mode].inFormat = stream_.userFormat; - stream_.convertInfo[mode].outFormat = stream_.deviceFormat[0]; - } - - if ( stream_.convertInfo[mode].inJump < stream_.convertInfo[mode].outJump ) - stream_.convertInfo[mode].channels = stream_.convertInfo[mode].inJump; - else - stream_.convertInfo[mode].channels = stream_.convertInfo[mode].outJump; - - // Set up the interleave/deinterleave offsets. - if ( stream_.deviceInterleaved[mode] != stream_.userInterleaved ) { - if ( ( mode == OUTPUT && stream_.deviceInterleaved[mode] ) || - ( mode == INPUT && stream_.userInterleaved ) ) { - for ( int k=0; k 0 ) { - if ( stream_.deviceInterleaved[mode] ) { - if ( mode == OUTPUT ) { - for ( int k=0; k> 8); - //out[info.outOffset[j]] >>= 8; - } - in += info.inJump; - out += info.outJump; - } - } - else if (info.inFormat == RTAUDIO_FLOAT32) { - Float32 *in = (Float32 *)inBuffer; - for (unsigned int i=0; i> 8); - } - in += info.inJump; - out += info.outJump; - } - } - else if (info.inFormat == RTAUDIO_SINT32) { - Int32 *in = (Int32 *)inBuffer; - for (unsigned int i=0; i> 16) & 0x0000ffff); - } - in += info.inJump; - out += info.outJump; - } - } - else if (info.inFormat == RTAUDIO_FLOAT32) { - Float32 *in = (Float32 *)inBuffer; - for (unsigned int i=0; i> 8) & 0x00ff); - } - in += info.inJump; - out += info.outJump; - } - } - else if (info.inFormat == RTAUDIO_SINT24) { - Int24 *in = (Int24 *)inBuffer; - for (unsigned int i=0; i> 16); - } - in += info.inJump; - out += info.outJump; - } - } - else if (info.inFormat == RTAUDIO_SINT32) { - Int32 *in = (Int32 *)inBuffer; - for (unsigned int i=0; i> 24) & 0x000000ff); - } - in += info.inJump; - out += info.outJump; - } - } - else if (info.inFormat == RTAUDIO_FLOAT32) { - Float32 *in = (Float32 *)inBuffer; - for (unsigned int i=0; i>8) | (x<<8); } -//static inline uint32_t bswap_32(uint32_t x) { return (bswap_16(x&0xffff)<<16) | (bswap_16(x>>16)); } -//static inline uint64_t bswap_64(uint64_t x) { return (((unsigned long long)bswap_32(x&0xffffffffull))<<32) | (bswap_32(x>>32)); } - -void RtApi :: byteSwapBuffer( char *buffer, unsigned int samples, RtAudioFormat format ) -{ - char val; - char *ptr; - - ptr = buffer; - if ( format == RTAUDIO_SINT16 ) { - for ( unsigned int i=0; i -#include -#include -#include - -/*! \typedef typedef unsigned long RtAudioFormat; - \brief RtAudio data format type. - - Support for signed integers and floats. Audio data fed to/from an - RtAudio stream is assumed to ALWAYS be in host byte order. The - internal routines will automatically take care of any necessary - byte-swapping between the host format and the soundcard. Thus, - endian-ness is not a concern in the following format definitions. - - - \e RTAUDIO_SINT8: 8-bit signed integer. - - \e RTAUDIO_SINT16: 16-bit signed integer. - - \e RTAUDIO_SINT24: 24-bit signed integer. - - \e RTAUDIO_SINT32: 32-bit signed integer. - - \e RTAUDIO_FLOAT32: Normalized between plus/minus 1.0. - - \e RTAUDIO_FLOAT64: Normalized between plus/minus 1.0. -*/ -typedef unsigned long RtAudioFormat; -static const RtAudioFormat RTAUDIO_SINT8 = 0x1; // 8-bit signed integer. -static const RtAudioFormat RTAUDIO_SINT16 = 0x2; // 16-bit signed integer. -static const RtAudioFormat RTAUDIO_SINT24 = 0x4; // 24-bit signed integer. -static const RtAudioFormat RTAUDIO_SINT32 = 0x8; // 32-bit signed integer. -static const RtAudioFormat RTAUDIO_FLOAT32 = 0x10; // Normalized between plus/minus 1.0. -static const RtAudioFormat RTAUDIO_FLOAT64 = 0x20; // Normalized between plus/minus 1.0. - -/*! \typedef typedef unsigned long RtAudioStreamFlags; - \brief RtAudio stream option flags. - - The following flags can be OR'ed together to allow a client to - make changes to the default stream behavior: - - - \e RTAUDIO_NONINTERLEAVED: Use non-interleaved buffers (default = interleaved). - - \e RTAUDIO_MINIMIZE_LATENCY: Attempt to set stream parameters for lowest possible latency. - - \e RTAUDIO_HOG_DEVICE: Attempt grab device for exclusive use. - - \e RTAUDIO_ALSA_USE_DEFAULT: Use the "default" PCM device (ALSA only). - - By default, RtAudio streams pass and receive audio data from the - client in an interleaved format. By passing the - RTAUDIO_NONINTERLEAVED flag to the openStream() function, audio - data will instead be presented in non-interleaved buffers. In - this case, each buffer argument in the RtAudioCallback function - will point to a single array of data, with \c nFrames samples for - each channel concatenated back-to-back. For example, the first - sample of data for the second channel would be located at index \c - nFrames (assuming the \c buffer pointer was recast to the correct - data type for the stream). - - Certain audio APIs offer a number of parameters that influence the - I/O latency of a stream. By default, RtAudio will attempt to set - these parameters internally for robust (glitch-free) performance - (though some APIs, like Windows Direct Sound, make this difficult). - By passing the RTAUDIO_MINIMIZE_LATENCY flag to the openStream() - function, internal stream settings will be influenced in an attempt - to minimize stream latency, though possibly at the expense of stream - performance. - - If the RTAUDIO_HOG_DEVICE flag is set, RtAudio will attempt to - open the input and/or output stream device(s) for exclusive use. - Note that this is not possible with all supported audio APIs. - - If the RTAUDIO_SCHEDULE_REALTIME flag is set, RtAudio will attempt - to select realtime scheduling (round-robin) for the callback thread. - - If the RTAUDIO_ALSA_USE_DEFAULT flag is set, RtAudio will attempt to - open the "default" PCM device when using the ALSA API. Note that this - will override any specified input or output device id. -*/ -typedef unsigned int RtAudioStreamFlags; -static const RtAudioStreamFlags RTAUDIO_NONINTERLEAVED = 0x1; // Use non-interleaved buffers (default = interleaved). -static const RtAudioStreamFlags RTAUDIO_MINIMIZE_LATENCY = 0x2; // Attempt to set stream parameters for lowest possible latency. -static const RtAudioStreamFlags RTAUDIO_HOG_DEVICE = 0x4; // Attempt grab device and prevent use by others. -static const RtAudioStreamFlags RTAUDIO_SCHEDULE_REALTIME = 0x8; // Try to select realtime scheduling for callback thread. -static const RtAudioStreamFlags RTAUDIO_ALSA_USE_DEFAULT = 0x10; // Use the "default" PCM device (ALSA only). - -/*! \typedef typedef unsigned long RtAudioStreamStatus; - \brief RtAudio stream status (over- or underflow) flags. - - Notification of a stream over- or underflow is indicated by a - non-zero stream \c status argument in the RtAudioCallback function. - The stream status can be one of the following two options, - depending on whether the stream is open for output and/or input: - - - \e RTAUDIO_INPUT_OVERFLOW: Input data was discarded because of an overflow condition at the driver. - - \e RTAUDIO_OUTPUT_UNDERFLOW: The output buffer ran low, likely producing a break in the output sound. -*/ -typedef unsigned int RtAudioStreamStatus; -static const RtAudioStreamStatus RTAUDIO_INPUT_OVERFLOW = 0x1; // Input data was discarded because of an overflow condition at the driver. -static const RtAudioStreamStatus RTAUDIO_OUTPUT_UNDERFLOW = 0x2; // The output buffer ran low, likely causing a gap in the output sound. - -//! RtAudio callback function prototype. -/*! - All RtAudio clients must create a function of type RtAudioCallback - to read and/or write data from/to the audio stream. When the - underlying audio system is ready for new input or output data, this - function will be invoked. - - \param outputBuffer For output (or duplex) streams, the client - should write \c nFrames of audio sample frames into this - buffer. This argument should be recast to the datatype - specified when the stream was opened. For input-only - streams, this argument will be NULL. - - \param inputBuffer For input (or duplex) streams, this buffer will - hold \c nFrames of input audio sample frames. This - argument should be recast to the datatype specified when the - stream was opened. For output-only streams, this argument - will be NULL. - - \param nFrames The number of sample frames of input or output - data in the buffers. The actual buffer size in bytes is - dependent on the data type and number of channels in use. - - \param streamTime The number of seconds that have elapsed since the - stream was started. - - \param status If non-zero, this argument indicates a data overflow - or underflow condition for the stream. The particular - condition can be determined by comparison with the - RtAudioStreamStatus flags. - - \param userData A pointer to optional data provided by the client - when opening the stream (default = NULL). - - To continue normal stream operation, the RtAudioCallback function - should return a value of zero. To stop the stream and drain the - output buffer, the function should return a value of one. To abort - the stream immediately, the client should return a value of two. - */ -typedef int (*RtAudioCallback)( void *outputBuffer, void *inputBuffer, - unsigned int nFrames, - double streamTime, - RtAudioStreamStatus status, - void *userData ); - -/************************************************************************/ -/*! \class RtAudioError - \brief Exception handling class for RtAudio. - - The RtAudioError class is quite simple but it does allow errors to be - "caught" by RtAudioError::Type. See the RtAudio documentation to know - which methods can throw an RtAudioError. -*/ -/************************************************************************/ - -class RtAudioError : public std::exception -{ - public: - //! Defined RtAudioError types. - enum Type { - WARNING, /*!< A non-critical error. */ - DEBUG_WARNING, /*!< A non-critical error which might be useful for debugging. */ - UNSPECIFIED, /*!< The default, unspecified error type. */ - NO_DEVICES_FOUND, /*!< No devices found on system. */ - INVALID_DEVICE, /*!< An invalid device ID was specified. */ - MEMORY_ERROR, /*!< An error occured during memory allocation. */ - INVALID_PARAMETER, /*!< An invalid parameter was specified to a function. */ - INVALID_USE, /*!< The function was called incorrectly. */ - DRIVER_ERROR, /*!< A system driver error occured. */ - SYSTEM_ERROR, /*!< A system error occured. */ - THREAD_ERROR /*!< A thread error occured. */ - }; - - //! The constructor. - RtAudioError( const std::string& message, Type type = RtAudioError::UNSPECIFIED ) throw() : message_(message), type_(type) {} - - //! The destructor. - virtual ~RtAudioError( void ) throw() {} - - //! Prints thrown error message to stderr. - virtual void printMessage( void ) const throw() { std::cerr << '\n' << message_ << "\n\n"; } - - //! Returns the thrown error message type. - virtual const Type& getType(void) const throw() { return type_; } - - //! Returns the thrown error message string. - virtual const std::string& getMessage(void) const throw() { return message_; } - - //! Returns the thrown error message as a c-style string. - virtual const char* what( void ) const throw() { return message_.c_str(); } - - protected: - std::string message_; - Type type_; -}; - -//! RtAudio error callback function prototype. -/*! - \param type Type of error. - \param errorText Error description. - */ -typedef void (*RtAudioErrorCallback)( RtAudioError::Type type, const std::string &errorText ); - -// **************************************************************** // -// -// RtAudio class declaration. -// -// RtAudio is a "controller" used to select an available audio i/o -// interface. It presents a common API for the user to call but all -// functionality is implemented by the class RtApi and its -// subclasses. RtAudio creates an instance of an RtApi subclass -// based on the user's API choice. If no choice is made, RtAudio -// attempts to make a "logical" API selection. -// -// **************************************************************** // - -class RtApi; - -class RtAudio -{ - public: - - //! Audio API specifier arguments. - enum Api { - UNSPECIFIED, /*!< Search for a working compiled API. */ - LINUX_ALSA, /*!< The Advanced Linux Sound Architecture API. */ - LINUX_PULSE, /*!< The Linux PulseAudio API. */ - LINUX_OSS, /*!< The Linux Open Sound System API. */ - UNIX_JACK, /*!< The Jack Low-Latency Audio Server API. */ - MACOSX_CORE, /*!< Macintosh OS-X Core Audio API. */ - WINDOWS_WASAPI, /*!< The Microsoft WASAPI API. */ - WINDOWS_ASIO, /*!< The Steinberg Audio Stream I/O API. */ - WINDOWS_DS, /*!< The Microsoft Direct Sound API. */ - RTAUDIO_DUMMY /*!< A compilable but non-functional API. */ - }; - - //! The public device information structure for returning queried values. - struct DeviceInfo { - bool probed; /*!< true if the device capabilities were successfully probed. */ - std::string name; /*!< Character string device identifier. */ - unsigned int outputChannels; /*!< Maximum output channels supported by device. */ - unsigned int inputChannels; /*!< Maximum input channels supported by device. */ - unsigned int duplexChannels; /*!< Maximum simultaneous input/output channels supported by device. */ - bool isDefaultOutput; /*!< true if this is the default output device. */ - bool isDefaultInput; /*!< true if this is the default input device. */ - std::vector sampleRates; /*!< Supported sample rates (queried from list of standard rates). */ - unsigned int preferredSampleRate; /*!< Preferred sample rate, eg. for WASAPI the system sample rate. */ - RtAudioFormat nativeFormats; /*!< Bit mask of supported data formats. */ - - // Default constructor. - DeviceInfo() - :probed(false), outputChannels(0), inputChannels(0), duplexChannels(0), - isDefaultOutput(false), isDefaultInput(false), preferredSampleRate(0), nativeFormats(0) {} - }; - - //! The structure for specifying input or ouput stream parameters. - struct StreamParameters { - unsigned int deviceId; /*!< Device index (0 to getDeviceCount() - 1). */ - unsigned int nChannels; /*!< Number of channels. */ - unsigned int firstChannel; /*!< First channel index on device (default = 0). */ - - // Default constructor. - StreamParameters() - : deviceId(0), nChannels(0), firstChannel(0) {} - }; - - //! The structure for specifying stream options. - /*! - The following flags can be OR'ed together to allow a client to - make changes to the default stream behavior: - - - \e RTAUDIO_NONINTERLEAVED: Use non-interleaved buffers (default = interleaved). - - \e RTAUDIO_MINIMIZE_LATENCY: Attempt to set stream parameters for lowest possible latency. - - \e RTAUDIO_HOG_DEVICE: Attempt grab device for exclusive use. - - \e RTAUDIO_SCHEDULE_REALTIME: Attempt to select realtime scheduling for callback thread. - - \e RTAUDIO_ALSA_USE_DEFAULT: Use the "default" PCM device (ALSA only). - - By default, RtAudio streams pass and receive audio data from the - client in an interleaved format. By passing the - RTAUDIO_NONINTERLEAVED flag to the openStream() function, audio - data will instead be presented in non-interleaved buffers. In - this case, each buffer argument in the RtAudioCallback function - will point to a single array of data, with \c nFrames samples for - each channel concatenated back-to-back. For example, the first - sample of data for the second channel would be located at index \c - nFrames (assuming the \c buffer pointer was recast to the correct - data type for the stream). - - Certain audio APIs offer a number of parameters that influence the - I/O latency of a stream. By default, RtAudio will attempt to set - these parameters internally for robust (glitch-free) performance - (though some APIs, like Windows Direct Sound, make this difficult). - By passing the RTAUDIO_MINIMIZE_LATENCY flag to the openStream() - function, internal stream settings will be influenced in an attempt - to minimize stream latency, though possibly at the expense of stream - performance. - - If the RTAUDIO_HOG_DEVICE flag is set, RtAudio will attempt to - open the input and/or output stream device(s) for exclusive use. - Note that this is not possible with all supported audio APIs. - - If the RTAUDIO_SCHEDULE_REALTIME flag is set, RtAudio will attempt - to select realtime scheduling (round-robin) for the callback thread. - The \c priority parameter will only be used if the RTAUDIO_SCHEDULE_REALTIME - flag is set. It defines the thread's realtime priority. - - If the RTAUDIO_ALSA_USE_DEFAULT flag is set, RtAudio will attempt to - open the "default" PCM device when using the ALSA API. Note that this - will override any specified input or output device id. - - The \c numberOfBuffers parameter can be used to control stream - latency in the Windows DirectSound, Linux OSS, and Linux Alsa APIs - only. A value of two is usually the smallest allowed. Larger - numbers can potentially result in more robust stream performance, - though likely at the cost of stream latency. The value set by the - user is replaced during execution of the RtAudio::openStream() - function by the value actually used by the system. - - The \c streamName parameter can be used to set the client name - when using the Jack API. By default, the client name is set to - RtApiJack. However, if you wish to create multiple instances of - RtAudio with Jack, each instance must have a unique client name. - */ - struct StreamOptions { - RtAudioStreamFlags flags; /*!< A bit-mask of stream flags (RTAUDIO_NONINTERLEAVED, RTAUDIO_MINIMIZE_LATENCY, RTAUDIO_HOG_DEVICE, RTAUDIO_ALSA_USE_DEFAULT). */ - unsigned int numberOfBuffers; /*!< Number of stream buffers. */ - std::string streamName; /*!< A stream name (currently used only in Jack). */ - int priority; /*!< Scheduling priority of callback thread (only used with flag RTAUDIO_SCHEDULE_REALTIME). */ - - // Default constructor. - StreamOptions() - : flags(0), numberOfBuffers(0), priority(0) {} - }; - - //! A static function to determine the current RtAudio version. - static std::string getVersion( void ) throw(); - - //! A static function to determine the available compiled audio APIs. - /*! - The values returned in the std::vector can be compared against - the enumerated list values. Note that there can be more than one - API compiled for certain operating systems. - */ - static void getCompiledApi( std::vector &apis ) throw(); - - //! The class constructor. - /*! - The constructor performs minor initialization tasks. An exception - can be thrown if no API support is compiled. - - If no API argument is specified and multiple API support has been - compiled, the default order of use is JACK, ALSA, OSS (Linux - systems) and ASIO, DS (Windows systems). - */ - RtAudio( RtAudio::Api api=UNSPECIFIED ); - - //! The destructor. - /*! - If a stream is running or open, it will be stopped and closed - automatically. - */ - ~RtAudio() throw(); - - //! Returns the audio API specifier for the current instance of RtAudio. - RtAudio::Api getCurrentApi( void ) throw(); - - //! A public function that queries for the number of audio devices available. - /*! - This function performs a system query of available devices each time it - is called, thus supporting devices connected \e after instantiation. If - a system error occurs during processing, a warning will be issued. - */ - unsigned int getDeviceCount( void ) throw(); - - //! Return an RtAudio::DeviceInfo structure for a specified device number. - /*! - - Any device integer between 0 and getDeviceCount() - 1 is valid. - If an invalid argument is provided, an RtAudioError (type = INVALID_USE) - will be thrown. If a device is busy or otherwise unavailable, the - structure member "probed" will have a value of "false" and all - other members are undefined. If the specified device is the - current default input or output device, the corresponding - "isDefault" member will have a value of "true". - */ - RtAudio::DeviceInfo getDeviceInfo( unsigned int device ); - - //! A function that returns the index of the default output device. - /*! - If the underlying audio API does not provide a "default - device", or if no devices are available, the return value will be - 0. Note that this is a valid device identifier and it is the - client's responsibility to verify that a device is available - before attempting to open a stream. - */ - unsigned int getDefaultOutputDevice( void ) throw(); - - //! A function that returns the index of the default input device. - /*! - If the underlying audio API does not provide a "default - device", or if no devices are available, the return value will be - 0. Note that this is a valid device identifier and it is the - client's responsibility to verify that a device is available - before attempting to open a stream. - */ - unsigned int getDefaultInputDevice( void ) throw(); - - //! A public function for opening a stream with the specified parameters. - /*! - An RtAudioError (type = SYSTEM_ERROR) is thrown if a stream cannot be - opened with the specified parameters or an error occurs during - processing. An RtAudioError (type = INVALID_USE) is thrown if any - invalid device ID or channel number parameters are specified. - - \param outputParameters Specifies output stream parameters to use - when opening a stream, including a device ID, number of channels, - and starting channel number. For input-only streams, this - argument should be NULL. The device ID is an index value between - 0 and getDeviceCount() - 1. - \param inputParameters Specifies input stream parameters to use - when opening a stream, including a device ID, number of channels, - and starting channel number. For output-only streams, this - argument should be NULL. The device ID is an index value between - 0 and getDeviceCount() - 1. - \param format An RtAudioFormat specifying the desired sample data format. - \param sampleRate The desired sample rate (sample frames per second). - \param *bufferFrames A pointer to a value indicating the desired - internal buffer size in sample frames. The actual value - used by the device is returned via the same pointer. A - value of zero can be specified, in which case the lowest - allowable value is determined. - \param callback A client-defined function that will be invoked - when input data is available and/or output data is needed. - \param userData An optional pointer to data that can be accessed - from within the callback function. - \param options An optional pointer to a structure containing various - global stream options, including a list of OR'ed RtAudioStreamFlags - and a suggested number of stream buffers that can be used to - control stream latency. More buffers typically result in more - robust performance, though at a cost of greater latency. If a - value of zero is specified, a system-specific median value is - chosen. If the RTAUDIO_MINIMIZE_LATENCY flag bit is set, the - lowest allowable value is used. The actual value used is - returned via the structure argument. The parameter is API dependent. - \param errorCallback A client-defined function that will be invoked - when an error has occured. - */ - void openStream( RtAudio::StreamParameters *outputParameters, - RtAudio::StreamParameters *inputParameters, - RtAudioFormat format, unsigned int sampleRate, - unsigned int *bufferFrames, RtAudioCallback callback, - void *userData = NULL, RtAudio::StreamOptions *options = NULL, RtAudioErrorCallback errorCallback = NULL ); - - //! A function that closes a stream and frees any associated stream memory. - /*! - If a stream is not open, this function issues a warning and - returns (no exception is thrown). - */ - void closeStream( void ) throw(); - - //! A function that starts a stream. - /*! - An RtAudioError (type = SYSTEM_ERROR) is thrown if an error occurs - during processing. An RtAudioError (type = INVALID_USE) is thrown if a - stream is not open. A warning is issued if the stream is already - running. - */ - void startStream( void ); - - //! Stop a stream, allowing any samples remaining in the output queue to be played. - /*! - An RtAudioError (type = SYSTEM_ERROR) is thrown if an error occurs - during processing. An RtAudioError (type = INVALID_USE) is thrown if a - stream is not open. A warning is issued if the stream is already - stopped. - */ - void stopStream( void ); - - //! Stop a stream, discarding any samples remaining in the input/output queue. - /*! - An RtAudioError (type = SYSTEM_ERROR) is thrown if an error occurs - during processing. An RtAudioError (type = INVALID_USE) is thrown if a - stream is not open. A warning is issued if the stream is already - stopped. - */ - void abortStream( void ); - - //! Returns true if a stream is open and false if not. - bool isStreamOpen( void ) const throw(); - - //! Returns true if the stream is running and false if it is stopped or not open. - bool isStreamRunning( void ) const throw(); - - //! Returns the number of elapsed seconds since the stream was started. - /*! - If a stream is not open, an RtAudioError (type = INVALID_USE) will be thrown. - */ - double getStreamTime( void ); - - //! Set the stream time to a time in seconds greater than or equal to 0.0. - /*! - If a stream is not open, an RtAudioError (type = INVALID_USE) will be thrown. - */ - void setStreamTime( double time ); - - //! Returns the internal stream latency in sample frames. - /*! - The stream latency refers to delay in audio input and/or output - caused by internal buffering by the audio system and/or hardware. - For duplex streams, the returned value will represent the sum of - the input and output latencies. If a stream is not open, an - RtAudioError (type = INVALID_USE) will be thrown. If the API does not - report latency, the return value will be zero. - */ - long getStreamLatency( void ); - - //! Returns actual sample rate in use by the stream. - /*! - On some systems, the sample rate used may be slightly different - than that specified in the stream parameters. If a stream is not - open, an RtAudioError (type = INVALID_USE) will be thrown. - */ - unsigned int getStreamSampleRate( void ); - - //! Specify whether warning messages should be printed to stderr. - void showWarnings( bool value = true ) throw(); - - protected: - - void openRtApi( RtAudio::Api api ); - RtApi *rtapi_; -}; - -// Operating system dependent thread functionality. -#if defined(__WINDOWS_DS__) || defined(__WINDOWS_ASIO__) || defined(__WINDOWS_WASAPI__) - - #ifndef NOMINMAX - #define NOMINMAX - #endif - #include - #include - - typedef uintptr_t ThreadHandle; - typedef CRITICAL_SECTION StreamMutex; - -#elif defined(__LINUX_ALSA__) || defined(__LINUX_PULSE__) || defined(__UNIX_JACK__) || defined(__LINUX_OSS__) || defined(__MACOSX_CORE__) - // Using pthread library for various flavors of unix. - #include - - typedef pthread_t ThreadHandle; - typedef pthread_mutex_t StreamMutex; - -#else // Setup for "dummy" behavior - - #define __RTAUDIO_DUMMY__ - typedef int ThreadHandle; - typedef int StreamMutex; - -#endif - -// This global structure type is used to pass callback information -// between the private RtAudio stream structure and global callback -// handling functions. -struct CallbackInfo { - void *object; // Used as a "this" pointer. - ThreadHandle thread; - void *callback; - void *userData; - void *errorCallback; - void *apiInfo; // void pointer for API specific callback information - bool isRunning; - bool doRealtime; - int priority; - - // Default constructor. - CallbackInfo() - :object(0), callback(0), userData(0), errorCallback(0), apiInfo(0), isRunning(false), doRealtime(false) {} -}; - -// **************************************************************** // -// -// RtApi class declaration. -// -// Subclasses of RtApi contain all API- and OS-specific code necessary -// to fully implement the RtAudio API. -// -// Note that RtApi is an abstract base class and cannot be -// explicitly instantiated. The class RtAudio will create an -// instance of an RtApi subclass (RtApiOss, RtApiAlsa, -// RtApiJack, RtApiCore, RtApiDs, or RtApiAsio). -// -// **************************************************************** // - -#pragma pack(push, 1) -class S24 { - - protected: - unsigned char c3[3]; - - public: - S24() {} - - S24& operator = ( const int& i ) { - c3[0] = (i & 0x000000ff); - c3[1] = (i & 0x0000ff00) >> 8; - c3[2] = (i & 0x00ff0000) >> 16; - return *this; - } - - S24( const S24& v ) { *this = v; } - S24( const double& d ) { *this = (int) d; } - S24( const float& f ) { *this = (int) f; } - S24( const signed short& s ) { *this = (int) s; } - S24( const char& c ) { *this = (int) c; } - - int asInt() { - int i = c3[0] | (c3[1] << 8) | (c3[2] << 16); - if (i & 0x800000) i |= ~0xffffff; - return i; - } -}; -#pragma pack(pop) - -#if defined( HAVE_GETTIMEOFDAY ) - #include -#endif - -#include - -class RtApi -{ -public: - - RtApi(); - virtual ~RtApi(); - virtual RtAudio::Api getCurrentApi( void ) = 0; - virtual unsigned int getDeviceCount( void ) = 0; - virtual RtAudio::DeviceInfo getDeviceInfo( unsigned int device ) = 0; - virtual unsigned int getDefaultInputDevice( void ); - virtual unsigned int getDefaultOutputDevice( void ); - void openStream( RtAudio::StreamParameters *outputParameters, - RtAudio::StreamParameters *inputParameters, - RtAudioFormat format, unsigned int sampleRate, - unsigned int *bufferFrames, RtAudioCallback callback, - void *userData, RtAudio::StreamOptions *options, - RtAudioErrorCallback errorCallback ); - virtual void closeStream( void ); - virtual void startStream( void ) = 0; - virtual void stopStream( void ) = 0; - virtual void abortStream( void ) = 0; - long getStreamLatency( void ); - unsigned int getStreamSampleRate( void ); - virtual double getStreamTime( void ); - virtual void setStreamTime( double time ); - bool isStreamOpen( void ) const { return stream_.state != STREAM_CLOSED; } - bool isStreamRunning( void ) const { return stream_.state == STREAM_RUNNING; } - void showWarnings( bool value ) { showWarnings_ = value; } - - -protected: - - static const unsigned int MAX_SAMPLE_RATES; - static const unsigned int SAMPLE_RATES[]; - - enum { FAILURE, SUCCESS }; - - enum StreamState { - STREAM_STOPPED, - STREAM_STOPPING, - STREAM_RUNNING, - STREAM_CLOSED = -50 - }; - - enum StreamMode { - OUTPUT, - INPUT, - DUPLEX, - UNINITIALIZED = -75 - }; - - // A protected structure used for buffer conversion. - struct ConvertInfo { - int channels; - int inJump, outJump; - RtAudioFormat inFormat, outFormat; - std::vector inOffset; - std::vector outOffset; - }; - - // A protected structure for audio streams. - struct RtApiStream { - unsigned int device[2]; // Playback and record, respectively. - void *apiHandle; // void pointer for API specific stream handle information - StreamMode mode; // OUTPUT, INPUT, or DUPLEX. - StreamState state; // STOPPED, RUNNING, or CLOSED - char *userBuffer[2]; // Playback and record, respectively. - char *deviceBuffer; - bool doConvertBuffer[2]; // Playback and record, respectively. - bool userInterleaved; - bool deviceInterleaved[2]; // Playback and record, respectively. - bool doByteSwap[2]; // Playback and record, respectively. - unsigned int sampleRate; - unsigned int bufferSize; - unsigned int nBuffers; - unsigned int nUserChannels[2]; // Playback and record, respectively. - unsigned int nDeviceChannels[2]; // Playback and record channels, respectively. - unsigned int channelOffset[2]; // Playback and record, respectively. - unsigned long latency[2]; // Playback and record, respectively. - RtAudioFormat userFormat; - RtAudioFormat deviceFormat[2]; // Playback and record, respectively. - StreamMutex mutex; - CallbackInfo callbackInfo; - ConvertInfo convertInfo[2]; - double streamTime; // Number of elapsed seconds since the stream started. - -#if defined(HAVE_GETTIMEOFDAY) - struct timeval lastTickTimestamp; -#endif - - RtApiStream() - :apiHandle(0), deviceBuffer(0) { device[0] = 11111; device[1] = 11111; } - }; - - typedef S24 Int24; - typedef signed short Int16; - typedef signed int Int32; - typedef float Float32; - typedef double Float64; - - std::ostringstream errorStream_; - std::string errorText_; - bool showWarnings_; - RtApiStream stream_; - bool firstErrorOccurred_; - - /*! - Protected, api-specific method that attempts to open a device - with the given parameters. This function MUST be implemented by - all subclasses. If an error is encountered during the probe, a - "warning" message is reported and FAILURE is returned. A - successful probe is indicated by a return value of SUCCESS. - */ - virtual bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, - unsigned int firstChannel, unsigned int sampleRate, - RtAudioFormat format, unsigned int *bufferSize, - RtAudio::StreamOptions *options ); - - //! A protected function used to increment the stream time. - void tickStreamTime( void ); - - //! Protected common method to clear an RtApiStream structure. - void clearStreamInfo(); - - /*! - Protected common method that throws an RtAudioError (type = - INVALID_USE) if a stream is not open. - */ - void verifyStream( void ); - - //! Protected common error method to allow global control over error handling. - void error( RtAudioError::Type type ); - - /*! - Protected method used to perform format, channel number, and/or interleaving - conversions between the user and device buffers. - */ - void convertBuffer( char *outBuffer, char *inBuffer, ConvertInfo &info ); - - //! Protected common method used to perform byte-swapping on buffers. - void byteSwapBuffer( char *buffer, unsigned int samples, RtAudioFormat format ); - - //! Protected common method that returns the number of bytes for a given format. - unsigned int formatBytes( RtAudioFormat format ); - - //! Protected common method that sets up the parameters for buffer conversion. - void setConvertInfo( StreamMode mode, unsigned int firstChannel ); -}; - -// **************************************************************** // -// -// Inline RtAudio definitions. -// -// **************************************************************** // - -inline RtAudio::Api RtAudio :: getCurrentApi( void ) throw() { return rtapi_->getCurrentApi(); } -inline unsigned int RtAudio :: getDeviceCount( void ) throw() { return rtapi_->getDeviceCount(); } -inline RtAudio::DeviceInfo RtAudio :: getDeviceInfo( unsigned int device ) { return rtapi_->getDeviceInfo( device ); } -inline unsigned int RtAudio :: getDefaultInputDevice( void ) throw() { return rtapi_->getDefaultInputDevice(); } -inline unsigned int RtAudio :: getDefaultOutputDevice( void ) throw() { return rtapi_->getDefaultOutputDevice(); } -inline void RtAudio :: closeStream( void ) throw() { return rtapi_->closeStream(); } -inline void RtAudio :: startStream( void ) { return rtapi_->startStream(); } -inline void RtAudio :: stopStream( void ) { return rtapi_->stopStream(); } -inline void RtAudio :: abortStream( void ) { return rtapi_->abortStream(); } -inline bool RtAudio :: isStreamOpen( void ) const throw() { return rtapi_->isStreamOpen(); } -inline bool RtAudio :: isStreamRunning( void ) const throw() { return rtapi_->isStreamRunning(); } -inline long RtAudio :: getStreamLatency( void ) { return rtapi_->getStreamLatency(); } -inline unsigned int RtAudio :: getStreamSampleRate( void ) { return rtapi_->getStreamSampleRate(); } -inline double RtAudio :: getStreamTime( void ) { return rtapi_->getStreamTime(); } -inline void RtAudio :: setStreamTime( double time ) { return rtapi_->setStreamTime( time ); } -inline void RtAudio :: showWarnings( bool value ) throw() { rtapi_->showWarnings( value ); } - -// RtApi Subclass prototypes. - -#if defined(__MACOSX_CORE__) - -#include - -class RtApiCore: public RtApi -{ -public: - - RtApiCore(); - ~RtApiCore(); - RtAudio::Api getCurrentApi( void ) { return RtAudio::MACOSX_CORE; } - unsigned int getDeviceCount( void ); - RtAudio::DeviceInfo getDeviceInfo( unsigned int device ); - unsigned int getDefaultOutputDevice( void ); - unsigned int getDefaultInputDevice( void ); - void closeStream( void ); - void startStream( void ); - void stopStream( void ); - void abortStream( void ); - long getStreamLatency( void ); - - // This function is intended for internal use only. It must be - // public because it is called by the internal callback handler, - // which is not a member of RtAudio. External use of this function - // will most likely produce highly undesireable results! - bool callbackEvent( AudioDeviceID deviceId, - const AudioBufferList *inBufferList, - const AudioBufferList *outBufferList ); - - private: - - bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, - unsigned int firstChannel, unsigned int sampleRate, - RtAudioFormat format, unsigned int *bufferSize, - RtAudio::StreamOptions *options ); - static const char* getErrorCode( OSStatus code ); -}; - -#endif - -#if defined(__UNIX_JACK__) - -class RtApiJack: public RtApi -{ -public: - - RtApiJack(); - ~RtApiJack(); - RtAudio::Api getCurrentApi( void ) { return RtAudio::UNIX_JACK; } - unsigned int getDeviceCount( void ); - RtAudio::DeviceInfo getDeviceInfo( unsigned int device ); - void closeStream( void ); - void startStream( void ); - void stopStream( void ); - void abortStream( void ); - long getStreamLatency( void ); - - // This function is intended for internal use only. It must be - // public because it is called by the internal callback handler, - // which is not a member of RtAudio. External use of this function - // will most likely produce highly undesireable results! - bool callbackEvent( unsigned long nframes ); - - private: - - bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, - unsigned int firstChannel, unsigned int sampleRate, - RtAudioFormat format, unsigned int *bufferSize, - RtAudio::StreamOptions *options ); -}; - -#endif - -#if defined(__WINDOWS_ASIO__) - -class RtApiAsio: public RtApi -{ -public: - - RtApiAsio(); - ~RtApiAsio(); - RtAudio::Api getCurrentApi( void ) { return RtAudio::WINDOWS_ASIO; } - unsigned int getDeviceCount( void ); - RtAudio::DeviceInfo getDeviceInfo( unsigned int device ); - void closeStream( void ); - void startStream( void ); - void stopStream( void ); - void abortStream( void ); - long getStreamLatency( void ); - - // This function is intended for internal use only. It must be - // public because it is called by the internal callback handler, - // which is not a member of RtAudio. External use of this function - // will most likely produce highly undesireable results! - bool callbackEvent( long bufferIndex ); - - private: - - std::vector devices_; - void saveDeviceInfo( void ); - bool coInitialized_; - bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, - unsigned int firstChannel, unsigned int sampleRate, - RtAudioFormat format, unsigned int *bufferSize, - RtAudio::StreamOptions *options ); -}; - -#endif - -#if defined(__WINDOWS_DS__) - -class RtApiDs: public RtApi -{ -public: - - RtApiDs(); - ~RtApiDs(); - RtAudio::Api getCurrentApi( void ) { return RtAudio::WINDOWS_DS; } - unsigned int getDeviceCount( void ); - unsigned int getDefaultOutputDevice( void ); - unsigned int getDefaultInputDevice( void ); - RtAudio::DeviceInfo getDeviceInfo( unsigned int device ); - void closeStream( void ); - void startStream( void ); - void stopStream( void ); - void abortStream( void ); - long getStreamLatency( void ); - - // This function is intended for internal use only. It must be - // public because it is called by the internal callback handler, - // which is not a member of RtAudio. External use of this function - // will most likely produce highly undesireable results! - void callbackEvent( void ); - - private: - - bool coInitialized_; - bool buffersRolling; - long duplexPrerollBytes; - std::vector dsDevices; - bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, - unsigned int firstChannel, unsigned int sampleRate, - RtAudioFormat format, unsigned int *bufferSize, - RtAudio::StreamOptions *options ); -}; - -#endif - -#if defined(__WINDOWS_WASAPI__) - -struct IMMDeviceEnumerator; - -class RtApiWasapi : public RtApi -{ -public: - RtApiWasapi(); - ~RtApiWasapi(); - - RtAudio::Api getCurrentApi( void ) { return RtAudio::WINDOWS_WASAPI; } - unsigned int getDeviceCount( void ); - RtAudio::DeviceInfo getDeviceInfo( unsigned int device ); - unsigned int getDefaultOutputDevice( void ); - unsigned int getDefaultInputDevice( void ); - void closeStream( void ); - void startStream( void ); - void stopStream( void ); - void abortStream( void ); - -private: - bool coInitialized_; - IMMDeviceEnumerator* deviceEnumerator_; - - bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, - unsigned int firstChannel, unsigned int sampleRate, - RtAudioFormat format, unsigned int* bufferSize, - RtAudio::StreamOptions* options ); - - static DWORD WINAPI runWasapiThread( void* wasapiPtr ); - static DWORD WINAPI stopWasapiThread( void* wasapiPtr ); - static DWORD WINAPI abortWasapiThread( void* wasapiPtr ); - void wasapiThread(); -}; - -#endif - -#if defined(__LINUX_ALSA__) - -class RtApiAlsa: public RtApi -{ -public: - - RtApiAlsa(); - ~RtApiAlsa(); - RtAudio::Api getCurrentApi() { return RtAudio::LINUX_ALSA; } - unsigned int getDeviceCount( void ); - RtAudio::DeviceInfo getDeviceInfo( unsigned int device ); - void closeStream( void ); - void startStream( void ); - void stopStream( void ); - void abortStream( void ); - - // This function is intended for internal use only. It must be - // public because it is called by the internal callback handler, - // which is not a member of RtAudio. External use of this function - // will most likely produce highly undesireable results! - void callbackEvent( void ); - - private: - - std::vector devices_; - void saveDeviceInfo( void ); - bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, - unsigned int firstChannel, unsigned int sampleRate, - RtAudioFormat format, unsigned int *bufferSize, - RtAudio::StreamOptions *options ); -}; - -#endif - -#if defined(__LINUX_PULSE__) - -class RtApiPulse: public RtApi -{ -public: - ~RtApiPulse(); - RtAudio::Api getCurrentApi() { return RtAudio::LINUX_PULSE; } - unsigned int getDeviceCount( void ); - RtAudio::DeviceInfo getDeviceInfo( unsigned int device ); - void closeStream( void ); - void startStream( void ); - void stopStream( void ); - void abortStream( void ); - - // This function is intended for internal use only. It must be - // public because it is called by the internal callback handler, - // which is not a member of RtAudio. External use of this function - // will most likely produce highly undesireable results! - void callbackEvent( void ); - - private: - - std::vector devices_; - void saveDeviceInfo( void ); - bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, - unsigned int firstChannel, unsigned int sampleRate, - RtAudioFormat format, unsigned int *bufferSize, - RtAudio::StreamOptions *options ); -}; - -#endif - -#if defined(__LINUX_OSS__) - -class RtApiOss: public RtApi -{ -public: - - RtApiOss(); - ~RtApiOss(); - RtAudio::Api getCurrentApi() { return RtAudio::LINUX_OSS; } - unsigned int getDeviceCount( void ); - RtAudio::DeviceInfo getDeviceInfo( unsigned int device ); - void closeStream( void ); - void startStream( void ); - void stopStream( void ); - void abortStream( void ); - - // This function is intended for internal use only. It must be - // public because it is called by the internal callback handler, - // which is not a member of RtAudio. External use of this function - // will most likely produce highly undesireable results! - void callbackEvent( void ); - - private: - - bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, - unsigned int firstChannel, unsigned int sampleRate, - RtAudioFormat format, unsigned int *bufferSize, - RtAudio::StreamOptions *options ); -}; - -#endif - -#if defined(__RTAUDIO_DUMMY__) - -class RtApiDummy: public RtApi -{ -public: - - RtApiDummy() { errorText_ = "RtApiDummy: This class provides no functionality."; error( RtAudioError::WARNING ); } - RtAudio::Api getCurrentApi( void ) { return RtAudio::RTAUDIO_DUMMY; } - unsigned int getDeviceCount( void ) { return 0; } - RtAudio::DeviceInfo getDeviceInfo( unsigned int /*device*/ ) { RtAudio::DeviceInfo info; return info; } - void closeStream( void ) {} - void startStream( void ) {} - void stopStream( void ) {} - void abortStream( void ) {} - - private: - - bool probeDeviceOpen( unsigned int /*device*/, StreamMode /*mode*/, unsigned int /*channels*/, - unsigned int /*firstChannel*/, unsigned int /*sampleRate*/, - RtAudioFormat /*format*/, unsigned int * /*bufferSize*/, - RtAudio::StreamOptions * /*options*/ ) { return false; } -}; - -#endif - -#endif - -// Indentation settings for Vim and Emacs -// -// Local Variables: -// c-basic-offset: 2 -// indent-tabs-mode: nil -// End: -// -// vim: et sts=2 sw=2 diff --git a/vendor/rtaudio/autogen.sh b/vendor/rtaudio/autogen.sh deleted file mode 100644 index 8bd52e88d..000000000 --- a/vendor/rtaudio/autogen.sh +++ /dev/null @@ -1,107 +0,0 @@ -#!/bin/sh -# Run this to generate all the initial makefiles, etc. - -srcdir=`dirname $0` -test -z "$srcdir" && srcdir=. - -DIE=0 - -if test -z "$*"; then - echo "**Warning**: I am going to run \`configure' with arguments for" - echo "developer/maintainer mode. If you wish to pass extra arguments," - echo "(such as --prefix), please specify them on the \`$0'" - echo "command line." - echo "If you wish to run configure yourself, please specify --no-configure." - echo -fi - -(test -f $srcdir/configure.ac) || { - echo -n "**Error**: Directory "\`$srcdir\'" does not look like the" - echo " top-level package directory" - exit 1 -} - -# Make some directories required by automake, if they don't exist -if ! [ -d config ]; then mkdir -v config; fi -if ! [ -d m4 ]; then mkdir -v m4; fi - -if ! autoreconf --version /dev/null 2>&1 -then - -(autoconf --version) < /dev/null > /dev/null 2>&1 || { - echo - echo "**Error**: You must have \`autoconf' installed." - echo "Download the appropriate package for your distribution," - echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/" - DIE=1 -} - -(grep "^LT_INIT" $srcdir/configure.ac >/dev/null) && { - (libtoolize --version) < /dev/null > /dev/null 2>&1 \ - && LIBTOOLIZE=libtoolize || { - (glibtoolize --version) < /dev/null > /dev/null 2>&1 \ - && LIBTOOLIZE=glibtoolize || { - echo - echo "**Error**: You must have \`libtool' installed." - echo "You can get it from: ftp://ftp.gnu.org/pub/gnu/" - DIE=1 - } - } -} - -(automake --version) < /dev/null > /dev/null 2>&1 || { - echo - echo "**Error**: You must have \`automake' installed." - echo "You can get it from: ftp://ftp.gnu.org/pub/gnu/" - DIE=1 - NO_AUTOMAKE=yes -} - - -# if no automake, don't bother testing for aclocal -test -n "$NO_AUTOMAKE" || (aclocal --version) < /dev/null > /dev/null 2>&1 || { - echo - echo "**Error**: Missing \`aclocal'. The version of \`automake'" - echo "installed doesn't appear recent enough." - echo "You can get automake from ftp://ftp.gnu.org/pub/gnu/" - DIE=1 -} - -if test "$DIE" -eq 1; then - exit 1 -fi - -case $CC in -xlc ) - am_opt=--include-deps;; -esac - -echo "Running aclocal $aclocalinclude ..." -aclocal $ACLOCAL_FLAGS || exit 1 -echo "Running $LIBTOOLIZE ..." -$LIBTOOLIZE || exit 1 -echo "Running automake --gnu $am_opt ..." -automake --add-missing --gnu $am_opt || exit 1 -echo "Running autoconf ..." -autoconf || exit 1 - -else # autoreconf instead - - echo "Running autoreconf --verbose --install ..." - autoreconf --verbose --install || exit 1 - -fi - -if ( echo "$@" | grep -q -e "--no-configure" ); then - NOCONFIGURE=1 -fi - -conf_flags="--enable-maintainer-mode --enable-debug --disable-silent-rules" - -if test x$NOCONFIGURE = x; then - echo Running $srcdir/configure $conf_flags "$@" ... - $srcdir/configure $conf_flags "$@" \ - && echo Now type \`make\' to compile. || exit 1 -else - echo Skipping configure process. -fi diff --git a/vendor/rtaudio/configure.ac b/vendor/rtaudio/configure.ac deleted file mode 100644 index e1a5ec398..000000000 --- a/vendor/rtaudio/configure.ac +++ /dev/null @@ -1,249 +0,0 @@ -# Process this file with autoconf to produce a configure script. -AC_INIT(RtAudio, 4.1.2, gary@music.mcgill.ca, rtaudio) -AC_CONFIG_AUX_DIR(config) -AC_CONFIG_SRCDIR(RtAudio.cpp) -AC_CONFIG_FILES([rtaudio-config rtaudio.pc Makefile tests/Makefile doc/Makefile doc/doxygen/Doxyfile]) -AM_INIT_AUTOMAKE([1.14 -Wall -Werror foreign subdir-objects]) - -# libtool version: current:revision:age -# -# If the library source code has changed at all since the last update, then -# increment revision (`c:r:a' becomes `c:r+1:a'). -# -# If any interfaces have been added, removed, or changed since the last update, -# increment current, and set revision to 0. -# -# If any interfaces have been added since the last public release, then -# increment age. -# -# If any interfaces have been removed since the last public release, then set -# age to 0. -m4_define([lt_current], 5) -m4_define([lt_revision], 0) -m4_define([lt_age], 0) - -m4_define([lt_version_info], [lt_current:lt_revision:lt_age]) -m4_define([lt_current_minus_age], [m4_eval(lt_current - lt_age)]) - -SO_VERSION=lt_version_info -AC_SUBST(SO_VERSION) - -# Enable some nice automake features if they are available -m4_ifdef([AM_MAINTAINER_MODE], [AM_MAINTAINER_MODE]) -m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) - -# Fill GXX with something before test. -AC_SUBST( GXX, ["no"] ) - -dnl Check for pkg-config program, used for configuring some libraries. -m4_define_default([PKG_PROG_PKG_CONFIG], -[AC_MSG_CHECKING([pkg-config]) -AC_MSG_RESULT([no])]) - -PKG_PROG_PKG_CONFIG - -dnl If the pkg-config autoconf support isn't installed, define its -dnl autoconf macro to disable any packages depending on it. -m4_define_default([PKG_CHECK_MODULES], -[AC_MSG_CHECKING([$1]) -AC_MSG_RESULT([no]) -$4]) - -# Checks for programs. -AC_PROG_CXX(g++ CC c++ cxx) -AM_PROG_AR -AC_PATH_PROG(AR, ar, no) -if [[ $AR = "no" ]] ; then - AC_MSG_ERROR("Could not find ar - needed to create a library"); -fi - -# Initialize libtool -LT_INIT([win32-dll]) -AC_CONFIG_MACRO_DIR([m4]) - -# Checks for header files. -AC_HEADER_STDC -AC_CHECK_HEADERS(sys/ioctl.h unistd.h) - -# Check version number coherency between RtAudio.h and configure.ac -AC_MSG_CHECKING([that version numbers are coherent]) -AC_RUN_IFELSE( - [AC_LANG_PROGRAM([#include - `grep "define RTAUDIO_VERSION" $srcdir/RtAudio.h`], - [return strcmp(RTAUDIO_VERSION, PACKAGE_VERSION);])], - [AC_MSG_RESULT([yes])], - [AC_MSG_FAILURE([testing RTAUDIO_VERSION==PACKAGE_VERSION failed, check that RtAudio.h defines RTAUDIO_VERSION as "$PACKAGE_VERSION" or that the first line of configure.ac has been updated.])]) - -# Check for debug -AC_MSG_CHECKING(whether to compile debug version) -AC_ARG_ENABLE(debug, - [ --enable-debug = enable various debug output], - [AC_SUBST( cppflag, [-D__RTAUDIO_DEBUG__] ) AC_SUBST( cxxflag, [-g] ) AC_SUBST( object_path, [Debug] ) AC_MSG_RESULT(yes)], - [AC_SUBST( cppflag, [] ) AC_SUBST( cxxflag, [-O2] ) AC_SUBST( object_path, [Release] ) AC_MSG_RESULT(no)]) - -# Checks for functions -AC_CHECK_FUNC(gettimeofday, [cppflag="$cppflag -DHAVE_GETTIMEOFDAY"], ) - -# Set paths if prefix is defined -if test "x$prefix" != "x" && test "x$prefix" != "xNONE"; then - LIBS="$LIBS -L$prefix/lib" - CPPFLAGS="$CPPFLAGS -I$prefix/include" -fi - -# For -I and -D flags -CPPFLAGS="$CPPFLAGS $cppflag" - -# For debugging and optimization ... overwrite default because it has both -g and -O2 -#CXXFLAGS="$CXXFLAGS $cxxflag" -CXXFLAGS="$cxxflag" - -# Check compiler and use -Wall if gnu. -if [test $GXX = "yes" ;] then - AC_SUBST( cxxflag, ["-Wall -Wextra"] ) -fi - -CXXFLAGS="$CXXFLAGS $cxxflag" - -# Checks for doxygen -AC_CHECK_PROG( DOXYGEN, [doxygen], [doxygen] ) -AM_CONDITIONAL( MAKE_DOC, [test "x${DOXYGEN}" != x] ) - -# Copy doc files to build dir if necessary -AC_CONFIG_LINKS( [doc/release.txt:doc/release.txt] ) -AC_CONFIG_LINKS( [doc/doxygen/footer.html:doc/doxygen/footer.html] ) -AC_CONFIG_LINKS( [doc/doxygen/error.txt:doc/doxygen/error.txt] ) -AC_CONFIG_LINKS( [doc/doxygen/tutorial.txt:doc/doxygen/tutorial.txt] ) -AC_CONFIG_LINKS( [doc/doxygen/compiling.txt:doc/doxygen/compiling.txt] ) -AC_CONFIG_LINKS( [doc/doxygen/acknowledge.txt:doc/doxygen/acknowledge.txt] ) -AC_CONFIG_LINKS( [doc/doxygen/license.txt:doc/doxygen/license.txt] ) -AC_CONFIG_LINKS( [doc/doxygen/header.html:doc/doxygen/header.html] ) -AC_CONFIG_LINKS( [doc/doxygen/duplex.txt:doc/doxygen/duplex.txt] ) -AC_CONFIG_LINKS( [doc/doxygen/settings.txt:doc/doxygen/settings.txt] ) -AC_CONFIG_LINKS( [doc/doxygen/probe.txt:doc/doxygen/probe.txt] ) -AC_CONFIG_LINKS( [doc/doxygen/playback.txt:doc/doxygen/playback.txt] ) -AC_CONFIG_LINKS( [doc/doxygen/multi.txt:doc/doxygen/multi.txt] ) -AC_CONFIG_LINKS( [doc/doxygen/recording.txt:doc/doxygen/recording.txt] ) -AC_CONFIG_LINKS( [doc/doxygen/apinotes.txt:doc/doxygen/apinotes.txt] ) -AC_CONFIG_LINKS( [doc/images/mcgill.gif:doc/images/mcgill.gif] ) -AC_CONFIG_LINKS( [doc/images/ccrma.gif:doc/images/ccrma.gif] ) - -# Checks for package options and external software -AC_CANONICAL_HOST - -AC_SUBST( api, [""] ) -AC_SUBST( req, [""] ) -AC_MSG_CHECKING(for audio API) -case $host in - *-*-netbsd*) - AC_MSG_RESULT(using OSS) - api="$api -D__LINUX_OSS__" - LIBS="$LIBS -lossaudio" - AC_CHECK_LIB(pthread, pthread_create, , AC_MSG_ERROR(RtAudio requires the pthread library!)) - ;; - - *-*-linux*) - AC_ARG_WITH(jack, [ --with-jack = choose JACK server support (mac and linux only)], [ - api="$api -D__UNIX_JACK__" - AC_MSG_RESULT(using JACK) - AC_CHECK_LIB(jack, jack_client_open, , AC_MSG_ERROR(JACK support requires the jack library!)) - AC_CHECK_LIB(asound, snd_pcm_open, , AC_MSG_ERROR(Jack support also requires the asound library!))], ) - - # Look for ALSA flag - AC_ARG_WITH(alsa, [ --with-alsa = choose native ALSA API support (linux only)], [ - api="$api -D__LINUX_ALSA__" - req="$req alsa" - AC_MSG_RESULT(using ALSA) - AC_CHECK_LIB(asound, snd_pcm_open, , AC_MSG_ERROR(ALSA support requires the asound library!))], ) - - # Look for PULSE flag - AC_ARG_WITH(pulse, [ --with-pulse = choose PulseAudio API support (linux only)], [ - api="$api -D__LINUX_PULSE__" - req="$req libpulse-simple" - AC_MSG_RESULT(using PulseAudio) - AC_CHECK_LIB(pulse-simple, pa_simple_flush, , AC_MSG_ERROR(PulseAudio support requires the pulse-simple library!))], ) - - # Look for OSS flag - AC_ARG_WITH(oss, [ --with-oss = choose OSS API support (linux only)], [ - api="$api -D__LINUX_OSS__" - AC_MSG_RESULT(using OSS)], ) - - # If no audio api flags specified, use ALSA - if [test "$api" == "";] then - AC_MSG_RESULT(using ALSA) - AC_SUBST( api, [-D__LINUX_ALSA__] ) - req="$req alsa" - AC_CHECK_LIB(asound, snd_pcm_open, , AC_MSG_ERROR(ALSA support requires the asound library!)) - fi - - AC_CHECK_LIB(pthread, pthread_create, , AC_MSG_ERROR(RtAudio requires the pthread library!)) - ;; - - *-apple*) - AC_ARG_WITH(jack, [ --with-jack = choose JACK server support (unix only)], [ - api="$api -D__UNIX_JACK__" - AC_MSG_RESULT(using JACK) - AC_CHECK_LIB(jack, jack_client_open, , AC_MSG_ERROR(JACK support requires the jack library!))], ) - -# AC_CHECK_HEADER(jack/jack.h, [], [AC_MSG_ERROR(Jack header file not found!)] ) -# LIBS="$LIBS -framework jackmp" ], ) - - - # Look for Core flag - AC_ARG_WITH(core, [ --with-core = choose CoreAudio API support (mac only)], [ - api="$api -D__MACOSX_CORE__" - AC_MSG_RESULT(using CoreAudio) - AC_CHECK_HEADER(CoreAudio/CoreAudio.h, [], [AC_MSG_ERROR(CoreAudio header files not found!)] ) - LIBS="$LIBS -framework CoreAudio -framework CoreFoundation" ], ) - - # If no audio api flags specified, use CoreAudio - if [test "$api" == ""; ] then - AC_SUBST( api, [-D__MACOSX_CORE__] ) - AC_MSG_RESULT(using CoreAudio) - AC_CHECK_HEADER(CoreAudio/CoreAudio.h, - [], - [AC_MSG_ERROR(CoreAudio header files not found!)] ) - AC_SUBST( LIBS, ["-framework CoreAudio -framework CoreFoundation"] ) - fi - - AC_CHECK_LIB(pthread, pthread_create, , AC_MSG_ERROR(RtAudio requires the pthread library!)) - ;; - - *-mingw32*) - AC_ARG_WITH(asio, [ --with-asio = choose ASIO API support (windoze only)], [ - api="$api -D__WINDOWS_ASIO__" - AC_MSG_RESULT(using ASIO) - AC_SUBST( objects, ["asio.o asiodrivers.o asiolist.o iasiothiscallresolver.o"] ) ], ) - - # Look for DirectSound flag - AC_ARG_WITH(ds, [ --with-ds = choose DirectSound API support (windoze only)], [ - api="$api -D__WINDOWS_DS__" - AC_MSG_RESULT(using DirectSound) - LIBS="-ldsound -lwinmm $LIBS" ], ) - - # Look for WASAPI flag - AC_ARG_WITH(wasapi, [ --with-wasapi = choose Windows Audio Session API support (windoze only)], [ - api="$api -D__WINDOWS_WASAPI__" - AC_MSG_RESULT(using WASAPI) - LIBS="-lwinmm -luuid -lksuser $LIBS" ], ) - - # If no audio api flags specified, use DS - if [test "$api" == "";] then - AC_SUBST( api, [-D__WINDOWS_DS__] ) - AC_MSG_RESULT(using DirectSound) - LIBS="-ldsound -lwinmm $LIBS" - fi - - LIBS="-lole32 $LIBS" - ;; - - *) - # Default case for unknown realtime systems. - AC_MSG_ERROR(Unknown system type for realtime support!) - ;; -esac - -CPPFLAGS="$CPPFLAGS $api" - -AC_OUTPUT - -chmod oug+x rtaudio-config diff --git a/vendor/rtaudio/include/FunctionDiscoveryKeys_devpkey.h b/vendor/rtaudio/include/FunctionDiscoveryKeys_devpkey.h deleted file mode 100644 index 854244d67..000000000 --- a/vendor/rtaudio/include/FunctionDiscoveryKeys_devpkey.h +++ /dev/null @@ -1,212 +0,0 @@ -#pragma once - -/*++ - -Copyright (c) Microsoft Corporation. All rights reserved. - -Module Name: - - devpkey.h - -Abstract: - - Defines property keys for the Plug and Play Device Property API. - -Author: - - Jim Cavalaris (jamesca) 10-14-2003 - -Environment: - - User-mode only. - -Revision History: - - 14-October-2003 jamesca - - Creation and initial implementation. - - 20-June-2006 dougb - - Copied Jim's version replaced "DEFINE_DEVPROPKEY(DEVPKEY_" with "DEFINE_PROPERTYKEY(PKEY_" - ---*/ - -//#include - -// -// _NAME -// - -DEFINE_PROPERTYKEY(PKEY_NAME, 0xb725f130, 0x47ef, 0x101a, 0xa5, 0xf1, 0x02, 0x60, 0x8c, 0x9e, 0xeb, 0xac, 10); // DEVPROP_TYPE_STRING - -// -// Device properties -// These PKEYs correspond to the old setupapi SPDRP_XXX properties -// -DEFINE_PROPERTYKEY(PKEY_Device_DeviceDesc, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 2); // DEVPROP_TYPE_STRING -DEFINE_PROPERTYKEY(PKEY_Device_HardwareIds, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 3); // DEVPROP_TYPE_STRING_LIST -DEFINE_PROPERTYKEY(PKEY_Device_CompatibleIds, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 4); // DEVPROP_TYPE_STRING_LIST -DEFINE_PROPERTYKEY(PKEY_Device_Service, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 6); // DEVPROP_TYPE_STRING -DEFINE_PROPERTYKEY(PKEY_Device_Class, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 9); // DEVPROP_TYPE_STRING -DEFINE_PROPERTYKEY(PKEY_Device_ClassGuid, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 10); // DEVPROP_TYPE_GUID -DEFINE_PROPERTYKEY(PKEY_Device_Driver, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 11); // DEVPROP_TYPE_STRING -DEFINE_PROPERTYKEY(PKEY_Device_ConfigFlags, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 12); // DEVPROP_TYPE_UINT32 -DEFINE_PROPERTYKEY(PKEY_Device_Manufacturer, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 13); // DEVPROP_TYPE_STRING -DEFINE_PROPERTYKEY(PKEY_Device_FriendlyName, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 14); // DEVPROP_TYPE_STRING -DEFINE_PROPERTYKEY(PKEY_Device_LocationInfo, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 15); // DEVPROP_TYPE_STRING -DEFINE_PROPERTYKEY(PKEY_Device_PDOName, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 16); // DEVPROP_TYPE_STRING -DEFINE_PROPERTYKEY(PKEY_Device_Capabilities, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 17); // DEVPROP_TYPE_UNINT32 -DEFINE_PROPERTYKEY(PKEY_Device_UINumber, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 18); // DEVPROP_TYPE_STRING -DEFINE_PROPERTYKEY(PKEY_Device_UpperFilters, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 19); // DEVPROP_TYPE_STRING_LIST -DEFINE_PROPERTYKEY(PKEY_Device_LowerFilters, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 20); // DEVPROP_TYPE_STRING_LIST -DEFINE_PROPERTYKEY(PKEY_Device_BusTypeGuid, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 21); // DEVPROP_TYPE_GUID -DEFINE_PROPERTYKEY(PKEY_Device_LegacyBusType, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 22); // DEVPROP_TYPE_UINT32 -DEFINE_PROPERTYKEY(PKEY_Device_BusNumber, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 23); // DEVPROP_TYPE_UINT32 -DEFINE_PROPERTYKEY(PKEY_Device_EnumeratorName, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 24); // DEVPROP_TYPE_STRING -DEFINE_PROPERTYKEY(PKEY_Device_Security, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 25); // DEVPROP_TYPE_SECURITY_DESCRIPTOR -DEFINE_PROPERTYKEY(PKEY_Device_SecuritySDS, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 26); // DEVPROP_TYPE_SECURITY_DESCRIPTOR_STRING -DEFINE_PROPERTYKEY(PKEY_Device_DevType, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 27); // DEVPROP_TYPE_UINT32 -DEFINE_PROPERTYKEY(PKEY_Device_Exclusive, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 28); // DEVPROP_TYPE_UINT32 -DEFINE_PROPERTYKEY(PKEY_Device_Characteristics, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 29); // DEVPROP_TYPE_UINT32 -DEFINE_PROPERTYKEY(PKEY_Device_Address, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 30); // DEVPROP_TYPE_UINT32 -DEFINE_PROPERTYKEY(PKEY_Device_UINumberDescFormat, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 31); // DEVPROP_TYPE_STRING -DEFINE_PROPERTYKEY(PKEY_Device_PowerData, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 32); // DEVPROP_TYPE_BINARY -DEFINE_PROPERTYKEY(PKEY_Device_RemovalPolicy, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 33); // DEVPROP_TYPE_UINT32 -DEFINE_PROPERTYKEY(PKEY_Device_RemovalPolicyDefault, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 34); // DEVPROP_TYPE_UINT32 -DEFINE_PROPERTYKEY(PKEY_Device_RemovalPolicyOverride, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 35); // DEVPROP_TYPE_UINT32 -DEFINE_PROPERTYKEY(PKEY_Device_InstallState, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 36); // DEVPROP_TYPE_UINT32 -DEFINE_PROPERTYKEY(PKEY_Device_LocationPaths, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 37); // DEVPROP_TYPE_STRING_LIST -DEFINE_PROPERTYKEY(PKEY_Device_BaseContainerId, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 38); // DEVPROP_TYPE_GUID - -// -// Device properties -// These PKEYs correspond to a device's status and problem code -// -DEFINE_PROPERTYKEY(PKEY_Device_DevNodeStatus, 0x4340a6c5, 0x93fa, 0x4706, 0x97, 0x2c, 0x7b, 0x64, 0x80, 0x08, 0xa5, 0xa7, 2); // DEVPROP_TYPE_UINT32 -DEFINE_PROPERTYKEY(PKEY_Device_ProblemCode, 0x4340a6c5, 0x93fa, 0x4706, 0x97, 0x2c, 0x7b, 0x64, 0x80, 0x08, 0xa5, 0xa7, 3); // DEVPROP_TYPE_UINT32 - -// -// Device properties -// These PKEYs correspond to device relations -// -DEFINE_PROPERTYKEY(PKEY_Device_EjectionRelations, 0x4340a6c5, 0x93fa, 0x4706, 0x97, 0x2c, 0x7b, 0x64, 0x80, 0x08, 0xa5, 0xa7, 4); // DEVPROP_TYPE_STRING_LIST -DEFINE_PROPERTYKEY(PKEY_Device_RemovalRelations, 0x4340a6c5, 0x93fa, 0x4706, 0x97, 0x2c, 0x7b, 0x64, 0x80, 0x08, 0xa5, 0xa7, 5); // DEVPROP_TYPE_STRING_LIST -DEFINE_PROPERTYKEY(PKEY_Device_PowerRelations, 0x4340a6c5, 0x93fa, 0x4706, 0x97, 0x2c, 0x7b, 0x64, 0x80, 0x08, 0xa5, 0xa7, 6); // DEVPROP_TYPE_STRING_LIST -DEFINE_PROPERTYKEY(PKEY_Device_BusRelations, 0x4340a6c5, 0x93fa, 0x4706, 0x97, 0x2c, 0x7b, 0x64, 0x80, 0x08, 0xa5, 0xa7, 7); // DEVPROP_TYPE_STRING_LIST -DEFINE_PROPERTYKEY(PKEY_Device_Parent, 0x4340a6c5, 0x93fa, 0x4706, 0x97, 0x2c, 0x7b, 0x64, 0x80, 0x08, 0xa5, 0xa7, 8); // DEVPROP_TYPE_STRING -DEFINE_PROPERTYKEY(PKEY_Device_Children, 0x4340a6c5, 0x93fa, 0x4706, 0x97, 0x2c, 0x7b, 0x64, 0x80, 0x08, 0xa5, 0xa7, 9); // DEVPROP_TYPE_STRING_LIST -DEFINE_PROPERTYKEY(PKEY_Device_Siblings, 0x4340a6c5, 0x93fa, 0x4706, 0x97, 0x2c, 0x7b, 0x64, 0x80, 0x08, 0xa5, 0xa7, 10); // DEVPROP_TYPE_STRING_LIST -DEFINE_PROPERTYKEY(PKEY_Device_TransportRelations, 0x4340a6c5, 0x93fa, 0x4706, 0x97, 0x2c, 0x7b, 0x64, 0x80, 0x08, 0xa5, 0xa7, 11); // DEVPROP_TYPE_STRING_LIST - -// -// Other Device properties -// -DEFINE_PROPERTYKEY(PKEY_Device_Reported, 0x80497100, 0x8c73, 0x48b9, 0xaa, 0xd9, 0xce, 0x38, 0x7e, 0x19, 0xc5, 0x6e, 2); // DEVPROP_TYPE_BOOLEAN -DEFINE_PROPERTYKEY(PKEY_Device_Legacy, 0x80497100, 0x8c73, 0x48b9, 0xaa, 0xd9, 0xce, 0x38, 0x7e, 0x19, 0xc5, 0x6e, 3); // DEVPROP_TYPE_BOOLEAN -DEFINE_PROPERTYKEY(PKEY_Device_InstanceId, 0x78c34fc8, 0x104a, 0x4aca, 0x9e, 0xa4, 0x52, 0x4d, 0x52, 0x99, 0x6e, 0x57, 256); // DEVPROP_TYPE_STRING - -DEFINE_PROPERTYKEY(PKEY_Device_ContainerId, 0x8c7ed206, 0x3f8a, 0x4827, 0xb3, 0xab, 0xae, 0x9e, 0x1f, 0xae, 0xfc, 0x6c, 2); // DEVPROP_TYPE_GUID - -DEFINE_PROPERTYKEY(PKEY_Device_ModelId, 0x80d81ea6, 0x7473, 0x4b0c, 0x82, 0x16, 0xef, 0xc1, 0x1a, 0x2c, 0x4c, 0x8b, 2); // DEVPROP_TYPE_GUID - -DEFINE_PROPERTYKEY(PKEY_Device_FriendlyNameAttributes, 0x80d81ea6, 0x7473, 0x4b0c, 0x82, 0x16, 0xef, 0xc1, 0x1a, 0x2c, 0x4c, 0x8b, 3); // DEVPROP_TYPE_UINT32 -DEFINE_PROPERTYKEY(PKEY_Device_ManufacturerAttributes, 0x80d81ea6, 0x7473, 0x4b0c, 0x82, 0x16, 0xef, 0xc1, 0x1a, 0x2c, 0x4c, 0x8b, 4); // DEVPROP_TYPE_UINT32 - -DEFINE_PROPERTYKEY(PKEY_Device_PresenceNotForDevice, 0x80d81ea6, 0x7473, 0x4b0c, 0x82, 0x16, 0xef, 0xc1, 0x1a, 0x2c, 0x4c, 0x8b, 5); // DEVPROP_TYPE_BOOLEAN - - -DEFINE_PROPERTYKEY(PKEY_Numa_Proximity_Domain, 0x540b947e, 0x8b40, 0x45bc, 0xa8, 0xa2, 0x6a, 0x0b, 0x89, 0x4c, 0xbd, 0xa2, 1); // DEVPROP_TYPE_UINT32 -DEFINE_PROPERTYKEY(PKEY_Device_DHP_Rebalance_Policy, 0x540b947e, 0x8b40, 0x45bc, 0xa8, 0xa2, 0x6a, 0x0b, 0x89, 0x4c, 0xbd, 0xa2, 2); // DEVPROP_TYPE_UINT32 -DEFINE_PROPERTYKEY(PKEY_Device_Numa_Node, 0x540b947e, 0x8b40, 0x45bc, 0xa8, 0xa2, 0x6a, 0x0b, 0x89, 0x4c, 0xbd, 0xa2, 3); // DEVPROP_TYPE_UINT32 -DEFINE_PROPERTYKEY(PKEY_Device_BusReportedDeviceDesc, 0x540b947e, 0x8b40, 0x45bc, 0xa8, 0xa2, 0x6a, 0x0b, 0x89, 0x4c, 0xbd, 0xa2, 4); // DEVPROP_TYPE_STRING - -DEFINE_PROPERTYKEY(PKEY_Device_InstallInProgress, 0x83da6326, 0x97a6, 0x4088, 0x94, 0x53, 0xa1, 0x92, 0x3f, 0x57, 0x3b, 0x29, 9); // DEVPROP_TYPE_BOOLEAN - -// -// Device driver properties -// -DEFINE_PROPERTYKEY(PKEY_Device_DriverDate, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 2); // DEVPROP_TYPE_FILETIME -DEFINE_PROPERTYKEY(PKEY_Device_DriverVersion, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 3); // DEVPROP_TYPE_STRING -DEFINE_PROPERTYKEY(PKEY_Device_DriverDesc, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 4); // DEVPROP_TYPE_STRING -DEFINE_PROPERTYKEY(PKEY_Device_DriverInfPath, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 5); // DEVPROP_TYPE_STRING -DEFINE_PROPERTYKEY(PKEY_Device_DriverInfSection, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 6); // DEVPROP_TYPE_STRING -DEFINE_PROPERTYKEY(PKEY_Device_DriverInfSectionExt, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 7); // DEVPROP_TYPE_STRING -DEFINE_PROPERTYKEY(PKEY_Device_MatchingDeviceId, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 8); // DEVPROP_TYPE_STRING -DEFINE_PROPERTYKEY(PKEY_Device_DriverProvider, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 9); // DEVPROP_TYPE_STRING -DEFINE_PROPERTYKEY(PKEY_Device_DriverPropPageProvider, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 10); // DEVPROP_TYPE_STRING -DEFINE_PROPERTYKEY(PKEY_Device_DriverCoInstallers, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 11); // DEVPROP_TYPE_STRING_LIST -DEFINE_PROPERTYKEY(PKEY_Device_ResourcePickerTags, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 12); // DEVPROP_TYPE_STRING -DEFINE_PROPERTYKEY(PKEY_Device_ResourcePickerExceptions, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 13); // DEVPROP_TYPE_STRING -DEFINE_PROPERTYKEY(PKEY_Device_DriverRank, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 14); // DEVPROP_TYPE_UINT32 -DEFINE_PROPERTYKEY(PKEY_Device_DriverLogoLevel, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 15); // DEVPROP_TYPE_UINT32 -DEFINE_PROPERTYKEY(PKEY_Device_NoConnectSound, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 17); // DEVPROP_TYPE_BOOLEAN -DEFINE_PROPERTYKEY(PKEY_Device_GenericDriverInstalled, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 18); // DEVPROP_TYPE_BOOLEAN -DEFINE_PROPERTYKEY(PKEY_Device_AdditionalSoftwareRequested, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 19);// DEVPROP_TYPE_BOOLEAN - -// -// Device safe-removal properties -// -DEFINE_PROPERTYKEY(PKEY_Device_SafeRemovalRequired, 0xafd97640, 0x86a3, 0x4210, 0xb6, 0x7c, 0x28, 0x9c, 0x41, 0xaa, 0xbe, 0x55, 2); // DEVPROP_TYPE_BOOLEAN -DEFINE_PROPERTYKEY(PKEY_Device_SafeRemovalRequiredOverride, 0xafd97640, 0x86a3, 0x4210, 0xb6, 0x7c, 0x28, 0x9c, 0x41, 0xaa, 0xbe, 0x55, 3);// DEVPROP_TYPE_BOOLEAN - - -// -// Device properties that were set by the driver package that was installed -// on the device. -// -DEFINE_PROPERTYKEY(PKEY_DrvPkg_Model, 0xcf73bb51, 0x3abf, 0x44a2, 0x85, 0xe0, 0x9a, 0x3d, 0xc7, 0xa1, 0x21, 0x32, 2); // DEVPROP_TYPE_STRING -DEFINE_PROPERTYKEY(PKEY_DrvPkg_VendorWebSite, 0xcf73bb51, 0x3abf, 0x44a2, 0x85, 0xe0, 0x9a, 0x3d, 0xc7, 0xa1, 0x21, 0x32, 3); // DEVPROP_TYPE_STRING -DEFINE_PROPERTYKEY(PKEY_DrvPkg_DetailedDescription, 0xcf73bb51, 0x3abf, 0x44a2, 0x85, 0xe0, 0x9a, 0x3d, 0xc7, 0xa1, 0x21, 0x32, 4); // DEVPROP_TYPE_STRING -DEFINE_PROPERTYKEY(PKEY_DrvPkg_DocumentationLink, 0xcf73bb51, 0x3abf, 0x44a2, 0x85, 0xe0, 0x9a, 0x3d, 0xc7, 0xa1, 0x21, 0x32, 5); // DEVPROP_TYPE_STRING -DEFINE_PROPERTYKEY(PKEY_DrvPkg_Icon, 0xcf73bb51, 0x3abf, 0x44a2, 0x85, 0xe0, 0x9a, 0x3d, 0xc7, 0xa1, 0x21, 0x32, 6); // DEVPROP_TYPE_STRING_LIST -DEFINE_PROPERTYKEY(PKEY_DrvPkg_BrandingIcon, 0xcf73bb51, 0x3abf, 0x44a2, 0x85, 0xe0, 0x9a, 0x3d, 0xc7, 0xa1, 0x21, 0x32, 7); // DEVPROP_TYPE_STRING_LIST - -// -// Device setup class properties -// These PKEYs correspond to the old setupapi SPCRP_XXX properties -// -DEFINE_PROPERTYKEY(PKEY_DeviceClass_UpperFilters, 0x4321918b, 0xf69e, 0x470d, 0xa5, 0xde, 0x4d, 0x88, 0xc7, 0x5a, 0xd2, 0x4b, 19); // DEVPROP_TYPE_STRING_LIST -DEFINE_PROPERTYKEY(PKEY_DeviceClass_LowerFilters, 0x4321918b, 0xf69e, 0x470d, 0xa5, 0xde, 0x4d, 0x88, 0xc7, 0x5a, 0xd2, 0x4b, 20); // DEVPROP_TYPE_STRING_LIST -DEFINE_PROPERTYKEY(PKEY_DeviceClass_Security, 0x4321918b, 0xf69e, 0x470d, 0xa5, 0xde, 0x4d, 0x88, 0xc7, 0x5a, 0xd2, 0x4b, 25); // DEVPROP_TYPE_SECURITY_DESCRIPTOR -DEFINE_PROPERTYKEY(PKEY_DeviceClass_SecuritySDS, 0x4321918b, 0xf69e, 0x470d, 0xa5, 0xde, 0x4d, 0x88, 0xc7, 0x5a, 0xd2, 0x4b, 26); // DEVPROP_TYPE_SECURITY_DESCRIPTOR_STRING -DEFINE_PROPERTYKEY(PKEY_DeviceClass_DevType, 0x4321918b, 0xf69e, 0x470d, 0xa5, 0xde, 0x4d, 0x88, 0xc7, 0x5a, 0xd2, 0x4b, 27); // DEVPROP_TYPE_UINT32 -DEFINE_PROPERTYKEY(PKEY_DeviceClass_Exclusive, 0x4321918b, 0xf69e, 0x470d, 0xa5, 0xde, 0x4d, 0x88, 0xc7, 0x5a, 0xd2, 0x4b, 28); // DEVPROP_TYPE_UINT32 -DEFINE_PROPERTYKEY(PKEY_DeviceClass_Characteristics, 0x4321918b, 0xf69e, 0x470d, 0xa5, 0xde, 0x4d, 0x88, 0xc7, 0x5a, 0xd2, 0x4b, 29); // DEVPROP_TYPE_UINT32 - -// -// Device setup class properties -// These PKEYs correspond to registry values under the device class GUID key -// -DEFINE_PROPERTYKEY(PKEY_DeviceClass_Name, 0x259abffc, 0x50a7, 0x47ce, 0xaf, 0x8, 0x68, 0xc9, 0xa7, 0xd7, 0x33, 0x66, 2); // DEVPROP_TYPE_STRING -DEFINE_PROPERTYKEY(PKEY_DeviceClass_ClassName, 0x259abffc, 0x50a7, 0x47ce, 0xaf, 0x8, 0x68, 0xc9, 0xa7, 0xd7, 0x33, 0x66, 3); // DEVPROP_TYPE_STRING -DEFINE_PROPERTYKEY(PKEY_DeviceClass_Icon, 0x259abffc, 0x50a7, 0x47ce, 0xaf, 0x8, 0x68, 0xc9, 0xa7, 0xd7, 0x33, 0x66, 4); // DEVPROP_TYPE_STRING -DEFINE_PROPERTYKEY(PKEY_DeviceClass_ClassInstaller, 0x259abffc, 0x50a7, 0x47ce, 0xaf, 0x8, 0x68, 0xc9, 0xa7, 0xd7, 0x33, 0x66, 5); // DEVPROP_TYPE_STRING -DEFINE_PROPERTYKEY(PKEY_DeviceClass_PropPageProvider, 0x259abffc, 0x50a7, 0x47ce, 0xaf, 0x8, 0x68, 0xc9, 0xa7, 0xd7, 0x33, 0x66, 6); // DEVPROP_TYPE_STRING -DEFINE_PROPERTYKEY(PKEY_DeviceClass_NoInstallClass, 0x259abffc, 0x50a7, 0x47ce, 0xaf, 0x8, 0x68, 0xc9, 0xa7, 0xd7, 0x33, 0x66, 7); // DEVPROP_TYPE_BOOLEAN -DEFINE_PROPERTYKEY(PKEY_DeviceClass_NoDisplayClass, 0x259abffc, 0x50a7, 0x47ce, 0xaf, 0x8, 0x68, 0xc9, 0xa7, 0xd7, 0x33, 0x66, 8); // DEVPROP_TYPE_BOOLEAN -DEFINE_PROPERTYKEY(PKEY_DeviceClass_SilentInstall, 0x259abffc, 0x50a7, 0x47ce, 0xaf, 0x8, 0x68, 0xc9, 0xa7, 0xd7, 0x33, 0x66, 9); // DEVPROP_TYPE_BOOLEAN -DEFINE_PROPERTYKEY(PKEY_DeviceClass_NoUseClass, 0x259abffc, 0x50a7, 0x47ce, 0xaf, 0x8, 0x68, 0xc9, 0xa7, 0xd7, 0x33, 0x66, 10); // DEVPROP_TYPE_BOOLEAN -DEFINE_PROPERTYKEY(PKEY_DeviceClass_DefaultService, 0x259abffc, 0x50a7, 0x47ce, 0xaf, 0x8, 0x68, 0xc9, 0xa7, 0xd7, 0x33, 0x66, 11); // DEVPROP_TYPE_STRING -DEFINE_PROPERTYKEY(PKEY_DeviceClass_IconPath, 0x259abffc, 0x50a7, 0x47ce, 0xaf, 0x8, 0x68, 0xc9, 0xa7, 0xd7, 0x33, 0x66, 12); // DEVPROP_TYPE_STRING_LIST - -// -// Other Device setup class properties -// -DEFINE_PROPERTYKEY(PKEY_DeviceClass_ClassCoInstallers, 0x713d1703, 0xa2e2, 0x49f5, 0x92, 0x14, 0x56, 0x47, 0x2e, 0xf3, 0xda, 0x5c, 2); // DEVPROP_TYPE_STRING_LIST - -// -// Device interface properties -// -DEFINE_PROPERTYKEY(PKEY_DeviceInterface_FriendlyName, 0x026e516e, 0xb814, 0x414b, 0x83, 0xcd, 0x85, 0x6d, 0x6f, 0xef, 0x48, 0x22, 2); // DEVPROP_TYPE_STRING -DEFINE_PROPERTYKEY(PKEY_DeviceInterface_Enabled, 0x026e516e, 0xb814, 0x414b, 0x83, 0xcd, 0x85, 0x6d, 0x6f, 0xef, 0x48, 0x22, 3); // DEVPROP_TYPE_BOOLEAN -DEFINE_PROPERTYKEY(PKEY_DeviceInterface_ClassGuid, 0x026e516e, 0xb814, 0x414b, 0x83, 0xcd, 0x85, 0x6d, 0x6f, 0xef, 0x48, 0x22, 4); // DEVPROP_TYPE_GUID - -// -// Device interface class properties -// -DEFINE_PROPERTYKEY(PKEY_DeviceInterfaceClass_DefaultInterface, 0x14c83a99, 0x0b3f, 0x44b7, 0xbe, 0x4c, 0xa1, 0x78, 0xd3, 0x99, 0x05, 0x64, 2); // DEVPROP_TYPE_STRING - - - - diff --git a/vendor/rtaudio/include/asio.cpp b/vendor/rtaudio/include/asio.cpp deleted file mode 100644 index b241663b3..000000000 --- a/vendor/rtaudio/include/asio.cpp +++ /dev/null @@ -1,257 +0,0 @@ -/* - Steinberg Audio Stream I/O API - (c) 1996, Steinberg Soft- und Hardware GmbH - - asio.cpp - - asio functions entries which translate the - asio interface to the asiodrvr class methods -*/ - -#include -#include "asiosys.h" // platform definition -#include "asio.h" - -#if MAC -#include "asiodrvr.h" - -#pragma export on - -AsioDriver *theAsioDriver = 0; - -extern "C" -{ - -long main() -{ - return 'ASIO'; -} - -#elif WINDOWS - -#include "windows.h" -#include "iasiodrv.h" -#include "asiodrivers.h" - -IASIO *theAsioDriver = 0; -extern AsioDrivers *asioDrivers; - -#elif SGI || SUN || BEOS || LINUX -#include "asiodrvr.h" -static AsioDriver *theAsioDriver = 0; -#endif - -//----------------------------------------------------------------------------------------------------- -ASIOError ASIOInit(ASIODriverInfo *info) -{ -#if MAC || SGI || SUN || BEOS || LINUX - if(theAsioDriver) - { - delete theAsioDriver; - theAsioDriver = 0; - } - info->driverVersion = 0; - strcpy(info->name, "No ASIO Driver"); - theAsioDriver = getDriver(); - if(!theAsioDriver) - { - strcpy(info->errorMessage, "Not enough memory for the ASIO driver!"); - return ASE_NotPresent; - } - if(!theAsioDriver->init(info->sysRef)) - { - theAsioDriver->getErrorMessage(info->errorMessage); - delete theAsioDriver; - theAsioDriver = 0; - return ASE_NotPresent; - } - strcpy(info->errorMessage, "No ASIO Driver Error"); - theAsioDriver->getDriverName(info->name); - info->driverVersion = theAsioDriver->getDriverVersion(); - return ASE_OK; - -#else - - info->driverVersion = 0; - strcpy(info->name, "No ASIO Driver"); - if(theAsioDriver) // must be loaded! - { - if(!theAsioDriver->init(info->sysRef)) - { - theAsioDriver->getErrorMessage(info->errorMessage); - theAsioDriver = 0; - return ASE_NotPresent; - } - - strcpy(info->errorMessage, "No ASIO Driver Error"); - theAsioDriver->getDriverName(info->name); - info->driverVersion = theAsioDriver->getDriverVersion(); - return ASE_OK; - } - return ASE_NotPresent; - -#endif // !MAC -} - -ASIOError ASIOExit(void) -{ - if(theAsioDriver) - { -#if WINDOWS - asioDrivers->removeCurrentDriver(); -#else - delete theAsioDriver; -#endif - } - theAsioDriver = 0; - return ASE_OK; -} - -ASIOError ASIOStart(void) -{ - if(!theAsioDriver) - return ASE_NotPresent; - return theAsioDriver->start(); -} - -ASIOError ASIOStop(void) -{ - if(!theAsioDriver) - return ASE_NotPresent; - return theAsioDriver->stop(); -} - -ASIOError ASIOGetChannels(long *numInputChannels, long *numOutputChannels) -{ - if(!theAsioDriver) - { - *numInputChannels = *numOutputChannels = 0; - return ASE_NotPresent; - } - return theAsioDriver->getChannels(numInputChannels, numOutputChannels); -} - -ASIOError ASIOGetLatencies(long *inputLatency, long *outputLatency) -{ - if(!theAsioDriver) - { - *inputLatency = *outputLatency = 0; - return ASE_NotPresent; - } - return theAsioDriver->getLatencies(inputLatency, outputLatency); -} - -ASIOError ASIOGetBufferSize(long *minSize, long *maxSize, long *preferredSize, long *granularity) -{ - if(!theAsioDriver) - { - *minSize = *maxSize = *preferredSize = *granularity = 0; - return ASE_NotPresent; - } - return theAsioDriver->getBufferSize(minSize, maxSize, preferredSize, granularity); -} - -ASIOError ASIOCanSampleRate(ASIOSampleRate sampleRate) -{ - if(!theAsioDriver) - return ASE_NotPresent; - return theAsioDriver->canSampleRate(sampleRate); -} - -ASIOError ASIOGetSampleRate(ASIOSampleRate *currentRate) -{ - if(!theAsioDriver) - return ASE_NotPresent; - return theAsioDriver->getSampleRate(currentRate); -} - -ASIOError ASIOSetSampleRate(ASIOSampleRate sampleRate) -{ - if(!theAsioDriver) - return ASE_NotPresent; - return theAsioDriver->setSampleRate(sampleRate); -} - -ASIOError ASIOGetClockSources(ASIOClockSource *clocks, long *numSources) -{ - if(!theAsioDriver) - { - *numSources = 0; - return ASE_NotPresent; - } - return theAsioDriver->getClockSources(clocks, numSources); -} - -ASIOError ASIOSetClockSource(long reference) -{ - if(!theAsioDriver) - return ASE_NotPresent; - return theAsioDriver->setClockSource(reference); -} - -ASIOError ASIOGetSamplePosition(ASIOSamples *sPos, ASIOTimeStamp *tStamp) -{ - if(!theAsioDriver) - return ASE_NotPresent; - return theAsioDriver->getSamplePosition(sPos, tStamp); -} - -ASIOError ASIOGetChannelInfo(ASIOChannelInfo *info) -{ - if(!theAsioDriver) - { - info->channelGroup = -1; - info->type = ASIOSTInt16MSB; - strcpy(info->name, "None"); - return ASE_NotPresent; - } - return theAsioDriver->getChannelInfo(info); -} - -ASIOError ASIOCreateBuffers(ASIOBufferInfo *bufferInfos, long numChannels, - long bufferSize, ASIOCallbacks *callbacks) -{ - if(!theAsioDriver) - { - ASIOBufferInfo *info = bufferInfos; - for(long i = 0; i < numChannels; i++, info++) - info->buffers[0] = info->buffers[1] = 0; - return ASE_NotPresent; - } - return theAsioDriver->createBuffers(bufferInfos, numChannels, bufferSize, callbacks); -} - -ASIOError ASIODisposeBuffers(void) -{ - if(!theAsioDriver) - return ASE_NotPresent; - return theAsioDriver->disposeBuffers(); -} - -ASIOError ASIOControlPanel(void) -{ - if(!theAsioDriver) - return ASE_NotPresent; - return theAsioDriver->controlPanel(); -} - -ASIOError ASIOFuture(long selector, void *opt) -{ - if(!theAsioDriver) - return ASE_NotPresent; - return theAsioDriver->future(selector, opt); -} - -ASIOError ASIOOutputReady(void) -{ - if(!theAsioDriver) - return ASE_NotPresent; - return theAsioDriver->outputReady(); -} - -#if MAC -} // extern "C" -#pragma export off -#endif - - diff --git a/vendor/rtaudio/include/asio.h b/vendor/rtaudio/include/asio.h deleted file mode 100644 index 8ec811f8f..000000000 --- a/vendor/rtaudio/include/asio.h +++ /dev/null @@ -1,1054 +0,0 @@ -//--------------------------------------------------------------------------------------------------- -//--------------------------------------------------------------------------------------------------- - -/* - Steinberg Audio Stream I/O API - (c) 1997 - 2005, Steinberg Media Technologies GmbH - - ASIO Interface Specification v 2.1 - - 2005 - Added support for DSD sample data (in cooperation with Sony) - - - basic concept is an i/o synchronous double-buffer scheme: - - on bufferSwitch(index == 0), host will read/write: - - after ASIOStart(), the - read first input buffer A (index 0) - | will be invalid (empty) - * ------------------------ - |------------------------|-----------------------| - | | | - | Input Buffer A (0) | Input Buffer B (1) | - | | | - |------------------------|-----------------------| - | | | - | Output Buffer A (0) | Output Buffer B (1) | - | | | - |------------------------|-----------------------| - * ------------------------- - | before calling ASIOStart(), - write host will have filled output - buffer B (index 1) already - - *please* take special care of proper statement of input - and output latencies (see ASIOGetLatencies()), these - control sequencer sync accuracy - -*/ - -//--------------------------------------------------------------------------------------------------- -//--------------------------------------------------------------------------------------------------- - -/* - -prototypes summary: - -ASIOError ASIOInit(ASIODriverInfo *info); -ASIOError ASIOExit(void); -ASIOError ASIOStart(void); -ASIOError ASIOStop(void); -ASIOError ASIOGetChannels(long *numInputChannels, long *numOutputChannels); -ASIOError ASIOGetLatencies(long *inputLatency, long *outputLatency); -ASIOError ASIOGetBufferSize(long *minSize, long *maxSize, long *preferredSize, long *granularity); -ASIOError ASIOCanSampleRate(ASIOSampleRate sampleRate); -ASIOError ASIOGetSampleRate(ASIOSampleRate *currentRate); -ASIOError ASIOSetSampleRate(ASIOSampleRate sampleRate); -ASIOError ASIOGetClockSources(ASIOClockSource *clocks, long *numSources); -ASIOError ASIOSetClockSource(long reference); -ASIOError ASIOGetSamplePosition (ASIOSamples *sPos, ASIOTimeStamp *tStamp); -ASIOError ASIOGetChannelInfo(ASIOChannelInfo *info); -ASIOError ASIOCreateBuffers(ASIOBufferInfo *bufferInfos, long numChannels, - long bufferSize, ASIOCallbacks *callbacks); -ASIOError ASIODisposeBuffers(void); -ASIOError ASIOControlPanel(void); -void *ASIOFuture(long selector, void *params); -ASIOError ASIOOutputReady(void); - -*/ - -//--------------------------------------------------------------------------------------------------- -//--------------------------------------------------------------------------------------------------- - -#ifndef __ASIO_H -#define __ASIO_H - -// force 4 byte alignment -#if defined(_MSC_VER) && !defined(__MWERKS__) -#pragma pack(push,4) -#elif PRAGMA_ALIGN_SUPPORTED -#pragma options align = native -#endif - -//- - - - - - - - - - - - - - - - - - - - - - - - - -// Type definitions -//- - - - - - - - - - - - - - - - - - - - - - - - - - -// number of samples data type is 64 bit integer -#if NATIVE_INT64 - typedef long long int ASIOSamples; -#else - typedef struct ASIOSamples { - unsigned long hi; - unsigned long lo; - } ASIOSamples; -#endif - -// Timestamp data type is 64 bit integer, -// Time format is Nanoseconds. -#if NATIVE_INT64 - typedef long long int ASIOTimeStamp ; -#else - typedef struct ASIOTimeStamp { - unsigned long hi; - unsigned long lo; - } ASIOTimeStamp; -#endif - -// Samplerates are expressed in IEEE 754 64 bit double float, -// native format as host computer -#if IEEE754_64FLOAT - typedef double ASIOSampleRate; -#else - typedef struct ASIOSampleRate { - char ieee[8]; - } ASIOSampleRate; -#endif - -// Boolean values are expressed as long -typedef long ASIOBool; -enum { - ASIOFalse = 0, - ASIOTrue = 1 -}; - -// Sample Types are expressed as long -typedef long ASIOSampleType; -enum { - ASIOSTInt16MSB = 0, - ASIOSTInt24MSB = 1, // used for 20 bits as well - ASIOSTInt32MSB = 2, - ASIOSTFloat32MSB = 3, // IEEE 754 32 bit float - ASIOSTFloat64MSB = 4, // IEEE 754 64 bit double float - - // these are used for 32 bit data buffer, with different alignment of the data inside - // 32 bit PCI bus systems can be more easily used with these - ASIOSTInt32MSB16 = 8, // 32 bit data with 16 bit alignment - ASIOSTInt32MSB18 = 9, // 32 bit data with 18 bit alignment - ASIOSTInt32MSB20 = 10, // 32 bit data with 20 bit alignment - ASIOSTInt32MSB24 = 11, // 32 bit data with 24 bit alignment - - ASIOSTInt16LSB = 16, - ASIOSTInt24LSB = 17, // used for 20 bits as well - ASIOSTInt32LSB = 18, - ASIOSTFloat32LSB = 19, // IEEE 754 32 bit float, as found on Intel x86 architecture - ASIOSTFloat64LSB = 20, // IEEE 754 64 bit double float, as found on Intel x86 architecture - - // these are used for 32 bit data buffer, with different alignment of the data inside - // 32 bit PCI bus systems can more easily used with these - ASIOSTInt32LSB16 = 24, // 32 bit data with 18 bit alignment - ASIOSTInt32LSB18 = 25, // 32 bit data with 18 bit alignment - ASIOSTInt32LSB20 = 26, // 32 bit data with 20 bit alignment - ASIOSTInt32LSB24 = 27, // 32 bit data with 24 bit alignment - - // ASIO DSD format. - ASIOSTDSDInt8LSB1 = 32, // DSD 1 bit data, 8 samples per byte. First sample in Least significant bit. - ASIOSTDSDInt8MSB1 = 33, // DSD 1 bit data, 8 samples per byte. First sample in Most significant bit. - ASIOSTDSDInt8NER8 = 40, // DSD 8 bit data, 1 sample per byte. No Endianness required. - - ASIOSTLastEntry -}; - -/*----------------------------------------------------------------------------- -// DSD operation and buffer layout -// Definition by Steinberg/Sony Oxford. -// -// We have tried to treat DSD as PCM and so keep a consistant structure across -// the ASIO interface. -// -// DSD's sample rate is normally referenced as a multiple of 44.1Khz, so -// the standard sample rate is refered to as 64Fs (or 2.8224Mhz). We looked -// at making a special case for DSD and adding a field to the ASIOFuture that -// would allow the user to select the Over Sampleing Rate (OSR) as a seperate -// entity but decided in the end just to treat it as a simple value of -// 2.8224Mhz and use the standard interface to set it. -// -// The second problem was the "word" size, in PCM the word size is always a -// greater than or equal to 8 bits (a byte). This makes life easy as we can -// then pack the samples into the "natural" size for the machine. -// In DSD the "word" size is 1 bit. This is not a major problem and can easily -// be dealt with if we ensure that we always deal with a multiple of 8 samples. -// -// DSD brings with it another twist to the Endianness religion. How are the -// samples packed into the byte. It would be nice to just say the most significant -// bit is always the first sample, however there would then be a performance hit -// on little endian machines. Looking at how some of the processing goes... -// Little endian machines like the first sample to be in the Least Significant Bit, -// this is because when you write it to memory the data is in the correct format -// to be shifted in and out of the words. -// Big endian machine prefer the first sample to be in the Most Significant Bit, -// again for the same reasion. -// -// And just when things were looking really muddy there is a proposed extension to -// DSD that uses 8 bit word sizes. It does not care what endianness you use. -// -// Switching the driver between DSD and PCM mode -// ASIOFuture allows for extending the ASIO API quite transparently. -// See kAsioSetIoFormat, kAsioGetIoFormat, kAsioCanDoIoFormat -// -//-----------------------------------------------------------------------------*/ - - -//- - - - - - - - - - - - - - - - - - - - - - - - - -// Error codes -//- - - - - - - - - - - - - - - - - - - - - - - - - - -typedef long ASIOError; -enum { - ASE_OK = 0, // This value will be returned whenever the call succeeded - ASE_SUCCESS = 0x3f4847a0, // unique success return value for ASIOFuture calls - ASE_NotPresent = -1000, // hardware input or output is not present or available - ASE_HWMalfunction, // hardware is malfunctioning (can be returned by any ASIO function) - ASE_InvalidParameter, // input parameter invalid - ASE_InvalidMode, // hardware is in a bad mode or used in a bad mode - ASE_SPNotAdvancing, // hardware is not running when sample position is inquired - ASE_NoClock, // sample clock or rate cannot be determined or is not present - ASE_NoMemory // not enough memory for completing the request -}; - -//--------------------------------------------------------------------------------------------------- -//--------------------------------------------------------------------------------------------------- - -//- - - - - - - - - - - - - - - - - - - - - - - - - -// Time Info support -//- - - - - - - - - - - - - - - - - - - - - - - - - - -typedef struct ASIOTimeCode -{ - double speed; // speed relation (fraction of nominal speed) - // optional; set to 0. or 1. if not supported - ASIOSamples timeCodeSamples; // time in samples - unsigned long flags; // some information flags (see below) - char future[64]; -} ASIOTimeCode; - -typedef enum ASIOTimeCodeFlags -{ - kTcValid = 1, - kTcRunning = 1 << 1, - kTcReverse = 1 << 2, - kTcOnspeed = 1 << 3, - kTcStill = 1 << 4, - - kTcSpeedValid = 1 << 8 -} ASIOTimeCodeFlags; - -typedef struct AsioTimeInfo -{ - double speed; // absolute speed (1. = nominal) - ASIOTimeStamp systemTime; // system time related to samplePosition, in nanoseconds - // on mac, must be derived from Microseconds() (not UpTime()!) - // on windows, must be derived from timeGetTime() - ASIOSamples samplePosition; - ASIOSampleRate sampleRate; // current rate - unsigned long flags; // (see below) - char reserved[12]; -} AsioTimeInfo; - -typedef enum AsioTimeInfoFlags -{ - kSystemTimeValid = 1, // must always be valid - kSamplePositionValid = 1 << 1, // must always be valid - kSampleRateValid = 1 << 2, - kSpeedValid = 1 << 3, - - kSampleRateChanged = 1 << 4, - kClockSourceChanged = 1 << 5 -} AsioTimeInfoFlags; - -typedef struct ASIOTime // both input/output -{ - long reserved[4]; // must be 0 - struct AsioTimeInfo timeInfo; // required - struct ASIOTimeCode timeCode; // optional, evaluated if (timeCode.flags & kTcValid) -} ASIOTime; - -/* - -using time info: -it is recommended to use the new method with time info even if the asio -device does not support timecode; continuous calls to ASIOGetSamplePosition -and ASIOGetSampleRate are avoided, and there is a more defined relationship -between callback time and the time info. - -see the example below. -to initiate time info mode, after you have received the callbacks pointer in -ASIOCreateBuffers, you will call the asioMessage callback with kAsioSupportsTimeInfo -as the argument. if this returns 1, host has accepted time info mode. -now host expects the new callback bufferSwitchTimeInfo to be used instead -of the old bufferSwitch method. the ASIOTime structure is assumed to be valid -and accessible until the callback returns. - -using time code: -if the device supports reading time code, it will call host's asioMessage callback -with kAsioSupportsTimeCode as the selector. it may then fill the according -fields and set the kTcValid flag. -host will call the future method with the kAsioEnableTimeCodeRead selector when -it wants to enable or disable tc reading by the device. you should also support -the kAsioCanTimeInfo and kAsioCanTimeCode selectors in ASIOFuture (see example). - -note: -the AsioTimeInfo/ASIOTimeCode pair is supposed to work in both directions. -as a matter of convention, the relationship between the sample -position counter and the time code at buffer switch time is -(ignoring offset between tc and sample pos when tc is running): - -on input: sample 0 -> input buffer sample 0 -> time code 0 -on output: sample 0 -> output buffer sample 0 -> time code 0 - -this means that for 'real' calculations, one has to take into account -the according latencies. - -example: - -ASIOTime asioTime; - -in createBuffers() -{ - memset(&asioTime, 0, sizeof(ASIOTime)); - AsioTimeInfo* ti = &asioTime.timeInfo; - ti->sampleRate = theSampleRate; - ASIOTimeCode* tc = &asioTime.timeCode; - tc->speed = 1.; - timeInfoMode = false; - canTimeCode = false; - if(callbacks->asioMessage(kAsioSupportsTimeInfo, 0, 0, 0) == 1) - { - timeInfoMode = true; -#if kCanTimeCode - if(callbacks->asioMessage(kAsioSupportsTimeCode, 0, 0, 0) == 1) - canTimeCode = true; -#endif - } -} - -void switchBuffers(long doubleBufferIndex, bool processNow) -{ - if(timeInfoMode) - { - AsioTimeInfo* ti = &asioTime.timeInfo; - ti->flags = kSystemTimeValid | kSamplePositionValid | kSampleRateValid; - ti->systemTime = theNanoSeconds; - ti->samplePosition = theSamplePosition; - if(ti->sampleRate != theSampleRate) - ti->flags |= kSampleRateChanged; - ti->sampleRate = theSampleRate; - -#if kCanTimeCode - if(canTimeCode && timeCodeEnabled) - { - ASIOTimeCode* tc = &asioTime.timeCode; - tc->timeCodeSamples = tcSamples; // tc in samples - tc->flags = kTcValid | kTcRunning | kTcOnspeed; // if so... - } - ASIOTime* bb = callbacks->bufferSwitchTimeInfo(&asioTime, doubleBufferIndex, processNow ? ASIOTrue : ASIOFalse); -#else - callbacks->bufferSwitchTimeInfo(&asioTime, doubleBufferIndex, processNow ? ASIOTrue : ASIOFalse); -#endif - } - else - callbacks->bufferSwitch(doubleBufferIndex, ASIOFalse); -} - -ASIOError ASIOFuture(long selector, void *params) -{ - switch(selector) - { - case kAsioEnableTimeCodeRead: - timeCodeEnabled = true; - return ASE_SUCCESS; - case kAsioDisableTimeCodeRead: - timeCodeEnabled = false; - return ASE_SUCCESS; - case kAsioCanTimeInfo: - return ASE_SUCCESS; - #if kCanTimeCode - case kAsioCanTimeCode: - return ASE_SUCCESS; - #endif - } - return ASE_NotPresent; -}; - -*/ - -//- - - - - - - - - - - - - - - - - - - - - - - - - -// application's audio stream handler callbacks -//- - - - - - - - - - - - - - - - - - - - - - - - - - -typedef struct ASIOCallbacks -{ - void (*bufferSwitch) (long doubleBufferIndex, ASIOBool directProcess); - // bufferSwitch indicates that both input and output are to be processed. - // the current buffer half index (0 for A, 1 for B) determines - // - the output buffer that the host should start to fill. the other buffer - // will be passed to output hardware regardless of whether it got filled - // in time or not. - // - the input buffer that is now filled with incoming data. Note that - // because of the synchronicity of i/o, the input always has at - // least one buffer latency in relation to the output. - // directProcess suggests to the host whether it should immedeately - // start processing (directProcess == ASIOTrue), or whether its process - // should be deferred because the call comes from a very low level - // (for instance, a high level priority interrupt), and direct processing - // would cause timing instabilities for the rest of the system. If in doubt, - // directProcess should be set to ASIOFalse. - // Note: bufferSwitch may be called at interrupt time for highest efficiency. - - void (*sampleRateDidChange) (ASIOSampleRate sRate); - // gets called when the AudioStreamIO detects a sample rate change - // If sample rate is unknown, 0 is passed (for instance, clock loss - // when externally synchronized). - - long (*asioMessage) (long selector, long value, void* message, double* opt); - // generic callback for various purposes, see selectors below. - // note this is only present if the asio version is 2 or higher - - ASIOTime* (*bufferSwitchTimeInfo) (ASIOTime* params, long doubleBufferIndex, ASIOBool directProcess); - // new callback with time info. makes ASIOGetSamplePosition() and various - // calls to ASIOGetSampleRate obsolete, - // and allows for timecode sync etc. to be preferred; will be used if - // the driver calls asioMessage with selector kAsioSupportsTimeInfo. -} ASIOCallbacks; - -// asioMessage selectors -enum -{ - kAsioSelectorSupported = 1, // selector in , returns 1L if supported, - // 0 otherwise - kAsioEngineVersion, // returns engine (host) asio implementation version, - // 2 or higher - kAsioResetRequest, // request driver reset. if accepted, this - // will close the driver (ASIO_Exit() ) and - // re-open it again (ASIO_Init() etc). some - // drivers need to reconfigure for instance - // when the sample rate changes, or some basic - // changes have been made in ASIO_ControlPanel(). - // returns 1L; note the request is merely passed - // to the application, there is no way to determine - // if it gets accepted at this time (but it usually - // will be). - kAsioBufferSizeChange, // not yet supported, will currently always return 0L. - // for now, use kAsioResetRequest instead. - // once implemented, the new buffer size is expected - // in , and on success returns 1L - kAsioResyncRequest, // the driver went out of sync, such that - // the timestamp is no longer valid. this - // is a request to re-start the engine and - // slave devices (sequencer). returns 1 for ok, - // 0 if not supported. - kAsioLatenciesChanged, // the drivers latencies have changed. The engine - // will refetch the latencies. - kAsioSupportsTimeInfo, // if host returns true here, it will expect the - // callback bufferSwitchTimeInfo to be called instead - // of bufferSwitch - kAsioSupportsTimeCode, // - kAsioMMCCommand, // unused - value: number of commands, message points to mmc commands - kAsioSupportsInputMonitor, // kAsioSupportsXXX return 1 if host supports this - kAsioSupportsInputGain, // unused and undefined - kAsioSupportsInputMeter, // unused and undefined - kAsioSupportsOutputGain, // unused and undefined - kAsioSupportsOutputMeter, // unused and undefined - kAsioOverload, // driver detected an overload - - kAsioNumMessageSelectors -}; - -//--------------------------------------------------------------------------------------------------- -//--------------------------------------------------------------------------------------------------- - -//- - - - - - - - - - - - - - - - - - - - - - - - - -// (De-)Construction -//- - - - - - - - - - - - - - - - - - - - - - - - - - -typedef struct ASIODriverInfo -{ - long asioVersion; // currently, 2 - long driverVersion; // driver specific - char name[32]; - char errorMessage[124]; - void *sysRef; // on input: system reference - // (Windows: application main window handle, Mac & SGI: 0) -} ASIODriverInfo; - -ASIOError ASIOInit(ASIODriverInfo *info); -/* Purpose: - Initialize the AudioStreamIO. - Parameter: - info: pointer to an ASIODriver structure: - - asioVersion: - - on input, the host version. *** Note *** this is 0 for earlier asio - implementations, and the asioMessage callback is implemeted - only if asioVersion is 2 or greater. sorry but due to a design fault - the driver doesn't have access to the host version in ASIOInit :-( - added selector for host (engine) version in the asioMessage callback - so we're ok from now on. - - on return, asio implementation version. - older versions are 1 - if you support this version (namely, ASIO_outputReady() ) - this should be 2 or higher. also see the note in - ASIO_getTimeStamp() ! - - version: on return, the driver version (format is driver specific) - - name: on return, a null-terminated string containing the driver's name - - error message: on return, should contain a user message describing - the type of error that occured during ASIOInit(), if any. - - sysRef: platform specific - Returns: - If neither input nor output is present ASE_NotPresent - will be returned. - ASE_NoMemory, ASE_HWMalfunction are other possible error conditions -*/ - -ASIOError ASIOExit(void); -/* Purpose: - Terminates the AudioStreamIO. - Parameter: - None. - Returns: - If neither input nor output is present ASE_NotPresent - will be returned. - Notes: this implies ASIOStop() and ASIODisposeBuffers(), - meaning that no host callbacks must be accessed after ASIOExit(). -*/ - -//- - - - - - - - - - - - - - - - - - - - - - - - - -// Start/Stop -//- - - - - - - - - - - - - - - - - - - - - - - - - - -ASIOError ASIOStart(void); -/* Purpose: - Start input and output processing synchronously. - This will - - reset the sample counter to zero - - start the hardware (both input and output) - The first call to the hosts' bufferSwitch(index == 0) then tells - the host to read from input buffer A (index 0), and start - processing to output buffer A while output buffer B (which - has been filled by the host prior to calling ASIOStart()) - is possibly sounding (see also ASIOGetLatencies()) - Parameter: - None. - Returns: - If neither input nor output is present, ASE_NotPresent - will be returned. - If the hardware fails to start, ASE_HWMalfunction will be returned. - Notes: - There is no restriction on the time that ASIOStart() takes - to perform (that is, it is not considered a realtime trigger). -*/ - -ASIOError ASIOStop(void); -/* Purpose: - Stops input and output processing altogether. - Parameter: - None. - Returns: - If neither input nor output is present ASE_NotPresent - will be returned. - Notes: - On return from ASIOStop(), the driver must in no - case call the hosts' bufferSwitch() routine. -*/ - -//- - - - - - - - - - - - - - - - - - - - - - - - - -// Inquiry methods and sample rate -//- - - - - - - - - - - - - - - - - - - - - - - - - - -ASIOError ASIOGetChannels(long *numInputChannels, long *numOutputChannels); -/* Purpose: - Returns number of individual input/output channels. - Parameter: - numInputChannels will hold the number of available input channels - numOutputChannels will hold the number of available output channels - Returns: - If no input/output is present ASE_NotPresent will be returned. - If only inputs, or only outputs are available, the according - other parameter will be zero, and ASE_OK is returned. -*/ - -ASIOError ASIOGetLatencies(long *inputLatency, long *outputLatency); -/* Purpose: - Returns the input and output latencies. This includes - device specific delays, like FIFOs etc. - Parameter: - inputLatency will hold the 'age' of the first sample frame - in the input buffer when the hosts reads it in bufferSwitch() - (this is theoretical, meaning it does not include the overhead - and delay between the actual physical switch, and the time - when bufferSitch() enters). - This will usually be the size of one block in sample frames, plus - device specific latencies. - - outputLatency will specify the time between the buffer switch, - and the time when the next play buffer will start to sound. - The next play buffer is defined as the one the host starts - processing after (or at) bufferSwitch(), indicated by the - index parameter (0 for buffer A, 1 for buffer B). - It will usually be either one block, if the host writes directly - to a dma buffer, or two or more blocks if the buffer is 'latched' by - the driver. As an example, on ASIOStart(), the host will have filled - the play buffer at index 1 already; when it gets the callback (with - the parameter index == 0), this tells it to read from the input - buffer 0, and start to fill the play buffer 0 (assuming that now - play buffer 1 is already sounding). In this case, the output - latency is one block. If the driver decides to copy buffer 1 - at that time, and pass it to the hardware at the next slot (which - is most commonly done, but should be avoided), the output latency - becomes two blocks instead, resulting in a total i/o latency of at least - 3 blocks. As memory access is the main bottleneck in native dsp processing, - and to acheive less latency, it is highly recommended to try to avoid - copying (this is also why the driver is the owner of the buffers). To - summarize, the minimum i/o latency can be acheived if the input buffer - is processed by the host into the output buffer which will physically - start to sound on the next time slice. Also note that the host expects - the bufferSwitch() callback to be accessed for each time slice in order - to retain sync, possibly recursively; if it fails to process a block in - time, it will suspend its operation for some time in order to recover. - Returns: - If no input/output is present ASE_NotPresent will be returned. -*/ - -ASIOError ASIOGetBufferSize(long *minSize, long *maxSize, long *preferredSize, long *granularity); -/* Purpose: - Returns min, max, and preferred buffer sizes for input/output - Parameter: - minSize will hold the minimum buffer size - maxSize will hold the maxium possible buffer size - preferredSize will hold the preferred buffer size (a size which - best fits performance and hardware requirements) - granularity will hold the granularity at which buffer sizes - may differ. Usually, the buffer size will be a power of 2; - in this case, granularity will hold -1 on return, signalling - possible buffer sizes starting from minSize, increased in - powers of 2 up to maxSize. - Returns: - If no input/output is present ASE_NotPresent will be returned. - Notes: - When minimum and maximum buffer size are equal, - the preferred buffer size has to be the same value as well; granularity - should be 0 in this case. -*/ - -ASIOError ASIOCanSampleRate(ASIOSampleRate sampleRate); -/* Purpose: - Inquires the hardware for the available sample rates. - Parameter: - sampleRate is the rate in question. - Returns: - If the inquired sample rate is not supported, ASE_NoClock will be returned. - If no input/output is present ASE_NotPresent will be returned. -*/ -ASIOError ASIOGetSampleRate(ASIOSampleRate *currentRate); -/* Purpose: - Get the current sample Rate. - Parameter: - currentRate will hold the current sample rate on return. - Returns: - If sample rate is unknown, sampleRate will be 0 and ASE_NoClock will be returned. - If no input/output is present ASE_NotPresent will be returned. - Notes: -*/ - -ASIOError ASIOSetSampleRate(ASIOSampleRate sampleRate); -/* Purpose: - Set the hardware to the requested sample Rate. If sampleRate == 0, - enable external sync. - Parameter: - sampleRate: on input, the requested rate - Returns: - If sampleRate is unknown ASE_NoClock will be returned. - If the current clock is external, and sampleRate is != 0, - ASE_InvalidMode will be returned - If no input/output is present ASE_NotPresent will be returned. - Notes: -*/ - -typedef struct ASIOClockSource -{ - long index; // as used for ASIOSetClockSource() - long associatedChannel; // for instance, S/PDIF or AES/EBU - long associatedGroup; // see channel groups (ASIOGetChannelInfo()) - ASIOBool isCurrentSource; // ASIOTrue if this is the current clock source - char name[32]; // for user selection -} ASIOClockSource; - -ASIOError ASIOGetClockSources(ASIOClockSource *clocks, long *numSources); -/* Purpose: - Get the available external audio clock sources - Parameter: - clocks points to an array of ASIOClockSource structures: - - index: this is used to identify the clock source - when ASIOSetClockSource() is accessed, should be - an index counting from zero - - associatedInputChannel: the first channel of an associated - input group, if any. - - associatedGroup: the group index of that channel. - groups of channels are defined to seperate for - instance analog, S/PDIF, AES/EBU, ADAT connectors etc, - when present simultaniously. Note that associated channel - is enumerated according to numInputs/numOutputs, means it - is independant from a group (see also ASIOGetChannelInfo()) - inputs are associated to a clock if the physical connection - transfers both data and clock (like S/PDIF, AES/EBU, or - ADAT inputs). if there is no input channel associated with - the clock source (like Word Clock, or internal oscillator), both - associatedChannel and associatedGroup should be set to -1. - - isCurrentSource: on exit, ASIOTrue if this is the current clock - source, ASIOFalse else - - name: a null-terminated string for user selection of the available sources. - numSources: - on input: the number of allocated array members - on output: the number of available clock sources, at least - 1 (internal clock generator). - Returns: - If no input/output is present ASE_NotPresent will be returned. - Notes: -*/ - -ASIOError ASIOSetClockSource(long index); -/* Purpose: - Set the audio clock source - Parameter: - index as obtained from an inquiry to ASIOGetClockSources() - Returns: - If no input/output is present ASE_NotPresent will be returned. - If the clock can not be selected because an input channel which - carries the current clock source is active, ASE_InvalidMode - *may* be returned (this depends on the properties of the driver - and/or hardware). - Notes: - Should *not* return ASE_NoClock if there is no clock signal present - at the selected source; this will be inquired via ASIOGetSampleRate(). - It should call the host callback procedure sampleRateHasChanged(), - if the switch causes a sample rate change, or if no external clock - is present at the selected source. -*/ - -ASIOError ASIOGetSamplePosition (ASIOSamples *sPos, ASIOTimeStamp *tStamp); -/* Purpose: - Inquires the sample position/time stamp pair. - Parameter: - sPos will hold the sample position on return. The sample - position is reset to zero when ASIOStart() gets called. - tStamp will hold the system time when the sample position - was latched. - Returns: - If no input/output is present, ASE_NotPresent will be returned. - If there is no clock, ASE_SPNotAdvancing will be returned. - Notes: - - in order to be able to synchronise properly, - the sample position / time stamp pair must refer to the current block, - that is, the engine will call ASIOGetSamplePosition() in its bufferSwitch() - callback and expect the time for the current block. thus, when requested - in the very first bufferSwitch after ASIO_Start(), the sample position - should be zero, and the time stamp should refer to the very time where - the stream was started. it also means that the sample position must be - block aligned. the driver must ensure proper interpolation if the system - time can not be determined for the block position. the driver is responsible - for precise time stamps as it usually has most direct access to lower - level resources. proper behaviour of ASIO_GetSamplePosition() and ASIO_GetLatencies() - are essential for precise media synchronization! -*/ - -typedef struct ASIOChannelInfo -{ - long channel; // on input, channel index - ASIOBool isInput; // on input - ASIOBool isActive; // on exit - long channelGroup; // dto - ASIOSampleType type; // dto - char name[32]; // dto -} ASIOChannelInfo; - -ASIOError ASIOGetChannelInfo(ASIOChannelInfo *info); -/* Purpose: - retreive information about the nature of a channel - Parameter: - info: pointer to a ASIOChannelInfo structure with - - channel: on input, the channel index of the channel in question. - - isInput: on input, ASIOTrue if info for an input channel is - requested, else output - - channelGroup: on return, the channel group that the channel - belongs to. For drivers which support different types of - channels, like analog, S/PDIF, AES/EBU, ADAT etc interfaces, - there should be a reasonable grouping of these types. Groups - are always independant form a channel index, that is, a channel - index always counts from 0 to numInputs/numOutputs regardless - of the group it may belong to. - There will always be at least one group (group 0). Please - also note that by default, the host may decide to activate - channels 0 and 1; thus, these should belong to the most - useful type (analog i/o, if present). - - type: on return, contains the sample type of the channel - - isActive: on return, ASIOTrue if channel is active as it was - installed by ASIOCreateBuffers(), ASIOFalse else - - name: describing the type of channel in question. Used to allow - for user selection, and enabling of specific channels. examples: - "Analog In", "SPDIF Out" etc - Returns: - If no input/output is present ASE_NotPresent will be returned. - Notes: - If possible, the string should be organised such that the first - characters are most significantly describing the nature of the - port, to allow for identification even if the view showing the - port name is too small to display more than 8 characters, for - instance. -*/ - -//- - - - - - - - - - - - - - - - - - - - - - - - - -// Buffer preparation -//- - - - - - - - - - - - - - - - - - - - - - - - - - -typedef struct ASIOBufferInfo -{ - ASIOBool isInput; // on input: ASIOTrue: input, else output - long channelNum; // on input: channel index - void *buffers[2]; // on output: double buffer addresses -} ASIOBufferInfo; - -ASIOError ASIOCreateBuffers(ASIOBufferInfo *bufferInfos, long numChannels, - long bufferSize, ASIOCallbacks *callbacks); - -/* Purpose: - Allocates input/output buffers for all input and output channels to be activated. - Parameter: - bufferInfos is a pointer to an array of ASIOBufferInfo structures: - - isInput: on input, ASIOTrue if the buffer is to be allocated - for an input, output buffer else - - channelNum: on input, the index of the channel in question - (counting from 0) - - buffers: on exit, 2 pointers to the halves of the channels' double-buffer. - the size of the buffer(s) of course depend on both the ASIOSampleType - as obtained from ASIOGetChannelInfo(), and bufferSize - numChannels is the sum of all input and output channels to be created; - thus bufferInfos is a pointer to an array of numChannels ASIOBufferInfo - structures. - bufferSize selects one of the possible buffer sizes as obtained from - ASIOGetBufferSizes(). - callbacks is a pointer to an ASIOCallbacks structure. - Returns: - If not enough memory is available ASE_NoMemory will be returned. - If no input/output is present ASE_NotPresent will be returned. - If bufferSize is not supported, or one or more of the bufferInfos elements - contain invalid settings, ASE_InvalidMode will be returned. - Notes: - If individual channel selection is not possible but requested, - the driver has to handle this. namely, bufferSwitch() will only - have filled buffers of enabled outputs. If possible, processing - and buss activities overhead should be avoided for channels which - were not enabled here. -*/ - -ASIOError ASIODisposeBuffers(void); -/* Purpose: - Releases all buffers for the device. - Parameter: - None. - Returns: - If no buffer were ever prepared, ASE_InvalidMode will be returned. - If no input/output is present ASE_NotPresent will be returned. - Notes: - This implies ASIOStop(). -*/ - -ASIOError ASIOControlPanel(void); -/* Purpose: - request the driver to start a control panel component - for device specific user settings. This will not be - accessed on some platforms (where the component is accessed - instead). - Parameter: - None. - Returns: - If no panel is available ASE_NotPresent will be returned. - Actually, the return code is ignored. - Notes: - if the user applied settings which require a re-configuration - of parts or all of the enigine and/or driver (such as a change of - the block size), the asioMessage callback can be used (see - ASIO_Callbacks). -*/ - -ASIOError ASIOFuture(long selector, void *params); -/* Purpose: - various - Parameter: - selector: operation Code as to be defined. zero is reserved for - testing purposes. - params: depends on the selector; usually pointer to a structure - for passing and retreiving any type and amount of parameters. - Returns: - the return value is also selector dependant. if the selector - is unknown, ASE_InvalidParameter should be returned to prevent - further calls with this selector. on success, ASE_SUCCESS - must be returned (note: ASE_OK is *not* sufficient!) - Notes: - see selectors defined below. -*/ - -enum -{ - kAsioEnableTimeCodeRead = 1, // no arguments - kAsioDisableTimeCodeRead, // no arguments - kAsioSetInputMonitor, // ASIOInputMonitor* in params - kAsioTransport, // ASIOTransportParameters* in params - kAsioSetInputGain, // ASIOChannelControls* in params, apply gain - kAsioGetInputMeter, // ASIOChannelControls* in params, fill meter - kAsioSetOutputGain, // ASIOChannelControls* in params, apply gain - kAsioGetOutputMeter, // ASIOChannelControls* in params, fill meter - kAsioCanInputMonitor, // no arguments for kAsioCanXXX selectors - kAsioCanTimeInfo, - kAsioCanTimeCode, - kAsioCanTransport, - kAsioCanInputGain, - kAsioCanInputMeter, - kAsioCanOutputGain, - kAsioCanOutputMeter, - - // DSD support - // The following extensions are required to allow switching - // and control of the DSD subsystem. - kAsioSetIoFormat = 0x23111961, /* ASIOIoFormat * in params. */ - kAsioGetIoFormat = 0x23111983, /* ASIOIoFormat * in params. */ - kAsioCanDoIoFormat = 0x23112004, /* ASIOIoFormat * in params. */ -}; - -typedef struct ASIOInputMonitor -{ - long input; // this input was set to monitor (or off), -1: all - long output; // suggested output for monitoring the input (if so) - long gain; // suggested gain, ranging 0 - 0x7fffffffL (-inf to +12 dB) - ASIOBool state; // ASIOTrue => on, ASIOFalse => off - long pan; // suggested pan, 0 => all left, 0x7fffffff => right -} ASIOInputMonitor; - -typedef struct ASIOChannelControls -{ - long channel; // on input, channel index - ASIOBool isInput; // on input - long gain; // on input, ranges 0 thru 0x7fffffff - long meter; // on return, ranges 0 thru 0x7fffffff - char future[32]; -} ASIOChannelControls; - -typedef struct ASIOTransportParameters -{ - long command; // see enum below - ASIOSamples samplePosition; - long track; - long trackSwitches[16]; // 512 tracks on/off - char future[64]; -} ASIOTransportParameters; - -enum -{ - kTransStart = 1, - kTransStop, - kTransLocate, // to samplePosition - kTransPunchIn, - kTransPunchOut, - kTransArmOn, // track - kTransArmOff, // track - kTransMonitorOn, // track - kTransMonitorOff, // track - kTransArm, // trackSwitches - kTransMonitor // trackSwitches -}; - -/* -// DSD support -// Some notes on how to use ASIOIoFormatType. -// -// The caller will fill the format with the request types. -// If the board can do the request then it will leave the -// values unchanged. If the board does not support the -// request then it will change that entry to Invalid (-1) -// -// So to request DSD then -// -// ASIOIoFormat NeedThis={kASIODSDFormat}; -// -// if(ASE_SUCCESS != ASIOFuture(kAsioSetIoFormat,&NeedThis) ){ -// // If the board did not accept one of the parameters then the -// // whole call will fail and the failing parameter will -// // have had its value changes to -1. -// } -// -// Note: Switching between the formats need to be done before the "prepared" -// state (see ASIO 2 documentation) is entered. -*/ -typedef long int ASIOIoFormatType; -enum ASIOIoFormatType_e -{ - kASIOFormatInvalid = -1, - kASIOPCMFormat = 0, - kASIODSDFormat = 1, -}; - -typedef struct ASIOIoFormat_s -{ - ASIOIoFormatType FormatType; - char future[512-sizeof(ASIOIoFormatType)]; -} ASIOIoFormat; - - -ASIOError ASIOOutputReady(void); -/* Purpose: - this tells the driver that the host has completed processing - the output buffers. if the data format required by the hardware - differs from the supported asio formats, but the hardware - buffers are DMA buffers, the driver will have to convert - the audio stream data; as the bufferSwitch callback is - usually issued at dma block switch time, the driver will - have to convert the *previous* host buffer, which increases - the output latency by one block. - when the host finds out that ASIOOutputReady() returns - true, it will issue this call whenever it completed - output processing. then the driver can convert the - host data directly to the dma buffer to be played next, - reducing output latency by one block. - another way to look at it is, that the buffer switch is called - in order to pass the *input* stream to the host, so that it can - process the input into the output, and the output stream is passed - to the driver when the host has completed its process. - Parameter: - None - Returns: - only if the above mentioned scenario is given, and a reduction - of output latency can be acheived by this mechanism, should - ASE_OK be returned. otherwise (and usually), ASE_NotPresent - should be returned in order to prevent further calls to this - function. note that the host may want to determine if it is - to use this when the system is not yet fully initialized, so - ASE_OK should always be returned if the mechanism makes sense. - Notes: - please remeber to adjust ASIOGetLatencies() according to - whether ASIOOutputReady() was ever called or not, if your - driver supports this scenario. - also note that the engine may fail to call ASIO_OutputReady() - in time in overload cases. as already mentioned, bufferSwitch - should be called for every block regardless of whether a block - could be processed in time. -*/ - -// restore old alignment -#if defined(_MSC_VER) && !defined(__MWERKS__) -#pragma pack(pop) -#elif PRAGMA_ALIGN_SUPPORTED -#pragma options align = reset -#endif - -#endif - diff --git a/vendor/rtaudio/include/asiodrivers.cpp b/vendor/rtaudio/include/asiodrivers.cpp deleted file mode 100644 index 5f56454c2..000000000 --- a/vendor/rtaudio/include/asiodrivers.cpp +++ /dev/null @@ -1,186 +0,0 @@ -#include -#include "asiodrivers.h" - -AsioDrivers* asioDrivers = 0; - -bool loadAsioDriver(char *name); - -bool loadAsioDriver(char *name) -{ - if(!asioDrivers) - asioDrivers = new AsioDrivers(); - if(asioDrivers) - return asioDrivers->loadDriver(name); - return false; -} - -//------------------------------------------------------------------------------------ - -#if MAC - -bool resolveASIO(unsigned long aconnID); - -AsioDrivers::AsioDrivers() : CodeFragments("ASIO Drivers", 'AsDr', 'Asio') -{ - connID = -1; - curIndex = -1; -} - -AsioDrivers::~AsioDrivers() -{ - removeCurrentDriver(); -} - -bool AsioDrivers::getCurrentDriverName(char *name) -{ - if(curIndex >= 0) - return getName(curIndex, name); - return false; -} - -long AsioDrivers::getDriverNames(char **names, long maxDrivers) -{ - for(long i = 0; i < getNumFragments() && i < maxDrivers; i++) - getName(i, names[i]); - return getNumFragments() < maxDrivers ? getNumFragments() : maxDrivers; -} - -bool AsioDrivers::loadDriver(char *name) -{ - char dname[64]; - unsigned long newID; - - for(long i = 0; i < getNumFragments(); i++) - { - if(getName(i, dname) && !strcmp(name, dname)) - { - if(newInstance(i, &newID)) - { - if(resolveASIO(newID)) - { - if(connID != -1) - removeInstance(curIndex, connID); - curIndex = i; - connID = newID; - return true; - } - } - break; - } - } - return false; -} - -void AsioDrivers::removeCurrentDriver() -{ - if(connID != -1) - removeInstance(curIndex, connID); - connID = -1; - curIndex = -1; -} - -//------------------------------------------------------------------------------------ - -#elif WINDOWS - -#include "iasiodrv.h" - -extern IASIO* theAsioDriver; - -AsioDrivers::AsioDrivers() : AsioDriverList() -{ - curIndex = -1; -} - -AsioDrivers::~AsioDrivers() -{ -} - -bool AsioDrivers::getCurrentDriverName(char *name) -{ - if(curIndex >= 0) - return asioGetDriverName(curIndex, name, 32) == 0 ? true : false; - name[0] = 0; - return false; -} - -long AsioDrivers::getDriverNames(char **names, long maxDrivers) -{ - for(long i = 0; i < asioGetNumDev() && i < maxDrivers; i++) - asioGetDriverName(i, names[i], 32); - return asioGetNumDev() < maxDrivers ? asioGetNumDev() : maxDrivers; -} - -bool AsioDrivers::loadDriver(char *name) -{ - char dname[64]; - char curName[64]; - - for(long i = 0; i < asioGetNumDev(); i++) - { - if(!asioGetDriverName(i, dname, 32) && !strcmp(name, dname)) - { - curName[0] = 0; - getCurrentDriverName(curName); // in case we fail... - removeCurrentDriver(); - - if(!asioOpenDriver(i, (void **)&theAsioDriver)) - { - curIndex = i; - return true; - } - else - { - theAsioDriver = 0; - if(curName[0] && strcmp(dname, curName)) - loadDriver(curName); // try restore - } - break; - } - } - return false; -} - -void AsioDrivers::removeCurrentDriver() -{ - if(curIndex != -1) - asioCloseDriver(curIndex); - curIndex = -1; -} - -#elif SGI || BEOS - -#include "asiolist.h" - -AsioDrivers::AsioDrivers() - : AsioDriverList() -{ - curIndex = -1; -} - -AsioDrivers::~AsioDrivers() -{ -} - -bool AsioDrivers::getCurrentDriverName(char *name) -{ - return false; -} - -long AsioDrivers::getDriverNames(char **names, long maxDrivers) -{ - return 0; -} - -bool AsioDrivers::loadDriver(char *name) -{ - return false; -} - -void AsioDrivers::removeCurrentDriver() -{ -} - -#else -#error implement me -#endif diff --git a/vendor/rtaudio/include/asiodrivers.h b/vendor/rtaudio/include/asiodrivers.h deleted file mode 100644 index 2ddf7ad02..000000000 --- a/vendor/rtaudio/include/asiodrivers.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef __AsioDrivers__ -#define __AsioDrivers__ - -#include "ginclude.h" - -#if MAC -#include "CodeFragments.hpp" - -class AsioDrivers : public CodeFragments - -#elif WINDOWS -#include -#include "asiolist.h" - -class AsioDrivers : public AsioDriverList - -#elif SGI || BEOS -#include "asiolist.h" - -class AsioDrivers : public AsioDriverList - -#else -#error implement me -#endif - -{ -public: - AsioDrivers(); - ~AsioDrivers(); - - bool getCurrentDriverName(char *name); - long getDriverNames(char **names, long maxDrivers); - bool loadDriver(char *name); - void removeCurrentDriver(); - long getCurrentDriverIndex() {return curIndex;} -protected: - unsigned long connID; - long curIndex; -}; - -#endif diff --git a/vendor/rtaudio/include/asiodrvr.h b/vendor/rtaudio/include/asiodrvr.h deleted file mode 100644 index 663f75a74..000000000 --- a/vendor/rtaudio/include/asiodrvr.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - Steinberg Audio Stream I/O API - (c) 1996, Steinberg Soft- und Hardware GmbH - charlie (May 1996) - - asiodrvr.h - c++ superclass to implement asio functionality. from this, - you can derive whatever required -*/ - -#ifndef _asiodrvr_ -#define _asiodrvr_ - -// cpu and os system we are running on -#include "asiosys.h" -// basic "C" interface -#include "asio.h" - -class AsioDriver; -extern AsioDriver *getDriver(); // for generic constructor - -#if WINDOWS -#include -#include "combase.h" -#include "iasiodrv.h" -class AsioDriver : public IASIO ,public CUnknown -{ -public: - AsioDriver(LPUNKNOWN pUnk, HRESULT *phr); - - DECLARE_IUNKNOWN - // Factory method - static CUnknown *CreateInstance(LPUNKNOWN pUnk, HRESULT *phr); - // IUnknown - virtual HRESULT STDMETHODCALLTYPE NonDelegatingQueryInterface(REFIID riid,void **ppvObject); - -#else - -class AsioDriver -{ -public: - AsioDriver(); -#endif - virtual ~AsioDriver(); - - virtual ASIOBool init(void* sysRef); - virtual void getDriverName(char *name); // max 32 bytes incl. terminating zero - virtual long getDriverVersion(); - virtual void getErrorMessage(char *string); // max 124 bytes incl. - - virtual ASIOError start(); - virtual ASIOError stop(); - - virtual ASIOError getChannels(long *numInputChannels, long *numOutputChannels); - virtual ASIOError getLatencies(long *inputLatency, long *outputLatency); - virtual ASIOError getBufferSize(long *minSize, long *maxSize, - long *preferredSize, long *granularity); - - virtual ASIOError canSampleRate(ASIOSampleRate sampleRate); - virtual ASIOError getSampleRate(ASIOSampleRate *sampleRate); - virtual ASIOError setSampleRate(ASIOSampleRate sampleRate); - virtual ASIOError getClockSources(ASIOClockSource *clocks, long *numSources); - virtual ASIOError setClockSource(long reference); - - virtual ASIOError getSamplePosition(ASIOSamples *sPos, ASIOTimeStamp *tStamp); - virtual ASIOError getChannelInfo(ASIOChannelInfo *info); - - virtual ASIOError createBuffers(ASIOBufferInfo *bufferInfos, long numChannels, - long bufferSize, ASIOCallbacks *callbacks); - virtual ASIOError disposeBuffers(); - - virtual ASIOError controlPanel(); - virtual ASIOError future(long selector, void *opt); - virtual ASIOError outputReady(); -}; -#endif diff --git a/vendor/rtaudio/include/asiolist.cpp b/vendor/rtaudio/include/asiolist.cpp deleted file mode 100644 index e4c73c29b..000000000 --- a/vendor/rtaudio/include/asiolist.cpp +++ /dev/null @@ -1,308 +0,0 @@ -#include -#include "iasiodrv.h" -#include "asiolist.h" - -#define ASIODRV_DESC "description" -#define INPROC_SERVER "InprocServer32" -#define ASIO_PATH "software\\asio" -#define COM_CLSID "clsid" - -// ****************************************************************** -// Local Functions -// ****************************************************************** -static LONG findDrvPath (char *clsidstr,char *dllpath,int dllpathsize) -{ - HKEY hkEnum,hksub,hkpath; - char databuf[512]; - LONG cr,rc = -1; - DWORD datatype,datasize; - DWORD index; - OFSTRUCT ofs; - HFILE hfile; - BOOL found = FALSE; - -#ifdef UNICODE - CharLowerBuffA(clsidstr,strlen(clsidstr)); - if ((cr = RegOpenKeyA(HKEY_CLASSES_ROOT,COM_CLSID,&hkEnum)) == ERROR_SUCCESS) { - - index = 0; - while (cr == ERROR_SUCCESS && !found) { - cr = RegEnumKeyA(hkEnum,index++,databuf,512); - if (cr == ERROR_SUCCESS) { - CharLowerBuffA(databuf,strlen(databuf)); - if (!(strcmp(databuf,clsidstr))) { - if ((cr = RegOpenKeyExA(hkEnum,databuf,0,KEY_READ,&hksub)) == ERROR_SUCCESS) { - if ((cr = RegOpenKeyExA(hksub,INPROC_SERVER,0,KEY_READ,&hkpath)) == ERROR_SUCCESS) { - datatype = REG_SZ; datasize = (DWORD)dllpathsize; - cr = RegQueryValueEx(hkpath,0,0,&datatype,(LPBYTE)dllpath,&datasize); - if (cr == ERROR_SUCCESS) { - memset(&ofs,0,sizeof(OFSTRUCT)); - ofs.cBytes = sizeof(OFSTRUCT); - hfile = OpenFile(dllpath,&ofs,OF_EXIST); - if (hfile) rc = 0; - } - RegCloseKey(hkpath); - } - RegCloseKey(hksub); - } - found = TRUE; // break out - } - } - } - RegCloseKey(hkEnum); - } -#else - CharLowerBuff(clsidstr,strlen(clsidstr)); - if ((cr = RegOpenKey(HKEY_CLASSES_ROOT,COM_CLSID,&hkEnum)) == ERROR_SUCCESS) { - - index = 0; - while (cr == ERROR_SUCCESS && !found) { - cr = RegEnumKey(hkEnum,index++,databuf,512); - if (cr == ERROR_SUCCESS) { - CharLowerBuff(databuf,strlen(databuf)); - if (!(strcmp(databuf,clsidstr))) { - if ((cr = RegOpenKeyEx(hkEnum,databuf,0,KEY_READ,&hksub)) == ERROR_SUCCESS) { - if ((cr = RegOpenKeyEx(hksub,INPROC_SERVER,0,KEY_READ,&hkpath)) == ERROR_SUCCESS) { - datatype = REG_SZ; datasize = (DWORD)dllpathsize; - cr = RegQueryValueEx(hkpath,0,0,&datatype,(LPBYTE)dllpath,&datasize); - if (cr == ERROR_SUCCESS) { - memset(&ofs,0,sizeof(OFSTRUCT)); - ofs.cBytes = sizeof(OFSTRUCT); - hfile = OpenFile(dllpath,&ofs,OF_EXIST); - if (hfile) rc = 0; - } - RegCloseKey(hkpath); - } - RegCloseKey(hksub); - } - found = TRUE; // break out - } - } - } - RegCloseKey(hkEnum); - } -#endif - return rc; -} - - -static LPASIODRVSTRUCT newDrvStruct (HKEY hkey,char *keyname,int drvID,LPASIODRVSTRUCT lpdrv) -{ - HKEY hksub; - char databuf[256]; - char dllpath[MAXPATHLEN]; - WORD wData[100]; - CLSID clsid; - DWORD datatype,datasize; - LONG cr,rc; - - if (!lpdrv) { - if ((cr = RegOpenKeyExA(hkey,keyname,0,KEY_READ,&hksub)) == ERROR_SUCCESS) { - - datatype = REG_SZ; datasize = 256; - cr = RegQueryValueExA(hksub,COM_CLSID,0,&datatype,(LPBYTE)databuf,&datasize); - if (cr == ERROR_SUCCESS) { - rc = findDrvPath (databuf,dllpath,MAXPATHLEN); - if (rc == 0) { - lpdrv = new ASIODRVSTRUCT[1]; - if (lpdrv) { - memset(lpdrv,0,sizeof(ASIODRVSTRUCT)); - lpdrv->drvID = drvID; - MultiByteToWideChar(CP_ACP,0,(LPCSTR)databuf,-1,(LPWSTR)wData,100); - if ((cr = CLSIDFromString((LPOLESTR)wData,(LPCLSID)&clsid)) == S_OK) { - memcpy(&lpdrv->clsid,&clsid,sizeof(CLSID)); - } - - datatype = REG_SZ; datasize = 256; - cr = RegQueryValueExA(hksub,ASIODRV_DESC,0,&datatype,(LPBYTE)databuf,&datasize); - if (cr == ERROR_SUCCESS) { - strcpy(lpdrv->drvname,databuf); - } - else strcpy(lpdrv->drvname,keyname); - } - } - } - RegCloseKey(hksub); - } - } - else lpdrv->next = newDrvStruct(hkey,keyname,drvID+1,lpdrv->next); - - return lpdrv; -} - -static void deleteDrvStruct (LPASIODRVSTRUCT lpdrv) -{ - IASIO *iasio; - - if (lpdrv != 0) { - deleteDrvStruct(lpdrv->next); - if (lpdrv->asiodrv) { - iasio = (IASIO *)lpdrv->asiodrv; - iasio->Release(); - } - delete lpdrv; - } -} - - -static LPASIODRVSTRUCT getDrvStruct (int drvID,LPASIODRVSTRUCT lpdrv) -{ - while (lpdrv) { - if (lpdrv->drvID == drvID) return lpdrv; - lpdrv = lpdrv->next; - } - return 0; -} -// ****************************************************************** - - -// ****************************************************************** -// AsioDriverList -// ****************************************************************** -AsioDriverList::AsioDriverList () -{ - HKEY hkEnum = 0; - char keyname[MAXDRVNAMELEN]; - LPASIODRVSTRUCT pdl; - LONG cr; - DWORD index = 0; - BOOL fin = FALSE; - - numdrv = 0; - lpdrvlist = 0; - -#ifdef UNICODE - cr = RegOpenKeyA(HKEY_LOCAL_MACHINE,ASIO_PATH,&hkEnum); -#else - cr = RegOpenKey(HKEY_LOCAL_MACHINE,ASIO_PATH,&hkEnum); -#endif - while (cr == ERROR_SUCCESS) { -#ifdef UNICODE - if ((cr = RegEnumKeyA(hkEnum,index++,keyname,MAXDRVNAMELEN))== ERROR_SUCCESS) { -#else - if ((cr = RegEnumKey(hkEnum,index++,keyname,MAXDRVNAMELEN))== ERROR_SUCCESS) { -#endif - lpdrvlist = newDrvStruct (hkEnum,keyname,0,lpdrvlist); - } - else fin = TRUE; - } - if (hkEnum) RegCloseKey(hkEnum); - - pdl = lpdrvlist; - while (pdl) { - numdrv++; - pdl = pdl->next; - } - - if (numdrv) CoInitialize(0); // initialize COM -} - -AsioDriverList::~AsioDriverList () -{ - if (numdrv) { - deleteDrvStruct(lpdrvlist); - CoUninitialize(); - } -} - - -LONG AsioDriverList::asioGetNumDev (VOID) -{ - return (LONG)numdrv; -} - - -LONG AsioDriverList::asioOpenDriver (int drvID,LPVOID *asiodrv) -{ - LPASIODRVSTRUCT lpdrv = 0; - long rc; - - if (!asiodrv) return DRVERR_INVALID_PARAM; - - if ((lpdrv = getDrvStruct(drvID,lpdrvlist)) != 0) { - if (!lpdrv->asiodrv) { - rc = CoCreateInstance(lpdrv->clsid,0,CLSCTX_INPROC_SERVER,lpdrv->clsid,asiodrv); - if (rc == S_OK) { - lpdrv->asiodrv = *asiodrv; - return 0; - } - // else if (rc == REGDB_E_CLASSNOTREG) - // strcpy (info->messageText, "Driver not registered in the Registration Database!"); - } - else rc = DRVERR_DEVICE_ALREADY_OPEN; - } - else rc = DRVERR_DEVICE_NOT_FOUND; - - return rc; -} - - -LONG AsioDriverList::asioCloseDriver (int drvID) -{ - LPASIODRVSTRUCT lpdrv = 0; - IASIO *iasio; - - if ((lpdrv = getDrvStruct(drvID,lpdrvlist)) != 0) { - if (lpdrv->asiodrv) { - iasio = (IASIO *)lpdrv->asiodrv; - iasio->Release(); - lpdrv->asiodrv = 0; - } - } - - return 0; -} - -LONG AsioDriverList::asioGetDriverName (int drvID,char *drvname,int drvnamesize) -{ - LPASIODRVSTRUCT lpdrv = 0; - - if (!drvname) return DRVERR_INVALID_PARAM; - - if ((lpdrv = getDrvStruct(drvID,lpdrvlist)) != 0) { - if (strlen(lpdrv->drvname) < (unsigned int)drvnamesize) { - strcpy(drvname,lpdrv->drvname); - } - else { - memcpy(drvname,lpdrv->drvname,drvnamesize-4); - drvname[drvnamesize-4] = '.'; - drvname[drvnamesize-3] = '.'; - drvname[drvnamesize-2] = '.'; - drvname[drvnamesize-1] = 0; - } - return 0; - } - return DRVERR_DEVICE_NOT_FOUND; -} - -LONG AsioDriverList::asioGetDriverPath (int drvID,char *dllpath,int dllpathsize) -{ - LPASIODRVSTRUCT lpdrv = 0; - - if (!dllpath) return DRVERR_INVALID_PARAM; - - if ((lpdrv = getDrvStruct(drvID,lpdrvlist)) != 0) { - if (strlen(lpdrv->dllpath) < (unsigned int)dllpathsize) { - strcpy(dllpath,lpdrv->dllpath); - return 0; - } - dllpath[0] = 0; - return DRVERR_INVALID_PARAM; - } - return DRVERR_DEVICE_NOT_FOUND; -} - -LONG AsioDriverList::asioGetDriverCLSID (int drvID,CLSID *clsid) -{ - LPASIODRVSTRUCT lpdrv = 0; - - if (!clsid) return DRVERR_INVALID_PARAM; - - if ((lpdrv = getDrvStruct(drvID,lpdrvlist)) != 0) { - memcpy(clsid,&lpdrv->clsid,sizeof(CLSID)); - return 0; - } - return DRVERR_DEVICE_NOT_FOUND; -} - - diff --git a/vendor/rtaudio/include/asiolist.h b/vendor/rtaudio/include/asiolist.h deleted file mode 100644 index 01c64f0bb..000000000 --- a/vendor/rtaudio/include/asiolist.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef __asiolist__ -#define __asiolist__ - -#define DRVERR -5000 -#define DRVERR_INVALID_PARAM DRVERR-1 -#define DRVERR_DEVICE_ALREADY_OPEN DRVERR-2 -#define DRVERR_DEVICE_NOT_FOUND DRVERR-3 - -#define MAXPATHLEN 512 -#define MAXDRVNAMELEN 128 - -struct asiodrvstruct -{ - int drvID; - CLSID clsid; - char dllpath[MAXPATHLEN]; - char drvname[MAXDRVNAMELEN]; - LPVOID asiodrv; - struct asiodrvstruct *next; -}; - -typedef struct asiodrvstruct ASIODRVSTRUCT; -typedef ASIODRVSTRUCT *LPASIODRVSTRUCT; - -class AsioDriverList { -public: - AsioDriverList(); - ~AsioDriverList(); - - LONG asioOpenDriver (int,VOID **); - LONG asioCloseDriver (int); - - // nice to have - LONG asioGetNumDev (VOID); - LONG asioGetDriverName (int,char *,int); - LONG asioGetDriverPath (int,char *,int); - LONG asioGetDriverCLSID (int,CLSID *); - - // or use directly access - LPASIODRVSTRUCT lpdrvlist; - int numdrv; -}; - -typedef class AsioDriverList *LPASIODRIVERLIST; - -#endif diff --git a/vendor/rtaudio/include/asiosys.h b/vendor/rtaudio/include/asiosys.h deleted file mode 100644 index 37f7a48a1..000000000 --- a/vendor/rtaudio/include/asiosys.h +++ /dev/null @@ -1,82 +0,0 @@ -#ifndef __asiosys__ - #define __asiosys__ - - #ifdef WIN32 - #undef MAC - #define PPC 0 - #define WINDOWS 1 - #define SGI 0 - #define SUN 0 - #define LINUX 0 - #define BEOS 0 - - #define NATIVE_INT64 0 - #define IEEE754_64FLOAT 1 - - #elif BEOS - #define MAC 0 - #define PPC 0 - #define WINDOWS 0 - #define PC 0 - #define SGI 0 - #define SUN 0 - #define LINUX 0 - - #define NATIVE_INT64 0 - #define IEEE754_64FLOAT 1 - - #ifndef DEBUG - #define DEBUG 0 - #if DEBUG - void DEBUGGERMESSAGE(char *string); - #else - #define DEBUGGERMESSAGE(a) - #endif - #endif - - #elif SGI - #define MAC 0 - #define PPC 0 - #define WINDOWS 0 - #define PC 0 - #define SUN 0 - #define LINUX 0 - #define BEOS 0 - - #define NATIVE_INT64 0 - #define IEEE754_64FLOAT 1 - - #ifndef DEBUG - #define DEBUG 0 - #if DEBUG - void DEBUGGERMESSAGE(char *string); - #else - #define DEBUGGERMESSAGE(a) - #endif - #endif - - #else // MAC - - #define MAC 1 - #define PPC 1 - #define WINDOWS 0 - #define PC 0 - #define SGI 0 - #define SUN 0 - #define LINUX 0 - #define BEOS 0 - - #define NATIVE_INT64 0 - #define IEEE754_64FLOAT 1 - - #ifndef DEBUG - #define DEBUG 0 - #if DEBUG - void DEBUGGERMESSAGE(char *string); - #else - #define DEBUGGERMESSAGE(a) - #endif - #endif - #endif - -#endif diff --git a/vendor/rtaudio/include/dsound.h b/vendor/rtaudio/include/dsound.h deleted file mode 100644 index cb19cca82..000000000 --- a/vendor/rtaudio/include/dsound.h +++ /dev/null @@ -1,2369 +0,0 @@ -/*==========================================================================; - * - * Copyright (c) Microsoft Corporation. All rights reserved. - * - * File: dsound.h - * Content: DirectSound include file - * - **************************************************************************/ - -#define COM_NO_WINDOWS_H -#include -#include - -#ifndef DIRECTSOUND_VERSION -#define DIRECTSOUND_VERSION 0x0900 /* Version 9.0 */ -#endif - -#ifdef __cplusplus -extern "C" { -#endif // __cplusplus - -#ifndef __DSOUND_INCLUDED__ -#define __DSOUND_INCLUDED__ - -/* Type definitions shared with Direct3D */ - -#ifndef DX_SHARED_DEFINES - -typedef float D3DVALUE, *LPD3DVALUE; - -#ifndef D3DCOLOR_DEFINED -typedef DWORD D3DCOLOR; -#define D3DCOLOR_DEFINED -#endif - -#ifndef LPD3DCOLOR_DEFINED -typedef DWORD *LPD3DCOLOR; -#define LPD3DCOLOR_DEFINED -#endif - -#ifndef D3DVECTOR_DEFINED -typedef struct _D3DVECTOR { - float x; - float y; - float z; -} D3DVECTOR; -#define D3DVECTOR_DEFINED -#endif - -#ifndef LPD3DVECTOR_DEFINED -typedef D3DVECTOR *LPD3DVECTOR; -#define LPD3DVECTOR_DEFINED -#endif - -#define DX_SHARED_DEFINES -#endif // DX_SHARED_DEFINES - -#define _FACDS 0x878 /* DirectSound's facility code */ -#define MAKE_DSHRESULT(code) MAKE_HRESULT(1, _FACDS, code) - -// DirectSound Component GUID {47D4D946-62E8-11CF-93BC-444553540000} -DEFINE_GUID(CLSID_DirectSound, 0x47d4d946, 0x62e8, 0x11cf, 0x93, 0xbc, 0x44, 0x45, 0x53, 0x54, 0x0, 0x0); - -// DirectSound 8.0 Component GUID {3901CC3F-84B5-4FA4-BA35-AA8172B8A09B} -DEFINE_GUID(CLSID_DirectSound8, 0x3901cc3f, 0x84b5, 0x4fa4, 0xba, 0x35, 0xaa, 0x81, 0x72, 0xb8, 0xa0, 0x9b); - -// DirectSound Capture Component GUID {B0210780-89CD-11D0-AF08-00A0C925CD16} -DEFINE_GUID(CLSID_DirectSoundCapture, 0xb0210780, 0x89cd, 0x11d0, 0xaf, 0x8, 0x0, 0xa0, 0xc9, 0x25, 0xcd, 0x16); - -// DirectSound 8.0 Capture Component GUID {E4BCAC13-7F99-4908-9A8E-74E3BF24B6E1} -DEFINE_GUID(CLSID_DirectSoundCapture8, 0xe4bcac13, 0x7f99, 0x4908, 0x9a, 0x8e, 0x74, 0xe3, 0xbf, 0x24, 0xb6, 0xe1); - -// DirectSound Full Duplex Component GUID {FEA4300C-7959-4147-B26A-2377B9E7A91D} -DEFINE_GUID(CLSID_DirectSoundFullDuplex, 0xfea4300c, 0x7959, 0x4147, 0xb2, 0x6a, 0x23, 0x77, 0xb9, 0xe7, 0xa9, 0x1d); - - -// DirectSound default playback device GUID {DEF00000-9C6D-47ED-AAF1-4DDA8F2B5C03} -DEFINE_GUID(DSDEVID_DefaultPlayback, 0xdef00000, 0x9c6d, 0x47ed, 0xaa, 0xf1, 0x4d, 0xda, 0x8f, 0x2b, 0x5c, 0x03); - -// DirectSound default capture device GUID {DEF00001-9C6D-47ED-AAF1-4DDA8F2B5C03} -DEFINE_GUID(DSDEVID_DefaultCapture, 0xdef00001, 0x9c6d, 0x47ed, 0xaa, 0xf1, 0x4d, 0xda, 0x8f, 0x2b, 0x5c, 0x03); - -// DirectSound default device for voice playback {DEF00002-9C6D-47ED-AAF1-4DDA8F2B5C03} -DEFINE_GUID(DSDEVID_DefaultVoicePlayback, 0xdef00002, 0x9c6d, 0x47ed, 0xaa, 0xf1, 0x4d, 0xda, 0x8f, 0x2b, 0x5c, 0x03); - -// DirectSound default device for voice capture {DEF00003-9C6D-47ED-AAF1-4DDA8F2B5C03} -DEFINE_GUID(DSDEVID_DefaultVoiceCapture, 0xdef00003, 0x9c6d, 0x47ed, 0xaa, 0xf1, 0x4d, 0xda, 0x8f, 0x2b, 0x5c, 0x03); - - -// -// Forward declarations for interfaces. -// 'struct' not 'class' per the way DECLARE_INTERFACE_ is defined -// - -#ifdef __cplusplus -struct IDirectSound; -struct IDirectSoundBuffer; -struct IDirectSound3DListener; -struct IDirectSound3DBuffer; -struct IDirectSoundCapture; -struct IDirectSoundCaptureBuffer; -struct IDirectSoundNotify; -#endif // __cplusplus - - -// -// DirectSound 8.0 interfaces. -// - -#if DIRECTSOUND_VERSION >= 0x0800 - -#ifdef __cplusplus -struct IDirectSound8; -struct IDirectSoundBuffer8; -struct IDirectSoundCaptureBuffer8; -struct IDirectSoundFXGargle; -struct IDirectSoundFXChorus; -struct IDirectSoundFXFlanger; -struct IDirectSoundFXEcho; -struct IDirectSoundFXDistortion; -struct IDirectSoundFXCompressor; -struct IDirectSoundFXParamEq; -struct IDirectSoundFXWavesReverb; -struct IDirectSoundFXI3DL2Reverb; -struct IDirectSoundCaptureFXAec; -struct IDirectSoundCaptureFXNoiseSuppress; -struct IDirectSoundFullDuplex; -#endif // __cplusplus - -// IDirectSound8, IDirectSoundBuffer8 and IDirectSoundCaptureBuffer8 are the -// only DirectSound 7.0 interfaces with changed functionality in version 8.0. -// The other level 8 interfaces as equivalent to their level 7 counterparts: - -#define IDirectSoundCapture8 IDirectSoundCapture -#define IDirectSound3DListener8 IDirectSound3DListener -#define IDirectSound3DBuffer8 IDirectSound3DBuffer -#define IDirectSoundNotify8 IDirectSoundNotify -#define IDirectSoundFXGargle8 IDirectSoundFXGargle -#define IDirectSoundFXChorus8 IDirectSoundFXChorus -#define IDirectSoundFXFlanger8 IDirectSoundFXFlanger -#define IDirectSoundFXEcho8 IDirectSoundFXEcho -#define IDirectSoundFXDistortion8 IDirectSoundFXDistortion -#define IDirectSoundFXCompressor8 IDirectSoundFXCompressor -#define IDirectSoundFXParamEq8 IDirectSoundFXParamEq -#define IDirectSoundFXWavesReverb8 IDirectSoundFXWavesReverb -#define IDirectSoundFXI3DL2Reverb8 IDirectSoundFXI3DL2Reverb -#define IDirectSoundCaptureFXAec8 IDirectSoundCaptureFXAec -#define IDirectSoundCaptureFXNoiseSuppress8 IDirectSoundCaptureFXNoiseSuppress -#define IDirectSoundFullDuplex8 IDirectSoundFullDuplex - -#endif // DIRECTSOUND_VERSION >= 0x0800 - -typedef struct IDirectSound *LPDIRECTSOUND; -typedef struct IDirectSoundBuffer *LPDIRECTSOUNDBUFFER; -typedef struct IDirectSound3DListener *LPDIRECTSOUND3DLISTENER; -typedef struct IDirectSound3DBuffer *LPDIRECTSOUND3DBUFFER; -typedef struct IDirectSoundCapture *LPDIRECTSOUNDCAPTURE; -typedef struct IDirectSoundCaptureBuffer *LPDIRECTSOUNDCAPTUREBUFFER; -typedef struct IDirectSoundNotify *LPDIRECTSOUNDNOTIFY; - - -#if DIRECTSOUND_VERSION >= 0x0800 - -typedef struct IDirectSoundFXGargle *LPDIRECTSOUNDFXGARGLE; -typedef struct IDirectSoundFXChorus *LPDIRECTSOUNDFXCHORUS; -typedef struct IDirectSoundFXFlanger *LPDIRECTSOUNDFXFLANGER; -typedef struct IDirectSoundFXEcho *LPDIRECTSOUNDFXECHO; -typedef struct IDirectSoundFXDistortion *LPDIRECTSOUNDFXDISTORTION; -typedef struct IDirectSoundFXCompressor *LPDIRECTSOUNDFXCOMPRESSOR; -typedef struct IDirectSoundFXParamEq *LPDIRECTSOUNDFXPARAMEQ; -typedef struct IDirectSoundFXWavesReverb *LPDIRECTSOUNDFXWAVESREVERB; -typedef struct IDirectSoundFXI3DL2Reverb *LPDIRECTSOUNDFXI3DL2REVERB; -typedef struct IDirectSoundCaptureFXAec *LPDIRECTSOUNDCAPTUREFXAEC; -typedef struct IDirectSoundCaptureFXNoiseSuppress *LPDIRECTSOUNDCAPTUREFXNOISESUPPRESS; -typedef struct IDirectSoundFullDuplex *LPDIRECTSOUNDFULLDUPLEX; - -typedef struct IDirectSound8 *LPDIRECTSOUND8; -typedef struct IDirectSoundBuffer8 *LPDIRECTSOUNDBUFFER8; -typedef struct IDirectSound3DListener8 *LPDIRECTSOUND3DLISTENER8; -typedef struct IDirectSound3DBuffer8 *LPDIRECTSOUND3DBUFFER8; -typedef struct IDirectSoundCapture8 *LPDIRECTSOUNDCAPTURE8; -typedef struct IDirectSoundCaptureBuffer8 *LPDIRECTSOUNDCAPTUREBUFFER8; -typedef struct IDirectSoundNotify8 *LPDIRECTSOUNDNOTIFY8; -typedef struct IDirectSoundFXGargle8 *LPDIRECTSOUNDFXGARGLE8; -typedef struct IDirectSoundFXChorus8 *LPDIRECTSOUNDFXCHORUS8; -typedef struct IDirectSoundFXFlanger8 *LPDIRECTSOUNDFXFLANGER8; -typedef struct IDirectSoundFXEcho8 *LPDIRECTSOUNDFXECHO8; -typedef struct IDirectSoundFXDistortion8 *LPDIRECTSOUNDFXDISTORTION8; -typedef struct IDirectSoundFXCompressor8 *LPDIRECTSOUNDFXCOMPRESSOR8; -typedef struct IDirectSoundFXParamEq8 *LPDIRECTSOUNDFXPARAMEQ8; -typedef struct IDirectSoundFXWavesReverb8 *LPDIRECTSOUNDFXWAVESREVERB8; -typedef struct IDirectSoundFXI3DL2Reverb8 *LPDIRECTSOUNDFXI3DL2REVERB8; -typedef struct IDirectSoundCaptureFXAec8 *LPDIRECTSOUNDCAPTUREFXAEC8; -typedef struct IDirectSoundCaptureFXNoiseSuppress8 *LPDIRECTSOUNDCAPTUREFXNOISESUPPRESS8; -typedef struct IDirectSoundFullDuplex8 *LPDIRECTSOUNDFULLDUPLEX8; - -#endif // DIRECTSOUND_VERSION >= 0x0800 - -// -// IID definitions for the unchanged DirectSound 8.0 interfaces -// - -#if DIRECTSOUND_VERSION >= 0x0800 - -#define IID_IDirectSoundCapture8 IID_IDirectSoundCapture -#define IID_IDirectSound3DListener8 IID_IDirectSound3DListener -#define IID_IDirectSound3DBuffer8 IID_IDirectSound3DBuffer -#define IID_IDirectSoundNotify8 IID_IDirectSoundNotify -#define IID_IDirectSoundFXGargle8 IID_IDirectSoundFXGargle -#define IID_IDirectSoundFXChorus8 IID_IDirectSoundFXChorus -#define IID_IDirectSoundFXFlanger8 IID_IDirectSoundFXFlanger -#define IID_IDirectSoundFXEcho8 IID_IDirectSoundFXEcho -#define IID_IDirectSoundFXDistortion8 IID_IDirectSoundFXDistortion -#define IID_IDirectSoundFXCompressor8 IID_IDirectSoundFXCompressor -#define IID_IDirectSoundFXParamEq8 IID_IDirectSoundFXParamEq -#define IID_IDirectSoundFXWavesReverb8 IID_IDirectSoundFXWavesReverb -#define IID_IDirectSoundFXI3DL2Reverb8 IID_IDirectSoundFXI3DL2Reverb -#define IID_IDirectSoundCaptureFXAec8 IID_IDirectSoundCaptureFXAec -#define IID_IDirectSoundCaptureFXNoiseSuppress8 IID_IDirectSoundCaptureFXNoiseSuppress -#define IID_IDirectSoundFullDuplex8 IID_IDirectSoundFullDuplex - -#endif // DIRECTSOUND_VERSION >= 0x0800 - -// -// Compatibility typedefs -// - -#ifndef _LPCWAVEFORMATEX_DEFINED -#define _LPCWAVEFORMATEX_DEFINED -typedef const WAVEFORMATEX *LPCWAVEFORMATEX; -#endif // _LPCWAVEFORMATEX_DEFINED - -#ifndef __LPCGUID_DEFINED__ -#define __LPCGUID_DEFINED__ -typedef const GUID *LPCGUID; -#endif // __LPCGUID_DEFINED__ - -typedef LPDIRECTSOUND *LPLPDIRECTSOUND; -typedef LPDIRECTSOUNDBUFFER *LPLPDIRECTSOUNDBUFFER; -typedef LPDIRECTSOUND3DLISTENER *LPLPDIRECTSOUND3DLISTENER; -typedef LPDIRECTSOUND3DBUFFER *LPLPDIRECTSOUND3DBUFFER; -typedef LPDIRECTSOUNDCAPTURE *LPLPDIRECTSOUNDCAPTURE; -typedef LPDIRECTSOUNDCAPTUREBUFFER *LPLPDIRECTSOUNDCAPTUREBUFFER; -typedef LPDIRECTSOUNDNOTIFY *LPLPDIRECTSOUNDNOTIFY; - -#if DIRECTSOUND_VERSION >= 0x0800 -typedef LPDIRECTSOUND8 *LPLPDIRECTSOUND8; -typedef LPDIRECTSOUNDBUFFER8 *LPLPDIRECTSOUNDBUFFER8; -typedef LPDIRECTSOUNDCAPTURE8 *LPLPDIRECTSOUNDCAPTURE8; -typedef LPDIRECTSOUNDCAPTUREBUFFER8 *LPLPDIRECTSOUNDCAPTUREBUFFER8; -#endif // DIRECTSOUND_VERSION >= 0x0800 - -// -// Structures -// - -typedef struct _DSCAPS -{ - DWORD dwSize; - DWORD dwFlags; - DWORD dwMinSecondarySampleRate; - DWORD dwMaxSecondarySampleRate; - DWORD dwPrimaryBuffers; - DWORD dwMaxHwMixingAllBuffers; - DWORD dwMaxHwMixingStaticBuffers; - DWORD dwMaxHwMixingStreamingBuffers; - DWORD dwFreeHwMixingAllBuffers; - DWORD dwFreeHwMixingStaticBuffers; - DWORD dwFreeHwMixingStreamingBuffers; - DWORD dwMaxHw3DAllBuffers; - DWORD dwMaxHw3DStaticBuffers; - DWORD dwMaxHw3DStreamingBuffers; - DWORD dwFreeHw3DAllBuffers; - DWORD dwFreeHw3DStaticBuffers; - DWORD dwFreeHw3DStreamingBuffers; - DWORD dwTotalHwMemBytes; - DWORD dwFreeHwMemBytes; - DWORD dwMaxContigFreeHwMemBytes; - DWORD dwUnlockTransferRateHwBuffers; - DWORD dwPlayCpuOverheadSwBuffers; - DWORD dwReserved1; - DWORD dwReserved2; -} DSCAPS, *LPDSCAPS; - -typedef const DSCAPS *LPCDSCAPS; - -typedef struct _DSBCAPS -{ - DWORD dwSize; - DWORD dwFlags; - DWORD dwBufferBytes; - DWORD dwUnlockTransferRate; - DWORD dwPlayCpuOverhead; -} DSBCAPS, *LPDSBCAPS; - -typedef const DSBCAPS *LPCDSBCAPS; - -#if DIRECTSOUND_VERSION >= 0x0800 - - typedef struct _DSEFFECTDESC - { - DWORD dwSize; - DWORD dwFlags; - GUID guidDSFXClass; - DWORD_PTR dwReserved1; - DWORD_PTR dwReserved2; - } DSEFFECTDESC, *LPDSEFFECTDESC; - typedef const DSEFFECTDESC *LPCDSEFFECTDESC; - - #define DSFX_LOCHARDWARE 0x00000001 - #define DSFX_LOCSOFTWARE 0x00000002 - - enum - { - DSFXR_PRESENT, // 0 - DSFXR_LOCHARDWARE, // 1 - DSFXR_LOCSOFTWARE, // 2 - DSFXR_UNALLOCATED, // 3 - DSFXR_FAILED, // 4 - DSFXR_UNKNOWN, // 5 - DSFXR_SENDLOOP // 6 - }; - - typedef struct _DSCEFFECTDESC - { - DWORD dwSize; - DWORD dwFlags; - GUID guidDSCFXClass; - GUID guidDSCFXInstance; - DWORD dwReserved1; - DWORD dwReserved2; - } DSCEFFECTDESC, *LPDSCEFFECTDESC; - typedef const DSCEFFECTDESC *LPCDSCEFFECTDESC; - - #define DSCFX_LOCHARDWARE 0x00000001 - #define DSCFX_LOCSOFTWARE 0x00000002 - - #define DSCFXR_LOCHARDWARE 0x00000010 - #define DSCFXR_LOCSOFTWARE 0x00000020 - -#endif // DIRECTSOUND_VERSION >= 0x0800 - -typedef struct _DSBUFFERDESC -{ - DWORD dwSize; - DWORD dwFlags; - DWORD dwBufferBytes; - DWORD dwReserved; - LPWAVEFORMATEX lpwfxFormat; -#if DIRECTSOUND_VERSION >= 0x0700 - GUID guid3DAlgorithm; -#endif -} DSBUFFERDESC, *LPDSBUFFERDESC; - -typedef const DSBUFFERDESC *LPCDSBUFFERDESC; - -// Older version of this structure: - -typedef struct _DSBUFFERDESC1 -{ - DWORD dwSize; - DWORD dwFlags; - DWORD dwBufferBytes; - DWORD dwReserved; - LPWAVEFORMATEX lpwfxFormat; -} DSBUFFERDESC1, *LPDSBUFFERDESC1; - -typedef const DSBUFFERDESC1 *LPCDSBUFFERDESC1; - -typedef struct _DS3DBUFFER -{ - DWORD dwSize; - D3DVECTOR vPosition; - D3DVECTOR vVelocity; - DWORD dwInsideConeAngle; - DWORD dwOutsideConeAngle; - D3DVECTOR vConeOrientation; - LONG lConeOutsideVolume; - D3DVALUE flMinDistance; - D3DVALUE flMaxDistance; - DWORD dwMode; -} DS3DBUFFER, *LPDS3DBUFFER; - -typedef const DS3DBUFFER *LPCDS3DBUFFER; - -typedef struct _DS3DLISTENER -{ - DWORD dwSize; - D3DVECTOR vPosition; - D3DVECTOR vVelocity; - D3DVECTOR vOrientFront; - D3DVECTOR vOrientTop; - D3DVALUE flDistanceFactor; - D3DVALUE flRolloffFactor; - D3DVALUE flDopplerFactor; -} DS3DLISTENER, *LPDS3DLISTENER; - -typedef const DS3DLISTENER *LPCDS3DLISTENER; - -typedef struct _DSCCAPS -{ - DWORD dwSize; - DWORD dwFlags; - DWORD dwFormats; - DWORD dwChannels; -} DSCCAPS, *LPDSCCAPS; - -typedef const DSCCAPS *LPCDSCCAPS; - -typedef struct _DSCBUFFERDESC1 -{ - DWORD dwSize; - DWORD dwFlags; - DWORD dwBufferBytes; - DWORD dwReserved; - LPWAVEFORMATEX lpwfxFormat; -} DSCBUFFERDESC1, *LPDSCBUFFERDESC1; - -typedef struct _DSCBUFFERDESC -{ - DWORD dwSize; - DWORD dwFlags; - DWORD dwBufferBytes; - DWORD dwReserved; - LPWAVEFORMATEX lpwfxFormat; -#if DIRECTSOUND_VERSION >= 0x0800 - DWORD dwFXCount; - LPDSCEFFECTDESC lpDSCFXDesc; -#endif -} DSCBUFFERDESC, *LPDSCBUFFERDESC; - -typedef const DSCBUFFERDESC *LPCDSCBUFFERDESC; - -typedef struct _DSCBCAPS -{ - DWORD dwSize; - DWORD dwFlags; - DWORD dwBufferBytes; - DWORD dwReserved; -} DSCBCAPS, *LPDSCBCAPS; - -typedef const DSCBCAPS *LPCDSCBCAPS; - -typedef struct _DSBPOSITIONNOTIFY -{ - DWORD dwOffset; - HANDLE hEventNotify; -} DSBPOSITIONNOTIFY, *LPDSBPOSITIONNOTIFY; - -typedef const DSBPOSITIONNOTIFY *LPCDSBPOSITIONNOTIFY; - -// -// DirectSound API -// - -typedef BOOL (CALLBACK *LPDSENUMCALLBACKA)(LPGUID, LPCSTR, LPCSTR, LPVOID); -typedef BOOL (CALLBACK *LPDSENUMCALLBACKW)(LPGUID, LPCWSTR, LPCWSTR, LPVOID); - -extern HRESULT WINAPI DirectSoundCreate(LPCGUID pcGuidDevice, LPDIRECTSOUND *ppDS, LPUNKNOWN pUnkOuter); -extern HRESULT WINAPI DirectSoundEnumerateA(LPDSENUMCALLBACKA pDSEnumCallback, LPVOID pContext); -extern HRESULT WINAPI DirectSoundEnumerateW(LPDSENUMCALLBACKW pDSEnumCallback, LPVOID pContext); - -extern HRESULT WINAPI DirectSoundCaptureCreate(LPCGUID pcGuidDevice, LPDIRECTSOUNDCAPTURE *ppDSC, LPUNKNOWN pUnkOuter); -extern HRESULT WINAPI DirectSoundCaptureEnumerateA(LPDSENUMCALLBACKA pDSEnumCallback, LPVOID pContext); -extern HRESULT WINAPI DirectSoundCaptureEnumerateW(LPDSENUMCALLBACKW pDSEnumCallback, LPVOID pContext); - -#if DIRECTSOUND_VERSION >= 0x0800 -extern HRESULT WINAPI DirectSoundCreate8(LPCGUID pcGuidDevice, LPDIRECTSOUND8 *ppDS8, LPUNKNOWN pUnkOuter); -extern HRESULT WINAPI DirectSoundCaptureCreate8(LPCGUID pcGuidDevice, LPDIRECTSOUNDCAPTURE8 *ppDSC8, LPUNKNOWN pUnkOuter); -extern HRESULT WINAPI DirectSoundFullDuplexCreate(LPCGUID pcGuidCaptureDevice, LPCGUID pcGuidRenderDevice, - LPCDSCBUFFERDESC pcDSCBufferDesc, LPCDSBUFFERDESC pcDSBufferDesc, HWND hWnd, - DWORD dwLevel, LPDIRECTSOUNDFULLDUPLEX* ppDSFD, LPDIRECTSOUNDCAPTUREBUFFER8 *ppDSCBuffer8, - LPDIRECTSOUNDBUFFER8 *ppDSBuffer8, LPUNKNOWN pUnkOuter); -#define DirectSoundFullDuplexCreate8 DirectSoundFullDuplexCreate - -extern HRESULT WINAPI GetDeviceID(LPCGUID pGuidSrc, LPGUID pGuidDest); -#endif // DIRECTSOUND_VERSION >= 0x0800 - -#ifdef UNICODE -#define LPDSENUMCALLBACK LPDSENUMCALLBACKW -#define DirectSoundEnumerate DirectSoundEnumerateW -#define DirectSoundCaptureEnumerate DirectSoundCaptureEnumerateW -#else // UNICODE -#define LPDSENUMCALLBACK LPDSENUMCALLBACKA -#define DirectSoundEnumerate DirectSoundEnumerateA -#define DirectSoundCaptureEnumerate DirectSoundCaptureEnumerateA -#endif // UNICODE - -// -// IUnknown -// - -#if !defined(__cplusplus) || defined(CINTERFACE) -#ifndef IUnknown_QueryInterface -#define IUnknown_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) -#endif // IUnknown_QueryInterface -#ifndef IUnknown_AddRef -#define IUnknown_AddRef(p) (p)->lpVtbl->AddRef(p) -#endif // IUnknown_AddRef -#ifndef IUnknown_Release -#define IUnknown_Release(p) (p)->lpVtbl->Release(p) -#endif // IUnknown_Release -#else // !defined(__cplusplus) || defined(CINTERFACE) -#ifndef IUnknown_QueryInterface -#define IUnknown_QueryInterface(p,a,b) (p)->QueryInterface(a,b) -#endif // IUnknown_QueryInterface -#ifndef IUnknown_AddRef -#define IUnknown_AddRef(p) (p)->AddRef() -#endif // IUnknown_AddRef -#ifndef IUnknown_Release -#define IUnknown_Release(p) (p)->Release() -#endif // IUnknown_Release -#endif // !defined(__cplusplus) || defined(CINTERFACE) - -#ifndef __IReferenceClock_INTERFACE_DEFINED__ -#define __IReferenceClock_INTERFACE_DEFINED__ - -typedef LONGLONG REFERENCE_TIME; -typedef REFERENCE_TIME *LPREFERENCE_TIME; - -DEFINE_GUID(IID_IReferenceClock, 0x56a86897, 0x0ad4, 0x11ce, 0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70); - -#undef INTERFACE -#define INTERFACE IReferenceClock - -DECLARE_INTERFACE_(IReferenceClock, IUnknown) -{ - // IUnknown methods - STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; - STDMETHOD_(ULONG,AddRef) (THIS) PURE; - STDMETHOD_(ULONG,Release) (THIS) PURE; - - // IReferenceClock methods - STDMETHOD(GetTime) (THIS_ REFERENCE_TIME *pTime) PURE; - STDMETHOD(AdviseTime) (THIS_ REFERENCE_TIME rtBaseTime, REFERENCE_TIME rtStreamTime, - HANDLE hEvent, LPDWORD pdwAdviseCookie) PURE; - STDMETHOD(AdvisePeriodic) (THIS_ REFERENCE_TIME rtStartTime, REFERENCE_TIME rtPeriodTime, - HANDLE hSemaphore, LPDWORD pdwAdviseCookie) PURE; - STDMETHOD(Unadvise) (THIS_ DWORD dwAdviseCookie) PURE; -}; - -#endif // __IReferenceClock_INTERFACE_DEFINED__ - -#ifndef IReferenceClock_QueryInterface - -#define IReferenceClock_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) -#define IReferenceClock_AddRef(p) IUnknown_AddRef(p) -#define IReferenceClock_Release(p) IUnknown_Release(p) - -#if !defined(__cplusplus) || defined(CINTERFACE) -#define IReferenceClock_GetTime(p,a) (p)->lpVtbl->GetTime(p,a) -#define IReferenceClock_AdviseTime(p,a,b,c,d) (p)->lpVtbl->AdviseTime(p,a,b,c,d) -#define IReferenceClock_AdvisePeriodic(p,a,b,c,d) (p)->lpVtbl->AdvisePeriodic(p,a,b,c,d) -#define IReferenceClock_Unadvise(p,a) (p)->lpVtbl->Unadvise(p,a) -#else // !defined(__cplusplus) || defined(CINTERFACE) -#define IReferenceClock_GetTime(p,a) (p)->GetTime(a) -#define IReferenceClock_AdviseTime(p,a,b,c,d) (p)->AdviseTime(a,b,c,d) -#define IReferenceClock_AdvisePeriodic(p,a,b,c,d) (p)->AdvisePeriodic(a,b,c,d) -#define IReferenceClock_Unadvise(p,a) (p)->Unadvise(a) -#endif // !defined(__cplusplus) || defined(CINTERFACE) - -#endif // IReferenceClock_QueryInterface - -// -// IDirectSound -// - -DEFINE_GUID(IID_IDirectSound, 0x279AFA83, 0x4981, 0x11CE, 0xA5, 0x21, 0x00, 0x20, 0xAF, 0x0B, 0xE5, 0x60); - -#undef INTERFACE -#define INTERFACE IDirectSound - -DECLARE_INTERFACE_(IDirectSound, IUnknown) -{ - // IUnknown methods - STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; - STDMETHOD_(ULONG,AddRef) (THIS) PURE; - STDMETHOD_(ULONG,Release) (THIS) PURE; - - // IDirectSound methods - STDMETHOD(CreateSoundBuffer) (THIS_ LPCDSBUFFERDESC pcDSBufferDesc, LPDIRECTSOUNDBUFFER *ppDSBuffer, LPUNKNOWN pUnkOuter) PURE; - STDMETHOD(GetCaps) (THIS_ LPDSCAPS pDSCaps) PURE; - STDMETHOD(DuplicateSoundBuffer) (THIS_ LPDIRECTSOUNDBUFFER pDSBufferOriginal, LPDIRECTSOUNDBUFFER *ppDSBufferDuplicate) PURE; - STDMETHOD(SetCooperativeLevel) (THIS_ HWND hwnd, DWORD dwLevel) PURE; - STDMETHOD(Compact) (THIS) PURE; - STDMETHOD(GetSpeakerConfig) (THIS_ LPDWORD pdwSpeakerConfig) PURE; - STDMETHOD(SetSpeakerConfig) (THIS_ DWORD dwSpeakerConfig) PURE; - STDMETHOD(Initialize) (THIS_ LPCGUID pcGuidDevice) PURE; -}; - -#define IDirectSound_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) -#define IDirectSound_AddRef(p) IUnknown_AddRef(p) -#define IDirectSound_Release(p) IUnknown_Release(p) - -#if !defined(__cplusplus) || defined(CINTERFACE) -#define IDirectSound_CreateSoundBuffer(p,a,b,c) (p)->lpVtbl->CreateSoundBuffer(p,a,b,c) -#define IDirectSound_GetCaps(p,a) (p)->lpVtbl->GetCaps(p,a) -#define IDirectSound_DuplicateSoundBuffer(p,a,b) (p)->lpVtbl->DuplicateSoundBuffer(p,a,b) -#define IDirectSound_SetCooperativeLevel(p,a,b) (p)->lpVtbl->SetCooperativeLevel(p,a,b) -#define IDirectSound_Compact(p) (p)->lpVtbl->Compact(p) -#define IDirectSound_GetSpeakerConfig(p,a) (p)->lpVtbl->GetSpeakerConfig(p,a) -#define IDirectSound_SetSpeakerConfig(p,b) (p)->lpVtbl->SetSpeakerConfig(p,b) -#define IDirectSound_Initialize(p,a) (p)->lpVtbl->Initialize(p,a) -#else // !defined(__cplusplus) || defined(CINTERFACE) -#define IDirectSound_CreateSoundBuffer(p,a,b,c) (p)->CreateSoundBuffer(a,b,c) -#define IDirectSound_GetCaps(p,a) (p)->GetCaps(a) -#define IDirectSound_DuplicateSoundBuffer(p,a,b) (p)->DuplicateSoundBuffer(a,b) -#define IDirectSound_SetCooperativeLevel(p,a,b) (p)->SetCooperativeLevel(a,b) -#define IDirectSound_Compact(p) (p)->Compact() -#define IDirectSound_GetSpeakerConfig(p,a) (p)->GetSpeakerConfig(a) -#define IDirectSound_SetSpeakerConfig(p,b) (p)->SetSpeakerConfig(b) -#define IDirectSound_Initialize(p,a) (p)->Initialize(a) -#endif // !defined(__cplusplus) || defined(CINTERFACE) - -#if DIRECTSOUND_VERSION >= 0x0800 - -// -// IDirectSound8 -// - -DEFINE_GUID(IID_IDirectSound8, 0xC50A7E93, 0xF395, 0x4834, 0x9E, 0xF6, 0x7F, 0xA9, 0x9D, 0xE5, 0x09, 0x66); - -#undef INTERFACE -#define INTERFACE IDirectSound8 - -DECLARE_INTERFACE_(IDirectSound8, IDirectSound) -{ - // IUnknown methods - STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; - STDMETHOD_(ULONG,AddRef) (THIS) PURE; - STDMETHOD_(ULONG,Release) (THIS) PURE; - - // IDirectSound methods - STDMETHOD(CreateSoundBuffer) (THIS_ LPCDSBUFFERDESC pcDSBufferDesc, LPDIRECTSOUNDBUFFER *ppDSBuffer, LPUNKNOWN pUnkOuter) PURE; - STDMETHOD(GetCaps) (THIS_ LPDSCAPS pDSCaps) PURE; - STDMETHOD(DuplicateSoundBuffer) (THIS_ LPDIRECTSOUNDBUFFER pDSBufferOriginal, LPDIRECTSOUNDBUFFER *ppDSBufferDuplicate) PURE; - STDMETHOD(SetCooperativeLevel) (THIS_ HWND hwnd, DWORD dwLevel) PURE; - STDMETHOD(Compact) (THIS) PURE; - STDMETHOD(GetSpeakerConfig) (THIS_ LPDWORD pdwSpeakerConfig) PURE; - STDMETHOD(SetSpeakerConfig) (THIS_ DWORD dwSpeakerConfig) PURE; - STDMETHOD(Initialize) (THIS_ LPCGUID pcGuidDevice) PURE; - - // IDirectSound8 methods - STDMETHOD(VerifyCertification) (THIS_ LPDWORD pdwCertified) PURE; -}; - -#define IDirectSound8_QueryInterface(p,a,b) IDirectSound_QueryInterface(p,a,b) -#define IDirectSound8_AddRef(p) IDirectSound_AddRef(p) -#define IDirectSound8_Release(p) IDirectSound_Release(p) -#define IDirectSound8_CreateSoundBuffer(p,a,b,c) IDirectSound_CreateSoundBuffer(p,a,b,c) -#define IDirectSound8_GetCaps(p,a) IDirectSound_GetCaps(p,a) -#define IDirectSound8_DuplicateSoundBuffer(p,a,b) IDirectSound_DuplicateSoundBuffer(p,a,b) -#define IDirectSound8_SetCooperativeLevel(p,a,b) IDirectSound_SetCooperativeLevel(p,a,b) -#define IDirectSound8_Compact(p) IDirectSound_Compact(p) -#define IDirectSound8_GetSpeakerConfig(p,a) IDirectSound_GetSpeakerConfig(p,a) -#define IDirectSound8_SetSpeakerConfig(p,a) IDirectSound_SetSpeakerConfig(p,a) -#define IDirectSound8_Initialize(p,a) IDirectSound_Initialize(p,a) - -#if !defined(__cplusplus) || defined(CINTERFACE) -#define IDirectSound8_VerifyCertification(p,a) (p)->lpVtbl->VerifyCertification(p,a) -#else // !defined(__cplusplus) || defined(CINTERFACE) -#define IDirectSound8_VerifyCertification(p,a) (p)->VerifyCertification(a) -#endif // !defined(__cplusplus) || defined(CINTERFACE) - -#endif // DIRECTSOUND_VERSION >= 0x0800 - -// -// IDirectSoundBuffer -// - -DEFINE_GUID(IID_IDirectSoundBuffer, 0x279AFA85, 0x4981, 0x11CE, 0xA5, 0x21, 0x00, 0x20, 0xAF, 0x0B, 0xE5, 0x60); - -#undef INTERFACE -#define INTERFACE IDirectSoundBuffer - -DECLARE_INTERFACE_(IDirectSoundBuffer, IUnknown) -{ - // IUnknown methods - STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; - STDMETHOD_(ULONG,AddRef) (THIS) PURE; - STDMETHOD_(ULONG,Release) (THIS) PURE; - - // IDirectSoundBuffer methods - STDMETHOD(GetCaps) (THIS_ LPDSBCAPS pDSBufferCaps) PURE; - STDMETHOD(GetCurrentPosition) (THIS_ LPDWORD pdwCurrentPlayCursor, LPDWORD pdwCurrentWriteCursor) PURE; - STDMETHOD(GetFormat) (THIS_ LPWAVEFORMATEX pwfxFormat, DWORD dwSizeAllocated, LPDWORD pdwSizeWritten) PURE; - STDMETHOD(GetVolume) (THIS_ LPLONG plVolume) PURE; - STDMETHOD(GetPan) (THIS_ LPLONG plPan) PURE; - STDMETHOD(GetFrequency) (THIS_ LPDWORD pdwFrequency) PURE; - STDMETHOD(GetStatus) (THIS_ LPDWORD pdwStatus) PURE; - STDMETHOD(Initialize) (THIS_ LPDIRECTSOUND pDirectSound, LPCDSBUFFERDESC pcDSBufferDesc) PURE; - STDMETHOD(Lock) (THIS_ DWORD dwOffset, DWORD dwBytes, LPVOID *ppvAudioPtr1, LPDWORD pdwAudioBytes1, - LPVOID *ppvAudioPtr2, LPDWORD pdwAudioBytes2, DWORD dwFlags) PURE; - STDMETHOD(Play) (THIS_ DWORD dwReserved1, DWORD dwPriority, DWORD dwFlags) PURE; - STDMETHOD(SetCurrentPosition) (THIS_ DWORD dwNewPosition) PURE; - STDMETHOD(SetFormat) (THIS_ LPCWAVEFORMATEX pcfxFormat) PURE; - STDMETHOD(SetVolume) (THIS_ LONG lVolume) PURE; - STDMETHOD(SetPan) (THIS_ LONG lPan) PURE; - STDMETHOD(SetFrequency) (THIS_ DWORD dwFrequency) PURE; - STDMETHOD(Stop) (THIS) PURE; - STDMETHOD(Unlock) (THIS_ LPVOID pvAudioPtr1, DWORD dwAudioBytes1, LPVOID pvAudioPtr2, DWORD dwAudioBytes2) PURE; - STDMETHOD(Restore) (THIS) PURE; -}; - -#define IDirectSoundBuffer_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) -#define IDirectSoundBuffer_AddRef(p) IUnknown_AddRef(p) -#define IDirectSoundBuffer_Release(p) IUnknown_Release(p) - -#if !defined(__cplusplus) || defined(CINTERFACE) -#define IDirectSoundBuffer_GetCaps(p,a) (p)->lpVtbl->GetCaps(p,a) -#define IDirectSoundBuffer_GetCurrentPosition(p,a,b) (p)->lpVtbl->GetCurrentPosition(p,a,b) -#define IDirectSoundBuffer_GetFormat(p,a,b,c) (p)->lpVtbl->GetFormat(p,a,b,c) -#define IDirectSoundBuffer_GetVolume(p,a) (p)->lpVtbl->GetVolume(p,a) -#define IDirectSoundBuffer_GetPan(p,a) (p)->lpVtbl->GetPan(p,a) -#define IDirectSoundBuffer_GetFrequency(p,a) (p)->lpVtbl->GetFrequency(p,a) -#define IDirectSoundBuffer_GetStatus(p,a) (p)->lpVtbl->GetStatus(p,a) -#define IDirectSoundBuffer_Initialize(p,a,b) (p)->lpVtbl->Initialize(p,a,b) -#define IDirectSoundBuffer_Lock(p,a,b,c,d,e,f,g) (p)->lpVtbl->Lock(p,a,b,c,d,e,f,g) -#define IDirectSoundBuffer_Play(p,a,b,c) (p)->lpVtbl->Play(p,a,b,c) -#define IDirectSoundBuffer_SetCurrentPosition(p,a) (p)->lpVtbl->SetCurrentPosition(p,a) -#define IDirectSoundBuffer_SetFormat(p,a) (p)->lpVtbl->SetFormat(p,a) -#define IDirectSoundBuffer_SetVolume(p,a) (p)->lpVtbl->SetVolume(p,a) -#define IDirectSoundBuffer_SetPan(p,a) (p)->lpVtbl->SetPan(p,a) -#define IDirectSoundBuffer_SetFrequency(p,a) (p)->lpVtbl->SetFrequency(p,a) -#define IDirectSoundBuffer_Stop(p) (p)->lpVtbl->Stop(p) -#define IDirectSoundBuffer_Unlock(p,a,b,c,d) (p)->lpVtbl->Unlock(p,a,b,c,d) -#define IDirectSoundBuffer_Restore(p) (p)->lpVtbl->Restore(p) -#else // !defined(__cplusplus) || defined(CINTERFACE) -#define IDirectSoundBuffer_GetCaps(p,a) (p)->GetCaps(a) -#define IDirectSoundBuffer_GetCurrentPosition(p,a,b) (p)->GetCurrentPosition(a,b) -#define IDirectSoundBuffer_GetFormat(p,a,b,c) (p)->GetFormat(a,b,c) -#define IDirectSoundBuffer_GetVolume(p,a) (p)->GetVolume(a) -#define IDirectSoundBuffer_GetPan(p,a) (p)->GetPan(a) -#define IDirectSoundBuffer_GetFrequency(p,a) (p)->GetFrequency(a) -#define IDirectSoundBuffer_GetStatus(p,a) (p)->GetStatus(a) -#define IDirectSoundBuffer_Initialize(p,a,b) (p)->Initialize(a,b) -#define IDirectSoundBuffer_Lock(p,a,b,c,d,e,f,g) (p)->Lock(a,b,c,d,e,f,g) -#define IDirectSoundBuffer_Play(p,a,b,c) (p)->Play(a,b,c) -#define IDirectSoundBuffer_SetCurrentPosition(p,a) (p)->SetCurrentPosition(a) -#define IDirectSoundBuffer_SetFormat(p,a) (p)->SetFormat(a) -#define IDirectSoundBuffer_SetVolume(p,a) (p)->SetVolume(a) -#define IDirectSoundBuffer_SetPan(p,a) (p)->SetPan(a) -#define IDirectSoundBuffer_SetFrequency(p,a) (p)->SetFrequency(a) -#define IDirectSoundBuffer_Stop(p) (p)->Stop() -#define IDirectSoundBuffer_Unlock(p,a,b,c,d) (p)->Unlock(a,b,c,d) -#define IDirectSoundBuffer_Restore(p) (p)->Restore() -#endif // !defined(__cplusplus) || defined(CINTERFACE) - -#if DIRECTSOUND_VERSION >= 0x0800 - -// -// IDirectSoundBuffer8 -// - -DEFINE_GUID(IID_IDirectSoundBuffer8, 0x6825a449, 0x7524, 0x4d82, 0x92, 0x0f, 0x50, 0xe3, 0x6a, 0xb3, 0xab, 0x1e); - -#undef INTERFACE -#define INTERFACE IDirectSoundBuffer8 - -DECLARE_INTERFACE_(IDirectSoundBuffer8, IDirectSoundBuffer) -{ - // IUnknown methods - STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; - STDMETHOD_(ULONG,AddRef) (THIS) PURE; - STDMETHOD_(ULONG,Release) (THIS) PURE; - - // IDirectSoundBuffer methods - STDMETHOD(GetCaps) (THIS_ LPDSBCAPS pDSBufferCaps) PURE; - STDMETHOD(GetCurrentPosition) (THIS_ LPDWORD pdwCurrentPlayCursor, LPDWORD pdwCurrentWriteCursor) PURE; - STDMETHOD(GetFormat) (THIS_ LPWAVEFORMATEX pwfxFormat, DWORD dwSizeAllocated, LPDWORD pdwSizeWritten) PURE; - STDMETHOD(GetVolume) (THIS_ LPLONG plVolume) PURE; - STDMETHOD(GetPan) (THIS_ LPLONG plPan) PURE; - STDMETHOD(GetFrequency) (THIS_ LPDWORD pdwFrequency) PURE; - STDMETHOD(GetStatus) (THIS_ LPDWORD pdwStatus) PURE; - STDMETHOD(Initialize) (THIS_ LPDIRECTSOUND pDirectSound, LPCDSBUFFERDESC pcDSBufferDesc) PURE; - STDMETHOD(Lock) (THIS_ DWORD dwOffset, DWORD dwBytes, LPVOID *ppvAudioPtr1, LPDWORD pdwAudioBytes1, - LPVOID *ppvAudioPtr2, LPDWORD pdwAudioBytes2, DWORD dwFlags) PURE; - STDMETHOD(Play) (THIS_ DWORD dwReserved1, DWORD dwPriority, DWORD dwFlags) PURE; - STDMETHOD(SetCurrentPosition) (THIS_ DWORD dwNewPosition) PURE; - STDMETHOD(SetFormat) (THIS_ LPCWAVEFORMATEX pcfxFormat) PURE; - STDMETHOD(SetVolume) (THIS_ LONG lVolume) PURE; - STDMETHOD(SetPan) (THIS_ LONG lPan) PURE; - STDMETHOD(SetFrequency) (THIS_ DWORD dwFrequency) PURE; - STDMETHOD(Stop) (THIS) PURE; - STDMETHOD(Unlock) (THIS_ LPVOID pvAudioPtr1, DWORD dwAudioBytes1, LPVOID pvAudioPtr2, DWORD dwAudioBytes2) PURE; - STDMETHOD(Restore) (THIS) PURE; - - // IDirectSoundBuffer8 methods - STDMETHOD(SetFX) (THIS_ DWORD dwEffectsCount, LPDSEFFECTDESC pDSFXDesc, LPDWORD pdwResultCodes) PURE; - STDMETHOD(AcquireResources) (THIS_ DWORD dwFlags, DWORD dwEffectsCount, LPDWORD pdwResultCodes) PURE; - STDMETHOD(GetObjectInPath) (THIS_ REFGUID rguidObject, DWORD dwIndex, REFGUID rguidInterface, LPVOID *ppObject) PURE; -}; - -// Special GUID meaning "select all objects" for use in GetObjectInPath() -DEFINE_GUID(GUID_All_Objects, 0xaa114de5, 0xc262, 0x4169, 0xa1, 0xc8, 0x23, 0xd6, 0x98, 0xcc, 0x73, 0xb5); - -#define IDirectSoundBuffer8_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) -#define IDirectSoundBuffer8_AddRef(p) IUnknown_AddRef(p) -#define IDirectSoundBuffer8_Release(p) IUnknown_Release(p) - -#define IDirectSoundBuffer8_GetCaps(p,a) IDirectSoundBuffer_GetCaps(p,a) -#define IDirectSoundBuffer8_GetCurrentPosition(p,a,b) IDirectSoundBuffer_GetCurrentPosition(p,a,b) -#define IDirectSoundBuffer8_GetFormat(p,a,b,c) IDirectSoundBuffer_GetFormat(p,a,b,c) -#define IDirectSoundBuffer8_GetVolume(p,a) IDirectSoundBuffer_GetVolume(p,a) -#define IDirectSoundBuffer8_GetPan(p,a) IDirectSoundBuffer_GetPan(p,a) -#define IDirectSoundBuffer8_GetFrequency(p,a) IDirectSoundBuffer_GetFrequency(p,a) -#define IDirectSoundBuffer8_GetStatus(p,a) IDirectSoundBuffer_GetStatus(p,a) -#define IDirectSoundBuffer8_Initialize(p,a,b) IDirectSoundBuffer_Initialize(p,a,b) -#define IDirectSoundBuffer8_Lock(p,a,b,c,d,e,f,g) IDirectSoundBuffer_Lock(p,a,b,c,d,e,f,g) -#define IDirectSoundBuffer8_Play(p,a,b,c) IDirectSoundBuffer_Play(p,a,b,c) -#define IDirectSoundBuffer8_SetCurrentPosition(p,a) IDirectSoundBuffer_SetCurrentPosition(p,a) -#define IDirectSoundBuffer8_SetFormat(p,a) IDirectSoundBuffer_SetFormat(p,a) -#define IDirectSoundBuffer8_SetVolume(p,a) IDirectSoundBuffer_SetVolume(p,a) -#define IDirectSoundBuffer8_SetPan(p,a) IDirectSoundBuffer_SetPan(p,a) -#define IDirectSoundBuffer8_SetFrequency(p,a) IDirectSoundBuffer_SetFrequency(p,a) -#define IDirectSoundBuffer8_Stop(p) IDirectSoundBuffer_Stop(p) -#define IDirectSoundBuffer8_Unlock(p,a,b,c,d) IDirectSoundBuffer_Unlock(p,a,b,c,d) -#define IDirectSoundBuffer8_Restore(p) IDirectSoundBuffer_Restore(p) - -#if !defined(__cplusplus) || defined(CINTERFACE) -#define IDirectSoundBuffer8_SetFX(p,a,b,c) (p)->lpVtbl->SetFX(p,a,b,c) -#define IDirectSoundBuffer8_AcquireResources(p,a,b,c) (p)->lpVtbl->AcquireResources(p,a,b,c) -#define IDirectSoundBuffer8_GetObjectInPath(p,a,b,c,d) (p)->lpVtbl->GetObjectInPath(p,a,b,c,d) -#else // !defined(__cplusplus) || defined(CINTERFACE) -#define IDirectSoundBuffer8_SetFX(p,a,b,c) (p)->SetFX(a,b,c) -#define IDirectSoundBuffer8_AcquireResources(p,a,b,c) (p)->AcquireResources(a,b,c) -#define IDirectSoundBuffer8_GetObjectInPath(p,a,b,c,d) (p)->GetObjectInPath(a,b,c,d) -#endif // !defined(__cplusplus) || defined(CINTERFACE) - -#endif // DIRECTSOUND_VERSION >= 0x0800 - -// -// IDirectSound3DListener -// - -DEFINE_GUID(IID_IDirectSound3DListener, 0x279AFA84, 0x4981, 0x11CE, 0xA5, 0x21, 0x00, 0x20, 0xAF, 0x0B, 0xE5, 0x60); - -#undef INTERFACE -#define INTERFACE IDirectSound3DListener - -DECLARE_INTERFACE_(IDirectSound3DListener, IUnknown) -{ - // IUnknown methods - STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; - STDMETHOD_(ULONG,AddRef) (THIS) PURE; - STDMETHOD_(ULONG,Release) (THIS) PURE; - - // IDirectSound3DListener methods - STDMETHOD(GetAllParameters) (THIS_ LPDS3DLISTENER pListener) PURE; - STDMETHOD(GetDistanceFactor) (THIS_ D3DVALUE* pflDistanceFactor) PURE; - STDMETHOD(GetDopplerFactor) (THIS_ D3DVALUE* pflDopplerFactor) PURE; - STDMETHOD(GetOrientation) (THIS_ D3DVECTOR* pvOrientFront, D3DVECTOR* pvOrientTop) PURE; - STDMETHOD(GetPosition) (THIS_ D3DVECTOR* pvPosition) PURE; - STDMETHOD(GetRolloffFactor) (THIS_ D3DVALUE* pflRolloffFactor) PURE; - STDMETHOD(GetVelocity) (THIS_ D3DVECTOR* pvVelocity) PURE; - STDMETHOD(SetAllParameters) (THIS_ LPCDS3DLISTENER pcListener, DWORD dwApply) PURE; - STDMETHOD(SetDistanceFactor) (THIS_ D3DVALUE flDistanceFactor, DWORD dwApply) PURE; - STDMETHOD(SetDopplerFactor) (THIS_ D3DVALUE flDopplerFactor, DWORD dwApply) PURE; - STDMETHOD(SetOrientation) (THIS_ D3DVALUE xFront, D3DVALUE yFront, D3DVALUE zFront, - D3DVALUE xTop, D3DVALUE yTop, D3DVALUE zTop, DWORD dwApply) PURE; - STDMETHOD(SetPosition) (THIS_ D3DVALUE x, D3DVALUE y, D3DVALUE z, DWORD dwApply) PURE; - STDMETHOD(SetRolloffFactor) (THIS_ D3DVALUE flRolloffFactor, DWORD dwApply) PURE; - STDMETHOD(SetVelocity) (THIS_ D3DVALUE x, D3DVALUE y, D3DVALUE z, DWORD dwApply) PURE; - STDMETHOD(CommitDeferredSettings) (THIS) PURE; -}; - -#define IDirectSound3DListener_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) -#define IDirectSound3DListener_AddRef(p) IUnknown_AddRef(p) -#define IDirectSound3DListener_Release(p) IUnknown_Release(p) - -#if !defined(__cplusplus) || defined(CINTERFACE) -#define IDirectSound3DListener_GetAllParameters(p,a) (p)->lpVtbl->GetAllParameters(p,a) -#define IDirectSound3DListener_GetDistanceFactor(p,a) (p)->lpVtbl->GetDistanceFactor(p,a) -#define IDirectSound3DListener_GetDopplerFactor(p,a) (p)->lpVtbl->GetDopplerFactor(p,a) -#define IDirectSound3DListener_GetOrientation(p,a,b) (p)->lpVtbl->GetOrientation(p,a,b) -#define IDirectSound3DListener_GetPosition(p,a) (p)->lpVtbl->GetPosition(p,a) -#define IDirectSound3DListener_GetRolloffFactor(p,a) (p)->lpVtbl->GetRolloffFactor(p,a) -#define IDirectSound3DListener_GetVelocity(p,a) (p)->lpVtbl->GetVelocity(p,a) -#define IDirectSound3DListener_SetAllParameters(p,a,b) (p)->lpVtbl->SetAllParameters(p,a,b) -#define IDirectSound3DListener_SetDistanceFactor(p,a,b) (p)->lpVtbl->SetDistanceFactor(p,a,b) -#define IDirectSound3DListener_SetDopplerFactor(p,a,b) (p)->lpVtbl->SetDopplerFactor(p,a,b) -#define IDirectSound3DListener_SetOrientation(p,a,b,c,d,e,f,g) (p)->lpVtbl->SetOrientation(p,a,b,c,d,e,f,g) -#define IDirectSound3DListener_SetPosition(p,a,b,c,d) (p)->lpVtbl->SetPosition(p,a,b,c,d) -#define IDirectSound3DListener_SetRolloffFactor(p,a,b) (p)->lpVtbl->SetRolloffFactor(p,a,b) -#define IDirectSound3DListener_SetVelocity(p,a,b,c,d) (p)->lpVtbl->SetVelocity(p,a,b,c,d) -#define IDirectSound3DListener_CommitDeferredSettings(p) (p)->lpVtbl->CommitDeferredSettings(p) -#else // !defined(__cplusplus) || defined(CINTERFACE) -#define IDirectSound3DListener_GetAllParameters(p,a) (p)->GetAllParameters(a) -#define IDirectSound3DListener_GetDistanceFactor(p,a) (p)->GetDistanceFactor(a) -#define IDirectSound3DListener_GetDopplerFactor(p,a) (p)->GetDopplerFactor(a) -#define IDirectSound3DListener_GetOrientation(p,a,b) (p)->GetOrientation(a,b) -#define IDirectSound3DListener_GetPosition(p,a) (p)->GetPosition(a) -#define IDirectSound3DListener_GetRolloffFactor(p,a) (p)->GetRolloffFactor(a) -#define IDirectSound3DListener_GetVelocity(p,a) (p)->GetVelocity(a) -#define IDirectSound3DListener_SetAllParameters(p,a,b) (p)->SetAllParameters(a,b) -#define IDirectSound3DListener_SetDistanceFactor(p,a,b) (p)->SetDistanceFactor(a,b) -#define IDirectSound3DListener_SetDopplerFactor(p,a,b) (p)->SetDopplerFactor(a,b) -#define IDirectSound3DListener_SetOrientation(p,a,b,c,d,e,f,g) (p)->SetOrientation(a,b,c,d,e,f,g) -#define IDirectSound3DListener_SetPosition(p,a,b,c,d) (p)->SetPosition(a,b,c,d) -#define IDirectSound3DListener_SetRolloffFactor(p,a,b) (p)->SetRolloffFactor(a,b) -#define IDirectSound3DListener_SetVelocity(p,a,b,c,d) (p)->SetVelocity(a,b,c,d) -#define IDirectSound3DListener_CommitDeferredSettings(p) (p)->CommitDeferredSettings() -#endif // !defined(__cplusplus) || defined(CINTERFACE) - -// -// IDirectSound3DBuffer -// - -DEFINE_GUID(IID_IDirectSound3DBuffer, 0x279AFA86, 0x4981, 0x11CE, 0xA5, 0x21, 0x00, 0x20, 0xAF, 0x0B, 0xE5, 0x60); - -#undef INTERFACE -#define INTERFACE IDirectSound3DBuffer - -DECLARE_INTERFACE_(IDirectSound3DBuffer, IUnknown) -{ - // IUnknown methods - STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; - STDMETHOD_(ULONG,AddRef) (THIS) PURE; - STDMETHOD_(ULONG,Release) (THIS) PURE; - - // IDirectSound3DBuffer methods - STDMETHOD(GetAllParameters) (THIS_ LPDS3DBUFFER pDs3dBuffer) PURE; - STDMETHOD(GetConeAngles) (THIS_ LPDWORD pdwInsideConeAngle, LPDWORD pdwOutsideConeAngle) PURE; - STDMETHOD(GetConeOrientation) (THIS_ D3DVECTOR* pvOrientation) PURE; - STDMETHOD(GetConeOutsideVolume) (THIS_ LPLONG plConeOutsideVolume) PURE; - STDMETHOD(GetMaxDistance) (THIS_ D3DVALUE* pflMaxDistance) PURE; - STDMETHOD(GetMinDistance) (THIS_ D3DVALUE* pflMinDistance) PURE; - STDMETHOD(GetMode) (THIS_ LPDWORD pdwMode) PURE; - STDMETHOD(GetPosition) (THIS_ D3DVECTOR* pvPosition) PURE; - STDMETHOD(GetVelocity) (THIS_ D3DVECTOR* pvVelocity) PURE; - STDMETHOD(SetAllParameters) (THIS_ LPCDS3DBUFFER pcDs3dBuffer, DWORD dwApply) PURE; - STDMETHOD(SetConeAngles) (THIS_ DWORD dwInsideConeAngle, DWORD dwOutsideConeAngle, DWORD dwApply) PURE; - STDMETHOD(SetConeOrientation) (THIS_ D3DVALUE x, D3DVALUE y, D3DVALUE z, DWORD dwApply) PURE; - STDMETHOD(SetConeOutsideVolume) (THIS_ LONG lConeOutsideVolume, DWORD dwApply) PURE; - STDMETHOD(SetMaxDistance) (THIS_ D3DVALUE flMaxDistance, DWORD dwApply) PURE; - STDMETHOD(SetMinDistance) (THIS_ D3DVALUE flMinDistance, DWORD dwApply) PURE; - STDMETHOD(SetMode) (THIS_ DWORD dwMode, DWORD dwApply) PURE; - STDMETHOD(SetPosition) (THIS_ D3DVALUE x, D3DVALUE y, D3DVALUE z, DWORD dwApply) PURE; - STDMETHOD(SetVelocity) (THIS_ D3DVALUE x, D3DVALUE y, D3DVALUE z, DWORD dwApply) PURE; -}; - -#define IDirectSound3DBuffer_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) -#define IDirectSound3DBuffer_AddRef(p) IUnknown_AddRef(p) -#define IDirectSound3DBuffer_Release(p) IUnknown_Release(p) - -#if !defined(__cplusplus) || defined(CINTERFACE) -#define IDirectSound3DBuffer_GetAllParameters(p,a) (p)->lpVtbl->GetAllParameters(p,a) -#define IDirectSound3DBuffer_GetConeAngles(p,a,b) (p)->lpVtbl->GetConeAngles(p,a,b) -#define IDirectSound3DBuffer_GetConeOrientation(p,a) (p)->lpVtbl->GetConeOrientation(p,a) -#define IDirectSound3DBuffer_GetConeOutsideVolume(p,a) (p)->lpVtbl->GetConeOutsideVolume(p,a) -#define IDirectSound3DBuffer_GetPosition(p,a) (p)->lpVtbl->GetPosition(p,a) -#define IDirectSound3DBuffer_GetMinDistance(p,a) (p)->lpVtbl->GetMinDistance(p,a) -#define IDirectSound3DBuffer_GetMaxDistance(p,a) (p)->lpVtbl->GetMaxDistance(p,a) -#define IDirectSound3DBuffer_GetMode(p,a) (p)->lpVtbl->GetMode(p,a) -#define IDirectSound3DBuffer_GetVelocity(p,a) (p)->lpVtbl->GetVelocity(p,a) -#define IDirectSound3DBuffer_SetAllParameters(p,a,b) (p)->lpVtbl->SetAllParameters(p,a,b) -#define IDirectSound3DBuffer_SetConeAngles(p,a,b,c) (p)->lpVtbl->SetConeAngles(p,a,b,c) -#define IDirectSound3DBuffer_SetConeOrientation(p,a,b,c,d) (p)->lpVtbl->SetConeOrientation(p,a,b,c,d) -#define IDirectSound3DBuffer_SetConeOutsideVolume(p,a,b) (p)->lpVtbl->SetConeOutsideVolume(p,a,b) -#define IDirectSound3DBuffer_SetPosition(p,a,b,c,d) (p)->lpVtbl->SetPosition(p,a,b,c,d) -#define IDirectSound3DBuffer_SetMinDistance(p,a,b) (p)->lpVtbl->SetMinDistance(p,a,b) -#define IDirectSound3DBuffer_SetMaxDistance(p,a,b) (p)->lpVtbl->SetMaxDistance(p,a,b) -#define IDirectSound3DBuffer_SetMode(p,a,b) (p)->lpVtbl->SetMode(p,a,b) -#define IDirectSound3DBuffer_SetVelocity(p,a,b,c,d) (p)->lpVtbl->SetVelocity(p,a,b,c,d) -#else // !defined(__cplusplus) || defined(CINTERFACE) -#define IDirectSound3DBuffer_GetAllParameters(p,a) (p)->GetAllParameters(a) -#define IDirectSound3DBuffer_GetConeAngles(p,a,b) (p)->GetConeAngles(a,b) -#define IDirectSound3DBuffer_GetConeOrientation(p,a) (p)->GetConeOrientation(a) -#define IDirectSound3DBuffer_GetConeOutsideVolume(p,a) (p)->GetConeOutsideVolume(a) -#define IDirectSound3DBuffer_GetPosition(p,a) (p)->GetPosition(a) -#define IDirectSound3DBuffer_GetMinDistance(p,a) (p)->GetMinDistance(a) -#define IDirectSound3DBuffer_GetMaxDistance(p,a) (p)->GetMaxDistance(a) -#define IDirectSound3DBuffer_GetMode(p,a) (p)->GetMode(a) -#define IDirectSound3DBuffer_GetVelocity(p,a) (p)->GetVelocity(a) -#define IDirectSound3DBuffer_SetAllParameters(p,a,b) (p)->SetAllParameters(a,b) -#define IDirectSound3DBuffer_SetConeAngles(p,a,b,c) (p)->SetConeAngles(a,b,c) -#define IDirectSound3DBuffer_SetConeOrientation(p,a,b,c,d) (p)->SetConeOrientation(a,b,c,d) -#define IDirectSound3DBuffer_SetConeOutsideVolume(p,a,b) (p)->SetConeOutsideVolume(a,b) -#define IDirectSound3DBuffer_SetPosition(p,a,b,c,d) (p)->SetPosition(a,b,c,d) -#define IDirectSound3DBuffer_SetMinDistance(p,a,b) (p)->SetMinDistance(a,b) -#define IDirectSound3DBuffer_SetMaxDistance(p,a,b) (p)->SetMaxDistance(a,b) -#define IDirectSound3DBuffer_SetMode(p,a,b) (p)->SetMode(a,b) -#define IDirectSound3DBuffer_SetVelocity(p,a,b,c,d) (p)->SetVelocity(a,b,c,d) -#endif // !defined(__cplusplus) || defined(CINTERFACE) - -// -// IDirectSoundCapture -// - -DEFINE_GUID(IID_IDirectSoundCapture, 0xb0210781, 0x89cd, 0x11d0, 0xaf, 0x8, 0x0, 0xa0, 0xc9, 0x25, 0xcd, 0x16); - -#undef INTERFACE -#define INTERFACE IDirectSoundCapture - -DECLARE_INTERFACE_(IDirectSoundCapture, IUnknown) -{ - // IUnknown methods - STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; - STDMETHOD_(ULONG,AddRef) (THIS) PURE; - STDMETHOD_(ULONG,Release) (THIS) PURE; - - // IDirectSoundCapture methods - STDMETHOD(CreateCaptureBuffer) (THIS_ LPCDSCBUFFERDESC pcDSCBufferDesc, LPDIRECTSOUNDCAPTUREBUFFER *ppDSCBuffer, LPUNKNOWN pUnkOuter) PURE; - STDMETHOD(GetCaps) (THIS_ LPDSCCAPS pDSCCaps) PURE; - STDMETHOD(Initialize) (THIS_ LPCGUID pcGuidDevice) PURE; -}; - -#define IDirectSoundCapture_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) -#define IDirectSoundCapture_AddRef(p) IUnknown_AddRef(p) -#define IDirectSoundCapture_Release(p) IUnknown_Release(p) - -#if !defined(__cplusplus) || defined(CINTERFACE) -#define IDirectSoundCapture_CreateCaptureBuffer(p,a,b,c) (p)->lpVtbl->CreateCaptureBuffer(p,a,b,c) -#define IDirectSoundCapture_GetCaps(p,a) (p)->lpVtbl->GetCaps(p,a) -#define IDirectSoundCapture_Initialize(p,a) (p)->lpVtbl->Initialize(p,a) -#else // !defined(__cplusplus) || defined(CINTERFACE) -#define IDirectSoundCapture_CreateCaptureBuffer(p,a,b,c) (p)->CreateCaptureBuffer(a,b,c) -#define IDirectSoundCapture_GetCaps(p,a) (p)->GetCaps(a) -#define IDirectSoundCapture_Initialize(p,a) (p)->Initialize(a) -#endif // !defined(__cplusplus) || defined(CINTERFACE) - -// -// IDirectSoundCaptureBuffer -// - -DEFINE_GUID(IID_IDirectSoundCaptureBuffer, 0xb0210782, 0x89cd, 0x11d0, 0xaf, 0x8, 0x0, 0xa0, 0xc9, 0x25, 0xcd, 0x16); - -#undef INTERFACE -#define INTERFACE IDirectSoundCaptureBuffer - -DECLARE_INTERFACE_(IDirectSoundCaptureBuffer, IUnknown) -{ - // IUnknown methods - STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; - STDMETHOD_(ULONG,AddRef) (THIS) PURE; - STDMETHOD_(ULONG,Release) (THIS) PURE; - - // IDirectSoundCaptureBuffer methods - STDMETHOD(GetCaps) (THIS_ LPDSCBCAPS pDSCBCaps) PURE; - STDMETHOD(GetCurrentPosition) (THIS_ LPDWORD pdwCapturePosition, LPDWORD pdwReadPosition) PURE; - STDMETHOD(GetFormat) (THIS_ LPWAVEFORMATEX pwfxFormat, DWORD dwSizeAllocated, LPDWORD pdwSizeWritten) PURE; - STDMETHOD(GetStatus) (THIS_ LPDWORD pdwStatus) PURE; - STDMETHOD(Initialize) (THIS_ LPDIRECTSOUNDCAPTURE pDirectSoundCapture, LPCDSCBUFFERDESC pcDSCBufferDesc) PURE; - STDMETHOD(Lock) (THIS_ DWORD dwOffset, DWORD dwBytes, LPVOID *ppvAudioPtr1, LPDWORD pdwAudioBytes1, - LPVOID *ppvAudioPtr2, LPDWORD pdwAudioBytes2, DWORD dwFlags) PURE; - STDMETHOD(Start) (THIS_ DWORD dwFlags) PURE; - STDMETHOD(Stop) (THIS) PURE; - STDMETHOD(Unlock) (THIS_ LPVOID pvAudioPtr1, DWORD dwAudioBytes1, LPVOID pvAudioPtr2, DWORD dwAudioBytes2) PURE; -}; - -#define IDirectSoundCaptureBuffer_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) -#define IDirectSoundCaptureBuffer_AddRef(p) IUnknown_AddRef(p) -#define IDirectSoundCaptureBuffer_Release(p) IUnknown_Release(p) - -#if !defined(__cplusplus) || defined(CINTERFACE) -#define IDirectSoundCaptureBuffer_GetCaps(p,a) (p)->lpVtbl->GetCaps(p,a) -#define IDirectSoundCaptureBuffer_GetCurrentPosition(p,a,b) (p)->lpVtbl->GetCurrentPosition(p,a,b) -#define IDirectSoundCaptureBuffer_GetFormat(p,a,b,c) (p)->lpVtbl->GetFormat(p,a,b,c) -#define IDirectSoundCaptureBuffer_GetStatus(p,a) (p)->lpVtbl->GetStatus(p,a) -#define IDirectSoundCaptureBuffer_Initialize(p,a,b) (p)->lpVtbl->Initialize(p,a,b) -#define IDirectSoundCaptureBuffer_Lock(p,a,b,c,d,e,f,g) (p)->lpVtbl->Lock(p,a,b,c,d,e,f,g) -#define IDirectSoundCaptureBuffer_Start(p,a) (p)->lpVtbl->Start(p,a) -#define IDirectSoundCaptureBuffer_Stop(p) (p)->lpVtbl->Stop(p) -#define IDirectSoundCaptureBuffer_Unlock(p,a,b,c,d) (p)->lpVtbl->Unlock(p,a,b,c,d) -#else // !defined(__cplusplus) || defined(CINTERFACE) -#define IDirectSoundCaptureBuffer_GetCaps(p,a) (p)->GetCaps(a) -#define IDirectSoundCaptureBuffer_GetCurrentPosition(p,a,b) (p)->GetCurrentPosition(a,b) -#define IDirectSoundCaptureBuffer_GetFormat(p,a,b,c) (p)->GetFormat(a,b,c) -#define IDirectSoundCaptureBuffer_GetStatus(p,a) (p)->GetStatus(a) -#define IDirectSoundCaptureBuffer_Initialize(p,a,b) (p)->Initialize(a,b) -#define IDirectSoundCaptureBuffer_Lock(p,a,b,c,d,e,f,g) (p)->Lock(a,b,c,d,e,f,g) -#define IDirectSoundCaptureBuffer_Start(p,a) (p)->Start(a) -#define IDirectSoundCaptureBuffer_Stop(p) (p)->Stop() -#define IDirectSoundCaptureBuffer_Unlock(p,a,b,c,d) (p)->Unlock(a,b,c,d) -#endif // !defined(__cplusplus) || defined(CINTERFACE) - - -#if DIRECTSOUND_VERSION >= 0x0800 - -// -// IDirectSoundCaptureBuffer8 -// - -DEFINE_GUID(IID_IDirectSoundCaptureBuffer8, 0x990df4, 0xdbb, 0x4872, 0x83, 0x3e, 0x6d, 0x30, 0x3e, 0x80, 0xae, 0xb6); - -#undef INTERFACE -#define INTERFACE IDirectSoundCaptureBuffer8 - -DECLARE_INTERFACE_(IDirectSoundCaptureBuffer8, IDirectSoundCaptureBuffer) -{ - // IUnknown methods - STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; - STDMETHOD_(ULONG,AddRef) (THIS) PURE; - STDMETHOD_(ULONG,Release) (THIS) PURE; - - // IDirectSoundCaptureBuffer methods - STDMETHOD(GetCaps) (THIS_ LPDSCBCAPS pDSCBCaps) PURE; - STDMETHOD(GetCurrentPosition) (THIS_ LPDWORD pdwCapturePosition, LPDWORD pdwReadPosition) PURE; - STDMETHOD(GetFormat) (THIS_ LPWAVEFORMATEX pwfxFormat, DWORD dwSizeAllocated, LPDWORD pdwSizeWritten) PURE; - STDMETHOD(GetStatus) (THIS_ LPDWORD pdwStatus) PURE; - STDMETHOD(Initialize) (THIS_ LPDIRECTSOUNDCAPTURE pDirectSoundCapture, LPCDSCBUFFERDESC pcDSCBufferDesc) PURE; - STDMETHOD(Lock) (THIS_ DWORD dwOffset, DWORD dwBytes, LPVOID *ppvAudioPtr1, LPDWORD pdwAudioBytes1, - LPVOID *ppvAudioPtr2, LPDWORD pdwAudioBytes2, DWORD dwFlags) PURE; - STDMETHOD(Start) (THIS_ DWORD dwFlags) PURE; - STDMETHOD(Stop) (THIS) PURE; - STDMETHOD(Unlock) (THIS_ LPVOID pvAudioPtr1, DWORD dwAudioBytes1, LPVOID pvAudioPtr2, DWORD dwAudioBytes2) PURE; - - // IDirectSoundCaptureBuffer8 methods - STDMETHOD(GetObjectInPath) (THIS_ REFGUID rguidObject, DWORD dwIndex, REFGUID rguidInterface, LPVOID *ppObject) PURE; - STDMETHOD(GetFXStatus) (DWORD dwFXCount, LPDWORD pdwFXStatus) PURE; -}; - -#define IDirectSoundCaptureBuffer8_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) -#define IDirectSoundCaptureBuffer8_AddRef(p) IUnknown_AddRef(p) -#define IDirectSoundCaptureBuffer8_Release(p) IUnknown_Release(p) - -#define IDirectSoundCaptureBuffer8_GetCaps(p,a) IDirectSoundCaptureBuffer_GetCaps(p,a) -#define IDirectSoundCaptureBuffer8_GetCurrentPosition(p,a,b) IDirectSoundCaptureBuffer_GetCurrentPosition(p,a,b) -#define IDirectSoundCaptureBuffer8_GetFormat(p,a,b,c) IDirectSoundCaptureBuffer_GetFormat(p,a,b,c) -#define IDirectSoundCaptureBuffer8_GetStatus(p,a) IDirectSoundCaptureBuffer_GetStatus(p,a) -#define IDirectSoundCaptureBuffer8_Initialize(p,a,b) IDirectSoundCaptureBuffer_Initialize(p,a,b) -#define IDirectSoundCaptureBuffer8_Lock(p,a,b,c,d,e,f,g) IDirectSoundCaptureBuffer_Lock(p,a,b,c,d,e,f,g) -#define IDirectSoundCaptureBuffer8_Start(p,a) IDirectSoundCaptureBuffer_Start(p,a) -#define IDirectSoundCaptureBuffer8_Stop(p) IDirectSoundCaptureBuffer_Stop(p)) -#define IDirectSoundCaptureBuffer8_Unlock(p,a,b,c,d) IDirectSoundCaptureBuffer_Unlock(p,a,b,c,d) - -#if !defined(__cplusplus) || defined(CINTERFACE) -#define IDirectSoundCaptureBuffer8_GetObjectInPath(p,a,b,c,d) (p)->lpVtbl->GetObjectInPath(p,a,b,c,d) -#define IDirectSoundCaptureBuffer8_GetFXStatus(p,a,b) (p)->lpVtbl->GetFXStatus(p,a,b) -#else // !defined(__cplusplus) || defined(CINTERFACE) -#define IDirectSoundCaptureBuffer8_GetObjectInPath(p,a,b,c,d) (p)->GetObjectInPath(a,b,c,d) -#define IDirectSoundCaptureBuffer8_GetFXStatus(p,a,b) (p)->GetFXStatus(a,b) -#endif // !defined(__cplusplus) || defined(CINTERFACE) - -#endif // DIRECTSOUND_VERSION >= 0x0800 - -// -// IDirectSoundNotify -// - -DEFINE_GUID(IID_IDirectSoundNotify, 0xb0210783, 0x89cd, 0x11d0, 0xaf, 0x8, 0x0, 0xa0, 0xc9, 0x25, 0xcd, 0x16); - -#undef INTERFACE -#define INTERFACE IDirectSoundNotify - -DECLARE_INTERFACE_(IDirectSoundNotify, IUnknown) -{ - // IUnknown methods - STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; - STDMETHOD_(ULONG,AddRef) (THIS) PURE; - STDMETHOD_(ULONG,Release) (THIS) PURE; - - // IDirectSoundNotify methods - STDMETHOD(SetNotificationPositions) (THIS_ DWORD dwPositionNotifies, LPCDSBPOSITIONNOTIFY pcPositionNotifies) PURE; -}; - -#define IDirectSoundNotify_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) -#define IDirectSoundNotify_AddRef(p) IUnknown_AddRef(p) -#define IDirectSoundNotify_Release(p) IUnknown_Release(p) - -#if !defined(__cplusplus) || defined(CINTERFACE) -#define IDirectSoundNotify_SetNotificationPositions(p,a,b) (p)->lpVtbl->SetNotificationPositions(p,a,b) -#else // !defined(__cplusplus) || defined(CINTERFACE) -#define IDirectSoundNotify_SetNotificationPositions(p,a,b) (p)->SetNotificationPositions(a,b) -#endif // !defined(__cplusplus) || defined(CINTERFACE) - -// -// IKsPropertySet -// - -#ifndef _IKsPropertySet_ -#define _IKsPropertySet_ - -#ifdef __cplusplus -// 'struct' not 'class' per the way DECLARE_INTERFACE_ is defined -struct IKsPropertySet; -#endif // __cplusplus - -typedef struct IKsPropertySet *LPKSPROPERTYSET; - -#define KSPROPERTY_SUPPORT_GET 0x00000001 -#define KSPROPERTY_SUPPORT_SET 0x00000002 - -DEFINE_GUID(IID_IKsPropertySet, 0x31efac30, 0x515c, 0x11d0, 0xa9, 0xaa, 0x00, 0xaa, 0x00, 0x61, 0xbe, 0x93); - -#undef INTERFACE -#define INTERFACE IKsPropertySet - -DECLARE_INTERFACE_(IKsPropertySet, IUnknown) -{ - // IUnknown methods - STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; - STDMETHOD_(ULONG,AddRef) (THIS) PURE; - STDMETHOD_(ULONG,Release) (THIS) PURE; - - // IKsPropertySet methods - STDMETHOD(Get) (THIS_ REFGUID rguidPropSet, ULONG ulId, LPVOID pInstanceData, ULONG ulInstanceLength, - LPVOID pPropertyData, ULONG ulDataLength, PULONG pulBytesReturned) PURE; - STDMETHOD(Set) (THIS_ REFGUID rguidPropSet, ULONG ulId, LPVOID pInstanceData, ULONG ulInstanceLength, - LPVOID pPropertyData, ULONG ulDataLength) PURE; - STDMETHOD(QuerySupport) (THIS_ REFGUID rguidPropSet, ULONG ulId, PULONG pulTypeSupport) PURE; -}; - -#define IKsPropertySet_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) -#define IKsPropertySet_AddRef(p) IUnknown_AddRef(p) -#define IKsPropertySet_Release(p) IUnknown_Release(p) - -#if !defined(__cplusplus) || defined(CINTERFACE) -#define IKsPropertySet_Get(p,a,b,c,d,e,f,g) (p)->lpVtbl->Get(p,a,b,c,d,e,f,g) -#define IKsPropertySet_Set(p,a,b,c,d,e,f) (p)->lpVtbl->Set(p,a,b,c,d,e,f) -#define IKsPropertySet_QuerySupport(p,a,b,c) (p)->lpVtbl->QuerySupport(p,a,b,c) -#else // !defined(__cplusplus) || defined(CINTERFACE) -#define IKsPropertySet_Get(p,a,b,c,d,e,f,g) (p)->Get(a,b,c,d,e,f,g) -#define IKsPropertySet_Set(p,a,b,c,d,e,f) (p)->Set(a,b,c,d,e,f) -#define IKsPropertySet_QuerySupport(p,a,b,c) (p)->QuerySupport(a,b,c) -#endif // !defined(__cplusplus) || defined(CINTERFACE) - -#endif // _IKsPropertySet_ - -#if DIRECTSOUND_VERSION >= 0x0800 - -// -// IDirectSoundFXGargle -// - -DEFINE_GUID(IID_IDirectSoundFXGargle, 0xd616f352, 0xd622, 0x11ce, 0xaa, 0xc5, 0x00, 0x20, 0xaf, 0x0b, 0x99, 0xa3); - -typedef struct _DSFXGargle -{ - DWORD dwRateHz; // Rate of modulation in hz - DWORD dwWaveShape; // DSFXGARGLE_WAVE_xxx -} DSFXGargle, *LPDSFXGargle; - -#define DSFXGARGLE_WAVE_TRIANGLE 0 -#define DSFXGARGLE_WAVE_SQUARE 1 - -typedef const DSFXGargle *LPCDSFXGargle; - -#define DSFXGARGLE_RATEHZ_MIN 1 -#define DSFXGARGLE_RATEHZ_MAX 1000 - -#undef INTERFACE -#define INTERFACE IDirectSoundFXGargle - -DECLARE_INTERFACE_(IDirectSoundFXGargle, IUnknown) -{ - // IUnknown methods - STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; - STDMETHOD_(ULONG,AddRef) (THIS) PURE; - STDMETHOD_(ULONG,Release) (THIS) PURE; - - // IDirectSoundFXGargle methods - STDMETHOD(SetAllParameters) (THIS_ LPCDSFXGargle pcDsFxGargle) PURE; - STDMETHOD(GetAllParameters) (THIS_ LPDSFXGargle pDsFxGargle) PURE; -}; - -#define IDirectSoundFXGargle_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) -#define IDirectSoundFXGargle_AddRef(p) IUnknown_AddRef(p) -#define IDirectSoundFXGargle_Release(p) IUnknown_Release(p) - -#if !defined(__cplusplus) || defined(CINTERFACE) -#define IDirectSoundFXGargle_SetAllParameters(p,a) (p)->lpVtbl->SetAllParameters(p,a) -#define IDirectSoundFXGargle_GetAllParameters(p,a) (p)->lpVtbl->GetAllParameters(p,a) -#else // !defined(__cplusplus) || defined(CINTERFACE) -#define IDirectSoundFXGargle_SetAllParameters(p,a) (p)->SetAllParameters(a) -#define IDirectSoundFXGargle_GetAllParameters(p,a) (p)->GetAllParameters(a) -#endif // !defined(__cplusplus) || defined(CINTERFACE) - -// -// IDirectSoundFXChorus -// - -DEFINE_GUID(IID_IDirectSoundFXChorus, 0x880842e3, 0x145f, 0x43e6, 0xa9, 0x34, 0xa7, 0x18, 0x06, 0xe5, 0x05, 0x47); - -typedef struct _DSFXChorus -{ - FLOAT fWetDryMix; - FLOAT fDepth; - FLOAT fFeedback; - FLOAT fFrequency; - LONG lWaveform; // LFO shape; DSFXCHORUS_WAVE_xxx - FLOAT fDelay; - LONG lPhase; -} DSFXChorus, *LPDSFXChorus; - -typedef const DSFXChorus *LPCDSFXChorus; - -#define DSFXCHORUS_WAVE_TRIANGLE 0 -#define DSFXCHORUS_WAVE_SIN 1 - -#define DSFXCHORUS_WETDRYMIX_MIN 0.0f -#define DSFXCHORUS_WETDRYMIX_MAX 100.0f -#define DSFXCHORUS_DEPTH_MIN 0.0f -#define DSFXCHORUS_DEPTH_MAX 100.0f -#define DSFXCHORUS_FEEDBACK_MIN -99.0f -#define DSFXCHORUS_FEEDBACK_MAX 99.0f -#define DSFXCHORUS_FREQUENCY_MIN 0.0f -#define DSFXCHORUS_FREQUENCY_MAX 10.0f -#define DSFXCHORUS_DELAY_MIN 0.0f -#define DSFXCHORUS_DELAY_MAX 20.0f -#define DSFXCHORUS_PHASE_MIN 0 -#define DSFXCHORUS_PHASE_MAX 4 - -#define DSFXCHORUS_PHASE_NEG_180 0 -#define DSFXCHORUS_PHASE_NEG_90 1 -#define DSFXCHORUS_PHASE_ZERO 2 -#define DSFXCHORUS_PHASE_90 3 -#define DSFXCHORUS_PHASE_180 4 - -#undef INTERFACE -#define INTERFACE IDirectSoundFXChorus - -DECLARE_INTERFACE_(IDirectSoundFXChorus, IUnknown) -{ - // IUnknown methods - STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; - STDMETHOD_(ULONG,AddRef) (THIS) PURE; - STDMETHOD_(ULONG,Release) (THIS) PURE; - - // IDirectSoundFXChorus methods - STDMETHOD(SetAllParameters) (THIS_ LPCDSFXChorus pcDsFxChorus) PURE; - STDMETHOD(GetAllParameters) (THIS_ LPDSFXChorus pDsFxChorus) PURE; -}; - -#define IDirectSoundFXChorus_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) -#define IDirectSoundFXChorus_AddRef(p) IUnknown_AddRef(p) -#define IDirectSoundFXChorus_Release(p) IUnknown_Release(p) - -#if !defined(__cplusplus) || defined(CINTERFACE) -#define IDirectSoundFXChorus_SetAllParameters(p,a) (p)->lpVtbl->SetAllParameters(p,a) -#define IDirectSoundFXChorus_GetAllParameters(p,a) (p)->lpVtbl->GetAllParameters(p,a) -#else // !defined(__cplusplus) || defined(CINTERFACE) -#define IDirectSoundFXChorus_SetAllParameters(p,a) (p)->SetAllParameters(a) -#define IDirectSoundFXChorus_GetAllParameters(p,a) (p)->GetAllParameters(a) -#endif // !defined(__cplusplus) || defined(CINTERFACE) - -// -// IDirectSoundFXFlanger -// - -DEFINE_GUID(IID_IDirectSoundFXFlanger, 0x903e9878, 0x2c92, 0x4072, 0x9b, 0x2c, 0xea, 0x68, 0xf5, 0x39, 0x67, 0x83); - -typedef struct _DSFXFlanger -{ - FLOAT fWetDryMix; - FLOAT fDepth; - FLOAT fFeedback; - FLOAT fFrequency; - LONG lWaveform; - FLOAT fDelay; - LONG lPhase; -} DSFXFlanger, *LPDSFXFlanger; - -typedef const DSFXFlanger *LPCDSFXFlanger; - -#define DSFXFLANGER_WAVE_TRIANGLE 0 -#define DSFXFLANGER_WAVE_SIN 1 - -#define DSFXFLANGER_WETDRYMIX_MIN 0.0f -#define DSFXFLANGER_WETDRYMIX_MAX 100.0f -#define DSFXFLANGER_FREQUENCY_MIN 0.0f -#define DSFXFLANGER_FREQUENCY_MAX 10.0f -#define DSFXFLANGER_DEPTH_MIN 0.0f -#define DSFXFLANGER_DEPTH_MAX 100.0f -#define DSFXFLANGER_PHASE_MIN 0 -#define DSFXFLANGER_PHASE_MAX 4 -#define DSFXFLANGER_FEEDBACK_MIN -99.0f -#define DSFXFLANGER_FEEDBACK_MAX 99.0f -#define DSFXFLANGER_DELAY_MIN 0.0f -#define DSFXFLANGER_DELAY_MAX 4.0f - -#define DSFXFLANGER_PHASE_NEG_180 0 -#define DSFXFLANGER_PHASE_NEG_90 1 -#define DSFXFLANGER_PHASE_ZERO 2 -#define DSFXFLANGER_PHASE_90 3 -#define DSFXFLANGER_PHASE_180 4 - -#undef INTERFACE -#define INTERFACE IDirectSoundFXFlanger - -DECLARE_INTERFACE_(IDirectSoundFXFlanger, IUnknown) -{ - // IUnknown methods - STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; - STDMETHOD_(ULONG,AddRef) (THIS) PURE; - STDMETHOD_(ULONG,Release) (THIS) PURE; - - // IDirectSoundFXFlanger methods - STDMETHOD(SetAllParameters) (THIS_ LPCDSFXFlanger pcDsFxFlanger) PURE; - STDMETHOD(GetAllParameters) (THIS_ LPDSFXFlanger pDsFxFlanger) PURE; -}; - -#define IDirectSoundFXFlanger_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) -#define IDirectSoundFXFlanger_AddRef(p) IUnknown_AddRef(p) -#define IDirectSoundFXFlanger_Release(p) IUnknown_Release(p) - -#if !defined(__cplusplus) || defined(CINTERFACE) -#define IDirectSoundFXFlanger_SetAllParameters(p,a) (p)->lpVtbl->SetAllParameters(p,a) -#define IDirectSoundFXFlanger_GetAllParameters(p,a) (p)->lpVtbl->GetAllParameters(p,a) -#else // !defined(__cplusplus) || defined(CINTERFACE) -#define IDirectSoundFXFlanger_SetAllParameters(p,a) (p)->SetAllParameters(a) -#define IDirectSoundFXFlanger_GetAllParameters(p,a) (p)->GetAllParameters(a) -#endif // !defined(__cplusplus) || defined(CINTERFACE) - -// -// IDirectSoundFXEcho -// - -DEFINE_GUID(IID_IDirectSoundFXEcho, 0x8bd28edf, 0x50db, 0x4e92, 0xa2, 0xbd, 0x44, 0x54, 0x88, 0xd1, 0xed, 0x42); - -typedef struct _DSFXEcho -{ - FLOAT fWetDryMix; - FLOAT fFeedback; - FLOAT fLeftDelay; - FLOAT fRightDelay; - LONG lPanDelay; -} DSFXEcho, *LPDSFXEcho; - -typedef const DSFXEcho *LPCDSFXEcho; - -#define DSFXECHO_WETDRYMIX_MIN 0.0f -#define DSFXECHO_WETDRYMIX_MAX 100.0f -#define DSFXECHO_FEEDBACK_MIN 0.0f -#define DSFXECHO_FEEDBACK_MAX 100.0f -#define DSFXECHO_LEFTDELAY_MIN 1.0f -#define DSFXECHO_LEFTDELAY_MAX 2000.0f -#define DSFXECHO_RIGHTDELAY_MIN 1.0f -#define DSFXECHO_RIGHTDELAY_MAX 2000.0f -#define DSFXECHO_PANDELAY_MIN 0 -#define DSFXECHO_PANDELAY_MAX 1 - -#undef INTERFACE -#define INTERFACE IDirectSoundFXEcho - -DECLARE_INTERFACE_(IDirectSoundFXEcho, IUnknown) -{ - // IUnknown methods - STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; - STDMETHOD_(ULONG,AddRef) (THIS) PURE; - STDMETHOD_(ULONG,Release) (THIS) PURE; - - // IDirectSoundFXEcho methods - STDMETHOD(SetAllParameters) (THIS_ LPCDSFXEcho pcDsFxEcho) PURE; - STDMETHOD(GetAllParameters) (THIS_ LPDSFXEcho pDsFxEcho) PURE; -}; - -#define IDirectSoundFXEcho_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) -#define IDirectSoundFXEcho_AddRef(p) IUnknown_AddRef(p) -#define IDirectSoundFXEcho_Release(p) IUnknown_Release(p) - -#if !defined(__cplusplus) || defined(CINTERFACE) -#define IDirectSoundFXEcho_SetAllParameters(p,a) (p)->lpVtbl->SetAllParameters(p,a) -#define IDirectSoundFXEcho_GetAllParameters(p,a) (p)->lpVtbl->GetAllParameters(p,a) -#else // !defined(__cplusplus) || defined(CINTERFACE) -#define IDirectSoundFXEcho_SetAllParameters(p,a) (p)->SetAllParameters(a) -#define IDirectSoundFXEcho_GetAllParameters(p,a) (p)->GetAllParameters(a) -#endif // !defined(__cplusplus) || defined(CINTERFACE) - -// -// IDirectSoundFXDistortion -// - -DEFINE_GUID(IID_IDirectSoundFXDistortion, 0x8ecf4326, 0x455f, 0x4d8b, 0xbd, 0xa9, 0x8d, 0x5d, 0x3e, 0x9e, 0x3e, 0x0b); - -typedef struct _DSFXDistortion -{ - FLOAT fGain; - FLOAT fEdge; - FLOAT fPostEQCenterFrequency; - FLOAT fPostEQBandwidth; - FLOAT fPreLowpassCutoff; -} DSFXDistortion, *LPDSFXDistortion; - -typedef const DSFXDistortion *LPCDSFXDistortion; - -#define DSFXDISTORTION_GAIN_MIN -60.0f -#define DSFXDISTORTION_GAIN_MAX 0.0f -#define DSFXDISTORTION_EDGE_MIN 0.0f -#define DSFXDISTORTION_EDGE_MAX 100.0f -#define DSFXDISTORTION_POSTEQCENTERFREQUENCY_MIN 100.0f -#define DSFXDISTORTION_POSTEQCENTERFREQUENCY_MAX 8000.0f -#define DSFXDISTORTION_POSTEQBANDWIDTH_MIN 100.0f -#define DSFXDISTORTION_POSTEQBANDWIDTH_MAX 8000.0f -#define DSFXDISTORTION_PRELOWPASSCUTOFF_MIN 100.0f -#define DSFXDISTORTION_PRELOWPASSCUTOFF_MAX 8000.0f - -#undef INTERFACE -#define INTERFACE IDirectSoundFXDistortion - -DECLARE_INTERFACE_(IDirectSoundFXDistortion, IUnknown) -{ - // IUnknown methods - STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; - STDMETHOD_(ULONG,AddRef) (THIS) PURE; - STDMETHOD_(ULONG,Release) (THIS) PURE; - - // IDirectSoundFXDistortion methods - STDMETHOD(SetAllParameters) (THIS_ LPCDSFXDistortion pcDsFxDistortion) PURE; - STDMETHOD(GetAllParameters) (THIS_ LPDSFXDistortion pDsFxDistortion) PURE; -}; - -#define IDirectSoundFXDistortion_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) -#define IDirectSoundFXDistortion_AddRef(p) IUnknown_AddRef(p) -#define IDirectSoundFXDistortion_Release(p) IUnknown_Release(p) - -#if !defined(__cplusplus) || defined(CINTERFACE) -#define IDirectSoundFXDistortion_SetAllParameters(p,a) (p)->lpVtbl->SetAllParameters(p,a) -#define IDirectSoundFXDistortion_GetAllParameters(p,a) (p)->lpVtbl->GetAllParameters(p,a) -#else // !defined(__cplusplus) || defined(CINTERFACE) -#define IDirectSoundFXDistortion_SetAllParameters(p,a) (p)->SetAllParameters(a) -#define IDirectSoundFXDistortion_GetAllParameters(p,a) (p)->GetAllParameters(a) -#endif // !defined(__cplusplus) || defined(CINTERFACE) - -// -// IDirectSoundFXCompressor -// - -DEFINE_GUID(IID_IDirectSoundFXCompressor, 0x4bbd1154, 0x62f6, 0x4e2c, 0xa1, 0x5c, 0xd3, 0xb6, 0xc4, 0x17, 0xf7, 0xa0); - -typedef struct _DSFXCompressor -{ - FLOAT fGain; - FLOAT fAttack; - FLOAT fRelease; - FLOAT fThreshold; - FLOAT fRatio; - FLOAT fPredelay; -} DSFXCompressor, *LPDSFXCompressor; - -typedef const DSFXCompressor *LPCDSFXCompressor; - -#define DSFXCOMPRESSOR_GAIN_MIN -60.0f -#define DSFXCOMPRESSOR_GAIN_MAX 60.0f -#define DSFXCOMPRESSOR_ATTACK_MIN 0.01f -#define DSFXCOMPRESSOR_ATTACK_MAX 500.0f -#define DSFXCOMPRESSOR_RELEASE_MIN 50.0f -#define DSFXCOMPRESSOR_RELEASE_MAX 3000.0f -#define DSFXCOMPRESSOR_THRESHOLD_MIN -60.0f -#define DSFXCOMPRESSOR_THRESHOLD_MAX 0.0f -#define DSFXCOMPRESSOR_RATIO_MIN 1.0f -#define DSFXCOMPRESSOR_RATIO_MAX 100.0f -#define DSFXCOMPRESSOR_PREDELAY_MIN 0.0f -#define DSFXCOMPRESSOR_PREDELAY_MAX 4.0f - -#undef INTERFACE -#define INTERFACE IDirectSoundFXCompressor - -DECLARE_INTERFACE_(IDirectSoundFXCompressor, IUnknown) -{ - // IUnknown methods - STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; - STDMETHOD_(ULONG,AddRef) (THIS) PURE; - STDMETHOD_(ULONG,Release) (THIS) PURE; - - // IDirectSoundFXCompressor methods - STDMETHOD(SetAllParameters) (THIS_ LPCDSFXCompressor pcDsFxCompressor) PURE; - STDMETHOD(GetAllParameters) (THIS_ LPDSFXCompressor pDsFxCompressor) PURE; -}; - -#define IDirectSoundFXCompressor_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) -#define IDirectSoundFXCompressor_AddRef(p) IUnknown_AddRef(p) -#define IDirectSoundFXCompressor_Release(p) IUnknown_Release(p) - -#if !defined(__cplusplus) || defined(CINTERFACE) -#define IDirectSoundFXCompressor_SetAllParameters(p,a) (p)->lpVtbl->SetAllParameters(p,a) -#define IDirectSoundFXCompressor_GetAllParameters(p,a) (p)->lpVtbl->GetAllParameters(p,a) -#else // !defined(__cplusplus) || defined(CINTERFACE) -#define IDirectSoundFXCompressor_SetAllParameters(p,a) (p)->SetAllParameters(a) -#define IDirectSoundFXCompressor_GetAllParameters(p,a) (p)->GetAllParameters(a) -#endif // !defined(__cplusplus) || defined(CINTERFACE) - -// -// IDirectSoundFXParamEq -// - -DEFINE_GUID(IID_IDirectSoundFXParamEq, 0xc03ca9fe, 0xfe90, 0x4204, 0x80, 0x78, 0x82, 0x33, 0x4c, 0xd1, 0x77, 0xda); - -typedef struct _DSFXParamEq -{ - FLOAT fCenter; - FLOAT fBandwidth; - FLOAT fGain; -} DSFXParamEq, *LPDSFXParamEq; - -typedef const DSFXParamEq *LPCDSFXParamEq; - -#define DSFXPARAMEQ_CENTER_MIN 80.0f -#define DSFXPARAMEQ_CENTER_MAX 16000.0f -#define DSFXPARAMEQ_BANDWIDTH_MIN 1.0f -#define DSFXPARAMEQ_BANDWIDTH_MAX 36.0f -#define DSFXPARAMEQ_GAIN_MIN -15.0f -#define DSFXPARAMEQ_GAIN_MAX 15.0f - -#undef INTERFACE -#define INTERFACE IDirectSoundFXParamEq - -DECLARE_INTERFACE_(IDirectSoundFXParamEq, IUnknown) -{ - // IUnknown methods - STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; - STDMETHOD_(ULONG,AddRef) (THIS) PURE; - STDMETHOD_(ULONG,Release) (THIS) PURE; - - // IDirectSoundFXParamEq methods - STDMETHOD(SetAllParameters) (THIS_ LPCDSFXParamEq pcDsFxParamEq) PURE; - STDMETHOD(GetAllParameters) (THIS_ LPDSFXParamEq pDsFxParamEq) PURE; -}; - -#define IDirectSoundFXParamEq_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) -#define IDirectSoundFXParamEq_AddRef(p) IUnknown_AddRef(p) -#define IDirectSoundFXParamEq_Release(p) IUnknown_Release(p) - -#if !defined(__cplusplus) || defined(CINTERFACE) -#define IDirectSoundFXParamEq_SetAllParameters(p,a) (p)->lpVtbl->SetAllParameters(p,a) -#define IDirectSoundFXParamEq_GetAllParameters(p,a) (p)->lpVtbl->GetAllParameters(p,a) -#else // !defined(__cplusplus) || defined(CINTERFACE) -#define IDirectSoundFXParamEq_SetAllParameters(p,a) (p)->SetAllParameters(a) -#define IDirectSoundFXParamEq_GetAllParameters(p,a) (p)->GetAllParameters(a) -#endif // !defined(__cplusplus) || defined(CINTERFACE) - -// -// IDirectSoundFXI3DL2Reverb -// - -DEFINE_GUID(IID_IDirectSoundFXI3DL2Reverb, 0x4b166a6a, 0x0d66, 0x43f3, 0x80, 0xe3, 0xee, 0x62, 0x80, 0xde, 0xe1, 0xa4); - -typedef struct _DSFXI3DL2Reverb -{ - LONG lRoom; // [-10000, 0] default: -1000 mB - LONG lRoomHF; // [-10000, 0] default: 0 mB - FLOAT flRoomRolloffFactor; // [0.0, 10.0] default: 0.0 - FLOAT flDecayTime; // [0.1, 20.0] default: 1.49s - FLOAT flDecayHFRatio; // [0.1, 2.0] default: 0.83 - LONG lReflections; // [-10000, 1000] default: -2602 mB - FLOAT flReflectionsDelay; // [0.0, 0.3] default: 0.007 s - LONG lReverb; // [-10000, 2000] default: 200 mB - FLOAT flReverbDelay; // [0.0, 0.1] default: 0.011 s - FLOAT flDiffusion; // [0.0, 100.0] default: 100.0 % - FLOAT flDensity; // [0.0, 100.0] default: 100.0 % - FLOAT flHFReference; // [20.0, 20000.0] default: 5000.0 Hz -} DSFXI3DL2Reverb, *LPDSFXI3DL2Reverb; - -typedef const DSFXI3DL2Reverb *LPCDSFXI3DL2Reverb; - -#define DSFX_I3DL2REVERB_ROOM_MIN (-10000) -#define DSFX_I3DL2REVERB_ROOM_MAX 0 -#define DSFX_I3DL2REVERB_ROOM_DEFAULT (-1000) - -#define DSFX_I3DL2REVERB_ROOMHF_MIN (-10000) -#define DSFX_I3DL2REVERB_ROOMHF_MAX 0 -#define DSFX_I3DL2REVERB_ROOMHF_DEFAULT (-100) - -#define DSFX_I3DL2REVERB_ROOMROLLOFFFACTOR_MIN 0.0f -#define DSFX_I3DL2REVERB_ROOMROLLOFFFACTOR_MAX 10.0f -#define DSFX_I3DL2REVERB_ROOMROLLOFFFACTOR_DEFAULT 0.0f - -#define DSFX_I3DL2REVERB_DECAYTIME_MIN 0.1f -#define DSFX_I3DL2REVERB_DECAYTIME_MAX 20.0f -#define DSFX_I3DL2REVERB_DECAYTIME_DEFAULT 1.49f - -#define DSFX_I3DL2REVERB_DECAYHFRATIO_MIN 0.1f -#define DSFX_I3DL2REVERB_DECAYHFRATIO_MAX 2.0f -#define DSFX_I3DL2REVERB_DECAYHFRATIO_DEFAULT 0.83f - -#define DSFX_I3DL2REVERB_REFLECTIONS_MIN (-10000) -#define DSFX_I3DL2REVERB_REFLECTIONS_MAX 1000 -#define DSFX_I3DL2REVERB_REFLECTIONS_DEFAULT (-2602) - -#define DSFX_I3DL2REVERB_REFLECTIONSDELAY_MIN 0.0f -#define DSFX_I3DL2REVERB_REFLECTIONSDELAY_MAX 0.3f -#define DSFX_I3DL2REVERB_REFLECTIONSDELAY_DEFAULT 0.007f - -#define DSFX_I3DL2REVERB_REVERB_MIN (-10000) -#define DSFX_I3DL2REVERB_REVERB_MAX 2000 -#define DSFX_I3DL2REVERB_REVERB_DEFAULT (200) - -#define DSFX_I3DL2REVERB_REVERBDELAY_MIN 0.0f -#define DSFX_I3DL2REVERB_REVERBDELAY_MAX 0.1f -#define DSFX_I3DL2REVERB_REVERBDELAY_DEFAULT 0.011f - -#define DSFX_I3DL2REVERB_DIFFUSION_MIN 0.0f -#define DSFX_I3DL2REVERB_DIFFUSION_MAX 100.0f -#define DSFX_I3DL2REVERB_DIFFUSION_DEFAULT 100.0f - -#define DSFX_I3DL2REVERB_DENSITY_MIN 0.0f -#define DSFX_I3DL2REVERB_DENSITY_MAX 100.0f -#define DSFX_I3DL2REVERB_DENSITY_DEFAULT 100.0f - -#define DSFX_I3DL2REVERB_HFREFERENCE_MIN 20.0f -#define DSFX_I3DL2REVERB_HFREFERENCE_MAX 20000.0f -#define DSFX_I3DL2REVERB_HFREFERENCE_DEFAULT 5000.0f - -#define DSFX_I3DL2REVERB_QUALITY_MIN 0 -#define DSFX_I3DL2REVERB_QUALITY_MAX 3 -#define DSFX_I3DL2REVERB_QUALITY_DEFAULT 2 - -#undef INTERFACE -#define INTERFACE IDirectSoundFXI3DL2Reverb - -DECLARE_INTERFACE_(IDirectSoundFXI3DL2Reverb, IUnknown) -{ - // IUnknown methods - STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; - STDMETHOD_(ULONG,AddRef) (THIS) PURE; - STDMETHOD_(ULONG,Release) (THIS) PURE; - - // IDirectSoundFXI3DL2Reverb methods - STDMETHOD(SetAllParameters) (THIS_ LPCDSFXI3DL2Reverb pcDsFxI3DL2Reverb) PURE; - STDMETHOD(GetAllParameters) (THIS_ LPDSFXI3DL2Reverb pDsFxI3DL2Reverb) PURE; - STDMETHOD(SetPreset) (THIS_ DWORD dwPreset) PURE; - STDMETHOD(GetPreset) (THIS_ LPDWORD pdwPreset) PURE; - STDMETHOD(SetQuality) (THIS_ LONG lQuality) PURE; - STDMETHOD(GetQuality) (THIS_ LONG *plQuality) PURE; -}; - -#define IDirectSoundFXI3DL2Reverb_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) -#define IDirectSoundFXI3DL2Reverb_AddRef(p) IUnknown_AddRef(p) -#define IDirectSoundFXI3DL2Reverb_Release(p) IUnknown_Release(p) - -#if !defined(__cplusplus) || defined(CINTERFACE) -#define IDirectSoundFXI3DL2Reverb_SetAllParameters(p,a) (p)->lpVtbl->SetAllParameters(p,a) -#define IDirectSoundFXI3DL2Reverb_GetAllParameters(p,a) (p)->lpVtbl->GetAllParameters(p,a) -#define IDirectSoundFXI3DL2Reverb_SetPreset(p,a) (p)->lpVtbl->SetPreset(p,a) -#define IDirectSoundFXI3DL2Reverb_GetPreset(p,a) (p)->lpVtbl->GetPreset(p,a) -#else // !defined(__cplusplus) || defined(CINTERFACE) -#define IDirectSoundFXI3DL2Reverb_SetAllParameters(p,a) (p)->SetAllParameters(a) -#define IDirectSoundFXI3DL2Reverb_GetAllParameters(p,a) (p)->GetAllParameters(a) -#define IDirectSoundFXI3DL2Reverb_SetPreset(p,a) (p)->SetPreset(a) -#define IDirectSoundFXI3DL2Reverb_GetPreset(p,a) (p)->GetPreset(a) -#endif // !defined(__cplusplus) || defined(CINTERFACE) - -// -// IDirectSoundFXWavesReverb -// - -DEFINE_GUID(IID_IDirectSoundFXWavesReverb,0x46858c3a,0x0dc6,0x45e3,0xb7,0x60,0xd4,0xee,0xf1,0x6c,0xb3,0x25); - -typedef struct _DSFXWavesReverb -{ - FLOAT fInGain; // [-96.0,0.0] default: 0.0 dB - FLOAT fReverbMix; // [-96.0,0.0] default: 0.0 db - FLOAT fReverbTime; // [0.001,3000.0] default: 1000.0 ms - FLOAT fHighFreqRTRatio; // [0.001,0.999] default: 0.001 -} DSFXWavesReverb, *LPDSFXWavesReverb; - -typedef const DSFXWavesReverb *LPCDSFXWavesReverb; - -#define DSFX_WAVESREVERB_INGAIN_MIN -96.0f -#define DSFX_WAVESREVERB_INGAIN_MAX 0.0f -#define DSFX_WAVESREVERB_INGAIN_DEFAULT 0.0f -#define DSFX_WAVESREVERB_REVERBMIX_MIN -96.0f -#define DSFX_WAVESREVERB_REVERBMIX_MAX 0.0f -#define DSFX_WAVESREVERB_REVERBMIX_DEFAULT 0.0f -#define DSFX_WAVESREVERB_REVERBTIME_MIN 0.001f -#define DSFX_WAVESREVERB_REVERBTIME_MAX 3000.0f -#define DSFX_WAVESREVERB_REVERBTIME_DEFAULT 1000.0f -#define DSFX_WAVESREVERB_HIGHFREQRTRATIO_MIN 0.001f -#define DSFX_WAVESREVERB_HIGHFREQRTRATIO_MAX 0.999f -#define DSFX_WAVESREVERB_HIGHFREQRTRATIO_DEFAULT 0.001f - -#undef INTERFACE -#define INTERFACE IDirectSoundFXWavesReverb - -DECLARE_INTERFACE_(IDirectSoundFXWavesReverb, IUnknown) -{ - // IUnknown methods - STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; - STDMETHOD_(ULONG,AddRef) (THIS) PURE; - STDMETHOD_(ULONG,Release) (THIS) PURE; - - // IDirectSoundFXWavesReverb methods - STDMETHOD(SetAllParameters) (THIS_ LPCDSFXWavesReverb pcDsFxWavesReverb) PURE; - STDMETHOD(GetAllParameters) (THIS_ LPDSFXWavesReverb pDsFxWavesReverb) PURE; -}; - -#define IDirectSoundFXWavesReverb_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) -#define IDirectSoundFXWavesReverb_AddRef(p) IUnknown_AddRef(p) -#define IDirectSoundFXWavesReverb_Release(p) IUnknown_Release(p) - -#if !defined(__cplusplus) || defined(CINTERFACE) -#define IDirectSoundFXWavesReverb_SetAllParameters(p,a) (p)->lpVtbl->SetAllParameters(p,a) -#define IDirectSoundFXWavesReverb_GetAllParameters(p,a) (p)->lpVtbl->GetAllParameters(p,a) -#else // !defined(__cplusplus) || defined(CINTERFACE) -#define IDirectSoundFXWavesReverb_SetAllParameters(p,a) (p)->SetAllParameters(a) -#define IDirectSoundFXWavesReverb_GetAllParameters(p,a) (p)->GetAllParameters(a) -#endif // !defined(__cplusplus) || defined(CINTERFACE) - -// -// IDirectSoundCaptureFXAec -// - -DEFINE_GUID(IID_IDirectSoundCaptureFXAec, 0xad74143d, 0x903d, 0x4ab7, 0x80, 0x66, 0x28, 0xd3, 0x63, 0x03, 0x6d, 0x65); - -typedef struct _DSCFXAec -{ - BOOL fEnable; - BOOL fNoiseFill; - DWORD dwMode; -} DSCFXAec, *LPDSCFXAec; - -typedef const DSCFXAec *LPCDSCFXAec; - -// These match the AEC_MODE_* constants in the DDK's ksmedia.h file -#define DSCFX_AEC_MODE_PASS_THROUGH 0x0 -#define DSCFX_AEC_MODE_HALF_DUPLEX 0x1 -#define DSCFX_AEC_MODE_FULL_DUPLEX 0x2 - -// These match the AEC_STATUS_* constants in ksmedia.h -#define DSCFX_AEC_STATUS_HISTORY_UNINITIALIZED 0x0 -#define DSCFX_AEC_STATUS_HISTORY_CONTINUOUSLY_CONVERGED 0x1 -#define DSCFX_AEC_STATUS_HISTORY_PREVIOUSLY_DIVERGED 0x2 -#define DSCFX_AEC_STATUS_CURRENTLY_CONVERGED 0x8 - -#undef INTERFACE -#define INTERFACE IDirectSoundCaptureFXAec - -DECLARE_INTERFACE_(IDirectSoundCaptureFXAec, IUnknown) -{ - // IUnknown methods - STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; - STDMETHOD_(ULONG,AddRef) (THIS) PURE; - STDMETHOD_(ULONG,Release) (THIS) PURE; - - // IDirectSoundCaptureFXAec methods - STDMETHOD(SetAllParameters) (THIS_ LPCDSCFXAec pDscFxAec) PURE; - STDMETHOD(GetAllParameters) (THIS_ LPDSCFXAec pDscFxAec) PURE; - STDMETHOD(GetStatus) (THIS_ PDWORD pdwStatus) PURE; - STDMETHOD(Reset) (THIS) PURE; -}; - -#define IDirectSoundCaptureFXAec_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) -#define IDirectSoundCaptureFXAec_AddRef(p) IUnknown_AddRef(p) -#define IDirectSoundCaptureFXAec_Release(p) IUnknown_Release(p) - -#if !defined(__cplusplus) || defined(CINTERFACE) -#define IDirectSoundCaptureFXAec_SetAllParameters(p,a) (p)->lpVtbl->SetAllParameters(p,a) -#define IDirectSoundCaptureFXAec_GetAllParameters(p,a) (p)->lpVtbl->GetAllParameters(p,a) -#else // !defined(__cplusplus) || defined(CINTERFACE) -#define IDirectSoundCaptureFXAec_SetAllParameters(p,a) (p)->SetAllParameters(a) -#define IDirectSoundCaptureFXAec_GetAllParameters(p,a) (p)->GetAllParameters(a) -#endif // !defined(__cplusplus) || defined(CINTERFACE) - - -// -// IDirectSoundCaptureFXNoiseSuppress -// - -DEFINE_GUID(IID_IDirectSoundCaptureFXNoiseSuppress, 0xed311e41, 0xfbae, 0x4175, 0x96, 0x25, 0xcd, 0x8, 0x54, 0xf6, 0x93, 0xca); - -typedef struct _DSCFXNoiseSuppress -{ - BOOL fEnable; -} DSCFXNoiseSuppress, *LPDSCFXNoiseSuppress; - -typedef const DSCFXNoiseSuppress *LPCDSCFXNoiseSuppress; - -#undef INTERFACE -#define INTERFACE IDirectSoundCaptureFXNoiseSuppress - -DECLARE_INTERFACE_(IDirectSoundCaptureFXNoiseSuppress, IUnknown) -{ - // IUnknown methods - STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; - STDMETHOD_(ULONG,AddRef) (THIS) PURE; - STDMETHOD_(ULONG,Release) (THIS) PURE; - - // IDirectSoundCaptureFXNoiseSuppress methods - STDMETHOD(SetAllParameters) (THIS_ LPCDSCFXNoiseSuppress pcDscFxNoiseSuppress) PURE; - STDMETHOD(GetAllParameters) (THIS_ LPDSCFXNoiseSuppress pDscFxNoiseSuppress) PURE; - STDMETHOD(Reset) (THIS) PURE; -}; - -#define IDirectSoundCaptureFXNoiseSuppress_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) -#define IDirectSoundCaptureFXNoiseSuppress_AddRef(p) IUnknown_AddRef(p) -#define IDirectSoundCaptureFXNoiseSuppress_Release(p) IUnknown_Release(p) - -#if !defined(__cplusplus) || defined(CINTERFACE) -#define IDirectSoundCaptureFXNoiseSuppress_SetAllParameters(p,a) (p)->lpVtbl->SetAllParameters(p,a) -#define IDirectSoundCaptureFXNoiseSuppress_GetAllParameters(p,a) (p)->lpVtbl->GetAllParameters(p,a) -#else // !defined(__cplusplus) || defined(CINTERFACE) -#define IDirectSoundCaptureFXNoiseSuppress_SetAllParameters(p,a) (p)->SetAllParameters(a) -#define IDirectSoundCaptureFXNoiseSuppress_GetAllParameters(p,a) (p)->GetAllParameters(a) -#endif // !defined(__cplusplus) || defined(CINTERFACE) - - -// -// IDirectSoundFullDuplex -// - -#ifndef _IDirectSoundFullDuplex_ -#define _IDirectSoundFullDuplex_ - -#ifdef __cplusplus -// 'struct' not 'class' per the way DECLARE_INTERFACE_ is defined -struct IDirectSoundFullDuplex; -#endif // __cplusplus - -typedef struct IDirectSoundFullDuplex *LPDIRECTSOUNDFULLDUPLEX; - -DEFINE_GUID(IID_IDirectSoundFullDuplex, 0xedcb4c7a, 0xdaab, 0x4216, 0xa4, 0x2e, 0x6c, 0x50, 0x59, 0x6d, 0xdc, 0x1d); - -#undef INTERFACE -#define INTERFACE IDirectSoundFullDuplex - -DECLARE_INTERFACE_(IDirectSoundFullDuplex, IUnknown) -{ - // IUnknown methods - STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; - STDMETHOD_(ULONG,AddRef) (THIS) PURE; - STDMETHOD_(ULONG,Release) (THIS) PURE; - - // IDirectSoundFullDuplex methods - STDMETHOD(Initialize) (THIS_ LPCGUID pCaptureGuid, LPCGUID pRenderGuid, LPCDSCBUFFERDESC lpDscBufferDesc, LPCDSBUFFERDESC lpDsBufferDesc, HWND hWnd, DWORD dwLevel, LPLPDIRECTSOUNDCAPTUREBUFFER8 lplpDirectSoundCaptureBuffer8, LPLPDIRECTSOUNDBUFFER8 lplpDirectSoundBuffer8) PURE; -}; - -#define IDirectSoundFullDuplex_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) -#define IDirectSoundFullDuplex_AddRef(p) IUnknown_AddRef(p) -#define IDirectSoundFullDuplex_Release(p) IUnknown_Release(p) - -#if !defined(__cplusplus) || defined(CINTERFACE) -#define IDirectSoundFullDuplex_Initialize(p,a,b,c,d,e,f,g,h) (p)->lpVtbl->Initialize(p,a,b,c,d,e,f,g,h) -#else // !defined(__cplusplus) || defined(CINTERFACE) -#define IDirectSoundFullDuplex_Initialize(p,a,b,c,d,e,f,g,h) (p)->Initialize(a,b,c,d,e,f,g,h) -#endif // !defined(__cplusplus) || defined(CINTERFACE) - -#endif // _IDirectSoundFullDuplex_ - -#endif // DIRECTSOUND_VERSION >= 0x0800 - -// -// Return Codes -// - -// The function completed successfully -#define DS_OK S_OK - -// The call succeeded, but we had to substitute the 3D algorithm -#define DS_NO_VIRTUALIZATION MAKE_HRESULT(0, _FACDS, 10) - -// The call failed because resources (such as a priority level) -// were already being used by another caller -#define DSERR_ALLOCATED MAKE_DSHRESULT(10) - -// The control (vol, pan, etc.) requested by the caller is not available -#define DSERR_CONTROLUNAVAIL MAKE_DSHRESULT(30) - -// An invalid parameter was passed to the returning function -#define DSERR_INVALIDPARAM E_INVALIDARG - -// This call is not valid for the current state of this object -#define DSERR_INVALIDCALL MAKE_DSHRESULT(50) - -// An undetermined error occurred inside the DirectSound subsystem -#define DSERR_GENERIC E_FAIL - -// The caller does not have the priority level required for the function to -// succeed -#define DSERR_PRIOLEVELNEEDED MAKE_DSHRESULT(70) - -// Not enough free memory is available to complete the operation -#define DSERR_OUTOFMEMORY E_OUTOFMEMORY - -// The specified WAVE format is not supported -#define DSERR_BADFORMAT MAKE_DSHRESULT(100) - -// The function called is not supported at this time -#define DSERR_UNSUPPORTED E_NOTIMPL - -// No sound driver is available for use -#define DSERR_NODRIVER MAKE_DSHRESULT(120) -// This object is already initialized -#define DSERR_ALREADYINITIALIZED MAKE_DSHRESULT(130) - -// This object does not support aggregation -#define DSERR_NOAGGREGATION CLASS_E_NOAGGREGATION - -// The buffer memory has been lost, and must be restored -#define DSERR_BUFFERLOST MAKE_DSHRESULT(150) - -// Another app has a higher priority level, preventing this call from -// succeeding -#define DSERR_OTHERAPPHASPRIO MAKE_DSHRESULT(160) - -// This object has not been initialized -#define DSERR_UNINITIALIZED MAKE_DSHRESULT(170) - -// The requested COM interface is not available -#define DSERR_NOINTERFACE E_NOINTERFACE - -// Access is denied -#define DSERR_ACCESSDENIED E_ACCESSDENIED - -// Tried to create a DSBCAPS_CTRLFX buffer shorter than DSBSIZE_FX_MIN milliseconds -#define DSERR_BUFFERTOOSMALL MAKE_DSHRESULT(180) - -// Attempt to use DirectSound 8 functionality on an older DirectSound object -#define DSERR_DS8_REQUIRED MAKE_DSHRESULT(190) - -// A circular loop of send effects was detected -#define DSERR_SENDLOOP MAKE_DSHRESULT(200) - -// The GUID specified in an audiopath file does not match a valid MIXIN buffer -#define DSERR_BADSENDBUFFERGUID MAKE_DSHRESULT(210) - -// The object requested was not found (numerically equal to DMUS_E_NOT_FOUND) -#define DSERR_OBJECTNOTFOUND MAKE_DSHRESULT(4449) - -// The effects requested could not be found on the system, or they were found -// but in the wrong order, or in the wrong hardware/software locations. -#define DSERR_FXUNAVAILABLE MAKE_DSHRESULT(220) - -// -// Flags -// - -#define DSCAPS_PRIMARYMONO 0x00000001 -#define DSCAPS_PRIMARYSTEREO 0x00000002 -#define DSCAPS_PRIMARY8BIT 0x00000004 -#define DSCAPS_PRIMARY16BIT 0x00000008 -#define DSCAPS_CONTINUOUSRATE 0x00000010 -#define DSCAPS_EMULDRIVER 0x00000020 -#define DSCAPS_CERTIFIED 0x00000040 -#define DSCAPS_SECONDARYMONO 0x00000100 -#define DSCAPS_SECONDARYSTEREO 0x00000200 -#define DSCAPS_SECONDARY8BIT 0x00000400 -#define DSCAPS_SECONDARY16BIT 0x00000800 - -#define DSSCL_NORMAL 0x00000001 -#define DSSCL_PRIORITY 0x00000002 -#define DSSCL_EXCLUSIVE 0x00000003 -#define DSSCL_WRITEPRIMARY 0x00000004 - -#define DSSPEAKER_DIRECTOUT 0x00000000 -#define DSSPEAKER_HEADPHONE 0x00000001 -#define DSSPEAKER_MONO 0x00000002 -#define DSSPEAKER_QUAD 0x00000003 -#define DSSPEAKER_STEREO 0x00000004 -#define DSSPEAKER_SURROUND 0x00000005 -#define DSSPEAKER_5POINT1 0x00000006 // obsolete 5.1 setting -#define DSSPEAKER_7POINT1 0x00000007 // obsolete 7.1 setting -#define DSSPEAKER_7POINT1_SURROUND 0x00000008 // correct 7.1 Home Theater setting -#define DSSPEAKER_7POINT1_WIDE DSSPEAKER_7POINT1 -#if (DIRECTSOUND_VERSION >= 0x1000) - #define DSSPEAKER_5POINT1_SURROUND 0x00000009 // correct 5.1 setting - #define DSSPEAKER_5POINT1_BACK DSSPEAKER_5POINT1 -#endif - -#define DSSPEAKER_GEOMETRY_MIN 0x00000005 // 5 degrees -#define DSSPEAKER_GEOMETRY_NARROW 0x0000000A // 10 degrees -#define DSSPEAKER_GEOMETRY_WIDE 0x00000014 // 20 degrees -#define DSSPEAKER_GEOMETRY_MAX 0x000000B4 // 180 degrees - -#define DSSPEAKER_COMBINED(c, g) ((DWORD)(((BYTE)(c)) | ((DWORD)((BYTE)(g))) << 16)) -#define DSSPEAKER_CONFIG(a) ((BYTE)(a)) -#define DSSPEAKER_GEOMETRY(a) ((BYTE)(((DWORD)(a) >> 16) & 0x00FF)) - -#define DSBCAPS_PRIMARYBUFFER 0x00000001 -#define DSBCAPS_STATIC 0x00000002 -#define DSBCAPS_LOCHARDWARE 0x00000004 -#define DSBCAPS_LOCSOFTWARE 0x00000008 -#define DSBCAPS_CTRL3D 0x00000010 -#define DSBCAPS_CTRLFREQUENCY 0x00000020 -#define DSBCAPS_CTRLPAN 0x00000040 -#define DSBCAPS_CTRLVOLUME 0x00000080 -#define DSBCAPS_CTRLPOSITIONNOTIFY 0x00000100 -#define DSBCAPS_CTRLFX 0x00000200 -#define DSBCAPS_STICKYFOCUS 0x00004000 -#define DSBCAPS_GLOBALFOCUS 0x00008000 -#define DSBCAPS_GETCURRENTPOSITION2 0x00010000 -#define DSBCAPS_MUTE3DATMAXDISTANCE 0x00020000 -#define DSBCAPS_LOCDEFER 0x00040000 -#if (DIRECTSOUND_VERSION >= 0x1000) - // Force GetCurrentPosition() to return a buffer's true play position; - // unmodified by aids to enhance backward compatibility. - #define DSBCAPS_TRUEPLAYPOSITION 0x00080000 -#endif - -#define DSBPLAY_LOOPING 0x00000001 -#define DSBPLAY_LOCHARDWARE 0x00000002 -#define DSBPLAY_LOCSOFTWARE 0x00000004 -#define DSBPLAY_TERMINATEBY_TIME 0x00000008 -#define DSBPLAY_TERMINATEBY_DISTANCE 0x000000010 -#define DSBPLAY_TERMINATEBY_PRIORITY 0x000000020 - -#define DSBSTATUS_PLAYING 0x00000001 -#define DSBSTATUS_BUFFERLOST 0x00000002 -#define DSBSTATUS_LOOPING 0x00000004 -#define DSBSTATUS_LOCHARDWARE 0x00000008 -#define DSBSTATUS_LOCSOFTWARE 0x00000010 -#define DSBSTATUS_TERMINATED 0x00000020 - -#define DSBLOCK_FROMWRITECURSOR 0x00000001 -#define DSBLOCK_ENTIREBUFFER 0x00000002 - -#define DSBFREQUENCY_ORIGINAL 0 -#define DSBFREQUENCY_MIN 100 -#if DIRECTSOUND_VERSION >= 0x0900 -#define DSBFREQUENCY_MAX 200000 -#else -#define DSBFREQUENCY_MAX 100000 -#endif - -#define DSBPAN_LEFT -10000 -#define DSBPAN_CENTER 0 -#define DSBPAN_RIGHT 10000 - -#define DSBVOLUME_MIN -10000 -#define DSBVOLUME_MAX 0 - -#define DSBSIZE_MIN 4 -#define DSBSIZE_MAX 0x0FFFFFFF -#define DSBSIZE_FX_MIN 150 // NOTE: Milliseconds, not bytes - -#define DSBNOTIFICATIONS_MAX 100000UL - -#define DS3DMODE_NORMAL 0x00000000 -#define DS3DMODE_HEADRELATIVE 0x00000001 -#define DS3DMODE_DISABLE 0x00000002 - -#define DS3D_IMMEDIATE 0x00000000 -#define DS3D_DEFERRED 0x00000001 - -#define DS3D_MINDISTANCEFACTOR FLT_MIN -#define DS3D_MAXDISTANCEFACTOR FLT_MAX -#define DS3D_DEFAULTDISTANCEFACTOR 1.0f - -#define DS3D_MINROLLOFFFACTOR 0.0f -#define DS3D_MAXROLLOFFFACTOR 10.0f -#define DS3D_DEFAULTROLLOFFFACTOR 1.0f - -#define DS3D_MINDOPPLERFACTOR 0.0f -#define DS3D_MAXDOPPLERFACTOR 10.0f -#define DS3D_DEFAULTDOPPLERFACTOR 1.0f - -#define DS3D_DEFAULTMINDISTANCE 1.0f -#define DS3D_DEFAULTMAXDISTANCE 1000000000.0f - -#define DS3D_MINCONEANGLE 0 -#define DS3D_MAXCONEANGLE 360 -#define DS3D_DEFAULTCONEANGLE 360 - -#define DS3D_DEFAULTCONEOUTSIDEVOLUME DSBVOLUME_MAX - -// IDirectSoundCapture attributes - -#define DSCCAPS_EMULDRIVER DSCAPS_EMULDRIVER -#define DSCCAPS_CERTIFIED DSCAPS_CERTIFIED -#define DSCCAPS_MULTIPLECAPTURE 0x00000001 - -// IDirectSoundCaptureBuffer attributes - -#define DSCBCAPS_WAVEMAPPED 0x80000000 - -#if DIRECTSOUND_VERSION >= 0x0800 -#define DSCBCAPS_CTRLFX 0x00000200 -#endif - - -#define DSCBLOCK_ENTIREBUFFER 0x00000001 - -#define DSCBSTATUS_CAPTURING 0x00000001 -#define DSCBSTATUS_LOOPING 0x00000002 - -#define DSCBSTART_LOOPING 0x00000001 - -#define DSBPN_OFFSETSTOP 0xFFFFFFFF - -#define DS_CERTIFIED 0x00000000 -#define DS_UNCERTIFIED 0x00000001 - - -// -// Flags for the I3DL2 effects -// - -// -// I3DL2 Material Presets -// - -enum -{ - DSFX_I3DL2_MATERIAL_PRESET_SINGLEWINDOW, - DSFX_I3DL2_MATERIAL_PRESET_DOUBLEWINDOW, - DSFX_I3DL2_MATERIAL_PRESET_THINDOOR, - DSFX_I3DL2_MATERIAL_PRESET_THICKDOOR, - DSFX_I3DL2_MATERIAL_PRESET_WOODWALL, - DSFX_I3DL2_MATERIAL_PRESET_BRICKWALL, - DSFX_I3DL2_MATERIAL_PRESET_STONEWALL, - DSFX_I3DL2_MATERIAL_PRESET_CURTAIN -}; - -#define I3DL2_MATERIAL_PRESET_SINGLEWINDOW -2800,0.71f -#define I3DL2_MATERIAL_PRESET_DOUBLEWINDOW -5000,0.40f -#define I3DL2_MATERIAL_PRESET_THINDOOR -1800,0.66f -#define I3DL2_MATERIAL_PRESET_THICKDOOR -4400,0.64f -#define I3DL2_MATERIAL_PRESET_WOODWALL -4000,0.50f -#define I3DL2_MATERIAL_PRESET_BRICKWALL -5000,0.60f -#define I3DL2_MATERIAL_PRESET_STONEWALL -6000,0.68f -#define I3DL2_MATERIAL_PRESET_CURTAIN -1200,0.15f - -enum -{ - DSFX_I3DL2_ENVIRONMENT_PRESET_DEFAULT, - DSFX_I3DL2_ENVIRONMENT_PRESET_GENERIC, - DSFX_I3DL2_ENVIRONMENT_PRESET_PADDEDCELL, - DSFX_I3DL2_ENVIRONMENT_PRESET_ROOM, - DSFX_I3DL2_ENVIRONMENT_PRESET_BATHROOM, - DSFX_I3DL2_ENVIRONMENT_PRESET_LIVINGROOM, - DSFX_I3DL2_ENVIRONMENT_PRESET_STONEROOM, - DSFX_I3DL2_ENVIRONMENT_PRESET_AUDITORIUM, - DSFX_I3DL2_ENVIRONMENT_PRESET_CONCERTHALL, - DSFX_I3DL2_ENVIRONMENT_PRESET_CAVE, - DSFX_I3DL2_ENVIRONMENT_PRESET_ARENA, - DSFX_I3DL2_ENVIRONMENT_PRESET_HANGAR, - DSFX_I3DL2_ENVIRONMENT_PRESET_CARPETEDHALLWAY, - DSFX_I3DL2_ENVIRONMENT_PRESET_HALLWAY, - DSFX_I3DL2_ENVIRONMENT_PRESET_STONECORRIDOR, - DSFX_I3DL2_ENVIRONMENT_PRESET_ALLEY, - DSFX_I3DL2_ENVIRONMENT_PRESET_FOREST, - DSFX_I3DL2_ENVIRONMENT_PRESET_CITY, - DSFX_I3DL2_ENVIRONMENT_PRESET_MOUNTAINS, - DSFX_I3DL2_ENVIRONMENT_PRESET_QUARRY, - DSFX_I3DL2_ENVIRONMENT_PRESET_PLAIN, - DSFX_I3DL2_ENVIRONMENT_PRESET_PARKINGLOT, - DSFX_I3DL2_ENVIRONMENT_PRESET_SEWERPIPE, - DSFX_I3DL2_ENVIRONMENT_PRESET_UNDERWATER, - DSFX_I3DL2_ENVIRONMENT_PRESET_SMALLROOM, - DSFX_I3DL2_ENVIRONMENT_PRESET_MEDIUMROOM, - DSFX_I3DL2_ENVIRONMENT_PRESET_LARGEROOM, - DSFX_I3DL2_ENVIRONMENT_PRESET_MEDIUMHALL, - DSFX_I3DL2_ENVIRONMENT_PRESET_LARGEHALL, - DSFX_I3DL2_ENVIRONMENT_PRESET_PLATE -}; - -// -// I3DL2 Reverberation Presets Values -// - -#define I3DL2_ENVIRONMENT_PRESET_DEFAULT -1000, -100, 0.0f, 1.49f, 0.83f, -2602, 0.007f, 200, 0.011f, 100.0f, 100.0f, 5000.0f -#define I3DL2_ENVIRONMENT_PRESET_GENERIC -1000, -100, 0.0f, 1.49f, 0.83f, -2602, 0.007f, 200, 0.011f, 100.0f, 100.0f, 5000.0f -#define I3DL2_ENVIRONMENT_PRESET_PADDEDCELL -1000,-6000, 0.0f, 0.17f, 0.10f, -1204, 0.001f, 207, 0.002f, 100.0f, 100.0f, 5000.0f -#define I3DL2_ENVIRONMENT_PRESET_ROOM -1000, -454, 0.0f, 0.40f, 0.83f, -1646, 0.002f, 53, 0.003f, 100.0f, 100.0f, 5000.0f -#define I3DL2_ENVIRONMENT_PRESET_BATHROOM -1000,-1200, 0.0f, 1.49f, 0.54f, -370, 0.007f, 1030, 0.011f, 100.0f, 60.0f, 5000.0f -#define I3DL2_ENVIRONMENT_PRESET_LIVINGROOM -1000,-6000, 0.0f, 0.50f, 0.10f, -1376, 0.003f, -1104, 0.004f, 100.0f, 100.0f, 5000.0f -#define I3DL2_ENVIRONMENT_PRESET_STONEROOM -1000, -300, 0.0f, 2.31f, 0.64f, -711, 0.012f, 83, 0.017f, 100.0f, 100.0f, 5000.0f -#define I3DL2_ENVIRONMENT_PRESET_AUDITORIUM -1000, -476, 0.0f, 4.32f, 0.59f, -789, 0.020f, -289, 0.030f, 100.0f, 100.0f, 5000.0f -#define I3DL2_ENVIRONMENT_PRESET_CONCERTHALL -1000, -500, 0.0f, 3.92f, 0.70f, -1230, 0.020f, -2, 0.029f, 100.0f, 100.0f, 5000.0f -#define I3DL2_ENVIRONMENT_PRESET_CAVE -1000, 0, 0.0f, 2.91f, 1.30f, -602, 0.015f, -302, 0.022f, 100.0f, 100.0f, 5000.0f -#define I3DL2_ENVIRONMENT_PRESET_ARENA -1000, -698, 0.0f, 7.24f, 0.33f, -1166, 0.020f, 16, 0.030f, 100.0f, 100.0f, 5000.0f -#define I3DL2_ENVIRONMENT_PRESET_HANGAR -1000,-1000, 0.0f,10.05f, 0.23f, -602, 0.020f, 198, 0.030f, 100.0f, 100.0f, 5000.0f -#define I3DL2_ENVIRONMENT_PRESET_CARPETEDHALLWAY -1000,-4000, 0.0f, 0.30f, 0.10f, -1831, 0.002f, -1630, 0.030f, 100.0f, 100.0f, 5000.0f -#define I3DL2_ENVIRONMENT_PRESET_HALLWAY -1000, -300, 0.0f, 1.49f, 0.59f, -1219, 0.007f, 441, 0.011f, 100.0f, 100.0f, 5000.0f -#define I3DL2_ENVIRONMENT_PRESET_STONECORRIDOR -1000, -237, 0.0f, 2.70f, 0.79f, -1214, 0.013f, 395, 0.020f, 100.0f, 100.0f, 5000.0f -#define I3DL2_ENVIRONMENT_PRESET_ALLEY -1000, -270, 0.0f, 1.49f, 0.86f, -1204, 0.007f, -4, 0.011f, 100.0f, 100.0f, 5000.0f -#define I3DL2_ENVIRONMENT_PRESET_FOREST -1000,-3300, 0.0f, 1.49f, 0.54f, -2560, 0.162f, -613, 0.088f, 79.0f, 100.0f, 5000.0f -#define I3DL2_ENVIRONMENT_PRESET_CITY -1000, -800, 0.0f, 1.49f, 0.67f, -2273, 0.007f, -2217, 0.011f, 50.0f, 100.0f, 5000.0f -#define I3DL2_ENVIRONMENT_PRESET_MOUNTAINS -1000,-2500, 0.0f, 1.49f, 0.21f, -2780, 0.300f, -2014, 0.100f, 27.0f, 100.0f, 5000.0f -#define I3DL2_ENVIRONMENT_PRESET_QUARRY -1000,-1000, 0.0f, 1.49f, 0.83f,-10000, 0.061f, 500, 0.025f, 100.0f, 100.0f, 5000.0f -#define I3DL2_ENVIRONMENT_PRESET_PLAIN -1000,-2000, 0.0f, 1.49f, 0.50f, -2466, 0.179f, -2514, 0.100f, 21.0f, 100.0f, 5000.0f -#define I3DL2_ENVIRONMENT_PRESET_PARKINGLOT -1000, 0, 0.0f, 1.65f, 1.50f, -1363, 0.008f, -1153, 0.012f, 100.0f, 100.0f, 5000.0f -#define I3DL2_ENVIRONMENT_PRESET_SEWERPIPE -1000,-1000, 0.0f, 2.81f, 0.14f, 429, 0.014f, 648, 0.021f, 80.0f, 60.0f, 5000.0f -#define I3DL2_ENVIRONMENT_PRESET_UNDERWATER -1000,-4000, 0.0f, 1.49f, 0.10f, -449, 0.007f, 1700, 0.011f, 100.0f, 100.0f, 5000.0f - -// -// Examples simulating 'musical' reverb presets -// -// Name Decay time Description -// Small Room 1.1s A small size room with a length of 5m or so. -// Medium Room 1.3s A medium size room with a length of 10m or so. -// Large Room 1.5s A large size room suitable for live performances. -// Medium Hall 1.8s A medium size concert hall. -// Large Hall 1.8s A large size concert hall suitable for a full orchestra. -// Plate 1.3s A plate reverb simulation. -// - -#define I3DL2_ENVIRONMENT_PRESET_SMALLROOM -1000, -600, 0.0f, 1.10f, 0.83f, -400, 0.005f, 500, 0.010f, 100.0f, 100.0f, 5000.0f -#define I3DL2_ENVIRONMENT_PRESET_MEDIUMROOM -1000, -600, 0.0f, 1.30f, 0.83f, -1000, 0.010f, -200, 0.020f, 100.0f, 100.0f, 5000.0f -#define I3DL2_ENVIRONMENT_PRESET_LARGEROOM -1000, -600, 0.0f, 1.50f, 0.83f, -1600, 0.020f, -1000, 0.040f, 100.0f, 100.0f, 5000.0f -#define I3DL2_ENVIRONMENT_PRESET_MEDIUMHALL -1000, -600, 0.0f, 1.80f, 0.70f, -1300, 0.015f, -800, 0.030f, 100.0f, 100.0f, 5000.0f -#define I3DL2_ENVIRONMENT_PRESET_LARGEHALL -1000, -600, 0.0f, 1.80f, 0.70f, -2000, 0.030f, -1400, 0.060f, 100.0f, 100.0f, 5000.0f -#define I3DL2_ENVIRONMENT_PRESET_PLATE -1000, -200, 0.0f, 1.30f, 0.90f, 0, 0.002f, 0, 0.010f, 100.0f, 75.0f, 5000.0f - -// -// DirectSound3D Algorithms -// - -// Default DirectSound3D algorithm {00000000-0000-0000-0000-000000000000} -#define DS3DALG_DEFAULT GUID_NULL - -// No virtualization (Pan3D) {C241333F-1C1B-11d2-94F5-00C04FC28ACA} -DEFINE_GUID(DS3DALG_NO_VIRTUALIZATION, 0xc241333f, 0x1c1b, 0x11d2, 0x94, 0xf5, 0x0, 0xc0, 0x4f, 0xc2, 0x8a, 0xca); - -// High-quality HRTF algorithm {C2413340-1C1B-11d2-94F5-00C04FC28ACA} -DEFINE_GUID(DS3DALG_HRTF_FULL, 0xc2413340, 0x1c1b, 0x11d2, 0x94, 0xf5, 0x0, 0xc0, 0x4f, 0xc2, 0x8a, 0xca); - -// Lower-quality HRTF algorithm {C2413342-1C1B-11d2-94F5-00C04FC28ACA} -DEFINE_GUID(DS3DALG_HRTF_LIGHT, 0xc2413342, 0x1c1b, 0x11d2, 0x94, 0xf5, 0x0, 0xc0, 0x4f, 0xc2, 0x8a, 0xca); - - -#if DIRECTSOUND_VERSION >= 0x0800 - -// -// DirectSound Internal Effect Algorithms -// - - -// Gargle {DAFD8210-5711-4B91-9FE3-F75B7AE279BF} -DEFINE_GUID(GUID_DSFX_STANDARD_GARGLE, 0xdafd8210, 0x5711, 0x4b91, 0x9f, 0xe3, 0xf7, 0x5b, 0x7a, 0xe2, 0x79, 0xbf); - -// Chorus {EFE6629C-81F7-4281-BD91-C9D604A95AF6} -DEFINE_GUID(GUID_DSFX_STANDARD_CHORUS, 0xefe6629c, 0x81f7, 0x4281, 0xbd, 0x91, 0xc9, 0xd6, 0x04, 0xa9, 0x5a, 0xf6); - -// Flanger {EFCA3D92-DFD8-4672-A603-7420894BAD98} -DEFINE_GUID(GUID_DSFX_STANDARD_FLANGER, 0xefca3d92, 0xdfd8, 0x4672, 0xa6, 0x03, 0x74, 0x20, 0x89, 0x4b, 0xad, 0x98); - -// Echo/Delay {EF3E932C-D40B-4F51-8CCF-3F98F1B29D5D} -DEFINE_GUID(GUID_DSFX_STANDARD_ECHO, 0xef3e932c, 0xd40b, 0x4f51, 0x8c, 0xcf, 0x3f, 0x98, 0xf1, 0xb2, 0x9d, 0x5d); - -// Distortion {EF114C90-CD1D-484E-96E5-09CFAF912A21} -DEFINE_GUID(GUID_DSFX_STANDARD_DISTORTION, 0xef114c90, 0xcd1d, 0x484e, 0x96, 0xe5, 0x09, 0xcf, 0xaf, 0x91, 0x2a, 0x21); - -// Compressor/Limiter {EF011F79-4000-406D-87AF-BFFB3FC39D57} -DEFINE_GUID(GUID_DSFX_STANDARD_COMPRESSOR, 0xef011f79, 0x4000, 0x406d, 0x87, 0xaf, 0xbf, 0xfb, 0x3f, 0xc3, 0x9d, 0x57); - -// Parametric Equalization {120CED89-3BF4-4173-A132-3CB406CF3231} -DEFINE_GUID(GUID_DSFX_STANDARD_PARAMEQ, 0x120ced89, 0x3bf4, 0x4173, 0xa1, 0x32, 0x3c, 0xb4, 0x06, 0xcf, 0x32, 0x31); - -// I3DL2 Environmental Reverberation: Reverb (Listener) Effect {EF985E71-D5C7-42D4-BA4D-2D073E2E96F4} -DEFINE_GUID(GUID_DSFX_STANDARD_I3DL2REVERB, 0xef985e71, 0xd5c7, 0x42d4, 0xba, 0x4d, 0x2d, 0x07, 0x3e, 0x2e, 0x96, 0xf4); - -// Waves Reverberation {87FC0268-9A55-4360-95AA-004A1D9DE26C} -DEFINE_GUID(GUID_DSFX_WAVES_REVERB, 0x87fc0268, 0x9a55, 0x4360, 0x95, 0xaa, 0x00, 0x4a, 0x1d, 0x9d, 0xe2, 0x6c); - -// -// DirectSound Capture Effect Algorithms -// - - -// Acoustic Echo Canceller {BF963D80-C559-11D0-8A2B-00A0C9255AC1} -// Matches KSNODETYPE_ACOUSTIC_ECHO_CANCEL in ksmedia.h -DEFINE_GUID(GUID_DSCFX_CLASS_AEC, 0xBF963D80L, 0xC559, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1); - -// Microsoft AEC {CDEBB919-379A-488a-8765-F53CFD36DE40} -DEFINE_GUID(GUID_DSCFX_MS_AEC, 0xcdebb919, 0x379a, 0x488a, 0x87, 0x65, 0xf5, 0x3c, 0xfd, 0x36, 0xde, 0x40); - -// System AEC {1C22C56D-9879-4f5b-A389-27996DDC2810} -DEFINE_GUID(GUID_DSCFX_SYSTEM_AEC, 0x1c22c56d, 0x9879, 0x4f5b, 0xa3, 0x89, 0x27, 0x99, 0x6d, 0xdc, 0x28, 0x10); - -// Noise Supression {E07F903F-62FD-4e60-8CDD-DEA7236665B5} -// Matches KSNODETYPE_NOISE_SUPPRESS in post Windows ME DDK's ksmedia.h -DEFINE_GUID(GUID_DSCFX_CLASS_NS, 0xe07f903f, 0x62fd, 0x4e60, 0x8c, 0xdd, 0xde, 0xa7, 0x23, 0x66, 0x65, 0xb5); - -// Microsoft Noise Suppresion {11C5C73B-66E9-4ba1-A0BA-E814C6EED92D} -DEFINE_GUID(GUID_DSCFX_MS_NS, 0x11c5c73b, 0x66e9, 0x4ba1, 0xa0, 0xba, 0xe8, 0x14, 0xc6, 0xee, 0xd9, 0x2d); - -// System Noise Suppresion {5AB0882E-7274-4516-877D-4EEE99BA4FD0} -DEFINE_GUID(GUID_DSCFX_SYSTEM_NS, 0x5ab0882e, 0x7274, 0x4516, 0x87, 0x7d, 0x4e, 0xee, 0x99, 0xba, 0x4f, 0xd0); - -#endif // DIRECTSOUND_VERSION >= 0x0800 - -#endif // __DSOUND_INCLUDED__ - - - -#ifdef __cplusplus -}; -#endif // __cplusplus - diff --git a/vendor/rtaudio/include/ginclude.h b/vendor/rtaudio/include/ginclude.h deleted file mode 100644 index b627dc2e7..000000000 --- a/vendor/rtaudio/include/ginclude.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef __gInclude__ -#define __gInclude__ - -#if SGI - #undef BEOS - #undef MAC - #undef WINDOWS - // - #define ASIO_BIG_ENDIAN 1 - #define ASIO_CPU_MIPS 1 -#elif defined WIN32 - #undef BEOS - #undef MAC - #undef SGI - #define WINDOWS 1 - #define ASIO_LITTLE_ENDIAN 1 - #define ASIO_CPU_X86 1 -#elif BEOS - #undef MAC - #undef SGI - #undef WINDOWS - #define ASIO_LITTLE_ENDIAN 1 - #define ASIO_CPU_X86 1 - // -#else - #define MAC 1 - #undef BEOS - #undef WINDOWS - #undef SGI - #define ASIO_BIG_ENDIAN 1 - #define ASIO_CPU_PPC 1 -#endif - -// always -#define NATIVE_INT64 0 -#define IEEE754_64FLOAT 1 - -#endif // __gInclude__ diff --git a/vendor/rtaudio/include/iasiodrv.h b/vendor/rtaudio/include/iasiodrv.h deleted file mode 100644 index 64d2dbb66..000000000 --- a/vendor/rtaudio/include/iasiodrv.h +++ /dev/null @@ -1,37 +0,0 @@ -#include "asiosys.h" -#include "asio.h" - -/* Forward Declarations */ - -#ifndef __ASIODRIVER_FWD_DEFINED__ -#define __ASIODRIVER_FWD_DEFINED__ -typedef interface IASIO IASIO; -#endif /* __ASIODRIVER_FWD_DEFINED__ */ - -interface IASIO : public IUnknown -{ - - virtual ASIOBool init(void *sysHandle) = 0; - virtual void getDriverName(char *name) = 0; - virtual long getDriverVersion() = 0; - virtual void getErrorMessage(char *string) = 0; - virtual ASIOError start() = 0; - virtual ASIOError stop() = 0; - virtual ASIOError getChannels(long *numInputChannels, long *numOutputChannels) = 0; - virtual ASIOError getLatencies(long *inputLatency, long *outputLatency) = 0; - virtual ASIOError getBufferSize(long *minSize, long *maxSize, - long *preferredSize, long *granularity) = 0; - virtual ASIOError canSampleRate(ASIOSampleRate sampleRate) = 0; - virtual ASIOError getSampleRate(ASIOSampleRate *sampleRate) = 0; - virtual ASIOError setSampleRate(ASIOSampleRate sampleRate) = 0; - virtual ASIOError getClockSources(ASIOClockSource *clocks, long *numSources) = 0; - virtual ASIOError setClockSource(long reference) = 0; - virtual ASIOError getSamplePosition(ASIOSamples *sPos, ASIOTimeStamp *tStamp) = 0; - virtual ASIOError getChannelInfo(ASIOChannelInfo *info) = 0; - virtual ASIOError createBuffers(ASIOBufferInfo *bufferInfos, long numChannels, - long bufferSize, ASIOCallbacks *callbacks) = 0; - virtual ASIOError disposeBuffers() = 0; - virtual ASIOError controlPanel() = 0; - virtual ASIOError future(long selector,void *opt) = 0; - virtual ASIOError outputReady() = 0; -}; diff --git a/vendor/rtaudio/include/iasiothiscallresolver.cpp b/vendor/rtaudio/include/iasiothiscallresolver.cpp deleted file mode 100644 index 08c55eacf..000000000 --- a/vendor/rtaudio/include/iasiothiscallresolver.cpp +++ /dev/null @@ -1,572 +0,0 @@ -/* - IASIOThiscallResolver.cpp see the comments in iasiothiscallresolver.h for - the top level description - this comment describes the technical details of - the implementation. - - The latest version of this file is available from: - http://www.audiomulch.com/~rossb/code/calliasio - - please email comments to Ross Bencina - - BACKGROUND - - The IASIO interface declared in the Steinberg ASIO 2 SDK declares - functions with no explicit calling convention. This causes MSVC++ to default - to using the thiscall convention, which is a proprietary convention not - implemented by some non-microsoft compilers - notably borland BCC, - C++Builder, and gcc. MSVC++ is the defacto standard compiler used by - Steinberg. As a result of this situation, the ASIO sdk will compile with - any compiler, however attempting to execute the compiled code will cause a - crash due to different default calling conventions on non-Microsoft - compilers. - - IASIOThiscallResolver solves the problem by providing an adapter class that - delegates to the IASIO interface using the correct calling convention - (thiscall). Due to the lack of support for thiscall in the Borland and GCC - compilers, the calls have been implemented in assembly language. - - A number of macros are defined for thiscall function calls with different - numbers of parameters, with and without return values - it may be possible - to modify the format of these macros to make them work with other inline - assemblers. - - - THISCALL DEFINITION - - A number of definitions of the thiscall calling convention are floating - around the internet. The following definition has been validated against - output from the MSVC++ compiler: - - For non-vararg functions, thiscall works as follows: the object (this) - pointer is passed in ECX. All arguments are passed on the stack in - right to left order. The return value is placed in EAX. The callee - clears the passed arguments from the stack. - - - FINDING FUNCTION POINTERS FROM AN IASIO POINTER - - The first field of a COM object is a pointer to its vtble. Thus a pointer - to an object implementing the IASIO interface also points to a pointer to - that object's vtbl. The vtble is a table of function pointers for all of - the virtual functions exposed by the implemented interfaces. - - If we consider a variable declared as a pointer to IASO: - - IASIO *theAsioDriver - - theAsioDriver points to: - - object implementing IASIO - { - IASIOvtbl *vtbl - other data - } - - in other words, theAsioDriver points to a pointer to an IASIOvtbl - - vtbl points to a table of function pointers: - - IASIOvtbl ( interface IASIO : public IUnknown ) - { - (IUnknown functions) - 0 virtual HRESULT STDMETHODCALLTYPE (*QueryInterface)(REFIID riid, void **ppv) = 0; - 4 virtual ULONG STDMETHODCALLTYPE (*AddRef)() = 0; - 8 virtual ULONG STDMETHODCALLTYPE (*Release)() = 0; - - (IASIO functions) - 12 virtual ASIOBool (*init)(void *sysHandle) = 0; - 16 virtual void (*getDriverName)(char *name) = 0; - 20 virtual long (*getDriverVersion)() = 0; - 24 virtual void (*getErrorMessage)(char *string) = 0; - 28 virtual ASIOError (*start)() = 0; - 32 virtual ASIOError (*stop)() = 0; - 36 virtual ASIOError (*getChannels)(long *numInputChannels, long *numOutputChannels) = 0; - 40 virtual ASIOError (*getLatencies)(long *inputLatency, long *outputLatency) = 0; - 44 virtual ASIOError (*getBufferSize)(long *minSize, long *maxSize, - long *preferredSize, long *granularity) = 0; - 48 virtual ASIOError (*canSampleRate)(ASIOSampleRate sampleRate) = 0; - 52 virtual ASIOError (*getSampleRate)(ASIOSampleRate *sampleRate) = 0; - 56 virtual ASIOError (*setSampleRate)(ASIOSampleRate sampleRate) = 0; - 60 virtual ASIOError (*getClockSources)(ASIOClockSource *clocks, long *numSources) = 0; - 64 virtual ASIOError (*setClockSource)(long reference) = 0; - 68 virtual ASIOError (*getSamplePosition)(ASIOSamples *sPos, ASIOTimeStamp *tStamp) = 0; - 72 virtual ASIOError (*getChannelInfo)(ASIOChannelInfo *info) = 0; - 76 virtual ASIOError (*createBuffers)(ASIOBufferInfo *bufferInfos, long numChannels, - long bufferSize, ASIOCallbacks *callbacks) = 0; - 80 virtual ASIOError (*disposeBuffers)() = 0; - 84 virtual ASIOError (*controlPanel)() = 0; - 88 virtual ASIOError (*future)(long selector,void *opt) = 0; - 92 virtual ASIOError (*outputReady)() = 0; - }; - - The numbers in the left column show the byte offset of each function ptr - from the beginning of the vtbl. These numbers are used in the code below - to select different functions. - - In order to find the address of a particular function, theAsioDriver - must first be dereferenced to find the value of the vtbl pointer: - - mov eax, theAsioDriver - mov edx, [theAsioDriver] // edx now points to vtbl[0] - - Then an offset must be added to the vtbl pointer to select a - particular function, for example vtbl+44 points to the slot containing - a pointer to the getBufferSize function. - - Finally vtbl+x must be dereferenced to obtain the value of the function - pointer stored in that address: - - call [edx+44] // call the function pointed to by - // the value in the getBufferSize field of the vtbl - - - SEE ALSO - - Martin Fay's OpenASIO DLL at http://www.martinfay.com solves the same - problem by providing a new COM interface which wraps IASIO with an - interface that uses portable calling conventions. OpenASIO must be compiled - with MSVC, and requires that you ship the OpenASIO DLL with your - application. - - - ACKNOWLEDGEMENTS - - Ross Bencina: worked out the thiscall details above, wrote the original - Borland asm macros, and a patch for asio.cpp (which is no longer needed). - Thanks to Martin Fay for introducing me to the issues discussed here, - and to Rene G. Ceballos for assisting with asm dumps from MSVC++. - - Antti Silvast: converted the original calliasio to work with gcc and NASM - by implementing the asm code in a separate file. - - Fraser Adams: modified the original calliasio containing the Borland inline - asm to add inline asm for gcc i.e. Intel syntax for Borland and AT&T syntax - for gcc. This seems a neater approach for gcc than to have a separate .asm - file and it means that we only need one version of the thiscall patch. - - Fraser Adams: rewrote the original calliasio patch in the form of the - IASIOThiscallResolver class in order to avoid modifications to files from - the Steinberg SDK, which may have had potential licence issues. - - Andrew Baldwin: contributed fixes for compatibility problems with more - recent versions of the gcc assembler. -*/ - - -// We only need IASIOThiscallResolver at all if we are on Win32. For other -// platforms we simply bypass the IASIOThiscallResolver definition to allow us -// to be safely #include'd whatever the platform to keep client code portable -#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) && !defined(_WIN64) - - -// If microsoft compiler we can call IASIO directly so IASIOThiscallResolver -// is not used. -#if !defined(_MSC_VER) - - -#include -#include - -// We have a mechanism in iasiothiscallresolver.h to ensure that asio.h is -// #include'd before it in client code, we do NOT want to do this test here. -#define iasiothiscallresolver_sourcefile 1 -#include "iasiothiscallresolver.h" -#undef iasiothiscallresolver_sourcefile - -// iasiothiscallresolver.h redefines ASIOInit for clients, but we don't want -// this macro defined in this translation unit. -#undef ASIOInit - - -// theAsioDriver is a global pointer to the current IASIO instance which the -// ASIO SDK uses to perform all actions on the IASIO interface. We substitute -// our own forwarding interface into this pointer. -extern IASIO* theAsioDriver; - - -// The following macros define the inline assembler for BORLAND first then gcc - -#if defined(__BCPLUSPLUS__) || defined(__BORLANDC__) - - -#define CALL_THISCALL_0( resultName, thisPtr, funcOffset )\ - void *this_ = (thisPtr); \ - __asm { \ - mov ecx, this_ ; \ - mov eax, [ecx] ; \ - call [eax+funcOffset] ; \ - mov resultName, eax ; \ - } - - -#define CALL_VOID_THISCALL_1( thisPtr, funcOffset, param1 )\ - void *this_ = (thisPtr); \ - __asm { \ - mov eax, param1 ; \ - push eax ; \ - mov ecx, this_ ; \ - mov eax, [ecx] ; \ - call [eax+funcOffset] ; \ - } - - -#define CALL_THISCALL_1( resultName, thisPtr, funcOffset, param1 )\ - void *this_ = (thisPtr); \ - __asm { \ - mov eax, param1 ; \ - push eax ; \ - mov ecx, this_ ; \ - mov eax, [ecx] ; \ - call [eax+funcOffset] ; \ - mov resultName, eax ; \ - } - - -#define CALL_THISCALL_1_DOUBLE( resultName, thisPtr, funcOffset, param1 )\ - void *this_ = (thisPtr); \ - void *doubleParamPtr_ (¶m1); \ - __asm { \ - mov eax, doubleParamPtr_ ; \ - push [eax+4] ; \ - push [eax] ; \ - mov ecx, this_ ; \ - mov eax, [ecx] ; \ - call [eax+funcOffset] ; \ - mov resultName, eax ; \ - } - - -#define CALL_THISCALL_2( resultName, thisPtr, funcOffset, param1, param2 )\ - void *this_ = (thisPtr); \ - __asm { \ - mov eax, param2 ; \ - push eax ; \ - mov eax, param1 ; \ - push eax ; \ - mov ecx, this_ ; \ - mov eax, [ecx] ; \ - call [eax+funcOffset] ; \ - mov resultName, eax ; \ - } - - -#define CALL_THISCALL_4( resultName, thisPtr, funcOffset, param1, param2, param3, param4 )\ - void *this_ = (thisPtr); \ - __asm { \ - mov eax, param4 ; \ - push eax ; \ - mov eax, param3 ; \ - push eax ; \ - mov eax, param2 ; \ - push eax ; \ - mov eax, param1 ; \ - push eax ; \ - mov ecx, this_ ; \ - mov eax, [ecx] ; \ - call [eax+funcOffset] ; \ - mov resultName, eax ; \ - } - - -#elif defined(__GNUC__) - - -#define CALL_THISCALL_0( resultName, thisPtr, funcOffset ) \ - __asm__ __volatile__ ("movl (%1), %%edx\n\t" \ - "call *"#funcOffset"(%%edx)\n\t" \ - :"=a"(resultName) /* Output Operands */ \ - :"c"(thisPtr) /* Input Operands */ \ - : "%edx" /* Clobbered Registers */ \ - ); \ - - -#define CALL_VOID_THISCALL_1( thisPtr, funcOffset, param1 ) \ - __asm__ __volatile__ ("pushl %0\n\t" \ - "movl (%1), %%edx\n\t" \ - "call *"#funcOffset"(%%edx)\n\t" \ - : /* Output Operands */ \ - :"r"(param1), /* Input Operands */ \ - "c"(thisPtr) \ - : "%edx" /* Clobbered Registers */ \ - ); \ - - -#define CALL_THISCALL_1( resultName, thisPtr, funcOffset, param1 ) \ - __asm__ __volatile__ ("pushl %1\n\t" \ - "movl (%2), %%edx\n\t" \ - "call *"#funcOffset"(%%edx)\n\t" \ - :"=a"(resultName) /* Output Operands */ \ - :"r"(param1), /* Input Operands */ \ - "c"(thisPtr) \ - : "%edx" /* Clobbered Registers */ \ - ); \ - - -#define CALL_THISCALL_1_DOUBLE( resultName, thisPtr, funcOffset, param1 ) \ - do { \ - double param1f64 = param1; /* Cast explicitly to double */ \ - double *param1f64Ptr = ¶m1f64; /* Make pointer to address */ \ - __asm__ __volatile__ ("pushl 4(%1)\n\t" \ - "pushl (%1)\n\t" \ - "movl (%2), %%edx\n\t" \ - "call *"#funcOffset"(%%edx);\n\t" \ - : "=a"(resultName) /* Output Operands */ \ - : "r"(param1f64Ptr), /* Input Operands */ \ - "c"(thisPtr), \ - "m"(*param1f64Ptr) /* Using address */ \ - : "%edx" /* Clobbered Registers */ \ - ); \ - } while (0); \ - - -#define CALL_THISCALL_2( resultName, thisPtr, funcOffset, param1, param2 ) \ - __asm__ __volatile__ ("pushl %1\n\t" \ - "pushl %2\n\t" \ - "movl (%3), %%edx\n\t" \ - "call *"#funcOffset"(%%edx)\n\t" \ - :"=a"(resultName) /* Output Operands */ \ - :"r"(param2), /* Input Operands */ \ - "r"(param1), \ - "c"(thisPtr) \ - : "%edx" /* Clobbered Registers */ \ - ); \ - - -#define CALL_THISCALL_4( resultName, thisPtr, funcOffset, param1, param2, param3, param4 )\ - __asm__ __volatile__ ("pushl %1\n\t" \ - "pushl %2\n\t" \ - "pushl %3\n\t" \ - "pushl %4\n\t" \ - "movl (%5), %%edx\n\t" \ - "call *"#funcOffset"(%%edx)\n\t" \ - :"=a"(resultName) /* Output Operands */ \ - :"r"(param4), /* Input Operands */ \ - "r"(param3), \ - "r"(param2), \ - "r"(param1), \ - "c"(thisPtr) \ - : "%edx" /* Clobbered Registers */ \ - ); \ - -#endif - - - -// Our static singleton instance. -IASIOThiscallResolver IASIOThiscallResolver::instance; - -// Constructor called to initialize static Singleton instance above. Note that -// it is important not to clear that_ incase it has already been set by the call -// to placement new in ASIOInit(). -IASIOThiscallResolver::IASIOThiscallResolver() -{ -} - -// Constructor called from ASIOInit() below -IASIOThiscallResolver::IASIOThiscallResolver(IASIO* that) -: that_( that ) -{ -} - -// Implement IUnknown methods as assert(false). IASIOThiscallResolver is not -// really a COM object, just a wrapper which will work with the ASIO SDK. -// If you wanted to use ASIO without the SDK you might want to implement COM -// aggregation in these methods. -HRESULT STDMETHODCALLTYPE IASIOThiscallResolver::QueryInterface(REFIID riid, void **ppv) -{ - (void)riid; // suppress unused variable warning - - assert( false ); // this function should never be called by the ASIO SDK. - - *ppv = NULL; - return E_NOINTERFACE; -} - -ULONG STDMETHODCALLTYPE IASIOThiscallResolver::AddRef() -{ - assert( false ); // this function should never be called by the ASIO SDK. - - return 1; -} - -ULONG STDMETHODCALLTYPE IASIOThiscallResolver::Release() -{ - assert( false ); // this function should never be called by the ASIO SDK. - - return 1; -} - - -// Implement the IASIO interface methods by performing the vptr manipulation -// described above then delegating to the real implementation. -ASIOBool IASIOThiscallResolver::init(void *sysHandle) -{ - ASIOBool result; - CALL_THISCALL_1( result, that_, 12, sysHandle ); - return result; -} - -void IASIOThiscallResolver::getDriverName(char *name) -{ - CALL_VOID_THISCALL_1( that_, 16, name ); -} - -long IASIOThiscallResolver::getDriverVersion() -{ - ASIOBool result; - CALL_THISCALL_0( result, that_, 20 ); - return result; -} - -void IASIOThiscallResolver::getErrorMessage(char *string) -{ - CALL_VOID_THISCALL_1( that_, 24, string ); -} - -ASIOError IASIOThiscallResolver::start() -{ - ASIOBool result; - CALL_THISCALL_0( result, that_, 28 ); - return result; -} - -ASIOError IASIOThiscallResolver::stop() -{ - ASIOBool result; - CALL_THISCALL_0( result, that_, 32 ); - return result; -} - -ASIOError IASIOThiscallResolver::getChannels(long *numInputChannels, long *numOutputChannels) -{ - ASIOBool result; - CALL_THISCALL_2( result, that_, 36, numInputChannels, numOutputChannels ); - return result; -} - -ASIOError IASIOThiscallResolver::getLatencies(long *inputLatency, long *outputLatency) -{ - ASIOBool result; - CALL_THISCALL_2( result, that_, 40, inputLatency, outputLatency ); - return result; -} - -ASIOError IASIOThiscallResolver::getBufferSize(long *minSize, long *maxSize, - long *preferredSize, long *granularity) -{ - ASIOBool result; - CALL_THISCALL_4( result, that_, 44, minSize, maxSize, preferredSize, granularity ); - return result; -} - -ASIOError IASIOThiscallResolver::canSampleRate(ASIOSampleRate sampleRate) -{ - ASIOBool result; - CALL_THISCALL_1_DOUBLE( result, that_, 48, sampleRate ); - return result; -} - -ASIOError IASIOThiscallResolver::getSampleRate(ASIOSampleRate *sampleRate) -{ - ASIOBool result; - CALL_THISCALL_1( result, that_, 52, sampleRate ); - return result; -} - -ASIOError IASIOThiscallResolver::setSampleRate(ASIOSampleRate sampleRate) -{ - ASIOBool result; - CALL_THISCALL_1_DOUBLE( result, that_, 56, sampleRate ); - return result; -} - -ASIOError IASIOThiscallResolver::getClockSources(ASIOClockSource *clocks, long *numSources) -{ - ASIOBool result; - CALL_THISCALL_2( result, that_, 60, clocks, numSources ); - return result; -} - -ASIOError IASIOThiscallResolver::setClockSource(long reference) -{ - ASIOBool result; - CALL_THISCALL_1( result, that_, 64, reference ); - return result; -} - -ASIOError IASIOThiscallResolver::getSamplePosition(ASIOSamples *sPos, ASIOTimeStamp *tStamp) -{ - ASIOBool result; - CALL_THISCALL_2( result, that_, 68, sPos, tStamp ); - return result; -} - -ASIOError IASIOThiscallResolver::getChannelInfo(ASIOChannelInfo *info) -{ - ASIOBool result; - CALL_THISCALL_1( result, that_, 72, info ); - return result; -} - -ASIOError IASIOThiscallResolver::createBuffers(ASIOBufferInfo *bufferInfos, - long numChannels, long bufferSize, ASIOCallbacks *callbacks) -{ - ASIOBool result; - CALL_THISCALL_4( result, that_, 76, bufferInfos, numChannels, bufferSize, callbacks ); - return result; -} - -ASIOError IASIOThiscallResolver::disposeBuffers() -{ - ASIOBool result; - CALL_THISCALL_0( result, that_, 80 ); - return result; -} - -ASIOError IASIOThiscallResolver::controlPanel() -{ - ASIOBool result; - CALL_THISCALL_0( result, that_, 84 ); - return result; -} - -ASIOError IASIOThiscallResolver::future(long selector,void *opt) -{ - ASIOBool result; - CALL_THISCALL_2( result, that_, 88, selector, opt ); - return result; -} - -ASIOError IASIOThiscallResolver::outputReady() -{ - ASIOBool result; - CALL_THISCALL_0( result, that_, 92 ); - return result; -} - - -// Implement our substitute ASIOInit() method -ASIOError IASIOThiscallResolver::ASIOInit(ASIODriverInfo *info) -{ - // To ensure that our instance's vptr is correctly constructed, even if - // ASIOInit is called prior to main(), we explicitly call its constructor - // (potentially over the top of an existing instance). Note that this is - // pretty ugly, and is only safe because IASIOThiscallResolver has no - // destructor and contains no objects with destructors. - new((void*)&instance) IASIOThiscallResolver( theAsioDriver ); - - // Interpose between ASIO client code and the real driver. - theAsioDriver = &instance; - - // Note that we never need to switch theAsioDriver back to point to the - // real driver because theAsioDriver is reset to zero in ASIOExit(). - - // Delegate to the real ASIOInit - return ::ASIOInit(info); -} - - -#endif /* !defined(_MSC_VER) */ - -#endif /* Win32 */ - diff --git a/vendor/rtaudio/include/iasiothiscallresolver.h b/vendor/rtaudio/include/iasiothiscallresolver.h deleted file mode 100644 index 63e91ca31..000000000 --- a/vendor/rtaudio/include/iasiothiscallresolver.h +++ /dev/null @@ -1,202 +0,0 @@ -// **************************************************************************** -// -// Changed: I have modified this file slightly (includes) to work with -// RtAudio. RtAudio.cpp must include this file after asio.h. -// -// File: IASIOThiscallResolver.h -// Description: The IASIOThiscallResolver class implements the IASIO -// interface and acts as a proxy to the real IASIO interface by -// calling through its vptr table using the thiscall calling -// convention. To put it another way, we interpose -// IASIOThiscallResolver between ASIO SDK code and the driver. -// This is necessary because most non-Microsoft compilers don't -// implement the thiscall calling convention used by IASIO. -// -// iasiothiscallresolver.cpp contains the background of this -// problem plus a technical description of the vptr -// manipulations. -// -// In order to use this mechanism one simply has to add -// iasiothiscallresolver.cpp to the list of files to compile -// and #include -// -// Note that this #include must come after the other ASIO SDK -// #includes, for example: -// -// #include -// #include -// #include -// #include -// #include -// -// Actually the important thing is to #include -// after . We have -// incorporated a test to enforce this ordering. -// -// The code transparently takes care of the interposition by -// using macro substitution to intercept calls to ASIOInit() -// and ASIOExit(). We save the original ASIO global -// "theAsioDriver" in our "that" variable, and then set -// "theAsioDriver" to equal our IASIOThiscallResolver instance. -// -// Whilst this method of resolving the thiscall problem requires -// the addition of #include to client -// code it has the advantage that it does not break the terms -// of the ASIO licence by publishing it. We are NOT modifying -// any Steinberg code here, we are merely implementing the IASIO -// interface in the same way that we would need to do if we -// wished to provide an open source ASIO driver. -// -// For compilation with MinGW -lole32 needs to be added to the -// linker options. For BORLAND, linking with Import32.lib is -// sufficient. -// -// The dependencies are with: CoInitialize, CoUninitialize, -// CoCreateInstance, CLSIDFromString - used by asiolist.cpp -// and are required on Windows whether ThiscallResolver is used -// or not. -// -// Searching for the above strings in the root library path -// of your compiler should enable the correct libraries to be -// identified if they aren't immediately obvious. -// -// Note that the current implementation of IASIOThiscallResolver -// is not COM compliant - it does not correctly implement the -// IUnknown interface. Implementing it is not necessary because -// it is not called by parts of the ASIO SDK which call through -// theAsioDriver ptr. The IUnknown methods are implemented as -// assert(false) to ensure that the code fails if they are -// ever called. -// Restrictions: None. Public Domain & Open Source distribute freely -// You may use IASIOThiscallResolver commercially as well as -// privately. -// You the user assume the responsibility for the use of the -// files, binary or text, and there is no guarantee or warranty, -// expressed or implied, including but not limited to the -// implied warranties of merchantability and fitness for a -// particular purpose. You assume all responsibility and agree -// to hold no entity, copyright holder or distributors liable -// for any loss of data or inaccurate representations of data -// as a result of using IASIOThiscallResolver. -// Version: 1.4 Added separate macro CALL_THISCALL_1_DOUBLE from -// Andrew Baldwin, and volatile for whole gcc asm blocks, -// both for compatibility with newer gcc versions. Cleaned up -// Borland asm to use one less register. -// 1.3 Switched to including assert.h for better compatibility. -// Wrapped entire .h and .cpp contents with a check for -// _MSC_VER to provide better compatibility with MS compilers. -// Changed Singleton implementation to use static instance -// instead of freestore allocated instance. Removed ASIOExit -// macro as it is no longer needed. -// 1.2 Removed semicolons from ASIOInit and ASIOExit macros to -// allow them to be embedded in expressions (if statements). -// Cleaned up some comments. Removed combase.c dependency (it -// doesn't compile with BCB anyway) by stubbing IUnknown. -// 1.1 Incorporated comments from Ross Bencina including things -// such as changing name from ThiscallResolver to -// IASIOThiscallResolver, tidying up the constructor, fixing -// a bug in IASIOThiscallResolver::ASIOExit() and improving -// portability through the use of conditional compilation -// 1.0 Initial working version. -// Created: 6/09/2003 -// Authors: Fraser Adams -// Ross Bencina -// Rene G. Ceballos -// Martin Fay -// Antti Silvast -// Andrew Baldwin -// -// **************************************************************************** - - -#ifndef included_iasiothiscallresolver_h -#define included_iasiothiscallresolver_h - -// We only need IASIOThiscallResolver at all if we are on Win32. For other -// platforms we simply bypass the IASIOThiscallResolver definition to allow us -// to be safely #include'd whatever the platform to keep client code portable -//#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) -#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) && !defined(_WIN64) - - -// If microsoft compiler we can call IASIO directly so IASIOThiscallResolver -// is not used. -#if !defined(_MSC_VER) - - -// The following is in order to ensure that this header is only included after -// the other ASIO headers (except for the case of iasiothiscallresolver.cpp). -// We need to do this because IASIOThiscallResolver works by eclipsing the -// original definition of ASIOInit() with a macro (see below). -#if !defined(iasiothiscallresolver_sourcefile) - #if !defined(__ASIO_H) - #error iasiothiscallresolver.h must be included AFTER asio.h - #endif -#endif - -#include -#include "iasiodrv.h" /* From ASIO SDK */ - - -class IASIOThiscallResolver : public IASIO { -private: - IASIO* that_; // Points to the real IASIO - - static IASIOThiscallResolver instance; // Singleton instance - - // Constructors - declared private so construction is limited to - // our Singleton instance - IASIOThiscallResolver(); - IASIOThiscallResolver(IASIO* that); -public: - - // Methods from the IUnknown interface. We don't fully implement IUnknown - // because the ASIO SDK never calls these methods through theAsioDriver ptr. - // These methods are implemented as assert(false). - virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppv); - virtual ULONG STDMETHODCALLTYPE AddRef(); - virtual ULONG STDMETHODCALLTYPE Release(); - - // Methods from the IASIO interface, implemented as forwarning calls to that. - virtual ASIOBool init(void *sysHandle); - virtual void getDriverName(char *name); - virtual long getDriverVersion(); - virtual void getErrorMessage(char *string); - virtual ASIOError start(); - virtual ASIOError stop(); - virtual ASIOError getChannels(long *numInputChannels, long *numOutputChannels); - virtual ASIOError getLatencies(long *inputLatency, long *outputLatency); - virtual ASIOError getBufferSize(long *minSize, long *maxSize, long *preferredSize, long *granularity); - virtual ASIOError canSampleRate(ASIOSampleRate sampleRate); - virtual ASIOError getSampleRate(ASIOSampleRate *sampleRate); - virtual ASIOError setSampleRate(ASIOSampleRate sampleRate); - virtual ASIOError getClockSources(ASIOClockSource *clocks, long *numSources); - virtual ASIOError setClockSource(long reference); - virtual ASIOError getSamplePosition(ASIOSamples *sPos, ASIOTimeStamp *tStamp); - virtual ASIOError getChannelInfo(ASIOChannelInfo *info); - virtual ASIOError createBuffers(ASIOBufferInfo *bufferInfos, long numChannels, long bufferSize, ASIOCallbacks *callbacks); - virtual ASIOError disposeBuffers(); - virtual ASIOError controlPanel(); - virtual ASIOError future(long selector,void *opt); - virtual ASIOError outputReady(); - - // Class method, see ASIOInit() macro below. - static ASIOError ASIOInit(ASIODriverInfo *info); // Delegates to ::ASIOInit -}; - - -// Replace calls to ASIOInit with our interposing version. -// This macro enables us to perform thiscall resolution simply by #including -// after the asio #includes (this file _must_ be -// included _after_ the asio #includes) - -#define ASIOInit(name) IASIOThiscallResolver::ASIOInit((name)) - - -#endif /* !defined(_MSC_VER) */ - -#endif /* Win32 */ - -#endif /* included_iasiothiscallresolver_h */ - - diff --git a/vendor/rtaudio/include/soundcard.h b/vendor/rtaudio/include/soundcard.h deleted file mode 100644 index 2cf3a2c5b..000000000 --- a/vendor/rtaudio/include/soundcard.h +++ /dev/null @@ -1,1878 +0,0 @@ -/* - * soundcard.h - */ - -/*- - * Copyright by Hannu Savolainen 1993 / 4Front Technologies 1993-2006 - * Modified for the new FreeBSD sound driver by Luigi Rizzo, 1997 - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD: src/sys/sys/soundcard.h,v 1.48 2006/11/26 11:55:48 netchild Exp $ - */ - -/* - * Unless coordinating changes with 4Front Technologies, do NOT make any - * modifications to ioctl commands, types, etc. that would break - * compatibility with the OSS API. - */ - -#ifndef _SYS_SOUNDCARD_H_ -#define _SYS_SOUNDCARD_H_ - /* - * If you make modifications to this file, please contact me before - * distributing the modified version. There is already enough - * diversity in the world. - * - * Regards, - * Hannu Savolainen - * hannu@voxware.pp.fi - * - ********************************************************************** - * PS. The Hacker's Guide to VoxWare available from - * nic.funet.fi:pub/Linux/ALPHA/sound. The file is - * snd-sdk-doc-0.1.ps.gz (gzipped postscript). It contains - * some useful information about programming with VoxWare. - * (NOTE! The pub/Linux/ALPHA/ directories are hidden. You have - * to cd inside them before the files are accessible.) - ********************************************************************** - */ - -/* - * SOUND_VERSION is only used by the voxware driver. Hopefully apps - * should not depend on it, but rather look at the capabilities - * of the driver in the kernel! - */ -#define SOUND_VERSION 301 -#define VOXWARE /* does this have any use ? */ - -/* - * Supported card ID numbers (Should be somewhere else? We keep - * them here just for compativility with the old driver, but these - * constants are of little or no use). - */ - -#define SNDCARD_ADLIB 1 -#define SNDCARD_SB 2 -#define SNDCARD_PAS 3 -#define SNDCARD_GUS 4 -#define SNDCARD_MPU401 5 -#define SNDCARD_SB16 6 -#define SNDCARD_SB16MIDI 7 -#define SNDCARD_UART6850 8 -#define SNDCARD_GUS16 9 -#define SNDCARD_MSS 10 -#define SNDCARD_PSS 11 -#define SNDCARD_SSCAPE 12 -#define SNDCARD_PSS_MPU 13 -#define SNDCARD_PSS_MSS 14 -#define SNDCARD_SSCAPE_MSS 15 -#define SNDCARD_TRXPRO 16 -#define SNDCARD_TRXPRO_SB 17 -#define SNDCARD_TRXPRO_MPU 18 -#define SNDCARD_MAD16 19 -#define SNDCARD_MAD16_MPU 20 -#define SNDCARD_CS4232 21 -#define SNDCARD_CS4232_MPU 22 -#define SNDCARD_MAUI 23 -#define SNDCARD_PSEUDO_MSS 24 -#define SNDCARD_AWE32 25 -#define SNDCARD_NSS 26 -#define SNDCARD_UART16550 27 -#define SNDCARD_OPL 28 - -#include -#include -#ifndef _IOWR -#include -#endif /* !_IOWR */ - -/* - * The first part of this file contains the new FreeBSD sound ioctl - * interface. Tries to minimize the number of different ioctls, and - * to be reasonably general. - * - * 970821: some of the new calls have not been implemented yet. - */ - -/* - * the following three calls extend the generic file descriptor - * interface. AIONWRITE is the dual of FIONREAD, i.e. returns the max - * number of bytes for a write operation to be non-blocking. - * - * AIOGSIZE/AIOSSIZE are used to change the behaviour of the device, - * from a character device (default) to a block device. In block mode, - * (not to be confused with blocking mode) the main difference for the - * application is that select() will return only when a complete - * block can be read/written to the device, whereas in character mode - * select will return true when one byte can be exchanged. For audio - * devices, character mode makes select almost useless since one byte - * will always be ready by the next sample time (which is often only a - * handful of microseconds away). - * Use a size of 0 or 1 to return to character mode. - */ -#define AIONWRITE _IOR('A', 10, int) /* get # bytes to write */ -struct snd_size { - int play_size; - int rec_size; -}; -#define AIOGSIZE _IOR('A', 11, struct snd_size)/* read current blocksize */ -#define AIOSSIZE _IOWR('A', 11, struct snd_size) /* sets blocksize */ - -/* - * The following constants define supported audio formats. The - * encoding follows voxware conventions, i.e. 1 bit for each supported - * format. We extend it by using bit 31 (RO) to indicate full-duplex - * capability, and bit 29 (RO) to indicate that the card supports/ - * needs different formats on capture & playback channels. - * Bit 29 (RW) is used to indicate/ask stereo. - * - * The number of bits required to store the sample is: - * o 4 bits for the IDA ADPCM format, - * o 8 bits for 8-bit formats, mu-law and A-law, - * o 16 bits for the 16-bit formats, and - * o 32 bits for the 24/32-bit formats. - * o undefined for the MPEG audio format. - */ - -#define AFMT_QUERY 0x00000000 /* Return current format */ -#define AFMT_MU_LAW 0x00000001 /* Logarithmic mu-law */ -#define AFMT_A_LAW 0x00000002 /* Logarithmic A-law */ -#define AFMT_IMA_ADPCM 0x00000004 /* A 4:1 compressed format where 16-bit - * squence represented using the - * the average 4 bits per sample */ -#define AFMT_U8 0x00000008 /* Unsigned 8-bit */ -#define AFMT_S16_LE 0x00000010 /* Little endian signed 16-bit */ -#define AFMT_S16_BE 0x00000020 /* Big endian signed 16-bit */ -#define AFMT_S8 0x00000040 /* Signed 8-bit */ -#define AFMT_U16_LE 0x00000080 /* Little endian unsigned 16-bit */ -#define AFMT_U16_BE 0x00000100 /* Big endian unsigned 16-bit */ -#define AFMT_MPEG 0x00000200 /* MPEG MP2/MP3 audio */ -#define AFMT_AC3 0x00000400 /* Dolby Digital AC3 */ - -#if _BYTE_ORDER == _LITTLE_ENDIAN -#define AFMT_S16_NE AFMT_S16_LE /* native endian signed 16 */ -#else -#define AFMT_S16_NE AFMT_S16_BE -#endif - -/* - * 32-bit formats below used for 24-bit audio data where the data is stored - * in the 24 most significant bits and the least significant bits are not used - * (should be set to 0). - */ -#define AFMT_S32_LE 0x00001000 /* Little endian signed 32-bit */ -#define AFMT_S32_BE 0x00002000 /* Big endian signed 32-bit */ -#define AFMT_U32_LE 0x00004000 /* Little endian unsigned 32-bit */ -#define AFMT_U32_BE 0x00008000 /* Big endian unsigned 32-bit */ -#define AFMT_S24_LE 0x00010000 /* Little endian signed 24-bit */ -#define AFMT_S24_BE 0x00020000 /* Big endian signed 24-bit */ -#define AFMT_U24_LE 0x00040000 /* Little endian unsigned 24-bit */ -#define AFMT_U24_BE 0x00080000 /* Big endian unsigned 24-bit */ - -#define AFMT_STEREO 0x10000000 /* can do/want stereo */ - -/* - * the following are really capabilities - */ -#define AFMT_WEIRD 0x20000000 /* weird hardware... */ - /* - * AFMT_WEIRD reports that the hardware might need to operate - * with different formats in the playback and capture - * channels when operating in full duplex. - * As an example, SoundBlaster16 cards only support U8 in one - * direction and S16 in the other one, and applications should - * be aware of this limitation. - */ -#define AFMT_FULLDUPLEX 0x80000000 /* can do full duplex */ - -/* - * The following structure is used to get/set format and sampling rate. - * While it would be better to have things such as stereo, bits per - * sample, endiannes, etc split in different variables, it turns out - * that formats are not that many, and not all combinations are possible. - * So we followed the Voxware approach of associating one bit to each - * format. - */ - -typedef struct _snd_chan_param { - u_long play_rate; /* sampling rate */ - u_long rec_rate; /* sampling rate */ - u_long play_format; /* everything describing the format */ - u_long rec_format; /* everything describing the format */ -} snd_chan_param; -#define AIOGFMT _IOR('f', 12, snd_chan_param) /* get format */ -#define AIOSFMT _IOWR('f', 12, snd_chan_param) /* sets format */ - -/* - * The following structure is used to get/set the mixer setting. - * Up to 32 mixers are supported, each one with up to 32 channels. - */ -typedef struct _snd_mix_param { - u_char subdev; /* which output */ - u_char line; /* which input */ - u_char left,right; /* volumes, 0..255, 0 = mute */ -} snd_mix_param ; - -/* XXX AIOGMIX, AIOSMIX not implemented yet */ -#define AIOGMIX _IOWR('A', 13, snd_mix_param) /* return mixer status */ -#define AIOSMIX _IOWR('A', 14, snd_mix_param) /* sets mixer status */ - -/* - * channel specifiers used in AIOSTOP and AIOSYNC - */ -#define AIOSYNC_PLAY 0x1 /* play chan */ -#define AIOSYNC_CAPTURE 0x2 /* capture chan */ -/* AIOSTOP stop & flush a channel, returns the residual count */ -#define AIOSTOP _IOWR ('A', 15, int) - -/* alternate method used to notify the sync condition */ -#define AIOSYNC_SIGNAL 0x100 -#define AIOSYNC_SELECT 0x200 - -/* what the 'pos' field refers to */ -#define AIOSYNC_READY 0x400 -#define AIOSYNC_FREE 0x800 - -typedef struct _snd_sync_parm { - long chan ; /* play or capture channel, plus modifier */ - long pos; -} snd_sync_parm; -#define AIOSYNC _IOWR ('A', 15, snd_sync_parm) /* misc. synchronization */ - -/* - * The following is used to return device capabilities. If the structure - * passed to the ioctl is zeroed, default values are returned for rate - * and formats, a bitmap of available mixers is returned, and values - * (inputs, different levels) for the first one are returned. - * - * If formats, mixers, inputs are instantiated, then detailed info - * are returned depending on the call. - */ -typedef struct _snd_capabilities { - u_long rate_min, rate_max; /* min-max sampling rate */ - u_long formats; - u_long bufsize; /* DMA buffer size */ - u_long mixers; /* bitmap of available mixers */ - u_long inputs; /* bitmap of available inputs (per mixer) */ - u_short left, right; /* how many levels are supported */ -} snd_capabilities; -#define AIOGCAP _IOWR('A', 15, snd_capabilities) /* get capabilities */ - -/* - * here is the old (Voxware) ioctl interface - */ - -/* - * IOCTL Commands for /dev/sequencer - */ - -#define SNDCTL_SEQ_RESET _IO ('Q', 0) -#define SNDCTL_SEQ_SYNC _IO ('Q', 1) -#define SNDCTL_SYNTH_INFO _IOWR('Q', 2, struct synth_info) -#define SNDCTL_SEQ_CTRLRATE _IOWR('Q', 3, int) /* Set/get timer res.(hz) */ -#define SNDCTL_SEQ_GETOUTCOUNT _IOR ('Q', 4, int) -#define SNDCTL_SEQ_GETINCOUNT _IOR ('Q', 5, int) -#define SNDCTL_SEQ_PERCMODE _IOW ('Q', 6, int) -#define SNDCTL_FM_LOAD_INSTR _IOW ('Q', 7, struct sbi_instrument) /* Valid for FM only */ -#define SNDCTL_SEQ_TESTMIDI _IOW ('Q', 8, int) -#define SNDCTL_SEQ_RESETSAMPLES _IOW ('Q', 9, int) -#define SNDCTL_SEQ_NRSYNTHS _IOR ('Q',10, int) -#define SNDCTL_SEQ_NRMIDIS _IOR ('Q',11, int) -#define SNDCTL_MIDI_INFO _IOWR('Q',12, struct midi_info) -#define SNDCTL_SEQ_THRESHOLD _IOW ('Q',13, int) -#define SNDCTL_SEQ_TRESHOLD SNDCTL_SEQ_THRESHOLD /* there was once a typo */ -#define SNDCTL_SYNTH_MEMAVL _IOWR('Q',14, int) /* in=dev#, out=memsize */ -#define SNDCTL_FM_4OP_ENABLE _IOW ('Q',15, int) /* in=dev# */ -#define SNDCTL_PMGR_ACCESS _IOWR('Q',16, struct patmgr_info) -#define SNDCTL_SEQ_PANIC _IO ('Q',17) -#define SNDCTL_SEQ_OUTOFBAND _IOW ('Q',18, struct seq_event_rec) -#define SNDCTL_SEQ_GETTIME _IOR ('Q',19, int) - -struct seq_event_rec { - u_char arr[8]; -}; - -#define SNDCTL_TMR_TIMEBASE _IOWR('T', 1, int) -#define SNDCTL_TMR_START _IO ('T', 2) -#define SNDCTL_TMR_STOP _IO ('T', 3) -#define SNDCTL_TMR_CONTINUE _IO ('T', 4) -#define SNDCTL_TMR_TEMPO _IOWR('T', 5, int) -#define SNDCTL_TMR_SOURCE _IOWR('T', 6, int) -# define TMR_INTERNAL 0x00000001 -# define TMR_EXTERNAL 0x00000002 -# define TMR_MODE_MIDI 0x00000010 -# define TMR_MODE_FSK 0x00000020 -# define TMR_MODE_CLS 0x00000040 -# define TMR_MODE_SMPTE 0x00000080 -#define SNDCTL_TMR_METRONOME _IOW ('T', 7, int) -#define SNDCTL_TMR_SELECT _IOW ('T', 8, int) - -/* - * Endian aware patch key generation algorithm. - */ - -#if defined(_AIX) || defined(AIX) -# define _PATCHKEY(id) (0xfd00|id) -#else -# define _PATCHKEY(id) ((id<<8)|0xfd) -#endif - -/* - * Sample loading mechanism for internal synthesizers (/dev/sequencer) - * The following patch_info structure has been designed to support - * Gravis UltraSound. It tries to be universal format for uploading - * sample based patches but is probably too limited. - */ - -struct patch_info { -/* u_short key; Use GUS_PATCH here */ - short key; /* Use GUS_PATCH here */ -#define GUS_PATCH _PATCHKEY(0x04) -#define OBSOLETE_GUS_PATCH _PATCHKEY(0x02) - - short device_no; /* Synthesizer number */ - short instr_no; /* Midi pgm# */ - - u_long mode; -/* - * The least significant byte has the same format than the GUS .PAT - * files - */ -#define WAVE_16_BITS 0x01 /* bit 0 = 8 or 16 bit wave data. */ -#define WAVE_UNSIGNED 0x02 /* bit 1 = Signed - Unsigned data. */ -#define WAVE_LOOPING 0x04 /* bit 2 = looping enabled-1. */ -#define WAVE_BIDIR_LOOP 0x08 /* bit 3 = Set is bidirectional looping. */ -#define WAVE_LOOP_BACK 0x10 /* bit 4 = Set is looping backward. */ -#define WAVE_SUSTAIN_ON 0x20 /* bit 5 = Turn sustaining on. (Env. pts. 3)*/ -#define WAVE_ENVELOPES 0x40 /* bit 6 = Enable envelopes - 1 */ - /* (use the env_rate/env_offs fields). */ -/* Linux specific bits */ -#define WAVE_VIBRATO 0x00010000 /* The vibrato info is valid */ -#define WAVE_TREMOLO 0x00020000 /* The tremolo info is valid */ -#define WAVE_SCALE 0x00040000 /* The scaling info is valid */ -/* Other bits must be zeroed */ - - long len; /* Size of the wave data in bytes */ - long loop_start, loop_end; /* Byte offsets from the beginning */ - -/* - * The base_freq and base_note fields are used when computing the - * playback speed for a note. The base_note defines the tone frequency - * which is heard if the sample is played using the base_freq as the - * playback speed. - * - * The low_note and high_note fields define the minimum and maximum note - * frequencies for which this sample is valid. It is possible to define - * more than one samples for an instrument number at the same time. The - * low_note and high_note fields are used to select the most suitable one. - * - * The fields base_note, high_note and low_note should contain - * the note frequency multiplied by 1000. For example value for the - * middle A is 440*1000. - */ - - u_int base_freq; - u_long base_note; - u_long high_note; - u_long low_note; - int panning; /* -128=left, 127=right */ - int detuning; - -/* New fields introduced in version 1.99.5 */ - - /* Envelope. Enabled by mode bit WAVE_ENVELOPES */ - u_char env_rate[ 6 ]; /* GUS HW ramping rate */ - u_char env_offset[ 6 ]; /* 255 == 100% */ - - /* - * The tremolo, vibrato and scale info are not supported yet. - * Enable by setting the mode bits WAVE_TREMOLO, WAVE_VIBRATO or - * WAVE_SCALE - */ - - u_char tremolo_sweep; - u_char tremolo_rate; - u_char tremolo_depth; - - u_char vibrato_sweep; - u_char vibrato_rate; - u_char vibrato_depth; - - int scale_frequency; - u_int scale_factor; /* from 0 to 2048 or 0 to 2 */ - - int volume; - int spare[4]; - char data[1]; /* The waveform data starts here */ -}; - -struct sysex_info { - short key; /* Use GUS_PATCH here */ -#define SYSEX_PATCH _PATCHKEY(0x05) -#define MAUI_PATCH _PATCHKEY(0x06) - short device_no; /* Synthesizer number */ - long len; /* Size of the sysex data in bytes */ - u_char data[1]; /* Sysex data starts here */ -}; - -/* - * Patch management interface (/dev/sequencer, /dev/patmgr#) - * Don't use these calls if you want to maintain compatibility with - * the future versions of the driver. - */ - -#define PS_NO_PATCHES 0 /* No patch support on device */ -#define PS_MGR_NOT_OK 1 /* Plain patch support (no mgr) */ -#define PS_MGR_OK 2 /* Patch manager supported */ -#define PS_MANAGED 3 /* Patch manager running */ - -#define SNDCTL_PMGR_IFACE _IOWR('P', 1, struct patmgr_info) - -/* - * The patmgr_info is a fixed size structure which is used for two - * different purposes. The intended use is for communication between - * the application using /dev/sequencer and the patch manager daemon - * associated with a synthesizer device (ioctl(SNDCTL_PMGR_ACCESS)). - * - * This structure is also used with ioctl(SNDCTL_PGMR_IFACE) which allows - * a patch manager daemon to read and write device parameters. This - * ioctl available through /dev/sequencer also. Avoid using it since it's - * extremely hardware dependent. In addition access trough /dev/sequencer - * may confuse the patch manager daemon. - */ - -struct patmgr_info { /* Note! size must be < 4k since kmalloc() is used */ - u_long key; /* Don't worry. Reserved for communication - between the patch manager and the driver. */ -#define PM_K_EVENT 1 /* Event from the /dev/sequencer driver */ -#define PM_K_COMMAND 2 /* Request from an application */ -#define PM_K_RESPONSE 3 /* From patmgr to application */ -#define PM_ERROR 4 /* Error returned by the patmgr */ - int device; - int command; - -/* - * Commands 0x000 to 0xfff reserved for patch manager programs - */ -#define PM_GET_DEVTYPE 1 /* Returns type of the patch mgr interface of dev */ -#define PMTYPE_FM2 1 /* 2 OP fm */ -#define PMTYPE_FM4 2 /* Mixed 4 or 2 op FM (OPL-3) */ -#define PMTYPE_WAVE 3 /* Wave table synthesizer (GUS) */ -#define PM_GET_NRPGM 2 /* Returns max # of midi programs in parm1 */ -#define PM_GET_PGMMAP 3 /* Returns map of loaded midi programs in data8 */ -#define PM_GET_PGM_PATCHES 4 /* Return list of patches of a program (parm1) */ -#define PM_GET_PATCH 5 /* Return patch header of patch parm1 */ -#define PM_SET_PATCH 6 /* Set patch header of patch parm1 */ -#define PM_READ_PATCH 7 /* Read patch (wave) data */ -#define PM_WRITE_PATCH 8 /* Write patch (wave) data */ - -/* - * Commands 0x1000 to 0xffff are for communication between the patch manager - * and the client - */ -#define _PM_LOAD_PATCH 0x100 - -/* - * Commands above 0xffff reserved for device specific use - */ - - long parm1; - long parm2; - long parm3; - - union { - u_char data8[4000]; - u_short data16[2000]; - u_long data32[1000]; - struct patch_info patch; - } data; -}; - -/* - * When a patch manager daemon is present, it will be informed by the - * driver when something important happens. For example when the - * /dev/sequencer is opened or closed. A record with key == PM_K_EVENT is - * returned. The command field contains the event type: - */ -#define PM_E_OPENED 1 /* /dev/sequencer opened */ -#define PM_E_CLOSED 2 /* /dev/sequencer closed */ -#define PM_E_PATCH_RESET 3 /* SNDCTL_RESETSAMPLES called */ -#define PM_E_PATCH_LOADED 4 /* A patch has been loaded by appl */ - -/* - * /dev/sequencer input events. - * - * The data written to the /dev/sequencer is a stream of events. Events - * are records of 4 or 8 bytes. The first byte defines the size. - * Any number of events can be written with a write call. There - * is a set of macros for sending these events. Use these macros if you - * want to maximize portability of your program. - * - * Events SEQ_WAIT, SEQ_MIDIPUTC and SEQ_ECHO. Are also input events. - * (All input events are currently 4 bytes long. Be prepared to support - * 8 byte events also. If you receive any event having first byte >= 128, - * it's a 8 byte event. - * - * The events are documented at the end of this file. - * - * Normal events (4 bytes) - * There is also a 8 byte version of most of the 4 byte events. The - * 8 byte one is recommended. - */ -#define SEQ_NOTEOFF 0 -#define SEQ_FMNOTEOFF SEQ_NOTEOFF /* Just old name */ -#define SEQ_NOTEON 1 -#define SEQ_FMNOTEON SEQ_NOTEON -#define SEQ_WAIT TMR_WAIT_ABS -#define SEQ_PGMCHANGE 3 -#define SEQ_FMPGMCHANGE SEQ_PGMCHANGE -#define SEQ_SYNCTIMER TMR_START -#define SEQ_MIDIPUTC 5 -#define SEQ_DRUMON 6 /*** OBSOLETE ***/ -#define SEQ_DRUMOFF 7 /*** OBSOLETE ***/ -#define SEQ_ECHO TMR_ECHO /* For synching programs with output */ -#define SEQ_AFTERTOUCH 9 -#define SEQ_CONTROLLER 10 - -/* - * Midi controller numbers - * - * Controllers 0 to 31 (0x00 to 0x1f) and 32 to 63 (0x20 to 0x3f) - * are continuous controllers. - * In the MIDI 1.0 these controllers are sent using two messages. - * Controller numbers 0 to 31 are used to send the MSB and the - * controller numbers 32 to 63 are for the LSB. Note that just 7 bits - * are used in MIDI bytes. - */ - -#define CTL_BANK_SELECT 0x00 -#define CTL_MODWHEEL 0x01 -#define CTL_BREATH 0x02 -/* undefined 0x03 */ -#define CTL_FOOT 0x04 -#define CTL_PORTAMENTO_TIME 0x05 -#define CTL_DATA_ENTRY 0x06 -#define CTL_MAIN_VOLUME 0x07 -#define CTL_BALANCE 0x08 -/* undefined 0x09 */ -#define CTL_PAN 0x0a -#define CTL_EXPRESSION 0x0b -/* undefined 0x0c - 0x0f */ -#define CTL_GENERAL_PURPOSE1 0x10 -#define CTL_GENERAL_PURPOSE2 0x11 -#define CTL_GENERAL_PURPOSE3 0x12 -#define CTL_GENERAL_PURPOSE4 0x13 -/* undefined 0x14 - 0x1f */ - -/* undefined 0x20 */ - -/* - * The controller numbers 0x21 to 0x3f are reserved for the - * least significant bytes of the controllers 0x00 to 0x1f. - * These controllers are not recognised by the driver. - * - * Controllers 64 to 69 (0x40 to 0x45) are on/off switches. - * 0=OFF and 127=ON (intermediate values are possible) - */ -#define CTL_DAMPER_PEDAL 0x40 -#define CTL_SUSTAIN CTL_DAMPER_PEDAL /* Alias */ -#define CTL_HOLD CTL_DAMPER_PEDAL /* Alias */ -#define CTL_PORTAMENTO 0x41 -#define CTL_SOSTENUTO 0x42 -#define CTL_SOFT_PEDAL 0x43 -/* undefined 0x44 */ -#define CTL_HOLD2 0x45 -/* undefined 0x46 - 0x4f */ - -#define CTL_GENERAL_PURPOSE5 0x50 -#define CTL_GENERAL_PURPOSE6 0x51 -#define CTL_GENERAL_PURPOSE7 0x52 -#define CTL_GENERAL_PURPOSE8 0x53 -/* undefined 0x54 - 0x5a */ -#define CTL_EXT_EFF_DEPTH 0x5b -#define CTL_TREMOLO_DEPTH 0x5c -#define CTL_CHORUS_DEPTH 0x5d -#define CTL_DETUNE_DEPTH 0x5e -#define CTL_CELESTE_DEPTH CTL_DETUNE_DEPTH /* Alias for the above one */ -#define CTL_PHASER_DEPTH 0x5f -#define CTL_DATA_INCREMENT 0x60 -#define CTL_DATA_DECREMENT 0x61 -#define CTL_NONREG_PARM_NUM_LSB 0x62 -#define CTL_NONREG_PARM_NUM_MSB 0x63 -#define CTL_REGIST_PARM_NUM_LSB 0x64 -#define CTL_REGIST_PARM_NUM_MSB 0x65 -/* undefined 0x66 - 0x78 */ -/* reserved 0x79 - 0x7f */ - -/* Pseudo controllers (not midi compatible) */ -#define CTRL_PITCH_BENDER 255 -#define CTRL_PITCH_BENDER_RANGE 254 -#define CTRL_EXPRESSION 253 /* Obsolete */ -#define CTRL_MAIN_VOLUME 252 /* Obsolete */ - -#define SEQ_BALANCE 11 -#define SEQ_VOLMODE 12 - -/* - * Volume mode decides how volumes are used - */ - -#define VOL_METHOD_ADAGIO 1 -#define VOL_METHOD_LINEAR 2 - -/* - * Note! SEQ_WAIT, SEQ_MIDIPUTC and SEQ_ECHO are used also as - * input events. - */ - -/* - * Event codes 0xf0 to 0xfc are reserved for future extensions. - */ - -#define SEQ_FULLSIZE 0xfd /* Long events */ -/* - * SEQ_FULLSIZE events are used for loading patches/samples to the - * synthesizer devices. These events are passed directly to the driver - * of the associated synthesizer device. There is no limit to the size - * of the extended events. These events are not queued but executed - * immediately when the write() is called (execution can take several - * seconds of time). - * - * When a SEQ_FULLSIZE message is written to the device, it must - * be written using exactly one write() call. Other events cannot - * be mixed to the same write. - * - * For FM synths (YM3812/OPL3) use struct sbi_instrument and write - * it to the /dev/sequencer. Don't write other data together with - * the instrument structure Set the key field of the structure to - * FM_PATCH. The device field is used to route the patch to the - * corresponding device. - * - * For Gravis UltraSound use struct patch_info. Initialize the key field - * to GUS_PATCH. - */ -#define SEQ_PRIVATE 0xfe /* Low level HW dependent events (8 bytes) */ -#define SEQ_EXTENDED 0xff /* Extended events (8 bytes) OBSOLETE */ - -/* - * Record for FM patches - */ - -typedef u_char sbi_instr_data[32]; - -struct sbi_instrument { - u_short key; /* FM_PATCH or OPL3_PATCH */ -#define FM_PATCH _PATCHKEY(0x01) -#define OPL3_PATCH _PATCHKEY(0x03) - short device; /* Synth# (0-4) */ - int channel; /* Program# to be initialized */ - sbi_instr_data operators; /* Reg. settings for operator cells - * (.SBI format) */ -}; - -struct synth_info { /* Read only */ - char name[30]; - int device; /* 0-N. INITIALIZE BEFORE CALLING */ - int synth_type; -#define SYNTH_TYPE_FM 0 -#define SYNTH_TYPE_SAMPLE 1 -#define SYNTH_TYPE_MIDI 2 /* Midi interface */ - - int synth_subtype; -#define FM_TYPE_ADLIB 0x00 -#define FM_TYPE_OPL3 0x01 -#define MIDI_TYPE_MPU401 0x401 - -#define SAMPLE_TYPE_BASIC 0x10 -#define SAMPLE_TYPE_GUS SAMPLE_TYPE_BASIC -#define SAMPLE_TYPE_AWE32 0x20 - - int perc_mode; /* No longer supported */ - int nr_voices; - int nr_drums; /* Obsolete field */ - int instr_bank_size; - u_long capabilities; -#define SYNTH_CAP_PERCMODE 0x00000001 /* No longer used */ -#define SYNTH_CAP_OPL3 0x00000002 /* Set if OPL3 supported */ -#define SYNTH_CAP_INPUT 0x00000004 /* Input (MIDI) device */ - int dummies[19]; /* Reserve space */ -}; - -struct sound_timer_info { - char name[32]; - int caps; -}; - -struct midi_info { - char name[30]; - int device; /* 0-N. INITIALIZE BEFORE CALLING */ - u_long capabilities; /* To be defined later */ - int dev_type; - int dummies[18]; /* Reserve space */ -}; - -/* - * ioctl commands for the /dev/midi## - */ -typedef struct { - u_char cmd; - char nr_args, nr_returns; - u_char data[30]; -} mpu_command_rec; - -#define SNDCTL_MIDI_PRETIME _IOWR('m', 0, int) -#define SNDCTL_MIDI_MPUMODE _IOWR('m', 1, int) -#define SNDCTL_MIDI_MPUCMD _IOWR('m', 2, mpu_command_rec) -#define MIOSPASSTHRU _IOWR('m', 3, int) -#define MIOGPASSTHRU _IOWR('m', 4, int) - -/* - * IOCTL commands for /dev/dsp and /dev/audio - */ - -#define SNDCTL_DSP_RESET _IO ('P', 0) -#define SNDCTL_DSP_SYNC _IO ('P', 1) -#define SNDCTL_DSP_SPEED _IOWR('P', 2, int) -#define SNDCTL_DSP_STEREO _IOWR('P', 3, int) -#define SNDCTL_DSP_GETBLKSIZE _IOR('P', 4, int) -#define SNDCTL_DSP_SETBLKSIZE _IOW('P', 4, int) -#define SNDCTL_DSP_SETFMT _IOWR('P',5, int) /* Selects ONE fmt*/ - -/* - * SOUND_PCM_WRITE_CHANNELS is not that different - * from SNDCTL_DSP_STEREO - */ -#define SOUND_PCM_WRITE_CHANNELS _IOWR('P', 6, int) -#define SNDCTL_DSP_CHANNELS SOUND_PCM_WRITE_CHANNELS -#define SOUND_PCM_WRITE_FILTER _IOWR('P', 7, int) -#define SNDCTL_DSP_POST _IO ('P', 8) - -/* - * SNDCTL_DSP_SETBLKSIZE and the following two calls mostly do - * the same thing, i.e. set the block size used in DMA transfers. - */ -#define SNDCTL_DSP_SUBDIVIDE _IOWR('P', 9, int) -#define SNDCTL_DSP_SETFRAGMENT _IOWR('P',10, int) - - -#define SNDCTL_DSP_GETFMTS _IOR ('P',11, int) /* Returns a mask */ -/* - * Buffer status queries. - */ -typedef struct audio_buf_info { - int fragments; /* # of avail. frags (partly used ones not counted) */ - int fragstotal; /* Total # of fragments allocated */ - int fragsize; /* Size of a fragment in bytes */ - - int bytes; /* Avail. space in bytes (includes partly used fragments) */ - /* Note! 'bytes' could be more than fragments*fragsize */ -} audio_buf_info; - -#define SNDCTL_DSP_GETOSPACE _IOR ('P',12, audio_buf_info) -#define SNDCTL_DSP_GETISPACE _IOR ('P',13, audio_buf_info) - -/* - * SNDCTL_DSP_NONBLOCK is the same (but less powerful, since the - * action cannot be undone) of FIONBIO. The same can be achieved - * by opening the device with O_NDELAY - */ -#define SNDCTL_DSP_NONBLOCK _IO ('P',14) - -#define SNDCTL_DSP_GETCAPS _IOR ('P',15, int) -#define DSP_CAP_REVISION 0x000000ff /* revision level (0 to 255) */ -#define DSP_CAP_DUPLEX 0x00000100 /* Full duplex record/playback */ -#define DSP_CAP_REALTIME 0x00000200 /* Real time capability */ -#define DSP_CAP_BATCH 0x00000400 - /* - * Device has some kind of internal buffers which may - * cause some delays and decrease precision of timing - */ -#define DSP_CAP_COPROC 0x00000800 - /* Has a coprocessor, sometimes it's a DSP but usually not */ -#define DSP_CAP_TRIGGER 0x00001000 /* Supports SETTRIGGER */ -#define DSP_CAP_MMAP 0x00002000 /* Supports mmap() */ - -/* - * What do these function do ? - */ -#define SNDCTL_DSP_GETTRIGGER _IOR ('P',16, int) -#define SNDCTL_DSP_SETTRIGGER _IOW ('P',16, int) -#define PCM_ENABLE_INPUT 0x00000001 -#define PCM_ENABLE_OUTPUT 0x00000002 - -typedef struct count_info { - int bytes; /* Total # of bytes processed */ - int blocks; /* # of fragment transitions since last time */ - int ptr; /* Current DMA pointer value */ -} count_info; - -/* - * GETIPTR and GETISPACE are not that different... same for out. - */ -#define SNDCTL_DSP_GETIPTR _IOR ('P',17, count_info) -#define SNDCTL_DSP_GETOPTR _IOR ('P',18, count_info) - -typedef struct buffmem_desc { - caddr_t buffer; - int size; -} buffmem_desc; - -#define SNDCTL_DSP_MAPINBUF _IOR ('P', 19, buffmem_desc) -#define SNDCTL_DSP_MAPOUTBUF _IOR ('P', 20, buffmem_desc) -#define SNDCTL_DSP_SETSYNCRO _IO ('P', 21) -#define SNDCTL_DSP_SETDUPLEX _IO ('P', 22) -#define SNDCTL_DSP_GETODELAY _IOR ('P', 23, int) - -/* - * I guess these are the readonly version of the same - * functions that exist above as SNDCTL_DSP_... - */ -#define SOUND_PCM_READ_RATE _IOR ('P', 2, int) -#define SOUND_PCM_READ_CHANNELS _IOR ('P', 6, int) -#define SOUND_PCM_READ_BITS _IOR ('P', 5, int) -#define SOUND_PCM_READ_FILTER _IOR ('P', 7, int) - -/* - * ioctl calls to be used in communication with coprocessors and - * DSP chips. - */ - -typedef struct copr_buffer { - int command; /* Set to 0 if not used */ - int flags; -#define CPF_NONE 0x0000 -#define CPF_FIRST 0x0001 /* First block */ -#define CPF_LAST 0x0002 /* Last block */ - int len; - int offs; /* If required by the device (0 if not used) */ - - u_char data[4000]; /* NOTE! 4000 is not 4k */ -} copr_buffer; - -typedef struct copr_debug_buf { - int command; /* Used internally. Set to 0 */ - int parm1; - int parm2; - int flags; - int len; /* Length of data in bytes */ -} copr_debug_buf; - -typedef struct copr_msg { - int len; - u_char data[4000]; -} copr_msg; - -#define SNDCTL_COPR_RESET _IO ('C', 0) -#define SNDCTL_COPR_LOAD _IOWR('C', 1, copr_buffer) -#define SNDCTL_COPR_RDATA _IOWR('C', 2, copr_debug_buf) -#define SNDCTL_COPR_RCODE _IOWR('C', 3, copr_debug_buf) -#define SNDCTL_COPR_WDATA _IOW ('C', 4, copr_debug_buf) -#define SNDCTL_COPR_WCODE _IOW ('C', 5, copr_debug_buf) -#define SNDCTL_COPR_RUN _IOWR('C', 6, copr_debug_buf) -#define SNDCTL_COPR_HALT _IOWR('C', 7, copr_debug_buf) -#define SNDCTL_COPR_SENDMSG _IOW ('C', 8, copr_msg) -#define SNDCTL_COPR_RCVMSG _IOR ('C', 9, copr_msg) - -/* - * IOCTL commands for /dev/mixer - */ - -/* - * Mixer devices - * - * There can be up to 20 different analog mixer channels. The - * SOUND_MIXER_NRDEVICES gives the currently supported maximum. - * The SOUND_MIXER_READ_DEVMASK returns a bitmask which tells - * the devices supported by the particular mixer. - */ - -#define SOUND_MIXER_NRDEVICES 25 -#define SOUND_MIXER_VOLUME 0 /* Master output level */ -#define SOUND_MIXER_BASS 1 /* Treble level of all output channels */ -#define SOUND_MIXER_TREBLE 2 /* Bass level of all output channels */ -#define SOUND_MIXER_SYNTH 3 /* Volume of synthesier input */ -#define SOUND_MIXER_PCM 4 /* Output level for the audio device */ -#define SOUND_MIXER_SPEAKER 5 /* Output level for the PC speaker - * signals */ -#define SOUND_MIXER_LINE 6 /* Volume level for the line in jack */ -#define SOUND_MIXER_MIC 7 /* Volume for the signal coming from - * the microphone jack */ -#define SOUND_MIXER_CD 8 /* Volume level for the input signal - * connected to the CD audio input */ -#define SOUND_MIXER_IMIX 9 /* Recording monitor. It controls the - * output volume of the selected - * recording sources while recording */ -#define SOUND_MIXER_ALTPCM 10 /* Volume of the alternative codec - * device */ -#define SOUND_MIXER_RECLEV 11 /* Global recording level */ -#define SOUND_MIXER_IGAIN 12 /* Input gain */ -#define SOUND_MIXER_OGAIN 13 /* Output gain */ -/* - * The AD1848 codec and compatibles have three line level inputs - * (line, aux1 and aux2). Since each card manufacturer have assigned - * different meanings to these inputs, it's inpractical to assign - * specific meanings (line, cd, synth etc.) to them. - */ -#define SOUND_MIXER_LINE1 14 /* Input source 1 (aux1) */ -#define SOUND_MIXER_LINE2 15 /* Input source 2 (aux2) */ -#define SOUND_MIXER_LINE3 16 /* Input source 3 (line) */ -#define SOUND_MIXER_DIGITAL1 17 /* Digital (input) 1 */ -#define SOUND_MIXER_DIGITAL2 18 /* Digital (input) 2 */ -#define SOUND_MIXER_DIGITAL3 19 /* Digital (input) 3 */ -#define SOUND_MIXER_PHONEIN 20 /* Phone input */ -#define SOUND_MIXER_PHONEOUT 21 /* Phone output */ -#define SOUND_MIXER_VIDEO 22 /* Video/TV (audio) in */ -#define SOUND_MIXER_RADIO 23 /* Radio in */ -#define SOUND_MIXER_MONITOR 24 /* Monitor (usually mic) volume */ - - -/* - * Some on/off settings (SOUND_SPECIAL_MIN - SOUND_SPECIAL_MAX) - * Not counted to SOUND_MIXER_NRDEVICES, but use the same number space - */ -#define SOUND_ONOFF_MIN 28 -#define SOUND_ONOFF_MAX 30 -#define SOUND_MIXER_MUTE 28 /* 0 or 1 */ -#define SOUND_MIXER_ENHANCE 29 /* Enhanced stereo (0, 40, 60 or 80) */ -#define SOUND_MIXER_LOUD 30 /* 0 or 1 */ - -/* Note! Number 31 cannot be used since the sign bit is reserved */ -#define SOUND_MIXER_NONE 31 - -#define SOUND_DEVICE_LABELS { \ - "Vol ", "Bass ", "Trebl", "Synth", "Pcm ", "Spkr ", "Line ", \ - "Mic ", "CD ", "Mix ", "Pcm2 ", "Rec ", "IGain", "OGain", \ - "Line1", "Line2", "Line3", "Digital1", "Digital2", "Digital3", \ - "PhoneIn", "PhoneOut", "Video", "Radio", "Monitor"} - -#define SOUND_DEVICE_NAMES { \ - "vol", "bass", "treble", "synth", "pcm", "speaker", "line", \ - "mic", "cd", "mix", "pcm2", "rec", "igain", "ogain", \ - "line1", "line2", "line3", "dig1", "dig2", "dig3", \ - "phin", "phout", "video", "radio", "monitor"} - -/* Device bitmask identifiers */ - -#define SOUND_MIXER_RECSRC 0xff /* 1 bit per recording source */ -#define SOUND_MIXER_DEVMASK 0xfe /* 1 bit per supported device */ -#define SOUND_MIXER_RECMASK 0xfd /* 1 bit per supp. recording source */ -#define SOUND_MIXER_CAPS 0xfc -#define SOUND_CAP_EXCL_INPUT 0x00000001 /* Only 1 rec. src at a time */ -#define SOUND_MIXER_STEREODEVS 0xfb /* Mixer channels supporting stereo */ - -/* Device mask bits */ - -#define SOUND_MASK_VOLUME (1 << SOUND_MIXER_VOLUME) -#define SOUND_MASK_BASS (1 << SOUND_MIXER_BASS) -#define SOUND_MASK_TREBLE (1 << SOUND_MIXER_TREBLE) -#define SOUND_MASK_SYNTH (1 << SOUND_MIXER_SYNTH) -#define SOUND_MASK_PCM (1 << SOUND_MIXER_PCM) -#define SOUND_MASK_SPEAKER (1 << SOUND_MIXER_SPEAKER) -#define SOUND_MASK_LINE (1 << SOUND_MIXER_LINE) -#define SOUND_MASK_MIC (1 << SOUND_MIXER_MIC) -#define SOUND_MASK_CD (1 << SOUND_MIXER_CD) -#define SOUND_MASK_IMIX (1 << SOUND_MIXER_IMIX) -#define SOUND_MASK_ALTPCM (1 << SOUND_MIXER_ALTPCM) -#define SOUND_MASK_RECLEV (1 << SOUND_MIXER_RECLEV) -#define SOUND_MASK_IGAIN (1 << SOUND_MIXER_IGAIN) -#define SOUND_MASK_OGAIN (1 << SOUND_MIXER_OGAIN) -#define SOUND_MASK_LINE1 (1 << SOUND_MIXER_LINE1) -#define SOUND_MASK_LINE2 (1 << SOUND_MIXER_LINE2) -#define SOUND_MASK_LINE3 (1 << SOUND_MIXER_LINE3) -#define SOUND_MASK_DIGITAL1 (1 << SOUND_MIXER_DIGITAL1) -#define SOUND_MASK_DIGITAL2 (1 << SOUND_MIXER_DIGITAL2) -#define SOUND_MASK_DIGITAL3 (1 << SOUND_MIXER_DIGITAL3) -#define SOUND_MASK_PHONEIN (1 << SOUND_MIXER_PHONEIN) -#define SOUND_MASK_PHONEOUT (1 << SOUND_MIXER_PHONEOUT) -#define SOUND_MASK_RADIO (1 << SOUND_MIXER_RADIO) -#define SOUND_MASK_VIDEO (1 << SOUND_MIXER_VIDEO) -#define SOUND_MASK_MONITOR (1 << SOUND_MIXER_MONITOR) - -/* Obsolete macros */ -#define SOUND_MASK_MUTE (1 << SOUND_MIXER_MUTE) -#define SOUND_MASK_ENHANCE (1 << SOUND_MIXER_ENHANCE) -#define SOUND_MASK_LOUD (1 << SOUND_MIXER_LOUD) - -#define MIXER_READ(dev) _IOR('M', dev, int) -#define SOUND_MIXER_READ_VOLUME MIXER_READ(SOUND_MIXER_VOLUME) -#define SOUND_MIXER_READ_BASS MIXER_READ(SOUND_MIXER_BASS) -#define SOUND_MIXER_READ_TREBLE MIXER_READ(SOUND_MIXER_TREBLE) -#define SOUND_MIXER_READ_SYNTH MIXER_READ(SOUND_MIXER_SYNTH) -#define SOUND_MIXER_READ_PCM MIXER_READ(SOUND_MIXER_PCM) -#define SOUND_MIXER_READ_SPEAKER MIXER_READ(SOUND_MIXER_SPEAKER) -#define SOUND_MIXER_READ_LINE MIXER_READ(SOUND_MIXER_LINE) -#define SOUND_MIXER_READ_MIC MIXER_READ(SOUND_MIXER_MIC) -#define SOUND_MIXER_READ_CD MIXER_READ(SOUND_MIXER_CD) -#define SOUND_MIXER_READ_IMIX MIXER_READ(SOUND_MIXER_IMIX) -#define SOUND_MIXER_READ_ALTPCM MIXER_READ(SOUND_MIXER_ALTPCM) -#define SOUND_MIXER_READ_RECLEV MIXER_READ(SOUND_MIXER_RECLEV) -#define SOUND_MIXER_READ_IGAIN MIXER_READ(SOUND_MIXER_IGAIN) -#define SOUND_MIXER_READ_OGAIN MIXER_READ(SOUND_MIXER_OGAIN) -#define SOUND_MIXER_READ_LINE1 MIXER_READ(SOUND_MIXER_LINE1) -#define SOUND_MIXER_READ_LINE2 MIXER_READ(SOUND_MIXER_LINE2) -#define SOUND_MIXER_READ_LINE3 MIXER_READ(SOUND_MIXER_LINE3) -#define SOUND_MIXER_READ_DIGITAL1 MIXER_READ(SOUND_MIXER_DIGITAL1) -#define SOUND_MIXER_READ_DIGITAL2 MIXER_READ(SOUND_MIXER_DIGITAL2) -#define SOUND_MIXER_READ_DIGITAL3 MIXER_READ(SOUND_MIXER_DIGITAL3) -#define SOUND_MIXER_READ_PHONEIN MIXER_READ(SOUND_MIXER_PHONEIN) -#define SOUND_MIXER_READ_PHONEOUT MIXER_READ(SOUND_MIXER_PHONEOUT) -#define SOUND_MIXER_READ_RADIO MIXER_READ(SOUND_MIXER_RADIO) -#define SOUND_MIXER_READ_VIDEO MIXER_READ(SOUND_MIXER_VIDEO) -#define SOUND_MIXER_READ_MONITOR MIXER_READ(SOUND_MIXER_MONITOR) - -/* Obsolete macros */ -#define SOUND_MIXER_READ_MUTE MIXER_READ(SOUND_MIXER_MUTE) -#define SOUND_MIXER_READ_ENHANCE MIXER_READ(SOUND_MIXER_ENHANCE) -#define SOUND_MIXER_READ_LOUD MIXER_READ(SOUND_MIXER_LOUD) - -#define SOUND_MIXER_READ_RECSRC MIXER_READ(SOUND_MIXER_RECSRC) -#define SOUND_MIXER_READ_DEVMASK MIXER_READ(SOUND_MIXER_DEVMASK) -#define SOUND_MIXER_READ_RECMASK MIXER_READ(SOUND_MIXER_RECMASK) -#define SOUND_MIXER_READ_STEREODEVS MIXER_READ(SOUND_MIXER_STEREODEVS) -#define SOUND_MIXER_READ_CAPS MIXER_READ(SOUND_MIXER_CAPS) - -#define MIXER_WRITE(dev) _IOWR('M', dev, int) -#define SOUND_MIXER_WRITE_VOLUME MIXER_WRITE(SOUND_MIXER_VOLUME) -#define SOUND_MIXER_WRITE_BASS MIXER_WRITE(SOUND_MIXER_BASS) -#define SOUND_MIXER_WRITE_TREBLE MIXER_WRITE(SOUND_MIXER_TREBLE) -#define SOUND_MIXER_WRITE_SYNTH MIXER_WRITE(SOUND_MIXER_SYNTH) -#define SOUND_MIXER_WRITE_PCM MIXER_WRITE(SOUND_MIXER_PCM) -#define SOUND_MIXER_WRITE_SPEAKER MIXER_WRITE(SOUND_MIXER_SPEAKER) -#define SOUND_MIXER_WRITE_LINE MIXER_WRITE(SOUND_MIXER_LINE) -#define SOUND_MIXER_WRITE_MIC MIXER_WRITE(SOUND_MIXER_MIC) -#define SOUND_MIXER_WRITE_CD MIXER_WRITE(SOUND_MIXER_CD) -#define SOUND_MIXER_WRITE_IMIX MIXER_WRITE(SOUND_MIXER_IMIX) -#define SOUND_MIXER_WRITE_ALTPCM MIXER_WRITE(SOUND_MIXER_ALTPCM) -#define SOUND_MIXER_WRITE_RECLEV MIXER_WRITE(SOUND_MIXER_RECLEV) -#define SOUND_MIXER_WRITE_IGAIN MIXER_WRITE(SOUND_MIXER_IGAIN) -#define SOUND_MIXER_WRITE_OGAIN MIXER_WRITE(SOUND_MIXER_OGAIN) -#define SOUND_MIXER_WRITE_LINE1 MIXER_WRITE(SOUND_MIXER_LINE1) -#define SOUND_MIXER_WRITE_LINE2 MIXER_WRITE(SOUND_MIXER_LINE2) -#define SOUND_MIXER_WRITE_LINE3 MIXER_WRITE(SOUND_MIXER_LINE3) -#define SOUND_MIXER_WRITE_DIGITAL1 MIXER_WRITE(SOUND_MIXER_DIGITAL1) -#define SOUND_MIXER_WRITE_DIGITAL2 MIXER_WRITE(SOUND_MIXER_DIGITAL2) -#define SOUND_MIXER_WRITE_DIGITAL3 MIXER_WRITE(SOUND_MIXER_DIGITAL3) -#define SOUND_MIXER_WRITE_PHONEIN MIXER_WRITE(SOUND_MIXER_PHONEIN) -#define SOUND_MIXER_WRITE_PHONEOUT MIXER_WRITE(SOUND_MIXER_PHONEOUT) -#define SOUND_MIXER_WRITE_RADIO MIXER_WRITE(SOUND_MIXER_RADIO) -#define SOUND_MIXER_WRITE_VIDEO MIXER_WRITE(SOUND_MIXER_VIDEO) -#define SOUND_MIXER_WRITE_MONITOR MIXER_WRITE(SOUND_MIXER_MONITOR) - -#define SOUND_MIXER_WRITE_MUTE MIXER_WRITE(SOUND_MIXER_MUTE) -#define SOUND_MIXER_WRITE_ENHANCE MIXER_WRITE(SOUND_MIXER_ENHANCE) -#define SOUND_MIXER_WRITE_LOUD MIXER_WRITE(SOUND_MIXER_LOUD) - -#define SOUND_MIXER_WRITE_RECSRC MIXER_WRITE(SOUND_MIXER_RECSRC) - -typedef struct mixer_info { - char id[16]; - char name[32]; - int modify_counter; - int fillers[10]; -} mixer_info; - -#define SOUND_MIXER_INFO _IOR('M', 101, mixer_info) - -#define LEFT_CHN 0 -#define RIGHT_CHN 1 - -/* - * Level 2 event types for /dev/sequencer - */ - -/* - * The 4 most significant bits of byte 0 specify the class of - * the event: - * - * 0x8X = system level events, - * 0x9X = device/port specific events, event[1] = device/port, - * The last 4 bits give the subtype: - * 0x02 = Channel event (event[3] = chn). - * 0x01 = note event (event[4] = note). - * (0x01 is not used alone but always with bit 0x02). - * event[2] = MIDI message code (0x80=note off etc.) - * - */ - -#define EV_SEQ_LOCAL 0x80 -#define EV_TIMING 0x81 -#define EV_CHN_COMMON 0x92 -#define EV_CHN_VOICE 0x93 -#define EV_SYSEX 0x94 -/* - * Event types 200 to 220 are reserved for application use. - * These numbers will not be used by the driver. - */ - -/* - * Events for event type EV_CHN_VOICE - */ - -#define MIDI_NOTEOFF 0x80 -#define MIDI_NOTEON 0x90 -#define MIDI_KEY_PRESSURE 0xA0 - -/* - * Events for event type EV_CHN_COMMON - */ - -#define MIDI_CTL_CHANGE 0xB0 -#define MIDI_PGM_CHANGE 0xC0 -#define MIDI_CHN_PRESSURE 0xD0 -#define MIDI_PITCH_BEND 0xE0 - -#define MIDI_SYSTEM_PREFIX 0xF0 - -/* - * Timer event types - */ -#define TMR_WAIT_REL 1 /* Time relative to the prev time */ -#define TMR_WAIT_ABS 2 /* Absolute time since TMR_START */ -#define TMR_STOP 3 -#define TMR_START 4 -#define TMR_CONTINUE 5 -#define TMR_TEMPO 6 -#define TMR_ECHO 8 -#define TMR_CLOCK 9 /* MIDI clock */ -#define TMR_SPP 10 /* Song position pointer */ -#define TMR_TIMESIG 11 /* Time signature */ - -/* - * Local event types - */ -#define LOCL_STARTAUDIO 1 - -#if (!defined(_KERNEL) && !defined(INKERNEL)) || defined(USE_SEQ_MACROS) -/* - * Some convenience macros to simplify programming of the - * /dev/sequencer interface - * - * These macros define the API which should be used when possible. - */ - -#ifndef USE_SIMPLE_MACROS -void seqbuf_dump(void); /* This function must be provided by programs */ - -/* Sample seqbuf_dump() implementation: - * - * SEQ_DEFINEBUF (2048); -- Defines a buffer for 2048 bytes - * - * int seqfd; -- The file descriptor for /dev/sequencer. - * - * void - * seqbuf_dump () - * { - * if (_seqbufptr) - * if (write (seqfd, _seqbuf, _seqbufptr) == -1) - * { - * perror ("write /dev/sequencer"); - * exit (-1); - * } - * _seqbufptr = 0; - * } - */ - -#define SEQ_DEFINEBUF(len) \ - u_char _seqbuf[len]; int _seqbuflen = len;int _seqbufptr = 0 -#define SEQ_USE_EXTBUF() \ - extern u_char _seqbuf[]; \ - extern int _seqbuflen;extern int _seqbufptr -#define SEQ_DECLAREBUF() SEQ_USE_EXTBUF() -#define SEQ_PM_DEFINES struct patmgr_info _pm_info -#define _SEQ_NEEDBUF(len) \ - if ((_seqbufptr+(len)) > _seqbuflen) \ - seqbuf_dump() -#define _SEQ_ADVBUF(len) _seqbufptr += len -#define SEQ_DUMPBUF seqbuf_dump -#else -/* - * This variation of the sequencer macros is used just to format one event - * using fixed buffer. - * - * The program using the macro library must define the following macros before - * using this library. - * - * #define _seqbuf name of the buffer (u_char[]) - * #define _SEQ_ADVBUF(len) If the applic needs to know the exact - * size of the event, this macro can be used. - * Otherwise this must be defined as empty. - * #define _seqbufptr Define the name of index variable or 0 if - * not required. - */ -#define _SEQ_NEEDBUF(len) /* empty */ -#endif - -#define PM_LOAD_PATCH(dev, bank, pgm) \ - (SEQ_DUMPBUF(), _pm_info.command = _PM_LOAD_PATCH, \ - _pm_info.device=dev, _pm_info.data.data8[0]=pgm, \ - _pm_info.parm1 = bank, _pm_info.parm2 = 1, \ - ioctl(seqfd, SNDCTL_PMGR_ACCESS, &_pm_info)) -#define PM_LOAD_PATCHES(dev, bank, pgm) \ - (SEQ_DUMPBUF(), _pm_info.command = _PM_LOAD_PATCH, \ - _pm_info.device=dev, bcopy( pgm, _pm_info.data.data8, 128), \ - _pm_info.parm1 = bank, _pm_info.parm2 = 128, \ - ioctl(seqfd, SNDCTL_PMGR_ACCESS, &_pm_info)) - -#define SEQ_VOLUME_MODE(dev, mode) { \ - _SEQ_NEEDBUF(8);\ - _seqbuf[_seqbufptr] = SEQ_EXTENDED;\ - _seqbuf[_seqbufptr+1] = SEQ_VOLMODE;\ - _seqbuf[_seqbufptr+2] = (dev);\ - _seqbuf[_seqbufptr+3] = (mode);\ - _seqbuf[_seqbufptr+4] = 0;\ - _seqbuf[_seqbufptr+5] = 0;\ - _seqbuf[_seqbufptr+6] = 0;\ - _seqbuf[_seqbufptr+7] = 0;\ - _SEQ_ADVBUF(8);} - -/* - * Midi voice messages - */ - -#define _CHN_VOICE(dev, event, chn, note, parm) { \ - _SEQ_NEEDBUF(8);\ - _seqbuf[_seqbufptr] = EV_CHN_VOICE;\ - _seqbuf[_seqbufptr+1] = (dev);\ - _seqbuf[_seqbufptr+2] = (event);\ - _seqbuf[_seqbufptr+3] = (chn);\ - _seqbuf[_seqbufptr+4] = (note);\ - _seqbuf[_seqbufptr+5] = (parm);\ - _seqbuf[_seqbufptr+6] = (0);\ - _seqbuf[_seqbufptr+7] = 0;\ - _SEQ_ADVBUF(8);} - -#define SEQ_START_NOTE(dev, chn, note, vol) \ - _CHN_VOICE(dev, MIDI_NOTEON, chn, note, vol) - -#define SEQ_STOP_NOTE(dev, chn, note, vol) \ - _CHN_VOICE(dev, MIDI_NOTEOFF, chn, note, vol) - -#define SEQ_KEY_PRESSURE(dev, chn, note, pressure) \ - _CHN_VOICE(dev, MIDI_KEY_PRESSURE, chn, note, pressure) - -/* - * Midi channel messages - */ - -#define _CHN_COMMON(dev, event, chn, p1, p2, w14) { \ - _SEQ_NEEDBUF(8);\ - _seqbuf[_seqbufptr] = EV_CHN_COMMON;\ - _seqbuf[_seqbufptr+1] = (dev);\ - _seqbuf[_seqbufptr+2] = (event);\ - _seqbuf[_seqbufptr+3] = (chn);\ - _seqbuf[_seqbufptr+4] = (p1);\ - _seqbuf[_seqbufptr+5] = (p2);\ - *(short *)&_seqbuf[_seqbufptr+6] = (w14);\ - _SEQ_ADVBUF(8);} -/* - * SEQ_SYSEX permits sending of sysex messages. (It may look that it permits - * sending any MIDI bytes but it's absolutely not possible. Trying to do - * so _will_ cause problems with MPU401 intelligent mode). - * - * Sysex messages are sent in blocks of 1 to 6 bytes. Longer messages must be - * sent by calling SEQ_SYSEX() several times (there must be no other events - * between them). First sysex fragment must have 0xf0 in the first byte - * and the last byte (buf[len-1] of the last fragment must be 0xf7. No byte - * between these sysex start and end markers cannot be larger than 0x7f. Also - * lengths of each fragments (except the last one) must be 6. - * - * Breaking the above rules may work with some MIDI ports but is likely to - * cause fatal problems with some other devices (such as MPU401). - */ -#define SEQ_SYSEX(dev, buf, len) { \ - int i, l=(len); if (l>6)l=6;\ - _SEQ_NEEDBUF(8);\ - _seqbuf[_seqbufptr] = EV_SYSEX;\ - for(i=0;i e.g. cmake .. -DAUDIO_WINDOWS_WASAPI=ON - - -WINDOWS: - -All Windows audio APIs in RtAudio compile with either the MinGW compiler (tested with latest tdm64-gcc-4.8.1) or MS Visual Studio. - -Visual C++ 6.0 project files (very old) are included for the test programs in the /tests/Windows/ directory. These projects compile API support for ASIO, WASAPI and DirectSound. - - -LINUX OSS: - -The OSS API support in RtAudio has not been tested for many years. I'm not even sure there are OSS drivers supporting recent linux kernels. In all likelihood, the OSS API code in RtAudio will disappear within the next year or two (if you don't want this to happen, let me know). diff --git a/vendor/rtaudio/readme b/vendor/rtaudio/readme deleted file mode 100644 index d86078fc1..000000000 --- a/vendor/rtaudio/readme +++ /dev/null @@ -1,61 +0,0 @@ -RtAudio - a set of C++ classes that provide a common API for realtime audio input/output across Linux (native ALSA, JACK, PulseAudio and OSS), Macintosh OS X (CoreAudio and JACK), and Windows (DirectSound, ASIO and WASAPI) operating systems. - -By Gary P. Scavone, 2001-2016. - -This distribution of RtAudio contains the following: - -doc: RtAudio documentation (see doc/html/index.html) -tests: example RtAudio programs -include: header and source files necessary for ASIO, DS & OSS compilation -tests/Windows: Visual C++ .net test program workspace and projects - -OVERVIEW: - -RtAudio is a set of C++ classes that provides a common API (Application Programming Interface) for realtime audio input/output across Linux (native ALSA, JACK, and OSS), Macintosh OS X, SGI, and Windows (DirectSound, ASIO and WASAPI) operating systems. RtAudio significantly simplifies the process of interacting with computer audio hardware. It was designed with the following objectives: - - - object-oriented C++ design - - simple, common API across all supported platforms - - only one source and one header file for easy inclusion in programming projects - - allow simultaneous multi-api support - - support dynamic connection of devices - - provide extensive audio device parameter control - - allow audio device capability probing - - automatic internal conversion for data format, channel number compensation, (de)interleaving, and byte-swapping - -RtAudio incorporates the concept of audio streams, which represent audio output (playback) and/or input (recording). Available audio devices and their capabilities can be enumerated and then specified when opening a stream. Where applicable, multiple API support can be compiled and a particular API specified when creating an RtAudio instance. See the \ref apinotes section for information specific to each of the supported audio APIs. - -FURTHER READING: - -For complete documentation on RtAudio, see the doc directory of the distribution or surf to http://www.music.mcgill.ca/~gary/rtaudio/. - - -LEGAL AND ETHICAL: - -The RtAudio license is similar to the MIT License. - - RtAudio: a set of realtime audio i/o C++ classes - Copyright (c) 2001-2016 Gary P. Scavone - - Permission is hereby granted, free of charge, to any person - obtaining a copy of this software and associated documentation files - (the "Software"), to deal in the Software without restriction, - including without limitation the rights to use, copy, modify, merge, - publish, distribute, sublicense, and/or sell copies of the Software, - and to permit persons to whom the Software is furnished to do so, - subject to the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - Any person wishing to distribute modifications to the Software is - asked to send the modifications to the original developer so that - they can be incorporated into the canonical version. This is, - however, not a binding provision of this license. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR - ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/rtaudio/rtaudio-config.in b/vendor/rtaudio/rtaudio-config.in deleted file mode 100644 index 5f83d512f..000000000 --- a/vendor/rtaudio/rtaudio-config.in +++ /dev/null @@ -1,19 +0,0 @@ -#! /bin/sh -if (test "x$#" != "x1") ; then - echo "Usage: $0 [--libs | --cxxflags | --cppflags]" - exit; -fi - -LIBRARY="@LIBS@" -CXXFLAGS="@CXXFLAGS@" -CPPFLAGS="@CPPFLAGS@" - -if (test "x$1" = "x--libs") ; then - echo "$LIBRARY -lrtaudio" -elif (test "x$1" = "x--cxxflags") ; then - echo "$CXXFLAGS" -elif (test "x$1" = "x--cppflags") ; then - echo "$CPPFLAGS" -else - echo "Unknown option: $1" -fi diff --git a/vendor/rtaudio/rtaudio.pc.in b/vendor/rtaudio/rtaudio.pc.in deleted file mode 100644 index e0aa40145..000000000 --- a/vendor/rtaudio/rtaudio.pc.in +++ /dev/null @@ -1,12 +0,0 @@ -prefix=@prefix@ -exec_prefix=${prefix} -libdir=${exec_prefix}/lib -includedir=${prefix}/include/rtaudio - -Name: librtaudio -Description: RtAudio - a set of C++ classes that provide a common API for realtime audio input/output -Version: @PACKAGE_VERSION@ -Requires: @req@ -Libs: -L${libdir} -lrtaudio -Libs.private: -lpthread -Cflags: -pthread -I${includedir} @CPPFLAGS@ diff --git a/vendor/rtaudio/tests/CMakeLists.txt b/vendor/rtaudio/tests/CMakeLists.txt deleted file mode 100644 index 0fb028fc1..000000000 --- a/vendor/rtaudio/tests/CMakeLists.txt +++ /dev/null @@ -1,25 +0,0 @@ -include_directories(..) -if (WIN32) - include_directories(../include) -endif (WIN32) - -add_executable(audioprobe audioprobe.cpp) -target_link_libraries(audioprobe rtaudio_static ${LINKLIBS}) - -add_executable(playsaw playsaw.cpp) -target_link_libraries(playsaw rtaudio_static ${LINKLIBS}) - -add_executable(playraw playraw.cpp) -target_link_libraries(playraw rtaudio_static ${LINKLIBS}) - -add_executable(record record.cpp) -target_link_libraries(record rtaudio_static ${LINKLIBS}) - -add_executable(duplex duplex.cpp) -target_link_libraries(duplex rtaudio_static ${LINKLIBS}) - -add_executable(testall testall.cpp) -target_link_libraries(testall rtaudio_static ${LINKLIBS}) - -add_executable(teststops teststops.cpp) -target_link_libraries(teststops rtaudio_static ${LINKLIBS}) diff --git a/vendor/rtaudio/tests/Debug/.placeholder b/vendor/rtaudio/tests/Debug/.placeholder deleted file mode 100644 index e69de29bb..000000000 diff --git a/vendor/rtaudio/tests/Makefile.am b/vendor/rtaudio/tests/Makefile.am deleted file mode 100644 index e39fdde25..000000000 --- a/vendor/rtaudio/tests/Makefile.am +++ /dev/null @@ -1,27 +0,0 @@ - -noinst_PROGRAMS = audioprobe playsaw playraw record duplex testall teststops - -AM_CXXFLAGS = -Wall -I$(top_srcdir) - -audioprobe_SOURCES = audioprobe.cpp -audioprobe_LDADD = $(top_builddir)/librtaudio.la - -playsaw_SOURCES = playsaw.cpp -playsaw_LDADD = $(top_builddir)/librtaudio.la - -playraw_SOURCES = playraw.cpp -playraw_LDADD = $(top_builddir)/librtaudio.la - -record_SOURCES = record.cpp -record_LDADD = $(top_builddir)/librtaudio.la - -duplex_SOURCES = duplex.cpp -duplex_LDADD = $(top_builddir)/librtaudio.la - -testall_SOURCES = testall.cpp -testall_LDADD = $(top_builddir)/librtaudio.la - -teststops_SOURCES = teststops.cpp -teststops_LDADD = $(top_builddir)/librtaudio.la - -EXTRA_DIST = Windows diff --git a/vendor/rtaudio/tests/Release/.placeholder b/vendor/rtaudio/tests/Release/.placeholder deleted file mode 100644 index e69de29bb..000000000 diff --git a/vendor/rtaudio/tests/Windows/Debug/.placeholder b/vendor/rtaudio/tests/Windows/Debug/.placeholder deleted file mode 100644 index e69de29bb..000000000 diff --git a/vendor/rtaudio/tests/Windows/Release/.placeholder b/vendor/rtaudio/tests/Windows/Release/.placeholder deleted file mode 100644 index e69de29bb..000000000 diff --git a/vendor/rtaudio/tests/Windows/audioprobe.dsp b/vendor/rtaudio/tests/Windows/audioprobe.dsp deleted file mode 100644 index a44ae3399..000000000 --- a/vendor/rtaudio/tests/Windows/audioprobe.dsp +++ /dev/null @@ -1,158 +0,0 @@ -# Microsoft Developer Studio Project File - Name="audioprobe" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -CFG=audioprobe - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "audioprobe.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "audioprobe.mak" CFG="audioprobe - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "audioprobe - Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "audioprobe - Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "audioprobe - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "audioprobe___Win32_Release" -# PROP BASE Intermediate_Dir "audioprobe___Win32_Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "" -# PROP Intermediate_Dir "Release" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /MT /W3 /GX /O2 /I "../../" /I "../../include" /D "NDEBUG" /D "__WINDOWS_DS__" /D "__WINDOWS_ASIO__" /D "__WINDOWS_WASAPI__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib dsound.lib /nologo /subsystem:console /machine:I386 - -!ELSEIF "$(CFG)" == "audioprobe - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "audioprobe___Win32_Debug" -# PROP BASE Intermediate_Dir "audioprobe___Win32_Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "" -# PROP Intermediate_Dir "Debug" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../../" /I "../../include" /D "_DEBUG" /D "__WINDOWS_DS__" /D "__WINDOWS_ASIO__" /D "__WINDOWS_WASAPI__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib dsound.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept - -!ENDIF - -# Begin Target - -# Name "audioprobe - Win32 Release" -# Name "audioprobe - Win32 Debug" -# Begin Group "Source Files" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" -# Begin Source File - -SOURCE=..\..\include\asio.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\include\asiodrivers.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\include\asiolist.cpp -# End Source File -# Begin Source File - -SOURCE=..\audioprobe.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\include\iasiothiscallresolver.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\RtAudio.cpp -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h;hpp;hxx;hm;inl" -# Begin Source File - -SOURCE=..\..\include\asio.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\asiodrivers.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\asiodrvr.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\asiolist.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\asiosys.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\ginclude.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\iasiodrv.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\iasiothiscallresolver.h -# End Source File -# Begin Source File - -SOURCE=..\..\RtAudio.h -# End Source File -# End Group -# Begin Group "Resource Files" - -# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" -# End Group -# End Target -# End Project diff --git a/vendor/rtaudio/tests/Windows/duplex.dsp b/vendor/rtaudio/tests/Windows/duplex.dsp deleted file mode 100644 index 475000a8d..000000000 --- a/vendor/rtaudio/tests/Windows/duplex.dsp +++ /dev/null @@ -1,158 +0,0 @@ -# Microsoft Developer Studio Project File - Name="duplex" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -CFG=duplex - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "duplex.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "duplex.mak" CFG="duplex - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "duplex - Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "duplex - Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "duplex - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "duplex___Win32_Release" -# PROP BASE Intermediate_Dir "duplex___Win32_Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "" -# PROP Intermediate_Dir "Release" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /MT /W3 /GX /O2 /I "../../" /I "../../include" /D "NDEBUG" /D "__WINDOWS_DS__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_ASIO__" /D "__WINDOWS_WASAPI__" /YX /FD /c -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib dsound.lib /nologo /subsystem:console /machine:I386 - -!ELSEIF "$(CFG)" == "duplex - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "duplex___Win32_Debug" -# PROP BASE Intermediate_Dir "duplex___Win32_Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "" -# PROP Intermediate_Dir "Debug" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../../" /I "../../include" /D "_DEBUG" /D "__WINDOWS_ASIO__.__WINDOWS_DS__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_ASIO__" /D "__WINDOWS_DS__" /D "__WINDOWS_WASAPI__" /YX /FD /GZ /c -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib dsound.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept - -!ENDIF - -# Begin Target - -# Name "duplex - Win32 Release" -# Name "duplex - Win32 Debug" -# Begin Group "Source Files" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" -# Begin Source File - -SOURCE=..\..\include\asio.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\include\asiodrivers.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\include\asiolist.cpp -# End Source File -# Begin Source File - -SOURCE=..\duplex.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\include\iasiothiscallresolver.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\RtAudio.cpp -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h;hpp;hxx;hm;inl" -# Begin Source File - -SOURCE=..\..\include\asio.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\asiodrivers.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\asiodrvr.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\asiolist.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\asiosys.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\ginclude.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\iasiodrv.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\iasiothiscallresolver.h -# End Source File -# Begin Source File - -SOURCE=..\..\RtAudio.h -# End Source File -# End Group -# Begin Group "Resource Files" - -# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" -# End Group -# End Target -# End Project diff --git a/vendor/rtaudio/tests/Windows/playraw.dsp b/vendor/rtaudio/tests/Windows/playraw.dsp deleted file mode 100644 index 58d8db794..000000000 --- a/vendor/rtaudio/tests/Windows/playraw.dsp +++ /dev/null @@ -1,158 +0,0 @@ -# Microsoft Developer Studio Project File - Name="playraw" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -CFG=playraw - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "playraw.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "playraw.mak" CFG="playraw - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "playraw - Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "playraw - Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "playraw - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "playraw___Win32_Release" -# PROP BASE Intermediate_Dir "playraw___Win32_Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "" -# PROP Intermediate_Dir "Release" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /MT /W3 /GX /O2 /I "../../" /I "../../include" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_ASIO__" /D "__WINDOWS_DS__" /D "__WINDOWS_WASAPI__" /YX /FD /c -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib dsound.lib /nologo /subsystem:console /machine:I386 - -!ELSEIF "$(CFG)" == "playraw - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "playraw___Win32_Debug" -# PROP BASE Intermediate_Dir "playraw___Win32_Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "" -# PROP Intermediate_Dir "Debug" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../../" /I "../../include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_ASIO__" /D "__WINDOWS_DS__" /D "__WINDOWS_WASAPI__" /YX /FD /GZ /c -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib dsound.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept - -!ENDIF - -# Begin Target - -# Name "playraw - Win32 Release" -# Name "playraw - Win32 Debug" -# Begin Group "Source Files" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" -# Begin Source File - -SOURCE=..\..\include\asio.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\include\asiodrivers.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\include\asiolist.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\include\iasiothiscallresolver.cpp -# End Source File -# Begin Source File - -SOURCE=..\playraw.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\RtAudio.cpp -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h;hpp;hxx;hm;inl" -# Begin Source File - -SOURCE=..\..\include\asio.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\asiodrivers.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\asiodrvr.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\asiolist.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\asiosys.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\ginclude.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\iasiodrv.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\iasiothiscallresolver.h -# End Source File -# Begin Source File - -SOURCE=..\..\RtAudio.h -# End Source File -# End Group -# Begin Group "Resource Files" - -# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" -# End Group -# End Target -# End Project diff --git a/vendor/rtaudio/tests/Windows/playsaw.dsp b/vendor/rtaudio/tests/Windows/playsaw.dsp deleted file mode 100644 index cca887a06..000000000 --- a/vendor/rtaudio/tests/Windows/playsaw.dsp +++ /dev/null @@ -1,158 +0,0 @@ -# Microsoft Developer Studio Project File - Name="playsaw" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -CFG=playsaw - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "playsaw.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "playsaw.mak" CFG="playsaw - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "playsaw - Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "playsaw - Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "playsaw - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "playsaw___Win32_Release" -# PROP BASE Intermediate_Dir "playsaw___Win32_Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "" -# PROP Intermediate_Dir "Release" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /MT /W3 /GX /O2 /I "../../" /I "../../include" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_ASIO__" /D "__WINDOWS_DS__" /D "__WINDOWS_WASAPI__" /YX /FD /c -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib dsound.lib /nologo /subsystem:console /machine:I386 - -!ELSEIF "$(CFG)" == "playsaw - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "playsaw___Win32_Debug" -# PROP BASE Intermediate_Dir "playsaw___Win32_Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "" -# PROP Intermediate_Dir "Debug" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../../" /I "../../include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_ASIO__" /D "__WINDOWS_DS__" /D "__WINDOWS_WASAPI__" /YX /FD /GZ /c -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib dsound.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept - -!ENDIF - -# Begin Target - -# Name "playsaw - Win32 Release" -# Name "playsaw - Win32 Debug" -# Begin Group "Source Files" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" -# Begin Source File - -SOURCE=..\..\include\asio.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\include\asiodrivers.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\include\asiolist.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\include\iasiothiscallresolver.cpp -# End Source File -# Begin Source File - -SOURCE=..\playsaw.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\RtAudio.cpp -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h;hpp;hxx;hm;inl" -# Begin Source File - -SOURCE=..\..\include\asio.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\asiodrivers.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\asiodrvr.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\asiolist.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\asiosys.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\ginclude.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\iasiodrv.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\iasiothiscallresolver.h -# End Source File -# Begin Source File - -SOURCE=..\..\RtAudio.h -# End Source File -# End Group -# Begin Group "Resource Files" - -# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" -# End Group -# End Target -# End Project diff --git a/vendor/rtaudio/tests/Windows/record.dsp b/vendor/rtaudio/tests/Windows/record.dsp deleted file mode 100644 index 0b3e892af..000000000 --- a/vendor/rtaudio/tests/Windows/record.dsp +++ /dev/null @@ -1,158 +0,0 @@ -# Microsoft Developer Studio Project File - Name="record" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -CFG=record - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "record.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "record.mak" CFG="record - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "record - Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "record - Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "record - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "record___Win32_Release" -# PROP BASE Intermediate_Dir "record___Win32_Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "" -# PROP Intermediate_Dir "Release" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /MT /W3 /GX /O2 /I "../../" /I "../../include" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_ASIO__" /D "__WINDOWS_DS__" /D "__WINDOWS_WASAPI__" /YX /FD /c -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib dsound.lib /nologo /subsystem:console /machine:I386 - -!ELSEIF "$(CFG)" == "record - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "record___Win32_Debug" -# PROP BASE Intermediate_Dir "record___Win32_Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "" -# PROP Intermediate_Dir "Debug" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../../" /I "../../include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_ASIO__" /D "__WINDOWS_DS__" /D "__WINDOWS_WASAPI__" /YX /FD /GZ /c -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib dsound.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept - -!ENDIF - -# Begin Target - -# Name "record - Win32 Release" -# Name "record - Win32 Debug" -# Begin Group "Source Files" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" -# Begin Source File - -SOURCE=..\..\include\asio.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\include\asiodrivers.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\include\asiolist.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\include\iasiothiscallresolver.cpp -# End Source File -# Begin Source File - -SOURCE=..\record.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\RtAudio.cpp -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h;hpp;hxx;hm;inl" -# Begin Source File - -SOURCE=..\..\include\asio.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\asiodrivers.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\asiodrvr.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\asiolist.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\asiosys.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\ginclude.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\iasiodrv.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\iasiothiscallresolver.h -# End Source File -# Begin Source File - -SOURCE=..\..\RtAudio.h -# End Source File -# End Group -# Begin Group "Resource Files" - -# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" -# End Group -# End Target -# End Project diff --git a/vendor/rtaudio/tests/Windows/rtaudio.dsw b/vendor/rtaudio/tests/Windows/rtaudio.dsw deleted file mode 100644 index 1869b31dc..000000000 --- a/vendor/rtaudio/tests/Windows/rtaudio.dsw +++ /dev/null @@ -1,101 +0,0 @@ -Microsoft Developer Studio Workspace File, Format Version 6.00 -# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! - -############################################################################### - -Project: "audioprobe"=.\audioprobe.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Project: "duplex"=.\duplex.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Project: "playraw"=.\playraw.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Project: "playsaw"=.\playsaw.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Project: "record"=.\record.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Project: "testall"=.\testall.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Project: "teststops"=.\teststops.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Global: - -Package=<5> -{{{ -}}} - -Package=<3> -{{{ -}}} - -############################################################################### - diff --git a/vendor/rtaudio/tests/Windows/testall.dsp b/vendor/rtaudio/tests/Windows/testall.dsp deleted file mode 100644 index 4a327c8f4..000000000 --- a/vendor/rtaudio/tests/Windows/testall.dsp +++ /dev/null @@ -1,158 +0,0 @@ -# Microsoft Developer Studio Project File - Name="testall" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -CFG=testall - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "testall.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "testall.mak" CFG="testall - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "testall - Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "testall - Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "testall - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "testall___Win32_Release" -# PROP BASE Intermediate_Dir "testall___Win32_Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "" -# PROP Intermediate_Dir "Release" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /MT /W3 /GX /O2 /I "../../" /I "../../include" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_ASIO__" /D "__WINDOWS_DS__" /D "__WINDOWS_WASAPI__" /YX /FD /c -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib dsound.lib /nologo /subsystem:console /machine:I386 - -!ELSEIF "$(CFG)" == "testall - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "testall___Win32_Debug" -# PROP BASE Intermediate_Dir "testall___Win32_Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "" -# PROP Intermediate_Dir "Debug" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../../" /I "../../include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_ASIO__" /D "__WINDOWS_DS__" /D "__WINDOWS_WASAPI__" /YX /FD /GZ /c -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib dsound.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept - -!ENDIF - -# Begin Target - -# Name "testall - Win32 Release" -# Name "testall - Win32 Debug" -# Begin Group "Source Files" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" -# Begin Source File - -SOURCE=..\..\include\asio.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\include\asiodrivers.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\include\asiolist.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\include\iasiothiscallresolver.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\RtAudio.cpp -# End Source File -# Begin Source File - -SOURCE=..\testall.cpp -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h;hpp;hxx;hm;inl" -# Begin Source File - -SOURCE=..\..\include\asio.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\asiodrivers.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\asiodrvr.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\asiolist.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\asiosys.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\ginclude.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\iasiodrv.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\iasiothiscallresolver.h -# End Source File -# Begin Source File - -SOURCE=..\..\RtAudio.h -# End Source File -# End Group -# Begin Group "Resource Files" - -# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" -# End Group -# End Target -# End Project diff --git a/vendor/rtaudio/tests/Windows/teststops.dsp b/vendor/rtaudio/tests/Windows/teststops.dsp deleted file mode 100644 index 15d09bd3b..000000000 --- a/vendor/rtaudio/tests/Windows/teststops.dsp +++ /dev/null @@ -1,158 +0,0 @@ -# Microsoft Developer Studio Project File - Name="teststops" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -CFG=teststops - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "teststops.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "teststops.mak" CFG="teststops - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "teststops - Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "teststops - Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "teststops - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "teststops___Win32_Release" -# PROP BASE Intermediate_Dir "teststops___Win32_Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "" -# PROP Intermediate_Dir "Release" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /MT /W3 /GX /O2 /I "../../" /I "../../include" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_ASIO__" /D "__WINDOWS_DS__" /D "__WINDOWS_WASAPI__" /YX /FD /c -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib dsound.lib /nologo /subsystem:console /machine:I386 - -!ELSEIF "$(CFG)" == "teststops - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "teststops___Win32_Debug" -# PROP BASE Intermediate_Dir "teststops___Win32_Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "" -# PROP Intermediate_Dir "Debug" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../../" /I "../../include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_ASIO__" /D "__WINDOWS_DS__" /D "__WINDOWS_WASAPI__" /YX /FD /GZ /c -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib dsound.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept - -!ENDIF - -# Begin Target - -# Name "teststops - Win32 Release" -# Name "teststops - Win32 Debug" -# Begin Group "Source Files" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" -# Begin Source File - -SOURCE=..\..\include\asio.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\include\asiodrivers.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\include\asiolist.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\include\iasiothiscallresolver.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\RtAudio.cpp -# End Source File -# Begin Source File - -SOURCE=..\teststops.cpp -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h;hpp;hxx;hm;inl" -# Begin Source File - -SOURCE=..\..\include\asio.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\asiodrivers.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\asiodrvr.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\asiolist.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\asiosys.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\ginclude.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\iasiodrv.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\iasiothiscallresolver.h -# End Source File -# Begin Source File - -SOURCE=..\..\RtAudio.h -# End Source File -# End Group -# Begin Group "Resource Files" - -# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" -# End Group -# End Target -# End Project diff --git a/vendor/rtaudio/tests/audioprobe.cpp b/vendor/rtaudio/tests/audioprobe.cpp deleted file mode 100644 index 1b9390874..000000000 --- a/vendor/rtaudio/tests/audioprobe.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/******************************************/ -/* - audioprobe.cpp - by Gary P. Scavone, 2001 - - Probe audio system and prints device info. -*/ -/******************************************/ - -#include "RtAudio.h" -#include -#include - -int main() -{ - // Create an api map. - std::map apiMap; - apiMap[RtAudio::MACOSX_CORE] = "OS-X Core Audio"; - apiMap[RtAudio::WINDOWS_ASIO] = "Windows ASIO"; - apiMap[RtAudio::WINDOWS_DS] = "Windows Direct Sound"; - apiMap[RtAudio::WINDOWS_WASAPI] = "Windows WASAPI"; - apiMap[RtAudio::UNIX_JACK] = "Jack Client"; - apiMap[RtAudio::LINUX_ALSA] = "Linux ALSA"; - apiMap[RtAudio::LINUX_PULSE] = "Linux PulseAudio"; - apiMap[RtAudio::LINUX_OSS] = "Linux OSS"; - apiMap[RtAudio::RTAUDIO_DUMMY] = "RtAudio Dummy"; - - std::vector< RtAudio::Api > apis; - RtAudio :: getCompiledApi( apis ); - - std::cout << "\nRtAudio Version " << RtAudio::getVersion() << std::endl; - - std::cout << "\nCompiled APIs:\n"; - for ( unsigned int i=0; i -#include -#include - -/* -typedef char MY_TYPE; -#define FORMAT RTAUDIO_SINT8 -*/ - -typedef signed short MY_TYPE; -#define FORMAT RTAUDIO_SINT16 - -/* -typedef S24 MY_TYPE; -#define FORMAT RTAUDIO_SINT24 - -typedef signed long MY_TYPE; -#define FORMAT RTAUDIO_SINT32 - -typedef float MY_TYPE; -#define FORMAT RTAUDIO_FLOAT32 - -typedef double MY_TYPE; -#define FORMAT RTAUDIO_FLOAT64 -*/ - -void usage( void ) { - // Error function in case of incorrect command-line - // argument specifications - std::cout << "\nuseage: duplex N fs \n"; - std::cout << " where N = number of channels,\n"; - std::cout << " fs = the sample rate,\n"; - std::cout << " iDevice = optional input device to use (default = 0),\n"; - std::cout << " oDevice = optional output device to use (default = 0),\n"; - std::cout << " iChannelOffset = an optional input channel offset (default = 0),\n"; - std::cout << " and oChannelOffset = optional output channel offset (default = 0).\n\n"; - exit( 0 ); -} - -int inout( void *outputBuffer, void *inputBuffer, unsigned int /*nBufferFrames*/, - double /*streamTime*/, RtAudioStreamStatus status, void *data ) -{ - // Since the number of input and output channels is equal, we can do - // a simple buffer copy operation here. - if ( status ) std::cout << "Stream over/underflow detected." << std::endl; - - unsigned int *bytes = (unsigned int *) data; - memcpy( outputBuffer, inputBuffer, *bytes ); - return 0; -} - -int main( int argc, char *argv[] ) -{ - unsigned int channels, fs, bufferBytes, oDevice = 0, iDevice = 0, iOffset = 0, oOffset = 0; - - // Minimal command-line checking - if (argc < 3 || argc > 7 ) usage(); - - RtAudio adac; - if ( adac.getDeviceCount() < 1 ) { - std::cout << "\nNo audio devices found!\n"; - exit( 1 ); - } - - channels = (unsigned int) atoi(argv[1]); - fs = (unsigned int) atoi(argv[2]); - if ( argc > 3 ) - iDevice = (unsigned int) atoi(argv[3]); - if ( argc > 4 ) - oDevice = (unsigned int) atoi(argv[4]); - if ( argc > 5 ) - iOffset = (unsigned int) atoi(argv[5]); - if ( argc > 6 ) - oOffset = (unsigned int) atoi(argv[6]); - - // Let RtAudio print messages to stderr. - adac.showWarnings( true ); - - // Set the same number of channels for both input and output. - unsigned int bufferFrames = 512; - RtAudio::StreamParameters iParams, oParams; - iParams.deviceId = iDevice; - iParams.nChannels = channels; - iParams.firstChannel = iOffset; - oParams.deviceId = oDevice; - oParams.nChannels = channels; - oParams.firstChannel = oOffset; - - if ( iDevice == 0 ) - iParams.deviceId = adac.getDefaultInputDevice(); - if ( oDevice == 0 ) - oParams.deviceId = adac.getDefaultOutputDevice(); - - RtAudio::StreamOptions options; - //options.flags |= RTAUDIO_NONINTERLEAVED; - - try { - adac.openStream( &oParams, &iParams, FORMAT, fs, &bufferFrames, &inout, (void *)&bufferBytes, &options ); - } - catch ( RtAudioError& e ) { - std::cout << '\n' << e.getMessage() << '\n' << std::endl; - exit( 1 ); - } - - bufferBytes = bufferFrames * channels * sizeof( MY_TYPE ); - - // Test RtAudio functionality for reporting latency. - std::cout << "\nStream latency = " << adac.getStreamLatency() << " frames" << std::endl; - - try { - adac.startStream(); - - char input; - std::cout << "\nRunning ... press to quit (buffer frames = " << bufferFrames << ").\n"; - std::cin.get(input); - - // Stop the stream. - adac.stopStream(); - } - catch ( RtAudioError& e ) { - std::cout << '\n' << e.getMessage() << '\n' << std::endl; - goto cleanup; - } - - cleanup: - if ( adac.isStreamOpen() ) adac.closeStream(); - - return 0; -} diff --git a/vendor/rtaudio/tests/playraw.cpp b/vendor/rtaudio/tests/playraw.cpp deleted file mode 100644 index f11f83c28..000000000 --- a/vendor/rtaudio/tests/playraw.cpp +++ /dev/null @@ -1,152 +0,0 @@ -/******************************************/ -/* - playraw.cpp - by Gary P. Scavone, 2007 - - Play a specified raw file. It is necessary - that the file be of the same data format as - defined below. -*/ -/******************************************/ - -#include "RtAudio.h" -#include -#include -#include -#include - -/* -typedef char MY_TYPE; -#define FORMAT RTAUDIO_SINT8 -#define SCALE 127.0 -*/ - -typedef signed short MY_TYPE; -#define FORMAT RTAUDIO_SINT16 -#define SCALE 32767.0 - -/* -typedef S24 MY_TYPE; -#define FORMAT RTAUDIO_SINT24 -#define SCALE 8388607.0 - -typedef signed int MY_TYPE; -#define FORMAT RTAUDIO_SINT32 -#define SCALE 2147483647.0 - -typedef float MY_TYPE; -#define FORMAT RTAUDIO_FLOAT32 -#define SCALE 1.0; - -typedef double MY_TYPE; -#define FORMAT RTAUDIO_FLOAT64 -#define SCALE 1.0; -*/ - -// Platform-dependent sleep routines. -#if defined( __WINDOWS_ASIO__ ) || defined( __WINDOWS_DS__ ) || defined( __WINDOWS_WASAPI__ ) - #include - #define SLEEP( milliseconds ) Sleep( (DWORD) milliseconds ) -#else // Unix variants - #include - #define SLEEP( milliseconds ) usleep( (unsigned long) (milliseconds * 1000.0) ) -#endif - -void usage( void ) { - // Error function in case of incorrect command-line - // argument specifications - std::cout << "\nuseage: playraw N fs file \n"; - std::cout << " where N = number of channels,\n"; - std::cout << " fs = the sample rate, \n"; - std::cout << " file = the raw file to play,\n"; - std::cout << " device = optional device to use (default = 0),\n"; - std::cout << " and channelOffset = an optional channel offset on the device (default = 0).\n\n"; - exit( 0 ); -} - -struct OutputData { - FILE *fd; - unsigned int channels; -}; - -// Interleaved buffers -int output( void *outputBuffer, void * /*inputBuffer*/, unsigned int nBufferFrames, - double /*streamTime*/, RtAudioStreamStatus /*status*/, void *data ) -{ - OutputData *oData = (OutputData*) data; - - // In general, it's not a good idea to do file input in the audio - // callback function but I'm doing it here because I don't know the - // length of the file we are reading. - unsigned int count = fread( outputBuffer, oData->channels * sizeof( MY_TYPE ), nBufferFrames, oData->fd); - if ( count < nBufferFrames ) { - unsigned int bytes = (nBufferFrames - count) * oData->channels * sizeof( MY_TYPE ); - unsigned int startByte = count * oData->channels * sizeof( MY_TYPE ); - memset( (char *)(outputBuffer)+startByte, 0, bytes ); - return 1; - } - - return 0; -} - -int main( int argc, char *argv[] ) -{ - unsigned int channels, fs, bufferFrames, device = 0, offset = 0; - char *file; - - // minimal command-line checking - if ( argc < 4 || argc > 6 ) usage(); - - RtAudio dac; - if ( dac.getDeviceCount() < 1 ) { - std::cout << "\nNo audio devices found!\n"; - exit( 0 ); - } - - channels = (unsigned int) atoi( argv[1]) ; - fs = (unsigned int) atoi( argv[2] ); - file = argv[3]; - if ( argc > 4 ) - device = (unsigned int) atoi( argv[4] ); - if ( argc > 5 ) - offset = (unsigned int) atoi( argv[5] ); - - OutputData data; - data.fd = fopen( file, "rb" ); - if ( !data.fd ) { - std::cout << "Unable to find or open file!\n"; - exit( 1 ); - } - - // Set our stream parameters for output only. - bufferFrames = 512; - RtAudio::StreamParameters oParams; - oParams.deviceId = device; - oParams.nChannels = channels; - oParams.firstChannel = offset; - - if ( device == 0 ) - oParams.deviceId = dac.getDefaultOutputDevice(); - - data.channels = channels; - try { - dac.openStream( &oParams, NULL, FORMAT, fs, &bufferFrames, &output, (void *)&data ); - dac.startStream(); - } - catch ( RtAudioError& e ) { - std::cout << '\n' << e.getMessage() << '\n' << std::endl; - goto cleanup; - } - - std::cout << "\nPlaying raw file " << file << " (buffer frames = " << bufferFrames << ")." << std::endl; - while ( 1 ) { - SLEEP( 100 ); // wake every 100 ms to check if we're done - if ( dac.isStreamRunning() == false ) break; - } - - cleanup: - fclose( data.fd ); - dac.closeStream(); - - return 0; -} diff --git a/vendor/rtaudio/tests/playsaw.cpp b/vendor/rtaudio/tests/playsaw.cpp deleted file mode 100644 index d1953b6ca..000000000 --- a/vendor/rtaudio/tests/playsaw.cpp +++ /dev/null @@ -1,217 +0,0 @@ -/******************************************/ -/* - playsaw.cpp - by Gary P. Scavone, 2006 - - This program will output sawtooth waveforms - of different frequencies on each channel. -*/ -/******************************************/ - -#include "RtAudio.h" -#include -#include - -/* -typedef char MY_TYPE; -#define FORMAT RTAUDIO_SINT8 -#define SCALE 127.0 -*/ - -typedef signed short MY_TYPE; -#define FORMAT RTAUDIO_SINT16 -#define SCALE 32767.0 - -/* -typedef S24 MY_TYPE; -#define FORMAT RTAUDIO_SINT24 -#define SCALE 8388607.0 - -typedef signed long MY_TYPE; -#define FORMAT RTAUDIO_SINT32 -#define SCALE 2147483647.0 - -typedef float MY_TYPE; -#define FORMAT RTAUDIO_FLOAT32 -#define SCALE 1.0 - -typedef double MY_TYPE; -#define FORMAT RTAUDIO_FLOAT64 -#define SCALE 1.0 -*/ - -// Platform-dependent sleep routines. -#if defined( __WINDOWS_ASIO__ ) || defined( __WINDOWS_DS__ ) || defined( __WINDOWS_WASAPI__ ) - #include - #define SLEEP( milliseconds ) Sleep( (DWORD) milliseconds ) -#else // Unix variants - #include - #define SLEEP( milliseconds ) usleep( (unsigned long) (milliseconds * 1000.0) ) -#endif - -#define BASE_RATE 0.005 -#define TIME 1.0 - -void usage( void ) { - // Error function in case of incorrect command-line - // argument specifications - std::cout << "\nuseage: playsaw N fs